xref: /csrg-svn/lib/libc/gen/popen.c (revision 17345)
1*17345Slepreau /* @(#)popen.c	4.6 (Berkeley) 11/10/84 */
216676Ssam 
32024Swnj #include <stdio.h>
42024Swnj #include <signal.h>
5*17345Slepreau #include <sys/param.h>
616676Ssam 
72024Swnj #define	tst(a,b)	(*mode == 'r'? (b) : (a))
82024Swnj #define	RDR	0
92024Swnj #define	WTR	1
102024Swnj 
11*17345Slepreau static	int popen_pid[NOFILE];
1216676Ssam 
132024Swnj FILE *
142024Swnj popen(cmd,mode)
1516676Ssam 	char *cmd;
1616676Ssam 	char *mode;
172024Swnj {
182024Swnj 	int p[2];
1916676Ssam 	int myside, hisside, pid;
202024Swnj 
2116676Ssam 	if (pipe(p) < 0)
2216676Ssam 		return (NULL);
232024Swnj 	myside = tst(p[WTR], p[RDR]);
242024Swnj 	hisside = tst(p[RDR], p[WTR]);
2516676Ssam 	if ((pid = fork()) == 0) {
262024Swnj 		/* myside and hisside reverse roles in child */
272024Swnj 		close(myside);
2814718Ssam 		if (hisside != tst(0, 1)) {
2914718Ssam 			dup2(hisside, tst(0, 1));
3014718Ssam 			close(hisside);
3114718Ssam 		}
322024Swnj 		execl("/bin/sh", "sh", "-c", cmd, 0);
332024Swnj 		_exit(1);
342024Swnj 	}
3516676Ssam 	if (pid == -1) {
3615073Skarels 		close(myside);
3715073Skarels 		close(hisside);
3816676Ssam 		return (NULL);
3915073Skarels 	}
402024Swnj 	popen_pid[myside] = pid;
412024Swnj 	close(hisside);
4216676Ssam 	return (fdopen(myside, mode));
432024Swnj }
442024Swnj 
452024Swnj pclose(ptr)
4616676Ssam 	FILE *ptr;
472024Swnj {
4816676Ssam 	int child, pid, status, omask;
492024Swnj 
5016676Ssam 	child = popen_pid[fileno(ptr)];
512024Swnj 	fclose(ptr);
5216676Ssam #define	mask(s)	(1 << ((s)-1))
5316676Ssam 	omask = sigblock(mask(SIGINT)|mask(SIGQUIT)|mask(SIGHUP));
5416676Ssam 	while ((pid = wait(&status)) != child && pid != -1)
552024Swnj 		;
5616676Ssam 	(void) sigsetmask(omask);
5716676Ssam 	return (pid == -1 ? -1 : status);
582024Swnj }
59