Fix last ChangeLog entry.
[gnulib.git] / lib / spawn-pipe.c
blob098352e2d506809eef29b5b31aa7ec339b770e5d
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. */
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 "windows-path.h"
41 #include "unistd-safer.h"
42 #include "wait-process.h"
43 #include "xalloc.h"
44 #include "gettext.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'
53 directly.
54 You can set this macro from a Makefile or at configure time, from the
55 CPPFLAGS. */
56 #ifndef SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN
57 # define SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN 0
58 #endif
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"
66 # else
67 # include <io.h>
68 # endif
69 # include <process.h>
70 # include "windows-spawn.h"
72 #elif defined __KLIBC__
74 /* OS/2 kLIBC API. */
75 # include <process.h>
76 # include "os2-spawn.h"
78 #else
80 /* Unix API. */
81 # include <spawn.h>
83 #endif
86 #ifdef EINTR
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. */
92 static int
93 nonintr_close (int fd)
95 int retval;
98 retval = close (fd);
99 while (retval < 0 && errno == EINTR);
101 return retval;
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
107 static int
108 nonintr_open (const char *pathname, int oflag, mode_t mode)
110 int retval;
113 retval = open (pathname, oflag, mode);
114 while (retval < 0 && errno == EINTR);
116 return retval;
118 # undef open /* avoid warning on VMS */
119 # define open nonintr_open
120 #endif
122 #endif
125 /* Open a pipe connected to a child process.
127 * write system read
128 * parent -> fd[1] -> STDIN_FILENO -> child if pipe_stdin
129 * parent <- fd[0] <- STDOUT_FILENO <- child if pipe_stdout
130 * read system write
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.
138 static pid_t
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,
146 bool null_stderr,
147 bool slave_process, bool exit_on_error,
148 int fd[2])
150 int saved_errno;
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))
193 abort ();
198 int ifd[2];
199 int ofd[2];
201 /* It is important to create the file descriptors with the close-on-exec bit
202 set.
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
209 calls.
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. */
216 if (pipe_stdout)
217 if (pipe2_safer (ifd, O_BINARY | O_CLOEXEC) < 0)
218 error (EXIT_FAILURE, errno, _("cannot create pipe"));
219 if (pipe_stdin)
220 if (pipe2_safer (ofd, O_BINARY | O_CLOEXEC) < 0)
221 error (EXIT_FAILURE, errno, _("cannot create pipe"));
222 /* Data flow diagram:
224 * write system read
225 * parent -> ofd[1] -> ofd[0] -> child if pipe_stdin
226 * parent <- ifd[0] <- ifd[1] <- child if pipe_stdout
227 * read system write
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;
239 int child;
240 int nulloutfd;
241 int stdinfd;
242 int stdoutfd;
244 const char **argv = prepare_spawn (prog_argv, &argv_mem_to_free);
245 if (argv == NULL)
246 xalloc_die ();
248 child = -1;
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;
257 nulloutfd = -1;
258 stdinfd = -1;
259 stdoutfd = -1;
260 if ((!null_stderr
261 || (nulloutfd = open ("NUL", O_RDWR, 0)) >= 0)
262 && (pipe_stdin
263 || prog_stdin == NULL
264 || (stdinfd = open (prog_stdin, O_RDONLY, 0)) >= 0)
265 && (pipe_stdout
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(). */
278 stdin_handle =
279 (HANDLE) _get_osfhandle (pipe_stdin ? ofd[0] :
280 prog_stdin == NULL ? STDIN_FILENO : stdinfd);
281 if (pipe_stdin)
283 HANDLE curr_process = GetCurrentProcess ();
284 HANDLE duplicate;
285 if (!DuplicateHandle (curr_process, stdin_handle,
286 curr_process, &duplicate,
287 0, TRUE, DUPLICATE_SAME_ACCESS))
289 errno = EBADF; /* arbitrary */
290 goto failed;
292 must_close_ofd0 = false;
293 close (ofd[0]); /* implies CloseHandle (stdin_handle); */
294 stdin_handle = duplicate;
296 stdout_handle =
297 (HANDLE) _get_osfhandle (pipe_stdout ? ifd[1] :
298 prog_stdout == NULL ? STDOUT_FILENO : stdoutfd);
299 if (pipe_stdout)
301 HANDLE curr_process = GetCurrentProcess ();
302 HANDLE duplicate;
303 if (!DuplicateHandle (curr_process, stdout_handle,
304 curr_process, &duplicate,
305 0, TRUE, DUPLICATE_SAME_ACCESS))
307 errno = EBADF; /* arbitrary */
308 goto failed;
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,
319 directory,
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. */
327 argv[1] = prog_path;
328 child = spawnpvech (P_NOWAIT, argv[0], argv,
329 (const char * const *) environ, dll_dirs,
330 directory,
331 stdin_handle, stdout_handle, stderr_handle);
333 # endif
335 failed:
336 if (child == -1)
337 saved_errno = errno;
338 if (stdinfd >= 0)
339 close (stdinfd);
340 if (stdoutfd >= 0)
341 close (stdoutfd);
342 if (nulloutfd >= 0)
343 close (nulloutfd);
345 if (pipe_stdin)
347 if (must_close_ofd0)
348 close (ofd[0]);
349 else
350 if (stdin_handle != INVALID_HANDLE_VALUE)
351 CloseHandle (stdin_handle);
353 if (pipe_stdout)
355 if (must_close_ifd1)
356 close (ifd[1]);
357 else
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. */
368 nulloutfd = -1;
369 stdinfd = -1;
370 stdoutfd = -1;
371 if ((!pipe_stdin || (new_stdin = ofd[0]) >= 0)
372 && (!pipe_stdout || (new_stdout = ifd[1]) >= 0)
373 && (!null_stderr
374 || ((nulloutfd = open ("NUL", O_RDWR | O_CLOEXEC, 0)) >= 0
375 && (new_stderr = nulloutfd) >= 0))
376 && (pipe_stdin
377 || prog_stdin == NULL
378 || ((stdinfd = open (prog_stdin, O_RDONLY | O_CLOEXEC, 0)) >= 0
379 && (new_stdin = stdinfd) >= 0))
380 && (pipe_stdout
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);
401 # endif
403 if (child == -1)
404 saved_errno = errno;
405 if (stdinfd >= 0)
406 close (stdinfd);
407 if (stdoutfd >= 0)
408 close (stdoutfd);
409 if (nulloutfd >= 0)
410 close (nulloutfd);
412 if (pipe_stdin)
413 close (ofd[0]);
414 if (pipe_stdout)
415 close (ifd[1]);
416 # endif
418 free (argv);
419 free (argv_mem_to_free);
420 free (prog_path_to_free);
422 if (child == -1)
424 if (pipe_stdout)
425 close (ifd[0]);
426 if (pipe_stdin)
427 close (ofd[1]);
428 goto fail_with_saved_errno;
431 if (pipe_stdout)
432 fd[0] = ifd[0];
433 if (pipe_stdin)
434 fd[1] = ofd[1];
435 return child;
437 #else
439 /* Unix API. */
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;
447 int err;
448 pid_t child;
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;
460 # endif
462 if (slave_process)
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,
471 (pipe_stdin
472 && (err = posix_spawn_file_actions_adddup2 (&actions,
473 ofd[0], STDIN_FILENO))
474 != 0)
475 || (pipe_stdout
476 && (err = posix_spawn_file_actions_adddup2 (&actions,
477 ifd[1], STDOUT_FILENO))
478 != 0)
479 || (pipe_stdin
480 && (err = posix_spawn_file_actions_addclose (&actions, ofd[0]))
481 != 0)
482 || (pipe_stdout
483 && (err = posix_spawn_file_actions_addclose (&actions, ifd[1]))
484 != 0)
485 || (pipe_stdin
486 && (err = posix_spawn_file_actions_addclose (&actions, ofd[1]))
487 != 0)
488 || (pipe_stdout
489 && (err = posix_spawn_file_actions_addclose (&actions, ifd[0]))
490 != 0)
491 || (null_stderr
492 && (err = posix_spawn_file_actions_addopen (&actions,
493 STDERR_FILENO,
494 "/dev/null", O_RDWR,
496 != 0)
497 || (!pipe_stdin
498 && prog_stdin != NULL
499 && (err = posix_spawn_file_actions_addopen (&actions,
500 STDIN_FILENO,
501 prog_stdin, O_RDONLY,
503 != 0)
504 || (!pipe_stdout
505 && prog_stdout != NULL
506 && (err = posix_spawn_file_actions_addopen (&actions,
507 STDOUT_FILENO,
508 prog_stdout, O_WRONLY,
510 != 0)
511 || (directory != NULL
512 && (err = posix_spawn_file_actions_addchdir (&actions,
513 directory)))
514 || (slave_process
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))
521 != 0
522 # else
523 (err = posix_spawnattr_setsigmask (&attrs,
524 &blocked_signals))
525 != 0
526 || (err = posix_spawnattr_setflags (&attrs,
527 POSIX_SPAWN_SETSIGMASK))
528 != 0
529 # endif
530 ) ) )
531 || (err = (directory != NULL
532 ? posix_spawn (&child, prog_path, &actions,
533 attrs_allocated ? &attrs : NULL,
534 (char * const *) prog_argv,
535 child_environ)
536 : posix_spawnp (&child, prog_path, &actions,
537 attrs_allocated ? &attrs : NULL,
538 (char * const *) prog_argv,
539 child_environ)))
540 != 0))
542 if (actions_allocated)
543 posix_spawn_file_actions_destroy (&actions);
544 if (attrs_allocated)
545 posix_spawnattr_destroy (&attrs);
546 if (slave_process)
547 unblock_fatal_signals ();
548 if (malloced_environ != NULL)
550 free (malloced_environ[0]);
551 free (malloced_environ);
553 if (pipe_stdout)
555 close (ifd[0]);
556 close (ifd[1]);
558 if (pipe_stdin)
560 close (ofd[0]);
561 close (ofd[1]);
563 free (prog_path_to_free);
564 saved_errno = err;
565 goto fail_with_saved_errno;
567 posix_spawn_file_actions_destroy (&actions);
568 if (attrs_allocated)
569 posix_spawnattr_destroy (&attrs);
570 if (slave_process)
572 register_slave_subprocess (child);
573 unblock_fatal_signals ();
575 if (malloced_environ != NULL)
577 free (malloced_environ[0]);
578 free (malloced_environ);
580 if (pipe_stdin)
581 close (ofd[0]);
582 if (pipe_stdout)
583 close (ifd[1]);
584 free (prog_path_to_free);
586 if (pipe_stdout)
587 fd[0] = ifd[0];
588 if (pipe_stdin)
589 fd[1] = ofd[1];
590 return child;
592 #endif
594 fail_with_errno:
595 saved_errno = errno;
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);
600 errno = saved_errno;
601 return -1;
604 /* Open a bidirectional pipe.
606 * write system read
607 * parent -> fd[1] -> STDIN_FILENO -> child
608 * parent <- fd[0] <- STDOUT_FILENO <- child
609 * read system write
612 pid_t
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,
617 bool null_stderr,
618 bool slave_process, bool exit_on_error,
619 int fd[2])
621 pid_t result = create_pipe (progname, prog_path, prog_argv, dll_dirs,
622 directory,
623 true, true, NULL, NULL,
624 null_stderr, slave_process, exit_on_error,
625 fd);
626 return result;
629 /* Open a pipe for input from a child process.
630 * The child's stdin comes from a file.
632 * read system write
633 * parent <- fd[0] <- STDOUT_FILENO <- child
636 pid_t
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,
643 int fd[1])
645 int iofd[2];
646 pid_t result = create_pipe (progname, prog_path, prog_argv, dll_dirs,
647 directory,
648 false, true, prog_stdin, NULL,
649 null_stderr, slave_process, exit_on_error,
650 iofd);
651 if (result != -1)
652 fd[0] = iofd[0];
653 return result;
656 /* Open a pipe for output to a child process.
657 * The child's stdout goes to a file.
659 * write system read
660 * parent -> fd[0] -> STDIN_FILENO -> child
663 pid_t
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,
670 int fd[1])
672 int iofd[2];
673 pid_t result = create_pipe (progname, prog_path, prog_argv, dll_dirs,
674 directory,
675 true, false, NULL, prog_stdout,
676 null_stderr, slave_process, exit_on_error,
677 iofd);
678 if (result != -1)
679 fd[0] = iofd[1];
680 return result;