nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 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: 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: 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: 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: 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: 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 }