passmenu (2865B)
1 #!/bin/sh 2 # requirements: dmenu(1), xdotool(1) (for -t, -n and -u options) 3 4 pass_dir="$HOME/.password-store" 5 6 show_help() 7 { 8 echo "usage: ${0##*/} [OPTIONS] [QUERY]" 9 echo "shows all passwords from pass(1) and allows interactive selection" 10 echo "via dmenu(1). By default, the password is copied to the X clipboard." 11 echo 12 echo "OPTIONS are one or more of the following:" 13 echo " -h show this message" 14 echo " -t type out the password instead of copying to clipboard" 15 echo " -n type out newline character after password type out (-t)" 16 echo " -u VAL type out VAL before copying password or typing it out" 17 echo " -- do not consider any following args as options" 18 echo 19 echo "EXAMPLES:" 20 echo "Open interactive menu with all passwords:" 21 echo " ${0##*/}" 22 echo 23 echo "Type out password matching 'newyorktimes':" 24 echo " ${0##*/} newyorktimes" 25 echo 26 echo "Type out username, tab character, and password selected from menu," 27 echo "and hit return:" 28 echo " ${0##*/} -n -t -u \"myusername\\t\"" 29 } 30 31 die() 32 { 33 printf '%s: error: %s\n' "${0##*/}" "$1" >&2 34 exit 1 35 } 36 37 get_password_files() 38 { 39 find "$pass_dir" -type f -iname "*.gpg" 40 printf 'primary\nclipboard\n' 41 } 42 43 strip_root_dir() 44 { 45 sed "s,${pass_dir%/}/,," 46 } 47 48 match_password_file() 49 { 50 _passfiles="$(get_password_files | strip_root_dir | sed 's/\.gpg$//')" 51 if [ "$#" -gt 0 ]; then 52 _passfile="$(printf '%s' "$_passfiles" | grep -i "$@")" 53 if [ "$(printf '%s\n' "$_passfile" | wc -l)" -eq 0 ]; then 54 die "no password matches '$@'" 55 elif [ "$(printf '%s\n' "$_passfile" | wc -l)" -gt 1 ]; then 56 die "more than one password matches '$@': $_passfile" 57 fi 58 else 59 _passfile="$(printf '%s\n' "$_passfiles" | dmenu -i)" 60 if [ $? -ne 0 ]; then 61 die 'aborted by user' 62 fi 63 fi 64 printf '%s\n' "$_passfile" 65 } 66 67 retrieve_password() 68 { 69 if [ "$1" = "clipboard" ] || [ "$1" = "primary" ]; then 70 xdotool type "$(xclip -o -selection "$1")" 71 exit 0 72 fi 73 74 _passfile="${pass_dir}/${1}.gpg" 75 if [ -n "$prefix" ]; then 76 xdotool type "$prefix" 77 fi 78 case "${_passfile}" in 79 */2fa-*) 80 f="$(printf '%s' "${_passfile}" | sed "s,$pass_dir/,,;s,.gpg,,")" 81 p="$(pass otp "$f")";; 82 *) 83 p="$(gpg2 -q -d "${_passfile}")";; 84 esac 85 86 if [ "$typeout" = 1 ]; then 87 printf '%s' "$p" | \ 88 { IFS= read -r pass; printf %s "$pass"; } | \ 89 xdotool type --clearmodifiers --file - 90 if [ "$newline" = 1 ]; then 91 xdotool key Return 92 fi 93 else 94 printf '%s' "$p" | xclip 95 fi 96 } 97 98 typeout=0 99 newline=0 100 prefix="" 101 while :; do 102 case "$1" in 103 -h) 104 show_help 105 exit 0 106 ;; 107 -t) 108 typeout=1 109 ;; 110 -n) 111 newline=1 112 ;; 113 -u) 114 prefix="$2" 115 shift 116 ;; 117 --) # end all options 118 shift 119 break 120 ;; 121 -?*) 122 die 'unknown option specified' 123 ;; 124 *) # No more options 125 break 126 esac 127 shift 128 done 129 130 pass="$(match_password_file "$@")" 131 if [ -n "$pass" ]; then 132 retrieve_password "$pass" 133 else 134 exit 1 135 fi