Commit | Line | Data |
---|---|---|
96c0abd0 | 1 | /* |
94ae9fca | 2 | * Copyright (c) 1988, 1993, 1994 |
065e054f | 3 | * The Regents of the University of California. All rights reserved. |
96c0abd0 KB |
4 | * |
5 | * This code is derived from software written by Ken Arnold and | |
6 | * published in UNIX Review, Vol. 6, No. 8. | |
7 | * | |
1343342a | 8 | * %sccs.include.redist.c% |
96c0abd0 | 9 | * |
96c0abd0 KB |
10 | */ |
11 | ||
12 | #ifndef lint | |
94ae9fca | 13 | static char sccsid[] = "@(#)popen.c 8.2 (Berkeley) %G%"; |
96c0abd0 KB |
14 | #endif /* not lint */ |
15 | ||
5f3a5fe7 | 16 | #include <sys/types.h> |
882508af | 17 | #include <sys/wait.h> |
60de319b | 18 | |
94ae9fca JSP |
19 | #include <errno.h> |
20 | #include <glob.h> | |
5bb0ca89 | 21 | #include <signal.h> |
96c0abd0 | 22 | #include <stdio.h> |
5bb0ca89 KB |
23 | #include <stdlib.h> |
24 | #include <string.h> | |
94ae9fca JSP |
25 | #include <unistd.h> |
26 | ||
60de319b | 27 | #include "extern.h" |
96c0abd0 | 28 | |
5f3a5fe7 | 29 | /* |
94ae9fca | 30 | * Special version of popen which avoids call to shell. This ensures noone |
5f3a5fe7 KB |
31 | * may create a pipe to a hidden program as a side effect of a list or dir |
32 | * command. | |
33 | */ | |
882508af | 34 | static int *pids; |
96c0abd0 KB |
35 | static int fds; |
36 | ||
37 | FILE * | |
5256bbac | 38 | ftpd_popen(program, type) |
96c0abd0 KB |
39 | char *program, *type; |
40 | { | |
94ae9fca | 41 | char *cp; |
96c0abd0 | 42 | FILE *iop; |
5f3a5fe7 | 43 | int argc, gargc, pdes[2], pid; |
94ae9fca | 44 | char **pop, *argv[100], *gargv[1000]; |
96c0abd0 KB |
45 | |
46 | if (*type != 'r' && *type != 'w' || type[1]) | |
94ae9fca | 47 | return (NULL); |
96c0abd0 KB |
48 | |
49 | if (!pids) { | |
50 | if ((fds = getdtablesize()) <= 0) | |
94ae9fca | 51 | return (NULL); |
882508af | 52 | if ((pids = (int *)malloc((u_int)(fds * sizeof(int)))) == NULL) |
94ae9fca | 53 | return (NULL); |
b14598e8 | 54 | memset(pids, 0, fds * sizeof(int)); |
96c0abd0 KB |
55 | } |
56 | if (pipe(pdes) < 0) | |
94ae9fca | 57 | return (NULL); |
5f3a5fe7 KB |
58 | |
59 | /* break up string into pieces */ | |
60 | for (argc = 0, cp = program;; cp = NULL) | |
61 | if (!(argv[argc++] = strtok(cp, " \t\n"))) | |
62 | break; | |
63 | ||
64 | /* glob each piece */ | |
65 | gargv[0] = argv[0]; | |
66 | for (gargc = argc = 1; argv[argc]; argc++) { | |
94ae9fca JSP |
67 | glob_t gl; |
68 | int flags = GLOB_BRACE|GLOB_QUOTE|GLOB_TILDE; | |
69 | ||
70 | memset(&gl, 0, sizeof(gl)); | |
71 | if (glob(argv[argc], flags, NULL, &gl)) | |
72 | gargv[gargc++] = strdup(argv[argc]); | |
73 | else | |
74 | for (pop = gl.gl_pathv; *pop; pop++) | |
75 | gargv[gargc++] = strdup(*pop); | |
76 | globfree(&gl); | |
5f3a5fe7 KB |
77 | } |
78 | gargv[gargc] = NULL; | |
79 | ||
80 | iop = NULL; | |
96c0abd0 KB |
81 | switch(pid = vfork()) { |
82 | case -1: /* error */ | |
83 | (void)close(pdes[0]); | |
84 | (void)close(pdes[1]); | |
97f47643 | 85 | goto pfree; |
96c0abd0 KB |
86 | /* NOTREACHED */ |
87 | case 0: /* child */ | |
88 | if (*type == 'r') { | |
94ae9fca JSP |
89 | if (pdes[1] != STDOUT_FILENO) { |
90 | dup2(pdes[1], STDOUT_FILENO); | |
96c0abd0 KB |
91 | (void)close(pdes[1]); |
92 | } | |
94ae9fca | 93 | dup2(STDOUT_FILENO, STDERR_FILENO); /* stderr too! */ |
96c0abd0 KB |
94 | (void)close(pdes[0]); |
95 | } else { | |
94ae9fca JSP |
96 | if (pdes[0] != STDIN_FILENO) { |
97 | dup2(pdes[0], STDIN_FILENO); | |
96c0abd0 KB |
98 | (void)close(pdes[0]); |
99 | } | |
100 | (void)close(pdes[1]); | |
101 | } | |
5f3a5fe7 KB |
102 | execv(gargv[0], gargv); |
103 | _exit(1); | |
96c0abd0 KB |
104 | } |
105 | /* parent; assume fdopen can't fail... */ | |
106 | if (*type == 'r') { | |
107 | iop = fdopen(pdes[0], type); | |
108 | (void)close(pdes[1]); | |
109 | } else { | |
110 | iop = fdopen(pdes[1], type); | |
111 | (void)close(pdes[0]); | |
112 | } | |
113 | pids[fileno(iop)] = pid; | |
5f3a5fe7 | 114 | |
94ae9fca JSP |
115 | pfree: for (argc = 1; gargv[argc] != NULL; argc++) |
116 | free(gargv[argc]); | |
117 | ||
118 | return (iop); | |
96c0abd0 KB |
119 | } |
120 | ||
60de319b | 121 | int |
882508af | 122 | ftpd_pclose(iop) |
96c0abd0 KB |
123 | FILE *iop; |
124 | { | |
94ae9fca JSP |
125 | int fdes, omask, status; |
126 | pid_t pid; | |
96c0abd0 KB |
127 | |
128 | /* | |
129 | * pclose returns -1 if stream is not associated with a | |
130 | * `popened' command, or, if already `pclosed'. | |
131 | */ | |
882508af | 132 | if (pids == 0 || pids[fdes = fileno(iop)] == 0) |
94ae9fca | 133 | return (-1); |
96c0abd0 KB |
134 | (void)fclose(iop); |
135 | omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); | |
94ae9fca JSP |
136 | while ((pid = waitpid(pids[fdes], &status, 0)) < 0 && errno == EINTR) |
137 | continue; | |
96c0abd0 KB |
138 | (void)sigsetmask(omask); |
139 | pids[fdes] = 0; | |
94ae9fca JSP |
140 | if (pid < 0) |
141 | return (pid); | |
142 | if (WIFEXITED(status)) | |
143 | return (WEXITSTATUS(status)); | |
144 | return (1); | |
96c0abd0 | 145 | } |