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