Auto starting the agent does now work on CE.
authorWerner Koch <wk@gnupg.org>
Tue, 4 May 2010 15:21:47 +0000 (15:21 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 4 May 2010 15:21:47 +0000 (15:21 +0000)
NEWS
agent/gpg-agent.c
common/ChangeLog
common/estream.c
common/exechelp-w32ce.c
configure.ac

diff --git a/NEWS b/NEWS
index 78e64b0..6f39200 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -23,6 +23,12 @@ Noteworthy changes in version 2.1.x (under development)
 
  * Support for Windows CE.
 
+ * If the agent's --use-standard-socket option is active, all tools
+   try to start and daemonize the agent on the fly.  In the past this
+   was only supported on W32; on non-W32 systems the new configure
+   option --use-standard-socket may now be used to use this feature by
+   default.
+
 
 Noteworthy changes in version 2.0.13 (2009-09-04)
 -------------------------------------------------
index 89027b5..6d96b52 100644 (file)
@@ -99,7 +99,6 @@ enum cmd_and_opt_values
   oEnablePassphraseHistory,
   oUseStandardSocket,
   oNoUseStandardSocket,
-  oStandardSocketP,
   oFakedSystemTime,
 
   oIgnoreCacheForSigning,
@@ -631,9 +630,8 @@ main (int argc, char **argv )
 
   /* Set default options.  */
   parse_rereadable_options (NULL, 0); /* Reset them to default values. */
-#ifdef HAVE_W32_SYSTEM
-  use_standard_socket = 1;  /* Under Windows we always use a standard
-                               socket.  */
+#ifdef USE_STANDARD_SOCKET
+  use_standard_socket = 1;
 #endif
   
   shell = getenv ("SHELL");
@@ -863,7 +861,11 @@ main (int argc, char **argv )
     }
   
   if (gpgconf_list == 3)
-    agent_exit (!use_standard_socket);
+    {
+      if (use_standard_socket && !opt.quiet)
+        log_info ("configured to use the standard socket\n");
+      agent_exit (!use_standard_socket);
+    }
   else if (gpgconf_list == 2)
     agent_exit (0);
   else if (gpgconf_list)
index 14ca0ef..76d5298 100644 (file)
@@ -1,3 +1,15 @@
+2010-05-04  Werner Koch  <wk@g10code.com>
+
+       * estream.c (_es_get_std_stream): Re-use registered standard fds.
+       (IS_INVALID_FD, ESTREAM_SYS_YIELD): New.
+       (es_func_fd_read, es_func_fd_write, es_func_fd_seek)
+       (es_func_fd_destroy): Implement a dummy stream.
+
+       * exechelp-w32ce.c (build_w32_commandline): Add args FD0_ISNULL
+       and FD1_ISNULL.  Remove arg PGMNAME.  Change callers. 
+       (gnupg_spawn_process_detached): Implement.
+       (gnupg_spawn_process_fd): Implement one special case for now.
+
 2010-05-03  Werner Koch  <wk@g10code.com>
 
        * asshelp.c (lock_agent_spawning, unlock_agent_spawning): New.
@@ -18,7 +30,7 @@
 2010-04-20  Werner Koch  <wk@g10code.com>
 
        * estream.c (es_deinit): New.
-       (es_init_do): Intll atexit handler to flush all streams.
+       (es_init_do): Install atexit handler to flush all streams.
 
        * Makefile.am (common_sources): Add gettime.h.
 
index 47ff94f..3a17910 100644 (file)
@@ -125,6 +125,12 @@ int _setmode (int handle, int mode);
 # define _set_errno(a)  do { errno = (a); } while (0)
 #endif
 
+#ifdef HAVE_W32_SYSTEM
+# define IS_INVALID_FD(a) ((void*)(a) == (void*)(-1))
+#else
+# define IS_INVALID_FD(a) ((a) == -1)
+#endif
+
 
 /* Generally used types.  */
 
@@ -184,9 +190,11 @@ dummy_mutex_call_int (estream_mutex_t mutex)
 #ifdef HAVE_PTH
 # define ESTREAM_SYS_READ  es_pth_read
 # define ESTREAM_SYS_WRITE es_pth_write
+# define ESTREAM_SYS_YIELD() pth_yield (NULL)
 #else
 # define ESTREAM_SYS_READ  read
 # define ESTREAM_SYS_WRITE write
+# define ESTREAM_SYS_YIELD() do { } while (0)
 #endif
 
 /* Misc definitions.  */
