neopassmenu.sh 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #!/usr/bin/env sh
  2. multi=false
  3. clipboard=false
  4. file=""
  5. dir=""
  6. dmenu="${DMENU_COMMAND:-dmenu}"
  7. usage="$(printf "USAGE:\nneopassmenu [OPTS] [Pass Entry]\n\nOptions:\n-c\t\tCopy to clipboard instead of printing to stdout\n-m\t\tSelect a specific line from a multiline file\n-h\\t\tPrint usage information\n\nCONFIGURATION:\nEnvironement variables:\nDMENU_COMMAND\tSpecify dmenu command (default: dmenu)")"
  8. cd "${PASSWORD_STORE_DIR:-"$HOME/.password-store"}" || exit 2
  9. while [ "$#" -gt 0 ]; do
  10. case "$1" in
  11. -c)
  12. clipboard=true
  13. shift
  14. ;;
  15. -m)
  16. multi=true
  17. shift
  18. ;;
  19. -h)
  20. echo "$usage"
  21. exit 0
  22. ;;
  23. *)
  24. if [ -f "$1" ] || [ -f "${1}.gpg" ] || [ -d "$1" ] ; then
  25. file="$1"
  26. shift
  27. elif [ -d "$1" ]; then
  28. dir="$1"
  29. shift
  30. else
  31. echo "$usage"
  32. exit 1
  33. fi
  34. ;;
  35. esac
  36. done
  37. while true; do
  38. 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)"
  39. if [ -z "$dir" ]; then
  40. newdir="$file"
  41. else
  42. newdir="${dir%/}/$file"
  43. fi
  44. if [ -z "$file" ]; then
  45. exit 127
  46. elif [ "$file" = ".." ]; then
  47. dir="${dir%/}"
  48. if echo "$dir" | grep -q "/"; then
  49. dir="${dir%/*}"
  50. else
  51. dir=""
  52. fi
  53. elif [ -d "$newdir" ]; then
  54. dir="$newdir"
  55. elif [ -f "$newdir" ] || [ -f "${newdir}.gpg" ]; then
  56. file="$newdir"
  57. break
  58. else
  59. break
  60. fi
  61. done
  62. if ! [ -f "$file" ] && ! [ -f "${file}.gpg" ]; then
  63. exit 127
  64. fi
  65. if $clipboard && ! $multi; then
  66. pass -c "$file"
  67. exit 0
  68. fi
  69. password_lines="$(pass "$file")"
  70. if ! $multi; then
  71. echo "$password_lines"
  72. exit 0
  73. fi
  74. password="$(echo "$password_lines" | sed '{ h; s/^.$//; s/^..//; s/./*/g; x; s/^\(..\).*/\1/; G; s/\n//; }' | $dmenu)"
  75. # Sed script:
  76. # Copy pattern space (line) to hold space. Pattern space: Foo Hold space: Foo
  77. # If the patter space is a single character, delete the character (prevents "a" to be outputted as "aa")
  78. # Delete the first two characters of the patter space. Pattern Space: o; Hold space: Foo
  79. # Replace all the characters in the pattern space with the literal "*". Pattern Space: *; Hold space: Foo
  80. # Swap pattern space with hold space. Pattern Space: Foo Hold space: *
  81. # Match the first two characters of the pattern space, then all the rest of the characters
  82. # substitute with the whole match (entire line) with the first submatch (first 2 characters). Pattern Space: Fo Hold Space: *
  83. # Append newline followed by the Hold Space to the Pattern Space. Pattern Space: Fo\n* Hold Space: *
  84. # Remove the (supposedly only) newline from the pattern space. Pattern Space: Fo* Hold Space: *
  85. # Sed automatically prints the pattern space at the end of a script (unless the -n option is given). Output: Fo*
  86. password="$(echo "$password_lines" | grep -xE "$(echo "$password" | sed 'y/*/./' )")"
  87. if "$clipboard"; then
  88. echo "$password" | xclip -selection clipboard -i -
  89. exit 0
  90. fi
  91. echo "$password"