xref: /csrg-svn/lib/libc/gen/popen.c (revision 16676)
1 /* @(#)popen.c	4.5 (Berkeley) 07/06/84 */
2 
3 #include <stdio.h>
4 #include <signal.h>
5 
6 #define	tst(a,b)	(*mode == 'r'? (b) : (a))
7 #define	RDR	0
8 #define	WTR	1
9 
10 static	int popen_pid[20];
11 
12 FILE *
13 popen(cmd,mode)
14 	char *cmd;
15 	char *mode;
16 {
17 	int p[2];
18 	int myside, hisside, pid;
19 
20 	if (pipe(p) < 0)
21 		return (NULL);
22 	myside = tst(p[WTR], p[RDR]);
23 	hisside = tst(p[RDR], p[WTR]);
24 	if ((pid = fork()) == 0) {
25 		/* myside and hisside reverse roles in child */
26 		close(myside);
27 		if (hisside != tst(0, 1)) {
28 			dup2(hisside, tst(0, 1));
29 			close(hisside);
30 		}
31 		execl("/bin/sh", "sh", "-c", cmd, 0);
32 		_exit(1);
33 	}
34 	if (pid == -1) {
35 		close(myside);
36 		close(hisside);
37 		return (NULL);
38 	}
39 	popen_pid[myside] = pid;
40 	close(hisside);
41 	return (fdopen(myside, mode));
42 }
43 
44 pclose(ptr)
45 	FILE *ptr;
46 {
47 	int child, pid, status, omask;
48 
49 	child = popen_pid[fileno(ptr)];
50 	fclose(ptr);
51 #define	mask(s)	(1 << ((s)-1))
52 	omask = sigblock(mask(SIGINT)|mask(SIGQUIT)|mask(SIGHUP));
53 	while ((pid = wait(&status)) != child && pid != -1)
54 		;
55 	(void) sigsetmask(omask);
56 	return (pid == -1 ? -1 : status);
57 }
58