In this patch, I've moved the filelock and all clipboard calls to after dmenu. This allows you to escape dmenu without effecting the clipboard. Say "xyz" is in your clipboard. You run passmenu and select a url, login and password. Then you start passmenu again, but change your mind and hit escape.
The behavior previously would restore your clipboard to "xyz". The new
behavior keeps the selected passwords in queue. I find this behavior
preferable.
Calling dmenu sooner should also have a small added benefit of making
the start of the program feel somewhat faster on slow machines.
I'm attaching two files.
passmenu_multi-clip.patch # Contains 11 commits.
0001-Delayed-file-lock-improves-corner-case.patch # Contains 1 commit.
e6f32f4d33fe022c4b13def31c401890298e5b1e
contrib/dmenu/passmenu | 51 +++++++++++++++++++++++++++-----------------------
1 file changed, 28 insertions(+), 23 deletions(-)
diff --git a/contrib/dmenu/passmenu b/contrib/dmenu/passmenu
index 68b4150..40dfe97 100755
--- a/contrib/dmenu/passmenu
+++ b/contrib/dmenu/passmenu
@@ -17,25 +17,37 @@ prefix="${PASSWORD_STORE_DIR:-$HOME/.password-store}"
password_files=( "$prefix"/**/*.gpg )
password_files=( "${password_files[@]#"$prefix"/}" )
password_files=( "${password_files[@]%.gpg}" )
-password=( ${password:-""} )
-before=( "${before:-}" )
-userID="$(id -u $(whoami))"
-stalelock=( "${stalelock:-""}" )
-stalelock=( "$(find '/tmp' -maxdepth 1 -name "passmenulock."$userID".*" -user
$(whoami) -print0 -quit)" ) &&
-cleanup=True || { true; cleanup=False; }
+password=( '' )
+cleanup=( '' )
+before=( '' )
+userID=( "$(id -u $(whoami))" )
_finish () {
- [[ -n $before ]] &&
+ [[ True == $cleanup ]] &&
printf "$before" | base64 -d | xclip -sel "$X_SELECTION" -i
[[ True = "$cleanup" ]] &&
if compgen -G "/tmp/passmenulock.1000*" >/dev/null 2>&1 ;then
- rmdir /tmp/passmenulock."$userID".* >/dev/null 2>&1
+ rmdir /tmp/passmenulock.*.*."$$" >/dev/null 2>&1
fi
exit
}
+
+## dmenu exits on KeyPress not KeyRelease.
+# It might be nice to send KeyRelease event to some dummy window.
+# psydocode: xdotool getwindowfocus; create dummy window;
+# exec dmenu; close dummy window; restore focus.
+for password in $(printf '%s\n' "${password_files[@]}" | dmenu -f "$@"); do
+ passel+=("$password")
+done
+
+[[ -n $password ]] || exit
+
trap _finish EXIT
-## Clearing stale Xclip loops avoids a posible race condition.
+## Clearing old filelock(s).
+umask 077
+stalelock=( "${stalelock:-''}" )
+stalelock=( "$(find '/tmp' -maxdepth 1 -name "passmenulock."$userID".*" -user
$(whoami) -print0 -quit)" ) &&
if test -n "$stalelock" ;then
report=( "$(ps -u $(id -u $(whoami)) aux | grep "bash" |
grep "passmenu" | grep -v "$$")" )
@@ -44,26 +56,19 @@ if test -n "$stalelock" ;then
if [[ "$report" == *"$stalePID"* ]] ;then
kill "$stalePID" || exit 1
else
- rmdir /tmp/passmenulock.$userID.* >/dev/null 2>&1 || exit 1
+ rmdir /tmp/passmenulock."$userID".* >/dev/null 2>&1 ||
+ { echo ":: Unable to clear old filelock"; exit 1; }
fi
fi
-## dmenu exits on KeyPress not KeyRelease.
-# It would be nice to send KeyRelease event to some dummy window.
-# psydocode: xdotool getwindowfocus; create dummy window;
-# exec dmenu; close dummy window; restore focus.
-for password in $(printf '%s\n' "${password_files[@]}" | dmenu -f "$@"); do
- passel+=("$password")
-done
-
-[[ -n $password ]] || exit
-# It would be nice to first somehow test if string exists.
-before="$(xclip -sel "$X_SELECTION" -o 2>/dev/null | base64)" || true
-
-umask 077
+## Adding a new filelock
( mktemp -d "/tmp/passmenulock."$userID".XXXXXXXXXX"."$$" >/dev/null 2>&1 &&
cleanup=True ||
{ echo >&2 ":: Unable to make a filelock."; exit 1; } )
+cleanup=True
+# It would be nice to first first test if string exists.
+before="$(xclip -sel "$X_SELECTION" -o 2>/dev/null | base64)" || true
+
if [[ $typeit -eq 0 ]]; then
if [ ${#passel[@]} -gt "1" ]; then
round=0
--
At your service,
mitfree
http://ampling.com
From 1d2e5d9d0b3e46e1ce72e4151193eb648d668176 Mon Sep 17 00:00:00 2001 From: ampling <[email protected]> Date: Fri, 8 Apr 2016 23:38:57 -0400 Subject: [PATCH 01/11] Adding xclip loop to select multiple pass entries. --- contrib/dmenu/passmenu | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/contrib/dmenu/passmenu b/contrib/dmenu/passmenu index 7a9c517..b80399c 100755 --- a/contrib/dmenu/passmenu +++ b/contrib/dmenu/passmenu @@ -4,22 +4,27 @@ shopt -s nullglob globstar typeit=0 if [[ $1 == "--type" ]]; then - typeit=1 - shift + typeit=1 + shift fi +X_SELECTION="$PASSWORD_STORE_X_SELECTION" prefix=${PASSWORD_STORE_DIR-~/.password-store} + password_files=( "$prefix"/**/*.gpg ) password_files=( "${password_files[@]#"$prefix"/}" ) password_files=( "${password_files[@]%.gpg}" ) -password=$(printf '%s\n' "${password_files[@]}" | dmenu "$@") +if [[ $typeit -eq 0 ]]; then + for password in $(printf '%s\n' "${password_files[@]}" | + dmenu -f "$@"); do + pass show $password | + xclip -l 1 -quiet -sel $X_SELECTION + done [[ -n $password ]] || exit -if [[ $typeit -eq 0 ]]; then - pass show -c "$password" 2>/dev/null else - pass show "$password" | { read -r pass; printf %s "$pass"; } | - xdotool type --clearmodifiers --file - + pass show "$password" | { read -r pass; printf %s "$pass"; } | + xdotool type --clearmodifiers --file - fi -- 2.8.0 From 4b003d9bbd9b79d71250aeee029468806bf16e09 Mon Sep 17 00:00:00 2001 From: ampling <[email protected]> Date: Sat, 9 Apr 2016 00:46:26 -0400 Subject: [PATCH 02/11] Add condition to skip xclip loop on 1 selection. --- contrib/dmenu/passmenu | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/contrib/dmenu/passmenu b/contrib/dmenu/passmenu index b80399c..ddfb07f 100755 --- a/contrib/dmenu/passmenu +++ b/contrib/dmenu/passmenu @@ -17,13 +17,20 @@ password_files=( "${password_files[@]%.gpg}" ) if [[ $typeit -eq 0 ]]; then for password in $(printf '%s\n' "${password_files[@]}" | - dmenu -f "$@"); do - pass show $password | - xclip -l 1 -quiet -sel $X_SELECTION + dmenu -f "$@"); do + lot+=($password) done -[[ -n $password ]] || exit + [[ -n $password ]] || exit + if [ ${#lot[@]} -gt "0" ]; then + for entry in "${lot[@]}"; do + pass show $entry | awk 'NR==1' | + xclip -l 1 -quiet -sel $X_SELECTION + done + else + pass show -c "$password" 2>/dev/null + fi else pass show "$password" | { read -r pass; printf %s "$pass"; } | xdotool type --clearmodifiers --file - -- 2.8.0 From 1e52e9fc165961a94bc834d5fd58ee2669eaae1d Mon Sep 17 00:00:00 2001 From: ampling <[email protected]> Date: Thu, 14 Apr 2016 02:03:17 -0400 Subject: [PATCH 03/11] Restores clipboard to previous state. --- contrib/dmenu/passmenu | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/contrib/dmenu/passmenu b/contrib/dmenu/passmenu index ddfb07f..789d0de 100755 --- a/contrib/dmenu/passmenu +++ b/contrib/dmenu/passmenu @@ -15,22 +15,24 @@ password_files=( "$prefix"/**/*.gpg ) password_files=( "${password_files[@]#"$prefix"/}" ) password_files=( "${password_files[@]%.gpg}" ) -if [[ $typeit -eq 0 ]]; then - for password in $(printf '%s\n' "${password_files[@]}" | - dmenu -f "$@"); do +for password in $(printf '%s\n' "${password_files[@]}" | + dmenu -f "$@"); do lot+=($password) - done +done - [[ -n $password ]] || exit +[[ -n $password ]] || exit - if [ ${#lot[@]} -gt "0" ]; then - for entry in "${lot[@]}"; do - pass show $entry | awk 'NR==1' | - xclip -l 1 -quiet -sel $X_SELECTION +if [[ $typeit -eq 0 ]]; then + xclip -sel clip -o | xclip -sel sec -i + if [ ${#lot[@]} -gt "1" ]; then + for entry in "${lot[@]}"; do + pass show $entry | awk 'NR==1' | + xclip -l 1 -quiet -sel $X_SELECTION &>/dev/null done + xclip -sel sec -o | xclip -sel clip -i else - pass show -c "$password" 2>/dev/null - fi + pass show -c "$password" &>/dev/null + fi else pass show "$password" | { read -r pass; printf %s "$pass"; } | xdotool type --clearmodifiers --file - -- 2.8.0 From 24d3194a119c4503d471d09159d11f3d4c12eda3 Mon Sep 17 00:00:00 2001 From: ampling <[email protected]> Date: Fri, 22 Apr 2016 14:44:51 -0400 Subject: [PATCH 04/11] Clears secondary clipboard after use. --- contrib/dmenu/passmenu | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/contrib/dmenu/passmenu b/contrib/dmenu/passmenu index 789d0de..84b4ae4 100755 --- a/contrib/dmenu/passmenu +++ b/contrib/dmenu/passmenu @@ -8,13 +8,14 @@ if [[ $1 == "--type" ]]; then shift fi -X_SELECTION="$PASSWORD_STORE_X_SELECTION" -prefix=${PASSWORD_STORE_DIR-~/.password-store} +X_SELECTION="${PASSWORD_STORE_X_SELECTION:-clipboard}" +prefix="${PASSWORD_STORE_DIR:-$HOME/.password-store}" password_files=( "$prefix"/**/*.gpg ) password_files=( "${password_files[@]#"$prefix"/}" ) password_files=( "${password_files[@]%.gpg}" ) +## Press Ctrl-Return to continue selecting entries. for password in $(printf '%s\n' "${password_files[@]}" | dmenu -f "$@"); do lot+=($password) @@ -23,15 +24,19 @@ done [[ -n $password ]] || exit if [[ $typeit -eq 0 ]]; then - xclip -sel clip -o | xclip -sel sec -i + xclip -sel "$X_SELECTION" -o | xclip -sel sec -i if [ ${#lot[@]} -gt "1" ]; then + x=0 for entry in "${lot[@]}"; do - pass show $entry | awk 'NR==1' | - xclip -l 1 -quiet -sel $X_SELECTION &>/dev/null + printf '%s\n' "Sending "${lot[$x]}" via "$X_SELECTION"" + pass show $entry | head -n 1 | tr -d '\n' | + xclip -l 1 -quiet -sel "$X_SELECTION" &>/dev/null + x=`expr $x + 1` done - xclip -sel sec -o | xclip -sel clip -i + xclip -sel sec -o | xclip -sel "$X_SELECTION" -i + printf "" | xclip -sel sec -i else - pass show -c "$password" &>/dev/null + pass -c "$password" 2>/dev/null fi else pass show "$password" | { read -r pass; printf %s "$pass"; } | -- 2.8.0 From 8e25eeeab68810ec295fb5d8cb2b4412bcd529f2 Mon Sep 17 00:00:00 2001 From: ampling <[email protected]> Date: Sat, 23 Apr 2016 02:36:55 -0400 Subject: [PATCH 05/11] Limits use of secondary clip to multi selections. --- contrib/dmenu/passmenu | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/dmenu/passmenu b/contrib/dmenu/passmenu index 84b4ae4..a784481 100755 --- a/contrib/dmenu/passmenu +++ b/contrib/dmenu/passmenu @@ -24,17 +24,17 @@ done [[ -n $password ]] || exit if [[ $typeit -eq 0 ]]; then - xclip -sel "$X_SELECTION" -o | xclip -sel sec -i if [ ${#lot[@]} -gt "1" ]; then x=0 + xclip -sel "$X_SELECTION" -o | xclip -sel sec -i for entry in "${lot[@]}"; do printf '%s\n' "Sending "${lot[$x]}" via "$X_SELECTION"" pass show $entry | head -n 1 | tr -d '\n' | xclip -l 1 -quiet -sel "$X_SELECTION" &>/dev/null x=`expr $x + 1` done - xclip -sel sec -o | xclip -sel "$X_SELECTION" -i - printf "" | xclip -sel sec -i + xclip -sel sec -o | xclip -sel "$X_SELECTION" -i + printf "" | xclip -sel sec -i else pass -c "$password" 2>/dev/null fi -- 2.8.0 From 20d3a8a8c55dfb31fa9cdc191b156f7d98ac3a53 Mon Sep 17 00:00:00 2001 From: ampling <[email protected]> Date: Sat, 23 Apr 2016 17:12:29 -0400 Subject: [PATCH 06/11] Changes variables and comments for readability. --- contrib/dmenu/passmenu | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/contrib/dmenu/passmenu b/contrib/dmenu/passmenu index a784481..45eb66f 100755 --- a/contrib/dmenu/passmenu +++ b/contrib/dmenu/passmenu @@ -8,30 +8,31 @@ if [[ $1 == "--type" ]]; then shift fi -X_SELECTION="${PASSWORD_STORE_X_SELECTION:-clipboard}" +X_SELECTION="${PASSWORD_STORE_X_SELECTION:-primary}" prefix="${PASSWORD_STORE_DIR:-$HOME/.password-store}" password_files=( "$prefix"/**/*.gpg ) password_files=( "${password_files[@]#"$prefix"/}" ) password_files=( "${password_files[@]%.gpg}" ) -## Press Ctrl-Return to continue selecting entries. +## dmenu exits on KeyPress. +## We should send KeyRelease event to some dummy window. for password in $(printf '%s\n' "${password_files[@]}" | dmenu -f "$@"); do - lot+=($password) + passel+=($password) done [[ -n $password ]] || exit if [[ $typeit -eq 0 ]]; then - if [ ${#lot[@]} -gt "1" ]; then - x=0 + if [ ${#passel[@]} -gt "1" ]; then + round=0 xclip -sel "$X_SELECTION" -o | xclip -sel sec -i - for entry in "${lot[@]}"; do - printf '%s\n' "Sending "${lot[$x]}" via "$X_SELECTION"" + for entry in "${passel[@]}"; do + printf '%s\n' "Sending "${passel[$round]}" via "$X_SELECTION"" pass show $entry | head -n 1 | tr -d '\n' | xclip -l 1 -quiet -sel "$X_SELECTION" &>/dev/null - x=`expr $x + 1` + round=`expr $round + 1` done xclip -sel sec -o | xclip -sel "$X_SELECTION" -i printf "" | xclip -sel sec -i -- 2.8.0 From 499a2b10739514860744c0179f00a551bd34cd12 Mon Sep 17 00:00:00 2001 From: ampling <[email protected]> Date: Sat, 23 Apr 2016 20:22:08 -0400 Subject: [PATCH 07/11] Adding multi password selection to option --type. --- contrib/dmenu/passmenu | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/contrib/dmenu/passmenu b/contrib/dmenu/passmenu index 45eb66f..1b0339f 100755 --- a/contrib/dmenu/passmenu +++ b/contrib/dmenu/passmenu @@ -40,6 +40,20 @@ if [[ $typeit -eq 0 ]]; then pass -c "$password" 2>/dev/null fi else - pass show "$password" | { read -r pass; printf %s "$pass"; } | - xdotool type --clearmodifiers --file - + if [ ${#passel[@]} -gt "1" ]; then + round=0 + xclip -sel "$X_SELECTION" -o | xclip -sel sec -i + for entry in "${passel[@]}"; do + printf '%s\n' "Sending "${passel[$round]}" via "$X_SELECTION"" + printf '' | xclip -l 1 -quiet -sel "$X_SELECTION" &>/dev/null + pass show "$entry" | { read -r pass; printf %s "$pass"; } | + xdotool type --clearmodifiers --file - + round=`expr $round + 1` + done + xclip -sel sec -o | xclip -sel "$X_SELECTION" -i + printf "" | xclip -sel sec -i + else + pass show "$password" | { read -r pass; printf %s "$pass"; } | + xdotool type --clearmodifiers --file - + fi fi -- 2.8.0 From 67dacee2237bf12dfa0f6e14806971ad2daab7ea Mon Sep 17 00:00:00 2001 From: ampling <[email protected]> Date: Wed, 27 Apr 2016 20:29:07 -0400 Subject: [PATCH 08/11] Locks script and attemps to clear old loop. --- contrib/dmenu/passmenu | 91 ++++++++++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 39 deletions(-) diff --git a/contrib/dmenu/passmenu b/contrib/dmenu/passmenu index 1b0339f..e842f13 100755 --- a/contrib/dmenu/passmenu +++ b/contrib/dmenu/passmenu @@ -4,56 +4,69 @@ shopt -s nullglob globstar typeit=0 if [[ $1 == "--type" ]]; then - typeit=1 - shift + typeit=1 + shift fi -X_SELECTION="${PASSWORD_STORE_X_SELECTION:-primary}" +X_SELECTION="${PASSWORD_STORE_X_SELECTION:-clipboard}" prefix="${PASSWORD_STORE_DIR:-$HOME/.password-store}" password_files=( "$prefix"/**/*.gpg ) password_files=( "${password_files[@]#"$prefix"/}" ) password_files=( "${password_files[@]%.gpg}" ) -## dmenu exits on KeyPress. -## We should send KeyRelease event to some dummy window. -for password in $(printf '%s\n' "${password_files[@]}" | - dmenu -f "$@"); do - passel+=($password) +## Preexisting xclip loops can cause unanticipated behavior. +exec {lock_fd}>/tmp/passmenulock || exit 1 +flock -n "$lock_fd" || + { xclip -sel "$X_SELECTION" -o >/dev/null 2>&1 + flock -n "$lock_fd" || + printf '%s\n' 'Already running' >&2 + exit 1 + } + +## dmenu exits on KeyPress not KeyRelease. +## It would be nice to send KeyRelease event to some dummy window. +for password in $(printf '%s\n' "${password_files[@]}" | + dmenu -f "$@"); do + passel+=($password) done [[ -n $password ]] || exit - + if [[ $typeit -eq 0 ]]; then - if [ ${#passel[@]} -gt "1" ]; then - round=0 - xclip -sel "$X_SELECTION" -o | xclip -sel sec -i - for entry in "${passel[@]}"; do - printf '%s\n' "Sending "${passel[$round]}" via "$X_SELECTION"" - pass show $entry | head -n 1 | tr -d '\n' | - xclip -l 1 -quiet -sel "$X_SELECTION" &>/dev/null - round=`expr $round + 1` - done - xclip -sel sec -o | xclip -sel "$X_SELECTION" -i - printf "" | xclip -sel sec -i - else - pass -c "$password" 2>/dev/null - fi + if [ ${#passel[@]} -gt "1" ]; then + xclip -sel "$X_SELECTION" -o | xclip -sel sec -i + round=0 + for entry in "${passel[@]}"; do + printf '%s\n' "Sending "${passel[$round]}" via "$X_SELECTION"" + pass show $entry | sed '1!d' | tr -d '\n' | + xclip -l 1 -quiet -sel "$X_SELECTION" >/dev/null 2>&1 + ~/bin/beeponce + round=`expr $round + 1` + done + xclip -sel sec -o | xclip -sel "$X_SELECTION" -i + else + pass -c "$password" 2>/dev/null + fi else - if [ ${#passel[@]} -gt "1" ]; then - round=0 - xclip -sel "$X_SELECTION" -o | xclip -sel sec -i - for entry in "${passel[@]}"; do - printf '%s\n' "Sending "${passel[$round]}" via "$X_SELECTION"" - printf '' | xclip -l 1 -quiet -sel "$X_SELECTION" &>/dev/null - pass show "$entry" | { read -r pass; printf %s "$pass"; } | - xdotool type --clearmodifiers --file - - round=`expr $round + 1` - done - xclip -sel sec -o | xclip -sel "$X_SELECTION" -i - printf "" | xclip -sel sec -i - else - pass show "$password" | { read -r pass; printf %s "$pass"; } | - xdotool type --clearmodifiers --file - - fi + command -v xdotool >/dev/null 2>&1 || + { echo >&2 "e: cannot find xdotool."; exit 1; } + if [ ${#passel[@]} -gt "1" ]; then + xclip -sel "$X_SELECTION" -o | xclip -sel sec -i + round=0 + for entry in "${passel[@]}"; do + printf '%s\n' "Sending "${passel[$round]}" via "$X_SELECTION"" + printf '' | xclip -l 1 -quiet -sel "$X_SELECTION" >/dev/null 2>&1 + ~/bin/beeponce + pass show "$entry" | sed '1!d' | tr -d '\n' | + xdotool type --clearmodifiers --file - + round=`expr $round + 1` + done + xclip -sel sec -o | xclip -sel "$X_SELECTION" -i + else + pass show "$password" | sed '1!d' | tr -d '\n' | + xdotool type --clearmodifiers --file - + fi fi +printf "" | xclip -sel sec -i +flock -u "$lock_fd" -- 2.8.0 From 5cee86eb671b0db6229bcb490ca1762ae2eb8d76 Mon Sep 17 00:00:00 2001 From: ampling <[email protected]> Date: Sun, 1 May 2016 17:49:36 -0400 Subject: [PATCH 09/11] A portable process lock avoids unanticipated behavior. --- contrib/dmenu/passmenu | 68 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 19 deletions(-) diff --git a/contrib/dmenu/passmenu b/contrib/dmenu/passmenu index e842f13..021c48f 100755 --- a/contrib/dmenu/passmenu +++ b/contrib/dmenu/passmenu @@ -1,6 +1,7 @@ #!/usr/bin/env bash shopt -s nullglob globstar +set -o errexit typeit=0 if [[ $1 == "--type" ]]; then @@ -9,64 +10,93 @@ if [[ $1 == "--type" ]]; then fi X_SELECTION="${PASSWORD_STORE_X_SELECTION:-clipboard}" +CLIP_TIME="${PASSWORD_STORE_CLIP_TIME:-45}" prefix="${PASSWORD_STORE_DIR:-$HOME/.password-store}" password_files=( "$prefix"/**/*.gpg ) password_files=( "${password_files[@]#"$prefix"/}" ) password_files=( "${password_files[@]%.gpg}" ) -## Preexisting xclip loops can cause unanticipated behavior. -exec {lock_fd}>/tmp/passmenulock || exit 1 -flock -n "$lock_fd" || - { xclip -sel "$X_SELECTION" -o >/dev/null 2>&1 - flock -n "$lock_fd" || - printf '%s\n' 'Already running' >&2 - exit 1 +_finish () { + [[ 1 = "$remove" ]] + rmdir /tmp/passmenu."$uid".* 2>/dev/null + ## kill more child processes here. + # echo $(ps -o pgid=$$ | grep -o [0-9]*) + printf "$buffer" | xclip -sel "$X_SELECTION" -i + exit } +trap _finish EXIT + +_fire () { + stale="$(find /tmp/passmenu."$uid".* -print -quit | + sed -e "s/\/tmp\/passmenu\.[0-9]\{1,6\}\?\..*\.//g")" + report="$(ps -u $(id -u $(whoami)) aux | grep "bash" | + grep "passmenu" | grep -v "$$")" + if [[ "$report" == *"passmenu"* ]] ;then + kill "$stale" && rmdir /tmp/passmenu.$uid.* >/dev/null 2>&1 || exit 1 + else + rmdir /tmp/passmenu.$uid.* >/dev/null 2>&1 || exit 1 + fi +} + +## Clearing stale Xclip loops avoids a posible race condition. +uid="$(id -u $(whoami))" +remove=0 +if compgen -G "/tmp/passmenu.1000*" >/dev/null 2>&1 ;then + question=$(printf 'yes\nno'| + dmenu -nf red -f -p "The clipboard is locked by another process. Kill it with fire?") + if [ "$question" = 'yes' ] ;then + _fire + else + exit 0 + fi +fi ## dmenu exits on KeyPress not KeyRelease. ## It would be nice to send KeyRelease event to some dummy window. +## psydocode: xdotool getwindowfocus; create dummy window; +## exec dmenu; close dummy window; restore focus. for password in $(printf '%s\n' "${password_files[@]}" | dmenu -f "$@"); do - passel+=($password) + passel+=("$password") done [[ -n $password ]] || exit - + +umask 077 +mktemp -d "/tmp/passmenu."$uid".XXXXXXXXXX"."$$" >/dev/null 2>&1 || exit 1 +remove=1 + +buffer="$(xclip -sel "$X_SELECTION" -o)" if [[ $typeit -eq 0 ]]; then if [ ${#passel[@]} -gt "1" ]; then - xclip -sel "$X_SELECTION" -o | xclip -sel sec -i round=0 for entry in "${passel[@]}"; do printf '%s\n' "Sending "${passel[$round]}" via "$X_SELECTION"" - pass show $entry | sed '1!d' | tr -d '\n' | + pass show "$entry" | sed '1!d' | tr -d '\n' | xclip -l 1 -quiet -sel "$X_SELECTION" >/dev/null 2>&1 - ~/bin/beeponce round=`expr $round + 1` done - xclip -sel sec -o | xclip -sel "$X_SELECTION" -i else - pass -c "$password" 2>/dev/null + pass show "$password" | sed '1!d' | tr -d '\n' | + xclip -sel "$X_SELECTION" -i + sleep "$CLIP_TIME" fi else command -v xdotool >/dev/null 2>&1 || { echo >&2 "e: cannot find xdotool."; exit 1; } if [ ${#passel[@]} -gt "1" ]; then - xclip -sel "$X_SELECTION" -o | xclip -sel sec -i round=0 for entry in "${passel[@]}"; do printf '%s\n' "Sending "${passel[$round]}" via "$X_SELECTION"" printf '' | xclip -l 1 -quiet -sel "$X_SELECTION" >/dev/null 2>&1 - ~/bin/beeponce pass show "$entry" | sed '1!d' | tr -d '\n' | xdotool type --clearmodifiers --file - round=`expr $round + 1` done - xclip -sel sec -o | xclip -sel "$X_SELECTION" -i else pass show "$password" | sed '1!d' | tr -d '\n' | xdotool type --clearmodifiers --file - fi fi -printf "" | xclip -sel sec -i -flock -u "$lock_fd" +exit -- 2.8.0 From f8b10ed59edbb293e3728f29fc087ddcf316cc3c Mon Sep 17 00:00:00 2001 From: ampling <[email protected]> Date: Fri, 6 May 2016 11:58:34 -0400 Subject: [PATCH 10/11] Adding strict mode. --- contrib/dmenu/passmenu | 58 ++++++++++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 32 deletions(-) diff --git a/contrib/dmenu/passmenu b/contrib/dmenu/passmenu index 021c48f..e6e2cfc 100755 --- a/contrib/dmenu/passmenu +++ b/contrib/dmenu/passmenu @@ -1,10 +1,11 @@ #!/usr/bin/env bash -shopt -s nullglob globstar -set -o errexit +shopt -s nullglob globstar failglob +set -euo pipefail +tool=${1:-} typeit=0 -if [[ $1 == "--type" ]]; then +if [[ $tool == "--type" ]]; then typeit=1 shift fi @@ -18,56 +19,49 @@ password_files=( "${password_files[@]#"$prefix"/}" ) password_files=( "${password_files[@]%.gpg}" ) _finish () { - [[ 1 = "$remove" ]] - rmdir /tmp/passmenu."$uid".* 2>/dev/null - ## kill more child processes here. - # echo $(ps -o pgid=$$ | grep -o [0-9]*) - printf "$buffer" | xclip -sel "$X_SELECTION" -i + [[ -n $before ]] && + printf "$before" | xclip -sel "$X_SELECTION" -i + [[ True = "$remove" ]] && + if compgen -G "/tmp/passmenu.1000*" >/dev/null 2>&1 ;then + rmdir /tmp/passmenu."$uid".* >/dev/null 2>&1 + fi exit - } +} trap _finish EXIT -_fire () { +## Clearing stale Xclip loops avoids a posible race condition. +uid="$(id -u $(whoami))" +remove=False +if compgen -G "/tmp/passmenu.1000*" >/dev/null 2>&1 ;then stale="$(find /tmp/passmenu."$uid".* -print -quit | sed -e "s/\/tmp\/passmenu\.[0-9]\{1,6\}\?\..*\.//g")" report="$(ps -u $(id -u $(whoami)) aux | grep "bash" | grep "passmenu" | grep -v "$$")" - if [[ "$report" == *"passmenu"* ]] ;then + if [[ "$report" == *"$stale"* ]] ;then kill "$stale" && rmdir /tmp/passmenu.$uid.* >/dev/null 2>&1 || exit 1 else rmdir /tmp/passmenu.$uid.* >/dev/null 2>&1 || exit 1 fi -} - -## Clearing stale Xclip loops avoids a posible race condition. -uid="$(id -u $(whoami))" -remove=0 -if compgen -G "/tmp/passmenu.1000*" >/dev/null 2>&1 ;then - question=$(printf 'yes\nno'| - dmenu -nf red -f -p "The clipboard is locked by another process. Kill it with fire?") - if [ "$question" = 'yes' ] ;then - _fire - else - exit 0 - fi fi ## dmenu exits on KeyPress not KeyRelease. ## It would be nice to send KeyRelease event to some dummy window. ## psydocode: xdotool getwindowfocus; create dummy window; ## exec dmenu; close dummy window; restore focus. -for password in $(printf '%s\n' "${password_files[@]}" | - dmenu -f "$@"); do +password=${password:-} +for password in $(printf '%s\n' "${password_files[@]}" | dmenu -f "$@"); do passel+=("$password") done +before=${before:-} [[ -n $password ]] || exit +before="$(xclip -sel "$X_SELECTION" -o >/dev/null 2>&1)" || true umask 077 -mktemp -d "/tmp/passmenu."$uid".XXXXXXXXXX"."$$" >/dev/null 2>&1 || exit 1 -remove=1 +mktemp -d "/tmp/passmenu."$uid".XXXXXXXXXX"."$$" >/dev/null 2>&1 || +{ echo >&2 ":: Unable to make a filelock."; exit 1; } +remove=True -buffer="$(xclip -sel "$X_SELECTION" -o)" if [[ $typeit -eq 0 ]]; then if [ ${#passel[@]} -gt "1" ]; then round=0 @@ -78,12 +72,12 @@ if [[ $typeit -eq 0 ]]; then round=`expr $round + 1` done else + printf '%s\n' "Sending "$password" via "$X_SELECTION"" pass show "$password" | sed '1!d' | tr -d '\n' | - xclip -sel "$X_SELECTION" -i - sleep "$CLIP_TIME" + xclip -sel "$X_SELECTION" -i && sleep "$CLIP_TIME" fi else - command -v xdotool >/dev/null 2>&1 || + command -v xdotool >/dev/null 2>&1 || { echo >&2 "e: cannot find xdotool."; exit 1; } if [ ${#passel[@]} -gt "1" ]; then round=0 -- 2.8.0 From 90a3613d854085e1fe1416714729aa24e2013cf3 Mon Sep 17 00:00:00 2001 From: ampling <[email protected]> Date: Sat, 7 May 2016 06:14:50 -0400 Subject: [PATCH 11/11] Improved filelock, and more appropriate variable names. --- contrib/dmenu/passmenu | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/contrib/dmenu/passmenu b/contrib/dmenu/passmenu index e6e2cfc..68b4150 100755 --- a/contrib/dmenu/passmenu +++ b/contrib/dmenu/passmenu @@ -17,50 +17,52 @@ prefix="${PASSWORD_STORE_DIR:-$HOME/.password-store}" password_files=( "$prefix"/**/*.gpg ) password_files=( "${password_files[@]#"$prefix"/}" ) password_files=( "${password_files[@]%.gpg}" ) +password=( ${password:-""} ) +before=( "${before:-}" ) +userID="$(id -u $(whoami))" +stalelock=( "${stalelock:-""}" ) +stalelock=( "$(find '/tmp' -maxdepth 1 -name "passmenulock."$userID".*" -user $(whoami) -print0 -quit)" ) && +cleanup=True || { true; cleanup=False; } _finish () { [[ -n $before ]] && - printf "$before" | xclip -sel "$X_SELECTION" -i - [[ True = "$remove" ]] && - if compgen -G "/tmp/passmenu.1000*" >/dev/null 2>&1 ;then - rmdir /tmp/passmenu."$uid".* >/dev/null 2>&1 + printf "$before" | base64 -d | xclip -sel "$X_SELECTION" -i + [[ True = "$cleanup" ]] && + if compgen -G "/tmp/passmenulock.1000*" >/dev/null 2>&1 ;then + rmdir /tmp/passmenulock."$userID".* >/dev/null 2>&1 fi exit } trap _finish EXIT ## Clearing stale Xclip loops avoids a posible race condition. -uid="$(id -u $(whoami))" -remove=False -if compgen -G "/tmp/passmenu.1000*" >/dev/null 2>&1 ;then - stale="$(find /tmp/passmenu."$uid".* -print -quit | - sed -e "s/\/tmp\/passmenu\.[0-9]\{1,6\}\?\..*\.//g")" - report="$(ps -u $(id -u $(whoami)) aux | grep "bash" | - grep "passmenu" | grep -v "$$")" - if [[ "$report" == *"$stale"* ]] ;then - kill "$stale" && rmdir /tmp/passmenu.$uid.* >/dev/null 2>&1 || exit 1 +if test -n "$stalelock" ;then + report=( "$(ps -u $(id -u $(whoami)) aux | grep "bash" | + grep "passmenu" | grep -v "$$")" ) + stalePID=( "$(printf $stalelock | + sed -e "s/\/tmp\/passmenulock\.[0-9]\{1,6\}\?\..*\.//g")" ) + if [[ "$report" == *"$stalePID"* ]] ;then + kill "$stalePID" || exit 1 else - rmdir /tmp/passmenu.$uid.* >/dev/null 2>&1 || exit 1 + rmdir /tmp/passmenulock.$userID.* >/dev/null 2>&1 || exit 1 fi fi ## dmenu exits on KeyPress not KeyRelease. -## It would be nice to send KeyRelease event to some dummy window. -## psydocode: xdotool getwindowfocus; create dummy window; -## exec dmenu; close dummy window; restore focus. -password=${password:-} +# It would be nice to send KeyRelease event to some dummy window. +# psydocode: xdotool getwindowfocus; create dummy window; +# exec dmenu; close dummy window; restore focus. for password in $(printf '%s\n' "${password_files[@]}" | dmenu -f "$@"); do passel+=("$password") done -before=${before:-} [[ -n $password ]] || exit -before="$(xclip -sel "$X_SELECTION" -o >/dev/null 2>&1)" || true +# It would be nice to first somehow test if string exists. +before="$(xclip -sel "$X_SELECTION" -o 2>/dev/null | base64)" || true umask 077 -mktemp -d "/tmp/passmenu."$uid".XXXXXXXXXX"."$$" >/dev/null 2>&1 || -{ echo >&2 ":: Unable to make a filelock."; exit 1; } -remove=True +( mktemp -d "/tmp/passmenulock."$userID".XXXXXXXXXX"."$$" >/dev/null 2>&1 && cleanup=True || + { echo >&2 ":: Unable to make a filelock."; exit 1; } ) if [[ $typeit -eq 0 ]]; then if [ ${#passel[@]} -gt "1" ]; then -- 2.8.0
From e6f32f4d33fe022c4b13def31c401890298e5b1e Mon Sep 17 00:00:00 2001 From: ampling <[email protected]> Date: Fri, 13 May 2016 16:40:32 -0400 Subject: [PATCH] Delayed file-lock improves corner-case. --- contrib/dmenu/passmenu | 51 +++++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/contrib/dmenu/passmenu b/contrib/dmenu/passmenu index 68b4150..40dfe97 100755 --- a/contrib/dmenu/passmenu +++ b/contrib/dmenu/passmenu @@ -17,25 +17,37 @@ prefix="${PASSWORD_STORE_DIR:-$HOME/.password-store}" password_files=( "$prefix"/**/*.gpg ) password_files=( "${password_files[@]#"$prefix"/}" ) password_files=( "${password_files[@]%.gpg}" ) -password=( ${password:-""} ) -before=( "${before:-}" ) -userID="$(id -u $(whoami))" -stalelock=( "${stalelock:-""}" ) -stalelock=( "$(find '/tmp' -maxdepth 1 -name "passmenulock."$userID".*" -user $(whoami) -print0 -quit)" ) && -cleanup=True || { true; cleanup=False; } +password=( '' ) +cleanup=( '' ) +before=( '' ) +userID=( "$(id -u $(whoami))" ) _finish () { - [[ -n $before ]] && + [[ True == $cleanup ]] && printf "$before" | base64 -d | xclip -sel "$X_SELECTION" -i [[ True = "$cleanup" ]] && if compgen -G "/tmp/passmenulock.1000*" >/dev/null 2>&1 ;then - rmdir /tmp/passmenulock."$userID".* >/dev/null 2>&1 + rmdir /tmp/passmenulock.*.*."$$" >/dev/null 2>&1 fi exit } + +## dmenu exits on KeyPress not KeyRelease. +# It might be nice to send KeyRelease event to some dummy window. +# psydocode: xdotool getwindowfocus; create dummy window; +# exec dmenu; close dummy window; restore focus. +for password in $(printf '%s\n' "${password_files[@]}" | dmenu -f "$@"); do + passel+=("$password") +done + +[[ -n $password ]] || exit + trap _finish EXIT -## Clearing stale Xclip loops avoids a posible race condition. +## Clearing old filelock(s). +umask 077 +stalelock=( "${stalelock:-''}" ) +stalelock=( "$(find '/tmp' -maxdepth 1 -name "passmenulock."$userID".*" -user $(whoami) -print0 -quit)" ) && if test -n "$stalelock" ;then report=( "$(ps -u $(id -u $(whoami)) aux | grep "bash" | grep "passmenu" | grep -v "$$")" ) @@ -44,26 +56,19 @@ if test -n "$stalelock" ;then if [[ "$report" == *"$stalePID"* ]] ;then kill "$stalePID" || exit 1 else - rmdir /tmp/passmenulock.$userID.* >/dev/null 2>&1 || exit 1 + rmdir /tmp/passmenulock."$userID".* >/dev/null 2>&1 || + { echo ":: Unable to clear old filelock"; exit 1; } fi fi -## dmenu exits on KeyPress not KeyRelease. -# It would be nice to send KeyRelease event to some dummy window. -# psydocode: xdotool getwindowfocus; create dummy window; -# exec dmenu; close dummy window; restore focus. -for password in $(printf '%s\n' "${password_files[@]}" | dmenu -f "$@"); do - passel+=("$password") -done - -[[ -n $password ]] || exit -# It would be nice to first somehow test if string exists. -before="$(xclip -sel "$X_SELECTION" -o 2>/dev/null | base64)" || true - -umask 077 +## Adding a new filelock ( mktemp -d "/tmp/passmenulock."$userID".XXXXXXXXXX"."$$" >/dev/null 2>&1 && cleanup=True || { echo >&2 ":: Unable to make a filelock."; exit 1; } ) +cleanup=True +# It would be nice to first first test if string exists. +before="$(xclip -sel "$X_SELECTION" -o 2>/dev/null | base64)" || true + if [[ $typeit -eq 0 ]]; then if [ ${#passel[@]} -gt "1" ]; then round=0 -- 2.8.0
signature.asc
Description: signature
_______________________________________________ Password-Store mailing list [email protected] http://lists.zx2c4.com/mailman/listinfo/password-store
