Include a printf implementation supporting C99 snprintf and SUS
[platform/upstream/glib.git] / glib / gspawn-win32.c
1 /* gspawn-win32.c - Process launching on Win32
2  *
3  *  Copyright 2000 Red Hat, Inc.
4  *
5  * GLib is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * GLib is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with GLib; see the file COPYING.LIB.  If not, write
17  * to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /*
22  * Implementation details on Win32.
23  *
24  * - There is no way to set the no-inherit flag for
25  *   a "file descriptor" in the MS C runtime. The flag is there,
26  *   and the dospawn() function uses it, but unfortunately
27  *   this flag can only be set when opening the file.
28  * - As there is no fork(), we cannot reliably change directory
29  *   before starting the child process. (There might be several threads
30  *   running, and the current directory is common for all threads.)
31  *
32  * Thus, we must in most cases use a helper program to handle closing
33  * of (inherited) file descriptors and changing of directory. In fact,
34  * we do it all the time.
35  */
36
37 /* Define this to get some logging all the time */
38 /* #define G_SPAWN_WIN32_DEBUG */
39
40 #include <config.h>
41
42 #include "glib.h"
43 #include "gprintfint.h"
44
45 #include <string.h>
46 #include <stdlib.h>
47 #include <stdio.h>
48
49 #include <windows.h>
50 #include <errno.h>
51 #include <fcntl.h>
52 #include <io.h>
53 #include <process.h>
54 #include <direct.h>
55
56 #include "glibintl.h"
57
58 #ifdef G_SPAWN_WIN32_DEBUG
59   static int debug = 1;
60   #define SETUP_DEBUG() /* empty */
61
62 #else
63   static int debug = -1;
64   #define SETUP_DEBUG()                                 \
65     G_STMT_START                                        \
66       {                                                 \
67         if (debug == -1)                                \
68           {                                             \
69             if (getenv ("G_SPAWN_WIN32_DEBUG") != NULL) \
70               debug = 1;                                \
71             else                                        \
72               debug = 0;                                \
73           }                                             \
74       }                                                 \
75     G_STMT_END
76 #endif
77
78 enum
79 {
80   CHILD_NO_ERROR,
81   CHILD_CHDIR_FAILED,
82   CHILD_SPAWN_FAILED,
83 };
84
85 enum {
86   ARG_CHILD_ERR_REPORT = 1,
87   ARG_STDIN,
88   ARG_STDOUT,
89   ARG_STDERR,
90   ARG_WORKING_DIRECTORY,
91   ARG_CLOSE_DESCRIPTORS,
92   ARG_USE_PATH,
93   ARG_WAIT,
94   ARG_PROGRAM,
95   ARG_COUNT = ARG_PROGRAM
96 };
97
98 #ifndef GSPAWN_HELPER
99
100 static gboolean make_pipe            (gint                  p[2],
101                                       GError              **error);
102 static gboolean do_spawn_with_pipes  (gboolean              dont_wait,
103                                       gboolean              dont_return_handle,
104                                       const gchar          *working_directory,
105                                       gchar               **argv,
106                                       gchar               **envp,
107                                       gboolean              close_descriptors,
108                                       gboolean              search_path,
109                                       gboolean              stdout_to_null,
110                                       gboolean              stderr_to_null,
111                                       gboolean              child_inherits_stdin,
112                                       GSpawnChildSetupFunc  child_setup,
113                                       gpointer              user_data,
114                                       gint                 *child_pid,
115                                       gint                 *standard_input,
116                                       gint                 *standard_output,
117                                       gint                 *standard_error,
118                                       gint                 *exit_status,
119                                       GError              **error);
120
121 GQuark
122 g_spawn_error_quark (void)
123 {
124   static GQuark quark = 0;
125   if (quark == 0)
126     quark = g_quark_from_static_string ("g-exec-error-quark");
127   return quark;
128 }
129
130 gboolean
131 g_spawn_async (const gchar          *working_directory,
132                gchar               **argv,
133                gchar               **envp,
134                GSpawnFlags           flags,
135                GSpawnChildSetupFunc  child_setup,
136                gpointer              user_data,
137                gint                 *child_pid,
138                GError              **error)
139 {
140   g_return_val_if_fail (argv != NULL, FALSE);
141   
142   return g_spawn_async_with_pipes (working_directory,
143                                    argv, envp,
144                                    flags,
145                                    child_setup,
146                                    user_data,
147                                    child_pid,
148                                    NULL, NULL, NULL,
149                                    error);
150 }
151
152 /* Avoids a danger in threaded situations (calling close()
153  * on a file descriptor twice, and another thread has
154  * re-opened it since the first close)
155  */
156 static gint
157 close_and_invalidate (gint *fd)
158 {
159   gint ret;
160
161   if (*fd < 0)
162     return -1;
163   else
164     {
165       ret = close (*fd);
166       *fd = -1;
167     }
168
169   return ret;
170 }
171
172 typedef enum
173 {
174   READ_FAILED = 0, /* FALSE */
175   READ_OK,
176   READ_EOF
177 } ReadResult;
178
179 static ReadResult
180 read_data (GString     *str,
181            GIOChannel  *iochannel,
182            GError     **error)
183 {
184   GIOStatus giostatus;
185   gssize bytes;
186   gchar buf[4096];
187
188  again:
189   
190   giostatus = g_io_channel_read_chars (iochannel, buf, sizeof (buf), &bytes, NULL);
191
192   if (bytes == 0)
193     return READ_EOF;
194   else if (bytes > 0)
195     {
196       g_string_append_len (str, buf, bytes);
197       return READ_OK;
198     }
199   else if (giostatus == G_IO_STATUS_AGAIN)
200     goto again;
201   else if (giostatus == G_IO_STATUS_ERROR)
202     {
203       g_set_error (error,
204                    G_SPAWN_ERROR,
205                    G_SPAWN_ERROR_READ,
206                    _("Failed to read data from child process"));
207       
208       return READ_FAILED;
209     }
210   else
211     return READ_OK;
212 }
213
214 gboolean
215 g_spawn_sync (const gchar          *working_directory,
216               gchar               **argv,
217               gchar               **envp,
218               GSpawnFlags           flags,
219               GSpawnChildSetupFunc  child_setup,
220               gpointer              user_data,
221               gchar               **standard_output,
222               gchar               **standard_error,
223               gint                 *exit_status,
224               GError              **error)     
225 {
226   gint outpipe = -1;
227   gint errpipe = -1;
228   gint pid;
229   GIOChannel *outchannel = NULL;
230   GIOChannel *errchannel = NULL;
231   GPollFD outfd, errfd;
232   GPollFD fds[2];
233   gint nfds;
234   gint outindex = -1;
235   gint errindex = -1;
236   gint ret;
237   GString *outstr = NULL;
238   GString *errstr = NULL;
239   gboolean failed;
240   gint status;
241   
242   g_return_val_if_fail (argv != NULL, FALSE);
243   g_return_val_if_fail (!(flags & G_SPAWN_DO_NOT_REAP_CHILD), FALSE);
244   g_return_val_if_fail (standard_output == NULL ||
245                         !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
246   g_return_val_if_fail (standard_error == NULL ||
247                         !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
248   
249   /* Just to ensure segfaults if callers try to use
250    * these when an error is reported.
251    */
252   if (standard_output)
253     *standard_output = NULL;
254
255   if (standard_error)
256     *standard_error = NULL;
257   
258   if (!do_spawn_with_pipes (FALSE,
259                             TRUE,
260                             working_directory,
261                             argv,
262                             envp,
263                             !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
264                             (flags & G_SPAWN_SEARCH_PATH) != 0,
265                             (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
266                             (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
267                             (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
268                             child_setup,
269                             user_data,
270                             &pid,
271                             NULL,
272                             standard_output ? &outpipe : NULL,
273                             standard_error ? &errpipe : NULL,
274                             &status,
275                             error))
276     return FALSE;
277
278   /* Read data from child. */
279   
280   failed = FALSE;
281
282   if (outpipe >= 0)
283     {
284       outstr = g_string_new ("");
285       outchannel = g_io_channel_win32_new_fd (outpipe);
286       g_io_channel_set_encoding (outchannel, NULL, NULL);
287       g_io_channel_win32_make_pollfd (outchannel,
288                                       G_IO_IN | G_IO_ERR | G_IO_HUP,
289                                       &outfd);
290     }
291       
292   if (errpipe >= 0)
293     {
294       errstr = g_string_new ("");
295       errchannel = g_io_channel_win32_new_fd (errpipe);
296       g_io_channel_set_encoding (errchannel, NULL, NULL);
297       g_io_channel_win32_make_pollfd (errchannel,
298                                       G_IO_IN | G_IO_ERR | G_IO_HUP,
299                                       &errfd);
300     }
301
302   /* Read data until we get EOF on both pipes. */
303   while (!failed &&
304          (outpipe >= 0 ||
305           errpipe >= 0))
306     {
307       nfds = 0;
308       if (outpipe >= 0)
309         {
310           fds[nfds] = outfd;
311           outindex = nfds;
312           nfds++;
313         }
314       if (errpipe >= 0)
315         {
316           fds[nfds] = errfd;
317           errindex = nfds;
318           nfds++;
319         }
320
321       if (debug)
322         g_print ("%s:g_spawn_sync: calling g_io_channel_win32_poll, nfds=%d\n",
323                  __FILE__, nfds);
324
325       ret = g_io_channel_win32_poll (fds, nfds, -1);
326
327       if (ret < 0)
328         {
329           failed = TRUE;
330
331           g_set_error (error,
332                        G_SPAWN_ERROR,
333                        G_SPAWN_ERROR_READ,
334                        _("Unexpected error in g_io_channel_win32_poll() reading data from a child process"));
335               
336           break;
337         }
338
339       if (outpipe >= 0 && (fds[outindex].revents & G_IO_IN))
340         {
341           switch (read_data (outstr, outchannel, error))
342             {
343             case READ_FAILED:
344               if (debug)
345                 g_print ("g_spawn_sync: outchannel: READ_FAILED\n");
346               failed = TRUE;
347               break;
348             case READ_EOF:
349               if (debug)
350                 g_print ("g_spawn_sync: outchannel: READ_EOF\n");
351               g_io_channel_unref (outchannel);
352               outchannel = NULL;
353               close_and_invalidate (&outpipe);
354               break;
355             default:
356               if (debug)
357                 g_print ("g_spawn_sync: outchannel: OK\n");
358               break;
359             }
360
361           if (failed)
362             break;
363         }
364
365       if (errpipe >= 0 && (fds[errindex].revents & G_IO_IN))
366         {
367           switch (read_data (errstr, errchannel, error))
368             {
369             case READ_FAILED:
370               if (debug)
371                 g_print ("g_spawn_sync: errchannel: READ_FAILED\n");
372               failed = TRUE;
373               break;
374             case READ_EOF:
375               if (debug)
376                 g_print ("g_spawn_sync: errchannel: READ_EOF\n");
377               g_io_channel_unref (errchannel);
378               errchannel = NULL;
379               close_and_invalidate (&errpipe);
380               break;
381             default:
382               if (debug)
383                 g_print ("g_spawn_sync: errchannel: OK\n");
384               break;
385             }
386
387           if (failed)
388             break;
389         }
390     }
391
392   /* These should only be open still if we had an error.  */
393   
394   if (outchannel != NULL)
395     g_io_channel_unref (outchannel);
396   if (errchannel != NULL)
397     g_io_channel_unref (errchannel);
398   if (outpipe >= 0)
399     close_and_invalidate (&outpipe);
400   if (errpipe >= 0)
401     close_and_invalidate (&errpipe);
402   
403   if (failed)
404     {
405       if (outstr)
406         g_string_free (outstr, TRUE);
407       if (errstr)
408         g_string_free (errstr, TRUE);
409
410       return FALSE;
411     }
412   else
413     {
414       if (exit_status)
415         *exit_status = status;
416       
417       if (standard_output)        
418         *standard_output = g_string_free (outstr, FALSE);
419
420       if (standard_error)
421         *standard_error = g_string_free (errstr, FALSE);
422
423       return TRUE;
424     }
425 }
426
427 gboolean
428 g_spawn_async_with_pipes (const gchar          *working_directory,
429                           gchar               **argv,
430                           gchar               **envp,
431                           GSpawnFlags           flags,
432                           GSpawnChildSetupFunc  child_setup,
433                           gpointer              user_data,
434                           gint                 *child_pid,
435                           gint                 *standard_input,
436                           gint                 *standard_output,
437                           gint                 *standard_error,
438                           GError              **error)
439 {
440   g_return_val_if_fail (argv != NULL, FALSE);
441   g_return_val_if_fail (standard_output == NULL ||
442                         !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
443   g_return_val_if_fail (standard_error == NULL ||
444                         !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
445   /* can't inherit stdin if we have an input pipe. */
446   g_return_val_if_fail (standard_input == NULL ||
447                         !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
448   
449   return do_spawn_with_pipes (TRUE,
450                               !(flags & G_SPAWN_DO_NOT_REAP_CHILD),
451                               working_directory,
452                               argv,
453                               envp,
454                               !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
455                               (flags & G_SPAWN_SEARCH_PATH) != 0,
456                               (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
457                               (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
458                               (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
459                               child_setup,
460                               user_data,
461                               child_pid,
462                               standard_input,
463                               standard_output,
464                               standard_error,
465                               NULL,
466                               error);
467 }
468
469 gboolean
470 g_spawn_command_line_sync (const gchar  *command_line,
471                            gchar       **standard_output,
472                            gchar       **standard_error,
473                            gint         *exit_status,
474                            GError      **error)
475 {
476   gboolean retval;
477   gchar **argv = 0;
478
479   g_return_val_if_fail (command_line != NULL, FALSE);
480   
481   if (!g_shell_parse_argv (command_line,
482                            NULL, &argv,
483                            error))
484     return FALSE;
485   
486   retval = g_spawn_sync (NULL,
487                          argv,
488                          NULL,
489                          G_SPAWN_SEARCH_PATH,
490                          NULL,
491                          NULL,
492                          standard_output,
493                          standard_error,
494                          exit_status,
495                          error);
496   g_strfreev (argv);
497
498   return retval;
499 }
500
501 gboolean
502 g_spawn_command_line_async (const gchar *command_line,
503                             GError     **error)
504 {
505   gboolean retval;
506   gchar **argv = 0;
507
508   g_return_val_if_fail (command_line != NULL, FALSE);
509
510   if (!g_shell_parse_argv (command_line,
511                            NULL, &argv,
512                            error))
513     return FALSE;
514   
515   retval = g_spawn_async (NULL,
516                           argv,
517                           NULL,
518                           G_SPAWN_SEARCH_PATH,
519                           NULL,
520                           NULL,
521                           NULL,
522                           error);
523   g_strfreev (argv);
524
525   return retval;
526 }
527
528 static gint
529 do_spawn (gboolean              dont_wait,
530           gint                  child_err_report_fd,
531           gint                  stdin_fd,
532           gint                  stdout_fd,
533           gint                  stderr_fd,
534           const gchar          *working_directory,
535           gchar               **argv,
536           gchar               **envp,
537           gboolean              close_descriptors,
538           gboolean              search_path,
539           gboolean              stdout_to_null,
540           gboolean              stderr_to_null,
541           gboolean              child_inherits_stdin,
542           GSpawnChildSetupFunc  child_setup,
543           gpointer              user_data)
544 {
545   gchar **new_argv;
546   gchar args[ARG_COUNT][10];
547   gint i;
548   int rc;
549   int argc = 0;
550
551   SETUP_DEBUG();
552
553   while (argv[argc])
554     ++argc;
555
556   new_argv = g_new (gchar *, argc + 1 + ARG_COUNT);
557
558   new_argv[0] = "gspawn-win32-helper";
559   _g_sprintf (args[ARG_CHILD_ERR_REPORT], "%d", child_err_report_fd);
560   new_argv[ARG_CHILD_ERR_REPORT] = args[ARG_CHILD_ERR_REPORT];
561
562   if (stdin_fd >= 0)
563     {
564       _g_sprintf (args[ARG_STDIN], "%d", stdin_fd);
565       new_argv[ARG_STDIN] = args[ARG_STDIN];
566     }
567   else if (child_inherits_stdin)
568     {
569       /* Let stdin be alone */
570       new_argv[ARG_STDIN] = "-";
571     }
572   else
573     {
574       /* Keep process from blocking on a read of stdin */
575       new_argv[ARG_STDIN] = "z";
576     }
577
578   if (stdout_fd >= 0)
579     {
580       _g_sprintf (args[ARG_STDOUT], "%d", stdout_fd);
581       new_argv[ARG_STDOUT] = args[ARG_STDOUT];
582     }
583   else if (stdout_to_null)
584     {
585       new_argv[ARG_STDOUT] = "z";
586     }
587   else
588     {
589       new_argv[ARG_STDOUT] = "-";
590     }
591
592   if (stderr_fd >= 0)
593     {
594       _g_sprintf (args[ARG_STDERR], "%d", stderr_fd);
595       new_argv[ARG_STDERR] = args[ARG_STDERR];
596     }
597   else if (stderr_to_null)
598     {
599       new_argv[ARG_STDERR] = "z";
600     }
601   else
602     {
603       new_argv[ARG_STDERR] = "-";
604     }
605
606   if (working_directory && *working_directory)
607     new_argv[ARG_WORKING_DIRECTORY] = g_strdup (working_directory);
608   else
609     new_argv[ARG_WORKING_DIRECTORY] = "-";
610
611   if (close_descriptors)
612     new_argv[ARG_CLOSE_DESCRIPTORS] = "y";
613   else
614     new_argv[ARG_CLOSE_DESCRIPTORS] = "-";
615
616   if (search_path)
617     new_argv[ARG_USE_PATH] = "y";
618   else
619     new_argv[ARG_USE_PATH] = "-";
620
621   if (dont_wait)
622     new_argv[ARG_WAIT] = "-";
623   else
624     new_argv[ARG_WAIT] = "w";
625
626   for (i = 0; i <= argc; i++)
627     new_argv[ARG_PROGRAM + i] = argv[i];
628
629   /* Call user function just before we execute the helper program,
630    * which executes the program. Dunno what's the usefulness of this.
631    * A child setup function used on Unix probably isn't of much use
632    * as such on Win32, anyhow
633    */
634   if (child_setup)
635     {
636       (* child_setup) (user_data);
637     }
638
639   if (debug)
640     {
641       g_print ("calling gspawn-win32-helper with argv:\n");
642       for (i = 0; i < argc + 1 + ARG_COUNT; i++)
643         g_print ("argv[%d]: %s\n", i, (new_argv[i] ? new_argv[i] : "NULL"));
644     }
645   
646   if (envp != NULL)
647     /* Let's hope envp hasn't mucked with PATH so that
648      * gspawn-win32-helper.exe isn't found.
649      */
650     rc = spawnvpe (P_NOWAIT, "gspawn-win32-helper", new_argv, envp);
651   else
652     rc = spawnvp (P_NOWAIT, "gspawn-win32-helper", new_argv);
653
654   /* Close the child_err_report_fd and the other process's ends of the
655    * pipes in this process, otherwise the reader will never get
656    * EOF.
657    */
658   close (child_err_report_fd);
659   if (stdin_fd >= 0)
660     close (stdin_fd);
661   if (stdout_fd >= 0)
662     close (stdout_fd);
663   if (stderr_fd >= 0)
664     close (stderr_fd);
665
666   g_free (new_argv[ARG_WORKING_DIRECTORY]);
667   g_free (new_argv);
668
669   return rc;
670 }
671
672 static gboolean
673 read_ints (int      fd,
674            gint*    buf,
675            gint     n_ints_in_buf,
676            gint    *n_ints_read,
677            GError **error)
678 {
679   gint bytes = 0;
680   
681   while (bytes < sizeof(gint)*n_ints_in_buf)
682     {
683       gint chunk;
684
685       if (debug)
686         g_print ("%s:read_ints: trying to read %d bytes from pipe...\n",
687                  __FILE__,
688                  sizeof(gint)*n_ints_in_buf - bytes);
689
690       chunk = read (fd, ((gchar*)buf) + bytes,
691                     sizeof(gint)*n_ints_in_buf - bytes);
692
693       if (debug)
694         g_print ("... got %d bytes\n", chunk);
695           
696       if (chunk < 0)
697         {
698           /* Some weird shit happened, bail out */
699               
700           g_set_error (error,
701                        G_SPAWN_ERROR,
702                        G_SPAWN_ERROR_FAILED,
703                        _("Failed to read from child pipe (%s)"),
704                        g_strerror (errno));
705
706           return FALSE;
707         }
708       else if (chunk == 0)
709         break; /* EOF */
710       else
711         bytes += chunk;
712     }
713
714   *n_ints_read = bytes/sizeof(gint);
715
716   return TRUE;
717 }
718
719 static gboolean
720 do_spawn_with_pipes (gboolean              dont_wait,
721                      gboolean              dont_return_handle,
722                      const gchar          *working_directory,
723                      gchar               **argv,
724                      gchar               **envp,
725                      gboolean              close_descriptors,
726                      gboolean              search_path,
727                      gboolean              stdout_to_null,
728                      gboolean              stderr_to_null,
729                      gboolean              child_inherits_stdin,
730                      GSpawnChildSetupFunc  child_setup,
731                      gpointer              user_data,
732                      gint                 *child_pid,
733                      gint                 *standard_input,
734                      gint                 *standard_output,
735                      gint                 *standard_error,
736                      gint                 *exit_status,
737                      GError              **error)     
738 {
739   gint stdin_pipe[2] = { -1, -1 };
740   gint stdout_pipe[2] = { -1, -1 };
741   gint stderr_pipe[2] = { -1, -1 };
742   gint child_err_report_pipe[2] = { -1, -1 };
743   gint helper = -1;
744   gint buf[2];
745   gint n_ints = 0;
746   
747   if (!make_pipe (child_err_report_pipe, error))
748     return FALSE;
749
750   if (standard_input && !make_pipe (stdin_pipe, error))
751     goto cleanup_and_fail;
752   
753   if (standard_output && !make_pipe (stdout_pipe, error))
754     goto cleanup_and_fail;
755
756   if (standard_error && !make_pipe (stderr_pipe, error))
757     goto cleanup_and_fail;
758
759   helper = do_spawn (dont_wait,
760                      child_err_report_pipe[1],
761                      stdin_pipe[0],
762                      stdout_pipe[1],
763                      stderr_pipe[1],
764                      working_directory,
765                      argv,
766                      envp,
767                      close_descriptors,
768                      search_path,
769                      stdout_to_null,
770                      stderr_to_null,
771                      child_inherits_stdin,
772                      child_setup,
773                      user_data);
774       
775   /* do_spawn() returns -1 if gspawn-win32-helper couldn't be run */
776   if (helper == -1)
777     {
778       g_set_error (error,
779                    G_SPAWN_ERROR,
780                    G_SPAWN_ERROR_FAILED,
781                    _("Failed to execute helper program"));
782       goto cleanup_and_fail;
783     }
784
785   if (!read_ints (child_err_report_pipe[0],
786                   buf, 2, &n_ints,
787                   error) ||
788       n_ints != 2)
789     goto cleanup_and_fail;
790         
791   /* Error code from gspawn-win32-helper. */
792   switch (buf[0])
793     {
794     case CHILD_NO_ERROR:
795       if (child_pid && dont_wait && !dont_return_handle)
796         {
797           /* helper is our HANDLE for gspawn-win32-helper. It has
798            * told us the HANDLE of its child. Duplicate that into
799            * a HANDLE valid in this process.
800            */
801           if (!DuplicateHandle ((HANDLE) helper, (HANDLE) buf[1],
802                                 GetCurrentProcess (), (LPHANDLE) child_pid,
803                                 0, TRUE, DUPLICATE_SAME_ACCESS))
804             *child_pid = 0;
805         }
806       else if (child_pid)
807         *child_pid = 0;
808       break;
809       
810     case CHILD_CHDIR_FAILED:
811       g_set_error (error,
812                    G_SPAWN_ERROR,
813                    G_SPAWN_ERROR_CHDIR,
814                    _("Failed to change to directory '%s' (%s)"),
815                    working_directory,
816                    g_strerror (buf[1]));
817       goto cleanup_and_fail;
818       
819     case CHILD_SPAWN_FAILED:
820       g_set_error (error,
821                    G_SPAWN_ERROR,
822                    G_SPAWN_ERROR_FAILED,
823                    _("Failed to execute child process (%s)"),
824                    g_strerror (buf[1]));
825       goto cleanup_and_fail;
826     }
827
828   /* Success against all odds! return the information */
829       
830   if (standard_input)
831     *standard_input = stdin_pipe[1];
832   if (standard_output)
833     *standard_output = stdout_pipe[0];
834   if (standard_error)
835     *standard_error = stderr_pipe[0];
836   if (exit_status)
837     *exit_status = buf[1];
838   CloseHandle ((HANDLE) helper);
839   
840   return TRUE;
841
842  cleanup_and_fail:
843   if (helper != -1)
844     CloseHandle ((HANDLE) helper);
845   close_and_invalidate (&child_err_report_pipe[0]);
846   close_and_invalidate (&child_err_report_pipe[1]);
847   close_and_invalidate (&stdin_pipe[0]);
848   close_and_invalidate (&stdin_pipe[1]);
849   close_and_invalidate (&stdout_pipe[0]);
850   close_and_invalidate (&stdout_pipe[1]);
851   close_and_invalidate (&stderr_pipe[0]);
852   close_and_invalidate (&stderr_pipe[1]);
853
854   return FALSE;
855 }
856
857 static gboolean
858 make_pipe (gint     p[2],
859            GError **error)
860 {
861   if (pipe (p) < 0)
862     {
863       g_set_error (error,
864                    G_SPAWN_ERROR,
865                    G_SPAWN_ERROR_FAILED,
866                    _("Failed to create pipe for communicating with child process (%s)"),
867                    g_strerror (errno));
868       return FALSE;
869     }
870   else
871     return TRUE;
872 }
873
874 #endif /* !GSPAWN_HELPER */