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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [libiberty/] [pex-unix.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
/* Utilities to execute a program in a subprocess (possibly linked by pipes
/* Utilities to execute a program in a subprocess (possibly linked by pipes
   with other subprocesses), and wait for it.  Generic Unix version
   with other subprocesses), and wait for it.  Generic Unix version
   (also used for UWIN and VMS).
   (also used for UWIN and VMS).
   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
 
 
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 <signal.h>
#include <signal.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
 
 
#include <sys/types.h>
#include <sys/types.h>
 
 
#ifdef HAVE_FCNTL_H
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#include <fcntl.h>
#endif
#endif
#ifdef HAVE_SYS_WAIT_H
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#include <sys/wait.h>
#endif
#endif
#ifdef HAVE_GETRUSAGE
#ifdef HAVE_GETRUSAGE
#include <sys/time.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/resource.h>
#endif
#endif
#ifdef HAVE_SYS_STAT_H
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#include <sys/stat.h>
#endif
#endif
 
 
 
 
#ifdef vfork /* Autoconf may define this to fork for us. */
#ifdef vfork /* Autoconf may define this to fork for us. */
# define VFORK_STRING "fork"
# define VFORK_STRING "fork"
#else
#else
# define VFORK_STRING "vfork"
# define VFORK_STRING "vfork"
#endif
#endif
#ifdef HAVE_VFORK_H
#ifdef HAVE_VFORK_H
#include <vfork.h>
#include <vfork.h>
#endif
#endif
#ifdef VMS
#ifdef VMS
#define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \
#define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \
               lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1)
               lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1)
