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 */
45 #include "gprintfint.h"
60 #ifdef G_SPAWN_WIN32_DEBUG
62 #define SETUP_DEBUG() /* empty */
65 static int debug = -1;
66 #define SETUP_DEBUG() \
71 if (getenv ("G_SPAWN_WIN32_DEBUG") != NULL) \
88 ARG_CHILD_ERR_REPORT = 1,
92 ARG_WORKING_DIRECTORY,
93 ARG_CLOSE_DESCRIPTORS,
97 ARG_COUNT = ARG_PROGRAM
100 #ifndef GSPAWN_HELPER
102 static gboolean make_pipe (gint p[2],
104 static gboolean do_spawn_with_pipes (gboolean dont_wait,
105 gboolean dont_return_handle,
106 const gchar *working_directory,
109 gboolean close_descriptors,
110 gboolean search_path,
111 gboolean stdout_to_null,
112 gboolean stderr_to_null,
113 gboolean child_inherits_stdin,
114 GSpawnChildSetupFunc child_setup,
117 gint *standard_input,
118 gint *standard_output,
119 gint *standard_error,
124 g_spawn_error_quark (void)
126 static GQuark quark = 0;
128 quark = g_quark_from_static_string ("g-exec-error-quark");
133 g_spawn_async (const gchar *working_directory,
137 GSpawnChildSetupFunc child_setup,
142 g_return_val_if_fail (argv != NULL, FALSE);
144 return g_spawn_async_with_pipes (working_directory,
154 /* Avoids a danger in threaded situations (calling close()
155 * on a file descriptor twice, and another thread has
156 * re-opened it since the first close)
159 close_and_invalidate (gint *fd)
176 READ_FAILED = 0, /* FALSE */
182 read_data (GString *str,
183 GIOChannel *iochannel,
192 giostatus = g_io_channel_read_chars (iochannel, buf, sizeof (buf), &bytes, NULL);
198 g_string_append_len (str, buf, bytes);
201 else if (giostatus == G_IO_STATUS_AGAIN)
203 else if (giostatus == G_IO_STATUS_ERROR)
208 _("Failed to read data from child process"));
217 g_spawn_sync (const gchar *working_directory,
221 GSpawnChildSetupFunc child_setup,
223 gchar **standard_output,
224 gchar **standard_error,
231 GIOChannel *outchannel = NULL;
232 GIOChannel *errchannel = NULL;
233 GPollFD outfd, errfd;
239 GString *outstr = NULL;
240 GString *errstr = NULL;
244 g_return_val_if_fail (argv != NULL, FALSE);
245 g_return_val_if_fail (!(flags & G_SPAWN_DO_NOT_REAP_CHILD), FALSE);
246 g_return_val_if_fail (standard_output == NULL ||
247 !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
248 g_return_val_if_fail (standard_error == NULL ||
249 !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
251 /* Just to ensure segfaults if callers try to use
252 * these when an error is reported.
255 *standard_output = NULL;
258 *standard_error = NULL;
260 if (!do_spawn_with_pipes (FALSE,
265 !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
266 (flags & G_SPAWN_SEARCH_PATH) != 0,
267 (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
268 (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
269 (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
274 standard_output ? &outpipe : NULL,
275 standard_error ? &errpipe : NULL,
280 /* Read data from child. */
286 outstr = g_string_new ("");
287 outchannel = g_io_channel_win32_new_fd (outpipe);
288 g_io_channel_set_encoding (outchannel, NULL, NULL);
289 g_io_channel_win32_make_pollfd (outchannel,
290 G_IO_IN | G_IO_ERR | G_IO_HUP,
296 errstr = g_string_new ("");
297 errchannel = g_io_channel_win32_new_fd (errpipe);
298 g_io_channel_set_encoding (errchannel, NULL, NULL);
299 g_io_channel_win32_make_pollfd (errchannel,
300 G_IO_IN | G_IO_ERR | G_IO_HUP,
304 /* Read data until we get EOF on both pipes. */
324 g_print ("%s:g_spawn_sync: calling g_io_channel_win32_poll, nfds=%d\n",
327 ret = g_io_channel_win32_poll (fds, nfds, -1);
336 _("Unexpected error in g_io_channel_win32_poll() reading data from a child process"));
341 if (outpipe >= 0 && (fds[outindex].revents & G_IO_IN))
343 switch (read_data (outstr, outchannel, error))
347 g_print ("g_spawn_sync: outchannel: READ_FAILED\n");
352 g_print ("g_spawn_sync: outchannel: READ_EOF\n");
353 g_io_channel_unref (outchannel);
355 close_and_invalidate (&outpipe);
359 g_print ("g_spawn_sync: outchannel: OK\n");
367 if (errpipe >= 0 && (fds[errindex].revents & G_IO_IN))
369 switch (read_data (errstr, errchannel, error))
373 g_print ("g_spawn_sync: errchannel: READ_FAILED\n");
378 g_print ("g_spawn_sync: errchannel: READ_EOF\n");
379 g_io_channel_unref (errchannel);
381 close_and_invalidate (&errpipe);
385 g_print ("g_spawn_sync: errchannel: OK\n");
394 /* These should only be open still if we had an error. */
396 if (outchannel != NULL)
397 g_io_channel_unref (outchannel);
398 if (errchannel != NULL)
399 g_io_channel_unref (errchannel);
401 close_and_invalidate (&outpipe);
403 close_and_invalidate (&errpipe);
408 g_string_free (outstr, TRUE);
410 g_string_free (errstr, TRUE);
417 *exit_status = status;
420 *standard_output = g_string_free (outstr, FALSE);
423 *standard_error = g_string_free (errstr, FALSE);
430 g_spawn_async_with_pipes (const gchar *working_directory,
434 GSpawnChildSetupFunc child_setup,
437 gint *standard_input,
438 gint *standard_output,
439 gint *standard_error,
442 g_return_val_if_fail (argv != NULL, FALSE);
443 g_return_val_if_fail (standard_output == NULL ||
444 !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
445 g_return_val_if_fail (standard_error == NULL ||
446 !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
447 /* can't inherit stdin if we have an input pipe. */
448 g_return_val_if_fail (standard_input == NULL ||
449 !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
451 return do_spawn_with_pipes (TRUE,
452 !(flags & G_SPAWN_DO_NOT_REAP_CHILD),
456 !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
457 (flags & G_SPAWN_SEARCH_PATH) != 0,
458 (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
459 (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
460 (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
472 g_spawn_command_line_sync (const gchar *command_line,
473 gchar **standard_output,
474 gchar **standard_error,
481 g_return_val_if_fail (command_line != NULL, FALSE);
483 if (!g_shell_parse_argv (command_line,
488 retval = g_spawn_sync (NULL,
504 g_spawn_command_line_async (const gchar *command_line,
510 g_return_val_if_fail (command_line != NULL, FALSE);
512 if (!g_shell_parse_argv (command_line,
517 retval = g_spawn_async (NULL,
531 do_spawn (gboolean dont_wait,
532 gint child_err_report_fd,
536 const gchar *working_directory,
539 gboolean close_descriptors,
540 gboolean search_path,
541 gboolean stdout_to_null,
542 gboolean stderr_to_null,
543 gboolean child_inherits_stdin,
544 GSpawnChildSetupFunc child_setup,
548 gchar args[ARG_COUNT][10];
558 new_argv = g_new (gchar *, argc + 1 + ARG_COUNT);
560 new_argv[0] = "gspawn-win32-helper";
561 _g_sprintf (args[ARG_CHILD_ERR_REPORT], "%d", child_err_report_fd);
562 new_argv[ARG_CHILD_ERR_REPORT] = args[ARG_CHILD_ERR_REPORT];
566 _g_sprintf (args[ARG_STDIN], "%d", stdin_fd);
567 new_argv[ARG_STDIN] = args[ARG_STDIN];
569 else if (child_inherits_stdin)
571 /* Let stdin be alone */
572 new_argv[ARG_STDIN] = "-";
576 /* Keep process from blocking on a read of stdin */
577 new_argv[ARG_STDIN] = "z";
582 _g_sprintf (args[ARG_STDOUT], "%d", stdout_fd);
583 new_argv[ARG_STDOUT] = args[ARG_STDOUT];
585 else if (stdout_to_null)
587 new_argv[ARG_STDOUT] = "z";
591 new_argv[ARG_STDOUT] = "-";
596 _g_sprintf (args[ARG_STDERR], "%d", stderr_fd);
597 new_argv[ARG_STDERR] = args[ARG_STDERR];
599 else if (stderr_to_null)
601 new_argv[ARG_STDERR] = "z";
605 new_argv[ARG_STDERR] = "-";
608 if (working_directory && *working_directory)
609 /* The g_strdup() to lose the constness */
610 new_argv[ARG_WORKING_DIRECTORY] = g_strdup (working_directory);
612 new_argv[ARG_WORKING_DIRECTORY] = g_strdup ("-");
614 if (close_descriptors)
615 new_argv[ARG_CLOSE_DESCRIPTORS] = "y";
617 new_argv[ARG_CLOSE_DESCRIPTORS] = "-";
620 new_argv[ARG_USE_PATH] = "y";
622 new_argv[ARG_USE_PATH] = "-";
625 new_argv[ARG_WAIT] = "-";
627 new_argv[ARG_WAIT] = "w";
629 for (i = 0; i <= argc; i++)
630 new_argv[ARG_PROGRAM + i] = argv[i];
632 /* Call user function just before we execute the helper program,
633 * which executes the program. Dunno what's the usefulness of this.
634 * A child setup function used on Unix probably isn't of much use
635 * as such on Win32, anyhow
639 (* child_setup) (user_data);
644 g_print ("calling gspawn-win32-helper with argv:\n");
645 for (i = 0; i < argc + 1 + ARG_COUNT; i++)
646 g_print ("argv[%d]: %s\n", i, (new_argv[i] ? new_argv[i] : "NULL"));
650 /* Let's hope envp hasn't mucked with PATH so that
651 * gspawn-win32-helper.exe isn't found.
653 rc = spawnvpe (P_NOWAIT, "gspawn-win32-helper", new_argv, envp);
655 rc = spawnvp (P_NOWAIT, "gspawn-win32-helper", new_argv);
657 /* Close the child_err_report_fd and the other process's ends of the
658 * pipes in this process, otherwise the reader will never get
661 close (child_err_report_fd);
669 g_free (new_argv[ARG_WORKING_DIRECTORY]);
684 while (bytes < sizeof(gint)*n_ints_in_buf)
689 g_print ("%s:read_ints: trying to read %d bytes from pipe...\n",
691 sizeof(gint)*n_ints_in_buf - bytes);
693 chunk = read (fd, ((gchar*)buf) + bytes,
694 sizeof(gint)*n_ints_in_buf - bytes);
697 g_print ("... got %d bytes\n", chunk);
701 /* Some weird shit happened, bail out */
705 G_SPAWN_ERROR_FAILED,
706 _("Failed to read from child pipe (%s)"),
717 *n_ints_read = bytes/sizeof(gint);
723 do_spawn_with_pipes (gboolean dont_wait,
724 gboolean dont_return_handle,
725 const gchar *working_directory,
728 gboolean close_descriptors,
729 gboolean search_path,
730 gboolean stdout_to_null,
731 gboolean stderr_to_null,
732 gboolean child_inherits_stdin,
733 GSpawnChildSetupFunc child_setup,
736 gint *standard_input,
737 gint *standard_output,
738 gint *standard_error,
742 gint stdin_pipe[2] = { -1, -1 };
743 gint stdout_pipe[2] = { -1, -1 };
744 gint stderr_pipe[2] = { -1, -1 };
745 gint child_err_report_pipe[2] = { -1, -1 };
750 if (!make_pipe (child_err_report_pipe, error))
753 if (standard_input && !make_pipe (stdin_pipe, error))
754 goto cleanup_and_fail;
756 if (standard_output && !make_pipe (stdout_pipe, error))
757 goto cleanup_and_fail;
759 if (standard_error && !make_pipe (stderr_pipe, error))
760 goto cleanup_and_fail;
762 helper = do_spawn (dont_wait,
763 child_err_report_pipe[1],
774 child_inherits_stdin,
778 /* do_spawn() returns -1 if gspawn-win32-helper couldn't be run */
783 G_SPAWN_ERROR_FAILED,
784 _("Failed to execute helper program"));
785 goto cleanup_and_fail;
788 if (!read_ints (child_err_report_pipe[0],
792 goto cleanup_and_fail;
794 /* Error code from gspawn-win32-helper. */
798 if (child_pid && dont_wait && !dont_return_handle)
800 /* helper is our HANDLE for gspawn-win32-helper. It has
801 * told us the HANDLE of its child. Duplicate that into
802 * a HANDLE valid in this process.
804 if (!DuplicateHandle ((HANDLE) helper, (HANDLE) buf[1],
805 GetCurrentProcess (), (LPHANDLE) child_pid,
806 0, TRUE, DUPLICATE_SAME_ACCESS))
813 case CHILD_CHDIR_FAILED:
817 _("Failed to change to directory '%s' (%s)"),
819 g_strerror (buf[1]));
820 goto cleanup_and_fail;
822 case CHILD_SPAWN_FAILED:
825 G_SPAWN_ERROR_FAILED,
826 _("Failed to execute child process (%s)"),
827 g_strerror (buf[1]));
828 goto cleanup_and_fail;
831 /* Success against all odds! return the information */
834 *standard_input = stdin_pipe[1];
836 *standard_output = stdout_pipe[0];
838 *standard_error = stderr_pipe[0];
840 *exit_status = buf[1];
841 CloseHandle ((HANDLE) helper);
847 CloseHandle ((HANDLE) helper);
848 close_and_invalidate (&child_err_report_pipe[0]);
849 close_and_invalidate (&child_err_report_pipe[1]);
850 close_and_invalidate (&stdin_pipe[0]);
851 close_and_invalidate (&stdin_pipe[1]);
852 close_and_invalidate (&stdout_pipe[0]);
853 close_and_invalidate (&stdout_pipe[1]);
854 close_and_invalidate (&stderr_pipe[0]);
855 close_and_invalidate (&stderr_pipe[1]);
861 make_pipe (gint p[2],
868 G_SPAWN_ERROR_FAILED,
869 _("Failed to create pipe for communicating with child process (%s)"),
877 #endif /* !GSPAWN_HELPER */