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 : 708 : read_data (GString *str,
163 : : gint fd,
164 : : GError **error)
165 : : {
166 : : gssize bytes;
167 : : gchar buf[4096];
168 : :
169 : 708 : again:
170 : 708 : bytes = read (fd, buf, 4096);
171 : :
172 : 708 : if (bytes == 0)
173 : 318 : return READ_EOF;
174 : 390 : else if (bytes > 0)
175 : : {
176 : : g_string_append_len (str, buf, bytes);
177 : 390 : 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 : 322 : 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 : 322 : gint outpipe = -1;
208 : 322 : gint errpipe = -1;
209 : : GPid pid;
210 : : gint ret;
211 : 322 : GString *outstr = NULL;
212 : 322 : GString *errstr = NULL;
213 : : gboolean failed;
214 : : gint status;
215 : :
216 : 322 : g_return_val_if_fail (argv != NULL, FALSE);
217 : 322 : g_return_val_if_fail (argv[0] != NULL, FALSE);
218 : 322 : g_return_val_if_fail (!(flags & G_SPAWN_DO_NOT_REAP_CHILD), FALSE);
219 : 322 : g_return_val_if_fail (standard_output == NULL ||
220 : : !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
221 : 322 : 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 : 322 : if (standard_output)
228 : 243 : *standard_output = NULL;
229 : :
230 : 322 : if (standard_error)
231 : 76 : *standard_error = NULL;
232 : :
233 : 644 : if (!fork_exec (FALSE,
234 : : working_directory,
235 : : (const gchar * const *) argv,
236 : : (const gchar * const *) envp,
237 : 322 : !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
238 : 322 : (flags & G_SPAWN_SEARCH_PATH) != 0,
239 : 322 : (flags & G_SPAWN_SEARCH_PATH_FROM_ENVP) != 0,
240 : 322 : (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
241 : 322 : (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
242 : 322 : (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
243 : 322 : (flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0,
244 : 322 : (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 : 316 : failed = FALSE;
259 : :
260 : 316 : if (outpipe >= 0)
261 : : {
262 : 242 : outstr = g_string_new (NULL);
263 : : }
264 : :
265 : 316 : if (errpipe >= 0)
266 : : {
267 : 76 : errstr = g_string_new (NULL);
268 : : }
269 : :
270 : : /* Read data until we get EOF on both pipes. */
271 : 952 : while (!failed &&
272 : 952 : (outpipe >= 0 ||
273 : 334 : 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 : 636 : 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 : 636 : ret = g_poll (fds, G_N_ELEMENTS (fds), -1 /* no timeout */);
285 : :
286 : 636 : 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 : 636 : if (outpipe >= 0 && fds[0].revents != 0)
305 : : {
306 : 608 : switch (read_data (outstr, outpipe, error))
307 : : {
308 : 0 : case READ_FAILED:
309 : 0 : failed = TRUE;
310 : 0 : break;
311 : 242 : case READ_EOF:
312 : 242 : g_clear_fd (&outpipe, NULL);
313 : 242 : break;
314 : 366 : default:
315 : 366 : break;
316 : : }
317 : :
318 : 608 : if (failed)
319 : 0 : break;
320 : : }
321 : :
322 : 636 : 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 : 316 : g_clear_fd (&outpipe, NULL);
343 : 316 : g_clear_fd (&errpipe, NULL);
344 : :
345 : : /* Wait for child to exit, even if we have
346 : : * an error pending.
347 : : */
348 : 316 : again:
349 : :
350 : 316 : ret = waitpid (pid, &status, 0);
351 : :
352 : 316 : 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 : 316 : 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 : 316 : if (wait_status)
396 : 280 : *wait_status = status;
397 : :
398 : 316 : if (standard_output)
399 : 242 : *standard_output = g_string_free (outstr, FALSE);
400 : :
401 : 316 : if (standard_error)
402 : 76 : *standard_error = g_string_free (errstr, FALSE);
403 : :
404 : 316 : return TRUE;
405 : : }
406 : : }
407 : :
408 : : gboolean
409 : 772 : 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 : 772 : g_return_val_if_fail (argv != NULL, FALSE);
428 : 772 : g_return_val_if_fail (argv[0] != NULL, FALSE);
429 : : /* can’t both inherit and set pipes to /dev/null */
430 : 772 : g_return_val_if_fail ((flags & INHERITS_OR_NULL_STDIN) != INHERITS_OR_NULL_STDIN, FALSE);
431 : 772 : g_return_val_if_fail ((flags & INHERITS_OR_NULL_STDOUT) != INHERITS_OR_NULL_STDOUT, FALSE);
432 : 772 : 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 : 772 : g_return_val_if_fail (stdin_pipe_out == NULL || stdin_fd < 0, FALSE);
435 : 772 : g_return_val_if_fail (stdout_pipe_out == NULL || stdout_fd < 0, FALSE);
436 : 772 : g_return_val_if_fail (stderr_pipe_out == NULL || stderr_fd < 0, FALSE);
437 : :
438 : 772 : if ((flags & INHERITS_OR_NULL_STDIN) != 0)
439 : 4 : stdin_pipe_out = NULL;
440 : 772 : if ((flags & INHERITS_OR_NULL_STDOUT) != 0)
441 : 34 : stdout_pipe_out = NULL;
442 : 772 : if ((flags & INHERITS_OR_NULL_STDERR) != 0)
443 : 25 : stderr_pipe_out = NULL;
444 : :
445 : 772 : return fork_exec (!(flags & G_SPAWN_DO_NOT_REAP_CHILD),
446 : : working_directory,
447 : : (const gchar * const *) argv,
448 : : (const gchar * const *) envp,
449 : 772 : !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
450 : 772 : (flags & G_SPAWN_SEARCH_PATH) != 0,
451 : 772 : (flags & G_SPAWN_SEARCH_PATH_FROM_ENVP) != 0,
452 : 772 : (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
453 : 772 : (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
454 : 772 : (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
455 : 772 : (flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0,
456 : 772 : (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 : 199 : g_spawn_check_wait_status_impl (gint wait_status,
474 : : GError **error)
475 : : {
476 : 199 : gboolean ret = FALSE;
477 : :
478 : 199 : if (WIFEXITED (wait_status))
479 : : {
480 : 193 : 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 : 148 : ret = TRUE;
510 : 199 : out:
511 : 199 : 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 : 2255 : set_cloexec (int fd)
559 : : {
560 : 2255 : fcntl (fd, F_SETFD, FD_CLOEXEC);
561 : 2255 : }
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 : 111 : dupfd_cloexec (int old_fd, int new_fd_min)
590 : : {
591 : : int fd, errsv;
592 : : #ifdef F_DUPFD_CLOEXEC
593 : : do
594 : : {
595 : 111 : fd = fcntl (old_fd, F_DUPFD_CLOEXEC, new_fd_min);
596 : 111 : errsv = errno;
597 : : }
598 : 111 : 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 : 111 : 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 : 3424 : safe_dup2 (gint fd1, gint fd2)
629 : : {
630 : : gint ret;
631 : :
632 : : do
633 : 3424 : ret = dup2 (fd1, fd2);
634 : 3424 : while (ret < 0 && (errno == EINTR || errno == EBUSY));
635 : :
636 : 3424 : 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 : 1253 : safe_open (const char *path, gint mode)
667 : : {
668 : : gint ret;
669 : :
670 : : do
671 : 1253 : ret = open (path, mode);
672 : 1253 : while (ret < 0 && errno == EINTR);
673 : :
674 : 1253 : 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 : 998 : 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 : 998 : gint max_target_fd = 0;
717 : :
718 : 998 : 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 : 998 : 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 : 998 : 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 : 938 : else if (!child_inherits_stdin)
759 : : {
760 : : /* Keep process from blocking on a read of stdin */
761 : 934 : gint read_null = safe_open ("/dev/null", O_RDONLY);
762 : 934 : if (read_null < 0)
763 : 0 : write_err_and_exit (child_err_report_fd,
764 : : CHILD_OPEN_FAILED);
765 : 934 : if (safe_dup2 (read_null, 0) < 0)
766 : 0 : write_err_and_exit (child_err_report_fd,
767 : : CHILD_DUPFD_FAILED);
768 : 934 : 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 : 998 : 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 : 998 : if (IS_VALID_FILENO (stdout_fd) && stdout_fd != STDOUT_FILENO)
789 : : {
790 : 724 : if (safe_dup2 (stdout_fd, 1) < 0)
791 : 0 : write_err_and_exit (child_err_report_fd,
792 : : CHILD_DUPFD_FAILED);
793 : :
794 : 724 : set_cloexec (stdout_fd);
795 : : }
796 : 274 : 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 : 998 : 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 : 998 : if (IS_VALID_FILENO (stderr_fd) && stderr_fd != STDERR_FILENO)
821 : : {
822 : 481 : if (safe_dup2 (stderr_fd, 2) < 0)
823 : 0 : write_err_and_exit (child_err_report_fd,
824 : : CHILD_DUPFD_FAILED);
825 : :
826 : 481 : set_cloexec (stderr_fd);
827 : : }
828 : 517 : 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 : 998 : if (close_descriptors)
846 : : {
847 : 998 : if (child_setup == NULL && n_fds == 0)
848 : : {
849 : 990 : if (safe_dup2 (child_err_report_fd, 3) < 0)
850 : 0 : write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
851 : 990 : set_cloexec (3);
852 : 990 : if (g_closefrom (4) < 0)
853 : 0 : write_err_and_exit (child_err_report_fd, CHILD_CLOSE_FAILED);
854 : 990 : 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 : 998 : 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 : int new_child_err_report_fd = dupfd_cloexec (child_err_report_fd, max_target_fd + 1);
921 : 2 : if (new_child_err_report_fd < 0)
922 : 0 : write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
923 : 2 : child_err_report_fd = new_child_err_report_fd;
924 : : }
925 : :
926 : 36 : if (target_fds[i] < 0 ||
927 : 18 : safe_dup2 (source_fds[i], target_fds[i]) < 0)
928 : 0 : write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
929 : :
930 : 18 : g_clear_fd (&source_fds[i], NULL);
931 : : }
932 : : }
933 : : }
934 : :
935 : : /* Call user function just before we exec */
936 : 998 : if (child_setup)
937 : : {
938 : 5 : (* child_setup) (user_data);
939 : : }
940 : :
941 : 998 : g_execute (argv[0],
942 : : (gchar **) (file_and_argv_zero ? argv + 1 : argv),
943 : : argv_buffer, argv_buffer_len,
944 : : (gchar **) envp, search_path, search_path_buffer, search_path_buffer_len);
945 : :
946 : : /* Exec failed */
947 : 0 : write_err_and_exit (child_err_report_fd,
948 : : CHILD_EXEC_FAILED);
949 : : }
950 : :
951 : : static gboolean
952 : 1107 : read_ints (int fd,
953 : : gint* buf,
954 : : gint n_ints_in_buf,
955 : : gint *n_ints_read,
956 : : GError **error)
957 : : {
958 : 1107 : gsize bytes = 0;
959 : :
960 : : while (TRUE)
961 : 118 : {
962 : : gssize chunk;
963 : :
964 : 1225 : if (bytes >= sizeof(gint)*2)
965 : 10 : break; /* give up, who knows what happened, should not be
966 : : * possible.
967 : : */
968 : :
969 : 1215 : again:
970 : 1215 : chunk = read (fd,
971 : : ((gchar*)buf) + bytes,
972 : 1215 : sizeof(gint) * n_ints_in_buf - bytes);
973 : 1215 : if (chunk < 0 && errno == EINTR)
974 : 0 : goto again;
975 : :
976 : 1215 : if (chunk < 0)
977 : : {
978 : 0 : int errsv = errno;
979 : :
980 : : /* Some weird shit happened, bail out */
981 : 0 : g_set_error (error,
982 : : G_SPAWN_ERROR,
983 : : G_SPAWN_ERROR_FAILED,
984 : : _("Failed to read from child pipe (%s)"),
985 : : g_strerror (errsv));
986 : :
987 : 0 : return FALSE;
988 : : }
989 : 1215 : else if (chunk == 0)
990 : 1097 : break; /* EOF */
991 : : else /* chunk > 0 */
992 : 118 : bytes += chunk;
993 : : }
994 : :
995 : 1107 : *n_ints_read = (gint)(bytes / sizeof(gint));
996 : :
997 : 1107 : return TRUE;
998 : : }
999 : :
1000 : : #ifdef POSIX_SPAWN_AVAILABLE
1001 : : static gboolean
1002 : 94 : do_posix_spawn (const gchar * const *argv,
1003 : : const gchar * const *envp,
1004 : : gboolean search_path,
1005 : : gboolean stdout_to_null,
1006 : : gboolean stderr_to_null,
1007 : : gboolean child_inherits_stdin,
1008 : : gboolean file_and_argv_zero,
1009 : : GPid *child_pid,
1010 : : gint *child_close_fds,
1011 : : gint stdin_fd,
1012 : : gint stdout_fd,
1013 : : gint stderr_fd,
1014 : : const gint *source_fds,
1015 : : const gint *target_fds,
1016 : : gsize n_fds)
1017 : : {
1018 : : pid_t pid;
1019 : 94 : gint *duped_source_fds = NULL;
1020 : 94 : gint max_target_fd = 0;
1021 : : const gchar * const *argv_pass;
1022 : : posix_spawnattr_t attr;
1023 : : posix_spawn_file_actions_t file_actions;
1024 : : gint parent_close_fds[3];
1025 : 94 : gsize num_parent_close_fds = 0;
1026 : 94 : GSList *child_close = NULL;
1027 : : GSList *elem;
1028 : : sigset_t mask;
1029 : : gsize i;
1030 : : int r;
1031 : :
1032 : 94 : g_assert (argv != NULL && argv[0] != NULL);
1033 : :
1034 : 94 : if (*argv[0] == '\0')
1035 : : {
1036 : : /* We check the simple case first. */
1037 : 0 : return ENOENT;
1038 : : }
1039 : :
1040 : 94 : r = posix_spawnattr_init (&attr);
1041 : 94 : if (r != 0)
1042 : 0 : return r;
1043 : :
1044 : 94 : if (child_close_fds)
1045 : : {
1046 : 94 : int i = -1;
1047 : 95 : while (child_close_fds[++i] != -1)
1048 : 1 : child_close = g_slist_prepend (child_close,
1049 : 1 : GINT_TO_POINTER (child_close_fds[i]));
1050 : : }
1051 : :
1052 : 94 : r = posix_spawnattr_setflags (&attr, POSIX_SPAWN_SETSIGDEF);
1053 : 94 : if (r != 0)
1054 : 0 : goto out_free_spawnattr;
1055 : :
1056 : : /* Reset some signal handlers that we may use */
1057 : 94 : sigemptyset (&mask);
1058 : 94 : sigaddset (&mask, SIGCHLD);
1059 : 94 : sigaddset (&mask, SIGINT);
1060 : 94 : sigaddset (&mask, SIGTERM);
1061 : 94 : sigaddset (&mask, SIGHUP);
1062 : :
1063 : 94 : r = posix_spawnattr_setsigdefault (&attr, &mask);
1064 : 94 : if (r != 0)
1065 : 0 : goto out_free_spawnattr;
1066 : :
1067 : 94 : r = posix_spawn_file_actions_init (&file_actions);
1068 : 94 : if (r != 0)
1069 : 0 : goto out_free_spawnattr;
1070 : :
1071 : : /* Redirect pipes as required */
1072 : :
1073 : 94 : if (stdin_fd >= 0)
1074 : : {
1075 : 0 : r = posix_spawn_file_actions_adddup2 (&file_actions, stdin_fd, 0);
1076 : 0 : if (r != 0)
1077 : 0 : goto out_close_fds;
1078 : :
1079 : 0 : if (!g_slist_find (child_close, GINT_TO_POINTER (stdin_fd)))
1080 : 0 : child_close = g_slist_prepend (child_close, GINT_TO_POINTER (stdin_fd));
1081 : : }
1082 : 94 : else if (!child_inherits_stdin)
1083 : : {
1084 : : /* Keep process from blocking on a read of stdin */
1085 : 94 : gint read_null = safe_open ("/dev/null", O_RDONLY | O_CLOEXEC);
1086 : 94 : g_assert (read_null != -1);
1087 : 94 : parent_close_fds[num_parent_close_fds++] = read_null;
1088 : :
1089 : : #ifndef HAVE_O_CLOEXEC
1090 : : fcntl (read_null, F_SETFD, FD_CLOEXEC);
1091 : : #endif
1092 : :
1093 : 94 : r = posix_spawn_file_actions_adddup2 (&file_actions, read_null, 0);
1094 : 94 : if (r != 0)
1095 : 0 : goto out_close_fds;
1096 : : }
1097 : :
1098 : 94 : if (stdout_fd >= 0)
1099 : : {
1100 : 1 : r = posix_spawn_file_actions_adddup2 (&file_actions, stdout_fd, 1);
1101 : 1 : if (r != 0)
1102 : 0 : goto out_close_fds;
1103 : :
1104 : 1 : if (!g_slist_find (child_close, GINT_TO_POINTER (stdout_fd)))
1105 : 1 : child_close = g_slist_prepend (child_close, GINT_TO_POINTER (stdout_fd));
1106 : : }
1107 : 93 : else if (stdout_to_null)
1108 : : {
1109 : 4 : gint write_null = safe_open ("/dev/null", O_WRONLY | O_CLOEXEC);
1110 : 4 : g_assert (write_null != -1);
1111 : 4 : parent_close_fds[num_parent_close_fds++] = write_null;
1112 : :
1113 : : #ifndef HAVE_O_CLOEXEC
1114 : : fcntl (write_null, F_SETFD, FD_CLOEXEC);
1115 : : #endif
1116 : :
1117 : 4 : r = posix_spawn_file_actions_adddup2 (&file_actions, write_null, 1);
1118 : 4 : if (r != 0)
1119 : 0 : goto out_close_fds;
1120 : : }
1121 : :
1122 : 94 : if (stderr_fd >= 0)
1123 : : {
1124 : 0 : r = posix_spawn_file_actions_adddup2 (&file_actions, stderr_fd, 2);
1125 : 0 : if (r != 0)
1126 : 0 : goto out_close_fds;
1127 : :
1128 : 0 : if (!g_slist_find (child_close, GINT_TO_POINTER (stderr_fd)))
1129 : 0 : child_close = g_slist_prepend (child_close, GINT_TO_POINTER (stderr_fd));
1130 : : }
1131 : 94 : else if (stderr_to_null)
1132 : : {
1133 : 4 : gint write_null = safe_open ("/dev/null", O_WRONLY | O_CLOEXEC);
1134 : 4 : g_assert (write_null != -1);
1135 : 4 : parent_close_fds[num_parent_close_fds++] = write_null;
1136 : :
1137 : : #ifndef HAVE_O_CLOEXEC
1138 : : fcntl (write_null, F_SETFD, FD_CLOEXEC);
1139 : : #endif
1140 : :
1141 : 4 : r = posix_spawn_file_actions_adddup2 (&file_actions, write_null, 2);
1142 : 4 : if (r != 0)
1143 : 0 : goto out_close_fds;
1144 : : }
1145 : :
1146 : : /* If source_fds[i] != target_fds[i], we need to handle the case
1147 : : * where the user has specified, e.g., 5 -> 4, 4 -> 6. We do this
1148 : : * by duping the source fds, taking care to ensure the new fds are
1149 : : * larger than any target fd to avoid introducing new conflicts.
1150 : : *
1151 : : * If source_fds[i] == target_fds[i], then we just need to leak
1152 : : * the fd into the child process, which we *could* do by temporarily
1153 : : * unsetting CLOEXEC and then setting it again after we spawn if
1154 : : * it was originally set. POSIX requires that the addup2 action unset
1155 : : * CLOEXEC if source and target are identical, so you'd think doing it
1156 : : * manually wouldn't be needed, but unfortunately as of 2021 many
1157 : : * libcs still don't do so. Example nonconforming libcs:
1158 : : * Bionic: https://android.googlesource.com/platform/bionic/+/f6e5b582604715729b09db3e36a7aeb8c24b36a4/libc/bionic/spawn.cpp#71
1159 : : * uclibc-ng: https://cgit.uclibc-ng.org/cgi/cgit/uclibc-ng.git/tree/librt/spawn.c?id=7c36bcae09d66bbaa35cbb02253ae0556f42677e#n88
1160 : : *
1161 : : * Anyway, unsetting CLOEXEC ourselves would open a small race window
1162 : : * where the fd could be inherited into a child process if another
1163 : : * thread spawns something at the same time, because we have not
1164 : : * called fork() and are multithreaded here. This race is avoidable by
1165 : : * using dupfd_cloexec, which we already have to do to handle the
1166 : : * source_fds[i] != target_fds[i] case. So let's always do it!
1167 : : */
1168 : :
1169 : 185 : for (i = 0; i < n_fds; i++)
1170 : 91 : max_target_fd = MAX (max_target_fd, target_fds[i]);
1171 : :
1172 : 94 : if (max_target_fd == G_MAXINT)
1173 : 0 : goto out_close_fds;
1174 : :
1175 : 94 : duped_source_fds = g_new (gint, n_fds);
1176 : 185 : for (i = 0; i < n_fds; i++)
1177 : 91 : duped_source_fds[i] = -1; /* initialise in case dupfd_cloexec() fails below */
1178 : 185 : for (i = 0; i < n_fds; i++)
1179 : : {
1180 : 91 : duped_source_fds[i] = dupfd_cloexec (source_fds[i], max_target_fd + 1);
1181 : 91 : if (duped_source_fds[i] < 0)
1182 : 0 : goto out_close_fds;
1183 : : }
1184 : :
1185 : 185 : for (i = 0; i < n_fds; i++)
1186 : : {
1187 : 91 : r = posix_spawn_file_actions_adddup2 (&file_actions, duped_source_fds[i], target_fds[i]);
1188 : 91 : if (r != 0)
1189 : 0 : goto out_close_fds;
1190 : : }
1191 : :
1192 : : /* Intentionally close the fds in the child as the last file action,
1193 : : * having been careful not to add the same fd to this list twice.
1194 : : *
1195 : : * This is important to allow (e.g.) for the same fd to be passed as stdout
1196 : : * and stderr (we must not close it before we have dupped it in both places,
1197 : : * and we must not attempt to close it twice).
1198 : : */
1199 : 96 : for (elem = child_close; elem != NULL; elem = elem->next)
1200 : : {
1201 : 2 : r = posix_spawn_file_actions_addclose (&file_actions,
1202 : 2 : GPOINTER_TO_INT (elem->data));
1203 : 2 : if (r != 0)
1204 : 0 : goto out_close_fds;
1205 : : }
1206 : :
1207 : 94 : argv_pass = file_and_argv_zero ? argv + 1 : argv;
1208 : 94 : if (envp == NULL)
1209 : 92 : envp = (const gchar * const *) environ;
1210 : :
1211 : : /* Don't search when it contains a slash. */
1212 : 94 : if (!search_path || strchr (argv[0], '/') != NULL)
1213 : 7 : r = posix_spawn (&pid, argv[0], &file_actions, &attr, (char * const *) argv_pass, (char * const *) envp);
1214 : : else
1215 : 87 : r = posix_spawnp (&pid, argv[0], &file_actions, &attr, (char * const *) argv_pass, (char * const *) envp);
1216 : :
1217 : 94 : if (r == 0 && child_pid != NULL)
1218 : 94 : *child_pid = pid;
1219 : :
1220 : 0 : out_close_fds:
1221 : 196 : for (i = 0; i < num_parent_close_fds; i++)
1222 : 102 : g_clear_fd (&parent_close_fds[i], NULL);
1223 : :
1224 : 94 : if (duped_source_fds != NULL)
1225 : : {
1226 : 180 : for (i = 0; i < n_fds; i++)
1227 : 91 : g_clear_fd (&duped_source_fds[i], NULL);
1228 : 89 : g_free (duped_source_fds);
1229 : : }
1230 : :
1231 : 94 : posix_spawn_file_actions_destroy (&file_actions);
1232 : 94 : out_free_spawnattr:
1233 : 94 : posix_spawnattr_destroy (&attr);
1234 : 94 : g_slist_free (child_close);
1235 : :
1236 : 94 : return r;
1237 : : }
1238 : : #endif /* POSIX_SPAWN_AVAILABLE */
1239 : :
1240 : : static gboolean
1241 : 2365 : source_fds_collide_with_pipe (const GUnixPipe *pipefd,
1242 : : const int *source_fds,
1243 : : gsize n_fds,
1244 : : GError **error)
1245 : : {
1246 : 4729 : return (_g_spawn_invalid_source_fd (pipefd->fds[G_UNIX_PIPE_END_READ], source_fds, n_fds, error) ||
1247 : 2364 : _g_spawn_invalid_source_fd (pipefd->fds[G_UNIX_PIPE_END_WRITE], source_fds, n_fds, error));
1248 : : }
1249 : :
1250 : : static gboolean
1251 : 1094 : fork_exec (gboolean intermediate_child,
1252 : : const gchar *working_directory,
1253 : : const gchar * const *argv,
1254 : : const gchar * const *envp,
1255 : : gboolean close_descriptors,
1256 : : gboolean search_path,
1257 : : gboolean search_path_from_envp,
1258 : : gboolean stdout_to_null,
1259 : : gboolean stderr_to_null,
1260 : : gboolean child_inherits_stdin,
1261 : : gboolean file_and_argv_zero,
1262 : : gboolean cloexec_pipes,
1263 : : GSpawnChildSetupFunc child_setup,
1264 : : gpointer user_data,
1265 : : GPid *child_pid,
1266 : : gint *stdin_pipe_out,
1267 : : gint *stdout_pipe_out,
1268 : : gint *stderr_pipe_out,
1269 : : gint stdin_fd,
1270 : : gint stdout_fd,
1271 : : gint stderr_fd,
1272 : : const gint *source_fds,
1273 : : const gint *target_fds,
1274 : : gsize n_fds,
1275 : : GError **error)
1276 : : {
1277 : 1094 : GPid pid = -1;
1278 : 1094 : GUnixPipe child_err_report_pipe = G_UNIX_PIPE_INIT;
1279 : 1094 : GUnixPipe child_pid_report_pipe = G_UNIX_PIPE_INIT;
1280 : 1094 : guint pipe_flags = cloexec_pipes ? O_CLOEXEC : 0;
1281 : : gint status;
1282 : : const gchar *chosen_search_path;
1283 : 1094 : gchar *search_path_buffer = NULL;
1284 : 1094 : gchar *search_path_buffer_heap = NULL;
1285 : 1094 : gsize search_path_buffer_len = 0;
1286 : 1094 : gchar **argv_buffer = NULL;
1287 : 1094 : gchar **argv_buffer_heap = NULL;
1288 : 1094 : gsize argv_buffer_len = 0;
1289 : 1094 : GUnixPipe stdin_pipe = G_UNIX_PIPE_INIT;
1290 : 1094 : GUnixPipe stdout_pipe = G_UNIX_PIPE_INIT;
1291 : 1094 : GUnixPipe stderr_pipe = G_UNIX_PIPE_INIT;
1292 : 1094 : gint child_close_fds[4] = { -1, -1, -1, -1 };
1293 : 1094 : gint n_child_close_fds = 0;
1294 : 1094 : gint *source_fds_copy = NULL;
1295 : :
1296 : 1094 : g_assert (argv != NULL && argv[0] != NULL);
1297 : 1094 : g_assert (stdin_pipe_out == NULL || stdin_fd < 0);
1298 : 1094 : g_assert (stdout_pipe_out == NULL || stdout_fd < 0);
1299 : 1094 : g_assert (stderr_pipe_out == NULL || stderr_fd < 0);
1300 : :
1301 : : /* If pipes have been requested, open them */
1302 : 1094 : if (stdin_pipe_out != NULL)
1303 : : {
1304 : 59 : if (!g_unix_pipe_open (&stdin_pipe, pipe_flags, error))
1305 : 0 : goto cleanup_and_fail;
1306 : 59 : if (source_fds_collide_with_pipe (&stdin_pipe, source_fds, n_fds, error))
1307 : 0 : goto cleanup_and_fail;
1308 : 59 : child_close_fds[n_child_close_fds++] = g_unix_pipe_get (&stdin_pipe, G_UNIX_PIPE_END_WRITE);
1309 : 59 : stdin_fd = g_unix_pipe_get (&stdin_pipe, G_UNIX_PIPE_END_READ);
1310 : : }
1311 : :
1312 : 1094 : if (stdout_pipe_out != NULL)
1313 : : {
1314 : 725 : if (!g_unix_pipe_open (&stdout_pipe, pipe_flags, error))
1315 : 0 : goto cleanup_and_fail;
1316 : 725 : if (source_fds_collide_with_pipe (&stdout_pipe, source_fds, n_fds, error))
1317 : 0 : goto cleanup_and_fail;
1318 : 725 : child_close_fds[n_child_close_fds++] = g_unix_pipe_get (&stdout_pipe, G_UNIX_PIPE_END_READ);
1319 : 725 : stdout_fd = g_unix_pipe_get (&stdout_pipe, G_UNIX_PIPE_END_WRITE);
1320 : : }
1321 : :
1322 : 1094 : if (stderr_pipe_out != NULL)
1323 : : {
1324 : 471 : if (!g_unix_pipe_open (&stderr_pipe, pipe_flags, error))
1325 : 0 : goto cleanup_and_fail;
1326 : 471 : if (source_fds_collide_with_pipe (&stderr_pipe, source_fds, n_fds, error))
1327 : 0 : goto cleanup_and_fail;
1328 : 471 : child_close_fds[n_child_close_fds++] = g_unix_pipe_get (&stderr_pipe, G_UNIX_PIPE_END_READ);
1329 : 471 : stderr_fd = g_unix_pipe_get (&stderr_pipe, G_UNIX_PIPE_END_WRITE);
1330 : : }
1331 : :
1332 : 1094 : child_close_fds[n_child_close_fds++] = -1;
1333 : :
1334 : : #ifdef POSIX_SPAWN_AVAILABLE
1335 : 1094 : if (!intermediate_child && working_directory == NULL && !close_descriptors &&
1336 : 94 : !search_path_from_envp && child_setup == NULL)
1337 : : {
1338 : 94 : g_trace_mark (G_TRACE_CURRENT_TIME, 0,
1339 : : "GLib", "posix_spawn",
1340 : : "%s", argv[0]);
1341 : :
1342 : 94 : status = do_posix_spawn (argv,
1343 : : envp,
1344 : : search_path,
1345 : : stdout_to_null,
1346 : : stderr_to_null,
1347 : : child_inherits_stdin,
1348 : : file_and_argv_zero,
1349 : : child_pid,
1350 : : child_close_fds,
1351 : : stdin_fd,
1352 : : stdout_fd,
1353 : : stderr_fd,
1354 : : source_fds,
1355 : : target_fds,
1356 : : n_fds);
1357 : 94 : if (status == 0)
1358 : 94 : goto success;
1359 : :
1360 : 0 : if (status != ENOEXEC)
1361 : : {
1362 : 0 : g_set_error (error,
1363 : : G_SPAWN_ERROR,
1364 : : G_SPAWN_ERROR_FAILED,
1365 : : _("Failed to spawn child process “%s” (%s)"),
1366 : : argv[0],
1367 : : g_strerror (status));
1368 : 0 : goto cleanup_and_fail;
1369 : : }
1370 : :
1371 : : /* posix_spawn is not intended to support script execution. It does in
1372 : : * some situations on some glibc versions, but that will be fixed.
1373 : : * So if it fails with ENOEXEC, we fall through to the regular
1374 : : * gspawn codepath so that script execution can be attempted,
1375 : : * per standard gspawn behaviour. */
1376 : 0 : g_debug ("posix_spawn failed (ENOEXEC), fall back to regular gspawn");
1377 : : }
1378 : : else
1379 : : {
1380 : 1000 : g_trace_mark (G_TRACE_CURRENT_TIME, 0,
1381 : : "GLib", "fork",
1382 : : "posix_spawn avoided %s%s%s%s%s",
1383 : : !intermediate_child ? "" : "(automatic reaping requested) ",
1384 : : working_directory == NULL ? "" : "(workdir specified) ",
1385 : : !close_descriptors ? "" : "(fd close requested) ",
1386 : : !search_path_from_envp ? "" : "(using envp for search path) ",
1387 : : child_setup == NULL ? "" : "(child_setup specified) ");
1388 : : }
1389 : : #endif /* POSIX_SPAWN_AVAILABLE */
1390 : :
1391 : : /* Choose a search path. This has to be done before calling fork()
1392 : : * as getenv() isn’t async-signal-safe (see `man 7 signal-safety`). */
1393 : 1000 : chosen_search_path = NULL;
1394 : 1000 : if (search_path_from_envp)
1395 : 36 : chosen_search_path = g_environ_getenv ((gchar **) envp, "PATH");
1396 : 1000 : if (search_path && chosen_search_path == NULL)
1397 : 240 : chosen_search_path = g_getenv ("PATH");
1398 : :
1399 : 1000 : if ((search_path || search_path_from_envp) && chosen_search_path == NULL)
1400 : : {
1401 : : /* There is no 'PATH' in the environment. The default
1402 : : * * search path in libc is the current directory followed by
1403 : : * * the path 'confstr' returns for '_CS_PATH'.
1404 : : * */
1405 : :
1406 : : /* In GLib we put . last, for security, and don't use the
1407 : : * * unportable confstr(); UNIX98 does not actually specify
1408 : : * * what to search if PATH is unset. POSIX may, dunno.
1409 : : * */
1410 : :
1411 : 2 : chosen_search_path = "/bin:/usr/bin:.";
1412 : : }
1413 : :
1414 : 1000 : if (search_path || search_path_from_envp)
1415 : 276 : g_assert (chosen_search_path != NULL);
1416 : : else
1417 : 724 : g_assert (chosen_search_path == NULL);
1418 : :
1419 : : /* Allocate a buffer which the fork()ed child can use to assemble potential
1420 : : * paths for the binary to exec(), combining the argv[0] and elements from
1421 : : * the chosen_search_path. This can’t be done in the child because malloc()
1422 : : * (or alloca()) are not async-signal-safe (see `man 7 signal-safety`).
1423 : : *
1424 : : * Add 2 for the nul terminator and a leading `/`. */
1425 : 1000 : if (chosen_search_path != NULL)
1426 : : {
1427 : 276 : search_path_buffer_len = strlen (chosen_search_path) + strlen (argv[0]) + 2;
1428 : 276 : if (search_path_buffer_len < 4000)
1429 : : {
1430 : : /* Prefer small stack allocations to avoid valgrind leak warnings
1431 : : * in forked child. The 4000B cutoff is arbitrary. */
1432 : 275 : search_path_buffer = g_alloca (search_path_buffer_len);
1433 : : }
1434 : : else
1435 : : {
1436 : 1 : search_path_buffer_heap = g_malloc (search_path_buffer_len);
1437 : 1 : search_path_buffer = search_path_buffer_heap;
1438 : : }
1439 : : }
1440 : :
1441 : 1000 : if (search_path || search_path_from_envp)
1442 : 276 : g_assert (search_path_buffer != NULL);
1443 : : else
1444 : 724 : g_assert (search_path_buffer == NULL);
1445 : :
1446 : : /* And allocate a buffer which is 2 elements longer than @argv, so that if
1447 : : * script_execute() has to be called later on, it can build a wrapper argv
1448 : : * array in this buffer. */
1449 : 1000 : argv_buffer_len = g_strv_length ((gchar **) argv) + 2;
1450 : 1000 : if (argv_buffer_len < 4000 / sizeof (gchar *))
1451 : : {
1452 : : /* Prefer small stack allocations to avoid valgrind leak warnings
1453 : : * in forked child. The 4000B cutoff is arbitrary. */
1454 : 998 : argv_buffer = g_newa (gchar *, argv_buffer_len);
1455 : : }
1456 : : else
1457 : : {
1458 : 2 : argv_buffer_heap = g_new (gchar *, argv_buffer_len);
1459 : 2 : argv_buffer = argv_buffer_heap;
1460 : : }
1461 : :
1462 : : /* And one to hold a copy of @source_fds for later manipulation in do_exec(). */
1463 : 1000 : source_fds_copy = g_new (int, n_fds);
1464 : 1000 : if (n_fds > 0)
1465 : 7 : memcpy (source_fds_copy, source_fds, sizeof (*source_fds) * n_fds);
1466 : :
1467 : 1000 : if (!g_unix_pipe_open (&child_err_report_pipe, pipe_flags, error))
1468 : 0 : goto cleanup_and_fail;
1469 : 1000 : if (source_fds_collide_with_pipe (&child_err_report_pipe, source_fds, n_fds, error))
1470 : 1 : goto cleanup_and_fail;
1471 : :
1472 : 999 : if (intermediate_child)
1473 : : {
1474 : 110 : if (!g_unix_pipe_open (&child_pid_report_pipe, pipe_flags, error))
1475 : 0 : goto cleanup_and_fail;
1476 : 110 : if (source_fds_collide_with_pipe (&child_pid_report_pipe, source_fds, n_fds, error))
1477 : 0 : goto cleanup_and_fail;
1478 : : }
1479 : :
1480 : 999 : pid = fork ();
1481 : :
1482 : 1887 : if (pid < 0)
1483 : : {
1484 : 0 : int errsv = errno;
1485 : :
1486 : 0 : g_set_error (error,
1487 : : G_SPAWN_ERROR,
1488 : : G_SPAWN_ERROR_FORK,
1489 : : _("Failed to fork (%s)"),
1490 : : g_strerror (errsv));
1491 : :
1492 : 0 : goto cleanup_and_fail;
1493 : : }
1494 : 1887 : else if (pid == 0)
1495 : : {
1496 : : /* Immediate child. This may or may not be the child that
1497 : : * actually execs the new process.
1498 : : */
1499 : :
1500 : : /* Reset some signal handlers that we may use */
1501 : 888 : signal (SIGCHLD, SIG_DFL);
1502 : 888 : signal (SIGINT, SIG_DFL);
1503 : 888 : signal (SIGTERM, SIG_DFL);
1504 : 888 : signal (SIGHUP, SIG_DFL);
1505 : :
1506 : : /* Be sure we crash if the parent exits
1507 : : * and we write to the err_report_pipe
1508 : : */
1509 : 888 : signal (SIGPIPE, SIG_DFL);
1510 : :
1511 : : /* Close the parent's end of the pipes;
1512 : : * not needed in the close_descriptors case,
1513 : : * though
1514 : : */
1515 : 888 : g_unix_pipe_close (&child_err_report_pipe, G_UNIX_PIPE_END_READ, NULL);
1516 : 888 : g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_READ, NULL);
1517 : 888 : if (child_close_fds[0] != -1)
1518 : : {
1519 : 760 : int i = -1;
1520 : 2014 : while (child_close_fds[++i] != -1)
1521 : 1254 : g_clear_fd (&child_close_fds[i], NULL);
1522 : : }
1523 : :
1524 : 888 : if (intermediate_child)
1525 : : {
1526 : : /* We need to fork an intermediate child that launches the
1527 : : * final child. The purpose of the intermediate child
1528 : : * is to exit, so we can waitpid() it immediately.
1529 : : * Then the grandchild will not become a zombie.
1530 : : */
1531 : : GPid grandchild_pid;
1532 : :
1533 : 0 : grandchild_pid = fork ();
1534 : :
1535 : 110 : if (grandchild_pid < 0)
1536 : : {
1537 : : /* report -1 as child PID */
1538 : 0 : write_all (g_unix_pipe_get (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE),
1539 : : &grandchild_pid, sizeof(grandchild_pid));
1540 : :
1541 : 0 : write_err_and_exit (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE),
1542 : : CHILD_FORK_FAILED);
1543 : : }
1544 : 110 : else if (grandchild_pid == 0)
1545 : : {
1546 : 110 : g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1547 : 110 : do_exec (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE),
1548 : : stdin_fd,
1549 : : stdout_fd,
1550 : : stderr_fd,
1551 : : source_fds_copy,
1552 : : target_fds,
1553 : : n_fds,
1554 : : working_directory,
1555 : : argv,
1556 : : argv_buffer,
1557 : : argv_buffer_len,
1558 : : envp,
1559 : : close_descriptors,
1560 : : chosen_search_path,
1561 : : search_path_buffer,
1562 : : search_path_buffer_len,
1563 : : stdout_to_null,
1564 : : stderr_to_null,
1565 : : child_inherits_stdin,
1566 : : file_and_argv_zero,
1567 : : child_setup,
1568 : : user_data);
1569 : : }
1570 : : else
1571 : : {
1572 : 0 : write_all (g_unix_pipe_get (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE),
1573 : : &grandchild_pid, sizeof(grandchild_pid));
1574 : 0 : g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1575 : :
1576 : 0 : _exit (0);
1577 : : }
1578 : : }
1579 : : else
1580 : : {
1581 : : /* Just run the child.
1582 : : */
1583 : :
1584 : 888 : do_exec (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE),
1585 : : stdin_fd,
1586 : : stdout_fd,
1587 : : stderr_fd,
1588 : : source_fds_copy,
1589 : : target_fds,
1590 : : n_fds,
1591 : : working_directory,
1592 : : argv,
1593 : : argv_buffer,
1594 : : argv_buffer_len,
1595 : : envp,
1596 : : close_descriptors,
1597 : : chosen_search_path,
1598 : : search_path_buffer,
1599 : : search_path_buffer_len,
1600 : : stdout_to_null,
1601 : : stderr_to_null,
1602 : : child_inherits_stdin,
1603 : : file_and_argv_zero,
1604 : : child_setup,
1605 : : user_data);
1606 : : }
1607 : : }
1608 : : else
1609 : : {
1610 : : /* Parent */
1611 : :
1612 : : gint buf[2];
1613 : 999 : gint n_ints = 0;
1614 : :
1615 : : /* Close the uncared-about ends of the pipes */
1616 : 999 : g_unix_pipe_close (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1617 : 999 : g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1618 : :
1619 : : /* If we had an intermediate child, reap it */
1620 : 999 : if (intermediate_child)
1621 : : {
1622 : 110 : wait_again:
1623 : 110 : if (waitpid (pid, &status, 0) < 0)
1624 : : {
1625 : 0 : if (errno == EINTR)
1626 : 0 : goto wait_again;
1627 : 0 : else if (errno == ECHILD)
1628 : : ; /* do nothing, child already reaped */
1629 : : else
1630 : 0 : g_warning ("waitpid() should not fail in 'fork_exec'");
1631 : : }
1632 : : }
1633 : :
1634 : :
1635 : 999 : if (!read_ints (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_READ),
1636 : : buf, 2, &n_ints,
1637 : : error))
1638 : 10 : goto cleanup_and_fail;
1639 : :
1640 : 999 : if (n_ints >= 2)
1641 : : {
1642 : : /* Error from the child. */
1643 : :
1644 : 10 : switch (buf[0])
1645 : : {
1646 : 0 : case CHILD_CHDIR_FAILED:
1647 : 0 : g_set_error (error,
1648 : : G_SPAWN_ERROR,
1649 : : G_SPAWN_ERROR_CHDIR,
1650 : : _("Failed to change to directory “%s” (%s)"),
1651 : : working_directory,
1652 : : g_strerror (buf[1]));
1653 : :
1654 : 0 : break;
1655 : :
1656 : 9 : case CHILD_EXEC_FAILED:
1657 : 9 : g_set_error (error,
1658 : : G_SPAWN_ERROR,
1659 : : _g_spawn_exec_err_to_g_error (buf[1]),
1660 : : _("Failed to execute child process “%s” (%s)"),
1661 : : argv[0],
1662 : : g_strerror (buf[1]));
1663 : :
1664 : 9 : break;
1665 : :
1666 : 0 : case CHILD_OPEN_FAILED:
1667 : 0 : g_set_error (error,
1668 : : G_SPAWN_ERROR,
1669 : : G_SPAWN_ERROR_FAILED,
1670 : : _("Failed to open file to remap file descriptor (%s)"),
1671 : : g_strerror (buf[1]));
1672 : 0 : break;
1673 : :
1674 : 1 : case CHILD_DUPFD_FAILED:
1675 : 1 : g_set_error (error,
1676 : : G_SPAWN_ERROR,
1677 : : G_SPAWN_ERROR_FAILED,
1678 : : _("Failed to duplicate file descriptor for child process (%s)"),
1679 : : g_strerror (buf[1]));
1680 : :
1681 : 1 : break;
1682 : :
1683 : 0 : case CHILD_FORK_FAILED:
1684 : 0 : g_set_error (error,
1685 : : G_SPAWN_ERROR,
1686 : : G_SPAWN_ERROR_FORK,
1687 : : _("Failed to fork child process (%s)"),
1688 : : g_strerror (buf[1]));
1689 : 0 : break;
1690 : :
1691 : 0 : case CHILD_CLOSE_FAILED:
1692 : 0 : g_set_error (error,
1693 : : G_SPAWN_ERROR,
1694 : : G_SPAWN_ERROR_FAILED,
1695 : : _("Failed to close file descriptor for child process (%s)"),
1696 : : g_strerror (buf[1]));
1697 : 0 : break;
1698 : :
1699 : 0 : default:
1700 : 0 : g_set_error (error,
1701 : : G_SPAWN_ERROR,
1702 : : G_SPAWN_ERROR_FAILED,
1703 : : _("Unknown error executing child process “%s”"),
1704 : : argv[0]);
1705 : 0 : break;
1706 : : }
1707 : :
1708 : 10 : goto cleanup_and_fail;
1709 : : }
1710 : :
1711 : : /* Get child pid from intermediate child pipe. */
1712 : 989 : if (intermediate_child)
1713 : : {
1714 : 108 : n_ints = 0;
1715 : :
1716 : 108 : if (!read_ints (g_unix_pipe_get (&child_pid_report_pipe, G_UNIX_PIPE_END_READ),
1717 : : buf, 1, &n_ints, error))
1718 : 0 : goto cleanup_and_fail;
1719 : :
1720 : 108 : if (n_ints < 1)
1721 : : {
1722 : 0 : int errsv = errno;
1723 : :
1724 : 0 : g_set_error (error,
1725 : : G_SPAWN_ERROR,
1726 : : G_SPAWN_ERROR_FAILED,
1727 : : _("Failed to read enough data from child pid pipe (%s)"),
1728 : : g_strerror (errsv));
1729 : 0 : goto cleanup_and_fail;
1730 : : }
1731 : : else
1732 : : {
1733 : : /* we have the child pid */
1734 : 108 : pid = buf[0];
1735 : : }
1736 : : }
1737 : :
1738 : : /* Success against all odds! return the information */
1739 : 989 : g_unix_pipe_close (&child_err_report_pipe, G_UNIX_PIPE_END_READ, NULL);
1740 : 989 : g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_READ, NULL);
1741 : :
1742 : 989 : g_free (search_path_buffer_heap);
1743 : 989 : g_free (argv_buffer_heap);
1744 : 989 : g_free (source_fds_copy);
1745 : :
1746 : 989 : if (child_pid)
1747 : 978 : *child_pid = pid;
1748 : :
1749 : 989 : goto success;
1750 : : }
1751 : :
1752 : 1083 : success:
1753 : : /* Close the uncared-about ends of the pipes */
1754 : 1083 : g_unix_pipe_close (&stdin_pipe, G_UNIX_PIPE_END_READ, NULL);
1755 : 1083 : g_unix_pipe_close (&stdout_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1756 : 1083 : g_unix_pipe_close (&stderr_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1757 : :
1758 : 1083 : if (stdin_pipe_out != NULL)
1759 : 59 : *stdin_pipe_out = g_unix_pipe_steal (&stdin_pipe, G_UNIX_PIPE_END_WRITE);
1760 : :
1761 : 1083 : if (stdout_pipe_out != NULL)
1762 : 724 : *stdout_pipe_out = g_unix_pipe_steal (&stdout_pipe, G_UNIX_PIPE_END_READ);
1763 : :
1764 : 1083 : if (stderr_pipe_out != NULL)
1765 : 471 : *stderr_pipe_out = g_unix_pipe_steal (&stderr_pipe, G_UNIX_PIPE_END_READ);
1766 : :
1767 : 1083 : return TRUE;
1768 : :
1769 : 11 : cleanup_and_fail:
1770 : :
1771 : : /* There was an error from the Child, reap the child to avoid it being
1772 : : a zombie.
1773 : : */
1774 : :
1775 : 11 : if (pid > 0)
1776 : : {
1777 : 10 : wait_failed:
1778 : 10 : if (waitpid (pid, NULL, 0) < 0)
1779 : : {
1780 : 2 : if (errno == EINTR)
1781 : 0 : goto wait_failed;
1782 : 2 : else if (errno == ECHILD)
1783 : : ; /* do nothing, child already reaped */
1784 : : else
1785 : 0 : g_warning ("waitpid() should not fail in 'fork_exec'");
1786 : : }
1787 : : }
1788 : :
1789 : 11 : g_unix_pipe_clear (&stdin_pipe);
1790 : 11 : g_unix_pipe_clear (&stdout_pipe);
1791 : 11 : g_unix_pipe_clear (&stderr_pipe);
1792 : 11 : g_unix_pipe_clear (&child_err_report_pipe);
1793 : 11 : g_unix_pipe_clear (&child_pid_report_pipe);
1794 : :
1795 : 11 : g_clear_pointer (&search_path_buffer_heap, g_free);
1796 : 11 : g_clear_pointer (&argv_buffer_heap, g_free);
1797 : 11 : g_clear_pointer (&source_fds_copy, g_free);
1798 : :
1799 : 11 : return FALSE;
1800 : : }
1801 : :
1802 : : /* Based on execvp from GNU C Library */
1803 : :
1804 : : /* This function is called between fork() and exec() and hence must be
1805 : : * async-signal-safe (see signal-safety(7)) until it calls exec(). */
1806 : : static gboolean
1807 : 0 : script_execute (const gchar *file,
1808 : : gchar **argv,
1809 : : gchar **argv_buffer,
1810 : : gsize argv_buffer_len,
1811 : : gchar **envp)
1812 : : {
1813 : : /* Count the arguments. */
1814 : 0 : gsize argc = 0;
1815 : 0 : while (argv[argc])
1816 : 0 : ++argc;
1817 : :
1818 : : /* Construct an argument list for the shell. */
1819 : 0 : if (argc + 2 > argv_buffer_len)
1820 : 0 : return FALSE;
1821 : :
1822 : 0 : argv_buffer[0] = (char *) "/bin/sh";
1823 : 0 : argv_buffer[1] = (char *) file;
1824 : 0 : while (argc > 0)
1825 : : {
1826 : 0 : argv_buffer[argc + 1] = argv[argc];
1827 : 0 : --argc;
1828 : : }
1829 : :
1830 : : /* Execute the shell. */
1831 : 0 : if (envp)
1832 : 0 : execve (argv_buffer[0], argv_buffer, envp);
1833 : : else
1834 : 0 : execv (argv_buffer[0], argv_buffer);
1835 : :
1836 : 0 : return TRUE;
1837 : : }
1838 : :
1839 : : /* This function is called between fork() and exec() and hence must be
1840 : : * async-signal-safe (see signal-safety(7)). */
1841 : : static gchar*
1842 : 173 : my_strchrnul (const gchar *str, gchar c)
1843 : : {
1844 : 173 : gchar *p = (gchar*) str;
1845 : 5767 : while (*p && (*p != c))
1846 : 5594 : ++p;
1847 : :
1848 : 173 : return p;
1849 : : }
1850 : :
1851 : : /* This function is called between fork() and exec() and hence must be
1852 : : * async-signal-safe (see signal-safety(7)) until it calls exec(). */
1853 : : static gint
1854 : 998 : g_execute (const gchar *file,
1855 : : gchar **argv,
1856 : : gchar **argv_buffer,
1857 : : gsize argv_buffer_len,
1858 : : gchar **envp,
1859 : : const gchar *search_path,
1860 : : gchar *search_path_buffer,
1861 : : gsize search_path_buffer_len)
1862 : : {
1863 : 998 : if (file == NULL || *file == '\0')
1864 : : {
1865 : : /* We check the simple case first. */
1866 : 0 : errno = ENOENT;
1867 : 0 : return -1;
1868 : : }
1869 : :
1870 : 998 : if (search_path == NULL || strchr (file, '/') != NULL)
1871 : : {
1872 : : /* Don't search when it contains a slash. */
1873 : 916 : if (envp)
1874 : 263 : execve (file, argv, envp);
1875 : : else
1876 : 653 : execv (file, argv);
1877 : :
1878 : 916 : if (errno == ENOEXEC &&
1879 : 0 : !script_execute (file, argv, argv_buffer, argv_buffer_len, envp))
1880 : : {
1881 : 0 : errno = ENOMEM;
1882 : 0 : return -1;
1883 : : }
1884 : : }
1885 : : else
1886 : : {
1887 : 82 : gboolean got_eacces = 0;
1888 : : const gchar *path, *p;
1889 : : gchar *name;
1890 : : gsize len;
1891 : : gsize pathlen;
1892 : :
1893 : 82 : path = search_path;
1894 : 82 : len = strlen (file) + 1;
1895 : 82 : pathlen = strlen (path);
1896 : 82 : name = search_path_buffer;
1897 : :
1898 : 82 : if (search_path_buffer_len < pathlen + len + 1)
1899 : : {
1900 : 0 : errno = ENOMEM;
1901 : 0 : return -1;
1902 : : }
1903 : :
1904 : : /* Copy the file name at the top, including '\0' */
1905 : 82 : memcpy (name + pathlen + 1, file, len);
1906 : 82 : name = name + pathlen;
1907 : : /* And add the slash before the filename */
1908 : 82 : *name = '/';
1909 : :
1910 : 82 : p = path;
1911 : : do
1912 : : {
1913 : : char *startp;
1914 : :
1915 : 255 : path = p;
1916 : 255 : p = my_strchrnul (path, ':');
1917 : :
1918 : 173 : if (p == path)
1919 : : /* Two adjacent colons, or a colon at the beginning or the end
1920 : : * of 'PATH' means to search the current directory.
1921 : : */
1922 : 0 : startp = name + 1;
1923 : : else
1924 : 173 : startp = memcpy (name - (p - path), path, p - path);
1925 : :
1926 : : /* Try to execute this name. If it works, execv will not return. */
1927 : 173 : if (envp)
1928 : 15 : execve (startp, argv, envp);
1929 : : else
1930 : 158 : execv (startp, argv);
1931 : :
1932 : 173 : if (errno == ENOEXEC &&
1933 : 0 : !script_execute (startp, argv, argv_buffer, argv_buffer_len, envp))
1934 : : {
1935 : 0 : errno = ENOMEM;
1936 : 0 : return -1;
1937 : : }
1938 : :
1939 : 173 : switch (errno)
1940 : : {
1941 : 0 : case EACCES:
1942 : : /* Record the we got a 'Permission denied' error. If we end
1943 : : * up finding no executable we can use, we want to diagnose
1944 : : * that we did find one but were denied access.
1945 : : */
1946 : 0 : got_eacces = TRUE;
1947 : :
1948 : : G_GNUC_FALLTHROUGH;
1949 : 173 : case ENOENT:
1950 : : #ifdef ESTALE
1951 : : case ESTALE:
1952 : : #endif
1953 : : #ifdef ENOTDIR
1954 : : case ENOTDIR:
1955 : : #endif
1956 : : /* Those errors indicate the file is missing or not executable
1957 : : * by us, in which case we want to just try the next path
1958 : : * directory.
1959 : : */
1960 : 173 : break;
1961 : :
1962 : 0 : case ENODEV:
1963 : : case ETIMEDOUT:
1964 : : /* Some strange filesystems like AFS return even
1965 : : * stranger error numbers. They cannot reasonably mean anything
1966 : : * else so ignore those, too.
1967 : : */
1968 : 0 : break;
1969 : :
1970 : 0 : default:
1971 : : /* Some other error means we found an executable file, but
1972 : : * something went wrong executing it; return the error to our
1973 : : * caller.
1974 : : */
1975 : 0 : return -1;
1976 : : }
1977 : : }
1978 : 173 : while (*p++ != '\0');
1979 : :
1980 : : /* We tried every element and none of them worked. */
1981 : 0 : if (got_eacces)
1982 : : /* At least one failure was due to permissions, so report that
1983 : : * error.
1984 : : */
1985 : 0 : errno = EACCES;
1986 : : }
1987 : :
1988 : : /* Return the error from the last attempt (probably ENOENT). */
1989 : 916 : return -1;
1990 : : }
1991 : :
1992 : : void
1993 : 189 : g_spawn_close_pid_impl (GPid pid)
1994 : : {
1995 : : /* no-op */
1996 : 189 : }
|