pex-common.c revision 1.1.1.2 1 1.1 skrll /* Common code for executing a program in a sub-process.
2 1.1 skrll Copyright (C) 2005 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 skrll (flags & PEX_BINARY_OUTPUT) != 0);
271 1.1 skrll if (out < 0)
272 1.1 skrll {
273 1.1 skrll *err = errno;
274 1.1 skrll errmsg = "open temporary output file";
275 1.1 skrll goto error_exit;
276 1.1 skrll }
277 1.1 skrll }
278 1.1 skrll
279 1.1 skrll if (outname_allocated)
280 1.1 skrll {
281 1.1 skrll free (outname);
282 1.1 skrll outname_allocated = 0;
283 1.1 skrll }
284 1.1 skrll
285 1.1 skrll /* Set ERRDES. */
286 1.1 skrll
287 1.1 skrll if (errname != NULL && (flags & PEX_STDERR_TO_PIPE) != 0)
288 1.1 skrll {
289 1.1 skrll *err = 0;
290 1.1 skrll errmsg = "both ERRNAME and PEX_STDERR_TO_PIPE specified.";
291 1.1 skrll goto error_exit;
292 1.1 skrll }
293 1.1 skrll
294 1.1 skrll if (obj->stderr_pipe != -1)
295 1.1 skrll {
296 1.1 skrll *err = 0;
297 1.1 skrll errmsg = "PEX_STDERR_TO_PIPE used in the middle of pipeline";
298 1.1 skrll goto error_exit;
299 1.1 skrll }
300 1.1 skrll
301 1.1 skrll if (errname == NULL)
302 1.1 skrll {
303 1.1 skrll if (flags & PEX_STDERR_TO_PIPE)
304 1.1 skrll {
305 1.1 skrll if (obj->funcs->pipe (obj, p, (flags & PEX_BINARY_ERROR) != 0) < 0)
306 1.1 skrll {
307 1.1 skrll *err = errno;
308 1.1 skrll errmsg = "pipe";
309 1.1 skrll goto error_exit;
310 1.1 skrll }
311 1.1 skrll
312 1.1 skrll errdes = p[WRITE_PORT];
313 1.1 skrll obj->stderr_pipe = p[READ_PORT];
314 1.1 skrll }
315 1.1 skrll else
316 1.1 skrll {
317 1.1 skrll errdes = STDERR_FILE_NO;
318 1.1 skrll }
319 1.1 skrll }
320 1.1 skrll else
321 1.1 skrll {
322 1.1 skrll errdes = obj->funcs->open_write (obj, errname,
323 1.1 skrll (flags & PEX_BINARY_ERROR) != 0);
324 1.1 skrll if (errdes < 0)
325 1.1 skrll {
326 1.1 skrll *err = errno;
327 1.1 skrll errmsg = "open error file";
328 1.1 skrll goto error_exit;
329 1.1 skrll }
330 1.1 skrll }
331 1.1 skrll
332 1.1 skrll /* If we are using pipes, the child process has to close the next
333 1.1 skrll input pipe. */
334 1.1 skrll
335 1.1 skrll if ((obj->flags & PEX_USE_PIPES) == 0)
336 1.1 skrll toclose = -1;
337 1.1 skrll else
338 1.1 skrll toclose = obj->next_input;
339 1.1 skrll
340 1.1 skrll /* Run the program. */
341 1.1 skrll
342 1.1 skrll pid = obj->funcs->exec_child (obj, flags, executable, argv, env,
343 1.1 skrll in, out, errdes, toclose, &errmsg, err);
344 1.1 skrll if (pid < 0)
345 1.1 skrll goto error_exit;
346 1.1 skrll
347 1.1 skrll ++obj->count;
348 1.1.1.2 christos obj->children = XRESIZEVEC (pid_t, obj->children, obj->count);
349 1.1 skrll obj->children[obj->count - 1] = pid;
350 1.1 skrll
351 1.1 skrll return NULL;
352 1.1 skrll
353 1.1 skrll error_exit:
354 1.1 skrll if (in >= 0 && in != STDIN_FILE_NO)
355 1.1 skrll obj->funcs->close (obj, in);
356 1.1 skrll if (out >= 0 && out != STDOUT_FILE_NO)
357 1.1 skrll obj->funcs->close (obj, out);
358 1.1 skrll if (errdes >= 0 && errdes != STDERR_FILE_NO)
359 1.1 skrll obj->funcs->close (obj, errdes);
360 1.1 skrll if (outname_allocated)
361 1.1 skrll free (outname);
362 1.1 skrll return errmsg;
363 1.1 skrll }
364 1.1 skrll
365 1.1 skrll /* Run a program. */
366 1.1 skrll
367 1.1 skrll const char *
368 1.1 skrll pex_run (struct pex_obj *obj, int flags, const char *executable,
369 1.1 skrll char * const * argv, const char *orig_outname, const char *errname,
370 1.1 skrll int *err)
371 1.1 skrll {
372 1.1 skrll return pex_run_in_environment (obj, flags, executable, argv, NULL,
373 1.1 skrll orig_outname, errname, err);
374 1.1 skrll }
375 1.1 skrll
376 1.1 skrll /* Return a FILE pointer for a temporary file to fill with input for
377 1.1 skrll the pipeline. */
378 1.1 skrll FILE *
379 1.1 skrll pex_input_file (struct pex_obj *obj, int flags, const char *in_name)
380 1.1 skrll {
381 1.1 skrll char *name = (char *) in_name;
382 1.1 skrll FILE *f;
383 1.1 skrll
384 1.1 skrll /* This must be called before the first pipeline stage is run, and
385 1.1 skrll there must not have been any other input selected. */
386 1.1 skrll if (obj->count != 0
387 1.1 skrll || (obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
388 1.1 skrll || obj->next_input_name)
389 1.1 skrll {
390 1.1 skrll errno = EINVAL;
391 1.1 skrll return NULL;
392 1.1 skrll }
393 1.1 skrll
394 1.1 skrll name = temp_file (obj, flags, name);
395 1.1 skrll if (! name)
396 1.1 skrll return NULL;
397 1.1 skrll
398 1.1 skrll f = fopen (name, (flags & PEX_BINARY_OUTPUT) ? "wb" : "w");
399 1.1 skrll if (! f)
400 1.1 skrll {
401 1.1 skrll free (name);
402 1.1 skrll return NULL;
403 1.1 skrll }
404 1.1 skrll
405 1.1 skrll obj->input_file = f;
406 1.1 skrll obj->next_input_name = name;
407 1.1 skrll obj->next_input_name_allocated = (name != in_name);
408 1.1 skrll
409 1.1 skrll return f;
410 1.1 skrll }
411 1.1 skrll
412 1.1 skrll /* Return a stream for a pipe connected to the standard input of the
413 1.1 skrll first stage of the pipeline. */
414 1.1 skrll FILE *
415 1.1 skrll pex_input_pipe (struct pex_obj *obj, int binary)
416 1.1 skrll {
417 1.1 skrll int p[2];
418 1.1 skrll FILE *f;
419 1.1 skrll
420 1.1 skrll /* You must call pex_input_pipe before the first pex_run or pex_one. */
421 1.1 skrll if (obj->count > 0)
422 1.1 skrll goto usage_error;
423 1.1 skrll
424 1.1 skrll /* You must be using pipes. Implementations that don't support
425 1.1 skrll pipes clear this flag before calling pex_init_common. */
426 1.1 skrll if (! (obj->flags & PEX_USE_PIPES))
427 1.1 skrll goto usage_error;
428 1.1 skrll
429 1.1 skrll /* If we have somehow already selected other input, that's a
430 1.1 skrll mistake. */
431 1.1 skrll if ((obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
432 1.1 skrll || obj->next_input_name)
433 1.1 skrll goto usage_error;
434 1.1 skrll
435 1.1 skrll if (obj->funcs->pipe (obj, p, binary != 0) < 0)
436 1.1 skrll return NULL;
437 1.1 skrll
438 1.1 skrll f = obj->funcs->fdopenw (obj, p[WRITE_PORT], binary != 0);
439 1.1 skrll if (! f)
440 1.1 skrll {
441 1.1 skrll int saved_errno = errno;
442 1.1 skrll obj->funcs->close (obj, p[READ_PORT]);
443 1.1 skrll obj->funcs->close (obj, p[WRITE_PORT]);
444 1.1 skrll errno = saved_errno;
445 1.1 skrll return NULL;
446 1.1 skrll }
447 1.1 skrll
448 1.1 skrll obj->next_input = p[READ_PORT];
449 1.1 skrll
450 1.1 skrll return f;
451 1.1 skrll
452 1.1 skrll usage_error:
453 1.1 skrll errno = EINVAL;
454 1.1 skrll return NULL;
455 1.1 skrll }
456 1.1 skrll
457 1.1 skrll /* Return a FILE pointer for the output of the last program
458 1.1 skrll executed. */
459 1.1 skrll
460 1.1 skrll FILE *
461 1.1 skrll pex_read_output (struct pex_obj *obj, int binary)
462 1.1 skrll {
463 1.1 skrll if (obj->next_input_name != NULL)
464 1.1 skrll {
465 1.1 skrll const char *errmsg;
466 1.1 skrll int err;
467 1.1 skrll
468 1.1 skrll /* We have to make sure that the process has completed before we
469 1.1 skrll try to read the file. */
470 1.1 skrll if (!pex_get_status_and_time (obj, 0, &errmsg, &err))
471 1.1 skrll {
472 1.1 skrll errno = err;
473 1.1 skrll return NULL;
474 1.1 skrll }
475 1.1 skrll
476 1.1 skrll obj->read_output = fopen (obj->next_input_name, binary ? "rb" : "r");
477 1.1 skrll
478 1.1 skrll if (obj->next_input_name_allocated)
479 1.1 skrll {
480 1.1 skrll free (obj->next_input_name);
481 1.1 skrll obj->next_input_name_allocated = 0;
482 1.1 skrll }
483 1.1 skrll obj->next_input_name = NULL;
484 1.1 skrll }
485 1.1 skrll else
486 1.1 skrll {
487 1.1 skrll int o;
488 1.1 skrll
489 1.1 skrll o = obj->next_input;
490 1.1 skrll if (o < 0 || o == STDIN_FILE_NO)
491 1.1 skrll return NULL;
492 1.1 skrll obj->read_output = obj->funcs->fdopenr (obj, o, binary);
493 1.1 skrll obj->next_input = -1;
494 1.1 skrll }
495 1.1 skrll
496 1.1 skrll return obj->read_output;
497 1.1 skrll }
498 1.1 skrll
499 1.1 skrll FILE *
500 1.1 skrll pex_read_err (struct pex_obj *obj, int binary)
501 1.1 skrll {
502 1.1 skrll int o;
503 1.1 skrll
504 1.1 skrll o = obj->stderr_pipe;
505 1.1 skrll if (o < 0 || o == STDIN_FILE_NO)
506 1.1 skrll return NULL;
507 1.1 skrll obj->read_err = obj->funcs->fdopenr (obj, o, binary);
508 1.1.1.2 christos obj->stderr_pipe = -1;
509 1.1 skrll return obj->read_err;
510 1.1 skrll }
511 1.1 skrll
512 1.1 skrll /* Get the exit status and, if requested, the resource time for all
513 1.1 skrll the child processes. Return 0 on failure, 1 on success. */
514 1.1 skrll
515 1.1 skrll static int
516 1.1 skrll pex_get_status_and_time (struct pex_obj *obj, int done, const char **errmsg,
517 1.1 skrll int *err)
518 1.1 skrll {
519 1.1 skrll int ret;
520 1.1 skrll int i;
521 1.1 skrll
522 1.1 skrll if (obj->number_waited == obj->count)
523 1.1 skrll return 1;
524 1.1 skrll
525 1.1 skrll obj->status = XRESIZEVEC (int, obj->status, obj->count);
526 1.1 skrll if ((obj->flags & PEX_RECORD_TIMES) != 0)
527 1.1 skrll obj->time = XRESIZEVEC (struct pex_time, obj->time, obj->count);
528 1.1 skrll
529 1.1 skrll ret = 1;
530 1.1 skrll for (i = obj->number_waited; i < obj->count; ++i)
531 1.1 skrll {
532 1.1 skrll if (obj->funcs->wait (obj, obj->children[i], &obj->status[i],
533 1.1 skrll obj->time == NULL ? NULL : &obj->time[i],
534 1.1 skrll done, errmsg, err) < 0)
535 1.1 skrll ret = 0;
536 1.1 skrll }
537 1.1 skrll obj->number_waited = i;
538 1.1 skrll
539 1.1 skrll return ret;
540 1.1 skrll }
541 1.1 skrll
542 1.1 skrll /* Get exit status of executed programs. */
543 1.1 skrll
544 1.1 skrll int
545 1.1 skrll pex_get_status (struct pex_obj *obj, int count, int *vector)
546 1.1 skrll {
547 1.1 skrll if (obj->status == NULL)
548 1.1 skrll {
549 1.1 skrll const char *errmsg;
550 1.1 skrll int err;
551 1.1 skrll
552 1.1 skrll if (!pex_get_status_and_time (obj, 0, &errmsg, &err))
553 1.1 skrll return 0;
554 1.1 skrll }
555 1.1 skrll
556 1.1 skrll if (count > obj->count)
557 1.1 skrll {
558 1.1 skrll memset (vector + obj->count, 0, (count - obj->count) * sizeof (int));
559 1.1 skrll count = obj->count;
560 1.1 skrll }
561 1.1 skrll
562 1.1 skrll memcpy (vector, obj->status, count * sizeof (int));
563 1.1 skrll
564 1.1 skrll return 1;
565 1.1 skrll }
566 1.1 skrll
567 1.1 skrll /* Get process times of executed programs. */
568 1.1 skrll
569 1.1 skrll int
570 1.1 skrll pex_get_times (struct pex_obj *obj, int count, struct pex_time *vector)
571 1.1 skrll {
572 1.1 skrll if (obj->status == NULL)
573 1.1 skrll {
574 1.1 skrll const char *errmsg;
575 1.1 skrll int err;
576 1.1 skrll
577 1.1 skrll if (!pex_get_status_and_time (obj, 0, &errmsg, &err))
578 1.1 skrll return 0;
579 1.1 skrll }
580 1.1 skrll
581 1.1 skrll if (obj->time == NULL)
582 1.1 skrll return 0;
583 1.1 skrll
584 1.1 skrll if (count > obj->count)
585 1.1 skrll {
586 1.1 skrll memset (vector + obj->count, 0,
587 1.1 skrll (count - obj->count) * sizeof (struct pex_time));
588 1.1 skrll count = obj->count;
589 1.1 skrll }
590 1.1 skrll
591 1.1 skrll memcpy (vector, obj->time, count * sizeof (struct pex_time));
592 1.1 skrll
593 1.1 skrll return 1;
594 1.1 skrll }
595 1.1 skrll
596 1.1 skrll /* Free a pex_obj structure. */
597 1.1 skrll
598 1.1 skrll void
599 1.1 skrll pex_free (struct pex_obj *obj)
600 1.1 skrll {
601 1.1.1.2 christos /* Close pipe file descriptors corresponding to child's stdout and
602 1.1.1.2 christos stderr so that the child does not hang trying to output something
603 1.1.1.2 christos while we're waiting for it. */
604 1.1 skrll if (obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
605 1.1 skrll obj->funcs->close (obj, obj->next_input);
606 1.1.1.2 christos if (obj->stderr_pipe >= 0 && obj->stderr_pipe != STDIN_FILE_NO)
607 1.1.1.2 christos obj->funcs->close (obj, obj->stderr_pipe);
608 1.1.1.2 christos if (obj->read_output != NULL)
609 1.1.1.2 christos fclose (obj->read_output);
610 1.1.1.2 christos if (obj->read_err != NULL)
611 1.1.1.2 christos fclose (obj->read_err);
612 1.1 skrll
613 1.1 skrll /* If the caller forgot to wait for the children, we do it here, to
614 1.1 skrll avoid zombies. */
615 1.1 skrll if (obj->status == NULL)
616 1.1 skrll {
617 1.1 skrll const char *errmsg;
618 1.1 skrll int err;
619 1.1 skrll
620 1.1 skrll obj->flags &= ~ PEX_RECORD_TIMES;
621 1.1 skrll pex_get_status_and_time (obj, 1, &errmsg, &err);
622 1.1 skrll }
623 1.1 skrll
624 1.1 skrll if (obj->next_input_name_allocated)
625 1.1 skrll free (obj->next_input_name);
626 1.1 skrll if (obj->children != NULL)
627 1.1 skrll free (obj->children);
628 1.1 skrll if (obj->status != NULL)
629 1.1 skrll free (obj->status);
630 1.1 skrll if (obj->time != NULL)
631 1.1 skrll free (obj->time);
632 1.1 skrll
633 1.1 skrll if (obj->remove_count > 0)
634 1.1 skrll {
635 1.1 skrll int i;
636 1.1 skrll
637 1.1 skrll for (i = 0; i < obj->remove_count; ++i)
638 1.1 skrll {
639 1.1 skrll remove (obj->remove[i]);
640 1.1 skrll free (obj->remove[i]);
641 1.1 skrll }
642 1.1 skrll free (obj->remove);
643 1.1 skrll }
644 1.1 skrll
645 1.1 skrll if (obj->funcs->cleanup != NULL)
646 1.1 skrll obj->funcs->cleanup (obj);
647 1.1 skrll
648 1.1 skrll free (obj);
649 1.1 skrll }
650