Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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 *
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
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
}