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.
4
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.
9
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.
14
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/>. */
17
18
19 /* Tell clang not to warn about the 'child' variable, below. */
20 #if defined __clang__
21 # pragma clang diagnostic ignored "-Wconditional-uninitialized"
22 #endif
23
24 #include <config.h>
25
26 /* Specification. */
27 #include "spawn-pipe.h"
28
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <stdlib.h>
32 #include <signal.h>
33 #include <unistd.h>
34
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"
44
45 #define _(str) gettext (str)
46
47
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
58
59
60 #if (defined _WIN32 && !defined __CYGWIN__) && SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN
61
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"
70
71 #elif defined __KLIBC__
72
73 /* OS/2 kLIBC API. */
74 # include <process.h>
75 # include "os2-spawn.h"
76
77 #else
78
79 /* Unix API. */
80 # include <spawn.h>
81
82 #endif
83
84
85 #ifdef EINTR
86
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. */
90
91 static int
92 nonintr_close (int fd)
93 {
94 int retval;
95
96 do
97 retval = close (fd);
98 while (retval < 0 && errno == EINTR);
99
100 return retval;
101 }
102 #undef close /* avoid warning related to gnulib module unistd */
103 #define close nonintr_close
104
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)
108 {
109 int retval;
110
111 do
112 retval = open (pathname, oflag, mode);
113 while (retval < 0 && errno == EINTR);
114
115 return retval;
116 }
117 # undef open /* avoid warning on VMS */
118 # define open nonintr_open
119 #endif
120
121 #endif
122
123
124 /* Open a pipe connected to a child process.
125 *
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
130 *
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.
136 */
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])
147 {
148 int saved_errno;
149 char *prog_path_to_free = NULL;
150
151 if (directory != NULL)
152 {
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))
168 {
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;
176
177 if (! IS_ABSOLUTE_FILE_NAME (prog_path))
178 {
179 char *absolute_prog =
180 canonicalize_filename_mode (prog_path, CAN_MISSING | CAN_NOLINKS);
181 if (absolute_prog == NULL)
182 {
183 free (prog_path_to_free);
184 goto fail_with_errno;
185 }
186 free (prog_path_to_free);
187 prog_path_to_free = absolute_prog;
188 prog_path = absolute_prog;
189
190 if (! IS_ABSOLUTE_FILE_NAME (prog_path))
191 abort ();
192 }
193 }
194 }
195
196 #if ((defined _WIN32 && !defined __CYGWIN__) && SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN) || defined __KLIBC__
197
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;
204 int ifd[2];
205 int ofd[2];
206 int child;
207 int nulloutfd;
208 int stdinfd;
209 int stdoutfd;
210
211 const char **argv = prepare_spawn (prog_argv, &argv_mem_to_free);
212 if (argv == NULL)
213 xalloc_die ();
214
215 if (pipe_stdout)
216 if (pipe2_safer (ifd, O_BINARY | O_CLOEXEC) < 0)
217 error (EXIT_FAILURE, errno, _("cannot create pipe"));
218 if (pipe_stdin)
219 if (pipe2_safer (ofd, O_BINARY | O_CLOEXEC) < 0)
220 error (EXIT_FAILURE, errno, _("cannot create pipe"));
221 /* Data flow diagram:
222 *
223 * write system read
224 * parent -> ofd[1] -> ofd[0] -> child if pipe_stdin
225 * parent <- ifd[0] <- ifd[1] <- child if pipe_stdout
226 * read system write
227 *
228 */
229
230 child = -1;
231
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;
235
236 /* Create standard file handles of child process. */
237 HANDLE stdin_handle = INVALID_HANDLE_VALUE;
238 HANDLE stdout_handle = INVALID_HANDLE_VALUE;
239 nulloutfd = -1;
240 stdinfd = -1;
241 stdoutfd = -1;
242 if ((!null_stderr
243 || (nulloutfd = open ("NUL", O_RDWR, 0)) >= 0)
244 && (pipe_stdin
245 || prog_stdin == NULL
246 || (stdinfd = open (prog_stdin, O_RDONLY, 0)) >= 0)
247 && (pipe_stdout
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(). */
259 {
260 stdin_handle =
261 (HANDLE) _get_osfhandle (pipe_stdin ? ofd[0] :
262 prog_stdin == NULL ? STDIN_FILENO : stdinfd);
263 if (pipe_stdin)
264 {
265 HANDLE curr_process = GetCurrentProcess ();
266 HANDLE duplicate;
267 if (!DuplicateHandle (curr_process, stdin_handle,
268 curr_process, &duplicate,
269 0, TRUE, DUPLICATE_SAME_ACCESS))
270 {
271 errno = EBADF; /* arbitrary */
272 goto failed;
273 }
274 must_close_ofd0 = false;
275 close (ofd[0]); /* implies CloseHandle (stdin_handle); */
276 stdin_handle = duplicate;
277 }
278 stdout_handle =
279 (HANDLE) _get_osfhandle (pipe_stdout ? ifd[1] :
280 prog_stdout == NULL ? STDOUT_FILENO : stdoutfd);
281 if (pipe_stdout)
282 {
283 HANDLE curr_process = GetCurrentProcess ();
284 HANDLE duplicate;
285 if (!DuplicateHandle (curr_process, stdout_handle,
286 curr_process, &duplicate,
287 0, TRUE, DUPLICATE_SAME_ACCESS))
288 {
289 errno = EBADF; /* arbitrary */
290 goto failed;
291 }
292 must_close_ifd1 = false;
293 close (ifd[1]); /* implies CloseHandle (stdout_handle); */
294 stdout_handle = duplicate;
295 }
296 HANDLE stderr_handle =
297 (HANDLE) _get_osfhandle (null_stderr ? nulloutfd : STDERR_FILENO);
298
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)
304 {
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. */
308 argv[1] = prog_path;
309 child = spawnpvech (P_NOWAIT, argv[0], argv,
310 (const char * const *) environ, directory,
311 stdin_handle, stdout_handle, stderr_handle);
312 }
313 # endif
314 }
315 failed:
316 if (child == -1)
317 saved_errno = errno;
318 if (stdinfd >= 0)
319 close (stdinfd);
320 if (stdoutfd >= 0)
321 close (stdoutfd);
322 if (nulloutfd >= 0)
323 close (nulloutfd);
324
325 if (pipe_stdin)
326 {
327 if (must_close_ofd0)
328 close (ofd[0]);
329 else
330 if (stdin_handle != INVALID_HANDLE_VALUE)
331 CloseHandle (stdin_handle);
332 }
333 if (pipe_stdout)
334 {
335 if (must_close_ifd1)
336 close (ifd[1]);
337 else
338 if (stdout_handle != INVALID_HANDLE_VALUE)
339 CloseHandle (stdout_handle);
340 }
341
342 # else /* __KLIBC__ */
343 if (!(directory == NULL || strcmp (directory, ".") == 0))
344 {
345 /* A directory argument is not supported in this implementation. */
346 saved_errno = EINVAL;
347 goto fail_with_saved_errno;
348 }
349
350 int orig_stdin;
351 int orig_stdout;
352 int orig_stderr;
353
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);
359 if (null_stderr)
360 orig_stderr = dup_safer_noinherit (STDERR_FILENO);
361
362 /* Create standard file handles of child process. */
363 nulloutfd = -1;
364 stdinfd = -1;
365 stdoutfd = -1;
366 if ((!pipe_stdin || dup2 (ofd[0], STDIN_FILENO) >= 0)
367 && (!pipe_stdout || dup2 (ifd[1], STDOUT_FILENO) >= 0)
368 && (!null_stderr
369 || ((nulloutfd = open ("NUL", O_RDWR, 0)) >= 0
370 && (nulloutfd == STDERR_FILENO
371 || (dup2 (nulloutfd, STDERR_FILENO) >= 0
372 && close (nulloutfd) >= 0))))
373 && (pipe_stdin
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))))
379 && (pipe_stdout
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). */
388 {
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)
393 {
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);
399 }
400 # endif
401 }
402 if (child == -1)
403 saved_errno = errno;
404 if (stdinfd >= 0)
405 close (stdinfd);
406 if (stdoutfd >= 0)
407 close (stdoutfd);
408 if (nulloutfd >= 0)
409 close (nulloutfd);
410
411 /* Restore standard file handles of parent process. */
412 if (null_stderr)
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);
418
419 if (pipe_stdin)
420 close (ofd[0]);
421 if (pipe_stdout)
422 close (ifd[1]);
423 # endif
424
425 free (argv);
426 free (argv_mem_to_free);
427 free (prog_path_to_free);
428
429 if (child == -1)
430 {
431 if (pipe_stdout)
432 close (ifd[0]);
433 if (pipe_stdin)
434 close (ofd[1]);
435 goto fail_with_saved_errno;
436 }
437
438 if (pipe_stdout)
439 fd[0] = ifd[0];
440 if (pipe_stdin)
441 fd[1] = ofd[1];
442 return child;
443
444 #else
445
446 /* Unix API. */
447 int ifd[2];
448 int ofd[2];
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;
454 int err;
455 pid_t child;
456
457 if (pipe_stdout)
458 if (pipe_safer (ifd) < 0)
459 error (EXIT_FAILURE, errno, _("cannot create pipe"));
460 if (pipe_stdin)
461 if (pipe_safer (ofd) < 0)
462 error (EXIT_FAILURE, errno, _("cannot create pipe"));
463 /* Data flow diagram:
464 *
465 * write system read
466 * parent -> ofd[1] -> ofd[0] -> child if pipe_stdin
467 * parent <- ifd[0] <- ifd[1] <- child if pipe_stdout
468 * read system write
469 *
470 */
471
472 if (slave_process)
473 {
474 sigprocmask (SIG_SETMASK, NULL, &blocked_signals);
475 block_fatal_signals ();
476 }
477 actions_allocated = false;
478 attrs_allocated = false;
479 if ((err = posix_spawn_file_actions_init (&actions)) != 0
480 || (actions_allocated = true,
481 (pipe_stdin
482 && (err = posix_spawn_file_actions_adddup2 (&actions,
483 ofd[0], STDIN_FILENO))
484 != 0)
485 || (pipe_stdout
486 && (err = posix_spawn_file_actions_adddup2 (&actions,
487 ifd[1], STDOUT_FILENO))
488 != 0)
489 || (pipe_stdin
490 && (err = posix_spawn_file_actions_addclose (&actions, ofd[0]))
491 != 0)
492 || (pipe_stdout
493 && (err = posix_spawn_file_actions_addclose (&actions, ifd[1]))
494 != 0)
495 || (pipe_stdin
496 && (err = posix_spawn_file_actions_addclose (&actions, ofd[1]))
497 != 0)
498 || (pipe_stdout
499 && (err = posix_spawn_file_actions_addclose (&actions, ifd[0]))
500 != 0)
501 || (null_stderr
502 && (err = posix_spawn_file_actions_addopen (&actions,
503 STDERR_FILENO,
504 "/dev/null", O_RDWR,
505 0))
506 != 0)
507 || (!pipe_stdin
508 && prog_stdin != NULL
509 && (err = posix_spawn_file_actions_addopen (&actions,
510 STDIN_FILENO,
511 prog_stdin, O_RDONLY,
512 0))
513 != 0)
514 || (!pipe_stdout
515 && prog_stdout != NULL
516 && (err = posix_spawn_file_actions_addopen (&actions,
517 STDOUT_FILENO,
518 prog_stdout, O_WRONLY,
519 0))
520 != 0)
521 || (directory != NULL
522 && (err = posix_spawn_file_actions_addchdir (&actions,
523 directory)))
524 || (slave_process
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))
531 != 0
532 # else
533 (err = posix_spawnattr_setsigmask (&attrs,
534 &blocked_signals))
535 != 0
536 || (err = posix_spawnattr_setflags (&attrs,
537 POSIX_SPAWN_SETSIGMASK))
538 != 0
539 # endif
540 ) ) )
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)))
548 != 0))
549 {
550 if (actions_allocated)
551 posix_spawn_file_actions_destroy (&actions);
552 if (attrs_allocated)
553 posix_spawnattr_destroy (&attrs);
554 if (slave_process)
555 unblock_fatal_signals ();
556 if (pipe_stdout)
557 {
558 close (ifd[0]);
559 close (ifd[1]);
560 }
561 if (pipe_stdin)
562 {
563 close (ofd[0]);
564 close (ofd[1]);
565 }
566 free (prog_path_to_free);
567 saved_errno = err;
568 goto fail_with_saved_errno;
569 }
570 posix_spawn_file_actions_destroy (&actions);
571 if (attrs_allocated)
572 posix_spawnattr_destroy (&attrs);
573 if (slave_process)
574 {
575 register_slave_subprocess (child);
576 unblock_fatal_signals ();
577 }
578 if (pipe_stdin)
579 close (ofd[0]);
580 if (pipe_stdout)
581 close (ifd[1]);
582 free (prog_path_to_free);
583
584 if (pipe_stdout)
585 fd[0] = ifd[0];
586 if (pipe_stdin)
587 fd[1] = ofd[1];
588 return child;
589
590 #endif
591
592 fail_with_errno:
593 saved_errno = errno;
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);
598 errno = saved_errno;
599 return -1;
600 }
601
602 /* Open a bidirectional pipe.
603 *
604 * write system read
605 * parent -> fd[1] -> STDIN_FILENO -> child
606 * parent <- fd[0] <- STDOUT_FILENO <- child
607 * read system write
608 *
609 */
610 pid_t
611 create_pipe_bidi (const char *progname,
612 const char *prog_path, const char * const *prog_argv,
613 const char *directory,
614 bool null_stderr,
615 bool slave_process, bool exit_on_error,
616 int fd[2])
617 {
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,
621 fd);
622 return result;
623 }
624
625 /* Open a pipe for input from a child process.
626 * The child's stdin comes from a file.
627 *
628 * read system write
629 * parent <- fd[0] <- STDOUT_FILENO <- child
630 *
631 */
632 pid_t
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,
638 int fd[1])
639 {
640 int iofd[2];
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,
644 iofd);
645 if (result != -1)
646 fd[0] = iofd[0];
647 return result;
648 }
649
650 /* Open a pipe for output to a child process.
651 * The child's stdout goes to a file.
652 *
653 * write system read
654 * parent -> fd[0] -> STDIN_FILENO -> child
655 *
656 */
657 pid_t
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,
663 int fd[1])
664 {
665 int iofd[2];
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,
669 iofd);
670 if (result != -1)
671 fd[0] = iofd[1];
672 return result;
673 }