1219b2ee8SDavid du Colombier #include <stdlib.h>
2219b2ee8SDavid du Colombier #include <stdio.h>
3219b2ee8SDavid du Colombier #include <sys/types.h>
4219b2ee8SDavid du Colombier #include <unistd.h>
5219b2ee8SDavid du Colombier #include <sys/wait.h>
6219b2ee8SDavid du Colombier
7219b2ee8SDavid du Colombier #define MAXFORKS 20
8219b2ee8SDavid du Colombier #define NSYSFILE 3
9219b2ee8SDavid du Colombier #define tst(a,b) (*mode == 'r'? (b) : (a))
10219b2ee8SDavid du Colombier #define RDR 0
11219b2ee8SDavid du Colombier #define WTR 1
12219b2ee8SDavid du Colombier
13219b2ee8SDavid du Colombier struct a_fork {
14219b2ee8SDavid du Colombier short done;
15219b2ee8SDavid du Colombier short fd;
16219b2ee8SDavid du Colombier int pid;
17219b2ee8SDavid du Colombier int status;
18219b2ee8SDavid du Colombier };
19219b2ee8SDavid du Colombier static struct a_fork the_fork[MAXFORKS];
20219b2ee8SDavid du Colombier
21219b2ee8SDavid du Colombier FILE *
popen(char * cmd,char * mode)22219b2ee8SDavid du Colombier popen(char *cmd, char *mode)
23219b2ee8SDavid du Colombier {
24219b2ee8SDavid du Colombier int p[2];
25219b2ee8SDavid du Colombier int myside, hisside, pid;
26219b2ee8SDavid du Colombier int i, ind;
27219b2ee8SDavid du Colombier
28219b2ee8SDavid du Colombier for (ind = 0; ind < MAXFORKS; ind++)
29219b2ee8SDavid du Colombier if (the_fork[ind].pid == 0)
30219b2ee8SDavid du Colombier break;
31219b2ee8SDavid du Colombier if (ind == MAXFORKS)
32219b2ee8SDavid du Colombier return NULL;
33219b2ee8SDavid du Colombier if(pipe(p) < 0)
34219b2ee8SDavid du Colombier return NULL;
35219b2ee8SDavid du Colombier myside = tst(p[WTR], p[RDR]);
36219b2ee8SDavid du Colombier hisside = tst(p[RDR], p[WTR]);
37219b2ee8SDavid du Colombier switch (pid = fork()) {
38219b2ee8SDavid du Colombier case -1:
39219b2ee8SDavid du Colombier return NULL;
40219b2ee8SDavid du Colombier case 0:
41219b2ee8SDavid du Colombier /* myside and hisside reverse roles in child */
42219b2ee8SDavid du Colombier close(myside);
43219b2ee8SDavid du Colombier dup2(hisside, tst(0, 1));
44219b2ee8SDavid du Colombier for (i=NSYSFILE; i<FOPEN_MAX; i++)
45219b2ee8SDavid du Colombier close(i);
46*f19e7b74SDavid du Colombier execl("/bin/ape/sh", "sh", "-c", cmd, NULL);
47219b2ee8SDavid du Colombier _exit(1);
48219b2ee8SDavid du Colombier default:
49219b2ee8SDavid du Colombier the_fork[ind].pid = pid;
50219b2ee8SDavid du Colombier the_fork[ind].fd = myside;
51219b2ee8SDavid du Colombier the_fork[ind].done = 0;
52219b2ee8SDavid du Colombier close(hisside);
53219b2ee8SDavid du Colombier return(fdopen(myside, mode));
54219b2ee8SDavid du Colombier }
55219b2ee8SDavid du Colombier }
56219b2ee8SDavid du Colombier
57219b2ee8SDavid du Colombier int
pclose(FILE * ptr)58219b2ee8SDavid du Colombier pclose(FILE *ptr)
59219b2ee8SDavid du Colombier {
60219b2ee8SDavid du Colombier int f, r, ind;
61219b2ee8SDavid du Colombier int status;
62219b2ee8SDavid du Colombier
63219b2ee8SDavid du Colombier f = fileno(ptr);
64219b2ee8SDavid du Colombier fclose(ptr);
65219b2ee8SDavid du Colombier for (ind = 0; ind < MAXFORKS; ind++)
66219b2ee8SDavid du Colombier if (the_fork[ind].fd == f && the_fork[ind].pid != 0)
67219b2ee8SDavid du Colombier break;
68219b2ee8SDavid du Colombier if (ind == MAXFORKS)
69219b2ee8SDavid du Colombier return 0;
70219b2ee8SDavid du Colombier if (!the_fork[ind].done) {
71219b2ee8SDavid du Colombier do {
72219b2ee8SDavid du Colombier r = wait(&status);
73219b2ee8SDavid du Colombier for (f = 0; f < MAXFORKS; f++)
74219b2ee8SDavid du Colombier if (the_fork[f].pid == r) {
75219b2ee8SDavid du Colombier the_fork[f].done = 1;
76219b2ee8SDavid du Colombier the_fork[f].status = status;
77219b2ee8SDavid du Colombier break;
78219b2ee8SDavid du Colombier }
79219b2ee8SDavid du Colombier } while(r != the_fork[ind].pid && r != -1);
80219b2ee8SDavid du Colombier the_fork[ind].status = r == -1 ? -1 : status;
81219b2ee8SDavid du Colombier }
82219b2ee8SDavid du Colombier the_fork[ind].pid = 0;
83219b2ee8SDavid du Colombier return (the_fork[ind].status);
84219b2ee8SDavid du Colombier }
85