eliminate local version of glob (cf ftp)
[unix-history] / usr / src / libexec / ftpd / popen.c
CommitLineData
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 13static 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 34static int *pids;
96c0abd0
KB
35static int fds;
36
37FILE *
5256bbac 38ftpd_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
115pfree: for (argc = 1; gargv[argc] != NULL; argc++)
116 free(gargv[argc]);
117
118 return (iop);
96c0abd0
KB
119}
120
60de319b 121int
882508af 122ftpd_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}