Home | History | Annotate | Line # | Download | only in libiberty
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