glib/gconvert.c glib/gspawn-win32.c some minor documentation fixes.
[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 "glib.h"
41
42 #include <string.h>
43 #include <stdlib.h>
44 #include <stdio.h>
45
46 #include <windows.h>
47 #include <errno.h>
48 #include <fcntl.h>
49 #include <io.h>
50 #include <process.h>
51 #include <direct.h>
52
53 #include "glibintl.h"
54
55 #ifdef G_SPAWN_WIN32_DEBUG
56   static int debug = 1;
57   #define SETUP_DEBUG() /* empty */
58
59 #else
60   static int debug = -1;
61   #define SETUP_DEBUG()                                 \
62     G_STMT_START                                        \
63       {                                                 \
64         if (debug == -1)                                \
65           {                                             \
66             if (getenv ("G_SPAWN_WIN32_DEBUG") != NULL) \
67               debug = 1;                                \
68             else                                        \
69               debug = 0;                                \
70           }                                             \
71       }                                                 \
72     G_STMT_END
73 #endif
74
75 enum
76 {
77   CHILD_NO_ERROR,
78   CHILD_CHDIR_FAILED,
79   CHILD_SPAWN_FAILED,
80 };
81
82 enum {
83   ARG_CHILD_ERR_REPORT = 1,
84   ARG_STDIN,
85   ARG_STDOUT,
86   ARG_STDERR,
87   ARG_WORKING_DIRECTORY,
88   ARG_CLOSE_DESCRIPTORS,
89   ARG_USE_PATH,
90   ARG_WAIT,
91   ARG_PROGRAM,
92   ARG_COUNT = ARG_PROGRAM
93 };
94
95 #ifndef GSPAWN_HELPER
96
97 static gboolean make_pipe            (gint                  p[2],
98                                       GError              **error);
99 static gboolean fork_exec_with_pipes (gboolean              dont_wait,
100                                       const gchar          *working_directory,
101                                       gchar               **argv,
102                                       gchar               **envp,
103                                       gboolean              close_descriptors,
104                                       gboolean              search_path,
105                                       gboolean              stdout_to_null,
106                                       gboolean              stderr_to_null,
107                                       gboolean              child_inherits_stdin,
108                                       GSpawnChildSetupFunc  child_setup,
109                                       gpointer              user_data,
110                                       gint                 *standard_input,
111                                       gint                 *standard_output,
112                                       gint                 *standard_error,
113                                       gint                 *exit_status,
114                                       GError              **error);
115
116 GQuark
117 g_spawn_error_quark (void)
118 {
119   static GQuark quark = 0;
120   if (quark == 0)
121     quark = g_quark_from_static_string ("g-exec-error-quark");
122   return quark;
123 }
124
125 /**
126  * g_spawn_async:
127  * @working_directory: child's current working directory, or NULL to inherit parent's
128  * @argv: child's argument vector
129  * @envp: child's environment, or NULL to inherit parent's
130  * @flags: flags from #GSpawnFlags
131  * @child_setup: function to run in the child just before exec()
132  * @user_data: user data for @child_setup
133  * @child_pid: return location for child process ID, or NULL
134  * @error: return location for error
135  * 
136  * See g_spawn_async_with_pipes() for a full description; this function
137  * simply calls the g_spawn_async_with_pipes() without any pipes.
138  * 
139  * Return value: TRUE on success, FALSE if error is set
140  **/
141 gboolean
142 g_spawn_async (const gchar          *working_directory,
143                gchar               **argv,
144                gchar               **envp,
145                GSpawnFlags           flags,
146                GSpawnChildSetupFunc  child_setup,
147                gpointer              user_data,
148                gint                 *child_pid,
149                GError              **error)
150 {
151   g_return_val_if_fail (argv != NULL, FALSE);
152   
153   return g_spawn_async_with_pipes (working_directory,
154                                    argv, envp,
155                                    flags,
156                                    child_setup,
157                                    user_data,
158                                    child_pid,
159                                    NULL, NULL, NULL,
160                                    error);
161 }
162
163 /* Avoids a danger in threaded situations (calling close()
164  * on a file descriptor twice, and another thread has
165  * re-opened it since the first close)
166  */
167 static gint
168 close_and_invalidate (gint *fd)
169 {
170   gint ret;
171
172   ret = close (*fd);
173   *fd = -1;
174
175   return ret;
176 }
177
178 typedef enum
179 {
180   READ_FAILED = 0, /* FALSE */
181   READ_OK,
182   READ_EOF
183 } ReadResult;
184
185 static ReadResult
186 read_data (GString     *str,
187            GIOChannel  *iochannel,
188            GError     **error)
189 {
190   GIOError gioerror;
191   gint bytes;
192   gchar buf[4096];
193
194  again:
195   
196   gioerror = g_io_channel_read (iochannel, buf, sizeof (buf), &bytes);
197
198   if (bytes == 0)
199     return READ_EOF;
200   else if (bytes > 0)
201     {
202       g_string_append_len (str, buf, bytes);
203       return READ_OK;
204     }
205   else if (gioerror == G_IO_ERROR_AGAIN)
206     goto again;
207   else if (gioerror != G_IO_ERROR_NONE)
208     {
209       g_set_error (error,
210                    G_SPAWN_ERROR,
211                    G_SPAWN_ERROR_READ,
212                    _("Failed to read data from child process"));
213       
214       return READ_FAILED;
215     }
216   else
217     return READ_OK;
218 }
219
220 /**
221  * g_spawn_sync:
222  * @working_directory: child's current working directory, or NULL to inherit parent's
223  * @argv: child's argument vector
224  * @envp: child's environment, or NULL to inherit parent's
225  * @flags: flags from #GSpawnFlags
226  * @child_setup: function to run in the child just before exec()
227  * @user_data: user data for @child_setup
228  * @standard_output: return location for child output 
229  * @standard_error: return location for child error messages
230  * @exit_status: child exit status, as returned by waitpid()
231  * @error: return location for error
232  *
233  * Executes a child synchronously (waits for the child to exit before returning).
234  * All output from the child is stored in @standard_output and @standard_error,
235  * if those parameters are non-NULL. If @exit_status is non-NULL, the exit status
236  * of the child is stored there as it would be by waitpid(); standard UNIX
237  * macros such as WIFEXITED() and WEXITSTATUS() must be used to evaluate the
238  * exit status. If an error occurs, no data is returned in @standard_output,
239  * @standard_error, or @exit_status.
240  * 
241  * This function calls g_spawn_async_with_pipes() internally; see that function
242  * for full details on the other parameters.
243  * 
244  * Return value: TRUE on success, FALSE if an error was set.
245  **/
246 gboolean
247 g_spawn_sync (const gchar          *working_directory,
248               gchar               **argv,
249               gchar               **envp,
250               GSpawnFlags           flags,
251               GSpawnChildSetupFunc  child_setup,
252               gpointer              user_data,
253               gchar               **standard_output,
254               gchar               **standard_error,
255               gint                 *exit_status,
256               GError              **error)     
257 {
258   gint outpipe = -1;
259   gint errpipe = -1;
260   GIOChannel *outchannel = NULL;
261   GIOChannel *errchannel = NULL;
262   GPollFD outfd, errfd;
263   GPollFD fds[2];
264   gint nfds;
265   gint outindex = -1;
266   gint errindex = -1;
267   gint ret;
268   GString *outstr = NULL;
269   GString *errstr = NULL;
270   gboolean failed;
271   gint status;
272   
273   g_return_val_if_fail (argv != NULL, FALSE);
274   g_return_val_if_fail (!(flags & G_SPAWN_DO_NOT_REAP_CHILD), FALSE);
275   g_return_val_if_fail (standard_output == NULL ||
276                         !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
277   g_return_val_if_fail (standard_error == NULL ||
278                         !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
279   
280   /* Just to ensure segfaults if callers try to use
281    * these when an error is reported.
282    */
283   if (standard_output)
284     *standard_output = NULL;
285
286   if (standard_error)
287     *standard_error = NULL;
288   
289   if (!fork_exec_with_pipes (FALSE,
290                              working_directory,
291                              argv,
292                              envp,
293                              !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
294                              (flags & G_SPAWN_SEARCH_PATH) != 0,
295                              (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
296                              (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
297                              (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
298                              child_setup,
299                              user_data,
300                              NULL,
301                              standard_output ? &outpipe : NULL,
302                              standard_error ? &errpipe : NULL,
303                              &status,
304                              error))
305     return FALSE;
306
307   /* Read data from child. */
308   
309   failed = FALSE;
310
311   if (outpipe >= 0)
312     {
313       outstr = g_string_new ("");
314       outchannel = g_io_channel_win32_new_fd (outpipe);
315       g_io_channel_win32_make_pollfd (outchannel,
316                                       G_IO_IN | G_IO_ERR | G_IO_HUP,
317                                       &outfd);
318     }
319       
320   if (errpipe >= 0)
321     {
322       errstr = g_string_new ("");
323       errchannel = g_io_channel_win32_new_fd (errpipe);
324       g_io_channel_win32_make_pollfd (errchannel,
325                                       G_IO_IN | G_IO_ERR | G_IO_HUP,
326                                       &errfd);
327     }
328
329   /* Read data until we get EOF on both pipes. */
330   while (!failed &&
331          (outpipe >= 0 ||
332           errpipe >= 0))
333     {
334       nfds = 0;
335       if (outpipe >= 0)
336         {
337           fds[nfds] = outfd;
338           outindex = nfds;
339           nfds++;
340         }
341       if (errpipe >= 0)
342         {
343           fds[nfds] = errfd;
344           errindex = nfds;
345           nfds++;
346         }
347
348       if (debug)
349         g_print ("%s:g_spawn_sync: calling g_io_channel_win32_poll, nfds=%d\n",
350                  __FILE__, nfds);
351
352       ret = g_io_channel_win32_poll (fds, nfds, -1);
353
354       if (ret < 0)
355         {
356           failed = TRUE;
357
358           g_set_error (error,
359                        G_SPAWN_ERROR,
360                        G_SPAWN_ERROR_READ,
361                        _("Unexpected error in g_io_channel_win32_poll() reading data from a child process"));
362               
363           break;
364         }
365
366       if (outpipe >= 0 && (fds[outindex].revents & G_IO_IN))
367         {
368           switch (read_data (outstr, outchannel, error))
369             {
370             case READ_FAILED:
371               if (debug)
372                 g_print ("g_spawn_sync: outchannel: READ_FAILED\n");
373               failed = TRUE;
374               break;
375             case READ_EOF:
376               if (debug)
377                 g_print ("g_spawn_sync: outchannel: READ_EOF\n");
378               g_io_channel_unref (outchannel);
379               outchannel = NULL;
380               close_and_invalidate (&outpipe);
381               break;
382             default:
383               if (debug)
384                 g_print ("g_spawn_sync: outchannel: OK\n");
385               break;
386             }
387
388           if (failed)
389             break;
390         }
391
392       if (errpipe >= 0 && (fds[errindex].revents & G_IO_IN))
393         {
394           switch (read_data (errstr, errchannel, error))
395             {
396             case READ_FAILED:
397               if (debug)
398                 g_print ("g_spawn_sync: errchannel: READ_FAILED\n");
399               failed = TRUE;
400               break;
401             case READ_EOF:
402               if (debug)
403                 g_print ("g_spawn_sync: errchannel: READ_EOF\n");
404               g_io_channel_unref (errchannel);
405               errchannel = NULL;
406               close_and_invalidate (&errpipe);
407               break;
408             default:
409               if (debug)
410                 g_print ("g_spawn_sync: errchannel: OK\n");
411               break;
412             }
413
414           if (failed)
415             break;
416         }
417     }
418
419   /* These should only be open still if we had an error.  */
420   
421   if (outchannel != NULL)
422     g_io_channel_unref (outchannel);
423   if (errchannel != NULL)
424     g_io_channel_unref (errchannel);
425   if (outpipe >= 0)
426     close_and_invalidate (&outpipe);
427   if (errpipe >= 0)
428     close_and_invalidate (&errpipe);
429   
430   if (failed)
431     {
432       if (outstr)
433         g_string_free (outstr, TRUE);
434       if (errstr)
435         g_string_free (errstr, TRUE);
436
437       return FALSE;
438     }
439   else
440     {
441       if (exit_status)
442         *exit_status = status;
443       
444       if (standard_output)        
445         *standard_output = g_string_free (outstr, FALSE);
446
447       if (standard_error)
448         *standard_error = g_string_free (errstr, FALSE);
449
450       return TRUE;
451     }
452 }
453
454 /**
455  * g_spawn_async_with_pipes:
456  * @working_directory: child's current working directory, or NULL to inherit parent's
457  * @argv: child's argument vector
458  * @envp: child's environment, or NULL to inherit parent's
459  * @flags: flags from #GSpawnFlags
460  * @child_setup: function to run in the child just before exec()
461  * @user_data: user data for @child_setup
462  * @child_pid: return location for child process ID, or NULL
463  * @standard_input: return location for file descriptor to write to child's stdin, or NULL
464  * @standard_output: return location for file descriptor to read child's stdout, or NULL
465  * @standard_error: return location for file descriptor to read child's stderr, or NULL
466  * @error: return location for error
467  *
468  * Executes a child program asynchronously (your program will not
469  * block waiting for the child to exit). The child program is
470  * specified by the only argument that must be provided, @argv. @argv
471  * should be a %NULL-terminated array of strings, to be passed as the
472  * argument vector for the child. The first string in @argv is of
473  * course the name of the program to execute. By default, the name of
474  * the program must be a full path; the PATH shell variable will only
475  * be searched if you pass the %G_SPAWN_SEARCH_PATH flag.
476  *
477  * @envp is a %NULL-terminated array of strings, where each string
478  * has the form <literal>KEY=VALUE</literal>. This will become
479  * the child's environment. If @envp is NULL, the child inherits its
480  * parent's environment.
481  *
482  * @flags should be the bitwise OR of any flags you want to affect the
483  * function's behavior. The %G_SPAWN_DO_NOT_REAP_CHILD means that the
484  * child will not be automatically reaped; you must call waitpid() or
485  * handle SIGCHLD yourself, or the child will become a zombie.
486  * %G_SPAWN_LEAVE_DESCRIPTORS_OPEN means that the parent's open file
487  * descriptors will be inherited by the child; otherwise all
488  * descriptors except stdin/stdout/stderr will be closed before
489  * calling exec() in the child. %G_SPAWN_SEARCH_PATH means that
490  * <literal>argv[0]</literal> need not be an absolute path, it
491  * will be looked for in the user's PATH. %G_SPAWN_STDOUT_TO_DEV_NULL
492  * means that the child's standad output will be discarded, instead
493  * of going to the same location as the parent's standard output.
494  * %G_SPAWN_STDERR_TO_DEV_NULL means that the child's standard error
495  * will be discarded. %G_SPAWN_CHILD_INHERITS_STDIN means that
496  * the child will inherit the parent's standard input (by default,
497  * the child's standard input is attached to /dev/null).
498  *
499  * @child_setup and @user_data are a function and user data to be
500  * called in the child after GLib has performed all the setup it plans
501  * to perform (including creating pipes, closing file descriptors,
502  * etc.) but before calling exec(). That is, @child_setup is called
503  * just before calling exec() in the child. Obviously actions taken in
504  * this function will only affect the child, not the parent. 
505  *
506  * If non-NULL, @child_pid will be filled with the child's process
507  * ID. You can use the process ID to send signals to the child, or
508  * to waitpid() if you specified the %G_SPAWN_DO_NOT_REAP_CHILD flag.
509  *
510  * If non-NULL, the @standard_input, @standard_output, @standard_error
511  * locations will be filled with file descriptors for writing to the child's
512  * standard input or reading from its standard output or standard error.
513  * The caller of g_spawn_async_with_pipes() must close these file descriptors
514  * when they are no longer in use. If these parameters are NULL, the
515  * corresponding pipe won't be created.
516  *
517  * @error can be NULL to ignore errors, or non-NULL to report errors.
518  * If an error is set, the function returns FALSE. Errors
519  * are reported even if they occur in the child (for example if the
520  * executable in <literal>argv[0]</literal> is not found). Typically
521  * the <literal>message</literal> field of returned errors should be displayed
522  * to users. Possible errors are those from the #G_SPAWN_ERROR domain.
523  *
524  * If an error occurs, @child_pid, @standard_input, @standard_output,
525  * and @standard_error will not be filled with valid values.
526  * 
527  * Return value: TRUE on success, FALSE if an error was set
528  **/
529 gboolean
530 g_spawn_async_with_pipes (const gchar          *working_directory,
531                           gchar               **argv,
532                           gchar               **envp,
533                           GSpawnFlags           flags,
534                           GSpawnChildSetupFunc  child_setup,
535                           gpointer              user_data,
536                           gint                 *child_pid,
537                           gint                 *standard_input,
538                           gint                 *standard_output,
539                           gint                 *standard_error,
540                           GError              **error)
541 {
542   g_return_val_if_fail (argv != NULL, FALSE);
543   g_return_val_if_fail (standard_output == NULL ||
544                         !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
545   g_return_val_if_fail (standard_error == NULL ||
546                         !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
547   /* can't inherit stdin if we have an input pipe. */
548   g_return_val_if_fail (standard_input == NULL ||
549                         !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
550   
551   return fork_exec_with_pipes (!(flags & G_SPAWN_DO_NOT_REAP_CHILD),
552                                working_directory,
553                                argv,
554                                envp,
555                                !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
556                                (flags & G_SPAWN_SEARCH_PATH) != 0,
557                                (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
558                                (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
559                                (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
560                                child_setup,
561                                user_data,
562                                standard_input,
563                                standard_output,
564                                standard_error,
565                                NULL,
566                                error);
567 }
568
569 /**
570  * g_spawn_command_line_sync:
571  * @command_line: a command line 
572  * @standard_output: return location for child output
573  * @standard_error: return location for child errors
574  * @exit_status: return location for child exit status
575  * @error: return location for errors
576  *
577  * A simple version of g_spawn_sync() with little-used parameters
578  * removed, taking a command line instead of an argument vector.  See
579  * g_spawn_sync() for full details. @command_line will be parsed by
580  * g_shell_parse_argv(). Unlike g_spawn_sync(), the %G_SPAWN_SEARCH_PATH flag
581  * is enabled. Note that %G_SPAWN_SEARCH_PATH can have security
582  * implications, so consider using g_spawn_sync() directly if
583  * appropriate. Possible errors are those from g_spawn_sync() and those
584  * from g_shell_parse_argv().
585  * 
586  * Return value: TRUE on success, FALSE if an error was set
587  **/
588 gboolean
589 g_spawn_command_line_sync (const gchar  *command_line,
590                            gchar       **standard_output,
591                            gchar       **standard_error,
592                            gint         *exit_status,
593                            GError      **error)
594 {
595   gboolean retval;
596   gchar **argv = 0;
597
598   g_return_val_if_fail (command_line != NULL, FALSE);
599   
600   if (!g_shell_parse_argv (command_line,
601                            NULL, &argv,
602                            error))
603     return FALSE;
604   
605   retval = g_spawn_sync (NULL,
606                          argv,
607                          NULL,
608                          G_SPAWN_SEARCH_PATH,
609                          NULL,
610                          NULL,
611                          standard_output,
612                          standard_error,
613                          exit_status,
614                          error);
615   g_strfreev (argv);
616
617   return retval;
618 }
619
620 /**
621  * g_spawn_command_line_async:
622  * @command_line: a command line
623  * @error: return location for errors
624  * 
625  * A simple version of g_spawn_async() that parses a command line with
626  * g_shell_parse_argv() and passes it to g_spawn_async(). Runs a
627  * command line in the background. Unlike g_spawn_async(), the
628  * %G_SPAWN_SEARCH_PATH flag is enabled, other flags are not. Note
629  * that %G_SPAWN_SEARCH_PATH can have security implications, so
630  * consider using g_spawn_async() directly if appropriate. Possible
631  * errors are those from g_shell_parse_argv() and g_spawn_async().
632  * 
633  * Return value: TRUE on success, FALSE if error is set.
634  **/
635 gboolean
636 g_spawn_command_line_async (const gchar *command_line,
637                             GError     **error)
638 {
639   gboolean retval;
640   gchar **argv = 0;
641
642   g_return_val_if_fail (command_line != NULL, FALSE);
643
644   if (!g_shell_parse_argv (command_line,
645                            NULL, &argv,
646                            error))
647     return FALSE;
648   
649   retval = g_spawn_async (NULL,
650                           argv,
651                           NULL,
652                           G_SPAWN_SEARCH_PATH,
653                           NULL,
654                           NULL,
655                           NULL,
656                           error);
657   g_strfreev (argv);
658
659   return retval;
660 }
661
662 static gint
663 do_exec (gboolean              dont_wait,
664          gint                  child_err_report_fd,
665          gint                  stdin_fd,
666          gint                  stdout_fd,
667          gint                  stderr_fd,
668          const gchar          *working_directory,
669          gchar               **argv,
670          gchar               **envp,
671          gboolean              close_descriptors,
672          gboolean              search_path,
673          gboolean              stdout_to_null,
674          gboolean              stderr_to_null,
675          gboolean              child_inherits_stdin,
676          GSpawnChildSetupFunc  child_setup,
677          gpointer              user_data)
678 {
679   gchar **new_argv;
680   gchar args[ARG_COUNT][10];
681   gint i;
682   int argc = 0;
683
684   SETUP_DEBUG();
685
686   while (argv[argc])
687     ++argc;
688
689   new_argv = g_new (gchar *, argc + 1 + ARG_COUNT);
690
691   new_argv[0] = "gspawn-win32-helper";
692   sprintf (args[ARG_CHILD_ERR_REPORT], "%d", child_err_report_fd);
693   new_argv[ARG_CHILD_ERR_REPORT] = args[ARG_CHILD_ERR_REPORT];
694
695   if (stdin_fd >= 0)
696     {
697       sprintf (args[ARG_STDIN], "%d", stdin_fd);
698       new_argv[ARG_STDIN] = args[ARG_STDIN];
699     }
700   else if (child_inherits_stdin)
701     {
702       /* Let stdin be alone */
703       new_argv[ARG_STDIN] = "-";
704     }
705   else
706     {
707       /* Keep process from blocking on a read of stdin */
708       new_argv[ARG_STDIN] = "z";
709     }
710
711   if (stdout_fd >= 0)
712     {
713       sprintf (args[ARG_STDOUT], "%d", stdout_fd);
714       new_argv[ARG_STDOUT] = args[ARG_STDOUT];
715     }
716   else if (stdout_to_null)
717     {
718       new_argv[ARG_STDOUT] = "z";
719     }
720   else
721     {
722       new_argv[ARG_STDOUT] = "-";
723     }
724
725   if (stderr_fd >= 0)
726     {
727       sprintf (args[ARG_STDERR], "%d", stderr_fd);
728       new_argv[ARG_STDERR] = args[ARG_STDERR];
729     }
730   else if (stderr_to_null)
731     {
732       new_argv[ARG_STDERR] = "z";
733     }
734   else
735     {
736       new_argv[ARG_STDERR] = "-";
737     }
738
739   if (working_directory && *working_directory)
740     new_argv[ARG_WORKING_DIRECTORY] = working_directory;
741   else
742     new_argv[ARG_WORKING_DIRECTORY] = "-";
743
744   if (close_descriptors)
745     new_argv[ARG_CLOSE_DESCRIPTORS] = "y";
746   else
747     new_argv[ARG_CLOSE_DESCRIPTORS] = "-";
748
749   if (search_path)
750     new_argv[ARG_USE_PATH] = "y";
751   else
752     new_argv[ARG_USE_PATH] = "-";
753
754   if (dont_wait)
755     new_argv[ARG_WAIT] = "-";
756   else
757     new_argv[ARG_WAIT] = "w";
758
759   for (i = 0; i <= argc; i++)
760     new_argv[ARG_PROGRAM + i] = argv[i];
761
762   /* Call user function just before we execute the helper program,
763    * which executes the program. Dunno what's the usefulness of this.
764    * A child setup function used on Unix probably isn't of much use
765    * as such on Win32, anyhow.
766    */
767   if (child_setup)
768     {
769       (* child_setup) (user_data);
770     }
771
772   if (debug)
773     {
774       g_print ("calling gspawn-win32-helper with argv:\n");
775       for (i = 0; i < argc + 1 + ARG_COUNT; i++)
776         g_print ("argv[%d]: %s\n", i, (new_argv[i] ? new_argv[i] : "NULL"));
777     }
778   
779   if (envp != NULL)
780     /* Let's hope envp hasn't mucked with PATH so that
781      * gspawn-win32-helper.exe isn't found.
782      */
783     spawnvpe (P_NOWAIT, "gspawn-win32-helper", new_argv, envp);
784   else
785     spawnvp (P_NOWAIT, "gspawn-win32-helper", new_argv);
786
787   /* FIXME: What if gspawn-win32-helper.exe isn't found? */
788
789   /* Close the child_err_report_fd and the other process's ends of the
790    * pipes in this process, otherwise the reader will never get
791    * EOF.
792    */
793   close (child_err_report_fd);
794   if (stdin_fd >= 0)
795     close (stdin_fd);
796   if (stdout_fd >= 0)
797     close (stdout_fd);
798   if (stderr_fd >= 0)
799     close (stderr_fd);
800
801   g_free (new_argv);
802
803   return 0;
804 }
805
806 static gboolean
807 read_ints (int      fd,
808            gint*    buf,
809            gint     n_ints_in_buf,
810            gint    *n_ints_read,
811            GError **error)
812 {
813   gint bytes = 0;
814   
815   while (bytes < sizeof(gint)*n_ints_in_buf)
816     {
817       gint chunk;
818
819       if (debug)
820         g_print ("%s:read_ints: trying to read %d bytes from pipe...\n",
821                  __FILE__,
822                  sizeof(gint)*n_ints_in_buf - bytes);
823
824       chunk = read (fd, ((gchar*)buf) + bytes,
825                     sizeof(gint)*n_ints_in_buf - bytes);
826
827       if (debug)
828         g_print ("... got %d bytes\n", chunk);
829           
830       if (chunk < 0)
831         {
832           /* Some weird shit happened, bail out */
833               
834           g_set_error (error,
835                        G_SPAWN_ERROR,
836                        G_SPAWN_ERROR_FAILED,
837                        _("Failed to read from child pipe (%s)"),
838                        g_strerror (errno));
839
840           return FALSE;
841         }
842       else if (chunk == 0)
843         break; /* EOF */
844       else
845         bytes += chunk;
846     }
847
848   *n_ints_read = bytes/sizeof(gint);
849
850   return TRUE;
851 }
852
853 static gboolean
854 fork_exec_with_pipes (gboolean              dont_wait,
855                       const gchar          *working_directory,
856                       gchar               **argv,
857                       gchar               **envp,
858                       gboolean              close_descriptors,
859                       gboolean              search_path,
860                       gboolean              stdout_to_null,
861                       gboolean              stderr_to_null,
862                       gboolean              child_inherits_stdin,
863                       GSpawnChildSetupFunc  child_setup,
864                       gpointer              user_data,
865                       gint                 *standard_input,
866                       gint                 *standard_output,
867                       gint                 *standard_error,
868                       gint                 *exit_status,
869                       GError              **error)     
870 {
871   gint stdin_pipe[2] = { -1, -1 };
872   gint stdout_pipe[2] = { -1, -1 };
873   gint stderr_pipe[2] = { -1, -1 };
874   gint child_err_report_pipe[2] = { -1, -1 };
875   gint status;
876   gint buf[2];
877   gint n_ints = 0;
878   
879   if (!make_pipe (child_err_report_pipe, error))
880     return FALSE;
881
882   if (standard_input && !make_pipe (stdin_pipe, error))
883     goto cleanup_and_fail;
884   
885   if (standard_output && !make_pipe (stdout_pipe, error))
886     goto cleanup_and_fail;
887
888   if (standard_error && !make_pipe (stderr_pipe, error))
889     goto cleanup_and_fail;
890
891   status = do_exec (dont_wait,
892                     child_err_report_pipe[1],
893                     stdin_pipe[0],
894                     stdout_pipe[1],
895                     stderr_pipe[1],
896                     working_directory,
897                     argv,
898                     envp,
899                     close_descriptors,
900                     search_path,
901                     stdout_to_null,
902                     stderr_to_null,
903                     child_inherits_stdin,
904                     child_setup,
905                     user_data);
906       
907   if (!read_ints (child_err_report_pipe[0],
908                   buf, 2, &n_ints,
909                   error))
910     goto cleanup_and_fail;
911         
912   if (n_ints == 2)
913     {
914       /* Error from the child. */
915       
916       switch (buf[0])
917         {
918         case CHILD_NO_ERROR:
919           break;
920           
921         case CHILD_CHDIR_FAILED:
922           g_set_error (error,
923                        G_SPAWN_ERROR,
924                        G_SPAWN_ERROR_CHDIR,
925                        _("Failed to change to directory '%s' (%s)"),
926                        working_directory,
927                        g_strerror (buf[1]));
928           goto cleanup_and_fail;
929           
930         case CHILD_SPAWN_FAILED:
931           g_set_error (error,
932                        G_SPAWN_ERROR,
933                        G_SPAWN_ERROR_FAILED,
934                        _("Failed to execute child process (%s)"),
935                        g_strerror (buf[1]));
936           goto cleanup_and_fail;
937         }
938     }
939
940   /* Success against all odds! return the information */
941       
942   if (standard_input)
943     *standard_input = stdin_pipe[1];
944   if (standard_output)
945     *standard_output = stdout_pipe[0];
946   if (standard_error)
947     *standard_error = stderr_pipe[0];
948   if (exit_status)
949     *exit_status = status;
950   
951   return TRUE;
952
953  cleanup_and_fail:
954   close_and_invalidate (&child_err_report_pipe[0]);
955   close_and_invalidate (&child_err_report_pipe[1]);
956   close_and_invalidate (&stdin_pipe[0]);
957   close_and_invalidate (&stdin_pipe[1]);
958   close_and_invalidate (&stdout_pipe[0]);
959   close_and_invalidate (&stdout_pipe[1]);
960   close_and_invalidate (&stderr_pipe[0]);
961   close_and_invalidate (&stderr_pipe[1]);
962
963   return FALSE;
964 }
965
966 static gboolean
967 make_pipe (gint     p[2],
968            GError **error)
969 {
970   if (pipe (p) < 0)
971     {
972       g_set_error (error,
973                    G_SPAWN_ERROR,
974                    G_SPAWN_ERROR_FAILED,
975                    _("Failed to create pipe for communicating with child process (%s)"),
976                    g_strerror (errno));
977       return FALSE;
978     }
979   else
980     return TRUE;
981 }
982
983 #endif /* !GSPAWN_HELPER */