xref: /minix3/libexec/ftpd/popen.c (revision 62da011387586b019f85cdc44165baf17b9633da)
1*62da0113SBen Gras /*	$NetBSD: popen.c,v 1.37 2010/03/20 18:23:30 christos Exp $	*/
2*62da0113SBen Gras 
3*62da0113SBen Gras /*-
4*62da0113SBen Gras  * Copyright (c) 1999-2009 The NetBSD Foundation, Inc.
5*62da0113SBen Gras  * All rights reserved.
6*62da0113SBen Gras  *
7*62da0113SBen Gras  * This code is derived from software contributed to The NetBSD Foundation
8*62da0113SBen Gras  * by Luke Mewburn.
9*62da0113SBen Gras  *
10*62da0113SBen Gras  * Redistribution and use in source and binary forms, with or without
11*62da0113SBen Gras  * modification, are permitted provided that the following conditions
12*62da0113SBen Gras  * are met:
13*62da0113SBen Gras  * 1. Redistributions of source code must retain the above copyright
14*62da0113SBen Gras  *    notice, this list of conditions and the following disclaimer.
15*62da0113SBen Gras  * 2. Redistributions in binary form must reproduce the above copyright
16*62da0113SBen Gras  *    notice, this list of conditions and the following disclaimer in the
17*62da0113SBen Gras  *    documentation and/or other materials provided with the distribution.
18*62da0113SBen Gras  *
19*62da0113SBen Gras  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20*62da0113SBen Gras  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21*62da0113SBen Gras  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*62da0113SBen Gras  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23*62da0113SBen Gras  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*62da0113SBen Gras  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*62da0113SBen Gras  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*62da0113SBen Gras  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*62da0113SBen Gras  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*62da0113SBen Gras  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*62da0113SBen Gras  * POSSIBILITY OF SUCH DAMAGE.
30*62da0113SBen Gras  */
31*62da0113SBen Gras 
32*62da0113SBen Gras /*
33*62da0113SBen Gras  * Copyright (c) 1988, 1993, 1994
34*62da0113SBen Gras  *	The Regents of the University of California.  All rights reserved.
35*62da0113SBen Gras  *
36*62da0113SBen Gras  * This code is derived from software written by Ken Arnold and
37*62da0113SBen Gras  * published in UNIX Review, Vol. 6, No. 8.
38*62da0113SBen Gras  *
39*62da0113SBen Gras  * Redistribution and use in source and binary forms, with or without
40*62da0113SBen Gras  * modification, are permitted provided that the following conditions
41*62da0113SBen Gras  * are met:
42*62da0113SBen Gras  * 1. Redistributions of source code must retain the above copyright
43*62da0113SBen Gras  *    notice, this list of conditions and the following disclaimer.
44*62da0113SBen Gras  * 2. Redistributions in binary form must reproduce the above copyright
45*62da0113SBen Gras  *    notice, this list of conditions and the following disclaimer in the
46*62da0113SBen Gras  *    documentation and/or other materials provided with the distribution.
47*62da0113SBen Gras  * 3. Neither the name of the University nor the names of its contributors
48*62da0113SBen Gras  *    may be used to endorse or promote products derived from this software
49*62da0113SBen Gras  *    without specific prior written permission.
50*62da0113SBen Gras  *
51*62da0113SBen Gras  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52*62da0113SBen Gras  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53*62da0113SBen Gras  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54*62da0113SBen Gras  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55*62da0113SBen Gras  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56*62da0113SBen Gras  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57*62da0113SBen Gras  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58*62da0113SBen Gras  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59*62da0113SBen Gras  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60*62da0113SBen Gras  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61*62da0113SBen Gras  * SUCH DAMAGE.
62*62da0113SBen Gras  *
63*62da0113SBen Gras  */
64*62da0113SBen Gras 
65*62da0113SBen Gras #include <sys/cdefs.h>
66*62da0113SBen Gras #ifndef lint
67*62da0113SBen Gras #if 0
68*62da0113SBen Gras static char sccsid[] = "@(#)popen.c	8.3 (Berkeley) 4/6/94";
69*62da0113SBen Gras #else
70*62da0113SBen Gras __RCSID("$NetBSD: popen.c,v 1.37 2010/03/20 18:23:30 christos Exp $");
71*62da0113SBen Gras #endif
72*62da0113SBen Gras #endif /* not lint */
73*62da0113SBen Gras 
74*62da0113SBen Gras #include <sys/types.h>
75*62da0113SBen Gras #include <sys/param.h>
76*62da0113SBen Gras #include <sys/wait.h>
77*62da0113SBen Gras 
78*62da0113SBen Gras #include <errno.h>
79*62da0113SBen Gras #include <glob.h>
80*62da0113SBen Gras #include <signal.h>
81*62da0113SBen Gras #include <stdio.h>
82*62da0113SBen Gras #include <stdlib.h>
83*62da0113SBen Gras #include <string.h>
84*62da0113SBen Gras #include <stringlist.h>
85*62da0113SBen Gras #include <syslog.h>
86*62da0113SBen Gras #include <unistd.h>
87*62da0113SBen Gras 
88*62da0113SBen Gras #ifdef KERBEROS5
89*62da0113SBen Gras #include <krb5/krb5.h>
90*62da0113SBen Gras #endif
91*62da0113SBen Gras 
92*62da0113SBen Gras #include "extern.h"
93*62da0113SBen Gras 
94*62da0113SBen Gras #define INCR	100
95*62da0113SBen Gras /*
96*62da0113SBen Gras  * Special version of popen which avoids call to shell.  This ensures no-one
97*62da0113SBen Gras  * may create a pipe to a hidden program as a side effect of a list or dir
98*62da0113SBen Gras  * command.
99*62da0113SBen Gras  * If stderrfd != -1, then send stderr of a read command there,
100*62da0113SBen Gras  * otherwise close stderr.
101*62da0113SBen Gras  */
102*62da0113SBen Gras static int *pids;
103*62da0113SBen Gras static int fds;
104*62da0113SBen Gras 
105*62da0113SBen Gras extern int ls_main(int, char *[]);
106*62da0113SBen Gras 
107*62da0113SBen Gras FILE *
ftpd_popen(const char * argv[],const char * ptype,int stderrfd)108*62da0113SBen Gras ftpd_popen(const char *argv[], const char *ptype, int stderrfd)
109*62da0113SBen Gras {
110*62da0113SBen Gras 	FILE *iop;
111*62da0113SBen Gras 	int argc, pdes[2], pid;
112*62da0113SBen Gras 	volatile int isls;
113*62da0113SBen Gras 	char **pop;
114*62da0113SBen Gras 	StringList *sl;
115*62da0113SBen Gras 
116*62da0113SBen Gras 	iop = NULL;
117*62da0113SBen Gras 	isls = 0;
118*62da0113SBen Gras 	if ((*ptype != 'r' && *ptype != 'w') || ptype[1])
119*62da0113SBen Gras 		return (NULL);
120*62da0113SBen Gras 
121*62da0113SBen Gras 	if (!pids) {
122*62da0113SBen Gras 		if ((fds = getdtablesize()) <= 0)
123*62da0113SBen Gras 			return (NULL);
124*62da0113SBen Gras 		if ((pids = (int *)malloc((unsigned int)(fds * sizeof(int)))) == NULL)
125*62da0113SBen Gras 			return (NULL);
126*62da0113SBen Gras 		memset(pids, 0, fds * sizeof(int));
127*62da0113SBen Gras 	}
128*62da0113SBen Gras 	if (pipe(pdes) < 0)
129*62da0113SBen Gras 		return (NULL);
130*62da0113SBen Gras 
131*62da0113SBen Gras 	if ((sl = sl_init()) == NULL)
132*62da0113SBen Gras 		goto pfree;
133*62da0113SBen Gras 
134*62da0113SBen Gras 					/* glob each piece */
135*62da0113SBen Gras 	if (sl_add(sl, ftpd_strdup(argv[0])) == -1)
136*62da0113SBen Gras 		goto pfree;
137*62da0113SBen Gras 	for (argc = 1; argv[argc]; argc++) {
138*62da0113SBen Gras 		glob_t gl;
139*62da0113SBen Gras 		int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_TILDE|GLOB_LIMIT;
140*62da0113SBen Gras 
141*62da0113SBen Gras 		memset(&gl, 0, sizeof(gl));
142*62da0113SBen Gras 		if (glob(argv[argc], flags, NULL, &gl)
143*62da0113SBen Gras 		    || gl.gl_pathv == NULL)  {
144*62da0113SBen Gras 			if (sl_add(sl, ftpd_strdup(argv[argc])) == -1) {
145*62da0113SBen Gras 				globfree(&gl);
146*62da0113SBen Gras 				goto pfree;
147*62da0113SBen Gras 			}
148*62da0113SBen Gras 		} else {
149*62da0113SBen Gras 			for (pop = gl.gl_pathv; *pop; pop++) {
150*62da0113SBen Gras 				if (sl_add(sl, ftpd_strdup(*pop)) == -1) {
151*62da0113SBen Gras 					globfree(&gl);
152*62da0113SBen Gras 					goto pfree;
153*62da0113SBen Gras 				}
154*62da0113SBen Gras 			}
155*62da0113SBen Gras 		}
156*62da0113SBen Gras 		globfree(&gl);
157*62da0113SBen Gras 	}
158*62da0113SBen Gras 	if (sl_add(sl, NULL) == -1)
159*62da0113SBen Gras 		goto pfree;
160*62da0113SBen Gras 
161*62da0113SBen Gras #ifndef NO_INTERNAL_LS
162*62da0113SBen Gras 	isls = (strcmp(sl->sl_str[0], INTERNAL_LS) == 0);
163*62da0113SBen Gras #endif
164*62da0113SBen Gras 
165*62da0113SBen Gras 	pid = isls ? fork() : vfork();
166*62da0113SBen Gras 	switch (pid) {
167*62da0113SBen Gras 	case -1:			/* error */
168*62da0113SBen Gras 		(void)close(pdes[0]);
169*62da0113SBen Gras 		(void)close(pdes[1]);
170*62da0113SBen Gras 		goto pfree;
171*62da0113SBen Gras 		/* NOTREACHED */
172*62da0113SBen Gras 	case 0:				/* child */
173*62da0113SBen Gras 		if (*ptype == 'r') {
174*62da0113SBen Gras 			if (pdes[1] != STDOUT_FILENO) {
175*62da0113SBen Gras 				dup2(pdes[1], STDOUT_FILENO);
176*62da0113SBen Gras 				(void)close(pdes[1]);
177*62da0113SBen Gras 			}
178*62da0113SBen Gras 			if (stderrfd == -1)
179*62da0113SBen Gras 				(void)close(STDERR_FILENO);
180*62da0113SBen Gras 			else
181*62da0113SBen Gras 				dup2(stderrfd, STDERR_FILENO);
182*62da0113SBen Gras 			(void)close(pdes[0]);
183*62da0113SBen Gras 		} else {
184*62da0113SBen Gras 			if (pdes[0] != STDIN_FILENO) {
185*62da0113SBen Gras 				dup2(pdes[0], STDIN_FILENO);
186*62da0113SBen Gras 				(void)close(pdes[0]);
187*62da0113SBen Gras 			}
188*62da0113SBen Gras 			(void)close(pdes[1]);
189*62da0113SBen Gras 		}
190*62da0113SBen Gras #ifndef NO_INTERNAL_LS
191*62da0113SBen Gras 		if (isls) {	/* use internal ls */
192*62da0113SBen Gras 			optreset = optind = optopt = 1;
193*62da0113SBen Gras 			closelog();
194*62da0113SBen Gras 			exit(ls_main(sl->sl_cur - 1, sl->sl_str));
195*62da0113SBen Gras 		}
196*62da0113SBen Gras #endif
197*62da0113SBen Gras 
198*62da0113SBen Gras 		execv(sl->sl_str[0], sl->sl_str);
199*62da0113SBen Gras 		_exit(1);
200*62da0113SBen Gras 	}
201*62da0113SBen Gras 	/* parent; assume fdopen can't fail...  */
202*62da0113SBen Gras 	if (*ptype == 'r') {
203*62da0113SBen Gras 		iop = fdopen(pdes[0], ptype);
204*62da0113SBen Gras 		(void)close(pdes[1]);
205*62da0113SBen Gras 	} else {
206*62da0113SBen Gras 		iop = fdopen(pdes[1], ptype);
207*62da0113SBen Gras 		(void)close(pdes[0]);
208*62da0113SBen Gras 	}
209*62da0113SBen Gras 	pids[fileno(iop)] = pid;
210*62da0113SBen Gras 
211*62da0113SBen Gras  pfree:
212*62da0113SBen Gras 	if (sl)
213*62da0113SBen Gras 		sl_free(sl, 1);
214*62da0113SBen Gras 	return (iop);
215*62da0113SBen Gras }
216*62da0113SBen Gras 
217*62da0113SBen Gras int
ftpd_pclose(FILE * iop)218*62da0113SBen Gras ftpd_pclose(FILE *iop)
219*62da0113SBen Gras {
220*62da0113SBen Gras 	int fdes, status;
221*62da0113SBen Gras 	pid_t pid;
222*62da0113SBen Gras 	sigset_t nsigset, osigset;
223*62da0113SBen Gras 
224*62da0113SBen Gras 	/*
225*62da0113SBen Gras 	 * pclose returns -1 if stream is not associated with a
226*62da0113SBen Gras 	 * `popened' command, or, if already `pclosed'.
227*62da0113SBen Gras 	 */
228*62da0113SBen Gras 	if (pids == 0 || pids[fdes = fileno(iop)] == 0)
229*62da0113SBen Gras 		return (-1);
230*62da0113SBen Gras 	(void)fclose(iop);
231*62da0113SBen Gras 	sigemptyset(&nsigset);
232*62da0113SBen Gras 	sigaddset(&nsigset, SIGINT);
233*62da0113SBen Gras 	sigaddset(&nsigset, SIGQUIT);
234*62da0113SBen Gras 	sigaddset(&nsigset, SIGHUP);
235*62da0113SBen Gras 	sigprocmask(SIG_BLOCK, &nsigset, &osigset);
236*62da0113SBen Gras 	while ((pid = waitpid(pids[fdes], &status, 0)) < 0 && errno == EINTR)
237*62da0113SBen Gras 		continue;
238*62da0113SBen Gras 	sigprocmask(SIG_SETMASK, &osigset, NULL);
239*62da0113SBen Gras 	pids[fdes] = 0;
240*62da0113SBen Gras 	if (pid < 0)
241*62da0113SBen Gras 		return (pid);
242*62da0113SBen Gras 	if (WIFEXITED(status))
243*62da0113SBen Gras 		return (WEXITSTATUS(status));
244*62da0113SBen Gras 	return (1);
245*62da0113SBen Gras }
246