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