#endif /* VMS */
#endif /* VMS */
 
 
 
 
/* File mode to use for private and world-readable files.  */
/* File mode to use for private and world-readable files.  */
 
 
#if defined (S_IRUSR) && defined (S_IWUSR) && defined (S_IRGRP) && defined (S_IWGRP) && defined (S_IROTH) && defined (S_IWOTH)
#if defined (S_IRUSR) && defined (S_IWUSR) && defined (S_IRGRP) && defined (S_IWGRP) && defined (S_IROTH) && defined (S_IWOTH)
#define PUBLIC_MODE  \
#define PUBLIC_MODE  \
    (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
    (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
#else
#else
#define PUBLIC_MODE 0666
#define PUBLIC_MODE 0666
#endif
#endif
 
 
/* Get the exit status of a particular process, and optionally get the
/* Get the exit status of a particular process, and optionally get the
   time that it took.  This is simple if we have wait4, slightly
   time that it took.  This is simple if we have wait4, slightly
   harder if we have waitpid, and is a pain if we only have wait.  */
   harder if we have waitpid, and is a pain if we only have wait.  */
 
 
static pid_t pex_wait (struct pex_obj *, pid_t, int *, struct pex_time *);
static pid_t pex_wait (struct pex_obj *, pid_t, int *, struct pex_time *);
 
 
#ifdef HAVE_WAIT4
#ifdef HAVE_WAIT4
 
 
static pid_t
static pid_t
pex_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid, int *status,
pex_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid, int *status,
          struct pex_time *time)
          struct pex_time *time)
{
{
  pid_t ret;
  pid_t ret;
  struct rusage r;
  struct rusage r;
 
 
#ifdef HAVE_WAITPID
#ifdef HAVE_WAITPID
  if (time == NULL)
  if (time == NULL)
    return waitpid (pid, status, 0);
    return waitpid (pid, status, 0);
#endif
#endif
 
 
  ret = wait4 (pid, status, 0, &r);
  ret = wait4 (pid, status, 0, &r);
 
 
  if (time != NULL)
  if (time != NULL)
    {
    {
      time->user_seconds = r.ru_utime.tv_sec;
      time->user_seconds = r.ru_utime.tv_sec;
      time->user_microseconds= r.ru_utime.tv_usec;
      time->user_microseconds= r.ru_utime.tv_usec;
      time->system_seconds = r.ru_stime.tv_sec;
      time->system_seconds = r.ru_stime.tv_sec;
      time->system_microseconds= r.ru_stime.tv_usec;
      time->system_microseconds= r.ru_stime.tv_usec;
    }
    }
 
 
  return ret;
  return ret;
}
}
 
 
#else /* ! defined (HAVE_WAIT4) */
#else /* ! defined (HAVE_WAIT4) */
 
 
#ifdef HAVE_WAITPID
#ifdef HAVE_WAITPID
 
 
#ifndef HAVE_GETRUSAGE
#ifndef HAVE_GETRUSAGE
 
 
static pid_t
static pid_t
pex_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid, int *status,
pex_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid, int *status,
          struct pex_time *time)
          struct pex_time *time)
{
{
  if (time != NULL)
  if (time != NULL)
    memset (time, 0, sizeof (struct pex_time));
    memset (time, 0, sizeof (struct pex_time));
  return waitpid (pid, status, 0);
  return waitpid (pid, status, 0);
}
}
 
 
#else /* defined (HAVE_GETRUSAGE) */
#else /* defined (HAVE_GETRUSAGE) */
 
 
static pid_t
static pid_t
pex_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid, int *status,
pex_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid, int *status,
          struct pex_time *time)
          struct pex_time *time)
{
{
  struct rusage r1, r2;
  struct rusage r1, r2;
  pid_t ret;
  pid_t ret;
 
 
  if (time == NULL)
  if (time == NULL)
    return waitpid (pid, status, 0);
    return waitpid (pid, status, 0);
 
 
  getrusage (RUSAGE_CHILDREN, &r1);
  getrusage (RUSAGE_CHILDREN, &r1);
 
 
  ret = waitpid (pid, status, 0);
  ret = waitpid (pid, status, 0);
  if (ret < 0)
  if (ret < 0)
    return ret;
    return ret;
 
 
  getrusage (RUSAGE_CHILDREN, &r2);
  getrusage (RUSAGE_CHILDREN, &r2);
 
 
  time->user_seconds = r2.ru_utime.tv_sec - r1.ru_utime.tv_sec;
  time->user_seconds = r2.ru_utime.tv_sec - r1.ru_utime.tv_sec;
  time->user_microseconds = r2.ru_utime.tv_usec - r1.ru_utime.tv_usec;
  time->user_microseconds = r2.ru_utime.tv_usec - r1.ru_utime.tv_usec;
  if (r2.ru_utime.tv_usec < r1.ru_utime.tv_usec)
  if (r2.ru_utime.tv_usec < r1.ru_utime.tv_usec)
    {
    {
      --time->user_seconds;
      --time->user_seconds;
      time->user_microseconds += 1000000;
      time->user_microseconds += 1000000;
    }
    }
 
 
  time->system_seconds = r2.ru_stime.tv_sec - r1.ru_stime.tv_sec;
  time->system_seconds = r2.ru_stime.tv_sec - r1.ru_stime.tv_sec;
  time->system_microseconds = r2.ru_stime.tv_usec - r1.ru_stime.tv_usec;
  time->system_microseconds = r2.ru_stime.tv_usec - r1.ru_stime.tv_usec;
  if (r2.ru_stime.tv_usec < r1.ru_stime.tv_usec)
  if (r2.ru_stime.tv_usec < r1.ru_stime.tv_usec)
    {
    {
      --time->system_seconds;
      --time->system_seconds;
      time->system_microseconds += 1000000;
      time->system_microseconds += 1000000;
    }
    }
 
 
  return ret;
  return ret;
}
}
 
 
#endif /* defined (HAVE_GETRUSAGE) */
#endif /* defined (HAVE_GETRUSAGE) */
 
 
#else /* ! defined (HAVE_WAITPID) */
#else /* ! defined (HAVE_WAITPID) */
 
 
struct status_list
struct status_list
{
{
  struct status_list *next;
  struct status_list *next;
  pid_t pid;
  pid_t pid;
  int status;
  int status;
  struct pex_time time;
  struct pex_time time;
};
};
 
 
static pid_t
static pid_t
pex_wait (struct pex_obj *obj, pid_t pid, int *status, struct pex_time *time)
pex_wait (struct pex_obj *obj, pid_t pid, int *status, struct pex_time *time)
{
{
  struct status_list **pp;
  struct status_list **pp;
 
 
  for (pp = (struct status_list **) &obj->sysdep;
  for (pp = (struct status_list **) &obj->sysdep;
       *pp != NULL;
       *pp != NULL;
       pp = &(*pp)->next)
       pp = &(*pp)->next)
    {
    {
      if ((*pp)->pid == pid)
      if ((*pp)->pid == pid)
        {
        {
          struct status_list *p;
          struct status_list *p;
 
 
          p = *pp;
          p = *pp;
          *status = p->status;
          *status = p->status;
          if (time != NULL)
          if (time != NULL)
            *time = p->time;
            *time = p->time;
          *pp = p->next;
          *pp = p->next;
          free (p);
          free (p);
          return pid;
          return pid;
        }
        }
    }
    }
 
 
  while (1)
  while (1)
    {
    {
      pid_t cpid;
      pid_t cpid;
      struct status_list *psl;
      struct status_list *psl;
      struct pex_time pt;
      struct pex_time pt;
#ifdef HAVE_GETRUSAGE
#ifdef HAVE_GETRUSAGE
      struct rusage r1, r2;
      struct rusage r1, r2;
#endif
#endif
 
 
      if (time != NULL)
      if (time != NULL)
        {
        {
#ifdef HAVE_GETRUSAGE
#ifdef HAVE_GETRUSAGE
          getrusage (RUSAGE_CHILDREN, &r1);
          getrusage (RUSAGE_CHILDREN, &r1);
#else
#else
          memset (&pt, 0, sizeof (struct pex_time));
          memset (&pt, 0, sizeof (struct pex_time));
#endif
#endif
        }
        }
 
 
      cpid = wait (status);
      cpid = wait (status);
 
 
#ifdef HAVE_GETRUSAGE
#ifdef HAVE_GETRUSAGE
      if (time != NULL && cpid >= 0)
      if (time != NULL && cpid >= 0)
        {
        {
          getrusage (RUSAGE_CHILDREN, &r2);
          getrusage (RUSAGE_CHILDREN, &r2);
 
 
          pt.user_seconds = r2.ru_utime.tv_sec - r1.ru_utime.tv_sec;
          pt.user_seconds = r2.ru_utime.tv_sec - r1.ru_utime.tv_sec;
          pt.user_microseconds = r2.ru_utime.tv_usec - r1.ru_utime.tv_usec;
          pt.user_microseconds = r2.ru_utime.tv_usec - r1.ru_utime.tv_usec;
          if (pt.user_microseconds < 0)
          if (pt.user_microseconds < 0)
            {
            {
              --pt.user_seconds;
              --pt.user_seconds;
              pt.user_microseconds += 1000000;
              pt.user_microseconds += 1000000;
            }
            }
 
 
          pt.system_seconds = r2.ru_stime.tv_sec - r1.ru_stime.tv_sec;
          pt.system_seconds = r2.ru_stime.tv_sec - r1.ru_stime.tv_sec;
          pt.system_microseconds = r2.ru_stime.tv_usec - r1.ru_stime.tv_usec;
          pt.system_microseconds = r2.ru_stime.tv_usec - r1.ru_stime.tv_usec;
          if (pt.system_microseconds < 0)
          if (pt.system_microseconds < 0)
            {
            {
              --pt.system_seconds;
              --pt.system_seconds;
              pt.system_microseconds += 1000000;
              pt.system_microseconds += 1000000;
            }
            }
        }
        }
#endif
#endif
 
 
      if (cpid < 0 || cpid == pid)
      if (cpid < 0 || cpid == pid)
        {
        {
          if (time != NULL)
          if (time != NULL)
            *time = pt;
            *time = pt;
          return cpid;
          return cpid;
        }
        }
 
 
      psl = XNEW (struct status_list);
      psl = XNEW (struct status_list);
      psl->pid = cpid;
      psl->pid = cpid;
      psl->status = *status;
      psl->status = *status;
      if (time != NULL)
      if (time != NULL)
        psl->time = pt;
        psl->time = pt;
      psl->next = (struct status_list *) obj->sysdep;
      psl->next = (struct status_list *) obj->sysdep;
      obj->sysdep = (void *) psl;
      obj->sysdep = (void *) psl;
    }
    }
}
}
 
 
#endif /* ! defined (HAVE_WAITPID) */
#endif /* ! defined (HAVE_WAITPID) */
#endif /* ! defined (HAVE_WAIT4) */
#endif /* ! defined (HAVE_WAIT4) */
 
 
static void pex_child_error (struct pex_obj *, const char *, const char *, int)
static void pex_child_error (struct pex_obj *, const char *, const char *, int)
     ATTRIBUTE_NORETURN;
     ATTRIBUTE_NORETURN;
