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