common/exechelp: Add general pipe function.
authorJustus Winter <justus@g10code.com>
Thu, 14 Jan 2016 13:14:25 +0000 (14:14 +0100)
committerJustus Winter <justus@g10code.com>
Tue, 23 Feb 2016 10:58:52 +0000 (11:58 +0100)
* common/exechelp-posix.c (gnupg_create_pipe): New function.
* common/exechelp-w32.c (INHERIT_{READ,WRITE,BOTH}): New macros.
(create_inheritable_pipe): Generalize so that both ends can be
inherited.
(do_create_pipe): Rename argument accordingly.
(gnupg_create_{in,out}bound_pipe): Use new flags.
(gnupg_create_pipe): New function.
(gnupg_spawn_process): Use new flags.
* common/exechelp-w32ce.c (gnupg_create_pipe): New stub.
* common/exechelp.h (gnupg_create_pipe): New prototype.

Signed-off-by: Justus Winter <justus@g10code.com>
common/exechelp-posix.c
common/exechelp-w32.c
common/exechelp-w32ce.c
common/exechelp.h

index 5706dbe..37abf55 100644 (file)
@@ -310,6 +310,15 @@ gnupg_create_outbound_pipe (int filedes[2])
 }
 
 
+/* Portable function to create a pipe.  Under Windows both ends are
+   inheritable.  */
+gpg_error_t
+gnupg_create_pipe (int filedes[2])
+{
+  return do_create_pipe (filedes);
+}
+
+
 
 static gpg_error_t
 create_pipe_and_estream (int filedes[2], estream_t *r_fp,
index a77e27c..68846f8 100644 (file)
@@ -233,45 +233,41 @@ build_w32_commandline (const char *pgmname, const char * const *argv,
 }
 
 
-/* Create pipe where one end is inheritable: With an INHERIT_IDX of 0
-   the read end is inheritable, with 1 the write end is inheritable.  */
+#define INHERIT_READ   1
+#define INHERIT_WRITE  2
+#define INHERIT_BOTH   (INHERIT_READ|INHERIT_WRITE)
+
+/* Create pipe.  FLAGS indicates which ends are inheritable.  */
 static int
-create_inheritable_pipe (HANDLE filedes[2], int inherit_idx)
+create_inheritable_pipe (HANDLE filedes[2], int flags)
 {
-  HANDLE r, w, h;
+  HANDLE r, w;
   SECURITY_ATTRIBUTES sec_attr;
 
   memset (&sec_attr, 0, sizeof sec_attr );
   sec_attr.nLength = sizeof sec_attr;
-  sec_attr.bInheritHandle = FALSE;
+  sec_attr.bInheritHandle = TRUE;
 
   if (!CreatePipe (&r, &w, &sec_attr, 0))
     return -1;
 
-  if (!DuplicateHandle (GetCurrentProcess(), inherit_idx? w : r,
-                        GetCurrentProcess(), &h, 0,
-                        TRUE, DUPLICATE_SAME_ACCESS ))
-    {
-      log_error ("DuplicateHandle failed: %s\n", w32_strerror (-1));
-      CloseHandle (r);
-      CloseHandle (w);
-      return -1;
-    }
+  if ((flags & INHERIT_READ) == 0)
+    if (! SetHandleInformation (r, HANDLE_FLAG_INHERIT, 0))
+      goto fail;
 
-  if (inherit_idx)
-    {
-      CloseHandle (w);
-      w = h;
-    }
-  else
-    {
-      CloseHandle (r);
-      r = h;
-    }
+  if ((flags & INHERIT_WRITE) == 0)
+    if (! SetHandleInformation (w, HANDLE_FLAG_INHERIT, 0))
+      goto fail;
 
   filedes[0] = r;
   filedes[1] = w;
   return 0;
+
+ fail:
+  log_error ("SetHandleInformation failed: %s\n", w32_strerror (-1));
+  CloseHandle (r);
+  CloseHandle (w);
+  return -1;
 }
 
 
@@ -291,14 +287,14 @@ w32_open_null (int for_write)
 
 
 static gpg_error_t
-do_create_pipe (int filedes[2], int inherit_idx)
+do_create_pipe (int filedes[2], int flags)
 {
   gpg_error_t err = 0;
   HANDLE fds[2];
 
   filedes[0] = filedes[1] = -1;
   err = gpg_error (GPG_ERR_GENERAL);
-  if (!create_inheritable_pipe (fds, inherit_idx))
+  if (!create_inheritable_pipe (fds, flags))
     {
       filedes[0] = _open_osfhandle (handle_to_fd (fds[0]), O_RDONLY);
       if (filedes[0] == -1)
@@ -328,7 +324,7 @@ do_create_pipe (int filedes[2], int inherit_idx)
 gpg_error_t
 gnupg_create_inbound_pipe (int filedes[2])
 {
-  return do_create_pipe (filedes, 1);
+  return do_create_pipe (filedes, INHERIT_WRITE);
 }
 
 
@@ -337,7 +333,16 @@ gnupg_create_inbound_pipe (int filedes[2])
 gpg_error_t
 gnupg_create_outbound_pipe (int filedes[2])
 {
-  return do_create_pipe (filedes, 0);
+  return do_create_pipe (filedes, INHERIT_READ);
+}
+
+
+/* Portable function to create a pipe.  Under Windows both ends are
+   inheritable.  */
+gpg_error_t
+gnupg_create_pipe (int filedes[2])
+{
+  return do_create_pipe (filedes, INHERIT_BOTH);
 }
 
 
@@ -385,7 +390,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
 
   if (r_infp)
     {
-      if (create_inheritable_pipe (inpipe, 0))
+      if (create_inheritable_pipe (inpipe, INHERIT_READ))
         {
           err = gpg_err_make (errsource, GPG_ERR_GENERAL);
           log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
@@ -409,7 +414,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
 
   if (r_outfp)
     {
-      if (create_inheritable_pipe (outpipe, 1))
+      if (create_inheritable_pipe (outpipe, INHERIT_WRITE))
         {
           err = gpg_err_make (errsource, GPG_ERR_GENERAL);
           log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
@@ -439,7 +444,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
 
   if (r_errfp)
     {
-      if (create_inheritable_pipe (errpipe, 1))
+      if (create_inheritable_pipe (errpipe, INHERIT_WRITE))
         {
           err = gpg_err_make (errsource, GPG_ERR_GENERAL);
           log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
index 49ccdbb..710c828 100644 (file)
@@ -465,6 +465,15 @@ gnupg_create_outbound_pipe (int filedes[2])
 }
 
 
+/* Portable function to create a pipe.  Under Windows both ends are
+   inheritable.  */
+gpg_error_t
+gnupg_create_pipe (int filedes[2])
+{
+  return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+}
+
+
 static int
 create_process (const char *pgmname, const char *cmdline,
                 PROCESS_INFORMATION *pi)
index 9088342..cdee300 100644 (file)
@@ -59,6 +59,11 @@ gpg_error_t gnupg_create_inbound_pipe (int filedes[2]);
    inheritable.  */
 gpg_error_t gnupg_create_outbound_pipe (int filedes[2]);
 
+/* Portable function to create a pipe.  Under Windows both ends are
+   inheritable.  */
+gpg_error_t gnupg_create_pipe (int filedes[2]);
+
+
 #define GNUPG_SPAWN_NONBLOCK   16
 #define GNUPG_SPAWN_RUN_ASFW   64
 #define GNUPG_SPAWN_DETACHED  128