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