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 : : #elif defined(__FreeBSD__)
104 : : /* FreeBSD has environ in crt rather than libc. Using "extern char** environ"
105 : : * in the code of a shared library makes it fail to link with -Wl,--no-undefined
106 : : * See https://reviews.freebsd.org/D30842#840642
107 : : */
108 : : #include <dlfcn.h>
109 : : #define environ (*((char***)dlsym(RTLD_DEFAULT, "environ")))
110 : : #else
111 : : extern char **environ;
112 : : #endif
113 : :
114 : : #ifndef O_CLOEXEC
115 : : #define O_CLOEXEC 0
116 : : #else
117 : : #define HAVE_O_CLOEXEC 1
118 : : #endif
119 : :
120 : : static gint g_execute (const gchar *file,
121 : : gchar **argv,
122 : : gchar **argv_buffer,
123 : : gsize argv_buffer_len,
124 : : gchar **envp,
125 : : const gchar *search_path,
126 : : gchar *search_path_buffer,
127 : : gsize search_path_buffer_len);
128 : :
129 : : static gboolean fork_exec (gboolean intermediate_child,
130 : : const gchar *working_directory,
131 : : const gchar * const *argv,
132 : : const gchar * const *envp,
133 : : gboolean close_descriptors,
134 : : gboolean search_path,
135 : : gboolean search_path_from_envp,
136 : : gboolean stdout_to_null,
137 : : gboolean stderr_to_null,
138 : : gboolean child_inherits_stdin,
139 : : gboolean file_and_argv_zero,
140 : : gboolean cloexec_pipes,
141 : : GSpawnChildSetupFunc child_setup,
142 : : gpointer user_data,
143 : : GPid *child_pid,
144 : : gint *stdin_pipe_out,
145 : : gint *stdout_pipe_out,
146 : : gint *stderr_pipe_out,
147 : : gint stdin_fd,
148 : : gint stdout_fd,
149 : : gint stderr_fd,
150 : : const gint *source_fds,
151 : : const gint *target_fds,
152 : : gsize n_fds,
153 : : GError **error);
154 : :
155 : 35 : G_DEFINE_QUARK (g-exec-error-quark, g_spawn_error)
156 : 64 : G_DEFINE_QUARK (g-spawn-exit-error-quark, g_spawn_exit_error)
157 : :
158 : : /* Some versions of OS X define READ_OK in public headers */
159 : : #undef READ_OK
160 : :
161 : : typedef enum
162 : : {
163 : : READ_FAILED = 0, /* FALSE */
164 : : READ_OK,
165 : : READ_EOF
166 : : } ReadResult;
167 : :
168 : : static ReadResult
169 : 706 : read_data (GString *str,
170 : : gint fd,
171 : : GError **error)
172 : : {
173 : : gssize bytes;
174 : : gchar buf[4096];
175 : :
176 : 706 : again:
177 : 706 : bytes = read (fd, buf, 4096);
178 : :
179 : 706 : if (bytes == 0)
180 : 318 : return READ_EOF;
181 : 388 : else if (bytes > 0)
182 : : {
183 : : g_string_append_len (str, buf, bytes);
184 : 388 : return READ_OK;
185 : : }
186 : 0 : else if (errno == EINTR)
187 : 0 : goto again;
188 : : else
189 : : {
190 : 0 : int errsv = errno;
191 : :
192 : 0 : g_set_error (error,
193 : : G_SPAWN_ERROR,
194 : : G_SPAWN_ERROR_READ,
195 : : _("Failed to read data from child process (%s)"),
196 : : g_strerror (errsv));
197 : :
198 : 0 : return READ_FAILED;
199 : : }
200 : : }
201 : :
202 : : gboolean
203 : 322 : g_spawn_sync_impl (const gchar *working_directory,
204 : : gchar **argv,
205 : : gchar **envp,
206 : : GSpawnFlags flags,
207 : : GSpawnChildSetupFunc child_setup,
208 : : gpointer user_data,
209 : : gchar **standard_output,
210 : : gchar **standard_error,
211 : : gint *wait_status,
212 : : GError **error)
213 : : {
214 : 322 : gint outpipe = -1;
215 : 322 : gint errpipe = -1;
216 : : GPid pid;
217 : : gint ret;
218 : 322 : GString *outstr = NULL;
219 : 322 : GString *errstr = NULL;
220 : : gboolean failed;
221 : : gint status;
222 : :
223 : 322 : g_return_val_if_fail (argv != NULL, FALSE);
224 : 322 : g_return_val_if_fail (argv[0] != NULL, FALSE);
225 : 322 : g_return_val_if_fail (!(flags & G_SPAWN_DO_NOT_REAP_CHILD), FALSE);
226 : 322 : g_return_val_if_fail (standard_output == NULL ||
227 : : !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
228 : 322 : g_return_val_if_fail (standard_error == NULL ||
229 : : !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
230 : :
231 : : /* Just to ensure segfaults if callers try to use
232 : : * these when an error is reported.
233 : : */
234 : 322 : if (standard_output)
235 : 243 : *standard_output = NULL;
236 : :
237 : 322 : if (standard_error)
238 : 76 : *standard_error = NULL;
239 : :
240 : 644 : if (!fork_exec (FALSE,
241 : : working_directory,
242 : : (const gchar * const *) argv,
243 : : (const gchar * const *) envp,
244 : 322 : !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
245 : 322 : (flags & G_SPAWN_SEARCH_PATH) != 0,
246 : 322 : (flags & G_SPAWN_SEARCH_PATH_FROM_ENVP) != 0,
247 : 322 : (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
248 : 322 : (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
249 : 322 : (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
250 : 322 : (flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0,
251 : 322 : (flags & G_SPAWN_CLOEXEC_PIPES) != 0,
252 : : child_setup,
253 : : user_data,
254 : : &pid,
255 : : NULL,
256 : : standard_output ? &outpipe : NULL,
257 : : standard_error ? &errpipe : NULL,
258 : : -1, -1, -1,
259 : : NULL, NULL, 0,
260 : : error))
261 : 6 : return FALSE;
262 : :
263 : : /* Read data from child. */
264 : :
265 : 316 : failed = FALSE;
266 : :
267 : 316 : if (outpipe >= 0)
268 : : {
269 : 242 : outstr = g_string_new (NULL);
270 : : }
271 : :
272 : 316 : if (errpipe >= 0)
273 : : {
274 : 76 : errstr = g_string_new (NULL);
275 : : }
276 : :
277 : : /* Read data until we get EOF on both pipes. */
278 : 954 : while (!failed &&
279 : 954 : (outpipe >= 0 ||
280 : 334 : errpipe >= 0))
281 : : {
282 : : /* Any negative FD in the array is ignored, so we can use a fixed length.
283 : : * We can use UNIX FDs here without worrying about Windows HANDLEs because
284 : : * the Windows implementation is entirely in gspawn-win32.c. */
285 : 638 : GPollFD fds[] =
286 : : {
287 : : { outpipe, G_IO_IN | G_IO_HUP | G_IO_ERR, 0 },
288 : : { errpipe, G_IO_IN | G_IO_HUP | G_IO_ERR, 0 },
289 : : };
290 : :
291 : 638 : ret = g_poll (fds, G_N_ELEMENTS (fds), -1 /* no timeout */);
292 : :
293 : 638 : if (ret < 0)
294 : : {
295 : 0 : int errsv = errno;
296 : :
297 : 0 : if (errno == EINTR)
298 : 0 : continue;
299 : :
300 : 0 : failed = TRUE;
301 : :
302 : 0 : g_set_error (error,
303 : : G_SPAWN_ERROR,
304 : : G_SPAWN_ERROR_READ,
305 : : _("Unexpected error in reading data from a child process (%s)"),
306 : : g_strerror (errsv));
307 : :
308 : 0 : break;
309 : : }
310 : :
311 : 638 : if (outpipe >= 0 && fds[0].revents != 0)
312 : : {
313 : 606 : switch (read_data (outstr, outpipe, error))
314 : : {
315 : 0 : case READ_FAILED:
316 : 0 : failed = TRUE;
317 : 0 : break;
318 : 242 : case READ_EOF:
319 : 242 : g_clear_fd (&outpipe, NULL);
320 : 242 : break;
321 : 364 : default:
322 : 364 : break;
323 : : }
324 : :
325 : 606 : if (failed)
326 : 0 : break;
327 : : }
328 : :
329 : 638 : if (errpipe >= 0 && fds[1].revents != 0)
330 : : {
331 : 100 : switch (read_data (errstr, errpipe, error))
332 : : {
333 : 0 : case READ_FAILED:
334 : 0 : failed = TRUE;
335 : 0 : break;
336 : 76 : case READ_EOF:
337 : 76 : g_clear_fd (&errpipe, NULL);
338 : 76 : break;
339 : 24 : default:
340 : 24 : break;
341 : : }
342 : :
343 : 100 : if (failed)
344 : 0 : break;
345 : : }
346 : : }
347 : :
348 : : /* These should only be open still if we had an error. */
349 : 316 : g_clear_fd (&outpipe, NULL);
350 : 316 : g_clear_fd (&errpipe, NULL);
351 : :
352 : : /* Wait for child to exit, even if we have
353 : : * an error pending.
354 : : */
355 : 316 : again:
356 : :
357 : 316 : ret = waitpid (pid, &status, 0);
358 : :
359 : 316 : if (ret < 0)
360 : : {
361 : 0 : if (errno == EINTR)
362 : 0 : goto again;
363 : 0 : else if (errno == ECHILD)
364 : : {
365 : 0 : if (wait_status)
366 : : {
367 : 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.");
368 : : }
369 : : else
370 : : {
371 : : /* We don't need the wait status. */
372 : : }
373 : : }
374 : : else
375 : : {
376 : 0 : if (!failed) /* avoid error pileups */
377 : : {
378 : 0 : int errsv = errno;
379 : :
380 : 0 : failed = TRUE;
381 : :
382 : 0 : g_set_error (error,
383 : : G_SPAWN_ERROR,
384 : : G_SPAWN_ERROR_READ,
385 : : _("Unexpected error in waitpid() (%s)"),
386 : : g_strerror (errsv));
387 : : }
388 : : }
389 : : }
390 : :
391 : 316 : if (failed)
392 : : {
393 : 0 : if (outstr)
394 : 0 : g_string_free (outstr, TRUE);
395 : 0 : if (errstr)
396 : 0 : g_string_free (errstr, TRUE);
397 : :
398 : 0 : return FALSE;
399 : : }
400 : : else
401 : : {
402 : 316 : if (wait_status)
403 : 280 : *wait_status = status;
404 : :
405 : 316 : if (standard_output)
406 : 242 : *standard_output = g_string_free (outstr, FALSE);
407 : :
408 : 316 : if (standard_error)
409 : 76 : *standard_error = g_string_free (errstr, FALSE);
410 : :
411 : 316 : return TRUE;
412 : : }
413 : : }
414 : :
415 : : gboolean
416 : 784 : g_spawn_async_with_pipes_and_fds_impl (const gchar *working_directory,
417 : : const gchar * const *argv,
418 : : const gchar * const *envp,
419 : : GSpawnFlags flags,
420 : : GSpawnChildSetupFunc child_setup,
421 : : gpointer user_data,
422 : : gint stdin_fd,
423 : : gint stdout_fd,
424 : : gint stderr_fd,
425 : : const gint *source_fds,
426 : : const gint *target_fds,
427 : : gsize n_fds,
428 : : GPid *child_pid_out,
429 : : gint *stdin_pipe_out,
430 : : gint *stdout_pipe_out,
431 : : gint *stderr_pipe_out,
432 : : GError **error)
433 : : {
434 : 784 : g_return_val_if_fail (argv != NULL, FALSE);
435 : 784 : g_return_val_if_fail (argv[0] != NULL, FALSE);
436 : : /* can’t both inherit and set pipes to /dev/null */
437 : 784 : g_return_val_if_fail ((flags & INHERITS_OR_NULL_STDIN) != INHERITS_OR_NULL_STDIN, FALSE);
438 : 784 : g_return_val_if_fail ((flags & INHERITS_OR_NULL_STDOUT) != INHERITS_OR_NULL_STDOUT, FALSE);
439 : 784 : g_return_val_if_fail ((flags & INHERITS_OR_NULL_STDERR) != INHERITS_OR_NULL_STDERR, FALSE);
440 : : /* can’t use pipes and stdin/stdout/stderr FDs */
441 : 784 : g_return_val_if_fail (stdin_pipe_out == NULL || stdin_fd < 0, FALSE);
442 : 784 : g_return_val_if_fail (stdout_pipe_out == NULL || stdout_fd < 0, FALSE);
443 : 784 : g_return_val_if_fail (stderr_pipe_out == NULL || stderr_fd < 0, FALSE);
444 : :
445 : 784 : if ((flags & INHERITS_OR_NULL_STDIN) != 0)
446 : 4 : stdin_pipe_out = NULL;
447 : 784 : if ((flags & INHERITS_OR_NULL_STDOUT) != 0)
448 : 34 : stdout_pipe_out = NULL;
449 : 784 : if ((flags & INHERITS_OR_NULL_STDERR) != 0)
450 : 25 : stderr_pipe_out = NULL;
451 : :
452 : 784 : return fork_exec (!(flags & G_SPAWN_DO_NOT_REAP_CHILD),
453 : : working_directory,
454 : : (const gchar * const *) argv,
455 : : (const gchar * const *) envp,
456 : 784 : !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
457 : 784 : (flags & G_SPAWN_SEARCH_PATH) != 0,
458 : 784 : (flags & G_SPAWN_SEARCH_PATH_FROM_ENVP) != 0,
459 : 784 : (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
460 : 784 : (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
461 : 784 : (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
462 : 784 : (flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0,
463 : 784 : (flags & G_SPAWN_CLOEXEC_PIPES) != 0,
464 : : child_setup,
465 : : user_data,
466 : : child_pid_out,
467 : : stdin_pipe_out,
468 : : stdout_pipe_out,
469 : : stderr_pipe_out,
470 : : stdin_fd,
471 : : stdout_fd,
472 : : stderr_fd,
473 : : source_fds,
474 : : target_fds,
475 : : n_fds,
476 : : error);
477 : : }
478 : :
479 : : gboolean
480 : 199 : g_spawn_check_wait_status_impl (gint wait_status,
481 : : GError **error)
482 : : {
483 : 199 : gboolean ret = FALSE;
484 : :
485 : 199 : if (WIFEXITED (wait_status))
486 : : {
487 : 193 : if (WEXITSTATUS (wait_status) != 0)
488 : : {
489 : 46 : g_set_error (error, G_SPAWN_EXIT_ERROR, WEXITSTATUS (wait_status),
490 : : _("Child process exited with code %ld"),
491 : 46 : (long) WEXITSTATUS (wait_status));
492 : 46 : goto out;
493 : : }
494 : : }
495 : 6 : else if (WIFSIGNALED (wait_status))
496 : : {
497 : 6 : g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
498 : : _("Child process killed by signal %ld"),
499 : 6 : (long) WTERMSIG (wait_status));
500 : 6 : goto out;
501 : : }
502 : 0 : else if (WIFSTOPPED (wait_status))
503 : : {
504 : 0 : g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
505 : : _("Child process stopped by signal %ld"),
506 : 0 : (long) WSTOPSIG (wait_status));
507 : 0 : goto out;
508 : : }
509 : : else
510 : : {
511 : 0 : g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
512 : : _("Child process exited abnormally"));
513 : 0 : goto out;
514 : : }
515 : :
516 : 147 : ret = TRUE;
517 : 199 : out:
518 : 199 : return ret;
519 : : }
520 : :
521 : : /* This function is called between fork() and exec() and hence must be
522 : : * async-signal-safe (see signal-safety(7)). */
523 : : static gssize
524 : 0 : write_all (gint fd, gconstpointer vbuf, gsize to_write)
525 : : {
526 : 0 : gchar *buf = (gchar *) vbuf;
527 : :
528 : 0 : while (to_write > 0)
529 : : {
530 : 0 : gssize count = write (fd, buf, to_write);
531 : 0 : if (count < 0)
532 : : {
533 : 0 : if (errno != EINTR)
534 : 0 : return FALSE;
535 : : }
536 : : else
537 : : {
538 : 0 : to_write -= count;
539 : 0 : buf += count;
540 : : }
541 : : }
542 : :
543 : 0 : return TRUE;
544 : : }
545 : :
546 : : /* This function is called between fork() and exec() and hence must be
547 : : * async-signal-safe (see signal-safety(7)). */
548 : : G_NORETURN
549 : : static void
550 : 0 : write_err_and_exit (gint fd, gint msg)
551 : : {
552 : 0 : gint en = errno;
553 : :
554 : 0 : write_all (fd, &msg, sizeof(msg));
555 : 0 : write_all (fd, &en, sizeof(en));
556 : :
557 : 0 : close (fd);
558 : :
559 : 0 : _exit (1);
560 : : }
561 : :
562 : : /* This function is called between fork() and exec() and hence must be
563 : : * async-signal-safe (see signal-safety(7)). */
564 : : static void
565 : 2273 : set_cloexec (int fd)
566 : : {
567 : 2273 : fcntl (fd, F_SETFD, FD_CLOEXEC);
568 : 2273 : }
569 : :
570 : : /* This function is called between fork() and exec() and hence must be
571 : : * async-signal-safe (see signal-safety(7)). */
572 : : static void
573 : 2 : unset_cloexec (int fd)
574 : : {
575 : : int flags;
576 : : int result;
577 : :
578 : 2 : flags = fcntl (fd, F_GETFD, 0);
579 : :
580 : 2 : if (flags != -1)
581 : : {
582 : : int errsv;
583 : 2 : flags &= (~FD_CLOEXEC);
584 : : do
585 : : {
586 : 2 : result = fcntl (fd, F_SETFD, flags);
587 : 2 : errsv = errno;
588 : : }
589 : 2 : while (result == -1 && errsv == EINTR);
590 : : }
591 : 2 : }
592 : :
593 : : /* This function is called between fork() and exec() and hence must be
594 : : * async-signal-safe (see signal-safety(7)). */
595 : : static int
596 : 117 : dupfd_cloexec (int old_fd, int new_fd_min)
597 : : {
598 : : int fd, errsv;
599 : : #ifdef F_DUPFD_CLOEXEC
600 : : do
601 : : {
602 : 117 : fd = fcntl (old_fd, F_DUPFD_CLOEXEC, new_fd_min);
603 : 117 : errsv = errno;
604 : : }
605 : 117 : while (fd == -1 && errsv == EINTR);
606 : : #else
607 : : /* OS X Snow Lion and earlier don't have F_DUPFD_CLOEXEC:
608 : : * https://bugzilla.gnome.org/show_bug.cgi?id=710962
609 : : */
610 : : int result, flags;
611 : : do
612 : : {
613 : : fd = fcntl (old_fd, F_DUPFD, new_fd_min);
614 : : errsv = errno;
615 : : }
616 : : while (fd == -1 && errsv == EINTR);
617 : : flags = fcntl (fd, F_GETFD, 0);
618 : : if (flags != -1)
619 : : {
620 : : flags |= FD_CLOEXEC;
621 : : do
622 : : {
623 : : result = fcntl (fd, F_SETFD, flags);
624 : : errsv = errno;
625 : : }
626 : : while (result == -1 && errsv == EINTR);
627 : : }
628 : : #endif
629 : 117 : return fd;
630 : : }
631 : :
632 : : /* This function is called between fork() and exec() and hence must be
633 : : * async-signal-safe (see signal-safety(7)). */
634 : : static gint
635 : 3444 : safe_dup2 (gint fd1, gint fd2)
636 : : {
637 : : gint ret;
638 : :
639 : : do
640 : 3444 : ret = dup2 (fd1, fd2);
641 : 3444 : while (ret < 0 && (errno == EINTR || errno == EBUSY));
642 : :
643 : 3444 : return ret;
644 : : }
645 : :
646 : : /* This function is called between fork() and exec() and hence must be
647 : : * async-signal-safe (see signal-safety(7)). */
648 : : static gboolean
649 : 16 : relocate_fd_out_of_standard_range (gint *fd)
650 : : {
651 : 16 : gint ret = -1;
652 : 16 : const int min_fileno = STDERR_FILENO + 1;
653 : :
654 : : do
655 : 16 : ret = fcntl (*fd, F_DUPFD, min_fileno);
656 : 16 : while (ret < 0 && errno == EINTR);
657 : :
658 : : /* Note we don't need to close the old fd, because the caller is expected
659 : : * to close fds in the standard range itself.
660 : : */
661 : 16 : if (ret >= min_fileno)
662 : : {
663 : 16 : *fd = ret;
664 : 16 : return TRUE;
665 : : }
666 : :
667 : 0 : return FALSE;
668 : : }
669 : :
670 : : /* This function is called between fork() and exec() and hence must be
671 : : * async-signal-safe (see signal-safety(7)). */
672 : : static gint
673 : 1265 : safe_open (const char *path, gint mode)
674 : : {
675 : : gint ret;
676 : :
677 : : do
678 : 1265 : ret = open (path, mode);
679 : 1265 : while (ret < 0 && errno == EINTR);
680 : :
681 : 1265 : return ret;
682 : : }
683 : :
684 : : enum
685 : : {
686 : : CHILD_CHDIR_FAILED,
687 : : CHILD_EXEC_FAILED,
688 : : CHILD_OPEN_FAILED,
689 : : CHILD_DUPFD_FAILED,
690 : : CHILD_FORK_FAILED,
691 : : CHILD_CLOSE_FAILED,
692 : : };
693 : :
694 : : /* This function is called between fork() and exec() and hence must be
695 : : * async-signal-safe (see signal-safety(7)) until it calls exec().
696 : : *
697 : : * All callers must guarantee that @argv and @argv[0] are non-NULL. */
698 : : static void
699 : 1004 : do_exec (gint child_err_report_fd,
700 : : gint stdin_fd,
701 : : gint stdout_fd,
702 : : gint stderr_fd,
703 : : gint *source_fds,
704 : : const gint *target_fds,
705 : : gsize n_fds,
706 : : const gchar *working_directory,
707 : : const gchar * const *argv,
708 : : gchar **argv_buffer,
709 : : gsize argv_buffer_len,
710 : : const gchar * const *envp,
711 : : gboolean close_descriptors,
712 : : const gchar *search_path,
713 : : gchar *search_path_buffer,
714 : : gsize search_path_buffer_len,
715 : : gboolean stdout_to_null,
716 : : gboolean stderr_to_null,
717 : : gboolean child_inherits_stdin,
718 : : gboolean file_and_argv_zero,
719 : : GSpawnChildSetupFunc child_setup,
720 : : gpointer user_data)
721 : : {
722 : : gsize i;
723 : 1004 : gint max_target_fd = 0;
724 : :
725 : 1004 : if (working_directory && chdir (working_directory) < 0)
726 : 0 : write_err_and_exit (child_err_report_fd,
727 : : CHILD_CHDIR_FAILED);
728 : :
729 : : /* It's possible the caller assigned stdin to an fd with a
730 : : * file number that is supposed to be reserved for
731 : : * stdout or stderr.
732 : : *
733 : : * If so, move it up out of the standard range, so it doesn't
734 : : * cause a conflict.
735 : : */
736 : 1004 : if (IS_STD_FILENO (stdin_fd) && stdin_fd != STDIN_FILENO)
737 : : {
738 : 0 : int old_fd = stdin_fd;
739 : :
740 : 0 : if (!relocate_fd_out_of_standard_range (&stdin_fd))
741 : 0 : write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
742 : :
743 : 0 : if (stdout_fd == old_fd)
744 : 0 : stdout_fd = stdin_fd;
745 : :
746 : 0 : if (stderr_fd == old_fd)
747 : 0 : stderr_fd = stdin_fd;
748 : : }
749 : :
750 : : /* Redirect pipes as required
751 : : *
752 : : * There are two cases where we don't need to do the redirection
753 : : * 1. Where the associated file descriptor is cleared/invalid
754 : : * 2. When the associated file descriptor is already given the
755 : : * correct file number.
756 : : */
757 : 1004 : if (IS_VALID_FILENO (stdin_fd) && stdin_fd != STDIN_FILENO)
758 : : {
759 : 60 : if (safe_dup2 (stdin_fd, 0) < 0)
760 : 0 : write_err_and_exit (child_err_report_fd,
761 : : CHILD_DUPFD_FAILED);
762 : :
763 : 60 : set_cloexec (stdin_fd);
764 : : }
765 : 944 : else if (!child_inherits_stdin)
766 : : {
767 : : /* Keep process from blocking on a read of stdin */
768 : 940 : gint read_null = safe_open ("/dev/null", O_RDONLY);
769 : 940 : if (read_null < 0)
770 : 0 : write_err_and_exit (child_err_report_fd,
771 : : CHILD_OPEN_FAILED);
772 : 940 : if (safe_dup2 (read_null, 0) < 0)
773 : 0 : write_err_and_exit (child_err_report_fd,
774 : : CHILD_DUPFD_FAILED);
775 : 940 : g_clear_fd (&read_null, NULL);
776 : : }
777 : :
778 : : /* Like with stdin above, it's possible the caller assigned
779 : : * stdout to an fd with a file number that's intruding on the
780 : : * standard range.
781 : : *
782 : : * If so, move it out of the way, too.
783 : : */
784 : 1004 : if (IS_STD_FILENO (stdout_fd) && stdout_fd != STDOUT_FILENO)
785 : : {
786 : 4 : int old_fd = stdout_fd;
787 : :
788 : 4 : if (!relocate_fd_out_of_standard_range (&stdout_fd))
789 : 0 : write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
790 : :
791 : 4 : if (stderr_fd == old_fd)
792 : 0 : stderr_fd = stdout_fd;
793 : : }
794 : :
795 : 1004 : if (IS_VALID_FILENO (stdout_fd) && stdout_fd != STDOUT_FILENO)
796 : : {
797 : 730 : if (safe_dup2 (stdout_fd, 1) < 0)
798 : 0 : write_err_and_exit (child_err_report_fd,
799 : : CHILD_DUPFD_FAILED);
800 : :
801 : 730 : set_cloexec (stdout_fd);
802 : : }
803 : 274 : else if (stdout_to_null)
804 : : {
805 : 90 : gint write_null = safe_open ("/dev/null", O_WRONLY);
806 : 90 : if (write_null < 0)
807 : 0 : write_err_and_exit (child_err_report_fd,
808 : : CHILD_OPEN_FAILED);
809 : 90 : if (safe_dup2 (write_null, 1) < 0)
810 : 0 : write_err_and_exit (child_err_report_fd,
811 : : CHILD_DUPFD_FAILED);
812 : 90 : g_clear_fd (&write_null, NULL);
813 : : }
814 : :
815 : 1004 : if (IS_STD_FILENO (stderr_fd) && stderr_fd != STDERR_FILENO)
816 : : {
817 : 12 : if (!relocate_fd_out_of_standard_range (&stderr_fd))
818 : 0 : write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
819 : : }
820 : :
821 : : /* Like with stdin/stdout above, it's possible the caller assigned
822 : : * stderr to an fd with a file number that's intruding on the
823 : : * standard range.
824 : : *
825 : : * Make sure it's out of the way, also.
826 : : */
827 : 1004 : if (IS_VALID_FILENO (stderr_fd) && stderr_fd != STDERR_FILENO)
828 : : {
829 : 487 : if (safe_dup2 (stderr_fd, 2) < 0)
830 : 0 : write_err_and_exit (child_err_report_fd,
831 : : CHILD_DUPFD_FAILED);
832 : :
833 : 487 : set_cloexec (stderr_fd);
834 : : }
835 : 517 : else if (stderr_to_null)
836 : : {
837 : 127 : gint write_null = safe_open ("/dev/null", O_WRONLY);
838 : 127 : if (write_null < 0)
839 : 0 : write_err_and_exit (child_err_report_fd,
840 : : CHILD_OPEN_FAILED);
841 : 127 : if (safe_dup2 (write_null, 2) < 0)
842 : 0 : write_err_and_exit (child_err_report_fd,
843 : : CHILD_DUPFD_FAILED);
844 : 127 : g_clear_fd (&write_null, NULL);
845 : : }
846 : :
847 : : /* Close all file descriptors but stdin, stdout and stderr, and any of source_fds,
848 : : * before we exec. Note that this includes
849 : : * child_err_report_fd, which keeps the parent from blocking
850 : : * forever on the other end of that pipe.
851 : : */
852 : 1004 : if (close_descriptors)
853 : : {
854 : 1000 : if (child_setup == NULL && n_fds == 0)
855 : : {
856 : 992 : if (safe_dup2 (child_err_report_fd, 3) < 0)
857 : 0 : write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
858 : 992 : set_cloexec (3);
859 : 992 : if (g_closefrom (4) < 0)
860 : 0 : write_err_and_exit (child_err_report_fd, CHILD_CLOSE_FAILED);
861 : 992 : child_err_report_fd = 3;
862 : : }
863 : : else
864 : : {
865 : 8 : if (g_fdwalk_set_cloexec (3) < 0)
866 : 0 : write_err_and_exit (child_err_report_fd, CHILD_CLOSE_FAILED);
867 : : }
868 : : }
869 : : else
870 : : {
871 : : /* We need to do child_err_report_fd anyway */
872 : 4 : set_cloexec (child_err_report_fd);
873 : : }
874 : :
875 : : /*
876 : : * Work through the @source_fds and @target_fds mapping.
877 : : *
878 : : * Based on code originally derived from
879 : : * gnome-terminal:src/terminal-screen.c:terminal_screen_child_setup(),
880 : : * used under the LGPLv2+ with permission from author. (The code has
881 : : * since migrated to vte:src/spawn.cc:SpawnContext::exec and is no longer
882 : : * terribly similar to what we have here.)
883 : : */
884 : :
885 : 1004 : if (n_fds > 0)
886 : : {
887 : 26 : for (i = 0; i < n_fds; i++)
888 : 20 : max_target_fd = MAX (max_target_fd, target_fds[i]);
889 : :
890 : 6 : if (max_target_fd == G_MAXINT)
891 : : {
892 : 0 : errno = EINVAL;
893 : 0 : write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
894 : : }
895 : :
896 : : /* If we're doing remapping fd assignments, we need to handle
897 : : * the case where the user has specified e.g. 5 -> 4, 4 -> 6.
898 : : * We do this by duping all source fds, taking care to ensure the new
899 : : * fds are larger than any target fd to avoid introducing new conflicts.
900 : : */
901 : 26 : for (i = 0; i < n_fds; i++)
902 : : {
903 : 20 : if (source_fds[i] != target_fds[i])
904 : : {
905 : 18 : source_fds[i] = dupfd_cloexec (source_fds[i], max_target_fd + 1);
906 : 18 : if (source_fds[i] < 0)
907 : 0 : write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
908 : : }
909 : : }
910 : :
911 : 26 : for (i = 0; i < n_fds; i++)
912 : : {
913 : : /* For basic fd assignments (where source == target), we can just
914 : : * unset FD_CLOEXEC.
915 : : */
916 : 20 : if (source_fds[i] == target_fds[i])
917 : : {
918 : 2 : unset_cloexec (source_fds[i]);
919 : : }
920 : : else
921 : : {
922 : : /* If any of the @target_fds conflict with @child_err_report_fd,
923 : : * dup it so it doesn’t get conflated.
924 : : */
925 : 18 : if (target_fds[i] == child_err_report_fd)
926 : : {
927 : 2 : int new_child_err_report_fd = dupfd_cloexec (child_err_report_fd, max_target_fd + 1);
928 : 2 : if (new_child_err_report_fd < 0)
929 : 0 : write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
930 : 2 : child_err_report_fd = new_child_err_report_fd;
931 : : }
932 : :
933 : 36 : if (target_fds[i] < 0 ||
934 : 18 : safe_dup2 (source_fds[i], target_fds[i]) < 0)
935 : 0 : write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
936 : :
937 : 18 : g_clear_fd (&source_fds[i], NULL);
938 : : }
939 : : }
940 : : }
941 : :
942 : : /* Call user function just before we exec */
943 : 1004 : if (child_setup)
944 : : {
945 : 5 : (* child_setup) (user_data);
946 : : }
947 : :
948 : 1004 : g_execute (argv[0],
949 : : (gchar **) (file_and_argv_zero ? argv + 1 : argv),
950 : : argv_buffer, argv_buffer_len,
951 : : (gchar **) envp, search_path, search_path_buffer, search_path_buffer_len);
952 : :
953 : : /* Exec failed */
954 : 0 : write_err_and_exit (child_err_report_fd,
955 : : CHILD_EXEC_FAILED);
956 : : }
957 : :
958 : : static gboolean
959 : 1113 : read_ints (int fd,
960 : : gint* buf,
961 : : gint n_ints_in_buf,
962 : : gint *n_ints_read,
963 : : GError **error)
964 : : {
965 : 1113 : gsize bytes = 0;
966 : :
967 : : while (TRUE)
968 : 118 : {
969 : : gssize chunk;
970 : :
971 : 1231 : if (bytes >= sizeof(gint)*2)
972 : 10 : break; /* give up, who knows what happened, should not be
973 : : * possible.
974 : : */
975 : :
976 : 1221 : again:
977 : 1221 : chunk = read (fd,
978 : : ((gchar*)buf) + bytes,
979 : 1221 : sizeof(gint) * n_ints_in_buf - bytes);
980 : 1221 : if (chunk < 0 && errno == EINTR)
981 : 0 : goto again;
982 : :
983 : 1221 : if (chunk < 0)
984 : : {
985 : 0 : int errsv = errno;
986 : :
987 : : /* Some weird shit happened, bail out */
988 : 0 : g_set_error (error,
989 : : G_SPAWN_ERROR,
990 : : G_SPAWN_ERROR_FAILED,
991 : : _("Failed to read from child pipe (%s)"),
992 : : g_strerror (errsv));
993 : :
994 : 0 : return FALSE;
995 : : }
996 : 1221 : else if (chunk == 0)
997 : 1103 : break; /* EOF */
998 : : else /* chunk > 0 */
999 : 118 : bytes += chunk;
1000 : : }
1001 : :
1002 : 1113 : *n_ints_read = (gint)(bytes / sizeof(gint));
1003 : :
1004 : 1113 : return TRUE;
1005 : : }
1006 : :
1007 : : #ifdef POSIX_SPAWN_AVAILABLE
1008 : : static gboolean
1009 : 100 : do_posix_spawn (const gchar * const *argv,
1010 : : const gchar * const *envp,
1011 : : gboolean search_path,
1012 : : gboolean stdout_to_null,
1013 : : gboolean stderr_to_null,
1014 : : gboolean child_inherits_stdin,
1015 : : gboolean file_and_argv_zero,
1016 : : GPid *child_pid,
1017 : : gint *child_close_fds,
1018 : : gint stdin_fd,
1019 : : gint stdout_fd,
1020 : : gint stderr_fd,
1021 : : const gint *source_fds,
1022 : : const gint *target_fds,
1023 : : gsize n_fds)
1024 : : {
1025 : : pid_t pid;
1026 : 100 : gint *duped_source_fds = NULL;
1027 : 100 : gint max_target_fd = 0;
1028 : : const gchar * const *argv_pass;
1029 : : posix_spawnattr_t attr;
1030 : : posix_spawn_file_actions_t file_actions;
1031 : : gint parent_close_fds[3];
1032 : 100 : gsize num_parent_close_fds = 0;
1033 : 100 : GSList *child_close = NULL;
1034 : : GSList *elem;
1035 : : sigset_t mask;
1036 : : gsize i;
1037 : : int r;
1038 : :
1039 : 100 : g_assert (argv != NULL && argv[0] != NULL);
1040 : :
1041 : 100 : if (*argv[0] == '\0')
1042 : : {
1043 : : /* We check the simple case first. */
1044 : 0 : return ENOENT;
1045 : : }
1046 : :
1047 : 100 : r = posix_spawnattr_init (&attr);
1048 : 100 : if (r != 0)
1049 : 0 : return r;
1050 : :
1051 : 100 : if (child_close_fds)
1052 : : {
1053 : 100 : int i = -1;
1054 : 101 : while (child_close_fds[++i] != -1)
1055 : 1 : child_close = g_slist_prepend (child_close,
1056 : 1 : GINT_TO_POINTER (child_close_fds[i]));
1057 : : }
1058 : :
1059 : 100 : r = posix_spawnattr_setflags (&attr, POSIX_SPAWN_SETSIGDEF);
1060 : 100 : if (r != 0)
1061 : 0 : goto out_free_spawnattr;
1062 : :
1063 : : /* Reset some signal handlers that we may use */
1064 : 100 : sigemptyset (&mask);
1065 : 100 : sigaddset (&mask, SIGCHLD);
1066 : 100 : sigaddset (&mask, SIGINT);
1067 : 100 : sigaddset (&mask, SIGTERM);
1068 : 100 : sigaddset (&mask, SIGHUP);
1069 : :
1070 : 100 : r = posix_spawnattr_setsigdefault (&attr, &mask);
1071 : 100 : if (r != 0)
1072 : 0 : goto out_free_spawnattr;
1073 : :
1074 : 100 : r = posix_spawn_file_actions_init (&file_actions);
1075 : 100 : if (r != 0)
1076 : 0 : goto out_free_spawnattr;
1077 : :
1078 : : /* Redirect pipes as required */
1079 : :
1080 : 100 : if (stdin_fd >= 0)
1081 : : {
1082 : 0 : r = posix_spawn_file_actions_adddup2 (&file_actions, stdin_fd, 0);
1083 : 0 : if (r != 0)
1084 : 0 : goto out_close_fds;
1085 : :
1086 : 0 : if (!g_slist_find (child_close, GINT_TO_POINTER (stdin_fd)))
1087 : 0 : child_close = g_slist_prepend (child_close, GINT_TO_POINTER (stdin_fd));
1088 : : }
1089 : 100 : else if (!child_inherits_stdin)
1090 : : {
1091 : : /* Keep process from blocking on a read of stdin */
1092 : 100 : gint read_null = safe_open ("/dev/null", O_RDONLY | O_CLOEXEC);
1093 : 100 : g_assert (read_null != -1);
1094 : 100 : parent_close_fds[num_parent_close_fds++] = read_null;
1095 : :
1096 : : #ifndef HAVE_O_CLOEXEC
1097 : : fcntl (read_null, F_SETFD, FD_CLOEXEC);
1098 : : #endif
1099 : :
1100 : 100 : r = posix_spawn_file_actions_adddup2 (&file_actions, read_null, 0);
1101 : 100 : if (r != 0)
1102 : 0 : goto out_close_fds;
1103 : : }
1104 : :
1105 : 100 : if (stdout_fd >= 0)
1106 : : {
1107 : 1 : r = posix_spawn_file_actions_adddup2 (&file_actions, stdout_fd, 1);
1108 : 1 : if (r != 0)
1109 : 0 : goto out_close_fds;
1110 : :
1111 : 1 : if (!g_slist_find (child_close, GINT_TO_POINTER (stdout_fd)))
1112 : 1 : child_close = g_slist_prepend (child_close, GINT_TO_POINTER (stdout_fd));
1113 : : }
1114 : 99 : else if (stdout_to_null)
1115 : : {
1116 : 4 : gint write_null = safe_open ("/dev/null", O_WRONLY | O_CLOEXEC);
1117 : 4 : g_assert (write_null != -1);
1118 : 4 : parent_close_fds[num_parent_close_fds++] = write_null;
1119 : :
1120 : : #ifndef HAVE_O_CLOEXEC
1121 : : fcntl (write_null, F_SETFD, FD_CLOEXEC);
1122 : : #endif
1123 : :
1124 : 4 : r = posix_spawn_file_actions_adddup2 (&file_actions, write_null, 1);
1125 : 4 : if (r != 0)
1126 : 0 : goto out_close_fds;
1127 : : }
1128 : :
1129 : 100 : if (stderr_fd >= 0)
1130 : : {
1131 : 0 : r = posix_spawn_file_actions_adddup2 (&file_actions, stderr_fd, 2);
1132 : 0 : if (r != 0)
1133 : 0 : goto out_close_fds;
1134 : :
1135 : 0 : if (!g_slist_find (child_close, GINT_TO_POINTER (stderr_fd)))
1136 : 0 : child_close = g_slist_prepend (child_close, GINT_TO_POINTER (stderr_fd));
1137 : : }
1138 : 100 : else if (stderr_to_null)
1139 : : {
1140 : 4 : gint write_null = safe_open ("/dev/null", O_WRONLY | O_CLOEXEC);
1141 : 4 : g_assert (write_null != -1);
1142 : 4 : parent_close_fds[num_parent_close_fds++] = write_null;
1143 : :
1144 : : #ifndef HAVE_O_CLOEXEC
1145 : : fcntl (write_null, F_SETFD, FD_CLOEXEC);
1146 : : #endif
1147 : :
1148 : 4 : r = posix_spawn_file_actions_adddup2 (&file_actions, write_null, 2);
1149 : 4 : if (r != 0)
1150 : 0 : goto out_close_fds;
1151 : : }
1152 : :
1153 : : /* If source_fds[i] != target_fds[i], we need to handle the case
1154 : : * where the user has specified, e.g., 5 -> 4, 4 -> 6. We do this
1155 : : * by duping the source fds, taking care to ensure the new fds are
1156 : : * larger than any target fd to avoid introducing new conflicts.
1157 : : *
1158 : : * If source_fds[i] == target_fds[i], then we just need to leak
1159 : : * the fd into the child process, which we *could* do by temporarily
1160 : : * unsetting CLOEXEC and then setting it again after we spawn if
1161 : : * it was originally set. POSIX requires that the addup2 action unset
1162 : : * CLOEXEC if source and target are identical, so you'd think doing it
1163 : : * manually wouldn't be needed, but unfortunately as of 2021 many
1164 : : * libcs still don't do so. Example nonconforming libcs:
1165 : : * Bionic: https://android.googlesource.com/platform/bionic/+/f6e5b582604715729b09db3e36a7aeb8c24b36a4/libc/bionic/spawn.cpp#71
1166 : : * uclibc-ng: https://cgit.uclibc-ng.org/cgi/cgit/uclibc-ng.git/tree/librt/spawn.c?id=7c36bcae09d66bbaa35cbb02253ae0556f42677e#n88
1167 : : *
1168 : : * Anyway, unsetting CLOEXEC ourselves would open a small race window
1169 : : * where the fd could be inherited into a child process if another
1170 : : * thread spawns something at the same time, because we have not
1171 : : * called fork() and are multithreaded here. This race is avoidable by
1172 : : * using dupfd_cloexec, which we already have to do to handle the
1173 : : * source_fds[i] != target_fds[i] case. So let's always do it!
1174 : : */
1175 : :
1176 : 197 : for (i = 0; i < n_fds; i++)
1177 : 97 : max_target_fd = MAX (max_target_fd, target_fds[i]);
1178 : :
1179 : 100 : if (max_target_fd == G_MAXINT)
1180 : 0 : goto out_close_fds;
1181 : :
1182 : 100 : duped_source_fds = g_new (gint, n_fds);
1183 : 197 : for (i = 0; i < n_fds; i++)
1184 : 97 : duped_source_fds[i] = -1; /* initialise in case dupfd_cloexec() fails below */
1185 : 197 : for (i = 0; i < n_fds; i++)
1186 : : {
1187 : 97 : duped_source_fds[i] = dupfd_cloexec (source_fds[i], max_target_fd + 1);
1188 : 97 : if (duped_source_fds[i] < 0)
1189 : 0 : goto out_close_fds;
1190 : : }
1191 : :
1192 : 197 : for (i = 0; i < n_fds; i++)
1193 : : {
1194 : 97 : r = posix_spawn_file_actions_adddup2 (&file_actions, duped_source_fds[i], target_fds[i]);
1195 : 97 : if (r != 0)
1196 : 0 : goto out_close_fds;
1197 : : }
1198 : :
1199 : : /* Intentionally close the fds in the child as the last file action,
1200 : : * having been careful not to add the same fd to this list twice.
1201 : : *
1202 : : * This is important to allow (e.g.) for the same fd to be passed as stdout
1203 : : * and stderr (we must not close it before we have dupped it in both places,
1204 : : * and we must not attempt to close it twice).
1205 : : */
1206 : 102 : for (elem = child_close; elem != NULL; elem = elem->next)
1207 : : {
1208 : 2 : r = posix_spawn_file_actions_addclose (&file_actions,
1209 : 2 : GPOINTER_TO_INT (elem->data));
1210 : 2 : if (r != 0)
1211 : 0 : goto out_close_fds;
1212 : : }
1213 : :
1214 : 100 : argv_pass = file_and_argv_zero ? argv + 1 : argv;
1215 : 100 : if (envp == NULL)
1216 : 98 : envp = (const gchar * const *) environ;
1217 : :
1218 : : /* Don't search when it contains a slash. */
1219 : 100 : if (!search_path || strchr (argv[0], '/') != NULL)
1220 : 7 : r = posix_spawn (&pid, argv[0], &file_actions, &attr, (char * const *) argv_pass, (char * const *) envp);
1221 : : else
1222 : 93 : r = posix_spawnp (&pid, argv[0], &file_actions, &attr, (char * const *) argv_pass, (char * const *) envp);
1223 : :
1224 : 100 : if (r == 0 && child_pid != NULL)
1225 : 100 : *child_pid = pid;
1226 : :
1227 : 0 : out_close_fds:
1228 : 208 : for (i = 0; i < num_parent_close_fds; i++)
1229 : 108 : g_clear_fd (&parent_close_fds[i], NULL);
1230 : :
1231 : 100 : if (duped_source_fds != NULL)
1232 : : {
1233 : 192 : for (i = 0; i < n_fds; i++)
1234 : 97 : g_clear_fd (&duped_source_fds[i], NULL);
1235 : 95 : g_free (duped_source_fds);
1236 : : }
1237 : :
1238 : 100 : posix_spawn_file_actions_destroy (&file_actions);
1239 : 100 : out_free_spawnattr:
1240 : 100 : posix_spawnattr_destroy (&attr);
1241 : 100 : g_slist_free (child_close);
1242 : :
1243 : 100 : return r;
1244 : : }
1245 : : #endif /* POSIX_SPAWN_AVAILABLE */
1246 : :
1247 : : static gboolean
1248 : 2383 : source_fds_collide_with_pipe (const GUnixPipe *pipefd,
1249 : : const int *source_fds,
1250 : : gsize n_fds,
1251 : : GError **error)
1252 : : {
1253 : 4765 : return (_g_spawn_invalid_source_fd (pipefd->fds[G_UNIX_PIPE_END_READ], source_fds, n_fds, error) ||
1254 : 2382 : _g_spawn_invalid_source_fd (pipefd->fds[G_UNIX_PIPE_END_WRITE], source_fds, n_fds, error));
1255 : : }
1256 : :
1257 : : static gboolean
1258 : 1106 : fork_exec (gboolean intermediate_child,
1259 : : const gchar *working_directory,
1260 : : const gchar * const *argv,
1261 : : const gchar * const *envp,
1262 : : gboolean close_descriptors,
1263 : : gboolean search_path,
1264 : : gboolean search_path_from_envp,
1265 : : gboolean stdout_to_null,
1266 : : gboolean stderr_to_null,
1267 : : gboolean child_inherits_stdin,
1268 : : gboolean file_and_argv_zero,
1269 : : gboolean cloexec_pipes,
1270 : : GSpawnChildSetupFunc child_setup,
1271 : : gpointer user_data,
1272 : : GPid *child_pid,
1273 : : gint *stdin_pipe_out,
1274 : : gint *stdout_pipe_out,
1275 : : gint *stderr_pipe_out,
1276 : : gint stdin_fd,
1277 : : gint stdout_fd,
1278 : : gint stderr_fd,
1279 : : const gint *source_fds,
1280 : : const gint *target_fds,
1281 : : gsize n_fds,
1282 : : GError **error)
1283 : : {
1284 : 1106 : GPid pid = -1;
1285 : 1106 : GUnixPipe child_err_report_pipe = G_UNIX_PIPE_INIT;
1286 : 1106 : GUnixPipe child_pid_report_pipe = G_UNIX_PIPE_INIT;
1287 : 1106 : guint pipe_flags = cloexec_pipes ? O_CLOEXEC : 0;
1288 : : gint status;
1289 : : const gchar *chosen_search_path;
1290 : 1106 : gchar *search_path_buffer = NULL;
1291 : 1106 : gchar *search_path_buffer_heap = NULL;
1292 : 1106 : gsize search_path_buffer_len = 0;
1293 : 1106 : gchar **argv_buffer = NULL;
1294 : 1106 : gchar **argv_buffer_heap = NULL;
1295 : 1106 : gsize argv_buffer_len = 0;
1296 : 1106 : GUnixPipe stdin_pipe = G_UNIX_PIPE_INIT;
1297 : 1106 : GUnixPipe stdout_pipe = G_UNIX_PIPE_INIT;
1298 : 1106 : GUnixPipe stderr_pipe = G_UNIX_PIPE_INIT;
1299 : 1106 : gint child_close_fds[4] = { -1, -1, -1, -1 };
1300 : 1106 : gint n_child_close_fds = 0;
1301 : 1106 : gint *source_fds_copy = NULL;
1302 : :
1303 : 1106 : g_assert (argv != NULL && argv[0] != NULL);
1304 : 1106 : g_assert (stdin_pipe_out == NULL || stdin_fd < 0);
1305 : 1106 : g_assert (stdout_pipe_out == NULL || stdout_fd < 0);
1306 : 1106 : g_assert (stderr_pipe_out == NULL || stderr_fd < 0);
1307 : :
1308 : : /* If pipes have been requested, open them */
1309 : 1106 : if (stdin_pipe_out != NULL)
1310 : : {
1311 : 59 : if (!g_unix_pipe_open (&stdin_pipe, pipe_flags, error))
1312 : 0 : goto cleanup_and_fail;
1313 : 59 : if (source_fds_collide_with_pipe (&stdin_pipe, source_fds, n_fds, error))
1314 : 0 : goto cleanup_and_fail;
1315 : 59 : child_close_fds[n_child_close_fds++] = g_unix_pipe_get (&stdin_pipe, G_UNIX_PIPE_END_WRITE);
1316 : 59 : stdin_fd = g_unix_pipe_get (&stdin_pipe, G_UNIX_PIPE_END_READ);
1317 : : }
1318 : :
1319 : 1106 : if (stdout_pipe_out != NULL)
1320 : : {
1321 : 731 : if (!g_unix_pipe_open (&stdout_pipe, pipe_flags, error))
1322 : 0 : goto cleanup_and_fail;
1323 : 731 : if (source_fds_collide_with_pipe (&stdout_pipe, source_fds, n_fds, error))
1324 : 0 : goto cleanup_and_fail;
1325 : 731 : child_close_fds[n_child_close_fds++] = g_unix_pipe_get (&stdout_pipe, G_UNIX_PIPE_END_READ);
1326 : 731 : stdout_fd = g_unix_pipe_get (&stdout_pipe, G_UNIX_PIPE_END_WRITE);
1327 : : }
1328 : :
1329 : 1106 : if (stderr_pipe_out != NULL)
1330 : : {
1331 : 477 : if (!g_unix_pipe_open (&stderr_pipe, pipe_flags, error))
1332 : 0 : goto cleanup_and_fail;
1333 : 477 : if (source_fds_collide_with_pipe (&stderr_pipe, source_fds, n_fds, error))
1334 : 0 : goto cleanup_and_fail;
1335 : 477 : child_close_fds[n_child_close_fds++] = g_unix_pipe_get (&stderr_pipe, G_UNIX_PIPE_END_READ);
1336 : 477 : stderr_fd = g_unix_pipe_get (&stderr_pipe, G_UNIX_PIPE_END_WRITE);
1337 : : }
1338 : :
1339 : 1106 : child_close_fds[n_child_close_fds++] = -1;
1340 : :
1341 : : #ifdef POSIX_SPAWN_AVAILABLE
1342 : 1106 : if (!intermediate_child && working_directory == NULL && !close_descriptors &&
1343 : 100 : !search_path_from_envp && child_setup == NULL)
1344 : : {
1345 : 100 : g_trace_mark (G_TRACE_CURRENT_TIME, 0,
1346 : : "GLib", "posix_spawn",
1347 : : "%s", argv[0]);
1348 : :
1349 : 100 : status = do_posix_spawn (argv,
1350 : : envp,
1351 : : search_path,
1352 : : stdout_to_null,
1353 : : stderr_to_null,
1354 : : child_inherits_stdin,
1355 : : file_and_argv_zero,
1356 : : child_pid,
1357 : : child_close_fds,
1358 : : stdin_fd,
1359 : : stdout_fd,
1360 : : stderr_fd,
1361 : : source_fds,
1362 : : target_fds,
1363 : : n_fds);
1364 : 100 : if (status == 0)
1365 : 100 : goto success;
1366 : :
1367 : 0 : if (status != ENOEXEC)
1368 : : {
1369 : 0 : g_set_error (error,
1370 : : G_SPAWN_ERROR,
1371 : : G_SPAWN_ERROR_FAILED,
1372 : : _("Failed to spawn child process “%s” (%s)"),
1373 : : argv[0],
1374 : : g_strerror (status));
1375 : 0 : goto cleanup_and_fail;
1376 : : }
1377 : :
1378 : : /* posix_spawn is not intended to support script execution. It does in
1379 : : * some situations on some glibc versions, but that will be fixed.
1380 : : * So if it fails with ENOEXEC, we fall through to the regular
1381 : : * gspawn codepath so that script execution can be attempted,
1382 : : * per standard gspawn behaviour. */
1383 : 0 : g_debug ("posix_spawn failed (ENOEXEC), fall back to regular gspawn");
1384 : : }
1385 : : else
1386 : : {
1387 : 1006 : g_trace_mark (G_TRACE_CURRENT_TIME, 0,
1388 : : "GLib", "fork",
1389 : : "posix_spawn avoided %s%s%s%s%s",
1390 : : !intermediate_child ? "" : "(automatic reaping requested) ",
1391 : : working_directory == NULL ? "" : "(workdir specified) ",
1392 : : !close_descriptors ? "" : "(fd close requested) ",
1393 : : !search_path_from_envp ? "" : "(using envp for search path) ",
1394 : : child_setup == NULL ? "" : "(child_setup specified) ");
1395 : : }
1396 : : #endif /* POSIX_SPAWN_AVAILABLE */
1397 : :
1398 : : /* Choose a search path. This has to be done before calling fork()
1399 : : * as getenv() isn’t async-signal-safe (see `man 7 signal-safety`). */
1400 : 1006 : chosen_search_path = NULL;
1401 : 1006 : if (search_path_from_envp)
1402 : 36 : chosen_search_path = g_environ_getenv ((gchar **) envp, "PATH");
1403 : 1006 : if (search_path && chosen_search_path == NULL)
1404 : 240 : chosen_search_path = g_getenv ("PATH");
1405 : :
1406 : 1006 : if ((search_path || search_path_from_envp) && chosen_search_path == NULL)
1407 : : {
1408 : : /* There is no 'PATH' in the environment. The default
1409 : : * * search path in libc is the current directory followed by
1410 : : * * the path 'confstr' returns for '_CS_PATH'.
1411 : : * */
1412 : :
1413 : : /* In GLib we put . last, for security, and don't use the
1414 : : * * unportable confstr(); UNIX98 does not actually specify
1415 : : * * what to search if PATH is unset. POSIX may, dunno.
1416 : : * */
1417 : :
1418 : 2 : chosen_search_path = "/bin:/usr/bin:.";
1419 : : }
1420 : :
1421 : 1006 : if (search_path || search_path_from_envp)
1422 : 276 : g_assert (chosen_search_path != NULL);
1423 : : else
1424 : 730 : g_assert (chosen_search_path == NULL);
1425 : :
1426 : : /* Allocate a buffer which the fork()ed child can use to assemble potential
1427 : : * paths for the binary to exec(), combining the argv[0] and elements from
1428 : : * the chosen_search_path. This can’t be done in the child because malloc()
1429 : : * (or alloca()) are not async-signal-safe (see `man 7 signal-safety`).
1430 : : *
1431 : : * Add 2 for the nul terminator and a leading `/`. */
1432 : 1006 : if (chosen_search_path != NULL)
1433 : : {
1434 : 276 : search_path_buffer_len = strlen (chosen_search_path) + strlen (argv[0]) + 2;
1435 : 276 : if (search_path_buffer_len < 4000)
1436 : : {
1437 : : /* Prefer small stack allocations to avoid valgrind leak warnings
1438 : : * in forked child. The 4000B cutoff is arbitrary. */
1439 : 275 : search_path_buffer = g_alloca (search_path_buffer_len);
1440 : : }
1441 : : else
1442 : : {
1443 : 1 : search_path_buffer_heap = g_malloc (search_path_buffer_len);
1444 : 1 : search_path_buffer = search_path_buffer_heap;
1445 : : }
1446 : : }
1447 : :
1448 : 1006 : if (search_path || search_path_from_envp)
1449 : 276 : g_assert (search_path_buffer != NULL);
1450 : : else
1451 : 730 : g_assert (search_path_buffer == NULL);
1452 : :
1453 : : /* And allocate a buffer which is 2 elements longer than @argv, so that if
1454 : : * script_execute() has to be called later on, it can build a wrapper argv
1455 : : * array in this buffer. */
1456 : 1006 : argv_buffer_len = g_strv_length ((gchar **) argv) + 2;
1457 : 1006 : if (argv_buffer_len < 4000 / sizeof (gchar *))
1458 : : {
1459 : : /* Prefer small stack allocations to avoid valgrind leak warnings
1460 : : * in forked child. The 4000B cutoff is arbitrary. */
1461 : 1004 : argv_buffer = g_newa (gchar *, argv_buffer_len);
1462 : : }
1463 : : else
1464 : : {
1465 : 2 : argv_buffer_heap = g_new (gchar *, argv_buffer_len);
1466 : 2 : argv_buffer = argv_buffer_heap;
1467 : : }
1468 : :
1469 : : /* And one to hold a copy of @source_fds for later manipulation in do_exec(). */
1470 : 1006 : source_fds_copy = g_new (int, n_fds);
1471 : 1006 : if (n_fds > 0)
1472 : 7 : memcpy (source_fds_copy, source_fds, sizeof (*source_fds) * n_fds);
1473 : :
1474 : 1006 : if (!g_unix_pipe_open (&child_err_report_pipe, pipe_flags, error))
1475 : 0 : goto cleanup_and_fail;
1476 : 1006 : if (source_fds_collide_with_pipe (&child_err_report_pipe, source_fds, n_fds, error))
1477 : 1 : goto cleanup_and_fail;
1478 : :
1479 : 1005 : if (intermediate_child)
1480 : : {
1481 : 110 : if (!g_unix_pipe_open (&child_pid_report_pipe, pipe_flags, error))
1482 : 0 : goto cleanup_and_fail;
1483 : 110 : if (source_fds_collide_with_pipe (&child_pid_report_pipe, source_fds, n_fds, error))
1484 : 0 : goto cleanup_and_fail;
1485 : : }
1486 : :
1487 : 1005 : pid = fork ();
1488 : :
1489 : 1899 : if (pid < 0)
1490 : : {
1491 : 0 : int errsv = errno;
1492 : :
1493 : 0 : g_set_error (error,
1494 : : G_SPAWN_ERROR,
1495 : : G_SPAWN_ERROR_FORK,
1496 : : _("Failed to fork (%s)"),
1497 : : g_strerror (errsv));
1498 : :
1499 : 0 : goto cleanup_and_fail;
1500 : : }
1501 : 1899 : else if (pid == 0)
1502 : : {
1503 : : /* Immediate child. This may or may not be the child that
1504 : : * actually execs the new process.
1505 : : */
1506 : :
1507 : : /* Reset some signal handlers that we may use */
1508 : 894 : signal (SIGCHLD, SIG_DFL);
1509 : 894 : signal (SIGINT, SIG_DFL);
1510 : 894 : signal (SIGTERM, SIG_DFL);
1511 : 894 : signal (SIGHUP, SIG_DFL);
1512 : :
1513 : : /* Be sure we crash if the parent exits
1514 : : * and we write to the err_report_pipe
1515 : : */
1516 : 894 : signal (SIGPIPE, SIG_DFL);
1517 : :
1518 : : /* Close the parent's end of the pipes;
1519 : : * not needed in the close_descriptors case,
1520 : : * though
1521 : : */
1522 : 894 : g_unix_pipe_close (&child_err_report_pipe, G_UNIX_PIPE_END_READ, NULL);
1523 : 894 : g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_READ, NULL);
1524 : 894 : if (child_close_fds[0] != -1)
1525 : : {
1526 : 766 : int i = -1;
1527 : 2032 : while (child_close_fds[++i] != -1)
1528 : 1266 : g_clear_fd (&child_close_fds[i], NULL);
1529 : : }
1530 : :
1531 : 894 : if (intermediate_child)
1532 : : {
1533 : : /* We need to fork an intermediate child that launches the
1534 : : * final child. The purpose of the intermediate child
1535 : : * is to exit, so we can waitpid() it immediately.
1536 : : * Then the grandchild will not become a zombie.
1537 : : */
1538 : : GPid grandchild_pid;
1539 : :
1540 : 0 : grandchild_pid = fork ();
1541 : :
1542 : 110 : if (grandchild_pid < 0)
1543 : : {
1544 : : /* report -1 as child PID */
1545 : 0 : write_all (g_unix_pipe_get (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE),
1546 : : &grandchild_pid, sizeof(grandchild_pid));
1547 : :
1548 : 0 : write_err_and_exit (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE),
1549 : : CHILD_FORK_FAILED);
1550 : : }
1551 : 110 : else if (grandchild_pid == 0)
1552 : : {
1553 : 110 : g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1554 : 110 : do_exec (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE),
1555 : : stdin_fd,
1556 : : stdout_fd,
1557 : : stderr_fd,
1558 : : source_fds_copy,
1559 : : target_fds,
1560 : : n_fds,
1561 : : working_directory,
1562 : : argv,
1563 : : argv_buffer,
1564 : : argv_buffer_len,
1565 : : envp,
1566 : : close_descriptors,
1567 : : chosen_search_path,
1568 : : search_path_buffer,
1569 : : search_path_buffer_len,
1570 : : stdout_to_null,
1571 : : stderr_to_null,
1572 : : child_inherits_stdin,
1573 : : file_and_argv_zero,
1574 : : child_setup,
1575 : : user_data);
1576 : : }
1577 : : else
1578 : : {
1579 : 0 : write_all (g_unix_pipe_get (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE),
1580 : : &grandchild_pid, sizeof(grandchild_pid));
1581 : 0 : g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1582 : :
1583 : 0 : _exit (0);
1584 : : }
1585 : : }
1586 : : else
1587 : : {
1588 : : /* Just run the child.
1589 : : */
1590 : :
1591 : 894 : do_exec (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE),
1592 : : stdin_fd,
1593 : : stdout_fd,
1594 : : stderr_fd,
1595 : : source_fds_copy,
1596 : : target_fds,
1597 : : n_fds,
1598 : : working_directory,
1599 : : argv,
1600 : : argv_buffer,
1601 : : argv_buffer_len,
1602 : : envp,
1603 : : close_descriptors,
1604 : : chosen_search_path,
1605 : : search_path_buffer,
1606 : : search_path_buffer_len,
1607 : : stdout_to_null,
1608 : : stderr_to_null,
1609 : : child_inherits_stdin,
1610 : : file_and_argv_zero,
1611 : : child_setup,
1612 : : user_data);
1613 : : }
1614 : : }
1615 : : else
1616 : : {
1617 : : /* Parent */
1618 : :
1619 : : gint buf[2];
1620 : 1005 : gint n_ints = 0;
1621 : :
1622 : : /* Close the uncared-about ends of the pipes */
1623 : 1005 : g_unix_pipe_close (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1624 : 1005 : g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1625 : :
1626 : : /* If we had an intermediate child, reap it */
1627 : 1005 : if (intermediate_child)
1628 : : {
1629 : 110 : wait_again:
1630 : 110 : if (waitpid (pid, &status, 0) < 0)
1631 : : {
1632 : 0 : if (errno == EINTR)
1633 : 0 : goto wait_again;
1634 : 0 : else if (errno == ECHILD)
1635 : : ; /* do nothing, child already reaped */
1636 : : else
1637 : 0 : g_warning ("waitpid() should not fail in 'fork_exec'");
1638 : : }
1639 : : }
1640 : :
1641 : :
1642 : 1005 : if (!read_ints (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_READ),
1643 : : buf, 2, &n_ints,
1644 : : error))
1645 : 10 : goto cleanup_and_fail;
1646 : :
1647 : 1005 : if (n_ints >= 2)
1648 : : {
1649 : : /* Error from the child. */
1650 : :
1651 : 10 : switch (buf[0])
1652 : : {
1653 : 0 : case CHILD_CHDIR_FAILED:
1654 : 0 : g_set_error (error,
1655 : : G_SPAWN_ERROR,
1656 : : G_SPAWN_ERROR_CHDIR,
1657 : : _("Failed to change to directory “%s” (%s)"),
1658 : : working_directory,
1659 : : g_strerror (buf[1]));
1660 : :
1661 : 0 : break;
1662 : :
1663 : 9 : case CHILD_EXEC_FAILED:
1664 : 9 : g_set_error (error,
1665 : : G_SPAWN_ERROR,
1666 : : _g_spawn_exec_err_to_g_error (buf[1]),
1667 : : _("Failed to execute child process “%s” (%s)"),
1668 : : argv[0],
1669 : : g_strerror (buf[1]));
1670 : :
1671 : 9 : break;
1672 : :
1673 : 0 : case CHILD_OPEN_FAILED:
1674 : 0 : g_set_error (error,
1675 : : G_SPAWN_ERROR,
1676 : : G_SPAWN_ERROR_FAILED,
1677 : : _("Failed to open file to remap file descriptor (%s)"),
1678 : : g_strerror (buf[1]));
1679 : 0 : break;
1680 : :
1681 : 1 : case CHILD_DUPFD_FAILED:
1682 : 1 : g_set_error (error,
1683 : : G_SPAWN_ERROR,
1684 : : G_SPAWN_ERROR_FAILED,
1685 : : _("Failed to duplicate file descriptor for child process (%s)"),
1686 : : g_strerror (buf[1]));
1687 : :
1688 : 1 : break;
1689 : :
1690 : 0 : case CHILD_FORK_FAILED:
1691 : 0 : g_set_error (error,
1692 : : G_SPAWN_ERROR,
1693 : : G_SPAWN_ERROR_FORK,
1694 : : _("Failed to fork child process (%s)"),
1695 : : g_strerror (buf[1]));
1696 : 0 : break;
1697 : :
1698 : 0 : case CHILD_CLOSE_FAILED:
1699 : 0 : g_set_error (error,
1700 : : G_SPAWN_ERROR,
1701 : : G_SPAWN_ERROR_FAILED,
1702 : : _("Failed to close file descriptor for child process (%s)"),
1703 : : g_strerror (buf[1]));
1704 : 0 : break;
1705 : :
1706 : 0 : default:
1707 : 0 : g_set_error (error,
1708 : : G_SPAWN_ERROR,
1709 : : G_SPAWN_ERROR_FAILED,
1710 : : _("Unknown error executing child process “%s”"),
1711 : : argv[0]);
1712 : 0 : break;
1713 : : }
1714 : :
1715 : 10 : goto cleanup_and_fail;
1716 : : }
1717 : :
1718 : : /* Get child pid from intermediate child pipe. */
1719 : 995 : if (intermediate_child)
1720 : : {
1721 : 108 : n_ints = 0;
1722 : :
1723 : 108 : if (!read_ints (g_unix_pipe_get (&child_pid_report_pipe, G_UNIX_PIPE_END_READ),
1724 : : buf, 1, &n_ints, error))
1725 : 0 : goto cleanup_and_fail;
1726 : :
1727 : 108 : if (n_ints < 1)
1728 : : {
1729 : 0 : int errsv = errno;
1730 : :
1731 : 0 : g_set_error (error,
1732 : : G_SPAWN_ERROR,
1733 : : G_SPAWN_ERROR_FAILED,
1734 : : _("Failed to read enough data from child pid pipe (%s)"),
1735 : : g_strerror (errsv));
1736 : 0 : goto cleanup_and_fail;
1737 : : }
1738 : : else
1739 : : {
1740 : : /* we have the child pid */
1741 : 108 : pid = buf[0];
1742 : : }
1743 : : }
1744 : :
1745 : : /* Success against all odds! return the information */
1746 : 995 : g_unix_pipe_close (&child_err_report_pipe, G_UNIX_PIPE_END_READ, NULL);
1747 : 995 : g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_READ, NULL);
1748 : :
1749 : 995 : g_free (search_path_buffer_heap);
1750 : 995 : g_free (argv_buffer_heap);
1751 : 995 : g_free (source_fds_copy);
1752 : :
1753 : 995 : if (child_pid)
1754 : 984 : *child_pid = pid;
1755 : :
1756 : 995 : goto success;
1757 : : }
1758 : :
1759 : 1095 : success:
1760 : : /* Close the uncared-about ends of the pipes */
1761 : 1095 : g_unix_pipe_close (&stdin_pipe, G_UNIX_PIPE_END_READ, NULL);
1762 : 1095 : g_unix_pipe_close (&stdout_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1763 : 1095 : g_unix_pipe_close (&stderr_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1764 : :
1765 : 1095 : if (stdin_pipe_out != NULL)
1766 : 59 : *stdin_pipe_out = g_unix_pipe_steal (&stdin_pipe, G_UNIX_PIPE_END_WRITE);
1767 : :
1768 : 1095 : if (stdout_pipe_out != NULL)
1769 : 730 : *stdout_pipe_out = g_unix_pipe_steal (&stdout_pipe, G_UNIX_PIPE_END_READ);
1770 : :
1771 : 1095 : if (stderr_pipe_out != NULL)
1772 : 477 : *stderr_pipe_out = g_unix_pipe_steal (&stderr_pipe, G_UNIX_PIPE_END_READ);
1773 : :
1774 : 1095 : return TRUE;
1775 : :
1776 : 11 : cleanup_and_fail:
1777 : :
1778 : : /* There was an error from the Child, reap the child to avoid it being
1779 : : a zombie.
1780 : : */
1781 : :
1782 : 11 : if (pid > 0)
1783 : : {
1784 : 10 : wait_failed:
1785 : 10 : if (waitpid (pid, NULL, 0) < 0)
1786 : : {
1787 : 2 : if (errno == EINTR)
1788 : 0 : goto wait_failed;
1789 : 2 : else if (errno == ECHILD)
1790 : : ; /* do nothing, child already reaped */
1791 : : else
1792 : 0 : g_warning ("waitpid() should not fail in 'fork_exec'");
1793 : : }
1794 : : }
1795 : :
1796 : 11 : g_unix_pipe_clear (&stdin_pipe);
1797 : 11 : g_unix_pipe_clear (&stdout_pipe);
1798 : 11 : g_unix_pipe_clear (&stderr_pipe);
1799 : 11 : g_unix_pipe_clear (&child_err_report_pipe);
1800 : 11 : g_unix_pipe_clear (&child_pid_report_pipe);
1801 : :
1802 : 11 : g_clear_pointer (&search_path_buffer_heap, g_free);
1803 : 11 : g_clear_pointer (&argv_buffer_heap, g_free);
1804 : 11 : g_clear_pointer (&source_fds_copy, g_free);
1805 : :
1806 : 11 : return FALSE;
1807 : : }
1808 : :
1809 : : /* Based on execvp from GNU C Library */
1810 : :
1811 : : /* This function is called between fork() and exec() and hence must be
1812 : : * async-signal-safe (see signal-safety(7)) until it calls exec(). */
1813 : : static gboolean
1814 : 0 : script_execute (const gchar *file,
1815 : : gchar **argv,
1816 : : gchar **argv_buffer,
1817 : : gsize argv_buffer_len,
1818 : : gchar **envp)
1819 : : {
1820 : : /* Count the arguments. */
1821 : 0 : gsize argc = 0;
1822 : 0 : while (argv[argc])
1823 : 0 : ++argc;
1824 : :
1825 : : /* Construct an argument list for the shell. */
1826 : 0 : if (argc + 2 > argv_buffer_len)
1827 : 0 : return FALSE;
1828 : :
1829 : 0 : argv_buffer[0] = (char *) "/bin/sh";
1830 : 0 : argv_buffer[1] = (char *) file;
1831 : 0 : while (argc > 0)
1832 : : {
1833 : 0 : argv_buffer[argc + 1] = argv[argc];
1834 : 0 : --argc;
1835 : : }
1836 : :
1837 : : /* Execute the shell. */
1838 : 0 : if (envp)
1839 : 0 : execve (argv_buffer[0], argv_buffer, envp);
1840 : : else
1841 : 0 : execv (argv_buffer[0], argv_buffer);
1842 : :
1843 : 0 : return TRUE;
1844 : : }
1845 : :
1846 : : /* This function is called between fork() and exec() and hence must be
1847 : : * async-signal-safe (see signal-safety(7)). */
1848 : : static gchar*
1849 : 173 : my_strchrnul (const gchar *str, gchar c)
1850 : : {
1851 : 173 : gchar *p = (gchar*) str;
1852 : 5767 : while (*p && (*p != c))
1853 : 5594 : ++p;
1854 : :
1855 : 173 : return p;
1856 : : }
1857 : :
1858 : : /* This function is called between fork() and exec() and hence must be
1859 : : * async-signal-safe (see signal-safety(7)) until it calls exec(). */
1860 : : static gint
1861 : 1004 : g_execute (const gchar *file,
1862 : : gchar **argv,
1863 : : gchar **argv_buffer,
1864 : : gsize argv_buffer_len,
1865 : : gchar **envp,
1866 : : const gchar *search_path,
1867 : : gchar *search_path_buffer,
1868 : : gsize search_path_buffer_len)
1869 : : {
1870 : 1004 : if (file == NULL || *file == '\0')
1871 : : {
1872 : : /* We check the simple case first. */
1873 : 0 : errno = ENOENT;
1874 : 0 : return -1;
1875 : : }
1876 : :
1877 : 1004 : if (search_path == NULL || strchr (file, '/') != NULL)
1878 : : {
1879 : : /* Don't search when it contains a slash. */
1880 : 922 : if (envp)
1881 : 263 : execve (file, argv, envp);
1882 : : else
1883 : 659 : execv (file, argv);
1884 : :
1885 : 922 : if (errno == ENOEXEC &&
1886 : 0 : !script_execute (file, argv, argv_buffer, argv_buffer_len, envp))
1887 : : {
1888 : 0 : errno = ENOMEM;
1889 : 0 : return -1;
1890 : : }
1891 : : }
1892 : : else
1893 : : {
1894 : 82 : gboolean got_eacces = 0;
1895 : : const gchar *path, *p;
1896 : : gchar *name;
1897 : : gsize len;
1898 : : gsize pathlen;
1899 : :
1900 : 82 : path = search_path;
1901 : 82 : len = strlen (file) + 1;
1902 : 82 : pathlen = strlen (path);
1903 : 82 : name = search_path_buffer;
1904 : :
1905 : 82 : if (search_path_buffer_len < pathlen + len + 1)
1906 : : {
1907 : 0 : errno = ENOMEM;
1908 : 0 : return -1;
1909 : : }
1910 : :
1911 : : /* Copy the file name at the top, including '\0' */
1912 : 82 : memcpy (name + pathlen + 1, file, len);
1913 : 82 : name = name + pathlen;
1914 : : /* And add the slash before the filename */
1915 : 82 : *name = '/';
1916 : :
1917 : 82 : p = path;
1918 : : do
1919 : : {
1920 : : char *startp;
1921 : :
1922 : 255 : path = p;
1923 : 255 : p = my_strchrnul (path, ':');
1924 : :
1925 : 173 : if (p == path)
1926 : : /* Two adjacent colons, or a colon at the beginning or the end
1927 : : * of 'PATH' means to search the current directory.
1928 : : */
1929 : 0 : startp = name + 1;
1930 : : else
1931 : 173 : startp = memcpy (name - (p - path), path, p - path);
1932 : :
1933 : : /* Try to execute this name. If it works, execv will not return. */
1934 : 173 : if (envp)
1935 : 15 : execve (startp, argv, envp);
1936 : : else
1937 : 158 : execv (startp, argv);
1938 : :
1939 : 173 : if (errno == ENOEXEC &&
1940 : 0 : !script_execute (startp, argv, argv_buffer, argv_buffer_len, envp))
1941 : : {
1942 : 0 : errno = ENOMEM;
1943 : 0 : return -1;
1944 : : }
1945 : :
1946 : 173 : switch (errno)
1947 : : {
1948 : 0 : case EACCES:
1949 : : /* Record the we got a 'Permission denied' error. If we end
1950 : : * up finding no executable we can use, we want to diagnose
1951 : : * that we did find one but were denied access.
1952 : : */
1953 : 0 : got_eacces = TRUE;
1954 : :
1955 : : G_GNUC_FALLTHROUGH;
1956 : 173 : case ENOENT:
1957 : : #ifdef ESTALE
1958 : : case ESTALE:
1959 : : #endif
1960 : : #ifdef ENOTDIR
1961 : : case ENOTDIR:
1962 : : #endif
1963 : : /* Those errors indicate the file is missing or not executable
1964 : : * by us, in which case we want to just try the next path
1965 : : * directory.
1966 : : */
1967 : 173 : break;
1968 : :
1969 : 0 : case ENODEV:
1970 : : case ETIMEDOUT:
1971 : : /* Some strange filesystems like AFS return even
1972 : : * stranger error numbers. They cannot reasonably mean anything
1973 : : * else so ignore those, too.
1974 : : */
1975 : 0 : break;
1976 : :
1977 : 0 : default:
1978 : : /* Some other error means we found an executable file, but
1979 : : * something went wrong executing it; return the error to our
1980 : : * caller.
1981 : : */
1982 : 0 : return -1;
1983 : : }
1984 : : }
1985 : 173 : while (*p++ != '\0');
1986 : :
1987 : : /* We tried every element and none of them worked. */
1988 : 0 : if (got_eacces)
1989 : : /* At least one failure was due to permissions, so report that
1990 : : * error.
1991 : : */
1992 : 0 : errno = EACCES;
1993 : : }
1994 : :
1995 : : /* Return the error from the last attempt (probably ENOENT). */
1996 : 922 : return -1;
1997 : : }
1998 : :
1999 : : void
2000 : 194 : g_spawn_close_pid_impl (GPid pid)
2001 : : {
2002 : : /* no-op */
2003 : 194 : }
|