.cvsignore updates
[glib.git] / gspawn-win32.c
blob2b81a22ba2a21396eab2c0f7908739aeef1aa7bc
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.
36 * This source file contains the source for that helper program.
37 * To compile it, #define GSPAWN_HELPER.
40 /* Define this to get some logging all the time */
41 /* #define G_SPAWN_WIN32_DEBUG */
43 #include "glib.h"
45 #include <string.h>
46 #include <stdlib.h>
47 #include <stdio.h>
49 #include <windows.h>
50 #include <errno.h>
51 #include <fcntl.h>
52 #include <io.h>
53 #include <process.h>
54 #include <direct.h>
56 #include "glibintl.h"
58 #ifdef G_SPAWN_WIN32_DEBUG
59 static int debug = 1;
60 #define SETUP_DEBUG() /* empty */
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
76 enum
78 CHILD_NO_ERROR,
79 CHILD_CHDIR_FAILED,
80 CHILD_SPAWN_FAILED,
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
96 #ifndef GSPAWN_HELPER
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);
117 GQuark
118 g_spawn_error_quark (void)
120 static GQuark quark = 0;
121 if (quark == 0)
122 quark = g_quark_from_static_string ("g-exec-error-quark");
123 return quark;
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
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.
140 * Return value: TRUE on success, FALSE if error is set
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)
152 g_return_val_if_fail (argv != NULL, FALSE);
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);
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)
168 static gint
169 close_and_invalidate (gint *fd)
171 gint ret;
173 ret = close (*fd);
174 *fd = -1;
176 return ret;
179 typedef enum
181 READ_FAILED = 0, /* FALSE */
182 READ_OK,
183 READ_EOF
184 } ReadResult;
186 static ReadResult
187 read_data (GString *str,
188 GIOChannel *iochannel,
189 GError **error)
191 GIOError gioerror;
192 gint bytes;
193 gchar buf[4096];
195 again:
197 gioerror = g_io_channel_read (iochannel, buf, sizeof (buf), &bytes);
199 if (bytes == 0)
200 return READ_EOF;
201 else if (bytes > 0)
203 g_string_append_len (str, buf, bytes);
204 return READ_OK;
206 else if (gioerror == G_IO_ERROR_AGAIN)
207 goto again;
208 else if (gioerror != G_IO_ERROR_NONE)
210 g_set_error (error,
211 G_SPAWN_ERROR,
212 G_SPAWN_ERROR_READ,
213 _("Failed to read data from child process"));
215 return READ_FAILED;
217 else
218 return READ_OK;
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
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.
242 * This function calls g_spawn_async_with_pipes() internally; see that function
243 * for full details on the other parameters.
245 * Return value: TRUE on success, FALSE if an error was set.
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)
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;
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);
281 /* Just to ensure segfaults if callers try to use
282 * these when an error is reported.
284 if (standard_output)
285 *standard_output = NULL;
287 if (standard_error)
288 *standard_error = NULL;
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;
308 /* Read data from child. */
310 failed = FALSE;
312 if (outpipe >= 0)
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);
321 if (errpipe >= 0)
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);
330 /* Read data until we get EOF on both pipes. */
331 while (!failed &&
332 (outpipe >= 0 ||
333 errpipe >= 0))
335 nfds = 0;
336 if (outpipe >= 0)
338 fds[nfds] = outfd;
339 outindex = nfds;
340 nfds++;
342 if (errpipe >= 0)
344 fds[nfds] = errfd;
345 errindex = nfds;
346 nfds++;
349 if (debug)
350 g_print ("%s:g_spawn_sync: calling g_io_channel_win32_poll, nfds=%d\n",
351 __FILE__, nfds);
353 ret = g_io_channel_win32_poll (fds, nfds, -1);
355 if (ret < 0)
357 failed = TRUE;
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"));
364 break;
367 if (outpipe >= 0 && (fds[outindex].revents & G_IO_IN))
369 switch (read_data (outstr, outchannel, error))
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;
389 if (failed)
390 break;
393 if (errpipe >= 0 && (fds[errindex].revents & G_IO_IN))
395 switch (read_data (errstr, errchannel, error))
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;
415 if (failed)
416 break;
420 /* These should only be open still if we had an error. */
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);
431 if (failed)
433 if (outstr)
434 g_string_free (outstr, TRUE);
435 if (errstr)
436 g_string_free (errstr, TRUE);
438 return FALSE;
440 else
442 if (exit_status)
443 *exit_status = status;
445 if (standard_output)
446 *standard_output = g_string_free (outstr, FALSE);
448 if (standard_error)
449 *standard_error = g_string_free (errstr, FALSE);
451 return TRUE;
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
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.
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.
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).
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.
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.
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.
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.
525 * If an error occurs, @child_pid, @standard_input, @standard_output,
526 * and @standard_error will not be filled with valid values.
528 * Return value: TRUE on success, FALSE if an error was set
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)
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);
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);
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
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().
587 * Return value: TRUE on success, FALSE if an error was set
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)
596 gboolean retval;
597 gchar **argv = 0;
599 g_return_val_if_fail (command_line != NULL, FALSE);
601 if (!g_shell_parse_argv (command_line,
602 NULL, &argv,
603 error))
604 return FALSE;
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);
618 return retval;
622 * g_spawn_command_line_async:
623 * @command_line: a command line
624 * @error: return location for errors
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().
634 * Return value: TRUE on success, FALSE if error is set.
636 gboolean
637 g_spawn_command_line_async (const gchar *command_line,
638 GError **error)
640 gboolean retval;
641 gchar **argv = 0;
643 g_return_val_if_fail (command_line != NULL, FALSE);
645 if (!g_shell_parse_argv (command_line,
646 NULL, &argv,
647 error))
648 return FALSE;
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);
660 return retval;
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)
680 gchar **new_argv;
681 gchar args[ARG_COUNT][10];
682 gint i;
683 int argc = 0;
685 SETUP_DEBUG();
687 while (argv[argc])
688 ++argc;
690 new_argv = g_new (gchar *, argc + 1 + ARG_COUNT);
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];
696 if (stdin_fd >= 0)
698 sprintf (args[ARG_STDIN], "%d", stdin_fd);
699 new_argv[ARG_STDIN] = args[ARG_STDIN];
701 else if (child_inherits_stdin)
703 /* Let stdin be alone */
704 new_argv[ARG_STDIN] = "-";
706 else
708 /* Keep process from blocking on a read of stdin */
709 new_argv[ARG_STDIN] = "z";
712 if (stdout_fd >= 0)
714 sprintf (args[ARG_STDOUT], "%d", stdout_fd);
715 new_argv[ARG_STDOUT] = args[ARG_STDOUT];
717 else if (stdout_to_null)
719 new_argv[ARG_STDOUT] = "z";
721 else
723 new_argv[ARG_STDOUT] = "-";
726 if (stderr_fd >= 0)
728 sprintf (args[ARG_STDERR], "%d", stderr_fd);
729 new_argv[ARG_STDERR] = args[ARG_STDERR];
731 else if (stderr_to_null)
733 new_argv[ARG_STDERR] = "z";
735 else
737 new_argv[ARG_STDERR] = "-";
740 if (working_directory && *working_directory)
741 new_argv[ARG_WORKING_DIRECTORY] = working_directory;
742 else
743 new_argv[ARG_WORKING_DIRECTORY] = "-";
745 if (close_descriptors)
746 new_argv[ARG_CLOSE_DESCRIPTORS] = "y";
747 else
748 new_argv[ARG_CLOSE_DESCRIPTORS] = "-";
750 if (search_path)
751 new_argv[ARG_USE_PATH] = "y";
752 else
753 new_argv[ARG_USE_PATH] = "-";
755 if (dont_wait)
756 new_argv[ARG_WAIT] = "-";
757 else
758 new_argv[ARG_WAIT] = "w";
760 for (i = 0; i <= argc; i++)
761 new_argv[ARG_PROGRAM + i] = argv[i];
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.
768 if (child_setup)
770 (* child_setup) (user_data);
773 if (debug)
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"));
780 if (envp != NULL)
781 /* Let's hope envp hasn't mucked with PATH so that
782 * gspawn-win32-helper.exe isn't found.
784 spawnvpe (P_NOWAIT, "gspawn-win32-helper", new_argv, envp);
785 else
786 spawnvp (P_NOWAIT, "gspawn-win32-helper", new_argv);
788 /* FIXME: What if gspawn-win32-helper.exe isn't found? */
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.
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);
802 g_free (new_argv);
804 return 0;
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)
814 gint bytes = 0;
816 while (bytes < sizeof(gint)*n_ints_in_buf)
818 gint chunk;
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);
825 chunk = read (fd, ((gchar*)buf) + bytes,
826 sizeof(gint)*n_ints_in_buf - bytes);
828 if (debug)
829 g_print ("... got %d bytes\n", chunk);
831 if (chunk < 0)
833 /* Some weird shit happened, bail out */
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));
841 return FALSE;
843 else if (chunk == 0)
844 break; /* EOF */
845 else
846 bytes += chunk;
849 *n_ints_read = bytes/sizeof(gint);
851 return TRUE;
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)
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;
881 if (!make_pipe (child_err_report_pipe, error))
882 return FALSE;
884 if (standard_input && !make_pipe (stdin_pipe, error))
885 goto cleanup_and_fail;
887 if (standard_output && !make_pipe (stdout_pipe, error))
888 goto cleanup_and_fail;
890 if (standard_error && !make_pipe (stderr_pipe, error))
891 goto cleanup_and_fail;
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);
909 if (!read_ints (child_err_report_pipe[0],
910 buf, 2, &n_ints,
911 error))
912 goto cleanup_and_fail;
914 if (n_ints == 2)
916 /* Error from the child. */
918 switch (buf[0])
920 case CHILD_NO_ERROR:
921 break;
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;
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;
942 /* Success against all odds! return the information */
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;
953 return TRUE;
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]);
965 return FALSE;
968 static gboolean
969 make_pipe (gint p[2],
970 GError **error)
972 if (pipe (p) < 0)
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;
981 else
982 return TRUE;
985 #endif /* !GSPAWN_HELPER */