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