#include "libioP.h"
#if _IO_HAVE_SYS_WAIT
#include <signal.h>
#include <unistd.h>
#ifdef __STDC__
#include <stdlib.h>
#endif
#ifdef _LIBC
# include <unistd.h>
#endif
#include <sys/types.h>
#include <sys/wait.h>
#ifndef _IO_fork
#define _IO_fork vfork
extern _IO_pid_t _IO_fork __P ((void));
#endif
#endif
#ifndef _IO_pipe
#define _IO_pipe pipe
extern int _IO_pipe __P ((int des[2]));
#endif
#ifndef _IO_dup2
#define _IO_dup2 dup2
extern int _IO_dup2 __P ((int fd, int fd2));
#endif
#ifndef _IO_waitpid
#define _IO_waitpid waitpid
#endif
#ifndef _IO_execl
#define _IO_execl execl
#endif
#ifndef _IO__exit
#define _IO__exit _exit
#endif
#ifndef _IO_close
#define _IO_close close
#endif
struct _IO_proc_file
{
struct _IO_FILE_plus file;
_IO_pid_t pid;
struct _IO_proc_file *next;
};
typedef struct _IO_proc_file _IO_proc_file;
static struct _IO_proc_file *proc_file_chain = NULL;
_IO_FILE *
_IO_proc_open (fp, command, mode)
_IO_FILE *fp;
const char *command;
const char *mode;
{
#if _IO_HAVE_SYS_WAIT
volatile int read_or_write;
volatile int parent_end, child_end;
int pipe_fds[2];
_IO_pid_t child_pid;
if (_IO_file_is_open (fp))
return NULL;
if (_IO_pipe (pipe_fds) < 0)
return NULL;
if (mode[0] == 'r')
{
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 = mode[0] == 'r' ? 1 : 0;
_IO_close (parent_end);
if (child_end != child_std_end)
{
_IO_dup2 (child_end, child_std_end);
_IO_close (child_end);
}
while (proc_file_chain)
{
_IO_close (_IO_fileno ((_IO_FILE *) proc_file_chain));
proc_file_chain = proc_file_chain->next;
}
_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;
}
_IO_fileno (fp) = parent_end;
((_IO_proc_file *) fp)->next = proc_file_chain;
proc_file_chain = (_IO_proc_file *) fp;
_IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
return fp;
#else
return NULL;
#endif
}
_IO_FILE *
_IO_popen (command, mode)
const char *command;
const char *mode;
{
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 = (_IO_FILE*)&new_f->fpx;
_IO_init (fp, 0);
_IO_JUMPS (fp) = &_IO_proc_jumps;
_IO_file_init (fp);
#if !_IO_UNIFIED_JUMPTABLES
((struct _IO_FILE_plus *) fp)->vtable = NULL;
#endif
if (_IO_proc_open (fp, command, mode) != NULL)
return fp;
free (new_f);
return NULL;
}
#ifdef strong_alias
strong_alias (_IO_popen, popen);
#endif
int
_IO_proc_close (fp)
_IO_FILE *fp;
{
#if _IO_HAVE_SYS_WAIT
int wstatus;
_IO_proc_file **ptr = &proc_file_chain;
_IO_pid_t wait_pid;
int status = -1;
for ( ; *ptr != NULL; ptr = &(*ptr)->next)
{
if (*ptr == (_IO_proc_file *) fp)
{
*ptr = (*ptr)->next;
status = 0;
break;
}
}
if (status < 0 || _IO_close (_IO_fileno(fp)) < 0)
return -1;
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
return -1;
#endif
}
struct _IO_jump_t _IO_proc_jumps = {
JUMP_INIT_DUMMY,
JUMP_INIT(finish, _IO_file_finish),
JUMP_INIT(overflow, _IO_file_overflow),
JUMP_INIT(underflow, _IO_file_underflow),
JUMP_INIT(uflow, _IO_default_uflow),
JUMP_INIT(pbackfail, _IO_default_pbackfail),
JUMP_INIT(xsputn, _IO_file_xsputn),
JUMP_INIT(xsgetn, _IO_default_xsgetn),
JUMP_INIT(seekoff, _IO_file_seekoff),
JUMP_INIT(seekpos, _IO_default_seekpos),
JUMP_INIT(setbuf, _IO_file_setbuf),
JUMP_INIT(sync, _IO_file_sync),
JUMP_INIT(doallocate, _IO_file_doallocate),
JUMP_INIT(read, _IO_file_read),
JUMP_INIT(write, _IO_file_write),
JUMP_INIT(seek, _IO_file_seek),
JUMP_INIT(close, _IO_proc_close),
JUMP_INIT(stat, _IO_file_stat)
};