[svn] gpgme - r1321 - in trunk: assuan gpgme

svn author marcus cvs at cvs.gnupg.org
Wed Jun 25 18:52:38 CEST 2008


Author: marcus
Date: 2008-06-25 18:52:31 +0200 (Wed, 25 Jun 2008)
New Revision: 1321

Added:
   trunk/gpgme/gpgme-w32spawn.c
Modified:
   trunk/assuan/ChangeLog
   trunk/assuan/assuan-pipe-connect.c
   trunk/gpgme/ChangeLog
   trunk/gpgme/Makefile.am
   trunk/gpgme/engine-gpgconf.c
   trunk/gpgme/engine-gpgsm.c
   trunk/gpgme/gpgme.h
   trunk/gpgme/posix-io.c
   trunk/gpgme/priv-io.h
   trunk/gpgme/rungpg.c
   trunk/gpgme/util.h
   trunk/gpgme/version.c
   trunk/gpgme/w32-glib-io.c
   trunk/gpgme/w32-io.c
   trunk/gpgme/w32-qt-io.cpp
   trunk/gpgme/w32-util.c
Log:
assuan/
2008-06-25  Marcus Brinkmann  <marcus at g10code.de>

	* assuan-pipe-connect.c (struct spawn_fd_item_s): Add new members.
	(HANDLE_TRANSLATION): New macro.
	(pipe_connect_gpgme): Adjust caller of _gpgme_io_spawn.
	[HANDLE_TRANSLATION]: Return translated handles.

gpgme/
2008-06-25  Marcus Brinkmann  <marcus at g10code.de>

	* gpgme-w32spawn.c: New file.
	* Makefile.am (libexec_PROGRAMS) [HAVE_W32_SYSTEM]: New variable
	with gpgme-w32spawn.
	* engine-gpgsm.c (gpgsm_new): Use server translated handles.
	(gpgsm_set_locale): Return early if locale value is NULL.
	* util.h (_gpgme_mkstemp)
	(_gpgme_get_w32spawn_path) [HAVE_W32_SYSTEM]: New function
	prototypes.
	* w32-util.c: Include <stdint.h>, <sys/stat.h> and <unistd.h>.
	(letters, mkstemp, _gpgme_mkstemp, _gpgme_get_w32spawn_path): New
	functions.
	* rungpg.c (gpg_decrypt, gpg_encrypt, gpg_encrypt_sign)
	(gpg_genkey, gpg_import, gpg_verify, gpg_sign): Pass data over
	special filename FD rather than stdin.
	(struct arg_and_data_s): Add member ARG_LOCP.
	(struct fd_data_map_s): Add member ARG_LOC.
	(struct engine_gpg): Add member ARG_LOC to status and colon.
	(_add_arg, add_arg_with_locp): New function.
	(add_arg_ext): Reimplement in terms of _add_arg.
	(gpg_new): Remember argument location for status FD.
	(build_argv): Set argument location if requested.  Also set
	argument location of fd_data_map for data items.
	(start): Adjust caller of _gpgme_io_spawn.
	* priv-io.h (struct spawn_fd_item_s): Add members peer_name and
	arg_loc.
	(_gpgme_io_spawn): Remove parent fd list argument.
	* posix-io.c (get_max_fds): New function.
	(_gpgme_io_dup): Add tracing.
	(_gpgme_io_spawn): Remove parent fd list.  Change meaning of child
	fd list to contain all child fds that should be inherited.  Close
	all other file descriptors after fork.
	* w32-io.c, w32-glib-io.c, w32-qt-io.c(_gpgme_io_spawn): Remove
	parent fd list.  Change meaning of child fd list to contain all
	child fds that should be inherited.  Do not inherit any file
	descriptors, but DuplicateHandle them.  Spawn process through
	wrapper process.  Provide wrapper process with a temporary file
	containing handle translation data.  Return translated handle
	names.
	* w32-io.c (reader): Add more tracing output.
	(_gpgme_io_read): Likewise.
	* engine-gpgconf.c (gpgconf_read): Adjust caller of
	_gpgme_io_spawn.
	* version.c (_gpgme_get_program_version): Likewise.


[The diff below has been truncated]

