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. */
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
))
199 /* It is important to create the file descriptors with the close-on-exec bit
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
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. */
215 if (pipe2_safer (ifd
, O_BINARY
| O_CLOEXEC
) < 0)
216 error (EXIT_FAILURE
, errno
, _("cannot create pipe"));
218 if (pipe2_safer (ofd
, O_BINARY
| O_CLOEXEC
) < 0)
219 error (EXIT_FAILURE
, errno
, _("cannot create pipe"));
220 /* Data flow diagram:
223 * parent -> ofd[1] -> ofd[0] -> child if pipe_stdin
224 * parent <- ifd[0] <- ifd[1] <- child if pipe_stdout
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
;
242 const char **argv
= prepare_spawn (prog_argv
, &argv_mem_to_free
);
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
;
259 || (nulloutfd
= open ("NUL", O_RDWR
, 0)) >= 0)
261 || prog_stdin
== NULL
262 || (stdinfd
= open (prog_stdin
, O_RDONLY
, 0)) >= 0)
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(). */
277 (HANDLE
) _get_osfhandle (pipe_stdin
? ofd
[0] :
278 prog_stdin
== NULL
? STDIN_FILENO
: stdinfd
);
281 HANDLE curr_process
= GetCurrentProcess ();
283 if (!DuplicateHandle (curr_process
, stdin_handle
,
284 curr_process
, &duplicate
,
285 0, TRUE
, DUPLICATE_SAME_ACCESS
))
287 errno
= EBADF
; /* arbitrary */
290 must_close_ofd0
= false;
291 close (ofd
[0]); /* implies CloseHandle (stdin_handle); */
292 stdin_handle
= duplicate
;
295 (HANDLE
) _get_osfhandle (pipe_stdout
? ifd
[1] :
296 prog_stdout
== NULL
? STDOUT_FILENO
: stdoutfd
);
299 HANDLE curr_process
= GetCurrentProcess ();
301 if (!DuplicateHandle (curr_process
, stdout_handle
,
302 curr_process
, &duplicate
,
303 0, TRUE
, DUPLICATE_SAME_ACCESS
))
305 errno
= EBADF
; /* arbitrary */
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. */
325 child
= spawnpvech (P_NOWAIT
, argv
[0], argv
,
326 (const char * const *) environ
, directory
,
327 stdin_handle
, stdout_handle
, stderr_handle
);
346 if (stdin_handle
!= INVALID_HANDLE_VALUE
)
347 CloseHandle (stdin_handle
);
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
;
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
);
376 orig_stderr
= dup_safer_noinherit (STDERR_FILENO
);
378 /* Create standard file handles of child process. */
382 if ((!pipe_stdin
|| dup2 (ofd
[0], STDIN_FILENO
) >= 0)
383 && (!pipe_stdout
|| dup2 (ifd
[1], STDOUT_FILENO
) >= 0)
385 || ((nulloutfd
= open ("NUL", O_RDWR
, 0)) >= 0
386 && (nulloutfd
== STDERR_FILENO
387 || (dup2 (nulloutfd
, STDERR_FILENO
) >= 0
388 && close (nulloutfd
) >= 0))))
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))))
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
);
427 /* Restore standard file handles of parent process. */
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
);
442 free (argv_mem_to_free
);
443 free (prog_path_to_free
);
451 goto fail_with_saved_errno
;
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
;
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,
481 && (err
= posix_spawn_file_actions_adddup2 (&actions
,
482 ofd
[0], STDIN_FILENO
))
485 && (err
= posix_spawn_file_actions_adddup2 (&actions
,
486 ifd
[1], STDOUT_FILENO
))
489 && (err
= posix_spawn_file_actions_addclose (&actions
, ofd
[0]))
492 && (err
= posix_spawn_file_actions_addclose (&actions
, ifd
[1]))
495 && (err
= posix_spawn_file_actions_addclose (&actions
, ofd
[1]))
498 && (err
= posix_spawn_file_actions_addclose (&actions
, ifd
[0]))
501 && (err
= posix_spawn_file_actions_addopen (&actions
,
507 && prog_stdin
!= NULL
508 && (err
= posix_spawn_file_actions_addopen (&actions
,
510 prog_stdin
, O_RDONLY
,
514 && prog_stdout
!= NULL
515 && (err
= posix_spawn_file_actions_addopen (&actions
,
517 prog_stdout
, O_WRONLY
,
520 || (directory
!= NULL
521 && (err
= posix_spawn_file_actions_addchdir (&actions
,
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
))
532 (err
= posix_spawnattr_setsigmask (&attrs
,
535 || (err
= posix_spawnattr_setflags (&attrs
,
536 POSIX_SPAWN_SETSIGMASK
))
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
)))
549 if (actions_allocated
)
550 posix_spawn_file_actions_destroy (&actions
);
552 posix_spawnattr_destroy (&attrs
);
554 unblock_fatal_signals ();
565 free (prog_path_to_free
);
567 goto fail_with_saved_errno
;
569 posix_spawn_file_actions_destroy (&actions
);
571 posix_spawnattr_destroy (&attrs
);
574 register_slave_subprocess (child
);
575 unblock_fatal_signals ();
581 free (prog_path_to_free
);
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
);
601 /* Open a bidirectional pipe.
604 * parent -> fd[1] -> STDIN_FILENO -> child
605 * parent <- fd[0] <- STDOUT_FILENO <- child
610 create_pipe_bidi (const char *progname
,
611 const char *prog_path
, const char * const *prog_argv
,
612 const char *directory
,
614 bool slave_process
, bool exit_on_error
,
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
,
624 /* Open a pipe for input from a child process.
625 * The child's stdin comes from a file.
628 * parent <- fd[0] <- STDOUT_FILENO <- child
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
,
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
,
649 /* Open a pipe for output to a child process.
650 * The child's stdout goes to a file.
653 * parent -> fd[0] -> STDIN_FILENO -> child
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
,
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
,