1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright © 2012 Red Hat, Inc.
4 * Copyright © 2012-2013 Canonical Limited
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 * See the included COPYING file for more information.
15 * Authors: Colin Walters <walters@verbum.org>
16 * Ryan Lortie <desrt@desrt.ca>
20 * SECTION:gsubprocesslauncher
21 * @title: GSubprocess Launcher
22 * @short_description: Environment options for launching a child process
25 * This class contains a set of options for launching child processes,
26 * such as where its standard input and output will be directed, the
27 * argument list, the environment, and more.
29 * While the #GSubprocess class has high level functions covering
30 * popular cases, use of this class allows access to more advanced
31 * options. It can also be used to launch multiple subprocesses with
32 * a similar configuration.
37 #define ALL_STDIN_FLAGS (G_SUBPROCESS_FLAGS_STDIN_PIPE | \
38 G_SUBPROCESS_FLAGS_STDIN_INHERIT)
39 #define ALL_STDOUT_FLAGS (G_SUBPROCESS_FLAGS_STDOUT_PIPE | \
40 G_SUBPROCESS_FLAGS_STDOUT_SILENCE)
41 #define ALL_STDERR_FLAGS (G_SUBPROCESS_FLAGS_STDERR_PIPE | \
42 G_SUBPROCESS_FLAGS_STDERR_SILENCE | \
43 G_SUBPROCESS_FLAGS_STDERR_MERGE)
47 #include "gsubprocesslauncher-private.h"
48 #include "gioenumtypes.h"
49 #include "gsubprocess.h"
50 #include "ginitable.h"
58 typedef GObjectClass GSubprocessLauncherClass;
60 G_DEFINE_TYPE (GSubprocessLauncher, g_subprocess_launcher, G_TYPE_OBJECT)
63 verify_disposition (const gchar *stream_name,
64 GSubprocessFlags filtered_flags,
66 const gchar *filename)
72 else if (((filtered_flags - 1) & filtered_flags) == 0)
75 n_bits = 2; /* ...or more */
77 if (n_bits + (fd >= 0) + (filename != NULL) > 1)
81 err = g_string_new (NULL);
87 class = g_type_class_peek (G_TYPE_SUBPROCESS_FLAGS);
89 for (i = 0; i < class->n_values; i++)
91 const GFlagsValue *value = &class->values[i];
93 if (filtered_flags & value->value)
94 g_string_append_printf (err, " %s", value->value_name);
97 g_type_class_unref (class);
101 g_string_append_printf (err, " g_subprocess_launcher_take_%s_fd()", stream_name);
104 g_string_append_printf (err, " g_subprocess_launcher_set_%s_file_path()", stream_name);
106 g_critical ("You may specify at most one disposition for the %s stream, but you specified:%s.",
107 stream_name, err->str);
108 g_string_free (err, TRUE);
117 verify_flags (GSubprocessFlags flags)
119 return verify_disposition ("stdin", flags & ALL_STDIN_FLAGS, -1, NULL) &&
120 verify_disposition ("stdout", flags & ALL_STDOUT_FLAGS, -1, NULL) &&
121 verify_disposition ("stderr", flags & ALL_STDERR_FLAGS, -1, NULL);
125 g_subprocess_launcher_set_property (GObject *object, guint prop_id,
126 const GValue *value, GParamSpec *pspec)
128 GSubprocessLauncher *launcher = G_SUBPROCESS_LAUNCHER (object);
130 g_assert (prop_id == 1);
132 if (verify_flags (g_value_get_flags (value)))
133 launcher->flags = g_value_get_flags (value);
137 g_subprocess_launcher_dispose (GObject *object)
139 GSubprocessLauncher *self = G_SUBPROCESS_LAUNCHER (object);
142 g_clear_pointer (&self->stdin_path, g_free);
143 g_clear_pointer (&self->stdout_path, g_free);
144 g_clear_pointer (&self->stderr_path, g_free);
146 g_subprocess_launcher_close (self);
148 if (self->child_setup_destroy_notify)
149 (* self->child_setup_destroy_notify) (self->child_setup_user_data);
150 self->child_setup_destroy_notify = NULL;
151 self->child_setup_user_data = NULL;
154 g_clear_pointer (&self->envp, g_strfreev);
155 g_clear_pointer (&self->cwd, g_free);
157 G_OBJECT_CLASS (g_subprocess_launcher_parent_class)->dispose (object);
161 g_subprocess_launcher_init (GSubprocessLauncher *self)
163 self->envp = g_get_environ ();
167 self->stdout_fd = -1;
168 self->stderr_fd = -1;
169 self->source_fds = g_array_new (FALSE, 0, sizeof (int));
170 self->target_fds = g_array_new (FALSE, 0, sizeof (int));
175 g_subprocess_launcher_class_init (GSubprocessLauncherClass *class)
177 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
179 gobject_class->set_property = g_subprocess_launcher_set_property;
180 gobject_class->dispose = g_subprocess_launcher_dispose;
182 g_object_class_install_property (gobject_class, 1,
183 g_param_spec_flags ("flags", "Flags", "GSubprocessFlags for launched processes",
184 G_TYPE_SUBPROCESS_FLAGS, 0, G_PARAM_WRITABLE |
185 G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY));
189 * g_subprocess_launcher_new:
190 * @flags: #GSubprocessFlags
192 * Creates a new #GSubprocessLauncher.
194 * The launcher is created with the default options. A copy of the
195 * environment of the calling process is made at the time of this call
196 * and will be used as the environment that the process is launched in.
200 GSubprocessLauncher *
201 g_subprocess_launcher_new (GSubprocessFlags flags)
203 if (!verify_flags (flags))
206 return g_object_new (G_TYPE_SUBPROCESS_LAUNCHER,
212 * g_subprocess_launcher_set_environ:
213 * @self: a #GSubprocessLauncher
214 * @env: (array zero-terminated=1) (element-type filename) (transfer none):
215 * the replacement environment
217 * Replace the entire environment of processes launched from this
218 * launcher with the given 'environ' variable.
220 * Typically you will build this variable by using g_listenv() to copy
221 * the process 'environ' and using the functions g_environ_setenv(),
222 * g_environ_unsetenv(), etc.
224 * As an alternative, you can use g_subprocess_launcher_setenv(),
225 * g_subprocess_launcher_unsetenv(), etc.
227 * Pass an empty array to set an empty environment. Pass %NULL to inherit the
228 * parent process’ environment. As of GLib 2.54, the parent process’ environment
229 * will be copied when g_subprocess_launcher_set_environ() is called.
230 * Previously, it was copied when the subprocess was executed. This means the
231 * copied environment may now be modified (using g_subprocess_launcher_setenv(),
232 * etc.) before launching the subprocess.
234 * On UNIX, all strings in this array can be arbitrary byte strings.
235 * On Windows, they should be in UTF-8.
240 g_subprocess_launcher_set_environ (GSubprocessLauncher *self,
243 g_strfreev (self->envp);
244 self->envp = g_strdupv (env);
246 if (self->envp == NULL)
247 self->envp = g_get_environ ();
251 * g_subprocess_launcher_setenv:
252 * @self: a #GSubprocessLauncher
253 * @variable: (type filename): the environment variable to set,
254 * must not contain '='
255 * @value: (type filename): the new value for the variable
256 * @overwrite: whether to change the variable if it already exists
258 * Sets the environment variable @variable in the environment of
259 * processes launched from this launcher.
261 * On UNIX, both the variable's name and value can be arbitrary byte
262 * strings, except that the variable's name cannot contain '='.
263 * On Windows, they should be in UTF-8.
268 g_subprocess_launcher_setenv (GSubprocessLauncher *self,
269 const gchar *variable,
273 self->envp = g_environ_setenv (self->envp, variable, value, overwrite);
277 * g_subprocess_launcher_unsetenv:
278 * @self: a #GSubprocessLauncher
279 * @variable: (type filename): the environment variable to unset,
280 * must not contain '='
282 * Removes the environment variable @variable from the environment of
283 * processes launched from this launcher.
285 * On UNIX, the variable's name can be an arbitrary byte string not
286 * containing '='. On Windows, it should be in UTF-8.
291 g_subprocess_launcher_unsetenv (GSubprocessLauncher *self,
292 const gchar *variable)
294 self->envp = g_environ_unsetenv (self->envp, variable);
298 * g_subprocess_launcher_getenv:
299 * @self: a #GSubprocessLauncher
300 * @variable: (type filename): the environment variable to get
302 * Returns the value of the environment variable @variable in the
303 * environment of processes launched from this launcher.
305 * On UNIX, the returned string can be an arbitrary byte string.
306 * On Windows, it will be UTF-8.
308 * Returns: (nullable) (type filename): the value of the environment variable,
314 g_subprocess_launcher_getenv (GSubprocessLauncher *self,
315 const gchar *variable)
317 return g_environ_getenv (self->envp, variable);
321 * g_subprocess_launcher_set_cwd:
322 * @self: a #GSubprocessLauncher
323 * @cwd: (type filename): the cwd for launched processes
325 * Sets the current working directory that processes will be launched
328 * By default processes are launched with the current working directory
329 * of the launching process at the time of launch.
334 g_subprocess_launcher_set_cwd (GSubprocessLauncher *self,
338 self->cwd = g_strdup (cwd);
342 * g_subprocess_launcher_set_flags:
343 * @self: a #GSubprocessLauncher
344 * @flags: #GSubprocessFlags
346 * Sets the flags on the launcher.
348 * The default flags are %G_SUBPROCESS_FLAGS_NONE.
350 * You may not set flags that specify conflicting options for how to
351 * handle a particular stdio stream (eg: specifying both
352 * %G_SUBPROCESS_FLAGS_STDIN_PIPE and
353 * %G_SUBPROCESS_FLAGS_STDIN_INHERIT).
355 * You may also not set a flag that conflicts with a previous call to a
356 * function like g_subprocess_launcher_set_stdin_file_path() or
357 * g_subprocess_launcher_take_stdout_fd().
362 g_subprocess_launcher_set_flags (GSubprocessLauncher *self,
363 GSubprocessFlags flags)
365 const gchar *stdin_path = NULL, *stdout_path = NULL, *stderr_path = NULL;
366 gint stdin_fd = -1, stdout_fd = -1, stderr_fd = -1;
369 stdin_fd = self->stdin_fd;
370 stdout_fd = self->stdout_fd;
371 stderr_fd = self->stderr_fd;
372 stdin_path = self->stdin_path;
373 stdout_path = self->stdout_path;
374 stderr_path = self->stderr_path;
377 if (verify_disposition ("stdin", flags & ALL_STDIN_FLAGS, stdin_fd, stdin_path) &&
378 verify_disposition ("stdout", flags & ALL_STDOUT_FLAGS, stdout_fd, stdout_path) &&
379 verify_disposition ("stderr", flags & ALL_STDERR_FLAGS, stderr_fd, stderr_path))
385 assign_fd (gint *fd_ptr, gint fd)
397 flags = fcntl (fd, F_GETFD);
398 if (~flags & FD_CLOEXEC)
399 fcntl (fd, F_SETFD, flags | FD_CLOEXEC);
404 * g_subprocess_launcher_set_stdin_file_path:
405 * @self: a #GSubprocessLauncher
406 * @path: (type filename) (nullable: a filename or %NULL
408 * Sets the file path to use as the stdin for spawned processes.
410 * If @path is %NULL then any previously given path is unset.
412 * The file must exist or spawning the process will fail.
414 * You may not set a stdin file path if a stdin fd is already set or if
415 * the launcher flags contain any flags directing stdin elsewhere.
417 * This feature is only available on UNIX.
422 g_subprocess_launcher_set_stdin_file_path (GSubprocessLauncher *self,
425 if (verify_disposition ("stdin", self->flags & ALL_STDIN_FLAGS, self->stdin_fd, path))
427 g_free (self->stdin_path);
428 self->stdin_path = g_strdup (path);
433 * g_subprocess_launcher_take_stdin_fd:
434 * @self: a #GSubprocessLauncher
435 * @fd: a file descriptor, or -1
437 * Sets the file descriptor to use as the stdin for spawned processes.
439 * If @fd is -1 then any previously given fd is unset.
441 * Note that if your intention is to have the stdin of the calling
442 * process inherited by the child then %G_SUBPROCESS_FLAGS_STDIN_INHERIT
443 * is a better way to go about doing that.
445 * The passed @fd is noted but will not be touched in the current
446 * process. It is therefore necessary that it be kept open by the
447 * caller until the subprocess is spawned. The file descriptor will
448 * also not be explicitly closed on the child side, so it must be marked
449 * O_CLOEXEC if that's what you want.
451 * You may not set a stdin fd if a stdin file path is already set or if
452 * the launcher flags contain any flags directing stdin elsewhere.
454 * This feature is only available on UNIX.
459 g_subprocess_launcher_take_stdin_fd (GSubprocessLauncher *self,
462 if (verify_disposition ("stdin", self->flags & ALL_STDIN_FLAGS, fd, self->stdin_path))
463 assign_fd (&self->stdin_fd, fd);
467 * g_subprocess_launcher_set_stdout_file_path:
468 * @self: a #GSubprocessLauncher
469 * @path: (type filename) (nullable): a filename or %NULL
471 * Sets the file path to use as the stdout for spawned processes.
473 * If @path is %NULL then any previously given path is unset.
475 * The file will be created or truncated when the process is spawned, as
476 * would be the case if using '>' at the shell.
478 * You may not set a stdout file path if a stdout fd is already set or
479 * if the launcher flags contain any flags directing stdout elsewhere.
481 * This feature is only available on UNIX.
486 g_subprocess_launcher_set_stdout_file_path (GSubprocessLauncher *self,
489 if (verify_disposition ("stdout", self->flags & ALL_STDOUT_FLAGS, self->stdout_fd, path))
491 g_free (self->stdout_path);
492 self->stdout_path = g_strdup (path);
497 * g_subprocess_launcher_take_stdout_fd:
498 * @self: a #GSubprocessLauncher
499 * @fd: a file descriptor, or -1
501 * Sets the file descriptor to use as the stdout for spawned processes.
503 * If @fd is -1 then any previously given fd is unset.
505 * Note that the default behaviour is to pass stdout through to the
506 * stdout of the parent process.
508 * The passed @fd is noted but will not be touched in the current
509 * process. It is therefore necessary that it be kept open by the
510 * caller until the subprocess is spawned. The file descriptor will
511 * also not be explicitly closed on the child side, so it must be marked
512 * O_CLOEXEC if that's what you want.
514 * You may not set a stdout fd if a stdout file path is already set or
515 * if the launcher flags contain any flags directing stdout elsewhere.
517 * This feature is only available on UNIX.
522 g_subprocess_launcher_take_stdout_fd (GSubprocessLauncher *self,
525 if (verify_disposition ("stdout", self->flags & ALL_STDOUT_FLAGS, fd, self->stdout_path))
526 assign_fd (&self->stdout_fd, fd);
530 * g_subprocess_launcher_set_stderr_file_path:
531 * @self: a #GSubprocessLauncher
532 * @path: (type filename) (nullable): a filename or %NULL
534 * Sets the file path to use as the stderr for spawned processes.
536 * If @path is %NULL then any previously given path is unset.
538 * The file will be created or truncated when the process is spawned, as
539 * would be the case if using '2>' at the shell.
541 * If you want to send both stdout and stderr to the same file then use
542 * %G_SUBPROCESS_FLAGS_STDERR_MERGE.
544 * You may not set a stderr file path if a stderr fd is already set or
545 * if the launcher flags contain any flags directing stderr elsewhere.
547 * This feature is only available on UNIX.
552 g_subprocess_launcher_set_stderr_file_path (GSubprocessLauncher *self,
555 if (verify_disposition ("stderr", self->flags & ALL_STDERR_FLAGS, self->stderr_fd, path))
557 g_free (self->stderr_path);
558 self->stderr_path = g_strdup (path);
563 * g_subprocess_launcher_take_stderr_fd:
564 * @self: a #GSubprocessLauncher
565 * @fd: a file descriptor, or -1
567 * Sets the file descriptor to use as the stderr for spawned processes.
569 * If @fd is -1 then any previously given fd is unset.
571 * Note that the default behaviour is to pass stderr through to the
572 * stderr of the parent process.
574 * The passed @fd belongs to the #GSubprocessLauncher. It will be
575 * automatically closed when the launcher is finalized. The file
576 * descriptor will also be closed on the child side when executing the
579 * You may not set a stderr fd if a stderr file path is already set or
580 * if the launcher flags contain any flags directing stderr elsewhere.
582 * This feature is only available on UNIX.
587 g_subprocess_launcher_take_stderr_fd (GSubprocessLauncher *self,
590 if (verify_disposition ("stderr", self->flags & ALL_STDERR_FLAGS, fd, self->stderr_path))
591 assign_fd (&self->stderr_fd, fd);
595 * g_subprocess_launcher_take_fd:
596 * @self: a #GSubprocessLauncher
597 * @source_fd: File descriptor in parent process
598 * @target_fd: Target descriptor for child process
600 * Transfer an arbitrary file descriptor from parent process to the
601 * child. This function takes ownership of the @source_fd; it will be closed
602 * in the parent when @self is freed.
604 * By default, all file descriptors from the parent will be closed.
605 * This function allows you to create (for example) a custom `pipe()` or
606 * `socketpair()` before launching the process, and choose the target
607 * descriptor in the child.
609 * An example use case is GNUPG, which has a command line argument
610 * `--passphrase-fd` providing a file descriptor number where it expects
611 * the passphrase to be written.
614 g_subprocess_launcher_take_fd (GSubprocessLauncher *self,
618 if (self->source_fds != NULL && self->target_fds != NULL)
620 g_array_append_val (self->source_fds, source_fd);
621 g_array_append_val (self->target_fds, target_fd);
626 * g_subprocess_launcher_close:
627 * @self: a #GSubprocessLauncher
629 * Closes all the file descriptors previously passed to the object with
630 * g_subprocess_launcher_take_fd(), g_subprocess_launcher_take_stderr_fd(), etc.
632 * After calling this method, any subsequent calls to g_subprocess_launcher_spawn() or g_subprocess_launcher_spawnv() will
633 * return %G_IO_ERROR_CLOSED. This method is idempotent if
634 * called more than once.
636 * This function is called automatically when the #GSubprocessLauncher
637 * is disposed, but is provided separately so that garbage collected
638 * language bindings can call it earlier to guarantee when FDs are closed.
643 g_subprocess_launcher_close (GSubprocessLauncher *self)
647 g_return_if_fail (G_IS_SUBPROCESS_LAUNCHER (self));
649 if (self->stdin_fd != -1)
650 close (self->stdin_fd);
653 if (self->stdout_fd != -1)
654 close (self->stdout_fd);
655 self->stdout_fd = -1;
657 if (self->stderr_fd != -1)
658 close (self->stderr_fd);
659 self->stderr_fd = -1;
661 if (self->source_fds)
663 g_assert (self->target_fds != NULL);
664 g_assert (self->source_fds->len == self->target_fds->len);
666 /* Note: Don’t close the target_fds, as they’re only valid FDs in the
667 * child process. This code never executes in the child process. */
668 for (i = 0; i < self->source_fds->len; i++)
669 (void) close (g_array_index (self->source_fds, int, i));
671 g_clear_pointer (&self->source_fds, g_array_unref);
672 g_clear_pointer (&self->target_fds, g_array_unref);
675 self->closed_fd = TRUE;
679 * g_subprocess_launcher_set_child_setup: (skip)
680 * @self: a #GSubprocessLauncher
681 * @child_setup: (closure user_data): a #GSpawnChildSetupFunc to use as the child setup function
682 * @user_data: user data for @child_setup
683 * @destroy_notify: a #GDestroyNotify for @user_data
685 * Sets up a child setup function.
687 * The child setup function will be called after fork() but before
688 * exec() on the child's side.
690 * @destroy_notify will not be automatically called on the child's side
691 * of the fork(). It will only be called when the last reference on the
692 * #GSubprocessLauncher is dropped or when a new child setup function is
695 * %NULL can be given as @child_setup to disable the functionality.
697 * Child setup functions are only available on UNIX.
702 g_subprocess_launcher_set_child_setup (GSubprocessLauncher *self,
703 GSpawnChildSetupFunc child_setup,
705 GDestroyNotify destroy_notify)
707 if (self->child_setup_destroy_notify)
708 (* self->child_setup_destroy_notify) (self->child_setup_user_data);
710 self->child_setup_func = child_setup;
711 self->child_setup_user_data = user_data;
712 self->child_setup_destroy_notify = destroy_notify;
717 * g_subprocess_launcher_spawn:
718 * @self: a #GSubprocessLauncher
720 * @argv0: Command line arguments
721 * @...: Continued arguments, %NULL terminated
723 * Creates a #GSubprocess given a provided varargs list of arguments.
726 * Returns: (transfer full): A new #GSubprocess, or %NULL on error (and @error will be set)
729 g_subprocess_launcher_spawn (GSubprocessLauncher *launcher,
739 g_return_val_if_fail (argv0 != NULL && argv0[0] != '\0', NULL);
740 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
742 args = g_ptr_array_new ();
744 va_start (ap, argv0);
745 g_ptr_array_add (args, (gchar *) argv0);
746 while ((arg = va_arg (ap, const gchar *)))
747 g_ptr_array_add (args, (gchar *) arg);
749 g_ptr_array_add (args, NULL);
752 result = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
754 g_ptr_array_free (args, TRUE);
761 * g_subprocess_launcher_spawnv:
762 * @self: a #GSubprocessLauncher
763 * @argv: (array zero-terminated=1) (element-type filename): Command line arguments
766 * Creates a #GSubprocess given a provided array of arguments.
769 * Returns: (transfer full): A new #GSubprocess, or %NULL on error (and @error will be set)
772 g_subprocess_launcher_spawnv (GSubprocessLauncher *launcher,
773 const gchar * const *argv,
776 GSubprocess *subprocess;
778 g_return_val_if_fail (argv != NULL && argv[0] != NULL && argv[0][0] != '\0', NULL);
781 if (launcher->closed_fd)
786 "Can't spawn a new child because a passed file descriptor has been closed.");
791 subprocess = g_object_new (G_TYPE_SUBPROCESS,
793 "flags", launcher->flags,
795 g_subprocess_set_launcher (subprocess, launcher);
797 if (!g_initable_init (G_INITABLE (subprocess), NULL, error))
799 g_object_unref (subprocess);