/* Utilities to execute a program in a subprocess (possibly linked by pipes with other subprocesses), and wait for it. OS/2 specialization. Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. This file is part of the libiberty library. Libiberty is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Libiberty is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with libiberty; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pex-common.h" #include #include #ifdef NEED_DECLARATION_ERRNO extern int errno; #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_SYS_WAIT_H #include #endif #ifndef HAVE_WAITPID #define waitpid(pid, status, flags) wait(status) #endif #include #define INCL_BASE #include #include int pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags) const char *program; char * const *argv; const char *this_pname; const char *temp_base; char **errmsg_fmt, **errmsg_arg; int flags; { static int last_pipe_input = STDIN_FILE_NO; int pid; int pdes[2], org_stdin, org_stdout; int input_desc = last_pipe_input; int output_desc = STDOUT_FILE_NO; #ifdef __OS2__ #define pipes_supported 1 #else int pipes_supported = _osmode != DOS_MODE || (_emx_env & 0x1000); if (!pipes_supported && (flags & PEXECUTE_ONE) != PEXECUTE_ONE) { static char *errtpl = "%s: exec %s (pipes not supported)"; *errmsg_fmt = (char *) xmalloc (strlen(errtpl) + \ strlen(this_pname) + strlen(program)); sprintf (*errmsg_fmt, errtpl, this_pname, program); *errmsg_arg = NULL; return -1; } #endif /* If this isn't the last process, make a pipe for its output, and record it as waiting to be the input to the next process. */ if (!(flags & PEXECUTE_LAST)) { if (pipe (pdes) < 0) { static char *errtpl = "%s: pipe to/from %s"; *errmsg_fmt = (char *) xmalloc (strlen(errtpl) + \ strlen(this_pname) + strlen(program)); sprintf (*errmsg_fmt, errtpl, this_pname, program); *errmsg_arg = NULL; return -1; } output_desc = pdes[WRITE_PORT]; last_pipe_input = pdes[READ_PORT]; /* we don't wanna have an extra handles in the child. */ fcntl (pdes[READ_PORT], F_SETFD, FD_CLOEXEC); fcntl (pdes[WRITE_PORT], F_SETFD, FD_CLOEXEC); } else last_pipe_input = STDIN_FILE_NO; if (pipes_supported && input_desc != STDIN_FILE_NO) { org_stdin = dup (STDIN_FILE_NO); fcntl (org_stdin, F_SETFD, FD_CLOEXEC); dup2 (input_desc, STDIN_FILE_NO); fcntl (STDIN_FILE_NO, F_SETFD, 0); /* paranoia. but what's the deal with this flag over dup? */ close (input_desc); } if (pipes_supported && output_desc != STDOUT_FILE_NO) { org_stdout = dup (STDOUT_FILE_NO); fcntl (org_stdout, F_SETFD, FD_CLOEXEC); dup2 (output_desc, STDOUT_FILE_NO); fcntl (STDOUT_FILE_NO, F_SETFD, 0); /* paranoia. but what's the deal with this flag over dup? */ close (output_desc); } pid = (flags & PEXECUTE_SEARCH ? spawnvp : spawnv) (P_NOWAIT, program, argv); if (pipes_supported && input_desc != STDIN_FILE_NO) { dup2 (org_stdin, STDIN_FILE_NO); fcntl (STDIN_FILE_NO, F_SETFD, 0); /* paranoia. but what's the deal with this flag over dup? */ close (org_stdin); } if (pipes_supported && output_desc != STDOUT_FILE_NO) { dup2 (org_stdout, STDOUT_FILE_NO); fcntl (STDOUT_FILE_NO, F_SETFD, 0); /* paranoia. but what's the deal with this flag over dup? */ close (org_stdout); } if (pid == -1) { static char *errtpl = "%s: error executing %s"; *errmsg_fmt = (char *) xmalloc (strlen(errtpl) + \ strlen(this_pname) + strlen(program)); sprintf (*errmsg_fmt, errtpl, this_pname, program); *errmsg_arg = NULL; } return pid; } int pwait (pid, status, flags) int pid; int *status; int flags; { /* ??? Here's an opportunity to canonicalize the values in STATUS. Needed? */ int rc; do rc = waitpid (pid, status, flags); while (rc < 0 && errno == EINTR); return rc; }