1 1.1 christos /* Utilities to execute a program in a subprocess (possibly linked by pipes 2 1.1 christos with other subprocesses), and wait for it. 3 1.10 christos Copyright (C) 2004-2024 Free Software Foundation, Inc. 4 1.1 christos 5 1.1 christos This file is part of the libiberty library. 6 1.1 christos Libiberty is free software; you can redistribute it and/or 7 1.1 christos modify it under the terms of the GNU Library General Public 8 1.1 christos License as published by the Free Software Foundation; either 9 1.1 christos version 2 of the License, or (at your option) any later version. 10 1.1 christos 11 1.1 christos Libiberty is distributed in the hope that it will be useful, 12 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 1.1 christos Library General Public License for more details. 15 1.1 christos 16 1.1 christos You should have received a copy of the GNU Library General Public 17 1.1 christos License along with libiberty; see the file COPYING.LIB. If not, 18 1.1 christos write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 19 1.1 christos Boston, MA 02110-1301, USA. */ 20 1.1 christos 21 1.1 christos /* pexecute is an old routine. This implementation uses the newer 22 1.1 christos pex_init/pex_run/pex_get_status/pex_free routines. Don't use 23 1.1 christos pexecute in new code. Use the newer routines instead. */ 24 1.1 christos 25 1.1 christos #include "config.h" 26 1.1 christos #include "libiberty.h" 27 1.1 christos 28 1.1 christos #ifdef HAVE_STDLIB_H 29 1.1 christos #include <stdlib.h> 30 1.1 christos #endif 31 1.1 christos 32 1.1 christos /* We only permit a single pexecute chain to execute at a time. This 33 1.1 christos was always true anyhow, though it wasn't documented. */ 34 1.1 christos 35 1.1 christos static struct pex_obj *pex; 36 1.1 christos static int idx; 37 1.1 christos 38 1.1 christos int 39 1.1 christos pexecute (const char *program, char * const *argv, const char *pname, 40 1.1 christos const char *temp_base, char **errmsg_fmt, char **errmsg_arg, 41 1.1 christos int flags) 42 1.1 christos { 43 1.1 christos const char *errmsg; 44 1.1 christos int err; 45 1.1 christos 46 1.1 christos if ((flags & PEXECUTE_FIRST) != 0) 47 1.1 christos { 48 1.1 christos if (pex != NULL) 49 1.1 christos { 50 1.1 christos *errmsg_fmt = (char *) "pexecute already in progress"; 51 1.1 christos *errmsg_arg = NULL; 52 1.1 christos return -1; 53 1.1 christos } 54 1.1 christos pex = pex_init (PEX_USE_PIPES, pname, temp_base); 55 1.1 christos idx = 0; 56 1.1 christos } 57 1.1 christos else 58 1.1 christos { 59 1.1 christos if (pex == NULL) 60 1.1 christos { 61 1.1 christos *errmsg_fmt = (char *) "pexecute not in progress"; 62 1.1 christos *errmsg_arg = NULL; 63 1.1 christos return -1; 64 1.1 christos } 65 1.1 christos } 66 1.1 christos 67 1.1 christos errmsg = pex_run (pex, 68 1.1 christos (((flags & PEXECUTE_LAST) != 0 ? PEX_LAST : 0) 69 1.1 christos | ((flags & PEXECUTE_SEARCH) != 0 ? PEX_SEARCH : 0)), 70 1.1 christos program, argv, NULL, NULL, &err); 71 1.1 christos if (errmsg != NULL) 72 1.1 christos { 73 1.1 christos *errmsg_fmt = (char *) errmsg; 74 1.1 christos *errmsg_arg = NULL; 75 1.1 christos return -1; 76 1.1 christos } 77 1.1 christos 78 1.1 christos /* Instead of a PID, we just return a one-based index into the 79 1.1 christos status values. We avoid zero just because the old pexecute would 80 1.1 christos never return it. */ 81 1.1 christos return ++idx; 82 1.1 christos } 83 1.1 christos 84 1.1 christos int 85 1.1 christos pwait (int pid, int *status, int flags ATTRIBUTE_UNUSED) 86 1.1 christos { 87 1.1 christos /* The PID returned by pexecute is one-based. */ 88 1.1 christos --pid; 89 1.1 christos 90 1.1 christos if (pex == NULL || pid < 0 || pid >= idx) 91 1.1 christos return -1; 92 1.1 christos 93 1.1 christos if (pid == 0 && idx == 1) 94 1.1 christos { 95 1.1 christos if (!pex_get_status (pex, 1, status)) 96 1.1 christos return -1; 97 1.1 christos } 98 1.1 christos else 99 1.1 christos { 100 1.1 christos int *vector; 101 1.1 christos 102 1.1 christos vector = XNEWVEC (int, idx); 103 1.1 christos if (!pex_get_status (pex, idx, vector)) 104 1.1 christos { 105 1.1 christos free (vector); 106 1.1 christos return -1; 107 1.1 christos } 108 1.1 christos *status = vector[pid]; 109 1.1 christos free (vector); 110 1.1 christos } 111 1.1 christos 112 1.1 christos /* Assume that we are done after the caller has retrieved the last 113 1.1 christos exit status. The original implementation did not require that 114 1.1 christos the exit statuses be retrieved in order, but this implementation 115 1.1 christos does. */ 116 1.1 christos if (pid + 1 == idx) 117 1.1 christos { 118 1.1 christos pex_free (pex); 119 1.1 christos pex = NULL; 120 1.1 christos idx = 0; 121 1.1 christos } 122 1.1 christos 123 1.1 christos return pid + 1; 124 1.1 christos } 125