xref: /openbsd-src/gnu/lib/libiberty/src/pexecute.c (revision c3d06a32ae101e66e5f91584bf2c64d053884853)
1c6adbc09Sespie /* Utilities to execute a program in a subprocess (possibly linked by pipes
2c6adbc09Sespie    with other subprocesses), and wait for it.
3818008ffSmiod    Copyright (C) 2004 Free Software Foundation, Inc.
4c6adbc09Sespie 
5c6adbc09Sespie This file is part of the libiberty library.
6c6adbc09Sespie Libiberty is free software; you can redistribute it and/or
7c6adbc09Sespie modify it under the terms of the GNU Library General Public
8c6adbc09Sespie License as published by the Free Software Foundation; either
9c6adbc09Sespie version 2 of the License, or (at your option) any later version.
10c6adbc09Sespie 
11c6adbc09Sespie Libiberty is distributed in the hope that it will be useful,
12c6adbc09Sespie but WITHOUT ANY WARRANTY; without even the implied warranty of
13c6adbc09Sespie MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14c6adbc09Sespie Library General Public License for more details.
15c6adbc09Sespie 
16c6adbc09Sespie You should have received a copy of the GNU Library General Public
17c6adbc09Sespie License along with libiberty; see the file COPYING.LIB.  If not,
18818008ffSmiod write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19818008ffSmiod Boston, MA 02110-1301, USA.  */
20c6adbc09Sespie 
21818008ffSmiod /* pexecute is an old routine.  This implementation uses the newer
22818008ffSmiod    pex_init/pex_run/pex_get_status/pex_free routines.  Don't use
23818008ffSmiod    pexecute in new code.  Use the newer routines instead.  */
24c6adbc09Sespie 
25c6adbc09Sespie #include "config.h"
26818008ffSmiod #include "libiberty.h"
27*c3d06a32Sespie #include "pex-protos.h"
28c6adbc09Sespie 
29c6adbc09Sespie #ifdef HAVE_STDLIB_H
30c6adbc09Sespie #include <stdlib.h>
31c6adbc09Sespie #endif
32c6adbc09Sespie 
33818008ffSmiod /* We only permit a single pexecute chain to execute at a time.  This
34818008ffSmiod    was always true anyhow, though it wasn't documented.  */
35c6adbc09Sespie 
36818008ffSmiod static struct pex_obj *pex;
37818008ffSmiod static int idx;
38c6adbc09Sespie 
39c6adbc09Sespie int
pexecute(const char * program,char * const * argv,const char * pname,const char * temp_base,char ** errmsg_fmt,char ** errmsg_arg,int flags)40818008ffSmiod pexecute (const char *program, char * const *argv, const char *pname,
41818008ffSmiod 	  const char *temp_base, char **errmsg_fmt, char **errmsg_arg,
42818008ffSmiod 	  int flags)
43c6adbc09Sespie {
44818008ffSmiod   const char *errmsg;
45818008ffSmiod   int err;
46c6adbc09Sespie 
47818008ffSmiod   if ((flags & PEXECUTE_FIRST) != 0)
48c6adbc09Sespie     {
49818008ffSmiod       if (pex != NULL)
50c6adbc09Sespie 	{
51818008ffSmiod 	  *errmsg_fmt = (char *) "pexecute already in progress";
52c6adbc09Sespie 	  *errmsg_arg = NULL;
53c6adbc09Sespie 	  return -1;
54c6adbc09Sespie 	}
55818008ffSmiod       pex = pex_init (PEX_USE_PIPES, pname, temp_base);
56818008ffSmiod       idx = 0;
57c6adbc09Sespie     }
58c6adbc09Sespie   else
59c6adbc09Sespie     {
60818008ffSmiod       if (pex == NULL)
61c6adbc09Sespie 	{
62818008ffSmiod 	  *errmsg_fmt = (char *) "pexecute not in progress";
63c6adbc09Sespie 	  *errmsg_arg = NULL;
64c6adbc09Sespie 	  return -1;
65c6adbc09Sespie 	}
66c6adbc09Sespie     }
67c6adbc09Sespie 
68818008ffSmiod   errmsg = pex_run (pex,
69818008ffSmiod 		    (((flags & PEXECUTE_LAST) != 0 ? PEX_LAST : 0)
70818008ffSmiod 		     | ((flags & PEXECUTE_SEARCH) != 0 ? PEX_SEARCH : 0)),
71818008ffSmiod 		    program, argv, NULL, NULL, &err);
72818008ffSmiod   if (errmsg != NULL)
73c6adbc09Sespie     {
74818008ffSmiod       *errmsg_fmt = (char *) errmsg;
75c6adbc09Sespie       *errmsg_arg = NULL;
76c6adbc09Sespie       return -1;
77c6adbc09Sespie     }
78c6adbc09Sespie 
79818008ffSmiod   /* Instead of a PID, we just return a one-based index into the
80818008ffSmiod      status values.  We avoid zero just because the old pexecute would
81818008ffSmiod      never return it.  */
82818008ffSmiod   return ++idx;
83c6adbc09Sespie }
84c6adbc09Sespie 
85c6adbc09Sespie int
pwait(int pid,int * status,int flags ATTRIBUTE_UNUSED)86818008ffSmiod pwait (int pid, int *status, int flags ATTRIBUTE_UNUSED)
87c6adbc09Sespie {
88818008ffSmiod   /* The PID returned by pexecute is one-based.  */
89818008ffSmiod   --pid;
90818008ffSmiod 
91818008ffSmiod   if (pex == NULL || pid < 0 || pid >= idx)
92818008ffSmiod     return -1;
93818008ffSmiod 
94818008ffSmiod   if (pid == 0 && idx == 1)
95818008ffSmiod     {
96818008ffSmiod       if (!pex_get_status (pex, 1, status))
97818008ffSmiod 	return -1;
98818008ffSmiod     }
99818008ffSmiod   else
100818008ffSmiod     {
101818008ffSmiod       int *vector;
102818008ffSmiod 
103818008ffSmiod       vector = XNEWVEC (int, idx);
104818008ffSmiod       if (!pex_get_status (pex, idx, vector))
105818008ffSmiod 	{
106818008ffSmiod 	  free (vector);
107818008ffSmiod 	  return -1;
108818008ffSmiod 	}
109818008ffSmiod       *status = vector[pid];
110818008ffSmiod       free (vector);
111c6adbc09Sespie     }
112c6adbc09Sespie 
113818008ffSmiod   /* Assume that we are done after the caller has retrieved the last
114818008ffSmiod      exit status.  The original implementation did not require that
115818008ffSmiod      the exit statuses be retrieved in order, but this implementation
116818008ffSmiod      does.  */
117818008ffSmiod   if (pid + 1 == idx)
118818008ffSmiod     {
119818008ffSmiod       pex_free (pex);
120818008ffSmiod       pex = NULL;
121818008ffSmiod       idx = 0;
122818008ffSmiod     }
123818008ffSmiod 
124818008ffSmiod   return pid + 1;
125818008ffSmiod }
126