xref: /csrg-svn/lib/libc/gen/popen.c (revision 16676)
1*16676Ssam /* @(#)popen.c	4.5 (Berkeley) 07/06/84 */
2*16676Ssam 
32024Swnj #include <stdio.h>
42024Swnj #include <signal.h>
5*16676Ssam 
62024Swnj #define	tst(a,b)	(*mode == 'r'? (b) : (a))
72024Swnj #define	RDR	0
82024Swnj #define	WTR	1
92024Swnj 
10*16676Ssam static	int popen_pid[20];
11*16676Ssam 
122024Swnj FILE *
132024Swnj popen(cmd,mode)
14*16676Ssam 	char *cmd;
15*16676Ssam 	char *mode;
162024Swnj {
172024Swnj 	int p[2];
18*16676Ssam 	int myside, hisside, pid;
192024Swnj 
20*16676Ssam 	if (pipe(p) < 0)
21*16676Ssam 		return (NULL);
222024Swnj 	myside = tst(p[WTR], p[RDR]);
232024Swnj 	hisside = tst(p[RDR], p[WTR]);
24*16676Ssam 	if ((pid = fork()) == 0) {
252024Swnj 		/* myside and hisside reverse roles in child */
262024Swnj 		close(myside);
2714718Ssam 		if (hisside != tst(0, 1)) {
2814718Ssam 			dup2(hisside, tst(0, 1));
2914718Ssam 			close(hisside);
3014718Ssam 		}
312024Swnj 		execl("/bin/sh", "sh", "-c", cmd, 0);
322024Swnj 		_exit(1);
332024Swnj 	}
34*16676Ssam 	if (pid == -1) {
3515073Skarels 		close(myside);
3615073Skarels 		close(hisside);
37*16676Ssam 		return (NULL);
3815073Skarels 	}
392024Swnj 	popen_pid[myside] = pid;
402024Swnj 	close(hisside);
41*16676Ssam 	return (fdopen(myside, mode));
422024Swnj }
432024Swnj 
442024Swnj pclose(ptr)
45*16676Ssam 	FILE *ptr;
462024Swnj {
47*16676Ssam 	int child, pid, status, omask;
482024Swnj 
49*16676Ssam 	child = popen_pid[fileno(ptr)];
502024Swnj 	fclose(ptr);
51*16676Ssam #define	mask(s)	(1 << ((s)-1))
52*16676Ssam 	omask = sigblock(mask(SIGINT)|mask(SIGQUIT)|mask(SIGHUP));
53*16676Ssam 	while ((pid = wait(&status)) != child && pid != -1)
542024Swnj 		;
55*16676Ssam 	(void) sigsetmask(omask);
56*16676Ssam 	return (pid == -1 ? -1 : status);
572024Swnj }
58