Mercurial > hg > octave-nkf > gnulib-hg
annotate lib/pipe.c @ 6259:96c32553b4c6
Use a consistent style for including <config.h>.
* __fpending.c, acl.c, argmatch.c,
argp-help.c, argp-parse.c,
argp-pvh.c, backupfile.c, basename.c, c-stack.c,
calloc.c, check-version.c, cloexec.c, closeout.c, copy-file.c,
creat-safer.c, cycle-check.c, dirfd.c, dirname.c, dup-safer.c,
dup2.c, euidaccess.c, exclude.c, exitfail.c, fatal-signal.c,
fd-safer.c, file-type.c, fileblocks.c, filemode.c,
filenamecat.c, findprog.c, fnmatch.c, fopen-safer.c, free.c,
fsusage.c, ftruncate.c, full-write.c, fwriteerror.c,
getaddrinfo.c, getcwd.c, getdelim.c, getline.c, getlogin_r.c,
getndelim2.c, getnline.c, getopt1.c, getpass.c, group-member.c,
hard-locale.c, hash-pjw.c, hash.c, human.c, idcache.c,
inet_ntop.c, isdir.c, long-options.c, malloc.c, memcasecmp.c,
memcmp.c, memcoll.c, memcpy.c, memmove.c, mkdir-p.c,
modechange.c, mountlist.c, open-safer.c, physmem.c,
pipe-safer.c, pipe.c, poll.c, posixver.c, progname.c,
progreloc.c, putenv.c, quote.c, quotearg.c, readline.c,
readlink.c, realloc.c, regex.c, rename.c, rmdir.c, rpmatch.c,
safe-read.c, same.c, save-cwd.c, savedir.c, sig2str.c,
strcspn.c, strerror.c, stripslash.c, strncasecmp.c, strndup.c,
strnlen.c, strnlen1.c, strsep.c, strstr.c, strtod.c,
strtoimax.c, strtol.c, strverscmp.c, tempname.c, time_r.c,
userspec.c, utimecmp.c, version-etc-fsf.c,
version-etc.c, wait-process.c, xalloc-die.c, xgetcwd.c,
xmalloc.c, xmemcoll.c, xnanosleep.c, xreadlink.c, xsetenv.c,
xstrndup.c, xstrtoimax.c, xstrtol.c, xstrtoumax.c, yesno.c:
Standardize inclusion of config.h.
* __fpending.h, dirfd.h, getdate.h, human.h,
inttostr.h: Removed inclusion of config.h from header files.
* inttostr.c: Adjusted in-tree users.
* timespec.h: Remove superfluous warning to include config.h.
* atexit.c, chdir-long.c chown.c, fchown-stub.c, getgroups.c,
gettimeofday.c, lchown.c, lstat.c, mkdir.c, mkstemp.c,
nanosleep.c, openat.c, raise.c, readtokens0.c, readutmp.c,
unlinkdir.c: Guard inclusion of config.h with HAVE_CONFIG_H.
author | Paul Eggert <eggert@cs.ucla.edu> |
---|---|
date | Mon, 19 Sep 2005 17:28:14 +0000 |
parents | a48fb0e98c8c |
children | 1b0092424a44 |
rev | line source |
---|---|
4940 | 1 /* Creation of subprocesses, communicating via pipes. |
2 Copyright (C) 2001-2004 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 2, or (at your option) | |
8 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, write to the Free Software Foundation, | |
5848
a48fb0e98c8c
*** empty log message ***
Paul Eggert <eggert@cs.ucla.edu>
parents:
5580
diff
changeset
|
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ |
4940 | 18 |
19 | |
20 #ifdef HAVE_CONFIG_H | |
6259
96c32553b4c6
Use a consistent style for including <config.h>.
Paul Eggert <eggert@cs.ucla.edu>
parents:
5848
diff
changeset
|
21 # include <config.h> |
4940 | 22 #endif |
23 | |
24 /* Specification. */ | |
25 #include "pipe.h" | |
26 | |
27 #include <errno.h> | |
28 #include <fcntl.h> | |
29 #include <stdlib.h> | |
30 #include <signal.h> | |
31 | |
32 #ifdef HAVE_UNISTD_H | |
33 # include <unistd.h> | |
34 #endif | |
35 | |
36 #include "error.h" | |
37 #include "exit.h" | |
38 #include "fatal-signal.h" | |
39 #include "wait-process.h" | |
40 #include "gettext.h" | |
41 | |
42 #define _(str) gettext (str) | |
43 | |
44 #if defined _MSC_VER || defined __MINGW32__ | |
45 | |
46 /* Native Woe32 API. */ | |
47 # include <process.h> | |
48 # include "w32spawn.h" | |
49 | |
50 #else | |
51 | |
52 /* Unix API. */ | |
53 # ifdef HAVE_POSIX_SPAWN | |
54 # include <spawn.h> | |
55 # else | |
56 # ifdef HAVE_VFORK_H | |
57 # include <vfork.h> | |
58 # endif | |
59 # endif | |
60 | |
61 #endif | |
62 | |
5580
19f7545b3c2b
Declare environ; not all systems declare it.
Bruno Haible <bruno@clisp.org>
parents:
4940
diff
changeset
|
63 #ifndef HAVE_ENVIRON_DECL |
19f7545b3c2b
Declare environ; not all systems declare it.
Bruno Haible <bruno@clisp.org>
parents:
4940
diff
changeset
|
64 extern char **environ; |
19f7545b3c2b
Declare environ; not all systems declare it.
Bruno Haible <bruno@clisp.org>
parents:
4940
diff
changeset
|
65 #endif |
19f7545b3c2b
Declare environ; not all systems declare it.
Bruno Haible <bruno@clisp.org>
parents:
4940
diff
changeset
|
66 |
4940 | 67 #ifndef STDIN_FILENO |
68 # define STDIN_FILENO 0 | |
69 #endif | |
70 #ifndef STDOUT_FILENO | |
71 # define STDOUT_FILENO 1 | |
72 #endif | |
73 #ifndef STDERR_FILENO | |
74 # define STDERR_FILENO 2 | |
75 #endif | |
76 | |
77 | |
78 #ifdef EINTR | |
79 | |
80 /* EINTR handling for close(). | |
81 These functions can return -1/EINTR even though we don't have any | |
82 signal handlers set up, namely when we get interrupted via SIGSTOP. */ | |
83 | |
84 static inline int | |
85 nonintr_close (int fd) | |
86 { | |
87 int retval; | |
88 | |
89 do | |
90 retval = close (fd); | |
91 while (retval < 0 && errno == EINTR); | |
92 | |
93 return retval; | |
94 } | |
95 #define close nonintr_close | |
96 | |
97 static inline int | |
98 nonintr_open (const char *pathname, int oflag, mode_t mode) | |
99 { | |
100 int retval; | |
101 | |
102 do | |
103 retval = open (pathname, oflag, mode); | |
104 while (retval < 0 && errno == EINTR); | |
105 | |
106 return retval; | |
107 } | |
108 #undef open /* avoid warning on VMS */ | |
109 #define open nonintr_open | |
110 | |
111 #endif | |
112 | |
113 | |
114 /* Open a pipe connected to a child process. | |
115 * | |
116 * write system read | |
117 * parent -> fd[1] -> STDIN_FILENO -> child if pipe_stdin | |
118 * parent <- fd[0] <- STDOUT_FILENO <- child if pipe_stdout | |
119 * read system write | |
120 * | |
121 * At least one of pipe_stdin, pipe_stdout must be true. | |
122 * pipe_stdin and prog_stdin together determine the child's standard input. | |
123 * pipe_stdout and prog_stdout together determine the child's standard output. | |
124 * If pipe_stdin is true, prog_stdin is ignored. | |
125 * If pipe_stdout is true, prog_stdout is ignored. | |
126 */ | |
127 static pid_t | |
128 create_pipe (const char *progname, | |
129 const char *prog_path, char **prog_argv, | |
130 bool pipe_stdin, bool pipe_stdout, | |
131 const char *prog_stdin, const char *prog_stdout, | |
132 bool null_stderr, | |
133 bool slave_process, bool exit_on_error, | |
134 int fd[2]) | |
135 { | |
136 #if defined _MSC_VER || defined __MINGW32__ | |
137 | |
138 /* Native Woe32 API. | |
139 This uses _pipe(), dup2(), and spawnv(). It could also be implemented | |
140 using the low-level functions CreatePipe(), DuplicateHandle(), | |
141 CreateProcess() and _open_osfhandle(); see the GNU make and GNU clisp | |
142 and cvs source code. */ | |
143 int ifd[2]; | |
144 int ofd[2]; | |
145 int orig_stdin; | |
146 int orig_stdout; | |
147 int orig_stderr; | |
148 int child; | |
149 int nulloutfd; | |
150 int stdinfd; | |
151 int stdoutfd; | |
152 | |
153 prog_argv = prepare_spawn (prog_argv); | |
154 | |
155 if (pipe_stdout) | |
156 if (_pipe (ifd, 4096, O_BINARY | O_NOINHERIT) < 0) | |
157 error (EXIT_FAILURE, errno, _("cannot create pipe")); | |
158 if (pipe_stdin) | |
159 if (_pipe (ofd, 4096, O_BINARY | O_NOINHERIT) < 0) | |
160 error (EXIT_FAILURE, errno, _("cannot create pipe")); | |
161 /* Data flow diagram: | |
162 * | |
163 * write system read | |
164 * parent -> ofd[1] -> ofd[0] -> child if pipe_stdin | |
165 * parent <- ifd[0] <- ifd[1] <- child if pipe_stdout | |
166 * read system write | |
167 * | |
168 */ | |
169 | |
170 /* Save standard file handles of parent process. */ | |
171 if (pipe_stdin || prog_stdin != NULL) | |
172 orig_stdin = dup_noinherit (STDIN_FILENO); | |
173 if (pipe_stdout || prog_stdout != NULL) | |
174 orig_stdout = dup_noinherit (STDOUT_FILENO); | |
175 if (null_stderr) | |
176 orig_stderr = dup_noinherit (STDERR_FILENO); | |
177 child = -1; | |
178 | |
179 /* Create standard file handles of child process. */ | |
180 nulloutfd = -1; | |
181 stdinfd = -1; | |
182 stdoutfd = -1; | |
183 if ((!pipe_stdin || dup2 (ofd[0], STDIN_FILENO) >= 0) | |
184 && (!pipe_stdout || dup2 (ifd[1], STDOUT_FILENO) >= 0) | |
185 && (!null_stderr | |
186 || ((nulloutfd = open ("NUL", O_RDWR, 0)) >= 0 | |
187 && (nulloutfd == STDERR_FILENO | |
188 || (dup2 (nulloutfd, STDERR_FILENO) >= 0 | |
189 && close (nulloutfd) >= 0)))) | |
190 && (pipe_stdin | |
191 || prog_stdin == NULL | |
192 || ((stdinfd = open (prog_stdin, O_RDONLY, 0)) >= 0 | |
193 && (stdinfd == STDIN_FILENO | |
194 || (dup2 (stdinfd, STDIN_FILENO) >= 0 | |
195 && close (stdinfd) >= 0)))) | |
196 && (pipe_stdout | |
197 || prog_stdout == NULL | |
198 || ((stdoutfd = open (prog_stdout, O_WRONLY, 0)) >= 0 | |
199 && (stdoutfd == STDOUT_FILENO | |
200 || (dup2 (stdoutfd, STDOUT_FILENO) >= 0 | |
201 && close (stdoutfd) >= 0))))) | |
202 /* The child process doesn't inherit ifd[0], ifd[1], ofd[0], ofd[1], | |
203 but it inherits all open()ed or dup2()ed file handles (which is what | |
204 we want in the case of STD*_FILENO) and also orig_stdin, | |
205 orig_stdout, orig_stderr (which is not explicitly wanted but | |
206 harmless). */ | |
207 child = spawnvp (P_NOWAIT, prog_path, prog_argv); | |
208 if (stdinfd >= 0) | |
209 close (stdinfd); | |
210 if (stdoutfd >= 0) | |
211 close (stdoutfd); | |
212 if (nulloutfd >= 0) | |
213 close (nulloutfd); | |
214 | |
215 /* Restore standard file handles of parent process. */ | |
216 if (null_stderr) | |
217 dup2 (orig_stderr, STDERR_FILENO), close (orig_stderr); | |
218 if (pipe_stdout || prog_stdout != NULL) | |
219 dup2 (orig_stdout, STDOUT_FILENO), close (orig_stdout); | |
220 if (pipe_stdin || prog_stdin != NULL) | |
221 dup2 (orig_stdin, STDIN_FILENO), close (orig_stdin); | |
222 | |
223 if (pipe_stdin) | |
224 close (ofd[0]); | |
225 if (pipe_stdout) | |
226 close (ifd[1]); | |
227 if (child == -1) | |
228 { | |
229 if (exit_on_error || !null_stderr) | |
230 error (exit_on_error ? EXIT_FAILURE : 0, errno, | |
231 _("%s subprocess failed"), progname); | |
232 if (pipe_stdout) | |
233 close (ifd[0]); | |
234 if (pipe_stdin) | |
235 close (ofd[1]); | |
236 return -1; | |
237 } | |
238 | |
239 if (pipe_stdout) | |
240 fd[0] = ifd[0]; | |
241 if (pipe_stdin) | |
242 fd[1] = ofd[1]; | |
243 return child; | |
244 | |
245 #else | |
246 | |
247 /* Unix API. */ | |
248 int ifd[2]; | |
249 int ofd[2]; | |
250 # if HAVE_POSIX_SPAWN | |
251 sigset_t blocked_signals; | |
252 posix_spawn_file_actions_t actions; | |
253 bool actions_allocated; | |
254 posix_spawnattr_t attrs; | |
255 bool attrs_allocated; | |
256 int err; | |
257 pid_t child; | |
258 # else | |
259 int child; | |
260 # endif | |
261 | |
262 if (pipe_stdout) | |
263 if (pipe (ifd) < 0) | |
264 error (EXIT_FAILURE, errno, _("cannot create pipe")); | |
265 if (pipe_stdin) | |
266 if (pipe (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 HAVE_POSIX_SPAWN | |
278 if (slave_process) | |
279 { | |
280 sigprocmask (SIG_SETMASK, NULL, &blocked_signals); | |
281 block_fatal_signals (); | |
282 } | |
283 actions_allocated = false; | |
284 attrs_allocated = false; | |
285 if ((err = posix_spawn_file_actions_init (&actions)) != 0 | |
286 || (actions_allocated = true, | |
287 (pipe_stdin | |
288 && (err = posix_spawn_file_actions_adddup2 (&actions, | |
289 ofd[0], STDIN_FILENO)) | |
290 != 0) | |
291 || (pipe_stdout | |
292 && (err = posix_spawn_file_actions_adddup2 (&actions, | |
293 ifd[1], STDOUT_FILENO)) | |
294 != 0) | |
295 || (pipe_stdin | |
296 && (err = posix_spawn_file_actions_addclose (&actions, ofd[0])) | |
297 != 0) | |
298 || (pipe_stdout | |
299 && (err = posix_spawn_file_actions_addclose (&actions, ifd[1])) | |
300 != 0) | |
301 || (pipe_stdin | |
302 && (err = posix_spawn_file_actions_addclose (&actions, ofd[1])) | |
303 != 0) | |
304 || (pipe_stdout | |
305 && (err = posix_spawn_file_actions_addclose (&actions, ifd[0])) | |
306 != 0) | |
307 || (null_stderr | |
308 && (err = posix_spawn_file_actions_addopen (&actions, | |
309 STDERR_FILENO, | |
310 "/dev/null", O_RDWR, | |
311 0)) | |
312 != 0) | |
313 || (!pipe_stdin | |
314 && prog_stdin != NULL | |
315 && (err = posix_spawn_file_actions_addopen (&actions, | |
316 STDIN_FILENO, | |
317 prog_stdin, O_RDONLY, | |
318 0)) | |
319 != 0) | |
320 || (!pipe_stdout | |
321 && prog_stdout != NULL | |
322 && (err = posix_spawn_file_actions_addopen (&actions, | |
323 STDOUT_FILENO, | |
324 prog_stdout, O_WRONLY, | |
325 0)) | |
326 != 0) | |
327 || (slave_process | |
328 && ((err = posix_spawnattr_init (&attrs)) != 0 | |
329 || (attrs_allocated = true, | |
330 (err = posix_spawnattr_setsigmask (&attrs, | |
331 &blocked_signals)) | |
332 != 0 | |
333 || (err = posix_spawnattr_setflags (&attrs, | |
334 POSIX_SPAWN_SETSIGMASK)) | |
335 != 0))) | |
336 || (err = posix_spawnp (&child, prog_path, &actions, | |
337 attrs_allocated ? &attrs : NULL, prog_argv, | |
338 environ)) | |
339 != 0)) | |
340 { | |
341 if (actions_allocated) | |
342 posix_spawn_file_actions_destroy (&actions); | |
343 if (attrs_allocated) | |
344 posix_spawnattr_destroy (&attrs); | |
345 if (slave_process) | |
346 unblock_fatal_signals (); | |
347 if (exit_on_error || !null_stderr) | |
348 error (exit_on_error ? EXIT_FAILURE : 0, err, | |
349 _("%s subprocess failed"), progname); | |
350 if (pipe_stdout) | |
351 { | |
352 close (ifd[0]); | |
353 close (ifd[1]); | |
354 } | |
355 if (pipe_stdin) | |
356 { | |
357 close (ofd[0]); | |
358 close (ofd[1]); | |
359 } | |
360 return -1; | |
361 } | |
362 posix_spawn_file_actions_destroy (&actions); | |
363 if (attrs_allocated) | |
364 posix_spawnattr_destroy (&attrs); | |
365 # else | |
366 if (slave_process) | |
367 block_fatal_signals (); | |
368 /* Use vfork() instead of fork() for efficiency. */ | |
369 if ((child = vfork ()) == 0) | |
370 { | |
371 /* Child process code. */ | |
372 int nulloutfd; | |
373 int stdinfd; | |
374 int stdoutfd; | |
375 | |
376 if ((!pipe_stdin || dup2 (ofd[0], STDIN_FILENO) >= 0) | |
377 && (!pipe_stdout || dup2 (ifd[1], STDOUT_FILENO) >= 0) | |
378 && (!pipe_stdin || close (ofd[0]) >= 0) | |
379 && (!pipe_stdout || close (ifd[1]) >= 0) | |
380 && (!pipe_stdin || close (ofd[1]) >= 0) | |
381 && (!pipe_stdout || close (ifd[0]) >= 0) | |
382 && (!null_stderr | |
383 || ((nulloutfd = open ("/dev/null", O_RDWR, 0)) >= 0 | |
384 && (nulloutfd == STDERR_FILENO | |
385 || (dup2 (nulloutfd, STDERR_FILENO) >= 0 | |
386 && close (nulloutfd) >= 0)))) | |
387 && (pipe_stdin | |
388 || prog_stdin == NULL | |
389 || ((stdinfd = open (prog_stdin, O_RDONLY, 0)) >= 0 | |
390 && (stdinfd == STDIN_FILENO | |
391 || (dup2 (stdinfd, STDIN_FILENO) >= 0 | |
392 && close (stdinfd) >= 0)))) | |
393 && (pipe_stdout | |
394 || prog_stdout == NULL | |
395 || ((stdoutfd = open (prog_stdout, O_WRONLY, 0)) >= 0 | |
396 && (stdoutfd == STDOUT_FILENO | |
397 || (dup2 (stdoutfd, STDOUT_FILENO) >= 0 | |
398 && close (stdoutfd) >= 0)))) | |
399 && (!slave_process || (unblock_fatal_signals (), true))) | |
400 execvp (prog_path, prog_argv); | |
401 _exit (127); | |
402 } | |
403 if (child == -1) | |
404 { | |
405 if (slave_process) | |
406 unblock_fatal_signals (); | |
407 if (exit_on_error || !null_stderr) | |
408 error (exit_on_error ? EXIT_FAILURE : 0, errno, | |
409 _("%s subprocess failed"), progname); | |
410 if (pipe_stdout) | |
411 { | |
412 close (ifd[0]); | |
413 close (ifd[1]); | |
414 } | |
415 if (pipe_stdin) | |
416 { | |
417 close (ofd[0]); | |
418 close (ofd[1]); | |
419 } | |
420 return -1; | |
421 } | |
422 # endif | |
423 if (slave_process) | |
424 { | |
425 register_slave_subprocess (child); | |
426 unblock_fatal_signals (); | |
427 } | |
428 if (pipe_stdin) | |
429 close (ofd[0]); | |
430 if (pipe_stdout) | |
431 close (ifd[1]); | |
432 | |
433 if (pipe_stdout) | |
434 fd[0] = ifd[0]; | |
435 if (pipe_stdin) | |
436 fd[1] = ofd[1]; | |
437 return child; | |
438 | |
439 #endif | |
440 } | |
441 | |
442 /* Open a bidirectional pipe. | |
443 * | |
444 * write system read | |
445 * parent -> fd[1] -> STDIN_FILENO -> child | |
446 * parent <- fd[0] <- STDOUT_FILENO <- child | |
447 * read system write | |
448 * | |
449 */ | |
450 pid_t | |
451 create_pipe_bidi (const char *progname, | |
452 const char *prog_path, char **prog_argv, | |
453 bool null_stderr, | |
454 bool slave_process, bool exit_on_error, | |
455 int fd[2]) | |
456 { | |
457 pid_t result = create_pipe (progname, prog_path, prog_argv, | |
458 true, true, NULL, NULL, | |
459 null_stderr, slave_process, exit_on_error, | |
460 fd); | |
461 return result; | |
462 } | |
463 | |
464 /* Open a pipe for input from a child process. | |
465 * The child's stdin comes from a file. | |
466 * | |
467 * read system write | |
468 * parent <- fd[0] <- STDOUT_FILENO <- child | |
469 * | |
470 */ | |
471 pid_t | |
472 create_pipe_in (const char *progname, | |
473 const char *prog_path, char **prog_argv, | |
474 const char *prog_stdin, bool null_stderr, | |
475 bool slave_process, bool exit_on_error, | |
476 int fd[1]) | |
477 { | |
478 int iofd[2]; | |
479 pid_t result = create_pipe (progname, prog_path, prog_argv, | |
480 false, true, prog_stdin, NULL, | |
481 null_stderr, slave_process, exit_on_error, | |
482 iofd); | |
483 if (result != -1) | |
484 fd[0] = iofd[0]; | |
485 return result; | |
486 } | |
487 | |
488 /* Open a pipe for output to a child process. | |
489 * The child's stdout goes to a file. | |
490 * | |
491 * write system read | |
492 * parent -> fd[0] -> STDIN_FILENO -> child | |
493 * | |
494 */ | |
495 pid_t | |
496 create_pipe_out (const char *progname, | |
497 const char *prog_path, char **prog_argv, | |
498 const char *prog_stdout, bool null_stderr, | |
499 bool slave_process, bool exit_on_error, | |
500 int fd[1]) | |
501 { | |
502 int iofd[2]; | |
503 pid_t result = create_pipe (progname, prog_path, prog_argv, | |
504 true, false, NULL, prog_stdout, | |
505 null_stderr, slave_process, exit_on_error, | |
506 iofd); | |
507 if (result != -1) | |
508 fd[0] = iofd[1]; | |
509 return result; | |
510 } |