1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright © 2012 Red Hat, Inc.
4 * Copyright © 2012-2013 Canonical Limited
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published
8 * by the Free Software Foundation; either version 2 of the licence or (at
9 * your option) any later version.
11 * See the included COPYING file for more information.
13 * Authors: Colin Walters <walters@verbum.org>
14 * Ryan Lortie <desrt@desrt.ca>
19 * @title: GSubprocess Launcher
20 * @short_description: Environment options for launching a child process
22 * This class contains a set of options for launching child processes,
23 * such as where its standard input and output will be directed, the
24 * argument list, the environment, and more.
26 * While the #GSubprocess class has high level functions covering
27 * popular cases, use of this class allows access to more advanced
28 * options. It can also be used to launch multiple subprocesses with
29 * a similar configuration.
34 #define ALL_STDIN_FLAGS (G_SUBPROCESS_FLAGS_STDIN_PIPE | \
35 G_SUBPROCESS_FLAGS_STDIN_INHERIT)
36 #define ALL_STDOUT_FLAGS (G_SUBPROCESS_FLAGS_STDOUT_PIPE | \
37 G_SUBPROCESS_FLAGS_STDOUT_SILENCE)
38 #define ALL_STDERR_FLAGS (G_SUBPROCESS_FLAGS_STDERR_PIPE | \
39 G_SUBPROCESS_FLAGS_STDERR_SILENCE | \
40 G_SUBPROCESS_FLAGS_STDERR_MERGE)
44 #include "gsubprocesslauncher-private.h"
45 #include "gioenumtypes.h"
46 #include "gsubprocess.h"
47 #include "ginitable.h"
54 typedef GObjectClass GSubprocessLauncherClass;
56 G_DEFINE_TYPE (GSubprocessLauncher, g_subprocess_launcher, G_TYPE_OBJECT);
59 verify_disposition (const gchar *stream_name,
60 GSubprocessFlags filtered_flags,
62 const gchar *filename)
68 else if (((filtered_flags - 1) & filtered_flags) == 0)
71 n_bits = 2; /* ...or more */
73 if (n_bits + (fd >= 0) + (filename != NULL) > 1)
77 err = g_string_new (NULL);
83 class = g_type_class_peek (G_TYPE_SUBPROCESS_FLAGS);
84 while ((value = g_flags_get_first_value (class, filtered_flags)))
86 g_string_append_printf (err, " %s", value->value_name);
87 filtered_flags &= value->value;
90 g_type_class_unref (class);
94 g_string_append_printf (err, " g_subprocess_launcher_take_%s_fd()", stream_name);
97 g_string_append_printf (err, " g_subprocess_launcher_set_%s_file_path()", stream_name);
99 g_critical ("You may specify at most one disposition for the %s stream, but you specified:%s.",
100 stream_name, err->str);
101 g_string_free (err, TRUE);
110 verify_flags (GSubprocessFlags flags)
112 return verify_disposition ("stdin", flags & ALL_STDIN_FLAGS, -1, NULL) &&
113 verify_disposition ("stdout", flags & ALL_STDOUT_FLAGS, -1, NULL) &&
114 verify_disposition ("stderr", flags & ALL_STDERR_FLAGS, -1, NULL);
118 g_subprocess_launcher_set_property (GObject *object, guint prop_id,
119 const GValue *value, GParamSpec *pspec)
121 GSubprocessLauncher *launcher = G_SUBPROCESS_LAUNCHER (object);
123 g_assert (prop_id == 1);
125 if (verify_flags (g_value_get_flags (value)))
126 launcher->flags = g_value_get_flags (value);
130 g_subprocess_launcher_finalize (GObject *object)
132 GSubprocessLauncher *self = G_SUBPROCESS_LAUNCHER (object);
134 g_strfreev (self->envp);
138 g_free (self->stdin_path);
139 g_free (self->stdout_path);
140 g_free (self->stderr_path);
142 if (self->stdin_fd != -1)
143 close (self->stdin_fd);
145 if (self->stdout_fd != -1)
146 close (self->stdout_fd);
148 if (self->stderr_fd != -1)
149 close (self->stderr_fd);
151 g_clear_pointer (&self->basic_fd_assignments, g_array_unref);
152 g_clear_pointer (&self->needdup_fd_assignments, g_array_unref);
155 if (self->child_setup_destroy_notify)
156 (* self->child_setup_destroy_notify) (self->child_setup_user_data);
158 G_OBJECT_CLASS (g_subprocess_launcher_parent_class)->finalize (object);
162 g_subprocess_launcher_init (GSubprocessLauncher *self)
164 self->envp = g_listenv ();
167 self->stdout_fd = -1;
168 self->stderr_fd = -1;
170 self->basic_fd_assignments = g_array_new (FALSE, 0, sizeof (int));
171 self->needdup_fd_assignments = g_array_new (FALSE, 0, sizeof (int));
176 g_subprocess_launcher_class_init (GSubprocessLauncherClass *class)
178 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
180 gobject_class->set_property = g_subprocess_launcher_set_property;
181 gobject_class->finalize = g_subprocess_launcher_finalize;
183 g_object_class_install_property (gobject_class, 1,
184 g_param_spec_flags ("flags", "Flags", "GSubprocessFlags for launched processes",
185 G_TYPE_SUBPROCESS_FLAGS, 0, G_PARAM_WRITABLE |
186 G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY));
190 * g_subprocess_launcher_new:
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 #GSubprocess
214 * @environ: the replacement environment
216 * Replace the entire environment of processes launched from this
217 * launcher with the given 'environ' variable.
219 * Typically you will build this variable by using g_listenv() to copy
220 * the process 'environ' and using the functions g_environ_setenv(),
221 * g_environ_unsetenv(), etc.
223 * As an alternative, you can use g_subprocess_launcher_setenv(),
224 * g_subprocess_launcher_unsetenv(), etc.
226 * All strings in this array are expected to be in the GLib file name
227 * encoding. On UNIX, this means that they can be arbitrary byte
228 * strings. On Windows, they should be in UTF-8.
233 g_subprocess_launcher_set_environ (GSubprocessLauncher *self,
236 g_strfreev (self->envp);
237 self->envp = g_strdupv (environ);
241 * g_subprocess_launcher_setenv:
242 * @self: a #GSubprocess
243 * @variable: the environment variable to set, must not contain '='
244 * @value: the new value for the variable
245 * @overwrite: whether to change the variable if it already exists
247 * Sets the environment variable @variable in the environment of
248 * processes launched from this launcher.
250 * Both the variable's name and value should be in the GLib file name
251 * encoding. On UNIX, this means that they can be arbitrary byte
252 * strings. On Windows, they should be in UTF-8.
258 g_subprocess_launcher_setenv (GSubprocessLauncher *self,
259 const gchar *variable,
263 self->envp = g_environ_setenv (self->envp, variable, value, overwrite);
267 * g_subprocess_launcher_unsetsenv:
268 * @self: a #GSubprocess
269 * @variable: the environment variable to unset, must not contain '='
271 * Removes the environment variable @variable from the environment of
272 * processes launched from this launcher.
274 * The variable name should be in the GLib file name encoding. On UNIX,
275 * this means that they can be arbitrary byte strings. On Windows, they
276 * should be in UTF-8.
281 g_subprocess_launcher_unsetenv (GSubprocessLauncher *self,
282 const gchar *variable)
284 self->envp = g_environ_unsetenv (self->envp, variable);
288 * g_subprocess_launcher_getenv:
289 * @self: a #GSubprocess
290 * @variable: the environment variable to get
292 * Returns the value of the environment variable @variable in the
293 * environment of processes launched from this launcher.
295 * The returned string is in the GLib file name encoding. On UNIX, this
296 * means that it can be an arbitrary byte string. On Windows, it will
299 * Returns: the value of the environment variable, %NULL if unset
304 g_subprocess_launcher_getenv (GSubprocessLauncher *self,
305 const gchar *variable)
307 return g_environ_getenv (self->envp, variable);
311 * g_subprocess_launcher_set_cwd:
312 * @self: a #GSubprocess
313 * @cwd: the cwd for launched processes
315 * Sets the current working directory that processes will be launched
318 * By default processes are launched with the current working directory
319 * of the launching process at the time of launch.
324 g_subprocess_launcher_set_cwd (GSubprocessLauncher *self,
328 self->cwd = g_strdup (cwd);
332 * g_subprocess_launcher_set_flags:
333 * @self: a #GSubprocessLauncher
334 * @flags: #GSubprocessFlags
336 * Sets the flags on the launcher.
338 * The default flags are %G_SUBPROCESS_FLAGS_NONE.
340 * You may not set flags that specify conflicting options for how to
341 * handle a particular stdio stream (eg: specifying both
342 * %G_SUBPROCESS_FLAGS_STDIN_PIPE and
343 * %G_SUBPROCESS_FLAGS_STDIN_INHERIT).
345 * You may also not set a flag that conflicts with a previous call to a
346 * function like g_subprocess_launcher_set_stdin_file_path() or
347 * g_subprocess_launcher_take_stdout_fd().
352 g_subprocess_launcher_set_flags (GSubprocessLauncher *self,
353 GSubprocessFlags flags)
355 if (verify_disposition ("stdin", flags & ALL_STDIN_FLAGS, self->stdin_fd, self->stdin_path) &&
356 verify_disposition ("stdout", flags & ALL_STDOUT_FLAGS, self->stdout_fd, self->stdout_path) &&
357 verify_disposition ("stderr", flags & ALL_STDERR_FLAGS, self->stderr_fd, self->stderr_path))
363 assign_fd (gint *fd_ptr, gint fd)
375 flags = fcntl (fd, F_GETFD);
376 if (~flags & FD_CLOEXEC)
377 fcntl (fd, F_SETFD, flags | FD_CLOEXEC);
382 * g_subprocess_launcher_set_stdin_file_path:
383 * @self: a #GSubprocessLauncher
384 * @path: a filename or %NULL
386 * Sets the file path to use as the stdin for spawned processes.
388 * If @path is %NULL then any previously given path is unset.
390 * The file must exist or spawning the process will fail.
392 * You may not set a stdin file path if a stdin fd is already set or if
393 * the launcher flags contain any flags directing stdin elsewhere.
395 * This feature is only available on UNIX.
400 g_subprocess_launcher_set_stdin_file_path (GSubprocessLauncher *self,
403 if (verify_disposition ("stdin", self->flags & ALL_STDIN_FLAGS, self->stdin_fd, path))
405 g_free (self->stdin_path);
406 self->stdin_path = g_strdup (path);
411 * g_subprocess_launcher_take_stdin_fd:
412 * @self: a #GSubprocessLauncher
413 * @fd: a file descriptor, or -1
415 * Sets the file descriptor to use as the stdin for spawned processes.
417 * If @fd is -1 then any previously given fd is unset.
419 * Note that if your intention is to have the stdin of the calling
420 * process inherited by the child then %G_SUBPROCESS_FLAGS_STDIN_INHERIT
421 * is a better way to go about doing that.
423 * The passed @fd is noted but will not be touched in the current
424 * process. It is therefore necessary that it be kept open by the
425 * caller until the subprocess is spawned. The file descriptor will
426 * also not be explicitly closed on the child side, so it must be marked
427 * O_CLOEXEC if that's what you want.
429 * You may not set a stdin fd if a stdin file path is already set or if
430 * the launcher flags contain any flags directing stdin elsewhere.
432 * This feature is only available on UNIX.
437 g_subprocess_launcher_take_stdin_fd (GSubprocessLauncher *self,
440 if (verify_disposition ("stdin", self->flags & ALL_STDIN_FLAGS, fd, self->stdin_path))
441 assign_fd (&self->stdin_fd, fd);
445 * g_subprocess_launcher_set_stdout_file_path:
446 * @self: a #GSubprocessLauncher
447 * @path: a filename or %NULL
449 * Sets the file path to use as the stdout for spawned processes.
451 * If @path is %NULL then any previously given path is unset.
453 * The file will be created or truncated when the process is spawned, as
454 * would be the case if using '>' at the shell.
456 * You may not set a stdout file path if a stdout fd is already set or
457 * if the launcher flags contain any flags directing stdout elsewhere.
459 * This feature is only available on UNIX.
464 g_subprocess_launcher_set_stdout_file_path (GSubprocessLauncher *self,
467 if (verify_disposition ("stdout", self->flags & ALL_STDOUT_FLAGS, self->stdout_fd, path))
469 g_free (self->stdout_path);
470 self->stdout_path = g_strdup (path);
475 * g_subprocess_launcher_take_stdout_fd:
476 * @self: a #GSubprocessLauncher
477 * @fd: a file descriptor, or -1
479 * Sets the file descriptor to use as the stdout for spawned processes.
481 * If @fd is -1 then any previously given fd is unset.
483 * Note that the default behaviour is to pass stdout through to the
484 * stdout of the parent process.
486 * The passed @fd is noted but will not be touched in the current
487 * process. It is therefore necessary that it be kept open by the
488 * caller until the subprocess is spawned. The file descriptor will
489 * also not be explicitly closed on the child side, so it must be marked
490 * O_CLOEXEC if that's what you want.
492 * You may not set a stdout fd if a stdout file path is already set or
493 * if the launcher flags contain any flags directing stdout elsewhere.
495 * This feature is only available on UNIX.
500 g_subprocess_launcher_take_stdout_fd (GSubprocessLauncher *self,
503 if (verify_disposition ("stdout", self->flags & ALL_STDOUT_FLAGS, fd, self->stdout_path))
504 assign_fd (&self->stdout_fd, fd);
508 * g_subprocess_launcher_set_stderr_file_path:
509 * @self: a #GSubprocessLauncher
510 * @path: a filename or %NULL
512 * Sets the file path to use as the stderr for spawned processes.
514 * If @path is %NULL then any previously given path is unset.
516 * The file will be created or truncated when the process is spawned, as
517 * would be the case if using '2>' at the shell.
519 * If you want to send both stdout and stderr to the same file then use
520 * %G_SUBPROCESS_FLAGS_STDERR_MERGE.
522 * You may not set a stderr file path if a stderr fd is already set or
523 * if the launcher flags contain any flags directing stderr elsewhere.
525 * This feature is only available on UNIX.
530 g_subprocess_launcher_set_stderr_file_path (GSubprocessLauncher *self,
533 if (verify_disposition ("stderr", self->flags & ALL_STDERR_FLAGS, self->stderr_fd, path))
535 g_free (self->stderr_path);
536 self->stderr_path = g_strdup (path);
541 * g_subprocess_launcher_take_stderr_fd:
542 * @self: a #GSubprocessLauncher
543 * @fd: a file descriptor, or -1
545 * Sets the file descriptor to use as the stderr for spawned processes.
547 * If @fd is -1 then any previously given fd is unset.
549 * Note that the default behaviour is to pass stderr through to the
550 * stderr of the parent process.
552 * The passed @fd belongs to the #GSubprocessLauncher. It will be
553 * automatically closed when the launcher is finalized. The file
554 * descriptor will also be closed on the child side when executing the
557 * You may not set a stderr fd if a stderr file path is already set or
558 * if the launcher flags contain any flags directing stderr elsewhere.
560 * This feature is only available on UNIX.
565 g_subprocess_launcher_take_stderr_fd (GSubprocessLauncher *self,
568 if (verify_disposition ("stderr", self->flags & ALL_STDERR_FLAGS, fd, self->stderr_path))
569 assign_fd (&self->stderr_fd, fd);
573 * g_subprocess_launcher_pass_fd:
574 * @self: a #GSubprocessLauncher
575 * @source_fd: File descriptor in parent process
576 * @target_fd: Target descriptor for child process
578 * Pass an arbitrary file descriptor from parent process to
579 * the child. By default, all file descriptors from the parent
580 * will be closed. This function allows you to create (for example)
581 * a custom pipe() or socketpair() before launching the process, and
582 * choose the target descriptor in the child.
584 * An example use case is GNUPG, which has a command line argument
585 * --passphrase-fd providing a file descriptor number where it expects
586 * the passphrase to be written.
589 g_subprocess_launcher_pass_fd (GSubprocessLauncher *self,
593 if (source_fd == target_fd)
595 g_array_append_val (self->basic_fd_assignments, source_fd);
599 g_array_append_val (self->needdup_fd_assignments, source_fd);
600 g_array_append_val (self->needdup_fd_assignments, target_fd);
605 * g_subprocess_launcher_set_child_setup:
606 * @self: a #GSubprocessLauncher
607 * @child_setup: a #GSpawnChildSetupFunc to use as the child setup function
608 * @user_data: user data for @child_setup
609 * @destroy_notify: a #GDestroyNotify for @user_data
611 * Sets up a child setup function.
613 * The child setup function will be called after fork() but before
614 * exec() on the child's side.
616 * @destroy_notify will not be automatically called on the child's side
617 * of the fork(). It will only be called when the last reference on the
618 * #GSubprocessLauncher is dropped or when a new child setup function is
621 * %NULL can be given as @child_setup to disable the functionality.
623 * Child setup functions are only available on UNIX.
628 g_subprocess_launcher_set_child_setup (GSubprocessLauncher *self,
629 GSpawnChildSetupFunc child_setup,
631 GDestroyNotify destroy_notify)
633 if (self->child_setup_destroy_notify)
634 (* self->child_setup_destroy_notify) (self->child_setup_user_data);
636 self->child_setup_func = child_setup;
637 self->child_setup_user_data = user_data;
638 self->child_setup_destroy_notify = destroy_notify;
643 * g_subprocess_launcher_spawn:
644 * @self: a #GSubprocessLauncher
646 * @argv0: Command line arguments
647 * @...: Continued arguments, %NULL terminated
649 * A convenience helper for creating a #GSubprocess given a provided
650 * varargs list of arguments.
653 * Returns: (transfer full): A new #GSubprocess, or %NULL on error (and @error will be set)
656 g_subprocess_launcher_spawn (GSubprocessLauncher *launcher,
666 g_return_val_if_fail (argv0 != NULL && argv0[0] != '\0', NULL);
667 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
669 args = g_ptr_array_new ();
671 va_start (ap, argv0);
672 g_ptr_array_add (args, (gchar *) argv0);
673 while ((arg = va_arg (ap, const gchar *)))
674 g_ptr_array_add (args, (gchar *) arg);
676 result = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
678 g_ptr_array_free (args, TRUE);
685 * g_subprocess_launcher_spawnv:
686 * @self: a #GSubprocessLauncher
687 * @argv: Command line arguments
690 * A convenience helper for creating a #GSubprocess given a provided
691 * array of arguments.
694 * Returns: (transfer full): A new #GSubprocess, or %NULL on error (and @error will be set)
697 g_subprocess_launcher_spawnv (GSubprocessLauncher *launcher,
698 const gchar * const *argv,
701 GSubprocess *subprocess;
703 g_return_val_if_fail (argv != NULL && argv[0] != NULL && argv[0][0] != '\0', NULL);
705 subprocess = g_object_new (G_TYPE_SUBPROCESS,
707 "flags", launcher->flags,
709 g_subprocess_set_launcher (subprocess, launcher);
711 if (!g_initable_init (G_INITABLE (subprocess), NULL, error))
713 g_object_unref (subprocess);