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