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