Back to index

cell-binutils  2.17cvs20070401
Classes | Defines | Functions | Variables
pex-unix.c File Reference
#include "config.h"
#include "libiberty.h"
#include "pex-common.h"
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>

Go to the source code of this file.

Classes

struct  status_list

Defines

#define VFORK_STRING   "vfork"
#define PUBLIC_MODE   0666
#define writeerr(s)   (void) write (STDERR_FILE_NO, s, strlen (s))

Functions

static pid_t pex_wait (struct pex_obj *, pid_t, int *, struct pex_time *)
static void pex_child_error (struct pex_obj *, static int pex_unix_open_read(struct pex_obj const char *, static int pex_unix_open_read(struct pex_obj const char *, static long pex_unix_exec_child(struct pex_obj int)
struct pex_objpex_init (int flags, const char *pname, const char *tempbase)
static int pex_unix_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, int binary ATTRIBUTE_UNUSED)
static int pex_unix_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, int binary ATTRIBUTE_UNUSED)
static int pex_unix_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd)
static void pex_child_error (struct pex_obj *obj, const char *executable, const char *errmsg, int err)
static long pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable, char *const *argv, char *const *env, int in, int out, int errdes, int toclose, const char **errmsg, int *err)
static int pex_unix_wait (struct pex_obj *obj, long pid, int *status, struct pex_time *time, int done, const char **errmsg, int *err)
static int pex_unix_pipe (struct pex_obj *obj ATTRIBUTE_UNUSED, int *p, int binary ATTRIBUTE_UNUSED)
static FILE * pex_unix_fdopenr (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd, int binary ATTRIBUTE_UNUSED)
static FILE * pex_unix_fdopenw (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd, int binary ATTRIBUTE_UNUSED)
static void pex_unix_cleanup (struct pex_obj *obj ATTRIBUTE_UNUSED)

Variables

char ** environ

Class Documentation

struct status_list

Definition at line 174 of file pex-unix.c.

Collaboration diagram for status_list:
Class Members
struct status_list * next
pid_t pid
int status

Define Documentation

#define PUBLIC_MODE   0666

Definition at line 80 of file pex-unix.c.

#define VFORK_STRING   "vfork"

Definition at line 63 of file pex-unix.c.

#define writeerr (   s)    (void) write (STDERR_FILE_NO, s, strlen (s))

Function Documentation

