Branch data Line data Source code
1 : : /* GIO - GLib Input, Output and Streaming Library
2 : : *
3 : : * Copyright © 2012, 2013 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 : : * GSubprocess:
21 : : *
22 : : * `GSubprocess` allows the creation of and interaction with child
23 : : * processes.
24 : : *
25 : : * Processes can be communicated with using standard GIO-style APIs (ie:
26 : : * [class@Gio.InputStream], [class@Gio.OutputStream]). There are GIO-style APIs
27 : : * to wait for process termination (ie: cancellable and with an asynchronous
28 : : * variant).
29 : : *
30 : : * There is an API to force a process to terminate, as well as a
31 : : * race-free API for sending UNIX signals to a subprocess.
32 : : *
33 : : * One major advantage that GIO brings over the core GLib library is
34 : : * comprehensive API for asynchronous I/O, such
35 : : * [method@Gio.OutputStream.splice_async]. This makes `GSubprocess`
36 : : * significantly more powerful and flexible than equivalent APIs in
37 : : * some other languages such as the `subprocess.py`
38 : : * included with Python. For example, using `GSubprocess` one could
39 : : * create two child processes, reading standard output from the first,
40 : : * processing it, and writing to the input stream of the second, all
41 : : * without blocking the main loop.
42 : : *
43 : : * A powerful [method@Gio.Subprocess.communicate] API is provided similar to the
44 : : * `communicate()` method of `subprocess.py`. This enables very easy
45 : : * interaction with a subprocess that has been opened with pipes.
46 : : *
47 : : * `GSubprocess` defaults to tight control over the file descriptors open
48 : : * in the child process, avoiding dangling-FD issues that are caused by
49 : : * a simple `fork()`/`exec()`. The only open file descriptors in the
50 : : * spawned process are ones that were explicitly specified by the
51 : : * `GSubprocess` API (unless `G_SUBPROCESS_FLAGS_INHERIT_FDS` was
52 : : * specified).
53 : : *
54 : : * `GSubprocess` will quickly reap all child processes as they exit,
55 : : * avoiding ‘zombie processes’ remaining around for long periods of
56 : : * time. [method@Gio.Subprocess.wait] can be used to wait for this to happen,
57 : : * but it will happen even without the call being explicitly made.
58 : : *
59 : : * As a matter of principle, `GSubprocess` has no API that accepts
60 : : * shell-style space-separated strings. It will, however, match the
61 : : * typical shell behaviour of searching the `PATH` for executables that do
62 : : * not contain a directory separator in their name. By default, the `PATH`
63 : : * of the current process is used. You can specify
64 : : * `G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP` to use the `PATH` of the
65 : : * launcher environment instead.
66 : : *
67 : : * `GSubprocess` attempts to have a very simple API for most uses (ie:
68 : : * spawning a subprocess with arguments and support for most typical
69 : : * kinds of input and output redirection). See [ctor@Gio.Subprocess.new]. The
70 : : * [class@Gio.SubprocessLauncher] API is provided for more complicated cases
71 : : * (advanced types of redirection, environment variable manipulation,
72 : : * change of working directory, child setup functions, etc).
73 : : *
74 : : * A typical use of `GSubprocess` will involve calling
75 : : * [ctor@Gio.Subprocess.new], followed by [method@Gio.Subprocess.wait_async] or
76 : : * [method@Gio.Subprocess.wait]. After the process exits, the status can be
77 : : * checked using functions such as [method@Gio.Subprocess.get_if_exited] (which
78 : : * are similar to the familiar `WIFEXITED`-style POSIX macros).
79 : : *
80 : : * Note that as of GLib 2.82, creating a `GSubprocess` causes the signal
81 : : * `SIGPIPE` to be ignored for the remainder of the program. If you are writing
82 : : * a command-line utility that uses `GSubprocess`, you may need to take into
83 : : * account the fact that your program will not automatically be killed
84 : : * if it tries to write to `stdout` after it has been closed.
85 : : *
86 : : * Since: 2.40
87 : : **/
88 : :
89 : : #include "config.h"
90 : :
91 : : #include "gsubprocess.h"
92 : : #include "gsubprocesslauncher-private.h"
93 : : #include "gasyncresult.h"
94 : : #include "giostream.h"
95 : : #include "gmemoryinputstream.h"
96 : : #include "glibintl.h"
97 : : #include "glib-private.h"
98 : :
99 : : #include <string.h>
100 : : #ifdef G_OS_UNIX
101 : : #include <gio/gunixoutputstream.h>
102 : : #include <gio/gfiledescriptorbased.h>
103 : : #include <gio/gunixinputstream.h>
104 : : #include <gstdio.h>
105 : : #include <glib-unix.h>
106 : : #include <fcntl.h>
107 : : #endif
108 : : #ifdef G_OS_WIN32
109 : : #include <windows.h>
110 : : #include <io.h>
111 : : #include "giowin32-priv.h"
112 : : #endif
113 : :
114 : : #ifndef O_BINARY
115 : : #define O_BINARY 0
116 : : #endif
117 : :
118 : : #ifndef O_CLOEXEC
119 : : #define O_CLOEXEC 0
120 : : #else
121 : : #define HAVE_O_CLOEXEC 1
122 : : #endif
123 : :
124 : : #define COMMUNICATE_READ_SIZE 4096
125 : :
126 : : /* A GSubprocess can have two possible states: running and not.
127 : : *
128 : : * These two states are reflected by the value of 'pid'. If it is
129 : : * non-zero then the process is running, with that pid.
130 : : *
131 : : * When a GSubprocess is first created with g_object_new() it is not
132 : : * running. When it is finalized, it is also not running.
133 : : *
134 : : * During initable_init(), if the g_spawn() is successful then we
135 : : * immediately register a child watch and take an extra ref on the
136 : : * subprocess. That reference doesn't drop until the child has quit,
137 : : * which is why finalize can only happen in the non-running state. In
138 : : * the event that the g_spawn() failed we will still be finalizing a
139 : : * non-running GSubprocess (before returning from g_subprocess_new())
140 : : * with NULL.
141 : : *
142 : : * We make extensive use of the glib worker thread to guarantee
143 : : * race-free operation. As with all child watches, glib calls waitpid()
144 : : * in the worker thread. It reports the child exiting to us via the
145 : : * worker thread (which means that we can do synchronous waits without
146 : : * running a separate loop). We also send signals to the child process
147 : : * via the worker thread so that we don't race with waitpid() and
148 : : * accidentally send a signal to an already-reaped child.
149 : : */
150 : : static void initable_iface_init (GInitableIface *initable_iface);
151 : :
152 : : typedef GObjectClass GSubprocessClass;
153 : :
154 : : struct _GSubprocess
155 : : {
156 : : GObject parent;
157 : :
158 : : /* only used during construction */
159 : : GSubprocessLauncher *launcher;
160 : : GSubprocessFlags flags;
161 : : gchar **argv;
162 : :
163 : : /* state tracking variables */
164 : : gchar identifier[24];
165 : : int status;
166 : : GPid pid;
167 : :
168 : : /* list of GTask */
169 : : GMutex pending_waits_lock;
170 : : GSList *pending_waits;
171 : :
172 : : /* These are the streams created if a pipe is requested via flags. */
173 : : GOutputStream *stdin_pipe;
174 : : GInputStream *stdout_pipe;
175 : : GInputStream *stderr_pipe;
176 : : };
177 : :
178 : 619 : G_DEFINE_TYPE_WITH_CODE (GSubprocess, g_subprocess, G_TYPE_OBJECT,
179 : : G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init))
180 : :
181 : : enum
182 : : {
183 : : PROP_0,
184 : : PROP_FLAGS,
185 : : PROP_ARGV,
186 : : N_PROPS
187 : : };
188 : :
189 : : static GInputStream *
190 : 174 : platform_input_stream_from_spawn_fd (gint fd)
191 : : {
192 : 174 : if (fd < 0)
193 : 120 : return NULL;
194 : :
195 : : #ifdef G_OS_UNIX
196 : 54 : return g_unix_input_stream_new (fd, TRUE);
197 : : #else
198 : : return g_win32_input_stream_new_from_fd (fd, TRUE);
199 : : #endif
200 : : }
201 : :
202 : : static GOutputStream *
203 : 87 : platform_output_stream_from_spawn_fd (gint fd)
204 : : {
205 : 87 : if (fd < 0)
206 : 28 : return NULL;
207 : :
208 : : #ifdef G_OS_UNIX
209 : 59 : return g_unix_output_stream_new (fd, TRUE);
210 : : #else
211 : : return g_win32_output_stream_new_from_fd (fd, TRUE);
212 : : #endif
213 : : }
214 : :
215 : : #ifdef G_OS_UNIX
216 : : static gint
217 : 1 : unix_open_file (const char *filename,
218 : : gint mode,
219 : : GError **error)
220 : : {
221 : : gint my_fd;
222 : :
223 : 1 : my_fd = g_open (filename, mode | O_BINARY | O_CLOEXEC, 0666);
224 : :
225 : : /* If we return -1 we should also set the error */
226 : 1 : if (my_fd < 0)
227 : : {
228 : 0 : gint saved_errno = errno;
229 : : char *display_name;
230 : :
231 : 0 : display_name = g_filename_display_name (filename);
232 : 0 : g_set_error (error, G_IO_ERROR, g_io_error_from_errno (saved_errno),
233 : : _("Error opening file “%s”: %s"), display_name,
234 : : g_strerror (saved_errno));
235 : 0 : g_free (display_name);
236 : : /* fall through... */
237 : : }
238 : : #ifndef HAVE_O_CLOEXEC
239 : : else
240 : : fcntl (my_fd, F_SETFD, FD_CLOEXEC);
241 : : #endif
242 : :
243 : 1 : return my_fd;
244 : : }
245 : : #endif
246 : :
247 : : static void
248 : 176 : g_subprocess_set_property (GObject *object,
249 : : guint prop_id,
250 : : const GValue *value,
251 : : GParamSpec *pspec)
252 : : {
253 : 176 : GSubprocess *self = G_SUBPROCESS (object);
254 : :
255 : 176 : switch (prop_id)
256 : : {
257 : 88 : case PROP_FLAGS:
258 : 88 : self->flags = g_value_get_flags (value);
259 : 88 : break;
260 : :
261 : 88 : case PROP_ARGV:
262 : 88 : self->argv = g_value_dup_boxed (value);
263 : 88 : break;
264 : :
265 : 0 : default:
266 : : g_assert_not_reached ();
267 : : }
268 : 176 : }
269 : :
270 : : static gboolean
271 : 87 : g_subprocess_exited (GPid pid,
272 : : gint status,
273 : : gpointer user_data)
274 : : {
275 : 87 : GSubprocess *self = user_data;
276 : : GSList *tasks;
277 : :
278 : 87 : g_assert (self->pid == pid);
279 : :
280 : 87 : g_mutex_lock (&self->pending_waits_lock);
281 : 87 : self->status = status;
282 : 87 : tasks = self->pending_waits;
283 : 87 : self->pending_waits = NULL;
284 : 87 : self->pid = 0;
285 : 87 : g_mutex_unlock (&self->pending_waits_lock);
286 : :
287 : : /* Signal anyone in g_subprocess_wait_async() to wake up now */
288 : 140 : while (tasks)
289 : : {
290 : 53 : g_task_return_boolean (tasks->data, TRUE);
291 : 53 : g_object_unref (tasks->data);
292 : 53 : tasks = g_slist_delete_link (tasks, tasks);
293 : : }
294 : :
295 : 87 : g_spawn_close_pid (pid);
296 : :
297 : 87 : return FALSE;
298 : : }
299 : :
300 : : static gboolean
301 : 88 : initable_init (GInitable *initable,
302 : : GCancellable *cancellable,
303 : : GError **error)
304 : : {
305 : 88 : GSubprocess *self = G_SUBPROCESS (initable);
306 : 88 : gint *pipe_ptrs[3] = { NULL, NULL, NULL };
307 : 88 : gint pipe_fds[3] = { -1, -1, -1 };
308 : 88 : gint close_fds[3] = { -1, -1, -1 };
309 : : #ifdef G_OS_UNIX
310 : 88 : gint stdin_fd = -1, stdout_fd = -1, stderr_fd = -1;
311 : : #endif
312 : 88 : GSpawnFlags spawn_flags = 0;
313 : 88 : gboolean success = FALSE;
314 : : gint i;
315 : :
316 : : /* this is a programmer error */
317 : 88 : if (!self->argv || !self->argv[0] || !self->argv[0][0])
318 : 1 : return FALSE;
319 : :
320 : 87 : if (g_cancellable_set_error_if_cancelled (cancellable, error))
321 : 0 : return FALSE;
322 : :
323 : : /* We must setup the three fds that will end up in the child as stdin,
324 : : * stdout and stderr.
325 : : *
326 : : * First, stdin.
327 : : */
328 : 87 : if (self->flags & G_SUBPROCESS_FLAGS_STDIN_INHERIT)
329 : 1 : spawn_flags |= G_SPAWN_CHILD_INHERITS_STDIN;
330 : 86 : else if (self->flags & G_SUBPROCESS_FLAGS_STDIN_PIPE)
331 : 59 : pipe_ptrs[0] = &pipe_fds[0];
332 : : #ifdef G_OS_UNIX
333 : 27 : else if (self->launcher)
334 : : {
335 : 15 : if (self->launcher->stdin_fd != -1)
336 : 0 : stdin_fd = self->launcher->stdin_fd;
337 : 15 : else if (self->launcher->stdin_path != NULL)
338 : : {
339 : 0 : stdin_fd = close_fds[0] = unix_open_file (self->launcher->stdin_path, O_RDONLY, error);
340 : 0 : if (stdin_fd == -1)
341 : 0 : goto out;
342 : : }
343 : : }
344 : : #endif
345 : :
346 : : /* Next, stdout. */
347 : 87 : if (self->flags & G_SUBPROCESS_FLAGS_STDOUT_SILENCE)
348 : 10 : spawn_flags |= G_SPAWN_STDOUT_TO_DEV_NULL;
349 : 77 : else if (self->flags & G_SUBPROCESS_FLAGS_STDOUT_PIPE)
350 : 38 : pipe_ptrs[1] = &pipe_fds[1];
351 : : #ifdef G_OS_UNIX
352 : 39 : else if (self->launcher)
353 : : {
354 : 14 : if (self->launcher->stdout_fd != -1)
355 : 1 : stdout_fd = self->launcher->stdout_fd;
356 : 13 : else if (self->launcher->stdout_path != NULL)
357 : : {
358 : 1 : stdout_fd = close_fds[1] = unix_open_file (self->launcher->stdout_path, O_CREAT | O_WRONLY, error);
359 : 1 : if (stdout_fd == -1)
360 : 0 : goto out;
361 : : }
362 : : }
363 : : #endif
364 : :
365 : : /* Finally, stderr. */
366 : 87 : if (self->flags & G_SUBPROCESS_FLAGS_STDERR_SILENCE)
367 : 1 : spawn_flags |= G_SPAWN_STDERR_TO_DEV_NULL;
368 : 86 : else if (self->flags & G_SUBPROCESS_FLAGS_STDERR_PIPE)
369 : 16 : pipe_ptrs[2] = &pipe_fds[2];
370 : : #ifdef G_OS_UNIX
371 : 70 : else if (self->flags & G_SUBPROCESS_FLAGS_STDERR_MERGE)
372 : : /* This will work because stderr gets set up after stdout. */
373 : 10 : stderr_fd = 1;
374 : 60 : else if (self->launcher)
375 : : {
376 : 21 : if (self->launcher->stderr_fd != -1)
377 : 0 : stderr_fd = self->launcher->stderr_fd;
378 : 21 : else if (self->launcher->stderr_path != NULL)
379 : : {
380 : 0 : stderr_fd = close_fds[2] = unix_open_file (self->launcher->stderr_path, O_CREAT | O_WRONLY, error);
381 : 0 : if (stderr_fd == -1)
382 : 0 : goto out;
383 : : }
384 : : }
385 : : #endif
386 : :
387 : : /* argv0 has no '/' in it? We better do a PATH lookup. */
388 : 87 : if (strchr (self->argv[0], G_DIR_SEPARATOR) == NULL)
389 : : {
390 : 4 : if (self->launcher && self->launcher->flags & G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP)
391 : 1 : spawn_flags |= G_SPAWN_SEARCH_PATH_FROM_ENVP;
392 : : else
393 : 3 : spawn_flags |= G_SPAWN_SEARCH_PATH;
394 : : }
395 : :
396 : 87 : if (self->flags & G_SUBPROCESS_FLAGS_INHERIT_FDS)
397 : 2 : spawn_flags |= G_SPAWN_LEAVE_DESCRIPTORS_OPEN;
398 : :
399 : 87 : spawn_flags |= G_SPAWN_DO_NOT_REAP_CHILD;
400 : 87 : spawn_flags |= G_SPAWN_CLOEXEC_PIPES;
401 : :
402 : 483 : success = g_spawn_async_with_pipes_and_fds (self->launcher ? self->launcher->cwd : NULL,
403 : 87 : (const gchar * const *) self->argv,
404 : 87 : (const gchar * const *) (self->launcher ? self->launcher->envp : NULL),
405 : : spawn_flags,
406 : : #ifdef G_OS_UNIX
407 : 87 : self->launcher ? self->launcher->child_setup_func : NULL,
408 : 87 : self->launcher ? self->launcher->child_setup_user_data : NULL,
409 : : stdin_fd, stdout_fd, stderr_fd,
410 : 87 : self->launcher ? (const gint *) self->launcher->source_fds->data : NULL,
411 : 87 : self->launcher ? (const gint *) self->launcher->target_fds->data : NULL,
412 : 87 : self->launcher ? self->launcher->source_fds->len : 0,
413 : : #else
414 : : NULL, NULL,
415 : : -1, -1, -1,
416 : : NULL, NULL, 0,
417 : : #endif
418 : : &self->pid,
419 : : pipe_ptrs[0], pipe_ptrs[1], pipe_ptrs[2],
420 : : error);
421 : 87 : g_assert (success == (self->pid != 0));
422 : :
423 : : {
424 : : guint64 identifier;
425 : : gint s G_GNUC_UNUSED /* when compiling with G_DISABLE_ASSERT */;
426 : :
427 : : #ifdef G_OS_WIN32
428 : : identifier = (guint64) GetProcessId (self->pid);
429 : : #else
430 : 87 : identifier = (guint64) self->pid;
431 : : #endif
432 : :
433 : 87 : s = g_snprintf (self->identifier, sizeof self->identifier, "%"G_GUINT64_FORMAT, identifier);
434 : 87 : g_assert (0 < s && (gsize) s < sizeof self->identifier);
435 : : }
436 : :
437 : : /* Start attempting to reap the child immediately */
438 : 87 : if (success)
439 : : {
440 : : GMainContext *worker_context;
441 : : GSource *source;
442 : :
443 : 87 : worker_context = GLIB_PRIVATE_CALL (g_get_worker_context) ();
444 : 87 : source = g_child_watch_source_new (self->pid);
445 : 87 : g_source_set_callback (source, (GSourceFunc) g_subprocess_exited, g_object_ref (self), g_object_unref);
446 : 87 : g_source_attach (source, worker_context);
447 : 87 : g_source_unref (source);
448 : : }
449 : :
450 : : #ifdef G_OS_UNIX
451 : 0 : out:
452 : : #endif
453 : : /* we don't need this past init... */
454 : 87 : self->launcher = NULL;
455 : :
456 : 348 : for (i = 0; i < 3; i++)
457 : 261 : if (close_fds[i] != -1)
458 : 1 : close (close_fds[i]);
459 : :
460 : 87 : self->stdin_pipe = platform_output_stream_from_spawn_fd (pipe_fds[0]);
461 : 87 : self->stdout_pipe = platform_input_stream_from_spawn_fd (pipe_fds[1]);
462 : 87 : self->stderr_pipe = platform_input_stream_from_spawn_fd (pipe_fds[2]);
463 : :
464 : 87 : return success;
465 : : }
466 : :
467 : : static void
468 : 76 : g_subprocess_finalize (GObject *object)
469 : : {
470 : 76 : GSubprocess *self = G_SUBPROCESS (object);
471 : :
472 : 76 : g_assert (self->pending_waits == NULL);
473 : 76 : g_assert (self->pid == 0);
474 : :
475 : 76 : g_clear_object (&self->stdin_pipe);
476 : 76 : g_clear_object (&self->stdout_pipe);
477 : 76 : g_clear_object (&self->stderr_pipe);
478 : 76 : g_strfreev (self->argv);
479 : :
480 : 76 : g_mutex_clear (&self->pending_waits_lock);
481 : :
482 : 76 : G_OBJECT_CLASS (g_subprocess_parent_class)->finalize (object);
483 : 76 : }
484 : :
485 : : static void
486 : 88 : g_subprocess_init (GSubprocess *self)
487 : : {
488 : 88 : g_mutex_init (&self->pending_waits_lock);
489 : 88 : }
490 : :
491 : : static void
492 : 10 : initable_iface_init (GInitableIface *initable_iface)
493 : : {
494 : 10 : initable_iface->init = initable_init;
495 : 10 : }
496 : :
497 : : static void
498 : 10 : g_subprocess_class_init (GSubprocessClass *class)
499 : : {
500 : 10 : GObjectClass *gobject_class = G_OBJECT_CLASS (class);
501 : :
502 : : #ifdef SIGPIPE
503 : : /* There is no portable, thread-safe way to avoid having the process
504 : : * be killed by SIGPIPE when calling write() on a pipe to a subprocess, so we
505 : : * are forced to simply ignore the signal process-wide.
506 : : *
507 : : * This can happen if `G_SUBPROCESS_FLAGS_STDIN_PIPE` is used and the
508 : : * subprocess calls close() on its stdin FD while the parent process is
509 : : * running g_subprocess_communicate().
510 : : *
511 : : * Even if we ignore it though, gdb will still stop if the app
512 : : * receives a SIGPIPE, which can be confusing and annoying. In `gsocket.c`,
513 : : * we can handily also set `MSG_NO_SIGNAL` / `SO_NOSIGPIPE`, but unfortunately
514 : : * there isn’t an equivalent of those for `pipe2`() FDs.
515 : : */
516 : 10 : signal (SIGPIPE, SIG_IGN);
517 : : #endif
518 : :
519 : 10 : gobject_class->finalize = g_subprocess_finalize;
520 : 10 : gobject_class->set_property = g_subprocess_set_property;
521 : :
522 : : /**
523 : : * GSubprocess:flags:
524 : : *
525 : : * Subprocess flags.
526 : : *
527 : : * Since: 2.40
528 : : */
529 : 10 : g_object_class_install_property (gobject_class, PROP_FLAGS,
530 : : g_param_spec_flags ("flags", NULL, NULL,
531 : : G_TYPE_SUBPROCESS_FLAGS, 0, G_PARAM_WRITABLE |
532 : : G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
533 : :
534 : : /**
535 : : * GSubprocess:argv:
536 : : *
537 : : * Argument vector.
538 : : *
539 : : * Since: 2.40
540 : : */
541 : 10 : g_object_class_install_property (gobject_class, PROP_ARGV,
542 : : g_param_spec_boxed ("argv", NULL, NULL,
543 : : G_TYPE_STRV, G_PARAM_WRITABLE |
544 : : G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
545 : 10 : }
546 : :
547 : : /**
548 : : * g_subprocess_new: (skip)
549 : : * @flags: flags that define the behaviour of the subprocess
550 : : * @error: (nullable): return location for an error, or %NULL
551 : : * @argv0: first commandline argument to pass to the subprocess
552 : : * @...: more commandline arguments, followed by %NULL
553 : : *
554 : : * Create a new process with the given flags and varargs argument
555 : : * list. By default, matching the g_spawn_async() defaults, the
556 : : * child's stdin will be set to the system null device, and
557 : : * stdout/stderr will be inherited from the parent. You can use
558 : : * @flags to control this behavior.
559 : : *
560 : : * The argument list must be terminated with %NULL.
561 : : *
562 : : * Returns: A newly created #GSubprocess, or %NULL on error (and @error
563 : : * will be set)
564 : : *
565 : : * Since: 2.40
566 : : */
567 : : GSubprocess *
568 : 3 : g_subprocess_new (GSubprocessFlags flags,
569 : : GError **error,
570 : : const gchar *argv0,
571 : : ...)
572 : : {
573 : : GSubprocess *result;
574 : : GPtrArray *args;
575 : : const gchar *arg;
576 : : va_list ap;
577 : :
578 : 3 : g_return_val_if_fail (argv0 != NULL && argv0[0] != '\0', NULL);
579 : 3 : g_return_val_if_fail (error == NULL || *error == NULL, NULL);
580 : :
581 : 3 : args = g_ptr_array_new ();
582 : :
583 : 3 : va_start (ap, argv0);
584 : 3 : g_ptr_array_add (args, (gchar *) argv0);
585 : 8 : while ((arg = va_arg (ap, const gchar *)))
586 : 5 : g_ptr_array_add (args, (gchar *) arg);
587 : 3 : g_ptr_array_add (args, NULL);
588 : 3 : va_end (ap);
589 : :
590 : 3 : result = g_subprocess_newv ((const gchar * const *) args->pdata, flags, error);
591 : :
592 : 3 : g_ptr_array_free (args, TRUE);
593 : :
594 : 3 : return result;
595 : : }
596 : :
597 : : /**
598 : : * g_subprocess_newv: (rename-to g_subprocess_new)
599 : : * @argv: (array zero-terminated=1) (element-type filename): commandline arguments for the subprocess
600 : : * @flags: flags that define the behaviour of the subprocess
601 : : * @error: (nullable): return location for an error, or %NULL
602 : : *
603 : : * Create a new process with the given flags and argument list.
604 : : *
605 : : * The argument list is expected to be %NULL-terminated.
606 : : *
607 : : * Returns: A newly created #GSubprocess, or %NULL on error (and @error
608 : : * will be set)
609 : : *
610 : : * Since: 2.40
611 : : */
612 : : GSubprocess *
613 : 66 : g_subprocess_newv (const gchar * const *argv,
614 : : GSubprocessFlags flags,
615 : : GError **error)
616 : : {
617 : 66 : g_return_val_if_fail (argv != NULL && argv[0] != NULL && argv[0][0] != '\0', NULL);
618 : :
619 : 66 : return g_initable_new (G_TYPE_SUBPROCESS, NULL, error,
620 : : "argv", argv,
621 : : "flags", flags,
622 : : NULL);
623 : : }
624 : :
625 : : /**
626 : : * g_subprocess_get_identifier:
627 : : * @subprocess: a #GSubprocess
628 : : *
629 : : * On UNIX, returns the process ID as a decimal string.
630 : : * On Windows, returns the result of GetProcessId() also as a string.
631 : : * If the subprocess has terminated, this will return %NULL.
632 : : *
633 : : * Returns: (nullable): the subprocess identifier, or %NULL if the subprocess
634 : : * has terminated
635 : : * Since: 2.40
636 : : */
637 : : const gchar *
638 : 2 : g_subprocess_get_identifier (GSubprocess *subprocess)
639 : : {
640 : 2 : g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), NULL);
641 : :
642 : 2 : if (subprocess->pid)
643 : 2 : return subprocess->identifier;
644 : : else
645 : 0 : return NULL;
646 : : }
647 : :
648 : : /**
649 : : * g_subprocess_get_stdin_pipe:
650 : : * @subprocess: a #GSubprocess
651 : : *
652 : : * Gets the #GOutputStream that you can write to in order to give data
653 : : * to the stdin of @subprocess.
654 : : *
655 : : * The process must have been created with %G_SUBPROCESS_FLAGS_STDIN_PIPE and
656 : : * not %G_SUBPROCESS_FLAGS_STDIN_INHERIT, otherwise %NULL will be returned.
657 : : *
658 : : * Returns: (nullable) (transfer none): the stdout pipe
659 : : *
660 : : * Since: 2.40
661 : : **/
662 : : GOutputStream *
663 : 8 : g_subprocess_get_stdin_pipe (GSubprocess *subprocess)
664 : : {
665 : 8 : g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), NULL);
666 : :
667 : 8 : return subprocess->stdin_pipe;
668 : : }
669 : :
670 : : /**
671 : : * g_subprocess_get_stdout_pipe:
672 : : * @subprocess: a #GSubprocess
673 : : *
674 : : * Gets the #GInputStream from which to read the stdout output of
675 : : * @subprocess.
676 : : *
677 : : * The process must have been created with %G_SUBPROCESS_FLAGS_STDOUT_PIPE,
678 : : * otherwise %NULL will be returned.
679 : : *
680 : : * Returns: (nullable) (transfer none): the stdout pipe
681 : : *
682 : : * Since: 2.40
683 : : **/
684 : : GInputStream *
685 : 11 : g_subprocess_get_stdout_pipe (GSubprocess *subprocess)
686 : : {
687 : 11 : g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), NULL);
688 : :
689 : 11 : return subprocess->stdout_pipe;
690 : : }
691 : :
692 : : /**
693 : : * g_subprocess_get_stderr_pipe:
694 : : * @subprocess: a #GSubprocess
695 : : *
696 : : * Gets the #GInputStream from which to read the stderr output of
697 : : * @subprocess.
698 : : *
699 : : * The process must have been created with %G_SUBPROCESS_FLAGS_STDERR_PIPE,
700 : : * otherwise %NULL will be returned.
701 : : *
702 : : * Returns: (nullable) (transfer none): the stderr pipe
703 : : *
704 : : * Since: 2.40
705 : : **/
706 : : GInputStream *
707 : 0 : g_subprocess_get_stderr_pipe (GSubprocess *subprocess)
708 : : {
709 : 0 : g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), NULL);
710 : :
711 : 0 : return subprocess->stderr_pipe;
712 : : }
713 : :
714 : : /* Remove the first list element containing @data, and return %TRUE. If no
715 : : * such element is found, return %FALSE. */
716 : : static gboolean
717 : 26 : slist_remove_if_present (GSList **list,
718 : : gconstpointer data)
719 : : {
720 : : GSList *l, *prev;
721 : :
722 : 26 : for (l = *list, prev = NULL; l != NULL; prev = l, l = prev->next)
723 : : {
724 : 24 : if (l->data == data)
725 : : {
726 : 24 : if (prev != NULL)
727 : 0 : prev->next = l->next;
728 : : else
729 : 24 : *list = l->next;
730 : :
731 : 24 : g_slist_free_1 (l);
732 : :
733 : 24 : return TRUE;
734 : : }
735 : : }
736 : :
737 : 2 : return FALSE;
738 : : }
739 : :
740 : : static void
741 : 26 : g_subprocess_wait_cancelled (GCancellable *cancellable,
742 : : gpointer user_data)
743 : : {
744 : 26 : GTask *task = user_data;
745 : : GSubprocess *self;
746 : : gboolean task_was_pending;
747 : :
748 : 26 : self = g_task_get_source_object (task);
749 : :
750 : 26 : g_mutex_lock (&self->pending_waits_lock);
751 : 26 : task_was_pending = slist_remove_if_present (&self->pending_waits, task);
752 : 26 : g_mutex_unlock (&self->pending_waits_lock);
753 : :
754 : 26 : if (task_was_pending)
755 : : {
756 : 24 : g_task_return_boolean (task, FALSE);
757 : 24 : g_object_unref (task); /* ref from pending_waits */
758 : : }
759 : 26 : }
760 : :
761 : : /**
762 : : * g_subprocess_wait_async:
763 : : * @subprocess: a #GSubprocess
764 : : * @cancellable: a #GCancellable, or %NULL
765 : : * @callback: a #GAsyncReadyCallback to call when the operation is complete
766 : : * @user_data: user_data for @callback
767 : : *
768 : : * Wait for the subprocess to terminate.
769 : : *
770 : : * This is the asynchronous version of g_subprocess_wait().
771 : : *
772 : : * Since: 2.40
773 : : */
774 : : void
775 : 77 : g_subprocess_wait_async (GSubprocess *subprocess,
776 : : GCancellable *cancellable,
777 : : GAsyncReadyCallback callback,
778 : : gpointer user_data)
779 : : {
780 : : GTask *task;
781 : :
782 : 77 : task = g_task_new (subprocess, cancellable, callback, user_data);
783 : 77 : g_task_set_source_tag (task, g_subprocess_wait_async);
784 : :
785 : 77 : g_mutex_lock (&subprocess->pending_waits_lock);
786 : 77 : if (subprocess->pid)
787 : : {
788 : : /* Only bother with cancellable if we're putting it in the list.
789 : : * If not, it's going to dispatch immediately anyway and we will
790 : : * see the cancellation in the _finish().
791 : : */
792 : 77 : if (cancellable)
793 : 54 : g_signal_connect_object (cancellable, "cancelled",
794 : : G_CALLBACK (g_subprocess_wait_cancelled),
795 : : task, G_CONNECT_DEFAULT);
796 : :
797 : 77 : subprocess->pending_waits = g_slist_prepend (subprocess->pending_waits, task);
798 : 77 : task = NULL;
799 : : }
800 : 77 : g_mutex_unlock (&subprocess->pending_waits_lock);
801 : :
802 : : /* If we still have task then it's because did_exit is already TRUE */
803 : 77 : if (task != NULL)
804 : : {
805 : 0 : g_task_return_boolean (task, TRUE);
806 : 0 : g_object_unref (task);
807 : : }
808 : 77 : }
809 : :
810 : : /**
811 : : * g_subprocess_wait_finish:
812 : : * @subprocess: a #GSubprocess
813 : : * @result: the #GAsyncResult passed to your #GAsyncReadyCallback
814 : : * @error: a pointer to a %NULL #GError, or %NULL
815 : : *
816 : : * Collects the result of a previous call to
817 : : * g_subprocess_wait_async().
818 : : *
819 : : * Returns: %TRUE if successful, or %FALSE with @error set
820 : : *
821 : : * Since: 2.40
822 : : */
823 : : gboolean
824 : 77 : g_subprocess_wait_finish (GSubprocess *subprocess,
825 : : GAsyncResult *result,
826 : : GError **error)
827 : : {
828 : 77 : return g_task_propagate_boolean (G_TASK (result), error);
829 : : }
830 : :
831 : : /* Some generic helpers for emulating synchronous operations using async
832 : : * operations.
833 : : */
834 : : static void
835 : 43 : g_subprocess_sync_setup (void)
836 : : {
837 : 43 : g_main_context_push_thread_default (g_main_context_new ());
838 : 43 : }
839 : :
840 : : static void
841 : 43 : g_subprocess_sync_done (GObject *source_object,
842 : : GAsyncResult *result,
843 : : gpointer user_data)
844 : : {
845 : 43 : GAsyncResult **result_ptr = user_data;
846 : :
847 : 43 : *result_ptr = g_object_ref (result);
848 : 43 : }
849 : :
850 : : static void
851 : 43 : g_subprocess_sync_complete (GAsyncResult **result)
852 : : {
853 : 43 : GMainContext *context = g_main_context_get_thread_default ();
854 : :
855 : 225 : while (!*result)
856 : 182 : g_main_context_iteration (context, TRUE);
857 : :
858 : 43 : g_main_context_pop_thread_default (context);
859 : 43 : g_main_context_unref (context);
860 : 43 : }
861 : :
862 : : /**
863 : : * g_subprocess_wait:
864 : : * @subprocess: a #GSubprocess
865 : : * @cancellable: a #GCancellable
866 : : * @error: a #GError
867 : : *
868 : : * Synchronously wait for the subprocess to terminate.
869 : : *
870 : : * After the process terminates you can query its exit status with
871 : : * functions such as g_subprocess_get_if_exited() and
872 : : * g_subprocess_get_exit_status().
873 : : *
874 : : * This function does not fail in the case of the subprocess having
875 : : * abnormal termination. See g_subprocess_wait_check() for that.
876 : : *
877 : : * Cancelling @cancellable doesn't kill the subprocess. Call
878 : : * g_subprocess_force_exit() if it is desirable.
879 : : *
880 : : * Returns: %TRUE on success, %FALSE if @cancellable was cancelled
881 : : *
882 : : * Since: 2.40
883 : : */
884 : : gboolean
885 : 19 : g_subprocess_wait (GSubprocess *subprocess,
886 : : GCancellable *cancellable,
887 : : GError **error)
888 : : {
889 : 19 : GAsyncResult *result = NULL;
890 : : gboolean success;
891 : :
892 : 19 : g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), FALSE);
893 : :
894 : : /* Synchronous waits are actually the 'more difficult' case because we
895 : : * need to deal with the possibility of cancellation. That more or
896 : : * less implies that we need a main context (to dispatch either of the
897 : : * possible reasons for the operation ending).
898 : : *
899 : : * So we make one and then do this async...
900 : : */
901 : :
902 : 19 : if (g_cancellable_set_error_if_cancelled (cancellable, error))
903 : 0 : return FALSE;
904 : :
905 : : /* We can shortcut in the case that the process already quit (but only
906 : : * after we checked the cancellable).
907 : : */
908 : 19 : if (subprocess->pid == 0)
909 : 3 : return TRUE;
910 : :
911 : : /* Otherwise, we need to do this the long way... */
912 : 16 : g_subprocess_sync_setup ();
913 : 16 : g_subprocess_wait_async (subprocess, cancellable, g_subprocess_sync_done, &result);
914 : 16 : g_subprocess_sync_complete (&result);
915 : 16 : success = g_subprocess_wait_finish (subprocess, result, error);
916 : 16 : g_object_unref (result);
917 : :
918 : 16 : return success;
919 : : }
920 : :
921 : : /**
922 : : * g_subprocess_wait_check:
923 : : * @subprocess: a #GSubprocess
924 : : * @cancellable: a #GCancellable
925 : : * @error: a #GError
926 : : *
927 : : * Combines g_subprocess_wait() with g_spawn_check_wait_status().
928 : : *
929 : : * Returns: %TRUE on success, %FALSE if process exited abnormally, or
930 : : * @cancellable was cancelled
931 : : *
932 : : * Since: 2.40
933 : : */
934 : : gboolean
935 : 16 : g_subprocess_wait_check (GSubprocess *subprocess,
936 : : GCancellable *cancellable,
937 : : GError **error)
938 : : {
939 : 32 : return g_subprocess_wait (subprocess, cancellable, error) &&
940 : 16 : g_spawn_check_wait_status (subprocess->status, error);
941 : : }
942 : :
943 : : /**
944 : : * g_subprocess_wait_check_async:
945 : : * @subprocess: a #GSubprocess
946 : : * @cancellable: a #GCancellable, or %NULL
947 : : * @callback: a #GAsyncReadyCallback to call when the operation is complete
948 : : * @user_data: user_data for @callback
949 : : *
950 : : * Combines g_subprocess_wait_async() with g_spawn_check_wait_status().
951 : : *
952 : : * This is the asynchronous version of g_subprocess_wait_check().
953 : : *
954 : : * Since: 2.40
955 : : */
956 : : void
957 : 3 : g_subprocess_wait_check_async (GSubprocess *subprocess,
958 : : GCancellable *cancellable,
959 : : GAsyncReadyCallback callback,
960 : : gpointer user_data)
961 : : {
962 : 3 : g_subprocess_wait_async (subprocess, cancellable, callback, user_data);
963 : 3 : }
964 : :
965 : : /**
966 : : * g_subprocess_wait_check_finish:
967 : : * @subprocess: a #GSubprocess
968 : : * @result: the #GAsyncResult passed to your #GAsyncReadyCallback
969 : : * @error: a pointer to a %NULL #GError, or %NULL
970 : : *
971 : : * Collects the result of a previous call to
972 : : * g_subprocess_wait_check_async().
973 : : *
974 : : * Returns: %TRUE if successful, or %FALSE with @error set
975 : : *
976 : : * Since: 2.40
977 : : */
978 : : gboolean
979 : 3 : g_subprocess_wait_check_finish (GSubprocess *subprocess,
980 : : GAsyncResult *result,
981 : : GError **error)
982 : : {
983 : 5 : return g_subprocess_wait_finish (subprocess, result, error) &&
984 : 2 : g_spawn_check_wait_status (subprocess->status, error);
985 : : }
986 : :
987 : : #ifdef G_OS_UNIX
988 : : typedef struct
989 : : {
990 : : GSubprocess *subprocess;
991 : : gint signalnum;
992 : : } SignalRecord;
993 : :
994 : : static gboolean
995 : 2 : g_subprocess_actually_send_signal (gpointer user_data)
996 : : {
997 : 2 : SignalRecord *signal_record = user_data;
998 : :
999 : : /* The pid is set to zero from the worker thread as well, so we don't
1000 : : * need to take a lock in order to prevent it from changing under us.
1001 : : */
1002 : 2 : if (signal_record->subprocess->pid)
1003 : 2 : kill (signal_record->subprocess->pid, signal_record->signalnum);
1004 : :
1005 : 2 : g_object_unref (signal_record->subprocess);
1006 : :
1007 : 2 : g_slice_free (SignalRecord, signal_record);
1008 : :
1009 : 2 : return FALSE;
1010 : : }
1011 : :
1012 : : static void
1013 : 2 : g_subprocess_dispatch_signal (GSubprocess *subprocess,
1014 : : gint signalnum)
1015 : : {
1016 : 2 : SignalRecord signal_record = { g_object_ref (subprocess), signalnum };
1017 : :
1018 : 2 : g_return_if_fail (G_IS_SUBPROCESS (subprocess));
1019 : :
1020 : : /* This MUST be a lower priority than the priority that the child
1021 : : * watch source uses in initable_init().
1022 : : *
1023 : : * Reaping processes, reporting the results back to GSubprocess and
1024 : : * sending signals is all done in the glib worker thread. We cannot
1025 : : * have a kill() done after the reap and before the report without
1026 : : * risking killing a process that's no longer there so the kill()
1027 : : * needs to have the lower priority.
1028 : : *
1029 : : * G_PRIORITY_HIGH_IDLE is lower priority than G_PRIORITY_DEFAULT.
1030 : : */
1031 : 2 : g_main_context_invoke_full (GLIB_PRIVATE_CALL (g_get_worker_context) (),
1032 : : G_PRIORITY_HIGH_IDLE,
1033 : : g_subprocess_actually_send_signal,
1034 : : g_slice_dup (SignalRecord, &signal_record),
1035 : : NULL);
1036 : : }
1037 : :
1038 : : /**
1039 : : * g_subprocess_send_signal:
1040 : : * @subprocess: a #GSubprocess
1041 : : * @signal_num: the signal number to send
1042 : : *
1043 : : * Sends the UNIX signal @signal_num to the subprocess, if it is still
1044 : : * running.
1045 : : *
1046 : : * This API is race-free. If the subprocess has terminated, it will not
1047 : : * be signalled.
1048 : : *
1049 : : * This API is not available on Windows.
1050 : : *
1051 : : * Since: 2.40
1052 : : **/
1053 : : void
1054 : 1 : g_subprocess_send_signal (GSubprocess *subprocess,
1055 : : gint signal_num)
1056 : : {
1057 : 1 : g_return_if_fail (G_IS_SUBPROCESS (subprocess));
1058 : :
1059 : 1 : g_subprocess_dispatch_signal (subprocess, signal_num);
1060 : : }
1061 : : #endif
1062 : :
1063 : : /**
1064 : : * g_subprocess_force_exit:
1065 : : * @subprocess: a #GSubprocess
1066 : : *
1067 : : * Use an operating-system specific method to attempt an immediate,
1068 : : * forceful termination of the process. There is no mechanism to
1069 : : * determine whether or not the request itself was successful;
1070 : : * however, you can use g_subprocess_wait() to monitor the status of
1071 : : * the process after calling this function.
1072 : : *
1073 : : * On Unix, this function sends %SIGKILL.
1074 : : *
1075 : : * Since: 2.40
1076 : : **/
1077 : : void
1078 : 1 : g_subprocess_force_exit (GSubprocess *subprocess)
1079 : : {
1080 : 1 : g_return_if_fail (G_IS_SUBPROCESS (subprocess));
1081 : :
1082 : : #ifdef G_OS_UNIX
1083 : 1 : g_subprocess_dispatch_signal (subprocess, SIGKILL);
1084 : : #else
1085 : : TerminateProcess (subprocess->pid, 1);
1086 : : #endif
1087 : : }
1088 : :
1089 : : /**
1090 : : * g_subprocess_get_status:
1091 : : * @subprocess: a #GSubprocess
1092 : : *
1093 : : * Gets the raw status code of the process, as from waitpid().
1094 : : *
1095 : : * This value has no particular meaning, but it can be used with the
1096 : : * macros defined by the system headers such as WIFEXITED. It can also
1097 : : * be used with g_spawn_check_wait_status().
1098 : : *
1099 : : * It is more likely that you want to use g_subprocess_get_if_exited()
1100 : : * followed by g_subprocess_get_exit_status().
1101 : : *
1102 : : * It is an error to call this function before g_subprocess_wait() has
1103 : : * returned.
1104 : : *
1105 : : * Returns: the (meaningless) waitpid() exit status from the kernel
1106 : : *
1107 : : * Since: 2.40
1108 : : **/
1109 : : gint
1110 : 5 : g_subprocess_get_status (GSubprocess *subprocess)
1111 : : {
1112 : 5 : g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), FALSE);
1113 : 5 : g_return_val_if_fail (subprocess->pid == 0, FALSE);
1114 : :
1115 : 5 : return subprocess->status;
1116 : : }
1117 : :
1118 : : /**
1119 : : * g_subprocess_get_successful:
1120 : : * @subprocess: a #GSubprocess
1121 : : *
1122 : : * Checks if the process was "successful". A process is considered
1123 : : * successful if it exited cleanly with an exit status of 0, either by
1124 : : * way of the exit() system call or return from main().
1125 : : *
1126 : : * It is an error to call this function before g_subprocess_wait() has
1127 : : * returned.
1128 : : *
1129 : : * Returns: %TRUE if the process exited cleanly with a exit status of 0
1130 : : *
1131 : : * Since: 2.40
1132 : : **/
1133 : : gboolean
1134 : 2 : g_subprocess_get_successful (GSubprocess *subprocess)
1135 : : {
1136 : 2 : g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), FALSE);
1137 : 2 : g_return_val_if_fail (subprocess->pid == 0, FALSE);
1138 : :
1139 : : #ifdef G_OS_UNIX
1140 : 2 : return WIFEXITED (subprocess->status) && WEXITSTATUS (subprocess->status) == 0;
1141 : : #else
1142 : : return subprocess->status == 0;
1143 : : #endif
1144 : : }
1145 : :
1146 : : /**
1147 : : * g_subprocess_get_if_exited:
1148 : : * @subprocess: a #GSubprocess
1149 : : *
1150 : : * Check if the given subprocess exited normally (ie: by way of exit()
1151 : : * or return from main()).
1152 : : *
1153 : : * This is equivalent to the system WIFEXITED macro.
1154 : : *
1155 : : * It is an error to call this function before g_subprocess_wait() has
1156 : : * returned.
1157 : : *
1158 : : * Returns: %TRUE if the case of a normal exit
1159 : : *
1160 : : * Since: 2.40
1161 : : **/
1162 : : gboolean
1163 : 1 : g_subprocess_get_if_exited (GSubprocess *subprocess)
1164 : : {
1165 : 1 : g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), FALSE);
1166 : 1 : g_return_val_if_fail (subprocess->pid == 0, FALSE);
1167 : :
1168 : : #ifdef G_OS_UNIX
1169 : 1 : return WIFEXITED (subprocess->status);
1170 : : #else
1171 : : return TRUE;
1172 : : #endif
1173 : : }
1174 : :
1175 : : /**
1176 : : * g_subprocess_get_exit_status:
1177 : : * @subprocess: a #GSubprocess
1178 : : *
1179 : : * Check the exit status of the subprocess, given that it exited
1180 : : * normally. This is the value passed to the exit() system call or the
1181 : : * return value from main.
1182 : : *
1183 : : * This is equivalent to the system WEXITSTATUS macro.
1184 : : *
1185 : : * It is an error to call this function before g_subprocess_wait() and
1186 : : * unless g_subprocess_get_if_exited() returned %TRUE.
1187 : : *
1188 : : * Returns: the exit status
1189 : : *
1190 : : * Since: 2.40
1191 : : **/
1192 : : gint
1193 : 1 : g_subprocess_get_exit_status (GSubprocess *subprocess)
1194 : : {
1195 : 1 : g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), 1);
1196 : 1 : g_return_val_if_fail (subprocess->pid == 0, 1);
1197 : :
1198 : : #ifdef G_OS_UNIX
1199 : 1 : g_return_val_if_fail (WIFEXITED (subprocess->status), 1);
1200 : :
1201 : 1 : return WEXITSTATUS (subprocess->status);
1202 : : #else
1203 : : return subprocess->status;
1204 : : #endif
1205 : : }
1206 : :
1207 : : /**
1208 : : * g_subprocess_get_if_signaled:
1209 : : * @subprocess: a #GSubprocess
1210 : : *
1211 : : * Check if the given subprocess terminated in response to a signal.
1212 : : *
1213 : : * This is equivalent to the system WIFSIGNALED macro.
1214 : : *
1215 : : * It is an error to call this function before g_subprocess_wait() has
1216 : : * returned.
1217 : : *
1218 : : * Returns: %TRUE if the case of termination due to a signal
1219 : : *
1220 : : * Since: 2.40
1221 : : **/
1222 : : gboolean
1223 : 2 : g_subprocess_get_if_signaled (GSubprocess *subprocess)
1224 : : {
1225 : 2 : g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), FALSE);
1226 : 2 : g_return_val_if_fail (subprocess->pid == 0, FALSE);
1227 : :
1228 : : #ifdef G_OS_UNIX
1229 : 2 : return WIFSIGNALED (subprocess->status);
1230 : : #else
1231 : : return FALSE;
1232 : : #endif
1233 : : }
1234 : :
1235 : : /**
1236 : : * g_subprocess_get_term_sig:
1237 : : * @subprocess: a #GSubprocess
1238 : : *
1239 : : * Get the signal number that caused the subprocess to terminate, given
1240 : : * that it terminated due to a signal.
1241 : : *
1242 : : * This is equivalent to the system WTERMSIG macro.
1243 : : *
1244 : : * It is an error to call this function before g_subprocess_wait() and
1245 : : * unless g_subprocess_get_if_signaled() returned %TRUE.
1246 : : *
1247 : : * Returns: the signal causing termination
1248 : : *
1249 : : * Since: 2.40
1250 : : **/
1251 : : gint
1252 : 2 : g_subprocess_get_term_sig (GSubprocess *subprocess)
1253 : : {
1254 : 2 : g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), 0);
1255 : 2 : g_return_val_if_fail (subprocess->pid == 0, 0);
1256 : :
1257 : : #ifdef G_OS_UNIX
1258 : 2 : g_return_val_if_fail (WIFSIGNALED (subprocess->status), 0);
1259 : :
1260 : 2 : return WTERMSIG (subprocess->status);
1261 : : #else
1262 : : g_critical ("g_subprocess_get_term_sig() called on Windows, where "
1263 : : "g_subprocess_get_if_signaled() always returns FALSE...");
1264 : : return 0;
1265 : : #endif
1266 : : }
1267 : :
1268 : : /*< private >*/
1269 : : void
1270 : 21 : g_subprocess_set_launcher (GSubprocess *subprocess,
1271 : : GSubprocessLauncher *launcher)
1272 : : {
1273 : 21 : subprocess->launcher = launcher;
1274 : 21 : }
1275 : :
1276 : :
1277 : : /* g_subprocess_communicate implementation below:
1278 : : *
1279 : : * This is a tough problem. We have to watch 5 things at the same time:
1280 : : *
1281 : : * - writing to stdin made progress
1282 : : * - reading from stdout made progress
1283 : : * - reading from stderr made progress
1284 : : * - process terminated
1285 : : * - cancellable being cancelled by caller
1286 : : *
1287 : : * We use a GMainContext for all of these (either as async function
1288 : : * calls or as a GSource (in the case of the cancellable). That way at
1289 : : * least we don't have to worry about threading.
1290 : : *
1291 : : * For the sync case we use the usual trick of creating a private main
1292 : : * context and iterating it until completion.
1293 : : *
1294 : : * It's very possible that the process will dump a lot of data to stdout
1295 : : * just before it quits, so we can easily have data to read from stdout
1296 : : * and see the process has terminated at the same time. We want to make
1297 : : * sure that we read all of the data from the pipes first, though, so we
1298 : : * do IO operations at a higher priority than the wait operation (which
1299 : : * is at G_IO_PRIORITY_DEFAULT). Even in the case that we have to do
1300 : : * multiple reads to get this data, the pipe() will always be polling
1301 : : * as ready and with the async result for the read at a higher priority,
1302 : : * the main context will not dispatch the completion for the wait().
1303 : : *
1304 : : * We keep our own private GCancellable. In the event that any of the
1305 : : * above suffers from an error condition (including the user cancelling
1306 : : * their cancellable) we immediately dispatch the GTask with the error
1307 : : * result and fire our cancellable to cleanup any pending operations.
1308 : : * In the case that the error is that the user's cancellable was fired,
1309 : : * it's vaguely wasteful to report an error because GTask will handle
1310 : : * this automatically, so we just return FALSE.
1311 : : *
1312 : : * We let each pending sub-operation take a ref on the GTask of the
1313 : : * communicate operation. We have to be careful that we don't report
1314 : : * the task completion more than once, though, so we keep a flag for
1315 : : * that.
1316 : : */
1317 : : typedef struct
1318 : : {
1319 : : const gchar *stdin_data;
1320 : : gsize stdin_length;
1321 : : gsize stdin_offset;
1322 : :
1323 : : gboolean add_nul;
1324 : :
1325 : : GInputStream *stdin_buf;
1326 : : GMemoryOutputStream *stdout_buf;
1327 : : GMemoryOutputStream *stderr_buf;
1328 : :
1329 : : GCancellable *cancellable;
1330 : : GSource *cancellable_source;
1331 : :
1332 : : guint outstanding_ops;
1333 : : gboolean reported_error;
1334 : : } CommunicateState;
1335 : :
1336 : : static void
1337 : 125 : g_subprocess_communicate_made_progress (GObject *source_object,
1338 : : GAsyncResult *result,
1339 : : gpointer user_data)
1340 : : {
1341 : : CommunicateState *state;
1342 : : GSubprocess *subprocess;
1343 : 125 : GError *error = NULL;
1344 : : gpointer source;
1345 : : GTask *task;
1346 : :
1347 : 125 : g_assert (source_object != NULL);
1348 : :
1349 : 125 : task = user_data;
1350 : 125 : subprocess = g_task_get_source_object (task);
1351 : 125 : state = g_task_get_task_data (task);
1352 : 125 : source = source_object;
1353 : :
1354 : 125 : state->outstanding_ops--;
1355 : :
1356 : 125 : if (source == subprocess->stdin_pipe ||
1357 : 86 : source == state->stdout_buf ||
1358 : 64 : source == state->stderr_buf)
1359 : : {
1360 : 73 : if (g_output_stream_splice_finish ((GOutputStream*) source, result, &error) == -1)
1361 : 22 : goto out;
1362 : :
1363 : 51 : if (source == state->stdout_buf ||
1364 : 35 : source == state->stderr_buf)
1365 : : {
1366 : : /* This is a memory stream, so it can't be cancelled or return
1367 : : * an error really.
1368 : : */
1369 : 24 : if (state->add_nul)
1370 : : {
1371 : : gsize bytes_written;
1372 : 14 : if (!g_output_stream_write_all (source, "\0", 1, &bytes_written,
1373 : : NULL, &error))
1374 : 0 : goto out;
1375 : : }
1376 : 24 : if (!g_output_stream_close (source, NULL, &error))
1377 : 0 : goto out;
1378 : : }
1379 : : }
1380 : 52 : else if (source == subprocess)
1381 : : {
1382 : 52 : (void) g_subprocess_wait_finish (subprocess, result, &error);
1383 : : }
1384 : : else
1385 : : g_assert_not_reached ();
1386 : :
1387 : 125 : out:
1388 : 125 : if (error)
1389 : : {
1390 : : /* Only report the first error we see.
1391 : : *
1392 : : * We might be seeing an error as a result of the cancellation
1393 : : * done when the process quits.
1394 : : */
1395 : 46 : if (!state->reported_error)
1396 : : {
1397 : 24 : state->reported_error = TRUE;
1398 : 24 : g_cancellable_cancel (state->cancellable);
1399 : 24 : g_task_return_error (task, error);
1400 : : }
1401 : : else
1402 : 22 : g_error_free (error);
1403 : : }
1404 : 79 : else if (state->outstanding_ops == 0)
1405 : : {
1406 : 28 : g_task_return_boolean (task, TRUE);
1407 : : }
1408 : :
1409 : : /* And drop the original ref */
1410 : 125 : g_object_unref (task);
1411 : 125 : }
1412 : :
1413 : : static gboolean
1414 : 24 : g_subprocess_communicate_cancelled (GCancellable *cancellable,
1415 : : gpointer user_data)
1416 : : {
1417 : 24 : CommunicateState *state = user_data;
1418 : :
1419 : 24 : g_cancellable_cancel (state->cancellable);
1420 : :
1421 : 24 : return FALSE;
1422 : : }
1423 : :
1424 : : static void
1425 : 40 : g_subprocess_communicate_state_free (gpointer data)
1426 : : {
1427 : 40 : CommunicateState *state = data;
1428 : :
1429 : 40 : g_clear_object (&state->cancellable);
1430 : 40 : g_clear_object (&state->stdin_buf);
1431 : 40 : g_clear_object (&state->stdout_buf);
1432 : 40 : g_clear_object (&state->stderr_buf);
1433 : :
1434 : 40 : if (state->cancellable_source)
1435 : : {
1436 : 12 : g_source_destroy (state->cancellable_source);
1437 : 12 : g_source_unref (state->cancellable_source);
1438 : : }
1439 : :
1440 : 40 : g_slice_free (CommunicateState, state);
1441 : 40 : }
1442 : :
1443 : : static CommunicateState *
1444 : 52 : g_subprocess_communicate_internal (GSubprocess *subprocess,
1445 : : gboolean add_nul,
1446 : : GBytes *stdin_buf,
1447 : : GCancellable *cancellable,
1448 : : GAsyncReadyCallback callback,
1449 : : gpointer user_data)
1450 : : {
1451 : : CommunicateState *state;
1452 : : GTask *task;
1453 : :
1454 : 52 : task = g_task_new (subprocess, cancellable, callback, user_data);
1455 : 52 : g_task_set_source_tag (task, g_subprocess_communicate_internal);
1456 : :
1457 : 52 : state = g_slice_new0 (CommunicateState);
1458 : 52 : g_task_set_task_data (task, state, g_subprocess_communicate_state_free);
1459 : :
1460 : 52 : state->cancellable = g_cancellable_new ();
1461 : 52 : state->add_nul = add_nul;
1462 : :
1463 : 52 : if (cancellable)
1464 : : {
1465 : 24 : state->cancellable_source = g_cancellable_source_new (cancellable);
1466 : : /* No ref held here, but we unref the source from state's free function */
1467 : 24 : g_source_set_callback (state->cancellable_source,
1468 : : G_SOURCE_FUNC (g_subprocess_communicate_cancelled),
1469 : : state, NULL);
1470 : 24 : g_source_attach (state->cancellable_source, g_main_context_get_thread_default ());
1471 : : }
1472 : :
1473 : 52 : if (subprocess->stdin_pipe)
1474 : : {
1475 : 51 : g_assert (stdin_buf != NULL);
1476 : :
1477 : : #ifdef G_OS_UNIX
1478 : : /* We're doing async writes to the pipe, and the async write mechanism assumes
1479 : : * that streams polling as writable do SOME progress (possibly partial) and then
1480 : : * stop, but never block.
1481 : : *
1482 : : * However, for blocking pipes, unix will return writable if there is *any* space left
1483 : : * but still block until the full buffer size is available before returning from write.
1484 : : * So, to avoid async blocking on the main loop we make this non-blocking here.
1485 : : *
1486 : : * It should be safe to change the fd because we're the only user at this point as
1487 : : * per the g_subprocess_communicate() docs, and all the code called by this function
1488 : : * properly handles non-blocking fds.
1489 : : */
1490 : 51 : g_unix_set_fd_nonblocking (g_unix_output_stream_get_fd (G_UNIX_OUTPUT_STREAM (subprocess->stdin_pipe)), TRUE, NULL);
1491 : : #endif
1492 : :
1493 : 51 : state->stdin_buf = g_memory_input_stream_new_from_bytes (stdin_buf);
1494 : 51 : g_output_stream_splice_async (subprocess->stdin_pipe, (GInputStream*)state->stdin_buf,
1495 : : G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
1496 : : G_PRIORITY_DEFAULT, state->cancellable,
1497 : : g_subprocess_communicate_made_progress, g_object_ref (task));
1498 : 51 : state->outstanding_ops++;
1499 : : }
1500 : :
1501 : 52 : if (subprocess->stdout_pipe)
1502 : : {
1503 : 28 : state->stdout_buf = (GMemoryOutputStream*)g_memory_output_stream_new_resizable ();
1504 : 28 : g_output_stream_splice_async ((GOutputStream*)state->stdout_buf, subprocess->stdout_pipe,
1505 : : G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE,
1506 : : G_PRIORITY_DEFAULT, state->cancellable,
1507 : : g_subprocess_communicate_made_progress, g_object_ref (task));
1508 : 28 : state->outstanding_ops++;
1509 : : }
1510 : :
1511 : 52 : if (subprocess->stderr_pipe)
1512 : : {
1513 : 16 : state->stderr_buf = (GMemoryOutputStream*)g_memory_output_stream_new_resizable ();
1514 : 16 : g_output_stream_splice_async ((GOutputStream*)state->stderr_buf, subprocess->stderr_pipe,
1515 : : G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE,
1516 : : G_PRIORITY_DEFAULT, state->cancellable,
1517 : : g_subprocess_communicate_made_progress, g_object_ref (task));
1518 : 16 : state->outstanding_ops++;
1519 : : }
1520 : :
1521 : 52 : g_subprocess_wait_async (subprocess, state->cancellable,
1522 : : g_subprocess_communicate_made_progress, g_object_ref (task));
1523 : 52 : state->outstanding_ops++;
1524 : :
1525 : 52 : g_object_unref (task);
1526 : 52 : return state;
1527 : : }
1528 : :
1529 : : /**
1530 : : * g_subprocess_communicate:
1531 : : * @subprocess: a #GSubprocess
1532 : : * @stdin_buf: (nullable): data to send to the stdin of the subprocess, or %NULL
1533 : : * @cancellable: a #GCancellable
1534 : : * @stdout_buf: (out) (nullable) (optional) (transfer full): data read from the subprocess stdout
1535 : : * @stderr_buf: (out) (nullable) (optional) (transfer full): data read from the subprocess stderr
1536 : : * @error: a pointer to a %NULL #GError pointer, or %NULL
1537 : : *
1538 : : * Communicate with the subprocess until it terminates, and all input
1539 : : * and output has been completed.
1540 : : *
1541 : : * If @stdin_buf is given, the subprocess must have been created with
1542 : : * %G_SUBPROCESS_FLAGS_STDIN_PIPE. The given data is fed to the
1543 : : * stdin of the subprocess and the pipe is closed (ie: EOF).
1544 : : *
1545 : : * At the same time (as not to cause blocking when dealing with large
1546 : : * amounts of data), if %G_SUBPROCESS_FLAGS_STDOUT_PIPE or
1547 : : * %G_SUBPROCESS_FLAGS_STDERR_PIPE were used, reads from those
1548 : : * streams. The data that was read is returned in @stdout and/or
1549 : : * the @stderr.
1550 : : *
1551 : : * If the subprocess was created with %G_SUBPROCESS_FLAGS_STDOUT_PIPE,
1552 : : * @stdout_buf will contain the data read from stdout. Otherwise, for
1553 : : * subprocesses not created with %G_SUBPROCESS_FLAGS_STDOUT_PIPE,
1554 : : * @stdout_buf will be set to %NULL. Similar provisions apply to
1555 : : * @stderr_buf and %G_SUBPROCESS_FLAGS_STDERR_PIPE.
1556 : : *
1557 : : * As usual, any output variable may be given as %NULL to ignore it.
1558 : : *
1559 : : * If you desire the stdout and stderr data to be interleaved, create
1560 : : * the subprocess with %G_SUBPROCESS_FLAGS_STDOUT_PIPE and
1561 : : * %G_SUBPROCESS_FLAGS_STDERR_MERGE. The merged result will be returned
1562 : : * in @stdout_buf and @stderr_buf will be set to %NULL.
1563 : : *
1564 : : * In case of any error (including cancellation), %FALSE will be
1565 : : * returned with @error set. Some or all of the stdin data may have
1566 : : * been written. Any stdout or stderr data that has been read will be
1567 : : * discarded. None of the out variables (aside from @error) will have
1568 : : * been set to anything in particular and should not be inspected.
1569 : : *
1570 : : * In the case that %TRUE is returned, the subprocess has exited and the
1571 : : * exit status inspection APIs (eg: g_subprocess_get_if_exited(),
1572 : : * g_subprocess_get_exit_status()) may be used.
1573 : : *
1574 : : * You should not attempt to use any of the subprocess pipes after
1575 : : * starting this function, since they may be left in strange states,
1576 : : * even if the operation was cancelled. You should especially not
1577 : : * attempt to interact with the pipes while the operation is in progress
1578 : : * (either from another thread or if using the asynchronous version).
1579 : : *
1580 : : * Returns: %TRUE if successful
1581 : : *
1582 : : * Since: 2.40
1583 : : **/
1584 : : gboolean
1585 : 12 : g_subprocess_communicate (GSubprocess *subprocess,
1586 : : GBytes *stdin_buf,
1587 : : GCancellable *cancellable,
1588 : : GBytes **stdout_buf,
1589 : : GBytes **stderr_buf,
1590 : : GError **error)
1591 : : {
1592 : 12 : GAsyncResult *result = NULL;
1593 : : gboolean success;
1594 : :
1595 : 12 : g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), FALSE);
1596 : 12 : g_return_val_if_fail (stdin_buf == NULL || (subprocess->flags & G_SUBPROCESS_FLAGS_STDIN_PIPE), FALSE);
1597 : 12 : g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
1598 : 12 : g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1599 : :
1600 : 12 : g_subprocess_sync_setup ();
1601 : 12 : g_subprocess_communicate_internal (subprocess, FALSE, stdin_buf, cancellable,
1602 : : g_subprocess_sync_done, &result);
1603 : 12 : g_subprocess_sync_complete (&result);
1604 : 12 : success = g_subprocess_communicate_finish (subprocess, result, stdout_buf, stderr_buf, error);
1605 : 12 : g_object_unref (result);
1606 : :
1607 : 12 : return success;
1608 : : }
1609 : :
1610 : : /**
1611 : : * g_subprocess_communicate_async:
1612 : : * @subprocess: Self
1613 : : * @stdin_buf: (nullable): Input data, or %NULL
1614 : : * @cancellable: (nullable): Cancellable
1615 : : * @callback: Callback
1616 : : * @user_data: User data
1617 : : *
1618 : : * Asynchronous version of g_subprocess_communicate(). Complete
1619 : : * invocation with g_subprocess_communicate_finish().
1620 : : */
1621 : : void
1622 : 12 : g_subprocess_communicate_async (GSubprocess *subprocess,
1623 : : GBytes *stdin_buf,
1624 : : GCancellable *cancellable,
1625 : : GAsyncReadyCallback callback,
1626 : : gpointer user_data)
1627 : : {
1628 : 12 : g_return_if_fail (G_IS_SUBPROCESS (subprocess));
1629 : 12 : g_return_if_fail (stdin_buf == NULL || (subprocess->flags & G_SUBPROCESS_FLAGS_STDIN_PIPE));
1630 : 12 : g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1631 : :
1632 : 12 : g_subprocess_communicate_internal (subprocess, FALSE, stdin_buf, cancellable, callback, user_data);
1633 : : }
1634 : :
1635 : : /**
1636 : : * g_subprocess_communicate_finish:
1637 : : * @subprocess: Self
1638 : : * @result: Result
1639 : : * @stdout_buf: (out) (nullable) (optional) (transfer full): Return location for stdout data
1640 : : * @stderr_buf: (out) (nullable) (optional) (transfer full): Return location for stderr data
1641 : : * @error: Error
1642 : : *
1643 : : * Complete an invocation of g_subprocess_communicate_async().
1644 : : */
1645 : : gboolean
1646 : 24 : g_subprocess_communicate_finish (GSubprocess *subprocess,
1647 : : GAsyncResult *result,
1648 : : GBytes **stdout_buf,
1649 : : GBytes **stderr_buf,
1650 : : GError **error)
1651 : : {
1652 : : gboolean success;
1653 : : CommunicateState *state;
1654 : :
1655 : 24 : g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), FALSE);
1656 : 24 : g_return_val_if_fail (g_task_is_valid (result, subprocess), FALSE);
1657 : 24 : g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1658 : :
1659 : 24 : g_object_ref (result);
1660 : :
1661 : 24 : state = g_task_get_task_data ((GTask*)result);
1662 : 24 : success = g_task_propagate_boolean ((GTask*)result, error);
1663 : :
1664 : 24 : if (success)
1665 : : {
1666 : 12 : if (stdout_buf)
1667 : 12 : *stdout_buf = (state->stdout_buf != NULL) ? g_memory_output_stream_steal_as_bytes (state->stdout_buf) : NULL;
1668 : 12 : if (stderr_buf)
1669 : 12 : *stderr_buf = (state->stderr_buf != NULL) ? g_memory_output_stream_steal_as_bytes (state->stderr_buf) : NULL;
1670 : : }
1671 : :
1672 : 24 : g_object_unref (result);
1673 : 24 : return success;
1674 : : }
1675 : :
1676 : : /**
1677 : : * g_subprocess_communicate_utf8:
1678 : : * @subprocess: a #GSubprocess
1679 : : * @stdin_buf: (nullable): data to send to the stdin of the subprocess, or %NULL
1680 : : * @cancellable: a #GCancellable
1681 : : * @stdout_buf: (out) (nullable) (optional) (transfer full): data read from the subprocess stdout
1682 : : * @stderr_buf: (out) (nullable) (optional) (transfer full): data read from the subprocess stderr
1683 : : * @error: a pointer to a %NULL #GError pointer, or %NULL
1684 : : *
1685 : : * Like g_subprocess_communicate(), but validates the output of the
1686 : : * process as UTF-8, and returns it as a regular NUL terminated string.
1687 : : *
1688 : : * On error, @stdout_buf and @stderr_buf will be set to undefined values and
1689 : : * should not be used.
1690 : : */
1691 : : gboolean
1692 : 15 : g_subprocess_communicate_utf8 (GSubprocess *subprocess,
1693 : : const char *stdin_buf,
1694 : : GCancellable *cancellable,
1695 : : char **stdout_buf,
1696 : : char **stderr_buf,
1697 : : GError **error)
1698 : : {
1699 : 15 : GAsyncResult *result = NULL;
1700 : : gboolean success;
1701 : : GBytes *stdin_bytes;
1702 : 15 : size_t stdin_buf_len = 0;
1703 : :
1704 : 15 : g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), FALSE);
1705 : 15 : g_return_val_if_fail (stdin_buf == NULL || (subprocess->flags & G_SUBPROCESS_FLAGS_STDIN_PIPE), FALSE);
1706 : 15 : g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
1707 : 15 : g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1708 : :
1709 : 15 : if (stdin_buf != NULL)
1710 : 14 : stdin_buf_len = strlen (stdin_buf);
1711 : 15 : stdin_bytes = g_bytes_new (stdin_buf, stdin_buf_len);
1712 : :
1713 : 15 : g_subprocess_sync_setup ();
1714 : 15 : g_subprocess_communicate_internal (subprocess, TRUE, stdin_bytes, cancellable,
1715 : : g_subprocess_sync_done, &result);
1716 : 15 : g_subprocess_sync_complete (&result);
1717 : 15 : success = g_subprocess_communicate_utf8_finish (subprocess, result, stdout_buf, stderr_buf, error);
1718 : 15 : g_object_unref (result);
1719 : :
1720 : 15 : g_bytes_unref (stdin_bytes);
1721 : 15 : return success;
1722 : : }
1723 : :
1724 : : /**
1725 : : * g_subprocess_communicate_utf8_async:
1726 : : * @subprocess: Self
1727 : : * @stdin_buf: (nullable): Input data, or %NULL
1728 : : * @cancellable: Cancellable
1729 : : * @callback: Callback
1730 : : * @user_data: User data
1731 : : *
1732 : : * Asynchronous version of g_subprocess_communicate_utf8(). Complete
1733 : : * invocation with g_subprocess_communicate_utf8_finish().
1734 : : */
1735 : : void
1736 : 13 : g_subprocess_communicate_utf8_async (GSubprocess *subprocess,
1737 : : const char *stdin_buf,
1738 : : GCancellable *cancellable,
1739 : : GAsyncReadyCallback callback,
1740 : : gpointer user_data)
1741 : : {
1742 : : GBytes *stdin_bytes;
1743 : 13 : size_t stdin_buf_len = 0;
1744 : :
1745 : 13 : g_return_if_fail (G_IS_SUBPROCESS (subprocess));
1746 : 13 : g_return_if_fail (stdin_buf == NULL || (subprocess->flags & G_SUBPROCESS_FLAGS_STDIN_PIPE));
1747 : 13 : g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1748 : :
1749 : 13 : if (stdin_buf != NULL)
1750 : 13 : stdin_buf_len = strlen (stdin_buf);
1751 : 13 : stdin_bytes = g_bytes_new (stdin_buf, stdin_buf_len);
1752 : :
1753 : 13 : g_subprocess_communicate_internal (subprocess, TRUE, stdin_bytes, cancellable, callback, user_data);
1754 : :
1755 : 13 : g_bytes_unref (stdin_bytes);
1756 : : }
1757 : :
1758 : : static gboolean
1759 : 30 : communicate_result_validate_utf8 (const char *stream_name,
1760 : : char **return_location,
1761 : : GMemoryOutputStream *buffer,
1762 : : GError **error)
1763 : : {
1764 : 30 : if (return_location == NULL)
1765 : 0 : return TRUE;
1766 : :
1767 : 30 : if (buffer)
1768 : : {
1769 : : const char *end;
1770 : 14 : *return_location = g_memory_output_stream_steal_data (buffer);
1771 : 14 : if (!g_utf8_validate (*return_location, -1, &end))
1772 : : {
1773 : 2 : g_free (*return_location);
1774 : 2 : *return_location = NULL;
1775 : 2 : g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
1776 : : "Invalid UTF-8 in child %s at offset %lu",
1777 : : stream_name,
1778 : 2 : (unsigned long) (end - *return_location));
1779 : 2 : return FALSE;
1780 : : }
1781 : : }
1782 : : else
1783 : 16 : *return_location = NULL;
1784 : :
1785 : 28 : return TRUE;
1786 : : }
1787 : :
1788 : : /**
1789 : : * g_subprocess_communicate_utf8_finish:
1790 : : * @subprocess: Self
1791 : : * @result: Result
1792 : : * @stdout_buf: (out) (nullable) (optional) (transfer full): Return location for stdout data
1793 : : * @stderr_buf: (out) (nullable) (optional) (transfer full): Return location for stderr data
1794 : : * @error: Error
1795 : : *
1796 : : * Complete an invocation of g_subprocess_communicate_utf8_async().
1797 : : */
1798 : : gboolean
1799 : 28 : g_subprocess_communicate_utf8_finish (GSubprocess *subprocess,
1800 : : GAsyncResult *result,
1801 : : char **stdout_buf,
1802 : : char **stderr_buf,
1803 : : GError **error)
1804 : : {
1805 : 28 : gboolean ret = FALSE;
1806 : : CommunicateState *state;
1807 : 28 : gchar *local_stdout_buf = NULL, *local_stderr_buf = NULL;
1808 : :
1809 : 28 : g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), FALSE);
1810 : 28 : g_return_val_if_fail (g_task_is_valid (result, subprocess), FALSE);
1811 : 28 : g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1812 : :
1813 : 28 : g_object_ref (result);
1814 : :
1815 : 28 : state = g_task_get_task_data ((GTask*)result);
1816 : 28 : if (!g_task_propagate_boolean ((GTask*)result, error))
1817 : 12 : goto out;
1818 : :
1819 : : /* TODO - validate UTF-8 while streaming, rather than all at once.
1820 : : */
1821 : 16 : if (!communicate_result_validate_utf8 ("stdout", &local_stdout_buf,
1822 : : state->stdout_buf,
1823 : : error))
1824 : 2 : goto out;
1825 : 14 : if (!communicate_result_validate_utf8 ("stderr", &local_stderr_buf,
1826 : : state->stderr_buf,
1827 : : error))
1828 : 0 : goto out;
1829 : :
1830 : 14 : ret = TRUE;
1831 : 28 : out:
1832 : 28 : g_object_unref (result);
1833 : :
1834 : 28 : if (ret && stdout_buf != NULL)
1835 : 14 : *stdout_buf = g_steal_pointer (&local_stdout_buf);
1836 : 28 : if (ret && stderr_buf != NULL)
1837 : 12 : *stderr_buf = g_steal_pointer (&local_stderr_buf);
1838 : :
1839 : 28 : g_free (local_stderr_buf);
1840 : 28 : g_free (local_stdout_buf);
1841 : :
1842 : 28 : return ret;
1843 : : }
|