OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [libiberty/] [pex-common.c] - Diff between revs 154 and 816

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 154 Rev 816
/* Common code for executing a program in a sub-process.
/* Common code for executing a program in a sub-process.
   Copyright (C) 2005 Free Software Foundation, Inc.
   Copyright (C) 2005 Free Software Foundation, Inc.
   Written by Ian Lance Taylor <ian@airs.com>.
   Written by Ian Lance Taylor <ian@airs.com>.
 
 
This file is part of the libiberty library.
This file is part of the libiberty library.
Libiberty is free software; you can redistribute it and/or
Libiberty is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
version 2 of the License, or (at your option) any later version.
 
 
Libiberty is distributed in the hope that it will be useful,
Libiberty is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Library General Public License for more details.
Library General Public License for more details.
 
 
You should have received a copy of the GNU Library General Public
You should have received a copy of the GNU Library General Public
License along with libiberty; see the file COPYING.LIB.  If not,
License along with libiberty; see the file COPYING.LIB.  If not,
write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
Boston, MA 02110-1301, USA.  */
Boston, MA 02110-1301, USA.  */
 
 
#include "config.h"
#include "config.h"
#include "libiberty.h"
#include "libiberty.h"
#include "pex-common.h"
#include "pex-common.h"
 
 
#include <stdio.h>
#include <stdio.h>
#include <errno.h>
#include <errno.h>
#ifdef NEED_DECLARATION_ERRNO
#ifdef NEED_DECLARATION_ERRNO
extern int errno;
extern int errno;
#endif
#endif
#ifdef HAVE_STDLIB_H
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#include <stdlib.h>
#endif
#endif
#ifdef HAVE_STRING_H
#ifdef HAVE_STRING_H
#include <string.h>
#include <string.h>
#endif
#endif
#ifdef HAVE_UNISTD_H
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#include <unistd.h>
#endif
#endif
 
 
extern int mkstemps (char *, int);
extern int mkstemps (char *, int);
 
 
/* This file contains subroutines for the program execution routines
/* This file contains subroutines for the program execution routines
   (pex_init, pex_run, etc.).  This file is compiled on all
   (pex_init, pex_run, etc.).  This file is compiled on all
   systems.  */
   systems.  */
 
 
static void pex_add_remove (struct pex_obj *, const char *, int);
static void pex_add_remove (struct pex_obj *, const char *, int);
static int pex_get_status_and_time (struct pex_obj *, int, const char **,
static int pex_get_status_and_time (struct pex_obj *, int, const char **,
                                    int *);
                                    int *);
 
 
