Use <envar>, not <envvar>.
[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 <function>exec()</function>
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 <function>exec()</function>
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 <function>waitpid()</function>
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 returned by <function>waitpid()</function>; standard UNIX
237  * macros such as <function>WIFEXITED()</function> and <function>WEXITSTATUS()</function> 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 <function>exec()</function>
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 <envar>PATH</envar> 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 
485  * <function>waitpid()</function> or handle %SIGCHLD yourself, or the 
486  * child will become a zombie. %G_SPAWN_LEAVE_DESCRIPTORS_OPEN means 
487  * that the parent's open file descriptors will be inherited by the child; 
488  * otherwise all descriptors except stdin/stdout/stderr will be closed before
489  * calling <function>exec()</function> in the child. %G_SPAWN_SEARCH_PATH 
490  * means that <literal>argv[0]</literal> need not be an absolute path, it
491  * will be looked for in the user's <envar>PATH</envar>. 
492  * %G_SPAWN_STDOUT_TO_DEV_NULL means that the child's standard output 
493  * will be discarded, instead of going to the same location as the parent's 
494  * standard output. %G_SPAWN_STDERR_TO_DEV_NULL means that the child's 
495  * standard error 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 <function>exec()</function>. That is, @child_setup 
503  * is called just before calling <function>exec()</function> in the child. 
504  * Obviously actions taken in this function will only affect the child, not 
505  * the parent. 
506  *
507  * If non-%NULL, @child_pid will be filled with the child's process
508  * ID. You can use the process ID to send signals to the child, or
509  * to <function>waitpid()</function> if you specified the 
510  * %G_SPAWN_DO_NOT_REAP_CHILD flag.
511  *
512  * If non-%NULL, the @standard_input, @standard_output, @standard_error
513  * locations will be filled with file descriptors for writing to the child's
514  * standard input or reading from its standard output or standard error.
515  * The caller of g_spawn_async_with_pipes() must close these file descriptors
516  * when they are no longer in use. If these parameters are %NULL, the
517  * corresponding pipe won't be created.
518  *
519  * @error can be %NULL to ignore errors, or non-%NULL to report errors.
520  * If an error is set, the function returns %FALSE. Errors
521  * are reported even if they occur in the child (for example if the
522  * executable in <literal>argv[0]</literal> is not found). Typically
523  * the <literal>message</literal> field of returned errors should be displayed
524  * to users. Possible errors are those from the #G_SPAWN_ERROR domain.
525  *
526  * If an error occurs, @child_pid, @standard_input, @standard_output,
527  * and @standard_error will not be filled with valid values.
528  * 
529  * Return value: %TRUE on success, %FALSE if an error was set
530  **/
531 gboolean
532 g_spawn_async_with_pipes (const gchar          *working_directory,
533                           gchar               **argv,
534                           gchar               **envp,
535                           GSpawnFlags           flags,
536                           GSpawnChildSetupFunc  child_setup,
537                           gpointer              user_data,
538                           gint                 *child_pid,
539                           gint                 *standard_input,
540                           gint                 *standard_output,
541                           gint                 *standard_error,
542                           GError              **error)
543 {
544   g_return_val_if_fail (argv != NULL, FALSE);
545   g_return_val_if_fail (standard_output == NULL ||
546                         !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
547   g_return_val_if_fail (standard_error == NULL ||
548                         !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
549   /* can't inherit stdin if we have an input pipe. */
550   g_return_val_if_fail (standard_input == NULL ||
551                         !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
552   
553   return fork_exec_with_pipes (!(flags & G_SPAWN_DO_NOT_REAP_CHILD),
554                                working_directory,
555                                argv,
556                                envp,
557                                !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
558                                (flags & G_SPAWN_SEARCH_PATH) != 0,
559                                (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
560                                (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
561                                (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
562                                child_setup,
563                                user_data,
564                                standard_input,
565                                standard_output,
566                                standard_error,
567                                NULL,
568                                error);
569 }
570
571 /**
572  * g_spawn_command_line_sync:
573  * @command_line: a command line 
574  * @standard_output: return location for child output
575  * @standard_error: return location for child errors
576  * @exit_status: return location for child exit status
577  * @error: return location for errors
578  *
579  * A simple version of g_spawn_sync() with little-used parameters
580  * removed, taking a command line instead of an argument vector.  See
581  * g_spawn_sync() for full details. @command_line will be parsed by
582  * g_shell_parse_argv(). Unlike g_spawn_sync(), the %G_SPAWN_SEARCH_PATH flag
583  * is enabled. Note that %G_SPAWN_SEARCH_PATH can have security
584  * implications, so consider using g_spawn_sync() directly if
585  * appropriate. Possible errors are those from g_spawn_sync() and those
586  * from g_shell_parse_argv().
587  * 
588  * Return value: %TRUE on success, %FALSE if an error was set
589  **/
590 gboolean
591 g_spawn_command_line_sync (const gchar  *command_line,
592                            gchar       **standard_output,
593                            gchar       **standard_error,
594                            gint         *exit_status,
595                            GError      **error)
596 {
597   gboolean retval;
598   gchar **argv = 0;
599
600   g_return_val_if_fail (command_line != NULL, FALSE);
601   
602   if (!g_shell_parse_argv (command_line,
603                            NULL, &argv,
604                            error))
605     return FALSE;
606   
607   retval = g_spawn_sync (NULL,
608                          argv,
609                          NULL,
610                          G_SPAWN_SEARCH_PATH,
611                          NULL,
612                          NULL,
613                          standard_output,
614                          standard_error,
615                          exit_status,
616                          error);
617   g_strfreev (argv);
618
619   return retval;
620 }
621
622 /**
623  * g_spawn_command_line_async:
624  * @command_line: a command line
625  * @error: return location for errors
626  * 
627  * A simple version of g_spawn_async() that parses a command line with
628  * g_shell_parse_argv() and passes it to g_spawn_async(). Runs a
629  * command line in the background. Unlike g_spawn_async(), the
630  * %G_SPAWN_SEARCH_PATH flag is enabled, other flags are not. Note
631  * that %G_SPAWN_SEARCH_PATH can have security implications, so
632  * consider using g_spawn_async() directly if appropriate. Possible
633  * errors are those from g_shell_parse_argv() and g_spawn_async().
634  * 
635  * Return value: %TRUE on success, %FALSE if error is set.
636  **/
637 gboolean
638 g_spawn_command_line_async (const gchar *command_line,
639                             GError     **error)
640 {
641   gboolean retval;
642   gchar **argv = 0;
643
644   g_return_val_if_fail (command_line != NULL, FALSE);
645
646   if (!g_shell_parse_argv (command_line,
647                            NULL, &argv,
648                            error))
649     return FALSE;
650   
651   retval = g_spawn_async (NULL,
652                           argv,
653                           NULL,
654                           G_SPAWN_SEARCH_PATH,
655                           NULL,
656                           NULL,
657                           NULL,
658                           error);
659   g_strfreev (argv);
660
661   return retval;
662 }
663
664 static gint
665 do_exec (gboolean              dont_wait,
666          gint                  child_err_report_fd,
667          gint                  stdin_fd,
668          gint                  stdout_fd,
669          gint                  stderr_fd,
670          const gchar          *working_directory,
671          gchar               **argv,
672          gchar               **envp,
673          gboolean              close_descriptors,
674          gboolean              search_path,
675          gboolean              stdout_to_null,
676          gboolean              stderr_to_null,
677          gboolean              child_inherits_stdin,
678          GSpawnChildSetupFunc  child_setup,
679          gpointer              user_data)
680 {
681   gchar **new_argv;
682   gchar args[ARG_COUNT][10];
683   gint i;
684   int argc = 0;
685
686   SETUP_DEBUG();
687
688   while (argv[argc])
689     ++argc;
690
691   new_argv = g_new (gchar *, argc + 1 + ARG_COUNT);
692
693   new_argv[0] = "gspawn-win32-helper";
694   sprintf (args[ARG_CHILD_ERR_REPORT], "%d", child_err_report_fd);
695   new_argv[ARG_CHILD_ERR_REPORT] = args[ARG_CHILD_ERR_REPORT];
696
697   if (stdin_fd >= 0)
698     {
699       sprintf (args[ARG_STDIN], "%d", stdin_fd);
700       new_argv[ARG_STDIN] = args[ARG_STDIN];
701     }
702   else if (child_inherits_stdin)
703     {
704       /* Let stdin be alone */
705       new_argv[ARG_STDIN] = "-";
706     }
707   else
708     {
709       /* Keep process from blocking on a read of stdin */
710       new_argv[ARG_STDIN] = "z";
711     }
712
713   if (stdout_fd >= 0)
714     {
715       sprintf (args[ARG_STDOUT], "%d", stdout_fd);
716       new_argv[ARG_STDOUT] = args[ARG_STDOUT];
717     }
718   else if (stdout_to_null)
719     {
720       new_argv[ARG_STDOUT] = "z";
721     }
722   else
723     {
724       new_argv[ARG_STDOUT] = "-";
725     }
726
727   if (stderr_fd >= 0)
728     {
729       sprintf (args[ARG_STDERR], "%d", stderr_fd);
730       new_argv[ARG_STDERR] = args[ARG_STDERR];
731     }
732   else if (stderr_to_null)
733     {
734       new_argv[ARG_STDERR] = "z";
735     }
736   else
737     {
738       new_argv[ARG_STDERR] = "-";
739     }
740
741   if (working_directory && *working_directory)
742     new_argv[ARG_WORKING_DIRECTORY] = working_directory;
743   else
744     new_argv[ARG_WORKING_DIRECTORY] = "-";
745
746   if (close_descriptors)
747     new_argv[ARG_CLOSE_DESCRIPTORS] = "y";
748   else
749     new_argv[ARG_CLOSE_DESCRIPTORS] = "-";
750
751   if (search_path)
752     new_argv[ARG_USE_PATH] = "y";
753   else
754     new_argv[ARG_USE_PATH] = "-";
755
756   if (dont_wait)
757     new_argv[ARG_WAIT] = "-";
758   else
759     new_argv[ARG_WAIT] = "w";
760
761   for (i = 0; i <= argc; i++)
762     new_argv[ARG_PROGRAM + i] = argv[i];
763
764   /* Call user function just before we execute the helper program,
765    * which executes the program. Dunno what's the usefulness of this.
766    * A child setup function used on Unix probably isn't of much use
767    * as such on Win32, anyhow
768    */
769   if (child_setup)
770     {
771       (* child_setup) (user_data);
772     }
773
774   if (debug)
775     {
776       g_print ("calling gspawn-win32-helper with argv:\n");
777       for (i = 0; i < argc + 1 + ARG_COUNT; i++)
778         g_print ("argv[%d]: %s\n", i, (new_argv[i] ? new_argv[i] : "NULL"));
779     }
780   
781   if (envp != NULL)
782     /* Let's hope envp hasn't mucked with PATH so that
783      * gspawn-win32-helper.exe isn't found.
784      */
785     spawnvpe (P_NOWAIT, "gspawn-win32-helper", new_argv, envp);
786   else
787     spawnvp (P_NOWAIT, "gspawn-win32-helper", new_argv);
788
789   /* FIXME: What if gspawn-win32-helper.exe isn't found? */
790
791   /* Close the child_err_report_fd and the other process's ends of the
792    * pipes in this process, otherwise the reader will never get
793    * EOF.
794    */
795   close (child_err_report_fd);
796   if (stdin_fd >= 0)
797     close (stdin_fd);
798   if (stdout_fd >= 0)
799     close (stdout_fd);
800   if (stderr_fd >= 0)
801     close (stderr_fd);
802
803   g_free (new_argv);
804
805   return 0;
806 }
807
808 static gboolean
809 read_ints (int      fd,
810            gint*    buf,
811            gint     n_ints_in_buf,
812            gint    *n_ints_read,
813            GError **error)
814 {
815   gint bytes = 0;
816   
817   while (bytes < sizeof(gint)*n_ints_in_buf)
818     {
819       gint chunk;
820
821       if (debug)
822         g_print ("%s:read_ints: trying to read %d bytes from pipe...\n",
823                  __FILE__,
824                  sizeof(gint)*n_ints_in_buf - bytes);
825
826       chunk = read (fd, ((gchar*)buf) + bytes,
827                     sizeof(gint)*n_ints_in_buf - bytes);
828
829       if (debug)
830         g_print ("... got %d bytes\n", chunk);
831           
832       if (chunk < 0)
833         {
834           /* Some weird shit happened, bail out */
835               
836           g_set_error (error,
837                        G_SPAWN_ERROR,
838                        G_SPAWN_ERROR_FAILED,
839                        _("Failed to read from child pipe (%s)"),
840                        g_strerror (errno));
841
842           return FALSE;
843         }
844       else if (chunk == 0)
845         break; /* EOF */
846       else
847         bytes += chunk;
848     }
849
850   *n_ints_read = bytes/sizeof(gint);
851
852   return TRUE;
853 }
854
855 static gboolean
856 fork_exec_with_pipes (gboolean              dont_wait,
857                       const gchar          *working_directory,
858                       gchar               **argv,
859                       gchar               **envp,
860                       gboolean              close_descriptors,
861                       gboolean              search_path,
862                       gboolean              stdout_to_null,
863                       gboolean              stderr_to_null,
864                       gboolean              child_inherits_stdin,
865                       GSpawnChildSetupFunc  child_setup,
866                       gpointer              user_data,
867                       gint                 *standard_input,
868                       gint                 *standard_output,
869                       gint                 *standard_error,
870                       gint                 *exit_status,
871                       GError              **error)     
872 {
873   gint stdin_pipe[2] = { -1, -1 };
874   gint stdout_pipe[2] = { -1, -1 };
875   gint stderr_pipe[2] = { -1, -1 };
876   gint child_err_report_pipe[2] = { -1, -1 };
877   gint status;
878   gint buf[2];
879   gint n_ints = 0;
880   
881   if (!make_pipe (child_err_report_pipe, error))
882     return FALSE;
883
884   if (standard_input && !make_pipe (stdin_pipe, error))
885     goto cleanup_and_fail;
886   
887   if (standard_output && !make_pipe (stdout_pipe, error))
888     goto cleanup_and_fail;
889
890   if (standard_error && !make_pipe (stderr_pipe, error))
891     goto cleanup_and_fail;
892
893   status = do_exec (dont_wait,
894                     child_err_report_pipe[1],
895                     stdin_pipe[0],
896                     stdout_pipe[1],
897                     stderr_pipe[1],
898                     working_directory,
899                     argv,
900                     envp,
901                     close_descriptors,
902                     search_path,
903                     stdout_to_null,
904                     stderr_to_null,
905                     child_inherits_stdin,
906                     child_setup,
907                     user_data);
908       
909   if (!read_ints (child_err_report_pipe[0],
910                   buf, 2, &n_ints,
911                   error))
912     goto cleanup_and_fail;
913         
914   if (n_ints == 2)
915     {
916       /* Error from the child. */
917       
918       switch (buf[0])
919         {
920         case CHILD_NO_ERROR:
921           break;
922           
923         case CHILD_CHDIR_FAILED:
924           g_set_error (error,
925                        G_SPAWN_ERROR,
926                        G_SPAWN_ERROR_CHDIR,
927                        _("Failed to change to directory '%s' (%s)"),
928                        working_directory,
929                        g_strerror (buf[1]));
930           goto cleanup_and_fail;
931           
932         case CHILD_SPAWN_FAILED:
933           g_set_error (error,
934                        G_SPAWN_ERROR,
935                        G_SPAWN_ERROR_FAILED,
936                        _("Failed to execute child process (%s)"),
937                        g_strerror (buf[1]));
938           goto cleanup_and_fail;
939         }
940     }
941
942   /* Success against all odds! return the information */
943       
944   if (standard_input)
945     *standard_input = stdin_pipe[1];
946   if (standard_output)
947     *standard_output = stdout_pipe[0];
948   if (standard_error)
949     *standard_error = stderr_pipe[0];
950   if (exit_status)
951     *exit_status = status;
952   
953   return TRUE;
954
955  cleanup_and_fail:
956   close_and_invalidate (&child_err_report_pipe[0]);
957   close_and_invalidate (&child_err_report_pipe[1]);
958   close_and_invalidate (&stdin_pipe[0]);
959   close_and_invalidate (&stdin_pipe[1]);
960   close_and_invalidate (&stdout_pipe[0]);
961   close_and_invalidate (&stdout_pipe[1]);
962   close_and_invalidate (&stderr_pipe[0]);
963   close_and_invalidate (&stderr_pipe[1]);
964
965   return FALSE;
966 }
967
968 static gboolean
969 make_pipe (gint     p[2],
970            GError **error)
971 {
972   if (pipe (p) < 0)
973     {
974       g_set_error (error,
975                    G_SPAWN_ERROR,
976                    G_SPAWN_ERROR_FAILED,
977                    _("Failed to create pipe for communicating with child process (%s)"),
978                    g_strerror (errno));
979       return FALSE;
980     }
981   else
982     return TRUE;
983 }
984
985 #endif /* !GSPAWN_HELPER */