minix/lib/libc/other/popen.c

123 lines
2.2 KiB
C

/*
* popen - open a pipe
*/
/* $Header$ */
#include <sys/types.h>
#include <limits.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#if defined(__BSD4_2)
union wait {
int w_status;
};
typedef union wait wait_arg;
#else
typedef int wait_arg;
#endif /* __BSD4_2 */
#include "../stdio/loc_incl.h"
#ifdef _ANSI
int _close(int d);
int _dup2(int oldd, int newd); /* not present in System 5 */
int _execl(const char *name, const char *_arg, ... );
pid_t _fork(void);
int _pipe(int fildes[2]);
pid_t _wait(wait_arg *status);
void _exit(int status);
#endif
static int pids[OPEN_MAX];
FILE *
popen(command, type)
_CONST char *command;
_CONST char *type;
{
int piped[2];
int Xtype = *type == 'r' ? 0 : *type == 'w' ? 1 : 2;
int pid;
if (Xtype == 2 ||
_pipe(piped) < 0 ||
(pid = _fork()) < 0) return 0;
if (pid == 0) {
/* child */
register int *p;
for (p = pids; p < &pids[OPEN_MAX]; p++) {
if (*p) _close((int)(p - pids));
}
_close(piped[Xtype]);
_dup2(piped[!Xtype], !Xtype);
_close(piped[!Xtype]);
_execl("/bin/sh", "sh", "-c", command, (char *) 0);
_exit(127); /* like system() ??? */
}
pids[piped[Xtype]] = pid;
_close(piped[!Xtype]);
return fdopen(piped[Xtype], type);
}
#if defined(__BSD4_2)
#define ret_val status.w_status
#else
#define ret_val status
#endif
int
pclose(stream)
FILE *stream;
{
int fd = fileno(stream);
wait_arg status;
int wret;
#ifdef _ANSI
void (*intsave)(int) = signal(SIGINT, SIG_IGN);
void (*quitsave)(int) = signal(SIGQUIT, SIG_IGN);
#else
void (*intsave)() = signal(SIGINT, SIG_IGN);
void (*quitsave)() = signal(SIGQUIT, SIG_IGN);
#endif
fclose(stream);
while ((wret = _wait(&status)) != -1) {
if (wret == pids[fd]) break;
}
if (wret == -1) ret_val = -1;
signal(SIGINT, intsave);
signal(SIGQUIT, quitsave);
pids[fd] = 0;
return ret_val;
}
#if defined(__USG)
int _dup(int fildes);
static int
_dup2(oldd, newd)
int oldd, newd;
{
int i = 0, fd, tmp;
int fdbuf[_NFILES];
/* ignore the error on the close() */
tmp = errno; (void) _close(newd); errno = tmp;
while ((fd = _dup(oldd)) != newd) {
if (fd == -1) break;
fdbuf[i++] = fd;
}
tmp = errno;
while (--i >= 0) {
_close(fdbuf[i]);
}
errno = tmp;
return -(fd == -1);
}
#endif /* __USG */