Modified: trunk/assuan/ChangeLog
===================================================================
--- trunk/assuan/ChangeLog	2008-06-25 01:44:50 UTC (rev 1320)
+++ trunk/assuan/ChangeLog	2008-06-25 16:52:31 UTC (rev 1321)
@@ -1,3 +1,10 @@
+2008-06-25  Marcus Brinkmann  <marcus at g10code.de>
+
+	* assuan-pipe-connect.c (struct spawn_fd_item_s): Add new members.
+	(HANDLE_TRANSLATION): New macro.
+	(pipe_connect_gpgme): Adjust caller of _gpgme_io_spawn.
+	[HANDLE_TRANSLATION]: Return translated handles.
+
 2008-02-14  Werner Koch  <wk at g10code.com>
 
 	* assuan-pipe-connect.c (_gpgme_io_spawn): Adjust prototype.

Modified: trunk/gpgme/ChangeLog
===================================================================
--- trunk/gpgme/ChangeLog	2008-06-25 01:44:50 UTC (rev 1320)
+++ trunk/gpgme/ChangeLog	2008-06-25 16:52:31 UTC (rev 1321)
@@ -1,3 +1,49 @@
+2008-06-25  Marcus Brinkmann  <marcus at g10code.de>
+
+	* gpgme-w32spawn.c: New file.
+	* Makefile.am (libexec_PROGRAMS) [HAVE_W32_SYSTEM]: New variable
+	with gpgme-w32spawn.
+	* engine-gpgsm.c (gpgsm_new): Use server translated handles.
+	(gpgsm_set_locale): Return early if locale value is NULL.
+	* util.h (_gpgme_mkstemp)
+	(_gpgme_get_w32spawn_path) [HAVE_W32_SYSTEM]: New function
+	prototypes.
+	* w32-util.c: Include <stdint.h>, <sys/stat.h> and <unistd.h>.
+	(letters, mkstemp, _gpgme_mkstemp, _gpgme_get_w32spawn_path): New
+	functions.
+	* rungpg.c (gpg_decrypt, gpg_encrypt, gpg_encrypt_sign)
+	(gpg_genkey, gpg_import, gpg_verify, gpg_sign): Pass data over
+	special filename FD rather than stdin.
+	(struct arg_and_data_s): Add member ARG_LOCP.
+	(struct fd_data_map_s): Add member ARG_LOC.
+	(struct engine_gpg): Add member ARG_LOC to status and colon.
+	(_add_arg, add_arg_with_locp): New function.
+	(add_arg_ext): Reimplement in terms of _add_arg.
+	(gpg_new): Remember argument location for status FD.
+	(build_argv): Set argument location if requested.  Also set
+	argument location of fd_data_map for data items.
+	(start): Adjust caller of _gpgme_io_spawn.
+	* priv-io.h (struct spawn_fd_item_s): Add members peer_name and
+	arg_loc.
+	(_gpgme_io_spawn): Remove parent fd list argument.
+	* posix-io.c (get_max_fds): New function.
+	(_gpgme_io_dup): Add tracing.
+	(_gpgme_io_spawn): Remove parent fd list.  Change meaning of child
+	fd list to contain all child fds that should be inherited.  Close
+	all other file descriptors after fork.
+	* w32-io.c, w32-glib-io.c, w32-qt-io.c(_gpgme_io_spawn): Remove
+	parent fd list.  Change meaning of child fd list to contain all
+	child fds that should be inherited.  Do not inherit any file
+	descriptors, but DuplicateHandle them.  Spawn process through
+	wrapper process.  Provide wrapper process with a temporary file
+	containing handle translation data.  Return translated handle
+	names.
+	* w32-io.c (reader): Add more tracing output.
+	(_gpgme_io_read): Likewise.
+	* engine-gpgconf.c (gpgconf_read): Adjust caller of
+	_gpgme_io_spawn.
+	* version.c (_gpgme_get_program_version): Likewise.
+
 2008-06-20  Werner Koch  <wk at g10code.com>
 
 	* engine-gpgconf.c (gpgconf_read): Change ARGV initialization for

Modified: trunk/assuan/assuan-pipe-connect.c
===================================================================
--- trunk/assuan/assuan-pipe-connect.c	2008-06-25 01:44:50 UTC (rev 1320)
+++ trunk/assuan/assuan-pipe-connect.c	2008-06-25 16:52:31 UTC (rev 1321)
@@ -41,10 +41,19 @@
 
 #ifdef _ASSUAN_IN_GPGME_BUILD_ASSUAN
 
