If you use GPG, you are probably familiar with the situation where suddenly the pinentry program pops up and interrupts whatever you're doing. Maybe you're in the middle of a game, maybe you are deeply engrossed in tracking down a bug, whatever. That pinentry is *intrusive*; it interrupts your thoughts and your actions, demanding immediate attention.

I was not surprised to find questions online asking how to make it non-intrusive; I *was* surprised that there was no solution offered. Eventually, after walking me into a nest of Biters one too many times, I hacked together a solution.

Caveat lector, as usual. For me, all this affects is the background syncing of my email and calendar, which is fairly infrequent in any case. It *blocks* pinentry until you tell it to go ahead and show you the dialog. You can check its state by calling it with `--bar`; it'll return `!!` if it needs attention, and `X` if it doesn't. This can be used to put the status in a bar, like i3bar or polybar. If your bar allows interactions, you can have it call the script with `--yes` on click, which will unblock the script and call your pinentry GUI.

Hopefully this helps other people fix a curious omission in the whole GPG pinentry workflow.

#!/bin/sh
# A non-intrusive GPG pinentry.
# The purpose of this script is to prevent GPG's pinentry from popping up and
# interrupting the user. It does this by blocking on a lockfile; running it
# with an argument removes the lockfile and unblocks the script, which can
# then call the pinentry GUI program.
#
# HOW TO USE
# 1. `cp THISSCRIPT ~/.local/bin/pinentry-preexec`
# 2. `chmod +x ~/.local/bin/pinentry-preexec`
# 3. Edit ~/.gnupg/gpg-agent.conf and change (or add) the line:
#    `pinentry-program ${HOME}/.local/bin/pinentry-preexec`
# 4. Optionally, if you're using a WM bar, call this script with
#    the `--bar` argument to get the status of the agent, and set
#    the action command to `--yes`. An example for polybar is at the
#    end of this file.
# 5. Reload your gpg agent:
#    `gpg-connect-agent reloadagent /bye`
# 6. Test it! Do something to trigger pinentry.

PINENTRY=/usr/bin/pinentry-rofi
LOCKDIR="${HOME}/.local/share/pinentry-preexec"
LOCKFILE="${LOCKDIR}/lock"
UNBLOCKED="X"
BLOCKED="!!"

test -d "$LOCKDIR" || 
	mkdir "$LOCKDIR"

test "$1" == "--bar" &&
	( test -f "$LOCKFILE" &&
	  echo -n "$BLOCKED" ||
	  echo -n "$UNBLOCKED" ) &&
	exit 0

test "$1" == "--yes" &&
	rm -f "$LOCKFILE" &&
	exit 0

test -f "$LOCKFILE" ||
	touch "$LOCKFILE"

while [[ -f "$LOCKFILE" ]]; do
	sleep 1
done

rm -f "$LOCKFILE"
exec $PINENTRY "$@"

###############################################################################
# Polybar configuration example
###############################################################################
# 
# # Create a module...
# 
# [module/pinentry]
# type = custom/script
# interval = 1
# label-padding = 1
# exec = ${env:HOME}/.local/bin/pinentry-preexec --bar
# click-left = ${env:HOME}/.local/bin/pinentry-preexec --yes
#
# # ... and add the module to your bar
#
# modules-right = alsa fm pinentry powermenu