Add some more cases to the app-id unit tests
[glib.git] / glib / gspawn-win32.c
blobe1048d2c382bb269472d120ba46fa935c9fcf89a
1 /* gspawn-win32.c - Process launching on Win32
3 * Copyright 2000 Red Hat, Inc.
4 * Copyright 2003 Tor Lillqvist
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this library; if not, see <http://www.gnu.org/licenses/>.
21 * Implementation details on Win32.
23 * - There is no way to set the no-inherit flag for
24 * a "file descriptor" in the MS C runtime. The flag is there,
25 * and the dospawn() function uses it, but unfortunately
26 * this flag can only be set when opening the file.
27 * - As there is no fork(), we cannot reliably change directory
28 * before starting the child process. (There might be several threads
29 * running, and the current directory is common for all threads.)
31 * Thus, we must in many cases use a helper program to handle closing
32 * of (inherited) file descriptors and changing of directory. The
33 * helper process is also needed if the standard input, standard
34 * output, or standard error of the process to be run are supposed to
35 * be redirected somewhere.
37 * The structure of the source code in this file is a mess, I know.
40 /* Define this to get some logging all the time */
41 /* #define G_SPAWN_WIN32_DEBUG */
43 #include "config.h"
45 #include "glib.h"
46 #include "glib-private.h"
47 #include "gprintfint.h"
48 #include "glibintl.h"
49 #include "gthread.h"
51 #include <string.h>
52 #include <stdlib.h>
53 #include <stdio.h>
55 #include <windows.h>
56 #include <errno.h>
57 #include <fcntl.h>
58 #include <io.h>
59 #include <process.h>
60 #include <direct.h>
61 #include <wchar.h>
63 #ifndef GSPAWN_HELPER
64 #ifdef G_SPAWN_WIN32_DEBUG
65 static int debug = 1;
66 #define SETUP_DEBUG() /* empty */
67 #else
68 static int debug = -1;
69 #define SETUP_DEBUG() \
70 G_STMT_START \
71 { \
72 if (debug == -1) \
73 { \
74 if (getenv ("G_SPAWN_WIN32_DEBUG") != NULL) \
75 debug = 1; \
76 else \
77 debug = 0; \
78 } \
79 } \
80 G_STMT_END
81 #endif
82 #endif
84 enum
86 CHILD_NO_ERROR,
87 CHILD_CHDIR_FAILED,
88 CHILD_SPAWN_FAILED,
91 enum {
92 ARG_CHILD_ERR_REPORT = 1,
93 ARG_HELPER_SYNC,
94 ARG_STDIN,
95 ARG_STDOUT,
96 ARG_STDERR,
97 ARG_WORKING_DIRECTORY,
98 ARG_CLOSE_DESCRIPTORS,
99 ARG_USE_PATH,
100 ARG_WAIT,
101 ARG_PROGRAM,
102 ARG_COUNT = ARG_PROGRAM
105 static int
106 dup_noninherited (int fd,
107 int mode)
109 HANDLE filehandle;
111 DuplicateHandle (GetCurrentProcess (), (LPHANDLE) _get_osfhandle (fd),
112 GetCurrentProcess (), &filehandle,
113 0, FALSE, DUPLICATE_SAME_ACCESS);
114 close (fd);
115 return _open_osfhandle ((gintptr) filehandle, mode | _O_NOINHERIT);
118 #ifndef GSPAWN_HELPER
120 #ifdef _WIN64
121 #define HELPER_PROCESS "gspawn-win64-helper"
122 #else
123 #define HELPER_PROCESS "gspawn-win32-helper"
124 #endif
126 static gchar *
127 protect_argv_string (const gchar *string)
129 const gchar *p = string;
130 gchar *retval, *q;
131 gint len = 0;
132 gboolean need_dblquotes = FALSE;
133 while (*p)
135 if (*p == ' ' || *p == '\t')
136 need_dblquotes = TRUE;
137 else if (*p == '"')
138 len++;
139 else if (*p == '\\')
141 const gchar *pp = p;
142 while (*pp && *pp == '\\')
143 pp++;
144 if (*pp == '"')
145 len++;
147 len++;
148 p++;
151 q = retval = g_malloc (len + need_dblquotes*2 + 1);
152 p = string;
154 if (need_dblquotes)
155 *q++ = '"';
157 while (*p)
159 if (*p == '"')
160 *q++ = '\\';
161 else if (*p == '\\')
163 const gchar *pp = p;
164 while (*pp && *pp == '\\')
165 pp++;
166 if (*pp == '"')
167 *q++ = '\\';
169 *q++ = *p;
170 p++;
173 if (need_dblquotes)
174 *q++ = '"';
175 *q++ = '\0';
177 return retval;
180 static gint
181 protect_argv (gchar **argv,
182 gchar ***new_argv)
184 gint i;
185 gint argc = 0;
187 while (argv[argc])
188 ++argc;
189 *new_argv = g_new (gchar *, argc+1);
191 /* Quote each argv element if necessary, so that it will get
192 * reconstructed correctly in the C runtime startup code. Note that
193 * the unquoting algorithm in the C runtime is really weird, and
194 * rather different than what Unix shells do. See stdargv.c in the C
195 * runtime sources (in the Platform SDK, in src/crt).
197 * Note that an new_argv[0] constructed by this function should
198 * *not* be passed as the filename argument to a spawn* or exec*
199 * family function. That argument should be the real file name
200 * without any quoting.
202 for (i = 0; i < argc; i++)
203 (*new_argv)[i] = protect_argv_string (argv[i]);
205 (*new_argv)[argc] = NULL;
207 return argc;
210 G_DEFINE_QUARK (g-exec-error-quark, g_spawn_error)
211 G_DEFINE_QUARK (g-spawn-exit-error-quark, g_spawn_exit_error)
213 gboolean
214 g_spawn_async_utf8 (const gchar *working_directory,
215 gchar **argv,
216 gchar **envp,
217 GSpawnFlags flags,
218 GSpawnChildSetupFunc child_setup,
219 gpointer user_data,
220 GPid *child_handle,
221 GError **error)
223 g_return_val_if_fail (argv != NULL, FALSE);
225 return g_spawn_async_with_pipes_utf8 (working_directory,
226 argv, envp,
227 flags,
228 child_setup,
229 user_data,
230 child_handle,
231 NULL, NULL, NULL,
232 error);
235 /* Avoids a danger in threaded situations (calling close()
236 * on a file descriptor twice, and another thread has
237 * re-opened it since the first close)
239 static void
240 close_and_invalidate (gint *fd)
242 if (*fd < 0)
243 return;
245 close (*fd);
246 *fd = -1;
249 typedef enum
251 READ_FAILED = 0, /* FALSE */
252 READ_OK,
253 READ_EOF
254 } ReadResult;
256 static ReadResult
257 read_data (GString *str,
258 GIOChannel *iochannel,
259 GError **error)
261 GIOStatus giostatus;
262 gsize bytes;
263 gchar buf[4096];
265 again:
267 giostatus = g_io_channel_read_chars (iochannel, buf, sizeof (buf), &bytes, NULL);
269 if (bytes == 0)
270 return READ_EOF;
271 else if (bytes > 0)
273 g_string_append_len (str, buf, bytes);
274 return READ_OK;
276 else if (giostatus == G_IO_STATUS_AGAIN)
277 goto again;
278 else if (giostatus == G_IO_STATUS_ERROR)
280 g_set_error_literal (error, G_SPAWN_ERROR, G_SPAWN_ERROR_READ,
281 _("Failed to read data from child process"));
283 return READ_FAILED;
285 else
286 return READ_OK;
289 static gboolean
290 make_pipe (gint p[2],
291 GError **error)
293 if (_pipe (p, 4096, _O_BINARY) < 0)
295 int errsv = errno;
297 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
298 _("Failed to create pipe for communicating with child process (%s)"),
299 g_strerror (errsv));
300 return FALSE;
302 else
303 return TRUE;
306 /* The helper process writes a status report back to us, through a
307 * pipe, consisting of two ints.
309 static gboolean
310 read_helper_report (int fd,
311 gintptr report[2],
312 GError **error)
314 gint bytes = 0;
316 while (bytes < sizeof(gintptr)*2)
318 gint chunk;
320 if (debug)
321 g_print ("%s:read_helper_report: read %" G_GSIZE_FORMAT "...\n",
322 __FILE__,
323 sizeof(gintptr)*2 - bytes);
325 chunk = read (fd, ((gchar*)report) + bytes,
326 sizeof(gintptr)*2 - bytes);
328 if (debug)
329 g_print ("...got %d bytes\n", chunk);
331 if (chunk < 0)
333 int errsv = errno;
335 /* Some weird shit happened, bail out */
336 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
337 _("Failed to read from child pipe (%s)"),
338 g_strerror (errsv));
340 return FALSE;
342 else if (chunk == 0)
344 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
345 _("Failed to read from child pipe (%s)"),
346 "EOF");
347 break; /* EOF */
349 else
350 bytes += chunk;
353 if (bytes < sizeof(gintptr)*2)
354 return FALSE;
356 return TRUE;
359 static void
360 set_child_error (gintptr report[2],
361 const gchar *working_directory,
362 GError **error)
364 switch (report[0])
366 case CHILD_CHDIR_FAILED:
367 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR,
368 _("Failed to change to directory “%s” (%s)"),
369 working_directory,
370 g_strerror (report[1]));
371 break;
372 case CHILD_SPAWN_FAILED:
373 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
374 _("Failed to execute child process (%s)"),
375 g_strerror (report[1]));
376 break;
377 default:
378 g_assert_not_reached ();
382 static gboolean
383 utf8_charv_to_wcharv (char **utf8_charv,
384 wchar_t ***wcharv,
385 int *error_index,
386 GError **error)
388 wchar_t **retval = NULL;
390 *wcharv = NULL;
391 if (utf8_charv != NULL)
393 int n = 0, i;
395 while (utf8_charv[n])
396 n++;
397 retval = g_new (wchar_t *, n + 1);
399 for (i = 0; i < n; i++)
401 retval[i] = g_utf8_to_utf16 (utf8_charv[i], -1, NULL, NULL, error);
402 if (retval[i] == NULL)
404 if (error_index)
405 *error_index = i;
406 while (i)
407 g_free (retval[--i]);
408 g_free (retval);
409 return FALSE;
413 retval[n] = NULL;
415 *wcharv = retval;
416 return TRUE;
419 static gboolean
420 do_spawn_directly (gint *exit_status,
421 gboolean do_return_handle,
422 GSpawnFlags flags,
423 gchar **argv,
424 char **envp,
425 char **protected_argv,
426 GPid *child_handle,
427 GError **error)
429 const int mode = (exit_status == NULL) ? P_NOWAIT : P_WAIT;
430 char **new_argv;
431 gintptr rc = -1;
432 int saved_errno;
433 GError *conv_error = NULL;
434 gint conv_error_index;
435 wchar_t *wargv0, **wargv, **wenvp;
437 new_argv = (flags & G_SPAWN_FILE_AND_ARGV_ZERO) ? protected_argv + 1 : protected_argv;
439 wargv0 = g_utf8_to_utf16 (argv[0], -1, NULL, NULL, &conv_error);
440 if (wargv0 == NULL)
442 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
443 _("Invalid program name: %s"),
444 conv_error->message);
445 g_error_free (conv_error);
447 return FALSE;
450 if (!utf8_charv_to_wcharv (new_argv, &wargv, &conv_error_index, &conv_error))
452 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
453 _("Invalid string in argument vector at %d: %s"),
454 conv_error_index, conv_error->message);
455 g_error_free (conv_error);
456 g_free (wargv0);
458 return FALSE;
461 if (!utf8_charv_to_wcharv (envp, &wenvp, NULL, &conv_error))
463 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
464 _("Invalid string in environment: %s"),
465 conv_error->message);
466 g_error_free (conv_error);
467 g_free (wargv0);
468 g_strfreev ((gchar **) wargv);
470 return FALSE;
473 if (flags & G_SPAWN_SEARCH_PATH)
474 if (wenvp != NULL)
475 rc = _wspawnvpe (mode, wargv0, (const wchar_t **) wargv, (const wchar_t **) wenvp);
476 else
477 rc = _wspawnvp (mode, wargv0, (const wchar_t **) wargv);
478 else
479 if (wenvp != NULL)
480 rc = _wspawnve (mode, wargv0, (const wchar_t **) wargv, (const wchar_t **) wenvp);
481 else
482 rc = _wspawnv (mode, wargv0, (const wchar_t **) wargv);
484 g_free (wargv0);
485 g_strfreev ((gchar **) wargv);
486 g_strfreev ((gchar **) wenvp);
488 saved_errno = errno;
490 if (rc == -1 && saved_errno != 0)
492 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
493 _("Failed to execute child process (%s)"),
494 g_strerror (saved_errno));
495 return FALSE;
498 if (exit_status == NULL)
500 if (child_handle && do_return_handle)
501 *child_handle = (GPid) rc;
502 else
504 CloseHandle ((HANDLE) rc);
505 if (child_handle)
506 *child_handle = 0;
509 else
510 *exit_status = rc;
512 return TRUE;
515 static gboolean
516 do_spawn_with_pipes (gint *exit_status,
517 gboolean do_return_handle,
518 const gchar *working_directory,
519 gchar **argv,
520 char **envp,
521 GSpawnFlags flags,
522 GSpawnChildSetupFunc child_setup,
523 GPid *child_handle,
524 gint *standard_input,
525 gint *standard_output,
526 gint *standard_error,
527 gint *err_report,
528 GError **error)
530 char **protected_argv;
531 char args[ARG_COUNT][10];
532 char **new_argv;
533 int i;
534 gintptr rc = -1;
535 int saved_errno;
536 int argc;
537 int stdin_pipe[2] = { -1, -1 };
538 int stdout_pipe[2] = { -1, -1 };
539 int stderr_pipe[2] = { -1, -1 };
540 int child_err_report_pipe[2] = { -1, -1 };
541 int helper_sync_pipe[2] = { -1, -1 };
542 gintptr helper_report[2];
543 static gboolean warned_about_child_setup = FALSE;
544 GError *conv_error = NULL;
545 gint conv_error_index;
546 gchar *helper_process;
547 CONSOLE_CURSOR_INFO cursor_info;
548 wchar_t *whelper, **wargv, **wenvp;
549 gchar *glib_dll_directory;
551 if (child_setup && !warned_about_child_setup)
553 warned_about_child_setup = TRUE;
554 g_warning ("passing a child setup function to the g_spawn functions is pointless on Windows and it is ignored");
557 argc = protect_argv (argv, &protected_argv);
559 if (!standard_input && !standard_output && !standard_error &&
560 (flags & G_SPAWN_CHILD_INHERITS_STDIN) &&
561 !(flags & G_SPAWN_STDOUT_TO_DEV_NULL) &&
562 !(flags & G_SPAWN_STDERR_TO_DEV_NULL) &&
563 (working_directory == NULL || !*working_directory) &&
564 (flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN))
566 /* We can do without the helper process */
567 gboolean retval =
568 do_spawn_directly (exit_status, do_return_handle, flags,
569 argv, envp, protected_argv,
570 child_handle, error);
571 g_strfreev (protected_argv);
572 return retval;
575 if (standard_input && !make_pipe (stdin_pipe, error))
576 goto cleanup_and_fail;
578 if (standard_output && !make_pipe (stdout_pipe, error))
579 goto cleanup_and_fail;
581 if (standard_error && !make_pipe (stderr_pipe, error))
582 goto cleanup_and_fail;
584 if (!make_pipe (child_err_report_pipe, error))
585 goto cleanup_and_fail;
587 if (!make_pipe (helper_sync_pipe, error))
588 goto cleanup_and_fail;
590 new_argv = g_new (char *, argc + 1 + ARG_COUNT);
591 if (GetConsoleWindow () != NULL)
592 helper_process = HELPER_PROCESS "-console.exe";
593 else
594 helper_process = HELPER_PROCESS ".exe";
596 glib_dll_directory = _glib_get_dll_directory ();
597 if (glib_dll_directory != NULL)
599 helper_process = g_build_filename (glib_dll_directory, helper_process, NULL);
600 g_free (glib_dll_directory);
602 else
603 helper_process = g_strdup (helper_process);
605 new_argv[0] = protect_argv_string (helper_process);
607 _g_sprintf (args[ARG_CHILD_ERR_REPORT], "%d", child_err_report_pipe[1]);
608 new_argv[ARG_CHILD_ERR_REPORT] = args[ARG_CHILD_ERR_REPORT];
610 /* Make the read end of the child error report pipe
611 * noninherited. Otherwise it will needlessly be inherited by the
612 * helper process, and the started actual user process. As such that
613 * shouldn't harm, but it is unnecessary.
615 child_err_report_pipe[0] = dup_noninherited (child_err_report_pipe[0], _O_RDONLY);
617 if (flags & G_SPAWN_FILE_AND_ARGV_ZERO)
619 /* Overload ARG_CHILD_ERR_REPORT to also encode the
620 * G_SPAWN_FILE_AND_ARGV_ZERO functionality.
622 strcat (args[ARG_CHILD_ERR_REPORT], "#");
625 _g_sprintf (args[ARG_HELPER_SYNC], "%d", helper_sync_pipe[0]);
626 new_argv[ARG_HELPER_SYNC] = args[ARG_HELPER_SYNC];
628 /* Make the write end of the sync pipe noninherited. Otherwise the
629 * helper process will inherit it, and thus if this process happens
630 * to crash before writing the sync byte to the pipe, the helper
631 * process won't read but won't get any EOF either, as it has the
632 * write end open itself.
634 helper_sync_pipe[1] = dup_noninherited (helper_sync_pipe[1], _O_WRONLY);
636 if (standard_input)
638 _g_sprintf (args[ARG_STDIN], "%d", stdin_pipe[0]);
639 new_argv[ARG_STDIN] = args[ARG_STDIN];
641 else if (flags & G_SPAWN_CHILD_INHERITS_STDIN)
643 /* Let stdin be alone */
644 new_argv[ARG_STDIN] = "-";
646 else
648 /* Keep process from blocking on a read of stdin */
649 new_argv[ARG_STDIN] = "z";
652 if (standard_output)
654 _g_sprintf (args[ARG_STDOUT], "%d", stdout_pipe[1]);
655 new_argv[ARG_STDOUT] = args[ARG_STDOUT];
657 else if (flags & G_SPAWN_STDOUT_TO_DEV_NULL)
659 new_argv[ARG_STDOUT] = "z";
661 else
663 new_argv[ARG_STDOUT] = "-";
666 if (standard_error)
668 _g_sprintf (args[ARG_STDERR], "%d", stderr_pipe[1]);
669 new_argv[ARG_STDERR] = args[ARG_STDERR];
671 else if (flags & G_SPAWN_STDERR_TO_DEV_NULL)
673 new_argv[ARG_STDERR] = "z";
675 else
677 new_argv[ARG_STDERR] = "-";
680 if (working_directory && *working_directory)
681 new_argv[ARG_WORKING_DIRECTORY] = protect_argv_string (working_directory);
682 else
683 new_argv[ARG_WORKING_DIRECTORY] = g_strdup ("-");
685 if (!(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN))
686 new_argv[ARG_CLOSE_DESCRIPTORS] = "y";
687 else
688 new_argv[ARG_CLOSE_DESCRIPTORS] = "-";
690 if (flags & G_SPAWN_SEARCH_PATH)
691 new_argv[ARG_USE_PATH] = "y";
692 else
693 new_argv[ARG_USE_PATH] = "-";
695 if (exit_status == NULL)
696 new_argv[ARG_WAIT] = "-";
697 else
698 new_argv[ARG_WAIT] = "w";
700 for (i = 0; i <= argc; i++)
701 new_argv[ARG_PROGRAM + i] = protected_argv[i];
703 SETUP_DEBUG();
705 if (debug)
707 g_print ("calling %s with argv:\n", helper_process);
708 for (i = 0; i < argc + 1 + ARG_COUNT; i++)
709 g_print ("argv[%d]: %s\n", i, (new_argv[i] ? new_argv[i] : "NULL"));
712 if (!utf8_charv_to_wcharv (new_argv, &wargv, &conv_error_index, &conv_error))
714 if (conv_error_index == ARG_WORKING_DIRECTORY)
715 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR,
716 _("Invalid working directory: %s"),
717 conv_error->message);
718 else
719 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
720 _("Invalid string in argument vector at %d: %s"),
721 conv_error_index - ARG_PROGRAM, conv_error->message);
722 g_error_free (conv_error);
723 g_strfreev (protected_argv);
724 g_free (new_argv[0]);
725 g_free (new_argv[ARG_WORKING_DIRECTORY]);
726 g_free (new_argv);
727 g_free (helper_process);
729 goto cleanup_and_fail;
732 if (!utf8_charv_to_wcharv (envp, &wenvp, NULL, &conv_error))
734 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
735 _("Invalid string in environment: %s"),
736 conv_error->message);
737 g_error_free (conv_error);
738 g_strfreev (protected_argv);
739 g_free (new_argv[0]);
740 g_free (new_argv[ARG_WORKING_DIRECTORY]);
741 g_free (new_argv);
742 g_free (helper_process);
743 g_strfreev ((gchar **) wargv);
745 goto cleanup_and_fail;
748 whelper = g_utf8_to_utf16 (helper_process, -1, NULL, NULL, NULL);
749 g_free (helper_process);
751 if (wenvp != NULL)
752 rc = _wspawnvpe (P_NOWAIT, whelper, (const wchar_t **) wargv, (const wchar_t **) wenvp);
753 else
754 rc = _wspawnvp (P_NOWAIT, whelper, (const wchar_t **) wargv);
756 saved_errno = errno;
758 g_free (whelper);
759 g_strfreev ((gchar **) wargv);
760 g_strfreev ((gchar **) wenvp);
762 /* Close the other process's ends of the pipes in this process,
763 * otherwise the reader will never get EOF.
765 close_and_invalidate (&child_err_report_pipe[1]);
766 close_and_invalidate (&helper_sync_pipe[0]);
767 close_and_invalidate (&stdin_pipe[0]);
768 close_and_invalidate (&stdout_pipe[1]);
769 close_and_invalidate (&stderr_pipe[1]);
771 g_strfreev (protected_argv);
773 g_free (new_argv[0]);
774 g_free (new_argv[ARG_WORKING_DIRECTORY]);
775 g_free (new_argv);
777 /* Check if gspawn-win32-helper couldn't be run */
778 if (rc == -1 && saved_errno != 0)
780 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
781 _("Failed to execute helper program (%s)"),
782 g_strerror (saved_errno));
783 goto cleanup_and_fail;
786 if (exit_status != NULL)
788 /* Synchronous case. Pass helper's report pipe back to caller,
789 * which takes care of reading it after the grandchild has
790 * finished.
792 g_assert (err_report != NULL);
793 *err_report = child_err_report_pipe[0];
794 write (helper_sync_pipe[1], " ", 1);
795 close_and_invalidate (&helper_sync_pipe[1]);
797 else
799 /* Asynchronous case. We read the helper's report right away. */
800 if (!read_helper_report (child_err_report_pipe[0], helper_report, error))
801 goto cleanup_and_fail;
803 close_and_invalidate (&child_err_report_pipe[0]);
805 switch (helper_report[0])
807 case CHILD_NO_ERROR:
808 if (child_handle && do_return_handle)
810 /* rc is our HANDLE for gspawn-win32-helper. It has
811 * told us the HANDLE of its child. Duplicate that into
812 * a HANDLE valid in this process.
814 if (!DuplicateHandle ((HANDLE) rc, (HANDLE) helper_report[1],
815 GetCurrentProcess (), (LPHANDLE) child_handle,
816 0, TRUE, DUPLICATE_SAME_ACCESS))
818 char *emsg = g_win32_error_message (GetLastError ());
819 g_print("%s\n", emsg);
820 *child_handle = 0;
823 else if (child_handle)
824 *child_handle = 0;
825 write (helper_sync_pipe[1], " ", 1);
826 close_and_invalidate (&helper_sync_pipe[1]);
827 break;
829 default:
830 write (helper_sync_pipe[1], " ", 1);
831 close_and_invalidate (&helper_sync_pipe[1]);
832 set_child_error (helper_report, working_directory, error);
833 goto cleanup_and_fail;
837 /* Success against all odds! return the information */
839 if (standard_input)
840 *standard_input = stdin_pipe[1];
841 if (standard_output)
842 *standard_output = stdout_pipe[0];
843 if (standard_error)
844 *standard_error = stderr_pipe[0];
845 if (rc != -1)
846 CloseHandle ((HANDLE) rc);
848 return TRUE;
850 cleanup_and_fail:
852 if (rc != -1)
853 CloseHandle ((HANDLE) rc);
854 if (child_err_report_pipe[0] != -1)
855 close (child_err_report_pipe[0]);
856 if (child_err_report_pipe[1] != -1)
857 close (child_err_report_pipe[1]);
858 if (helper_sync_pipe[0] != -1)
859 close (helper_sync_pipe[0]);
860 if (helper_sync_pipe[1] != -1)
861 close (helper_sync_pipe[1]);
862 if (stdin_pipe[0] != -1)
863 close (stdin_pipe[0]);
864 if (stdin_pipe[1] != -1)
865 close (stdin_pipe[1]);
866 if (stdout_pipe[0] != -1)
867 close (stdout_pipe[0]);
868 if (stdout_pipe[1] != -1)
869 close (stdout_pipe[1]);
870 if (stderr_pipe[0] != -1)
871 close (stderr_pipe[0]);
872 if (stderr_pipe[1] != -1)
873 close (stderr_pipe[1]);
875 return FALSE;
878 gboolean
879 g_spawn_sync_utf8 (const gchar *working_directory,
880 gchar **argv,
881 gchar **envp,
882 GSpawnFlags flags,
883 GSpawnChildSetupFunc child_setup,
884 gpointer user_data,
885 gchar **standard_output,
886 gchar **standard_error,
887 gint *exit_status,
888 GError **error)
890 gint outpipe = -1;
891 gint errpipe = -1;
892 gint reportpipe = -1;
893 GIOChannel *outchannel = NULL;
894 GIOChannel *errchannel = NULL;
895 GPollFD outfd, errfd;
896 GPollFD fds[2];
897 gint nfds;
898 gint outindex = -1;
899 gint errindex = -1;
900 gint ret;
901 GString *outstr = NULL;
902 GString *errstr = NULL;
903 gboolean failed;
904 gint status;
906 g_return_val_if_fail (argv != NULL, FALSE);
907 g_return_val_if_fail (!(flags & G_SPAWN_DO_NOT_REAP_CHILD), FALSE);
908 g_return_val_if_fail (standard_output == NULL ||
909 !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
910 g_return_val_if_fail (standard_error == NULL ||
911 !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
913 /* Just to ensure segfaults if callers try to use
914 * these when an error is reported.
916 if (standard_output)
917 *standard_output = NULL;
919 if (standard_error)
920 *standard_error = NULL;
922 if (!do_spawn_with_pipes (&status,
923 FALSE,
924 working_directory,
925 argv,
926 envp,
927 flags,
928 child_setup,
929 NULL,
930 NULL,
931 standard_output ? &outpipe : NULL,
932 standard_error ? &errpipe : NULL,
933 &reportpipe,
934 error))
935 return FALSE;
937 /* Read data from child. */
939 failed = FALSE;
941 if (outpipe >= 0)
943 outstr = g_string_new (NULL);
944 outchannel = g_io_channel_win32_new_fd (outpipe);
945 g_io_channel_set_encoding (outchannel, NULL, NULL);
946 g_io_channel_set_buffered (outchannel, FALSE);
947 g_io_channel_win32_make_pollfd (outchannel,
948 G_IO_IN | G_IO_ERR | G_IO_HUP,
949 &outfd);
950 if (debug)
951 g_print ("outfd=%p\n", (HANDLE) outfd.fd);
954 if (errpipe >= 0)
956 errstr = g_string_new (NULL);
957 errchannel = g_io_channel_win32_new_fd (errpipe);
958 g_io_channel_set_encoding (errchannel, NULL, NULL);
959 g_io_channel_set_buffered (errchannel, FALSE);
960 g_io_channel_win32_make_pollfd (errchannel,
961 G_IO_IN | G_IO_ERR | G_IO_HUP,
962 &errfd);
963 if (debug)
964 g_print ("errfd=%p\n", (HANDLE) errfd.fd);
967 /* Read data until we get EOF on all pipes. */
968 while (!failed && (outpipe >= 0 || errpipe >= 0))
970 nfds = 0;
971 if (outpipe >= 0)
973 fds[nfds] = outfd;
974 outindex = nfds;
975 nfds++;
977 if (errpipe >= 0)
979 fds[nfds] = errfd;
980 errindex = nfds;
981 nfds++;
984 if (debug)
985 g_print ("g_spawn_sync: calling g_io_channel_win32_poll, nfds=%d\n",
986 nfds);
988 ret = g_io_channel_win32_poll (fds, nfds, -1);
990 if (ret < 0)
992 failed = TRUE;
994 g_set_error_literal (error, G_SPAWN_ERROR, G_SPAWN_ERROR_READ,
995 _("Unexpected error in g_io_channel_win32_poll() reading data from a child process"));
997 break;
1000 if (outpipe >= 0 && (fds[outindex].revents & G_IO_IN))
1002 switch (read_data (outstr, outchannel, error))
1004 case READ_FAILED:
1005 if (debug)
1006 g_print ("g_spawn_sync: outchannel: READ_FAILED\n");
1007 failed = TRUE;
1008 break;
1009 case READ_EOF:
1010 if (debug)
1011 g_print ("g_spawn_sync: outchannel: READ_EOF\n");
1012 g_io_channel_unref (outchannel);
1013 outchannel = NULL;
1014 close_and_invalidate (&outpipe);
1015 break;
1016 default:
1017 if (debug)
1018 g_print ("g_spawn_sync: outchannel: OK\n");
1019 break;
1022 if (failed)
1023 break;
1026 if (errpipe >= 0 && (fds[errindex].revents & G_IO_IN))
1028 switch (read_data (errstr, errchannel, error))
1030 case READ_FAILED:
1031 if (debug)
1032 g_print ("g_spawn_sync: errchannel: READ_FAILED\n");
1033 failed = TRUE;
1034 break;
1035 case READ_EOF:
1036 if (debug)
1037 g_print ("g_spawn_sync: errchannel: READ_EOF\n");
1038 g_io_channel_unref (errchannel);
1039 errchannel = NULL;
1040 close_and_invalidate (&errpipe);
1041 break;
1042 default:
1043 if (debug)
1044 g_print ("g_spawn_sync: errchannel: OK\n");
1045 break;
1048 if (failed)
1049 break;
1053 if (reportpipe == -1)
1055 /* No helper process, exit status of actual spawned process
1056 * already available.
1058 if (exit_status)
1059 *exit_status = status;
1061 else
1063 /* Helper process was involved. Read its report now after the
1064 * grandchild has finished.
1066 gintptr helper_report[2];
1068 if (!read_helper_report (reportpipe, helper_report, error))
1069 failed = TRUE;
1070 else
1072 switch (helper_report[0])
1074 case CHILD_NO_ERROR:
1075 if (exit_status)
1076 *exit_status = helper_report[1];
1077 break;
1078 default:
1079 set_child_error (helper_report, working_directory, error);
1080 failed = TRUE;
1081 break;
1084 close_and_invalidate (&reportpipe);
1088 /* These should only be open still if we had an error. */
1090 if (outchannel != NULL)
1091 g_io_channel_unref (outchannel);
1092 if (errchannel != NULL)
1093 g_io_channel_unref (errchannel);
1094 if (outpipe >= 0)
1095 close_and_invalidate (&outpipe);
1096 if (errpipe >= 0)
1097 close_and_invalidate (&errpipe);
1099 if (failed)
1101 if (outstr)
1102 g_string_free (outstr, TRUE);
1103 if (errstr)
1104 g_string_free (errstr, TRUE);
1106 return FALSE;
1108 else
1110 if (standard_output)
1111 *standard_output = g_string_free (outstr, FALSE);
1113 if (standard_error)
1114 *standard_error = g_string_free (errstr, FALSE);
1116 return TRUE;
1120 gboolean
1121 g_spawn_async_with_pipes_utf8 (const gchar *working_directory,
1122 gchar **argv,
1123 gchar **envp,
1124 GSpawnFlags flags,
1125 GSpawnChildSetupFunc child_setup,
1126 gpointer user_data,
1127 GPid *child_handle,
1128 gint *standard_input,
1129 gint *standard_output,
1130 gint *standard_error,
1131 GError **error)
1133 g_return_val_if_fail (argv != NULL, FALSE);
1134 g_return_val_if_fail (standard_output == NULL ||
1135 !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
1136 g_return_val_if_fail (standard_error == NULL ||
1137 !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
1138 /* can't inherit stdin if we have an input pipe. */
1139 g_return_val_if_fail (standard_input == NULL ||
1140 !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
1142 return do_spawn_with_pipes (NULL,
1143 (flags & G_SPAWN_DO_NOT_REAP_CHILD),
1144 working_directory,
1145 argv,
1146 envp,
1147 flags,
1148 child_setup,
1149 child_handle,
1150 standard_input,
1151 standard_output,
1152 standard_error,
1153 NULL,
1154 error);
1157 gboolean
1158 g_spawn_command_line_sync_utf8 (const gchar *command_line,
1159 gchar **standard_output,
1160 gchar **standard_error,
1161 gint *exit_status,
1162 GError **error)
1164 gboolean retval;
1165 gchar **argv = 0;
1167 g_return_val_if_fail (command_line != NULL, FALSE);
1169 if (!g_shell_parse_argv (command_line,
1170 NULL, &argv,
1171 error))
1172 return FALSE;
1174 retval = g_spawn_sync_utf8 (NULL,
1175 argv,
1176 NULL,
1177 G_SPAWN_SEARCH_PATH,
1178 NULL,
1179 NULL,
1180 standard_output,
1181 standard_error,
1182 exit_status,
1183 error);
1184 g_strfreev (argv);
1186 return retval;
1189 gboolean
1190 g_spawn_command_line_async_utf8 (const gchar *command_line,
1191 GError **error)
1193 gboolean retval;
1194 gchar **argv = 0;
1196 g_return_val_if_fail (command_line != NULL, FALSE);
1198 if (!g_shell_parse_argv (command_line,
1199 NULL, &argv,
1200 error))
1201 return FALSE;
1203 retval = g_spawn_async_utf8 (NULL,
1204 argv,
1205 NULL,
1206 G_SPAWN_SEARCH_PATH,
1207 NULL,
1208 NULL,
1209 NULL,
1210 error);
1211 g_strfreev (argv);
1213 return retval;
1216 void
1217 g_spawn_close_pid (GPid pid)
1219 CloseHandle (pid);
1222 gboolean
1223 g_spawn_check_exit_status (gint exit_status,
1224 GError **error)
1226 gboolean ret = FALSE;
1228 if (exit_status != 0)
1230 g_set_error (error, G_SPAWN_EXIT_ERROR, exit_status,
1231 _("Child process exited with code %ld"),
1232 (long) exit_status);
1233 goto out;
1236 ret = TRUE;
1237 out:
1238 return ret;
1241 #if !defined (_WIN64)
1243 /* Binary compatibility versions that take system codepage pathnames,
1244 * argument vectors and environments. These get used only by code
1245 * built against 2.8.1 or earlier. Code built against 2.8.2 or later
1246 * will use the _utf8 versions above (see the #defines in gspawn.h).
1249 #undef g_spawn_async
1250 #undef g_spawn_async_with_pipes
1251 #undef g_spawn_sync
1252 #undef g_spawn_command_line_sync
1253 #undef g_spawn_command_line_async
1255 static gboolean
1256 setup_utf8_copies (const gchar *working_directory,
1257 gchar **utf8_working_directory,
1258 gchar **argv,
1259 gchar ***utf8_argv,
1260 gchar **envp,
1261 gchar ***utf8_envp,
1262 GError **error)
1264 gint i, argc, envc;
1266 if (working_directory == NULL)
1267 *utf8_working_directory = NULL;
1268 else
1270 GError *conv_error = NULL;
1272 *utf8_working_directory = g_locale_to_utf8 (working_directory, -1, NULL, NULL, &conv_error);
1273 if (*utf8_working_directory == NULL)
1275 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR,
1276 _("Invalid working directory: %s"),
1277 conv_error->message);
1278 g_error_free (conv_error);
1279 return FALSE;
1283 argc = 0;
1284 while (argv[argc])
1285 ++argc;
1286 *utf8_argv = g_new (gchar *, argc + 1);
1287 for (i = 0; i < argc; i++)
1289 GError *conv_error = NULL;
1291 (*utf8_argv)[i] = g_locale_to_utf8 (argv[i], -1, NULL, NULL, &conv_error);
1292 if ((*utf8_argv)[i] == NULL)
1294 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
1295 _("Invalid string in argument vector at %d: %s"),
1296 i, conv_error->message);
1297 g_error_free (conv_error);
1299 g_strfreev (*utf8_argv);
1300 *utf8_argv = NULL;
1302 g_free (*utf8_working_directory);
1303 *utf8_working_directory = NULL;
1305 return FALSE;
1308 (*utf8_argv)[argc] = NULL;
1310 if (envp == NULL)
1312 *utf8_envp = NULL;
1314 else
1316 envc = 0;
1317 while (envp[envc])
1318 ++envc;
1319 *utf8_envp = g_new (gchar *, envc + 1);
1320 for (i = 0; i < envc; i++)
1322 GError *conv_error = NULL;
1324 (*utf8_envp)[i] = g_locale_to_utf8 (envp[i], -1, NULL, NULL, &conv_error);
1325 if ((*utf8_envp)[i] == NULL)
1327 g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
1328 _("Invalid string in environment: %s"),
1329 conv_error->message);
1330 g_error_free (conv_error);
1332 g_strfreev (*utf8_envp);
1333 *utf8_envp = NULL;
1335 g_strfreev (*utf8_argv);
1336 *utf8_argv = NULL;
1338 g_free (*utf8_working_directory);
1339 *utf8_working_directory = NULL;
1341 return FALSE;
1344 (*utf8_envp)[envc] = NULL;
1346 return TRUE;
1349 static void
1350 free_utf8_copies (gchar *utf8_working_directory,
1351 gchar **utf8_argv,
1352 gchar **utf8_envp)
1354 g_free (utf8_working_directory);
1355 g_strfreev (utf8_argv);
1356 g_strfreev (utf8_envp);
1359 gboolean
1360 g_spawn_async_with_pipes (const gchar *working_directory,
1361 gchar **argv,
1362 gchar **envp,
1363 GSpawnFlags flags,
1364 GSpawnChildSetupFunc child_setup,
1365 gpointer user_data,
1366 GPid *child_handle,
1367 gint *standard_input,
1368 gint *standard_output,
1369 gint *standard_error,
1370 GError **error)
1372 gchar *utf8_working_directory;
1373 gchar **utf8_argv;
1374 gchar **utf8_envp;
1375 gboolean retval;
1377 if (!setup_utf8_copies (working_directory, &utf8_working_directory,
1378 argv, &utf8_argv,
1379 envp, &utf8_envp,
1380 error))
1381 return FALSE;
1383 retval = g_spawn_async_with_pipes_utf8 (utf8_working_directory,
1384 utf8_argv, utf8_envp,
1385 flags, child_setup, user_data,
1386 child_handle,
1387 standard_input, standard_output, standard_error,
1388 error);
1390 free_utf8_copies (utf8_working_directory, utf8_argv, utf8_envp);
1392 return retval;
1395 gboolean
1396 g_spawn_async (const gchar *working_directory,
1397 gchar **argv,
1398 gchar **envp,
1399 GSpawnFlags flags,
1400 GSpawnChildSetupFunc child_setup,
1401 gpointer user_data,
1402 GPid *child_handle,
1403 GError **error)
1405 return g_spawn_async_with_pipes (working_directory,
1406 argv, envp,
1407 flags,
1408 child_setup,
1409 user_data,
1410 child_handle,
1411 NULL, NULL, NULL,
1412 error);
1415 gboolean
1416 g_spawn_sync (const gchar *working_directory,
1417 gchar **argv,
1418 gchar **envp,
1419 GSpawnFlags flags,
1420 GSpawnChildSetupFunc child_setup,
1421 gpointer user_data,
1422 gchar **standard_output,
1423 gchar **standard_error,
1424 gint *exit_status,
1425 GError **error)
1427 gchar *utf8_working_directory;
1428 gchar **utf8_argv;
1429 gchar **utf8_envp;
1430 gboolean retval;
1432 if (!setup_utf8_copies (working_directory, &utf8_working_directory,
1433 argv, &utf8_argv,
1434 envp, &utf8_envp,
1435 error))
1436 return FALSE;
1438 retval = g_spawn_sync_utf8 (utf8_working_directory,
1439 utf8_argv, utf8_envp,
1440 flags, child_setup, user_data,
1441 standard_output, standard_error, exit_status,
1442 error);
1444 free_utf8_copies (utf8_working_directory, utf8_argv, utf8_envp);
1446 return retval;
1449 gboolean
1450 g_spawn_command_line_sync (const gchar *command_line,
1451 gchar **standard_output,
1452 gchar **standard_error,
1453 gint *exit_status,
1454 GError **error)
1456 gboolean retval;
1457 gchar **argv = 0;
1459 g_return_val_if_fail (command_line != NULL, FALSE);
1461 if (!g_shell_parse_argv (command_line,
1462 NULL, &argv,
1463 error))
1464 return FALSE;
1466 retval = g_spawn_sync (NULL,
1467 argv,
1468 NULL,
1469 G_SPAWN_SEARCH_PATH,
1470 NULL,
1471 NULL,
1472 standard_output,
1473 standard_error,
1474 exit_status,
1475 error);
1476 g_strfreev (argv);
1478 return retval;
1481 gboolean
1482 g_spawn_command_line_async (const gchar *command_line,
1483 GError **error)
1485 gboolean retval;
1486 gchar **argv = 0;
1488 g_return_val_if_fail (command_line != NULL, FALSE);
1490 if (!g_shell_parse_argv (command_line,
1491 NULL, &argv,
1492 error))
1493 return FALSE;
1495 retval = g_spawn_async (NULL,
1496 argv,
1497 NULL,
1498 G_SPAWN_SEARCH_PATH,
1499 NULL,
1500 NULL,
1501 NULL,
1502 error);
1503 g_strfreev (argv);
1505 return retval;
1508 #endif /* !_WIN64 */
1510 #endif /* !GSPAWN_HELPER */