Home | History | Annotate | Line # | Download | only in libiberty
      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