static int pex_unix_open_read (struct pex_obj *, const char *, int);
static int pex_unix_open_read (struct pex_obj *, const char *, int);
static int pex_unix_open_write (struct pex_obj *, const char *, int);
static int pex_unix_open_write (struct pex_obj *, const char *, int);
static long pex_unix_exec_child (struct pex_obj *, int, const char *,
static long pex_unix_exec_child (struct pex_obj *, int, const char *,
                                 char * const *, char * const *,
                                 char * const *, char * const *,
                                 int, int, int, int,
                                 int, int, int, int,
                                 const char **, int *);
                                 const char **, int *);
static int pex_unix_close (struct pex_obj *, int);
static int pex_unix_close (struct pex_obj *, int);
static int pex_unix_wait (struct pex_obj *, long, int *, struct pex_time *,
static int pex_unix_wait (struct pex_obj *, long, int *, struct pex_time *,
                          int, const char **, int *);
                          int, const char **, int *);
static int pex_unix_pipe (struct pex_obj *, int *, int);
static int pex_unix_pipe (struct pex_obj *, int *, int);
static FILE *pex_unix_fdopenr (struct pex_obj *, int, int);
static FILE *pex_unix_fdopenr (struct pex_obj *, int, int);
static FILE *pex_unix_fdopenw (struct pex_obj *, int, int);
static FILE *pex_unix_fdopenw (struct pex_obj *, int, int);
static void pex_unix_cleanup (struct pex_obj *);
static void pex_unix_cleanup (struct pex_obj *);
 
 
/* The list of functions we pass to the common routines.  */
/* The list of functions we pass to the common routines.  */
 
 
const struct pex_funcs funcs =
const struct pex_funcs funcs =
{
{
  pex_unix_open_read,
  pex_unix_open_read,
  pex_unix_open_write,
  pex_unix_open_write,
  pex_unix_exec_child,
  pex_unix_exec_child,
  pex_unix_close,
  pex_unix_close,
  pex_unix_wait,
  pex_unix_wait,
  pex_unix_pipe,
  pex_unix_pipe,
  pex_unix_fdopenr,
  pex_unix_fdopenr,
  pex_unix_fdopenw,
  pex_unix_fdopenw,
  pex_unix_cleanup
  pex_unix_cleanup
};
};
 
 
/* Return a newly initialized pex_obj structure.  */
/* Return a newly initialized pex_obj structure.  */
 
 
struct pex_obj *
struct pex_obj *
pex_init (int flags, const char *pname, const char *tempbase)
pex_init (int flags, const char *pname, const char *tempbase)
{
{
  return pex_init_common (flags, pname, tempbase, &funcs);
  return pex_init_common (flags, pname, tempbase, &funcs);
}
}
 
 
/* Open a file for reading.  */
/* Open a file for reading.  */
 
 
static int
static int
pex_unix_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
pex_unix_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
                    int binary ATTRIBUTE_UNUSED)
                    int binary ATTRIBUTE_UNUSED)
{
{
  return open (name, O_RDONLY);
  return open (name, O_RDONLY);
}
}
 
 
/* Open a file for writing.  */
/* Open a file for writing.  */
 
 
static int
static int
pex_unix_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
pex_unix_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
                     int binary ATTRIBUTE_UNUSED)
                     int binary ATTRIBUTE_UNUSED)
{
{
  /* Note that we can't use O_EXCL here because gcc may have already
  /* Note that we can't use O_EXCL here because gcc may have already
     created the temporary file via make_temp_file.  */
     created the temporary file via make_temp_file.  */
  return open (name, O_WRONLY | O_CREAT | O_TRUNC, PUBLIC_MODE);
  return open (name, O_WRONLY | O_CREAT | O_TRUNC, PUBLIC_MODE);
}
}
 
 
/* Close a file.  */
/* Close a file.  */
 
 
static int
static int
pex_unix_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd)
pex_unix_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd)
{
{
  return close (fd);
  return close (fd);
}
}
 
 
/* Report an error from a child process.  We don't use stdio routines,
/* Report an error from a child process.  We don't use stdio routines,
   because we might be here due to a vfork call.  */
   because we might be here due to a vfork call.  */
 
 
