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 */
57 #ifdef G_SPAWN_WIN32_DEBUG
59 #define SETUP_DEBUG() /* empty */
62 static int debug = -1;
63 #define SETUP_DEBUG() \
68 if (getenv ("G_SPAWN_WIN32_DEBUG") != NULL) \
85 ARG_CHILD_ERR_REPORT = 1,
89 ARG_WORKING_DIRECTORY,
90 ARG_CLOSE_DESCRIPTORS,
94 ARG_COUNT = ARG_PROGRAM
99 static gboolean make_pipe (gint p[2],
101 static gboolean do_spawn_with_pipes (gboolean dont_wait,
102 const gchar *working_directory,
105 gboolean close_descriptors,
106 gboolean search_path,
107 gboolean stdout_to_null,
108 gboolean stderr_to_null,
109 gboolean child_inherits_stdin,
110 GSpawnChildSetupFunc child_setup,
112 gint *standard_input,
113 gint *standard_output,
114 gint *standard_error,
119 g_spawn_error_quark (void)
121 static GQuark quark = 0;
123 quark = g_quark_from_static_string ("g-exec-error-quark");
128 g_spawn_async (const gchar *working_directory,
132 GSpawnChildSetupFunc child_setup,
137 g_return_val_if_fail (argv != NULL, FALSE);
139 return g_spawn_async_with_pipes (working_directory,
149 /* Avoids a danger in threaded situations (calling close()
150 * on a file descriptor twice, and another thread has
151 * re-opened it since the first close)
154 close_and_invalidate (gint *fd)
171 READ_FAILED = 0, /* FALSE */
177 read_data (GString *str,
178 GIOChannel *iochannel,
187 giostatus = g_io_channel_read_chars (iochannel, buf, sizeof (buf), &bytes, NULL);
193 g_string_append_len (str, buf, bytes);
196 else if (giostatus == G_IO_STATUS_AGAIN)
198 else if (giostatus == G_IO_STATUS_ERROR)
203 _("Failed to read data from child process"));
212 g_spawn_sync (const gchar *working_directory,
216 GSpawnChildSetupFunc child_setup,
218 gchar **standard_output,
219 gchar **standard_error,
225 GIOChannel *outchannel = NULL;
226 GIOChannel *errchannel = NULL;
227 GPollFD outfd, errfd;
233 GString *outstr = NULL;
234 GString *errstr = NULL;
238 g_return_val_if_fail (argv != NULL, FALSE);
239 g_return_val_if_fail (!(flags & G_SPAWN_DO_NOT_REAP_CHILD), FALSE);
240 g_return_val_if_fail (standard_output == NULL ||
241 !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
242 g_return_val_if_fail (standard_error == NULL ||
243 !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
245 /* Just to ensure segfaults if callers try to use
246 * these when an error is reported.
249 *standard_output = NULL;
252 *standard_error = NULL;
254 if (!do_spawn_with_pipes (FALSE,
258 !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
259 (flags & G_SPAWN_SEARCH_PATH) != 0,
260 (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
261 (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
262 (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
266 standard_output ? &outpipe : NULL,
267 standard_error ? &errpipe : NULL,
272 /* Read data from child. */
278 outstr = g_string_new ("");
279 outchannel = g_io_channel_win32_new_fd (outpipe);
280 g_io_channel_set_encoding (outchannel, NULL, NULL);
281 g_io_channel_win32_make_pollfd (outchannel,
282 G_IO_IN | G_IO_ERR | G_IO_HUP,
288 errstr = g_string_new ("");
289 errchannel = g_io_channel_win32_new_fd (errpipe);
290 g_io_channel_set_encoding (errchannel, NULL, NULL);
291 g_io_channel_win32_make_pollfd (errchannel,
292 G_IO_IN | G_IO_ERR | G_IO_HUP,
296 /* Read data until we get EOF on both pipes. */
316 g_print ("%s:g_spawn_sync: calling g_io_channel_win32_poll, nfds=%d\n",
319 ret = g_io_channel_win32_poll (fds, nfds, -1);
328 _("Unexpected error in g_io_channel_win32_poll() reading data from a child process"));
333 if (outpipe >= 0 && (fds[outindex].revents & G_IO_IN))
335 switch (read_data (outstr, outchannel, error))
339 g_print ("g_spawn_sync: outchannel: READ_FAILED\n");
344 g_print ("g_spawn_sync: outchannel: READ_EOF\n");
345 g_io_channel_unref (outchannel);
347 close_and_invalidate (&outpipe);
351 g_print ("g_spawn_sync: outchannel: OK\n");
359 if (errpipe >= 0 && (fds[errindex].revents & G_IO_IN))
361 switch (read_data (errstr, errchannel, error))
365 g_print ("g_spawn_sync: errchannel: READ_FAILED\n");
370 g_print ("g_spawn_sync: errchannel: READ_EOF\n");
371 g_io_channel_unref (errchannel);
373 close_and_invalidate (&errpipe);
377 g_print ("g_spawn_sync: errchannel: OK\n");
386 /* These should only be open still if we had an error. */
388 if (outchannel != NULL)
389 g_io_channel_unref (outchannel);
390 if (errchannel != NULL)
391 g_io_channel_unref (errchannel);
393 close_and_invalidate (&outpipe);
395 close_and_invalidate (&errpipe);
400 g_string_free (outstr, TRUE);
402 g_string_free (errstr, TRUE);
409 *exit_status = status;
412 *standard_output = g_string_free (outstr, FALSE);
415 *standard_error = g_string_free (errstr, FALSE);
422 g_spawn_async_with_pipes (const gchar *working_directory,
426 GSpawnChildSetupFunc child_setup,
429 gint *standard_input,
430 gint *standard_output,
431 gint *standard_error,
434 g_return_val_if_fail (argv != NULL, FALSE);
435 g_return_val_if_fail (standard_output == NULL ||
436 !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
437 g_return_val_if_fail (standard_error == NULL ||
438 !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
439 /* can't inherit stdin if we have an input pipe. */
440 g_return_val_if_fail (standard_input == NULL ||
441 !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
443 return do_spawn_with_pipes (TRUE,
447 !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
448 (flags & G_SPAWN_SEARCH_PATH) != 0,
449 (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
450 (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
451 (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
462 g_spawn_command_line_sync (const gchar *command_line,
463 gchar **standard_output,
464 gchar **standard_error,
471 g_return_val_if_fail (command_line != NULL, FALSE);
473 if (!g_shell_parse_argv (command_line,
478 retval = g_spawn_sync (NULL,
494 g_spawn_command_line_async (const gchar *command_line,
500 g_return_val_if_fail (command_line != NULL, FALSE);
502 if (!g_shell_parse_argv (command_line,
507 retval = g_spawn_async (NULL,
521 do_spawn (gboolean dont_wait,
522 gint child_err_report_fd,
526 const gchar *working_directory,
529 gboolean close_descriptors,
530 gboolean search_path,
531 gboolean stdout_to_null,
532 gboolean stderr_to_null,
533 gboolean child_inherits_stdin,
534 GSpawnChildSetupFunc child_setup,
538 gchar args[ARG_COUNT][10];
547 new_argv = g_new (gchar *, argc + 1 + ARG_COUNT);
549 new_argv[0] = "gspawn-win32-helper";
550 sprintf (args[ARG_CHILD_ERR_REPORT], "%d", child_err_report_fd);
551 new_argv[ARG_CHILD_ERR_REPORT] = args[ARG_CHILD_ERR_REPORT];
555 sprintf (args[ARG_STDIN], "%d", stdin_fd);
556 new_argv[ARG_STDIN] = args[ARG_STDIN];
558 else if (child_inherits_stdin)
560 /* Let stdin be alone */
561 new_argv[ARG_STDIN] = "-";
565 /* Keep process from blocking on a read of stdin */
566 new_argv[ARG_STDIN] = "z";
571 sprintf (args[ARG_STDOUT], "%d", stdout_fd);
572 new_argv[ARG_STDOUT] = args[ARG_STDOUT];
574 else if (stdout_to_null)
576 new_argv[ARG_STDOUT] = "z";
580 new_argv[ARG_STDOUT] = "-";
585 sprintf (args[ARG_STDERR], "%d", stderr_fd);
586 new_argv[ARG_STDERR] = args[ARG_STDERR];
588 else if (stderr_to_null)
590 new_argv[ARG_STDERR] = "z";
594 new_argv[ARG_STDERR] = "-";
597 if (working_directory && *working_directory)
598 new_argv[ARG_WORKING_DIRECTORY] = working_directory;
600 new_argv[ARG_WORKING_DIRECTORY] = "-";
602 if (close_descriptors)
603 new_argv[ARG_CLOSE_DESCRIPTORS] = "y";
605 new_argv[ARG_CLOSE_DESCRIPTORS] = "-";
608 new_argv[ARG_USE_PATH] = "y";
610 new_argv[ARG_USE_PATH] = "-";
613 new_argv[ARG_WAIT] = "-";
615 new_argv[ARG_WAIT] = "w";
617 for (i = 0; i <= argc; i++)
618 new_argv[ARG_PROGRAM + i] = argv[i];
620 /* Call user function just before we execute the helper program,
621 * which executes the program. Dunno what's the usefulness of this.
622 * A child setup function used on Unix probably isn't of much use
623 * as such on Win32, anyhow
627 (* child_setup) (user_data);
632 g_print ("calling gspawn-win32-helper with argv:\n");
633 for (i = 0; i < argc + 1 + ARG_COUNT; i++)
634 g_print ("argv[%d]: %s\n", i, (new_argv[i] ? new_argv[i] : "NULL"));
638 /* Let's hope envp hasn't mucked with PATH so that
639 * gspawn-win32-helper.exe isn't found.
641 spawnvpe (P_NOWAIT, "gspawn-win32-helper", new_argv, envp);
643 spawnvp (P_NOWAIT, "gspawn-win32-helper", new_argv);
645 /* FIXME: What if gspawn-win32-helper.exe isn't found? */
647 /* Close the child_err_report_fd and the other process's ends of the
648 * pipes in this process, otherwise the reader will never get
651 close (child_err_report_fd);
673 while (bytes < sizeof(gint)*n_ints_in_buf)
678 g_print ("%s:read_ints: trying to read %d bytes from pipe...\n",
680 sizeof(gint)*n_ints_in_buf - bytes);
682 chunk = read (fd, ((gchar*)buf) + bytes,
683 sizeof(gint)*n_ints_in_buf - bytes);
686 g_print ("... got %d bytes\n", chunk);
690 /* Some weird shit happened, bail out */
694 G_SPAWN_ERROR_FAILED,
695 _("Failed to read from child pipe (%s)"),
706 *n_ints_read = bytes/sizeof(gint);
712 do_spawn_with_pipes (gboolean dont_wait,
713 const gchar *working_directory,
716 gboolean close_descriptors,
717 gboolean search_path,
718 gboolean stdout_to_null,
719 gboolean stderr_to_null,
720 gboolean child_inherits_stdin,
721 GSpawnChildSetupFunc child_setup,
723 gint *standard_input,
724 gint *standard_output,
725 gint *standard_error,
729 gint stdin_pipe[2] = { -1, -1 };
730 gint stdout_pipe[2] = { -1, -1 };
731 gint stderr_pipe[2] = { -1, -1 };
732 gint child_err_report_pipe[2] = { -1, -1 };
737 if (!make_pipe (child_err_report_pipe, error))
740 if (standard_input && !make_pipe (stdin_pipe, error))
741 goto cleanup_and_fail;
743 if (standard_output && !make_pipe (stdout_pipe, error))
744 goto cleanup_and_fail;
746 if (standard_error && !make_pipe (stderr_pipe, error))
747 goto cleanup_and_fail;
749 status = do_spawn (dont_wait,
750 child_err_report_pipe[1],
761 child_inherits_stdin,
765 if (!read_ints (child_err_report_pipe[0],
768 goto cleanup_and_fail;
772 /* Error from the child. */
779 case CHILD_CHDIR_FAILED:
783 _("Failed to change to directory '%s' (%s)"),
785 g_strerror (buf[1]));
786 goto cleanup_and_fail;
788 case CHILD_SPAWN_FAILED:
791 G_SPAWN_ERROR_FAILED,
792 _("Failed to execute child process (%s)"),
793 g_strerror (buf[1]));
794 goto cleanup_and_fail;
798 /* Success against all odds! return the information */
801 *standard_input = stdin_pipe[1];
803 *standard_output = stdout_pipe[0];
805 *standard_error = stderr_pipe[0];
807 *exit_status = status;
812 close_and_invalidate (&child_err_report_pipe[0]);
813 close_and_invalidate (&child_err_report_pipe[1]);
814 close_and_invalidate (&stdin_pipe[0]);
815 close_and_invalidate (&stdin_pipe[1]);
816 close_and_invalidate (&stdout_pipe[0]);
817 close_and_invalidate (&stdout_pipe[1]);
818 close_and_invalidate (&stderr_pipe[0]);
819 close_and_invalidate (&stderr_pipe[1]);
825 make_pipe (gint p[2],
832 G_SPAWN_ERROR_FAILED,
833 _("Failed to create pipe for communicating with child process (%s)"),
841 #endif /* !GSPAWN_HELPER */