1 | /* Creation of subprocesses, communicating via pipes. |
2 | Copyright (C) 2001-2004, 2006-2019 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 <https://www.gnu.org/licenses/>. */ |
17 | |
18 | |
19 | /* Tell clang not to warn about the 'child' variable, below. */ |
20 | #if defined __clang__ |
21 | # pragma clang diagnostic ignored "-Wconditional-uninitialized" |
22 | #endif |
23 | |
24 | #include <config.h> |
25 | |
26 | /* Specification. */ |
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 "error.h" |
36 | #include "fatal-signal.h" |
37 | #include "unistd-safer.h" |
38 | #include "wait-process.h" |
39 | #include "gettext.h" |
40 | |
41 | #define _(str) gettext (str) |
42 | |
43 | #if (defined _WIN32 && ! defined __CYGWIN__) || defined __KLIBC__ |
44 | |
45 | /* Native Windows API. */ |
46 | # include <process.h> |
47 | # include "w32spawn.h" |
48 | |
49 | #else |
50 | |
51 | /* Unix API. */ |
52 | # include <spawn.h> |
53 | |
54 | #endif |
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 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 | #undef close /* avoid warning related to gnulib module unistd */ |
75 | #define close nonintr_close |
76 | |
77 | #if defined _WIN32 && ! defined __CYGWIN__ |
78 | static int |
79 | nonintr_open (const char *pathname, int oflag, mode_t mode) |
80 | { |
81 | int retval; |
82 | |
83 | do |
84 | retval = open (pathname, oflag, mode); |
85 | while (retval < 0 && errno == EINTR); |
86 | |
87 | return retval; |
88 | } |
89 | # undef open /* avoid warning on VMS */ |
90 | # define open nonintr_open |
91 | #endif |
92 | |
93 | #endif |
94 | |
95 | |
96 | /* Open a pipe connected to a child process. |
97 | * |
98 | * write system read |
99 | * parent -> fd[1] -> STDIN_FILENO -> child if pipe_stdin |
100 | * parent <- fd[0] <- STDOUT_FILENO <- child if pipe_stdout |
101 | * read system write |
102 | * |
103 | * At least one of pipe_stdin, pipe_stdout must be true. |
104 | * pipe_stdin and prog_stdin together determine the child's standard input. |
105 | * pipe_stdout and prog_stdout together determine the child's standard output. |
106 | * If pipe_stdin is true, prog_stdin is ignored. |
107 | * If pipe_stdout is true, prog_stdout is ignored. |
108 | */ |
109 | static pid_t |
110 | create_pipe (const char *progname, |
111 | const char *prog_path, char **prog_argv, |
112 | bool pipe_stdin, bool pipe_stdout, |
113 | const char *prog_stdin, const char *prog_stdout, |
114 | bool null_stderr, |
115 | bool slave_process, bool exit_on_error, |
116 | int fd[2]) |
117 | { |
118 | #if (defined _WIN32 && ! defined __CYGWIN__) || defined __KLIBC__ |
119 | |
120 | /* Native Windows API. |
121 | This uses _pipe(), dup2(), and spawnv(). It could also be implemented |
122 | using the low-level functions CreatePipe(), DuplicateHandle(), |
123 | CreateProcess() and _open_osfhandle(); see the GNU make and GNU clisp |
124 | and cvs source code. */ |
125 | int ifd[2]; |
126 | int ofd[2]; |
127 | int orig_stdin; |
128 | int orig_stdout; |
129 | int orig_stderr; |
130 | int child; |
131 | int nulloutfd; |
132 | int stdinfd; |
133 | int stdoutfd; |
134 | int saved_errno; |
135 | |
136 | /* FIXME: Need to free memory allocated by prepare_spawn. */ |
137 | prog_argv = prepare_spawn (prog_argv); |
138 | |
139 | if (pipe_stdout) |
140 | if (pipe2_safer (ifd, O_BINARY | O_CLOEXEC) < 0) |
141 | error (EXIT_FAILURE, errno, _("cannot create pipe" )); |
142 | if (pipe_stdin) |
143 | if (pipe2_safer (ofd, O_BINARY | O_CLOEXEC) < 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_safer_noinherit (STDIN_FILENO); |
157 | if (pipe_stdout || prog_stdout != NULL) |
158 | orig_stdout = dup_safer_noinherit (STDOUT_FILENO); |
159 | if (null_stderr) |
160 | orig_stderr = dup_safer_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). */ |
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 a 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 (child == -1) |
211 | saved_errno = errno; |
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 | undup_safer_noinherit (orig_stderr, STDERR_FILENO); |
222 | if (pipe_stdout || prog_stdout != NULL) |
223 | undup_safer_noinherit (orig_stdout, STDOUT_FILENO); |
224 | if (pipe_stdin || prog_stdin != NULL) |
225 | undup_safer_noinherit (orig_stdin, STDIN_FILENO); |
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, saved_errno, |
235 | _("%s subprocess failed" ), progname); |
236 | if (pipe_stdout) |
237 | close (ifd[0]); |
238 | if (pipe_stdin) |
239 | close (ofd[1]); |
240 | errno = saved_errno; |
241 | return -1; |
242 | } |
243 | |
244 | if (pipe_stdout) |
245 | fd[0] = ifd[0]; |
246 | if (pipe_stdin) |
247 | fd[1] = ofd[1]; |
248 | return child; |
249 | |
250 | #else |
251 | |
252 | /* Unix API. */ |
253 | int ifd[2]; |
254 | int ofd[2]; |
255 | sigset_t blocked_signals; |
256 | posix_spawn_file_actions_t actions; |
257 | bool actions_allocated; |
258 | posix_spawnattr_t attrs; |
259 | bool attrs_allocated; |
260 | int err; |
261 | pid_t child; |
262 | |
263 | if (pipe_stdout) |
264 | if (pipe_safer (ifd) < 0) |
265 | error (EXIT_FAILURE, errno, _("cannot create pipe" )); |
266 | if (pipe_stdin) |
267 | if (pipe_safer (ofd) < 0) |
268 | error (EXIT_FAILURE, errno, _("cannot create pipe" )); |
269 | /* Data flow diagram: |
270 | * |
271 | * write system read |
272 | * parent -> ofd[1] -> ofd[0] -> child if pipe_stdin |
273 | * parent <- ifd[0] <- ifd[1] <- child if pipe_stdout |
274 | * read system write |
275 | * |
276 | */ |
277 | |
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 | errno = err; |
361 | return -1; |
362 | } |
363 | posix_spawn_file_actions_destroy (&actions); |
364 | if (attrs_allocated) |
365 | posix_spawnattr_destroy (&attrs); |
366 | if (slave_process) |
367 | { |
368 | register_slave_subprocess (child); |
369 | unblock_fatal_signals (); |
370 | } |
371 | if (pipe_stdin) |
372 | close (ofd[0]); |
373 | if (pipe_stdout) |
374 | close (ifd[1]); |
375 | |
376 | if (pipe_stdout) |
377 | fd[0] = ifd[0]; |
378 | if (pipe_stdin) |
379 | fd[1] = ofd[1]; |
380 | return child; |
381 | |
382 | #endif |
383 | } |
384 | |
385 | /* Open a bidirectional pipe. |
386 | * |
387 | * write system read |
388 | * parent -> fd[1] -> STDIN_FILENO -> child |
389 | * parent <- fd[0] <- STDOUT_FILENO <- child |
390 | * read system write |
391 | * |
392 | */ |
393 | pid_t |
394 | create_pipe_bidi (const char *progname, |
395 | const char *prog_path, char **prog_argv, |
396 | bool null_stderr, |
397 | bool slave_process, bool exit_on_error, |
398 | int fd[2]) |
399 | { |
400 | pid_t result = create_pipe (progname, prog_path, prog_argv, |
401 | true, true, NULL, NULL, |
402 | null_stderr, slave_process, exit_on_error, |
403 | fd); |
404 | return result; |
405 | } |
406 | |
407 | /* Open a pipe for input from a child process. |
408 | * The child's stdin comes from a file. |
409 | * |
410 | * read system write |
411 | * parent <- fd[0] <- STDOUT_FILENO <- child |
412 | * |
413 | */ |
414 | pid_t |
415 | create_pipe_in (const char *progname, |
416 | const char *prog_path, char **prog_argv, |
417 | const char *prog_stdin, bool null_stderr, |
418 | bool slave_process, bool exit_on_error, |
419 | int fd[1]) |
420 | { |
421 | int iofd[2]; |
422 | pid_t result = create_pipe (progname, prog_path, prog_argv, |
423 | false, true, prog_stdin, NULL, |
424 | null_stderr, slave_process, exit_on_error, |
425 | iofd); |
426 | if (result != -1) |
427 | fd[0] = iofd[0]; |
428 | return result; |
429 | } |
430 | |
431 | /* Open a pipe for output to a child process. |
432 | * The child's stdout goes to a file. |
433 | * |
434 | * write system read |
435 | * parent -> fd[0] -> STDIN_FILENO -> child |
436 | * |
437 | */ |
438 | pid_t |
439 | create_pipe_out (const char *progname, |
440 | const char *prog_path, char **prog_argv, |
441 | const char *prog_stdout, bool null_stderr, |
442 | bool slave_process, bool exit_on_error, |
443 | int fd[1]) |
444 | { |
445 | int iofd[2]; |
446 | pid_t result = create_pipe (progname, prog_path, prog_argv, |
447 | true, false, NULL, prog_stdout, |
448 | null_stderr, slave_process, exit_on_error, |
449 | iofd); |
450 | if (result != -1) |
451 | fd[0] = iofd[1]; |
452 | return result; |
453 | } |
454 | |