105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Creation of subprocesses, communicating via pipes. 205436638acc7c010349a69c3395f1a57c642dc62Ying Wang Copyright (C) 2001-2004, 2006-2012 Free Software Foundation, Inc. 305436638acc7c010349a69c3395f1a57c642dc62Ying Wang Written by Bruno Haible <haible@clisp.cons.org>, 2001. 405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 505436638acc7c010349a69c3395f1a57c642dc62Ying Wang This program is free software: you can redistribute it and/or modify 605436638acc7c010349a69c3395f1a57c642dc62Ying Wang it under the terms of the GNU General Public License as published by 705436638acc7c010349a69c3395f1a57c642dc62Ying Wang the Free Software Foundation; either version 3 of the License, or 805436638acc7c010349a69c3395f1a57c642dc62Ying Wang (at your option) any later version. 905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1005436638acc7c010349a69c3395f1a57c642dc62Ying Wang This program is distributed in the hope that it will be useful, 1105436638acc7c010349a69c3395f1a57c642dc62Ying Wang but WITHOUT ANY WARRANTY; without even the implied warranty of 1205436638acc7c010349a69c3395f1a57c642dc62Ying Wang MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1305436638acc7c010349a69c3395f1a57c642dc62Ying Wang GNU General Public License for more details. 1405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1505436638acc7c010349a69c3395f1a57c642dc62Ying Wang You should have received a copy of the GNU General Public License 1605436638acc7c010349a69c3395f1a57c642dc62Ying Wang along with this program. If not, see <http://www.gnu.org/licenses/>. */ 1705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <config.h> 2005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Specification. */ 2205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "spawn-pipe.h" 2305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <errno.h> 2505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <fcntl.h> 2605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <stdlib.h> 2705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <signal.h> 2805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <unistd.h> 2905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "error.h" 3105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "fatal-signal.h" 3205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "unistd-safer.h" 3305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "wait-process.h" 3405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "gettext.h" 3505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define _(str) gettext (str) 3705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ 3905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 4005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Native Windows API. */ 4105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <process.h> 4205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include "w32spawn.h" 4305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 4405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#else 4505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 4605436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Unix API. */ 4705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <spawn.h> 4805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 4905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 5005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 5105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* The results of open() in this file are not used with fchdir, 5205436638acc7c010349a69c3395f1a57c642dc62Ying Wang therefore save some unnecessary work in fchdir.c. */ 5305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef open 5405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef close 5505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 5605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 5705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifdef EINTR 5805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 5905436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* EINTR handling for close(). 6005436638acc7c010349a69c3395f1a57c642dc62Ying Wang These functions can return -1/EINTR even though we don't have any 6105436638acc7c010349a69c3395f1a57c642dc62Ying Wang signal handlers set up, namely when we get interrupted via SIGSTOP. */ 6205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 6305436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic int 6405436638acc7c010349a69c3395f1a57c642dc62Ying Wangnonintr_close (int fd) 6505436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 6605436638acc7c010349a69c3395f1a57c642dc62Ying Wang int retval; 6705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 6805436638acc7c010349a69c3395f1a57c642dc62Ying Wang do 6905436638acc7c010349a69c3395f1a57c642dc62Ying Wang retval = close (fd); 7005436638acc7c010349a69c3395f1a57c642dc62Ying Wang while (retval < 0 && errno == EINTR); 7105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 7205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return retval; 7305436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 7405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define close nonintr_close 7505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 7605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ 7705436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic int 7805436638acc7c010349a69c3395f1a57c642dc62Ying Wangnonintr_open (const char *pathname, int oflag, mode_t mode) 7905436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 8005436638acc7c010349a69c3395f1a57c642dc62Ying Wang int retval; 8105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 8205436638acc7c010349a69c3395f1a57c642dc62Ying Wang do 8305436638acc7c010349a69c3395f1a57c642dc62Ying Wang retval = open (pathname, oflag, mode); 8405436638acc7c010349a69c3395f1a57c642dc62Ying Wang while (retval < 0 && errno == EINTR); 8505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 8605436638acc7c010349a69c3395f1a57c642dc62Ying Wang return retval; 8705436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 8805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# undef open /* avoid warning on VMS */ 8905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define open nonintr_open 9005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 9105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 9205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 9305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 9405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 9505436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Open a pipe connected to a child process. 9605436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 9705436638acc7c010349a69c3395f1a57c642dc62Ying Wang * write system read 9805436638acc7c010349a69c3395f1a57c642dc62Ying Wang * parent -> fd[1] -> STDIN_FILENO -> child if pipe_stdin 9905436638acc7c010349a69c3395f1a57c642dc62Ying Wang * parent <- fd[0] <- STDOUT_FILENO <- child if pipe_stdout 10005436638acc7c010349a69c3395f1a57c642dc62Ying Wang * read system write 10105436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 10205436638acc7c010349a69c3395f1a57c642dc62Ying Wang * At least one of pipe_stdin, pipe_stdout must be true. 10305436638acc7c010349a69c3395f1a57c642dc62Ying Wang * pipe_stdin and prog_stdin together determine the child's standard input. 10405436638acc7c010349a69c3395f1a57c642dc62Ying Wang * pipe_stdout and prog_stdout together determine the child's standard output. 10505436638acc7c010349a69c3395f1a57c642dc62Ying Wang * If pipe_stdin is true, prog_stdin is ignored. 10605436638acc7c010349a69c3395f1a57c642dc62Ying Wang * If pipe_stdout is true, prog_stdout is ignored. 10705436638acc7c010349a69c3395f1a57c642dc62Ying Wang */ 10805436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic pid_t 10905436638acc7c010349a69c3395f1a57c642dc62Ying Wangcreate_pipe (const char *progname, 11005436638acc7c010349a69c3395f1a57c642dc62Ying Wang const char *prog_path, char **prog_argv, 11105436638acc7c010349a69c3395f1a57c642dc62Ying Wang bool pipe_stdin, bool pipe_stdout, 11205436638acc7c010349a69c3395f1a57c642dc62Ying Wang const char *prog_stdin, const char *prog_stdout, 11305436638acc7c010349a69c3395f1a57c642dc62Ying Wang bool null_stderr, 11405436638acc7c010349a69c3395f1a57c642dc62Ying Wang bool slave_process, bool exit_on_error, 11505436638acc7c010349a69c3395f1a57c642dc62Ying Wang int fd[2]) 11605436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 11705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ 11805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 11905436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Native Windows API. 12005436638acc7c010349a69c3395f1a57c642dc62Ying Wang This uses _pipe(), dup2(), and spawnv(). It could also be implemented 12105436638acc7c010349a69c3395f1a57c642dc62Ying Wang using the low-level functions CreatePipe(), DuplicateHandle(), 12205436638acc7c010349a69c3395f1a57c642dc62Ying Wang CreateProcess() and _open_osfhandle(); see the GNU make and GNU clisp 12305436638acc7c010349a69c3395f1a57c642dc62Ying Wang and cvs source code. */ 12405436638acc7c010349a69c3395f1a57c642dc62Ying Wang int ifd[2]; 12505436638acc7c010349a69c3395f1a57c642dc62Ying Wang int ofd[2]; 12605436638acc7c010349a69c3395f1a57c642dc62Ying Wang int orig_stdin; 12705436638acc7c010349a69c3395f1a57c642dc62Ying Wang int orig_stdout; 12805436638acc7c010349a69c3395f1a57c642dc62Ying Wang int orig_stderr; 12905436638acc7c010349a69c3395f1a57c642dc62Ying Wang int child; 13005436638acc7c010349a69c3395f1a57c642dc62Ying Wang int nulloutfd; 13105436638acc7c010349a69c3395f1a57c642dc62Ying Wang int stdinfd; 13205436638acc7c010349a69c3395f1a57c642dc62Ying Wang int stdoutfd; 13305436638acc7c010349a69c3395f1a57c642dc62Ying Wang int saved_errno; 13405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 13505436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* FIXME: Need to free memory allocated by prepare_spawn. */ 13605436638acc7c010349a69c3395f1a57c642dc62Ying Wang prog_argv = prepare_spawn (prog_argv); 13705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 13805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe_stdout) 13905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe2_safer (ifd, O_BINARY | O_CLOEXEC) < 0) 14005436638acc7c010349a69c3395f1a57c642dc62Ying Wang error (EXIT_FAILURE, errno, _("cannot create pipe")); 14105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe_stdin) 14205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe2_safer (ofd, O_BINARY | O_CLOEXEC) < 0) 14305436638acc7c010349a69c3395f1a57c642dc62Ying Wang error (EXIT_FAILURE, errno, _("cannot create pipe")); 14405436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Data flow diagram: 14505436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 14605436638acc7c010349a69c3395f1a57c642dc62Ying Wang * write system read 14705436638acc7c010349a69c3395f1a57c642dc62Ying Wang * parent -> ofd[1] -> ofd[0] -> child if pipe_stdin 14805436638acc7c010349a69c3395f1a57c642dc62Ying Wang * parent <- ifd[0] <- ifd[1] <- child if pipe_stdout 14905436638acc7c010349a69c3395f1a57c642dc62Ying Wang * read system write 15005436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 15105436638acc7c010349a69c3395f1a57c642dc62Ying Wang */ 15205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 15305436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Save standard file handles of parent process. */ 15405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe_stdin || prog_stdin != NULL) 15505436638acc7c010349a69c3395f1a57c642dc62Ying Wang orig_stdin = dup_safer_noinherit (STDIN_FILENO); 15605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe_stdout || prog_stdout != NULL) 15705436638acc7c010349a69c3395f1a57c642dc62Ying Wang orig_stdout = dup_safer_noinherit (STDOUT_FILENO); 15805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (null_stderr) 15905436638acc7c010349a69c3395f1a57c642dc62Ying Wang orig_stderr = dup_safer_noinherit (STDERR_FILENO); 16005436638acc7c010349a69c3395f1a57c642dc62Ying Wang child = -1; 16105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 16205436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Create standard file handles of child process. */ 16305436638acc7c010349a69c3395f1a57c642dc62Ying Wang nulloutfd = -1; 16405436638acc7c010349a69c3395f1a57c642dc62Ying Wang stdinfd = -1; 16505436638acc7c010349a69c3395f1a57c642dc62Ying Wang stdoutfd = -1; 16605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if ((!pipe_stdin || dup2 (ofd[0], STDIN_FILENO) >= 0) 16705436638acc7c010349a69c3395f1a57c642dc62Ying Wang && (!pipe_stdout || dup2 (ifd[1], STDOUT_FILENO) >= 0) 16805436638acc7c010349a69c3395f1a57c642dc62Ying Wang && (!null_stderr 16905436638acc7c010349a69c3395f1a57c642dc62Ying Wang || ((nulloutfd = open ("NUL", O_RDWR, 0)) >= 0 17005436638acc7c010349a69c3395f1a57c642dc62Ying Wang && (nulloutfd == STDERR_FILENO 17105436638acc7c010349a69c3395f1a57c642dc62Ying Wang || (dup2 (nulloutfd, STDERR_FILENO) >= 0 17205436638acc7c010349a69c3395f1a57c642dc62Ying Wang && close (nulloutfd) >= 0)))) 17305436638acc7c010349a69c3395f1a57c642dc62Ying Wang && (pipe_stdin 17405436638acc7c010349a69c3395f1a57c642dc62Ying Wang || prog_stdin == NULL 17505436638acc7c010349a69c3395f1a57c642dc62Ying Wang || ((stdinfd = open (prog_stdin, O_RDONLY, 0)) >= 0 17605436638acc7c010349a69c3395f1a57c642dc62Ying Wang && (stdinfd == STDIN_FILENO 17705436638acc7c010349a69c3395f1a57c642dc62Ying Wang || (dup2 (stdinfd, STDIN_FILENO) >= 0 17805436638acc7c010349a69c3395f1a57c642dc62Ying Wang && close (stdinfd) >= 0)))) 17905436638acc7c010349a69c3395f1a57c642dc62Ying Wang && (pipe_stdout 18005436638acc7c010349a69c3395f1a57c642dc62Ying Wang || prog_stdout == NULL 18105436638acc7c010349a69c3395f1a57c642dc62Ying Wang || ((stdoutfd = open (prog_stdout, O_WRONLY, 0)) >= 0 18205436638acc7c010349a69c3395f1a57c642dc62Ying Wang && (stdoutfd == STDOUT_FILENO 18305436638acc7c010349a69c3395f1a57c642dc62Ying Wang || (dup2 (stdoutfd, STDOUT_FILENO) >= 0 18405436638acc7c010349a69c3395f1a57c642dc62Ying Wang && close (stdoutfd) >= 0))))) 18505436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* The child process doesn't inherit ifd[0], ifd[1], ofd[0], ofd[1], 18605436638acc7c010349a69c3395f1a57c642dc62Ying Wang but it inherits all open()ed or dup2()ed file handles (which is what 18705436638acc7c010349a69c3395f1a57c642dc62Ying Wang we want in the case of STD*_FILENO). */ 18805436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Use spawnvpe and pass the environment explicitly. This is needed if 18905436638acc7c010349a69c3395f1a57c642dc62Ying Wang the program has modified the environment using putenv() or [un]setenv(). 19005436638acc7c010349a69c3395f1a57c642dc62Ying Wang On Windows, programs have two environments, one in the "environment 19105436638acc7c010349a69c3395f1a57c642dc62Ying Wang block" of the process and managed through SetEnvironmentVariable(), and 19205436638acc7c010349a69c3395f1a57c642dc62Ying Wang one inside the process, in the location retrieved by the 'environ' 19305436638acc7c010349a69c3395f1a57c642dc62Ying Wang macro. When using spawnvp() without 'e', the child process inherits a 19405436638acc7c010349a69c3395f1a57c642dc62Ying Wang copy of the environment block - ignoring the effects of putenv() and 19505436638acc7c010349a69c3395f1a57c642dc62Ying Wang [un]setenv(). */ 19605436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 19705436638acc7c010349a69c3395f1a57c642dc62Ying Wang child = spawnvpe (P_NOWAIT, prog_path, (const char **) prog_argv, 19805436638acc7c010349a69c3395f1a57c642dc62Ying Wang (const char **) environ); 19905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (child < 0 && errno == ENOEXEC) 20005436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 20105436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* prog is not a native executable. Try to execute it as a 20205436638acc7c010349a69c3395f1a57c642dc62Ying Wang shell script. Note that prepare_spawn() has already prepended 20305436638acc7c010349a69c3395f1a57c642dc62Ying Wang a hidden element "sh.exe" to prog_argv. */ 20405436638acc7c010349a69c3395f1a57c642dc62Ying Wang --prog_argv; 20505436638acc7c010349a69c3395f1a57c642dc62Ying Wang child = spawnvpe (P_NOWAIT, prog_argv[0], (const char **) prog_argv, 20605436638acc7c010349a69c3395f1a57c642dc62Ying Wang (const char **) environ); 20705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 20805436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 20905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (child == -1) 21005436638acc7c010349a69c3395f1a57c642dc62Ying Wang saved_errno = errno; 21105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (stdinfd >= 0) 21205436638acc7c010349a69c3395f1a57c642dc62Ying Wang close (stdinfd); 21305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (stdoutfd >= 0) 21405436638acc7c010349a69c3395f1a57c642dc62Ying Wang close (stdoutfd); 21505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (nulloutfd >= 0) 21605436638acc7c010349a69c3395f1a57c642dc62Ying Wang close (nulloutfd); 21705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 21805436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Restore standard file handles of parent process. */ 21905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (null_stderr) 22005436638acc7c010349a69c3395f1a57c642dc62Ying Wang undup_safer_noinherit (orig_stderr, STDERR_FILENO); 22105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe_stdout || prog_stdout != NULL) 22205436638acc7c010349a69c3395f1a57c642dc62Ying Wang undup_safer_noinherit (orig_stdout, STDOUT_FILENO); 22305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe_stdin || prog_stdin != NULL) 22405436638acc7c010349a69c3395f1a57c642dc62Ying Wang undup_safer_noinherit (orig_stdin, STDIN_FILENO); 22505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 22605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe_stdin) 22705436638acc7c010349a69c3395f1a57c642dc62Ying Wang close (ofd[0]); 22805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe_stdout) 22905436638acc7c010349a69c3395f1a57c642dc62Ying Wang close (ifd[1]); 23005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (child == -1) 23105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 23205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (exit_on_error || !null_stderr) 23305436638acc7c010349a69c3395f1a57c642dc62Ying Wang error (exit_on_error ? EXIT_FAILURE : 0, saved_errno, 23405436638acc7c010349a69c3395f1a57c642dc62Ying Wang _("%s subprocess failed"), progname); 23505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe_stdout) 23605436638acc7c010349a69c3395f1a57c642dc62Ying Wang close (ifd[0]); 23705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe_stdin) 23805436638acc7c010349a69c3395f1a57c642dc62Ying Wang close (ofd[1]); 23905436638acc7c010349a69c3395f1a57c642dc62Ying Wang errno = saved_errno; 24005436638acc7c010349a69c3395f1a57c642dc62Ying Wang return -1; 24105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 24205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 24305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe_stdout) 24405436638acc7c010349a69c3395f1a57c642dc62Ying Wang fd[0] = ifd[0]; 24505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe_stdin) 24605436638acc7c010349a69c3395f1a57c642dc62Ying Wang fd[1] = ofd[1]; 24705436638acc7c010349a69c3395f1a57c642dc62Ying Wang return child; 24805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 24905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#else 25005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 25105436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Unix API. */ 25205436638acc7c010349a69c3395f1a57c642dc62Ying Wang int ifd[2]; 25305436638acc7c010349a69c3395f1a57c642dc62Ying Wang int ofd[2]; 25405436638acc7c010349a69c3395f1a57c642dc62Ying Wang sigset_t blocked_signals; 25505436638acc7c010349a69c3395f1a57c642dc62Ying Wang posix_spawn_file_actions_t actions; 25605436638acc7c010349a69c3395f1a57c642dc62Ying Wang bool actions_allocated; 25705436638acc7c010349a69c3395f1a57c642dc62Ying Wang posix_spawnattr_t attrs; 25805436638acc7c010349a69c3395f1a57c642dc62Ying Wang bool attrs_allocated; 25905436638acc7c010349a69c3395f1a57c642dc62Ying Wang int err; 26005436638acc7c010349a69c3395f1a57c642dc62Ying Wang pid_t child; 26105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 26205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe_stdout) 26305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe_safer (ifd) < 0) 26405436638acc7c010349a69c3395f1a57c642dc62Ying Wang error (EXIT_FAILURE, errno, _("cannot create pipe")); 26505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe_stdin) 26605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe_safer (ofd) < 0) 26705436638acc7c010349a69c3395f1a57c642dc62Ying Wang error (EXIT_FAILURE, errno, _("cannot create pipe")); 26805436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Data flow diagram: 26905436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 27005436638acc7c010349a69c3395f1a57c642dc62Ying Wang * write system read 27105436638acc7c010349a69c3395f1a57c642dc62Ying Wang * parent -> ofd[1] -> ofd[0] -> child if pipe_stdin 27205436638acc7c010349a69c3395f1a57c642dc62Ying Wang * parent <- ifd[0] <- ifd[1] <- child if pipe_stdout 27305436638acc7c010349a69c3395f1a57c642dc62Ying Wang * read system write 27405436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 27505436638acc7c010349a69c3395f1a57c642dc62Ying Wang */ 27605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 27705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (slave_process) 27805436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 27905436638acc7c010349a69c3395f1a57c642dc62Ying Wang sigprocmask (SIG_SETMASK, NULL, &blocked_signals); 28005436638acc7c010349a69c3395f1a57c642dc62Ying Wang block_fatal_signals (); 28105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 28205436638acc7c010349a69c3395f1a57c642dc62Ying Wang actions_allocated = false; 28305436638acc7c010349a69c3395f1a57c642dc62Ying Wang attrs_allocated = false; 28405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if ((err = posix_spawn_file_actions_init (&actions)) != 0 28505436638acc7c010349a69c3395f1a57c642dc62Ying Wang || (actions_allocated = true, 28605436638acc7c010349a69c3395f1a57c642dc62Ying Wang (pipe_stdin 28705436638acc7c010349a69c3395f1a57c642dc62Ying Wang && (err = posix_spawn_file_actions_adddup2 (&actions, 28805436638acc7c010349a69c3395f1a57c642dc62Ying Wang ofd[0], STDIN_FILENO)) 28905436638acc7c010349a69c3395f1a57c642dc62Ying Wang != 0) 29005436638acc7c010349a69c3395f1a57c642dc62Ying Wang || (pipe_stdout 29105436638acc7c010349a69c3395f1a57c642dc62Ying Wang && (err = posix_spawn_file_actions_adddup2 (&actions, 29205436638acc7c010349a69c3395f1a57c642dc62Ying Wang ifd[1], STDOUT_FILENO)) 29305436638acc7c010349a69c3395f1a57c642dc62Ying Wang != 0) 29405436638acc7c010349a69c3395f1a57c642dc62Ying Wang || (pipe_stdin 29505436638acc7c010349a69c3395f1a57c642dc62Ying Wang && (err = posix_spawn_file_actions_addclose (&actions, ofd[0])) 29605436638acc7c010349a69c3395f1a57c642dc62Ying Wang != 0) 29705436638acc7c010349a69c3395f1a57c642dc62Ying Wang || (pipe_stdout 29805436638acc7c010349a69c3395f1a57c642dc62Ying Wang && (err = posix_spawn_file_actions_addclose (&actions, ifd[1])) 29905436638acc7c010349a69c3395f1a57c642dc62Ying Wang != 0) 30005436638acc7c010349a69c3395f1a57c642dc62Ying Wang || (pipe_stdin 30105436638acc7c010349a69c3395f1a57c642dc62Ying Wang && (err = posix_spawn_file_actions_addclose (&actions, ofd[1])) 30205436638acc7c010349a69c3395f1a57c642dc62Ying Wang != 0) 30305436638acc7c010349a69c3395f1a57c642dc62Ying Wang || (pipe_stdout 30405436638acc7c010349a69c3395f1a57c642dc62Ying Wang && (err = posix_spawn_file_actions_addclose (&actions, ifd[0])) 30505436638acc7c010349a69c3395f1a57c642dc62Ying Wang != 0) 30605436638acc7c010349a69c3395f1a57c642dc62Ying Wang || (null_stderr 30705436638acc7c010349a69c3395f1a57c642dc62Ying Wang && (err = posix_spawn_file_actions_addopen (&actions, 30805436638acc7c010349a69c3395f1a57c642dc62Ying Wang STDERR_FILENO, 30905436638acc7c010349a69c3395f1a57c642dc62Ying Wang "/dev/null", O_RDWR, 31005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 0)) 31105436638acc7c010349a69c3395f1a57c642dc62Ying Wang != 0) 31205436638acc7c010349a69c3395f1a57c642dc62Ying Wang || (!pipe_stdin 31305436638acc7c010349a69c3395f1a57c642dc62Ying Wang && prog_stdin != NULL 31405436638acc7c010349a69c3395f1a57c642dc62Ying Wang && (err = posix_spawn_file_actions_addopen (&actions, 31505436638acc7c010349a69c3395f1a57c642dc62Ying Wang STDIN_FILENO, 31605436638acc7c010349a69c3395f1a57c642dc62Ying Wang prog_stdin, O_RDONLY, 31705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 0)) 31805436638acc7c010349a69c3395f1a57c642dc62Ying Wang != 0) 31905436638acc7c010349a69c3395f1a57c642dc62Ying Wang || (!pipe_stdout 32005436638acc7c010349a69c3395f1a57c642dc62Ying Wang && prog_stdout != NULL 32105436638acc7c010349a69c3395f1a57c642dc62Ying Wang && (err = posix_spawn_file_actions_addopen (&actions, 32205436638acc7c010349a69c3395f1a57c642dc62Ying Wang STDOUT_FILENO, 32305436638acc7c010349a69c3395f1a57c642dc62Ying Wang prog_stdout, O_WRONLY, 32405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 0)) 32505436638acc7c010349a69c3395f1a57c642dc62Ying Wang != 0) 32605436638acc7c010349a69c3395f1a57c642dc62Ying Wang || (slave_process 32705436638acc7c010349a69c3395f1a57c642dc62Ying Wang && ((err = posix_spawnattr_init (&attrs)) != 0 32805436638acc7c010349a69c3395f1a57c642dc62Ying Wang || (attrs_allocated = true, 32905436638acc7c010349a69c3395f1a57c642dc62Ying Wang (err = posix_spawnattr_setsigmask (&attrs, 33005436638acc7c010349a69c3395f1a57c642dc62Ying Wang &blocked_signals)) 33105436638acc7c010349a69c3395f1a57c642dc62Ying Wang != 0 33205436638acc7c010349a69c3395f1a57c642dc62Ying Wang || (err = posix_spawnattr_setflags (&attrs, 33305436638acc7c010349a69c3395f1a57c642dc62Ying Wang POSIX_SPAWN_SETSIGMASK)) 33405436638acc7c010349a69c3395f1a57c642dc62Ying Wang != 0))) 33505436638acc7c010349a69c3395f1a57c642dc62Ying Wang || (err = posix_spawnp (&child, prog_path, &actions, 33605436638acc7c010349a69c3395f1a57c642dc62Ying Wang attrs_allocated ? &attrs : NULL, prog_argv, 33705436638acc7c010349a69c3395f1a57c642dc62Ying Wang environ)) 33805436638acc7c010349a69c3395f1a57c642dc62Ying Wang != 0)) 33905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 34005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (actions_allocated) 34105436638acc7c010349a69c3395f1a57c642dc62Ying Wang posix_spawn_file_actions_destroy (&actions); 34205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (attrs_allocated) 34305436638acc7c010349a69c3395f1a57c642dc62Ying Wang posix_spawnattr_destroy (&attrs); 34405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (slave_process) 34505436638acc7c010349a69c3395f1a57c642dc62Ying Wang unblock_fatal_signals (); 34605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (exit_on_error || !null_stderr) 34705436638acc7c010349a69c3395f1a57c642dc62Ying Wang error (exit_on_error ? EXIT_FAILURE : 0, err, 34805436638acc7c010349a69c3395f1a57c642dc62Ying Wang _("%s subprocess failed"), progname); 34905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe_stdout) 35005436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 35105436638acc7c010349a69c3395f1a57c642dc62Ying Wang close (ifd[0]); 35205436638acc7c010349a69c3395f1a57c642dc62Ying Wang close (ifd[1]); 35305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 35405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe_stdin) 35505436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 35605436638acc7c010349a69c3395f1a57c642dc62Ying Wang close (ofd[0]); 35705436638acc7c010349a69c3395f1a57c642dc62Ying Wang close (ofd[1]); 35805436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 35905436638acc7c010349a69c3395f1a57c642dc62Ying Wang errno = err; 36005436638acc7c010349a69c3395f1a57c642dc62Ying Wang return -1; 36105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 36205436638acc7c010349a69c3395f1a57c642dc62Ying Wang posix_spawn_file_actions_destroy (&actions); 36305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (attrs_allocated) 36405436638acc7c010349a69c3395f1a57c642dc62Ying Wang posix_spawnattr_destroy (&attrs); 36505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (slave_process) 36605436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 36705436638acc7c010349a69c3395f1a57c642dc62Ying Wang register_slave_subprocess (child); 36805436638acc7c010349a69c3395f1a57c642dc62Ying Wang unblock_fatal_signals (); 36905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 37005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe_stdin) 37105436638acc7c010349a69c3395f1a57c642dc62Ying Wang close (ofd[0]); 37205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe_stdout) 37305436638acc7c010349a69c3395f1a57c642dc62Ying Wang close (ifd[1]); 37405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 37505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe_stdout) 37605436638acc7c010349a69c3395f1a57c642dc62Ying Wang fd[0] = ifd[0]; 37705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pipe_stdin) 37805436638acc7c010349a69c3395f1a57c642dc62Ying Wang fd[1] = ofd[1]; 37905436638acc7c010349a69c3395f1a57c642dc62Ying Wang return child; 38005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 38105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 38205436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 38305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 38405436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Open a bidirectional pipe. 38505436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 38605436638acc7c010349a69c3395f1a57c642dc62Ying Wang * write system read 38705436638acc7c010349a69c3395f1a57c642dc62Ying Wang * parent -> fd[1] -> STDIN_FILENO -> child 38805436638acc7c010349a69c3395f1a57c642dc62Ying Wang * parent <- fd[0] <- STDOUT_FILENO <- child 38905436638acc7c010349a69c3395f1a57c642dc62Ying Wang * read system write 39005436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 39105436638acc7c010349a69c3395f1a57c642dc62Ying Wang */ 39205436638acc7c010349a69c3395f1a57c642dc62Ying Wangpid_t 39305436638acc7c010349a69c3395f1a57c642dc62Ying Wangcreate_pipe_bidi (const char *progname, 39405436638acc7c010349a69c3395f1a57c642dc62Ying Wang const char *prog_path, char **prog_argv, 39505436638acc7c010349a69c3395f1a57c642dc62Ying Wang bool null_stderr, 39605436638acc7c010349a69c3395f1a57c642dc62Ying Wang bool slave_process, bool exit_on_error, 39705436638acc7c010349a69c3395f1a57c642dc62Ying Wang int fd[2]) 39805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 39905436638acc7c010349a69c3395f1a57c642dc62Ying Wang pid_t result = create_pipe (progname, prog_path, prog_argv, 40005436638acc7c010349a69c3395f1a57c642dc62Ying Wang true, true, NULL, NULL, 40105436638acc7c010349a69c3395f1a57c642dc62Ying Wang null_stderr, slave_process, exit_on_error, 40205436638acc7c010349a69c3395f1a57c642dc62Ying Wang fd); 40305436638acc7c010349a69c3395f1a57c642dc62Ying Wang return result; 40405436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 40505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 40605436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Open a pipe for input from a child process. 40705436638acc7c010349a69c3395f1a57c642dc62Ying Wang * The child's stdin comes from a file. 40805436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 40905436638acc7c010349a69c3395f1a57c642dc62Ying Wang * read system write 41005436638acc7c010349a69c3395f1a57c642dc62Ying Wang * parent <- fd[0] <- STDOUT_FILENO <- child 41105436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 41205436638acc7c010349a69c3395f1a57c642dc62Ying Wang */ 41305436638acc7c010349a69c3395f1a57c642dc62Ying Wangpid_t 41405436638acc7c010349a69c3395f1a57c642dc62Ying Wangcreate_pipe_in (const char *progname, 41505436638acc7c010349a69c3395f1a57c642dc62Ying Wang const char *prog_path, char **prog_argv, 41605436638acc7c010349a69c3395f1a57c642dc62Ying Wang const char *prog_stdin, bool null_stderr, 41705436638acc7c010349a69c3395f1a57c642dc62Ying Wang bool slave_process, bool exit_on_error, 41805436638acc7c010349a69c3395f1a57c642dc62Ying Wang int fd[1]) 41905436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 42005436638acc7c010349a69c3395f1a57c642dc62Ying Wang int iofd[2]; 42105436638acc7c010349a69c3395f1a57c642dc62Ying Wang pid_t result = create_pipe (progname, prog_path, prog_argv, 42205436638acc7c010349a69c3395f1a57c642dc62Ying Wang false, true, prog_stdin, NULL, 42305436638acc7c010349a69c3395f1a57c642dc62Ying Wang null_stderr, slave_process, exit_on_error, 42405436638acc7c010349a69c3395f1a57c642dc62Ying Wang iofd); 42505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (result != -1) 42605436638acc7c010349a69c3395f1a57c642dc62Ying Wang fd[0] = iofd[0]; 42705436638acc7c010349a69c3395f1a57c642dc62Ying Wang return result; 42805436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 42905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 43005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Open a pipe for output to a child process. 43105436638acc7c010349a69c3395f1a57c642dc62Ying Wang * The child's stdout goes to a file. 43205436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 43305436638acc7c010349a69c3395f1a57c642dc62Ying Wang * write system read 43405436638acc7c010349a69c3395f1a57c642dc62Ying Wang * parent -> fd[0] -> STDIN_FILENO -> child 43505436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 43605436638acc7c010349a69c3395f1a57c642dc62Ying Wang */ 43705436638acc7c010349a69c3395f1a57c642dc62Ying Wangpid_t 43805436638acc7c010349a69c3395f1a57c642dc62Ying Wangcreate_pipe_out (const char *progname, 43905436638acc7c010349a69c3395f1a57c642dc62Ying Wang const char *prog_path, char **prog_argv, 44005436638acc7c010349a69c3395f1a57c642dc62Ying Wang const char *prog_stdout, bool null_stderr, 44105436638acc7c010349a69c3395f1a57c642dc62Ying Wang bool slave_process, bool exit_on_error, 44205436638acc7c010349a69c3395f1a57c642dc62Ying Wang int fd[1]) 44305436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 44405436638acc7c010349a69c3395f1a57c642dc62Ying Wang int iofd[2]; 44505436638acc7c010349a69c3395f1a57c642dc62Ying Wang pid_t result = create_pipe (progname, prog_path, prog_argv, 44605436638acc7c010349a69c3395f1a57c642dc62Ying Wang true, false, NULL, prog_stdout, 44705436638acc7c010349a69c3395f1a57c642dc62Ying Wang null_stderr, slave_process, exit_on_error, 44805436638acc7c010349a69c3395f1a57c642dc62Ying Wang iofd); 44905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (result != -1) 45005436638acc7c010349a69c3395f1a57c642dc62Ying Wang fd[0] = iofd[1]; 45105436638acc7c010349a69c3395f1a57c642dc62Ying Wang return result; 45205436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 453