xref: /csrg-svn/libexec/ftpd/popen.c (revision 35675)
1*35675Sbostic /*
2*35675Sbostic  * Copyright (c) 1988 The Regents of the University of California.
3*35675Sbostic  * All rights reserved.
4*35675Sbostic  *
5*35675Sbostic  * This code is derived from software written by Ken Arnold and
6*35675Sbostic  * published in UNIX Review, Vol. 6, No. 8.
7*35675Sbostic  *
8*35675Sbostic  * Redistribution and use in source and binary forms are permitted
9*35675Sbostic  * provided that the above copyright notice and this paragraph are
10*35675Sbostic  * duplicated in all such forms and that any documentation,
11*35675Sbostic  * advertising materials, and other materials related to such
12*35675Sbostic  * distribution and use acknowledge that the software was developed
13*35675Sbostic  * by the University of California, Berkeley.  The name of the
14*35675Sbostic  * University may not be used to endorse or promote products derived
15*35675Sbostic  * from this software without specific prior written permission.
16*35675Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17*35675Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18*35675Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19*35675Sbostic  *
20*35675Sbostic  * static char sccsid[] = "@(#)popen.c	5.7 (Berkeley) 9/1/88";
21*35675Sbostic  */
22*35675Sbostic 
23*35675Sbostic #ifndef lint
24*35675Sbostic static char sccsid[] = "@(#)popen.c	5.1 (Berkeley) 09/22/88";
25*35675Sbostic #endif /* not lint */
26*35675Sbostic 
27*35675Sbostic #include <sys/param.h>
28*35675Sbostic #include <sys/signal.h>
29*35675Sbostic #include <sys/wait.h>
30*35675Sbostic #include <stdio.h>
31*35675Sbostic 
32*35675Sbostic static uid_t *pids;
33*35675Sbostic static int fds;
34*35675Sbostic 
35*35675Sbostic FILE *
36*35675Sbostic popen(program, type)
37*35675Sbostic 	char *program, *type;
38*35675Sbostic {
39*35675Sbostic 	FILE *iop;
40*35675Sbostic 	int pdes[2], pid;
41*35675Sbostic 	char *malloc();
42*35675Sbostic 
43*35675Sbostic 	if (*type != 'r' && *type != 'w' || type[1])
44*35675Sbostic 		return(NULL);
45*35675Sbostic 
46*35675Sbostic 	if (!pids) {
47*35675Sbostic 		if ((fds = getdtablesize()) <= 0)
48*35675Sbostic 			return(NULL);
49*35675Sbostic 		if (!(pids =
50*35675Sbostic 		    (uid_t *)malloc((u_int)(fds * sizeof(uid_t)))))
51*35675Sbostic 			return(NULL);
52*35675Sbostic 		bzero(pids, fds * sizeof(uid_t));
53*35675Sbostic 	}
54*35675Sbostic 	if (pipe(pdes) < 0)
55*35675Sbostic 		return(NULL);
56*35675Sbostic 	switch(pid = vfork()) {
57*35675Sbostic 	case -1:			/* error */
58*35675Sbostic 		(void)close(pdes[0]);
59*35675Sbostic 		(void)close(pdes[1]);
60*35675Sbostic 		return(NULL);
61*35675Sbostic 		/* NOTREACHED */
62*35675Sbostic 	case 0:				/* child */
63*35675Sbostic 		if (*type == 'r') {
64*35675Sbostic 			if (pdes[1] != 1) {
65*35675Sbostic 				dup2(pdes[1], 1);
66*35675Sbostic 				(void)close(pdes[1]);
67*35675Sbostic 			}
68*35675Sbostic 			(void)close(pdes[0]);
69*35675Sbostic 		} else {
70*35675Sbostic 			if (pdes[0] != 0) {
71*35675Sbostic 				dup2(pdes[0], 0);
72*35675Sbostic 				(void)close(pdes[0]);
73*35675Sbostic 			}
74*35675Sbostic 			(void)close(pdes[1]);
75*35675Sbostic 		}
76*35675Sbostic 		execl("/bin/sh", "sh", "-c", program, NULL);
77*35675Sbostic 		_exit(127);
78*35675Sbostic 		/* NOTREACHED */
79*35675Sbostic 	}
80*35675Sbostic 	/* parent; assume fdopen can't fail...  */
81*35675Sbostic 	if (*type == 'r') {
82*35675Sbostic 		iop = fdopen(pdes[0], type);
83*35675Sbostic 		(void)close(pdes[1]);
84*35675Sbostic 	} else {
85*35675Sbostic 		iop = fdopen(pdes[1], type);
86*35675Sbostic 		(void)close(pdes[0]);
87*35675Sbostic 	}
88*35675Sbostic 	pids[fileno(iop)] = pid;
89*35675Sbostic 	return(iop);
90*35675Sbostic }
91*35675Sbostic 
92*35675Sbostic pclose(iop)
93*35675Sbostic 	FILE *iop;
94*35675Sbostic {
95*35675Sbostic 	register int fdes;
96*35675Sbostic 	long omask;
97*35675Sbostic 	int stat_loc;
98*35675Sbostic 	pid_t waitpid();
99*35675Sbostic 
100*35675Sbostic 	/*
101*35675Sbostic 	 * pclose returns -1 if stream is not associated with a
102*35675Sbostic 	 * `popened' command, or, if already `pclosed'.
103*35675Sbostic 	 */
104*35675Sbostic 	if (pids[fdes = fileno(iop)] == 0)
105*35675Sbostic 		return(-1);
106*35675Sbostic 	(void)fclose(iop);
107*35675Sbostic 	omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
108*35675Sbostic 	stat_loc = waitpid(pids[fdes], &stat_loc, 0) == -1 ?
109*35675Sbostic 	    -1 : WEXITSTATUS(stat_loc);
110*35675Sbostic 	(void)sigsetmask(omask);
111*35675Sbostic 	pids[fdes] = 0;
112*35675Sbostic 	return(stat_loc);
113*35675Sbostic }
114