1214082Sdim/* Utilities to execute a program in a subprocess (possibly linked by pipes 2214082Sdim with other subprocesses), and wait for it. 3214082Sdim Copyright (C) 2004 Free Software Foundation, Inc. 4214082Sdim 5214082SdimThis file is part of the libiberty library. 6214082SdimLibiberty is free software; you can redistribute it and/or 7214082Sdimmodify it under the terms of the GNU Library General Public 8214082SdimLicense as published by the Free Software Foundation; either 9214082Sdimversion 2 of the License, or (at your option) any later version. 10214082Sdim 11214082SdimLibiberty is distributed in the hope that it will be useful, 12214082Sdimbut WITHOUT ANY WARRANTY; without even the implied warranty of 13214082SdimMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14214082SdimLibrary General Public License for more details. 15214082Sdim 16214082SdimYou should have received a copy of the GNU Library General Public 17214082SdimLicense along with libiberty; see the file COPYING.LIB. If not, 18214082Sdimwrite to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 19214082SdimBoston, MA 02110-1301, USA. */ 20214082Sdim 21214082Sdim/* pexecute is an old routine. This implementation uses the newer 22214082Sdim pex_init/pex_run/pex_get_status/pex_free routines. Don't use 23214082Sdim pexecute in new code. Use the newer routines instead. */ 24214082Sdim 25214082Sdim#include "config.h" 26214082Sdim#include "libiberty.h" 27214082Sdim 28214082Sdim#ifdef HAVE_STDLIB_H 29214082Sdim#include <stdlib.h> 30214082Sdim#endif 31214082Sdim 32214082Sdim/* We only permit a single pexecute chain to execute at a time. This 33214082Sdim was always true anyhow, though it wasn't documented. */ 34214082Sdim 35214082Sdimstatic struct pex_obj *pex; 36214082Sdimstatic int idx; 37214082Sdim 38214082Sdimint 39214082Sdimpexecute (const char *program, char * const *argv, const char *pname, 40214082Sdim const char *temp_base, char **errmsg_fmt, char **errmsg_arg, 41214082Sdim int flags) 42214082Sdim{ 43214082Sdim const char *errmsg; 44214082Sdim int err; 45214082Sdim 46214082Sdim if ((flags & PEXECUTE_FIRST) != 0) 47214082Sdim { 48214082Sdim if (pex != NULL) 49214082Sdim { 50214082Sdim *errmsg_fmt = (char *) "pexecute already in progress"; 51214082Sdim *errmsg_arg = NULL; 52214082Sdim return -1; 53214082Sdim } 54214082Sdim pex = pex_init (PEX_USE_PIPES, pname, temp_base); 55214082Sdim idx = 0; 56214082Sdim } 57214082Sdim else 58214082Sdim { 59214082Sdim if (pex == NULL) 60214082Sdim { 61214082Sdim *errmsg_fmt = (char *) "pexecute not in progress"; 62214082Sdim *errmsg_arg = NULL; 63214082Sdim return -1; 64214082Sdim } 65214082Sdim } 66214082Sdim 67214082Sdim errmsg = pex_run (pex, 68214082Sdim (((flags & PEXECUTE_LAST) != 0 ? PEX_LAST : 0) 69214082Sdim | ((flags & PEXECUTE_SEARCH) != 0 ? PEX_SEARCH : 0)), 70214082Sdim program, argv, NULL, NULL, &err); 71214082Sdim if (errmsg != NULL) 72214082Sdim { 73214082Sdim *errmsg_fmt = (char *) errmsg; 74214082Sdim *errmsg_arg = NULL; 75214082Sdim return -1; 76214082Sdim } 77214082Sdim 78214082Sdim /* Instead of a PID, we just return a one-based index into the 79214082Sdim status values. We avoid zero just because the old pexecute would 80214082Sdim never return it. */ 81214082Sdim return ++idx; 82214082Sdim} 83214082Sdim 84214082Sdimint 85214082Sdimpwait (int pid, int *status, int flags ATTRIBUTE_UNUSED) 86214082Sdim{ 87214082Sdim /* The PID returned by pexecute is one-based. */ 88214082Sdim --pid; 89214082Sdim 90214082Sdim if (pex == NULL || pid < 0 || pid >= idx) 91214082Sdim return -1; 92214082Sdim 93214082Sdim if (pid == 0 && idx == 1) 94214082Sdim { 95214082Sdim if (!pex_get_status (pex, 1, status)) 96214082Sdim return -1; 97214082Sdim } 98214082Sdim else 99214082Sdim { 100214082Sdim int *vector; 101214082Sdim 102214082Sdim vector = XNEWVEC (int, idx); 103214082Sdim if (!pex_get_status (pex, idx, vector)) 104214082Sdim { 105214082Sdim free (vector); 106214082Sdim return -1; 107214082Sdim } 108214082Sdim *status = vector[pid]; 109214082Sdim free (vector); 110214082Sdim } 111214082Sdim 112214082Sdim /* Assume that we are done after the caller has retrieved the last 113214082Sdim exit status. The original implementation did not require that 114214082Sdim the exit statuses be retrieved in order, but this implementation 115214082Sdim does. */ 116214082Sdim if (pid + 1 == idx) 117214082Sdim { 118214082Sdim pex_free (pex); 119214082Sdim pex = NULL; 120214082Sdim idx = 0; 121214082Sdim } 122214082Sdim 123214082Sdim return pid + 1; 124214082Sdim} 125