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