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 the above copyright notice and this paragraph are
10: * duplicated in all such forms and that any documentation,
11: * advertising materials, and other materials related to such
12: * distribution and use acknowledge that the software was developed
13: * by the University of California, Berkeley. The name of the
14: * University may not be used to endorse or promote products derived
15: * from this software without specific prior written permission.
16: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19: *
20: */
21:
22: #if !defined(lint) && defined(DOSCCS)
23: static char sccsid[] = "@(#)popen.c 5.7.1 (2.11BSD) 1999/10/25";
24: #endif
25:
26: #include <sys/types.h>
27: #include <sys/signal.h>
28: #include <sys/wait.h>
29: #include <stdio.h>
30: #include <string.h>
31:
32: /*
33: * Special version of popen which avoids call to shell. This insures noone
34: * may create a pipe to a hidden program as a side effect of a list or dir
35: * command.
36: */
37: static int *pids;
38: static int fds;
39:
40: FILE *
41: ftpd_popen(program, type)
42: char *program, *type;
43: {
44: register char *cp;
45: FILE *iop;
46: int argc, gargc, pdes[2], pid;
47: char **pop, *argv[100], *gargv[1000], *vv[2], **ppop, *endprogram;
48: extern char **glob(), **copyblk(), *malloc();
49:
50: if (*type != 'r' && *type != 'w' || type[1])
51: return(NULL);
52:
53: if (!pids) {
54: if ((fds = getdtablesize()) <= 0)
55: return(NULL);
56: if ((pids = (int *)malloc((u_int)(fds * sizeof(int)))) == NULL)
57: return(NULL);
58: bzero((char *)pids, fds * sizeof(int));
59: }
60: if (pipe(pdes) < 0)
61: return(NULL);
62: endprogram = program + strlen(program);
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: for (ppop = pop; *ppop != NULL; ppop++) {
78: if (*ppop >= program && *ppop <= endprogram) {
79: cp = (char *) malloc(strlen(*ppop) + 1);
80: strcpy(cp, *ppop);
81: *ppop = cp;
82: }
83: }
84: argv[argc] = (char *)pop; /* save to free later */
85: while (*pop && gargc < 1000)
86: gargv[gargc++] = *pop++;
87: }
88: gargv[gargc] = NULL;
89:
90: iop = NULL;
91: switch(pid = vfork()) {
92: case -1: /* error */
93: (void)close(pdes[0]);
94: (void)close(pdes[1]);
95: goto pfree;
96: /* NOTREACHED */
97: case 0: /* child */
98: if (*type == 'r') {
99: if (pdes[1] != 1) {
100: dup2(pdes[1], 1);
101: dup2(pdes[1], 2); /* stderr, too! */
102: (void)close(pdes[1]);
103: }
104: (void)close(pdes[0]);
105: } else {
106: if (pdes[0] != 0) {
107: dup2(pdes[0], 0);
108: (void)close(pdes[0]);
109: }
110: (void)close(pdes[1]);
111: }
112: execv(gargv[0], gargv);
113: _exit(1);
114: }
115: /* parent; assume fdopen can't fail... */
116: if (*type == 'r') {
117: iop = fdopen(pdes[0], type);
118: (void)close(pdes[1]);
119: } else {
120: iop = fdopen(pdes[1], type);
121: (void)close(pdes[0]);
122: }
123: pids[fileno(iop)] = pid;
124:
125: pfree: for (argc = 1; argv[argc] != NULL; argc++) {
126: blkfree((char **)argv[argc]);
127: free((char *)argv[argc]);
128: }
129: return(iop);
130: }
131:
132: ftpd_pclose(iop)
133: FILE *iop;
134: {
135: register int fdes;
136: sigset_t set;
137: union wait stat_loc;
138: int pid;
139:
140: /*
141: * pclose returns -1 if stream is not associated with a
142: * `popened' command, or, if already `pclosed'.
143: */
144: if (pids == 0 || pids[fdes = fileno(iop)] == 0)
145: return(-1);
146: (void)fclose(iop);
147: sigemptyset(&set);
148: sigaddset(&set, SIGINT);
149: sigaddset(&set, SIGQUIT);
150: sigaddset(&set, SIGHUP);
151: (void)sigprocmask(SIG_BLOCK, &set, NULL);
152: while ((pid = wait(&stat_loc)) != pids[fdes] && pid != -1);
153: (void)sigprocmask(SIG_UNBLOCK, &set, NULL);
154: pids[fdes] = 0;
155: return(pid == -1 ? -1 : stat_loc.w_status);
156: }
Defined functions
Defined variables
fds
defined in line
38; used 3 times
pids
defined in line
37; used 8 times