|
|
1.1 root 1: /* @(#)popen.c 4.1 (Berkeley) 12/21/80 */
2: #include <stdio.h>
3: #include <signal.h>
4: #include <sys/param.h>
5:
6: #define MAXFORKS 20
7: #define tst(a,b) (*mode == 'r'? (b) : (a))
8: #define RDR 0
9: #define WTR 1
10:
11: struct a_fork {
12: short done;
13: short fd;
14: int pid;
15: int status;
16: };
17: static struct a_fork the_fork[MAXFORKS];
18:
19: static FILE *
20: _popen(cmd,mode,paranoid,args,env)
21: char *cmd;
22: char *mode;
23: int paranoid;
24: char **args, **env;
25: {
26: int p[2];
27: register myside, hisside, pid;
28: register i, ind;
29:
30: for (ind = 0; ind < MAXFORKS; ind++)
31: if (the_fork[ind].pid == 0)
32: break;
33: if (ind == MAXFORKS)
34: return NULL;
35: if(pipe(p) < 0)
36: return NULL;
37: myside = tst(p[WTR], p[RDR]);
38: hisside = tst(p[RDR], p[WTR]);
39: switch (pid = vfork()) {
40: case -1:
41: return NULL;
42: case 0:
43: /* myside and hisside reverse roles in child */
44: close(myside);
45: dup2(hisside, tst(0, 1));
46: if (paranoid!=2) {
47: /* a hack for "safety" against incautious SUIDs */
48: setuid(getuid());
49: setgid(getgid());
50: }
51: for (i=NSYSFILE; i<_NFILE; i++)
52: close(i);
53: if (paranoid==2)
54: execve(cmd, args, env);
55: else if (paranoid==1)
56: execl("/bin/sh", "sh", "-c", "-p", cmd, 0);
57: else
58: execl("/bin/sh", "sh", "-c", cmd, 0);
59: _exit(1);
60: default:
61: the_fork[ind].pid = pid;
62: the_fork[ind].fd = myside;
63: the_fork[ind].done = 0;
64: close(hisside);
65: return(fdopen(myside, mode));
66: }
67: }
68:
69: FILE *
70: popen(cmd,mode)
71: char *cmd;
72: char *mode;
73: {
74: return _popen(cmd, mode, 0, (char **)NULL, (char **)NULL);
75: }
76:
77: FILE *
78: ppopen(cmd,mode)
79: char *cmd;
80: char *mode;
81: {
82: return _popen(cmd, mode, 1, (char **)NULL, (char **)NULL);
83: }
84:
85: FILE *
86: vepopen(cmd,mode,args,env)
87: char *cmd;
88: char *mode;
89: char **args;
90: char **env;
91: {
92: return(_popen(cmd, mode, 2, args, env));
93: }
94:
95: pclose(ptr)
96: FILE *ptr;
97: {
98: register f, r, ind, (*hstat)(), (*istat)(), (*qstat)();
99: int status;
100:
101: f = fileno(ptr);
102: fclose(ptr);
103: for (ind = 0; ind < MAXFORKS; ind++)
104: if (the_fork[ind].fd == f && the_fork[ind].pid != 0)
105: break;
106: if (ind == MAXFORKS)
107: return 0;
108: if (!the_fork[ind].done) {
109: istat = signal(SIGINT, SIG_IGN);
110: qstat = signal(SIGQUIT, SIG_IGN);
111: hstat = signal(SIGHUP, SIG_IGN);
112: do {
113: r = wait(&status);
114: for (f = 0; f < MAXFORKS; f++)
115: if (the_fork[f].pid == r) {
116: the_fork[f].done = 1;
117: the_fork[f].status = status;
118: break;
119: }
120: } while(r != the_fork[ind].pid && r != -1);
121: the_fork[ind].status = r == -1 ? -1 : status;
122: signal(SIGINT, istat);
123: signal(SIGQUIT, qstat);
124: signal(SIGHUP, hstat);
125: }
126: the_fork[ind].pid = 0;
127: return (the_fork[ind].status);
128: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.