neopassmenu.sh 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. #!/usr/bin/env sh
  2. multi=false
  3. clipboard=false
  4. type=false
  5. add=false
  6. otp=false
  7. file=""
  8. dir=""
  9. checkmenu(){
  10. for i in "$@"; do
  11. if command -v "$i" >/dev/null 2>&1; then
  12. echo "$i";
  13. break;
  14. fi
  15. done
  16. }
  17. if [ -n "$WAYLAND_DISPLAY" ]; then
  18. x11=false
  19. if [ -z "$DMENU_COMMAND" ]; then
  20. dmenu="$(checkmenu dmenu-wl bemenu tofi yofi wofi)"
  21. case "$dmenu" in
  22. yofi)
  23. dmenu="yofi dialog"
  24. ;;
  25. wofi)
  26. dmenu="wofi -dmenu"
  27. ;;
  28. esac
  29. else
  30. dmenu="$DMENU_COMMAND"
  31. fi
  32. else
  33. x11=true
  34. if [ -z "$DMENU_COMMAND" ]; then
  35. dmenu="$(checkmenu dmenu rofi bemenu)"
  36. case "$dmenu" in
  37. rofi)
  38. dmenu="rofi -dmenu"
  39. ;;
  40. esac
  41. else
  42. dmenu="$DMENU_COMMAND"
  43. fi
  44. fi
  45. prompt_prefix="$(case "$(echo "$dmenu" | cut -d " " -f 1)" in
  46. tofi)
  47. printf "%s" "--prompt="
  48. ;;
  49. *)
  50. printf "%s" "-p "
  51. ;;
  52. esac
  53. )"
  54. if [ -z "$dmenu" ]; then
  55. echo "No menu found, specify menu with the DMENU_COMMAND environment variable or install a known menu"
  56. exit 1;
  57. fi
  58. usage="$(printf "USAGE:\nneopassmenu [OPTS] [Pass Entry]\n\nOptions:\n-a\t\tGenerate or modify a password\n-c\t\tCopy to clipboard instead of printing to stdout\n-t\t\tSimulate typing instead of printing to stdout\n-m\t\tSelect a specific line from a multiline file\n-o\t\tGet an otp instead of the password file (precedence over -m)\n-h\t\tPrint usage information\n\nCONFIGURATION:\nEnvironement variables:\nDMENU_COMMAND\tSpecify dmenu command (default: dmenu)")"
  59. cd "${PASSWORD_STORE_DIR:-"$HOME/.password-store"}" || exit 2
  60. while [ "$#" -gt 0 ]; do
  61. case "$1" in
  62. -a)
  63. add=true
  64. shift
  65. ;;
  66. -c)
  67. clipboard=true
  68. type=false
  69. shift
  70. ;;
  71. -t)
  72. clipboard=false
  73. type=true
  74. shift
  75. ;;
  76. -m)
  77. multi=true
  78. shift
  79. ;;
  80. -h)
  81. echo "$usage"
  82. exit 0
  83. ;;
  84. -o)
  85. otp=true
  86. shift
  87. ;;
  88. *)
  89. if [ -f "$1" ] || [ -f "${1}.gpg" ]; then
  90. file="$1"
  91. shift
  92. elif [ -d "$1" ]; then
  93. dir="$1"
  94. shift
  95. else
  96. echo "$usage" >&2
  97. exit 1
  98. fi
  99. ;;
  100. esac
  101. done
  102. if [ -z "$file" ]; then
  103. while true; do
  104. file="$(printf "..\n%s" "$(find "./$dir" -maxdepth 1)" | sed -e 's#^'"./$dir"'##;s#^/##;s/.gpg$//' -e '/^$/d; /^.gpg-id$/d; /^.git\(attributes\)\{0,1\}$/d' | $dmenu $prompt_prefix"Choose Password")"
  105. if [ -z "$dir" ]; then
  106. newdir="$file"
  107. else
  108. newdir="${dir%/}/$file"
  109. fi
  110. if [ -z "$file" ]; then
  111. exit 127
  112. elif [ "$file" = ".." ]; then
  113. dir="${dir%/}"
  114. if echo "$dir" | grep -q "/"; then
  115. dir="${dir%/*}"
  116. else
  117. dir=""
  118. fi
  119. elif [ -d "$newdir" ]; then
  120. dir="$newdir"
  121. elif [ -f "$newdir" ] || [ -f "${newdir}.gpg" ] || "$add"; then
  122. file="$newdir"
  123. break
  124. else
  125. break
  126. fi
  127. done
  128. fi
  129. if "$add"; then
  130. if [ -f "${file}.gpg" ]; then
  131. pass "$file" > /tmp/pass.txt
  132. fi
  133. printf "\n\n%s" "$(dd count=2 if=/dev/random of=/dev/stdout 2>/dev/null ibs=512 obs=512 | uuencode -m /dev/stdout | tail -n +2 | tr -d '\n')" >> /tmp/pass.txt
  134. fileopener /tmp/pass.txt || notify-send "Error $?"
  135. if [ -n "$(cat /tmp/pass.txt)" ]; then
  136. save="$(printf "yes\nno" | $dmenu $prompt_prefix "Save changes? ")"
  137. if [ "$save" = "yes" ]; then
  138. cat /tmp/pass.txt | pass add -m -f "$file"
  139. fi
  140. rm /tmp/pass.txt
  141. exit 0
  142. fi
  143. rm /tmp/pass.txt
  144. exit 1
  145. fi
  146. if ! [ -f "$file" ] && ! [ -f "${file}.gpg" ]; then
  147. exit 127
  148. fi
  149. if ! $otp; then
  150. password_lines="$(pass "$file")"
  151. else
  152. password_lines="$(pass otp "$file")"
  153. fi
  154. if $multi && ! $otp; then
  155. sel_password="$(echo "$password_lines" | sed 'h; s/^.\{1,2\}//; s/./*/g; x; s/^\(.\{1,2\}\).*/\1/; G; s/\n//' | $dmenu)"
  156. password_lines="$(echo "$password_lines" | grep -x "$(echo "$sel_password" | sed 'y/*/./' )")"
  157. # Sed script:
  158. # Copy pattern space (line) to hold space. Pattern space: Foo Hold space: Foo
  159. # Delete first or first two characters in pattern space. Pattern space: o Hold space: Foo
  160. # Replace every character in patter space with "*", Pattern space: * Hold Space: Foo
  161. # Swap pattern space with hold space. Pattern Space: Foo Hold space: *
  162. # Delete all the characters in pattern space after the first two. Pattern Space: Fo Hold Space: *
  163. # Append newline followed by the Hold Space to the Pattern Space. Pattern Space: Fo\n* Hold Space: *
  164. # Remove the (supposedly only) newline from the pattern space. Pattern Space: Fo* Hold Space: *
  165. # Sed automatically prints the pattern space at the end of a script (unless the -n option is given). Output: Fo*
  166. fi
  167. if [ -z "$password_lines" ]; then
  168. "No password found or selected"
  169. fi
  170. if $clipboard; then
  171. if $x11; then
  172. printf "%s" "$password_lines" | xclip -in -selection clipboard
  173. else
  174. printf "%s" "$password_lines" | wl-copy -n
  175. fi
  176. exit 0
  177. elif $type; then
  178. if $x11; then
  179. printf "%s" "$password_lines" | xdotool type --clearmodifiers --file -
  180. else
  181. printf "%s" "$password_lines" | ydotool type --file -
  182. fi
  183. exit 0
  184. fi
  185. echo "$password_lines"