pipe: be robust in face of closed fds
[gnulib.git] / lib / pipe.c
1 /* Creation of subprocesses, communicating via pipes.
2    Copyright (C) 2001-2004, 2006-2009 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 # include <spawn.h>
48
49 #endif
50
51 /* The results of open() in this file are not used with fchdir,
52    therefore save some unnecessary work in fchdir.c.  */
53 #undef open
54 #undef close
55
56
57 #ifdef EINTR
58
59 /* EINTR handling for close().
60    These functions can return -1/EINTR even though we don't have any
61    signal handlers set up, namely when we get interrupted via SIGSTOP.  */
62
63 static inline int
64 nonintr_close (int fd)
65 {
66   int retval;
67
68   do
69     retval = close (fd);
70   while (retval < 0 && errno == EINTR);
71
72   return retval;
73 }
74 #define close nonintr_close
75
76 static inline int
77 nonintr_open (const char *pathname, int oflag, mode_t mode)
78 {
79   int retval;
80
81   do
82     retval = open (pathname, oflag, mode);
83   while (retval < 0 && errno == EINTR);
84
85   return retval;
86 }
87 #undef open /* avoid warning on VMS */
88 #define open nonintr_open
89
90 #endif
91
92
93 /* Open a pipe connected to a child process.
94  *
95  *           write       system                read
96  *    parent  ->   fd[1]   ->   STDIN_FILENO    ->   child       if pipe_stdin
97  *    parent  <-   fd[0]   <-   STDOUT_FILENO   <-   child       if pipe_stdout
98  *           read        system                write
99  *
100  * At least one of pipe_stdin, pipe_stdout must be true.
101  * pipe_stdin and prog_stdin together determine the child's standard input.
102  * pipe_stdout and prog_stdout together determine the child's standard output.
103  * If pipe_stdin is true, prog_stdin is ignored.
104  * If pipe_stdout is true, prog_stdout is ignored.
105  */
106 static pid_t
107 create_pipe (const char *progname,
108              const char *prog_path, char **prog_argv,
109              bool pipe_stdin, bool pipe_stdout,
110              const char *prog_stdin, const char *prog_stdout,
111              bool null_stderr,
112              bool slave_process, bool exit_on_error,
113              int fd[2])
114 {
115 #if defined _MSC_VER || defined __MINGW32__
116
117   /* Native Woe32 API.
118      This uses _pipe(), dup2(), and spawnv().  It could also be implemented
119      using the low-level functions CreatePipe(), DuplicateHandle(),
120      CreateProcess() and _open_osfhandle(); see the GNU make and GNU clisp
121      and cvs source code.  */
122   int ifd[2];
123   int ofd[2];
124   int orig_stdin;
125   int orig_stdout;
126   int orig_stderr;
127   int child;
128   int nulloutfd;
129   int stdinfd;
130   int stdoutfd;
131
132   /* FIXME: Need to free memory allocated by prepare_spawn.  */
133   prog_argv = prepare_spawn (prog_argv);
134
135   if (pipe_stdout)
136     if (_pipe (ifd, 4096, O_BINARY | O_NOINHERIT) < 0
137         || (ifd[0] = fd_safer (ifd[0])) < 0
138         || (ifd[1] = fd_safer (ifd[1])) < 0)
139       error (EXIT_FAILURE, errno, _("cannot create pipe"));
140   if (pipe_stdin)
141     if (_pipe (ofd, 4096, O_BINARY | O_NOINHERIT) < 0
142         || (ofd[0] = fd_safer (ofd[0])) < 0
143         || (ofd[1] = fd_safer (ofd[1])) < 0)
144       error (EXIT_FAILURE, errno, _("cannot create pipe"));
145 /* Data flow diagram:
146  *
147  *           write        system         read
148  *    parent  ->   ofd[1]   ->   ofd[0]   ->   child       if pipe_stdin
149  *    parent  <-   ifd[0]   <-   ifd[1]   <-   child       if pipe_stdout
150  *           read         system         write
151  *
152  */
153
154   /* Save standard file handles of parent process.  */
155   if (pipe_stdin || prog_stdin != NULL)
156     orig_stdin = dup_noinherit (STDIN_FILENO);
157   if (pipe_stdout || prog_stdout != NULL)
158     orig_stdout = dup_noinherit (STDOUT_FILENO);
159   if (null_stderr)
160     orig_stderr = dup_noinherit (STDERR_FILENO);
161   child = -1;
162
163   /* Create standard file handles of child process.  */
164   nulloutfd = -1;
165   stdinfd = -1;
166   stdoutfd = -1;
167   if ((!pipe_stdin || dup2 (ofd[0], STDIN_FILENO) >= 0)
168       && (!pipe_stdout || dup2 (ifd[1], STDOUT_FILENO) >= 0)
169       && (!null_stderr
170           || ((nulloutfd = open ("NUL", O_RDWR, 0)) >= 0
171               && (nulloutfd == STDERR_FILENO
172                   || (dup2 (nulloutfd, STDERR_FILENO) >= 0
173                       && close (nulloutfd) >= 0))))
174       && (pipe_stdin
175           || prog_stdin == NULL
176           || ((stdinfd = open (prog_stdin, O_RDONLY, 0)) >= 0
177               && (stdinfd == STDIN_FILENO
178                   || (dup2 (stdinfd, STDIN_FILENO) >= 0
179                       && close (stdinfd) >= 0))))
180       && (pipe_stdout
181           || prog_stdout == NULL
182           || ((stdoutfd = open (prog_stdout, O_WRONLY, 0)) >= 0
183               && (stdoutfd == STDOUT_FILENO
184                   || (dup2 (stdoutfd, STDOUT_FILENO) >= 0
185                       && close (stdoutfd) >= 0)))))
186     /* The child process doesn't inherit ifd[0], ifd[1], ofd[0], ofd[1],
187        but it inherits all open()ed or dup2()ed file handles (which is what
188        we want in the case of STD*_FILENO) and also orig_stdin,
189        orig_stdout, orig_stderr (which is not explicitly wanted but
190        harmless).  */
191     /* Use spawnvpe and pass the environment explicitly.  This is needed if
192        the program has modified the environment using putenv() or [un]setenv().
193        On Windows, programs have two environments, one in the "environment
194        block" of the process and managed through SetEnvironmentVariable(), and
195        one inside the process, in the location retrieved by the 'environ'
196        macro.  When using spawnvp() without 'e', the child process inherits a
197        copy of the environment block - ignoring the effects of putenv() and
198        [un]setenv().  */
199     {
200       child = spawnvpe (P_NOWAIT, prog_path, (const char **) prog_argv,
201                         (const char **) environ);
202       if (child < 0 && errno == ENOEXEC)
203         {
204           /* prog is not an native executable.  Try to execute it as a
205              shell script.  Note that prepare_spawn() has already prepended
206              a hidden element "sh.exe" to prog_argv.  */
207           --prog_argv;
208           child = spawnvpe (P_NOWAIT, prog_argv[0], (const char **) prog_argv,
209                             (const char **) environ);
210         }
211     }
212   if (stdinfd >= 0)
213     close (stdinfd);
214   if (stdoutfd >= 0)
215     close (stdoutfd);
216   if (nulloutfd >= 0)
217     close (nulloutfd);
218
219   /* Restore standard file handles of parent process.  */
220   if (null_stderr)
221     dup2 (orig_stderr, STDERR_FILENO), close (orig_stderr);
222   if (pipe_stdout || prog_stdout != NULL)
223     dup2 (orig_stdout, STDOUT_FILENO), close (orig_stdout);
224   if (pipe_stdin || prog_stdin != NULL)
225     dup2 (orig_stdin, STDIN_FILENO), close (orig_stdin);
226
227   if (pipe_stdin)
228     close (ofd[0]);
229   if (pipe_stdout)
230     close (ifd[1]);
231   if (child == -1)
232     {
233       if (exit_on_error || !null_stderr)
234         error (exit_on_error ? EXIT_FAILURE : 0, errno,
235                _("%s subprocess failed"), progname);
236       if (pipe_stdout)
237         close (ifd[0]);
238       if (pipe_stdin)
239         close (ofd[1]);
240       return -1;
241     }
242
243   if (pipe_stdout)
244     fd[0] = ifd[0];
245   if (pipe_stdin)
246     fd[1] = ofd[1];
247   return child;
248
249 #else
250
251   /* Unix API.  */
252   int ifd[2];
253   int ofd[2];
254   sigset_t blocked_signals;
255   posix_spawn_file_actions_t actions;
256   bool actions_allocated;
257   posix_spawnattr_t attrs;
258   bool attrs_allocated;
259   int err;
260   pid_t child;
261
262   if (pipe_stdout)
263     if (pipe_safer (ifd) < 0)
264       error (EXIT_FAILURE, errno, _("cannot create pipe"));
265   if (pipe_stdin)
266     if (pipe_safer (ofd) < 0)
267       error (EXIT_FAILURE, errno, _("cannot create pipe"));
268 /* Data flow diagram:
269  *
270  *           write        system         read
271  *    parent  ->   ofd[1]   ->   ofd[0]   ->   child       if pipe_stdin
272  *    parent  <-   ifd[0]   <-   ifd[1]   <-   child       if pipe_stdout
273  *           read         system         write
274  *
275  */
276
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   if (slave_process)
365     {
366       register_slave_subprocess (child);
367       unblock_fatal_signals ();
368     }
369   if (pipe_stdin)
370     close (ofd[0]);
371   if (pipe_stdout)
372     close (ifd[1]);
373
374   if (pipe_stdout)
375     fd[0] = ifd[0];
376   if (pipe_stdin)
377     fd[1] = ofd[1];
378   return child;
379
380 #endif
381 }
382
383 /* Open a bidirectional pipe.
384  *
385  *           write       system                read
386  *    parent  ->   fd[1]   ->   STDIN_FILENO    ->   child
387  *    parent  <-   fd[0]   <-   STDOUT_FILENO   <-   child
388  *           read        system                write
389  *
390  */
391 pid_t
392 create_pipe_bidi (const char *progname,
393                   const char *prog_path, char **prog_argv,
394                   bool null_stderr,
395                   bool slave_process, bool exit_on_error,
396                   int fd[2])
397 {
398   pid_t result = create_pipe (progname, prog_path, prog_argv,
399                               true, true, NULL, NULL,
400                               null_stderr, slave_process, exit_on_error,
401                               fd);
402   return result;
403 }
404
405 /* Open a pipe for input from a child process.
406  * The child's stdin comes from a file.
407  *
408  *           read        system                write
409  *    parent  <-   fd[0]   <-   STDOUT_FILENO   <-   child
410  *
411  */
412 pid_t
413 create_pipe_in (const char *progname,
414                 const char *prog_path, char **prog_argv,
415                 const char *prog_stdin, bool null_stderr,
416                 bool slave_process, bool exit_on_error,
417                 int fd[1])
418 {
419   int iofd[2];
420   pid_t result = create_pipe (progname, prog_path, prog_argv,
421                               false, true, prog_stdin, NULL,
422                               null_stderr, slave_process, exit_on_error,
423                               iofd);
424   if (result != -1)
425     fd[0] = iofd[0];
426   return result;
427 }
428
429 /* Open a pipe for output to a child process.
430  * The child's stdout goes to a file.
431  *
432  *           write       system                read
433  *    parent  ->   fd[0]   ->   STDIN_FILENO    ->   child
434  *
435  */
436 pid_t
437 create_pipe_out (const char *progname,
438                  const char *prog_path, char **prog_argv,
439                  const char *prog_stdout, bool null_stderr,
440                  bool slave_process, bool exit_on_error,
441                  int fd[1])
442 {
443   int iofd[2];
444   pid_t result = create_pipe (progname, prog_path, prog_argv,
445                               true, false, NULL, prog_stdout,
446                               null_stderr, slave_process, exit_on_error,
447                               iofd);
448   if (result != -1)
449     fd[0] = iofd[1];
450   return result;
451 }