kdbus: Fixup signal subscription
[platform/upstream/glib.git] / gio / gsubprocesslauncher.c
1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright © 2012 Red Hat, Inc.
4  * Copyright © 2012-2013 Canonical Limited
5  *
6  * SPDX-License-Identifier: LGPL-2.1-or-later
7  *
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.
12  *
13  * See the included COPYING file for more information.
14  *
15  * Authors: Colin Walters <walters@verbum.org>
16  *          Ryan Lortie <desrt@desrt.ca>
17  */
18
19 /**
20  * GSubprocessLauncher:
21  *
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.
25  *
26  * While the [class@Gio.Subprocess] 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.
30  *
31  * Since: 2.40
32  */
33
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)
41
42 #include "config.h"
43
44 #include "gsubprocesslauncher-private.h"
45 #include "gioenumtypes.h"
46 #include "gsubprocess.h"
47 #include "ginitable.h"
48 #include "gioerror.h"
49
50 #ifdef G_OS_UNIX
51 #include <unistd.h>
52 #include <fcntl.h>
53 #endif
54
55 typedef GObjectClass GSubprocessLauncherClass;
56
57 G_DEFINE_TYPE (GSubprocessLauncher, g_subprocess_launcher, G_TYPE_OBJECT)
58
59 static gboolean
60 verify_disposition (const gchar      *stream_name,
61                     GSubprocessFlags  filtered_flags,
62                     gint              fd,
63                     const gchar      *filename)
64 {
65   guint n_bits;
66
67   if (!filtered_flags)
68     n_bits = 0;
69   else if (((filtered_flags - 1) & filtered_flags) == 0)
70     n_bits = 1;
71   else
72     n_bits = 2; /* ...or more */
73
74   if (n_bits + (fd >= 0) + (filename != NULL) > 1)
75     {
76       GString *err;
77
78       err = g_string_new (NULL);
79       if (n_bits)
80         {
81           GFlagsClass *class;
82           guint i;
83
84           class = g_type_class_peek (G_TYPE_SUBPROCESS_FLAGS);
85
86           for (i = 0; i < class->n_values; i++)
87             {
88               const GFlagsValue *value = &class->values[i];
89
90               if (filtered_flags & value->value)
91                 g_string_append_printf (err, " %s", value->value_name);
92             }
93
94           g_type_class_unref (class);
95         }
96
97       if (fd >= 0)
98         g_string_append_printf (err, " g_subprocess_launcher_take_%s_fd()", stream_name);
99
100       if (filename)
101         g_string_append_printf (err, " g_subprocess_launcher_set_%s_file_path()", stream_name);
102
103       g_critical ("You may specify at most one disposition for the %s stream, but you specified:%s.",
104                   stream_name, err->str);
105       g_string_free (err, TRUE);
106
107       return FALSE;
108     }
109
110   return TRUE;
111 }
112
113 static gboolean
114 verify_flags (GSubprocessFlags flags)
115 {
116   return verify_disposition ("stdin", flags & ALL_STDIN_FLAGS, -1, NULL) &&
117          verify_disposition ("stdout", flags & ALL_STDOUT_FLAGS, -1, NULL) &&
118          verify_disposition ("stderr", flags & ALL_STDERR_FLAGS, -1, NULL);
119 }
120
121 static void
122 g_subprocess_launcher_set_property (GObject *object, guint prop_id,
123                                     const GValue *value, GParamSpec *pspec)
124 {
125   GSubprocessLauncher *launcher = G_SUBPROCESS_LAUNCHER (object);
126
127   g_assert (prop_id == 1);
128
129   if (verify_flags (g_value_get_flags (value)))
130     launcher->flags = g_value_get_flags (value);
131 }
132
133 static void
134 g_subprocess_launcher_dispose (GObject *object)
135 {
136   GSubprocessLauncher *self = G_SUBPROCESS_LAUNCHER (object);
137
138 #ifdef G_OS_UNIX
139   g_clear_pointer (&self->stdin_path, g_free);
140   g_clear_pointer (&self->stdout_path, g_free);
141   g_clear_pointer (&self->stderr_path, g_free);
142
143   g_subprocess_launcher_close (self);
144
145   if (self->child_setup_destroy_notify)
146     (* self->child_setup_destroy_notify) (self->child_setup_user_data);
147   self->child_setup_destroy_notify = NULL;
148   self->child_setup_user_data = NULL;
149 #endif
150
151   g_clear_pointer (&self->envp, g_strfreev);
152   g_clear_pointer (&self->cwd, g_free);
153
154   G_OBJECT_CLASS (g_subprocess_launcher_parent_class)->dispose (object);
155 }
156
157 static void
158 g_subprocess_launcher_init (GSubprocessLauncher  *self)
159 {
160   self->envp = g_get_environ ();
161
162 #ifdef G_OS_UNIX
163   self->stdin_fd = -1;
164   self->stdout_fd = -1;
165   self->stderr_fd = -1;
166   self->source_fds = g_array_new (FALSE, 0, sizeof (int));
167   self->target_fds = g_array_new (FALSE, 0, sizeof (int));
168 #endif
169 }
170
171 static void
172 g_subprocess_launcher_class_init (GSubprocessLauncherClass *class)
173 {
174   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
175
176   gobject_class->set_property = g_subprocess_launcher_set_property;
177   gobject_class->dispose = g_subprocess_launcher_dispose;
178
179   /**
180    * GSubprocessLauncher:flags:
181    *
182    * [flags@Gio.SubprocessFlags] for launched processes.
183    *
184    * Since: 2.40
185    */
186   g_object_class_install_property (gobject_class, 1,
187                                    g_param_spec_flags ("flags", NULL, NULL,
188                                                        G_TYPE_SUBPROCESS_FLAGS, 0, G_PARAM_WRITABLE |
189                                                        G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY));
190 }
191
192 /**
193  * g_subprocess_launcher_new:
194  * @flags: #GSubprocessFlags
195  *
196  * Creates a new #GSubprocessLauncher.
197  *
198  * The launcher is created with the default options.  A copy of the
199  * environment of the calling process is made at the time of this call
200  * and will be used as the environment that the process is launched in.
201  *
202  * Since: 2.40
203  **/
204 GSubprocessLauncher *
205 g_subprocess_launcher_new (GSubprocessFlags flags)
206 {
207   if (!verify_flags (flags))
208     return NULL;
209
210   return g_object_new (G_TYPE_SUBPROCESS_LAUNCHER,
211                        "flags", flags,
212                        NULL);
213 }
214
215 /**
216  * g_subprocess_launcher_set_environ:
217  * @self: a #GSubprocessLauncher
218  * @env: (array zero-terminated=1) (element-type filename) (transfer none):
219  *     the replacement environment
220  *
221  * Replace the entire environment of processes launched from this
222  * launcher with the given 'environ' variable.
223  *
224  * Typically you will build this variable by using g_listenv() to copy
225  * the process 'environ' and using the functions g_environ_setenv(),
226  * g_environ_unsetenv(), etc.
227  *
228  * As an alternative, you can use g_subprocess_launcher_setenv(),
229  * g_subprocess_launcher_unsetenv(), etc.
230  *
231  * Pass an empty array to set an empty environment. Pass %NULL to inherit the
232  * parent process’ environment. As of GLib 2.54, the parent process’ environment
233  * will be copied when g_subprocess_launcher_set_environ() is called.
234  * Previously, it was copied when the subprocess was executed. This means the
235  * copied environment may now be modified (using g_subprocess_launcher_setenv(),
236  * etc.) before launching the subprocess.
237  *
238  * On UNIX, all strings in this array can be arbitrary byte strings.
239  * On Windows, they should be in UTF-8.
240  *
241  * Since: 2.40
242  **/
243 void
244 g_subprocess_launcher_set_environ (GSubprocessLauncher  *self,
245                                    gchar               **env)
246 {
247   g_strfreev (self->envp);
248   self->envp = g_strdupv (env);
249
250   if (self->envp == NULL)
251     self->envp = g_get_environ ();
252 }
253
254 /**
255  * g_subprocess_launcher_setenv:
256  * @self: a #GSubprocessLauncher
257  * @variable: (type filename): the environment variable to set,
258  *     must not contain '='
259  * @value: (type filename): the new value for the variable
260  * @overwrite: whether to change the variable if it already exists
261  *
262  * Sets the environment variable @variable in the environment of
263  * processes launched from this launcher.
264  *
265  * On UNIX, both the variable's name and value can be arbitrary byte
266  * strings, except that the variable's name cannot contain '='.
267  * On Windows, they should be in UTF-8.
268  *
269  * Since: 2.40
270  **/
271 void
272 g_subprocess_launcher_setenv (GSubprocessLauncher *self,
273                               const gchar         *variable,
274                               const gchar         *value,
275                               gboolean             overwrite)
276 {
277   self->envp = g_environ_setenv (self->envp, variable, value, overwrite);
278 }
279
280 /**
281  * g_subprocess_launcher_unsetenv:
282  * @self: a #GSubprocessLauncher
283  * @variable: (type filename): the environment variable to unset,
284  *     must not contain '='
285  *
286  * Removes the environment variable @variable from the environment of
287  * processes launched from this launcher.
288  *
289  * On UNIX, the variable's name can be an arbitrary byte string not
290  * containing '='. On Windows, it should be in UTF-8.
291  *
292  * Since: 2.40
293  **/
294 void
295 g_subprocess_launcher_unsetenv (GSubprocessLauncher *self,
296                                 const gchar         *variable)
297 {
298   self->envp = g_environ_unsetenv (self->envp, variable);
299 }
300
301 /**
302  * g_subprocess_launcher_getenv:
303  * @self: a #GSubprocessLauncher
304  * @variable: (type filename): the environment variable to get
305  *
306  * Returns the value of the environment variable @variable in the
307  * environment of processes launched from this launcher.
308  *
309  * On UNIX, the returned string can be an arbitrary byte string.
310  * On Windows, it will be UTF-8.
311  *
312  * Returns: (nullable) (type filename): the value of the environment variable,
313  *     %NULL if unset
314  *
315  * Since: 2.40
316  **/
317 const gchar *
318 g_subprocess_launcher_getenv (GSubprocessLauncher *self,
319                               const gchar         *variable)
320 {
321   return g_environ_getenv (self->envp, variable);
322 }
323
324 /**
325  * g_subprocess_launcher_set_cwd:
326  * @self: a #GSubprocessLauncher
327  * @cwd: (type filename): the cwd for launched processes
328  *
329  * Sets the current working directory that processes will be launched
330  * with.
331  *
332  * By default processes are launched with the current working directory
333  * of the launching process at the time of launch.
334  *
335  * Since: 2.40
336  **/
337 void
338 g_subprocess_launcher_set_cwd (GSubprocessLauncher *self,
339                                const gchar         *cwd)
340 {
341   g_free (self->cwd);
342   self->cwd = g_strdup (cwd);
343 }
344
345 /**
346  * g_subprocess_launcher_set_flags:
347  * @self: a #GSubprocessLauncher
348  * @flags: #GSubprocessFlags
349  *
350  * Sets the flags on the launcher.
351  *
352  * The default flags are %G_SUBPROCESS_FLAGS_NONE.
353  *
354  * You may not set flags that specify conflicting options for how to
355  * handle a particular stdio stream (eg: specifying both
356  * %G_SUBPROCESS_FLAGS_STDIN_PIPE and
357  * %G_SUBPROCESS_FLAGS_STDIN_INHERIT).
358  *
359  * You may also not set a flag that conflicts with a previous call to a
360  * function like g_subprocess_launcher_set_stdin_file_path() or
361  * g_subprocess_launcher_take_stdout_fd().
362  *
363  * Since: 2.40
364  **/
365 void
366 g_subprocess_launcher_set_flags (GSubprocessLauncher *self,
367                                  GSubprocessFlags     flags)
368 {
369   const gchar *stdin_path = NULL, *stdout_path = NULL, *stderr_path = NULL;
370   gint stdin_fd = -1, stdout_fd = -1, stderr_fd = -1;
371
372 #ifdef G_OS_UNIX
373   stdin_fd = self->stdin_fd;
374   stdout_fd = self->stdout_fd;
375   stderr_fd = self->stderr_fd;
376   stdin_path = self->stdin_path;
377   stdout_path = self->stdout_path;
378   stderr_path = self->stderr_path;
379 #endif
380
381   if (verify_disposition ("stdin", flags & ALL_STDIN_FLAGS, stdin_fd, stdin_path) &&
382       verify_disposition ("stdout", flags & ALL_STDOUT_FLAGS, stdout_fd, stdout_path) &&
383       verify_disposition ("stderr", flags & ALL_STDERR_FLAGS, stderr_fd, stderr_path))
384     self->flags = flags;
385 }
386
387 #ifdef G_OS_UNIX
388 static void
389 assign_fd (gint *fd_ptr, gint fd)
390 {
391   gint flags;
392
393   if (*fd_ptr != -1)
394     close (*fd_ptr);
395
396   *fd_ptr = fd;
397
398   if (fd != -1)
399     {
400       /* best effort */
401       flags = fcntl (fd, F_GETFD);
402       if (~flags & FD_CLOEXEC)
403         fcntl (fd, F_SETFD, flags | FD_CLOEXEC);
404     }
405 }
406
407 /**
408  * g_subprocess_launcher_set_stdin_file_path:
409  * @self: a #GSubprocessLauncher
410  * @path: (type filename) (nullable): a filename or %NULL
411  *
412  * Sets the file path to use as the stdin for spawned processes.
413  *
414  * If @path is %NULL then any previously given path is unset.
415  *
416  * The file must exist or spawning the process will fail.
417  *
418  * You may not set a stdin file path if a stdin fd is already set or if
419  * the launcher flags contain any flags directing stdin elsewhere.
420  *
421  * This feature is only available on UNIX.
422  *
423  * Since: 2.40
424  **/
425 void
426 g_subprocess_launcher_set_stdin_file_path (GSubprocessLauncher *self,
427                                            const gchar         *path)
428 {
429   if (verify_disposition ("stdin", self->flags & ALL_STDIN_FLAGS, self->stdin_fd, path))
430     {
431       g_free (self->stdin_path);
432       self->stdin_path = g_strdup (path);
433     }
434 }
435
436 /**
437  * g_subprocess_launcher_take_stdin_fd:
438  * @self: a #GSubprocessLauncher
439  * @fd: a file descriptor, or -1
440  *
441  * Sets the file descriptor to use as the stdin for spawned processes.
442  *
443  * If @fd is -1 then any previously given fd is unset.
444  *
445  * Note that if your intention is to have the stdin of the calling
446  * process inherited by the child then %G_SUBPROCESS_FLAGS_STDIN_INHERIT
447  * is a better way to go about doing that.
448  *
449  * The passed @fd is noted but will not be touched in the current
450  * process.  It is therefore necessary that it be kept open by the
451  * caller until the subprocess is spawned.  The file descriptor will
452  * also not be explicitly closed on the child side, so it must be marked
453  * O_CLOEXEC if that's what you want.
454  *
455  * You may not set a stdin fd if a stdin file path is already set or if
456  * the launcher flags contain any flags directing stdin elsewhere.
457  *
458  * This feature is only available on UNIX.
459  *
460  * Since: 2.40
461  **/
462 void
463 g_subprocess_launcher_take_stdin_fd (GSubprocessLauncher *self,
464                                      gint                 fd)
465 {
466   if (verify_disposition ("stdin", self->flags & ALL_STDIN_FLAGS, fd, self->stdin_path))
467     assign_fd (&self->stdin_fd, fd);
468 }
469
470 /**
471  * g_subprocess_launcher_set_stdout_file_path:
472  * @self: a #GSubprocessLauncher
473  * @path: (type filename) (nullable): a filename or %NULL
474  *
475  * Sets the file path to use as the stdout for spawned processes.
476  *
477  * If @path is %NULL then any previously given path is unset.
478  *
479  * The file will be created or truncated when the process is spawned, as
480  * would be the case if using '>' at the shell.
481  *
482  * You may not set a stdout file path if a stdout fd is already set or
483  * if the launcher flags contain any flags directing stdout elsewhere.
484  *
485  * This feature is only available on UNIX.
486  *
487  * Since: 2.40
488  **/
489 void
490 g_subprocess_launcher_set_stdout_file_path (GSubprocessLauncher *self,
491                                             const gchar         *path)
492 {
493   if (verify_disposition ("stdout", self->flags & ALL_STDOUT_FLAGS, self->stdout_fd, path))
494     {
495       g_free (self->stdout_path);
496       self->stdout_path = g_strdup (path);
497     }
498 }
499
500 /**
501  * g_subprocess_launcher_take_stdout_fd:
502  * @self: a #GSubprocessLauncher
503  * @fd: a file descriptor, or -1
504  *
505  * Sets the file descriptor to use as the stdout for spawned processes.
506  *
507  * If @fd is -1 then any previously given fd is unset.
508  *
509  * Note that the default behaviour is to pass stdout through to the
510  * stdout of the parent process.
511  *
512  * The passed @fd is noted but will not be touched in the current
513  * process.  It is therefore necessary that it be kept open by the
514  * caller until the subprocess is spawned.  The file descriptor will
515  * also not be explicitly closed on the child side, so it must be marked
516  * O_CLOEXEC if that's what you want.
517  *
518  * You may not set a stdout fd if a stdout file path is already set or
519  * if the launcher flags contain any flags directing stdout elsewhere.
520  *
521  * This feature is only available on UNIX.
522  *
523  * Since: 2.40
524  **/
525 void
526 g_subprocess_launcher_take_stdout_fd (GSubprocessLauncher *self,
527                                       gint                 fd)
528 {
529   if (verify_disposition ("stdout", self->flags & ALL_STDOUT_FLAGS, fd, self->stdout_path))
530     assign_fd (&self->stdout_fd, fd);
531 }
532
533 /**
534  * g_subprocess_launcher_set_stderr_file_path:
535  * @self: a #GSubprocessLauncher
536  * @path: (type filename) (nullable): a filename or %NULL
537  *
538  * Sets the file path to use as the stderr for spawned processes.
539  *
540  * If @path is %NULL then any previously given path is unset.
541  *
542  * The file will be created or truncated when the process is spawned, as
543  * would be the case if using '2>' at the shell.
544  *
545  * If you want to send both stdout and stderr to the same file then use
546  * %G_SUBPROCESS_FLAGS_STDERR_MERGE.
547  *
548  * You may not set a stderr file path if a stderr fd is already set or
549  * if the launcher flags contain any flags directing stderr elsewhere.
550  *
551  * This feature is only available on UNIX.
552  *
553  * Since: 2.40
554  **/
555 void
556 g_subprocess_launcher_set_stderr_file_path (GSubprocessLauncher *self,
557                                             const gchar         *path)
558 {
559   if (verify_disposition ("stderr", self->flags & ALL_STDERR_FLAGS, self->stderr_fd, path))
560     {
561       g_free (self->stderr_path);
562       self->stderr_path = g_strdup (path);
563     }
564 }
565
566 /**
567  * g_subprocess_launcher_take_stderr_fd:
568  * @self: a #GSubprocessLauncher
569  * @fd: a file descriptor, or -1
570  *
571  * Sets the file descriptor to use as the stderr for spawned processes.
572  *
573  * If @fd is -1 then any previously given fd is unset.
574  *
575  * Note that the default behaviour is to pass stderr through to the
576  * stderr of the parent process.
577  *
578  * The passed @fd belongs to the #GSubprocessLauncher.  It will be
579  * automatically closed when the launcher is finalized.  The file
580  * descriptor will also be closed on the child side when executing the
581  * spawned process.
582  *
583  * You may not set a stderr fd if a stderr file path is already set or
584  * if the launcher flags contain any flags directing stderr elsewhere.
585  *
586  * This feature is only available on UNIX.
587  *
588  * Since: 2.40
589  **/
590 void
591 g_subprocess_launcher_take_stderr_fd (GSubprocessLauncher *self,
592                                      gint                 fd)
593 {
594   if (verify_disposition ("stderr", self->flags & ALL_STDERR_FLAGS, fd, self->stderr_path))
595     assign_fd (&self->stderr_fd, fd);
596 }
597
598 /**
599  * g_subprocess_launcher_take_fd:
600  * @self: a #GSubprocessLauncher
601  * @source_fd: File descriptor in parent process
602  * @target_fd: Target descriptor for child process
603  *
604  * Transfer an arbitrary file descriptor from parent process to the
605  * child.  This function takes ownership of the @source_fd; it will be closed
606  * in the parent when @self is freed.
607  *
608  * By default, all file descriptors from the parent will be closed.
609  * This function allows you to create (for example) a custom `pipe()` or
610  * `socketpair()` before launching the process, and choose the target
611  * descriptor in the child.
612  *
613  * An example use case is GNUPG, which has a command line argument
614  * `--passphrase-fd` providing a file descriptor number where it expects
615  * the passphrase to be written.
616  */
617 void
618 g_subprocess_launcher_take_fd (GSubprocessLauncher   *self,
619                                gint                   source_fd,
620                                gint                   target_fd)
621 {
622   if (self->source_fds != NULL && self->target_fds != NULL)
623     {
624       g_array_append_val (self->source_fds, source_fd);
625       g_array_append_val (self->target_fds, target_fd);
626     }
627 }
628
629 /**
630  * g_subprocess_launcher_close:
631  * @self: a #GSubprocessLauncher
632  *
633  * Closes all the file descriptors previously passed to the object with
634  * g_subprocess_launcher_take_fd(), g_subprocess_launcher_take_stderr_fd(), etc.
635  *
636  * After calling this method, any subsequent calls to g_subprocess_launcher_spawn() or g_subprocess_launcher_spawnv() will
637  * return %G_IO_ERROR_CLOSED. This method is idempotent if
638  * called more than once.
639  *
640  * This function is called automatically when the #GSubprocessLauncher
641  * is disposed, but is provided separately so that garbage collected
642  * language bindings can call it earlier to guarantee when FDs are closed.
643  *
644  * Since: 2.68
645  */
646 void
647 g_subprocess_launcher_close (GSubprocessLauncher *self)
648 {
649   guint i;
650
651   g_return_if_fail (G_IS_SUBPROCESS_LAUNCHER (self));
652
653   if (self->stdin_fd != -1)
654     close (self->stdin_fd);
655   self->stdin_fd = -1;
656
657   if (self->stdout_fd != -1)
658     close (self->stdout_fd);
659   self->stdout_fd = -1;
660
661   if (self->stderr_fd != -1)
662     close (self->stderr_fd);
663   self->stderr_fd = -1;
664
665   if (self->source_fds)
666     {
667       g_assert (self->target_fds != NULL);
668       g_assert (self->source_fds->len == self->target_fds->len);
669
670       /* Note: Don’t close the target_fds, as they’re only valid FDs in the
671        * child process. This code never executes in the child process. */
672       for (i = 0; i < self->source_fds->len; i++)
673         (void) close (g_array_index (self->source_fds, int, i));
674
675       g_clear_pointer (&self->source_fds, g_array_unref);
676       g_clear_pointer (&self->target_fds, g_array_unref);
677     }
678
679   self->closed_fd = TRUE;
680 }
681
682 /**
683  * g_subprocess_launcher_set_child_setup: (skip)
684  * @self: a #GSubprocessLauncher
685  * @child_setup: (closure user_data): a #GSpawnChildSetupFunc to use as the child setup function
686  * @user_data: user data for @child_setup
687  * @destroy_notify: a #GDestroyNotify for @user_data
688  *
689  * Sets up a child setup function.
690  *
691  * The child setup function will be called after fork() but before
692  * exec() on the child's side.
693  *
694  * @destroy_notify will not be automatically called on the child's side
695  * of the fork().  It will only be called when the last reference on the
696  * #GSubprocessLauncher is dropped or when a new child setup function is
697  * given.
698  *
699  * %NULL can be given as @child_setup to disable the functionality.
700  *
701  * Child setup functions are only available on UNIX.
702  *
703  * Since: 2.40
704  **/
705 void
706 g_subprocess_launcher_set_child_setup (GSubprocessLauncher  *self,
707                                        GSpawnChildSetupFunc  child_setup,
708                                        gpointer              user_data,
709                                        GDestroyNotify        destroy_notify)
710 {
711   if (self->child_setup_destroy_notify)
712     (* self->child_setup_destroy_notify) (self->child_setup_user_data);
713
714   self->child_setup_func = child_setup;
715   self->child_setup_user_data = user_data;
716   self->child_setup_destroy_notify = destroy_notify;
717 }
718 #endif
719
720 /**
721  * g_subprocess_launcher_spawn:
722  * @self: a #GSubprocessLauncher
723  * @error: Error
724  * @argv0: Command line arguments
725  * @...: Continued arguments, %NULL terminated
726  *
727  * Creates a #GSubprocess given a provided varargs list of arguments.
728  *
729  * Since: 2.40
730  * Returns: (transfer full): A new #GSubprocess, or %NULL on error (and @error will be set)
731  **/
732 GSubprocess *
733 g_subprocess_launcher_spawn (GSubprocessLauncher  *launcher,
734                              GError              **error,
735                              const gchar          *argv0,
736                              ...)
737 {
738   GSubprocess *result;
739   GPtrArray *args;
740   const gchar *arg;
741   va_list ap;
742
743   g_return_val_if_fail (argv0 != NULL && argv0[0] != '\0', NULL);
744   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
745
746   args = g_ptr_array_new ();
747
748   va_start (ap, argv0);
749   g_ptr_array_add (args, (gchar *) argv0);
750   while ((arg = va_arg (ap, const gchar *)))
751     g_ptr_array_add (args, (gchar *) arg);
752
753   g_ptr_array_add (args, NULL);
754   va_end (ap);
755
756   result = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
757
758   g_ptr_array_free (args, TRUE);
759
760   return result;
761
762 }
763
764 /**
765  * g_subprocess_launcher_spawnv:
766  * @self: a #GSubprocessLauncher
767  * @argv: (array zero-terminated=1) (element-type filename): Command line arguments
768  * @error: Error
769  *
770  * Creates a #GSubprocess given a provided array of arguments.
771  *
772  * Since: 2.40
773  * Returns: (transfer full): A new #GSubprocess, or %NULL on error (and @error will be set)
774  **/
775 GSubprocess *
776 g_subprocess_launcher_spawnv (GSubprocessLauncher  *launcher,
777                               const gchar * const  *argv,
778                               GError              **error)
779 {
780   GSubprocess *subprocess;
781
782   g_return_val_if_fail (argv != NULL && argv[0] != NULL && argv[0][0] != '\0', NULL);
783
784 #ifdef G_OS_UNIX
785   if (launcher->closed_fd)
786     {
787       g_set_error (error,
788                    G_IO_ERROR,
789                    G_IO_ERROR_CLOSED,
790                    "Can't spawn a new child because a passed file descriptor has been closed.");
791       return NULL;
792     }
793 #endif
794
795   subprocess = g_object_new (G_TYPE_SUBPROCESS,
796                              "argv", argv,
797                              "flags", launcher->flags,
798                              NULL);
799   g_subprocess_set_launcher (subprocess, launcher);
800
801   if (!g_initable_init (G_INITABLE (subprocess), NULL, error))
802     {
803       g_object_unref (subprocess);
804       return NULL;
805     }
806
807   return subprocess;
808 }