xref: /netbsd-src/libexec/ftpd/popen.c (revision f2192299b934b4a13516e0f2db3477282299b3c0)
1*f2192299Schristos /*	$NetBSD: popen.c,v 1.38 2016/03/17 00:17:58 christos Exp $	*/
221d03121Slukem 
321d03121Slukem /*-
40053962fSlukem  * Copyright (c) 1999-2009 The NetBSD Foundation, Inc.
521d03121Slukem  * All rights reserved.
621d03121Slukem  *
721d03121Slukem  * This code is derived from software contributed to The NetBSD Foundation
821d03121Slukem  * by Luke Mewburn.
921d03121Slukem  *
1021d03121Slukem  * Redistribution and use in source and binary forms, with or without
1121d03121Slukem  * modification, are permitted provided that the following conditions
1221d03121Slukem  * are met:
1321d03121Slukem  * 1. Redistributions of source code must retain the above copyright
1421d03121Slukem  *    notice, this list of conditions and the following disclaimer.
1521d03121Slukem  * 2. Redistributions in binary form must reproduce the above copyright
1621d03121Slukem  *    notice, this list of conditions and the following disclaimer in the
1721d03121Slukem  *    documentation and/or other materials provided with the distribution.
1821d03121Slukem  *
1921d03121Slukem  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2021d03121Slukem  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2121d03121Slukem  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2221d03121Slukem  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2321d03121Slukem  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2421d03121Slukem  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2521d03121Slukem  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2621d03121Slukem  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2721d03121Slukem  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2821d03121Slukem  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2921d03121Slukem  * POSSIBILITY OF SUCH DAMAGE.
3021d03121Slukem  */
316a991762Scgd 
3261f28255Scgd /*
33d6743f02Sderaadt  * Copyright (c) 1988, 1993, 1994
34d6743f02Sderaadt  *	The Regents of the University of California.  All rights reserved.
3561f28255Scgd  *
3661f28255Scgd  * This code is derived from software written by Ken Arnold and
3761f28255Scgd  * published in UNIX Review, Vol. 6, No. 8.
3861f28255Scgd  *
3961f28255Scgd  * Redistribution and use in source and binary forms, with or without
4061f28255Scgd  * modification, are permitted provided that the following conditions
4161f28255Scgd  * are met:
4261f28255Scgd  * 1. Redistributions of source code must retain the above copyright
4361f28255Scgd  *    notice, this list of conditions and the following disclaimer.
4461f28255Scgd  * 2. Redistributions in binary form must reproduce the above copyright
4561f28255Scgd  *    notice, this list of conditions and the following disclaimer in the
4661f28255Scgd  *    documentation and/or other materials provided with the distribution.
478e6ab883Sagc  * 3. Neither the name of the University nor the names of its contributors
4861f28255Scgd  *    may be used to endorse or promote products derived from this software
4961f28255Scgd  *    without specific prior written permission.
5061f28255Scgd  *
5161f28255Scgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
5261f28255Scgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5361f28255Scgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5461f28255Scgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
5561f28255Scgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5661f28255Scgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5761f28255Scgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5861f28255Scgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5961f28255Scgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
6061f28255Scgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6161f28255Scgd  * SUCH DAMAGE.
6261f28255Scgd  *
6361f28255Scgd  */
6461f28255Scgd 
652424c4f9Schristos #include <sys/cdefs.h>
6661f28255Scgd #ifndef lint
676a991762Scgd #if 0
68d6743f02Sderaadt static char sccsid[] = "@(#)popen.c	8.3 (Berkeley) 4/6/94";
696a991762Scgd #else
70*f2192299Schristos __RCSID("$NetBSD: popen.c,v 1.38 2016/03/17 00:17:58 christos Exp $");
716a991762Scgd #endif
7261f28255Scgd #endif /* not lint */
7361f28255Scgd 
7461f28255Scgd #include <sys/types.h>
75f318090cSlukem #include <sys/param.h>
7661f28255Scgd #include <sys/wait.h>
77d6743f02Sderaadt 
78d6743f02Sderaadt #include <errno.h>
79d6743f02Sderaadt #include <glob.h>
8061f28255Scgd #include <signal.h>
8161f28255Scgd #include <stdio.h>
8261f28255Scgd #include <stdlib.h>
8361f28255Scgd #include <string.h>
84397e2cfcSlukem #include <stringlist.h>
8525cf35a4Slukem #include <syslog.h>
86d6743f02Sderaadt #include <unistd.h>
87d6743f02Sderaadt 
88b2f939acSexplorer #ifdef KERBEROS5
89cee9ac24Schristos #include <krb5/krb5.h>
90b2f939acSexplorer #endif
91b2f939acSexplorer 
92d6743f02Sderaadt #include "extern.h"
9361f28255Scgd 
942424c4f9Schristos #define INCR	100
9561f28255Scgd /*
969c9d43e6Slukem  * Special version of popen which avoids call to shell.  This ensures no-one
9761f28255Scgd  * may create a pipe to a hidden program as a side effect of a list or dir
9861f28255Scgd  * command.
999c9d43e6Slukem  * If stderrfd != -1, then send stderr of a read command there,
1009c9d43e6Slukem  * otherwise close stderr.
10161f28255Scgd  */
10261f28255Scgd static int *pids;
10361f28255Scgd static int fds;
10461f28255Scgd 
105dcc88422Slukem extern int ls_main(int, char *[]);
10625cf35a4Slukem 
10761f28255Scgd FILE *
ftpd_popen(const char * argv[],const char * ptype,int stderrfd)1080053962fSlukem ftpd_popen(const char *argv[], const char *ptype, int stderrfd)
10961f28255Scgd {
110*f2192299Schristos 	FILE * volatile iop;
111fd6e8748Slukem 	int argc, pdes[2], pid;
112fd6e8748Slukem 	volatile int isls;
113397e2cfcSlukem 	char **pop;
114397e2cfcSlukem 	StringList *sl;
11561f28255Scgd 
116397e2cfcSlukem 	iop = NULL;
117397e2cfcSlukem 	isls = 0;
1183a491edaSlukem 	if ((*ptype != 'r' && *ptype != 'w') || ptype[1])
11961f28255Scgd 		return (NULL);
12061f28255Scgd 
12161f28255Scgd 	if (!pids) {
12261f28255Scgd 		if ((fds = getdtablesize()) <= 0)
12361f28255Scgd 			return (NULL);
124ef70558fSlukem 		if ((pids = (int *)malloc((unsigned int)(fds * sizeof(int)))) == NULL)
12561f28255Scgd 			return (NULL);
126d6743f02Sderaadt 		memset(pids, 0, fds * sizeof(int));
12761f28255Scgd 	}
12861f28255Scgd 	if (pipe(pdes) < 0)
12961f28255Scgd 		return (NULL);
13061f28255Scgd 
131397e2cfcSlukem 	if ((sl = sl_init()) == NULL)
1322424c4f9Schristos 		goto pfree;
13361f28255Scgd 
13461f28255Scgd 					/* glob each piece */
1351edbda9aSchristos 	if (sl_add(sl, ftpd_strdup(argv[0])) == -1)
136397e2cfcSlukem 		goto pfree;
137397e2cfcSlukem 	for (argc = 1; argv[argc]; argc++) {
138d6743f02Sderaadt 		glob_t gl;
13962f543d9Schristos 		int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_TILDE|GLOB_LIMIT;
140d6743f02Sderaadt 
141d6743f02Sderaadt 		memset(&gl, 0, sizeof(gl));
142692b0132Schristos 		if (glob(argv[argc], flags, NULL, &gl)
143692b0132Schristos 		    || gl.gl_pathv == NULL)  {
1441edbda9aSchristos 			if (sl_add(sl, ftpd_strdup(argv[argc])) == -1) {
14555dd4165Schristos 				globfree(&gl);
1462424c4f9Schristos 				goto pfree;
14755dd4165Schristos 			}
14855dd4165Schristos 		} else {
1492424c4f9Schristos 			for (pop = gl.gl_pathv; *pop; pop++) {
1501edbda9aSchristos 				if (sl_add(sl, ftpd_strdup(*pop)) == -1) {
15155dd4165Schristos 					globfree(&gl);
1522424c4f9Schristos 					goto pfree;
1532424c4f9Schristos 				}
15455dd4165Schristos 			}
15555dd4165Schristos 		}
156d6743f02Sderaadt 		globfree(&gl);
15761f28255Scgd 	}
158397e2cfcSlukem 	if (sl_add(sl, NULL) == -1)
159397e2cfcSlukem 		goto pfree;
16061f28255Scgd 
161be437fb5Slukem #ifndef NO_INTERNAL_LS
162397e2cfcSlukem 	isls = (strcmp(sl->sl_str[0], INTERNAL_LS) == 0);
163be437fb5Slukem #endif
16425cf35a4Slukem 
16525cf35a4Slukem 	pid = isls ? fork() : vfork();
16625cf35a4Slukem 	switch (pid) {
16761f28255Scgd 	case -1:			/* error */
16861f28255Scgd 		(void)close(pdes[0]);
16961f28255Scgd 		(void)close(pdes[1]);
17061f28255Scgd 		goto pfree;
17161f28255Scgd 		/* NOTREACHED */
17261f28255Scgd 	case 0:				/* child */
1733a491edaSlukem 		if (*ptype == 'r') {
174d6743f02Sderaadt 			if (pdes[1] != STDOUT_FILENO) {
175d6743f02Sderaadt 				dup2(pdes[1], STDOUT_FILENO);
17661f28255Scgd 				(void)close(pdes[1]);
17761f28255Scgd 			}
1789c9d43e6Slukem 			if (stderrfd == -1)
17931547ec6Slukem 				(void)close(STDERR_FILENO);
1809c9d43e6Slukem 			else
1819c9d43e6Slukem 				dup2(stderrfd, STDERR_FILENO);
18261f28255Scgd 			(void)close(pdes[0]);
18361f28255Scgd 		} else {
184d6743f02Sderaadt 			if (pdes[0] != STDIN_FILENO) {
185d6743f02Sderaadt 				dup2(pdes[0], STDIN_FILENO);
18661f28255Scgd 				(void)close(pdes[0]);
18761f28255Scgd 			}
18861f28255Scgd 			(void)close(pdes[1]);
18961f28255Scgd 		}
190be437fb5Slukem #ifndef NO_INTERNAL_LS
19125cf35a4Slukem 		if (isls) {	/* use internal ls */
19225cf35a4Slukem 			optreset = optind = optopt = 1;
19325cf35a4Slukem 			closelog();
194397e2cfcSlukem 			exit(ls_main(sl->sl_cur - 1, sl->sl_str));
19525cf35a4Slukem 		}
196be437fb5Slukem #endif
197be437fb5Slukem 
198397e2cfcSlukem 		execv(sl->sl_str[0], sl->sl_str);
19961f28255Scgd 		_exit(1);
20061f28255Scgd 	}
20161f28255Scgd 	/* parent; assume fdopen can't fail...  */
2023a491edaSlukem 	if (*ptype == 'r') {
2033a491edaSlukem 		iop = fdopen(pdes[0], ptype);
20461f28255Scgd 		(void)close(pdes[1]);
20561f28255Scgd 	} else {
2063a491edaSlukem 		iop = fdopen(pdes[1], ptype);
20761f28255Scgd 		(void)close(pdes[0]);
20861f28255Scgd 	}
20961f28255Scgd 	pids[fileno(iop)] = pid;
21061f28255Scgd 
21118be3cd9Slukem  pfree:
21218be3cd9Slukem 	if (sl)
213397e2cfcSlukem 		sl_free(sl, 1);
21461f28255Scgd 	return (iop);
21561f28255Scgd }
21661f28255Scgd 
217d6743f02Sderaadt int
ftpd_pclose(FILE * iop)218dcc88422Slukem ftpd_pclose(FILE *iop)
21961f28255Scgd {
22066783f1fSlukem 	int fdes, status;
221d6743f02Sderaadt 	pid_t pid;
222b3df6303Skleink 	sigset_t nsigset, osigset;
22361f28255Scgd 
22461f28255Scgd 	/*
22561f28255Scgd 	 * pclose returns -1 if stream is not associated with a
22661f28255Scgd 	 * `popened' command, or, if already `pclosed'.
22761f28255Scgd 	 */
22861f28255Scgd 	if (pids == 0 || pids[fdes = fileno(iop)] == 0)
22961f28255Scgd 		return (-1);
23061f28255Scgd 	(void)fclose(iop);
231b3df6303Skleink 	sigemptyset(&nsigset);
232b3df6303Skleink 	sigaddset(&nsigset, SIGINT);
233b3df6303Skleink 	sigaddset(&nsigset, SIGQUIT);
234b3df6303Skleink 	sigaddset(&nsigset, SIGHUP);
235b3df6303Skleink 	sigprocmask(SIG_BLOCK, &nsigset, &osigset);
236d6743f02Sderaadt 	while ((pid = waitpid(pids[fdes], &status, 0)) < 0 && errno == EINTR)
237d6743f02Sderaadt 		continue;
238ebeae88dSmycroft 	sigprocmask(SIG_SETMASK, &osigset, NULL);
23961f28255Scgd 	pids[fdes] = 0;
240d6743f02Sderaadt 	if (pid < 0)
241d6743f02Sderaadt 		return (pid);
242d6743f02Sderaadt 	if (WIFEXITED(status))
243d6743f02Sderaadt 		return (WEXITSTATUS(status));
244d6743f02Sderaadt 	return (1);
24561f28255Scgd }
246