1 /* Creation of subprocesses, communicating via pipes.
2 Copyright (C) 2001-2004, 2006-2025 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 "windows-path.h"
41 #include "unistd-safer.h"
42 #include "wait-process.h"
46 #define _(msgid) dgettext ("gnulib", msgid)
49 /* Choice of implementation for native Windows.
50 - Define to 0 to use the posix_spawn facility (modules 'posix_spawn' and
51 'posix_spawnp'), that is based on the module 'windows-spawn'.
52 - Define to 1 to use the older code, that uses the module 'windows-spawn'
54 You can set this macro from a Makefile or at configure time, from the
56 #ifndef SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN
57 # define SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN 0
61 #if (defined _WIN32 && !defined __CYGWIN__) && SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN
63 /* Native Windows API. */
64 # if GNULIB_MSVC_NOTHROW
65 # include "msvc-nothrow.h"
70 # include "windows-spawn.h"
72 #elif defined __KLIBC__
76 # include "os2-spawn.h"
88 /* EINTR handling for close().
89 These functions can return -1/EINTR even though we don't have any
90 signal handlers set up, namely when we get interrupted via SIGSTOP. */
93 nonintr_close (int fd
)
99 while (retval
< 0 && errno
== EINTR
);
103 #undef close /* avoid warning related to gnulib module unistd */
104 #define close nonintr_close
106 #if (defined _WIN32 && !defined __CYGWIN__) && SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN
108 nonintr_open (const char *pathname
, int oflag
, mode_t mode
)
113 retval
= open (pathname
, oflag
, mode
);
114 while (retval
< 0 && errno
== EINTR
);
118 # undef open /* avoid warning on VMS */
119 # define open nonintr_open
125 /* Open a pipe connected to a child process.
128 * parent -> fd[1] -> STDIN_FILENO -> child if pipe_stdin
129 * parent <- fd[0] <- STDOUT_FILENO <- child if pipe_stdout
132 * At least one of pipe_stdin, pipe_stdout must be true.
133 * pipe_stdin and prog_stdin together determine the child's standard input.
134 * pipe_stdout and prog_stdout together determine the child's standard output.
135 * If pipe_stdin is true, prog_stdin is ignored.
136 * If pipe_stdout is true, prog_stdout is ignored.
139 create_pipe (const char *progname
,
140 const char *prog_path
,
141 const char * const *prog_argv
,
142 const char * const *dll_dirs
,
143 const char *directory
,
144 bool pipe_stdin
, bool pipe_stdout
,
145 const char *prog_stdin
, const char *prog_stdout
,
147 bool slave_process
, bool exit_on_error
,
151 char *prog_path_to_free
= NULL
;
153 if (directory
!= NULL
)
155 /* If a change of directory is requested, make sure PROG_PATH is absolute
156 before we do so. This is needed because
157 - posix_spawn and posix_spawnp are required to resolve a relative
158 PROG_PATH *after* changing the directory. See
159 <https://www.austingroupbugs.net/view.php?id=1208>:
160 "if this pathname does not start with a <slash> it shall be
161 interpreted relative to the working directory of the child
162 process _after_ all file_actions have been performed."
163 But this would be a surprising application behaviour, possibly
164 even security relevant.
165 - For the Windows CreateProcess() function, it is unspecified whether
166 a relative file name is interpreted to the parent's current
167 directory or to the specified directory. See
168 <https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa> */
169 if (! IS_ABSOLUTE_FILE_NAME (prog_path
))
171 const char *resolved_prog
=
172 find_in_given_path (prog_path
, getenv ("PATH"), NULL
, false);
173 if (resolved_prog
== NULL
)
174 goto fail_with_errno
;
175 if (resolved_prog
!= prog_path
)
176 prog_path_to_free
= (char *) resolved_prog
;
177 prog_path
= resolved_prog
;
179 if (! IS_ABSOLUTE_FILE_NAME (prog_path
))
181 char *absolute_prog
=
182 canonicalize_filename_mode (prog_path
, CAN_MISSING
| CAN_NOLINKS
);
183 if (absolute_prog
== NULL
)
185 free (prog_path_to_free
);
186 goto fail_with_errno
;
188 free (prog_path_to_free
);
189 prog_path_to_free
= absolute_prog
;
190 prog_path
= absolute_prog
;
192 if (! IS_ABSOLUTE_FILE_NAME (prog_path
))
201 /* It is important to create the file descriptors with the close-on-exec bit
203 * In the child process that we are about to create here, the file
204 descriptors ofd[0] -> STDIN_FILENO and ifd[1] -> STDOUT_FILENO will be
205 preserved across exec, because each dup2 call scheduled by
206 posix_spawn_file_actions_adddup2 creates a file descriptor with the
207 close-on-exec bit clear. Similarly on native Windows, where we use
208 explicit DuplicateHandle calls, and on kLIBC, where we use explicit dup2
210 * In the parent process, we close ofd[0] and ifd[1]; so, ofd[1] and ofd[0]
211 are still open. But if the parent process spawns another child process
212 later, if ofd[1] and ofd[0] were inherited by that child process, the
213 "end of input" / "end of output" detection would not work any more. The
214 parent or the child process would block, as long as that other child
215 process is running. */
217 if (pipe2_safer (ifd
, O_BINARY
| O_CLOEXEC
) < 0)
218 error (EXIT_FAILURE
, errno
, _("cannot create pipe"));
220 if (pipe2_safer (ofd
, O_BINARY
| O_CLOEXEC
) < 0)
221 error (EXIT_FAILURE
, errno
, _("cannot create pipe"));
222 /* Data flow diagram:
225 * parent -> ofd[1] -> ofd[0] -> child if pipe_stdin
226 * parent <- ifd[0] <- ifd[1] <- child if pipe_stdout
231 #if ((defined _WIN32 && !defined __CYGWIN__) && SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN) || defined __KLIBC__
233 /* Native Windows API.
234 This uses _pipe(), dup2(), and _spawnv(). It could also be implemented
235 using the low-level functions CreatePipe(), DuplicateHandle(),
236 CreateProcess() and _open_osfhandle(); see the GNU make and GNU clisp
237 and cvs source code. */
238 char *argv_mem_to_free
;
244 const char **argv
= prepare_spawn (prog_argv
, &argv_mem_to_free
);
250 # if (defined _WIN32 && !defined __CYGWIN__) && SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN
251 bool must_close_ifd1
= pipe_stdout
;
252 bool must_close_ofd0
= pipe_stdin
;
254 /* Create standard file handles of child process. */
255 HANDLE stdin_handle
= INVALID_HANDLE_VALUE
;
256 HANDLE stdout_handle
= INVALID_HANDLE_VALUE
;
261 || (nulloutfd
= open ("NUL", O_RDWR
, 0)) >= 0)
263 || prog_stdin
== NULL
264 || (stdinfd
= open (prog_stdin
, O_RDONLY
, 0)) >= 0)
266 || prog_stdout
== NULL
267 || (stdoutfd
= open (prog_stdout
, O_WRONLY
, 0)) >= 0))
268 /* The child process doesn't inherit ifd[0], ifd[1], ofd[0], ofd[1],
269 but it inherits the three STD*_FILENO for which we pass the handles. */
270 /* Pass the environment explicitly. This is needed if the program has
271 modified the environment using putenv() or [un]setenv(). On Windows,
272 processes have two environments, one in the "environment block" of the
273 process and managed through SetEnvironmentVariable(), and one inside the
274 process, in the location retrieved by the 'environ' macro. If we were
275 to pass NULL, the child process would inherit a copy of the environment
276 block - ignoring the effects of putenv() and [un]setenv(). */
279 (HANDLE
) _get_osfhandle (pipe_stdin
? ofd
[0] :
280 prog_stdin
== NULL
? STDIN_FILENO
: stdinfd
);
283 HANDLE curr_process
= GetCurrentProcess ();
285 if (!DuplicateHandle (curr_process
, stdin_handle
,
286 curr_process
, &duplicate
,
287 0, TRUE
, DUPLICATE_SAME_ACCESS
))
289 errno
= EBADF
; /* arbitrary */
292 must_close_ofd0
= false;
293 close (ofd
[0]); /* implies CloseHandle (stdin_handle); */
294 stdin_handle
= duplicate
;
297 (HANDLE
) _get_osfhandle (pipe_stdout
? ifd
[1] :
298 prog_stdout
== NULL
? STDOUT_FILENO
: stdoutfd
);
301 HANDLE curr_process
= GetCurrentProcess ();
303 if (!DuplicateHandle (curr_process
, stdout_handle
,
304 curr_process
, &duplicate
,
305 0, TRUE
, DUPLICATE_SAME_ACCESS
))
307 errno
= EBADF
; /* arbitrary */
310 must_close_ifd1
= false;
311 close (ifd
[1]); /* implies CloseHandle (stdout_handle); */
312 stdout_handle
= duplicate
;
314 HANDLE stderr_handle
=
315 (HANDLE
) _get_osfhandle (null_stderr
? nulloutfd
: STDERR_FILENO
);
317 child
= spawnpvech (P_NOWAIT
, prog_path
, argv
+ 1,
318 (const char * const *) environ
, dll_dirs
,
320 stdin_handle
, stdout_handle
, stderr_handle
);
321 # if 0 /* Executing arbitrary files as shell scripts is unsecure. */
322 if (child
== -1 && errno
== ENOEXEC
)
324 /* prog is not a native executable. Try to execute it as a
325 shell script. Note that prepare_spawn() has already prepended
326 a hidden element "sh.exe" to argv. */
328 child
= spawnpvech (P_NOWAIT
, argv
[0], argv
,
329 (const char * const *) environ
, dll_dirs
,
331 stdin_handle
, stdout_handle
, stderr_handle
);
350 if (stdin_handle
!= INVALID_HANDLE_VALUE
)
351 CloseHandle (stdin_handle
);
358 if (stdout_handle
!= INVALID_HANDLE_VALUE
)
359 CloseHandle (stdout_handle
);
362 # else /* __KLIBC__ */
363 int new_stdin
= STDIN_FILENO
;
364 int new_stdout
= STDOUT_FILENO
;
365 int new_stderr
= STDERR_FILENO
;
367 /* Create standard file handles of child process. */
371 if ((!pipe_stdin
|| (new_stdin
= ofd
[0]) >= 0)
372 && (!pipe_stdout
|| (new_stdout
= ifd
[1]) >= 0)
374 || ((nulloutfd
= open ("NUL", O_RDWR
| O_CLOEXEC
, 0)) >= 0
375 && (new_stderr
= nulloutfd
) >= 0))
377 || prog_stdin
== NULL
378 || ((stdinfd
= open (prog_stdin
, O_RDONLY
| O_CLOEXEC
, 0)) >= 0
379 && (new_stdin
= stdinfd
) >= 0))
381 || prog_stdout
== NULL
382 || ((stdoutfd
= open (prog_stdout
, O_WRONLY
| O_CLOEXEC
, 0)) >= 0
383 && (new_stdout
= stdoutfd
) >= 0)))
384 /* The child process doesn't inherit ifd[0], ifd[1], ofd[0], ofd[1],
385 but it inherits all open()ed or dup2()ed file handles (which is what
386 we want in the case of STD*_FILENO). */
388 child
= spawnpvech (P_NOWAIT
, prog_path
, argv
+ 1,
389 (const char **) environ
, directory
,
390 new_stdin
, new_stdout
, new_stderr
);
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
= spawnpvech (P_NOWAIT
, argv
[0], argv
,
398 (const char **) environ
, directory
,
399 new_stdin
, new_stdout
, new_stderr
);
419 free (argv_mem_to_free
);
420 free (prog_path_to_free
);
428 goto fail_with_saved_errno
;
440 char **child_environ
;
441 char **malloced_environ
;
442 sigset_t blocked_signals
;
443 posix_spawn_file_actions_t actions
;
444 bool actions_allocated
;
445 posix_spawnattr_t attrs
;
446 bool attrs_allocated
;
450 child_environ
= environ
;
451 malloced_environ
= NULL
;
452 # if defined _WIN32 || defined __CYGWIN__
453 if (dll_dirs
!= NULL
&& dll_dirs
[0] != NULL
)
455 malloced_environ
= extended_environ (dll_dirs
);
456 if (malloced_environ
== NULL
)
457 goto fail_with_errno
;
458 child_environ
= malloced_environ
;
464 sigprocmask (SIG_SETMASK
, NULL
, &blocked_signals
);
465 block_fatal_signals ();
467 actions_allocated
= false;
468 attrs_allocated
= false;
469 if ((err
= posix_spawn_file_actions_init (&actions
)) != 0
470 || (actions_allocated
= true,
472 && (err
= posix_spawn_file_actions_adddup2 (&actions
,
473 ofd
[0], STDIN_FILENO
))
476 && (err
= posix_spawn_file_actions_adddup2 (&actions
,
477 ifd
[1], STDOUT_FILENO
))
480 && (err
= posix_spawn_file_actions_addclose (&actions
, ofd
[0]))
483 && (err
= posix_spawn_file_actions_addclose (&actions
, ifd
[1]))
486 && (err
= posix_spawn_file_actions_addclose (&actions
, ofd
[1]))
489 && (err
= posix_spawn_file_actions_addclose (&actions
, ifd
[0]))
492 && (err
= posix_spawn_file_actions_addopen (&actions
,
498 && prog_stdin
!= NULL
499 && (err
= posix_spawn_file_actions_addopen (&actions
,
501 prog_stdin
, O_RDONLY
,
505 && prog_stdout
!= NULL
506 && (err
= posix_spawn_file_actions_addopen (&actions
,
508 prog_stdout
, O_WRONLY
,
511 || (directory
!= NULL
512 && (err
= posix_spawn_file_actions_addchdir (&actions
,
515 && ((err
= posix_spawnattr_init (&attrs
)) != 0
516 || (attrs_allocated
= true,
517 # if defined _WIN32 && !defined __CYGWIN__
518 (err
= posix_spawnattr_setpgroup (&attrs
, 0)) != 0
519 || (err
= posix_spawnattr_setflags (&attrs
,
520 POSIX_SPAWN_SETPGROUP
))
523 (err
= posix_spawnattr_setsigmask (&attrs
,
526 || (err
= posix_spawnattr_setflags (&attrs
,
527 POSIX_SPAWN_SETSIGMASK
))
531 || (err
= (directory
!= NULL
532 ? posix_spawn (&child
, prog_path
, &actions
,
533 attrs_allocated
? &attrs
: NULL
,
534 (char * const *) prog_argv
,
536 : posix_spawnp (&child
, prog_path
, &actions
,
537 attrs_allocated
? &attrs
: NULL
,
538 (char * const *) prog_argv
,
542 if (actions_allocated
)
543 posix_spawn_file_actions_destroy (&actions
);
545 posix_spawnattr_destroy (&attrs
);
547 unblock_fatal_signals ();
548 if (malloced_environ
!= NULL
)
550 free (malloced_environ
[0]);
551 free (malloced_environ
);
563 free (prog_path_to_free
);
565 goto fail_with_saved_errno
;
567 posix_spawn_file_actions_destroy (&actions
);
569 posix_spawnattr_destroy (&attrs
);
572 register_slave_subprocess (child
);
573 unblock_fatal_signals ();
575 if (malloced_environ
!= NULL
)
577 free (malloced_environ
[0]);
578 free (malloced_environ
);
584 free (prog_path_to_free
);
596 fail_with_saved_errno
:
597 if (exit_on_error
|| !null_stderr
)
598 error (exit_on_error
? EXIT_FAILURE
: 0, saved_errno
,
599 _("%s subprocess failed"), progname
);
604 /* Open a bidirectional pipe.
607 * parent -> fd[1] -> STDIN_FILENO -> child
608 * parent <- fd[0] <- STDOUT_FILENO <- child
613 create_pipe_bidi (const char *progname
,
614 const char *prog_path
, const char * const *prog_argv
,
615 const char * const *dll_dirs
,
616 const char *directory
,
618 bool slave_process
, bool exit_on_error
,
621 pid_t result
= create_pipe (progname
, prog_path
, prog_argv
, dll_dirs
,
623 true, true, NULL
, NULL
,
624 null_stderr
, slave_process
, exit_on_error
,
629 /* Open a pipe for input from a child process.
630 * The child's stdin comes from a file.
633 * parent <- fd[0] <- STDOUT_FILENO <- child
637 create_pipe_in (const char *progname
,
638 const char *prog_path
, const char * const *prog_argv
,
639 const char * const *dll_dirs
,
640 const char *directory
,
641 const char *prog_stdin
, bool null_stderr
,
642 bool slave_process
, bool exit_on_error
,
646 pid_t result
= create_pipe (progname
, prog_path
, prog_argv
, dll_dirs
,
648 false, true, prog_stdin
, NULL
,
649 null_stderr
, slave_process
, exit_on_error
,
656 /* Open a pipe for output to a child process.
657 * The child's stdout goes to a file.
660 * parent -> fd[0] -> STDIN_FILENO -> child
664 create_pipe_out (const char *progname
,
665 const char *prog_path
, const char * const *prog_argv
,
666 const char * const *dll_dirs
,
667 const char *directory
,
668 const char *prog_stdout
, bool null_stderr
,
669 bool slave_process
, bool exit_on_error
,
673 pid_t result
= create_pipe (progname
, prog_path
, prog_argv
, dll_dirs
,
675 true, false, NULL
, prog_stdout
,
676 null_stderr
, slave_process
, exit_on_error
,