|
|
1.1 root 1: /*
2: * Copyright (c) 1988 The Regents of the University of California.
3: * All rights reserved.
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 are permitted
9: * provided that: (1) source distributions retain this entire copyright
10: * notice and comment, and (2) distributions including binaries display
11: * the following acknowledgement: ``This product includes software
12: * developed by the University of California, Berkeley and its contributors''
13: * in the documentation or other materials provided with the distribution
14: * and in all advertising materials mentioning features or use of this
15: * software. Neither the name of the University nor the names of its
16: * contributors may be used to endorse or promote products derived
17: * from this software without specific prior written permission.
18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21: *
22: */
23:
24: #ifndef lint
25: static char sccsid[] = "@(#)popen.c 5.8 (Berkeley) 6/1/90";
26: #endif /* not lint */
27:
28: #include <sys/types.h>
29: #include <sys/signal.h>
30: #include <sys/wait.h>
31: #include <stdio.h>
32:
33: /*
34: * Special version of popen which avoids call to shell. This insures noone
35: * may create a pipe to a hidden program as a side effect of a list or dir
36: * command.
37: */
38: static int *pids;
39: static int fds;
40:
41: FILE *
42: ftpd_popen(program, type)
43: char *program, *type;
44: {
45: register char *cp;
46: FILE *iop;
47: int argc, gargc, pdes[2], pid;
48: char **pop, *argv[100], *gargv[1000], *vv[2];
49: extern char **glob(), **copyblk(), *strtok(), *malloc();
50:
51: if (*type != 'r' && *type != 'w' || type[1])
52: return(NULL);
53:
54: if (!pids) {
55: if ((fds = getdtablesize()) <= 0)
56: return(NULL);
57: if ((pids = (int *)malloc((u_int)(fds * sizeof(int)))) == NULL)
58: return(NULL);
59: bzero((char *)pids, fds * sizeof(int));
60: }
61: if (pipe(pdes) < 0)
62: return(NULL);
63:
64: /* break up string into pieces */
65: for (argc = 0, cp = program;; cp = NULL)
66: if (!(argv[argc++] = strtok(cp, " \t\n")))
67: break;
68:
69: /* glob each piece */
70: gargv[0] = argv[0];
71: for (gargc = argc = 1; argv[argc]; argc++) {
72: if (!(pop = glob(argv[argc]))) { /* globbing failed */
73: vv[0] = argv[argc];
74: vv[1] = NULL;
75: pop = copyblk(vv);
76: }
77: argv[argc] = (char *)pop; /* save to free later */
78: while (*pop && gargc < 1000)
79: gargv[gargc++] = *pop++;
80: }
81: gargv[gargc] = NULL;
82:
83: iop = NULL;
84: switch(pid = vfork()) {
85: case -1: /* error */
86: (void)close(pdes[0]);
87: (void)close(pdes[1]);
88: goto pfree;
89: /* NOTREACHED */
90: case 0: /* child */
91: if (*type == 'r') {
92: if (pdes[1] != 1) {
93: dup2(pdes[1], 1);
94: dup2(pdes[1], 2); /* stderr, too! */
95: (void)close(pdes[1]);
96: }
97: (void)close(pdes[0]);
98: } else {
99: if (pdes[0] != 0) {
100: dup2(pdes[0], 0);
101: (void)close(pdes[0]);
102: }
103: (void)close(pdes[1]);
104: }
105: execv(gargv[0], gargv);
106: _exit(1);
107: }
108: /* parent; assume fdopen can't fail... */
109: if (*type == 'r') {
110: iop = fdopen(pdes[0], type);
111: (void)close(pdes[1]);
112: } else {
113: iop = fdopen(pdes[1], type);
114: (void)close(pdes[0]);
115: }
116: pids[fileno(iop)] = pid;
117:
118: pfree: for (argc = 1; argv[argc] != NULL; argc++) {
119: blkfree((char **)argv[argc]);
120: free((char *)argv[argc]);
121: }
122: return(iop);
123: }
124:
125: ftpd_pclose(iop)
126: FILE *iop;
127: {
128: register int fdes;
129: int omask;
130: union wait stat_loc;
131: int pid;
132:
133: /*
134: * pclose returns -1 if stream is not associated with a
135: * `popened' command, or, if already `pclosed'.
136: */
137: if (pids == 0 || pids[fdes = fileno(iop)] == 0)
138: return(-1);
139: (void)fclose(iop);
140: omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
141: while ((pid = wait(&stat_loc)) != pids[fdes] && pid != -1);
142: (void)sigsetmask(omask);
143: pids[fdes] = 0;
144: return(pid == -1 ? -1 : stat_loc.w_status);
145: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.