Branch data Line data Source code
1 : : /* gspawn.c - Process launching
2 : : *
3 : : * Copyright 2000 Red Hat, Inc.
4 : : * g_execvpe implementation based on GNU libc execvp:
5 : : * Copyright 1991, 92, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
6 : : *
7 : : * SPDX-License-Identifier: LGPL-2.1-or-later
8 : : *
9 : : * This library is free software; you can redistribute it and/or
10 : : * modify it under the terms of the GNU Lesser General Public
11 : : * License as published by the Free Software Foundation; either
12 : : * version 2.1 of the License, or (at your option) any later version.
13 : : *
14 : : * This library is distributed in the hope that it will be useful,
15 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : : * Lesser General Public License for more details.
18 : : *
19 : : * You should have received a copy of the GNU Lesser General Public License
20 : : * along with this library; if not, see <http://www.gnu.org/licenses/>.
21 : : */
22 : :
23 : : #include "config.h"
24 : :
25 : : #include <sys/time.h>
26 : : #include <sys/types.h>
27 : : #include <sys/wait.h>
28 : : #include <unistd.h>
29 : : #include <errno.h>
30 : : #include <fcntl.h>
31 : : #include <signal.h>
32 : : #include <string.h>
33 : : #include <stdlib.h> /* for fdwalk */
34 : : #include <dirent.h>
35 : : #include <unistd.h>
36 : :
37 : : #ifdef HAVE_SPAWN_H
38 : : #include <spawn.h>
39 : : #endif /* HAVE_SPAWN_H */
40 : :
41 : : #ifdef HAVE_CRT_EXTERNS_H
42 : : #include <crt_externs.h> /* for _NSGetEnviron */
43 : : #endif
44 : :
45 : : #ifdef HAVE_SYS_SELECT_H
46 : : #include <sys/select.h>
47 : : #endif /* HAVE_SYS_SELECT_H */
48 : :
49 : : #ifdef HAVE_SYS_RESOURCE_H
50 : : #include <sys/resource.h>
51 : : #endif /* HAVE_SYS_RESOURCE_H */
52 : :
53 : : #if defined(__linux__) || defined(__DragonFly__)
54 : : #include <sys/syscall.h> /* for syscall and SYS_getdents64 */
55 : : #endif
56 : :
57 : : #include "gspawn.h"
58 : : #include "gspawn-private.h"
59 : : #include "gthread.h"
60 : : #include "gtrace-private.h"
61 : : #include "glib/gstdio.h"
62 : :
63 : : #include "genviron.h"
64 : : #include "gmem.h"
65 : : #include "gshell.h"
66 : : #include "gstring.h"
67 : : #include "gstrfuncs.h"
68 : : #include "gtestutils.h"
69 : : #include "gutils.h"
70 : : #include "glibintl.h"
71 : : #include "glib-unix.h"
72 : :
73 : : #if defined(__APPLE__) && defined(HAVE_LIBPROC_H)
74 : : #include <libproc.h>
75 : : #include <sys/proc_info.h>
76 : : #endif
77 : :
78 : : #define INHERITS_OR_NULL_STDIN (G_SPAWN_STDIN_FROM_DEV_NULL | G_SPAWN_CHILD_INHERITS_STDIN)
79 : : #define INHERITS_OR_NULL_STDOUT (G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_CHILD_INHERITS_STDOUT)
80 : : #define INHERITS_OR_NULL_STDERR (G_SPAWN_STDERR_TO_DEV_NULL | G_SPAWN_CHILD_INHERITS_STDERR)
81 : :
82 : : #define IS_STD_FILENO(_fd) ((_fd >= STDIN_FILENO) && (_fd <= STDERR_FILENO))
83 : : #define IS_VALID_FILENO(_fd) (_fd >= 0)
84 : :
85 : : /* posix_spawn() is assumed the fastest way to spawn, but glibc's
86 : : * implementation was buggy before glibc 2.24, so avoid it on old versions.
87 : : */
88 : : #ifdef HAVE_POSIX_SPAWN
89 : : #ifdef __GLIBC__
90 : :
91 : : #if __GLIBC_PREREQ(2,24)
92 : : #define POSIX_SPAWN_AVAILABLE
93 : : #endif
94 : :
95 : : #else /* !__GLIBC__ */
96 : : /* Assume that all non-glibc posix_spawn implementations are fine. */
97 : : #define POSIX_SPAWN_AVAILABLE
98 : : #endif /* __GLIBC__ */
99 : : #endif /* HAVE_POSIX_SPAWN */
100 : :
101 : : #ifdef HAVE__NSGETENVIRON
102 : : #define environ (*_NSGetEnviron())
103 : : #else
104 : : extern char **environ;
105 : : #endif
106 : :
107 : : #ifndef O_CLOEXEC
108 : : #define O_CLOEXEC 0
109 : : #else
110 : : #define HAVE_O_CLOEXEC 1
111 : : #endif
112 : :
113 : : static gint g_execute (const gchar *file,
114 : : gchar **argv,
115 : : gchar **argv_buffer,
116 : : gsize argv_buffer_len,
117 : : gchar **envp,
118 : : const gchar *search_path,
119 : : gchar *search_path_buffer,
120 : : gsize search_path_buffer_len);
121 : :
122 : : static gboolean fork_exec (gboolean intermediate_child,
123 : : const gchar *working_directory,
124 : : const gchar * const *argv,
125 : : const gchar * const *envp,
126 : : gboolean close_descriptors,
127 : : gboolean search_path,
128 : : gboolean search_path_from_envp,
129 : : gboolean stdout_to_null,
130 : : gboolean stderr_to_null,
131 : : gboolean child_inherits_stdin,
132 : : gboolean file_and_argv_zero,
133 : : gboolean cloexec_pipes,
134 : : GSpawnChildSetupFunc child_setup,
135 : : gpointer user_data,
136 : : GPid *child_pid,
137 : : gint *stdin_pipe_out,
138 : : gint *stdout_pipe_out,
139 : : gint *stderr_pipe_out,
140 : : gint stdin_fd,
141 : : gint stdout_fd,
142 : : gint stderr_fd,
143 : : const gint *source_fds,
144 : : const gint *target_fds,
145 : : gsize n_fds,
146 : : GError **error);
147 : :
148 [ + + ]: 31 : G_DEFINE_QUARK (g-exec-error-quark, g_spawn_error)
149 [ + + ]: 64 : G_DEFINE_QUARK (g-spawn-exit-error-quark, g_spawn_exit_error)
150 : :
151 : : /**
152 : : * g_spawn_async:
153 : : * @working_directory: (type filename) (nullable): child's current working
154 : : * directory, or %NULL to inherit parent's
155 : : * @argv: (array zero-terminated=1) (element-type filename):
156 : : * child's argument vector
157 : : * @envp: (array zero-terminated=1) (element-type filename) (nullable):
158 : : * child's environment, or %NULL to inherit parent's
159 : : * @flags: flags from #GSpawnFlags
160 : : * @child_setup: (scope async) (closure user_data) (nullable): function to run
161 : : * in the child just before `exec()`
162 : : * @user_data: user data for @child_setup
163 : : * @child_pid: (out) (optional): return location for child process reference, or %NULL
164 : : * @error: return location for error
165 : : *
166 : : * Executes a child program asynchronously.
167 : : *
168 : : * See g_spawn_async_with_pipes() for a full description; this function
169 : : * simply calls the g_spawn_async_with_pipes() without any pipes.
170 : : *
171 : : * You should call g_spawn_close_pid() on the returned child process
172 : : * reference when you don't need it any more.
173 : : *
174 : : * If you are writing a GTK application, and the program you are spawning is a
175 : : * graphical application too, then to ensure that the spawned program opens its
176 : : * windows on the right screen, you may want to use #GdkAppLaunchContext,
177 : : * #GAppLaunchContext, or set the %DISPLAY environment variable.
178 : : *
179 : : * Note that the returned @child_pid on Windows is a handle to the child
180 : : * process and not its identifier. Process handles and process identifiers
181 : : * are different concepts on Windows.
182 : : *
183 : : * Returns: %TRUE on success, %FALSE if error is set
184 : : **/
185 : : gboolean
186 : 38 : g_spawn_async (const gchar *working_directory,
187 : : gchar **argv,
188 : : gchar **envp,
189 : : GSpawnFlags flags,
190 : : GSpawnChildSetupFunc child_setup,
191 : : gpointer user_data,
192 : : GPid *child_pid,
193 : : GError **error)
194 : : {
195 : 38 : return g_spawn_async_with_pipes (working_directory,
196 : : argv, envp,
197 : : flags,
198 : : child_setup,
199 : : user_data,
200 : : child_pid,
201 : : NULL, NULL, NULL,
202 : : error);
203 : : }
204 : :
205 : : /* Some versions of OS X define READ_OK in public headers */
206 : : #undef READ_OK
207 : :
208 : : typedef enum
209 : : {
210 : : READ_FAILED = 0, /* FALSE */
211 : : READ_OK,
212 : : READ_EOF
213 : : } ReadResult;
214 : :
215 : : static ReadResult
216 : 624 : read_data (GString *str,
217 : : gint fd,
218 : : GError **error)
219 : : {
220 : : gssize bytes;
221 : : gchar buf[4096];
222 : :
223 : 624 : again:
224 : 624 : bytes = read (fd, buf, 4096);
225 : :
226 [ + + ]: 624 : if (bytes == 0)
227 : 292 : return READ_EOF;
228 [ + - ]: 332 : else if (bytes > 0)
229 : : {
230 : : g_string_append_len (str, buf, bytes);
231 : 332 : return READ_OK;
232 : : }
233 [ # # ]: 0 : else if (errno == EINTR)
234 : 0 : goto again;
235 : : else
236 : : {
237 : 0 : int errsv = errno;
238 : :
239 : 0 : g_set_error (error,
240 : : G_SPAWN_ERROR,
241 : : G_SPAWN_ERROR_READ,
242 : : _("Failed to read data from child process (%s)"),
243 : : g_strerror (errsv));
244 : :
245 : 0 : return READ_FAILED;
246 : : }
247 : : }
248 : :
249 : : /**
250 : : * g_spawn_sync:
251 : : * @working_directory: (type filename) (nullable): child's current working
252 : : * directory, or %NULL to inherit parent's
253 : : * @argv: (array zero-terminated=1) (element-type filename):
254 : : * child's argument vector, which must be non-empty and %NULL-terminated
255 : : * @envp: (array zero-terminated=1) (element-type filename) (nullable):
256 : : * child's environment, or %NULL to inherit parent's
257 : : * @flags: flags from #GSpawnFlags
258 : : * @child_setup: (scope call) (closure user_data) (nullable): function to run
259 : : * in the child just before `exec()`
260 : : * @user_data: user data for @child_setup
261 : : * @standard_output: (out) (array zero-terminated=1) (element-type guint8) (optional): return location for child output, or %NULL
262 : : * @standard_error: (out) (array zero-terminated=1) (element-type guint8) (optional): return location for child error messages, or %NULL
263 : : * @wait_status: (out) (optional): return location for child wait status, as returned by waitpid(), or %NULL
264 : : * @error: return location for error, or %NULL
265 : : *
266 : : * Executes a child synchronously (waits for the child to exit before returning).
267 : : *
268 : : * All output from the child is stored in @standard_output and @standard_error,
269 : : * if those parameters are non-%NULL. Note that you must set the
270 : : * %G_SPAWN_STDOUT_TO_DEV_NULL and %G_SPAWN_STDERR_TO_DEV_NULL flags when
271 : : * passing %NULL for @standard_output and @standard_error.
272 : : *
273 : : * If @wait_status is non-%NULL, the platform-specific status of
274 : : * the child is stored there; see the documentation of
275 : : * g_spawn_check_wait_status() for how to use and interpret this.
276 : : * On Unix platforms, note that it is usually not equal
277 : : * to the integer passed to `exit()` or returned from `main()`.
278 : : *
279 : : * Note that it is invalid to pass %G_SPAWN_DO_NOT_REAP_CHILD in
280 : : * @flags, and on POSIX platforms, the same restrictions as for
281 : : * g_child_watch_source_new() apply.
282 : : *
283 : : * If an error occurs, no data is returned in @standard_output,
284 : : * @standard_error, or @wait_status.
285 : : *
286 : : * This function calls g_spawn_async_with_pipes() internally; see that
287 : : * function for full details on the other parameters and details on
288 : : * how these functions work on Windows.
289 : : *
290 : : * Returns: %TRUE on success, %FALSE if an error was set
291 : : */
292 : : gboolean
293 : 296 : g_spawn_sync (const gchar *working_directory,
294 : : gchar **argv,
295 : : gchar **envp,
296 : : GSpawnFlags flags,
297 : : GSpawnChildSetupFunc child_setup,
298 : : gpointer user_data,
299 : : gchar **standard_output,
300 : : gchar **standard_error,
301 : : gint *wait_status,
302 : : GError **error)
303 : : {
304 : 296 : gint outpipe = -1;
305 : 296 : gint errpipe = -1;
306 : : GPid pid;
307 : : gint ret;
308 : 296 : GString *outstr = NULL;
309 : 296 : GString *errstr = NULL;
310 : : gboolean failed;
311 : : gint status;
312 : :
313 : 296 : g_return_val_if_fail (argv != NULL, FALSE);
314 : 296 : g_return_val_if_fail (argv[0] != NULL, FALSE);
315 : 296 : g_return_val_if_fail (!(flags & G_SPAWN_DO_NOT_REAP_CHILD), FALSE);
316 : 296 : g_return_val_if_fail (standard_output == NULL ||
317 : : !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
318 : 296 : g_return_val_if_fail (standard_error == NULL ||
319 : : !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
320 : :
321 : : /* Just to ensure segfaults if callers try to use
322 : : * these when an error is reported.
323 : : */
324 [ + + ]: 296 : if (standard_output)
325 : 217 : *standard_output = NULL;
326 : :
327 [ + + ]: 296 : if (standard_error)
328 : 76 : *standard_error = NULL;
329 : :
330 [ + + + + : 592 : if (!fork_exec (FALSE,
+ + ]
331 : : working_directory,
332 : : (const gchar * const *) argv,
333 : : (const gchar * const *) envp,
334 : 296 : !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
335 : 296 : (flags & G_SPAWN_SEARCH_PATH) != 0,
336 : 296 : (flags & G_SPAWN_SEARCH_PATH_FROM_ENVP) != 0,
337 : 296 : (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
338 : 296 : (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
339 : 296 : (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
340 : 296 : (flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0,
341 : 296 : (flags & G_SPAWN_CLOEXEC_PIPES) != 0,
342 : : child_setup,
343 : : user_data,
344 : : &pid,
345 : : NULL,
346 : : standard_output ? &outpipe : NULL,
347 : : standard_error ? &errpipe : NULL,
348 : : -1, -1, -1,
349 : : NULL, NULL, 0,
350 : : error))
351 : 6 : return FALSE;
352 : :
353 : : /* Read data from child. */
354 : :
355 : 290 : failed = FALSE;
356 : :
357 [ + + ]: 290 : if (outpipe >= 0)
358 : : {
359 : 216 : outstr = g_string_new (NULL);
360 : : }
361 : :
362 [ + + ]: 290 : if (errpipe >= 0)
363 : : {
364 : 76 : errstr = g_string_new (NULL);
365 : : }
366 : :
367 : : /* Read data until we get EOF on both pipes. */
368 [ + - ]: 859 : while (!failed &&
369 [ + + ]: 859 : (outpipe >= 0 ||
370 [ + + ]: 308 : errpipe >= 0))
371 : : {
372 : : /* Any negative FD in the array is ignored, so we can use a fixed length.
373 : : * We can use UNIX FDs here without worrying about Windows HANDLEs because
374 : : * the Windows implementation is entirely in gspawn-win32.c. */
375 : 569 : GPollFD fds[] =
376 : : {
377 : : { outpipe, G_IO_IN | G_IO_HUP | G_IO_ERR, 0 },
378 : : { errpipe, G_IO_IN | G_IO_HUP | G_IO_ERR, 0 },
379 : : };
380 : :
381 : 569 : ret = g_poll (fds, G_N_ELEMENTS (fds), -1 /* no timeout */);
382 : :
383 [ - + ]: 569 : if (ret < 0)
384 : : {
385 : 0 : int errsv = errno;
386 : :
387 [ # # ]: 0 : if (errno == EINTR)
388 : 0 : continue;
389 : :
390 : 0 : failed = TRUE;
391 : :
392 : 0 : g_set_error (error,
393 : : G_SPAWN_ERROR,
394 : : G_SPAWN_ERROR_READ,
395 : : _("Unexpected error in reading data from a child process (%s)"),
396 : : g_strerror (errsv));
397 : :
398 : 0 : break;
399 : : }
400 : :
401 [ + + + + ]: 569 : if (outpipe >= 0 && fds[0].revents != 0)
402 : : {
403 [ - + + ]: 524 : switch (read_data (outstr, outpipe, error))
404 : : {
405 : 0 : case READ_FAILED:
406 : 0 : failed = TRUE;
407 : 0 : break;
408 : 216 : case READ_EOF:
409 : 216 : g_clear_fd (&outpipe, NULL);
410 : 216 : break;
411 : 308 : default:
412 : 308 : break;
413 : : }
414 : :
415 [ - + ]: 524 : if (failed)
416 : 0 : break;
417 : : }
418 : :
419 [ + + + + ]: 569 : if (errpipe >= 0 && fds[1].revents != 0)
420 : : {
421 [ - + + ]: 100 : switch (read_data (errstr, errpipe, error))
422 : : {
423 : 0 : case READ_FAILED:
424 : 0 : failed = TRUE;
425 : 0 : break;
426 : 76 : case READ_EOF:
427 : 76 : g_clear_fd (&errpipe, NULL);
428 : 76 : break;
429 : 24 : default:
430 : 24 : break;
431 : : }
432 : :
433 [ - + ]: 100 : if (failed)
434 : 0 : break;
435 : : }
436 : : }
437 : :
438 : : /* These should only be open still if we had an error. */
439 : 290 : g_clear_fd (&outpipe, NULL);
440 : 290 : g_clear_fd (&errpipe, NULL);
441 : :
442 : : /* Wait for child to exit, even if we have
443 : : * an error pending.
444 : : */
445 : 290 : again:
446 : :
447 : 290 : ret = waitpid (pid, &status, 0);
448 : :
449 [ - + ]: 290 : if (ret < 0)
450 : : {
451 [ # # ]: 0 : if (errno == EINTR)
452 : 0 : goto again;
453 [ # # ]: 0 : else if (errno == ECHILD)
454 : : {
455 [ # # ]: 0 : if (wait_status)
456 : : {
457 : 0 : g_warning ("In call to g_spawn_sync(), wait status of a child process was requested but ECHILD was received by waitpid(). See the documentation of g_child_watch_source_new() for possible causes.");
458 : : }
459 : : else
460 : : {
461 : : /* We don't need the wait status. */
462 : : }
463 : : }
464 : : else
465 : : {
466 [ # # ]: 0 : if (!failed) /* avoid error pileups */
467 : : {
468 : 0 : int errsv = errno;
469 : :
470 : 0 : failed = TRUE;
471 : :
472 : 0 : g_set_error (error,
473 : : G_SPAWN_ERROR,
474 : : G_SPAWN_ERROR_READ,
475 : : _("Unexpected error in waitpid() (%s)"),
476 : : g_strerror (errsv));
477 : : }
478 : : }
479 : : }
480 : :
481 [ - + ]: 290 : if (failed)
482 : : {
483 [ # # ]: 0 : if (outstr)
484 : 0 : g_string_free (outstr, TRUE);
485 [ # # ]: 0 : if (errstr)
486 : 0 : g_string_free (errstr, TRUE);
487 : :
488 : 0 : return FALSE;
489 : : }
490 : : else
491 : : {
492 [ + + ]: 290 : if (wait_status)
493 : 254 : *wait_status = status;
494 : :
495 [ + + ]: 290 : if (standard_output)
496 : 216 : *standard_output = g_string_free (outstr, FALSE);
497 : :
498 [ + + ]: 290 : if (standard_error)
499 : 76 : *standard_error = g_string_free (errstr, FALSE);
500 : :
501 : 290 : return TRUE;
502 : : }
503 : : }
504 : :
505 : : /**
506 : : * g_spawn_async_with_pipes:
507 : : * @working_directory: (type filename) (nullable): child's current working
508 : : * directory, or %NULL to inherit parent's, in the GLib file name encoding
509 : : * @argv: (array zero-terminated=1) (element-type filename): child's argument
510 : : * vector, in the GLib file name encoding; it must be non-empty and %NULL-terminated
511 : : * @envp: (array zero-terminated=1) (element-type filename) (nullable):
512 : : * child's environment, or %NULL to inherit parent's, in the GLib file
513 : : * name encoding
514 : : * @flags: flags from #GSpawnFlags
515 : : * @child_setup: (scope async) (closure user_data) (nullable): function to run
516 : : * in the child just before `exec()`
517 : : * @user_data: user data for @child_setup
518 : : * @child_pid: (out) (optional): return location for child process ID, or %NULL
519 : : * @standard_input: (out) (optional): return location for file descriptor to write to child's stdin, or %NULL
520 : : * @standard_output: (out) (optional): return location for file descriptor to read child's stdout, or %NULL
521 : : * @standard_error: (out) (optional): return location for file descriptor to read child's stderr, or %NULL
522 : : * @error: return location for error
523 : : *
524 : : * Identical to g_spawn_async_with_pipes_and_fds() but with `n_fds` set to zero,
525 : : * so no FD assignments are used.
526 : : *
527 : : * Returns: %TRUE on success, %FALSE if an error was set
528 : : */
529 : : gboolean
530 : 430 : g_spawn_async_with_pipes (const gchar *working_directory,
531 : : gchar **argv,
532 : : gchar **envp,
533 : : GSpawnFlags flags,
534 : : GSpawnChildSetupFunc child_setup,
535 : : gpointer user_data,
536 : : GPid *child_pid,
537 : : gint *standard_input,
538 : : gint *standard_output,
539 : : gint *standard_error,
540 : : GError **error)
541 : : {
542 : 430 : return g_spawn_async_with_pipes_and_fds (working_directory,
543 : : (const gchar * const *) argv,
544 : : (const gchar * const *) envp,
545 : : flags,
546 : : child_setup, user_data,
547 : : -1, -1, -1,
548 : : NULL, NULL, 0,
549 : : child_pid,
550 : : standard_input,
551 : : standard_output,
552 : : standard_error,
553 : : error);
554 : : }
555 : :
556 : : /**
557 : : * g_spawn_async_with_pipes_and_fds:
558 : : * @working_directory: (type filename) (nullable): child's current working
559 : : * directory, or %NULL to inherit parent's, in the GLib file name encoding
560 : : * @argv: (array zero-terminated=1) (element-type filename): child's argument
561 : : * vector, in the GLib file name encoding; it must be non-empty and %NULL-terminated
562 : : * @envp: (array zero-terminated=1) (element-type filename) (nullable):
563 : : * child's environment, or %NULL to inherit parent's, in the GLib file
564 : : * name encoding
565 : : * @flags: flags from #GSpawnFlags
566 : : * @child_setup: (scope async) (closure user_data) (nullable): function to run
567 : : * in the child just before `exec()`
568 : : * @user_data: user data for @child_setup
569 : : * @stdin_fd: file descriptor to use for child's stdin, or `-1`
570 : : * @stdout_fd: file descriptor to use for child's stdout, or `-1`
571 : : * @stderr_fd: file descriptor to use for child's stderr, or `-1`
572 : : * @source_fds: (array length=n_fds) (nullable): array of FDs from the parent
573 : : * process to make available in the child process
574 : : * @target_fds: (array length=n_fds) (nullable): array of FDs to remap
575 : : * @source_fds to in the child process
576 : : * @n_fds: number of FDs in @source_fds and @target_fds
577 : : * @child_pid_out: (out) (optional): return location for child process ID, or %NULL
578 : : * @stdin_pipe_out: (out) (optional): return location for file descriptor to write to child's stdin, or %NULL
579 : : * @stdout_pipe_out: (out) (optional): return location for file descriptor to read child's stdout, or %NULL
580 : : * @stderr_pipe_out: (out) (optional): return location for file descriptor to read child's stderr, or %NULL
581 : : * @error: return location for error
582 : : *
583 : : * Executes a child program asynchronously (your program will not
584 : : * block waiting for the child to exit).
585 : : *
586 : : * The child program is specified by the only argument that must be
587 : : * provided, @argv. @argv should be a %NULL-terminated array of strings,
588 : : * to be passed as the argument vector for the child. The first string
589 : : * in @argv is of course the name of the program to execute. By default,
590 : : * the name of the program must be a full path. If @flags contains the
591 : : * %G_SPAWN_SEARCH_PATH flag, the `PATH` environment variable is used to
592 : : * search for the executable. If @flags contains the
593 : : * %G_SPAWN_SEARCH_PATH_FROM_ENVP flag, the `PATH` variable from @envp
594 : : * is used to search for the executable. If both the
595 : : * %G_SPAWN_SEARCH_PATH and %G_SPAWN_SEARCH_PATH_FROM_ENVP flags are
596 : : * set, the `PATH` variable from @envp takes precedence over the
597 : : * environment variable.
598 : : *
599 : : * If the program name is not a full path and %G_SPAWN_SEARCH_PATH flag
600 : : * is not used, then the program will be run from the current directory
601 : : * (or @working_directory, if specified); this might be unexpected or even
602 : : * dangerous in some cases when the current directory is world-writable.
603 : : *
604 : : * On Windows, note that all the string or string vector arguments to
605 : : * this function and the other `g_spawn*()` functions are in UTF-8, the
606 : : * GLib file name encoding. Unicode characters that are not part of
607 : : * the system codepage passed in these arguments will be correctly
608 : : * available in the spawned program only if it uses wide character API
609 : : * to retrieve its command line. For C programs built with Microsoft's
610 : : * tools it is enough to make the program have a `wmain()` instead of
611 : : * `main()`. `wmain()` has a wide character argument vector as parameter.
612 : : *
613 : : * At least currently, mingw doesn't support `wmain()`, so if you use
614 : : * mingw to develop the spawned program, it should call
615 : : * g_win32_get_command_line() to get arguments in UTF-8.
616 : : *
617 : : * On Windows the low-level child process creation API `CreateProcess()`
618 : : * doesn't use argument vectors, but a command line. The C runtime
619 : : * library's `spawn*()` family of functions (which g_spawn_async_with_pipes()
620 : : * eventually calls) paste the argument vector elements together into
621 : : * a command line, and the C runtime startup code does a corresponding
622 : : * reconstruction of an argument vector from the command line, to be
623 : : * passed to `main()`. Complications arise when you have argument vector
624 : : * elements that contain spaces or double quotes. The `spawn*()` functions
625 : : * don't do any quoting or escaping, but on the other hand the startup
626 : : * code does do unquoting and unescaping in order to enable receiving
627 : : * arguments with embedded spaces or double quotes. To work around this
628 : : * asymmetry, g_spawn_async_with_pipes() will do quoting and escaping on
629 : : * argument vector elements that need it before calling the C runtime
630 : : * `spawn()` function.
631 : : *
632 : : * The returned @child_pid on Windows is a handle to the child
633 : : * process, not its identifier. Process handles and process
634 : : * identifiers are different concepts on Windows.
635 : : *
636 : : * @envp is a %NULL-terminated array of strings, where each string
637 : : * has the form `KEY=VALUE`. This will become the child's environment.
638 : : * If @envp is %NULL, the child inherits its parent's environment.
639 : : *
640 : : * @flags should be the bitwise OR of any flags you want to affect the
641 : : * function's behaviour. The %G_SPAWN_DO_NOT_REAP_CHILD means that the
642 : : * child will not automatically be reaped; you must use a child watch
643 : : * (g_child_watch_add()) to be notified about the death of the child process,
644 : : * otherwise it will stay around as a zombie process until this process exits.
645 : : * Eventually you must call g_spawn_close_pid() on the @child_pid, in order to
646 : : * free resources which may be associated with the child process. (On Unix,
647 : : * using a child watch is equivalent to calling waitpid() or handling
648 : : * the `SIGCHLD` signal manually. On Windows, calling g_spawn_close_pid()
649 : : * is equivalent to calling `CloseHandle()` on the process handle returned
650 : : * in @child_pid). See g_child_watch_add().
651 : : *
652 : : * Open UNIX file descriptors marked as `FD_CLOEXEC` will be automatically
653 : : * closed in the child process. %G_SPAWN_LEAVE_DESCRIPTORS_OPEN means that
654 : : * other open file descriptors will be inherited by the child; otherwise all
655 : : * descriptors except stdin/stdout/stderr will be closed before calling `exec()`
656 : : * in the child. %G_SPAWN_SEARCH_PATH means that @argv[0] need not be an
657 : : * absolute path, it will be looked for in the `PATH` environment
658 : : * variable. %G_SPAWN_SEARCH_PATH_FROM_ENVP means need not be an
659 : : * absolute path, it will be looked for in the `PATH` variable from
660 : : * @envp. If both %G_SPAWN_SEARCH_PATH and %G_SPAWN_SEARCH_PATH_FROM_ENVP
661 : : * are used, the value from @envp takes precedence over the environment.
662 : : *
663 : : * %G_SPAWN_CHILD_INHERITS_STDIN means that the child will inherit the parent's
664 : : * standard input (by default, the child's standard input is attached to
665 : : * `/dev/null`). %G_SPAWN_STDIN_FROM_DEV_NULL explicitly imposes the default
666 : : * behavior. Both flags cannot be enabled at the same time and, in both cases,
667 : : * the @stdin_pipe_out argument is ignored.
668 : : *
669 : : * %G_SPAWN_STDOUT_TO_DEV_NULL means that the child's standard output
670 : : * will be discarded (by default, it goes to the same location as the parent's
671 : : * standard output). %G_SPAWN_CHILD_INHERITS_STDOUT explicitly imposes the
672 : : * default behavior. Both flags cannot be enabled at the same time and, in
673 : : * both cases, the @stdout_pipe_out argument is ignored.
674 : : *
675 : : * %G_SPAWN_STDERR_TO_DEV_NULL means that the child's standard error
676 : : * will be discarded (by default, it goes to the same location as the parent's
677 : : * standard error). %G_SPAWN_CHILD_INHERITS_STDERR explicitly imposes the
678 : : * default behavior. Both flags cannot be enabled at the same time and, in
679 : : * both cases, the @stderr_pipe_out argument is ignored.
680 : : *
681 : : * It is valid to pass the same FD in multiple parameters (e.g. you can pass
682 : : * a single FD for both @stdout_fd and @stderr_fd, and include it in
683 : : * @source_fds too).
684 : : *
685 : : * @source_fds and @target_fds allow zero or more FDs from this process to be
686 : : * remapped to different FDs in the spawned process. If @n_fds is greater than
687 : : * zero, @source_fds and @target_fds must both be non-%NULL and the same length.
688 : : * Each FD in @source_fds is remapped to the FD number at the same index in
689 : : * @target_fds. The source and target FD may be equal to simply propagate an FD
690 : : * to the spawned process. FD remappings are processed after standard FDs, so
691 : : * any target FDs which equal @stdin_fd, @stdout_fd or @stderr_fd will overwrite
692 : : * them in the spawned process.
693 : : *
694 : : * @source_fds is supported on Windows since 2.72.
695 : : *
696 : : * %G_SPAWN_FILE_AND_ARGV_ZERO means that the first element of @argv is
697 : : * the file to execute, while the remaining elements are the actual
698 : : * argument vector to pass to the file. Normally g_spawn_async_with_pipes()
699 : : * uses @argv[0] as the file to execute, and passes all of @argv to the child.
700 : : *
701 : : * @child_setup and @user_data are a function and user data. On POSIX
702 : : * platforms, the function is called in the child after GLib has
703 : : * performed all the setup it plans to perform (including creating
704 : : * pipes, closing file descriptors, etc.) but before calling `exec()`.
705 : : * That is, @child_setup is called just before calling `exec()` in the
706 : : * child. Obviously actions taken in this function will only affect
707 : : * the child, not the parent.
708 : : *
709 : : * On Windows, there is no separate `fork()` and `exec()` functionality.
710 : : * Child processes are created and run with a single API call,
711 : : * `CreateProcess()`. There is no sensible thing @child_setup
712 : : * could be used for on Windows so it is ignored and not called.
713 : : *
714 : : * If non-%NULL, @child_pid will on Unix be filled with the child's
715 : : * process ID. You can use the process ID to send signals to the child,
716 : : * or to use g_child_watch_add() (or `waitpid()`) if you specified the
717 : : * %G_SPAWN_DO_NOT_REAP_CHILD flag. On Windows, @child_pid will be
718 : : * filled with a handle to the child process only if you specified the
719 : : * %G_SPAWN_DO_NOT_REAP_CHILD flag. You can then access the child
720 : : * process using the Win32 API, for example wait for its termination
721 : : * with the `WaitFor*()` functions, or examine its exit code with
722 : : * `GetExitCodeProcess()`. You should close the handle with `CloseHandle()`
723 : : * or g_spawn_close_pid() when you no longer need it.
724 : : *
725 : : * If non-%NULL, the @stdin_pipe_out, @stdout_pipe_out, @stderr_pipe_out
726 : : * locations will be filled with file descriptors for writing to the child's
727 : : * standard input or reading from its standard output or standard error.
728 : : * The caller of g_spawn_async_with_pipes() must close these file descriptors
729 : : * when they are no longer in use. If these parameters are %NULL, the
730 : : * corresponding pipe won't be created.
731 : : *
732 : : * If @stdin_pipe_out is %NULL, the child's standard input is attached to
733 : : * `/dev/null` unless %G_SPAWN_CHILD_INHERITS_STDIN is set.
734 : : *
735 : : * If @stderr_pipe_out is NULL, the child's standard error goes to the same
736 : : * location as the parent's standard error unless %G_SPAWN_STDERR_TO_DEV_NULL
737 : : * is set.
738 : : *
739 : : * If @stdout_pipe_out is NULL, the child's standard output goes to the same
740 : : * location as the parent's standard output unless %G_SPAWN_STDOUT_TO_DEV_NULL
741 : : * is set.
742 : : *
743 : : * @error can be %NULL to ignore errors, or non-%NULL to report errors.
744 : : * If an error is set, the function returns %FALSE. Errors are reported
745 : : * even if they occur in the child (for example if the executable in
746 : : * `@argv[0]` is not found). Typically the `message` field of returned
747 : : * errors should be displayed to users. Possible errors are those from
748 : : * the %G_SPAWN_ERROR domain.
749 : : *
750 : : * If an error occurs, @child_pid, @stdin_pipe_out, @stdout_pipe_out,
751 : : * and @stderr_pipe_out will not be filled with valid values.
752 : : *
753 : : * If @child_pid is not %NULL and an error does not occur then the returned
754 : : * process reference must be closed using g_spawn_close_pid().
755 : : *
756 : : * On modern UNIX platforms, GLib can use an efficient process launching
757 : : * codepath driven internally by `posix_spawn()`. This has the advantage of
758 : : * avoiding the fork-time performance costs of cloning the parent process
759 : : * address space, and avoiding associated memory overcommit checks that are
760 : : * not relevant in the context of immediately executing a distinct process.
761 : : * This optimized codepath will be used provided that the following conditions
762 : : * are met:
763 : : *
764 : : * 1. %G_SPAWN_DO_NOT_REAP_CHILD is set
765 : : * 2. %G_SPAWN_LEAVE_DESCRIPTORS_OPEN is set
766 : : * 3. %G_SPAWN_SEARCH_PATH_FROM_ENVP is not set
767 : : * 4. @working_directory is %NULL
768 : : * 5. @child_setup is %NULL
769 : : * 6. The program is of a recognised binary format, or has a shebang.
770 : : * Otherwise, GLib will have to execute the program through the
771 : : * shell, which is not done using the optimized codepath.
772 : : *
773 : : * If you are writing a GTK application, and the program you are spawning is a
774 : : * graphical application too, then to ensure that the spawned program opens its
775 : : * windows on the right screen, you may want to use #GdkAppLaunchContext,
776 : : * #GAppLaunchContext, or set the `DISPLAY` environment variable.
777 : : *
778 : : * Returns: %TRUE on success, %FALSE if an error was set
779 : : *
780 : : * Since: 2.68
781 : : */
782 : : gboolean
783 : 579 : g_spawn_async_with_pipes_and_fds (const gchar *working_directory,
784 : : const gchar * const *argv,
785 : : const gchar * const *envp,
786 : : GSpawnFlags flags,
787 : : GSpawnChildSetupFunc child_setup,
788 : : gpointer user_data,
789 : : gint stdin_fd,
790 : : gint stdout_fd,
791 : : gint stderr_fd,
792 : : const gint *source_fds,
793 : : const gint *target_fds,
794 : : gsize n_fds,
795 : : GPid *child_pid_out,
796 : : gint *stdin_pipe_out,
797 : : gint *stdout_pipe_out,
798 : : gint *stderr_pipe_out,
799 : : GError **error)
800 : : {
801 : 579 : g_return_val_if_fail (argv != NULL, FALSE);
802 : 579 : g_return_val_if_fail (argv[0] != NULL, FALSE);
803 : : /* can’t both inherit and set pipes to /dev/null */
804 : 579 : g_return_val_if_fail ((flags & INHERITS_OR_NULL_STDIN) != INHERITS_OR_NULL_STDIN, FALSE);
805 : 579 : g_return_val_if_fail ((flags & INHERITS_OR_NULL_STDOUT) != INHERITS_OR_NULL_STDOUT, FALSE);
806 : 579 : g_return_val_if_fail ((flags & INHERITS_OR_NULL_STDERR) != INHERITS_OR_NULL_STDERR, FALSE);
807 : : /* can’t use pipes and stdin/stdout/stderr FDs */
808 : 579 : g_return_val_if_fail (stdin_pipe_out == NULL || stdin_fd < 0, FALSE);
809 : 579 : g_return_val_if_fail (stdout_pipe_out == NULL || stdout_fd < 0, FALSE);
810 : 579 : g_return_val_if_fail (stderr_pipe_out == NULL || stderr_fd < 0, FALSE);
811 : :
812 [ + + ]: 579 : if ((flags & INHERITS_OR_NULL_STDIN) != 0)
813 : 1 : stdin_pipe_out = NULL;
814 [ + + ]: 579 : if ((flags & INHERITS_OR_NULL_STDOUT) != 0)
815 : 34 : stdout_pipe_out = NULL;
816 [ + + ]: 579 : if ((flags & INHERITS_OR_NULL_STDERR) != 0)
817 : 25 : stderr_pipe_out = NULL;
818 : :
819 : 579 : return fork_exec (!(flags & G_SPAWN_DO_NOT_REAP_CHILD),
820 : : working_directory,
821 : : (const gchar * const *) argv,
822 : : (const gchar * const *) envp,
823 : 579 : !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
824 : 579 : (flags & G_SPAWN_SEARCH_PATH) != 0,
825 : 579 : (flags & G_SPAWN_SEARCH_PATH_FROM_ENVP) != 0,
826 : 579 : (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
827 : 579 : (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
828 : 579 : (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
829 : 579 : (flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0,
830 : 579 : (flags & G_SPAWN_CLOEXEC_PIPES) != 0,
831 : : child_setup,
832 : : user_data,
833 : : child_pid_out,
834 : : stdin_pipe_out,
835 : : stdout_pipe_out,
836 : : stderr_pipe_out,
837 : : stdin_fd,
838 : : stdout_fd,
839 : : stderr_fd,
840 : : source_fds,
841 : : target_fds,
842 : : n_fds,
843 : : error);
844 : : }
845 : :
846 : : /**
847 : : * g_spawn_async_with_fds:
848 : : * @working_directory: (type filename) (nullable): child's current working directory, or %NULL to inherit parent's, in the GLib file name encoding
849 : : * @argv: (array zero-terminated=1): child's argument vector, in the GLib file name encoding;
850 : : * it must be non-empty and %NULL-terminated
851 : : * @envp: (array zero-terminated=1) (nullable): child's environment, or %NULL to inherit parent's, in the GLib file name encoding
852 : : * @flags: flags from #GSpawnFlags
853 : : * @child_setup: (scope async) (closure user_data) (nullable): function to run
854 : : * in the child just before `exec()`
855 : : * @user_data: user data for @child_setup
856 : : * @child_pid: (out) (optional): return location for child process ID, or %NULL
857 : : * @stdin_fd: file descriptor to use for child's stdin, or `-1`
858 : : * @stdout_fd: file descriptor to use for child's stdout, or `-1`
859 : : * @stderr_fd: file descriptor to use for child's stderr, or `-1`
860 : : * @error: return location for error
861 : : *
862 : : * Executes a child program asynchronously.
863 : : *
864 : : * Identical to g_spawn_async_with_pipes_and_fds() but with `n_fds` set to zero,
865 : : * so no FD assignments are used.
866 : : *
867 : : * Returns: %TRUE on success, %FALSE if an error was set
868 : : *
869 : : * Since: 2.58
870 : : */
871 : : gboolean
872 : 98 : g_spawn_async_with_fds (const gchar *working_directory,
873 : : gchar **argv,
874 : : gchar **envp,
875 : : GSpawnFlags flags,
876 : : GSpawnChildSetupFunc child_setup,
877 : : gpointer user_data,
878 : : GPid *child_pid,
879 : : gint stdin_fd,
880 : : gint stdout_fd,
881 : : gint stderr_fd,
882 : : GError **error)
883 : : {
884 : 98 : g_return_val_if_fail (argv != NULL, FALSE);
885 : 98 : g_return_val_if_fail (argv[0] != NULL, FALSE);
886 : 98 : g_return_val_if_fail (stdout_fd < 0 ||
887 : : !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
888 : 98 : g_return_val_if_fail (stderr_fd < 0 ||
889 : : !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
890 : : /* can't inherit stdin if we have an input pipe. */
891 : 98 : g_return_val_if_fail (stdin_fd < 0 ||
892 : : !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
893 : :
894 : 98 : return fork_exec (!(flags & G_SPAWN_DO_NOT_REAP_CHILD),
895 : : working_directory,
896 : : (const gchar * const *) argv,
897 : : (const gchar * const *) envp,
898 : 98 : !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
899 : 98 : (flags & G_SPAWN_SEARCH_PATH) != 0,
900 : 98 : (flags & G_SPAWN_SEARCH_PATH_FROM_ENVP) != 0,
901 : 98 : (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
902 : 98 : (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
903 : 98 : (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
904 : 98 : (flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0,
905 : 98 : (flags & G_SPAWN_CLOEXEC_PIPES) != 0,
906 : : child_setup,
907 : : user_data,
908 : : child_pid,
909 : : NULL, NULL, NULL,
910 : : stdin_fd,
911 : : stdout_fd,
912 : : stderr_fd,
913 : : NULL, NULL, 0,
914 : : error);
915 : : }
916 : :
917 : : /**
918 : : * g_spawn_command_line_sync:
919 : : * @command_line: (type filename): a command line
920 : : * @standard_output: (out) (array zero-terminated=1) (element-type guint8) (optional): return location for child output
921 : : * @standard_error: (out) (array zero-terminated=1) (element-type guint8) (optional): return location for child errors
922 : : * @wait_status: (out) (optional): return location for child wait status, as returned by waitpid()
923 : : * @error: return location for errors
924 : : *
925 : : * A simple version of g_spawn_sync() with little-used parameters
926 : : * removed, taking a command line instead of an argument vector.
927 : : *
928 : : * See g_spawn_sync() for full details.
929 : : *
930 : : * The @command_line argument will be parsed by g_shell_parse_argv().
931 : : *
932 : : * Unlike g_spawn_sync(), the %G_SPAWN_SEARCH_PATH flag is enabled.
933 : : * Note that %G_SPAWN_SEARCH_PATH can have security implications, so
934 : : * consider using g_spawn_sync() directly if appropriate.
935 : : *
936 : : * Possible errors are those from g_spawn_sync() and those
937 : : * from g_shell_parse_argv().
938 : : *
939 : : * If @wait_status is non-%NULL, the platform-specific status of
940 : : * the child is stored there; see the documentation of
941 : : * g_spawn_check_wait_status() for how to use and interpret this.
942 : : * On Unix platforms, note that it is usually not equal
943 : : * to the integer passed to `exit()` or returned from `main()`.
944 : : *
945 : : * On Windows, please note the implications of g_shell_parse_argv()
946 : : * parsing @command_line. Parsing is done according to Unix shell rules, not
947 : : * Windows command interpreter rules.
948 : : * Space is a separator, and backslashes are
949 : : * special. Thus you cannot simply pass a @command_line containing
950 : : * canonical Windows paths, like "c:\\program files\\app\\app.exe", as
951 : : * the backslashes will be eaten, and the space will act as a
952 : : * separator. You need to enclose such paths with single quotes, like
953 : : * "'c:\\program files\\app\\app.exe' 'e:\\folder\\argument.txt'".
954 : : *
955 : : * Returns: %TRUE on success, %FALSE if an error was set
956 : : **/
957 : : gboolean
958 : 58 : g_spawn_command_line_sync (const gchar *command_line,
959 : : gchar **standard_output,
960 : : gchar **standard_error,
961 : : gint *wait_status,
962 : : GError **error)
963 : : {
964 : : gboolean retval;
965 : 58 : gchar **argv = NULL;
966 : :
967 : 58 : g_return_val_if_fail (command_line != NULL, FALSE);
968 : :
969 : : /* This will return a runtime error if @command_line is the empty string. */
970 [ - + ]: 58 : if (!g_shell_parse_argv (command_line,
971 : : NULL, &argv,
972 : : error))
973 : 0 : return FALSE;
974 : :
975 : 58 : retval = g_spawn_sync (NULL,
976 : : argv,
977 : : NULL,
978 : : G_SPAWN_SEARCH_PATH,
979 : : NULL,
980 : : NULL,
981 : : standard_output,
982 : : standard_error,
983 : : wait_status,
984 : : error);
985 : 58 : g_strfreev (argv);
986 : :
987 : 58 : return retval;
988 : : }
989 : :
990 : : /**
991 : : * g_spawn_command_line_async:
992 : : * @command_line: (type filename): a command line
993 : : * @error: return location for errors
994 : : *
995 : : * A simple version of g_spawn_async() that parses a command line with
996 : : * g_shell_parse_argv() and passes it to g_spawn_async().
997 : : *
998 : : * Runs a command line in the background. Unlike g_spawn_async(), the
999 : : * %G_SPAWN_SEARCH_PATH flag is enabled, other flags are not. Note
1000 : : * that %G_SPAWN_SEARCH_PATH can have security implications, so
1001 : : * consider using g_spawn_async() directly if appropriate. Possible
1002 : : * errors are those from g_shell_parse_argv() and g_spawn_async().
1003 : : *
1004 : : * The same concerns on Windows apply as for g_spawn_command_line_sync().
1005 : : *
1006 : : * Returns: %TRUE on success, %FALSE if error is set
1007 : : **/
1008 : : gboolean
1009 : 12 : g_spawn_command_line_async (const gchar *command_line,
1010 : : GError **error)
1011 : : {
1012 : : gboolean retval;
1013 : 12 : gchar **argv = NULL;
1014 : :
1015 : 12 : g_return_val_if_fail (command_line != NULL, FALSE);
1016 : :
1017 : : /* This will return a runtime error if @command_line is the empty string. */
1018 [ - + ]: 12 : if (!g_shell_parse_argv (command_line,
1019 : : NULL, &argv,
1020 : : error))
1021 : 0 : return FALSE;
1022 : :
1023 : 12 : retval = g_spawn_async (NULL,
1024 : : argv,
1025 : : NULL,
1026 : : G_SPAWN_SEARCH_PATH,
1027 : : NULL,
1028 : : NULL,
1029 : : NULL,
1030 : : error);
1031 : 12 : g_strfreev (argv);
1032 : :
1033 : 12 : return retval;
1034 : : }
1035 : :
1036 : : /**
1037 : : * g_spawn_check_wait_status:
1038 : : * @wait_status: A platform-specific wait status as returned from g_spawn_sync()
1039 : : * @error: a #GError
1040 : : *
1041 : : * Set @error if @wait_status indicates the child exited abnormally
1042 : : * (e.g. with a nonzero exit code, or via a fatal signal).
1043 : : *
1044 : : * The g_spawn_sync() and g_child_watch_add() family of APIs return the
1045 : : * status of subprocesses encoded in a platform-specific way.
1046 : : * On Unix, this is guaranteed to be in the same format waitpid() returns,
1047 : : * and on Windows it is guaranteed to be the result of GetExitCodeProcess().
1048 : : *
1049 : : * Prior to the introduction of this function in GLib 2.34, interpreting
1050 : : * @wait_status required use of platform-specific APIs, which is problematic
1051 : : * for software using GLib as a cross-platform layer.
1052 : : *
1053 : : * Additionally, many programs simply want to determine whether or not
1054 : : * the child exited successfully, and either propagate a #GError or
1055 : : * print a message to standard error. In that common case, this function
1056 : : * can be used. Note that the error message in @error will contain
1057 : : * human-readable information about the wait status.
1058 : : *
1059 : : * The @domain and @code of @error have special semantics in the case
1060 : : * where the process has an "exit code", as opposed to being killed by
1061 : : * a signal. On Unix, this happens if WIFEXITED() would be true of
1062 : : * @wait_status. On Windows, it is always the case.
1063 : : *
1064 : : * The special semantics are that the actual exit code will be the
1065 : : * code set in @error, and the domain will be %G_SPAWN_EXIT_ERROR.
1066 : : * This allows you to differentiate between different exit codes.
1067 : : *
1068 : : * If the process was terminated by some means other than an exit
1069 : : * status (for example if it was killed by a signal), the domain will be
1070 : : * %G_SPAWN_ERROR and the code will be %G_SPAWN_ERROR_FAILED.
1071 : : *
1072 : : * This function just offers convenience; you can of course also check
1073 : : * the available platform via a macro such as %G_OS_UNIX, and use
1074 : : * WIFEXITED() and WEXITSTATUS() on @wait_status directly. Do not attempt
1075 : : * to scan or parse the error message string; it may be translated and/or
1076 : : * change in future versions of GLib.
1077 : : *
1078 : : * Prior to version 2.70, g_spawn_check_exit_status() provides the same
1079 : : * functionality, although under a misleading name.
1080 : : *
1081 : : * Returns: %TRUE if child exited successfully, %FALSE otherwise (and
1082 : : * @error will be set)
1083 : : *
1084 : : * Since: 2.70
1085 : : */
1086 : : gboolean
1087 : 195 : g_spawn_check_wait_status (gint wait_status,
1088 : : GError **error)
1089 : : {
1090 : 195 : gboolean ret = FALSE;
1091 : :
1092 [ + + ]: 195 : if (WIFEXITED (wait_status))
1093 : : {
1094 [ + + ]: 189 : if (WEXITSTATUS (wait_status) != 0)
1095 : : {
1096 : 46 : g_set_error (error, G_SPAWN_EXIT_ERROR, WEXITSTATUS (wait_status),
1097 : : _("Child process exited with code %ld"),
1098 : 46 : (long) WEXITSTATUS (wait_status));
1099 : 46 : goto out;
1100 : : }
1101 : : }
1102 [ + - ]: 6 : else if (WIFSIGNALED (wait_status))
1103 : : {
1104 : 6 : g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
1105 : : _("Child process killed by signal %ld"),
1106 : 6 : (long) WTERMSIG (wait_status));
1107 : 6 : goto out;
1108 : : }
1109 [ # # ]: 0 : else if (WIFSTOPPED (wait_status))
1110 : : {
1111 : 0 : g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
1112 : : _("Child process stopped by signal %ld"),
1113 : 0 : (long) WSTOPSIG (wait_status));
1114 : 0 : goto out;
1115 : : }
1116 : : else
1117 : : {
1118 : 0 : g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
1119 : : _("Child process exited abnormally"));
1120 : 0 : goto out;
1121 : : }
1122 : :
1123 : 143 : ret = TRUE;
1124 : 195 : out:
1125 : 195 : return ret;
1126 : : }
1127 : :
1128 : : /**
1129 : : * g_spawn_check_exit_status:
1130 : : * @wait_status: A status as returned from g_spawn_sync()
1131 : : * @error: a #GError
1132 : : *
1133 : : * An old name for g_spawn_check_wait_status(), deprecated because its
1134 : : * name is misleading.
1135 : : *
1136 : : * Despite the name of the function, @wait_status must be the wait status
1137 : : * as returned by g_spawn_sync(), g_subprocess_get_status(), `waitpid()`,
1138 : : * etc. On Unix platforms, it is incorrect for it to be the exit status
1139 : : * as passed to `exit()` or returned by g_subprocess_get_exit_status() or
1140 : : * `WEXITSTATUS()`.
1141 : : *
1142 : : * Returns: %TRUE if child exited successfully, %FALSE otherwise (and
1143 : : * @error will be set)
1144 : : *
1145 : : * Since: 2.34
1146 : : *
1147 : : * Deprecated: 2.70: Use g_spawn_check_wait_status() instead, and check whether your code is conflating wait and exit statuses.
1148 : : */
1149 : : gboolean
1150 : 0 : g_spawn_check_exit_status (gint wait_status,
1151 : : GError **error)
1152 : : {
1153 : 0 : return g_spawn_check_wait_status (wait_status, error);
1154 : : }
1155 : :
1156 : : /* This function is called between fork() and exec() and hence must be
1157 : : * async-signal-safe (see signal-safety(7)). */
1158 : : static gssize
1159 : 0 : write_all (gint fd, gconstpointer vbuf, gsize to_write)
1160 : : {
1161 : 0 : gchar *buf = (gchar *) vbuf;
1162 : :
1163 [ # # ]: 0 : while (to_write > 0)
1164 : : {
1165 : 0 : gssize count = write (fd, buf, to_write);
1166 [ # # ]: 0 : if (count < 0)
1167 : : {
1168 [ # # ]: 0 : if (errno != EINTR)
1169 : 0 : return FALSE;
1170 : : }
1171 : : else
1172 : : {
1173 : 0 : to_write -= count;
1174 : 0 : buf += count;
1175 : : }
1176 : : }
1177 : :
1178 : 0 : return TRUE;
1179 : : }
1180 : :
1181 : : /* This function is called between fork() and exec() and hence must be
1182 : : * async-signal-safe (see signal-safety(7)). */
1183 : : G_NORETURN
1184 : : static void
1185 : 0 : write_err_and_exit (gint fd, gint msg)
1186 : : {
1187 : 0 : gint en = errno;
1188 : :
1189 : 0 : write_all (fd, &msg, sizeof(msg));
1190 : 0 : write_all (fd, &en, sizeof(en));
1191 : :
1192 : 0 : _exit (1);
1193 : : }
1194 : :
1195 : : /* This function is called between fork() and exec() and hence must be
1196 : : * async-signal-safe (see signal-safety(7)). */
1197 : : static void
1198 : 2039 : set_cloexec (int fd)
1199 : : {
1200 : 2039 : fcntl (fd, F_SETFD, FD_CLOEXEC);
1201 : 2039 : }
1202 : :
1203 : : /* This function is called between fork() and exec() and hence must be
1204 : : * async-signal-safe (see signal-safety(7)). */
1205 : : static void
1206 : 2 : unset_cloexec (int fd)
1207 : : {
1208 : : int flags;
1209 : : int result;
1210 : :
1211 : 2 : flags = fcntl (fd, F_GETFD, 0);
1212 : :
1213 [ + - ]: 2 : if (flags != -1)
1214 : : {
1215 : : int errsv;
1216 : 2 : flags &= (~FD_CLOEXEC);
1217 : : do
1218 : : {
1219 : 2 : result = fcntl (fd, F_SETFD, flags);
1220 : 2 : errsv = errno;
1221 : : }
1222 [ - + - - ]: 2 : while (result == -1 && errsv == EINTR);
1223 : : }
1224 : 2 : }
1225 : :
1226 : : /* This function is called between fork() and exec() and hence must be
1227 : : * async-signal-safe (see signal-safety(7)). */
1228 : : static int
1229 : 84 : dupfd_cloexec (int old_fd, int new_fd_min)
1230 : : {
1231 : : int fd, errsv;
1232 : : #ifdef F_DUPFD_CLOEXEC
1233 : : do
1234 : : {
1235 : 84 : fd = fcntl (old_fd, F_DUPFD_CLOEXEC, new_fd_min);
1236 : 84 : errsv = errno;
1237 : : }
1238 [ - + - - ]: 84 : while (fd == -1 && errsv == EINTR);
1239 : : #else
1240 : : /* OS X Snow Lion and earlier don't have F_DUPFD_CLOEXEC:
1241 : : * https://bugzilla.gnome.org/show_bug.cgi?id=710962
1242 : : */
1243 : : int result, flags;
1244 : : do
1245 : : {
1246 : : fd = fcntl (old_fd, F_DUPFD, new_fd_min);
1247 : : errsv = errno;
1248 : : }
1249 : : while (fd == -1 && errsv == EINTR);
1250 : : flags = fcntl (fd, F_GETFD, 0);
1251 : : if (flags != -1)
1252 : : {
1253 : : flags |= FD_CLOEXEC;
1254 : : do
1255 : : {
1256 : : result = fcntl (fd, F_SETFD, flags);
1257 : : errsv = errno;
1258 : : }
1259 : : while (result == -1 && errsv == EINTR);
1260 : : }
1261 : : #endif
1262 : 84 : return fd;
1263 : : }
1264 : :
1265 : : /* This function is called between fork() and exec() and hence must be
1266 : : * async-signal-safe (see signal-safety(7)). */
1267 : : static gint
1268 : 3117 : safe_dup2 (gint fd1, gint fd2)
1269 : : {
1270 : : gint ret;
1271 : :
1272 : : do
1273 : 3117 : ret = dup2 (fd1, fd2);
1274 [ - + - - : 3117 : while (ret < 0 && (errno == EINTR || errno == EBUSY));
- - ]
1275 : :
1276 : 3117 : return ret;
1277 : : }
1278 : :
1279 : : /* This function is called between fork() and exec() and hence must be
1280 : : * async-signal-safe (see signal-safety(7)). */
1281 : : static gboolean
1282 : 16 : relocate_fd_out_of_standard_range (gint *fd)
1283 : : {
1284 : 16 : gint ret = -1;
1285 : 16 : const int min_fileno = STDERR_FILENO + 1;
1286 : :
1287 : : do
1288 : 16 : ret = fcntl (*fd, F_DUPFD, min_fileno);
1289 [ - + - - ]: 16 : while (ret < 0 && errno == EINTR);
1290 : :
1291 : : /* Note we don't need to close the old fd, because the caller is expected
1292 : : * to close fds in the standard range itself.
1293 : : */
1294 [ + - ]: 16 : if (ret >= min_fileno)
1295 : : {
1296 : 16 : *fd = ret;
1297 : 16 : return TRUE;
1298 : : }
1299 : :
1300 : 0 : return FALSE;
1301 : : }
1302 : :
1303 : : /* This function is called between fork() and exec() and hence must be
1304 : : * async-signal-safe (see signal-safety(7)). */
1305 : : static gint
1306 : 1135 : safe_open (const char *path, gint mode)
1307 : : {
1308 : : gint ret;
1309 : :
1310 : : do
1311 : 1135 : ret = open (path, mode);
1312 [ - + - - ]: 1135 : while (ret < 0 && errno == EINTR);
1313 : :
1314 : 1135 : return ret;
1315 : : }
1316 : :
1317 : : enum
1318 : : {
1319 : : CHILD_CHDIR_FAILED,
1320 : : CHILD_EXEC_FAILED,
1321 : : CHILD_OPEN_FAILED,
1322 : : CHILD_DUPFD_FAILED,
1323 : : CHILD_FORK_FAILED,
1324 : : CHILD_CLOSE_FAILED,
1325 : : };
1326 : :
1327 : : /* This function is called between fork() and exec() and hence must be
1328 : : * async-signal-safe (see signal-safety(7)) until it calls exec().
1329 : : *
1330 : : * All callers must guarantee that @argv and @argv[0] are non-NULL. */
1331 : : static void
1332 : 904 : do_exec (gint child_err_report_fd,
1333 : : gint stdin_fd,
1334 : : gint stdout_fd,
1335 : : gint stderr_fd,
1336 : : gint *source_fds,
1337 : : const gint *target_fds,
1338 : : gsize n_fds,
1339 : : const gchar *working_directory,
1340 : : const gchar * const *argv,
1341 : : gchar **argv_buffer,
1342 : : gsize argv_buffer_len,
1343 : : const gchar * const *envp,
1344 : : gboolean close_descriptors,
1345 : : const gchar *search_path,
1346 : : gchar *search_path_buffer,
1347 : : gsize search_path_buffer_len,
1348 : : gboolean stdout_to_null,
1349 : : gboolean stderr_to_null,
1350 : : gboolean child_inherits_stdin,
1351 : : gboolean file_and_argv_zero,
1352 : : GSpawnChildSetupFunc child_setup,
1353 : : gpointer user_data)
1354 : : {
1355 : : gsize i;
1356 : 904 : gint max_target_fd = 0;
1357 : :
1358 [ + + - + ]: 904 : if (working_directory && chdir (working_directory) < 0)
1359 : 0 : write_err_and_exit (child_err_report_fd,
1360 : : CHILD_CHDIR_FAILED);
1361 : :
1362 : : /* It's possible the caller assigned stdin to an fd with a
1363 : : * file number that is supposed to be reserved for
1364 : : * stdout or stderr.
1365 : : *
1366 : : * If so, move it up out of the standard range, so it doesn't
1367 : : * cause a conflict.
1368 : : */
1369 [ + + - + : 904 : if (IS_STD_FILENO (stdin_fd) && stdin_fd != STDIN_FILENO)
- - ]
1370 : : {
1371 : 0 : int old_fd = stdin_fd;
1372 : :
1373 [ # # ]: 0 : if (!relocate_fd_out_of_standard_range (&stdin_fd))
1374 : 0 : write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
1375 : :
1376 [ # # ]: 0 : if (stdout_fd == old_fd)
1377 : 0 : stdout_fd = stdin_fd;
1378 : :
1379 [ # # ]: 0 : if (stderr_fd == old_fd)
1380 : 0 : stderr_fd = stdin_fd;
1381 : : }
1382 : :
1383 : : /* Redirect pipes as required
1384 : : *
1385 : : * There are two cases where we don't need to do the redirection
1386 : : * 1. Where the associated file descriptor is cleared/invalid
1387 : : * 2. When the associated file descriptor is already given the
1388 : : * correct file number.
1389 : : */
1390 [ + + + - ]: 904 : if (IS_VALID_FILENO (stdin_fd) && stdin_fd != STDIN_FILENO)
1391 : : {
1392 [ - + ]: 60 : if (safe_dup2 (stdin_fd, 0) < 0)
1393 : 0 : write_err_and_exit (child_err_report_fd,
1394 : : CHILD_DUPFD_FAILED);
1395 : :
1396 : 60 : set_cloexec (stdin_fd);
1397 : : }
1398 [ + + ]: 844 : else if (!child_inherits_stdin)
1399 : : {
1400 : : /* Keep process from blocking on a read of stdin */
1401 : 843 : gint read_null = safe_open ("/dev/null", O_RDONLY);
1402 [ - + ]: 843 : if (read_null < 0)
1403 : 0 : write_err_and_exit (child_err_report_fd,
1404 : : CHILD_OPEN_FAILED);
1405 [ - + ]: 843 : if (safe_dup2 (read_null, 0) < 0)
1406 : 0 : write_err_and_exit (child_err_report_fd,
1407 : : CHILD_DUPFD_FAILED);
1408 : 843 : g_clear_fd (&read_null, NULL);
1409 : : }
1410 : :
1411 : : /* Like with stdin above, it's possible the caller assigned
1412 : : * stdout to an fd with a file number that's intruding on the
1413 : : * standard range.
1414 : : *
1415 : : * If so, move it out of the way, too.
1416 : : */
1417 [ + + + + : 904 : if (IS_STD_FILENO (stdout_fd) && stdout_fd != STDOUT_FILENO)
+ + ]
1418 : : {
1419 : 4 : int old_fd = stdout_fd;
1420 : :
1421 [ - + ]: 4 : if (!relocate_fd_out_of_standard_range (&stdout_fd))
1422 : 0 : write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
1423 : :
1424 [ - + ]: 4 : if (stderr_fd == old_fd)
1425 : 0 : stderr_fd = stdout_fd;
1426 : : }
1427 : :
1428 [ + + + + ]: 904 : if (IS_VALID_FILENO (stdout_fd) && stdout_fd != STDOUT_FILENO)
1429 : : {
1430 [ - + ]: 638 : if (safe_dup2 (stdout_fd, 1) < 0)
1431 : 0 : write_err_and_exit (child_err_report_fd,
1432 : : CHILD_DUPFD_FAILED);
1433 : :
1434 : 638 : set_cloexec (stdout_fd);
1435 : : }
1436 [ + + ]: 266 : else if (stdout_to_null)
1437 : : {
1438 : 90 : gint write_null = safe_open ("/dev/null", O_WRONLY);
1439 [ - + ]: 90 : if (write_null < 0)
1440 : 0 : write_err_and_exit (child_err_report_fd,
1441 : : CHILD_OPEN_FAILED);
1442 [ - + ]: 90 : if (safe_dup2 (write_null, 1) < 0)
1443 : 0 : write_err_and_exit (child_err_report_fd,
1444 : : CHILD_DUPFD_FAILED);
1445 : 90 : g_clear_fd (&write_null, NULL);
1446 : : }
1447 : :
1448 [ + + + + : 904 : if (IS_STD_FILENO (stderr_fd) && stderr_fd != STDERR_FILENO)
+ + ]
1449 : : {
1450 [ - + ]: 12 : if (!relocate_fd_out_of_standard_range (&stderr_fd))
1451 : 0 : write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
1452 : : }
1453 : :
1454 : : /* Like with stdin/stdout above, it's possible the caller assigned
1455 : : * stderr to an fd with a file number that's intruding on the
1456 : : * standard range.
1457 : : *
1458 : : * Make sure it's out of the way, also.
1459 : : */
1460 [ + + + + ]: 904 : if (IS_VALID_FILENO (stderr_fd) && stderr_fd != STDERR_FILENO)
1461 : : {
1462 [ - + ]: 445 : if (safe_dup2 (stderr_fd, 2) < 0)
1463 : 0 : write_err_and_exit (child_err_report_fd,
1464 : : CHILD_DUPFD_FAILED);
1465 : :
1466 : 445 : set_cloexec (stderr_fd);
1467 : : }
1468 [ + + ]: 459 : else if (stderr_to_null)
1469 : : {
1470 : 127 : gint write_null = safe_open ("/dev/null", O_WRONLY);
1471 [ - + ]: 127 : if (write_null < 0)
1472 : 0 : write_err_and_exit (child_err_report_fd,
1473 : : CHILD_OPEN_FAILED);
1474 [ - + ]: 127 : if (safe_dup2 (write_null, 2) < 0)
1475 : 0 : write_err_and_exit (child_err_report_fd,
1476 : : CHILD_DUPFD_FAILED);
1477 : 127 : g_clear_fd (&write_null, NULL);
1478 : : }
1479 : :
1480 : : /* Close all file descriptors but stdin, stdout and stderr, and any of source_fds,
1481 : : * before we exec. Note that this includes
1482 : : * child_err_report_fd, which keeps the parent from blocking
1483 : : * forever on the other end of that pipe.
1484 : : */
1485 [ + - ]: 904 : if (close_descriptors)
1486 : : {
1487 [ + + + + ]: 904 : if (child_setup == NULL && n_fds == 0)
1488 : : {
1489 [ - + ]: 896 : if (safe_dup2 (child_err_report_fd, 3) < 0)
1490 : 0 : write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
1491 : 896 : set_cloexec (3);
1492 [ - + ]: 896 : if (g_closefrom (4) < 0)
1493 : 0 : write_err_and_exit (child_err_report_fd, CHILD_CLOSE_FAILED);
1494 : 896 : child_err_report_fd = 3;
1495 : : }
1496 : : else
1497 : : {
1498 [ - + ]: 8 : if (g_fdwalk_set_cloexec (3) < 0)
1499 : 0 : write_err_and_exit (child_err_report_fd, CHILD_CLOSE_FAILED);
1500 : : }
1501 : : }
1502 : : else
1503 : : {
1504 : : /* We need to do child_err_report_fd anyway */
1505 : 0 : set_cloexec (child_err_report_fd);
1506 : : }
1507 : :
1508 : : /*
1509 : : * Work through the @source_fds and @target_fds mapping.
1510 : : *
1511 : : * Based on code originally derived from
1512 : : * gnome-terminal:src/terminal-screen.c:terminal_screen_child_setup(),
1513 : : * used under the LGPLv2+ with permission from author. (The code has
1514 : : * since migrated to vte:src/spawn.cc:SpawnContext::exec and is no longer
1515 : : * terribly similar to what we have here.)
1516 : : */
1517 : :
1518 [ + + ]: 904 : if (n_fds > 0)
1519 : : {
1520 [ + + ]: 26 : for (i = 0; i < n_fds; i++)
1521 : 20 : max_target_fd = MAX (max_target_fd, target_fds[i]);
1522 : :
1523 [ - + ]: 6 : if (max_target_fd == G_MAXINT)
1524 : : {
1525 : 0 : errno = EINVAL;
1526 : 0 : write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
1527 : : }
1528 : :
1529 : : /* If we're doing remapping fd assignments, we need to handle
1530 : : * the case where the user has specified e.g. 5 -> 4, 4 -> 6.
1531 : : * We do this by duping all source fds, taking care to ensure the new
1532 : : * fds are larger than any target fd to avoid introducing new conflicts.
1533 : : */
1534 [ + + ]: 26 : for (i = 0; i < n_fds; i++)
1535 : : {
1536 [ + + ]: 20 : if (source_fds[i] != target_fds[i])
1537 : : {
1538 : 18 : source_fds[i] = dupfd_cloexec (source_fds[i], max_target_fd + 1);
1539 [ - + ]: 18 : if (source_fds[i] < 0)
1540 : 0 : write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
1541 : : }
1542 : : }
1543 : :
1544 [ + + ]: 26 : for (i = 0; i < n_fds; i++)
1545 : : {
1546 : : /* For basic fd assignments (where source == target), we can just
1547 : : * unset FD_CLOEXEC.
1548 : : */
1549 [ + + ]: 20 : if (source_fds[i] == target_fds[i])
1550 : : {
1551 : 2 : unset_cloexec (source_fds[i]);
1552 : : }
1553 : : else
1554 : : {
1555 : : /* If any of the @target_fds conflict with @child_err_report_fd,
1556 : : * dup it so it doesn’t get conflated.
1557 : : */
1558 [ + + ]: 18 : if (target_fds[i] == child_err_report_fd)
1559 : : {
1560 : 2 : child_err_report_fd = dupfd_cloexec (child_err_report_fd, max_target_fd + 1);
1561 [ - + ]: 2 : if (child_err_report_fd < 0)
1562 : 0 : write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
1563 : : }
1564 : :
1565 [ - + ]: 18 : if (safe_dup2 (source_fds[i], target_fds[i]) < 0)
1566 : 0 : write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
1567 : :
1568 : 18 : g_clear_fd (&source_fds[i], NULL);
1569 : : }
1570 : : }
1571 : : }
1572 : :
1573 : : /* Call user function just before we exec */
1574 [ + + ]: 904 : if (child_setup)
1575 : : {
1576 : 5 : (* child_setup) (user_data);
1577 : : }
1578 : :
1579 [ - + ]: 904 : g_execute (argv[0],
1580 : : (gchar **) (file_and_argv_zero ? argv + 1 : argv),
1581 : : argv_buffer, argv_buffer_len,
1582 : : (gchar **) envp, search_path, search_path_buffer, search_path_buffer_len);
1583 : :
1584 : : /* Exec failed */
1585 : 0 : write_err_and_exit (child_err_report_fd,
1586 : : CHILD_EXEC_FAILED);
1587 : : }
1588 : :
1589 : : static gboolean
1590 : 1010 : read_ints (int fd,
1591 : : gint* buf,
1592 : : gint n_ints_in_buf,
1593 : : gint *n_ints_read,
1594 : : GError **error)
1595 : : {
1596 : 1010 : gsize bytes = 0;
1597 : :
1598 : : while (TRUE)
1599 : 115 : {
1600 : : gssize chunk;
1601 : :
1602 [ + + ]: 1125 : if (bytes >= sizeof(gint)*2)
1603 : 9 : break; /* give up, who knows what happened, should not be
1604 : : * possible.
1605 : : */
1606 : :
1607 : 1116 : again:
1608 : 1116 : chunk = read (fd,
1609 : : ((gchar*)buf) + bytes,
1610 : 1116 : sizeof(gint) * n_ints_in_buf - bytes);
1611 [ - + - - ]: 1116 : if (chunk < 0 && errno == EINTR)
1612 : 0 : goto again;
1613 : :
1614 [ - + ]: 1116 : if (chunk < 0)
1615 : : {
1616 : 0 : int errsv = errno;
1617 : :
1618 : : /* Some weird shit happened, bail out */
1619 : 0 : g_set_error (error,
1620 : : G_SPAWN_ERROR,
1621 : : G_SPAWN_ERROR_FAILED,
1622 : : _("Failed to read from child pipe (%s)"),
1623 : : g_strerror (errsv));
1624 : :
1625 : 0 : return FALSE;
1626 : : }
1627 [ + + ]: 1116 : else if (chunk == 0)
1628 : 1001 : break; /* EOF */
1629 : : else /* chunk > 0 */
1630 : 115 : bytes += chunk;
1631 : : }
1632 : :
1633 : 1010 : *n_ints_read = (gint)(bytes / sizeof(gint));
1634 : :
1635 : 1010 : return TRUE;
1636 : : }
1637 : :
1638 : : #ifdef POSIX_SPAWN_AVAILABLE
1639 : : static gboolean
1640 : 67 : do_posix_spawn (const gchar * const *argv,
1641 : : const gchar * const *envp,
1642 : : gboolean search_path,
1643 : : gboolean stdout_to_null,
1644 : : gboolean stderr_to_null,
1645 : : gboolean child_inherits_stdin,
1646 : : gboolean file_and_argv_zero,
1647 : : GPid *child_pid,
1648 : : gint *child_close_fds,
1649 : : gint stdin_fd,
1650 : : gint stdout_fd,
1651 : : gint stderr_fd,
1652 : : const gint *source_fds,
1653 : : const gint *target_fds,
1654 : : gsize n_fds)
1655 : : {
1656 : : pid_t pid;
1657 : 67 : gint *duped_source_fds = NULL;
1658 : 67 : gint max_target_fd = 0;
1659 : : const gchar * const *argv_pass;
1660 : : posix_spawnattr_t attr;
1661 : : posix_spawn_file_actions_t file_actions;
1662 : : gint parent_close_fds[3];
1663 : 67 : gsize num_parent_close_fds = 0;
1664 : 67 : GSList *child_close = NULL;
1665 : : GSList *elem;
1666 : : sigset_t mask;
1667 : : gsize i;
1668 : : int r;
1669 : :
1670 : 67 : g_assert (argv != NULL && argv[0] != NULL);
1671 : :
1672 [ - + ]: 67 : if (*argv[0] == '\0')
1673 : : {
1674 : : /* We check the simple case first. */
1675 : 0 : return ENOENT;
1676 : : }
1677 : :
1678 : 67 : r = posix_spawnattr_init (&attr);
1679 [ - + ]: 67 : if (r != 0)
1680 : 0 : return r;
1681 : :
1682 [ + - ]: 67 : if (child_close_fds)
1683 : : {
1684 : 67 : int i = -1;
1685 [ + + ]: 68 : while (child_close_fds[++i] != -1)
1686 : 1 : child_close = g_slist_prepend (child_close,
1687 : 1 : GINT_TO_POINTER (child_close_fds[i]));
1688 : : }
1689 : :
1690 : 67 : r = posix_spawnattr_setflags (&attr, POSIX_SPAWN_SETSIGDEF);
1691 [ - + ]: 67 : if (r != 0)
1692 : 0 : goto out_free_spawnattr;
1693 : :
1694 : : /* Reset some signal handlers that we may use */
1695 : 67 : sigemptyset (&mask);
1696 : 67 : sigaddset (&mask, SIGCHLD);
1697 : 67 : sigaddset (&mask, SIGINT);
1698 : 67 : sigaddset (&mask, SIGTERM);
1699 : 67 : sigaddset (&mask, SIGHUP);
1700 : :
1701 : 67 : r = posix_spawnattr_setsigdefault (&attr, &mask);
1702 [ - + ]: 67 : if (r != 0)
1703 : 0 : goto out_free_spawnattr;
1704 : :
1705 : 67 : r = posix_spawn_file_actions_init (&file_actions);
1706 [ - + ]: 67 : if (r != 0)
1707 : 0 : goto out_free_spawnattr;
1708 : :
1709 : : /* Redirect pipes as required */
1710 : :
1711 [ - + ]: 67 : if (stdin_fd >= 0)
1712 : : {
1713 : 0 : r = posix_spawn_file_actions_adddup2 (&file_actions, stdin_fd, 0);
1714 [ # # ]: 0 : if (r != 0)
1715 : 0 : goto out_close_fds;
1716 : :
1717 [ # # ]: 0 : if (!g_slist_find (child_close, GINT_TO_POINTER (stdin_fd)))
1718 : 0 : child_close = g_slist_prepend (child_close, GINT_TO_POINTER (stdin_fd));
1719 : : }
1720 [ + - ]: 67 : else if (!child_inherits_stdin)
1721 : : {
1722 : : /* Keep process from blocking on a read of stdin */
1723 : 67 : gint read_null = safe_open ("/dev/null", O_RDONLY | O_CLOEXEC);
1724 : 67 : g_assert (read_null != -1);
1725 : 67 : parent_close_fds[num_parent_close_fds++] = read_null;
1726 : :
1727 : : #ifndef HAVE_O_CLOEXEC
1728 : : fcntl (read_null, F_SETFD, FD_CLOEXEC);
1729 : : #endif
1730 : :
1731 : 67 : r = posix_spawn_file_actions_adddup2 (&file_actions, read_null, 0);
1732 [ - + ]: 67 : if (r != 0)
1733 : 0 : goto out_close_fds;
1734 : : }
1735 : :
1736 [ + + ]: 67 : if (stdout_fd >= 0)
1737 : : {
1738 : 1 : r = posix_spawn_file_actions_adddup2 (&file_actions, stdout_fd, 1);
1739 [ - + ]: 1 : if (r != 0)
1740 : 0 : goto out_close_fds;
1741 : :
1742 [ + - ]: 1 : if (!g_slist_find (child_close, GINT_TO_POINTER (stdout_fd)))
1743 : 1 : child_close = g_slist_prepend (child_close, GINT_TO_POINTER (stdout_fd));
1744 : : }
1745 [ + + ]: 66 : else if (stdout_to_null)
1746 : : {
1747 : 4 : gint write_null = safe_open ("/dev/null", O_WRONLY | O_CLOEXEC);
1748 : 4 : g_assert (write_null != -1);
1749 : 4 : parent_close_fds[num_parent_close_fds++] = write_null;
1750 : :
1751 : : #ifndef HAVE_O_CLOEXEC
1752 : : fcntl (write_null, F_SETFD, FD_CLOEXEC);
1753 : : #endif
1754 : :
1755 : 4 : r = posix_spawn_file_actions_adddup2 (&file_actions, write_null, 1);
1756 [ - + ]: 4 : if (r != 0)
1757 : 0 : goto out_close_fds;
1758 : : }
1759 : :
1760 [ - + ]: 67 : if (stderr_fd >= 0)
1761 : : {
1762 : 0 : r = posix_spawn_file_actions_adddup2 (&file_actions, stderr_fd, 2);
1763 [ # # ]: 0 : if (r != 0)
1764 : 0 : goto out_close_fds;
1765 : :
1766 [ # # ]: 0 : if (!g_slist_find (child_close, GINT_TO_POINTER (stderr_fd)))
1767 : 0 : child_close = g_slist_prepend (child_close, GINT_TO_POINTER (stderr_fd));
1768 : : }
1769 [ + + ]: 67 : else if (stderr_to_null)
1770 : : {
1771 : 4 : gint write_null = safe_open ("/dev/null", O_WRONLY | O_CLOEXEC);
1772 : 4 : g_assert (write_null != -1);
1773 : 4 : parent_close_fds[num_parent_close_fds++] = write_null;
1774 : :
1775 : : #ifndef HAVE_O_CLOEXEC
1776 : : fcntl (write_null, F_SETFD, FD_CLOEXEC);
1777 : : #endif
1778 : :
1779 : 4 : r = posix_spawn_file_actions_adddup2 (&file_actions, write_null, 2);
1780 [ - + ]: 4 : if (r != 0)
1781 : 0 : goto out_close_fds;
1782 : : }
1783 : :
1784 : : /* If source_fds[i] != target_fds[i], we need to handle the case
1785 : : * where the user has specified, e.g., 5 -> 4, 4 -> 6. We do this
1786 : : * by duping the source fds, taking care to ensure the new fds are
1787 : : * larger than any target fd to avoid introducing new conflicts.
1788 : : *
1789 : : * If source_fds[i] == target_fds[i], then we just need to leak
1790 : : * the fd into the child process, which we *could* do by temporarily
1791 : : * unsetting CLOEXEC and then setting it again after we spawn if
1792 : : * it was originally set. POSIX requires that the addup2 action unset
1793 : : * CLOEXEC if source and target are identical, so you'd think doing it
1794 : : * manually wouldn't be needed, but unfortunately as of 2021 many
1795 : : * libcs still don't do so. Example nonconforming libcs:
1796 : : * Bionic: https://android.googlesource.com/platform/bionic/+/f6e5b582604715729b09db3e36a7aeb8c24b36a4/libc/bionic/spawn.cpp#71
1797 : : * uclibc-ng: https://cgit.uclibc-ng.org/cgi/cgit/uclibc-ng.git/tree/librt/spawn.c?id=7c36bcae09d66bbaa35cbb02253ae0556f42677e#n88
1798 : : *
1799 : : * Anyway, unsetting CLOEXEC ourselves would open a small race window
1800 : : * where the fd could be inherited into a child process if another
1801 : : * thread spawns something at the same time, because we have not
1802 : : * called fork() and are multithreaded here. This race is avoidable by
1803 : : * using dupfd_cloexec, which we already have to do to handle the
1804 : : * source_fds[i] != target_fds[i] case. So let's always do it!
1805 : : */
1806 : :
1807 [ + + ]: 131 : for (i = 0; i < n_fds; i++)
1808 : 64 : max_target_fd = MAX (max_target_fd, target_fds[i]);
1809 : :
1810 [ - + ]: 67 : if (max_target_fd == G_MAXINT)
1811 : 0 : goto out_close_fds;
1812 : :
1813 : 67 : duped_source_fds = g_new (gint, n_fds);
1814 [ + + ]: 131 : for (i = 0; i < n_fds; i++)
1815 : 64 : duped_source_fds[i] = -1; /* initialise in case dupfd_cloexec() fails below */
1816 [ + + ]: 131 : for (i = 0; i < n_fds; i++)
1817 : : {
1818 : 64 : duped_source_fds[i] = dupfd_cloexec (source_fds[i], max_target_fd + 1);
1819 [ - + ]: 64 : if (duped_source_fds[i] < 0)
1820 : 0 : goto out_close_fds;
1821 : : }
1822 : :
1823 [ + + ]: 131 : for (i = 0; i < n_fds; i++)
1824 : : {
1825 : 64 : r = posix_spawn_file_actions_adddup2 (&file_actions, duped_source_fds[i], target_fds[i]);
1826 [ - + ]: 64 : if (r != 0)
1827 : 0 : goto out_close_fds;
1828 : : }
1829 : :
1830 : : /* Intentionally close the fds in the child as the last file action,
1831 : : * having been careful not to add the same fd to this list twice.
1832 : : *
1833 : : * This is important to allow (e.g.) for the same fd to be passed as stdout
1834 : : * and stderr (we must not close it before we have dupped it in both places,
1835 : : * and we must not attempt to close it twice).
1836 : : */
1837 [ + + ]: 69 : for (elem = child_close; elem != NULL; elem = elem->next)
1838 : : {
1839 : 2 : r = posix_spawn_file_actions_addclose (&file_actions,
1840 : 2 : GPOINTER_TO_INT (elem->data));
1841 [ - + ]: 2 : if (r != 0)
1842 : 0 : goto out_close_fds;
1843 : : }
1844 : :
1845 [ - + ]: 67 : argv_pass = file_and_argv_zero ? argv + 1 : argv;
1846 [ + + ]: 67 : if (envp == NULL)
1847 : 65 : envp = (const gchar * const *) environ;
1848 : :
1849 : : /* Don't search when it contains a slash. */
1850 [ + + - + ]: 67 : if (!search_path || strchr (argv[0], '/') != NULL)
1851 : 7 : r = posix_spawn (&pid, argv[0], &file_actions, &attr, (char * const *) argv_pass, (char * const *) envp);
1852 : : else
1853 : 60 : r = posix_spawnp (&pid, argv[0], &file_actions, &attr, (char * const *) argv_pass, (char * const *) envp);
1854 : :
1855 [ - + - + ]: 67 : if (r == 0 && child_pid != NULL)
1856 : 67 : *child_pid = pid;
1857 : :
1858 : 0 : out_close_fds:
1859 [ + + ]: 142 : for (i = 0; i < num_parent_close_fds; i++)
1860 : 75 : g_clear_fd (&parent_close_fds[i], NULL);
1861 : :
1862 [ + + ]: 67 : if (duped_source_fds != NULL)
1863 : : {
1864 [ + + ]: 126 : for (i = 0; i < n_fds; i++)
1865 : 64 : g_clear_fd (&duped_source_fds[i], NULL);
1866 : 62 : g_free (duped_source_fds);
1867 : : }
1868 : :
1869 : 67 : posix_spawn_file_actions_destroy (&file_actions);
1870 : 67 : out_free_spawnattr:
1871 : 67 : posix_spawnattr_destroy (&attr);
1872 : 67 : g_slist_free (child_close);
1873 : :
1874 : 67 : return r;
1875 : : }
1876 : : #endif /* POSIX_SPAWN_AVAILABLE */
1877 : :
1878 : : static gboolean
1879 : 2147 : source_fds_collide_with_pipe (const GUnixPipe *pipefd,
1880 : : const int *source_fds,
1881 : : gsize n_fds,
1882 : : GError **error)
1883 : : {
1884 [ + + - + ]: 4293 : return (_g_spawn_invalid_source_fd (pipefd->fds[G_UNIX_PIPE_END_READ], source_fds, n_fds, error) ||
1885 : 2146 : _g_spawn_invalid_source_fd (pipefd->fds[G_UNIX_PIPE_END_WRITE], source_fds, n_fds, error));
1886 : : }
1887 : :
1888 : : static gboolean
1889 : 973 : fork_exec (gboolean intermediate_child,
1890 : : const gchar *working_directory,
1891 : : const gchar * const *argv,
1892 : : const gchar * const *envp,
1893 : : gboolean close_descriptors,
1894 : : gboolean search_path,
1895 : : gboolean search_path_from_envp,
1896 : : gboolean stdout_to_null,
1897 : : gboolean stderr_to_null,
1898 : : gboolean child_inherits_stdin,
1899 : : gboolean file_and_argv_zero,
1900 : : gboolean cloexec_pipes,
1901 : : GSpawnChildSetupFunc child_setup,
1902 : : gpointer user_data,
1903 : : GPid *child_pid,
1904 : : gint *stdin_pipe_out,
1905 : : gint *stdout_pipe_out,
1906 : : gint *stderr_pipe_out,
1907 : : gint stdin_fd,
1908 : : gint stdout_fd,
1909 : : gint stderr_fd,
1910 : : const gint *source_fds,
1911 : : const gint *target_fds,
1912 : : gsize n_fds,
1913 : : GError **error)
1914 : : {
1915 : 973 : GPid pid = -1;
1916 : 973 : GUnixPipe child_err_report_pipe = G_UNIX_PIPE_INIT;
1917 : 973 : GUnixPipe child_pid_report_pipe = G_UNIX_PIPE_INIT;
1918 [ + + ]: 973 : guint pipe_flags = cloexec_pipes ? O_CLOEXEC : 0;
1919 : : gint status;
1920 : : const gchar *chosen_search_path;
1921 : 973 : gchar *search_path_buffer = NULL;
1922 : 973 : gchar *search_path_buffer_heap = NULL;
1923 : 973 : gsize search_path_buffer_len = 0;
1924 : 973 : gchar **argv_buffer = NULL;
1925 : 973 : gchar **argv_buffer_heap = NULL;
1926 : 973 : gsize argv_buffer_len = 0;
1927 : 973 : GUnixPipe stdin_pipe = G_UNIX_PIPE_INIT;
1928 : 973 : GUnixPipe stdout_pipe = G_UNIX_PIPE_INIT;
1929 : 973 : GUnixPipe stderr_pipe = G_UNIX_PIPE_INIT;
1930 : 973 : gint child_close_fds[4] = { -1, -1, -1, -1 };
1931 : 973 : gint n_child_close_fds = 0;
1932 : 973 : gint *source_fds_copy = NULL;
1933 : :
1934 : 973 : g_assert (argv != NULL && argv[0] != NULL);
1935 : 973 : g_assert (stdin_pipe_out == NULL || stdin_fd < 0);
1936 : 973 : g_assert (stdout_pipe_out == NULL || stdout_fd < 0);
1937 : 973 : g_assert (stderr_pipe_out == NULL || stderr_fd < 0);
1938 : :
1939 : : /* If pipes have been requested, open them */
1940 [ + + ]: 973 : if (stdin_pipe_out != NULL)
1941 : : {
1942 [ - + ]: 59 : if (!g_unix_pipe_open (&stdin_pipe, pipe_flags, error))
1943 : 0 : goto cleanup_and_fail;
1944 [ - + ]: 59 : if (source_fds_collide_with_pipe (&stdin_pipe, source_fds, n_fds, error))
1945 : 0 : goto cleanup_and_fail;
1946 : 59 : child_close_fds[n_child_close_fds++] = g_unix_pipe_get (&stdin_pipe, G_UNIX_PIPE_END_WRITE);
1947 : 59 : stdin_fd = g_unix_pipe_get (&stdin_pipe, G_UNIX_PIPE_END_READ);
1948 : : }
1949 : :
1950 [ + + ]: 973 : if (stdout_pipe_out != NULL)
1951 : : {
1952 [ - + ]: 639 : if (!g_unix_pipe_open (&stdout_pipe, pipe_flags, error))
1953 : 0 : goto cleanup_and_fail;
1954 [ - + ]: 639 : if (source_fds_collide_with_pipe (&stdout_pipe, source_fds, n_fds, error))
1955 : 0 : goto cleanup_and_fail;
1956 : 639 : child_close_fds[n_child_close_fds++] = g_unix_pipe_get (&stdout_pipe, G_UNIX_PIPE_END_READ);
1957 : 639 : stdout_fd = g_unix_pipe_get (&stdout_pipe, G_UNIX_PIPE_END_WRITE);
1958 : : }
1959 : :
1960 [ + + ]: 973 : if (stderr_pipe_out != NULL)
1961 : : {
1962 [ - + ]: 435 : if (!g_unix_pipe_open (&stderr_pipe, pipe_flags, error))
1963 : 0 : goto cleanup_and_fail;
1964 [ - + ]: 435 : if (source_fds_collide_with_pipe (&stderr_pipe, source_fds, n_fds, error))
1965 : 0 : goto cleanup_and_fail;
1966 : 435 : child_close_fds[n_child_close_fds++] = g_unix_pipe_get (&stderr_pipe, G_UNIX_PIPE_END_READ);
1967 : 435 : stderr_fd = g_unix_pipe_get (&stderr_pipe, G_UNIX_PIPE_END_WRITE);
1968 : : }
1969 : :
1970 : 973 : child_close_fds[n_child_close_fds++] = -1;
1971 : :
1972 : : #ifdef POSIX_SPAWN_AVAILABLE
1973 [ + + + + : 973 : if (!intermediate_child && working_directory == NULL && !close_descriptors &&
+ + + - ]
1974 [ + - ]: 67 : !search_path_from_envp && child_setup == NULL)
1975 : : {
1976 : : g_trace_mark (G_TRACE_CURRENT_TIME, 0,
1977 : : "GLib", "posix_spawn",
1978 : : "%s", argv[0]);
1979 : :
1980 : 67 : status = do_posix_spawn (argv,
1981 : : envp,
1982 : : search_path,
1983 : : stdout_to_null,
1984 : : stderr_to_null,
1985 : : child_inherits_stdin,
1986 : : file_and_argv_zero,
1987 : : child_pid,
1988 : : child_close_fds,
1989 : : stdin_fd,
1990 : : stdout_fd,
1991 : : stderr_fd,
1992 : : source_fds,
1993 : : target_fds,
1994 : : n_fds);
1995 [ + - ]: 67 : if (status == 0)
1996 : 67 : goto success;
1997 : :
1998 [ # # ]: 0 : if (status != ENOEXEC)
1999 : : {
2000 : 0 : g_set_error (error,
2001 : : G_SPAWN_ERROR,
2002 : : G_SPAWN_ERROR_FAILED,
2003 : : _("Failed to spawn child process “%s” (%s)"),
2004 : : argv[0],
2005 : : g_strerror (status));
2006 : 0 : goto cleanup_and_fail;
2007 : : }
2008 : :
2009 : : /* posix_spawn is not intended to support script execution. It does in
2010 : : * some situations on some glibc versions, but that will be fixed.
2011 : : * So if it fails with ENOEXEC, we fall through to the regular
2012 : : * gspawn codepath so that script execution can be attempted,
2013 : : * per standard gspawn behaviour. */
2014 : 0 : g_debug ("posix_spawn failed (ENOEXEC), fall back to regular gspawn");
2015 : : }
2016 : : else
2017 : : {
2018 : : g_trace_mark (G_TRACE_CURRENT_TIME, 0,
2019 : : "GLib", "fork",
2020 : : "posix_spawn avoided %s%s%s%s%s",
2021 : : !intermediate_child ? "" : "(automatic reaping requested) ",
2022 : : working_directory == NULL ? "" : "(workdir specified) ",
2023 : : !close_descriptors ? "" : "(fd close requested) ",
2024 : : !search_path_from_envp ? "" : "(using envp for search path) ",
2025 : : child_setup == NULL ? "" : "(child_setup specified) ");
2026 : : }
2027 : : #endif /* POSIX_SPAWN_AVAILABLE */
2028 : :
2029 : : /* Choose a search path. This has to be done before calling fork()
2030 : : * as getenv() isn’t async-signal-safe (see `man 7 signal-safety`). */
2031 : 906 : chosen_search_path = NULL;
2032 [ + + ]: 906 : if (search_path_from_envp)
2033 : 36 : chosen_search_path = g_environ_getenv ((gchar **) envp, "PATH");
2034 [ + + + + ]: 906 : if (search_path && chosen_search_path == NULL)
2035 : 233 : chosen_search_path = g_getenv ("PATH");
2036 : :
2037 [ + + + + : 906 : if ((search_path || search_path_from_envp) && chosen_search_path == NULL)
+ + ]
2038 : : {
2039 : : /* There is no 'PATH' in the environment. The default
2040 : : * * search path in libc is the current directory followed by
2041 : : * * the path 'confstr' returns for '_CS_PATH'.
2042 : : * */
2043 : :
2044 : : /* In GLib we put . last, for security, and don't use the
2045 : : * * unportable confstr(); UNIX98 does not actually specify
2046 : : * * what to search if PATH is unset. POSIX may, dunno.
2047 : : * */
2048 : :
2049 : 2 : chosen_search_path = "/bin:/usr/bin:.";
2050 : : }
2051 : :
2052 [ + + + + ]: 906 : if (search_path || search_path_from_envp)
2053 : 269 : g_assert (chosen_search_path != NULL);
2054 : : else
2055 : 637 : g_assert (chosen_search_path == NULL);
2056 : :
2057 : : /* Allocate a buffer which the fork()ed child can use to assemble potential
2058 : : * paths for the binary to exec(), combining the argv[0] and elements from
2059 : : * the chosen_search_path. This can’t be done in the child because malloc()
2060 : : * (or alloca()) are not async-signal-safe (see `man 7 signal-safety`).
2061 : : *
2062 : : * Add 2 for the nul terminator and a leading `/`. */
2063 [ + + ]: 906 : if (chosen_search_path != NULL)
2064 : : {
2065 : 269 : search_path_buffer_len = strlen (chosen_search_path) + strlen (argv[0]) + 2;
2066 [ + + ]: 269 : if (search_path_buffer_len < 4000)
2067 : : {
2068 : : /* Prefer small stack allocations to avoid valgrind leak warnings
2069 : : * in forked child. The 4000B cutoff is arbitrary. */
2070 : 268 : search_path_buffer = g_alloca (search_path_buffer_len);
2071 : : }
2072 : : else
2073 : : {
2074 : 1 : search_path_buffer_heap = g_malloc (search_path_buffer_len);
2075 : 1 : search_path_buffer = search_path_buffer_heap;
2076 : : }
2077 : : }
2078 : :
2079 [ + + + + ]: 906 : if (search_path || search_path_from_envp)
2080 : 269 : g_assert (search_path_buffer != NULL);
2081 : : else
2082 : 637 : g_assert (search_path_buffer == NULL);
2083 : :
2084 : : /* And allocate a buffer which is 2 elements longer than @argv, so that if
2085 : : * script_execute() has to be called later on, it can build a wrapper argv
2086 : : * array in this buffer. */
2087 : 906 : argv_buffer_len = g_strv_length ((gchar **) argv) + 2;
2088 [ + + ]: 906 : if (argv_buffer_len < 4000 / sizeof (gchar *))
2089 : : {
2090 : : /* Prefer small stack allocations to avoid valgrind leak warnings
2091 : : * in forked child. The 4000B cutoff is arbitrary. */
2092 : 904 : argv_buffer = g_newa (gchar *, argv_buffer_len);
2093 : : }
2094 : : else
2095 : : {
2096 : 2 : argv_buffer_heap = g_new (gchar *, argv_buffer_len);
2097 : 2 : argv_buffer = argv_buffer_heap;
2098 : : }
2099 : :
2100 : : /* And one to hold a copy of @source_fds for later manipulation in do_exec(). */
2101 : 906 : source_fds_copy = g_new (int, n_fds);
2102 [ + + ]: 906 : if (n_fds > 0)
2103 : 7 : memcpy (source_fds_copy, source_fds, sizeof (*source_fds) * n_fds);
2104 : :
2105 [ - + ]: 906 : if (!g_unix_pipe_open (&child_err_report_pipe, pipe_flags, error))
2106 : 0 : goto cleanup_and_fail;
2107 [ + + ]: 906 : if (source_fds_collide_with_pipe (&child_err_report_pipe, source_fds, n_fds, error))
2108 : 1 : goto cleanup_and_fail;
2109 : :
2110 [ + + ]: 905 : if (intermediate_child)
2111 : : {
2112 [ - + ]: 108 : if (!g_unix_pipe_open (&child_pid_report_pipe, pipe_flags, error))
2113 : 0 : goto cleanup_and_fail;
2114 [ - + ]: 108 : if (source_fds_collide_with_pipe (&child_pid_report_pipe, source_fds, n_fds, error))
2115 : 0 : goto cleanup_and_fail;
2116 : : }
2117 : :
2118 : 905 : pid = fork ();
2119 : :
2120 [ - + ]: 1702 : if (pid < 0)
2121 : : {
2122 : 0 : int errsv = errno;
2123 : :
2124 : 0 : g_set_error (error,
2125 : : G_SPAWN_ERROR,
2126 : : G_SPAWN_ERROR_FORK,
2127 : : _("Failed to fork (%s)"),
2128 : : g_strerror (errsv));
2129 : :
2130 : 0 : goto cleanup_and_fail;
2131 : : }
2132 [ + + ]: 1702 : else if (pid == 0)
2133 : : {
2134 : : /* Immediate child. This may or may not be the child that
2135 : : * actually execs the new process.
2136 : : */
2137 : :
2138 : : /* Reset some signal handlers that we may use */
2139 : 797 : signal (SIGCHLD, SIG_DFL);
2140 : 797 : signal (SIGINT, SIG_DFL);
2141 : 797 : signal (SIGTERM, SIG_DFL);
2142 : 797 : signal (SIGHUP, SIG_DFL);
2143 : :
2144 : : /* Be sure we crash if the parent exits
2145 : : * and we write to the err_report_pipe
2146 : : */
2147 : 797 : signal (SIGPIPE, SIG_DFL);
2148 : :
2149 : : /* Close the parent's end of the pipes;
2150 : : * not needed in the close_descriptors case,
2151 : : * though
2152 : : */
2153 : 797 : g_unix_pipe_close (&child_err_report_pipe, G_UNIX_PIPE_END_READ, NULL);
2154 : 797 : g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_READ, NULL);
2155 [ + + ]: 797 : if (child_close_fds[0] != -1)
2156 : : {
2157 : 674 : int i = -1;
2158 [ + + ]: 1806 : while (child_close_fds[++i] != -1)
2159 : 1132 : g_clear_fd (&child_close_fds[i], NULL);
2160 : : }
2161 : :
2162 [ - + ]: 797 : if (intermediate_child)
2163 : : {
2164 : : /* We need to fork an intermediate child that launches the
2165 : : * final child. The purpose of the intermediate child
2166 : : * is to exit, so we can waitpid() it immediately.
2167 : : * Then the grandchild will not become a zombie.
2168 : : */
2169 : : GPid grandchild_pid;
2170 : :
2171 : 0 : grandchild_pid = fork ();
2172 : :
2173 [ - + ]: 107 : if (grandchild_pid < 0)
2174 : : {
2175 : : /* report -1 as child PID */
2176 : 0 : write_all (g_unix_pipe_get (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE),
2177 : : &grandchild_pid, sizeof(grandchild_pid));
2178 : :
2179 : 0 : write_err_and_exit (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE),
2180 : : CHILD_FORK_FAILED);
2181 : : }
2182 [ + - ]: 107 : else if (grandchild_pid == 0)
2183 : : {
2184 : 107 : g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
2185 : 107 : do_exec (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE),
2186 : : stdin_fd,
2187 : : stdout_fd,
2188 : : stderr_fd,
2189 : : source_fds_copy,
2190 : : target_fds,
2191 : : n_fds,
2192 : : working_directory,
2193 : : argv,
2194 : : argv_buffer,
2195 : : argv_buffer_len,
2196 : : envp,
2197 : : close_descriptors,
2198 : : chosen_search_path,
2199 : : search_path_buffer,
2200 : : search_path_buffer_len,
2201 : : stdout_to_null,
2202 : : stderr_to_null,
2203 : : child_inherits_stdin,
2204 : : file_and_argv_zero,
2205 : : child_setup,
2206 : : user_data);
2207 : : }
2208 : : else
2209 : : {
2210 : 0 : write_all (g_unix_pipe_get (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE),
2211 : : &grandchild_pid, sizeof(grandchild_pid));
2212 : 0 : g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
2213 : :
2214 : 0 : _exit (0);
2215 : : }
2216 : : }
2217 : : else
2218 : : {
2219 : : /* Just run the child.
2220 : : */
2221 : :
2222 : 797 : do_exec (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE),
2223 : : stdin_fd,
2224 : : stdout_fd,
2225 : : stderr_fd,
2226 : : source_fds_copy,
2227 : : target_fds,
2228 : : n_fds,
2229 : : working_directory,
2230 : : argv,
2231 : : argv_buffer,
2232 : : argv_buffer_len,
2233 : : envp,
2234 : : close_descriptors,
2235 : : chosen_search_path,
2236 : : search_path_buffer,
2237 : : search_path_buffer_len,
2238 : : stdout_to_null,
2239 : : stderr_to_null,
2240 : : child_inherits_stdin,
2241 : : file_and_argv_zero,
2242 : : child_setup,
2243 : : user_data);
2244 : : }
2245 : : }
2246 : : else
2247 : : {
2248 : : /* Parent */
2249 : :
2250 : : gint buf[2];
2251 : 905 : gint n_ints = 0;
2252 : :
2253 : : /* Close the uncared-about ends of the pipes */
2254 : 905 : g_unix_pipe_close (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
2255 : 905 : g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
2256 : :
2257 : : /* If we had an intermediate child, reap it */
2258 [ + + ]: 905 : if (intermediate_child)
2259 : : {
2260 : 108 : wait_again:
2261 [ - + ]: 108 : if (waitpid (pid, &status, 0) < 0)
2262 : : {
2263 [ # # ]: 0 : if (errno == EINTR)
2264 : 0 : goto wait_again;
2265 [ # # ]: 0 : else if (errno == ECHILD)
2266 : : ; /* do nothing, child already reaped */
2267 : : else
2268 : 0 : g_warning ("waitpid() should not fail in 'fork_exec'");
2269 : : }
2270 : : }
2271 : :
2272 : :
2273 [ - + ]: 905 : if (!read_ints (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_READ),
2274 : : buf, 2, &n_ints,
2275 : : error))
2276 : 9 : goto cleanup_and_fail;
2277 : :
2278 [ + + ]: 905 : if (n_ints >= 2)
2279 : : {
2280 : : /* Error from the child. */
2281 : :
2282 [ - + - + : 9 : switch (buf[0])
- - - ]
2283 : : {
2284 : 0 : case CHILD_CHDIR_FAILED:
2285 : 0 : g_set_error (error,
2286 : : G_SPAWN_ERROR,
2287 : : G_SPAWN_ERROR_CHDIR,
2288 : : _("Failed to change to directory “%s” (%s)"),
2289 : : working_directory,
2290 : : g_strerror (buf[1]));
2291 : :
2292 : 0 : break;
2293 : :
2294 : 8 : case CHILD_EXEC_FAILED:
2295 : 8 : g_set_error (error,
2296 : : G_SPAWN_ERROR,
2297 : : _g_spawn_exec_err_to_g_error (buf[1]),
2298 : : _("Failed to execute child process “%s” (%s)"),
2299 : : argv[0],
2300 : : g_strerror (buf[1]));
2301 : :
2302 : 8 : break;
2303 : :
2304 : 0 : case CHILD_OPEN_FAILED:
2305 : 0 : g_set_error (error,
2306 : : G_SPAWN_ERROR,
2307 : : G_SPAWN_ERROR_FAILED,
2308 : : _("Failed to open file to remap file descriptor (%s)"),
2309 : : g_strerror (buf[1]));
2310 : 0 : break;
2311 : :
2312 : 1 : case CHILD_DUPFD_FAILED:
2313 : 1 : g_set_error (error,
2314 : : G_SPAWN_ERROR,
2315 : : G_SPAWN_ERROR_FAILED,
2316 : : _("Failed to duplicate file descriptor for child process (%s)"),
2317 : : g_strerror (buf[1]));
2318 : :
2319 : 1 : break;
2320 : :
2321 : 0 : case CHILD_FORK_FAILED:
2322 : 0 : g_set_error (error,
2323 : : G_SPAWN_ERROR,
2324 : : G_SPAWN_ERROR_FORK,
2325 : : _("Failed to fork child process (%s)"),
2326 : : g_strerror (buf[1]));
2327 : 0 : break;
2328 : :
2329 : 0 : case CHILD_CLOSE_FAILED:
2330 : 0 : g_set_error (error,
2331 : : G_SPAWN_ERROR,
2332 : : G_SPAWN_ERROR_FAILED,
2333 : : _("Failed to close file descriptor for child process (%s)"),
2334 : : g_strerror (buf[1]));
2335 : 0 : break;
2336 : :
2337 : 0 : default:
2338 : 0 : g_set_error (error,
2339 : : G_SPAWN_ERROR,
2340 : : G_SPAWN_ERROR_FAILED,
2341 : : _("Unknown error executing child process “%s”"),
2342 : : argv[0]);
2343 : 0 : break;
2344 : : }
2345 : :
2346 : 9 : goto cleanup_and_fail;
2347 : : }
2348 : :
2349 : : /* Get child pid from intermediate child pipe. */
2350 [ + + ]: 896 : if (intermediate_child)
2351 : : {
2352 : 105 : n_ints = 0;
2353 : :
2354 [ - + ]: 105 : if (!read_ints (g_unix_pipe_get (&child_pid_report_pipe, G_UNIX_PIPE_END_READ),
2355 : : buf, 1, &n_ints, error))
2356 : 0 : goto cleanup_and_fail;
2357 : :
2358 [ - + ]: 105 : if (n_ints < 1)
2359 : : {
2360 : 0 : int errsv = errno;
2361 : :
2362 : 0 : g_set_error (error,
2363 : : G_SPAWN_ERROR,
2364 : : G_SPAWN_ERROR_FAILED,
2365 : : _("Failed to read enough data from child pid pipe (%s)"),
2366 : : g_strerror (errsv));
2367 : 0 : goto cleanup_and_fail;
2368 : : }
2369 : : else
2370 : : {
2371 : : /* we have the child pid */
2372 : 105 : pid = buf[0];
2373 : : }
2374 : : }
2375 : :
2376 : : /* Success against all odds! return the information */
2377 : 896 : g_unix_pipe_close (&child_err_report_pipe, G_UNIX_PIPE_END_READ, NULL);
2378 : 896 : g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_READ, NULL);
2379 : :
2380 : 896 : g_free (search_path_buffer_heap);
2381 : 896 : g_free (argv_buffer_heap);
2382 : 896 : g_free (source_fds_copy);
2383 : :
2384 [ + + ]: 896 : if (child_pid)
2385 : 885 : *child_pid = pid;
2386 : :
2387 : 896 : goto success;
2388 : : }
2389 : :
2390 : 963 : success:
2391 : : /* Close the uncared-about ends of the pipes */
2392 : 963 : g_unix_pipe_close (&stdin_pipe, G_UNIX_PIPE_END_READ, NULL);
2393 : 963 : g_unix_pipe_close (&stdout_pipe, G_UNIX_PIPE_END_WRITE, NULL);
2394 : 963 : g_unix_pipe_close (&stderr_pipe, G_UNIX_PIPE_END_WRITE, NULL);
2395 : :
2396 [ + + ]: 963 : if (stdin_pipe_out != NULL)
2397 : 59 : *stdin_pipe_out = g_unix_pipe_steal (&stdin_pipe, G_UNIX_PIPE_END_WRITE);
2398 : :
2399 [ + + ]: 963 : if (stdout_pipe_out != NULL)
2400 : 638 : *stdout_pipe_out = g_unix_pipe_steal (&stdout_pipe, G_UNIX_PIPE_END_READ);
2401 : :
2402 [ + + ]: 963 : if (stderr_pipe_out != NULL)
2403 : 435 : *stderr_pipe_out = g_unix_pipe_steal (&stderr_pipe, G_UNIX_PIPE_END_READ);
2404 : :
2405 : 963 : return TRUE;
2406 : :
2407 : 10 : cleanup_and_fail:
2408 : :
2409 : : /* There was an error from the Child, reap the child to avoid it being
2410 : : a zombie.
2411 : : */
2412 : :
2413 [ + + ]: 10 : if (pid > 0)
2414 : : {
2415 : 9 : wait_failed:
2416 [ + + ]: 9 : if (waitpid (pid, NULL, 0) < 0)
2417 : : {
2418 [ - + ]: 3 : if (errno == EINTR)
2419 : 0 : goto wait_failed;
2420 [ - + ]: 3 : else if (errno == ECHILD)
2421 : : ; /* do nothing, child already reaped */
2422 : : else
2423 : 0 : g_warning ("waitpid() should not fail in 'fork_exec'");
2424 : : }
2425 : : }
2426 : :
2427 : 10 : g_unix_pipe_clear (&stdin_pipe);
2428 : 10 : g_unix_pipe_clear (&stdout_pipe);
2429 : 10 : g_unix_pipe_clear (&stderr_pipe);
2430 : 10 : g_unix_pipe_clear (&child_err_report_pipe);
2431 : 10 : g_unix_pipe_clear (&child_pid_report_pipe);
2432 : :
2433 : 10 : g_clear_pointer (&search_path_buffer_heap, g_free);
2434 : 10 : g_clear_pointer (&argv_buffer_heap, g_free);
2435 : 10 : g_clear_pointer (&source_fds_copy, g_free);
2436 : :
2437 : 10 : return FALSE;
2438 : : }
2439 : :
2440 : : /* Based on execvp from GNU C Library */
2441 : :
2442 : : /* This function is called between fork() and exec() and hence must be
2443 : : * async-signal-safe (see signal-safety(7)) until it calls exec(). */
2444 : : static gboolean
2445 : 0 : script_execute (const gchar *file,
2446 : : gchar **argv,
2447 : : gchar **argv_buffer,
2448 : : gsize argv_buffer_len,
2449 : : gchar **envp)
2450 : : {
2451 : : /* Count the arguments. */
2452 : 0 : gsize argc = 0;
2453 [ # # ]: 0 : while (argv[argc])
2454 : 0 : ++argc;
2455 : :
2456 : : /* Construct an argument list for the shell. */
2457 [ # # ]: 0 : if (argc + 2 > argv_buffer_len)
2458 : 0 : return FALSE;
2459 : :
2460 : 0 : argv_buffer[0] = (char *) "/bin/sh";
2461 : 0 : argv_buffer[1] = (char *) file;
2462 [ # # ]: 0 : while (argc > 0)
2463 : : {
2464 : 0 : argv_buffer[argc + 1] = argv[argc];
2465 : 0 : --argc;
2466 : : }
2467 : :
2468 : : /* Execute the shell. */
2469 [ # # ]: 0 : if (envp)
2470 : 0 : execve (argv_buffer[0], argv_buffer, envp);
2471 : : else
2472 : 0 : execv (argv_buffer[0], argv_buffer);
2473 : :
2474 : 0 : return TRUE;
2475 : : }
2476 : :
2477 : : /* This function is called between fork() and exec() and hence must be
2478 : : * async-signal-safe (see signal-safety(7)). */
2479 : : static gchar*
2480 : 167 : my_strchrnul (const gchar *str, gchar c)
2481 : : {
2482 : 167 : gchar *p = (gchar*) str;
2483 [ + + + + ]: 5706 : while (*p && (*p != c))
2484 : 5539 : ++p;
2485 : :
2486 : 167 : return p;
2487 : : }
2488 : :
2489 : : /* This function is called between fork() and exec() and hence must be
2490 : : * async-signal-safe (see signal-safety(7)) until it calls exec(). */
2491 : : static gint
2492 : 904 : g_execute (const gchar *file,
2493 : : gchar **argv,
2494 : : gchar **argv_buffer,
2495 : : gsize argv_buffer_len,
2496 : : gchar **envp,
2497 : : const gchar *search_path,
2498 : : gchar *search_path_buffer,
2499 : : gsize search_path_buffer_len)
2500 : : {
2501 [ + - - + ]: 904 : if (file == NULL || *file == '\0')
2502 : : {
2503 : : /* We check the simple case first. */
2504 : 0 : errno = ENOENT;
2505 : 0 : return -1;
2506 : : }
2507 : :
2508 [ + + + + ]: 904 : if (search_path == NULL || strchr (file, '/') != NULL)
2509 : : {
2510 : : /* Don't search when it contains a slash. */
2511 [ + + ]: 823 : if (envp)
2512 : 228 : execve (file, argv, envp);
2513 : : else
2514 : 595 : execv (file, argv);
2515 : :
2516 [ - + - - ]: 823 : if (errno == ENOEXEC &&
2517 : 0 : !script_execute (file, argv, argv_buffer, argv_buffer_len, envp))
2518 : : {
2519 : 0 : errno = ENOMEM;
2520 : 0 : return -1;
2521 : : }
2522 : : }
2523 : : else
2524 : : {
2525 : 81 : gboolean got_eacces = 0;
2526 : : const gchar *path, *p;
2527 : : gchar *name;
2528 : : gsize len;
2529 : : gsize pathlen;
2530 : :
2531 : 81 : path = search_path;
2532 : 81 : len = strlen (file) + 1;
2533 : 81 : pathlen = strlen (path);
2534 : 81 : name = search_path_buffer;
2535 : :
2536 [ - + ]: 81 : if (search_path_buffer_len < pathlen + len + 1)
2537 : : {
2538 : 0 : errno = ENOMEM;
2539 : 0 : return -1;
2540 : : }
2541 : :
2542 : : /* Copy the file name at the top, including '\0' */
2543 : 81 : memcpy (name + pathlen + 1, file, len);
2544 : 81 : name = name + pathlen;
2545 : : /* And add the slash before the filename */
2546 : 81 : *name = '/';
2547 : :
2548 : 81 : p = path;
2549 : : do
2550 : : {
2551 : : char *startp;
2552 : :
2553 : 248 : path = p;
2554 : 248 : p = my_strchrnul (path, ':');
2555 : :
2556 [ - + ]: 167 : if (p == path)
2557 : : /* Two adjacent colons, or a colon at the beginning or the end
2558 : : * of 'PATH' means to search the current directory.
2559 : : */
2560 : 0 : startp = name + 1;
2561 : : else
2562 : 167 : startp = memcpy (name - (p - path), path, p - path);
2563 : :
2564 : : /* Try to execute this name. If it works, execv will not return. */
2565 [ + + ]: 167 : if (envp)
2566 : 15 : execve (startp, argv, envp);
2567 : : else
2568 : 152 : execv (startp, argv);
2569 : :
2570 [ - + - - ]: 167 : if (errno == ENOEXEC &&
2571 : 0 : !script_execute (startp, argv, argv_buffer, argv_buffer_len, envp))
2572 : : {
2573 : 0 : errno = ENOMEM;
2574 : 0 : return -1;
2575 : : }
2576 : :
2577 [ - + - - ]: 167 : switch (errno)
2578 : : {
2579 : 0 : case EACCES:
2580 : : /* Record the we got a 'Permission denied' error. If we end
2581 : : * up finding no executable we can use, we want to diagnose
2582 : : * that we did find one but were denied access.
2583 : : */
2584 : 0 : got_eacces = TRUE;
2585 : :
2586 : : G_GNUC_FALLTHROUGH;
2587 : 167 : case ENOENT:
2588 : : #ifdef ESTALE
2589 : : case ESTALE:
2590 : : #endif
2591 : : #ifdef ENOTDIR
2592 : : case ENOTDIR:
2593 : : #endif
2594 : : /* Those errors indicate the file is missing or not executable
2595 : : * by us, in which case we want to just try the next path
2596 : : * directory.
2597 : : */
2598 : 167 : break;
2599 : :
2600 : 0 : case ENODEV:
2601 : : case ETIMEDOUT:
2602 : : /* Some strange filesystems like AFS return even
2603 : : * stranger error numbers. They cannot reasonably mean anything
2604 : : * else so ignore those, too.
2605 : : */
2606 : 0 : break;
2607 : :
2608 : 0 : default:
2609 : : /* Some other error means we found an executable file, but
2610 : : * something went wrong executing it; return the error to our
2611 : : * caller.
2612 : : */
2613 : 0 : return -1;
2614 : : }
2615 : : }
2616 [ + - ]: 167 : while (*p++ != '\0');
2617 : :
2618 : : /* We tried every element and none of them worked. */
2619 [ # # ]: 0 : if (got_eacces)
2620 : : /* At least one failure was due to permissions, so report that
2621 : : * error.
2622 : : */
2623 : 0 : errno = EACCES;
2624 : : }
2625 : :
2626 : : /* Return the error from the last attempt (probably ENOENT). */
2627 : 823 : return -1;
2628 : : }
2629 : :
2630 : : /**
2631 : : * g_spawn_close_pid:
2632 : : * @pid: The process reference to close
2633 : : *
2634 : : * On some platforms, notably Windows, the #GPid type represents a resource
2635 : : * which must be closed to prevent resource leaking. g_spawn_close_pid()
2636 : : * is provided for this purpose. It should be used on all platforms, even
2637 : : * though it doesn't do anything under UNIX.
2638 : : **/
2639 : : void
2640 : 162 : g_spawn_close_pid (GPid pid)
2641 : : {
2642 : 162 : }
|