xref: /csrg-svn/lib/libc/gen/popen.c (revision 26575)
122101Smckusick /*
222101Smckusick  * Copyright (c) 1980 Regents of the University of California.
322101Smckusick  * All rights reserved.  The Berkeley software License Agreement
422101Smckusick  * specifies the terms and conditions for redistribution.
522101Smckusick  */
616676Ssam 
7*26575Sdonn #if defined(LIBC_SCCS) && !defined(lint)
8*26575Sdonn static char sccsid[] = "@(#)popen.c	5.3 (Berkeley) 03/09/86";
9*26575Sdonn #endif LIBC_SCCS and not lint
1022101Smckusick 
112024Swnj #include <stdio.h>
122024Swnj #include <signal.h>
1317345Slepreau #include <sys/param.h>
1416676Ssam 
152024Swnj #define	tst(a,b)	(*mode == 'r'? (b) : (a))
162024Swnj #define	RDR	0
172024Swnj #define	WTR	1
182024Swnj 
1918246Sserge extern	char *malloc();
2016676Ssam 
2118246Sserge static	int *popen_pid;
2218246Sserge static	int nfiles;
2318246Sserge 
242024Swnj FILE *
252024Swnj popen(cmd,mode)
2616676Ssam 	char *cmd;
2716676Ssam 	char *mode;
282024Swnj {
292024Swnj 	int p[2];
3016676Ssam 	int myside, hisside, pid;
312024Swnj 
3218246Sserge 	if (nfiles <= 0)
3318246Sserge 		nfiles = getdtablesize();
3418246Sserge 	if (popen_pid == NULL) {
3518246Sserge 		popen_pid = (int *)malloc(nfiles * sizeof *popen_pid);
3618246Sserge 		if (popen_pid == NULL)
3718246Sserge 			return (NULL);
3818246Sserge 		for (pid = 0; pid < nfiles; pid++)
3918246Sserge 			popen_pid[pid] = -1;
4018246Sserge 	}
4116676Ssam 	if (pipe(p) < 0)
4216676Ssam 		return (NULL);
432024Swnj 	myside = tst(p[WTR], p[RDR]);
442024Swnj 	hisside = tst(p[RDR], p[WTR]);
4518246Sserge 	if ((pid = vfork()) == 0) {
462024Swnj 		/* myside and hisside reverse roles in child */
472024Swnj 		close(myside);
4814718Ssam 		if (hisside != tst(0, 1)) {
4914718Ssam 			dup2(hisside, tst(0, 1));
5014718Ssam 			close(hisside);
5114718Ssam 		}
5218246Sserge 		execl("/bin/sh", "sh", "-c", cmd, (char *)NULL);
5318246Sserge 		_exit(127);
542024Swnj 	}
5516676Ssam 	if (pid == -1) {
5615073Skarels 		close(myside);
5715073Skarels 		close(hisside);
5816676Ssam 		return (NULL);
5915073Skarels 	}
602024Swnj 	popen_pid[myside] = pid;
612024Swnj 	close(hisside);
6216676Ssam 	return (fdopen(myside, mode));
632024Swnj }
642024Swnj 
652024Swnj pclose(ptr)
6616676Ssam 	FILE *ptr;
672024Swnj {
6816676Ssam 	int child, pid, status, omask;
692024Swnj 
7016676Ssam 	child = popen_pid[fileno(ptr)];
7118246Sserge 	popen_pid[fileno(ptr)] = -1;
722024Swnj 	fclose(ptr);
7318246Sserge 	if (child == -1)
7418246Sserge 		return (-1);
7518246Sserge 	omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
7616676Ssam 	while ((pid = wait(&status)) != child && pid != -1)
772024Swnj 		;
7816676Ssam 	(void) sigsetmask(omask);
7916676Ssam 	return (pid == -1 ? -1 : status);
802024Swnj }
81