pexecute.c revision 1.10 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