diff options
-rw-r--r-- | README | 11 | ||||
-rw-r--r-- | contrib/dmenu/README.md | 10 | ||||
-rwxr-xr-x | contrib/dmenu/passmenu | 15 | ||||
-rw-r--r-- | contrib/emacs/CHANGELOG.md | 4 | ||||
-rw-r--r-- | contrib/emacs/password-store.el | 5 | ||||
-rw-r--r-- | contrib/vim/redact_pass.vim | 7 | ||||
-rw-r--r-- | src/completion/pass.bash-completion | 2 | ||||
-rw-r--r-- | src/completion/pass.fish-completion | 124 | ||||
-rw-r--r-- | src/completion/pass.zsh-completion | 2 | ||||
-rwxr-xr-x | src/password-store.sh | 26 | ||||
-rw-r--r-- | src/platform/darwin.sh | 2 | ||||
-rw-r--r-- | tests/setup.sh | 2 | ||||
-rwxr-xr-x | tests/t0020-show-tests.sh | 5 |
13 files changed, 130 insertions, 85 deletions
@@ -1,8 +1,15 @@ -====================== +=============================== Simple Password Store by Jason Donenfeld Jason@zx2c4.com -====================== + +as forked by Marcin Chrzanowski +=============================== + +In this fork: + +- passmenu is enhanced to work with pass-otp + (https://github.com/tadfisher/pass-otp) This is a very simple password store that encrypts passwords using gpg and places the encrypted password in a directory. It can generate new passwords diff --git a/contrib/dmenu/README.md b/contrib/dmenu/README.md index cc810e2..b4bc81d 100644 --- a/contrib/dmenu/README.md +++ b/contrib/dmenu/README.md @@ -19,9 +19,19 @@ If `--otp-pattern REGEXP` is specified, password IDs matching the regular expression will be interpreted as secrets for OTP-style two-factor authentication. When used with `--otp`, only OTP password IDs will be displayed. +On wayland [dmenu-wl][] is used to replace dmenu and [ydotool][] to replace xdotool. +Note that the latter requires access to the [uinput][] device, so you'll probably +need to add an extra udev rule or similar to give certain non-root users permission. + +# Usage + + passmenu [--type] [--otp] [--infer-otp] [--otp-pattern <regexp>] [dmenu arguments...] [dmenu]: http://tools.suckless.org/dmenu/ [xdotool]: http://www.semicomplete.com/projects/xdotool/ [pass]: http://www.zx2c4.com/projects/password-store/ +[dmenu-wl]: https://github.com/nyyManni/dmenu-wayland +[ydotool]: https://github.com/ReimuNotMoe/ydotool +[uinput]: https://www.kernel.org/doc/html/v4.12/input/uinput.html [pass-otp]: https://github.com/tadfisher/pass-otp diff --git a/contrib/dmenu/passmenu b/contrib/dmenu/passmenu index bb8e7d6..e5635fd 100755 --- a/contrib/dmenu/passmenu +++ b/contrib/dmenu/passmenu @@ -20,6 +20,17 @@ while [[ $# -gt 0 && $finish -eq 0 ]]; do [[ $finish -eq 0 ]] && shift done +if [[ -n $WAYLAND_DISPLAY ]]; then + dmenu=dmenu-wl + xdotool="ydotool type --file -" +elif [[ -n $DISPLAY ]]; then + dmenu=dmenu + xdotool="xdotool type --clearmodifiers --file -" +else + echo "Error: No Wayland or X11 display detected" >&2 + exit 1 +fi + prefix=${PASSWORD_STORE_DIR-~/.password-store} password_files=( "$prefix"/**/*.gpg ) password_files=( "${password_files[@]#"$prefix"/}" ) @@ -33,7 +44,7 @@ if [[ $otp -eq 1 ]]; then password_files=(${filtered_files[@]}) fi -password=$(printf '%s\n' "${password_files[@]}" | dmenu "$@") +password=$(printf '%s\n' "${password_files[@]}" | "$dmenu" "$@") [[ -n $password ]] || exit @@ -50,5 +61,5 @@ if [[ $typeit -eq 0 ]]; then pass $otp_arg show -c "$password" 2>/dev/null else pass $otp_arg show "$password" | { IFS= read -r pass; printf %s "$pass"; } | - xdotool type --clearmodifiers --file - + $xdotool fi diff --git a/contrib/emacs/CHANGELOG.md b/contrib/emacs/CHANGELOG.md index 7173f65..ed85577 100644 --- a/contrib/emacs/CHANGELOG.md +++ b/contrib/emacs/CHANGELOG.md @@ -1,3 +1,7 @@ +# 2.1.5 + +* (bugfix) Fix an infloop on Windows enviroments. + # 2.1.4 * Drop dependency on f library. diff --git a/contrib/emacs/password-store.el b/contrib/emacs/password-store.el index 61c339e..1d23090 100644 --- a/contrib/emacs/password-store.el +++ b/contrib/emacs/password-store.el @@ -88,9 +88,10 @@ or outputs error message on failure." (setq output (concat output text))) :sentinel (lambda (process state) (cond - ((string= state "finished\n") + ((and (eq (process-status process) 'exit) + (zerop (process-exit-status process))) (funcall callback output)) - ((string= state "open\n") (accept-process-output process)) + ((eq (process-status process) 'run) (accept-process-output process)) (t (error (concat "password-store: " state)))))))) (defun password-store--run (&rest args) diff --git a/contrib/vim/redact_pass.vim b/contrib/vim/redact_pass.vim index a3d67e8..2e752fe 100644 --- a/contrib/vim/redact_pass.vim +++ b/contrib/vim/redact_pass.vim @@ -35,6 +35,7 @@ function! s:CheckArgsRedact() " Tell the user what we're doing so they know this worked, via a message and " a global variable they can check + redraw echomsg 'Editing password file--disabled leaky options!' let g:redact_pass_redacted = 1 @@ -48,4 +49,10 @@ augroup redact_pass \,$TMPDIR/pass.?*/?*.txt \,/tmp/pass.?*/?*.txt \ call s:CheckArgsRedact() + " Work around macOS' dynamic symlink structure for temporary directories + if has('mac') + autocmd VimEnter + \ /private/var/?*/pass.?*/?*.txt + \ call s:CheckArgsRedact() + endif augroup END diff --git a/src/completion/pass.bash-completion b/src/completion/pass.bash-completion index 95d3e1e..2d23cbf 100644 --- a/src/completion/pass.bash-completion +++ b/src/completion/pass.bash-completion @@ -72,7 +72,7 @@ _pass_complete_folders () { _pass_complete_keys () { local GPG="gpg" - which gpg2 &>/dev/null && GPG="gpg2" + command -v gpg2 &>/dev/null && GPG="gpg2" local IFS=$'\n' # Extract names and email addresses from gpg --list-keys diff --git a/src/completion/pass.fish-completion b/src/completion/pass.fish-completion index 8637874..0f57dd2 100644 --- a/src/completion/pass.fish-completion +++ b/src/completion/pass.fish-completion @@ -1,28 +1,22 @@ -#!/usr/bin/env fish - # Copyright (C) 2012-2014 Dmitry Medvinsky <me@dmedvinsky.name>. All Rights Reserved. # This file is licensed under the GPLv2+. Please see COPYING for more information. -set PROG 'pass' +set -l PROG 'pass' function __fish_pass_get_prefix - set -l prefix "$PASSWORD_STORE_DIR" - if [ -z "$prefix" ] - set prefix "$HOME/.password-store" + if set -q PASSWORD_STORE_DIR + realpath -- "$PASSWORD_STORE_DIR" + else + echo "$HOME/.password-store" end - echo "$prefix" end function __fish_pass_needs_command - set -l cmd (commandline -opc) - if [ (count $cmd) -eq 1 -a $cmd[1] = $PROG ] - return 0 - end - return 1 + [ (count (commandline -opc)) -eq 1 ] end function __fish_pass_uses_command - set cmd (commandline -opc) + set -l cmd (commandline -opc) if [ (count $cmd) -gt 1 ] if [ $argv[1] = $cmd[2] ] return 0 @@ -39,7 +33,8 @@ function __fish_pass_print set -l ext $argv[1] set -l strip $argv[2] set -l prefix (__fish_pass_get_prefix) - printf '%s\n' "$prefix"/**"$ext" | sed "s#$prefix/\(.*\)$strip#\1#" + set -l matches $prefix/**$ext + printf '%s\n' $matches | sed "s#$prefix/\(.*\)$strip#\1#" end function __fish_pass_print_entry_dirs @@ -55,63 +50,66 @@ function __fish_pass_print_entries_and_dirs __fish_pass_print_entries end +function __fish_pass_git_complete + set -l prefix (__fish_pass_get_prefix) + set -l git_cmd (commandline -opc) (commandline -ct) + set -e git_cmd[1 2] # Drop "pass git". + complete -C"git -C $prefix $git_cmd" +end -complete -c $PROG -e -complete -c $PROG -f -A -n '__fish_pass_needs_command' -a help -d 'Command: show usage help' -complete -c $PROG -f -A -n '__fish_pass_needs_command' -a version -d 'Command: show program version' +complete -c $PROG -f -n '__fish_pass_needs_command' -a help -d 'Command: show usage help' +complete -c $PROG -f -n '__fish_pass_needs_command' -a version -d 'Command: show program version' -complete -c $PROG -f -A -n '__fish_pass_needs_command' -a init -d 'Command: initialize new password storage' -complete -c $PROG -f -A -n '__fish_pass_uses_command init' -s p -l path -d 'Assign gpg-id for specified sub folder of password store' +complete -c $PROG -f -n '__fish_pass_needs_command' -a init -d 'Command: initialize new password storage' +complete -c $PROG -f -n '__fish_pass_uses_command init' -s p -l path -d 'Assign gpg-id for specified sub folder of password store' -complete -c $PROG -f -A -n '__fish_pass_needs_command' -a ls -d 'Command: list passwords' -complete -c $PROG -f -A -n '__fish_pass_uses_command ls' -a "(__fish_pass_print_entry_dirs)" +complete -c $PROG -f -n '__fish_pass_needs_command' -a ls -d 'Command: list passwords' +complete -c $PROG -f -n '__fish_pass_uses_command ls' -a "(__fish_pass_print_entry_dirs)" -complete -c $PROG -f -A -n '__fish_pass_needs_command' -a insert -d 'Command: insert new password' -complete -c $PROG -f -A -n '__fish_pass_uses_command insert' -s e -l echo -d 'Echo the password on console' -complete -c $PROG -f -A -n '__fish_pass_uses_command insert' -s m -l multiline -d 'Provide multiline password entry' -complete -c $PROG -f -A -n '__fish_pass_uses_command insert' -s f -l force -d 'Do not prompt before overwritting' -complete -c $PROG -f -A -n '__fish_pass_uses_command insert' -a "(__fish_pass_print_entry_dirs)" +complete -c $PROG -f -n '__fish_pass_needs_command' -a insert -d 'Command: insert new password' +complete -c $PROG -f -n '__fish_pass_uses_command insert' -s e -l echo -d 'Echo the password on console' +complete -c $PROG -f -n '__fish_pass_uses_command insert' -s m -l multiline -d 'Provide multiline password entry' +complete -c $PROG -f -n '__fish_pass_uses_command insert' -s f -l force -d 'Do not prompt before overwritting' +complete -c $PROG -f -n '__fish_pass_uses_command insert' -a "(__fish_pass_print_entry_dirs)" -complete -c $PROG -f -A -n '__fish_pass_needs_command' -a generate -d 'Command: generate new password' -complete -c $PROG -f -A -n '__fish_pass_uses_command generate' -s n -l no-symbols -d 'Do not use special symbols' -complete -c $PROG -f -A -n '__fish_pass_uses_command generate' -s c -l clip -d 'Put the password in clipboard' -complete -c $PROG -f -A -n '__fish_pass_uses_command generate' -s f -l force -d 'Do not prompt before overwritting' -complete -c $PROG -f -A -n '__fish_pass_uses_command generate' -s i -l in-place -d 'Replace only the first line with the generated password' -complete -c $PROG -f -A -n '__fish_pass_uses_command generate' -a "(__fish_pass_print_entry_dirs)" +complete -c $PROG -f -n '__fish_pass_needs_command' -a generate -d 'Command: generate new password' +complete -c $PROG -f -n '__fish_pass_uses_command generate' -s n -l no-symbols -d 'Do not use special symbols' +complete -c $PROG -f -n '__fish_pass_uses_command generate' -s c -l clip -d 'Put the password in clipboard' +complete -c $PROG -f -n '__fish_pass_uses_command generate' -s f -l force -d 'Do not prompt before overwritting' +complete -c $PROG -f -n '__fish_pass_uses_command generate' -s i -l in-place -d 'Replace only the first line with the generated password' +complete -c $PROG -f -n '__fish_pass_uses_command generate' -a "(__fish_pass_print_entry_dirs)" -complete -c $PROG -f -A -n '__fish_pass_needs_command' -a mv -d 'Command: rename existing password' -complete -c $PROG -f -A -n '__fish_pass_uses_command mv' -s f -l force -d 'Force rename' -complete -c $PROG -f -A -n '__fish_pass_uses_command mv' -a "(__fish_pass_print_entries_and_dirs)" +complete -c $PROG -f -n '__fish_pass_needs_command' -a mv -d 'Command: rename existing password' +complete -c $PROG -f -n '__fish_pass_uses_command mv' -s f -l force -d 'Force rename' +complete -c $PROG -f -n '__fish_pass_uses_command mv' -a "(__fish_pass_print_entries_and_dirs)" -complete -c $PROG -f -A -n '__fish_pass_needs_command' -a cp -d 'Command: copy existing password' -complete -c $PROG -f -A -n '__fish_pass_uses_command cp' -s f -l force -d 'Force copy' -complete -c $PROG -f -A -n '__fish_pass_uses_command cp' -a "(__fish_pass_print_entries_and_dirs)" +complete -c $PROG -f -n '__fish_pass_needs_command' -a cp -d 'Command: copy existing password' +complete -c $PROG -f -n '__fish_pass_uses_command cp' -s f -l force -d 'Force copy' +complete -c $PROG -f -n '__fish_pass_uses_command cp' -a "(__fish_pass_print_entries_and_dirs)" -complete -c $PROG -f -A -n '__fish_pass_needs_command' -a rm -d 'Command: remove existing password' -complete -c $PROG -f -A -n '__fish_pass_uses_command rm' -s r -l recursive -d 'Remove password groups recursively' -complete -c $PROG -f -A -n '__fish_pass_uses_command rm' -s f -l force -d 'Force removal' -complete -c $PROG -f -A -n '__fish_pass_uses_command rm' -a "(__fish_pass_print_entries_and_dirs)" +complete -c $PROG -f -n '__fish_pass_needs_command' -a rm -d 'Command: remove existing password' +complete -c $PROG -f -n '__fish_pass_uses_command rm' -s r -l recursive -d 'Remove password groups recursively' +complete -c $PROG -f -n '__fish_pass_uses_command rm' -s f -l force -d 'Force removal' +complete -c $PROG -f -n '__fish_pass_uses_command rm' -a "(__fish_pass_print_entries_and_dirs)" -complete -c $PROG -f -A -n '__fish_pass_needs_command' -a edit -d 'Command: edit password using text editor' -complete -c $PROG -f -A -n '__fish_pass_uses_command edit' -a "(__fish_pass_print_entries)" +complete -c $PROG -f -n '__fish_pass_needs_command' -a edit -d 'Command: edit password using text editor' +complete -c $PROG -f -n '__fish_pass_uses_command edit' -a "(__fish_pass_print_entries)" -complete -c $PROG -f -A -n '__fish_pass_needs_command' -a show -d 'Command: show existing password' -complete -c $PROG -f -A -n '__fish_pass_uses_command show' -s c -l clip -d 'Put password in clipboard' -complete -c $PROG -f -A -n '__fish_pass_uses_command show' -a "(__fish_pass_print_entries)" +complete -c $PROG -f -n '__fish_pass_needs_command' -a show -d 'Command: show existing password' +complete -c $PROG -f -n '__fish_pass_uses_command show' -s c -l clip -d 'Put password in clipboard' +complete -c $PROG -f -n '__fish_pass_uses_command show' -a "(__fish_pass_print_entries)" # When no command is given, `show` is defaulted. -complete -c $PROG -f -A -n '__fish_pass_needs_command' -s c -l clip -d 'Put password in clipboard' -complete -c $PROG -f -A -n '__fish_pass_needs_command' -a "(__fish_pass_print_entries)" -complete -c $PROG -f -A -n '__fish_pass_uses_command -c' -a "(__fish_pass_print_entries)" -complete -c $PROG -f -A -n '__fish_pass_uses_command --clip' -a "(__fish_pass_print_entries)" - -complete -c $PROG -f -A -n '__fish_pass_needs_command' -a git -d 'Command: execute a git command' -complete -c $PROG -f -A -n '__fish_pass_uses_command git' -a 'init' -d 'Initialize git repository' -complete -c $PROG -f -A -n '__fish_pass_uses_command git' -a 'status' -d 'Show status of the repo' -complete -c $PROG -f -A -n '__fish_pass_uses_command git' -a 'add' -d 'Add changes to the index' -complete -c $PROG -f -A -n '__fish_pass_uses_command git' -a 'commit' -d 'Commit changes to the repo' -complete -c $PROG -f -A -n '__fish_pass_uses_command git' -a 'push' -d 'Push changes to remote repo' -complete -c $PROG -f -A -n '__fish_pass_uses_command git' -a 'pull' -d 'Pull changes from remote repo' -complete -c $PROG -f -A -n '__fish_pass_uses_command git' -a 'log' -d 'View changelog' - -complete -c $PROG -f -A -n '__fish_pass_needs_command' -a find -d 'Command: find a password file or directory matching pattern' -complete -c $PROG -f -A -n '__fish_pass_needs_command' -a grep -d 'Command: search inside of decrypted password files for matching pattern' +complete -c $PROG -f -n '__fish_pass_needs_command' -s c -l clip -d 'Put password in clipboard' +complete -c $PROG -f -n '__fish_pass_needs_command' -a "(__fish_pass_print_entries)" +complete -c $PROG -f -n '__fish_pass_uses_command -c' -a "(__fish_pass_print_entries)" +complete -c $PROG -f -n '__fish_pass_uses_command --clip' -a "(__fish_pass_print_entries)" + +complete -c $PROG -f -n '__fish_pass_needs_command' -a git -d 'Command: execute a git command' +complete -c $PROG -f -n '__fish_pass_uses_command git' -a '(__fish_pass_git_complete)' +complete -c $PROG -f -n '__fish_pass_needs_command' -a find -d 'Command: find a password file or directory matching pattern' +complete -c $PROG -f -n '__fish_pass_needs_command' -a grep -d 'Command: search inside of decrypted password files for matching pattern' +complete -c $PROG -f -n '__fish_pass_uses_command grep' -a '(begin + set -l cmd (commandline -opc) (commandline -ct) + set -e cmd[1 2] # Drop "pass grep". + complete -C"grep $cmd" +end)' diff --git a/src/completion/pass.zsh-completion b/src/completion/pass.zsh-completion index 27ce15a..d911e12 100644 --- a/src/completion/pass.zsh-completion +++ b/src/completion/pass.zsh-completion @@ -124,7 +124,7 @@ _pass_complete_entries_helper () { local IFS=$'\n' local prefix zstyle -s ":completion:${curcontext}:" prefix prefix || prefix="${PASSWORD_STORE_DIR:-$HOME/.password-store}" - _values -C 'passwords' ${$(find -L "$prefix" \( -name .git -o -name .gpg-id \) -prune -o $@ -print 2>/dev/null | sed -e "s#${prefix}/\{0,1\}##" -e 's#\.gpg##' -e 's#\\#\\\\#' | sort):-""} + _values -C 'passwords' ${$(find -L "$prefix" \( -name .git -o -name .gpg-id \) -prune -o $@ -print 2>/dev/null | sed -e "s#${prefix}/\{0,1\}##" -e 's#\.gpg##' -e 's#\\#\\\\#g' -e 's#:#\\:#g' | sort):-""} } _pass_complete_entries_with_subdirs () { diff --git a/src/password-store.sh b/src/password-store.sh index 77f3eda..22e818f 100755 --- a/src/password-store.sh +++ b/src/password-store.sh @@ -9,7 +9,7 @@ set -o pipefail GPG_OPTS=( $PASSWORD_STORE_GPG_OPTS "--quiet" "--yes" "--compress-algo=none" "--no-encrypt-to" ) GPG="gpg" export GPG_TTY="${GPG_TTY:-$(tty 2>/dev/null)}" -which gpg2 &>/dev/null && GPG="gpg2" +command -v gpg2 &>/dev/null && GPG="gpg2" [[ -n $GPG_AGENT_INFO || $GPG == "gpg2" ]] && GPG_OPTS+=( "--batch" "--use-agent" ) PREFIX="${PASSWORD_STORE_DIR:-$HOME/.password-store}" @@ -70,6 +70,7 @@ verify_file() { set_gpg_recipients() { GPG_RECIPIENT_ARGS=( ) GPG_RECIPIENTS=( ) + local gpg_id if [[ -n $PASSWORD_STORE_KEY ]]; then for gpg_id in $PASSWORD_STORE_KEY; do @@ -98,8 +99,9 @@ set_gpg_recipients() { verify_file "$current" - local gpg_id while read -r gpg_id; do + gpg_id="${gpg_id%%#*}" # strip comment + [[ -n $gpg_id ]] || continue GPG_RECIPIENT_ARGS+=( "-r" "$gpg_id" ) GPG_RECIPIENTS+=( "$gpg_id" ) done < "$current" @@ -127,7 +129,7 @@ reencrypt_path() { done gpg_keys="$($GPG $PASSWORD_STORE_GPG_OPTS --list-keys --with-colons "${GPG_RECIPIENTS[@]}" | sed -n 's/^sub:[^idr:]*:[^:]*:[^:]*:\([^:]*\):[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[a-zA-Z]*e[a-zA-Z]*:.*/\1/p' | LC_ALL=C sort -u)" fi - current_keys="$(LC_ALL=C $GPG $PASSWORD_STORE_GPG_OPTS -v --no-secmem-warning --no-permission-warning --decrypt --list-only --keyid-format long "$passfile" 2>&1 | sed -n 's/^gpg: public key is \([A-F0-9]\+\)$/\1/p' | LC_ALL=C sort -u)" + current_keys="$(LC_ALL=C $GPG $PASSWORD_STORE_GPG_OPTS -v --no-secmem-warning --no-permission-warning --decrypt --list-only --keyid-format long "$passfile" 2>&1 | sed -nE 's/^gpg: public key is ([A-F0-9]+)$/\1/p' | LC_ALL=C sort -u)" if [[ $gpg_keys != "$current_keys" ]]; then echo "$passfile_display: reencrypting to ${gpg_keys//$'\n'/ }" @@ -135,7 +137,7 @@ reencrypt_path() { mv "$passfile_temp" "$passfile" || rm -f "$passfile_temp" fi prev_gpg_recipients="${GPG_RECIPIENTS[*]}" - done < <(find "$1" -path '*/.git' -prune -o -iname '*.gpg' -print0) + done < <(find "$1" -path '*/.git' -prune -o -path '*/.extensions' -prune -o -iname '*.gpg' -print0) } check_sneaky_paths() { local path @@ -153,7 +155,7 @@ check_sneaky_paths() { # clip() { - if [[ -n $WAYLAND_DISPLAY ]]; then + if [[ -n $WAYLAND_DISPLAY ]] && command -v wl-copy &> /dev/null; then local copy_cmd=( wl-copy ) local paste_cmd=( wl-paste -n ) if [[ $X_SELECTION == primary ]]; then @@ -161,12 +163,12 @@ clip() { paste_cmd+=( --primary ) fi local display_name="$WAYLAND_DISPLAY" - elif [[ -n $DISPLAY ]]; then + elif [[ -n $DISPLAY ]] && command -v xclip &> /dev/null; then local copy_cmd=( xclip -selection "$X_SELECTION" ) local paste_cmd=( xclip -o -selection "$X_SELECTION" ) local display_name="$DISPLAY" else - die "Error: No X11 or Wayland display detected" + die "Error: No X11 or Wayland display and clipper detected" fi local sleep_argv0="password store sleep on display $display_name" @@ -260,7 +262,7 @@ cmd_version() { ============================================ = pass: the standard unix password manager = = = - = v1.7.3 = + = v1.7.4 = = = = Jason A. Donenfeld = = Jason@zx2c4.com = @@ -353,7 +355,7 @@ cmd_init() { signing_keys+=( --default-key $key ) done $GPG "${GPG_OPTS[@]}" "${signing_keys[@]}" --detach-sign "$gpg_id" || die "Could not sign .gpg_id." - key="$($GPG --verify --status-fd=1 "$gpg_id.sig" "$gpg_id" 2>/dev/null | sed -n 's/^\[GNUPG:\] VALIDSIG [A-F0-9]\{40\} .* \([A-F0-9]\{40\}\)$/\1/p')" + key="$($GPG "${GPG_OPTS[@]}" --verify --status-fd=1 "$gpg_id.sig" "$gpg_id" 2>/dev/null | sed -n 's/^\[GNUPG:\] VALIDSIG [A-F0-9]\{40\} .* \([A-F0-9]\{40\}\)$/\1/p')" [[ -n $key ]] || die "Signing of .gpg_id unsuccessful." git_add_file "$gpg_id.sig" "Signing new GPG id with ${key//[$IFS]/,}." fi @@ -400,7 +402,7 @@ cmd_show() { else echo "${path%\/}" fi - tree -C -l --noreport "$PREFIX/$path" | tail -n +2 | sed -E 's/\.gpg(\x1B\[[0-9]+m)?( ->|$)/\1\2/g' # remove .gpg at end of line, but keep colors + tree -N -C -l --noreport "$PREFIX/$path" 3>&- | tail -n +2 | sed -E 's/\.gpg(\x1B\[[0-9]+m)?( ->|$)/\1\2/g' # remove .gpg at end of line, but keep colors elif [[ -z $path ]]; then die "Error: password store is empty. Try \"pass init\"." else @@ -412,7 +414,7 @@ cmd_find() { [[ $# -eq 0 ]] && die "Usage: $PROGRAM $COMMAND pass-names..." IFS="," eval 'echo "Search Terms: $*"' local terms="*$(printf '%s*|*' "$@")" - tree -C -l --noreport -P "${terms%|*}" --prune --matchdirs --ignore-case "$PREFIX" | tail -n +2 | sed -E 's/\.gpg(\x1B\[[0-9]+m)?( ->|$)/\1\2/g' + tree -N -C -l --noreport -P "${terms%|*}" --prune --matchdirs --ignore-case "$PREFIX" 3>&- | tail -n +2 | sed -E 's/\.gpg(\x1B\[[0-9]+m)?( ->|$)/\1\2/g' } cmd_grep() { @@ -428,7 +430,7 @@ cmd_grep() { passfile="${passfile##*/}" printf "\e[94m%s\e[1m%s\e[0m:\n" "$passfile_dir" "$passfile" echo "$grepresults" - done < <(find -L "$PREFIX" -path '*/.git' -prune -o -iname '*.gpg' -print0) + done < <(find -L "$PREFIX" -path '*/.git' -prune -o -path '*/.extensions' -prune -o -iname '*.gpg' -print0) } cmd_insert() { diff --git a/src/platform/darwin.sh b/src/platform/darwin.sh index f6cc471..9a1fda8 100644 --- a/src/platform/darwin.sh +++ b/src/platform/darwin.sh @@ -39,6 +39,6 @@ qrcode() { fi } -GETOPT="$({ test -x /usr/local/opt/gnu-getopt/bin/getopt && echo /usr/local/opt/gnu-getopt; } || brew --prefix gnu-getopt 2>/dev/null || { which port &>/dev/null && echo /opt/local; } || echo /usr/local)/bin/getopt" +GETOPT="$({ test -x /usr/local/opt/gnu-getopt/bin/getopt && echo /usr/local/opt/gnu-getopt; } || brew --prefix gnu-getopt 2>/dev/null || { command -v port &>/dev/null && echo /opt/local; } || echo /usr/local)/bin/getopt" SHRED="srm -f -z" BASE64="openssl base64" diff --git a/tests/setup.sh b/tests/setup.sh index 5d1e794..20dd7ea 100644 --- a/tests/setup.sh +++ b/tests/setup.sh @@ -52,7 +52,7 @@ fi export GNUPGHOME="$TEST_HOME/gnupg/" chmod 700 "$GNUPGHOME" GPG="gpg" -which gpg2 &>/dev/null && GPG="gpg2" +command -v gpg2 &>/dev/null && GPG="gpg2" # We don't want any currently running agent to conflict. unset GPG_AGENT_INFO diff --git a/tests/t0020-show-tests.sh b/tests/t0020-show-tests.sh index a4b782f..81b87b4 100755 --- a/tests/t0020-show-tests.sh +++ b/tests/t0020-show-tests.sh @@ -15,6 +15,11 @@ test_expect_success 'Test "show" command with spaces' ' [[ $("$PASS" show "I am a cred with lots of spaces") == "BLAH!!" ]] ' +test_expect_success 'Test "show" command with unicode' ' + "$PASS" generate 🏠 && + "$PASS" show | grep -q '🏠' +' + test_expect_success 'Test "show" of nonexistant password' ' test_must_fail "$PASS" show cred2 ' |