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