@@ -777,10 +785,18 @@ es_func_fd_read (void *cookie, void *buffer, size_t size)
 {
   estream_cookie_fd_t file_cookie = cookie;
   ssize_t bytes_read;
-
-  do 
-    bytes_read = ESTREAM_SYS_READ (file_cookie->fd, buffer, size);
-  while (bytes_read == -1 && errno == EINTR);
+  
+  if (IS_INVALID_FD (file_cookie->fd))
+    {
+      ESTREAM_SYS_YIELD ();
+      bytes_read = 0;
+    }
+  else
+    {
+      do 
+        bytes_read = ESTREAM_SYS_READ (file_cookie->fd, buffer, size);
+      while (bytes_read == -1 && errno == EINTR);
+    }
 
   return bytes_read;
 }
@@ -788,14 +804,21 @@ es_func_fd_read (void *cookie, void *buffer, size_t size)
 /* Write function for fd objects.  */
 static ssize_t
 es_func_fd_write (void *cookie, const void *buffer, size_t size)
-                          
 {
   estream_cookie_fd_t file_cookie = cookie;
   ssize_t bytes_written;
 
-  do
-    bytes_written = ESTREAM_SYS_WRITE (file_cookie->fd, buffer, size);
-  while (bytes_written == -1 && errno == EINTR);
+  if (IS_INVALID_FD (file_cookie->fd))
+    {
+      ESTREAM_SYS_YIELD ();
+      bytes_written = size; /* Yeah:  Success writing to the bit bucket.  */
+    }
+  else
+    {
+      do
+        bytes_written = ESTREAM_SYS_WRITE (file_cookie->fd, buffer, size);
+      while (bytes_written == -1 && errno == EINTR);
+    }
 
   return bytes_written;
 }
@@ -808,13 +831,21 @@ es_func_fd_seek (void *cookie, off_t *offset, int whence)
   off_t offset_new;
   int err;
 
-  offset_new = lseek (file_cookie->fd, *offset, whence);
-  if (offset_new == -1)
-    err = -1;
+  if (IS_INVALID_FD (file_cookie->fd))
+    {
+      _set_errno (ESPIPE);
+      err = -1;
+    }
   else
     {
-      *offset = offset_new;
-      err = 0;
+      offset_new = lseek (file_cookie->fd, *offset, whence);
+      if (offset_new == -1)
+        err = -1;
+      else
+        {
+          *offset = offset_new;
+          err = 0;
+        }
     }
 
   return err;
@@ -829,7 +860,10 @@ es_func_fd_destroy (void *cookie)
 
   if (fd_cookie)
     {
-      err = fd_cookie->no_close? 0 : close (fd_cookie->fd);
+      if (IS_INVALID_FD (fd_cookie->fd))
+        err = 0;
+      else
+        err = fd_cookie->no_close? 0 : close (fd_cookie->fd);
       mem_free (fd_cookie);
     }
   else
@@ -2405,19 +2439,21 @@ _es_get_std_stream (int fd)
         stream = do_fdopen (custom_std_fds[1], "a", 1, 1);
       else if (custom_std_fds_valid[2])
         stream = do_fdopen (custom_std_fds[1], "a", 1, 1);
