xref: /csrg-svn/lib/libc/gen/popen.c (revision 18246)
1*18246Sserge /* @(#)popen.c	4.7 (Berkeley) 03/04/85 */
216676Ssam 
32024Swnj #include <stdio.h>
42024Swnj #include <signal.h>
517345Slepreau #include <sys/param.h>
616676Ssam 
72024Swnj #define	tst(a,b)	(*mode == 'r'? (b) : (a))
82024Swnj #define	RDR	0
92024Swnj #define	WTR	1
102024Swnj 
11*18246Sserge extern	char *malloc();
1216676Ssam 
13*18246Sserge static	int *popen_pid;
14*18246Sserge static	int nfiles;
15*18246Sserge 
162024Swnj FILE *
172024Swnj popen(cmd,mode)
1816676Ssam 	char *cmd;
1916676Ssam 	char *mode;
202024Swnj {
212024Swnj 	int p[2];
2216676Ssam 	int myside, hisside, pid;
232024Swnj 
24*18246Sserge 	if (nfiles <= 0)
25*18246Sserge 		nfiles = getdtablesize();
26*18246Sserge 	if (popen_pid == NULL) {
27*18246Sserge 		popen_pid = (int *)malloc(nfiles * sizeof *popen_pid);
28*18246Sserge 		if (popen_pid == NULL)
29*18246Sserge 			return (NULL);
30*18246Sserge 		for (pid = 0; pid < nfiles; pid++)
31*18246Sserge 			popen_pid[pid] = -1;
32*18246Sserge 	}
3316676Ssam 	if (pipe(p) < 0)
3416676Ssam 		return (NULL);
352024Swnj 	myside = tst(p[WTR], p[RDR]);
362024Swnj 	hisside = tst(p[RDR], p[WTR]);
37*18246Sserge 	if ((pid = vfork()) == 0) {
382024Swnj 		/* myside and hisside reverse roles in child */
392024Swnj 		close(myside);
4014718Ssam 		if (hisside != tst(0, 1)) {
4114718Ssam 			dup2(hisside, tst(0, 1));
4214718Ssam 			close(hisside);
4314718Ssam 		}
44*18246Sserge 		execl("/bin/sh", "sh", "-c", cmd, (char *)NULL);
45*18246Sserge 		_exit(127);
462024Swnj 	}
4716676Ssam 	if (pid == -1) {
4815073Skarels 		close(myside);
4915073Skarels 		close(hisside);
5016676Ssam 		return (NULL);
5115073Skarels 	}
522024Swnj 	popen_pid[myside] = pid;
532024Swnj 	close(hisside);
5416676Ssam 	return (fdopen(myside, mode));
552024Swnj }
562024Swnj 
572024Swnj pclose(ptr)
5816676Ssam 	FILE *ptr;
592024Swnj {
6016676Ssam 	int child, pid, status, omask;
612024Swnj 
6216676Ssam 	child = popen_pid[fileno(ptr)];
63*18246Sserge 	popen_pid[fileno(ptr)] = -1;
642024Swnj 	fclose(ptr);
65*18246Sserge 	if (child == -1)
66*18246Sserge 		return (-1);
67*18246Sserge 	omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
6816676Ssam 	while ((pid = wait(&status)) != child && pid != -1)
692024Swnj 		;
7016676Ssam 	(void) sigsetmask(omask);
7116676Ssam 	return (pid == -1 ? -1 : status);
722024Swnj }
73