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