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