exp2l: Work around a NetBSD 10.0/i386 bug.
[gnulib.git] / lib / spawn-pipe.c
blob0f03926e9fa2e7e151f63c784d90762bc2fe9515
1 /* Creation of subprocesses, communicating via pipes.
2 Copyright (C) 2001-2004, 2006-2024 Free Software Foundation, Inc.
3 Written by Bruno Haible <haible@clisp.cons.org>, 2001.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
19 /* Tell clang not to warn about the 'child' variable, below. */
20 #if defined __clang__
21 # pragma clang diagnostic ignored "-Wconditional-uninitialized"
22 #endif
24 #include <config.h>
26 /* Specification. */
27 #include "spawn-pipe.h"
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <stdlib.h>
32 #include <signal.h>
33 #include <unistd.h>
35 #include "canonicalize.h"
36 #include <error.h>
37 #include "fatal-signal.h"
38 #include "filename.h"
39 #include "findprog.h"
40 #include "unistd-safer.h"
41 #include "wait-process.h"
42 #include "xalloc.h"
43 #include "gettext.h"
45 #define _(str) gettext (str)
48 /* Choice of implementation for native Windows.
49 - Define to 0 to use the posix_spawn facility (modules 'posix_spawn' and
50 'posix_spawnp'), that is based on the module 'windows-spawn'.
51 - Define to 1 to use the older code, that uses the module 'windows-spawn'
52 directly.
53 You can set this macro from a Makefile or at configure time, from the
54 CPPFLAGS. */
55 #ifndef SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN
56 # define SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN 0
57 #endif
60 #if (defined _WIN32 && !defined __CYGWIN__) && SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN
62 /* Native Windows API. */
63 # if GNULIB_MSVC_NOTHROW
64 # include "msvc-nothrow.h"
65 # else
66 # include <io.h>
67 # endif
68 # include <process.h>
69 # include "windows-spawn.h"
71 #elif defined __KLIBC__
73 /* OS/2 kLIBC API. */
74 # include <process.h>
75 # include "os2-spawn.h"
77 #else
79 /* Unix API. */
80 # include <spawn.h>
82 #endif
85 #ifdef EINTR
87 /* EINTR handling for close().
88 These functions can return -1/EINTR even though we don't have any
89 signal handlers set up, namely when we get interrupted via SIGSTOP. */
91 static int
92 nonintr_close (int fd)
94 int retval;
97 retval = close (fd);
98 while (retval < 0 && errno == EINTR);
100 return retval;
102 #undef close /* avoid warning related to gnulib module unistd */
103 #define close nonintr_close
105 #if (defined _WIN32 && !defined __CYGWIN__) && SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN
106 static int
107 nonintr_open (const char *pathname, int oflag, mode_t mode)
109 int retval;
112 retval = open (pathname, oflag, mode);
113 while (retval < 0 && errno == EINTR);
115 return retval;
117 # undef open /* avoid warning on VMS */
118 # define open nonintr_open
119 #endif
121 #endif
124 /* Open a pipe connected to a child process.
126 * write system read
127 * parent -> fd[1] -> STDIN_FILENO -> child if pipe_stdin
128 * parent <- fd[0] <- STDOUT_FILENO <- child if pipe_stdout
129 * read system write
131 * At least one of pipe_stdin, pipe_stdout must be true.
132 * pipe_stdin and prog_stdin together determine the child's standard input.
133 * pipe_stdout and prog_stdout together determine the child's standard output.
134 * If pipe_stdin is true, prog_stdin is ignored.
135 * If pipe_stdout is true, prog_stdout is ignored.
137 static pid_t
138 create_pipe (const char *progname,
139 const char *prog_path,
140 const char * const *prog_argv,
141 const char *directory,
142 bool pipe_stdin, bool pipe_stdout,
143 const char *prog_stdin, const char *prog_stdout,
144 bool null_stderr,
145 bool slave_process, bool exit_on_error,
146 int fd[2])
148 int saved_errno;
149 char *prog_path_to_free = NULL;
151 if (directory != NULL)
153 /* If a change of directory is requested, make sure PROG_PATH is absolute
154 before we do so. This is needed because
155 - posix_spawn and posix_spawnp are required to resolve a relative
156 PROG_PATH *after* changing the directory. See
157 <https://www.austingroupbugs.net/view.php?id=1208>:
158 "if this pathname does not start with a <slash> it shall be
159 interpreted relative to the working directory of the child
160 process _after_ all file_actions have been performed."
161 But this would be a surprising application behaviour, possibly
162 even security relevant.
163 - For the Windows CreateProcess() function, it is unspecified whether
164 a relative file name is interpreted to the parent's current
165 directory or to the specified directory. See
166 <https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa> */
167 if (! IS_ABSOLUTE_FILE_NAME (prog_path))
169 const char *resolved_prog =
170 find_in_given_path (prog_path, getenv ("PATH"), NULL, false);
171 if (resolved_prog == NULL)
172 goto fail_with_errno;
173 if (resolved_prog != prog_path)
174 prog_path_to_free = (char *) resolved_prog;
175 prog_path = resolved_prog;
177 if (! IS_ABSOLUTE_FILE_NAME (prog_path))
179 char *absolute_prog =
180 canonicalize_filename_mode (prog_path, CAN_MISSING | CAN_NOLINKS);
181 if (absolute_prog == NULL)
183 free (prog_path_to_free);
184 goto fail_with_errno;
186 free (prog_path_to_free);
187 prog_path_to_free = absolute_prog;
188 prog_path = absolute_prog;
190 if (! IS_ABSOLUTE_FILE_NAME (prog_path))
191 abort ();
196 int ifd[2];
197 int ofd[2];
199 /* It is important to create the file descriptors with the close-on-exec bit
200 set.
201 * In the child process that we are about to create here, the file
202 descriptors ofd[0] -> STDIN_FILENO and ifd[1] -> STDOUT_FILENO will be
203 preserved across exec, because each dup2 call scheduled by
204 posix_spawn_file_actions_adddup2 creates a file descriptor with the
205 close-on-exec bit clear. Similarly on native Windows, where we use
206 explicit DuplicateHandle calls, and on kLIBC, where we use explicit dup2
207 calls.
208 * In the parent process, we close ofd[0] and ifd[1]; so, ofd[1] and ofd[0]
209 are still open. But if the parent process spawns another child process
210 later, if ofd[1] and ofd[0] were inherited by that child process, the
211 "end of input" / "end of output" detection would not work any more. The
212 parent or the child process would block, as long as that other child
213 process is running. */
214 if (pipe_stdout)
215 if (pipe2_safer (ifd, O_BINARY | O_CLOEXEC) < 0)
216 error (EXIT_FAILURE, errno, _("cannot create pipe"));
217 if (pipe_stdin)
218 if (pipe2_safer (ofd, O_BINARY | O_CLOEXEC) < 0)
219 error (EXIT_FAILURE, errno, _("cannot create pipe"));
220 /* Data flow diagram:
222 * write system read
223 * parent -> ofd[1] -> ofd[0] -> child if pipe_stdin
224 * parent <- ifd[0] <- ifd[1] <- child if pipe_stdout
225 * read system write
229 #if ((defined _WIN32 && !defined __CYGWIN__) && SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN) || defined __KLIBC__
231 /* Native Windows API.
232 This uses _pipe(), dup2(), and _spawnv(). It could also be implemented
233 using the low-level functions CreatePipe(), DuplicateHandle(),
234 CreateProcess() and _open_osfhandle(); see the GNU make and GNU clisp
235 and cvs source code. */
236 char *argv_mem_to_free;
237 int child;
238 int nulloutfd;
239 int stdinfd;
240 int stdoutfd;
242 const char **argv = prepare_spawn (prog_argv, &argv_mem_to_free);
243 if (argv == NULL)
244 xalloc_die ();
246 child = -1;
248 # if (defined _WIN32 && !defined __CYGWIN__) && SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN
249 bool must_close_ifd1 = pipe_stdout;
250 bool must_close_ofd0 = pipe_stdin;
252 /* Create standard file handles of child process. */
253 HANDLE stdin_handle = INVALID_HANDLE_VALUE;
254 HANDLE stdout_handle = INVALID_HANDLE_VALUE;
255 nulloutfd = -1;
256 stdinfd = -1;
257 stdoutfd = -1;
258 if ((!null_stderr
259 || (nulloutfd = open ("NUL", O_RDWR, 0)) >= 0)
260 && (pipe_stdin
261 || prog_stdin == NULL
262 || (stdinfd = open (prog_stdin, O_RDONLY, 0)) >= 0)
263 && (pipe_stdout
264 || prog_stdout == NULL
265 || (stdoutfd = open (prog_stdout, O_WRONLY, 0)) >= 0))
266 /* The child process doesn't inherit ifd[0], ifd[1], ofd[0], ofd[1],
267 but it inherits the three STD*_FILENO for which we pass the handles. */
268 /* Pass the environment explicitly. This is needed if the program has
269 modified the environment using putenv() or [un]setenv(). On Windows,
270 processes have two environments, one in the "environment block" of the
271 process and managed through SetEnvironmentVariable(), and one inside the
272 process, in the location retrieved by the 'environ' macro. If we were
273 to pass NULL, the child process would inherit a copy of the environment
274 block - ignoring the effects of putenv() and [un]setenv(). */
276 stdin_handle =
277 (HANDLE) _get_osfhandle (pipe_stdin ? ofd[0] :
278 prog_stdin == NULL ? STDIN_FILENO : stdinfd);
279 if (pipe_stdin)
281 HANDLE curr_process = GetCurrentProcess ();
282 HANDLE duplicate;
283 if (!DuplicateHandle (curr_process, stdin_handle,
284 curr_process, &duplicate,
285 0, TRUE, DUPLICATE_SAME_ACCESS))
287 errno = EBADF; /* arbitrary */
288 goto failed;
290 must_close_ofd0 = false;
291 close (ofd[0]); /* implies CloseHandle (stdin_handle); */
292 stdin_handle = duplicate;
294 stdout_handle =
295 (HANDLE) _get_osfhandle (pipe_stdout ? ifd[1] :
296 prog_stdout == NULL ? STDOUT_FILENO : stdoutfd);
297 if (pipe_stdout)
299 HANDLE curr_process = GetCurrentProcess ();
300 HANDLE duplicate;
301 if (!DuplicateHandle (curr_process, stdout_handle,
302 curr_process, &duplicate,
303 0, TRUE, DUPLICATE_SAME_ACCESS))
305 errno = EBADF; /* arbitrary */
306 goto failed;
308 must_close_ifd1 = false;
309 close (ifd[1]); /* implies CloseHandle (stdout_handle); */
310 stdout_handle = duplicate;
312 HANDLE stderr_handle =
313 (HANDLE) _get_osfhandle (null_stderr ? nulloutfd : STDERR_FILENO);
315 child = spawnpvech (P_NOWAIT, prog_path, argv + 1,
316 (const char * const *) environ, directory,
317 stdin_handle, stdout_handle, stderr_handle);
318 # if 0 /* Executing arbitrary files as shell scripts is unsecure. */
319 if (child == -1 && errno == ENOEXEC)
321 /* prog is not a native executable. Try to execute it as a
322 shell script. Note that prepare_spawn() has already prepended
323 a hidden element "sh.exe" to argv. */
324 argv[1] = prog_path;
325 child = spawnpvech (P_NOWAIT, argv[0], argv,
326 (const char * const *) environ, directory,
327 stdin_handle, stdout_handle, stderr_handle);
329 # endif
331 failed:
332 if (child == -1)
333 saved_errno = errno;
334 if (stdinfd >= 0)
335 close (stdinfd);
336 if (stdoutfd >= 0)
337 close (stdoutfd);
338 if (nulloutfd >= 0)
339 close (nulloutfd);
341 if (pipe_stdin)
343 if (must_close_ofd0)
344 close (ofd[0]);
345 else
346 if (stdin_handle != INVALID_HANDLE_VALUE)
347 CloseHandle (stdin_handle);
349 if (pipe_stdout)
351 if (must_close_ifd1)
352 close (ifd[1]);
353 else
354 if (stdout_handle != INVALID_HANDLE_VALUE)
355 CloseHandle (stdout_handle);
358 # else /* __KLIBC__ */
359 if (!(directory == NULL || strcmp (directory, ".") == 0))
361 /* A directory argument is not supported in this implementation. */
362 saved_errno = EINVAL;
363 goto fail_with_saved_errno;
366 int orig_stdin;
367 int orig_stdout;
368 int orig_stderr;
370 /* Save standard file handles of parent process. */
371 if (pipe_stdin || prog_stdin != NULL)
372 orig_stdin = dup_safer_noinherit (STDIN_FILENO);
373 if (pipe_stdout || prog_stdout != NULL)
374 orig_stdout = dup_safer_noinherit (STDOUT_FILENO);
375 if (null_stderr)
376 orig_stderr = dup_safer_noinherit (STDERR_FILENO);
378 /* Create standard file handles of child process. */
379 nulloutfd = -1;
380 stdinfd = -1;
381 stdoutfd = -1;
382 if ((!pipe_stdin || dup2 (ofd[0], STDIN_FILENO) >= 0)
383 && (!pipe_stdout || dup2 (ifd[1], STDOUT_FILENO) >= 0)
384 && (!null_stderr
385 || ((nulloutfd = open ("NUL", O_RDWR, 0)) >= 0
386 && (nulloutfd == STDERR_FILENO
387 || (dup2 (nulloutfd, STDERR_FILENO) >= 0
388 && close (nulloutfd) >= 0))))
389 && (pipe_stdin
390 || prog_stdin == NULL
391 || ((stdinfd = open (prog_stdin, O_RDONLY, 0)) >= 0
392 && (stdinfd == STDIN_FILENO
393 || (dup2 (stdinfd, STDIN_FILENO) >= 0
394 && close (stdinfd) >= 0))))
395 && (pipe_stdout
396 || prog_stdout == NULL
397 || ((stdoutfd = open (prog_stdout, O_WRONLY, 0)) >= 0
398 && (stdoutfd == STDOUT_FILENO
399 || (dup2 (stdoutfd, STDOUT_FILENO) >= 0
400 && close (stdoutfd) >= 0)))))
401 /* The child process doesn't inherit ifd[0], ifd[1], ofd[0], ofd[1],
402 but it inherits all open()ed or dup2()ed file handles (which is what
403 we want in the case of STD*_FILENO). */
405 child = _spawnvpe (P_NOWAIT, prog_path, argv + 1,
406 (const char **) environ);
407 # if 0 /* Executing arbitrary files as shell scripts is unsecure. */
408 if (child == -1 && errno == ENOEXEC)
410 /* prog is not a native executable. Try to execute it as a
411 shell script. Note that prepare_spawn() has already prepended
412 a hidden element "sh.exe" to argv. */
413 child = _spawnvpe (P_NOWAIT, argv[0], argv,
414 (const char **) environ);
416 # endif
418 if (child == -1)
419 saved_errno = errno;
420 if (stdinfd >= 0)
421 close (stdinfd);
422 if (stdoutfd >= 0)
423 close (stdoutfd);
424 if (nulloutfd >= 0)
425 close (nulloutfd);
427 /* Restore standard file handles of parent process. */
428 if (null_stderr)
429 undup_safer_noinherit (orig_stderr, STDERR_FILENO);
430 if (pipe_stdout || prog_stdout != NULL)
431 undup_safer_noinherit (orig_stdout, STDOUT_FILENO);
432 if (pipe_stdin || prog_stdin != NULL)
433 undup_safer_noinherit (orig_stdin, STDIN_FILENO);
435 if (pipe_stdin)
436 close (ofd[0]);
437 if (pipe_stdout)
438 close (ifd[1]);
439 # endif
441 free (argv);
442 free (argv_mem_to_free);
443 free (prog_path_to_free);
445 if (child == -1)
447 if (pipe_stdout)
448 close (ifd[0]);
449 if (pipe_stdin)
450 close (ofd[1]);
451 goto fail_with_saved_errno;
454 if (pipe_stdout)
455 fd[0] = ifd[0];
456 if (pipe_stdin)
457 fd[1] = ofd[1];
458 return child;
460 #else
462 /* Unix API. */
463 sigset_t blocked_signals;
464 posix_spawn_file_actions_t actions;
465 bool actions_allocated;
466 posix_spawnattr_t attrs;
467 bool attrs_allocated;
468 int err;
469 pid_t child;
471 if (slave_process)
473 sigprocmask (SIG_SETMASK, NULL, &blocked_signals);
474 block_fatal_signals ();
476 actions_allocated = false;
477 attrs_allocated = false;
478 if ((err = posix_spawn_file_actions_init (&actions)) != 0
479 || (actions_allocated = true,
480 (pipe_stdin
481 && (err = posix_spawn_file_actions_adddup2 (&actions,
482 ofd[0], STDIN_FILENO))
483 != 0)
484 || (pipe_stdout
485 && (err = posix_spawn_file_actions_adddup2 (&actions,
486 ifd[1], STDOUT_FILENO))
487 != 0)
488 || (pipe_stdin
489 && (err = posix_spawn_file_actions_addclose (&actions, ofd[0]))
490 != 0)
491 || (pipe_stdout
492 && (err = posix_spawn_file_actions_addclose (&actions, ifd[1]))
493 != 0)
494 || (pipe_stdin
495 && (err = posix_spawn_file_actions_addclose (&actions, ofd[1]))
496 != 0)
497 || (pipe_stdout
498 && (err = posix_spawn_file_actions_addclose (&actions, ifd[0]))
499 != 0)
500 || (null_stderr
501 && (err = posix_spawn_file_actions_addopen (&actions,
502 STDERR_FILENO,
503 "/dev/null", O_RDWR,
505 != 0)
506 || (!pipe_stdin
507 && prog_stdin != NULL
508 && (err = posix_spawn_file_actions_addopen (&actions,
509 STDIN_FILENO,
510 prog_stdin, O_RDONLY,
512 != 0)
513 || (!pipe_stdout
514 && prog_stdout != NULL
515 && (err = posix_spawn_file_actions_addopen (&actions,
516 STDOUT_FILENO,
517 prog_stdout, O_WRONLY,
519 != 0)
520 || (directory != NULL
521 && (err = posix_spawn_file_actions_addchdir (&actions,
522 directory)))
523 || (slave_process
524 && ((err = posix_spawnattr_init (&attrs)) != 0
525 || (attrs_allocated = true,
526 # if defined _WIN32 && !defined __CYGWIN__
527 (err = posix_spawnattr_setpgroup (&attrs, 0)) != 0
528 || (err = posix_spawnattr_setflags (&attrs,
529 POSIX_SPAWN_SETPGROUP))
530 != 0
531 # else
532 (err = posix_spawnattr_setsigmask (&attrs,
533 &blocked_signals))
534 != 0
535 || (err = posix_spawnattr_setflags (&attrs,
536 POSIX_SPAWN_SETSIGMASK))
537 != 0
538 # endif
539 ) ) )
540 || (err = (directory != NULL
541 ? posix_spawn (&child, prog_path, &actions,
542 attrs_allocated ? &attrs : NULL,
543 (char * const *) prog_argv, environ)
544 : posix_spawnp (&child, prog_path, &actions,
545 attrs_allocated ? &attrs : NULL,
546 (char * const *) prog_argv, environ)))
547 != 0))
549 if (actions_allocated)
550 posix_spawn_file_actions_destroy (&actions);
551 if (attrs_allocated)
552 posix_spawnattr_destroy (&attrs);
553 if (slave_process)
554 unblock_fatal_signals ();
555 if (pipe_stdout)
557 close (ifd[0]);
558 close (ifd[1]);
560 if (pipe_stdin)
562 close (ofd[0]);
563 close (ofd[1]);
565 free (prog_path_to_free);
566 saved_errno = err;
567 goto fail_with_saved_errno;
569 posix_spawn_file_actions_destroy (&actions);
570 if (attrs_allocated)
571 posix_spawnattr_destroy (&attrs);
572 if (slave_process)
574 register_slave_subprocess (child);
575 unblock_fatal_signals ();
577 if (pipe_stdin)
578 close (ofd[0]);
579 if (pipe_stdout)
580 close (ifd[1]);
581 free (prog_path_to_free);
583 if (pipe_stdout)
584 fd[0] = ifd[0];
585 if (pipe_stdin)
586 fd[1] = ofd[1];
587 return child;
589 #endif
591 fail_with_errno:
592 saved_errno = errno;
593 fail_with_saved_errno:
594 if (exit_on_error || !null_stderr)
595 error (exit_on_error ? EXIT_FAILURE : 0, saved_errno,
596 _("%s subprocess failed"), progname);
597 errno = saved_errno;
598 return -1;
601 /* Open a bidirectional pipe.
603 * write system read
604 * parent -> fd[1] -> STDIN_FILENO -> child
605 * parent <- fd[0] <- STDOUT_FILENO <- child
606 * read system write
609 pid_t
610 create_pipe_bidi (const char *progname,
611 const char *prog_path, const char * const *prog_argv,
612 const char *directory,
613 bool null_stderr,
614 bool slave_process, bool exit_on_error,
615 int fd[2])
617 pid_t result = create_pipe (progname, prog_path, prog_argv, directory,
618 true, true, NULL, NULL,
619 null_stderr, slave_process, exit_on_error,
620 fd);
621 return result;
624 /* Open a pipe for input from a child process.
625 * The child's stdin comes from a file.
627 * read system write
628 * parent <- fd[0] <- STDOUT_FILENO <- child
631 pid_t
632 create_pipe_in (const char *progname,
633 const char *prog_path, const char * const *prog_argv,
634 const char *directory,
635 const char *prog_stdin, bool null_stderr,
636 bool slave_process, bool exit_on_error,
637 int fd[1])
639 int iofd[2];
640 pid_t result = create_pipe (progname, prog_path, prog_argv, directory,
641 false, true, prog_stdin, NULL,
642 null_stderr, slave_process, exit_on_error,
643 iofd);
644 if (result != -1)
645 fd[0] = iofd[0];
646 return result;
649 /* Open a pipe for output to a child process.
650 * The child's stdout goes to a file.
652 * write system read
653 * parent -> fd[0] -> STDIN_FILENO -> child
656 pid_t
657 create_pipe_out (const char *progname,
658 const char *prog_path, const char * const *prog_argv,
659 const char *directory,
660 const char *prog_stdout, bool null_stderr,
661 bool slave_process, bool exit_on_error,
662 int fd[1])
664 int iofd[2];
665 pid_t result = create_pipe (progname, prog_path, prog_argv, directory,
666 true, false, NULL, prog_stdout,
667 null_stderr, slave_process, exit_on_error,
668 iofd);
669 if (result != -1)
670 fd[0] = iofd[1];
671 return result;