Back to index

glibc  2.9
Classes | Defines | Typedefs | Functions | Variables
iopopen.c File Reference
#include "libioP.h"

Go to the source code of this file.

Classes

struct  _IO_proc_file

Defines

#define _POSIX_SOURCE
#define _IO_dup2   dup2
#define _IO_waitpid   waitpid
#define _IO_execl   execl
#define _IO__exit   _exit
#define _IO_close   close

Typedefs

typedef struct _IO_proc_file

Functions

int _IO_dup2 (int fd, int fd2) __THROW
_IO_FILE_IO_new_proc_open (_IO_FILE *fp, const char *command, const char *mode)
_IO_FILE_IO_new_popen (char *command, const char *mode) const
int _IO_new_proc_close (_IO_FILE *fp)

Variables

static struct _IO_jump_t
static struct _IO_proc_fileproc_file_chain

Class Documentation

struct _IO_proc_file

Definition at line 92 of file iopopen.c.

Collaboration diagram for _IO_proc_file:
Class Members
struct _IO_proc_file * next
_IO_pid_t pid

Define Documentation

#define _IO__exit   _exit

Definition at line 81 of file iopopen.c.

#define _IO_close   close

Definition at line 88 of file iopopen.c.

#define _IO_dup2   dup2

Definition at line 64 of file iopopen.c.

#define _IO_execl   execl

Definition at line 78 of file iopopen.c.

#define _IO_waitpid   waitpid

Definition at line 73 of file iopopen.c.

#define _POSIX_SOURCE

Definition at line 31 of file iopopen.c.


Typedef Documentation

typedef struct _IO_proc_file

Definition at line 99 of file iopopen.c.


Function Documentation

int _IO_dup2 ( int  fd,
int  fd2 
)
_IO_FILE* _IO_new_popen ( char *  command,
const char *  mode 
) const

Definition at line 286 of file iopopen.c.

{
  struct locked_FILE
  {
    struct _IO_proc_file fpx;
#ifdef _IO_MTSAFE_IO
    _IO_lock_t lock;
#endif
  } *new_f;
  _IO_FILE *fp;

  new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
  if (new_f == NULL)
    return NULL;
#ifdef _IO_MTSAFE_IO
  new_f->fpx.file.file._lock = &new_f->lock;
#endif
  fp = &new_f->fpx.file.file;
  INTUSE(_IO_init) (fp, 0);
  _IO_JUMPS (&new_f->fpx.file) = &_IO_proc_jumps;
  _IO_new_file_init (&new_f->fpx.file);
#if  !_IO_UNIFIED_JUMPTABLES
  new_f->fpx.file.vtable = NULL;
#endif
  if (_IO_new_proc_open (fp, command, mode) != NULL)
    return (_IO_FILE *) &new_f->fpx.file;
  INTUSE(_IO_un_link) (&new_f->fpx.file);
  free (new_f);
  return NULL;
}

Here is the call graph for this function:

Definition at line 320 of file iopopen.c.

{
  /* This is not name-space clean. FIXME! */
#if _IO_HAVE_SYS_WAIT
  int wstatus;
  _IO_proc_file **ptr = &proc_file_chain;
  _IO_pid_t wait_pid;
  int status = -1;

  /* Unlink from proc_file_chain. */
#ifdef _IO_MTSAFE_IO
  _IO_cleanup_region_start_noarg (unlock);
  _IO_lock_lock (proc_file_chain_lock);
#endif
  for ( ; *ptr != NULL; ptr = &(*ptr)->next)
    {
      if (*ptr == (_IO_proc_file *) fp)
       {
         *ptr = (*ptr)->next;
         status = 0;
         break;
       }
    }
#ifdef _IO_MTSAFE_IO
  _IO_lock_unlock (proc_file_chain_lock);
  _IO_cleanup_region_end (0);
#endif

  if (status < 0 || _IO_close (_IO_fileno(fp)) < 0)
    return -1;
  /* POSIX.2 Rationale:  "Some historical implementations either block
     or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting
     for the child process to terminate.  Since this behavior is not
     described in POSIX.2, such implementations are not conforming." */
  do
    {
      wait_pid = _IO_waitpid (((_IO_proc_file *) fp)->pid, &wstatus, 0);
    }
  while (wait_pid == -1 && errno == EINTR);
  if (wait_pid == -1)
    return -1;
  return wstatus;
#else /* !_IO_HAVE_SYS_WAIT */
  return -1;
#endif
}
_IO_FILE* _IO_new_proc_open ( _IO_FILE fp,
const char *  command,
const char *  mode 
)

Definition at line 116 of file iopopen.c.

