pex-common.c revision 1.1.1.1.8.2 1 1.1.1.1.8.2 tls /* Common code for executing a program in a sub-process.
2 1.1.1.1.8.2 tls Copyright (C) 2005 Free Software Foundation, Inc.
3 1.1.1.1.8.2 tls Written by Ian Lance Taylor <ian (at) airs.com>.
4 1.1.1.1.8.2 tls
5 1.1.1.1.8.2 tls This file is part of the libiberty library.
6 1.1.1.1.8.2 tls Libiberty is free software; you can redistribute it and/or
7 1.1.1.1.8.2 tls modify it under the terms of the GNU Library General Public
8 1.1.1.1.8.2 tls License as published by the Free Software Foundation; either
9 1.1.1.1.8.2 tls version 2 of the License, or (at your option) any later version.
10 1.1.1.1.8.2 tls
11 1.1.1.1.8.2 tls Libiberty is distributed in the hope that it will be useful,
12 1.1.1.1.8.2 tls but WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1.1.1.8.2 tls MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 1.1.1.1.8.2 tls Library General Public License for more details.
15 1.1.1.1.8.2 tls
16 1.1.1.1.8.2 tls You should have received a copy of the GNU Library General Public
17 1.1.1.1.8.2 tls License along with libiberty; see the file COPYING.LIB. If not,
18 1.1.1.1.8.2 tls write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19 1.1.1.1.8.2 tls Boston, MA 02110-1301, USA. */
20 1.1.1.1.8.2 tls
21 1.1.1.1.8.2 tls #include "config.h"
22 1.1.1.1.8.2 tls #include "libiberty.h"
23 1.1.1.1.8.2 tls #include "pex-common.h"
24 1.1.1.1.8.2 tls
25 1.1.1.1.8.2 tls #include <stdio.h>
26 1.1.1.1.8.2 tls #include <errno.h>
27 1.1.1.1.8.2 tls #ifdef NEED_DECLARATION_ERRNO
28 1.1.1.1.8.2 tls extern int errno;
29 1.1.1.1.8.2 tls #endif
30 1.1.1.1.8.2 tls #ifdef HAVE_STDLIB_H
31 1.1.1.1.8.2 tls #include <stdlib.h>
32 1.1.1.1.8.2 tls #endif
33 1.1.1.1.8.2 tls #ifdef HAVE_STRING_H
34 1.1.1.1.8.2 tls #include <string.h>
35 1.1.1.1.8.2 tls #endif
36 1.1.1.1.8.2 tls #ifdef HAVE_UNISTD_H
37 1.1.1.1.8.2 tls #include <unistd.h>
38 1.1.1.1.8.2 tls #endif
39 1.1.1.1.8.2 tls
40 1.1.1.1.8.2 tls extern int mkstemps (char *, int);
41 1.1.1.1.8.2 tls
42 1.1.1.1.8.2 tls /* This file contains subroutines for the program execution routines
43 1.1.1.1.8.2 tls (pex_init, pex_run, etc.). This file is compiled on all
44 1.1.1.1.8.2 tls systems. */
45 1.1.1.1.8.2 tls
46 1.1.1.1.8.2 tls static void pex_add_remove (struct pex_obj *, const char *, int);
47 1.1.1.1.8.2 tls static int pex_get_status_and_time (struct pex_obj *, int, const char **,
48 1.1.1.1.8.2 tls int *);
49 1.1.1.1.8.2 tls
50 1.1.1.1.8.2 tls /* Initialize a pex_obj structure. */
51 1.1.1.1.8.2 tls
52 1.1.1.1.8.2 tls struct pex_obj *
53 1.1.1.1.8.2 tls pex_init_common (int flags, const char *pname, const char *tempbase,
54 1.1.1.1.8.2 tls const struct pex_funcs *funcs)
55 1.1.1.1.8.2 tls {
56 1.1.1.1.8.2 tls struct pex_obj *obj;
57 1.1.1.1.8.2 tls
58 1.1.1.1.8.2 tls obj = XNEW (struct pex_obj);
59 1.1.1.1.8.2 tls obj->flags = flags;
60 1.1.1.1.8.2 tls obj->pname = pname;
61 1.1.1.1.8.2 tls obj->tempbase = tempbase;
62 1.1.1.1.8.2 tls obj->next_input = STDIN_FILE_NO;
63 1.1.1.1.8.2 tls obj->next_input_name = NULL;
64 1.1.1.1.8.2 tls obj->next_input_name_allocated = 0;
65 1.1.1.1.8.2 tls obj->stderr_pipe = -1;
66 1.1.1.1.8.2 tls obj->count = 0;
67 1.1.1.1.8.2 tls obj->children = NULL;
68 1.1.1.1.8.2 tls obj->status = NULL;
69 1.1.1.1.8.2 tls obj->time = NULL;
70 1.1.1.1.8.2 tls obj->number_waited = 0;
71 1.1.1.1.8.2 tls obj->input_file = NULL;
72 1.1.1.1.8.2 tls obj->read_output = NULL;
73 1.1.1.1.8.2 tls obj->read_err = NULL;
74 1.1.1.1.8.2 tls obj->remove_count = 0;
75 1.1.1.1.8.2 tls obj->remove = NULL;
76 1.1.1.1.8.2 tls obj->funcs = funcs;
77 1.1.1.1.8.2 tls obj->sysdep = NULL;
78 1.1.1.1.8.2 tls return obj;
79 1.1.1.1.8.2 tls }
80 1.1.1.1.8.2 tls
81 1.1.1.1.8.2 tls /* Add a file to be removed when we are done. */
82 1.1.1.1.8.2 tls
83 1.1.1.1.8.2 tls static void
84 1.1.1.1.8.2 tls pex_add_remove (struct pex_obj *obj, const char *name, int allocated)
85 1.1.1.1.8.2 tls {
86 1.1.1.1.8.2 tls char *add;
87 1.1.1.1.8.2 tls
88 1.1.1.1.8.2 tls ++obj->remove_count;
89 1.1.1.1.8.2 tls obj->remove = XRESIZEVEC (char *, obj->remove, obj->remove_count);
90 1.1.1.1.8.2 tls if (allocated)
91 1.1.1.1.8.2 tls add = (char *) name;
92 1.1.1.1.8.2 tls else
93 1.1.1.1.8.2 tls add = xstrdup (name);
94 1.1.1.1.8.2 tls obj->remove[obj->remove_count - 1] = add;
95 1.1.1.1.8.2 tls }
96 1.1.1.1.8.2 tls
97 1.1.1.1.8.2 tls /* Generate a temporary file name based on OBJ, FLAGS, and NAME.
98 1.1.1.1.8.2 tls Return NULL if we were unable to reserve a temporary filename.
99 1.1.1.1.8.2 tls
100 1.1.1.1.8.2 tls If non-NULL, the result is either allocated with malloc, or the
101 1.1.1.1.8.2 tls same pointer as NAME. */
102 1.1.1.1.8.2 tls static char *
103 1.1.1.1.8.2 tls temp_file (struct pex_obj *obj, int flags, char *name)
104 1.1.1.1.8.2 tls {
105 1.1.1.1.8.2 tls if (name == NULL)
106 1.1.1.1.8.2 tls {
107 1.1.1.1.8.2 tls if (obj->tempbase == NULL)
108 1.1.1.1.8.2 tls {
109 1.1.1.1.8.2 tls name = make_temp_file (NULL);
110 1.1.1.1.8.2 tls }
111 1.1.1.1.8.2 tls else
112 1.1.1.1.8.2 tls {
113 1.1.1.1.8.2 tls int len = strlen (obj->tempbase);
114 1.1.1.1.8.2 tls int out;
115 1.1.1.1.8.2 tls
116 1.1.1.1.8.2 tls if (len >= 6
117 1.1.1.1.8.2 tls && strcmp (obj->tempbase + len - 6, "XXXXXX") == 0)
118 1.1.1.1.8.2 tls name = xstrdup (obj->tempbase);
119 1.1.1.1.8.2 tls else
120 1.1.1.1.8.2 tls name = concat (obj->tempbase, "XXXXXX", NULL);
121 1.1.1.1.8.2 tls
122 1.1.1.1.8.2 tls out = mkstemps (name, 0);
123 1.1.1.1.8.2 tls if (out < 0)
124 1.1.1.1.8.2 tls {
125 1.1.1.1.8.2 tls free (name);
126 1.1.1.1.8.2 tls return NULL;
127 1.1.1.1.8.2 tls }
128 1.1.1.1.8.2 tls
129 1.1.1.1.8.2 tls /* This isn't obj->funcs->close because we got the
130 1.1.1.1.8.2 tls descriptor from mkstemps, not from a function in
131 1.1.1.1.8.2 tls obj->funcs. Calling close here is just like what
132 1.1.1.1.8.2 tls make_temp_file does. */
133 1.1.1.1.8.2 tls close (out);
134 1.1.1.1.8.2 tls }
135 1.1.1.1.8.2 tls }
136 1.1.1.1.8.2 tls else if ((flags & PEX_SUFFIX) != 0)
137 1.1.1.1.8.2 tls {
138 1.1.1.1.8.2 tls if (obj->tempbase == NULL)
139 1.1.1.1.8.2 tls name = make_temp_file (name);
140 1.1.1.1.8.2 tls else
141 1.1.1.1.8.2 tls name = concat (obj->tempbase, name, NULL);
142 1.1.1.1.8.2 tls }
143 1.1.1.1.8.2 tls
144 1.1.1.1.8.2 tls return name;
145 1.1.1.1.8.2 tls }
146 1.1.1.1.8.2 tls
147 1.1.1.1.8.2 tls
148 1.1.1.1.8.2 tls /* As for pex_run (), but permits the environment for the child process
149 1.1.1.1.8.2 tls to be specified. */
150 1.1.1.1.8.2 tls
151 1.1.1.1.8.2 tls const char *
152 1.1.1.1.8.2 tls pex_run_in_environment (struct pex_obj *obj, int flags, const char *executable,
153 1.1.1.1.8.2 tls char * const * argv, char * const * env,
154 1.1.1.1.8.2 tls const char *orig_outname, const char *errname,
155 1.1.1.1.8.2 tls int *err)
156 1.1.1.1.8.2 tls {
157 1.1.1.1.8.2 tls const char *errmsg;
158 1.1.1.1.8.2 tls int in, out, errdes;
159 1.1.1.1.8.2 tls char *outname;
160 1.1.1.1.8.2 tls int outname_allocated;
161 1.1.1.1.8.2 tls int p[2];
162 1.1.1.1.8.2 tls int toclose;
163 1.1.1.1.8.2 tls pid_t pid;
164 1.1.1.1.8.2 tls
165 1.1.1.1.8.2 tls in = -1;
166 1.1.1.1.8.2 tls out = -1;
167 1.1.1.1.8.2 tls errdes = -1;
168 1.1.1.1.8.2 tls outname = (char *) orig_outname;
169 1.1.1.1.8.2 tls outname_allocated = 0;
170 1.1.1.1.8.2 tls
171 1.1.1.1.8.2 tls /* If the user called pex_input_file, close the file now. */
172 1.1.1.1.8.2 tls if (obj->input_file)
173 1.1.1.1.8.2 tls {
174 1.1.1.1.8.2 tls if (fclose (obj->input_file) == EOF)
175 1.1.1.1.8.2 tls {
176 1.1.1.1.8.2 tls errmsg = "closing pipeline input file";
177 1.1.1.1.8.2 tls goto error_exit;
178 1.1.1.1.8.2 tls }
179 1.1.1.1.8.2 tls obj->input_file = NULL;
180 1.1.1.1.8.2 tls }
181 1.1.1.1.8.2 tls
182 1.1.1.1.8.2 tls /* Set IN. */
183 1.1.1.1.8.2 tls
184 1.1.1.1.8.2 tls if (obj->next_input_name != NULL)
185 1.1.1.1.8.2 tls {
186 1.1.1.1.8.2 tls /* We have to make sure that the previous process has completed
187 1.1.1.1.8.2 tls before we try to read the file. */
188 1.1.1.1.8.2 tls if (!pex_get_status_and_time (obj, 0, &errmsg, err))
189 1.1.1.1.8.2 tls goto error_exit;
190 1.1.1.1.8.2 tls
191 1.1.1.1.8.2 tls in = obj->funcs->open_read (obj, obj->next_input_name,
192 1.1.1.1.8.2 tls (flags & PEX_BINARY_INPUT) != 0);
193 1.1.1.1.8.2 tls if (in < 0)
194 1.1.1.1.8.2 tls {
195 1.1.1.1.8.2 tls *err = errno;
196 1.1.1.1.8.2 tls errmsg = "open temporary file";
197 1.1.1.1.8.2 tls goto error_exit;
198 1.1.1.1.8.2 tls }
199 1.1.1.1.8.2 tls if (obj->next_input_name_allocated)
200 1.1.1.1.8.2 tls {
201 1.1.1.1.8.2 tls free (obj->next_input_name);
202 1.1.1.1.8.2 tls obj->next_input_name_allocated = 0;
203 1.1.1.1.8.2 tls }
204 1.1.1.1.8.2 tls obj->next_input_name = NULL;
205 1.1.1.1.8.2 tls }
206 1.1.1.1.8.2 tls else
207 1.1.1.1.8.2 tls {
208 1.1.1.1.8.2 tls in = obj->next_input;
209 1.1.1.1.8.2 tls if (in < 0)
210 1.1.1.1.8.2 tls {
211 1.1.1.1.8.2 tls *err = 0;
212 1.1.1.1.8.2 tls errmsg = "pipeline already complete";
213 1.1.1.1.8.2 tls goto error_exit;
214 1.1.1.1.8.2 tls }
215 1.1.1.1.8.2 tls }
216 1.1.1.1.8.2 tls
217 1.1.1.1.8.2 tls /* Set OUT and OBJ->NEXT_INPUT/OBJ->NEXT_INPUT_NAME. */
218 1.1.1.1.8.2 tls
219 1.1.1.1.8.2 tls if ((flags & PEX_LAST) != 0)
220 1.1.1.1.8.2 tls {
221 1.1.1.1.8.2 tls if (outname == NULL)
222 1.1.1.1.8.2 tls out = STDOUT_FILE_NO;
223 1.1.1.1.8.2 tls else if ((flags & PEX_SUFFIX) != 0)
224 1.1.1.1.8.2 tls {
225 1.1.1.1.8.2 tls outname = concat (obj->tempbase, outname, NULL);
226 1.1.1.1.8.2 tls outname_allocated = 1;
227 1.1.1.1.8.2 tls }
228 1.1.1.1.8.2 tls obj->next_input = -1;
229 1.1.1.1.8.2 tls }
230 1.1.1.1.8.2 tls else if ((obj->flags & PEX_USE_PIPES) == 0)
231 1.1.1.1.8.2 tls {
232 1.1.1.1.8.2 tls outname = temp_file (obj, flags, outname);
233 1.1.1.1.8.2 tls if (! outname)
234 1.1.1.1.8.2 tls {
235 1.1.1.1.8.2 tls *err = 0;
236 1.1.1.1.8.2 tls errmsg = "could not create temporary file";
237 1.1.1.1.8.2 tls goto error_exit;
238 1.1.1.1.8.2 tls }
239 1.1.1.1.8.2 tls
240 1.1.1.1.8.2 tls if (outname != orig_outname)
241 1.1.1.1.8.2 tls outname_allocated = 1;
242 1.1.1.1.8.2 tls
243 1.1.1.1.8.2 tls if ((obj->flags & PEX_SAVE_TEMPS) == 0)
244 1.1.1.1.8.2 tls {
245 1.1.1.1.8.2 tls pex_add_remove (obj, outname, outname_allocated);
246 1.1.1.1.8.2 tls outname_allocated = 0;
247 1.1.1.1.8.2 tls }
248 1.1.1.1.8.2 tls
249 1.1.1.1.8.2 tls /* Hand off ownership of outname to the next stage. */
250 1.1.1.1.8.2 tls obj->next_input_name = outname;
251 1.1.1.1.8.2 tls obj->next_input_name_allocated = outname_allocated;
252 1.1.1.1.8.2 tls outname_allocated = 0;
253 1.1.1.1.8.2 tls }
254 1.1.1.1.8.2 tls else
255 1.1.1.1.8.2 tls {
256 1.1.1.1.8.2 tls if (obj->funcs->pipe (obj, p, (flags & PEX_BINARY_OUTPUT) != 0) < 0)
257 1.1.1.1.8.2 tls {
258 1.1.1.1.8.2 tls *err = errno;
259 1.1.1.1.8.2 tls errmsg = "pipe";
260 1.1.1.1.8.2 tls goto error_exit;
261 1.1.1.1.8.2 tls }
262 1.1.1.1.8.2 tls
263 1.1.1.1.8.2 tls out = p[WRITE_PORT];
264 1.1.1.1.8.2 tls obj->next_input = p[READ_PORT];
265 1.1.1.1.8.2 tls }
266 1.1.1.1.8.2 tls
267 1.1.1.1.8.2 tls if (out < 0)
268 1.1.1.1.8.2 tls {
269 1.1.1.1.8.2 tls out = obj->funcs->open_write (obj, outname,
270 1.1.1.1.8.2 tls (flags & PEX_BINARY_OUTPUT) != 0);
271 1.1.1.1.8.2 tls if (out < 0)
272 1.1.1.1.8.2 tls {
273 1.1.1.1.8.2 tls *err = errno;
274 1.1.1.1.8.2 tls errmsg = "open temporary output file";
275 1.1.1.1.8.2 tls goto error_exit;
276 1.1.1.1.8.2 tls }
277 1.1.1.1.8.2 tls }
278 1.1.1.1.8.2 tls
279 1.1.1.1.8.2 tls if (outname_allocated)
280 1.1.1.1.8.2 tls {
281 1.1.1.1.8.2 tls free (outname);
282 1.1.1.1.8.2 tls outname_allocated = 0;
283 1.1.1.1.8.2 tls }
284 1.1.1.1.8.2 tls
285 1.1.1.1.8.2 tls /* Set ERRDES. */
286 1.1.1.1.8.2 tls
287 1.1.1.1.8.2 tls if (errname != NULL && (flags & PEX_STDERR_TO_PIPE) != 0)
288 1.1.1.1.8.2 tls {
289 1.1.1.1.8.2 tls *err = 0;
290 1.1.1.1.8.2 tls errmsg = "both ERRNAME and PEX_STDERR_TO_PIPE specified.";
291 1.1.1.1.8.2 tls goto error_exit;
292 1.1.1.1.8.2 tls }
293 1.1.1.1.8.2 tls
294 1.1.1.1.8.2 tls if (obj->stderr_pipe != -1)
295 1.1.1.1.8.2 tls {
296 1.1.1.1.8.2 tls *err = 0;
297 1.1.1.1.8.2 tls errmsg = "PEX_STDERR_TO_PIPE used in the middle of pipeline";
298 1.1.1.1.8.2 tls goto error_exit;
299 1.1.1.1.8.2 tls }
300 1.1.1.1.8.2 tls
301 1.1.1.1.8.2 tls if (errname == NULL)
302 1.1.1.1.8.2 tls {
303 1.1.1.1.8.2 tls if (flags & PEX_STDERR_TO_PIPE)
304 1.1.1.1.8.2 tls {
305 1.1.1.1.8.2 tls if (obj->funcs->pipe (obj, p, (flags & PEX_BINARY_ERROR) != 0) < 0)
306 1.1.1.1.8.2 tls {
307 1.1.1.1.8.2 tls *err = errno;
308 1.1.1.1.8.2 tls errmsg = "pipe";
309 1.1.1.1.8.2 tls goto error_exit;
310 1.1.1.1.8.2 tls }
311 1.1.1.1.8.2 tls
312 1.1.1.1.8.2 tls errdes = p[WRITE_PORT];
313 1.1.1.1.8.2 tls obj->stderr_pipe = p[READ_PORT];
314 1.1.1.1.8.2 tls }
315 1.1.1.1.8.2 tls else
316 1.1.1.1.8.2 tls {
317 1.1.1.1.8.2 tls errdes = STDERR_FILE_NO;
318 1.1.1.1.8.2 tls }
319 1.1.1.1.8.2 tls }
320 1.1.1.1.8.2 tls else
321 1.1.1.1.8.2 tls {
322 1.1.1.1.8.2 tls errdes = obj->funcs->open_write (obj, errname,
323 1.1.1.1.8.2 tls (flags & PEX_BINARY_ERROR) != 0);
324 1.1.1.1.8.2 tls if (errdes < 0)
325 1.1.1.1.8.2 tls {
326 1.1.1.1.8.2 tls *err = errno;
327 1.1.1.1.8.2 tls errmsg = "open error file";
328 1.1.1.1.8.2 tls goto error_exit;
329 1.1.1.1.8.2 tls }
330 1.1.1.1.8.2 tls }
331 1.1.1.1.8.2 tls
332 1.1.1.1.8.2 tls /* If we are using pipes, the child process has to close the next
333 1.1.1.1.8.2 tls input pipe. */
334 1.1.1.1.8.2 tls
335 1.1.1.1.8.2 tls if ((obj->flags & PEX_USE_PIPES) == 0)
336 1.1.1.1.8.2 tls toclose = -1;
337 1.1.1.1.8.2 tls else
338 1.1.1.1.8.2 tls toclose = obj->next_input;
339 1.1.1.1.8.2 tls
340 1.1.1.1.8.2 tls /* Run the program. */
341 1.1.1.1.8.2 tls
342 1.1.1.1.8.2 tls pid = obj->funcs->exec_child (obj, flags, executable, argv, env,
343 1.1.1.1.8.2 tls in, out, errdes, toclose, &errmsg, err);
344 1.1.1.1.8.2 tls if (pid < 0)
345 1.1.1.1.8.2 tls goto error_exit;
346 1.1.1.1.8.2 tls
347 1.1.1.1.8.2 tls ++obj->count;
348 1.1.1.1.8.2 tls obj->children = XRESIZEVEC (pid_t, obj->children, obj->count);
349 1.1.1.1.8.2 tls obj->children[obj->count - 1] = pid;
350 1.1.1.1.8.2 tls
351 1.1.1.1.8.2 tls return NULL;
352 1.1.1.1.8.2 tls
353 1.1.1.1.8.2 tls error_exit:
354 1.1.1.1.8.2 tls if (in >= 0 && in != STDIN_FILE_NO)
355 1.1.1.1.8.2 tls obj->funcs->close (obj, in);
356 1.1.1.1.8.2 tls if (out >= 0 && out != STDOUT_FILE_NO)
357 1.1.1.1.8.2 tls obj->funcs->close (obj, out);
358 1.1.1.1.8.2 tls if (errdes >= 0 && errdes != STDERR_FILE_NO)
359 1.1.1.1.8.2 tls obj->funcs->close (obj, errdes);
360 1.1.1.1.8.2 tls if (outname_allocated)
361 1.1.1.1.8.2 tls free (outname);
362 1.1.1.1.8.2 tls return errmsg;
363 1.1.1.1.8.2 tls }
364 1.1.1.1.8.2 tls
365 1.1.1.1.8.2 tls /* Run a program. */
366 1.1.1.1.8.2 tls
367 1.1.1.1.8.2 tls const char *
368 1.1.1.1.8.2 tls pex_run (struct pex_obj *obj, int flags, const char *executable,
369 1.1.1.1.8.2 tls char * const * argv, const char *orig_outname, const char *errname,
370 1.1.1.1.8.2 tls int *err)
371 1.1.1.1.8.2 tls {
372 1.1.1.1.8.2 tls return pex_run_in_environment (obj, flags, executable, argv, NULL,
373 1.1.1.1.8.2 tls orig_outname, errname, err);
374 1.1.1.1.8.2 tls }
375 1.1.1.1.8.2 tls
376 1.1.1.1.8.2 tls /* Return a FILE pointer for a temporary file to fill with input for
377 1.1.1.1.8.2 tls the pipeline. */
378 1.1.1.1.8.2 tls FILE *
379 1.1.1.1.8.2 tls pex_input_file (struct pex_obj *obj, int flags, const char *in_name)
380 1.1.1.1.8.2 tls {
381 1.1.1.1.8.2 tls char *name = (char *) in_name;
382 1.1.1.1.8.2 tls FILE *f;
383 1.1.1.1.8.2 tls
384 1.1.1.1.8.2 tls /* This must be called before the first pipeline stage is run, and
385 1.1.1.1.8.2 tls there must not have been any other input selected. */
386 1.1.1.1.8.2 tls if (obj->count != 0
387 1.1.1.1.8.2 tls || (obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
388 1.1.1.1.8.2 tls || obj->next_input_name)
389 1.1.1.1.8.2 tls {
390 1.1.1.1.8.2 tls errno = EINVAL;
391 1.1.1.1.8.2 tls return NULL;
392 1.1.1.1.8.2 tls }
393 1.1.1.1.8.2 tls
394 1.1.1.1.8.2 tls name = temp_file (obj, flags, name);
395 1.1.1.1.8.2 tls if (! name)
396 1.1.1.1.8.2 tls return NULL;
397 1.1.1.1.8.2 tls
398 1.1.1.1.8.2 tls f = fopen (name, (flags & PEX_BINARY_OUTPUT) ? "wb" : "w");
399 1.1.1.1.8.2 tls if (! f)
400 1.1.1.1.8.2 tls {
401 1.1.1.1.8.2 tls free (name);
402 1.1.1.1.8.2 tls return NULL;
403 1.1.1.1.8.2 tls }
404 1.1.1.1.8.2 tls
405 1.1.1.1.8.2 tls obj->input_file = f;
406 1.1.1.1.8.2 tls obj->next_input_name = name;
407 1.1.1.1.8.2 tls obj->next_input_name_allocated = (name != in_name);
408 1.1.1.1.8.2 tls
409 1.1.1.1.8.2 tls return f;
410 1.1.1.1.8.2 tls }
411 1.1.1.1.8.2 tls
412 1.1.1.1.8.2 tls /* Return a stream for a pipe connected to the standard input of the
413 1.1.1.1.8.2 tls first stage of the pipeline. */
414 1.1.1.1.8.2 tls FILE *
415 1.1.1.1.8.2 tls pex_input_pipe (struct pex_obj *obj, int binary)
416 1.1.1.1.8.2 tls {
417 1.1.1.1.8.2 tls int p[2];
418 1.1.1.1.8.2 tls FILE *f;
419 1.1.1.1.8.2 tls
420 1.1.1.1.8.2 tls /* You must call pex_input_pipe before the first pex_run or pex_one. */
421 1.1.1.1.8.2 tls if (obj->count > 0)
422 1.1.1.1.8.2 tls goto usage_error;
423 1.1.1.1.8.2 tls
424 1.1.1.1.8.2 tls /* You must be using pipes. Implementations that don't support
425 1.1.1.1.8.2 tls pipes clear this flag before calling pex_init_common. */
426 1.1.1.1.8.2 tls if (! (obj->flags & PEX_USE_PIPES))
427 1.1.1.1.8.2 tls goto usage_error;
428 1.1.1.1.8.2 tls
429 1.1.1.1.8.2 tls /* If we have somehow already selected other input, that's a
430 1.1.1.1.8.2 tls mistake. */
431 1.1.1.1.8.2 tls if ((obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
432 1.1.1.1.8.2 tls || obj->next_input_name)
433 1.1.1.1.8.2 tls goto usage_error;
434 1.1.1.1.8.2 tls
435 1.1.1.1.8.2 tls if (obj->funcs->pipe (obj, p, binary != 0) < 0)
436 1.1.1.1.8.2 tls return NULL;
437 1.1.1.1.8.2 tls
438 1.1.1.1.8.2 tls f = obj->funcs->fdopenw (obj, p[WRITE_PORT], binary != 0);
439 1.1.1.1.8.2 tls if (! f)
440 1.1.1.1.8.2 tls {
441 1.1.1.1.8.2 tls int saved_errno = errno;
442 1.1.1.1.8.2 tls obj->funcs->close (obj, p[READ_PORT]);
443 1.1.1.1.8.2 tls obj->funcs->close (obj, p[WRITE_PORT]);
444 1.1.1.1.8.2 tls errno = saved_errno;
445 1.1.1.1.8.2 tls return NULL;
446 1.1.1.1.8.2 tls }
447 1.1.1.1.8.2 tls
448 1.1.1.1.8.2 tls obj->next_input = p[READ_PORT];
449 1.1.1.1.8.2 tls
450 1.1.1.1.8.2 tls return f;
451 1.1.1.1.8.2 tls
452 1.1.1.1.8.2 tls usage_error:
453 1.1.1.1.8.2 tls errno = EINVAL;
454 1.1.1.1.8.2 tls return NULL;
455 1.1.1.1.8.2 tls }
456 1.1.1.1.8.2 tls
457 1.1.1.1.8.2 tls /* Return a FILE pointer for the output of the last program
458 1.1.1.1.8.2 tls executed. */
459 1.1.1.1.8.2 tls
460 1.1.1.1.8.2 tls FILE *
461 1.1.1.1.8.2 tls pex_read_output (struct pex_obj *obj, int binary)
462 1.1.1.1.8.2 tls {
463 1.1.1.1.8.2 tls if (obj->next_input_name != NULL)
464 1.1.1.1.8.2 tls {
465 1.1.1.1.8.2 tls const char *errmsg;
466 1.1.1.1.8.2 tls int err;
467 1.1.1.1.8.2 tls
468 1.1.1.1.8.2 tls /* We have to make sure that the process has completed before we
469 1.1.1.1.8.2 tls try to read the file. */
470 1.1.1.1.8.2 tls if (!pex_get_status_and_time (obj, 0, &errmsg, &err))
471 1.1.1.1.8.2 tls {
472 1.1.1.1.8.2 tls errno = err;
473 1.1.1.1.8.2 tls return NULL;
474 1.1.1.1.8.2 tls }
475 1.1.1.1.8.2 tls
476 1.1.1.1.8.2 tls obj->read_output = fopen (obj->next_input_name, binary ? "rb" : "r");
477 1.1.1.1.8.2 tls
478 1.1.1.1.8.2 tls if (obj->next_input_name_allocated)
479 1.1.1.1.8.2 tls {
480 1.1.1.1.8.2 tls free (obj->next_input_name);
481 1.1.1.1.8.2 tls obj->next_input_name_allocated = 0;
482 1.1.1.1.8.2 tls }
483 1.1.1.1.8.2 tls obj->next_input_name = NULL;
484 1.1.1.1.8.2 tls }
485 1.1.1.1.8.2 tls else
486 1.1.1.1.8.2 tls {
487 1.1.1.1.8.2 tls int o;
488 1.1.1.1.8.2 tls
489 1.1.1.1.8.2 tls o = obj->next_input;
490 1.1.1.1.8.2 tls if (o < 0 || o == STDIN_FILE_NO)
491 1.1.1.1.8.2 tls return NULL;
492 1.1.1.1.8.2 tls obj->read_output = obj->funcs->fdopenr (obj, o, binary);
493 1.1.1.1.8.2 tls obj->next_input = -1;
494 1.1.1.1.8.2 tls }
495 1.1.1.1.8.2 tls
496 1.1.1.1.8.2 tls return obj->read_output;
497 1.1.1.1.8.2 tls }
498 1.1.1.1.8.2 tls
499 1.1.1.1.8.2 tls FILE *
500 1.1.1.1.8.2 tls pex_read_err (struct pex_obj *obj, int binary)
501 1.1.1.1.8.2 tls {
502 1.1.1.1.8.2 tls int o;
503 1.1.1.1.8.2 tls
504 1.1.1.1.8.2 tls o = obj->stderr_pipe;
505 1.1.1.1.8.2 tls if (o < 0 || o == STDIN_FILE_NO)
506 1.1.1.1.8.2 tls return NULL;
507 1.1.1.1.8.2 tls obj->read_err = obj->funcs->fdopenr (obj, o, binary);
508 1.1.1.1.8.2 tls return obj->read_err;
509 1.1.1.1.8.2 tls }
510 1.1.1.1.8.2 tls
511 1.1.1.1.8.2 tls /* Get the exit status and, if requested, the resource time for all
512 1.1.1.1.8.2 tls the child processes. Return 0 on failure, 1 on success. */
513 1.1.1.1.8.2 tls
514 1.1.1.1.8.2 tls static int
515 1.1.1.1.8.2 tls pex_get_status_and_time (struct pex_obj *obj, int done, const char **errmsg,
516 1.1.1.1.8.2 tls int *err)
517 1.1.1.1.8.2 tls {
518 1.1.1.1.8.2 tls int ret;
519 1.1.1.1.8.2 tls int i;
520 1.1.1.1.8.2 tls
521 1.1.1.1.8.2 tls if (obj->number_waited == obj->count)
522 1.1.1.1.8.2 tls return 1;
523 1.1.1.1.8.2 tls
524 1.1.1.1.8.2 tls obj->status = XRESIZEVEC (int, obj->status, obj->count);
525 1.1.1.1.8.2 tls if ((obj->flags & PEX_RECORD_TIMES) != 0)
526 1.1.1.1.8.2 tls obj->time = XRESIZEVEC (struct pex_time, obj->time, obj->count);
527 1.1.1.1.8.2 tls
528 1.1.1.1.8.2 tls ret = 1;
529 1.1.1.1.8.2 tls for (i = obj->number_waited; i < obj->count; ++i)
530 1.1.1.1.8.2 tls {
531 1.1.1.1.8.2 tls if (obj->funcs->wait (obj, obj->children[i], &obj->status[i],
532 1.1.1.1.8.2 tls obj->time == NULL ? NULL : &obj->time[i],
533 1.1.1.1.8.2 tls done, errmsg, err) < 0)
534 1.1.1.1.8.2 tls ret = 0;
535 1.1.1.1.8.2 tls }
536 1.1.1.1.8.2 tls obj->number_waited = i;
537 1.1.1.1.8.2 tls
538 1.1.1.1.8.2 tls return ret;
539 1.1.1.1.8.2 tls }
540 1.1.1.1.8.2 tls
541 1.1.1.1.8.2 tls /* Get exit status of executed programs. */
542 1.1.1.1.8.2 tls
543 1.1.1.1.8.2 tls int
544 1.1.1.1.8.2 tls pex_get_status (struct pex_obj *obj, int count, int *vector)
545 1.1.1.1.8.2 tls {
546 1.1.1.1.8.2 tls if (obj->status == NULL)
547 1.1.1.1.8.2 tls {
548 1.1.1.1.8.2 tls const char *errmsg;
549 1.1.1.1.8.2 tls int err;
550 1.1.1.1.8.2 tls
551 1.1.1.1.8.2 tls if (!pex_get_status_and_time (obj, 0, &errmsg, &err))
552 1.1.1.1.8.2 tls return 0;
553 1.1.1.1.8.2 tls }
554 1.1.1.1.8.2 tls
555 1.1.1.1.8.2 tls if (count > obj->count)
556 1.1.1.1.8.2 tls {
557 1.1.1.1.8.2 tls memset (vector + obj->count, 0, (count - obj->count) * sizeof (int));
558 1.1.1.1.8.2 tls count = obj->count;
559 1.1.1.1.8.2 tls }
560 1.1.1.1.8.2 tls
561 1.1.1.1.8.2 tls memcpy (vector, obj->status, count * sizeof (int));
562 1.1.1.1.8.2 tls
563 1.1.1.1.8.2 tls return 1;
564 1.1.1.1.8.2 tls }
565 1.1.1.1.8.2 tls
566 1.1.1.1.8.2 tls /* Get process times of executed programs. */
567 1.1.1.1.8.2 tls
568 1.1.1.1.8.2 tls int
569 1.1.1.1.8.2 tls pex_get_times (struct pex_obj *obj, int count, struct pex_time *vector)
570 1.1.1.1.8.2 tls {
571 1.1.1.1.8.2 tls if (obj->status == NULL)
572 1.1.1.1.8.2 tls {
573 1.1.1.1.8.2 tls const char *errmsg;
574 1.1.1.1.8.2 tls int err;
575 1.1.1.1.8.2 tls
576 1.1.1.1.8.2 tls if (!pex_get_status_and_time (obj, 0, &errmsg, &err))
577 1.1.1.1.8.2 tls return 0;
578 1.1.1.1.8.2 tls }
579 1.1.1.1.8.2 tls
580 1.1.1.1.8.2 tls if (obj->time == NULL)
581 1.1.1.1.8.2 tls return 0;
582 1.1.1.1.8.2 tls
583 1.1.1.1.8.2 tls if (count > obj->count)
584 1.1.1.1.8.2 tls {
585 1.1.1.1.8.2 tls memset (vector + obj->count, 0,
586 1.1.1.1.8.2 tls (count - obj->count) * sizeof (struct pex_time));
587 1.1.1.1.8.2 tls count = obj->count;
588 1.1.1.1.8.2 tls }
589 1.1.1.1.8.2 tls
590 1.1.1.1.8.2 tls memcpy (vector, obj->time, count * sizeof (struct pex_time));
591 1.1.1.1.8.2 tls
592 1.1.1.1.8.2 tls return 1;
593 1.1.1.1.8.2 tls }
594 1.1.1.1.8.2 tls
595 1.1.1.1.8.2 tls /* Free a pex_obj structure. */
596 1.1.1.1.8.2 tls
597 1.1.1.1.8.2 tls void
598 1.1.1.1.8.2 tls pex_free (struct pex_obj *obj)
599 1.1.1.1.8.2 tls {
600 1.1.1.1.8.2 tls if (obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
601 1.1.1.1.8.2 tls obj->funcs->close (obj, obj->next_input);
602 1.1.1.1.8.2 tls
603 1.1.1.1.8.2 tls /* If the caller forgot to wait for the children, we do it here, to
604 1.1.1.1.8.2 tls avoid zombies. */
605 1.1.1.1.8.2 tls if (obj->status == NULL)
606 1.1.1.1.8.2 tls {
607 1.1.1.1.8.2 tls const char *errmsg;
608 1.1.1.1.8.2 tls int err;
609 1.1.1.1.8.2 tls
610 1.1.1.1.8.2 tls obj->flags &= ~ PEX_RECORD_TIMES;
611 1.1.1.1.8.2 tls pex_get_status_and_time (obj, 1, &errmsg, &err);
612 1.1.1.1.8.2 tls }
613 1.1.1.1.8.2 tls
614 1.1.1.1.8.2 tls if (obj->next_input_name_allocated)
615 1.1.1.1.8.2 tls free (obj->next_input_name);
616 1.1.1.1.8.2 tls if (obj->children != NULL)
617 1.1.1.1.8.2 tls free (obj->children);
618 1.1.1.1.8.2 tls if (obj->status != NULL)
619 1.1.1.1.8.2 tls free (obj->status);
620 1.1.1.1.8.2 tls if (obj->time != NULL)
621 1.1.1.1.8.2 tls free (obj->time);
622 1.1.1.1.8.2 tls if (obj->read_output != NULL)
623 1.1.1.1.8.2 tls fclose (obj->read_output);
624 1.1.1.1.8.2 tls if (obj->read_err != NULL)
625 1.1.1.1.8.2 tls fclose (obj->read_err);
626 1.1.1.1.8.2 tls
627 1.1.1.1.8.2 tls if (obj->remove_count > 0)
628 1.1.1.1.8.2 tls {
629 1.1.1.1.8.2 tls int i;
630 1.1.1.1.8.2 tls
631 1.1.1.1.8.2 tls for (i = 0; i < obj->remove_count; ++i)
632 1.1.1.1.8.2 tls {
633 1.1.1.1.8.2 tls remove (obj->remove[i]);
634 1.1.1.1.8.2 tls free (obj->remove[i]);
635 1.1.1.1.8.2 tls }
636 1.1.1.1.8.2 tls free (obj->remove);
637 1.1.1.1.8.2 tls }
638 1.1.1.1.8.2 tls
639 1.1.1.1.8.2 tls if (obj->funcs->cleanup != NULL)
640 1.1.1.1.8.2 tls obj->funcs->cleanup (obj);
641 1.1.1.1.8.2 tls
642 1.1.1.1.8.2 tls free (obj);
643 1.1.1.1.8.2 tls }
644