1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <sys/types.h>
4 #include <unistd.h>
5 #include <sys/wait.h>
6
7 #define MAXFORKS 20
8 #define NSYSFILE 3
9 #define tst(a,b) (*mode == 'r'? (b) : (a))
10 #define RDR 0
11 #define WTR 1
12
13 struct a_fork {
14 short done;
15 short fd;
16 int pid;
17 int status;
18 };
19 static struct a_fork the_fork[MAXFORKS];
20
21 FILE *
popen(char * cmd,char * mode)22 popen(char *cmd, char *mode)
23 {
24 int p[2];
25 int myside, hisside, pid;
26 int i, ind;
27
28 for (ind = 0; ind < MAXFORKS; ind++)
29 if (the_fork[ind].pid == 0)
30 break;
31 if (ind == MAXFORKS)
32 return NULL;
33 if(pipe(p) < 0)
34 return NULL;
35 myside = tst(p[WTR], p[RDR]);
36 hisside = tst(p[RDR], p[WTR]);
37 switch (pid = fork()) {
38 case -1:
39 return NULL;
40 case 0:
41 /* myside and hisside reverse roles in child */
42 close(myside);
43 dup2(hisside, tst(0, 1));
44 for (i=NSYSFILE; i<FOPEN_MAX; i++)
45 close(i);
46 execl("/bin/ape/sh", "sh", "-c", cmd, NULL);
47 _exit(1);
48 default:
49 the_fork[ind].pid = pid;
50 the_fork[ind].fd = myside;
51 the_fork[ind].done = 0;
52 close(hisside);
53 return(fdopen(myside, mode));
54 }
55 }
56
57 int
pclose(FILE * ptr)58 pclose(FILE *ptr)
59 {
60 int f, r, ind;
61 int status;
62
63 f = fileno(ptr);
64 fclose(ptr);
65 for (ind = 0; ind < MAXFORKS; ind++)
66 if (the_fork[ind].fd == f && the_fork[ind].pid != 0)
67 break;
68 if (ind == MAXFORKS)
69 return 0;
70 if (!the_fork[ind].done) {
71 do {
72 r = wait(&status);
73 for (f = 0; f < MAXFORKS; f++)
74 if (the_fork[f].pid == r) {
75 the_fork[f].done = 1;
76 the_fork[f].status = status;
77 break;
78 }
79 } while(r != the_fork[ind].pid && r != -1);
80 the_fork[ind].status = r == -1 ? -1 : status;
81 }
82 the_fork[ind].pid = 0;
83 return (the_fork[ind].status);
84 }
85