gpg-agent: patch to provide --foreground option
Martin A. Brown
martin at linux-ip.net
Thu Aug 10 08:48:43 CEST 2006
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Greetings GnuPG developers,
I have recently begun using gpg-agent and have desired to be able to
use one of the common process supervision utilities [0,1,2,3] to
manage the gpg-agent process (to restart gpg-agent in the event the
process croaks for any reason).
My initial workaround [4] seems to work, but I thought I might be
able to provide a patch to gpg-agent which would allow the process
to remain in the foreground, but accept commands on a socket as it
does in --daemon mode.
Attached is a patch which adds the "--foreground" option to the
gpg-agent binary for version gnupg-1.9.21 [5]. I welcome any
feedback about the patch.
- -Martin
[0] http://cr.yp.to/daemontools/supervise.html
[1] http://smarden.org/runit/runsv.8.html
[2] http://offog.org/code/freedt.html
[3] http://www.plope.com/software/supervisor/
http://www.plope.com/software/supervisor2/
[4] My supervised shell script
==========================
#! /bin/bash
#
# -- start up gpg-agent in the foreground
AGENT_FILE="$HOME/.gpg-agent-info"
env - HOME=$HOME \
gpg-agent \
--write-env-file "$AGENT_FILE" \
--no-detach \
--daemon \
sleep 999d
A line in $HOME/.bashrc:
========================
. $HOME/.gpg-agent-info >/dev/null ; export GPG_AGENT_INFO
[5] ftp://ftp.gnupg.org/gcrypt/alpha/gnupg/gnupg-1.9.21.tar.bz2
- --
Martin A. Brown
http://linux-ip.net/
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)
Comment: pgf-0.71 (http://linux-ip.net/sw/pine-gpg-filter/)
iD8DBQFE2tbRHEoZD1iZ+YcRAquTAKC5eBVtHmK92Qc+dmST/zPe7amPbACgjfzp
JFZJYLtEqBG/eU4Dx0/nOvk=
=j6gU
-----END PGP SIGNATURE-----
-------------- next part --------------
diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index fc2a200..3bcacd6 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -74,6 +74,7 @@ enum cmd_and_opt_values
oLogFile,
oServer,
oDaemon,
+ oForeground,
oBatch,
oPinentryProgram,
@@ -108,8 +109,9 @@ static ARGPARSE_OPTS opts[] = {
{ 301, NULL, 0, N_("@Options:\n ") },
- { oServer, "server", 0, N_("run in server mode (foreground)") },
+ { oServer, "server", 0, N_("run in server mode (pipe_server)") },
{ oDaemon, "daemon", 0, N_("run in daemon mode (background)") },
+ { oForeground, "foreground", 0, N_("do not fork") },
{ oVerbose, "verbose", 0, N_("verbose") },
{ oQuiet, "quiet", 0, N_("be somewhat more quiet") },
{ oSh, "sh", 0, N_("sh-style command output") },
@@ -445,6 +447,7 @@ main (int argc, char **argv )
int nogreeting = 0;
int pipe_server = 0;
int is_daemon = 0;
+ int is_foreground = 0;
int nodetach = 0;
int csh_style = 0;
char *logfile = NULL;
@@ -619,6 +622,7 @@ #endif
case oSh: csh_style = 0; break;
case oServer: pipe_server = 1; break;
case oDaemon: is_daemon = 1; break;
+ case oForeground: is_foreground = 1; nodetach = 1; break;
case oDisplay: default_display = xstrdup (pargs.r.ret_str); break;
case oTTYname: default_ttyname = xstrdup (pargs.r.ret_str); break;
@@ -748,7 +752,7 @@ #define GC_OPT_FLAG_NO_ARG_DESC (1UL <<
/* If this has been called without any options, we merely check
whether an agent is already running. We do this here so that we
don't clobber a logfile but print it directly to stderr. */
- if (!pipe_server && !is_daemon)
+ if (!pipe_server && !is_daemon && !is_foreground)
{
log_set_prefix (NULL, JNLIB_LOG_WITH_PREFIX);
check_for_running_agent (0);
@@ -787,7 +791,7 @@ #endif
{ /* this is the simple pipe based server */
start_command_handler (-1, -1);
}
- else if (!is_daemon)
+ else if (!is_daemon && !is_foreground)
; /* NOTREACHED */
else
{ /* Regular server mode */
@@ -829,21 +833,34 @@ #endif
parent_pid = getpid ();
fflush (NULL);
-#ifdef HAVE_W32_SYSTEM
pid = getpid ();
+#ifdef HAVE_W32_SYSTEM
printf ("set GPG_AGENT_INFO=%s;%lu;1\n", socket_name, (ulong)pid);
#else /*!HAVE_W32_SYSTEM*/
- pid = fork ();
- if (pid == (pid_t)-1)
+ if (is_daemon)
{
- log_fatal ("fork failed: %s\n", strerror (errno) );
- exit (1);
+ pid = fork ();
+ if (pid == (pid_t)-1)
+ {
+ log_fatal ("fork failed: %s\n", strerror (errno) );
+ exit (1);
+ }
+ else if (pid)
+ { /* parent; is_daemon = 1 */
+ close(fd);
+ if (opt.ssh_support)
+ close(fd_ssh);
+ }
+ else
+ { /* child; is_daemon = 2 */
+ ++is_daemon;
+ }
}
- else if (pid)
- { /* We are the parent */
- char *infostr, *infostr_ssh_sock, *infostr_ssh_pid;
-
- close (fd);
+
+ char *infostr, *infostr_ssh_sock, *infostr_ssh_pid;
+
+ if ( is_foreground || is_daemon == 1 )
+ { /* We are the proud parent (or in foreground mode) */
/* Create the info string: <name>:<pid>:<protocol_version> */
if (asprintf (&infostr, "GPG_AGENT_INFO=%s:%lu:1",
@@ -871,11 +888,6 @@ #else /*!HAVE_W32_SYSTEM*/
}
}
- *socket_name = 0; /* Don't let cleanup() remove the socket -
- the child should do this from now on */
- if (opt.ssh_support)
- *socket_name_ssh = 0;
-
if (env_file_name)
{
FILE *fp;
@@ -899,7 +911,17 @@ #else /*!HAVE_W32_SYSTEM*/
}
}
+ if (is_daemon == 1)
+ {
+ *socket_name = 0; /* Don't let cleanup() remove the socket -
+ the child should do this from now on */
+ if (opt.ssh_support)
+ *socket_name_ssh = 0;
+ }
+ }
+ if (is_daemon == 1)
+ {
if (argc)
{ /* Run the program given on the commandline. */
if (putenv (infostr))
@@ -953,15 +975,19 @@ #else /*!HAVE_W32_SYSTEM*/
printf ("%s; export SSH_AGENT_PID;\n", infostr_ssh_pid);
}
}
- free (infostr); /* (Note that a vanilla free is here correct.) */
- if (opt.ssh_support)
- {
- free (infostr_ssh_sock);
- free (infostr_ssh_pid);
- }
- exit (0);
}
- /*NOTREACHED*/
+ }
+
+ if (is_foreground || is_daemon == 1)
+ {
+ free (infostr); /* (Note that a vanilla free is here correct.) */
+ if (opt.ssh_support)
+ {
+ free (infostr_ssh_sock);
+ free (infostr_ssh_pid);
+ }
+ if (is_daemon == 1) /* traditional invocation, parent exits */
+ exit (0);
} /* End parent */
/*
More information about the Gnupg-devel
mailing list