1 /* gspawn-win32.c - Process launching on Win32
3 * Copyright 2000 Red Hat, Inc.
4 * Copyright 2003 Tor Lillqvist
6 * SPDX-License-Identifier: LGPL-2.1-or-later
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this library; if not, see <http://www.gnu.org/licenses/>.
23 * Implementation details on Win32.
25 * - There is no way to set the no-inherit flag for
26 * a "file descriptor" in the MS C runtime. The flag is there,
27 * and the dospawn() function uses it, but unfortunately
28 * this flag can only be set when opening the file.
29 * - As there is no fork(), we cannot reliably change directory
30 * before starting the child process. (There might be several threads
31 * running, and the current directory is common for all threads.)
33 * Thus, we must in many cases use a helper program to handle closing
34 * of (inherited) file descriptors and changing of directory. The
35 * helper process is also needed if the standard input, standard
36 * output, or standard error of the process to be run are supposed to
37 * be redirected somewhere.
39 * The structure of the source code in this file is a mess, I know.
42 /* Define this to get some logging all the time */
43 /* #define G_SPAWN_WIN32_DEBUG */
47 #include "glib-init.h"
48 #include "glib-private.h"
51 #include "gprintfint.h"
52 #include "gspawn-private.h"
68 #include <vcruntime.h> /* for _UCRT */
72 #ifdef G_SPAWN_WIN32_DEBUG
74 #define SETUP_DEBUG() /* empty */
76 static int debug = -1;
77 #define SETUP_DEBUG() \
82 if (g_getenv ("G_SPAWN_WIN32_DEBUG") != NULL) \
102 ARG_CHILD_ERR_REPORT = 1,
107 ARG_WORKING_DIRECTORY,
108 ARG_CLOSE_DESCRIPTORS,
113 ARG_COUNT = ARG_PROGRAM
116 #ifndef GSPAWN_HELPER
119 #define HELPER_PROCESS "gspawn-win64-helper"
121 #define HELPER_PROCESS "gspawn-win32-helper"
126 /* The wspawn*e functions are thread-safe only in the Universal
127 * CRT (UCRT). If we are linking against the MSVCRT.dll or the
128 * pre-2015 MSVC runtime (MSVCRXXX.dll), then we have to use a
132 static GMutex safe_wspawn_e_mutex;
135 safe_wspawnve (int _Mode,
136 const wchar_t *_Filename,
137 const wchar_t *const *_ArgList,
138 const wchar_t *const *_Env)
140 intptr_t ret_val = -1;
142 g_mutex_lock (&safe_wspawn_e_mutex);
143 ret_val = _wspawnve (_Mode, _Filename, _ArgList, _Env);
144 g_mutex_unlock (&safe_wspawn_e_mutex);
150 safe_wspawnvpe (int _Mode,
151 const wchar_t *_Filename,
152 const wchar_t *const *_ArgList,
153 const wchar_t *const *_Env)
155 intptr_t ret_val = -1;
157 g_mutex_lock (&safe_wspawn_e_mutex);
158 ret_val = _wspawnvpe (_Mode, _Filename, _ArgList, _Env);
159 g_mutex_unlock (&safe_wspawn_e_mutex);
166 #define safe_wspawnve _spawnve
167 #define safe_wspawnvpe _wspawnvpe
171 /* This logic has a copy for wchar_t in gspawn-win32-helper.c, protect_wargv() */
173 protect_argv_string (const gchar *string)
175 const gchar *p = string;
179 gboolean need_dblquotes = FALSE;
182 if (*p == ' ' || *p == '\t')
183 need_dblquotes = TRUE;
184 /* estimate max len, assuming that all escapable characters will be escaped */
185 if (*p == '"' || *p == '\\')
192 q = retval = g_malloc (len + need_dblquotes*2 + 1);
197 /* Only quotes and backslashes preceding quotes are escaped:
198 * see "Parsing C Command-Line Arguments" at
199 * https://docs.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments
205 /* Add backslash for escaping quote itself */
207 /* Add backslash for every preceding backslash for escaping it */
208 for (;pre_bslash > 0; --pre_bslash)
212 /* Count length of continuous sequence of preceding backslashes. */
224 /* Add backslash for every preceding backslash for escaping it,
225 * do NOT escape quote itself.
227 for (;pre_bslash > 0; --pre_bslash)
237 protect_argv (const gchar * const *argv,
245 *new_argv = g_new (gchar *, argc+1);
247 /* Quote each argv element if necessary, so that it will get
248 * reconstructed correctly in the C runtime startup code. Note that
249 * the unquoting algorithm in the C runtime is really weird, and
250 * rather different than what Unix shells do. See stdargv.c in the C
251 * runtime sources (in the Platform SDK, in src/crt).
253 * Note that a new_argv[0] constructed by this function should
254 * *not* be passed as the filename argument to a spawn* or exec*
255 * family function. That argument should be the real file name
256 * without any quoting.
258 for (i = 0; i < argc; i++)
259 (*new_argv)[i] = protect_argv_string (argv[i]);
261 (*new_argv)[argc] = NULL;
266 G_DEFINE_QUARK (g-exec-error-quark, g_spawn_error)
267 G_DEFINE_QUARK (g-spawn-exit-error-quark, g_spawn_exit_error)
270 g_spawn_async (const gchar *working_directory,
274 GSpawnChildSetupFunc child_setup,
279 g_return_val_if_fail (argv != NULL && argv[0] != NULL, FALSE);
281 return g_spawn_async_with_pipes (working_directory,
291 /* Avoids a danger in threaded situations (calling close()
292 * on a file descriptor twice, and another thread has
293 * re-opened it since the first close)
296 close_and_invalidate (gint *fd)
307 READ_FAILED = 0, /* FALSE */
313 read_data (GString *str,
314 GIOChannel *iochannel,
323 giostatus = g_io_channel_read_chars (iochannel, buf, sizeof (buf), &bytes, NULL);
329 g_string_append_len (str, buf, bytes);
332 else if (giostatus == G_IO_STATUS_AGAIN)
334 else if (giostatus == G_IO_STATUS_ERROR)
336 g_set_error_literal (error, G_SPAWN_ERROR, G_SPAWN_ERROR_READ,
337 _("Failed to read data from child process"));
346 make_pipe (gint p[2],
349 if (_pipe (p, 4096, _O_BINARY) < 0)
353 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
354 _("Failed to create pipe for communicating with child process (%s)"),
362 /* The helper process writes a status report back to us, through a
363 * pipe, consisting of two ints.
366 read_helper_report (int fd,
372 while (bytes < sizeof(gintptr)*2)
378 g_print ("%s:read_helper_report: read %" G_GSIZE_FORMAT "...\n",
380 sizeof(gintptr)*2 - bytes);
382 chunk = read (fd, ((gchar*)report) + bytes,
383 sizeof(gintptr)*2 - bytes);
387 g_print ("...got %d bytes\n", chunk);
391 /* Some weird shit happened, bail out */
392 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
393 _("Failed to read from child pipe (%s)"),
400 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
401 _("Failed to read from child pipe (%s)"),
409 if (bytes < sizeof(gintptr)*2)
416 set_child_error (gintptr report[2],
417 const gchar *working_directory,
422 case CHILD_CHDIR_FAILED:
423 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR,
424 _("Failed to change to directory “%s” (%s)"),
426 g_strerror (report[1]));
428 case CHILD_SPAWN_FAILED:
429 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
430 _("Failed to execute child process (%s)"),
431 g_strerror (report[1]));
433 case CHILD_SPAWN_NOENT:
434 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_NOENT,
435 _("Failed to execute child process (%s)"),
436 g_strerror (report[1]));
438 case CHILD_DUP_FAILED:
439 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
440 _("Failed to dup() in child process (%s)"),
441 g_strerror (report[1]));
444 g_assert_not_reached ();
449 utf8_charv_to_wcharv (const gchar * const *utf8_charv,
454 wchar_t **retval = NULL;
457 if (utf8_charv != NULL)
461 while (utf8_charv[n])
463 retval = g_new (wchar_t *, n + 1);
465 for (i = 0; i < n; i++)
467 retval[i] = g_utf8_to_utf16 (utf8_charv[i], -1, NULL, NULL, error);
468 if (retval[i] == NULL)
473 g_free (retval[--i]);
486 do_spawn_directly (gint *exit_status,
487 gboolean do_return_handle,
489 const gchar * const *argv,
490 const gchar * const *envp,
491 const gchar * const *protected_argv,
495 const int mode = (exit_status == NULL) ? P_NOWAIT : P_WAIT;
496 const gchar * const *new_argv;
499 GError *conv_error = NULL;
500 gint conv_error_index;
501 wchar_t *wargv0, **wargv, **wenvp;
503 g_assert (argv != NULL && argv[0] != NULL);
505 new_argv = (flags & G_SPAWN_FILE_AND_ARGV_ZERO) ? protected_argv + 1 : protected_argv;
507 wargv0 = g_utf8_to_utf16 (argv[0], -1, NULL, NULL, &conv_error);
510 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
511 _("Invalid program name: %s"),
512 conv_error->message);
513 g_error_free (conv_error);
518 if (!utf8_charv_to_wcharv (new_argv, &wargv, &conv_error_index, &conv_error))
520 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
521 _("Invalid string in argument vector at %d: %s"),
522 conv_error_index, conv_error->message);
523 g_error_free (conv_error);
529 if (!utf8_charv_to_wcharv (envp, &wenvp, NULL, &conv_error))
531 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
532 _("Invalid string in environment: %s"),
533 conv_error->message);
534 g_error_free (conv_error);
536 g_strfreev ((gchar **) wargv);
541 if (flags & G_SPAWN_SEARCH_PATH)
543 rc = safe_wspawnvpe (mode, wargv0, (const wchar_t **) wargv, (const wchar_t **) wenvp);
545 rc = _wspawnvp (mode, wargv0, (const wchar_t **) wargv);
548 rc = safe_wspawnve (mode, wargv0, (const wchar_t **) wargv, (const wchar_t **) wenvp);
550 rc = _wspawnv (mode, wargv0, (const wchar_t **) wargv);
555 g_strfreev ((gchar **) wargv);
556 g_strfreev ((gchar **) wenvp);
558 if (rc == -1 && errsv != 0)
560 g_set_error (error, G_SPAWN_ERROR, _g_spawn_exec_err_to_g_error (errsv),
561 _("Failed to execute child process (%s)"),
566 if (exit_status == NULL)
568 if (child_pid && do_return_handle)
569 *child_pid = (GPid) rc;
572 CloseHandle ((HANDLE) rc);
584 might_be_console_process (void)
586 // we should always fail to attach ourself to a console (because we're
587 // either already attached, or we do not have a console)
588 gboolean attached_to_self = AttachConsole (GetCurrentProcessId ());
589 g_return_val_if_fail (!attached_to_self, TRUE);
591 switch (GetLastError ())
593 // current process is already attached to a console
594 case ERROR_ACCESS_DENIED:
596 // current process does not have a console
597 case ERROR_INVALID_HANDLE:
599 // we should not get ERROR_INVALID_PARAMETER
602 g_return_val_if_reached (FALSE);
606 fork_exec (gint *exit_status,
607 gboolean do_return_handle,
608 const gchar *working_directory,
609 const gchar * const *argv,
610 const gchar * const *envp,
612 GSpawnChildSetupFunc child_setup,
615 gint *stdin_pipe_out,
616 gint *stdout_pipe_out,
617 gint *stderr_pipe_out,
621 const gint *source_fds,
622 const gint *target_fds,
627 char **protected_argv;
628 char args[ARG_COUNT][10];
634 int child_err_report_pipe[2] = { -1, -1 };
635 int helper_sync_pipe[2] = { -1, -1 };
636 gintptr helper_report[2];
637 static gboolean warned_about_child_setup = FALSE;
638 GError *conv_error = NULL;
639 gint conv_error_index;
640 gchar *helper_process;
641 wchar_t *whelper, **wargv, **wenvp;
642 int stdin_pipe[2] = { -1, -1 };
643 int stdout_pipe[2] = { -1, -1 };
644 int stderr_pipe[2] = { -1, -1 };
646 g_assert (argv != NULL && argv[0] != NULL);
647 g_assert (stdin_pipe_out == NULL || stdin_fd < 0);
648 g_assert (stdout_pipe_out == NULL || stdout_fd < 0);
649 g_assert (stderr_pipe_out == NULL || stderr_fd < 0);
651 if (child_setup && !warned_about_child_setup)
653 warned_about_child_setup = TRUE;
654 g_warning ("passing a child setup function to the g_spawn functions is pointless on Windows and it is ignored");
657 if (stdin_pipe_out != NULL)
659 if (!make_pipe (stdin_pipe, error))
660 goto cleanup_and_fail;
661 stdin_fd = stdin_pipe[0];
664 if (stdout_pipe_out != NULL)
666 if (!make_pipe (stdout_pipe, error))
667 goto cleanup_and_fail;
668 stdout_fd = stdout_pipe[1];
671 if (stderr_pipe_out != NULL)
673 if (!make_pipe (stderr_pipe, error))
674 goto cleanup_and_fail;
675 stderr_fd = stderr_pipe[1];
678 argc = protect_argv (argv, &protected_argv);
681 * FIXME: Workaround broken spawnvpe functions that SEGV when "=X:="
682 * environment variables are missing. Calling chdir() will set the magic
683 * environment variable again.
687 if (stdin_fd == -1 && stdout_fd == -1 && stderr_fd == -1 &&
688 (flags & G_SPAWN_CHILD_INHERITS_STDIN) &&
689 !(flags & G_SPAWN_STDOUT_TO_DEV_NULL) &&
690 !(flags & G_SPAWN_STDERR_TO_DEV_NULL) &&
691 (working_directory == NULL || !*working_directory) &&
692 (flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN) &&
695 /* We can do without the helper process */
697 do_spawn_directly (exit_status, do_return_handle, flags,
698 argv, envp, (const gchar * const *) protected_argv,
700 g_strfreev (protected_argv);
704 if (!make_pipe (child_err_report_pipe, error))
705 goto cleanup_and_fail;
707 if (!make_pipe (helper_sync_pipe, error))
708 goto cleanup_and_fail;
710 new_argv = g_new (char *, argc + 1 + ARG_COUNT);
711 if (might_be_console_process ())
712 helper_process = HELPER_PROCESS "-console.exe";
714 helper_process = HELPER_PROCESS ".exe";
716 helper_process = g_win32_find_helper_executable_path (helper_process, glib_dll);
717 new_argv[0] = protect_argv_string (helper_process);
719 _g_sprintf (args[ARG_CHILD_ERR_REPORT], "%d", child_err_report_pipe[1]);
720 new_argv[ARG_CHILD_ERR_REPORT] = args[ARG_CHILD_ERR_REPORT];
722 /* Make the read end of the child error report pipe
723 * noninherited. Otherwise it will needlessly be inherited by the
724 * helper process, and the started actual user process. As such that
725 * shouldn't harm, but it is unnecessary.
727 child_err_report_pipe[0] = g_win32_reopen_noninherited (
728 child_err_report_pipe[0], _O_RDONLY, error);
729 if (child_err_report_pipe[0] == -1)
730 goto cleanup_and_fail;
732 if (flags & G_SPAWN_FILE_AND_ARGV_ZERO)
734 /* Overload ARG_CHILD_ERR_REPORT to also encode the
735 * G_SPAWN_FILE_AND_ARGV_ZERO functionality.
737 strcat (args[ARG_CHILD_ERR_REPORT], "#");
740 _g_sprintf (args[ARG_HELPER_SYNC], "%d", helper_sync_pipe[0]);
741 new_argv[ARG_HELPER_SYNC] = args[ARG_HELPER_SYNC];
743 /* Make the write end of the sync pipe noninherited. Otherwise the
744 * helper process will inherit it, and thus if this process happens
745 * to crash before writing the sync byte to the pipe, the helper
746 * process won't read but won't get any EOF either, as it has the
747 * write end open itself.
749 helper_sync_pipe[1] = g_win32_reopen_noninherited (
750 helper_sync_pipe[1], _O_WRONLY, error);
751 if (helper_sync_pipe[1] == -1)
752 goto cleanup_and_fail;
756 _g_sprintf (args[ARG_STDIN], "%d", stdin_fd);
757 new_argv[ARG_STDIN] = args[ARG_STDIN];
759 else if (flags & G_SPAWN_CHILD_INHERITS_STDIN)
761 /* Let stdin be alone */
762 new_argv[ARG_STDIN] = "-";
766 /* Keep process from blocking on a read of stdin */
767 new_argv[ARG_STDIN] = "z";
772 _g_sprintf (args[ARG_STDOUT], "%d", stdout_fd);
773 new_argv[ARG_STDOUT] = args[ARG_STDOUT];
775 else if (flags & G_SPAWN_STDOUT_TO_DEV_NULL)
777 new_argv[ARG_STDOUT] = "z";
781 new_argv[ARG_STDOUT] = "-";
786 _g_sprintf (args[ARG_STDERR], "%d", stderr_fd);
787 new_argv[ARG_STDERR] = args[ARG_STDERR];
789 else if (flags & G_SPAWN_STDERR_TO_DEV_NULL)
791 new_argv[ARG_STDERR] = "z";
795 new_argv[ARG_STDERR] = "-";
798 if (working_directory && *working_directory)
799 new_argv[ARG_WORKING_DIRECTORY] = protect_argv_string (working_directory);
801 new_argv[ARG_WORKING_DIRECTORY] = g_strdup ("-");
803 if (!(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN))
804 new_argv[ARG_CLOSE_DESCRIPTORS] = "y";
806 new_argv[ARG_CLOSE_DESCRIPTORS] = "-";
808 if (flags & G_SPAWN_SEARCH_PATH)
809 new_argv[ARG_USE_PATH] = "y";
811 new_argv[ARG_USE_PATH] = "-";
813 if (exit_status == NULL)
814 new_argv[ARG_WAIT] = "-";
816 new_argv[ARG_WAIT] = "w";
819 new_argv[ARG_FDS] = g_strdup ("-");
822 GString *fds = g_string_new ("");
825 for (n = 0; n < n_fds; n++)
826 g_string_append_printf (fds, "%d:%d,", source_fds[n], target_fds[n]);
828 /* remove the trailing , */
829 g_string_truncate (fds, fds->len - 1);
830 new_argv[ARG_FDS] = g_string_free (fds, FALSE);
833 for (i = 0; i <= argc; i++)
834 new_argv[ARG_PROGRAM + i] = protected_argv[i];
840 g_print ("calling %s with argv:\n", helper_process);
841 for (i = 0; i < argc + 1 + ARG_COUNT; i++)
842 g_print ("argv[%d]: %s\n", i, (new_argv[i] ? new_argv[i] : "NULL"));
845 if (!utf8_charv_to_wcharv ((const gchar * const *) new_argv, &wargv, &conv_error_index, &conv_error))
847 if (conv_error_index == ARG_WORKING_DIRECTORY)
848 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR,
849 _("Invalid working directory: %s"),
850 conv_error->message);
852 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
853 _("Invalid string in argument vector at %d: %s"),
854 conv_error_index - ARG_PROGRAM, conv_error->message);
855 g_error_free (conv_error);
856 g_strfreev (protected_argv);
857 g_free (new_argv[0]);
858 g_free (new_argv[ARG_WORKING_DIRECTORY]);
859 g_free (new_argv[ARG_FDS]);
861 g_free (helper_process);
863 goto cleanup_and_fail;
866 if (!utf8_charv_to_wcharv (envp, &wenvp, NULL, &conv_error))
868 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
869 _("Invalid string in environment: %s"),
870 conv_error->message);
871 g_error_free (conv_error);
872 g_strfreev (protected_argv);
873 g_free (new_argv[0]);
874 g_free (new_argv[ARG_WORKING_DIRECTORY]);
875 g_free (new_argv[ARG_FDS]);
877 g_free (helper_process);
878 g_strfreev ((gchar **) wargv);
880 goto cleanup_and_fail;
883 whelper = g_utf8_to_utf16 (helper_process, -1, NULL, NULL, NULL);
884 g_free (helper_process);
887 rc = safe_wspawnvpe (P_NOWAIT, whelper, (const wchar_t **) wargv, (const wchar_t **) wenvp);
889 rc = _wspawnvp (P_NOWAIT, whelper, (const wchar_t **) wargv);
894 g_strfreev ((gchar **) wargv);
895 g_strfreev ((gchar **) wenvp);
897 /* Close the other process's ends of the pipes in this process,
898 * otherwise the reader will never get EOF.
900 close_and_invalidate (&child_err_report_pipe[1]);
901 close_and_invalidate (&helper_sync_pipe[0]);
903 g_strfreev (protected_argv);
905 g_free (new_argv[0]);
906 g_free (new_argv[ARG_WORKING_DIRECTORY]);
907 g_free (new_argv[ARG_FDS]);
910 /* Check if gspawn-win32-helper couldn't be run */
911 if (rc == -1 && errsv != 0)
913 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
914 _("Failed to execute helper program (%s)"),
916 goto cleanup_and_fail;
919 if (exit_status != NULL)
921 /* Synchronous case. Pass helper's report pipe back to caller,
922 * which takes care of reading it after the grandchild has
925 g_assert (err_report != NULL);
926 *err_report = child_err_report_pipe[0];
927 write (helper_sync_pipe[1], " ", 1);
928 close_and_invalidate (&helper_sync_pipe[1]);
932 /* Asynchronous case. We read the helper's report right away. */
933 if (!read_helper_report (child_err_report_pipe[0], helper_report, error))
934 goto cleanup_and_fail;
936 close_and_invalidate (&child_err_report_pipe[0]);
938 switch (helper_report[0])
941 if (child_pid && do_return_handle)
943 /* rc is our HANDLE for gspawn-win32-helper. It has
944 * told us the HANDLE of its child. Duplicate that into
945 * a HANDLE valid in this process.
947 if (!DuplicateHandle ((HANDLE) rc, (HANDLE) helper_report[1],
948 GetCurrentProcess (), (LPHANDLE) child_pid,
949 0, TRUE, DUPLICATE_SAME_ACCESS))
951 char *emsg = g_win32_error_message (GetLastError ());
952 g_print ("%s\n", emsg);
959 write (helper_sync_pipe[1], " ", 1);
960 close_and_invalidate (&helper_sync_pipe[1]);
964 write (helper_sync_pipe[1], " ", 1);
965 close_and_invalidate (&helper_sync_pipe[1]);
966 set_child_error (helper_report, working_directory, error);
967 goto cleanup_and_fail;
971 /* Success against all odds! return the information */
974 CloseHandle ((HANDLE) rc);
976 /* Close the other process's ends of the pipes in this process,
977 * otherwise the reader will never get EOF.
979 close_and_invalidate (&stdin_pipe[0]);
980 close_and_invalidate (&stdout_pipe[1]);
981 close_and_invalidate (&stderr_pipe[1]);
983 if (stdin_pipe_out != NULL)
984 *stdin_pipe_out = stdin_pipe[1];
985 if (stdout_pipe_out != NULL)
986 *stdout_pipe_out = stdout_pipe[0];
987 if (stderr_pipe_out != NULL)
988 *stderr_pipe_out = stderr_pipe[0];
995 CloseHandle ((HANDLE) rc);
996 if (child_err_report_pipe[0] != -1)
997 close (child_err_report_pipe[0]);
998 if (child_err_report_pipe[1] != -1)
999 close (child_err_report_pipe[1]);
1000 if (helper_sync_pipe[0] != -1)
1001 close (helper_sync_pipe[0]);
1002 if (helper_sync_pipe[1] != -1)
1003 close (helper_sync_pipe[1]);
1005 if (stdin_pipe[0] != -1)
1006 close (stdin_pipe[0]);
1007 if (stdin_pipe[1] != -1)
1008 close (stdin_pipe[1]);
1009 if (stdout_pipe[0] != -1)
1010 close (stdout_pipe[0]);
1011 if (stdout_pipe[1] != -1)
1012 close (stdout_pipe[1]);
1013 if (stderr_pipe[0] != -1)
1014 close (stderr_pipe[0]);
1015 if (stderr_pipe[1] != -1)
1016 close (stderr_pipe[1]);
1022 g_spawn_sync (const gchar *working_directory,
1026 GSpawnChildSetupFunc child_setup,
1028 gchar **standard_output,
1029 gchar **standard_error,
1035 gint reportpipe = -1;
1036 GIOChannel *outchannel = NULL;
1037 GIOChannel *errchannel = NULL;
1038 GPollFD outfd = { -1, 0, 0 }, errfd = { -1, 0, 0 };
1044 GString *outstr = NULL;
1045 GString *errstr = NULL;
1049 g_return_val_if_fail (argv != NULL && argv[0] != NULL, FALSE);
1050 g_return_val_if_fail (!(flags & G_SPAWN_DO_NOT_REAP_CHILD), FALSE);
1051 g_return_val_if_fail (standard_output == NULL ||
1052 !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
1053 g_return_val_if_fail (standard_error == NULL ||
1054 !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
1056 /* Just to ensure segfaults if callers try to use
1057 * these when an error is reported.
1059 if (standard_output)
1060 *standard_output = NULL;
1063 *standard_error = NULL;
1065 if (!fork_exec (&status,
1068 (const gchar * const *) argv,
1069 (const gchar * const *) envp,
1075 standard_output ? &outpipe : NULL,
1076 standard_error ? &errpipe : NULL,
1085 /* Read data from child. */
1091 outstr = g_string_new (NULL);
1092 outchannel = g_io_channel_win32_new_fd (outpipe);
1093 g_io_channel_set_encoding (outchannel, NULL, NULL);
1094 g_io_channel_set_buffered (outchannel, FALSE);
1095 g_io_channel_win32_make_pollfd (outchannel,
1096 G_IO_IN | G_IO_ERR | G_IO_HUP,
1099 g_print ("outfd=%p\n", (HANDLE) outfd.fd);
1104 errstr = g_string_new (NULL);
1105 errchannel = g_io_channel_win32_new_fd (errpipe);
1106 g_io_channel_set_encoding (errchannel, NULL, NULL);
1107 g_io_channel_set_buffered (errchannel, FALSE);
1108 g_io_channel_win32_make_pollfd (errchannel,
1109 G_IO_IN | G_IO_ERR | G_IO_HUP,
1112 g_print ("errfd=%p\n", (HANDLE) errfd.fd);
1115 /* Read data until we get EOF on all pipes. */
1116 while (!failed && (outpipe >= 0 || errpipe >= 0))
1133 g_print ("g_spawn_sync: calling g_io_channel_win32_poll, nfds=%d\n",
1136 ret = g_io_channel_win32_poll (fds, nfds, -1);
1142 g_set_error_literal (error, G_SPAWN_ERROR, G_SPAWN_ERROR_READ,
1143 _("Unexpected error in g_io_channel_win32_poll() reading data from a child process"));
1148 if (outpipe >= 0 && (fds[outindex].revents & G_IO_IN))
1150 switch (read_data (outstr, outchannel, error))
1154 g_print ("g_spawn_sync: outchannel: READ_FAILED\n");
1159 g_print ("g_spawn_sync: outchannel: READ_EOF\n");
1160 g_io_channel_unref (outchannel);
1162 close_and_invalidate (&outpipe);
1166 g_print ("g_spawn_sync: outchannel: OK\n");
1174 if (errpipe >= 0 && (fds[errindex].revents & G_IO_IN))
1176 switch (read_data (errstr, errchannel, error))
1180 g_print ("g_spawn_sync: errchannel: READ_FAILED\n");
1185 g_print ("g_spawn_sync: errchannel: READ_EOF\n");
1186 g_io_channel_unref (errchannel);
1188 close_and_invalidate (&errpipe);
1192 g_print ("g_spawn_sync: errchannel: OK\n");
1201 if (reportpipe == -1)
1203 /* No helper process, exit status of actual spawned process
1204 * already available.
1207 *wait_status = status;
1211 /* Helper process was involved. Read its report now after the
1212 * grandchild has finished.
1214 gintptr helper_report[2];
1216 if (!read_helper_report (reportpipe, helper_report, error))
1220 switch (helper_report[0])
1222 case CHILD_NO_ERROR:
1224 *wait_status = helper_report[1];
1227 set_child_error (helper_report, working_directory, error);
1232 close_and_invalidate (&reportpipe);
1236 /* These should only be open still if we had an error. */
1238 if (outchannel != NULL)
1239 g_io_channel_unref (outchannel);
1240 if (errchannel != NULL)
1241 g_io_channel_unref (errchannel);
1243 close_and_invalidate (&outpipe);
1245 close_and_invalidate (&errpipe);
1250 g_string_free (outstr, TRUE);
1252 g_string_free (errstr, TRUE);
1258 if (standard_output)
1259 *standard_output = g_string_free (outstr, FALSE);
1262 *standard_error = g_string_free (errstr, FALSE);
1269 g_spawn_async_with_pipes (const gchar *working_directory,
1273 GSpawnChildSetupFunc child_setup,
1276 gint *standard_input,
1277 gint *standard_output,
1278 gint *standard_error,
1281 g_return_val_if_fail (argv != NULL && argv[0] != NULL, FALSE);
1282 g_return_val_if_fail (standard_output == NULL ||
1283 !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
1284 g_return_val_if_fail (standard_error == NULL ||
1285 !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
1286 /* can't inherit stdin if we have an input pipe. */
1287 g_return_val_if_fail (standard_input == NULL ||
1288 !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
1290 return fork_exec (NULL,
1291 (flags & G_SPAWN_DO_NOT_REAP_CHILD),
1293 (const gchar * const *) argv,
1294 (const gchar * const *) envp,
1311 g_spawn_async_with_fds (const gchar *working_directory,
1315 GSpawnChildSetupFunc child_setup,
1323 g_return_val_if_fail (argv != NULL && argv[0] != NULL, FALSE);
1324 g_return_val_if_fail (stdin_fd == -1 ||
1325 !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
1326 g_return_val_if_fail (stderr_fd == -1 ||
1327 !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
1328 /* can't inherit stdin if we have an input pipe. */
1329 g_return_val_if_fail (stdin_fd == -1 ||
1330 !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
1332 return fork_exec (NULL,
1333 (flags & G_SPAWN_DO_NOT_REAP_CHILD),
1335 (const gchar * const *) argv,
1336 (const gchar * const *) envp,
1354 g_spawn_async_with_pipes_and_fds (const gchar *working_directory,
1355 const gchar * const *argv,
1356 const gchar * const *envp,
1358 GSpawnChildSetupFunc child_setup,
1363 const gint *source_fds,
1364 const gint *target_fds,
1366 GPid *child_pid_out,
1367 gint *stdin_pipe_out,
1368 gint *stdout_pipe_out,
1369 gint *stderr_pipe_out,
1372 g_return_val_if_fail (argv != NULL && argv[0] != NULL, FALSE);
1373 g_return_val_if_fail (stdout_pipe_out == NULL ||
1374 !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
1375 g_return_val_if_fail (stderr_pipe_out == NULL ||
1376 !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
1377 /* can't inherit stdin if we have an input pipe. */
1378 g_return_val_if_fail (stdin_pipe_out == NULL ||
1379 !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
1380 /* can’t use pipes and stdin/stdout/stderr FDs */
1381 g_return_val_if_fail (stdin_pipe_out == NULL || stdin_fd < 0, FALSE);
1382 g_return_val_if_fail (stdout_pipe_out == NULL || stdout_fd < 0, FALSE);
1383 g_return_val_if_fail (stderr_pipe_out == NULL || stderr_fd < 0, FALSE);
1385 return fork_exec (NULL,
1386 (flags & G_SPAWN_DO_NOT_REAP_CHILD),
1408 g_spawn_command_line_sync (const gchar *command_line,
1409 gchar **standard_output,
1410 gchar **standard_error,
1417 g_return_val_if_fail (command_line != NULL, FALSE);
1419 /* This will return a runtime error if @command_line is the empty string. */
1420 if (!g_shell_parse_argv (command_line,
1425 retval = g_spawn_sync (NULL,
1428 G_SPAWN_SEARCH_PATH,
1441 g_spawn_command_line_async (const gchar *command_line,
1447 g_return_val_if_fail (command_line != NULL, FALSE);
1449 /* This will return a runtime error if @command_line is the empty string. */
1450 if (!g_shell_parse_argv (command_line,
1455 retval = g_spawn_async (NULL,
1458 G_SPAWN_SEARCH_PATH,
1469 g_spawn_close_pid (GPid pid)
1471 /* CRT functions such as _wspawn* return (HANDLE)-1
1472 * on failure, so check also for that value. */
1473 if (pid != NULL && pid != (HANDLE) -1)
1478 g_spawn_check_wait_status (gint wait_status,
1481 gboolean ret = FALSE;
1483 if (wait_status != 0)
1485 /* On Windows, the wait status is just the exit status: the
1486 * difference between the two that exists on Unix is not relevant */
1487 g_set_error (error, G_SPAWN_EXIT_ERROR, wait_status,
1488 _("Child process exited with code %ld"),
1489 (long) wait_status);
1499 g_spawn_check_exit_status (gint wait_status,
1502 return g_spawn_check_wait_status (wait_status, error);
1507 /* Binary compatibility versions. Not for newly compiled code. */
1509 _GLIB_EXTERN gboolean g_spawn_async_utf8 (const gchar *working_directory,
1513 GSpawnChildSetupFunc child_setup,
1517 _GLIB_EXTERN gboolean g_spawn_async_with_pipes_utf8 (const gchar *working_directory,
1521 GSpawnChildSetupFunc child_setup,
1524 gint *standard_input,
1525 gint *standard_output,
1526 gint *standard_error,
1528 _GLIB_EXTERN gboolean g_spawn_sync_utf8 (const gchar *working_directory,
1532 GSpawnChildSetupFunc child_setup,
1534 gchar **standard_output,
1535 gchar **standard_error,
1538 _GLIB_EXTERN gboolean g_spawn_command_line_sync_utf8 (const gchar *command_line,
1539 gchar **standard_output,
1540 gchar **standard_error,
1543 _GLIB_EXTERN gboolean g_spawn_command_line_async_utf8 (const gchar *command_line,
1547 g_spawn_async_utf8 (const gchar *working_directory,
1551 GSpawnChildSetupFunc child_setup,
1556 return g_spawn_async (working_directory,
1567 g_spawn_async_with_pipes_utf8 (const gchar *working_directory,
1571 GSpawnChildSetupFunc child_setup,
1574 gint *standard_input,
1575 gint *standard_output,
1576 gint *standard_error,
1579 return g_spawn_async_with_pipes (working_directory,
1593 g_spawn_sync_utf8 (const gchar *working_directory,
1597 GSpawnChildSetupFunc child_setup,
1599 gchar **standard_output,
1600 gchar **standard_error,
1604 return g_spawn_sync (working_directory,
1617 g_spawn_command_line_sync_utf8 (const gchar *command_line,
1618 gchar **standard_output,
1619 gchar **standard_error,
1623 return g_spawn_command_line_sync (command_line,
1631 g_spawn_command_line_async_utf8 (const gchar *command_line,
1634 return g_spawn_command_line_async (command_line, error);
1637 #endif /* G_OS_WIN32 */
1639 #endif /* !GSPAWN_HELPER */