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