/* Initialize a pex_obj structure.  */
/* Initialize a pex_obj structure.  */
 
 
struct pex_obj *
struct pex_obj *
pex_init_common (int flags, const char *pname, const char *tempbase,
pex_init_common (int flags, const char *pname, const char *tempbase,
                 const struct pex_funcs *funcs)
                 const struct pex_funcs *funcs)
{
{
  struct pex_obj *obj;
  struct pex_obj *obj;
 
 
  obj = XNEW (struct pex_obj);
  obj = XNEW (struct pex_obj);
  obj->flags = flags;
  obj->flags = flags;
  obj->pname = pname;
  obj->pname = pname;
  obj->tempbase = tempbase;
  obj->tempbase = tempbase;
  obj->next_input = STDIN_FILE_NO;
  obj->next_input = STDIN_FILE_NO;
  obj->next_input_name = NULL;
  obj->next_input_name = NULL;
  obj->next_input_name_allocated = 0;
  obj->next_input_name_allocated = 0;
  obj->count = 0;
  obj->count = 0;
  obj->children = NULL;
  obj->children = NULL;
  obj->status = NULL;
  obj->status = NULL;
  obj->time = NULL;
  obj->time = NULL;
  obj->number_waited = 0;
  obj->number_waited = 0;
  obj->input_file = NULL;
  obj->input_file = NULL;
  obj->read_output = NULL;
  obj->read_output = NULL;
  obj->remove_count = 0;
  obj->remove_count = 0;
  obj->remove = NULL;
  obj->remove = NULL;
  obj->funcs = funcs;
  obj->funcs = funcs;
  obj->sysdep = NULL;
  obj->sysdep = NULL;
  return obj;
  return obj;
}
}
 
 
/* Add a file to be removed when we are done.  */
/* Add a file to be removed when we are done.  */
 
 
static void
static void
pex_add_remove (struct pex_obj *obj, const char *name, int allocated)
pex_add_remove (struct pex_obj *obj, const char *name, int allocated)
{
{
  char *add;
  char *add;
 
 
  ++obj->remove_count;
  ++obj->remove_count;
  obj->remove = XRESIZEVEC (char *, obj->remove, obj->remove_count);
  obj->remove = XRESIZEVEC (char *, obj->remove, obj->remove_count);
  if (allocated)
  if (allocated)
    add = (char *) name;
    add = (char *) name;
  else
  else
    add = xstrdup (name);
    add = xstrdup (name);
  obj->remove[obj->remove_count - 1] = add;
  obj->remove[obj->remove_count - 1] = add;
}
}
 
 
/* Generate a temporary file name based on OBJ, FLAGS, and NAME.
/* Generate a temporary file name based on OBJ, FLAGS, and NAME.
   Return NULL if we were unable to reserve a temporary filename.
   Return NULL if we were unable to reserve a temporary filename.
 
 
   If non-NULL, the result is either allocated with malloc, or the
   If non-NULL, the result is either allocated with malloc, or the
   same pointer as NAME.  */
   same pointer as NAME.  */
static char *
static char *
temp_file (struct pex_obj *obj, int flags, char *name)
temp_file (struct pex_obj *obj, int flags, char *name)
{
{
  if (name == NULL)
  if (name == NULL)
    {
    {
      if (obj->tempbase == NULL)
      if (obj->tempbase == NULL)
        {
        {
          name = make_temp_file (NULL);
          name = make_temp_file (NULL);
        }
        }
      else
      else
        {
        {
          int len = strlen (obj->tempbase);
          int len = strlen (obj->tempbase);
          int out;
          int out;
 
 
          if (len >= 6
          if (len >= 6
              && strcmp (obj->tempbase + len - 6, "XXXXXX") == 0)
              && strcmp (obj->tempbase + len - 6, "XXXXXX") == 0)
            name = xstrdup (obj->tempbase);
            name = xstrdup (obj->tempbase);
          else
          else
            name = concat (obj->tempbase, "XXXXXX", NULL);
            name = concat (obj->tempbase, "XXXXXX", NULL);
 
 
          out = mkstemps (name, 0);
          out = mkstemps (name, 0);
          if (out < 0)
          if (out < 0)
            {
            {
              free (name);
              free (name);
              return NULL;
              return NULL;
            }
            }
 
 
          /* This isn't obj->funcs->close because we got the
          /* This isn't obj->funcs->close because we got the
             descriptor from mkstemps, not from a function in
             descriptor from mkstemps, not from a function in
             obj->funcs.  Calling close here is just like what
             obj->funcs.  Calling close here is just like what
             make_temp_file does.  */
             make_temp_file does.  */
          close (out);
          close (out);
        }
        }
    }
    }
  else if ((flags & PEX_SUFFIX) != 0)
  else if ((flags & PEX_SUFFIX) != 0)
    {
    {
      if (obj->tempbase == NULL)
      if (obj->tempbase == NULL)
        name = make_temp_file (name);
        name = make_temp_file (name);
      else
      else
        name = concat (obj->tempbase, name, NULL);
        name = concat (obj->tempbase, name, NULL);
    }
    }
 
 
  return name;
  return name;
}
}
 
 
 
 
/* As for pex_run (), but permits the environment for the child process
/* As for pex_run (), but permits the environment for the child process
   to be specified. */
   to be specified. */
 
 
