Make create_pipe_* safer w.r.t. file descriptor conflicts.
[gnulib.git] / lib / pipe.c
1 /* Creation of subprocesses, communicating via pipes.
2    Copyright (C) 2001-2004, 2006-2008 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 <http://www.gnu.org/licenses/>.  */
17
18
19 #include <config.h>
20
21 /* Specification.  */
22 #include "pipe.h"
23
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <stdlib.h>
27 #include <signal.h>
28 #include <unistd.h>
29
30 #include "error.h"
31 #include "fatal-signal.h"
32 #include "unistd-safer.h"
33 #include "wait-process.h"
34 #include "gettext.h"
35
36 #define _(str) gettext (str)
37
38 #if defined _MSC_VER || defined __MINGW32__
39
40 /* Native Woe32 API.  */
41 # include <process.h>
42 # include "w32spawn.h"
43
44 #else
45
46 /* Unix API.  */
47 # if HAVE_POSIX_SPAWN
48 #  include <spawn.h>
49 # else
50 #  if HAVE_VFORK_H
51 #   include <vfork.h>
52 #  endif
53 # endif
54
55 #endif
56
57 #ifndef STDIN_FILENO
58 # define STDIN_FILENO 0
59 #endif
60 #ifndef STDOUT_FILENO
61 # define STDOUT_FILENO 1
62 #endif
63 #ifndef STDERR_FILENO
64 # define STDERR_FILENO 2
65 #endif
66
67 /* The results of open() in this file are not used with fchdir,
68    therefore save some unnecessary work in fchdir.c.  */
69 #undef open
70 #undef close
71
72
73 #ifdef EINTR
74
75 /* EINTR handling for close().
76    These functions can return -1/EINTR even though we don't have any
77    signal handlers set up, namely when we get interrupted via SIGSTOP.  */
78
79 static inline int
80 nonintr_close (int fd)
81 {
82   int retval;
83
84   do
85     retval = close (fd);
86   while (retval < 0 && errno == EINTR);
87
88   return retval;
89 }
90 #define close nonintr_close
91
92 static inline int
93 nonintr_open (const char *pathname, int oflag, mode_t mode)
94 {
95   int retval;
96
97   do
98     retval = open (pathname, oflag, mode);
99   while (retval < 0 && errno == EINTR);
100
101   return retval;
102 }
103 #undef open /* avoid warning on VMS */
104 #define open nonintr_open
105
106 #endif
107
108
109 /* Open a pipe connected to a child process.
110  *
111  *           write       system                read
112  *    parent  ->   fd[1]   ->   STDIN_FILENO    ->   child       if pipe_stdin
113  *    parent  <-   fd[0]   <-   STDOUT_FILENO   <-   child       if pipe_stdout
114  *           read        system                write
115  *
116  * At least one of pipe_stdin, pipe_stdout must be true.
117  * pipe_stdin and prog_stdin together determine the child's standard input.
118  * pipe_stdout and prog_stdout together determine the child's standard output.
119  * If pipe_stdin is true, prog_stdin is ignored.
120  * If pipe_stdout is true, prog_stdout is ignored.
121  */
122 static pid_t
123 create_pipe (const char *progname,
124              const char *prog_path, char **prog_argv,
125              bool pipe_stdin, bool pipe_stdout,
126              const char *prog_stdin, const char *prog_stdout,
127              bool null_stderr,
128              bool slave_process, bool exit_on_error,
129              int fd[2])
130 {
131 #if defined _MSC_VER || defined __MINGW32__
132
133   /* Native Woe32 API.
134      This uses _pipe(), dup2(), and spawnv().  It could also be implemented
135      using the low-level functions CreatePipe(), DuplicateHandle(),
136      CreateProcess() and _open_osfhandle(); see the GNU make and GNU clisp
137      and cvs source code.  */
138   int ifd[2];
139   int ofd[2];
140   int orig_stdin;
141   int orig_stdout;
142   int orig_stderr;
143   int child;
144   int nulloutfd;
145   int stdinfd;
146   int stdoutfd;
147
148   prog_argv = prepare_spawn (prog_argv);
149
150   if (pipe_stdout)
151     if (_pipe (ifd, 4096, O_BINARY | O_NOINHERIT) < 0
152         || (ifd[0] = fd_safer (ifd[0])) < 0)
153       error (EXIT_FAILURE, errno, _("cannot create pipe"));
154   if (pipe_stdin)
155     if (_pipe (ofd, 4096, O_BINARY | O_NOINHERIT) < 0
156         || (ofd[1] = fd_safer (ofd[1])) < 0)
157       error (EXIT_FAILURE, errno, _("cannot create pipe"));
158 /* Data flow diagram:
159  *
160  *           write        system         read
161  *    parent  ->   ofd[1]   ->   ofd[0]   ->   child       if pipe_stdin
162  *    parent  <-   ifd[0]   <-   ifd[1]   <-   child       if pipe_stdout
163  *           read         system         write
164  *
165  */
166
167   /* Save standard file handles of parent process.  */
168   if (pipe_stdin || prog_stdin != NULL)
169     orig_stdin = dup_noinherit (STDIN_FILENO);
170   if (pipe_stdout || prog_stdout != NULL)
171     orig_stdout = dup_noinherit (STDOUT_FILENO);
172   if (null_stderr)
173     orig_stderr = dup_noinherit (STDERR_FILENO);
174   child = -1;
175
176   /* Create standard file handles of child process.  */
177   nulloutfd = -1;
178   stdinfd = -1;
179   stdoutfd = -1;
180   if ((!pipe_stdin || dup2 (ofd[0], STDIN_FILENO) >= 0)
181       && (!pipe_stdout || dup2 (ifd[1], STDOUT_FILENO) >= 0)
182       && (!null_stderr
183           || ((nulloutfd = open ("NUL", O_RDWR, 0)) >= 0
184               && (nulloutfd == STDERR_FILENO
185                   || (dup2 (nulloutfd, STDERR_FILENO) >= 0
186                       && close (nulloutfd) >= 0))))
187       && (pipe_stdin
188           || prog_stdin == NULL
189           || ((stdinfd = open (prog_stdin, O_RDONLY, 0)) >= 0
190               && (stdinfd == STDIN_FILENO
191                   || (dup2 (stdinfd, STDIN_FILENO) >= 0
192                       && close (stdinfd) >= 0))))
193       && (pipe_stdout
194           || prog_stdout == NULL
195           || ((stdoutfd = open (prog_stdout, O_WRONLY, 0)) >= 0
196               && (stdoutfd == STDOUT_FILENO
197                   || (dup2 (stdoutfd, STDOUT_FILENO) >= 0
198                       && close (stdoutfd) >= 0)))))
199     /* The child process doesn't inherit ifd[0], ifd[1], ofd[0], ofd[1],
200        but it inherits all open()ed or dup2()ed file handles (which is what
201        we want in the case of STD*_FILENO) and also orig_stdin,
202        orig_stdout, orig_stderr (which is not explicitly wanted but
203        harmless).  */
204     child = spawnvp (P_NOWAIT, prog_path, prog_argv);
205   if (stdinfd >= 0)
206     close (stdinfd);
207   if (stdoutfd >= 0)
208     close (stdoutfd);
209   if (nulloutfd >= 0)
210     close (nulloutfd);
211
212   /* Restore standard file handles of parent process.  */
213   if (null_stderr)
214     dup2 (orig_stderr, STDERR_FILENO), close (orig_stderr);
215   if (pipe_stdout || prog_stdout != NULL)
216     dup2 (orig_stdout, STDOUT_FILENO), close (orig_stdout);
217   if (pipe_stdin || prog_stdin != NULL)
218     dup2 (orig_stdin, STDIN_FILENO), close (orig_stdin);
219
220   if (pipe_stdin)
221     close (ofd[0]);
222   if (pipe_stdout)
223     close (ifd[1]);
224   if (child == -1)
225     {
226       if (exit_on_error || !null_stderr)
227         error (exit_on_error ? EXIT_FAILURE : 0, errno,
228                _("%s subprocess failed"), progname);
229       if (pipe_stdout)
230         close (ifd[0]);
231       if (pipe_stdin)
232         close (ofd[1]);
233       return -1;
234     }
235
236   if (pipe_stdout)
237     fd[0] = ifd[0];
238   if (pipe_stdin)
239     fd[1] = ofd[1];
240   return child;
241
242 #else
243
244   /* Unix API.  */
245   int ifd[2];
246   int ofd[2];
247 # if HAVE_POSIX_SPAWN
248   sigset_t blocked_signals;
249   posix_spawn_file_actions_t actions;
250   bool actions_allocated;
251   posix_spawnattr_t attrs;
252   bool attrs_allocated;
253   int err;
254   pid_t child;
255 # else
256   int child;
257 # endif
258
259   if (pipe_stdout)
260     if (pipe (ifd) < 0
261         || (ifd[0] = fd_safer (ifd[0])) < 0)
262       error (EXIT_FAILURE, errno, _("cannot create pipe"));
263   if (pipe_stdin)
264     if (pipe (ofd) < 0
265         || (ofd[1] = fd_safer (ofd[1])) < 0)
266       error (EXIT_FAILURE, errno, _("cannot create pipe"));
267 /* Data flow diagram:
268  *
269  *           write        system         read
270  *    parent  ->   ofd[1]   ->   ofd[0]   ->   child       if pipe_stdin
271  *    parent  <-   ifd[0]   <-   ifd[1]   <-   child       if pipe_stdout
272  *           read         system         write
273  *
274  */
275
276 # if HAVE_POSIX_SPAWN
277   if (slave_process)
278     {
279       sigprocmask (SIG_SETMASK, NULL, &blocked_signals);
280       block_fatal_signals ();
281     }
282   actions_allocated = false;
283   attrs_allocated = false;
284   if ((err = posix_spawn_file_actions_init (&actions)) != 0
285       || (actions_allocated = true,
286           (pipe_stdin
287            && (err = posix_spawn_file_actions_adddup2 (&actions,
288                                                        ofd[0], STDIN_FILENO))
289               != 0)
290           || (pipe_stdout
291               && (err = posix_spawn_file_actions_adddup2 (&actions,
292                                                           ifd[1], STDOUT_FILENO))
293                  != 0)
294           || (pipe_stdin
295               && (err = posix_spawn_file_actions_addclose (&actions, ofd[0]))
296                  != 0)
297           || (pipe_stdout
298               && (err = posix_spawn_file_actions_addclose (&actions, ifd[1]))
299                  != 0)
300           || (pipe_stdin
301               && (err = posix_spawn_file_actions_addclose (&actions, ofd[1]))
302                  != 0)
303           || (pipe_stdout
304               && (err = posix_spawn_file_actions_addclose (&actions, ifd[0]))
305                  != 0)
306           || (null_stderr
307               && (err = posix_spawn_file_actions_addopen (&actions,
308                                                           STDERR_FILENO,
309                                                           "/dev/null", O_RDWR,
310                                                           0))
311                  != 0)
312           || (!pipe_stdin
313               && prog_stdin != NULL
314               && (err = posix_spawn_file_actions_addopen (&actions,
315                                                           STDIN_FILENO,
316                                                           prog_stdin, O_RDONLY,
317                                                           0))
318                  != 0)
319           || (!pipe_stdout
320               && prog_stdout != NULL
321               && (err = posix_spawn_file_actions_addopen (&actions,
322                                                           STDOUT_FILENO,
323                                                           prog_stdout, O_WRONLY,
324                                                           0))
325                  != 0)
326           || (slave_process
327               && ((err = posix_spawnattr_init (&attrs)) != 0
328                   || (attrs_allocated = true,
329                       (err = posix_spawnattr_setsigmask (&attrs,
330                                                          &blocked_signals))
331                       != 0
332                       || (err = posix_spawnattr_setflags (&attrs,
333                                                         POSIX_SPAWN_SETSIGMASK))
334                          != 0)))
335           || (err = posix_spawnp (&child, prog_path, &actions,
336                                   attrs_allocated ? &attrs : NULL, prog_argv,
337                                   environ))
338              != 0))
339     {
340       if (actions_allocated)
341         posix_spawn_file_actions_destroy (&actions);
342       if (attrs_allocated)
343         posix_spawnattr_destroy (&attrs);
344       if (slave_process)
345         unblock_fatal_signals ();
346       if (exit_on_error || !null_stderr)
347         error (exit_on_error ? EXIT_FAILURE : 0, err,
348                _("%s subprocess failed"), progname);
349       if (pipe_stdout)
350         {
351           close (ifd[0]);
352           close (ifd[1]);
353         }
354       if (pipe_stdin)
355         {
356           close (ofd[0]);
357           close (ofd[1]);
358         }
359       return -1;
360     }
361   posix_spawn_file_actions_destroy (&actions);
362   if (attrs_allocated)
363     posix_spawnattr_destroy (&attrs);
364 # else
365   if (slave_process)
366     block_fatal_signals ();
367   /* Use vfork() instead of fork() for efficiency.  */
368   if ((child = vfork ()) == 0)
369     {
370       /* Child process code.  */
371       int nulloutfd;
372       int stdinfd;
373       int stdoutfd;
374
375       if ((!pipe_stdin || dup2 (ofd[0], STDIN_FILENO) >= 0)
376           && (!pipe_stdout || dup2 (ifd[1], STDOUT_FILENO) >= 0)
377           && (!pipe_stdin || close (ofd[0]) >= 0)
378           && (!pipe_stdout || close (ifd[1]) >= 0)
379           && (!pipe_stdin || close (ofd[1]) >= 0)
380           && (!pipe_stdout || close (ifd[0]) >= 0)
381           && (!null_stderr
382               || ((nulloutfd = open ("/dev/null", O_RDWR, 0)) >= 0
383                   && (nulloutfd == STDERR_FILENO
384                       || (dup2 (nulloutfd, STDERR_FILENO) >= 0
385                           && close (nulloutfd) >= 0))))
386           && (pipe_stdin
387               || prog_stdin == NULL
388               || ((stdinfd = open (prog_stdin, O_RDONLY, 0)) >= 0
389                   && (stdinfd == STDIN_FILENO
390                       || (dup2 (stdinfd, STDIN_FILENO) >= 0
391                           && close (stdinfd) >= 0))))
392           && (pipe_stdout
393               || prog_stdout == NULL
394               || ((stdoutfd = open (prog_stdout, O_WRONLY, 0)) >= 0
395                   && (stdoutfd == STDOUT_FILENO
396                       || (dup2 (stdoutfd, STDOUT_FILENO) >= 0
397                           && close (stdoutfd) >= 0))))
398           && (!slave_process || (unblock_fatal_signals (), true)))
399         execvp (prog_path, prog_argv);
400       _exit (127);
401     }
402   if (child == -1)
403     {
404       if (slave_process)
405         unblock_fatal_signals ();
406       if (exit_on_error || !null_stderr)
407         error (exit_on_error ? EXIT_FAILURE : 0, errno,
408                _("%s subprocess failed"), progname);
409       if (pipe_stdout)
410         {
411           close (ifd[0]);
412           close (ifd[1]);
413         }
414       if (pipe_stdin)
415         {
416           close (ofd[0]);
417           close (ofd[1]);
418         }
419       return -1;
420     }
421 # endif
422   if (slave_process)
423     {
424       register_slave_subprocess (child);
425       unblock_fatal_signals ();
426     }
427   if (pipe_stdin)
428     close (ofd[0]);
429   if (pipe_stdout)
430     close (ifd[1]);
431
432   if (pipe_stdout)
433     fd[0] = ifd[0];
434   if (pipe_stdin)
435     fd[1] = ofd[1];
436   return child;
437
438 #endif
439 }
440
441 /* Open a bidirectional pipe.
442  *
443  *           write       system                read
444  *    parent  ->   fd[1]   ->   STDIN_FILENO    ->   child
445  *    parent  <-   fd[0]   <-   STDOUT_FILENO   <-   child
446  *           read        system                write
447  *
448  */
449 pid_t
450 create_pipe_bidi (const char *progname,
451                   const char *prog_path, char **prog_argv,
452                   bool null_stderr,
453                   bool slave_process, bool exit_on_error,
454                   int fd[2])
455 {
456   pid_t result = create_pipe (progname, prog_path, prog_argv,
457                               true, true, NULL, NULL,
458                               null_stderr, slave_process, exit_on_error,
459                               fd);
460   return result;
461 }
462
463 /* Open a pipe for input from a child process.
464  * The child's stdin comes from a file.
465  *
466  *           read        system                write
467  *    parent  <-   fd[0]   <-   STDOUT_FILENO   <-   child
468  *
469  */
470 pid_t
471 create_pipe_in (const char *progname,
472                 const char *prog_path, char **prog_argv,
473                 const char *prog_stdin, bool null_stderr,
474                 bool slave_process, bool exit_on_error,
475                 int fd[1])
476 {
477   int iofd[2];
478   pid_t result = create_pipe (progname, prog_path, prog_argv,
479                               false, true, prog_stdin, NULL,
480                               null_stderr, slave_process, exit_on_error,
481                               iofd);
482   if (result != -1)
483     fd[0] = iofd[0];
484   return result;
485 }
486
487 /* Open a pipe for output to a child process.
488  * The child's stdout goes to a file.
489  *
490  *           write       system                read
491  *    parent  ->   fd[0]   ->   STDIN_FILENO    ->   child
492  *
493  */
494 pid_t
495 create_pipe_out (const char *progname,
496                  const char *prog_path, char **prog_argv,
497                  const char *prog_stdout, bool null_stderr,
498                  bool slave_process, bool exit_on_error,
499                  int fd[1])
500 {
501   int iofd[2];
502   pid_t result = create_pipe (progname, prog_path, prog_argv,
503                               true, false, NULL, prog_stdout,
504                               null_stderr, slave_process, exit_on_error,
505                               iofd);
506   if (result != -1)
507     fd[0] = iofd[1];
508   return result;
509 }