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>
18 * SECTION:gsubprocesslauncher
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
);
137 g_free (self
->stdin_path
);
138 g_free (self
->stdout_path
);
139 g_free (self
->stderr_path
);
141 if (self
->stdin_fd
!= -1)
142 close (self
->stdin_fd
);
144 if (self
->stdout_fd
!= -1)
145 close (self
->stdout_fd
);
147 if (self
->stderr_fd
!= -1)
148 close (self
->stderr_fd
);
150 if (self
->basic_fd_assignments
)
152 for (i
= 0; i
< self
->basic_fd_assignments
->len
; i
++)
153 (void) close (g_array_index (self
->basic_fd_assignments
, int, i
));
154 g_array_unref (self
->basic_fd_assignments
);
156 if (self
->needdup_fd_assignments
)
158 for (i
= 0; i
< self
->needdup_fd_assignments
->len
; i
+= 2)
159 (void) close (g_array_index (self
->needdup_fd_assignments
, int, i
));
160 g_array_unref (self
->needdup_fd_assignments
);
163 if (self
->child_setup_destroy_notify
)
164 (* self
->child_setup_destroy_notify
) (self
->child_setup_user_data
);
167 g_strfreev (self
->envp
);
170 G_OBJECT_CLASS (g_subprocess_launcher_parent_class
)->finalize (object
);
174 g_subprocess_launcher_init (GSubprocessLauncher
*self
)
176 self
->envp
= g_listenv ();
180 self
->stdout_fd
= -1;
181 self
->stderr_fd
= -1;
182 self
->basic_fd_assignments
= g_array_new (FALSE
, 0, sizeof (int));
183 self
->needdup_fd_assignments
= g_array_new (FALSE
, 0, sizeof (int));
188 g_subprocess_launcher_class_init (GSubprocessLauncherClass
*class)
190 GObjectClass
*gobject_class
= G_OBJECT_CLASS (class);
192 gobject_class
->set_property
= g_subprocess_launcher_set_property
;
193 gobject_class
->finalize
= g_subprocess_launcher_finalize
;
195 g_object_class_install_property (gobject_class
, 1,
196 g_param_spec_flags ("flags", "Flags", "GSubprocessFlags for launched processes",
197 G_TYPE_SUBPROCESS_FLAGS
, 0, G_PARAM_WRITABLE
|
198 G_PARAM_STATIC_STRINGS
| G_PARAM_CONSTRUCT_ONLY
));
202 * g_subprocess_launcher_new:
203 * @flags: #GSubprocessFlags
205 * Creates a new #GSubprocessLauncher.
207 * The launcher is created with the default options. A copy of the
208 * environment of the calling process is made at the time of this call
209 * and will be used as the environment that the process is launched in.
213 GSubprocessLauncher
*
214 g_subprocess_launcher_new (GSubprocessFlags flags
)
216 if (!verify_flags (flags
))
219 return g_object_new (G_TYPE_SUBPROCESS_LAUNCHER
,
225 * g_subprocess_launcher_set_environ:
226 * @self: a #GSubprocess
227 * @environ: the replacement environment
229 * Replace the entire environment of processes launched from this
230 * launcher with the given 'environ' variable.
232 * Typically you will build this variable by using g_listenv() to copy
233 * the process 'environ' and using the functions g_environ_setenv(),
234 * g_environ_unsetenv(), etc.
236 * As an alternative, you can use g_subprocess_launcher_setenv(),
237 * g_subprocess_launcher_unsetenv(), etc.
239 * All strings in this array are expected to be in the GLib file name
240 * encoding. On UNIX, this means that they can be arbitrary byte
241 * strings. On Windows, they should be in UTF-8.
246 g_subprocess_launcher_set_environ (GSubprocessLauncher
*self
,
249 g_strfreev (self
->envp
);
250 self
->envp
= g_strdupv (environ
);
254 * g_subprocess_launcher_setenv:
255 * @self: a #GSubprocess
256 * @variable: the environment variable to set, must not contain '='
257 * @value: the new value for the variable
258 * @overwrite: whether to change the variable if it already exists
260 * Sets the environment variable @variable in the environment of
261 * processes launched from this launcher.
263 * Both the variable's name and value should be in the GLib file name
264 * encoding. On UNIX, this means that they can be arbitrary byte
265 * strings. On Windows, they should be in UTF-8.
271 g_subprocess_launcher_setenv (GSubprocessLauncher
*self
,
272 const gchar
*variable
,
276 self
->envp
= g_environ_setenv (self
->envp
, variable
, value
, overwrite
);
280 * g_subprocess_launcher_unsetenv:
281 * @self: a #GSubprocess
282 * @variable: the environment variable to unset, must not contain '='
284 * Removes the environment variable @variable from the environment of
285 * processes launched from this launcher.
287 * The variable name should be in the GLib file name encoding. On UNIX,
288 * this means that they can be arbitrary byte strings. On Windows, they
289 * should be in UTF-8.
294 g_subprocess_launcher_unsetenv (GSubprocessLauncher
*self
,
295 const gchar
*variable
)
297 self
->envp
= g_environ_unsetenv (self
->envp
, variable
);
301 * g_subprocess_launcher_getenv:
302 * @self: a #GSubprocess
303 * @variable: the environment variable to get
305 * Returns the value of the environment variable @variable in the
306 * environment of processes launched from this launcher.
308 * The returned string is in the GLib file name encoding. On UNIX, this
309 * means that it can be an arbitrary byte string. On Windows, it will
312 * Returns: the value of the environment variable, %NULL if unset
317 g_subprocess_launcher_getenv (GSubprocessLauncher
*self
,
318 const gchar
*variable
)
320 return g_environ_getenv (self
->envp
, variable
);
324 * g_subprocess_launcher_set_cwd:
325 * @self: a #GSubprocess
326 * @cwd: the cwd for launched processes
328 * Sets the current working directory that processes will be launched
331 * By default processes are launched with the current working directory
332 * of the launching process at the time of launch.
337 g_subprocess_launcher_set_cwd (GSubprocessLauncher
*self
,
341 self
->cwd
= g_strdup (cwd
);
345 * g_subprocess_launcher_set_flags:
346 * @self: a #GSubprocessLauncher
347 * @flags: #GSubprocessFlags
349 * Sets the flags on the launcher.
351 * The default flags are %G_SUBPROCESS_FLAGS_NONE.
353 * You may not set flags that specify conflicting options for how to
354 * handle a particular stdio stream (eg: specifying both
355 * %G_SUBPROCESS_FLAGS_STDIN_PIPE and
356 * %G_SUBPROCESS_FLAGS_STDIN_INHERIT).
358 * You may also not set a flag that conflicts with a previous call to a
359 * function like g_subprocess_launcher_set_stdin_file_path() or
360 * g_subprocess_launcher_take_stdout_fd().
365 g_subprocess_launcher_set_flags (GSubprocessLauncher
*self
,
366 GSubprocessFlags flags
)
368 const gchar
*stdin_path
= NULL
, *stdout_path
= NULL
, *stderr_path
= NULL
;
369 gint stdin_fd
= -1, stdout_fd
= -1, stderr_fd
= -1;
372 stdin_fd
= self
->stdin_fd
;
373 stdout_fd
= self
->stdout_fd
;
374 stderr_fd
= self
->stderr_fd
;
375 stdin_path
= self
->stdin_path
;
376 stdout_path
= self
->stdout_path
;
377 stderr_path
= self
->stderr_path
;
380 if (verify_disposition ("stdin", flags
& ALL_STDIN_FLAGS
, stdin_fd
, stdin_path
) &&
381 verify_disposition ("stdout", flags
& ALL_STDOUT_FLAGS
, stdout_fd
, stdout_path
) &&
382 verify_disposition ("stderr", flags
& ALL_STDERR_FLAGS
, stderr_fd
, stderr_path
))
388 assign_fd (gint
*fd_ptr
, gint fd
)
400 flags
= fcntl (fd
, F_GETFD
);
401 if (~flags
& FD_CLOEXEC
)
402 fcntl (fd
, F_SETFD
, flags
| FD_CLOEXEC
);
407 * g_subprocess_launcher_set_stdin_file_path:
408 * @self: a #GSubprocessLauncher
409 * @path: a filename or %NULL
411 * Sets the file path to use as the stdin for spawned processes.
413 * If @path is %NULL then any previously given path is unset.
415 * The file must exist or spawning the process will fail.
417 * You may not set a stdin file path if a stdin fd is already set or if
418 * the launcher flags contain any flags directing stdin elsewhere.
420 * This feature is only available on UNIX.
425 g_subprocess_launcher_set_stdin_file_path (GSubprocessLauncher
*self
,
428 if (verify_disposition ("stdin", self
->flags
& ALL_STDIN_FLAGS
, self
->stdin_fd
, path
))
430 g_free (self
->stdin_path
);
431 self
->stdin_path
= g_strdup (path
);
436 * g_subprocess_launcher_take_stdin_fd:
437 * @self: a #GSubprocessLauncher
438 * @fd: a file descriptor, or -1
440 * Sets the file descriptor to use as the stdin for spawned processes.
442 * If @fd is -1 then any previously given fd is unset.
444 * Note that if your intention is to have the stdin of the calling
445 * process inherited by the child then %G_SUBPROCESS_FLAGS_STDIN_INHERIT
446 * is a better way to go about doing that.
448 * The passed @fd is noted but will not be touched in the current
449 * process. It is therefore necessary that it be kept open by the
450 * caller until the subprocess is spawned. The file descriptor will
451 * also not be explicitly closed on the child side, so it must be marked
452 * O_CLOEXEC if that's what you want.
454 * You may not set a stdin fd if a stdin file path is already set or if
455 * the launcher flags contain any flags directing stdin elsewhere.
457 * This feature is only available on UNIX.
462 g_subprocess_launcher_take_stdin_fd (GSubprocessLauncher
*self
,
465 if (verify_disposition ("stdin", self
->flags
& ALL_STDIN_FLAGS
, fd
, self
->stdin_path
))
466 assign_fd (&self
->stdin_fd
, fd
);
470 * g_subprocess_launcher_set_stdout_file_path:
471 * @self: a #GSubprocessLauncher
472 * @path: a filename or %NULL
474 * Sets the file path to use as the stdout for spawned processes.
476 * If @path is %NULL then any previously given path is unset.
478 * The file will be created or truncated when the process is spawned, as
479 * would be the case if using '>' at the shell.
481 * You may not set a stdout file path if a stdout fd is already set or
482 * if the launcher flags contain any flags directing stdout elsewhere.
484 * This feature is only available on UNIX.
489 g_subprocess_launcher_set_stdout_file_path (GSubprocessLauncher
*self
,
492 if (verify_disposition ("stdout", self
->flags
& ALL_STDOUT_FLAGS
, self
->stdout_fd
, path
))
494 g_free (self
->stdout_path
);
495 self
->stdout_path
= g_strdup (path
);
500 * g_subprocess_launcher_take_stdout_fd:
501 * @self: a #GSubprocessLauncher
502 * @fd: a file descriptor, or -1
504 * Sets the file descriptor to use as the stdout for spawned processes.
506 * If @fd is -1 then any previously given fd is unset.
508 * Note that the default behaviour is to pass stdout through to the
509 * stdout of the parent process.
511 * The passed @fd is noted but will not be touched in the current
512 * process. It is therefore necessary that it be kept open by the
513 * caller until the subprocess is spawned. The file descriptor will
514 * also not be explicitly closed on the child side, so it must be marked
515 * O_CLOEXEC if that's what you want.
517 * You may not set a stdout fd if a stdout file path is already set or
518 * if the launcher flags contain any flags directing stdout elsewhere.
520 * This feature is only available on UNIX.
525 g_subprocess_launcher_take_stdout_fd (GSubprocessLauncher
*self
,
528 if (verify_disposition ("stdout", self
->flags
& ALL_STDOUT_FLAGS
, fd
, self
->stdout_path
))
529 assign_fd (&self
->stdout_fd
, fd
);
533 * g_subprocess_launcher_set_stderr_file_path:
534 * @self: a #GSubprocessLauncher
535 * @path: a filename or %NULL
537 * Sets the file path to use as the stderr for spawned processes.
539 * If @path is %NULL then any previously given path is unset.
541 * The file will be created or truncated when the process is spawned, as
542 * would be the case if using '2>' at the shell.
544 * If you want to send both stdout and stderr to the same file then use
545 * %G_SUBPROCESS_FLAGS_STDERR_MERGE.
547 * You may not set a stderr file path if a stderr fd is already set or
548 * if the launcher flags contain any flags directing stderr elsewhere.
550 * This feature is only available on UNIX.
555 g_subprocess_launcher_set_stderr_file_path (GSubprocessLauncher
*self
,
558 if (verify_disposition ("stderr", self
->flags
& ALL_STDERR_FLAGS
, self
->stderr_fd
, path
))
560 g_free (self
->stderr_path
);
561 self
->stderr_path
= g_strdup (path
);
566 * g_subprocess_launcher_take_stderr_fd:
567 * @self: a #GSubprocessLauncher
568 * @fd: a file descriptor, or -1
570 * Sets the file descriptor to use as the stderr for spawned processes.
572 * If @fd is -1 then any previously given fd is unset.
574 * Note that the default behaviour is to pass stderr through to the
575 * stderr of the parent process.
577 * The passed @fd belongs to the #GSubprocessLauncher. It will be
578 * automatically closed when the launcher is finalized. The file
579 * descriptor will also be closed on the child side when executing the
582 * You may not set a stderr fd if a stderr file path is already set or
583 * if the launcher flags contain any flags directing stderr elsewhere.
585 * This feature is only available on UNIX.
590 g_subprocess_launcher_take_stderr_fd (GSubprocessLauncher
*self
,
593 if (verify_disposition ("stderr", self
->flags
& ALL_STDERR_FLAGS
, fd
, self
->stderr_path
))
594 assign_fd (&self
->stderr_fd
, fd
);
598 * g_subprocess_launcher_take_fd:
599 * @self: a #GSubprocessLauncher
600 * @source_fd: File descriptor in parent process
601 * @target_fd: Target descriptor for child process
603 * Transfer an arbitrary file descriptor from parent process to the
604 * child. This function takes "ownership" of the fd; it will be closed
605 * in the parent when @self is freed.
607 * By default, all file descriptors from the parent will be closed.
608 * This function allows you to create (for example) a custom pipe() or
609 * socketpair() before launching the process, and choose the target
610 * descriptor in the child.
612 * An example use case is GNUPG, which has a command line argument
613 * --passphrase-fd providing a file descriptor number where it expects
614 * the passphrase to be written.
617 g_subprocess_launcher_take_fd (GSubprocessLauncher
*self
,
621 if (source_fd
== target_fd
)
623 g_array_append_val (self
->basic_fd_assignments
, source_fd
);
627 g_array_append_val (self
->needdup_fd_assignments
, source_fd
);
628 g_array_append_val (self
->needdup_fd_assignments
, target_fd
);
633 * g_subprocess_launcher_set_child_setup:
634 * @self: a #GSubprocessLauncher
635 * @child_setup: a #GSpawnChildSetupFunc to use as the child setup function
636 * @user_data: user data for @child_setup
637 * @destroy_notify: a #GDestroyNotify for @user_data
639 * Sets up a child setup function.
641 * The child setup function will be called after fork() but before
642 * exec() on the child's side.
644 * @destroy_notify will not be automatically called on the child's side
645 * of the fork(). It will only be called when the last reference on the
646 * #GSubprocessLauncher is dropped or when a new child setup function is
649 * %NULL can be given as @child_setup to disable the functionality.
651 * Child setup functions are only available on UNIX.
656 g_subprocess_launcher_set_child_setup (GSubprocessLauncher
*self
,
657 GSpawnChildSetupFunc child_setup
,
659 GDestroyNotify destroy_notify
)
661 if (self
->child_setup_destroy_notify
)
662 (* self
->child_setup_destroy_notify
) (self
->child_setup_user_data
);
664 self
->child_setup_func
= child_setup
;
665 self
->child_setup_user_data
= user_data
;
666 self
->child_setup_destroy_notify
= destroy_notify
;
671 * g_subprocess_launcher_spawn:
672 * @self: a #GSubprocessLauncher
674 * @argv0: Command line arguments
675 * @...: Continued arguments, %NULL terminated
677 * A convenience helper for creating a #GSubprocess given a provided
678 * varargs list of arguments.
681 * Returns: (transfer full): A new #GSubprocess, or %NULL on error (and @error will be set)
684 g_subprocess_launcher_spawn (GSubprocessLauncher
*launcher
,
694 g_return_val_if_fail (argv0
!= NULL
&& argv0
[0] != '\0', NULL
);
695 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, NULL
);
697 args
= g_ptr_array_new ();
699 va_start (ap
, argv0
);
700 g_ptr_array_add (args
, (gchar
*) argv0
);
701 while ((arg
= va_arg (ap
, const gchar
*)))
702 g_ptr_array_add (args
, (gchar
*) arg
);
704 result
= g_subprocess_launcher_spawnv (launcher
, (const gchar
* const *) args
->pdata
, error
);
706 g_ptr_array_free (args
, TRUE
);
713 * g_subprocess_launcher_spawnv:
714 * @self: a #GSubprocessLauncher
715 * @argv: Command line arguments
718 * A convenience helper for creating a #GSubprocess given a provided
719 * array of arguments.
722 * Returns: (transfer full): A new #GSubprocess, or %NULL on error (and @error will be set)
725 g_subprocess_launcher_spawnv (GSubprocessLauncher
*launcher
,
726 const gchar
* const *argv
,
729 GSubprocess
*subprocess
;
731 g_return_val_if_fail (argv
!= NULL
&& argv
[0] != NULL
&& argv
[0][0] != '\0', NULL
);
733 subprocess
= g_object_new (G_TYPE_SUBPROCESS
,
735 "flags", launcher
->flags
,
737 g_subprocess_set_launcher (subprocess
, launcher
);
739 if (!g_initable_init (G_INITABLE (subprocess
), NULL
, error
))
741 g_object_unref (subprocess
);