const char *
const char *
pex_run_in_environment (struct pex_obj *obj, int flags, const char *executable,
pex_run_in_environment (struct pex_obj *obj, int flags, const char *executable,
                        char * const * argv, char * const * env,
                        char * const * argv, char * const * env,
                        const char *orig_outname, const char *errname,
                        const char *orig_outname, const char *errname,
                        int *err)
                        int *err)
{
{
  const char *errmsg;
  const char *errmsg;
  int in, out, errdes;
  int in, out, errdes;
  char *outname;
  char *outname;
  int outname_allocated;
  int outname_allocated;
  int p[2];
  int p[2];
  int toclose;
  int toclose;
  long pid;
  long pid;
 
 
  in = -1;
  in = -1;
  out = -1;
  out = -1;
  errdes = -1;
  errdes = -1;
  outname = (char *) orig_outname;
  outname = (char *) orig_outname;
  outname_allocated = 0;
  outname_allocated = 0;
 
 
  /* If the user called pex_input_file, close the file now.  */
  /* If the user called pex_input_file, close the file now.  */
  if (obj->input_file)
  if (obj->input_file)
    {
    {
      if (fclose (obj->input_file) == EOF)
      if (fclose (obj->input_file) == EOF)
        {
        {
          errmsg = "closing pipeline input file";
          errmsg = "closing pipeline input file";
          goto error_exit;
          goto error_exit;
        }
        }
      obj->input_file = NULL;
      obj->input_file = NULL;
    }
    }
 
 
  /* Set IN.  */
  /* Set IN.  */
 
 
  if (obj->next_input_name != NULL)
  if (obj->next_input_name != NULL)
    {
    {
      /* We have to make sure that the previous process has completed
      /* We have to make sure that the previous process has completed
         before we try to read the file.  */
         before we try to read the file.  */
      if (!pex_get_status_and_time (obj, 0, &errmsg, err))
      if (!pex_get_status_and_time (obj, 0, &errmsg, err))
        goto error_exit;
        goto error_exit;
 
 
      in = obj->funcs->open_read (obj, obj->next_input_name,
      in = obj->funcs->open_read (obj, obj->next_input_name,
                                  (flags & PEX_BINARY_INPUT) != 0);
                                  (flags & PEX_BINARY_INPUT) != 0);
      if (in < 0)
      if (in < 0)
        {
        {
          *err = errno;
          *err = errno;
          errmsg = "open temporary file";
          errmsg = "open temporary file";
          goto error_exit;
          goto error_exit;
        }
        }
      if (obj->next_input_name_allocated)
      if (obj->next_input_name_allocated)
        {
        {
          free (obj->next_input_name);
          free (obj->next_input_name);
          obj->next_input_name_allocated = 0;
          obj->next_input_name_allocated = 0;
        }
        }
      obj->next_input_name = NULL;
      obj->next_input_name = NULL;
    }
    }
  else
  else
    {
    {
      in = obj->next_input;
      in = obj->next_input;
      if (in < 0)
      if (in < 0)
        {
        {
          *err = 0;
          *err = 0;
          errmsg = "pipeline already complete";
          errmsg = "pipeline already complete";
          goto error_exit;
          goto error_exit;
        }
        }
    }
    }
 
 
  /* Set OUT and OBJ->NEXT_INPUT/OBJ->NEXT_INPUT_NAME.  */
  /* Set OUT and OBJ->NEXT_INPUT/OBJ->NEXT_INPUT_NAME.  */
 
 
  if ((flags & PEX_LAST) != 0)
  if ((flags & PEX_LAST) != 0)
    {
    {
      if (outname == NULL)
      if (outname == NULL)
        out = STDOUT_FILE_NO;
        out = STDOUT_FILE_NO;
      else if ((flags & PEX_SUFFIX) != 0)
      else if ((flags & PEX_SUFFIX) != 0)
        {
        {
          outname = concat (obj->tempbase, outname, NULL);
          outname = concat (obj->tempbase, outname, NULL);
          outname_allocated = 1;
          outname_allocated = 1;
        }
        }
      obj->next_input = -1;
      obj->next_input = -1;
    }
    }
  else if ((obj->flags & PEX_USE_PIPES) == 0)
  else if ((obj->flags & PEX_USE_PIPES) == 0)
    {
    {
      outname = temp_file (obj, flags, outname);
      outname = temp_file (obj, flags, outname);
      if (! outname)
      if (! outname)
        {
        {
          *err = 0;
          *err = 0;
          errmsg = "could not create temporary file";
          errmsg = "could not create temporary file";
          goto error_exit;
          goto error_exit;
        }
        }
 
 
      if (outname != orig_outname)
      if (outname != orig_outname)
        outname_allocated = 1;
        outname_allocated = 1;
 
 
      if ((obj->flags & PEX_SAVE_TEMPS) == 0)
      if ((obj->flags & PEX_SAVE_TEMPS) == 0)
        {
        {
          pex_add_remove (obj, outname, outname_allocated);
          pex_add_remove (obj, outname, outname_allocated);
          outname_allocated = 0;
          outname_allocated = 0;
        }
        }
 
 
      /* Hand off ownership of outname to the next stage.  */
      /* Hand off ownership of outname to the next stage.  */
      obj->next_input_name = outname;
      obj->next_input_name = outname;
      obj->next_input_name_allocated = outname_allocated;
      obj->next_input_name_allocated = outname_allocated;
      outname_allocated = 0;
      outname_allocated = 0;
    }
    }
  else
  else
    {
    {
      if (obj->funcs->pipe (obj, p, (flags & PEX_BINARY_OUTPUT) != 0) < 0)
      if (obj->funcs->pipe (obj, p, (flags & PEX_BINARY_OUTPUT) != 0) < 0)
        {
        {
          *err = errno;
          *err = errno;
          errmsg = "pipe";
          errmsg = "pipe";
          goto error_exit;
          goto error_exit;
        }
        }
 
 
      out = p[WRITE_PORT];
      out = p[WRITE_PORT];
      obj->next_input = p[READ_PORT];
      obj->next_input = p[READ_PORT];
    }
    }
 
 
  if (out < 0)
  if (out < 0)
    {
    {
      out = obj->funcs->open_write (obj, outname,
      out = obj->funcs->open_write (obj, outname,
                                    (flags & PEX_BINARY_OUTPUT) != 0);
                                    (flags & PEX_BINARY_OUTPUT) != 0);
      if (out < 0)
      if (out < 0)
        {
        {
          *err = errno;
          *err = errno;
          errmsg = "open temporary output file";
          errmsg = "open temporary output file";
          goto error_exit;
          goto error_exit;
        }
        }
    }
    }
 
 
  if (outname_allocated)
  if (outname_allocated)
    {
    {
      free (outname);
      free (outname);
      outname_allocated = 0;
      outname_allocated = 0;
    }
    }
 
 
  /* Set ERRDES.  */
  /* Set ERRDES.  */
 
 
  if (errname == NULL)
  if (errname == NULL)
    errdes = STDERR_FILE_NO;
    errdes = STDERR_FILE_NO;
  else
  else
    {
    {
      /* We assume that stderr is in text mode--it certainly shouldn't
      /* We assume that stderr is in text mode--it certainly shouldn't
         be controlled by PEX_BINARY_OUTPUT.  If necessary, we can add
         be controlled by PEX_BINARY_OUTPUT.  If necessary, we can add
         a PEX_BINARY_STDERR flag.  */
         a PEX_BINARY_STDERR flag.  */
      errdes = obj->funcs->open_write (obj, errname, 0);
      errdes = obj->funcs->open_write (obj, errname, 0);
      if (errdes < 0)
      if (errdes < 0)
        {
        {
          *err = errno;
          *err = errno;
          errmsg = "open error file";
          errmsg = "open error file";
          goto error_exit;
          goto error_exit;
        }
        }
    }
    }
 
 
  /* If we are using pipes, the child process has to close the next
  /* If we are using pipes, the child process has to close the next
     input pipe.  */
     input pipe.  */
 
 
  if ((obj->flags & PEX_USE_PIPES) == 0)
  if ((obj->flags & PEX_USE_PIPES) == 0)
    toclose = -1;
    toclose = -1;
  else
  else
    toclose = obj->next_input;
    toclose = obj->next_input;
 
 
  /* Run the program.  */
  /* Run the program.  */
 
 
  pid = obj->funcs->exec_child (obj, flags, executable, argv, env,
  pid = obj->funcs->exec_child (obj, flags, executable, argv, env,
                                in, out, errdes, toclose, &errmsg, err);
                                in, out, errdes, toclose, &errmsg, err);
  if (pid < 0)
  if (pid < 0)
    goto error_exit;
    goto error_exit;
 
 
  ++obj->count;
  ++obj->count;
  obj->children = XRESIZEVEC (long, obj->children, obj->count);
  obj->children = XRESIZEVEC (long, obj->children, obj->count);
  obj->children[obj->count - 1] = pid;
  obj->children[obj->count - 1] = pid;
 
 
  return NULL;
  return NULL;
 
 
 error_exit:
 error_exit:
  if (in >= 0 && in != STDIN_FILE_NO)
  if (in >= 0 && in != STDIN_FILE_NO)
    obj->funcs->close (obj, in);
    obj->funcs->close (obj, in);
  if (out >= 0 && out != STDOUT_FILE_NO)
  if (out >= 0 && out != STDOUT_FILE_NO)
    obj->funcs->close (obj, out);
    obj->funcs->close (obj, out);
  if (errdes >= 0 && errdes != STDERR_FILE_NO)
  if (errdes >= 0 && errdes != STDERR_FILE_NO)
    obj->funcs->close (obj, errdes);
    obj->funcs->close (obj, errdes);
  if (outname_allocated)
  if (outname_allocated)
    free (outname);
    free (outname);
  return errmsg;
  return errmsg;
}
}
 
 
/* Run a program.  */
/* Run a program.  */
 
 
const char *
const char *
pex_run (struct pex_obj *obj, int flags, const char *executable,
pex_run (struct pex_obj *obj, int flags, const char *executable,
         char * const * argv, const char *orig_outname, const char *errname,
         char * const * argv, const char *orig_outname, const char *errname,
         int *err)
         int *err)
{
{
  return pex_run_in_environment (obj, flags, executable, argv, NULL,
  return pex_run_in_environment (obj, flags, executable, argv, NULL,
                                 orig_outname, errname, err);
                                 orig_outname, errname, err);
}
}
 
 
/* Return a FILE pointer for a temporary file to fill with input for
/* Return a FILE pointer for a temporary file to fill with input for
   the pipeline.  */
   the pipeline.  */