{
#if _IO_HAVE_SYS_WAIT
  int read_or_write;
  int parent_end, child_end;
  int pipe_fds[2];
  _IO_pid_t child_pid;

  int do_read = 0;
  int do_write = 0;
  int do_cloexec = 0;
  while (*mode != '\0')
    switch (*mode++)
      {
      case 'r':
       do_read = 1;
       break;
      case 'w':
       do_write = 1;
       break;
      case 'e':
       do_cloexec = 1;
       break;
      default:
      errout:
       __set_errno (EINVAL);
       return NULL;
      }

  if ((do_read ^ do_write) == 0)
    goto errout;

  if (_IO_file_is_open (fp))
    return NULL;

#ifdef O_CLOEXEC
# ifndef __ASSUME_PIPE2
  if (__have_pipe2 >= 0)
# endif
    {
      int r = __pipe2 (pipe_fds, O_CLOEXEC);
# ifndef __ASSUME_PIPE2
      if (__have_pipe2 == 0)
       __have_pipe2 = r != -1 || errno != ENOSYS ? 1 : -1;

      if (__have_pipe2 > 0)
# endif
       if (r < 0)
         return NULL;
    }
#endif
#ifndef __ASSUME_PIPE2
# ifdef O_CLOEXEC
  if (__have_pipe2 < 0)
# endif
    if (__pipe (pipe_fds) < 0)
      return NULL;
#endif

  if (do_read)
    {
      parent_end = pipe_fds[0];
      child_end = pipe_fds[1];
      read_or_write = _IO_NO_WRITES;
    }
  else
    {
      parent_end = pipe_fds[1];
      child_end = pipe_fds[0];
      read_or_write = _IO_NO_READS;
    }

  ((_IO_proc_file *) fp)->pid = child_pid = _IO_fork ();
  if (child_pid == 0)
    {
      int child_std_end = do_read ? 1 : 0;
      struct _IO_proc_file *p;

#ifndef __ASSUME_PIPE2
      /* If we have pipe2 the descriptor is marked for close-on-exec.  */
      _IO_close (parent_end);
#endif
      if (child_end != child_std_end)
       {
         _IO_dup2 (child_end, child_std_end);
#ifndef __ASSUME_PIPE2
         _IO_close (child_end);
#endif
       }
#ifdef O_CLOEXEC
      else
       {
         /* The descriptor is already the one we will use.  But it must
            not be marked close-on-exec.  Undo the effects.  */
# ifndef __ASSUME_PIPE2
         if (__have_pipe2 > 0)
# endif
           __fcntl (child_end, F_SETFD, 0);
       }
#endif
      /* POSIX.2:  "popen() shall ensure that any streams from previous
         popen() calls that remain open in the parent process are closed
        in the new child process." */
      for (p = proc_file_chain; p; p = p->next)
       {
         int fd = _IO_fileno ((_IO_FILE *) p);

         /* If any stream from previous popen() calls has fileno
            child_std_end, it has been already closed by the dup2 syscall
            above.  */
         if (fd != child_std_end)
           _IO_close (fd);
       }

      _IO_execl ("/bin/sh", "sh", "-c", command, (char *) 0);
      _IO__exit (127);
    }
  _IO_close (child_end);
  if (child_pid < 0)
    {
      _IO_close (parent_end);
      return NULL;
    }

  if (do_cloexec)
    {
#ifndef __ASSUME_PIPE2
# ifdef O_CLOEXEC
      if (__have_pipe2 < 0)
# endif
       __fcntl (parent_end, F_SETFD, FD_CLOEXEC);
#endif
    }
  else
    {
#ifdef O_CLOEXEC
      /* Undo the effects of the pipe2 call which set the
        close-on-exec flag.  */
# ifndef __ASSUME_PIPE2
      if (__have_pipe2 > 0)
# endif
       __fcntl (parent_end, F_SETFD, 0);
#endif
    }

  _IO_fileno (fp) = parent_end;

  /* Link into proc_file_chain. */
#ifdef _IO_MTSAFE_IO
  _IO_cleanup_region_start_noarg (unlock);
  _IO_lock_lock (proc_file_chain_lock);
#endif
  ((_IO_proc_file *) fp)->next = proc_file_chain;
  proc_file_chain = (_IO_proc_file *) fp;
#ifdef _IO_MTSAFE_IO
  _IO_lock_unlock (proc_file_chain_lock);
  _IO_cleanup_region_end (0);
#endif

  _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
  return fp;
#else /* !_IO_HAVE_SYS_WAIT */
  return NULL;
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

static struct _IO_jump_t [static]
struct _IO_proc_file* proc_file_chain [static]

Definition at line 103 of file iopopen.c.