4.3BSD beta release manual page
[unix-history] / usr / src / lib / libc / gen / popen.c
CommitLineData
fec6f225 1/* @(#)popen.c 4.7 (Berkeley) %G% */
99756664 2
01a56307
BJ
3#include <stdio.h>
4#include <signal.h>
43d12555 5#include <sys/param.h>
99756664 6
01a56307
BJ
7#define tst(a,b) (*mode == 'r'? (b) : (a))
8#define RDR 0
9#define WTR 1
99756664 10
fec6f225
S
11extern char *malloc();
12
13static int *popen_pid;
14static int nfiles;
01a56307
BJ
15
16FILE *
17popen(cmd,mode)
99756664
SL
18 char *cmd;
19 char *mode;
01a56307
BJ
20{
21 int p[2];
99756664 22 int myside, hisside, pid;
01a56307 23
fec6f225
S
24 if (nfiles <= 0)
25 nfiles = getdtablesize();
26 if (popen_pid == NULL) {
27 popen_pid = (int *)malloc(nfiles * sizeof *popen_pid);
28 if (popen_pid == NULL)
29 return (NULL);
30 for (pid = 0; pid < nfiles; pid++)
31 popen_pid[pid] = -1;
32 }
99756664
SL
33 if (pipe(p) < 0)
34 return (NULL);
01a56307
BJ
35 myside = tst(p[WTR], p[RDR]);
36 hisside = tst(p[RDR], p[WTR]);
fec6f225 37 if ((pid = vfork()) == 0) {
01a56307
BJ
38 /* myside and hisside reverse roles in child */
39 close(myside);
482b978e
SL
40 if (hisside != tst(0, 1)) {
41 dup2(hisside, tst(0, 1));
42 close(hisside);
43 }
fec6f225
S
44 execl("/bin/sh", "sh", "-c", cmd, (char *)NULL);
45 _exit(127);
01a56307 46 }
99756664 47 if (pid == -1) {
2337e291
MK
48 close(myside);
49 close(hisside);
99756664 50 return (NULL);
2337e291 51 }
01a56307
BJ
52 popen_pid[myside] = pid;
53 close(hisside);
99756664 54 return (fdopen(myside, mode));
01a56307
BJ
55}
56
57pclose(ptr)
99756664 58 FILE *ptr;
01a56307 59{
99756664 60 int child, pid, status, omask;
01a56307 61
99756664 62 child = popen_pid[fileno(ptr)];
fec6f225 63 popen_pid[fileno(ptr)] = -1;
01a56307 64 fclose(ptr);
fec6f225
S
65 if (child == -1)
66 return (-1);
67 omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
99756664 68 while ((pid = wait(&status)) != child && pid != -1)
01a56307 69 ;
99756664
SL
70 (void) sigsetmask(omask);
71 return (pid == -1 ? -1 : status);
01a56307 72}