xref: /csrg-svn/lib/libc/gen/popen.c (revision 35458)
122101Smckusick /*
235451Sbostic  * Copyright (c) 1988 The Regents of the University of California.
335451Sbostic  * All rights reserved.
435451Sbostic  *
5*35458Sbostic  * This code is derived from software written by Ken Arnold and
6*35458Sbostic  * published in UNIX Review, Vol. 6, No. 8.
735451Sbostic  *
835451Sbostic  * Redistribution and use in source and binary forms are permitted
935451Sbostic  * provided that the above copyright notice and this paragraph are
1035451Sbostic  * duplicated in all such forms and that any documentation,
1135451Sbostic  * advertising materials, and other materials related to such
1235451Sbostic  * distribution and use acknowledge that the software was developed
1335451Sbostic  * by the University of California, Berkeley.  The name of the
1435451Sbostic  * University may not be used to endorse or promote products derived
1535451Sbostic  * from this software without specific prior written permission.
1635451Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1735451Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1835451Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1922101Smckusick  */
2016676Ssam 
2126575Sdonn #if defined(LIBC_SCCS) && !defined(lint)
22*35458Sbostic static char sccsid[] = "@(#)popen.c	5.7 (Berkeley) 09/01/88";
2335451Sbostic #endif /* LIBC_SCCS and not lint */
2422101Smckusick 
25*35458Sbostic #include <sys/param.h>
26*35458Sbostic #include <sys/signal.h>
27*35458Sbostic #include <sys/wait.h>
282024Swnj #include <stdio.h>
2916676Ssam 
30*35458Sbostic static uid_t *pids;
31*35458Sbostic static int fds;
322024Swnj 
332024Swnj FILE *
3435451Sbostic popen(program, type)
35*35458Sbostic 	char *program, *type;
362024Swnj {
37*35458Sbostic 	FILE *iop;
3835451Sbostic 	int pdes[2], pid;
39*35458Sbostic 	char *malloc();
402024Swnj 
41*35458Sbostic 	if (*type != 'r' && *type != 'w' || type[1])
42*35458Sbostic 		return(NULL);
43*35458Sbostic 
44*35458Sbostic 	if (!pids) {
45*35458Sbostic 		if ((fds = getdtablesize()) <= 0)
46*35458Sbostic 			return(NULL);
47*35458Sbostic 		if (!(pids =
48*35458Sbostic 		    (uid_t *)malloc((u_int)(fds * sizeof(uid_t)))))
49*35458Sbostic 			return(NULL);
50*35458Sbostic 		bzero(pids, fds * sizeof(uid_t));
51*35458Sbostic 	}
5235451Sbostic 	if (pipe(pdes) < 0)
53*35458Sbostic 		return(NULL);
54*35458Sbostic 	switch(pid = vfork()) {
55*35458Sbostic 	case -1:			/* error */
56*35458Sbostic 		(void)close(pdes[0]);
57*35458Sbostic 		(void)close(pdes[1]);
58*35458Sbostic 		return(NULL);
59*35458Sbostic 		/* NOTREACHED */
60*35458Sbostic 	case 0:				/* child */
6135451Sbostic 		if (*type == 'r') {
62*35458Sbostic 			if (pdes[1] != 1) {
63*35458Sbostic 				dup2(pdes[1], 1);
64*35458Sbostic 				(void)close(pdes[1]);
65*35458Sbostic 			}
66*35458Sbostic 			(void)close(pdes[0]);
67*35458Sbostic 		} else {
68*35458Sbostic 			if (pdes[0] != 0) {
69*35458Sbostic 				dup2(pdes[0], 0);
70*35458Sbostic 				(void)close(pdes[0]);
71*35458Sbostic 			}
72*35458Sbostic 			(void)close(pdes[1]);
7314718Ssam 		}
7435451Sbostic 		execl("/bin/sh", "sh", "-c", program, NULL);
75*35458Sbostic 		_exit(127);
7635451Sbostic 		/* NOTREACHED */
772024Swnj 	}
78*35458Sbostic 	/* parent; assume fdopen can't fail...  */
79*35458Sbostic 	if (*type == 'r') {
80*35458Sbostic 		iop = fdopen(pdes[0], type);
81*35458Sbostic 		(void)close(pdes[1]);
82*35458Sbostic 	} else {
83*35458Sbostic 		iop = fdopen(pdes[1], type);
84*35458Sbostic 		(void)close(pdes[0]);
8515073Skarels 	}
86*35458Sbostic 	pids[fileno(iop)] = pid;
87*35458Sbostic 	return(iop);
882024Swnj }
892024Swnj 
9035451Sbostic pclose(iop)
91*35458Sbostic 	FILE *iop;
922024Swnj {
93*35458Sbostic 	register int fdes;
94*35458Sbostic 	long omask;
95*35458Sbostic 	int stat_loc;
96*35458Sbostic 	pid_t waitpid();
972024Swnj 
98*35458Sbostic 	/*
99*35458Sbostic 	 * pclose returns -1 if stream is not associated with a
100*35458Sbostic 	 * `popened' command, or, if already `pclosed'.
101*35458Sbostic 	 */
102*35458Sbostic 	if (pids[fdes = fileno(iop)] == 0)
103*35458Sbostic 		return(-1);
104*35458Sbostic 	(void)fclose(iop);
105*35458Sbostic 	omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
106*35458Sbostic 	stat_loc = waitpid(pids[fdes], &stat_loc, 0) == -1 ?
107*35458Sbostic 	    -1 : WEXITSTATUS(stat_loc);
108*35458Sbostic 	(void)sigsetmask(omask);
109*35458Sbostic 	pids[fdes] = 0;
110*35458Sbostic 	return(stat_loc);
1112024Swnj }
112