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