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