-    }
-  if (!stream)
-    {
-      /* Standard stream not yet created - do it now.  */
-      if (!fd)
-        stream = do_fpopen (stdin, "r", 1, 1);
-      else if (fd == 1)
-        stream = do_fpopen (stdout, "a", 1, 1);
-      else
-        stream = do_fpopen (stderr, "a", 1, 1);
-
-      if (!stream) /* Fallback: Create a bit bucket.  */
+      
+      if (!stream)
         {
+          /* Second try is to use the standard C streams.  */
+          if (!fd)
+            stream = do_fpopen (stdin, "r", 1, 1);
+          else if (fd == 1)
+            stream = do_fpopen (stdout, "a", 1, 1);
+          else
+            stream = do_fpopen (stderr, "a", 1, 1);
+        }
+      
+      if (!stream) 
+        {
+          /* Last try: Create a bit bucket.  */
           stream = do_fpopen (NULL, fd? "a":"r", 0, 1);
           if (!stream)
             {
@@ -2426,6 +2462,7 @@ _es_get_std_stream (int fd)
               abort();
             }
         }
+
       stream->intern->is_stdstream = 1;
       stream->intern->stdstream_fd = fd;
       if (fd == 2)
index ac7602d..809641c 100644 (file)
@@ -334,8 +334,10 @@ copy_quoted (char *p, const char *string)
 /* Build a command line for use with W32's CreateProcess.  On success
    CMDLINE gets the address of a newly allocated string.  */
 static int
-build_w32_commandline (const char *pgmname, const char * const *argv,
-                      int fd0, int fd1, int fd2, int fd2_isnull,
+build_w32_commandline (const char * const *argv,
+                      int fd0, int fd0_isnull,
+                       int fd1, int fd1_isnull,
+                       int fd2, int fd2_isnull,
                        char **cmdline)
 {
   int i, n;
@@ -347,12 +349,18 @@ build_w32_commandline (const char *pgmname, const char * const *argv,
   *p = 0;
   if (fd0)
     {
-      snprintf (p, 25, "-&S0=%d ", fd0);
+      if (fd0_isnull)
+        strcpy (p, "-&S0=null ");
+      else
+        snprintf (p, 25, "-&S0=%d ", fd0);
       p += strlen (p);
     }
   if (fd1)
     {
-      snprintf (p, 25, "-&S1=%d ", fd1);
+      if (fd1_isnull)
+        strcpy (p, "-&S1=null ");
+      else
+        snprintf (p, 25, "-&S1=%d ", fd1);
       p += strlen (p);
     }
   if (fd2)
@@ -366,7 +374,6 @@ build_w32_commandline (const char *pgmname, const char * const *argv,
   
   *cmdline = NULL;
   n = strlen (fdbuf);
-  n += strlen (pgmname) + 1 + 2; /* (1 space, 2 quoting) */
   for (i=0; (s = argv[i]); i++)
     {
       n += strlen (s) + 1 + 2;  /* (1 space, 2 quoting) */
@@ -381,7 +388,6 @@ build_w32_commandline (const char *pgmname, const char * const *argv,
     return -1;
 
   p = stpcpy (p, fdbuf);
-  p = copy_quoted (p, pgmname);
   for (i = 0; argv[i]; i++) 
     {
       *p++ = ' ';
@@ -540,8 +546,11 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
     }
 
   /* Build the command line.  */
-  err = build_w32_commandline (pgmname, argv, inpipe[0], outpipe[1], errpipe[1],
-                               0, &cmdline);
+  err = build_w32_commandline (argv,
+                               inpipe[0], 0,
+                               outpipe[1], 0,
+                               errpipe[1], 0,
+                               &cmdline);
   if (err)
     {
       CloseHandle (fd_to_handle (errpipe[0]));
@@ -601,68 +610,42 @@ gpg_error_t
 gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
                         int infd, int outfd, int errfd, pid_t *pid)
 {
-  return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
-#if 0
   gpg_error_t err;
-  PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
-  STARTUPINFO si;
+  PROCESS_INFORMATION pi = {NULL};
   char *cmdline;
-  int i;
-  HANDLE stdhd[3];
 
   /* Setup return values.  */
   *pid = (pid_t)(-1);
 
+  if (infd != -1 || outfd != -1 || errfd != -1)
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   /* Build the command line.  */
-  err = build_w32_commandline (pgmname, argv, &cmdline);
+  err = build_w32_commandline (argv, -1, 1, -1, 1, -1, 1, &cmdline);
   if (err)
     return err; 
 
-  /* si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; */
-  /* stdhd[0] = infd  == -1? w32_open_null (0) : INVALID_HANDLE_VALUE; */
-  /* stdhd[1] = outfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE; */
-  /* stdhd[2] = errfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE; */
-  /* si.hStdInput  = infd  == -1? stdhd[0] : (void*)_get_osfhandle (infd); */
-  /* si.hStdOutput = outfd == -1? stdhd[1] : (void*)_get_osfhandle (outfd); */
-  /* si.hStdError  = errfd == -1? stdhd[2] : (void*)_get_osfhandle (errfd); */
-
-/*   log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline); */
-  if (!CreateProcess (pgmname,       /* Program to start.  */
-                      cmdline,       /* Command line arguments.  */
-                      NULL,          /* Process security attributes.  */
-                      NULL,          /* Thread security attributes.  */
-                      FALSE,          /* Inherit handles.  */
-                      CREATE_SUSPENDED,
-                      NULL,          /* Environment.  */
-                      NULL,          /* Use current drive/directory.  */
-                      NULL,           /* Startup information. */
-                      &pi            /* Returns process information.  */
-                      ))
+  log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline);
+  if (!create_process (pgmname, cmdline, &pi))
     {
-      log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
-      err = gpg_error (GPG_ERR_GENERAL);
+      log_error ("CreateProcess(fd) failed: %s\n", w32_strerror (-1));
+      xfree (cmdline);
+      return gpg_error (GPG_ERR_GENERAL);
     }
-  else
-    err = 0;
   xfree (cmdline);
-  for (i=0; i < 3; i++)
-    if (stdhd[i] != INVALID_HANDLE_VALUE)
-      CloseHandle (stdhd[i]);
-  if (err)
-    return err;
-
-/*   log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
-/*              " dwProcessID=%d dwThreadId=%d\n", */
-/*              pi.hProcess, pi.hThread, */
-/*              (int) pi.dwProcessId, (int) pi.dwThreadId); */
+  cmdline = NULL;
 
+  log_debug ("CreateProcess(fd) ready: hProcess=%p hThread=%p"
+             " dwProcessID=%d dwThreadId=%d\n",
+             pi.hProcess, pi.hThread,
+             (int) pi.dwProcessId, (int) pi.dwThreadId);
+  
   /* Process has been created suspended; resume it now. */
   ResumeThread (pi.hThread);
   CloseHandle (pi.hThread); 
 
   *pid = handle_to_pid (pi.hProcess);
   return 0;
-#endif
 }
 
 /* Wait for the process identified by PID to terminate. PGMNAME should
@@ -743,42 +726,20 @@ gpg_error_t
 gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
                               const char *envp[] )
 {
-  return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
-#if 0
   gpg_error_t err;
-  PROCESS_INFORMATION pi = 
-    {
-      NULL,      /* Returns process handle.  */
-      0,         /* Returns primary thread handle.  */
-      0,         /* Returns pid.  */
-      0          /* Returns tid.  */
-    };
-  STARTUPINFO si;
   char *cmdline;
+  PROCESS_INFORMATION pi = {NULL };
 
   (void)envp;
-
-  if (access (pgmname, X_OK))
-    return gpg_error_from_syserror ();
-
+  
   /* Build the command line.  */
-  err = build_w32_commandline (pgmname, argv, &cmdline);
+  err = build_w32_commandline (argv, -1, 1, -1, 1, -1, 1, &cmdline);
   if (err)
     return err; 
 
-/*   log_debug ("CreateProcess(detached), path=`%s' cmdline=`%s'\n", */
-/*              pgmname, cmdline); */
-  if (!CreateProcess (pgmname,       /* Program to start.  */
-                      cmdline,       /* Command line arguments.  */
-                      NULL,          /* Process security attributes.  */
-                      NULL,          /* Thread security attributes.  */
-                      FALSE,         /* Inherit handles.  */
-                      0,             /* Creation flags.  */
-                      NULL,          /* Environment.  */
-                      NULL,          /* Use current drive/directory.  */
-                      NULL,           /* Startup information. */
-                      &pi            /* Returns process information.  */
-                      ))
+  /* Note: There is no detached flag under CE.  */
+  log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline);
+  if (!create_process (pgmname, cmdline, &pi))
     {
       log_error ("CreateProcess(detached) failed: %s\n", w32_strerror (-1));
       xfree (cmdline);
@@ -787,17 +748,19 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
   xfree (cmdline);
   cmdline = NULL;
 
-/*   log_debug ("CreateProcess(detached) ready: hProcess=%p hThread=%p" */
-/*              " dwProcessID=%d dwThreadId=%d\n", */
-/*              pi.hProcess, pi.hThread, */
-/*              (int) pi.dwProcessId, (int) pi.dwThreadId); */
-
+  log_debug ("CreateProcess(detached) ready: hProcess=%p hThread=%p"
+             " dwProcessID=%d dwThreadId=%d\n",
+             pi.hProcess, pi.hThread,
+             (int) pi.dwProcessId, (int) pi.dwThreadId);
+  
+  /* Process has been created suspended; resume it now. */
+  ResumeThread (pi.hThread);
   CloseHandle (pi.hThread); 
 
   return 0;
-#endif
 }
 
+
 /* Kill a process; that is send an appropriate signal to the process.
    gnupg_wait_process must be called to actually remove the process
    from the system.  An invalid PID is ignored.  */
index 280e408..22d6383 100644 (file)
@@ -1584,12 +1584,13 @@ echo "
         Smartcard: $build_scdaemon $build_scdaemon_extra
         G13:       $build_g13
 
-
         Protect tool:      $show_gnupg_protect_tool_pgm
         Default agent:     $show_gnupg_agent_pgm
         Default pinentry:  $show_gnupg_pinentry_pgm
         Default scdaemon:  $show_gnupg_scdaemon_pgm
         Default dirmngr:   $show_gnupg_dirmngr_pgm
+
+        Use standard socket: $use_standard_socket
 "
 if test x"$use_regex" != xyes ; then
 echo "