static void
static void
pex_child_error (struct pex_obj *obj, const char *executable,
pex_child_error (struct pex_obj *obj, const char *executable,
                 const char *errmsg, int err)
                 const char *errmsg, int err)
{
{
#define writeerr(s) write (STDERR_FILE_NO, s, strlen (s))
#define writeerr(s) write (STDERR_FILE_NO, s, strlen (s))
  writeerr (obj->pname);
  writeerr (obj->pname);
  writeerr (": error trying to exec '");
  writeerr (": error trying to exec '");
  writeerr (executable);
  writeerr (executable);
  writeerr ("': ");
  writeerr ("': ");
  writeerr (errmsg);
  writeerr (errmsg);
  writeerr (": ");
  writeerr (": ");
  writeerr (xstrerror (err));
  writeerr (xstrerror (err));
  writeerr ("\n");
  writeerr ("\n");
  _exit (-1);
  _exit (-1);
}
}
 
 
/* Execute a child.  */
/* Execute a child.  */
 
 
extern char **environ;
extern char **environ;
 
 
static long
static long
pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable,
pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable,
                     char * const * argv, char * const * env,
                     char * const * argv, char * const * env,
                     int in, int out, int errdes,
                     int in, int out, int errdes,
                     int toclose, const char **errmsg, int *err)
                     int toclose, const char **errmsg, int *err)
{
{
  pid_t pid;
  pid_t pid;
 
 
  /* We declare these to be volatile to avoid warnings from gcc about
  /* We declare these to be volatile to avoid warnings from gcc about
     them being clobbered by vfork.  */
     them being clobbered by vfork.  */
  volatile int sleep_interval;
  volatile int sleep_interval;
  volatile int retries;
  volatile int retries;
 
 
  sleep_interval = 1;
  sleep_interval = 1;
  pid = -1;
  pid = -1;
  for (retries = 0; retries < 4; ++retries)
  for (retries = 0; retries < 4; ++retries)
    {
    {
      pid = vfork ();
      pid = vfork ();
      if (pid >= 0)
      if (pid >= 0)
        break;
        break;
      sleep (sleep_interval);
      sleep (sleep_interval);
      sleep_interval *= 2;
      sleep_interval *= 2;
    }
    }
 
 
  switch (pid)
  switch (pid)
    {
    {
    case -1:
    case -1:
      *err = errno;
      *err = errno;
      *errmsg = VFORK_STRING;
      *errmsg = VFORK_STRING;
      return -1;
      return -1;
 
 
    case 0:
    case 0:
      /* Child process.  */
      /* Child process.  */
      if (in != STDIN_FILE_NO)
      if (in != STDIN_FILE_NO)
        {
        {
          if (dup2 (in, STDIN_FILE_NO) < 0)
          if (dup2 (in, STDIN_FILE_NO) < 0)
            pex_child_error (obj, executable, "dup2", errno);
            pex_child_error (obj, executable, "dup2", errno);
          if (close (in) < 0)
          if (close (in) < 0)
            pex_child_error (obj, executable, "close", errno);
            pex_child_error (obj, executable, "close", errno);
        }
        }
      if (out != STDOUT_FILE_NO)
      if (out != STDOUT_FILE_NO)
        {
        {
          if (dup2 (out, STDOUT_FILE_NO) < 0)
          if (dup2 (out, STDOUT_FILE_NO) < 0)
            pex_child_error (obj, executable, "dup2", errno);
            pex_child_error (obj, executable, "dup2", errno);
          if (close (out) < 0)
          if (close (out) < 0)
            pex_child_error (obj, executable, "close", errno);
            pex_child_error (obj, executable, "close", errno);
        }
        }
      if (errdes != STDERR_FILE_NO)
      if (errdes != STDERR_FILE_NO)
        {
        {
          if (dup2 (errdes, STDERR_FILE_NO) < 0)
          if (dup2 (errdes, STDERR_FILE_NO) < 0)
            pex_child_error (obj, executable, "dup2", errno);
            pex_child_error (obj, executable, "dup2", errno);
          if (close (errdes) < 0)
          if (close (errdes) < 0)
            pex_child_error (obj, executable, "close", errno);
            pex_child_error (obj, executable, "close", errno);
        }
        }
      if (toclose >= 0)
      if (toclose >= 0)
        {
        {
          if (close (toclose) < 0)
          if (close (toclose) < 0)
            pex_child_error (obj, executable, "close", errno);
            pex_child_error (obj, executable, "close", errno);
        }
        }
      if ((flags & PEX_STDERR_TO_STDOUT) != 0)
      if ((flags & PEX_STDERR_TO_STDOUT) != 0)
        {
        {
          if (dup2 (STDOUT_FILE_NO, STDERR_FILE_NO) < 0)
          if (dup2 (STDOUT_FILE_NO, STDERR_FILE_NO) < 0)
            pex_child_error (obj, executable, "dup2", errno);
            pex_child_error (obj, executable, "dup2", errno);
        }
        }
 
 
      if (env)
      if (env)
        environ = (char**) env;
        environ = (char**) env;
 
 
      if ((flags & PEX_SEARCH) != 0)
      if ((flags & PEX_SEARCH) != 0)
        {
        {
          execvp (executable, argv);
          execvp (executable, argv);
          pex_child_error (obj, executable, "execvp", errno);
          pex_child_error (obj, executable, "execvp", errno);
        }
        }
      else
      else
        {
        {
          execv (executable, argv);
          execv (executable, argv);
          pex_child_error (obj, executable, "execv", errno);
          pex_child_error (obj, executable, "execv", errno);
        }
        }
 
 
      /* NOTREACHED */
      /* NOTREACHED */
      return -1;
      return -1;
 
 
    default:
    default:
      /* Parent process.  */
      /* Parent process.  */
      if (in != STDIN_FILE_NO)
      if (in != STDIN_FILE_NO)
        {
        {
          if (close (in) < 0)
          if (close (in) < 0)
            {
            {
              *err = errno;
              *err = errno;
              *errmsg = "close";
              *errmsg = "close";
              return -1;
              return -1;
            }
            }
        }
        }
      if (out != STDOUT_FILE_NO)
      if (out != STDOUT_FILE_NO)
        {
        {
          if (close (out) < 0)
          if (close (out) < 0)
            {
            {
              *err = errno;
              *err = errno;
              *errmsg = "close";
              *errmsg = "close";
              return -1;
              return -1;
            }
            }
        }
        }
      if (errdes != STDERR_FILE_NO)
      if (errdes != STDERR_FILE_NO)
        {
        {
          if (close (errdes) < 0)
          if (close (errdes) < 0)
            {
            {
              *err = errno;
              *err = errno;
              *errmsg = "close";
              *errmsg = "close";
              return -1;
              return -1;
            }
            }
        }
        }
 
 
      return (long) pid;
      return (long) pid;
    }
    }
}
}
 
 
/* Wait for a child process to complete.  */
/* Wait for a child process to complete.  */
 
 
static int
static int
pex_unix_wait (struct pex_obj *obj, long pid, int *status,
pex_unix_wait (struct pex_obj *obj, long pid, int *status,
               struct pex_time *time, int done, const char **errmsg,
               struct pex_time *time, int done, const char **errmsg,
               int *err)
               int *err)
{
{
  /* If we are cleaning up when the caller didn't retrieve process
  /* If we are cleaning up when the caller didn't retrieve process
     status for some reason, encourage the process to go away.  */
     status for some reason, encourage the process to go away.  */
  if (done)
  if (done)
    kill (pid, SIGTERM);
    kill (pid, SIGTERM);
 
 
  if (pex_wait (obj, pid, status, time) < 0)
  if (pex_wait (obj, pid, status, time) < 0)
    {
    {
      *err = errno;
      *err = errno;
      *errmsg = "wait";
      *errmsg = "wait";
      return -1;
      return -1;
    }
    }
 
 
  return 0;
  return 0;
}
}
 
 
/* Create a pipe.  */
/* Create a pipe.  */
 
 
static int
static int
pex_unix_pipe (struct pex_obj *obj ATTRIBUTE_UNUSED, int *p,
pex_unix_pipe (struct pex_obj *obj ATTRIBUTE_UNUSED, int *p,
               int binary ATTRIBUTE_UNUSED)
               int binary ATTRIBUTE_UNUSED)
{
{
  return pipe (p);
  return pipe (p);
}
}
 
 
/* Get a FILE pointer to read from a file descriptor.  */
/* Get a FILE pointer to read from a file descriptor.  */
 
 
static FILE *
static FILE *
pex_unix_fdopenr (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
pex_unix_fdopenr (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
                  int binary ATTRIBUTE_UNUSED)
                  int binary ATTRIBUTE_UNUSED)
{
{
  return fdopen (fd, "r");
  return fdopen (fd, "r");
}
}
 
 
static FILE *
static FILE *
pex_unix_fdopenw (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
pex_unix_fdopenw (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
                  int binary ATTRIBUTE_UNUSED)
                  int binary ATTRIBUTE_UNUSED)
{
{
  if (fcntl (fd, F_SETFD, FD_CLOEXEC) < 0)
  if (fcntl (fd, F_SETFD, FD_CLOEXEC) < 0)
    return NULL;
    return NULL;
  return fdopen (fd, "w");
  return fdopen (fd, "w");
}
}
 
 
static void
static void
pex_unix_cleanup (struct pex_obj *obj ATTRIBUTE_UNUSED)
pex_unix_cleanup (struct pex_obj *obj ATTRIBUTE_UNUSED)
{
{
#if !defined (HAVE_WAIT4) && !defined (HAVE_WAITPID)
#if !defined (HAVE_WAIT4) && !defined (HAVE_WAITPID)
  while (obj->sysdep != NULL)
  while (obj->sysdep != NULL)
    {
    {
      struct status_list *this;
      struct status_list *this;
      struct status_list *next;
      struct status_list *next;
 
 
      this = (struct status_list *) obj->sysdep;
      this = (struct status_list *) obj->sysdep;
      next = this->next;
      next = this->next;
      free (this);
      free (this);
      obj->sysdep = (void *) next;
      obj->sysdep = (void *) next;
    }
    }
#endif
#endif
}
}
 
 

powered by: WebSVN 2.1.0

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