This source file includes following definitions.
- nonintr_close
- nonintr_open
- create_pipe
- create_pipe_bidi
- create_pipe_in
- create_pipe_out
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #if defined __clang__
21 # pragma clang diagnostic ignored "-Wconditional-uninitialized"
22 #endif
23
24 #include <config.h>
25
26
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
49
50
51
52
53
54
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
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
74 # include <process.h>
75 # include "os2-spawn.h"
76
77 #else
78
79
80 # include <spawn.h>
81
82 #endif
83
84
85 #ifdef EINTR
86
87
88
89
90
91 static int
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
103 #define close nonintr_close
104
105 #if (defined _WIN32 && !defined __CYGWIN__) && SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN
106 static int
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
118 # define open nonintr_open
119 #endif
120
121 #endif
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137 static pid_t
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
154
155
156
157
158
159
160
161
162
163
164
165
166
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 free (prog_path_to_free);
184 goto fail_with_errno;
185 }
186 free (prog_path_to_free);
187 prog_path_to_free = absolute_prog;
188 prog_path = absolute_prog;
189
190 if (! IS_ABSOLUTE_FILE_NAME (prog_path))
191 abort ();
192 }
193 }
194 }
195
196 #if ((defined _WIN32 && !defined __CYGWIN__) && SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN) || defined __KLIBC__
197
198
199
200
201
202
203 char *argv_mem_to_free;
204 int ifd[2];
205 int ofd[2];
206 int child;
207 int nulloutfd;
208 int stdinfd;
209 int stdoutfd;
210
211 const char **argv = prepare_spawn (prog_argv, &argv_mem_to_free);
212 if (argv == NULL)
213 xalloc_die ();
214
215 if (pipe_stdout)
216 if (pipe2_safer (ifd, O_BINARY | O_CLOEXEC) < 0)
217 error (EXIT_FAILURE, errno, _("cannot create pipe"));
218 if (pipe_stdin)
219 if (pipe2_safer (ofd, O_BINARY | O_CLOEXEC) < 0)
220 error (EXIT_FAILURE, errno, _("cannot create pipe"));
221
222
223
224
225
226
227
228
229
230 child = -1;
231
232 # if (defined _WIN32 && !defined __CYGWIN__) && SPAWN_PIPE_IMPL_AVOID_POSIX_SPAWN
233 bool must_close_ifd1 = pipe_stdout;
234 bool must_close_ofd0 = pipe_stdin;
235
236
237 HANDLE stdin_handle = INVALID_HANDLE_VALUE;
238 HANDLE stdout_handle = INVALID_HANDLE_VALUE;
239 nulloutfd = -1;
240 stdinfd = -1;
241 stdoutfd = -1;
242 if ((!null_stderr
243 || (nulloutfd = open ("NUL", O_RDWR, 0)) >= 0)
244 && (pipe_stdin
245 || prog_stdin == NULL
246 || (stdinfd = open (prog_stdin, O_RDONLY, 0)) >= 0)
247 && (pipe_stdout
248 || prog_stdout == NULL
249 || (stdoutfd = open (prog_stdout, O_WRONLY, 0)) >= 0))
250
251
252
253
254
255
256
257
258
259 {
260 stdin_handle =
261 (HANDLE) _get_osfhandle (pipe_stdin ? ofd[0] :
262 prog_stdin == NULL ? STDIN_FILENO : stdinfd);
263 if (pipe_stdin)
264 {
265 HANDLE curr_process = GetCurrentProcess ();
266 HANDLE duplicate;
267 if (!DuplicateHandle (curr_process, stdin_handle,
268 curr_process, &duplicate,
269 0, TRUE, DUPLICATE_SAME_ACCESS))
270 {
271 errno = EBADF;
272 goto failed;
273 }
274 must_close_ofd0 = false;
275 close (ofd[0]);
276 stdin_handle = duplicate;
277 }
278 stdout_handle =
279 (HANDLE) _get_osfhandle (pipe_stdout ? ifd[1] :
280 prog_stdout == NULL ? STDOUT_FILENO : stdoutfd);
281 if (pipe_stdout)
282 {
283 HANDLE curr_process = GetCurrentProcess ();
284 HANDLE duplicate;
285 if (!DuplicateHandle (curr_process, stdout_handle,
286 curr_process, &duplicate,
287 0, TRUE, DUPLICATE_SAME_ACCESS))
288 {
289 errno = EBADF;
290 goto failed;
291 }
292 must_close_ifd1 = false;
293 close (ifd[1]);
294 stdout_handle = duplicate;
295 }
296 HANDLE stderr_handle =
297 (HANDLE) _get_osfhandle (null_stderr ? nulloutfd : STDERR_FILENO);
298
299 child = spawnpvech (P_NOWAIT, prog_path, argv + 1,
300 (const char * const *) environ, directory,
301 stdin_handle, stdout_handle, stderr_handle);
302 # if 0
303 if (child == -1 && errno == ENOEXEC)
304 {
305
306
307
308 argv[1] = prog_path;
309 child = spawnpvech (P_NOWAIT, argv[0], argv,
310 (const char * const *) environ, directory,
311 stdin_handle, stdout_handle, stderr_handle);
312 }
313 # endif
314 }
315 failed:
316 if (child == -1)
317 saved_errno = errno;
318 if (stdinfd >= 0)
319 close (stdinfd);
320 if (stdoutfd >= 0)
321 close (stdoutfd);
322 if (nulloutfd >= 0)
323 close (nulloutfd);
324
325 if (pipe_stdin)
326 {
327 if (must_close_ofd0)
328 close (ofd[0]);
329 else
330 if (stdin_handle != INVALID_HANDLE_VALUE)
331 CloseHandle (stdin_handle);
332 }
333 if (pipe_stdout)
334 {
335 if (must_close_ifd1)
336 close (ifd[1]);
337 else
338 if (stdout_handle != INVALID_HANDLE_VALUE)
339 CloseHandle (stdout_handle);
340 }
341
342 # else
343 if (!(directory == NULL || strcmp (directory, ".") == 0))
344 {
345
346 saved_errno = EINVAL;
347 goto fail_with_saved_errno;
348 }
349
350 int orig_stdin;
351 int orig_stdout;
352 int orig_stderr;
353
354
355 if (pipe_stdin || prog_stdin != NULL)
356 orig_stdin = dup_safer_noinherit (STDIN_FILENO);
357 if (pipe_stdout || prog_stdout != NULL)
358 orig_stdout = dup_safer_noinherit (STDOUT_FILENO);
359 if (null_stderr)
360 orig_stderr = dup_safer_noinherit (STDERR_FILENO);
361
362
363 nulloutfd = -1;
364 stdinfd = -1;
365 stdoutfd = -1;
366 if ((!pipe_stdin || dup2 (ofd[0], STDIN_FILENO) >= 0)
367 && (!pipe_stdout || dup2 (ifd[1], STDOUT_FILENO) >= 0)
368 && (!null_stderr
369 || ((nulloutfd = open ("NUL", O_RDWR, 0)) >= 0
370 && (nulloutfd == STDERR_FILENO
371 || (dup2 (nulloutfd, STDERR_FILENO) >= 0
372 && close (nulloutfd) >= 0))))
373 && (pipe_stdin
374 || prog_stdin == NULL
375 || ((stdinfd = open (prog_stdin, O_RDONLY, 0)) >= 0
376 && (stdinfd == STDIN_FILENO
377 || (dup2 (stdinfd, STDIN_FILENO) >= 0
378 && close (stdinfd) >= 0))))
379 && (pipe_stdout
380 || prog_stdout == NULL
381 || ((stdoutfd = open (prog_stdout, O_WRONLY, 0)) >= 0
382 && (stdoutfd == STDOUT_FILENO
383 || (dup2 (stdoutfd, STDOUT_FILENO) >= 0
384 && close (stdoutfd) >= 0)))))
385
386
387
388 {
389 child = _spawnvpe (P_NOWAIT, prog_path, argv + 1,
390 (const char **) environ);
391 # if 0
392 if (child == -1 && errno == ENOEXEC)
393 {
394
395
396
397 child = _spawnvpe (P_NOWAIT, argv[0], argv,
398 (const char **) environ);
399 }
400 # endif
401 }
402 if (child == -1)
403 saved_errno = errno;
404 if (stdinfd >= 0)
405 close (stdinfd);
406 if (stdoutfd >= 0)
407 close (stdoutfd);
408 if (nulloutfd >= 0)
409 close (nulloutfd);
410
411
412 if (null_stderr)
413 undup_safer_noinherit (orig_stderr, STDERR_FILENO);
414 if (pipe_stdout || prog_stdout != NULL)
415 undup_safer_noinherit (orig_stdout, STDOUT_FILENO);
416 if (pipe_stdin || prog_stdin != NULL)
417 undup_safer_noinherit (orig_stdin, STDIN_FILENO);
418
419 if (pipe_stdin)
420 close (ofd[0]);
421 if (pipe_stdout)
422 close (ifd[1]);
423 # endif
424
425 free (argv);
426 free (argv_mem_to_free);
427 free (prog_path_to_free);
428
429 if (child == -1)
430 {
431 if (pipe_stdout)
432 close (ifd[0]);
433 if (pipe_stdin)
434 close (ofd[1]);
435 goto fail_with_saved_errno;
436 }
437
438 if (pipe_stdout)
439 fd[0] = ifd[0];
440 if (pipe_stdin)
441 fd[1] = ofd[1];
442 return child;
443
444 #else
445
446
447 int ifd[2];
448 int ofd[2];
449 sigset_t blocked_signals;
450 posix_spawn_file_actions_t actions;
451 bool actions_allocated;
452 posix_spawnattr_t attrs;
453 bool attrs_allocated;
454 int err;
455 pid_t child;
456
457 if (pipe_stdout)
458 if (pipe_safer (ifd) < 0)
459 error (EXIT_FAILURE, errno, _("cannot create pipe"));
460 if (pipe_stdin)
461 if (pipe_safer (ofd) < 0)
462 error (EXIT_FAILURE, errno, _("cannot create pipe"));
463
464
465
466
467
468
469
470
471
472 if (slave_process)
473 {
474 sigprocmask (SIG_SETMASK, NULL, &blocked_signals);
475 block_fatal_signals ();
476 }
477 actions_allocated = false;
478 attrs_allocated = false;
479 if ((err = posix_spawn_file_actions_init (&actions)) != 0
480 || (actions_allocated = true,
481 (pipe_stdin
482 && (err = posix_spawn_file_actions_adddup2 (&actions,
483 ofd[0], STDIN_FILENO))
484 != 0)
485 || (pipe_stdout
486 && (err = posix_spawn_file_actions_adddup2 (&actions,
487 ifd[1], STDOUT_FILENO))
488 != 0)
489 || (pipe_stdin
490 && (err = posix_spawn_file_actions_addclose (&actions, ofd[0]))
491 != 0)
492 || (pipe_stdout
493 && (err = posix_spawn_file_actions_addclose (&actions, ifd[1]))
494 != 0)
495 || (pipe_stdin
496 && (err = posix_spawn_file_actions_addclose (&actions, ofd[1]))
497 != 0)
498 || (pipe_stdout
499 && (err = posix_spawn_file_actions_addclose (&actions, ifd[0]))
500 != 0)
501 || (null_stderr
502 && (err = posix_spawn_file_actions_addopen (&actions,
503 STDERR_FILENO,
504 "/dev/null", O_RDWR,
505 0))
506 != 0)
507 || (!pipe_stdin
508 && prog_stdin != NULL
509 && (err = posix_spawn_file_actions_addopen (&actions,
510 STDIN_FILENO,
511 prog_stdin, O_RDONLY,
512 0))
513 != 0)
514 || (!pipe_stdout
515 && prog_stdout != NULL
516 && (err = posix_spawn_file_actions_addopen (&actions,
517 STDOUT_FILENO,
518 prog_stdout, O_WRONLY,
519 0))
520 != 0)
521 || (directory != NULL
522 && (err = posix_spawn_file_actions_addchdir (&actions,
523 directory)))
524 || (slave_process
525 && ((err = posix_spawnattr_init (&attrs)) != 0
526 || (attrs_allocated = true,
527 # if defined _WIN32 && !defined __CYGWIN__
528 (err = posix_spawnattr_setpgroup (&attrs, 0)) != 0
529 || (err = posix_spawnattr_setflags (&attrs,
530 POSIX_SPAWN_SETPGROUP))
531 != 0
532 # else
533 (err = posix_spawnattr_setsigmask (&attrs,
534 &blocked_signals))
535 != 0
536 || (err = posix_spawnattr_setflags (&attrs,
537 POSIX_SPAWN_SETSIGMASK))
538 != 0
539 # endif
540 ) ) )
541 || (err = (directory != NULL
542 ? posix_spawn (&child, prog_path, &actions,
543 attrs_allocated ? &attrs : NULL,
544 (char * const *) prog_argv, environ)
545 : posix_spawnp (&child, prog_path, &actions,
546 attrs_allocated ? &attrs : NULL,
547 (char * const *) prog_argv, environ)))
548 != 0))
549 {
550 if (actions_allocated)
551 posix_spawn_file_actions_destroy (&actions);
552 if (attrs_allocated)
553 posix_spawnattr_destroy (&attrs);
554 if (slave_process)
555 unblock_fatal_signals ();
556 if (pipe_stdout)
557 {
558 close (ifd[0]);
559 close (ifd[1]);
560 }
561 if (pipe_stdin)
562 {
563 close (ofd[0]);
564 close (ofd[1]);
565 }
566 free (prog_path_to_free);
567 saved_errno = err;
568 goto fail_with_saved_errno;
569 }
570 posix_spawn_file_actions_destroy (&actions);
571 if (attrs_allocated)
572 posix_spawnattr_destroy (&attrs);
573 if (slave_process)
574 {
575 register_slave_subprocess (child);
576 unblock_fatal_signals ();
577 }
578 if (pipe_stdin)
579 close (ofd[0]);
580 if (pipe_stdout)
581 close (ifd[1]);
582 free (prog_path_to_free);
583
584 if (pipe_stdout)
585 fd[0] = ifd[0];
586 if (pipe_stdin)
587 fd[1] = ofd[1];
588 return child;
589
590 #endif
591
592 fail_with_errno:
593 saved_errno = errno;
594 fail_with_saved_errno:
595 if (exit_on_error || !null_stderr)
596 error (exit_on_error ? EXIT_FAILURE : 0, saved_errno,
597 _("%s subprocess failed"), progname);
598 errno = saved_errno;
599 return -1;
600 }
601
602
603
604
605
606
607
608
609
610 pid_t
611 create_pipe_bidi (const char *progname,
612 const char *prog_path, const char * const *prog_argv,
613 const char *directory,
614 bool null_stderr,
615 bool slave_process, bool exit_on_error,
616 int fd[2])
617 {
618 pid_t result = create_pipe (progname, prog_path, prog_argv, directory,
619 true, true, NULL, NULL,
620 null_stderr, slave_process, exit_on_error,
621 fd);
622 return result;
623 }
624
625
626
627
628
629
630
631
632 pid_t
633 create_pipe_in (const char *progname,
634 const char *prog_path, const char * const *prog_argv,
635 const char *directory,
636 const char *prog_stdin, bool null_stderr,
637 bool slave_process, bool exit_on_error,
638 int fd[1])
639 {
640 int iofd[2];
641 pid_t result = create_pipe (progname, prog_path, prog_argv, directory,
642 false, true, prog_stdin, NULL,
643 null_stderr, slave_process, exit_on_error,
644 iofd);
645 if (result != -1)
646 fd[0] = iofd[0];
647 return result;
648 }
649
650
651
652
653
654
655
656
657 pid_t
658 create_pipe_out (const char *progname,
659 const char *prog_path, const char * const *prog_argv,
660 const char *directory,
661 const char *prog_stdout, bool null_stderr,
662 bool slave_process, bool exit_on_error,
663 int fd[1])
664 {
665 int iofd[2];
666 pid_t result = create_pipe (progname, prog_path, prog_argv, directory,
667 true, false, NULL, prog_stdout,
668 null_stderr, slave_process, exit_on_error,
669 iofd);
670 if (result != -1)
671 fd[0] = iofd[1];
672 return result;
673 }