Cosmetics.
[glib.git] / gspawn-win32.c
blobc1bb2222d765c309d27ce8663086df0f10b4520a
1 /* gspawn.c - Process launching
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 #ifdef _
57 #warning "FIXME remove gettext hack"
58 #endif
60 #define _(x) x
62 #ifdef G_SPAWN_WIN32_DEBUG
63 static int debug = 1;
64 #define SETUP_DEBUG() /* empty */
66 #else
67 static int debug = -1;
68 #define SETUP_DEBUG() \
69 G_STMT_START \
70 { \
71 if (debug == -1) \
72 if (getenv ("G_SPAWN_WIN32_DEBUG") != NULL) \
73 debug = 1; \
74 else \
75 debug = 0; \
76 } \
77 G_STMT_END
78 #endif
80 enum
82 CHILD_NO_ERROR,
83 CHILD_CHDIR_FAILED,
84 CHILD_SPAWN_FAILED,
87 enum {
88 ARG_CHILD_ERR_REPORT = 1,
89 ARG_STDIN,
90 ARG_STDOUT,
91 ARG_STDERR,
92 ARG_WORKING_DIRECTORY,
93 ARG_CLOSE_DESCRIPTORS,
94 ARG_USE_PATH,
95 ARG_WAIT,
96 ARG_PROGRAM,
97 ARG_COUNT = ARG_PROGRAM
100 #ifndef GSPAWN_HELPER
102 static gboolean make_pipe (gint p[2],
103 GError **error);
104 static gboolean fork_exec_with_pipes (gboolean dont_wait,
105 const gchar *working_directory,
106 gchar **argv,
107 gchar **envp,
108 gboolean close_descriptors,
109 gboolean search_path,
110 gboolean stdout_to_null,
111 gboolean stderr_to_null,
112 gboolean child_inherits_stdin,
113 GSpawnChildSetupFunc child_setup,
114 gpointer user_data,
115 gint *standard_input,
116 gint *standard_output,
117 gint *standard_error,
118 gint *exit_status,
119 GError **error);
121 GQuark
122 g_spawn_error_quark (void)
124 static GQuark quark = 0;
125 if (quark == 0)
126 quark = g_quark_from_static_string ("g-exec-error-quark");
127 return quark;
131 * g_spawn_async:
132 * @working_directory: child's current working directory, or NULL to inherit parent's
133 * @argv: child's argument vector
134 * @envp: child's environment, or NULL to inherit parent's
135 * @flags: flags from #GSpawnFlags
136 * @child_setup: function to run in the child just before exec()
137 * @user_data: user data for @child_setup
138 * @child_pid: return location for child process ID, or NULL
139 * @error: return location for error
141 * See g_spawn_async_with_pipes() for a full description; this function
142 * simply calls the g_spawn_async_with_pipes() without any pipes.
144 * Return value: TRUE on success, FALSE if error is set
146 gboolean
147 g_spawn_async (const gchar *working_directory,
148 gchar **argv,
149 gchar **envp,
150 GSpawnFlags flags,
151 GSpawnChildSetupFunc child_setup,
152 gpointer user_data,
153 gint *child_pid,
154 GError **error)
156 g_return_val_if_fail (argv != NULL, FALSE);
158 return g_spawn_async_with_pipes (working_directory,
159 argv, envp,
160 flags,
161 child_setup,
162 user_data,
163 child_pid,
164 NULL, NULL, NULL,
165 error);
168 /* Avoids a danger in threaded situations (calling close()
169 * on a file descriptor twice, and another thread has
170 * re-opened it since the first close)
172 static gint
173 close_and_invalidate (gint *fd)
175 gint ret;
177 ret = close (*fd);
178 *fd = -1;
180 return ret;
183 typedef enum
185 READ_FAILED = 0, /* FALSE */
186 READ_OK,
187 READ_EOF
188 } ReadResult;
190 static ReadResult
191 read_data (GString *str,
192 GIOChannel *iochannel,
193 GError **error)
195 GIOError gioerror;
196 gint bytes;
197 gchar buf[4096];
199 again:
201 gioerror = g_io_channel_read (iochannel, buf, sizeof (buf), &bytes);
203 if (bytes == 0)
204 return READ_EOF;
205 else if (bytes > 0)
207 g_string_append_len (str, buf, bytes);
208 return READ_OK;
210 else if (gioerror == G_IO_ERROR_AGAIN)
211 goto again;
212 else if (gioerror != G_IO_ERROR_NONE)
214 g_set_error (error,
215 G_SPAWN_ERROR,
216 G_SPAWN_ERROR_READ,
217 _("Failed to read data from child process"));
219 return READ_FAILED;
221 else
222 return READ_OK;
226 * g_spawn_sync:
227 * @working_directory: child's current working directory, or NULL to inherit parent's
228 * @argv: child's argument vector
229 * @envp: child's environment, or NULL to inherit parent's
230 * @flags: flags from #GSpawnFlags
231 * @child_setup: function to run in the child just before exec()
232 * @user_data: user data for @child_setup
233 * @standard_output: return location for child output
234 * @standard_error: return location for child error messages
235 * @exit_status: child exit status, as returned by waitpid()
236 * @error: return location for error
238 * Executes a child synchronously (waits for the child to exit before returning).
239 * All output from the child is stored in @standard_output and @standard_error,
240 * if those parameters are non-NULL. If @exit_status is non-NULL, the exit status
241 * of the child is stored there as it would be by waitpid(); standard UNIX
242 * macros such as WIFEXITED() and WEXITSTATUS() must be used to evaluate the
243 * exit status. If an error occurs, no data is returned in @standard_output,
244 * @standard_error, or @exit_status.
246 * This function calls g_spawn_async_with_pipes() internally; see that function
247 * for full details on the other parameters.
249 * Return value: TRUE on success, FALSE if an error was set.
251 gboolean
252 g_spawn_sync (const gchar *working_directory,
253 gchar **argv,
254 gchar **envp,
255 GSpawnFlags flags,
256 GSpawnChildSetupFunc child_setup,
257 gpointer user_data,
258 gchar **standard_output,
259 gchar **standard_error,
260 gint *exit_status,
261 GError **error)
263 gint outpipe = -1;
264 gint errpipe = -1;
265 GIOChannel *outchannel = NULL;
266 GIOChannel *errchannel = NULL;
267 GPollFD outfd, errfd;
268 GPollFD fds[2];
269 gint nfds;
270 gint outindex = -1;
271 gint errindex = -1;
272 gint ret;
273 GString *outstr = NULL;
274 GString *errstr = NULL;
275 gboolean failed;
276 gint status;
278 g_return_val_if_fail (argv != NULL, FALSE);
279 g_return_val_if_fail (!(flags & G_SPAWN_DO_NOT_REAP_CHILD), FALSE);
280 g_return_val_if_fail (standard_output == NULL ||
281 !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
282 g_return_val_if_fail (standard_error == NULL ||
283 !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
285 /* Just to ensure segfaults if callers try to use
286 * these when an error is reported.
288 if (standard_output)
289 *standard_output = NULL;
291 if (standard_error)
292 *standard_error = NULL;
294 if (!fork_exec_with_pipes (FALSE,
295 working_directory,
296 argv,
297 envp,
298 !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
299 (flags & G_SPAWN_SEARCH_PATH) != 0,
300 (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
301 (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
302 (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
303 child_setup,
304 user_data,
305 NULL,
306 standard_output ? &outpipe : NULL,
307 standard_error ? &errpipe : NULL,
308 &status,
309 error))
310 return FALSE;
312 /* Read data from child. */
314 failed = FALSE;
316 if (outpipe >= 0)
318 outstr = g_string_new ("");
319 outchannel = g_io_channel_win32_new_fd (outpipe);
320 g_io_channel_win32_make_pollfd (outchannel,
321 G_IO_IN | G_IO_ERR | G_IO_HUP,
322 &outfd);
325 if (errpipe >= 0)
327 errstr = g_string_new ("");
328 errchannel = g_io_channel_win32_new_fd (errpipe);
329 g_io_channel_win32_make_pollfd (errchannel,
330 G_IO_IN | G_IO_ERR | G_IO_HUP,
331 &errfd);
334 /* Read data until we get EOF on both pipes. */
335 while (!failed &&
336 (outpipe >= 0 ||
337 errpipe >= 0))
339 nfds = 0;
340 if (outpipe >= 0)
342 fds[nfds] = outfd;
343 outindex = nfds;
344 nfds++;
346 if (errpipe >= 0)
348 fds[nfds] = errfd;
349 errindex = nfds;
350 nfds++;
353 if (debug)
354 g_print ("%s:g_spawn_sync: calling g_io_channel_win32_poll, nfds=%d\n",
355 __FILE__, nfds);
357 ret = g_io_channel_win32_poll (fds, nfds, -1);
359 if (ret < 0)
361 failed = TRUE;
363 g_set_error (error,
364 G_SPAWN_ERROR,
365 G_SPAWN_ERROR_READ,
366 _("Unexpected error in g_io_channel_win32_poll() reading data from a child process"));
368 break;
371 if (outpipe >= 0 && (fds[outindex].revents & G_IO_IN))
373 switch (read_data (outstr, outchannel, error))
375 case READ_FAILED:
376 if (debug)
377 g_print ("g_spawn_sync: outchannel: READ_FAILED\n");
378 failed = TRUE;
379 break;
380 case READ_EOF:
381 if (debug)
382 g_print ("g_spawn_sync: outchannel: READ_EOF\n");
383 g_io_channel_unref (outchannel);
384 outchannel = NULL;
385 close_and_invalidate (&outpipe);
386 break;
387 default:
388 if (debug)
389 g_print ("g_spawn_sync: outchannel: OK\n");
390 break;
393 if (failed)
394 break;
397 if (errpipe >= 0 && (fds[errindex].revents & G_IO_IN))
399 switch (read_data (errstr, errchannel, error))
401 case READ_FAILED:
402 if (debug)
403 g_print ("g_spawn_sync: errchannel: READ_FAILED\n");
404 failed = TRUE;
405 break;
406 case READ_EOF:
407 if (debug)
408 g_print ("g_spawn_sync: errchannel: READ_EOF\n");
409 g_io_channel_unref (errchannel);
410 errchannel = NULL;
411 close_and_invalidate (&errpipe);
412 break;
413 default:
414 if (debug)
415 g_print ("g_spawn_sync: errchannel: OK\n");
416 break;
419 if (failed)
420 break;
424 /* These should only be open still if we had an error. */
426 if (outchannel != NULL)
427 g_io_channel_unref (outchannel);
428 if (errchannel != NULL)
429 g_io_channel_unref (errchannel);
430 if (outpipe >= 0)
431 close_and_invalidate (&outpipe);
432 if (errpipe >= 0)
433 close_and_invalidate (&errpipe);
435 if (failed)
437 if (outstr)
438 g_string_free (outstr, TRUE);
439 if (errstr)
440 g_string_free (errstr, TRUE);
442 return FALSE;
444 else
446 if (exit_status)
447 *exit_status = status;
449 if (standard_output)
450 *standard_output = g_string_free (outstr, FALSE);
452 if (standard_error)
453 *standard_error = g_string_free (errstr, FALSE);
455 return TRUE;
460 * g_spawn_async_with_pipes:
461 * @working_directory: child's current working directory, or NULL to inherit parent's
462 * @argv: child's argument vector
463 * @envp: child's environment, or NULL to inherit parent's
464 * @flags: flags from #GSpawnFlags
465 * @child_setup: function to run in the child just before exec()
466 * @user_data: user data for @child_setup
467 * @child_pid: return location for child process ID, or NULL
468 * @standard_input: return location for file descriptor to write to child's stdin, or NULL
469 * @standard_output: return location for file descriptor to read child's stdout, or NULL
470 * @standard_error: return location for file descriptor to read child's stderr, or NULL
471 * @error: return location for error
473 * Executes a child program asynchronously (your program will not
474 * block waiting for the child to exit). The child program is
475 * specified by the only argument that must be provided, @argv. @argv
476 * should be a NULL-terminated array of strings, to be passed as the
477 * argument vector for the child. The first string in @argv is of
478 * course the name of the program to execute. By default, the name of
479 * the program must be a full path; the PATH shell variable will only
480 * be searched if you pass the %G_SPAWN_SEARCH_PATH flag.
482 * @envp is a NULL-terminated array of strings, where each string
483 * has the form <literal>KEY=VALUE</literal>. This will become
484 * the child's environment. If @envp is NULL, the child inherits its
485 * parent's environment.
487 * @flags should be the bitwise OR of any flags you want to affect the
488 * function's behavior. The %G_SPAWN_DO_NOT_REAP_CHILD means that the
489 * child will not be automatically reaped; you must call waitpid() or
490 * handle SIGCHLD yourself, or the child will become a zombie.
491 * %G_SPAWN_LEAVE_DESCRIPTORS_OPEN means that the parent's open file
492 * descriptors will be inherited by the child; otherwise all
493 * descriptors except stdin/stdout/stderr will be closed before
494 * calling exec() in the child. %G_SPAWN_SEARCH_PATH means that
495 * <literal>argv[0]</literal> need not be an absolute path, it
496 * will be looked for in the user's PATH. %G_SPAWN_STDOUT_TO_DEV_NULL
497 * means that the child's standad output will be discarded, instead
498 * of going to the same location as the parent's standard output.
499 * %G_SPAWN_STDERR_TO_DEV_NULL means that the child's standard error
500 * will be discarded. %G_SPAWN_CHILD_INHERITS_STDIN means that
501 * the child will inherit the parent's standard input (by default,
502 * the child's standard input is attached to /dev/null).
504 * @child_setup and @user_data are a function and user data to be
505 * called in the child after GLib has performed all the setup it plans
506 * to perform (including creating pipes, closing file descriptors,
507 * etc.) but before calling exec(). That is, @child_setup is called
508 * just before calling exec() in the child. Obviously actions taken in
509 * this function will only affect the child, not the parent.
511 * If non-NULL, @child_pid will be filled with the child's process
512 * ID. You can use the process ID to send signals to the child, or
513 * to waitpid() if you specified the %G_SPAWN_DO_NOT_REAP_CHILD flag.
515 * If non-NULL, the @standard_input, @standard_output, @standard_error
516 * locations will be filled with file descriptors for writing to the child's
517 * standard input or reading from its standard output or standard error.
518 * The caller of g_spawn_async_with_pipes() must close these file descriptors
519 * when they are no longer in use. If these parameters are NULL, the
520 * corresponding pipe won't be created.
522 * @error can be NULL to ignore errors, or non-NULL to report errors.
523 * If an error is set, the function returns FALSE. Errors
524 * are reported even if they occur in the child (for example if the
525 * executable in <literal>argv[0]</literal> is not found). Typically
526 * the <literal>message</literal> field of returned errors should be displayed
527 * to users. Possible errors are those from the #G_SPAWN_ERROR domain.
529 * If an error occurs, @child_pid, @standard_input, @standard_output,
530 * and @standard_error will not be filled with valid values.
532 * Return value: TRUE on success, FALSE if an error was set
534 gboolean
535 g_spawn_async_with_pipes (const gchar *working_directory,
536 gchar **argv,
537 gchar **envp,
538 GSpawnFlags flags,
539 GSpawnChildSetupFunc child_setup,
540 gpointer user_data,
541 gint *child_pid,
542 gint *standard_input,
543 gint *standard_output,
544 gint *standard_error,
545 GError **error)
547 g_return_val_if_fail (argv != NULL, FALSE);
548 g_return_val_if_fail (standard_output == NULL ||
549 !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
550 g_return_val_if_fail (standard_error == NULL ||
551 !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
552 /* can't inherit stdin if we have an input pipe. */
553 g_return_val_if_fail (standard_input == NULL ||
554 !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
556 return fork_exec_with_pipes (!(flags & G_SPAWN_DO_NOT_REAP_CHILD),
557 working_directory,
558 argv,
559 envp,
560 !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
561 (flags & G_SPAWN_SEARCH_PATH) != 0,
562 (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
563 (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
564 (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
565 child_setup,
566 user_data,
567 standard_input,
568 standard_output,
569 standard_error,
570 NULL,
571 error);
575 * g_spawn_command_line_sync:
576 * @command_line: a command line
577 * @standard_output: return location for child output
578 * @standard_error: return location for child errors
579 * @exit_status: return location for child exit status
580 * @error: return location for errors
582 * A simple version of g_spawn_sync() with little-used parameters
583 * removed, taking a command line instead of an argument vector. See
584 * g_spawn_sync() for full details. @command_line will be parsed by
585 * g_shell_parse_argv(). Unlike g_spawn_sync(), the %G_SPAWN_SEARCH_PATH flag
586 * is enabled. Note that %G_SPAWN_SEARCH_PATH can have security
587 * implications, so consider using g_spawn_sync() directly if
588 * appropriate. Possible errors are those from g_spawn_sync() and those
589 * from g_shell_parse_argv().
591 * Return value: TRUE on success, FALSE if an error was set
593 gboolean
594 g_spawn_command_line_sync (const gchar *command_line,
595 gchar **standard_output,
596 gchar **standard_error,
597 gint *exit_status,
598 GError **error)
600 gboolean retval;
601 gchar **argv = 0;
603 g_return_val_if_fail (command_line != NULL, FALSE);
605 if (!g_shell_parse_argv (command_line,
606 NULL, &argv,
607 error))
608 return FALSE;
610 retval = g_spawn_sync (NULL,
611 argv,
612 NULL,
613 G_SPAWN_SEARCH_PATH,
614 NULL,
615 NULL,
616 standard_output,
617 standard_error,
618 exit_status,
619 error);
620 g_strfreev (argv);
622 return retval;
626 * g_spawn_command_line_async:
627 * @command_line: a command line
628 * @error: return location for errors
630 * A simple version of g_spawn_async() that parses a command line with
631 * g_shell_parse_argv() and passes it to g_spawn_async(). Runs a
632 * command line in the background. Unlike g_spawn_async(), the
633 * %G_SPAWN_SEARCH_PATH flag is enabled, other flags are not. Note
634 * that %G_SPAWN_SEARCH_PATH can have security implications, so
635 * consider using g_spawn_async() directly if appropriate. Possible
636 * errors are those from g_shell_parse_argv() and g_spawn_async().
638 * Return value: TRUE on success, FALSE if error is set.
640 gboolean
641 g_spawn_command_line_async (const gchar *command_line,
642 GError **error)
644 gboolean retval;
645 gchar **argv = 0;
647 g_return_val_if_fail (command_line != NULL, FALSE);
649 if (!g_shell_parse_argv (command_line,
650 NULL, &argv,
651 error))
652 return FALSE;
654 retval = g_spawn_async (NULL,
655 argv,
656 NULL,
657 G_SPAWN_SEARCH_PATH,
658 NULL,
659 NULL,
660 NULL,
661 error);
662 g_strfreev (argv);
664 return retval;
667 static gint
668 do_exec (gboolean dont_wait,
669 gint child_err_report_fd,
670 gint stdin_fd,
671 gint stdout_fd,
672 gint stderr_fd,
673 const gchar *working_directory,
674 gchar **argv,
675 gchar **envp,
676 gboolean close_descriptors,
677 gboolean search_path,
678 gboolean stdout_to_null,
679 gboolean stderr_to_null,
680 gboolean child_inherits_stdin,
681 GSpawnChildSetupFunc child_setup,
682 gpointer user_data)
684 gchar **new_argv;
685 gchar args[ARG_COUNT][10];
686 gint i;
687 int argc = 0;
689 SETUP_DEBUG();
691 while (argv[argc])
692 ++argc;
694 new_argv = g_new (gchar *, argc + 1 + ARG_COUNT);
696 new_argv[0] = "gspawn-win32-helper";
697 sprintf (args[ARG_CHILD_ERR_REPORT], "%d", child_err_report_fd);
698 new_argv[ARG_CHILD_ERR_REPORT] = args[ARG_CHILD_ERR_REPORT];
700 if (stdin_fd >= 0)
702 sprintf (args[ARG_STDIN], "%d", stdin_fd);
703 new_argv[ARG_STDIN] = args[ARG_STDIN];
705 else if (child_inherits_stdin)
707 /* Let stdin be alone */
708 new_argv[ARG_STDIN] = "-";
710 else
712 /* Keep process from blocking on a read of stdin */
713 new_argv[ARG_STDIN] = "z";
716 if (stdout_fd >= 0)
718 sprintf (args[ARG_STDOUT], "%d", stdout_fd);
719 new_argv[ARG_STDOUT] = args[ARG_STDOUT];
721 else if (stdout_to_null)
723 new_argv[ARG_STDOUT] = "z";
725 else
727 new_argv[ARG_STDOUT] = "-";
730 if (stderr_fd >= 0)
732 sprintf (args[ARG_STDERR], "%d", stderr_fd);
733 new_argv[ARG_STDERR] = args[ARG_STDERR];
735 else if (stderr_to_null)
737 new_argv[ARG_STDERR] = "z";
739 else
741 new_argv[ARG_STDERR] = "-";
744 if (working_directory && *working_directory)
745 new_argv[ARG_WORKING_DIRECTORY] = working_directory;
746 else
747 new_argv[ARG_WORKING_DIRECTORY] = "-";
749 if (close_descriptors)
750 new_argv[ARG_CLOSE_DESCRIPTORS] = "y";
751 else
752 new_argv[ARG_CLOSE_DESCRIPTORS] = "-";
754 if (search_path)
755 new_argv[ARG_USE_PATH] = "y";
756 else
757 new_argv[ARG_USE_PATH] = "-";
759 if (dont_wait)
760 new_argv[ARG_WAIT] = "-";
761 else
762 new_argv[ARG_WAIT] = "w";
764 for (i = 0; i <= argc; i++)
765 new_argv[ARG_PROGRAM + i] = argv[i];
767 /* Call user function just before we execute the helper program,
768 * which executes the program. Dunno what's the usefulness of this.
769 * A child setup function used on Unix probably isn't of much use
770 * as such on Win32, anyhow.
772 if (child_setup)
774 (* child_setup) (user_data);
777 if (debug)
779 g_print ("calling gspawn-win32-helper with argv:\n");
780 for (i = 0; i < argc + 1 + ARG_COUNT; i++)
781 g_print ("argv[%d]: %s\n", i, (new_argv[i] ? new_argv[i] : "NULL"));
784 if (envp != NULL)
785 /* Let's hope envp hasn't mucked with PATH so that
786 * gspawn-win32-helper.exe isn't found.
788 spawnvpe (P_NOWAIT, "gspawn-win32-helper", new_argv, envp);
789 else
790 spawnvp (P_NOWAIT, "gspawn-win32-helper", new_argv);
792 /* FIXME: What if gspawn-win32-helper.exe isn't found? */
794 /* Close the child_err_report_fd and the other process's ends of the
795 * pipes in this process, otherwise the reader will never get
796 * EOF.
798 close (child_err_report_fd);
799 if (stdin_fd >= 0)
800 close (stdin_fd);
801 if (stdout_fd >= 0)
802 close (stdout_fd);
803 if (stderr_fd >= 0)
804 close (stderr_fd);
806 g_free (new_argv);
808 return 0;
811 static gboolean
812 read_ints (int fd,
813 gint* buf,
814 gint n_ints_in_buf,
815 gint *n_ints_read,
816 GError **error)
818 gint bytes = 0;
820 while (bytes < sizeof(gint)*n_ints_in_buf)
822 gint chunk;
824 if (debug)
825 g_print ("%s:read_ints: trying to read %d bytes from pipe...\n",
826 __FILE__,
827 sizeof(gint)*n_ints_in_buf - bytes);
829 chunk = read (fd, ((gchar*)buf) + bytes,
830 sizeof(gint)*n_ints_in_buf - bytes);
832 if (debug)
833 g_print ("... got %d bytes\n", chunk);
835 if (chunk < 0)
837 /* Some weird shit happened, bail out */
839 g_set_error (error,
840 G_SPAWN_ERROR,
841 G_SPAWN_ERROR_FAILED,
842 _("Failed to read from child pipe (%s)"),
843 g_strerror (errno));
845 return FALSE;
847 else if (chunk == 0)
848 break; /* EOF */
849 else
850 bytes += chunk;
853 *n_ints_read = bytes/sizeof(gint);
855 return TRUE;
858 static gboolean
859 fork_exec_with_pipes (gboolean dont_wait,
860 const gchar *working_directory,
861 gchar **argv,
862 gchar **envp,
863 gboolean close_descriptors,
864 gboolean search_path,
865 gboolean stdout_to_null,
866 gboolean stderr_to_null,
867 gboolean child_inherits_stdin,
868 GSpawnChildSetupFunc child_setup,
869 gpointer user_data,
870 gint *standard_input,
871 gint *standard_output,
872 gint *standard_error,
873 gint *exit_status,
874 GError **error)
876 gint stdin_pipe[2] = { -1, -1 };
877 gint stdout_pipe[2] = { -1, -1 };
878 gint stderr_pipe[2] = { -1, -1 };
879 gint child_err_report_pipe[2] = { -1, -1 };
880 gint status;
881 gint bytes;
882 gint buf[2];
883 gint n_ints = 0;
885 if (!make_pipe (child_err_report_pipe, error))
886 return FALSE;
888 if (standard_input && !make_pipe (stdin_pipe, error))
889 goto cleanup_and_fail;
891 if (standard_output && !make_pipe (stdout_pipe, error))
892 goto cleanup_and_fail;
894 if (standard_error && !make_pipe (stderr_pipe, error))
895 goto cleanup_and_fail;
897 status = do_exec (dont_wait,
898 child_err_report_pipe[1],
899 stdin_pipe[0],
900 stdout_pipe[1],
901 stderr_pipe[1],
902 working_directory,
903 argv,
904 envp,
905 close_descriptors,
906 search_path,
907 stdout_to_null,
908 stderr_to_null,
909 child_inherits_stdin,
910 child_setup,
911 user_data);
913 if (!read_ints (child_err_report_pipe[0],
914 buf, 2, &n_ints,
915 error))
916 goto cleanup_and_fail;
918 if (n_ints == 2)
920 /* Error from the child. */
922 switch (buf[0])
924 case CHILD_NO_ERROR:
925 break;
927 case CHILD_CHDIR_FAILED:
928 g_set_error (error,
929 G_SPAWN_ERROR,
930 G_SPAWN_ERROR_CHDIR,
931 _("Failed to change to directory '%s' (%s)"),
932 working_directory,
933 g_strerror (buf[1]));
934 goto cleanup_and_fail;
936 case CHILD_SPAWN_FAILED:
937 g_set_error (error,
938 G_SPAWN_ERROR,
939 G_SPAWN_ERROR_FAILED,
940 _("Failed to execute child process (%s)"),
941 g_strerror (buf[1]));
942 goto cleanup_and_fail;
946 /* Success against all odds! return the information */
948 if (standard_input)
949 *standard_input = stdin_pipe[1];
950 if (standard_output)
951 *standard_output = stdout_pipe[0];
952 if (standard_error)
953 *standard_error = stderr_pipe[0];
954 if (exit_status)
955 *exit_status = status;
957 return TRUE;
959 cleanup_and_fail:
960 close_and_invalidate (&child_err_report_pipe[0]);
961 close_and_invalidate (&child_err_report_pipe[1]);
962 close_and_invalidate (&stdin_pipe[0]);
963 close_and_invalidate (&stdin_pipe[1]);
964 close_and_invalidate (&stdout_pipe[0]);
965 close_and_invalidate (&stdout_pipe[1]);
966 close_and_invalidate (&stderr_pipe[0]);
967 close_and_invalidate (&stderr_pipe[1]);
969 return FALSE;
972 static gboolean
973 make_pipe (gint p[2],
974 GError **error)
976 if (pipe (p) < 0)
978 g_set_error (error,
979 G_SPAWN_ERROR,
980 G_SPAWN_ERROR_FAILED,
981 _("Failed to create pipe for communicating with child process (%s)"),
982 g_strerror (errno));
983 return FALSE;
985 else
986 return TRUE;
989 #else /* GSPAWN_HELPER */
991 static void
992 write_err_and_exit (gint fd,
993 gint msg)
995 gint en = errno;
997 write (fd, &msg, sizeof(msg));
998 write (fd, &en, sizeof(en));
1000 _exit (1);
1003 static void
1004 write_no_error (gint fd)
1006 gint msg = CHILD_NO_ERROR;
1007 gint en = 0;
1009 write (fd, &msg, sizeof(msg));
1010 write (fd, &en, sizeof(en));
1013 #ifdef __GNUC__
1014 # ifndef _stdcall
1015 # define _stdcall __attribute__((stdcall))
1016 # endif
1017 #endif
1019 /* We build gspawn-win32-helper.exe as a Windows GUI application
1020 * to avoid any temporarily flashing console windows in case
1021 * the gspawn function is invoked by a GUI program. Thus, no main()
1022 * but a WinMain(). We do, however, still use argc and argv tucked
1023 * away in the global __argc and __argv by the C runtime startup code.
1026 int _stdcall
1027 WinMain (struct HINSTANCE__ *hInstance,
1028 struct HINSTANCE__ *hPrevInstance,
1029 char *lpszCmdLine,
1030 int nCmdShow)
1032 int child_err_report_fd;
1033 int i;
1034 int fd;
1035 int mode;
1036 GString *debugstring;
1038 SETUP_DEBUG();
1040 if (debug)
1042 debugstring = g_string_new ("");
1044 g_string_append (debugstring,
1045 g_strdup_printf ("g-spawn-win32-helper: "
1046 "argc = %d, argv: ",
1047 __argc));
1048 for (i = 0; i < __argc; i++)
1050 if (i > 0)
1051 g_string_append (debugstring, " ");
1052 g_string_append (debugstring, __argv[i]);
1055 MessageBox (NULL, debugstring->str, "gspawn-win32-helper", 0);
1058 g_assert (__argc >= ARG_COUNT);
1060 /* argv[ARG_CHILD_ERR_REPORT] is the file descriptor onto which
1061 * write error messages.
1063 child_err_report_fd = atoi (__argv[ARG_CHILD_ERR_REPORT]);
1065 /* argv[ARG_STDIN..ARG_STDERR] are the file descriptors that should
1066 * be dup2'd to stdin, stdout and stderr, '-' if the corresponding
1067 * std* should be let alone, and 'z' if it should be connected to
1068 * the bit bucket NUL:.
1070 if (__argv[ARG_STDIN][0] == '-')
1071 ; /* Nothing */
1072 else if (__argv[ARG_STDIN][0] == 'z')
1074 fd = open ("NUL:", O_RDONLY);
1075 if (fd != 0)
1077 dup2 (fd, 0);
1078 close (fd);
1081 else
1083 fd = atoi (__argv[ARG_STDIN]);
1084 if (fd != 0)
1086 dup2 (fd, 0);
1087 close (fd);
1091 if (__argv[ARG_STDOUT][0] == '-')
1092 ; /* Nothing */
1093 else if (__argv[ARG_STDOUT][0] == 'z')
1095 fd = open ("NUL:", O_WRONLY);
1096 if (fd != 1)
1098 dup2 (fd, 1);
1099 close (fd);
1102 else
1104 fd = atoi (__argv[ARG_STDOUT]);
1105 if (fd != 1)
1107 dup2 (fd, 1);
1108 close (fd);
1112 if (__argv[ARG_STDERR][0] == '-')
1113 ; /* Nothing */
1114 else if (__argv[ARG_STDERR][0] == 'z')
1116 fd = open ("NUL:", O_WRONLY);
1117 if (fd != 2)
1119 dup2 (fd, 2);
1120 close (fd);
1123 else
1125 fd = atoi (__argv[ARG_STDERR]);
1126 if (fd != 2)
1128 dup2 (fd, 2);
1129 close (fd);
1133 /* __argv[ARG_WORKING_DIRECTORY] is the directory in which to run the
1134 * process. If "-", don't change directory.
1136 if (__argv[ARG_WORKING_DIRECTORY][0] == '-' &&
1137 __argv[ARG_WORKING_DIRECTORY][1] == 0)
1138 ; /* Nothing */
1139 else if (chdir (__argv[ARG_WORKING_DIRECTORY]) < 0)
1140 write_err_and_exit (child_err_report_fd,
1141 CHILD_CHDIR_FAILED);
1143 /* __argv[ARG_CLOSE_DESCRIPTORS] is "y" if file descriptors from 3
1144 * upwards should be closed
1147 if (__argv[ARG_CLOSE_DESCRIPTORS][0] == 'y')
1148 for (i = 3; i < 1000; i++) /* FIXME real limit? */
1149 if (i != child_err_report_fd)
1150 close (i);
1152 /* __argv[ARG_WAIT] is "w" to wait for the program to exit */
1154 if (__argv[ARG_WAIT][0] == 'w')
1155 mode = P_WAIT;
1156 else
1157 mode = P_NOWAIT;
1159 /* __argv[ARG_USE_PATH] is "y" to use PATH, otherwise not */
1161 /* __argv[ARG_PROGRAM] is program file to run,
1162 * __argv[ARG_PROGRAM+1]... is its __argv.
1165 if (debug)
1167 debugstring = g_string_new ("");
1168 g_string_append (debugstring,
1169 g_strdup_printf ("calling %s on program %s, __argv: ",
1170 (__argv[ARG_USE_PATH][0] == 'y' ?
1171 "spawnvp" : "spawnv"),
1172 __argv[ARG_PROGRAM]));
1173 i = ARG_PROGRAM+1;
1174 while (__argv[i])
1175 g_string_append (debugstring, __argv[i++]);
1176 MessageBox (NULL, debugstring->str, "gspawn-win32-helper", 0);
1179 if (__argv[ARG_USE_PATH][0] == 'y')
1181 if (spawnvp (mode, __argv[ARG_PROGRAM], __argv+ARG_PROGRAM) < 0)
1182 write_err_and_exit (child_err_report_fd, CHILD_SPAWN_FAILED);
1184 else
1186 if (spawnv (mode, __argv[ARG_PROGRAM], __argv+ARG_PROGRAM) < 0)
1187 write_err_and_exit (child_err_report_fd, CHILD_SPAWN_FAILED);
1190 return 0;
1193 #endif /* GSPAWN_HELPER */