96f8454fe3c985b36084fa1533f0d94764c62472
[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  *
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 #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.
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
49 #ifdef G_OS_UNIX
50 #include <unistd.h>
51 #include <fcntl.h>
52 #endif
53
54 typedef GObjectClass GSubprocessLauncherClass;
55
56 G_DEFINE_TYPE (GSubprocessLauncher, g_subprocess_launcher, G_TYPE_OBJECT);
57
58 static gboolean
59 verify_disposition (const gchar      *stream_name,
60                     GSubprocessFlags  filtered_flags,
61                     gint              fd,
62                     const gchar      *filename)
63 {
64   guint n_bits;
65
66   if (!filtered_flags)
67     n_bits = 0;
68   else if (((filtered_flags - 1) & filtered_flags) == 0)
69     n_bits = 1;
70   else
71     n_bits = 2; /* ...or more */
72
73   if (n_bits + (fd >= 0) + (filename != NULL) > 1)
74     {
75       GString *err;
76
77       err = g_string_new (NULL);
78       if (n_bits)
79         {
80           GFlagsClass *class;
81           GFlagsValue *value;
82
83           class = g_type_class_peek (G_TYPE_SUBPROCESS_FLAGS);
84           while ((value = g_flags_get_first_value (class, filtered_flags)))
85             {
86               g_string_append_printf (err, " %s", value->value_name);
87               filtered_flags &= value->value;
88             }
89
90           g_type_class_unref (class);
91         }
92
93       if (fd >= 0)
94         g_string_append_printf (err, " g_subprocess_launcher_take_%s_fd()", stream_name);
95
96       if (filename)
97         g_string_append_printf (err, " g_subprocess_launcher_set_%s_file_path()", stream_name);
98
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);
102
103       return FALSE;
104     }
105
106   return TRUE;
107 }
108
109 static gboolean
110 verify_flags (GSubprocessFlags flags)
111 {
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);
115 }
116
117 static void
118 g_subprocess_launcher_set_property (GObject *object, guint prop_id,
119                                     const GValue *value, GParamSpec *pspec)
120 {
121   GSubprocessLauncher *launcher = G_SUBPROCESS_LAUNCHER (object);
122
123   g_assert (prop_id == 1);
124
125   if (verify_flags (g_value_get_flags (value)))
126     launcher->flags = g_value_get_flags (value);
127 }
128
129 static void
130 g_subprocess_launcher_finalize (GObject *object)
131 {
132   GSubprocessLauncher *self = G_SUBPROCESS_LAUNCHER (object);
133
134 #ifdef G_OS_UNIX
135   guint i;
136
137   g_free (self->stdin_path);
138   g_free (self->stdout_path);
139   g_free (self->stderr_path);
140
141   if (self->stdin_fd != -1)
142     close (self->stdin_fd);
143
144   if (self->stdout_fd != -1)
145     close (self->stdout_fd);
146
147   if (self->stderr_fd != -1)
148     close (self->stderr_fd);
149
150   if (self->basic_fd_assignments)
151     {
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);
155     }
156   if (self->needdup_fd_assignments)
157     {
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);
161     }
162
163   if (self->child_setup_destroy_notify)
164     (* self->child_setup_destroy_notify) (self->child_setup_user_data);
165 #endif
166
167   g_strfreev (self->envp);
168   g_free (self->cwd);
169
170   G_OBJECT_CLASS (g_subprocess_launcher_parent_class)->finalize (object);
171 }
172
173 static void
174 g_subprocess_launcher_init (GSubprocessLauncher  *self)
175 {
176   self->envp = g_listenv ();
177
178 #ifdef G_OS_UNIX
179   self->stdin_fd = -1;
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));
184 #endif
185 }
186
187 static void
188 g_subprocess_launcher_class_init (GSubprocessLauncherClass *class)
189 {
190   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
191
192   gobject_class->set_property = g_subprocess_launcher_set_property;
193   gobject_class->finalize = g_subprocess_launcher_finalize;
194
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));
199 }
200
201 /**
202  * g_subprocess_launcher_new:
203  * @flags: #GSubprocessFlags
204  *
205  * Creates a new #GSubprocessLauncher.
206  *
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.
210  *
211  * Since: 2.40
212  **/
213 GSubprocessLauncher *
214 g_subprocess_launcher_new (GSubprocessFlags flags)
215 {
216   if (!verify_flags (flags))
217     return NULL;
218
219   return g_object_new (G_TYPE_SUBPROCESS_LAUNCHER,
220                        "flags", flags,
221                        NULL);
222 }
223
224 /**
225  * g_subprocess_launcher_set_environ:
226  * @self: a #GSubprocess
227  * @environ: the replacement environment
228  *
229  * Replace the entire environment of processes launched from this
230  * launcher with the given 'environ' variable.
231  *
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.
235  *
236  * As an alternative, you can use g_subprocess_launcher_setenv(),
237  * g_subprocess_launcher_unsetenv(), etc.
238  *
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.
242  *
243  * Since: 2.40
244  **/
245 void
246 g_subprocess_launcher_set_environ (GSubprocessLauncher  *self,
247                                    gchar               **environ)
248 {
249   g_strfreev (self->envp);
250   self->envp = g_strdupv (environ);
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  * 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.
266  *
267  *
268  * Since: 2.40
269  **/
270 void
271 g_subprocess_launcher_setenv (GSubprocessLauncher *self,
272                               const gchar         *variable,
273                               const gchar         *value,
274                               gboolean             overwrite)
275 {
276   self->envp = g_environ_setenv (self->envp, variable, value, overwrite);
277 }
278
279 /**
280  * g_subprocess_launcher_unsetenv:
281  * @self: a #GSubprocess
282  * @variable: the environment variable to unset, must not contain '='
283  *
284  * Removes the environment variable @variable from the environment of
285  * processes launched from this launcher.
286  *
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.
290  *
291  * Since: 2.40
292  **/
293 void
294 g_subprocess_launcher_unsetenv (GSubprocessLauncher *self,
295                                 const gchar         *variable)
296 {
297   self->envp = g_environ_unsetenv (self->envp, variable);
298 }
299
300 /**
301  * g_subprocess_launcher_getenv:
302  * @self: a #GSubprocess
303  * @variable: the environment variable to get
304  *
305  * Returns the value of the environment variable @variable in the
306  * environment of processes launched from this launcher.
307  *
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
310  * be UTF-8.
311  *
312  * Returns: the value of the environment variable, %NULL if unset
313  *
314  * Since: 2.40
315  **/
316 const gchar *
317 g_subprocess_launcher_getenv (GSubprocessLauncher *self,
318                               const gchar         *variable)
319 {
320   return g_environ_getenv (self->envp, variable);
321 }
322
323 /**
324  * g_subprocess_launcher_set_cwd:
325  * @self: a #GSubprocess
326  * @cwd: the cwd for launched processes
327  *
328  * Sets the current working directory that processes will be launched
329  * with.
330  *
331  * By default processes are launched with the current working directory
332  * of the launching process at the time of launch.
333  *
334  * Since: 2.40
335  **/
336 void
337 g_subprocess_launcher_set_cwd (GSubprocessLauncher *self,
338                                const gchar         *cwd)
339 {
340   g_free (self->cwd);
341   self->cwd = g_strdup (cwd);
342 }
343
344 /**
345  * g_subprocess_launcher_set_flags:
346  * @self: a #GSubprocessLauncher
347  * @flags: #GSubprocessFlags
348  *
349  * Sets the flags on the launcher.
350  *
351  * The default flags are %G_SUBPROCESS_FLAGS_NONE.
352  *
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).
357  *
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().
361  *
362  * Since: 2.40
363  **/
364 void
365 g_subprocess_launcher_set_flags (GSubprocessLauncher *self,
366                                  GSubprocessFlags     flags)
367 {
368   const gchar *stdin_path = NULL, *stdout_path = NULL, *stderr_path = NULL;
369   gint stdin_fd = -1, stdout_fd = -1, stderr_fd = -1;
370
371 #ifdef G_OS_UNIX
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;
378 #endif
379
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))
383     self->flags = flags;
384 }
385
386 #ifdef G_OS_UNIX
387 static void
388 assign_fd (gint *fd_ptr, gint fd)
389 {
390   gint flags;
391
392   if (*fd_ptr != -1)
393     close (*fd_ptr);
394
395   *fd_ptr = fd;
396
397   if (fd != -1)
398     {
399       /* best effort */
400       flags = fcntl (fd, F_GETFD);
401       if (~flags & FD_CLOEXEC)
402         fcntl (fd, F_SETFD, flags | FD_CLOEXEC);
403     }
404 }
405
406 /**
407  * g_subprocess_launcher_set_stdin_file_path:
408  * @self: a #GSubprocessLauncher
409  * @path: a filename or %NULL
410  *
411  * Sets the file path to use as the stdin for spawned processes.
412  *
413  * If @path is %NULL then any previously given path is unset.
414  *
415  * The file must exist or spawning the process will fail.
416  *
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.
419  *
420  * This feature is only available on UNIX.
421  *
422  * Since: 2.40
423  **/
424 void
425 g_subprocess_launcher_set_stdin_file_path (GSubprocessLauncher *self,
426                                            const gchar         *path)
427 {
428   if (verify_disposition ("stdin", self->flags & ALL_STDIN_FLAGS, self->stdin_fd, path))
429     {
430       g_free (self->stdin_path);
431       self->stdin_path = g_strdup (path);
432     }
433 }
434
435 /**
436  * g_subprocess_launcher_take_stdin_fd:
437  * @self: a #GSubprocessLauncher
438  * @fd: a file descriptor, or -1
439  *
440  * Sets the file descriptor to use as the stdin for spawned processes.
441  *
442  * If @fd is -1 then any previously given fd is unset.
443  *
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.
447  *
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.
453  *
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.
456  *
457  * This feature is only available on UNIX.
458  *
459  * Since: 2.40
460  **/
461 void
462 g_subprocess_launcher_take_stdin_fd (GSubprocessLauncher *self,
463                                      gint                 fd)
464 {
465   if (verify_disposition ("stdin", self->flags & ALL_STDIN_FLAGS, fd, self->stdin_path))
466     assign_fd (&self->stdin_fd, fd);
467 }
468
469 /**
470  * g_subprocess_launcher_set_stdout_file_path:
471  * @self: a #GSubprocessLauncher
472  * @path: a filename or %NULL
473  *
474  * Sets the file path to use as the stdout for spawned processes.
475  *
476  * If @path is %NULL then any previously given path is unset.
477  *
478  * The file will be created or truncated when the process is spawned, as
479  * would be the case if using '>' at the shell.
480  *
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.
483  *
484  * This feature is only available on UNIX.
485  *
486  * Since: 2.40
487  **/
488 void
489 g_subprocess_launcher_set_stdout_file_path (GSubprocessLauncher *self,
490                                             const gchar         *path)
491 {
492   if (verify_disposition ("stdout", self->flags & ALL_STDOUT_FLAGS, self->stdout_fd, path))
493     {
494       g_free (self->stdout_path);
495       self->stdout_path = g_strdup (path);
496     }
497 }
498
499 /**
500  * g_subprocess_launcher_take_stdout_fd:
501  * @self: a #GSubprocessLauncher
502  * @fd: a file descriptor, or -1
503  *
504  * Sets the file descriptor to use as the stdout for spawned processes.
505  *
506  * If @fd is -1 then any previously given fd is unset.
507  *
508  * Note that the default behaviour is to pass stdout through to the
509  * stdout of the parent process.
510  *
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.
516  *
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.
519  *
520  * This feature is only available on UNIX.
521  *
522  * Since: 2.40
523  **/
524 void
525 g_subprocess_launcher_take_stdout_fd (GSubprocessLauncher *self,
526                                       gint                 fd)
527 {
528   if (verify_disposition ("stdout", self->flags & ALL_STDOUT_FLAGS, fd, self->stdout_path))
529     assign_fd (&self->stdout_fd, fd);
530 }
531
532 /**
533  * g_subprocess_launcher_set_stderr_file_path:
534  * @self: a #GSubprocessLauncher
535  * @path: a filename or %NULL
536  *
537  * Sets the file path to use as the stderr for spawned processes.
538  *
539  * If @path is %NULL then any previously given path is unset.
540  *
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.
543  *
544  * If you want to send both stdout and stderr to the same file then use
545  * %G_SUBPROCESS_FLAGS_STDERR_MERGE.
546  *
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.
549  *
550  * This feature is only available on UNIX.
551  *
552  * Since: 2.40
553  **/
554 void
555 g_subprocess_launcher_set_stderr_file_path (GSubprocessLauncher *self,
556                                             const gchar         *path)
557 {
558   if (verify_disposition ("stderr", self->flags & ALL_STDERR_FLAGS, self->stderr_fd, path))
559     {
560       g_free (self->stderr_path);
561       self->stderr_path = g_strdup (path);
562     }
563 }
564
565 /**
566  * g_subprocess_launcher_take_stderr_fd:
567  * @self: a #GSubprocessLauncher
568  * @fd: a file descriptor, or -1
569  *
570  * Sets the file descriptor to use as the stderr for spawned processes.
571  *
572  * If @fd is -1 then any previously given fd is unset.
573  *
574  * Note that the default behaviour is to pass stderr through to the
575  * stderr of the parent process.
576  *
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
580  * spawned process.
581  *
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.
584  *
585  * This feature is only available on UNIX.
586  *
587  * Since: 2.40
588  **/
589 void
590 g_subprocess_launcher_take_stderr_fd (GSubprocessLauncher *self,
591                                      gint                 fd)
592 {
593   if (verify_disposition ("stderr", self->flags & ALL_STDERR_FLAGS, fd, self->stderr_path))
594     assign_fd (&self->stderr_fd, fd);
595 }
596
597 /**
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
602  *
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.
606  *
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.
611  *
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.
615  */
616 void
617 g_subprocess_launcher_take_fd (GSubprocessLauncher   *self,
618                                gint                   source_fd,
619                                gint                   target_fd)
620 {
621   if (source_fd == target_fd)
622     {
623       g_array_append_val (self->basic_fd_assignments, source_fd);
624     }
625   else
626     {
627       g_array_append_val (self->needdup_fd_assignments, source_fd);
628       g_array_append_val (self->needdup_fd_assignments, target_fd);
629     }
630 }
631
632 /**
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
638  *
639  * Sets up a child setup function.
640  *
641  * The child setup function will be called after fork() but before
642  * exec() on the child's side.
643  *
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
647  * given.
648  *
649  * %NULL can be given as @child_setup to disable the functionality.
650  *
651  * Child setup functions are only available on UNIX.
652  *
653  * Since: 2.40
654  **/
655 void
656 g_subprocess_launcher_set_child_setup (GSubprocessLauncher  *self,
657                                        GSpawnChildSetupFunc  child_setup,
658                                        gpointer              user_data,
659                                        GDestroyNotify        destroy_notify)
660 {
661   if (self->child_setup_destroy_notify)
662     (* self->child_setup_destroy_notify) (self->child_setup_user_data);
663
664   self->child_setup_func = child_setup;
665   self->child_setup_user_data = user_data;
666   self->child_setup_destroy_notify = destroy_notify;
667 }
668 #endif
669
670 /**
671  * g_subprocess_launcher_spawn:
672  * @self: a #GSubprocessLauncher
673  * @error: Error
674  * @argv0: Command line arguments
675  * @...: Continued arguments, %NULL terminated
676  *
677  * A convenience helper for creating a #GSubprocess given a provided
678  * varargs list of arguments.
679  *
680  * Since: 2.40
681  * Returns: (transfer full): A new #GSubprocess, or %NULL on error (and @error will be set)
682  **/
683 GSubprocess *
684 g_subprocess_launcher_spawn (GSubprocessLauncher  *launcher,
685                              GError              **error,
686                              const gchar          *argv0,
687                              ...)
688 {
689   GSubprocess *result;
690   GPtrArray *args;
691   const gchar *arg;
692   va_list ap;
693
694   g_return_val_if_fail (argv0 != NULL && argv0[0] != '\0', NULL);
695   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
696
697   args = g_ptr_array_new ();
698
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);
703
704   g_ptr_array_add (args, NULL);
705
706   result = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
707
708   g_ptr_array_free (args, TRUE);
709
710   return result;
711
712 }
713
714 /**
715  * g_subprocess_launcher_spawnv:
716  * @self: a #GSubprocessLauncher
717  * @argv: Command line arguments
718  * @error: Error
719  *
720  * A convenience helper for creating a #GSubprocess given a provided
721  * array of arguments.
722  *
723  * Since: 2.40
724  * Returns: (transfer full): A new #GSubprocess, or %NULL on error (and @error will be set)
725  **/
726 GSubprocess *
727 g_subprocess_launcher_spawnv (GSubprocessLauncher  *launcher,
728                               const gchar * const  *argv,
729                               GError              **error)
730 {
731   GSubprocess *subprocess;
732
733   g_return_val_if_fail (argv != NULL && argv[0] != NULL && argv[0][0] != '\0', NULL);
734
735   subprocess = g_object_new (G_TYPE_SUBPROCESS,
736                              "argv", argv,
737                              "flags", launcher->flags,
738                              NULL);
739   g_subprocess_set_launcher (subprocess, launcher);
740
741   if (!g_initable_init (G_INITABLE (subprocess), NULL, error))
742     {
743       g_object_unref (subprocess);
744       return NULL;
745     }
746
747   return subprocess;
748 }