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