Hi,

This is my third patch to passmenu; the last was on May 14th, 2016.

If you install this patch, passmenu lock will have a '.lock' extension.
My first email on May 8th, 2016 better explains why I'm using a file
lock and adding a multiclip feature in the first place. This file lock 
business is just an empty folder which holds the pid of passmenu in the
filename. It's a safe (cross platform) way to prevent two passmenu sessions
from running at the same time. I'm aiming for a more consistent user
experience. 

I hope you find this update to be as stable as I found the last patch.
I'm testing on Linux. I would particularly welcome feedback from others.

For those who like github:
https://github.com/ampling/pass/blob/passmenu_multi-clip/contrib/dmenu/passmenu


From dacf9f38ba38b86b79420d2cc3b25ff0191ed9b2 Mon Sep 17 00:00:00 2001
From: ampling <[email protected]>
Date: Tue, 19 Jul 2016 16:11:10 -0400
Subject: [PATCH] Renamed filelock for clarity.

---
 contrib/dmenu/passmenu | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/contrib/dmenu/passmenu b/contrib/dmenu/passmenu
index 40dfe97..e1835d2 100755
--- a/contrib/dmenu/passmenu
+++ b/contrib/dmenu/passmenu
@@ -26,8 +26,8 @@ _finish () {
   [[ 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.*.*."$$" >/dev/null 2>&1
+  if compgen -G "/tmp/passmenu.1000*" >/dev/null 2>&1 ;then
+    rmdir /tmp/passmenu.*.*."$$".lock >/dev/null 2>&1
   fi
   exit
 }
@@ -47,22 +47,23 @@ trap _finish EXIT
 ## Clearing old filelock(s). 
 umask 077
 stalelock=( "${stalelock:-''}" )
-stalelock=( "$(find '/tmp' -maxdepth 1 -name "passmenulock."$userID".*" -user 
$(whoami) -print0  -quit)" ) &&
+stalelock=( "$(find '/tmp' -maxdepth 1 -name "passmenu."$userID".*" -user 
$(whoami) -print0  -quit -type d)" ) &&
 if test -n "$stalelock" ;then
+  stalename=${stalelock%.*}
   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")" )
+  stalePID=( "$(printf $stalename | 
+  sed -e "s/\/tmp\/passmenu\.[0-9]\{1,6\}\?\..*\.//g")" )
   if [[ "$report" == *"$stalePID"* ]] ;then
     kill "$stalePID" || exit 1
   else
-    rmdir /tmp/passmenulock."$userID".* >/dev/null 2>&1 ||
+    rmdir /tmp/passmenu."$userID".* >/dev/null 2>&1 ||
     { echo ":: Unable to clear old filelock"; exit 1; }
   fi
 fi
 
 ## Adding a new filelock
-( mktemp -d "/tmp/passmenulock."$userID".XXXXXXXXXX"."$$" >/dev/null 2>&1 && 
cleanup=True ||
+( mktemp -d "/tmp/passmenu."$userID".XXXXXXXXXX"."$$".lock >/dev/null 2>&1 && 
cleanup=True ||
   { echo >&2 ":: Unable to make a filelock."; exit 1; } )
 
 cleanup=True
-- 
2.9.0





--
At your service,
mitfree
https://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 dacf9f38ba38b86b79420d2cc3b25ff0191ed9b2 Mon Sep 17 00:00:00 2001
From: ampling <[email protected]>
Date: Tue, 19 Jul 2016 16:11:10 -0400
Subject: [PATCH] Renamed filelock for clarity.

---
 contrib/dmenu/passmenu | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/contrib/dmenu/passmenu b/contrib/dmenu/passmenu
index 40dfe97..e1835d2 100755
--- a/contrib/dmenu/passmenu
+++ b/contrib/dmenu/passmenu
@@ -26,8 +26,8 @@ _finish () {
   [[ 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.*.*."$$" >/dev/null 2>&1
+  if compgen -G "/tmp/passmenu.1000*" >/dev/null 2>&1 ;then
+    rmdir /tmp/passmenu.*.*."$$".lock >/dev/null 2>&1
   fi
   exit
 }
@@ -47,22 +47,23 @@ trap _finish EXIT
 ## Clearing old filelock(s). 
 umask 077
 stalelock=( "${stalelock:-''}" )
-stalelock=( "$(find '/tmp' -maxdepth 1 -name "passmenulock."$userID".*" -user $(whoami) -print0  -quit)" ) &&
+stalelock=( "$(find '/tmp' -maxdepth 1 -name "passmenu."$userID".*" -user $(whoami) -print0  -quit -type d)" ) &&
 if test -n "$stalelock" ;then
+  stalename=${stalelock%.*}
   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")" )
+  stalePID=( "$(printf $stalename | 
+  sed -e "s/\/tmp\/passmenu\.[0-9]\{1,6\}\?\..*\.//g")" )
   if [[ "$report" == *"$stalePID"* ]] ;then
     kill "$stalePID" || exit 1
   else
-    rmdir /tmp/passmenulock."$userID".* >/dev/null 2>&1 ||
+    rmdir /tmp/passmenu."$userID".* >/dev/null 2>&1 ||
     { echo ":: Unable to clear old filelock"; exit 1; }
   fi
 fi
 
 ## Adding a new filelock
-( mktemp -d "/tmp/passmenulock."$userID".XXXXXXXXXX"."$$" >/dev/null 2>&1 && cleanup=True ||
+( mktemp -d "/tmp/passmenu."$userID".XXXXXXXXXX"."$$".lock >/dev/null 2>&1 && cleanup=True ||
   { echo >&2 ":: Unable to make a filelock."; exit 1; } )
 
 cleanup=True
-- 
2.9.0

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/12] 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/12] 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/12] 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/12] 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/12] 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/12] 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/12] 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/12] 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/12] 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/12] 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/12] 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 12/12] 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

Attachment: signature.asc
Description: signature

_______________________________________________
Password-Store mailing list
[email protected]
http://lists.zx2c4.com/mailman/listinfo/password-store

Reply via email to