+/* From GPGME priv-io.h  */
+struct spawn_fd_item_s
+{
+  int fd;
+  int dup_to;
+  int peer_name;
+  int arg_loc;
+};
+
+
 int _gpgme_io_pipe (int filedes[2], int inherit_idx);
 int _gpgme_io_spawn (const char *path, char **argv,
-		     struct spawn_fd_item_s *fd_child_list,
-		     struct spawn_fd_item_s *fd_parent_list, pid_t *r_pid);
+		     struct spawn_fd_item_s *fd_list, pid_t *r_pid);
 #endif
 
 /* Hacks for Slowaris.  */
@@ -566,13 +575,6 @@
 
 #define pipe_connect pipe_connect_gpgme
 
-/* From GPGME priv-io.h  */
-struct spawn_fd_item_s
-{
-  int fd;
-  int dup_to;
-};
-
 /* W32 version of the pipe connection code. */
 static assuan_error_t
 pipe_connect_gpgme (assuan_context_t *ctx,
@@ -583,14 +585,25 @@
 {
   assuan_error_t err;
   int res;
+  int idx;
+  int nr;
   int rp[2];
   int wp[2];
   char mypidstr[50];
-  struct spawn_fd_item_s child_fds[3]; /* stdin, stdout, terminating -1 */
+  struct spawn_fd_item_s *child_fds;
 
   if (!ctx || !name || !argv || !argv[0])
     return _assuan_error (ASSUAN_Invalid_Value);
 
+  /* stdin, stdout, terminating -1 */
+  nr = 3;
+  for (idx = 0; fd_child_list[idx] != -1; idx++)
+    nr++;
+
+  child_fds = calloc (nr, sizeof *child_fds);
+  if (! child_fds)
+    return _assuan_error (ASSUAN_Out_Of_Core);
+
   /* Actually, GPGME does this for us.  But we plan to reuse this code
      in the generic assuan.  */
   fix_signals ();
@@ -631,19 +644,28 @@
      the old value, changeit, create proces and restore it, is not
      thread safe.  */
 
-  /* Parent list is same as client list.  Note that GPGME will dup nul
-     to stderr even if the caller wants to inherit the handle for
-     it.  */
+  nr = 0;
   /* Server stdout is its write end of our read pipe.  */
-  child_fds[0].fd = rp[1];
-  child_fds[0].dup_to = 1;
+  child_fds[nr].fd = rp[1];
+  child_fds[nr].dup_to = 1;
+  nr++;
   /* Server stdin is its read end of our write pipe.  */
-  child_fds[1].fd = wp[0];
-  child_fds[1].dup_to = 0;
-  child_fds[2].fd = -1;
+  child_fds[nr].fd = wp[0];
+  child_fds[nr].dup_to = 0;
+  nr++;
 
+  for (idx = 0; fd_child_list[idx] != -1; idx++)
+    {
+      child_fds[nr].fd = fd_child_list[idx];
+      child_fds[nr].dup_to = -1;
+      nr++;
+    }
+
+  child_fds[nr].fd = -1;
+  child_fds[nr].dup_to = -1;
+
   /* Start the process.  */
-  res = _gpgme_io_spawn (name, argv, child_fds, child_fds, NULL);
+  res = _gpgme_io_spawn (name, argv, child_fds, NULL);
   if (res == -1)
     {
       _assuan_log_printf ("CreateProcess failed: %s\n", strerror (errno));
@@ -653,6 +675,14 @@
       _gpgme_io_close (wp[1]);
       return _assuan_error (ASSUAN_General_Error);
     }
+  else
+    {
+      /* For W32, the user needs to know the server-local names of the
+	 inherited handles.  Return them here.  */
+      for (idx = 0; fd_child_list[idx] != -1; idx++)
+	/* We add 2 to skip over the stdin/stdout pair.  */
+	fd_child_list[idx] = child_fds[idx + 2].peer_name;
+    }
 
   (*ctx)->pid = 0;  /* We don't use the PID. */
 

Modified: trunk/gpgme/Makefile.am
===================================================================
--- trunk/gpgme/Makefile.am	2008-06-25 01:44:50 UTC (rev 1320)
+++ trunk/gpgme/Makefile.am	2008-06-25 16:52:31 UTC (rev 1321)
@@ -142,6 +142,12 @@
 
 if HAVE_W32_SYSTEM
 
+# Windows provides us with an endless stream of Tough Love.  To spawn
+# processes with a controlled set of inherited handles, we need a
+# wrapper process.
+libexec_PROGRAMS = gpgme-w32spawn
+
+
 LTRCCOMPILE = $(LIBTOOL) --mode=compile $(RC) \
      `echo $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) | \
      sed -e 's/-I/--include-dir /g;s/-D/--define /g'`

Modified: trunk/gpgme/engine-gpgconf.c
===================================================================
--- trunk/gpgme/engine-gpgconf.c	2008-06-25 01:44:50 UTC (rev 1320)
+++ trunk/gpgme/engine-gpgconf.c	2008-06-25 16:52:31 UTC (rev 1321)
@@ -201,8 +201,8 @@
   int linelen = 0;
   char *argv[4] = { NULL /* file_name */, NULL, NULL, NULL };
   int rp[2];
-  struct spawn_fd_item_s pfd[] = { {0, -1}, {-1, -1} };
-  struct spawn_fd_item_s cfd[] = { {-1, 1 /* STDOUT_FILENO */}, {-1, -1} };
+  struct spawn_fd_item_s cfd[] = { {-1, 1 /* STDOUT_FILENO */, -1, 0},
+				   {-1, -1} };
   int status;
   int nread;
   char *mark = NULL;
@@ -219,10 +219,9 @@
   if (_gpgme_io_pipe (rp, 1) < 0)
     return gpg_error_from_syserror ();
 
-  pfd[0].fd = rp[1];
   cfd[0].fd = rp[1];
 
-  status = _gpgme_io_spawn (gpgconf->file_name, argv, cfd, pfd, NULL);
+  status = _gpgme_io_spawn (gpgconf->file_name, argv, cfd, NULL);
   if (status < 0)
     {
       _gpgme_io_close (rp[0]);
@@ -645,7 +644,6 @@
   int buflen = 0;
   char *argv[] = { NULL /* file_name */, arg1, arg2, 0 };
   int rp[2];
-  struct spawn_fd_item_s pfd[] = { {1, -1}, {-1, -1} };
   struct spawn_fd_item_s cfd[] = { {-1, 0 /* STDIN_FILENO */}, {-1, -1} };
   int status;
   int nwrite;
@@ -659,10 +657,9 @@
   if (_gpgme_io_pipe (rp, 0) < 0)
     return gpg_error_from_syserror ();
 
-  pfd[0].fd = rp[0];
   cfd[0].fd = rp[0];
 
-  status = _gpgme_io_spawn (gpgconf->file_name, argv, cfd, pfd, NULL);
+  status = _gpgme_io_spawn (gpgconf->file_name, argv, cfd, NULL);
   if (status < 0)
     {
       _gpgme_io_close (rp[0]);

Modified: trunk/gpgme/engine-gpgsm.c
===================================================================
--- trunk/gpgme/engine-gpgsm.c	2008-06-25 01:44:50 UTC (rev 1320)
+++ trunk/gpgme/engine-gpgsm.c	2008-06-25 16:52:31 UTC (rev 1321)
@@ -405,9 +405,6 @@
     }
   gpgsm->input_cb.fd = fds[1];
   gpgsm->input_cb.server_fd = fds[0];
-  _gpgme_io_fd2str (gpgsm->input_cb.server_fd_str, 
-                    sizeof gpgsm->input_cb.server_fd_str,
-                    gpgsm->input_cb.server_fd);
 
   if (_gpgme_io_pipe (fds, 1) < 0)
     {
@@ -416,9 +413,6 @@
     }
   gpgsm->output_cb.fd = fds[0];
   gpgsm->output_cb.server_fd = fds[1];
-  _gpgme_io_fd2str (gpgsm->output_cb.server_fd_str, 
-                    sizeof gpgsm->output_cb.server_fd_str,
-                    gpgsm->output_cb.server_fd);
 
   if (_gpgme_io_pipe (fds, 0) < 0)
     {
@@ -427,9 +421,6 @@
     }
   gpgsm->message_cb.fd = fds[1];
   gpgsm->message_cb.server_fd = fds[0];
-  _gpgme_io_fd2str (gpgsm->message_cb.server_fd_str, 
-                    sizeof gpgsm->message_cb.server_fd_str,
-                    gpgsm->message_cb.server_fd);
 
   child_fds[0] = gpgsm->input_cb.server_fd;
   child_fds[1] = gpgsm->output_cb.server_fd;
@@ -455,10 +446,35 @@
   err = assuan_pipe_connect
     (&gpgsm->assuan_ctx, file_name ? file_name : _gpgme_get_gpgsm_path (),
      argv, child_fds);
+
+  /* On Windows, handles are inserted in the spawned process with
+     DuplicateHandle, and child_fds contains the server-local names
+     for the inserted handles when assuan_pipe_connect returns.  */
+  if (!err)
+    {
+      /* Note: We don't use _gpgme_io_fd2str here.  On W32 the
+	 returned handles are real W32 system handles, not whatever
+	 GPGME uses internally (which may be a system handle, a C
+	 library handle or a GLib/Qt channel.  Confusing, yes, but
+	 remember these are server-local names, so they are not part
+	 of GPGME at all.  */
+      snprintf (gpgsm->input_cb.server_fd_str,
+		sizeof gpgsm->input_cb.server_fd_str, "%d", child_fds[0]);
+      snprintf (gpgsm->output_cb.server_fd_str,
+		sizeof gpgsm->output_cb.server_fd_str, "%d", child_fds[1]);
+      snprintf (gpgsm->message_cb.server_fd_str,
+		sizeof gpgsm->message_cb.server_fd_str, "%d", child_fds[2]);
+    }
 #endif
   if (err)
     goto leave;
 
+  /* assuan_pipe_connect in this case uses _gpgme_io_spawn which
+     closes the child fds for us.  */
+  gpgsm->input_cb.server_fd = -1;
+  gpgsm->output_cb.server_fd = -1;
+  gpgsm->message_cb.server_fd = -1;
+
   err = _gpgme_getenv ("DISPLAY", &dft_display);
   if (err)
     goto leave;
@@ -623,6 +639,10 @@
   else
     return gpg_error (GPG_ERR_INV_VALUE);
 
+  /* FIXME: Reset value to default.  */
+  if (!value) 
+    return 0;
+
   if (asprintf (&optstr, "OPTION %s=%s", catstr, value) < 0)
     err = gpg_error_from_errno (errno);
   else
@@ -633,6 +653,7 @@
       if (err)
 	err = map_assuan_error (err);
     }
+
   return err;
 }
 

Added: trunk/gpgme/gpgme-w32spawn.c
===================================================================
--- trunk/gpgme/gpgme-w32spawn.c	2008-06-25 01:44:50 UTC (rev 1320)
+++ trunk/gpgme/gpgme-w32spawn.c	2008-06-25 16:52:31 UTC (rev 1321)
@@ -0,0 +1,434 @@
+/* gpgme-w32spawn.c - Wrapper to spawn a process under Windows.
+   Copyright (C) 2008 g10 Code GmbH
+
+   This file is part of GPGME.
+ 
+   GPGME is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of
+   the License, or (at your option) any later version.
+   
+   GPGME is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+   
+   You should have received a copy of the GNU Lesser General Public
+   License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdint.h>
+#include <process.h>
+#include <windows.h>
+
+
+
+struct spawn_fd_item_s
+{
+  int handle;
+  int dup_to;
+  int peer_name;
+  int arg_loc;
+};
+
+
+static char *
+build_commandline (char **argv)
+{
+  int i;
+  int n = 0;
+  char *buf;
+  char *p;
+  
+  /* We have to quote some things because under Windows the program
+     parses the commandline and does some unquoting.  We enclose the
+     whole argument in double-quotes, and escape literal double-quotes
+     as well as backslashes with a backslash.  We end up with a
+     trailing space at the end of the line, but that is harmless.  */
+  for (i = 0; argv[i]; i++)
+    {
+      p = argv[i];
+      /* The leading double-quote.  */
+      n++;
+      while (*p)
+	{
+	  /* An extra one for each literal that must be escaped.  */
+	  if (*p == '\\' || *p == '"')
+	    n++;
+	  n++;
+	  p++;
+	}
+      /* The trailing double-quote and the delimiter.  */
+      n += 2;
+    }
+  /* And a trailing zero.  */
+  n++;
+
+  buf = p = malloc (n);
+  if (!buf)
+    return NULL;
+  for (i = 0; argv[i]; i++)
+    {
+      char *argvp = argv[i];
+
+      *(p++) = '"';
+      while (*argvp)
+	{
+	  if (*argvp == '\\' || *argvp == '"')
+	    *(p++) = '\\';
+	  *(p++) = *(argvp++);
+	}
+      *(p++) = '"';
+      *(p++) = ' ';
+    }
+  *(p++) = 0;
+
+  return buf;
+}
+
+
+int
+my_spawn (char **argv, struct spawn_fd_item_s *fd_list)
+{
+  SECURITY_ATTRIBUTES sec_attr;
+  PROCESS_INFORMATION pi =
+    {
+      NULL,      /* returns process handle */
+      0,         /* returns primary thread handle */
+      0,         /* returns pid */
+      0          /* returns tid */
+    };
+  STARTUPINFO si;
+  char *envblock = NULL;
+  int cr_flags = CREATE_DEFAULT_ERROR_MODE
+    | GetPriorityClass (GetCurrentProcess ());
+  int i;
+  char *arg_string;
+  int duped_stdin = 0;
+  int duped_stdout = 0;
+  int duped_stderr = 0;
+  HANDLE hnul = INVALID_HANDLE_VALUE;
+  /* FIXME.  */
+  int debug_me = 0;
+
+  i = 0;
+  while (argv[i])
+    {
+      fprintf (stderr, "argv[%2i] = %s\n", i, argv[i]);
+      i++;
+    }
+
+  memset (&sec_attr, 0, sizeof sec_attr);
+  sec_attr.nLength = sizeof sec_attr;
+  sec_attr.bInheritHandle = FALSE;
+  
+  arg_string = build_commandline (argv);
+  if (!arg_string)
+    return -1;
+
+  memset (&si, 0, sizeof si);
+  si.cb = sizeof (si);
+  si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+  si.wShowWindow = debug_me ? SW_SHOW : SW_HIDE;
+  si.hStdInput = GetStdHandle (STD_INPUT_HANDLE);
+  si.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
+  si.hStdError = GetStdHandle (STD_ERROR_HANDLE);
+
+  fprintf (stderr, "spawning: %s\n", arg_string);
+
+  for (i = 0; fd_list[i].handle != -1; i++)
+    {
+      /* The handle already is inheritable.  */
+      if (fd_list[i].dup_to == 0)
+	{
+	  si.hStdInput = (HANDLE) fd_list[i].peer_name;
+	  duped_stdin = 1;
+	  fprintf (stderr, "dup 0x%x to stdin\n", fd_list[i].peer_name);
+        }
+      else if (fd_list[i].dup_to == 1)
+	{
+	  si.hStdOutput = (HANDLE) fd_list[i].peer_name;
+	  duped_stdout = 1;
+	  fprintf (stderr, "dup 0x%x to stdout\n", fd_list[i].peer_name);
+        }
+      else if (fd_list[i].dup_to == 2)
+	{
+	  si.hStdError = (HANDLE) fd_list[i].peer_name;
+	  duped_stderr = 1;
+	  fprintf (stderr, "dup 0x%x to stderr\n", fd_list[i].peer_name);
+        }
+    }
+  
+  if (!duped_stdin || !duped_stdout || !duped_stderr)
+    {
+      SECURITY_ATTRIBUTES sa;
+      
+      memset (&sa, 0, sizeof sa);
+      sa.nLength = sizeof sa;
+      sa.bInheritHandle = TRUE;
+      hnul = CreateFile ("nul",
+			 GENERIC_READ|GENERIC_WRITE,
+			 FILE_SHARE_READ|FILE_SHARE_WRITE,
+			 &sa,
+			 OPEN_EXISTING,
+			 FILE_ATTRIBUTE_NORMAL,
+			 NULL);
+      if (hnul == INVALID_HANDLE_VALUE)
+	{
+	  free (arg_string);
+	  /* FIXME: Should translate the error code.  */
+	  errno = EIO;
+	  return -1;
+        }
+      /* Make sure that the process has a connected stdin.  */
+      if (!duped_stdin)
+	si.hStdInput = hnul;
+      /* Make sure that the process has a connected stdout.  */
+      if (!duped_stdout)
+	si.hStdOutput = hnul;
+      /* We normally don't want all the normal output.  */
+      if (!duped_stderr)
+	si.hStdError = hnul;
+    }
+  
+  cr_flags |= CREATE_SUSPENDED; 
+  cr_flags |= DETACHED_PROCESS;
+  if (!CreateProcessA (argv[0],
+		       arg_string,
+		       &sec_attr,     /* process security attributes */
+		       &sec_attr,     /* thread security attributes */
+		       TRUE,          /* inherit handles */
+		       cr_flags,      /* creation flags */
+		       envblock,      /* environment */
+		       NULL,          /* use current drive/directory */
+		       &si,           /* startup information */
+		       &pi))          /* returns process information */




More information about the Gnupg-commits mailing list