static void pex_child_error ( struct pex_obj ,
static int pex_unix_open_read (struct pex_obj  const char *,
static int pex_unix_open_read (struct pex_obj  const char *,
static long pex_unix_exec_child (struct pex_obj  int 
) [static]

Definition at line 268 of file pex-unix.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void pex_child_error ( struct pex_obj obj,
const char *  executable,
const char *  errmsg,
int  err 
) [static]

Definition at line 339 of file pex-unix.c.

{
#define writeerr(s) (void) write (STDERR_FILE_NO, s, strlen (s))
  writeerr (obj->pname);
  writeerr (": error trying to exec '");
  writeerr (executable);
  writeerr ("': ");
  writeerr (errmsg);
  writeerr (": ");
  writeerr (xstrerror (err));
  writeerr ("\n");
  _exit (-1);
}

Here is the call graph for this function:

struct pex_obj* pex_init ( int  flags,
const char *  pname,
const char *  tempbase 
) [read]

Definition at line 302 of file pex-unix.c.

Here is the call graph for this function:

static void pex_unix_cleanup ( struct pex_obj *obj  ATTRIBUTE_UNUSED) [static]

Definition at line 524 of file pex-unix.c.

{
#if !defined (HAVE_WAIT4) && !defined (HAVE_WAITPID)
  while (obj->sysdep != NULL)
    {
      struct status_list *this;
      struct status_list *next;

      this = (struct status_list *) obj->sysdep;
      next = this->next;
      free (this);
      obj->sysdep = (void *) next;
    }
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int pex_unix_close ( struct pex_obj *obj  ATTRIBUTE_UNUSED,
int  fd 
) [static]

Definition at line 330 of file pex-unix.c.

{
  return close (fd);
}

Here is the caller graph for this function:

static long pex_unix_exec_child ( struct pex_obj obj,
int  flags,
const char *  executable,
char *const argv,
char *const env,
int  in,
int  out,
int  errdes,
int  toclose,
const char **  errmsg,
int err 
) [static]

Definition at line 359 of file pex-unix.c.

{
  pid_t pid;

  /* We declare these to be volatile to avoid warnings from gcc about
     them being clobbered by vfork.  */
  volatile int sleep_interval;
  volatile int retries;

  sleep_interval = 1;
  pid = -1;
  for (retries = 0; retries < 4; ++retries)
    {
      pid = vfork ();
      if (pid >= 0)
       break;
      sleep (sleep_interval);
      sleep_interval *= 2;
    }

  switch (pid)
    {
    case -1:
      *err = errno;
      *errmsg = VFORK_STRING;
      return -1;

    case 0:
      /* Child process.  */
      if (in != STDIN_FILE_NO)
       {
         if (dup2 (in, STDIN_FILE_NO) < 0)
           pex_child_error (obj, executable, "dup2", errno);
         if (close (in) < 0)
           pex_child_error (obj, executable, "close", errno);
       }
      if (out != STDOUT_FILE_NO)
       {
         if (dup2 (out, STDOUT_FILE_NO) < 0)
           pex_child_error (obj, executable, "dup2", errno);
         if (close (out) < 0)
           pex_child_error (obj, executable, "close", errno);
       }
      if (errdes != STDERR_FILE_NO)
       {
         if (dup2 (errdes, STDERR_FILE_NO) < 0)
           pex_child_error (obj, executable, "dup2", errno);
         if (close (errdes) < 0)
           pex_child_error (obj, executable, "close", errno);
       }
      if (toclose >= 0)
       {
         if (close (toclose) < 0)
           pex_child_error (obj, executable, "close", errno);
       }
      if ((flags & PEX_STDERR_TO_STDOUT) != 0)
       {
         if (dup2 (STDOUT_FILE_NO, STDERR_FILE_NO) < 0)
           pex_child_error (obj, executable, "dup2", errno);
       }

      if (env)
        environ = (char**) env;

      if ((flags & PEX_SEARCH) != 0)
       {
         execvp (executable, argv);
         pex_child_error (obj, executable, "execvp", errno);
       }
      else
       {
         execv (executable, argv);
         pex_child_error (obj, executable, "execv", errno);
       }

      /* NOTREACHED */
      return -1;

    default:
      /* Parent process.  */
      if (in != STDIN_FILE_NO)
       {
         if (close (in) < 0)
           {
             *err = errno;
             *errmsg = "close";
             return -1;
           }
       }
      if (out != STDOUT_FILE_NO)
       {
         if (close (out) < 0)
           {
             *err = errno;
             *errmsg = "close";
             return -1;
           }
       }
      if (errdes != STDERR_FILE_NO)
       {
         if (close (errdes) < 0)
           {
             *err = errno;
             *errmsg = "close";
             return -1;
           }
       }

      return (long) pid;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static FILE* pex_unix_fdopenr ( struct pex_obj *obj  ATTRIBUTE_UNUSED,
int  fd,
int binary  ATTRIBUTE_UNUSED 
) [static]

Definition at line 508 of file pex-unix.c.

{
  return fdopen (fd, "r");
}

Here is the caller graph for this function:

static FILE* pex_unix_fdopenw ( struct pex_obj *obj  ATTRIBUTE_UNUSED,
int  fd,
int binary  ATTRIBUTE_UNUSED 
) [static]

Definition at line 515 of file pex-unix.c.

{
  if (fcntl (fd, F_SETFD, FD_CLOEXEC) < 0)
    return NULL;
  return fdopen (fd, "w");
}

Here is the caller graph for this function:

static int pex_unix_open_read ( struct pex_obj *obj  ATTRIBUTE_UNUSED,
const char *  name,
int binary  ATTRIBUTE_UNUSED 
) [static]

Definition at line 310 of file pex-unix.c.

{
  return open (name, O_RDONLY);
}

Here is the caller graph for this function:

static int pex_unix_open_write ( struct pex_obj *obj  ATTRIBUTE_UNUSED,
const char *  name,
int binary  ATTRIBUTE_UNUSED 
) [static]

Definition at line 319 of file pex-unix.c.

{
  /* Note that we can't use O_EXCL here because gcc may have already
     created the temporary file via make_temp_file.  */
  return open (name, O_WRONLY | O_CREAT | O_TRUNC, PUBLIC_MODE);
}

Here is the caller graph for this function:

static int pex_unix_pipe ( struct pex_obj *obj  ATTRIBUTE_UNUSED,
int p,
int binary  ATTRIBUTE_UNUSED 
) [static]

Definition at line 499 of file pex-unix.c.

{
  return pipe (p);
}

Here is the caller graph for this function:

static int pex_unix_wait ( struct pex_obj obj,
long  pid,
int status,
struct pex_time time,
int  done,
const char **  errmsg,
int err 
) [static]

Definition at line 477 of file pex-unix.c.

{
  /* If we are cleaning up when the caller didn't retrieve process
     status for some reason, encourage the process to go away.  */
  if (done)
    kill (pid, SIGTERM);

  if (pex_wait (obj, pid, status, time) < 0)
    {
      *err = errno;
      *errmsg = "wait";
      return -1;
    }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static pid_t pex_wait ( struct pex_obj obj,
pid_t  pid,
int status,
struct pex_time time 
) [static]

Definition at line 183 of file pex-unix.c.

{
  struct status_list **pp;

  for (pp = (struct status_list **) &obj->sysdep;
       *pp != NULL;
       pp = &(*pp)->next)
    {
      if ((*pp)->pid == pid)
       {
         struct status_list *p;

         p = *pp;
         *status = p->status;
         if (time != NULL)
           *time = p->time;
         *pp = p->next;
         free (p);
         return pid;
       }
    }

  while (1)
    {
      pid_t cpid;
      struct status_list *psl;
      struct pex_time pt;
#ifdef HAVE_GETRUSAGE
      struct rusage r1, r2;
#endif

      if (time != NULL)
       {
#ifdef HAVE_GETRUSAGE
         getrusage (RUSAGE_CHILDREN, &r1);
#else
         memset (&pt, 0, sizeof (struct pex_time));
#endif
       }

      cpid = wait (status);

#ifdef HAVE_GETRUSAGE
      if (time != NULL && cpid >= 0)
       {
         getrusage (RUSAGE_CHILDREN, &r2);

         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;
         if (pt.user_microseconds < 0)
           {
             --pt.user_seconds;
             pt.user_microseconds += 1000000;
           }

         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;
         if (pt.system_microseconds < 0)
           {
             --pt.system_seconds;
             pt.system_microseconds += 1000000;
           }
       }
#endif

      if (cpid < 0 || cpid == pid)
       {
         if (time != NULL)
           *time = pt;
         return cpid;
       }

      psl = XNEW (struct status_list);
      psl->pid = cpid;
      psl->status = *status;
      if (time != NULL)
       psl->time = pt;
      psl->next = (struct status_list *) obj->sysdep;
      obj->sysdep = (void *) psl;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

char** environ