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