tty_get_ttyname breaks gpg-agent/pinentry?

Hank Leininger Hank Leininger <>
Wed Jul 2 17:27:02 2003


It appears that tty_get_ttyname added in 1.2.2 breaks gpg-agent / pinentry
on Linux 2.4 / glibc 2.2 at least (although if so I'm surprised it hasn't
been reported already, but I can't see any references on gnupg-users or

gpg-agent thinks it starts up fine, but when gpg tries to use it:

timmy:~(33)$ gpg -a -o foo.asc -se foo

You need a passphrase to unlock the secret key for
user: "Hank Leininger <>"
1024-bit DSA key, ID 861AA6F1, created 2001-07-09

gpg: cancelled by user
gpg: no default secret key: bad passphrase
gpg: foo: sign+encrypt failed: bad passphrase

(I touched nothing after the first 'enter'.)

debug-all doesn't help much, but when strace -f'ing gpg-agent, I see:

[pid 23675] execve("/usr/local/bin/pinentry", ["pinentry", [snip]
[blah blah]
[pid 23675] open("/dev/tty", O_RDONLY)  = -1 ENXIO (No such device or
[pid 23675] write(1, "ERR 111 canceled", 16) = 16
[pid 23670] <... read resumed> "ERR 111 canceled", 1002) = 16

..Tracing backwards, it looks like pinentry gets passed the tty from
gpg-agent, which in turn gets it from gpg.  In 1.2.1 passphrase.c calls
ttyname(3) and gets /dev/pts/56 or whatever--correct, and everything works.

In 1.2.2 calls to ttyname(3) have been replaced with the new function
tty_get_ttyname in util/ttyio.c.  This uses ctermid(3), which works, er,
differently from ttyname(3); on Linux it seems to always returns '/dev/tty'
(and in fact, tty_get_ttyname has comments to that effect, and has a
hardcoded '/dev/tty' if it can't call ctermid(3)).  This works fine for gpg
for normal interactive use I suppose, but kills a previously working gpg +
gpg-agent + pinentry.

Prior to tracking it down to tty_get_ttyname, no amount of fiddling with
gpg-agent's no-detach, keep-tty, etc options worked around the problem.
I haven't yet tried just ripping out tty_get_ttyname and putting ttyname(3)
calls back in; presumably it was added for a reason :-P

At least one other person has been bitten by this so far (cc'ed):


Hank Leininger <>