ack/lang/cem/libcc.ansi/misc/popen.c

120 lines
2 KiB
C
Raw Normal View History

1989-12-18 14:40:54 +00:00
/*
* popen - open a pipe
*/
1994-06-24 14:02:31 +00:00
/* $Id$ */
1989-12-18 14:40:54 +00:00
2018-06-21 20:33:47 +00:00
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#if defined(__BSD4_2)
1989-12-18 14:40:54 +00:00
union wait {
2018-06-21 20:33:47 +00:00
int w_status;
1989-12-18 14:40:54 +00:00
};
typedef union wait wait_arg;
#else
typedef int wait_arg;
2018-06-21 20:33:47 +00:00
#endif /* __BSD4_2 */
#include "../stdio/loc_incl.h"
1989-12-18 14:40:54 +00:00
int _close(int d);
#if defined(__USG)
static
#endif
2018-06-21 20:33:47 +00:00
int
_dup2(int oldd, int newd); /* not present in System 5 */
int _execl(const char* name, ...);
int _fork(void);
int _pipe(int fildes[2]);
2018-06-21 20:33:47 +00:00
int _wait(wait_arg* status);
1989-12-18 14:40:54 +00:00
void _exit(int status);
static int pids[FOPEN_MAX];
1989-12-18 14:40:54 +00:00
2018-06-21 20:33:47 +00:00
FILE* popen(const char* command, const char* type)
1989-12-18 14:40:54 +00:00
{
int piped[2];
int Xtype = *type == 'r' ? 0 : *type == 'w' ? 1 : 2;
int pid;
2018-06-21 20:33:47 +00:00
if (Xtype == 2 || _pipe(piped) < 0 || (pid = _fork()) < 0)
return 0;
if (pid == 0)
{
1989-12-18 14:40:54 +00:00
/* child */
2018-06-21 20:33:47 +00:00
register int* p;
1989-12-18 14:40:54 +00:00
2018-06-21 20:33:47 +00:00
for (p = pids; p < &pids[FOPEN_MAX]; p++)
{
if (*p)
_close(p - pids);
1989-12-18 14:40:54 +00:00
}
_close(piped[Xtype]);
_dup2(piped[!Xtype], !Xtype);
_close(piped[!Xtype]);
2018-06-21 20:33:47 +00:00
_execl("/bin/sh", "sh", "-c", command, (char*)0);
_exit(127); /* like system() ??? */
1989-12-18 14:40:54 +00:00
}
pids[piped[Xtype]] = pid;
_close(piped[!Xtype]);
1989-12-18 14:40:54 +00:00
return fdopen(piped[Xtype], type);
}
2018-06-21 20:33:47 +00:00
#if defined(__BSD4_2)
#define ret_val status.w_status
1989-12-18 14:40:54 +00:00
#else
2018-06-21 20:33:47 +00:00
#define ret_val status
1989-12-18 14:40:54 +00:00
#endif
2018-06-21 20:33:47 +00:00
int pclose(FILE* stream)
1989-12-18 14:40:54 +00:00
{
int fd = fileno(stream);
wait_arg status;
int wret;
void (*intsave)(int) = signal(SIGINT, SIG_IGN);
void (*quitsave)(int) = signal(SIGQUIT, SIG_IGN);
fclose(stream);
2018-06-21 20:33:47 +00:00
while ((wret = _wait(&status)) != -1)
{
if (wret == pids[fd])
break;
1989-12-18 14:40:54 +00:00
}
2018-06-21 20:33:47 +00:00
if (wret == -1)
ret_val = -1;
1989-12-18 14:40:54 +00:00
signal(SIGINT, intsave);
signal(SIGQUIT, quitsave);
pids[fd] = 0;
return ret_val;
}
2018-06-21 20:33:47 +00:00
#if defined(__USG)
int _dup(int fildes);
static int
_dup2(int oldd, int newd)
1989-12-18 14:40:54 +00:00
{
int i = 0, fd, tmp;
int fdbuf[FOPEN_MAX];
1989-12-18 14:40:54 +00:00
/* ignore the error on the close() */
2018-06-21 20:33:47 +00:00
tmp = errno;
(void)_close(newd);
errno = tmp;
while ((fd = _dup(oldd)) != newd)
{
if (fd == -1)
break;
1989-12-18 14:40:54 +00:00
fdbuf[i++] = fd;
}
tmp = errno;
2018-06-21 20:33:47 +00:00
while (--i >= 0)
{
_close(fdbuf[i]);
1989-12-18 14:40:54 +00:00
}
errno = tmp;
return -(fd == -1);
}
2018-06-21 20:33:47 +00:00
#endif /* __USG */