Version 11, interface, binary age 0.
[glib.git] / glib / gspawn-win32.c
blob17a98fc6082ad15cfc55fc89f989ec96e1058f39
1 /* gspawn-win32.c - Process launching on Win32
3 * Copyright 2000 Red Hat, Inc.
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.
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.
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.
22 * Implementation details on Win32.
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.)
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.
37 /* Define this to get some logging all the time */
38 /* #define G_SPAWN_WIN32_DEBUG */
40 #include "glib.h"
42 #include <string.h>
43 #include <stdlib.h>
44 #include <stdio.h>
46 #include <windows.h>
47 #include <errno.h>
48 #include <fcntl.h>
49 #include <io.h>
50 #include <process.h>
51 #include <direct.h>
53 #include "glibintl.h"
55 #ifdef G_SPAWN_WIN32_DEBUG
56 static int debug = 1;
57 #define SETUP_DEBUG() /* empty */
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
75 enum
77 CHILD_NO_ERROR,
78 CHILD_CHDIR_FAILED,
79 CHILD_SPAWN_FAILED,
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
95 #ifndef GSPAWN_HELPER
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);
116 GQuark
117 g_spawn_error_quark (void)
119 static GQuark quark = 0;
120 if (quark == 0)
121 quark = g_quark_from_static_string ("g-exec-error-quark");
122 return quark;
126 * g_spawn_async:
127 * @working_directory: child's current working directory, or NULL to inherit parent's
128 * @argv: child's argument vector
129 * @envp: child's environment, or NULL to inherit parent's
130 * @flags: flags from #GSpawnFlags
131 * @child_setup: function to run in the child just before exec()
132 * @user_data: user data for @child_setup
133 * @child_pid: return location for child process ID, or NULL
134 * @error: return location for error
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.
139 * Return value: TRUE on success, FALSE if error is set
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)
151 g_return_val_if_fail (argv != NULL, FALSE);
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);
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)
167 static gint
168 close_and_invalidate (gint *fd)
170 gint ret;
172 ret = close (*fd);
173 *fd = -1;
175 return ret;
178 typedef enum
180 READ_FAILED = 0, /* FALSE */
181 READ_OK,
182 READ_EOF
183 } ReadResult;
185 static ReadResult
186 read_data (GString *str,
187 GIOChannel *iochannel,
188 GError **error)
190 GIOError gioerror;
191 gint bytes;
192 gchar buf[4096];
194 again:
196 gioerror = g_io_channel_read (iochannel, buf, sizeof (buf), &bytes);
198 if (bytes == 0)
199 return READ_EOF;
200 else if (bytes > 0)
202 g_string_append_len (str, buf, bytes);
203 return READ_OK;
205 else if (gioerror == G_IO_ERROR_AGAIN)
206 goto again;
207 else if (gioerror != G_IO_ERROR_NONE)
209 g_set_error (error,
210 G_SPAWN_ERROR,
211 G_SPAWN_ERROR_READ,
212 _("Failed to read data from child process"));
214 return READ_FAILED;
216 else
217 return READ_OK;
221 * g_spawn_sync:
222 * @working_directory: child's current working directory, or NULL to inherit parent's
223 * @argv: child's argument vector
224 * @envp: child's environment, or NULL to inherit parent's
225 * @flags: flags from #GSpawnFlags
226 * @child_setup: function to run in the child just before exec()
227 * @user_data: user data for @child_setup
228 * @standard_output: return location for child output
229 * @standard_error: return location for child error messages
230 * @exit_status: child exit status, as returned by waitpid()
231 * @error: return location for error
233 * Executes a child synchronously (waits for the child to exit before returning).
234 * All output from the child is stored in @standard_output and @standard_error,
235 * if those parameters are non-NULL. If @exit_status is non-NULL, the exit status
236 * of the child is stored there as it would be by waitpid(); standard UNIX
237 * macros such as WIFEXITED() and WEXITSTATUS() must be used to evaluate the
238 * exit status. If an error occurs, no data is returned in @standard_output,
239 * @standard_error, or @exit_status.
241 * This function calls g_spawn_async_with_pipes() internally; see that function
242 * for full details on the other parameters.
244 * Return value: TRUE on success, FALSE if an error was set.
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)
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;
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);
280 /* Just to ensure segfaults if callers try to use
281 * these when an error is reported.
283 if (standard_output)
284 *standard_output = NULL;
286 if (standard_error)
287 *standard_error = NULL;
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;
307 /* Read data from child. */
309 failed = FALSE;
311 if (outpipe >= 0)
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);
320 if (errpipe >= 0)
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);
329 /* Read data until we get EOF on both pipes. */
330 while (!failed &&
331 (outpipe >= 0 ||
332 errpipe >= 0))
334 nfds = 0;
335 if (outpipe >= 0)
337 fds[nfds] = outfd;
338 outindex = nfds;
339 nfds++;
341 if (errpipe >= 0)
343 fds[nfds] = errfd;
344 errindex = nfds;
345 nfds++;
348 if (debug)
349 g_print ("%s:g_spawn_sync: calling g_io_channel_win32_poll, nfds=%d\n",
350 __FILE__, nfds);
352 ret = g_io_channel_win32_poll (fds, nfds, -1);
354 if (ret < 0)
356 failed = TRUE;
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"));
363 break;
366 if (outpipe >= 0 && (fds[outindex].revents & G_IO_IN))
368 switch (read_data (outstr, outchannel, error))
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;
388 if (failed)
389 break;
392 if (errpipe >= 0 && (fds[errindex].revents & G_IO_IN))
394 switch (read_data (errstr, errchannel, error))
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;
414 if (failed)
415 break;
419 /* These should only be open still if we had an error. */
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);
430 if (failed)
432 if (outstr)
433 g_string_free (outstr, TRUE);
434 if (errstr)
435 g_string_free (errstr, TRUE);
437 return FALSE;
439 else
441 if (exit_status)
442 *exit_status = status;
444 if (standard_output)
445 *standard_output = g_string_free (outstr, FALSE);
447 if (standard_error)
448 *standard_error = g_string_free (errstr, FALSE);
450 return TRUE;
455 * g_spawn_async_with_pipes:
456 * @working_directory: child's current working directory, or NULL to inherit parent's
457 * @argv: child's argument vector
458 * @envp: child's environment, or NULL to inherit parent's
459 * @flags: flags from #GSpawnFlags
460 * @child_setup: function to run in the child just before exec()
461 * @user_data: user data for @child_setup
462 * @child_pid: return location for child process ID, or NULL
463 * @standard_input: return location for file descriptor to write to child's stdin, or NULL
464 * @standard_output: return location for file descriptor to read child's stdout, or NULL
465 * @standard_error: return location for file descriptor to read child's stderr, or NULL
466 * @error: return location for error
468 * Executes a child program asynchronously (your program will not
469 * block waiting for the child to exit). The child program is
470 * specified by the only argument that must be provided, @argv. @argv
471 * should be a %NULL-terminated array of strings, to be passed as the
472 * argument vector for the child. The first string in @argv is of
473 * course the name of the program to execute. By default, the name of
474 * the program must be a full path; the PATH shell variable will only
475 * be searched if you pass the %G_SPAWN_SEARCH_PATH flag.
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.
482 * @flags should be the bitwise OR of any flags you want to affect the
483 * function's behavior. The %G_SPAWN_DO_NOT_REAP_CHILD means that the
484 * child will not be automatically reaped; you must call waitpid() or
485 * handle SIGCHLD yourself, or the child will become a zombie.
486 * %G_SPAWN_LEAVE_DESCRIPTORS_OPEN means that the parent's open file
487 * descriptors will be inherited by the child; otherwise all
488 * descriptors except stdin/stdout/stderr will be closed before
489 * calling exec() in the child. %G_SPAWN_SEARCH_PATH means that
490 * <literal>argv[0]</literal> need not be an absolute path, it
491 * will be looked for in the user's PATH. %G_SPAWN_STDOUT_TO_DEV_NULL
492 * means that the child's standad output will be discarded, instead
493 * of going to the same location as the parent's standard output.
494 * %G_SPAWN_STDERR_TO_DEV_NULL means that the child's standard error
495 * will be discarded. %G_SPAWN_CHILD_INHERITS_STDIN means that
496 * the child will inherit the parent's standard input (by default,
497 * the child's standard input is attached to /dev/null).
499 * @child_setup and @user_data are a function and user data to be
500 * called in the child after GLib has performed all the setup it plans
501 * to perform (including creating pipes, closing file descriptors,
502 * etc.) but before calling exec(). That is, @child_setup is called
503 * just before calling exec() in the child. Obviously actions taken in
504 * this function will only affect the child, not the parent.
506 * If non-NULL, @child_pid will be filled with the child's process
507 * ID. You can use the process ID to send signals to the child, or
508 * to waitpid() if you specified the %G_SPAWN_DO_NOT_REAP_CHILD flag.
510 * If non-NULL, the @standard_input, @standard_output, @standard_error
511 * locations will be filled with file descriptors for writing to the child's
512 * standard input or reading from its standard output or standard error.
513 * The caller of g_spawn_async_with_pipes() must close these file descriptors
514 * when they are no longer in use. If these parameters are NULL, the
515 * corresponding pipe won't be created.
517 * @error can be NULL to ignore errors, or non-NULL to report errors.
518 * If an error is set, the function returns FALSE. Errors
519 * are reported even if they occur in the child (for example if the
520 * executable in <literal>argv[0]</literal> is not found). Typically
521 * the <literal>message</literal> field of returned errors should be displayed
522 * to users. Possible errors are those from the #G_SPAWN_ERROR domain.
524 * If an error occurs, @child_pid, @standard_input, @standard_output,
525 * and @standard_error will not be filled with valid values.
527 * Return value: TRUE on success, FALSE if an error was set
529 gboolean
530 g_spawn_async_with_pipes (const gchar *working_directory,
531 gchar **argv,
532 gchar **envp,
533 GSpawnFlags flags,
534 GSpawnChildSetupFunc child_setup,
535 gpointer user_data,
536 gint *child_pid,
537 gint *standard_input,
538 gint *standard_output,
539 gint *standard_error,
540 GError **error)
542 g_return_val_if_fail (argv != NULL, FALSE);
543 g_return_val_if_fail (standard_output == NULL ||
544 !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
545 g_return_val_if_fail (standard_error == NULL ||
546 !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
547 /* can't inherit stdin if we have an input pipe. */
548 g_return_val_if_fail (standard_input == NULL ||
549 !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
551 return fork_exec_with_pipes (!(flags & G_SPAWN_DO_NOT_REAP_CHILD),
552 working_directory,
553 argv,
554 envp,
555 !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
556 (flags & G_SPAWN_SEARCH_PATH) != 0,
557 (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
558 (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
559 (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
560 child_setup,
561 user_data,
562 standard_input,
563 standard_output,
564 standard_error,
565 NULL,
566 error);
570 * g_spawn_command_line_sync:
571 * @command_line: a command line
572 * @standard_output: return location for child output
573 * @standard_error: return location for child errors
574 * @exit_status: return location for child exit status
575 * @error: return location for errors
577 * A simple version of g_spawn_sync() with little-used parameters
578 * removed, taking a command line instead of an argument vector. See
579 * g_spawn_sync() for full details. @command_line will be parsed by
580 * g_shell_parse_argv(). Unlike g_spawn_sync(), the %G_SPAWN_SEARCH_PATH flag
581 * is enabled. Note that %G_SPAWN_SEARCH_PATH can have security
582 * implications, so consider using g_spawn_sync() directly if
583 * appropriate. Possible errors are those from g_spawn_sync() and those
584 * from g_shell_parse_argv().
586 * Return value: TRUE on success, FALSE if an error was set
588 gboolean
589 g_spawn_command_line_sync (const gchar *command_line,
590 gchar **standard_output,
591 gchar **standard_error,
592 gint *exit_status,
593 GError **error)
595 gboolean retval;
596 gchar **argv = 0;
598 g_return_val_if_fail (command_line != NULL, FALSE);
600 if (!g_shell_parse_argv (command_line,
601 NULL, &argv,
602 error))
603 return FALSE;
605 retval = g_spawn_sync (NULL,
606 argv,
607 NULL,
608 G_SPAWN_SEARCH_PATH,
609 NULL,
610 NULL,
611 standard_output,
612 standard_error,
613 exit_status,
614 error);
615 g_strfreev (argv);
617 return retval;
621 * g_spawn_command_line_async:
622 * @command_line: a command line
623 * @error: return location for errors
625 * A simple version of g_spawn_async() that parses a command line with
626 * g_shell_parse_argv() and passes it to g_spawn_async(). Runs a
627 * command line in the background. Unlike g_spawn_async(), the
628 * %G_SPAWN_SEARCH_PATH flag is enabled, other flags are not. Note
629 * that %G_SPAWN_SEARCH_PATH can have security implications, so
630 * consider using g_spawn_async() directly if appropriate. Possible
631 * errors are those from g_shell_parse_argv() and g_spawn_async().
633 * Return value: TRUE on success, FALSE if error is set.
635 gboolean
636 g_spawn_command_line_async (const gchar *command_line,
637 GError **error)
639 gboolean retval;
640 gchar **argv = 0;
642 g_return_val_if_fail (command_line != NULL, FALSE);
644 if (!g_shell_parse_argv (command_line,
645 NULL, &argv,
646 error))
647 return FALSE;
649 retval = g_spawn_async (NULL,
650 argv,
651 NULL,
652 G_SPAWN_SEARCH_PATH,
653 NULL,
654 NULL,
655 NULL,
656 error);
657 g_strfreev (argv);
659 return retval;
662 static gint
663 do_exec (gboolean dont_wait,
664 gint child_err_report_fd,
665 gint stdin_fd,
666 gint stdout_fd,
667 gint stderr_fd,
668 const gchar *working_directory,
669 gchar **argv,
670 gchar **envp,
671 gboolean close_descriptors,
672 gboolean search_path,
673 gboolean stdout_to_null,
674 gboolean stderr_to_null,
675 gboolean child_inherits_stdin,
676 GSpawnChildSetupFunc child_setup,
677 gpointer user_data)
679 gchar **new_argv;
680 gchar args[ARG_COUNT][10];
681 gint i;
682 int argc = 0;
684 SETUP_DEBUG();
686 while (argv[argc])
687 ++argc;
689 new_argv = g_new (gchar *, argc + 1 + ARG_COUNT);
691 new_argv[0] = "gspawn-win32-helper";
692 sprintf (args[ARG_CHILD_ERR_REPORT], "%d", child_err_report_fd);
693 new_argv[ARG_CHILD_ERR_REPORT] = args[ARG_CHILD_ERR_REPORT];
695 if (stdin_fd >= 0)
697 sprintf (args[ARG_STDIN], "%d", stdin_fd);
698 new_argv[ARG_STDIN] = args[ARG_STDIN];
700 else if (child_inherits_stdin)
702 /* Let stdin be alone */
703 new_argv[ARG_STDIN] = "-";
705 else
707 /* Keep process from blocking on a read of stdin */
708 new_argv[ARG_STDIN] = "z";
711 if (stdout_fd >= 0)
713 sprintf (args[ARG_STDOUT], "%d", stdout_fd);
714 new_argv[ARG_STDOUT] = args[ARG_STDOUT];
716 else if (stdout_to_null)
718 new_argv[ARG_STDOUT] = "z";
720 else
722 new_argv[ARG_STDOUT] = "-";
725 if (stderr_fd >= 0)
727 sprintf (args[ARG_STDERR], "%d", stderr_fd);
728 new_argv[ARG_STDERR] = args[ARG_STDERR];
730 else if (stderr_to_null)
732 new_argv[ARG_STDERR] = "z";
734 else
736 new_argv[ARG_STDERR] = "-";
739 if (working_directory && *working_directory)
740 new_argv[ARG_WORKING_DIRECTORY] = working_directory;
741 else
742 new_argv[ARG_WORKING_DIRECTORY] = "-";
744 if (close_descriptors)
745 new_argv[ARG_CLOSE_DESCRIPTORS] = "y";
746 else
747 new_argv[ARG_CLOSE_DESCRIPTORS] = "-";
749 if (search_path)
750 new_argv[ARG_USE_PATH] = "y";
751 else
752 new_argv[ARG_USE_PATH] = "-";
754 if (dont_wait)
755 new_argv[ARG_WAIT] = "-";
756 else
757 new_argv[ARG_WAIT] = "w";
759 for (i = 0; i <= argc; i++)
760 new_argv[ARG_PROGRAM + i] = argv[i];
762 /* Call user function just before we execute the helper program,
763 * which executes the program. Dunno what's the usefulness of this.
764 * A child setup function used on Unix probably isn't of much use
765 * as such on Win32, anyhow.
767 if (child_setup)
769 (* child_setup) (user_data);
772 if (debug)
774 g_print ("calling gspawn-win32-helper with argv:\n");
775 for (i = 0; i < argc + 1 + ARG_COUNT; i++)
776 g_print ("argv[%d]: %s\n", i, (new_argv[i] ? new_argv[i] : "NULL"));
779 if (envp != NULL)
780 /* Let's hope envp hasn't mucked with PATH so that
781 * gspawn-win32-helper.exe isn't found.
783 spawnvpe (P_NOWAIT, "gspawn-win32-helper", new_argv, envp);
784 else
785 spawnvp (P_NOWAIT, "gspawn-win32-helper", new_argv);
787 /* FIXME: What if gspawn-win32-helper.exe isn't found? */
789 /* Close the child_err_report_fd and the other process's ends of the
790 * pipes in this process, otherwise the reader will never get
791 * EOF.
793 close (child_err_report_fd);
794 if (stdin_fd >= 0)
795 close (stdin_fd);
796 if (stdout_fd >= 0)
797 close (stdout_fd);
798 if (stderr_fd >= 0)
799 close (stderr_fd);
801 g_free (new_argv);
803 return 0;
806 static gboolean
807 read_ints (int fd,
808 gint* buf,
809 gint n_ints_in_buf,
810 gint *n_ints_read,
811 GError **error)
813 gint bytes = 0;
815 while (bytes < sizeof(gint)*n_ints_in_buf)
817 gint chunk;
819 if (debug)
820 g_print ("%s:read_ints: trying to read %d bytes from pipe...\n",
821 __FILE__,
822 sizeof(gint)*n_ints_in_buf - bytes);
824 chunk = read (fd, ((gchar*)buf) + bytes,
825 sizeof(gint)*n_ints_in_buf - bytes);
827 if (debug)
828 g_print ("... got %d bytes\n", chunk);
830 if (chunk < 0)
832 /* Some weird shit happened, bail out */
834 g_set_error (error,
835 G_SPAWN_ERROR,
836 G_SPAWN_ERROR_FAILED,
837 _("Failed to read from child pipe (%s)"),
838 g_strerror (errno));
840 return FALSE;
842 else if (chunk == 0)
843 break; /* EOF */
844 else
845 bytes += chunk;
848 *n_ints_read = bytes/sizeof(gint);
850 return TRUE;
853 static gboolean
854 fork_exec_with_pipes (gboolean dont_wait,
855 const gchar *working_directory,
856 gchar **argv,
857 gchar **envp,
858 gboolean close_descriptors,
859 gboolean search_path,
860 gboolean stdout_to_null,
861 gboolean stderr_to_null,
862 gboolean child_inherits_stdin,
863 GSpawnChildSetupFunc child_setup,
864 gpointer user_data,
865 gint *standard_input,
866 gint *standard_output,
867 gint *standard_error,
868 gint *exit_status,
869 GError **error)
871 gint stdin_pipe[2] = { -1, -1 };
872 gint stdout_pipe[2] = { -1, -1 };
873 gint stderr_pipe[2] = { -1, -1 };
874 gint child_err_report_pipe[2] = { -1, -1 };
875 gint status;
876 gint buf[2];
877 gint n_ints = 0;
879 if (!make_pipe (child_err_report_pipe, error))
880 return FALSE;
882 if (standard_input && !make_pipe (stdin_pipe, error))
883 goto cleanup_and_fail;
885 if (standard_output && !make_pipe (stdout_pipe, error))
886 goto cleanup_and_fail;
888 if (standard_error && !make_pipe (stderr_pipe, error))
889 goto cleanup_and_fail;
891 status = do_exec (dont_wait,
892 child_err_report_pipe[1],
893 stdin_pipe[0],
894 stdout_pipe[1],
895 stderr_pipe[1],
896 working_directory,
897 argv,
898 envp,
899 close_descriptors,
900 search_path,
901 stdout_to_null,
902 stderr_to_null,
903 child_inherits_stdin,
904 child_setup,
905 user_data);
907 if (!read_ints (child_err_report_pipe[0],
908 buf, 2, &n_ints,
909 error))
910 goto cleanup_and_fail;
912 if (n_ints == 2)
914 /* Error from the child. */
916 switch (buf[0])
918 case CHILD_NO_ERROR:
919 break;
921 case CHILD_CHDIR_FAILED:
922 g_set_error (error,
923 G_SPAWN_ERROR,
924 G_SPAWN_ERROR_CHDIR,
925 _("Failed to change to directory '%s' (%s)"),
926 working_directory,
927 g_strerror (buf[1]));
928 goto cleanup_and_fail;
930 case CHILD_SPAWN_FAILED:
931 g_set_error (error,
932 G_SPAWN_ERROR,
933 G_SPAWN_ERROR_FAILED,
934 _("Failed to execute child process (%s)"),
935 g_strerror (buf[1]));
936 goto cleanup_and_fail;
940 /* Success against all odds! return the information */
942 if (standard_input)
943 *standard_input = stdin_pipe[1];
944 if (standard_output)
945 *standard_output = stdout_pipe[0];
946 if (standard_error)
947 *standard_error = stderr_pipe[0];
948 if (exit_status)
949 *exit_status = status;
951 return TRUE;
953 cleanup_and_fail:
954 close_and_invalidate (&child_err_report_pipe[0]);
955 close_and_invalidate (&child_err_report_pipe[1]);
956 close_and_invalidate (&stdin_pipe[0]);
957 close_and_invalidate (&stdin_pipe[1]);
958 close_and_invalidate (&stdout_pipe[0]);
959 close_and_invalidate (&stdout_pipe[1]);
960 close_and_invalidate (&stderr_pipe[0]);
961 close_and_invalidate (&stderr_pipe[1]);
963 return FALSE;
966 static gboolean
967 make_pipe (gint p[2],
968 GError **error)
970 if (pipe (p) < 0)
972 g_set_error (error,
973 G_SPAWN_ERROR,
974 G_SPAWN_ERROR_FAILED,
975 _("Failed to create pipe for communicating with child process (%s)"),
976 g_strerror (errno));
977 return FALSE;
979 else
980 return TRUE;
983 #endif /* !GSPAWN_HELPER */