pinentry-curses unusable with gpg-agent --no-detach

Ciprian Dorin Craciun ciprian.craciun at
Fri Feb 6 07:54:05 CET 2015

On Thu, Feb 5, 2015 at 6:38 PM, Matt Garman <matthew.garman at> wrote:
> Steps to demonstrate issue:
> (1) Start gpg-agent with --no-detach option
> (2) Make sure $DISPLAY is not set to force pinentry to fallback to curses
> (3) Attempt to decode a gpg-encrypted file to trigger pinentry
> [...]
> (I realize the gpg-agent --no-detach option is meant for debugging,
> but we are intending to modify gpg to not use the agent if it's not
> running on the same TTY as gpg.  Without --no-detach, agent runs
> without a TTY, and our gpg modification renders agent useless.  But
> the behavior described above occurs without any gpg modification.)

Welcome to my worst nightmare:  trying to make GnuPG agent (and for
that matter the SSH agent) runnable in the foreground.  (My purpose
was to run it under a process supervisor like `runit` or `s6`, but

Short answer:  you can't convince any of these agents to behave and
run in the foreground.

What is worse is that no matter how you configure GnuPG agent or
`pinentry-curses` to use a certain TTY, it will always "finds" the
"current" TTY your GnuPG is running on.  (And I've tried to write my
own `pinentry-curses` wrapper that was set to GnuPG agent with
`--pinentry-program`, and the wrapper calls `pinentry-curses` with all
the right parameters like `--ttyname`.)

However hope is not lost...  I did modify that wrapper script to
actually mangle the protocol and always replace the `OPTION ttyname`
(and others) commands with hardcoded values.  Below is the portion of
the wrapper script you might find useful. (Just replace `/dev/tty`
with a proper value. In my case the uses some tricks to open it on the
11th virtual console).

Thus run `gpg-agent` like you would normaly do (i.e. let it fork into
the background), and use this trick.

pinentry-curses \
        --timeout 6 \
        --display __none__ \
        --ttyname /dev/tty \
        --ttytype linux \
        --lc-ctype en_US.utf8 \
        --lc-messages en_US.utf8 \
< <(
    exec sed -u -r \
            -e 's|^OPTION display=.*$|OPTION display=__none__|' \
            -e 's|^OPTION ttyname=.*$|OPTION ttyname=/dev/tty|' \
            -e 's|^OPTION ttytype=.*$|OPTION ttytype=linux|' \
            -e 's|^OPTION lc-ctype=.*$|OPTION lc-ctype=en_US.utf8|' \
            -e 's|^OPTION lc-messages=.*$|OPTION lc-messages=en_US.utf8|'

For the record I've opened a similar thread on this subject in 2009
and then 2010 without any real solution:

Hopefully you are more lucky,

P.S.:  I really like GnuPG, and I salute the developers effort.
However the way the GnuPG agent integrates with other software (mainly
process supervisors) and the PIN entry, are really abysmal...  Some
updates in this regard are welcome and in fact quite easy.

Below is a patch I did in 2009 to add a new option `--daemon-fg` which
makes GnuPG agent behave like in `--daemon` mode but without forking
into the background.  (Although the patch was trivial was not

More information about the Gnupg-users mailing list