1 /* Creation of subprocesses, communicating via pipes.
2 Copyright (C) 2001-2004, 2006-2021 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. */
21 # pragma clang diagnostic ignored "-Wconditional-uninitialized"
27 #include "spawn-pipe.h"
35 #include "canonicalize.h"
37 #include "fatal-signal.h"
40 #include "unistd-safer.h"
41 #include "wait-process.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'
53 You can set this macro from a Makefile or at configure time, from the
55 #ifndef SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN
56 # define SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN 0
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"
69 # include "windows-spawn.h"
71 #elif defined __KLIBC__
75 # include "os2-spawn.h"
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. */
92 nonintr_close (int fd)
98 while (retval < 0 && errno == EINTR);
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
107 nonintr_open (const char *pathname, int oflag, mode_t mode)
112 retval = open (pathname, oflag, mode);
113 while (retval < 0 && errno == EINTR);
117 # undef open /* avoid warning on VMS */
118 # define open nonintr_open
124 /* Open a pipe connected to a child process.
127 * parent -> fd[1] -> STDIN_FILENO -> child if pipe_stdin
128 * parent <- fd[0] <- STDOUT_FILENO <- child if pipe_stdout
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.
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,
145 bool slave_process, bool exit_on_error,
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))
196 #if ((defined _WIN32 && !defined __CYGWIN__) && SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN) || defined __KLIBC__
198 /* Native Windows API.
199 This uses _pipe(), dup2(), and _spawnv(). It could also be implemented
200 using the low-level functions CreatePipe(), DuplicateHandle(),
201 CreateProcess() and _open_osfhandle(); see the GNU make and GNU clisp
202 and cvs source code. */
203 char *argv_mem_to_free;
211 const char **argv = prepare_spawn (prog_argv, &argv_mem_to_free);
216 if (pipe2_safer (ifd, O_BINARY | O_CLOEXEC) < 0)
217 error (EXIT_FAILURE, errno, _("cannot create pipe"));
219 if (pipe2_safer (ofd, O_BINARY | O_CLOEXEC) < 0)
220 error (EXIT_FAILURE, errno, _("cannot create pipe"));
221 /* Data flow diagram:
224 * parent -> ofd[1] -> ofd[0] -> child if pipe_stdin
225 * parent <- ifd[0] <- ifd[1] <- child if pipe_stdout
232 # if (defined _WIN32 && !defined __CYGWIN__) && SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN
233 bool must_close_ifd1 = pipe_stdout;
234 bool must_close_ofd0 = pipe_stdin;
236 /* Create standard file handles of child process. */
237 HANDLE stdin_handle = INVALID_HANDLE_VALUE;
238 HANDLE stdout_handle = INVALID_HANDLE_VALUE;
243 || (nulloutfd = open ("NUL", O_RDWR, 0)) >= 0)
245 || prog_stdin == NULL
246 || (stdinfd = open (prog_stdin, O_RDONLY, 0)) >= 0)
248 || prog_stdout == NULL
249 || (stdoutfd = open (prog_stdout, O_WRONLY, 0)) >= 0))
250 /* The child process doesn't inherit ifd[0], ifd[1], ofd[0], ofd[1],
251 but it inherits the three STD*_FILENO for which we pass the handles. */
252 /* Pass the environment explicitly. This is needed if the program has
253 modified the environment using putenv() or [un]setenv(). On Windows,
254 processes have two environments, one in the "environment block" of the
255 process and managed through SetEnvironmentVariable(), and one inside the
256 process, in the location retrieved by the 'environ' macro. If we were
257 to pass NULL, the child process would inherit a copy of the environment
258 block - ignoring the effects of putenv() and [un]setenv(). */
261 (HANDLE) _get_osfhandle (pipe_stdin ? ofd[0] :
262 prog_stdin == NULL ? STDIN_FILENO : stdinfd);
265 HANDLE curr_process = GetCurrentProcess ();
267 if (!DuplicateHandle (curr_process, stdin_handle,
268 curr_process, &duplicate,
269 0, TRUE, DUPLICATE_SAME_ACCESS))
271 errno = EBADF; /* arbitrary */
274 must_close_ofd0 = false;
275 close (ofd[0]); /* implies CloseHandle (stdin_handle); */
276 stdin_handle = duplicate;
279 (HANDLE) _get_osfhandle (pipe_stdout ? ifd[1] :
280 prog_stdout == NULL ? STDOUT_FILENO : stdoutfd);
283 HANDLE curr_process = GetCurrentProcess ();
285 if (!DuplicateHandle (curr_process, stdout_handle,
286 curr_process, &duplicate,
287 0, TRUE, DUPLICATE_SAME_ACCESS))
289 errno = EBADF; /* arbitrary */
292 must_close_ifd1 = false;
293 close (ifd[1]); /* implies CloseHandle (stdout_handle); */
294 stdout_handle = duplicate;
296 HANDLE stderr_handle =
297 (HANDLE) _get_osfhandle (null_stderr ? nulloutfd : STDERR_FILENO);
299 child = spawnpvech (P_NOWAIT, prog_path, argv + 1,
300 (const char * const *) environ, directory,
301 stdin_handle, stdout_handle, stderr_handle);
302 # if 0 /* Executing arbitrary files as shell scripts is unsecure. */
303 if (child == -1 && errno == ENOEXEC)
305 /* prog is not a native executable. Try to execute it as a
306 shell script. Note that prepare_spawn() has already prepended
307 a hidden element "sh.exe" to argv. */
309 child = spawnpvech (P_NOWAIT, argv[0], argv,
310 (const char * const *) environ, directory,
311 stdin_handle, stdout_handle, stderr_handle);
330 if (stdin_handle != INVALID_HANDLE_VALUE)
331 CloseHandle (stdin_handle);
338 if (stdout_handle != INVALID_HANDLE_VALUE)
339 CloseHandle (stdout_handle);
342 # else /* __KLIBC__ */
343 if (!(directory == NULL || strcmp (directory, ".") == 0))
345 /* A directory argument is not supported in this implementation. */
346 saved_errno = EINVAL;
347 goto fail_with_saved_errno;
354 /* Save standard file handles of parent process. */
355 if (pipe_stdin || prog_stdin != NULL)
356 orig_stdin = dup_safer_noinherit (STDIN_FILENO);
357 if (pipe_stdout || prog_stdout != NULL)
358 orig_stdout = dup_safer_noinherit (STDOUT_FILENO);
360 orig_stderr = dup_safer_noinherit (STDERR_FILENO);
362 /* Create standard file handles of child process. */
366 if ((!pipe_stdin || dup2 (ofd[0], STDIN_FILENO) >= 0)
367 && (!pipe_stdout || dup2 (ifd[1], STDOUT_FILENO) >= 0)
369 || ((nulloutfd = open ("NUL", O_RDWR, 0)) >= 0
370 && (nulloutfd == STDERR_FILENO
371 || (dup2 (nulloutfd, STDERR_FILENO) >= 0
372 && close (nulloutfd) >= 0))))
374 || prog_stdin == NULL
375 || ((stdinfd = open (prog_stdin, O_RDONLY, 0)) >= 0
376 && (stdinfd == STDIN_FILENO
377 || (dup2 (stdinfd, STDIN_FILENO) >= 0
378 && close (stdinfd) >= 0))))
380 || prog_stdout == NULL
381 || ((stdoutfd = open (prog_stdout, O_WRONLY, 0)) >= 0
382 && (stdoutfd == STDOUT_FILENO
383 || (dup2 (stdoutfd, STDOUT_FILENO) >= 0
384 && close (stdoutfd) >= 0)))))
385 /* The child process doesn't inherit ifd[0], ifd[1], ofd[0], ofd[1],
386 but it inherits all open()ed or dup2()ed file handles (which is what
387 we want in the case of STD*_FILENO). */
389 child = _spawnvpe (P_NOWAIT, prog_path, argv + 1,
390 (const char **) environ);
391 # if 0 /* Executing arbitrary files as shell scripts is unsecure. */
392 if (child == -1 && errno == ENOEXEC)
394 /* prog is not a native executable. Try to execute it as a
395 shell script. Note that prepare_spawn() has already prepended
396 a hidden element "sh.exe" to argv. */
397 child = _spawnvpe (P_NOWAIT, argv[0], argv,
398 (const char **) environ);
411 /* Restore standard file handles of parent process. */
413 undup_safer_noinherit (orig_stderr, STDERR_FILENO);
414 if (pipe_stdout || prog_stdout != NULL)
415 undup_safer_noinherit (orig_stdout, STDOUT_FILENO);
416 if (pipe_stdin || prog_stdin != NULL)
417 undup_safer_noinherit (orig_stdin, STDIN_FILENO);
426 free (argv_mem_to_free);
427 free (prog_path_to_free);
435 goto fail_with_saved_errno;
449 sigset_t blocked_signals;
450 posix_spawn_file_actions_t actions;
451 bool actions_allocated;
452 posix_spawnattr_t attrs;
453 bool attrs_allocated;
458 if (pipe_safer (ifd) < 0)
459 error (EXIT_FAILURE, errno, _("cannot create pipe"));
461 if (pipe_safer (ofd) < 0)
462 error (EXIT_FAILURE, errno, _("cannot create pipe"));
463 /* Data flow diagram:
466 * parent -> ofd[1] -> ofd[0] -> child if pipe_stdin
467 * parent <- ifd[0] <- ifd[1] <- child if pipe_stdout
474 sigprocmask (SIG_SETMASK, NULL, &blocked_signals);
475 block_fatal_signals ();
477 actions_allocated = false;
478 attrs_allocated = false;
479 if ((err = posix_spawn_file_actions_init (&actions)) != 0
480 || (actions_allocated = true,
482 && (err = posix_spawn_file_actions_adddup2 (&actions,
483 ofd[0], STDIN_FILENO))
486 && (err = posix_spawn_file_actions_adddup2 (&actions,
487 ifd[1], STDOUT_FILENO))
490 && (err = posix_spawn_file_actions_addclose (&actions, ofd[0]))
493 && (err = posix_spawn_file_actions_addclose (&actions, ifd[1]))
496 && (err = posix_spawn_file_actions_addclose (&actions, ofd[1]))
499 && (err = posix_spawn_file_actions_addclose (&actions, ifd[0]))
502 && (err = posix_spawn_file_actions_addopen (&actions,
508 && prog_stdin != NULL
509 && (err = posix_spawn_file_actions_addopen (&actions,
511 prog_stdin, O_RDONLY,
515 && prog_stdout != NULL
516 && (err = posix_spawn_file_actions_addopen (&actions,
518 prog_stdout, O_WRONLY,
521 || (directory != NULL
522 && (err = posix_spawn_file_actions_addchdir (&actions,
525 && ((err = posix_spawnattr_init (&attrs)) != 0
526 || (attrs_allocated = true,
527 # if defined _WIN32 && !defined __CYGWIN__
528 (err = posix_spawnattr_setpgroup (&attrs, 0)) != 0
529 || (err = posix_spawnattr_setflags (&attrs,
530 POSIX_SPAWN_SETPGROUP))
533 (err = posix_spawnattr_setsigmask (&attrs,
536 || (err = posix_spawnattr_setflags (&attrs,
537 POSIX_SPAWN_SETSIGMASK))
541 || (err = (directory != NULL
542 ? posix_spawn (&child, prog_path, &actions,
543 attrs_allocated ? &attrs : NULL,
544 (char * const *) prog_argv, environ)
545 : posix_spawnp (&child, prog_path, &actions,
546 attrs_allocated ? &attrs : NULL,
547 (char * const *) prog_argv, environ)))
550 if (actions_allocated)
551 posix_spawn_file_actions_destroy (&actions);
553 posix_spawnattr_destroy (&attrs);
555 unblock_fatal_signals ();
566 free (prog_path_to_free);
568 goto fail_with_saved_errno;
570 posix_spawn_file_actions_destroy (&actions);
572 posix_spawnattr_destroy (&attrs);
575 register_slave_subprocess (child);
576 unblock_fatal_signals ();
582 free (prog_path_to_free);
594 fail_with_saved_errno:
595 if (exit_on_error || !null_stderr)
596 error (exit_on_error ? EXIT_FAILURE : 0, saved_errno,
597 _("%s subprocess failed"), progname);
602 /* Open a bidirectional pipe.
605 * parent -> fd[1] -> STDIN_FILENO -> child
606 * parent <- fd[0] <- STDOUT_FILENO <- child
611 create_pipe_bidi (const char *progname,
612 const char *prog_path, const char * const *prog_argv,
613 const char *directory,
615 bool slave_process, bool exit_on_error,
618 pid_t result = create_pipe (progname, prog_path, prog_argv, directory,
619 true, true, NULL, NULL,
620 null_stderr, slave_process, exit_on_error,
625 /* Open a pipe for input from a child process.
626 * The child's stdin comes from a file.
629 * parent <- fd[0] <- STDOUT_FILENO <- child
633 create_pipe_in (const char *progname,
634 const char *prog_path, const char * const *prog_argv,
635 const char *directory,
636 const char *prog_stdin, bool null_stderr,
637 bool slave_process, bool exit_on_error,
641 pid_t result = create_pipe (progname, prog_path, prog_argv, directory,
642 false, true, prog_stdin, NULL,
643 null_stderr, slave_process, exit_on_error,
650 /* Open a pipe for output to a child process.
651 * The child's stdout goes to a file.
654 * parent -> fd[0] -> STDIN_FILENO -> child
658 create_pipe_out (const char *progname,
659 const char *prog_path, const char * const *prog_argv,
660 const char *directory,
661 const char *prog_stdout, bool null_stderr,
662 bool slave_process, bool exit_on_error,
666 pid_t result = create_pipe (progname, prog_path, prog_argv, directory,
667 true, false, NULL, prog_stdout,
668 null_stderr, slave_process, exit_on_error,