common: Support different digest algorithms for ssh fingerprints.
[gnupg.git] / common / exechelp-w32.c
index 418eb9b..2c44e2c 100644 (file)
@@ -25,7 +25,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
@@ -128,11 +128,14 @@ close_all_fds (int first, int *except)
 
 
 /* Returns an array with all currently open file descriptors.  The end
-   of the array is marked by -1.  The caller needs to release this
-   array using the *standard free* and not with xfree.  This allow the
-   use of this function right at startup even before libgcrypt has
-   been initialized.  Returns NULL on error and sets ERRNO
-   accordingly.  */
+ * of the array is marked by -1.  The caller needs to release this
+ * array using the *standard free* and not with xfree.  This allow the
+ * use of this function right at startup even before libgcrypt has
+ * been initialized.  Returns NULL on error and sets ERRNO
+ * accordingly.  Note that fstat prints a warning to DebugView for all
+ * invalid fds which is a bit annoying.  We actually do not need this
+ * function in real code (close_all_fds is a dummy anyway) but we keep
+ * it for use by t-exechelp.c.  */
 int *
 get_all_open_fds (void)
 {
@@ -301,10 +304,12 @@ w32_open_null (int for_write)
 
 
 static gpg_error_t
-do_create_pipe (int filedes[2], int flags)
+create_pipe_and_estream (int filedes[2], int flags,
+                         estream_t *r_fp, int outbound, int nonblock)
 {
   gpg_error_t err = 0;
   HANDLE fds[2];
+  es_syshd_t syshd;
 
   filedes[0] = filedes[1] = -1;
   err = my_error (GPG_ERR_GENERAL);
@@ -330,6 +335,32 @@ do_create_pipe (int filedes[2], int flags)
             err = 0;
         }
     }
+
+  if (! err && r_fp)
+    {
+      syshd.type = ES_SYSHD_HANDLE;
+      if (!outbound)
+        {
+          syshd.u.handle = fds[0];
+          *r_fp = es_sysopen (&syshd, nonblock? "r,nonblock" : "r");
+        }
+      else
+        {
+          syshd.u.handle = fds[1];
+          *r_fp = es_sysopen (&syshd, nonblock? "w,nonblock" : "w");
+        }
+      if (!*r_fp)
+        {
+          err = my_error_from_syserror ();
+          log_error (_("error creating a stream for a pipe: %s\n"),
+                     gpg_strerror (err));
+          close (filedes[0]);
+          close (filedes[1]);
+          filedes[0] = filedes[1] = -1;
+          return err;
+        }
+    }
+
   return err;
 }
 
@@ -339,10 +370,8 @@ do_create_pipe (int filedes[2], int flags)
 gpg_error_t
 gnupg_create_inbound_pipe (int filedes[2], estream_t *r_fp, int nonblock)
 {
-  if (r_fp)
-    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
-  else
-    return do_create_pipe (filedes, INHERIT_WRITE);
+  return create_pipe_and_estream (filedes, INHERIT_WRITE,
+                                  r_fp, 0, nonblock);
 }
 
 
@@ -352,10 +381,8 @@ gnupg_create_inbound_pipe (int filedes[2], estream_t *r_fp, int nonblock)
 gpg_error_t
 gnupg_create_outbound_pipe (int filedes[2], estream_t *r_fp, int nonblock)
 {
-  if (r_fp)
-    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
-  else
-    return do_create_pipe (filedes, INHERIT_READ);
+  return create_pipe_and_estream (filedes, INHERIT_READ,
+                                  r_fp, 1, nonblock);
 }
 
 
@@ -364,7 +391,8 @@ gnupg_create_outbound_pipe (int filedes[2], estream_t *r_fp, int nonblock)
 gpg_error_t
 gnupg_create_pipe (int filedes[2])
 {
-  return do_create_pipe (filedes, INHERIT_BOTH);
+  return create_pipe_and_estream (filedes, INHERIT_BOTH,
+                                  NULL, 0, 0);
 }
 
 
@@ -401,6 +429,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
   int i;
   es_syshd_t syshd;
   gpg_err_source_t errsource = default_errsource;
+  int nonblock = !!(flags & GNUPG_SPAWN_NONBLOCK);
 
   (void)except; /* Not yet used.  */
 
@@ -423,7 +452,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
 
       syshd.type = ES_SYSHD_HANDLE;
       syshd.u.handle = inpipe[1];
-      infp = es_sysopen (&syshd, "w");
+      infp = es_sysopen (&syshd, nonblock? "w,nonblock" : "w");
       if (!infp)
         {
           err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
@@ -447,7 +476,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
 
       syshd.type = ES_SYSHD_HANDLE;
       syshd.u.handle = outpipe[0];
-      outfp = es_sysopen (&syshd, "r");
+      outfp = es_sysopen (&syshd, nonblock? "r,nonblock" : "r");
       if (!outfp)
         {
           err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
@@ -477,7 +506,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
 
       syshd.type = ES_SYSHD_HANDLE;
       syshd.u.handle = errpipe[0];
-      errfp = es_sysopen (&syshd, "r");
+      errfp = es_sysopen (&syshd, nonblock? "r,nonblock" : "r");
       if (!errfp)
         {
           err = gpg_err_make (errsource, gpg_err_code_from_syserror ());