FILE *
FILE *
pex_input_file (struct pex_obj *obj, int flags, const char *in_name)
pex_input_file (struct pex_obj *obj, int flags, const char *in_name)
{
{
  char *name = (char *) in_name;
  char *name = (char *) in_name;
  FILE *f;
  FILE *f;
 
 
  /* This must be called before the first pipeline stage is run, and
  /* This must be called before the first pipeline stage is run, and
     there must not have been any other input selected.  */
     there must not have been any other input selected.  */
  if (obj->count != 0
  if (obj->count != 0
      || (obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
      || (obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
      || obj->next_input_name)
      || obj->next_input_name)
    {
    {
      errno = EINVAL;
      errno = EINVAL;
      return NULL;
      return NULL;
    }
    }
 
 
  name = temp_file (obj, flags, name);
  name = temp_file (obj, flags, name);
  if (! name)
  if (! name)
    return NULL;
    return NULL;
 
 
  f = fopen (name, (flags & PEX_BINARY_OUTPUT) ? "wb" : "w");
  f = fopen (name, (flags & PEX_BINARY_OUTPUT) ? "wb" : "w");
  if (! f)
  if (! f)
    {
    {
      free (name);
      free (name);
      return NULL;
      return NULL;
    }
    }
 
 
  obj->input_file = f;
  obj->input_file = f;
  obj->next_input_name = name;
  obj->next_input_name = name;
  obj->next_input_name_allocated = (name != in_name);
  obj->next_input_name_allocated = (name != in_name);
 
 
  return f;
  return f;
}
}
 
 
/* Return a stream for a pipe connected to the standard input of the
/* Return a stream for a pipe connected to the standard input of the
   first stage of the pipeline.  */
   first stage of the pipeline.  */
FILE *
FILE *
pex_input_pipe (struct pex_obj *obj, int binary)
pex_input_pipe (struct pex_obj *obj, int binary)
{
{
  int p[2];
  int p[2];
  FILE *f;
  FILE *f;
 
 
  /* You must call pex_input_pipe before the first pex_run or pex_one.  */
  /* You must call pex_input_pipe before the first pex_run or pex_one.  */
  if (obj->count > 0)
  if (obj->count > 0)
    goto usage_error;
    goto usage_error;
 
 
  /* You must be using pipes.  Implementations that don't support
  /* You must be using pipes.  Implementations that don't support
     pipes clear this flag before calling pex_init_common.  */
     pipes clear this flag before calling pex_init_common.  */
  if (! (obj->flags & PEX_USE_PIPES))
  if (! (obj->flags & PEX_USE_PIPES))
    goto usage_error;
    goto usage_error;
 
 
  /* If we have somehow already selected other input, that's a
  /* If we have somehow already selected other input, that's a
     mistake.  */
     mistake.  */
  if ((obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
  if ((obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
      || obj->next_input_name)
      || obj->next_input_name)
    goto usage_error;
    goto usage_error;
 
 
  if (obj->funcs->pipe (obj, p, binary != 0) < 0)
  if (obj->funcs->pipe (obj, p, binary != 0) < 0)
    return NULL;
    return NULL;
 
 
  f = obj->funcs->fdopenw (obj, p[WRITE_PORT], binary != 0);
  f = obj->funcs->fdopenw (obj, p[WRITE_PORT], binary != 0);
  if (! f)
  if (! f)
    {
    {
      int saved_errno = errno;
      int saved_errno = errno;
      obj->funcs->close (obj, p[READ_PORT]);
      obj->funcs->close (obj, p[READ_PORT]);
      obj->funcs->close (obj, p[WRITE_PORT]);
      obj->funcs->close (obj, p[WRITE_PORT]);
      errno = saved_errno;
      errno = saved_errno;
      return NULL;
      return NULL;
    }
    }
 
 
  obj->next_input = p[READ_PORT];
  obj->next_input = p[READ_PORT];
 
 
  return f;
  return f;
 
 
 usage_error:
 usage_error:
  errno = EINVAL;
  errno = EINVAL;
  return NULL;
  return NULL;
}
}
 
 
/* Return a FILE pointer for the output of the last program
/* Return a FILE pointer for the output of the last program
   executed.  */
   executed.  */
 
 
FILE *
FILE *
pex_read_output (struct pex_obj *obj, int binary)
pex_read_output (struct pex_obj *obj, int binary)
{
{
  if (obj->next_input_name != NULL)
  if (obj->next_input_name != NULL)
    {
    {
      const char *errmsg;
      const char *errmsg;
      int err;
      int err;
 
 
      /* We have to make sure that the process has completed before we
      /* We have to make sure that the process has completed before we
         try to read the file.  */
         try to read the file.  */
      if (!pex_get_status_and_time (obj, 0, &errmsg, &err))
      if (!pex_get_status_and_time (obj, 0, &errmsg, &err))
        {
        {
          errno = err;
          errno = err;
          return NULL;
          return NULL;
        }
        }
 
 
      obj->read_output = fopen (obj->next_input_name, binary ? "rb" : "r");
      obj->read_output = fopen (obj->next_input_name, binary ? "rb" : "r");
 
 
      if (obj->next_input_name_allocated)
      if (obj->next_input_name_allocated)
        {
        {
          free (obj->next_input_name);
          free (obj->next_input_name);
          obj->next_input_name_allocated = 0;
          obj->next_input_name_allocated = 0;
        }
        }
      obj->next_input_name = NULL;
      obj->next_input_name = NULL;
    }
    }
  else
  else
    {
    {
      int o;
      int o;
 
 
      o = obj->next_input;
      o = obj->next_input;
      if (o < 0 || o == STDIN_FILE_NO)
      if (o < 0 || o == STDIN_FILE_NO)
        return NULL;
        return NULL;
      obj->read_output = obj->funcs->fdopenr (obj, o, binary);
      obj->read_output = obj->funcs->fdopenr (obj, o, binary);
      obj->next_input = -1;
      obj->next_input = -1;
    }
    }
 
 
  return obj->read_output;
  return obj->read_output;
}
}
 
 
/* Get the exit status and, if requested, the resource time for all
/* Get the exit status and, if requested, the resource time for all
   the child processes.  Return 0 on failure, 1 on success.  */
   the child processes.  Return 0 on failure, 1 on success.  */
 
 
static int
static int
pex_get_status_and_time (struct pex_obj *obj, int done, const char **errmsg,
pex_get_status_and_time (struct pex_obj *obj, int done, const char **errmsg,
                         int *err)
                         int *err)
{
{
  int ret;
  int ret;
  int i;
  int i;
 
 
  if (obj->number_waited == obj->count)
  if (obj->number_waited == obj->count)
    return 1;
    return 1;
 
 
  obj->status = XRESIZEVEC (int, obj->status, obj->count);
  obj->status = XRESIZEVEC (int, obj->status, obj->count);
  if ((obj->flags & PEX_RECORD_TIMES) != 0)
  if ((obj->flags & PEX_RECORD_TIMES) != 0)
    obj->time = XRESIZEVEC (struct pex_time, obj->time, obj->count);
    obj->time = XRESIZEVEC (struct pex_time, obj->time, obj->count);
 
 
  ret = 1;
  ret = 1;
  for (i = obj->number_waited; i < obj->count; ++i)
  for (i = obj->number_waited; i < obj->count; ++i)
    {
    {
      if (obj->funcs->wait (obj, obj->children[i], &obj->status[i],
      if (obj->funcs->wait (obj, obj->children[i], &obj->status[i],
                            obj->time == NULL ? NULL : &obj->time[i],
                            obj->time == NULL ? NULL : &obj->time[i],
                            done, errmsg, err) < 0)
                            done, errmsg, err) < 0)
        ret = 0;
        ret = 0;
    }
    }
  obj->number_waited = i;
  obj->number_waited = i;
 
 
  return ret;
  return ret;
}
}
 
 
/* Get exit status of executed programs.  */
/* Get exit status of executed programs.  */
 
 
int
int
pex_get_status (struct pex_obj *obj, int count, int *vector)
pex_get_status (struct pex_obj *obj, int count, int *vector)
{
{
  if (obj->status == NULL)
  if (obj->status == NULL)
    {
    {
      const char *errmsg;
      const char *errmsg;
      int err;
      int err;
 
 
      if (!pex_get_status_and_time (obj, 0, &errmsg, &err))
      if (!pex_get_status_and_time (obj, 0, &errmsg, &err))
        return 0;
        return 0;
    }
    }
 
 
  if (count > obj->count)
  if (count > obj->count)
    {
    {
      memset (vector + obj->count, 0, (count - obj->count) * sizeof (int));
      memset (vector + obj->count, 0, (count - obj->count) * sizeof (int));
      count = obj->count;
      count = obj->count;
    }
    }
 
 
  memcpy (vector, obj->status, count * sizeof (int));
  memcpy (vector, obj->status, count * sizeof (int));
 
 
  return 1;
  return 1;
}
}
 
 
/* Get process times of executed programs.  */
/* Get process times of executed programs.  */
 
 
int
int
pex_get_times (struct pex_obj *obj, int count, struct pex_time *vector)
pex_get_times (struct pex_obj *obj, int count, struct pex_time *vector)
{
{
  if (obj->status == NULL)
  if (obj->status == NULL)
    {
    {
      const char *errmsg;
      const char *errmsg;
      int err;
      int err;
 
 
      if (!pex_get_status_and_time (obj, 0, &errmsg, &err))
      if (!pex_get_status_and_time (obj, 0, &errmsg, &err))
        return 0;
        return 0;
    }
    }
 
 
  if (obj->time == NULL)
  if (obj->time == NULL)
    return 0;
    return 0;
 
 
  if (count > obj->count)
  if (count > obj->count)
    {
    {
      memset (vector + obj->count, 0,
      memset (vector + obj->count, 0,
              (count - obj->count) * sizeof (struct pex_time));
              (count - obj->count) * sizeof (struct pex_time));
      count = obj->count;
      count = obj->count;
    }
    }
 
 
  memcpy (vector, obj->time, count * sizeof (struct pex_time));
  memcpy (vector, obj->time, count * sizeof (struct pex_time));
 
 
  return 1;
  return 1;
}
}
 
 
/* Free a pex_obj structure.  */
/* Free a pex_obj structure.  */
 
 
void
void
pex_free (struct pex_obj *obj)
pex_free (struct pex_obj *obj)
{
{
  if (obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
  if (obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
    obj->funcs->close (obj, obj->next_input);
    obj->funcs->close (obj, obj->next_input);
 
 
  /* If the caller forgot to wait for the children, we do it here, to
  /* If the caller forgot to wait for the children, we do it here, to
     avoid zombies.  */
     avoid zombies.  */
  if (obj->status == NULL)
  if (obj->status == NULL)
    {
    {
      const char *errmsg;
      const char *errmsg;
      int err;
      int err;
 
 
      obj->flags &= ~ PEX_RECORD_TIMES;
      obj->flags &= ~ PEX_RECORD_TIMES;
      pex_get_status_and_time (obj, 1, &errmsg, &err);
      pex_get_status_and_time (obj, 1, &errmsg, &err);
    }
    }
 
 
  if (obj->next_input_name_allocated)
  if (obj->next_input_name_allocated)
    free (obj->next_input_name);
    free (obj->next_input_name);
  if (obj->children != NULL)
  if (obj->children != NULL)
    free (obj->children);
    free (obj->children);
  if (obj->status != NULL)
  if (obj->status != NULL)
    free (obj->status);
    free (obj->status);
  if (obj->time != NULL)
  if (obj->time != NULL)
    free (obj->time);
    free (obj->time);
  if (obj->read_output != NULL)
  if (obj->read_output != NULL)
    fclose (obj->read_output);
    fclose (obj->read_output);
 
 
  if (obj->remove_count > 0)
  if (obj->remove_count > 0)
    {
    {
      int i;
      int i;
 
 
      for (i = 0; i < obj->remove_count; ++i)
      for (i = 0; i < obj->remove_count; ++i)
        {
        {
          remove (obj->remove[i]);
          remove (obj->remove[i]);
          free (obj->remove[i]);
          free (obj->remove[i]);
        }
        }
      free (obj->remove);
      free (obj->remove);
    }
    }
 
 
  if (obj->funcs->cleanup != NULL)
  if (obj->funcs->cleanup != NULL)
    obj->funcs->cleanup (obj);
    obj->funcs->cleanup (obj);
 
 
  free (obj);
  free (obj);
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.