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