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
|
#bindsym XF86LaunchA exec --no-startup-id touchpad-toggle
|
||||||
|
|
||||||
# ~~ Password manager: passmenu
|
# ~~ Password manager: passmenu
|
||||||
bindsym $mod+Shift+p exec --no-startup-id passmenu
|
bindsym $mod+Shift+p exec passrofi
|
||||||
|
|
||||||
# ~~ Screenshot tool
|
# ~~ Screenshot tool
|
||||||
bindsym $mod+Print exec flameshot gui
|
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