Add casts, to avoid warnings.
[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       error (EXIT_FAILURE, errno, _("cannot create pipe"));
139   if (pipe_stdin)
140     if (_pipe (ofd, 4096, O_BINARY | O_NOINHERIT) < 0
141         || (ofd[1] = fd_safer (ofd[1])) < 0)
142       error (EXIT_FAILURE, errno, _("cannot create pipe"));
143 /* Data flow diagram:
144  *
145  *           write        system         read
146  *    parent  ->   ofd[1]   ->   ofd[0]   ->   child       if pipe_stdin
147  *    parent  <-   ifd[0]   <-   ifd[1]   <-   child       if pipe_stdout
148  *           read         system         write
149  *
150  */
151
152   /* Save standard file handles of parent process.  */
153   if (pipe_stdin || prog_stdin != NULL)
154     orig_stdin = dup_noinherit (STDIN_FILENO);
155   if (pipe_stdout || prog_stdout != NULL)
156     orig_stdout = dup_noinherit (STDOUT_FILENO);
157   if (null_stderr)
158     orig_stderr = dup_noinherit (STDERR_FILENO);
159   child = -1;
160
161   /* Create standard file handles of child process.  */
162   nulloutfd = -1;
163   stdinfd = -1;
164   stdoutfd = -1;
165   if ((!pipe_stdin || dup2 (ofd[0], STDIN_FILENO) >= 0)
166       && (!pipe_stdout || dup2 (ifd[1], STDOUT_FILENO) >= 0)
167       && (!null_stderr
168           || ((nulloutfd = open ("NUL", O_RDWR, 0)) >= 0
169               && (nulloutfd == STDERR_FILENO
170                   || (dup2 (nulloutfd, STDERR_FILENO) >= 0
171                       && close (nulloutfd) >= 0))))
172       && (pipe_stdin
173           || prog_stdin == NULL
174           || ((stdinfd = open (prog_stdin, O_RDONLY, 0)) >= 0
175               && (stdinfd == STDIN_FILENO
176                   || (dup2 (stdinfd, STDIN_FILENO) >= 0
177                       && close (stdinfd) >= 0))))
178       && (pipe_stdout
179           || prog_stdout == NULL
180           || ((stdoutfd = open (prog_stdout, O_WRONLY, 0)) >= 0
181               && (stdoutfd == STDOUT_FILENO
182                   || (dup2 (stdoutfd, STDOUT_FILENO) >= 0
183                       && close (stdoutfd) >= 0)))))
184     /* The child process doesn't inherit ifd[0], ifd[1], ofd[0], ofd[1],
185        but it inherits all open()ed or dup2()ed file handles (which is what
186        we want in the case of STD*_FILENO) and also orig_stdin,
187        orig_stdout, orig_stderr (which is not explicitly wanted but
188        harmless).  */
189     /* Use spawnvpe and pass the environment explicitly.  This is needed if
190        the program has modified the environment using putenv() or [un]setenv().
191        On Windows, programs have two environments, one in the "environment
192        block" of the process and managed through SetEnvironmentVariable(), and
193        one inside the process, in the location retrieved by the 'environ'
194        macro.  When using spawnvp() without 'e', the child process inherits a
195        copy of the environment block - ignoring the effects of putenv() and
196        [un]setenv().  */
197     {
198       child = spawnvpe (P_NOWAIT, prog_path, (const char **) prog_argv,
199                         (const char **) environ);
200       if (child < 0 && errno == ENOEXEC)
201         {
202           /* prog is not an native executable.  Try to execute it as a
203              shell script.  Note that prepare_spawn() has already prepended
204              a hidden element "sh.exe" to prog_argv.  */
205           --prog_argv;
206           child = spawnvpe (P_NOWAIT, prog_argv[0], (const char **) prog_argv,
207                             (const char **) environ);
208         }
209     }
210   if (stdinfd >= 0)
211     close (stdinfd);
212   if (stdoutfd >= 0)
213     close (stdoutfd);
214   if (nulloutfd >= 0)
215     close (nulloutfd);
216
217   /* Restore standard file handles of parent process.  */
218   if (null_stderr)
219     dup2 (orig_stderr, STDERR_FILENO), close (orig_stderr);
220   if (pipe_stdout || prog_stdout != NULL)
221     dup2 (orig_stdout, STDOUT_FILENO), close (orig_stdout);
222   if (pipe_stdin || prog_stdin != NULL)
223     dup2 (orig_stdin, STDIN_FILENO), close (orig_stdin);
224
225   if (pipe_stdin)
226     close (ofd[0]);
227   if (pipe_stdout)
228     close (ifd[1]);
229   if (child == -1)
230     {
231       if (exit_on_error || !null_stderr)
232         error (exit_on_error ? EXIT_FAILURE : 0, errno,
233                _("%s subprocess failed"), progname);
234       if (pipe_stdout)
235         close (ifd[0]);
236       if (pipe_stdin)
237         close (ofd[1]);
238       return -1;
239     }
240
241   if (pipe_stdout)
242     fd[0] = ifd[0];
243   if (pipe_stdin)
244     fd[1] = ofd[1];
245   return child;
246
247 #else
248
249   /* Unix API.  */
250   int ifd[2];
251   int ofd[2];
252   sigset_t blocked_signals;
253   posix_spawn_file_actions_t actions;
254   bool actions_allocated;
255   posix_spawnattr_t attrs;
256   bool attrs_allocated;
257   int err;
258   pid_t child;
259
260   if (pipe_stdout)
261     if (pipe (ifd) < 0
262         || (ifd[0] = fd_safer (ifd[0])) < 0)
263       error (EXIT_FAILURE, errno, _("cannot create pipe"));
264   if (pipe_stdin)
265     if (pipe (ofd) < 0
266         || (ofd[1] = fd_safer (ofd[1])) < 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 }