Imported Upstream version 2.50.2
[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  * 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.
10  *
11  * See the included COPYING file for more information.
12  *
13  * Authors: Colin Walters <walters@verbum.org>
14  *          Ryan Lortie <desrt@desrt.ca>
15  */
16
17 /**
18  * SECTION:gsubprocesslauncher
19  * @title: GSubprocess Launcher
20  * @short_description: Environment options for launching a child process
21  * @include: gio/gio.h
22  *
23  * This class contains a set of options for launching child processes,
24  * such as where its standard input and output will be directed, the
25  * argument list, the environment, and more.
26  *
27  * While the #GSubprocess class has high level functions covering
28  * popular cases, use of this class allows access to more advanced
29  * options.  It can also be used to launch multiple subprocesses with
30  * a similar configuration.
31  *
32  * Since: 2.40
33  */
34
35 #define ALL_STDIN_FLAGS         (G_SUBPROCESS_FLAGS_STDIN_PIPE |        \
36                                  G_SUBPROCESS_FLAGS_STDIN_INHERIT)
37 #define ALL_STDOUT_FLAGS        (G_SUBPROCESS_FLAGS_STDOUT_PIPE |       \
38                                  G_SUBPROCESS_FLAGS_STDOUT_SILENCE)
39 #define ALL_STDERR_FLAGS        (G_SUBPROCESS_FLAGS_STDERR_PIPE |       \
40                                  G_SUBPROCESS_FLAGS_STDERR_SILENCE |    \
41                                  G_SUBPROCESS_FLAGS_STDERR_MERGE)
42
43 #include "config.h"
44
45 #include "gsubprocesslauncher-private.h"
46 #include "gioenumtypes.h"
47 #include "gsubprocess.h"
48 #include "ginitable.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           GFlagsValue *value;
83
84           class = g_type_class_peek (G_TYPE_SUBPROCESS_FLAGS);
85           while ((value = g_flags_get_first_value (class, filtered_flags)))
86             {
87               g_string_append_printf (err, " %s", value->value_name);
88               filtered_flags &= value->value;
89             }
90
91           g_type_class_unref (class);
92         }
93
94       if (fd >= 0)
95         g_string_append_printf (err, " g_subprocess_launcher_take_%s_fd()", stream_name);
96
97       if (filename)
98         g_string_append_printf (err, " g_subprocess_launcher_set_%s_file_path()", stream_name);
99
100       g_critical ("You may specify at most one disposition for the %s stream, but you specified:%s.",
101                   stream_name, err->str);
102       g_string_free (err, TRUE);
103
104       return FALSE;
105     }
106
107   return TRUE;
108 }
109
110 static gboolean
111 verify_flags (GSubprocessFlags flags)
112 {
113   return verify_disposition ("stdin", flags & ALL_STDIN_FLAGS, -1, NULL) &&
114          verify_disposition ("stdout", flags & ALL_STDOUT_FLAGS, -1, NULL) &&
115          verify_disposition ("stderr", flags & ALL_STDERR_FLAGS, -1, NULL);
116 }
117
118 static void
119 g_subprocess_launcher_set_property (GObject *object, guint prop_id,
120                                     const GValue *value, GParamSpec *pspec)
121 {
122   GSubprocessLauncher *launcher = G_SUBPROCESS_LAUNCHER (object);
123
124   g_assert (prop_id == 1);
125
126   if (verify_flags (g_value_get_flags (value)))
127     launcher->flags = g_value_get_flags (value);
128 }
129
130 static void
131 g_subprocess_launcher_finalize (GObject *object)
132 {
133   GSubprocessLauncher *self = G_SUBPROCESS_LAUNCHER (object);
134
135 #ifdef G_OS_UNIX
136   guint i;
137
138   g_free (self->stdin_path);
139   g_free (self->stdout_path);
140   g_free (self->stderr_path);
141
142   if (self->stdin_fd != -1)
143     close (self->stdin_fd);
144
145   if (self->stdout_fd != -1)
146     close (self->stdout_fd);
147
148   if (self->stderr_fd != -1)
149     close (self->stderr_fd);
150
151   if (self->basic_fd_assignments)
152     {
153       for (i = 0; i < self->basic_fd_assignments->len; i++)
154         (void) close (g_array_index (self->basic_fd_assignments, int, i));
155       g_array_unref (self->basic_fd_assignments);
156     }
157   if (self->needdup_fd_assignments)
158     {
159       for (i = 0; i < self->needdup_fd_assignments->len; i += 2)
160         (void) close (g_array_index (self->needdup_fd_assignments, int, i));
161       g_array_unref (self->needdup_fd_assignments);
162     }
163
164   if (self->child_setup_destroy_notify)
165     (* self->child_setup_destroy_notify) (self->child_setup_user_data);
166 #endif
167
168   g_strfreev (self->envp);
169   g_free (self->cwd);
170
171   G_OBJECT_CLASS (g_subprocess_launcher_parent_class)->finalize (object);
172 }
173
174 static void
175 g_subprocess_launcher_init (GSubprocessLauncher  *self)
176 {
177   self->envp = g_get_environ ();
178
179 #ifdef G_OS_UNIX
180   self->stdin_fd = -1;
181   self->stdout_fd = -1;
182   self->stderr_fd = -1;
183   self->basic_fd_assignments = g_array_new (FALSE, 0, sizeof (int));
184   self->needdup_fd_assignments = g_array_new (FALSE, 0, sizeof (int));
185 #endif
186 }
187
188 static void
189 g_subprocess_launcher_class_init (GSubprocessLauncherClass *class)
190 {
191   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
192
193   gobject_class->set_property = g_subprocess_launcher_set_property;
194   gobject_class->finalize = g_subprocess_launcher_finalize;
195
196   g_object_class_install_property (gobject_class, 1,
197                                    g_param_spec_flags ("flags", "Flags", "GSubprocessFlags for launched processes",
198                                                        G_TYPE_SUBPROCESS_FLAGS, 0, G_PARAM_WRITABLE |
199                                                        G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY));
200 }
201
202 /**
203  * g_subprocess_launcher_new:
204  * @flags: #GSubprocessFlags
205  *
206  * Creates a new #GSubprocessLauncher.
207  *
208  * The launcher is created with the default options.  A copy of the
209  * environment of the calling process is made at the time of this call
210  * and will be used as the environment that the process is launched in.
211  *
212  * Since: 2.40
213  **/
214 GSubprocessLauncher *
215 g_subprocess_launcher_new (GSubprocessFlags flags)
216 {
217   if (!verify_flags (flags))
218     return NULL;
219
220   return g_object_new (G_TYPE_SUBPROCESS_LAUNCHER,
221                        "flags", flags,
222                        NULL);
223 }
224
225 /**
226  * g_subprocess_launcher_set_environ:
227  * @self: a #GSubprocess
228  * @env: (array zero-terminated=1): the replacement environment
229  *
230  * Replace the entire environment of processes launched from this
231  * launcher with the given 'environ' variable.
232  *
233  * Typically you will build this variable by using g_listenv() to copy
234  * the process 'environ' and using the functions g_environ_setenv(),
235  * g_environ_unsetenv(), etc.
236  *
237  * As an alternative, you can use g_subprocess_launcher_setenv(),
238  * g_subprocess_launcher_unsetenv(), etc.
239  *
240  * On UNIX, all strings in this array can be arbitrary byte strings.
241  * On Windows, they should be in UTF-8.
242  *
243  * Since: 2.40
244  **/
245 void
246 g_subprocess_launcher_set_environ (GSubprocessLauncher  *self,
247                                    gchar               **env)
248 {
249   g_strfreev (self->envp);
250   self->envp = g_strdupv (env);
251 }
252
253 /**
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
259  *
260  * Sets the environment variable @variable in the environment of
261  * processes launched from this launcher.
262  *
263  * On UNIX, both the variable's name and value can be arbitrary byte
264  * strings, except that the variable's name cannot contain '='.
265  * On Windows, they should be in UTF-8.
266  *
267  * Since: 2.40
268  **/
269 void
270 g_subprocess_launcher_setenv (GSubprocessLauncher *self,
271                               const gchar         *variable,
272                               const gchar         *value,
273                               gboolean             overwrite)
274 {
275   self->envp = g_environ_setenv (self->envp, variable, value, overwrite);
276 }
277
278 /**
279  * g_subprocess_launcher_unsetenv:
280  * @self: a #GSubprocess
281  * @variable: the environment variable to unset, must not contain '='
282  *
283  * Removes the environment variable @variable from the environment of
284  * processes launched from this launcher.
285  *
286  * On UNIX, the variable's name can be an arbitrary byte string not
287  * containing '='. On Windows, it should be in UTF-8.
288  *
289  * Since: 2.40
290  **/
291 void
292 g_subprocess_launcher_unsetenv (GSubprocessLauncher *self,
293                                 const gchar         *variable)
294 {
295   self->envp = g_environ_unsetenv (self->envp, variable);
296 }
297
298 /**
299  * g_subprocess_launcher_getenv:
300  * @self: a #GSubprocess
301  * @variable: the environment variable to get
302  *
303  * Returns the value of the environment variable @variable in the
304  * environment of processes launched from this launcher.
305  *
306  * On UNIX, the returned string can be an arbitrary byte string.
307  * On Windows, it will be UTF-8.
308  *
309  * Returns: the value of the environment variable, %NULL if unset
310  *
311  * Since: 2.40
312  **/
313 const gchar *
314 g_subprocess_launcher_getenv (GSubprocessLauncher *self,
315                               const gchar         *variable)
316 {
317   return g_environ_getenv (self->envp, variable);
318 }
319
320 /**
321  * g_subprocess_launcher_set_cwd:
322  * @self: a #GSubprocess
323  * @cwd: (type filename): the cwd for launched processes
324  *
325  * Sets the current working directory that processes will be launched
326  * with.
327  *
328  * By default processes are launched with the current working directory
329  * of the launching process at the time of launch.
330  *
331  * Since: 2.40
332  **/
333 void
334 g_subprocess_launcher_set_cwd (GSubprocessLauncher *self,
335                                const gchar         *cwd)
336 {
337   g_free (self->cwd);
338   self->cwd = g_strdup (cwd);
339 }
340
341 /**
342  * g_subprocess_launcher_set_flags:
343  * @self: a #GSubprocessLauncher
344  * @flags: #GSubprocessFlags
345  *
346  * Sets the flags on the launcher.
347  *
348  * The default flags are %G_SUBPROCESS_FLAGS_NONE.
349  *
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).
354  *
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().
358  *
359  * Since: 2.40
360  **/
361 void
362 g_subprocess_launcher_set_flags (GSubprocessLauncher *self,
363                                  GSubprocessFlags     flags)
364 {
365   const gchar *stdin_path = NULL, *stdout_path = NULL, *stderr_path = NULL;
366   gint stdin_fd = -1, stdout_fd = -1, stderr_fd = -1;
367
368 #ifdef G_OS_UNIX
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;
375 #endif
376
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))
380     self->flags = flags;
381 }
382
383 #ifdef G_OS_UNIX
384 static void
385 assign_fd (gint *fd_ptr, gint fd)
386 {
387   gint flags;
388
389   if (*fd_ptr != -1)
390     close (*fd_ptr);
391
392   *fd_ptr = fd;
393
394   if (fd != -1)
395     {
396       /* best effort */
397       flags = fcntl (fd, F_GETFD);
398       if (~flags & FD_CLOEXEC)
399         fcntl (fd, F_SETFD, flags | FD_CLOEXEC);
400     }
401 }
402
403 /**
404  * g_subprocess_launcher_set_stdin_file_path:
405  * @self: a #GSubprocessLauncher
406  * @path: (type filename) (nullable: a filename or %NULL
407  *
408  * Sets the file path to use as the stdin for spawned processes.
409  *
410  * If @path is %NULL then any previously given path is unset.
411  *
412  * The file must exist or spawning the process will fail.
413  *
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.
416  *
417  * This feature is only available on UNIX.
418  *
419  * Since: 2.40
420  **/
421 void
422 g_subprocess_launcher_set_stdin_file_path (GSubprocessLauncher *self,
423                                            const gchar         *path)
424 {
425   if (verify_disposition ("stdin", self->flags & ALL_STDIN_FLAGS, self->stdin_fd, path))
426     {
427       g_free (self->stdin_path);
428       self->stdin_path = g_strdup (path);
429     }
430 }
431
432 /**
433  * g_subprocess_launcher_take_stdin_fd:
434  * @self: a #GSubprocessLauncher
435  * @fd: a file descriptor, or -1
436  *
437  * Sets the file descriptor to use as the stdin for spawned processes.
438  *
439  * If @fd is -1 then any previously given fd is unset.
440  *
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.
444  *
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.
450  *
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.
453  *
454  * This feature is only available on UNIX.
455  *
456  * Since: 2.40
457  **/
458 void
459 g_subprocess_launcher_take_stdin_fd (GSubprocessLauncher *self,
460                                      gint                 fd)
461 {
462   if (verify_disposition ("stdin", self->flags & ALL_STDIN_FLAGS, fd, self->stdin_path))
463     assign_fd (&self->stdin_fd, fd);
464 }
465
466 /**
467  * g_subprocess_launcher_set_stdout_file_path:
468  * @self: a #GSubprocessLauncher
469  * @path: (type filename) (nullable): a filename or %NULL
470  *
471  * Sets the file path to use as the stdout for spawned processes.
472  *
473  * If @path is %NULL then any previously given path is unset.
474  *
475  * The file will be created or truncated when the process is spawned, as
476  * would be the case if using '>' at the shell.
477  *
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.
480  *
481  * This feature is only available on UNIX.
482  *
483  * Since: 2.40
484  **/
485 void
486 g_subprocess_launcher_set_stdout_file_path (GSubprocessLauncher *self,
487                                             const gchar         *path)
488 {
489   if (verify_disposition ("stdout", self->flags & ALL_STDOUT_FLAGS, self->stdout_fd, path))
490     {
491       g_free (self->stdout_path);
492       self->stdout_path = g_strdup (path);
493     }
494 }
495
496 /**
497  * g_subprocess_launcher_take_stdout_fd:
498  * @self: a #GSubprocessLauncher
499  * @fd: a file descriptor, or -1
500  *
501  * Sets the file descriptor to use as the stdout for spawned processes.
502  *
503  * If @fd is -1 then any previously given fd is unset.
504  *
505  * Note that the default behaviour is to pass stdout through to the
506  * stdout of the parent process.
507  *
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.
513  *
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.
516  *
517  * This feature is only available on UNIX.
518  *
519  * Since: 2.40
520  **/
521 void
522 g_subprocess_launcher_take_stdout_fd (GSubprocessLauncher *self,
523                                       gint                 fd)
524 {
525   if (verify_disposition ("stdout", self->flags & ALL_STDOUT_FLAGS, fd, self->stdout_path))
526     assign_fd (&self->stdout_fd, fd);
527 }
528
529 /**
530  * g_subprocess_launcher_set_stderr_file_path:
531  * @self: a #GSubprocessLauncher
532  * @path: (type filename) (nullable): a filename or %NULL
533  *
534  * Sets the file path to use as the stderr for spawned processes.
535  *
536  * If @path is %NULL then any previously given path is unset.
537  *
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.
540  *
541  * If you want to send both stdout and stderr to the same file then use
542  * %G_SUBPROCESS_FLAGS_STDERR_MERGE.
543  *
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.
546  *
547  * This feature is only available on UNIX.
548  *
549  * Since: 2.40
550  **/
551 void
552 g_subprocess_launcher_set_stderr_file_path (GSubprocessLauncher *self,
553                                             const gchar         *path)
554 {
555   if (verify_disposition ("stderr", self->flags & ALL_STDERR_FLAGS, self->stderr_fd, path))
556     {
557       g_free (self->stderr_path);
558       self->stderr_path = g_strdup (path);
559     }
560 }
561
562 /**
563  * g_subprocess_launcher_take_stderr_fd:
564  * @self: a #GSubprocessLauncher
565  * @fd: a file descriptor, or -1
566  *
567  * Sets the file descriptor to use as the stderr for spawned processes.
568  *
569  * If @fd is -1 then any previously given fd is unset.
570  *
571  * Note that the default behaviour is to pass stderr through to the
572  * stderr of the parent process.
573  *
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
577  * spawned process.
578  *
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.
581  *
582  * This feature is only available on UNIX.
583  *
584  * Since: 2.40
585  **/
586 void
587 g_subprocess_launcher_take_stderr_fd (GSubprocessLauncher *self,
588                                      gint                 fd)
589 {
590   if (verify_disposition ("stderr", self->flags & ALL_STDERR_FLAGS, fd, self->stderr_path))
591     assign_fd (&self->stderr_fd, fd);
592 }
593
594 /**
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
599  *
600  * Transfer an arbitrary file descriptor from parent process to the
601  * child.  This function takes "ownership" of the fd; it will be closed
602  * in the parent when @self is freed.
603  *
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.
608  *
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.
612  */
613 void
614 g_subprocess_launcher_take_fd (GSubprocessLauncher   *self,
615                                gint                   source_fd,
616                                gint                   target_fd)
617 {
618   if (source_fd == target_fd)
619     {
620       g_array_append_val (self->basic_fd_assignments, source_fd);
621     }
622   else
623     {
624       g_array_append_val (self->needdup_fd_assignments, source_fd);
625       g_array_append_val (self->needdup_fd_assignments, target_fd);
626     }
627 }
628
629 /**
630  * g_subprocess_launcher_set_child_setup:
631  * @self: a #GSubprocessLauncher
632  * @child_setup: a #GSpawnChildSetupFunc to use as the child setup function
633  * @user_data: user data for @child_setup
634  * @destroy_notify: a #GDestroyNotify for @user_data
635  *
636  * Sets up a child setup function.
637  *
638  * The child setup function will be called after fork() but before
639  * exec() on the child's side.
640  *
641  * @destroy_notify will not be automatically called on the child's side
642  * of the fork().  It will only be called when the last reference on the
643  * #GSubprocessLauncher is dropped or when a new child setup function is
644  * given.
645  *
646  * %NULL can be given as @child_setup to disable the functionality.
647  *
648  * Child setup functions are only available on UNIX.
649  *
650  * Since: 2.40
651  **/
652 void
653 g_subprocess_launcher_set_child_setup (GSubprocessLauncher  *self,
654                                        GSpawnChildSetupFunc  child_setup,
655                                        gpointer              user_data,
656                                        GDestroyNotify        destroy_notify)
657 {
658   if (self->child_setup_destroy_notify)
659     (* self->child_setup_destroy_notify) (self->child_setup_user_data);
660
661   self->child_setup_func = child_setup;
662   self->child_setup_user_data = user_data;
663   self->child_setup_destroy_notify = destroy_notify;
664 }
665 #endif
666
667 /**
668  * g_subprocess_launcher_spawn:
669  * @self: a #GSubprocessLauncher
670  * @error: Error
671  * @argv0: Command line arguments
672  * @...: Continued arguments, %NULL terminated
673  *
674  * Creates a #GSubprocess given a provided varargs list of arguments.
675  *
676  * Since: 2.40
677  * Returns: (transfer full): A new #GSubprocess, or %NULL on error (and @error will be set)
678  **/
679 GSubprocess *
680 g_subprocess_launcher_spawn (GSubprocessLauncher  *launcher,
681                              GError              **error,
682                              const gchar          *argv0,
683                              ...)
684 {
685   GSubprocess *result;
686   GPtrArray *args;
687   const gchar *arg;
688   va_list ap;
689
690   g_return_val_if_fail (argv0 != NULL && argv0[0] != '\0', NULL);
691   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
692
693   args = g_ptr_array_new ();
694
695   va_start (ap, argv0);
696   g_ptr_array_add (args, (gchar *) argv0);
697   while ((arg = va_arg (ap, const gchar *)))
698     g_ptr_array_add (args, (gchar *) arg);
699
700   g_ptr_array_add (args, NULL);
701   va_end (ap);
702
703   result = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
704
705   g_ptr_array_free (args, TRUE);
706
707   return result;
708
709 }
710
711 /**
712  * g_subprocess_launcher_spawnv:
713  * @self: a #GSubprocessLauncher
714  * @argv: (array zero-terminated=1) (element-type utf8): Command line arguments
715  * @error: Error
716  *
717  * Creates a #GSubprocess given a provided array of arguments.
718  *
719  * Since: 2.40
720  * Returns: (transfer full): A new #GSubprocess, or %NULL on error (and @error will be set)
721  **/
722 GSubprocess *
723 g_subprocess_launcher_spawnv (GSubprocessLauncher  *launcher,
724                               const gchar * const  *argv,
725                               GError              **error)
726 {
727   GSubprocess *subprocess;
728
729   g_return_val_if_fail (argv != NULL && argv[0] != NULL && argv[0][0] != '\0', NULL);
730
731   subprocess = g_object_new (G_TYPE_SUBPROCESS,
732                              "argv", argv,
733                              "flags", launcher->flags,
734                              NULL);
735   g_subprocess_set_launcher (subprocess, launcher);
736
737   if (!g_initable_init (G_INITABLE (subprocess), NULL, error))
738     {
739       g_object_unref (subprocess);
740       return NULL;
741     }
742
743   return subprocess;
744 }