Add passrofi version 0.1.0
This commit is contained in:
parent
6485bc1deb
commit
f7526687dc
|
|
@ -384,7 +384,7 @@ bindsym Pause exec --no-startup-id "volctl mute toggle"
|
|||
#bindsym XF86LaunchA exec --no-startup-id touchpad-toggle
|
||||
|
||||
# ~~ Password manager: passmenu
|
||||
bindsym $mod+Shift+p exec --no-startup-id passmenu
|
||||
bindsym $mod+Shift+p exec passrofi
|
||||
|
||||
# ~~ Screenshot tool
|
||||
bindsym $mod+Print exec flameshot gui
|
||||
|
|
|
|||
|
|
@ -0,0 +1,334 @@
|
|||
#!/bin/bash
|
||||
|
||||
# passrofi -- Rofi script for pass (passwordstore.org)
|
||||
# Version: 0.1.0
|
||||
# Author: binaryDiv
|
||||
|
||||
|
||||
# Strict mode
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
# Set some generic variables
|
||||
SCRIPTNAME=$0
|
||||
BASENAME=$(basename $0)
|
||||
|
||||
|
||||
# Usage
|
||||
# -----
|
||||
|
||||
usage() {
|
||||
cat << END_OF_USAGE
|
||||
Usage: $BASENAME [-d DIR] [-p PROMPT]
|
||||
|
||||
Simple rofi script to query passwords from pass (passwordstore.org).
|
||||
|
||||
Calling this script directly will start rofi in script mode.
|
||||
|
||||
General options:
|
||||
-h, --help Print this help message
|
||||
-v, --verbose Enables debug logging via stderr
|
||||
-d DIR Sets the password-store directory (default: ~/.password-store)
|
||||
-p PROMPT Sets the rofi prompt to PROMPT (default: "Password")
|
||||
END_OF_USAGE
|
||||
}
|
||||
|
||||
|
||||
# Helper functions
|
||||
# ----------------
|
||||
|
||||
# Logs a message to stderr if verbose mode is enabled (with a '#' prefix)
|
||||
log() {
|
||||
if [[ -n $PASSROFI_VERBOSE ]]; then
|
||||
echo "# $@" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
# Prints a message to stderr and exits with status 1
|
||||
fail() {
|
||||
echo "$@" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
# Main entrypoint
|
||||
# ---------------
|
||||
|
||||
# Main entrypoint: Checks if the script was called from the command line or as a rofi script, then
|
||||
# calls either main_cli (first case) or main_rofi (second case).
|
||||
main() {
|
||||
# Set defaults for environment variables
|
||||
set_default_env
|
||||
|
||||
# If the script was called by rofi, this env variable will be defined
|
||||
if [[ -v ROFI_RETV ]]; then
|
||||
main_rofi "$@"
|
||||
else
|
||||
main_cli "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
set_default_env() {
|
||||
# Set default values for environment variables (unless already set)
|
||||
PASSWORD_STORE_DIR=${PASSWORD_STORE_DIR:-~/.password-store}
|
||||
PASSROFI_VERBOSE=${PASSROFI_VERBOSE:-}
|
||||
PASSROFI_PROMPT=${PASSROFI_PROMPT:-Password}
|
||||
}
|
||||
|
||||
|
||||
# CLI mode (called from command line)
|
||||
# -----------------------------------
|
||||
|
||||
# Entrypoint when called from the command line: Parses command line arguments, sets some environment
|
||||
# variables, and starts rofi (which then calls this script again, using main_rofi as entrypoint).
|
||||
main_cli() {
|
||||
# Parse command line arguments (sets variables)
|
||||
parse_cli_args "$@"
|
||||
|
||||
# Start rofi
|
||||
exec_rofi
|
||||
}
|
||||
|
||||
# Parses command line arguments and sets variables accordingly
|
||||
parse_cli_args() {
|
||||
# Use "-:" to sort of parse long options
|
||||
while getopts ":hvd:p:-:" option; do
|
||||
# getopts does not support long options, so we build a workaround
|
||||
if [[ $option == "-" ]]; then
|
||||
option="-$OPTARG"
|
||||
OPTARG=""
|
||||
fi
|
||||
|
||||
case $option in
|
||||
h|-help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
|
||||
v|-verbose)
|
||||
export PASSROFI_VERBOSE=1
|
||||
log "I can be very verbose if you want me to, HOOT HOOT"
|
||||
;;
|
||||
|
||||
d)
|
||||
export PASSWORD_STORE_DIR="$OPTARG"
|
||||
log "Setting password store directory to $PASSWORD_STORE_DIR"
|
||||
;;
|
||||
|
||||
p)
|
||||
export PASSROFI_PROMPT="$OPTARG"
|
||||
log "Setting rofi prompt to $PASSROFI_PROMPT"
|
||||
;;
|
||||
|
||||
:)
|
||||
fail "$BASENAME: option -$OPTARG requires an argument."
|
||||
;;
|
||||
|
||||
?|*)
|
||||
fail "$BASENAME: invalid option: -${OPTARG:-$option}"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# Executes rofi with the needed parameters and environment variables
|
||||
exec_rofi() {
|
||||
exec rofi -show pass \
|
||||
-modi "pass:$SCRIPTNAME" \
|
||||
-kb-custom-1 "Alt-h" \
|
||||
-kb-custom-2 "Alt-u" \
|
||||
-kb-custom-3 "Alt-v"
|
||||
}
|
||||
|
||||
|
||||
# Rofi script mode (called by rofi)
|
||||
# ---------------------------------
|
||||
|
||||
# Entrypoint when called by rofi as a rofi script: Lists available password files and parses input.
|
||||
main_rofi() {
|
||||
# Debug output
|
||||
log "Called by rofi: ROFI_RETV=${ROFI_RETV:-}"
|
||||
log " ARGS: $@"
|
||||
log " ROFI_INFO: ${ROFI_INFO:-}"
|
||||
log " PASSWORD_STORE_DIR: ${PASSWORD_STORE_DIR:-}"
|
||||
|
||||
# Ensure all environment variables are set correctly, directories exist etc.
|
||||
ensure_environment
|
||||
|
||||
# Set rofi mode options (outputs specially formatted strings)
|
||||
set_rofi_mode_options
|
||||
|
||||
# Get user selection from arguments
|
||||
USER_SELECTION="$@"
|
||||
|
||||
# Check current script state and decide which action to take next
|
||||
handle_rofi_state
|
||||
}
|
||||
|
||||
# Checks the current script state and executes the next action
|
||||
handle_rofi_state() {
|
||||
# First, check if we're coming from the help screen
|
||||
if [[ ${ROFI_INFO:-} == 'help_menu' ]]; then
|
||||
# Change state so that we show the password list again
|
||||
ROFI_RETV=0
|
||||
ROFI_INFO=""
|
||||
fi
|
||||
|
||||
# Check state to determine what to do
|
||||
case $ROFI_RETV in
|
||||
# Initial call of script
|
||||
0)
|
||||
# Generate a list of password files for rofi to show
|
||||
generate_password_list
|
||||
;;
|
||||
|
||||
# User selected an entry from the list (1) or a custom entry (2)
|
||||
1|2)
|
||||
# Use pass to decrypt and copy the password
|
||||
handle_user_selection
|
||||
;;
|
||||
|
||||
# Custom keybinding 1 (Alt-h): Show help for keybindings
|
||||
10)
|
||||
show_help_menu
|
||||
;;
|
||||
|
||||
# Custom keybinding 2 (Alt-u): Copy username
|
||||
11)
|
||||
# Copy username to clipboard
|
||||
handle_copy_username
|
||||
;;
|
||||
|
||||
# Custom keybinding 3 (Alt-v): View password file in terminal
|
||||
12)
|
||||
# Open password file in a less inside a terminal
|
||||
handle_view_file
|
||||
;;
|
||||
|
||||
# Unused custom keybindings: Show help menu
|
||||
1[3-9]|2[0-8])
|
||||
log "Unused keybinding $((ROFI_RETV - 9)), showing help instead."
|
||||
show_help_menu
|
||||
;;
|
||||
|
||||
# Unknown state
|
||||
*)
|
||||
fail "Unknown ROFI_RETV state: $ROFI_RETV"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Ensures all environment variables are set correctly
|
||||
ensure_environment() {
|
||||
# Check if the password store directory exists
|
||||
[[ -d $PASSWORD_STORE_DIR ]] || fail "Invalid password store directory: $PASSWORD_STORE_DIR"
|
||||
}
|
||||
|
||||
# Sets (outputs) rofi mode options
|
||||
set_rofi_mode_options() {
|
||||
# This enables custom keybindings for the script
|
||||
echo -en "\0use-hot-keys\x1ftrue\n"
|
||||
|
||||
# Disable custom input
|
||||
echo -en "\0no-custom\x1ftrue\n"
|
||||
|
||||
# Set default prompt and message
|
||||
echo -en "\0prompt\x1f$PASSROFI_PROMPT\n"
|
||||
echo -en "\0message\x1f\n"
|
||||
}
|
||||
|
||||
# Custom keybinding (Alt-h) to show a help menu with keybindings
|
||||
show_help_menu() {
|
||||
# Set prompt and message
|
||||
echo -en "\0prompt\x1fHelp\n"
|
||||
echo -en "\0message\x1fThis is a list of custom keybindings for passrofi.\n"
|
||||
|
||||
# Helper function that adds an info string to the entry
|
||||
_echo() {
|
||||
echo -en "$@\0info\x1fhelp_menu\n"
|
||||
}
|
||||
|
||||
# Print help page
|
||||
_echo "Alt-h: Shows this help page"
|
||||
_echo " "
|
||||
_echo "Alt-u: Copy username"
|
||||
_echo "Alt-v: View password file"
|
||||
}
|
||||
|
||||
# Lists all password files as input for rofi
|
||||
generate_password_list() {
|
||||
# Get list of all .gpg files in password-store
|
||||
password_store_dir="${PASSWORD_STORE_DIR%/}"
|
||||
for password_file in $(find "$password_store_dir" -type f -name '*.gpg' | sort); do
|
||||
# Strip prefix and suffix
|
||||
password_file="${password_file#"$password_store_dir"/}"
|
||||
password_file="${password_file%.gpg}"
|
||||
|
||||
# Output filename
|
||||
echo $password_file
|
||||
done
|
||||
}
|
||||
|
||||
# Parse user selection: Use pass to decrypt and copy password
|
||||
handle_user_selection() {
|
||||
log "User selected entry: $USER_SELECTION"
|
||||
|
||||
# External programs need to be launched asynchronously, otherwise rofi blocks
|
||||
coproc (
|
||||
# Copy password to clipboard (pass will automatically clear the clipboard after 45 seconds)
|
||||
pass show -c "$USER_SELECTION" &>/dev/null
|
||||
)
|
||||
|
||||
# End here
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Copys the username of a selected password file to the clipboard
|
||||
handle_copy_username() {
|
||||
log "User wants to copy username of: $USER_SELECTION"
|
||||
|
||||
# We can get the username directly from the filename
|
||||
username=${USER_SELECTION##*/}
|
||||
|
||||
log "Username is: $username"
|
||||
|
||||
# Copy to clipboard
|
||||
coproc (
|
||||
echo "$username" | xclip -selection clipboard -r -silent &>/dev/null
|
||||
)
|
||||
|
||||
# End here
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Views the selected password file in a pager inside a terminal
|
||||
handle_view_file() {
|
||||
log "User wants to view file: $USER_SELECTION"
|
||||
|
||||
# Get full filename
|
||||
password_store_dir="${PASSWORD_STORE_DIR%/}"
|
||||
filename="$password_store_dir/$USER_SELECTION.gpg"
|
||||
|
||||
# Open file in a pager inside a terminal
|
||||
coproc (
|
||||
rofi-sensible-terminal -e "bash -ic 'pass show \"$USER_SELECTION\" | less'" &>/dev/null
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
# Run script
|
||||
main "$@"
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------
|
||||
#
|
||||
# CHANGELOG
|
||||
# =========
|
||||
#
|
||||
# Version 0.1.0:
|
||||
#
|
||||
# - First version
|
||||
# - Built-in help page
|
||||
# - List password files, copy password, copy username, view file in terminal
|
||||
#
|
||||
# --------------------------------------------------------------------------------
|
||||
Loading…
Reference in New Issue