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
nonintr_close(int fd)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
nonintr_open(const char * pathname,int oflag,mode_t mode)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
create_pipe(const char * progname,const char * prog_path,const char * const * prog_argv,const char * directory,bool pipe_stdin,bool pipe_stdout,const char * prog_stdin,const char * prog_stdout,bool null_stderr,bool slave_process,bool exit_on_error,int fd[2])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                   saved_errno = errno;
184                   free (prog_path_to_free);
185                   goto fail_with_saved_errno;
186                 }
187               free (prog_path_to_free);
188               prog_path_to_free = absolute_prog;
189               prog_path = absolute_prog;
190 
191               if (! IS_ABSOLUTE_FILE_NAME (prog_path))
192                 abort ();
193             }
194         }
195     }
196 
197 #if ((defined _WIN32 && !defined __CYGWIN__) && SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN) || defined __KLIBC__
198 
199   /* Native Windows API.
200      This uses _pipe(), dup2(), and _spawnv().  It could also be implemented
201      using the low-level functions CreatePipe(), DuplicateHandle(),
202      CreateProcess() and _open_osfhandle(); see the GNU make and GNU clisp
203      and cvs source code.  */
204   char *argv_mem_to_free;
205   int ifd[2];
206   int ofd[2];
207   int child;
208   int nulloutfd;
209   int stdinfd;
210   int stdoutfd;
211 
212   const char **argv = prepare_spawn (prog_argv, &argv_mem_to_free);
213   if (argv == NULL)
214     xalloc_die ();
215 
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:
223  *
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
228  *
229  */
230 
231   child = -1;
232 
233 # if (defined _WIN32 && !defined __CYGWIN__) && SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN
234   bool must_close_ifd1 = pipe_stdout;
235   bool must_close_ofd0 = pipe_stdin;
236 
237   /* Create standard file handles of child process.  */
238   HANDLE stdin_handle = INVALID_HANDLE_VALUE;
239   HANDLE stdout_handle = INVALID_HANDLE_VALUE;
240   nulloutfd = -1;
241   stdinfd = -1;
242   stdoutfd = -1;
243   if ((!null_stderr
244        || (nulloutfd = open ("NUL", O_RDWR, 0)) >= 0)
245       && (pipe_stdin
246           || prog_stdin == NULL
247           || (stdinfd = open (prog_stdin, O_RDONLY, 0)) >= 0)
248       && (pipe_stdout
249           || prog_stdout == NULL
250           || (stdoutfd = open (prog_stdout, O_WRONLY, 0)) >= 0))
251     /* The child process doesn't inherit ifd[0], ifd[1], ofd[0], ofd[1],
252        but it inherits the three STD*_FILENO for which we pass the handles.  */
253     /* Pass the environment explicitly.  This is needed if the program has
254        modified the environment using putenv() or [un]setenv().  On Windows,
255        processes have two environments, one in the "environment block" of the
256        process and managed through SetEnvironmentVariable(), and one inside the
257        process, in the location retrieved by the 'environ' macro.  If we were
258        to pass NULL, the child process would inherit a copy of the environment
259        block - ignoring the effects of putenv() and [un]setenv().  */
260     {
261       stdin_handle =
262         (HANDLE) _get_osfhandle (pipe_stdin ? ofd[0] :
263                                  prog_stdin == NULL ? STDIN_FILENO : stdinfd);
264       if (pipe_stdin)
265         {
266           HANDLE curr_process = GetCurrentProcess ();
267           HANDLE duplicate;
268           if (!DuplicateHandle (curr_process, stdin_handle,
269                                 curr_process, &duplicate,
270                                 0, TRUE, DUPLICATE_SAME_ACCESS))
271             {
272               errno = EBADF; /* arbitrary */
273               goto failed;
274             }
275           must_close_ofd0 = false;
276           close (ofd[0]); /* implies CloseHandle (stdin_handle); */
277           stdin_handle = duplicate;
278         }
279       stdout_handle =
280         (HANDLE) _get_osfhandle (pipe_stdout ? ifd[1] :
281                                  prog_stdout == NULL ? STDOUT_FILENO : stdoutfd);
282       if (pipe_stdout)
283         {
284           HANDLE curr_process = GetCurrentProcess ();
285           HANDLE duplicate;
286           if (!DuplicateHandle (curr_process, stdout_handle,
287                                 curr_process, &duplicate,
288                                 0, TRUE, DUPLICATE_SAME_ACCESS))
289             {
290               errno = EBADF; /* arbitrary */
291               goto failed;
292             }
293           must_close_ifd1 = false;
294           close (ifd[1]); /* implies CloseHandle (stdout_handle); */
295           stdout_handle = duplicate;
296         }
297       HANDLE stderr_handle =
298         (HANDLE) _get_osfhandle (null_stderr ? nulloutfd : STDERR_FILENO);
299 
300       child = spawnpvech (P_NOWAIT, prog_path, argv + 1,
301                           (const char * const *) environ, directory,
302                           stdin_handle, stdout_handle, stderr_handle);
303 #  if 0 /* Executing arbitrary files as shell scripts is unsecure.  */
304       if (child == -1 && errno == ENOEXEC)
305         {
306           /* prog is not a native executable.  Try to execute it as a
307              shell script.  Note that prepare_spawn() has already prepended
308              a hidden element "sh.exe" to argv.  */
309           argv[1] = prog_path;
310           child = spawnpvech (P_NOWAIT, argv[0], argv,
311                               (const char * const *) environ, directory,
312                               stdin_handle, stdout_handle, stderr_handle);
313         }
314 #  endif
315     }
316  failed:
317   if (child == -1)
318     saved_errno = errno;
319   if (stdinfd >= 0)
320     close (stdinfd);
321   if (stdoutfd >= 0)
322     close (stdoutfd);
323   if (nulloutfd >= 0)
324     close (nulloutfd);
325 
326   if (pipe_stdin)
327     {
328       if (must_close_ofd0)
329         close (ofd[0]);
330       else
331         if (stdin_handle != INVALID_HANDLE_VALUE)
332           CloseHandle (stdin_handle);
333     }
334   if (pipe_stdout)
335     {
336       if (must_close_ifd1)
337         close (ifd[1]);
338       else
339         if (stdout_handle != INVALID_HANDLE_VALUE)
340           CloseHandle (stdout_handle);
341     }
342 
343 # else /* __KLIBC__ */
344   if (!(directory == NULL || strcmp (directory, ".") == 0))
345     {
346       /* A directory argument is not supported in this implementation.  */
347       saved_errno = EINVAL;
348       goto fail_with_saved_errno;
349     }
350 
351   int orig_stdin;
352   int orig_stdout;
353   int orig_stderr;
354 
355   /* Save standard file handles of parent process.  */
356   if (pipe_stdin || prog_stdin != NULL)
357     orig_stdin = dup_safer_noinherit (STDIN_FILENO);
358   if (pipe_stdout || prog_stdout != NULL)
359     orig_stdout = dup_safer_noinherit (STDOUT_FILENO);
360   if (null_stderr)
361     orig_stderr = dup_safer_noinherit (STDERR_FILENO);
362 
363   /* Create standard file handles of child process.  */
364   nulloutfd = -1;
365   stdinfd = -1;
366   stdoutfd = -1;
367   if ((!pipe_stdin || dup2 (ofd[0], STDIN_FILENO) >= 0)
368       && (!pipe_stdout || dup2 (ifd[1], STDOUT_FILENO) >= 0)
369       && (!null_stderr
370           || ((nulloutfd = open ("NUL", O_RDWR, 0)) >= 0
371               && (nulloutfd == STDERR_FILENO
372                   || (dup2 (nulloutfd, STDERR_FILENO) >= 0
373                       && close (nulloutfd) >= 0))))
374       && (pipe_stdin
375           || prog_stdin == NULL
376           || ((stdinfd = open (prog_stdin, O_RDONLY, 0)) >= 0
377               && (stdinfd == STDIN_FILENO
378                   || (dup2 (stdinfd, STDIN_FILENO) >= 0
379                       && close (stdinfd) >= 0))))
380       && (pipe_stdout
381           || prog_stdout == NULL
382           || ((stdoutfd = open (prog_stdout, O_WRONLY, 0)) >= 0
383               && (stdoutfd == STDOUT_FILENO
384                   || (dup2 (stdoutfd, STDOUT_FILENO) >= 0
385                       && close (stdoutfd) >= 0)))))
386     /* The child process doesn't inherit ifd[0], ifd[1], ofd[0], ofd[1],
387        but it inherits all open()ed or dup2()ed file handles (which is what
388        we want in the case of STD*_FILENO).  */
389     {
390       child = _spawnvpe (P_NOWAIT, prog_path, argv + 1,
391                          (const char **) environ);
392 #  if 0 /* Executing arbitrary files as shell scripts is unsecure.  */
393       if (child == -1 && errno == ENOEXEC)
394         {
395           /* prog is not a native executable.  Try to execute it as a
396              shell script.  Note that prepare_spawn() has already prepended
397              a hidden element "sh.exe" to argv.  */
398           child = _spawnvpe (P_NOWAIT, argv[0], argv,
399                              (const char **) environ);
400         }
401 #  endif
402     }
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);
411 
412   /* Restore standard file handles of parent process.  */
413   if (null_stderr)
414     undup_safer_noinherit (orig_stderr, STDERR_FILENO);
415   if (pipe_stdout || prog_stdout != NULL)
416     undup_safer_noinherit (orig_stdout, STDOUT_FILENO);
417   if (pipe_stdin || prog_stdin != NULL)
418     undup_safer_noinherit (orig_stdin, STDIN_FILENO);
419 
420   if (pipe_stdin)
421     close (ofd[0]);
422   if (pipe_stdout)
423     close (ifd[1]);
424 # endif
425 
426   free (argv);
427   free (argv_mem_to_free);
428   free (prog_path_to_free);
429 
430   if (child == -1)
431     {
432       if (pipe_stdout)
433         close (ifd[0]);
434       if (pipe_stdin)
435         close (ofd[1]);
436       goto fail_with_saved_errno;
437     }
438 
439   if (pipe_stdout)
440     fd[0] = ifd[0];
441   if (pipe_stdin)
442     fd[1] = ofd[1];
443   return child;
444 
445 #else
446 
447   /* Unix API.  */
448   int ifd[2];
449   int ofd[2];
450   sigset_t blocked_signals;
451   posix_spawn_file_actions_t actions;
452   bool actions_allocated;
453   posix_spawnattr_t attrs;
454   bool attrs_allocated;
455   int err;
456   pid_t child;
457 
458   if (pipe_stdout)
459     if (pipe_safer (ifd) < 0)
460       error (EXIT_FAILURE, errno, _("cannot create pipe"));
461   if (pipe_stdin)
462     if (pipe_safer (ofd) < 0)
463       error (EXIT_FAILURE, errno, _("cannot create pipe"));
464 /* Data flow diagram:
465  *
466  *           write        system         read
467  *    parent  ->   ofd[1]   ->   ofd[0]   ->   child       if pipe_stdin
468  *    parent  <-   ifd[0]   <-   ifd[1]   <-   child       if pipe_stdout
469  *           read         system         write
470  *
471  */
472 
473   if (slave_process)
474     {
475       sigprocmask (SIG_SETMASK, NULL, &blocked_signals);
476       block_fatal_signals ();
477     }
478   actions_allocated = false;
479   attrs_allocated = false;
480   if ((err = posix_spawn_file_actions_init (&actions)) != 0
481       || (actions_allocated = true,
482           (pipe_stdin
483            && (err = posix_spawn_file_actions_adddup2 (&actions,
484                                                        ofd[0], STDIN_FILENO))
485               != 0)
486           || (pipe_stdout
487               && (err = posix_spawn_file_actions_adddup2 (&actions,
488                                                           ifd[1], STDOUT_FILENO))
489                  != 0)
490           || (pipe_stdin
491               && (err = posix_spawn_file_actions_addclose (&actions, ofd[0]))
492                  != 0)
493           || (pipe_stdout
494               && (err = posix_spawn_file_actions_addclose (&actions, ifd[1]))
495                  != 0)
496           || (pipe_stdin
497               && (err = posix_spawn_file_actions_addclose (&actions, ofd[1]))
498                  != 0)
499           || (pipe_stdout
500               && (err = posix_spawn_file_actions_addclose (&actions, ifd[0]))
501                  != 0)
502           || (null_stderr
503               && (err = posix_spawn_file_actions_addopen (&actions,
504                                                           STDERR_FILENO,
505                                                           "/dev/null", O_RDWR,
506                                                           0))
507                  != 0)
508           || (!pipe_stdin
509               && prog_stdin != NULL
510               && (err = posix_spawn_file_actions_addopen (&actions,
511                                                           STDIN_FILENO,
512                                                           prog_stdin, O_RDONLY,
513                                                           0))
514                  != 0)
515           || (!pipe_stdout
516               && prog_stdout != NULL
517               && (err = posix_spawn_file_actions_addopen (&actions,
518                                                           STDOUT_FILENO,
519                                                           prog_stdout, O_WRONLY,
520                                                           0))
521                  != 0)
522           || (directory != NULL
523               && (err = posix_spawn_file_actions_addchdir (&actions,
524                                                            directory)))
525           || (slave_process
526               && ((err = posix_spawnattr_init (&attrs)) != 0
527                   || (attrs_allocated = true,
528 # if defined _WIN32 && !defined __CYGWIN__
529                       (err = posix_spawnattr_setpgroup (&attrs, 0)) != 0
530                       || (err = posix_spawnattr_setflags (&attrs,
531                                                          POSIX_SPAWN_SETPGROUP))
532                          != 0
533 # else
534                       (err = posix_spawnattr_setsigmask (&attrs,
535                                                          &blocked_signals))
536                       != 0
537                       || (err = posix_spawnattr_setflags (&attrs,
538                                                         POSIX_SPAWN_SETSIGMASK))
539                          != 0
540 # endif
541              )   )   )
542           || (err = (directory != NULL
543                      ? posix_spawn (&child, prog_path, &actions,
544                                     attrs_allocated ? &attrs : NULL,
545                                     (char * const *) prog_argv, environ)
546                      : posix_spawnp (&child, prog_path, &actions,
547                                      attrs_allocated ? &attrs : NULL,
548                                      (char * const *) prog_argv, environ)))
549              != 0))
550     {
551       if (actions_allocated)
552         posix_spawn_file_actions_destroy (&actions);
553       if (attrs_allocated)
554         posix_spawnattr_destroy (&attrs);
555       if (slave_process)
556         unblock_fatal_signals ();
557       if (pipe_stdout)
558         {
559           close (ifd[0]);
560           close (ifd[1]);
561         }
562       if (pipe_stdin)
563         {
564           close (ofd[0]);
565           close (ofd[1]);
566         }
567       free (prog_path_to_free);
568       saved_errno = err;
569       goto fail_with_saved_errno;
570     }
571   posix_spawn_file_actions_destroy (&actions);
572   if (attrs_allocated)
573     posix_spawnattr_destroy (&attrs);
574   if (slave_process)
575     {
576       register_slave_subprocess (child);
577       unblock_fatal_signals ();
578     }
579   if (pipe_stdin)
580     close (ofd[0]);
581   if (pipe_stdout)
582     close (ifd[1]);
583   free (prog_path_to_free);
584 
585   if (pipe_stdout)
586     fd[0] = ifd[0];
587   if (pipe_stdin)
588     fd[1] = ofd[1];
589   return child;
590 
591 #endif
592 
593  fail_with_errno:
594   saved_errno = errno;
595  fail_with_saved_errno:
596   if (exit_on_error || !null_stderr)
597     error (exit_on_error ? EXIT_FAILURE : 0, saved_errno,
598            _("%s subprocess failed"), progname);
599   errno = saved_errno;
600   return -1;
601 }
602 
603 /* Open a bidirectional pipe.
604  *
605  *           write       system                read
606  *    parent  ->   fd[1]   ->   STDIN_FILENO    ->   child
607  *    parent  <-   fd[0]   <-   STDOUT_FILENO   <-   child
608  *           read        system                write
609  *
610  */
611 pid_t
create_pipe_bidi(const char * progname,const char * prog_path,const char * const * prog_argv,const char * directory,bool null_stderr,bool slave_process,bool exit_on_error,int fd[2])612 create_pipe_bidi (const char *progname,
613                   const char *prog_path, const char * const *prog_argv,
614                   const char *directory,
615                   bool null_stderr,
616                   bool slave_process, bool exit_on_error,
617                   int fd[2])
618 {
619   pid_t result = create_pipe (progname, prog_path, prog_argv, directory,
620                               true, true, NULL, NULL,
621                               null_stderr, slave_process, exit_on_error,
622                               fd);
623   return result;
624 }
625 
626 /* Open a pipe for input from a child process.
627  * The child's stdin comes from a file.
628  *
629  *           read        system                write
630  *    parent  <-   fd[0]   <-   STDOUT_FILENO   <-   child
631  *
632  */
633 pid_t
create_pipe_in(const char * progname,const char * prog_path,const char * const * prog_argv,const char * directory,const char * prog_stdin,bool null_stderr,bool slave_process,bool exit_on_error,int fd[1])634 create_pipe_in (const char *progname,
635                 const char *prog_path, const char * const *prog_argv,
636                 const char *directory,
637                 const char *prog_stdin, bool null_stderr,
638                 bool slave_process, bool exit_on_error,
639                 int fd[1])
640 {
641   int iofd[2];
642   pid_t result = create_pipe (progname, prog_path, prog_argv, directory,
643                               false, true, prog_stdin, NULL,
644                               null_stderr, slave_process, exit_on_error,
645                               iofd);
646   if (result != -1)
647     fd[0] = iofd[0];
648   return result;
649 }
650 
651 /* Open a pipe for output to a child process.
652  * The child's stdout goes to a file.
653  *
654  *           write       system                read
655  *    parent  ->   fd[0]   ->   STDIN_FILENO    ->   child
656  *
657  */
658 pid_t
create_pipe_out(const char * progname,const char * prog_path,const char * const * prog_argv,const char * directory,const char * prog_stdout,bool null_stderr,bool slave_process,bool exit_on_error,int fd[1])659 create_pipe_out (const char *progname,
660                  const char *prog_path, const char * const *prog_argv,
661                  const char *directory,
662                  const char *prog_stdout, bool null_stderr,
663                  bool slave_process, bool exit_on_error,
664                  int fd[1])
665 {
666   int iofd[2];
667   pid_t result = create_pipe (progname, prog_path, prog_argv, directory,
668                               true, false, NULL, prog_stdout,
669                               null_stderr, slave_process, exit_on_error,
670                               iofd);
671   if (result != -1)
672     fd[0] = iofd[1];
673   return result;
674 }
675