Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/appl/ftp/ftpd/popen.c
34914 views
1
/*
2
* Copyright (c) 1988, 1993, 1994
3
* The Regents of the University of California. 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, 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
#ifdef HAVE_CONFIG_H
39
#include <config.h>
40
RCSID("$Id$");
41
#endif
42
43
#include <sys/types.h>
44
#ifdef TIME_WITH_SYS_TIME
45
#include <sys/time.h>
46
#include <time.h>
47
#elif defined(HAVE_SYS_TIME_H)
48
#include <sys/time.h>
49
#else
50
#include <time.h>
51
#endif
52
#ifdef HAVE_SYS_RESOURCE_H
53
#include <sys/resource.h>
54
#endif
55
#include <sys/wait.h>
56
57
#include <errno.h>
58
#include <glob.h>
59
#include <signal.h>
60
#include <stdio.h>
61
#include <stdlib.h>
62
#include <string.h>
63
#include <unistd.h>
64
#include <roken.h>
65
#include "extern.h"
66
67
68
/*
69
* Special version of popen which avoids call to shell. This ensures
70
* no one may create a pipe to a hidden program as a side effect of a
71
* list or dir command.
72
*/
73
static int *pids;
74
static int fds;
75
76
/* return path prepended with ~ftp if that file exists, otherwise
77
* return path unchanged
78
*/
79
80
const char *
81
ftp_rooted(const char *path)
82
{
83
static char home[MaxPathLen] = "";
84
static char newpath[MaxPathLen];
85
struct passwd *pwd;
86
87
if(!home[0])
88
if((pwd = k_getpwnam("ftp")))
89
strlcpy(home, pwd->pw_dir, sizeof(home));
90
snprintf(newpath, sizeof(newpath), "%s/%s", home, path);
91
if(access(newpath, X_OK))
92
strlcpy(newpath, path, sizeof(newpath));
93
return newpath;
94
}
95
96
97
#define MAXARGS 100
98
#define MAXGLOBS 1000
99
100
FILE *
101
ftpd_popen(char *program, char *type, int do_stderr, int no_glob)
102
{
103
char *cp;
104
FILE *iop;
105
int argc, gargc, pdes[2], pid;
106
char **pop, *argv[MAXARGS], *gargv[MAXGLOBS];
107
char *foo;
108
109
if (strcmp(type, "r") && strcmp(type, "w"))
110
return (NULL);
111
112
if (!pids) {
113
114
/* This function is ugly and should be rewritten, in
115
* modern unices there is no such thing as a maximum
116
* filedescriptor.
117
*/
118
119
fds = getdtablesize();
120
pids = (int*)calloc(fds, sizeof(int));
121
if(!pids)
122
return NULL;
123
}
124
if (pipe(pdes) < 0)
125
return (NULL);
126
127
/* break up string into pieces */
128
foo = NULL;
129
for (argc = 0, cp = program; argc < MAXARGS - 1; cp = NULL) {
130
if (!(argv[argc++] = strtok_r(cp, " \t\n", &foo)))
131
break;
132
}
133
argv[MAXARGS - 1] = NULL;
134
135
gargv[0] = (char*)ftp_rooted(argv[0]);
136
/* glob each piece */
137
for (gargc = argc = 1; argv[argc] && gargc < MAXGLOBS - 1; argc++) {
138
glob_t gl;
139
int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE
140
|
141
#ifdef GLOB_MAXPATH
142
GLOB_MAXPATH
143
#else
144
GLOB_LIMIT
145
#endif
146
;
147
148
memset(&gl, 0, sizeof(gl));
149
if (no_glob ||
150
glob(argv[argc], flags, NULL, &gl) ||
151
gl.gl_pathc == 0)
152
gargv[gargc++] = strdup(argv[argc]);
153
else
154
for (pop = gl.gl_pathv;
155
*pop && gargc < MAXGLOBS - 1;
156
pop++)
157
gargv[gargc++] = strdup(*pop);
158
globfree(&gl);
159
}
160
gargv[gargc] = NULL;
161
162
iop = NULL;
163
switch(pid = fork()) {
164
case -1: /* error */
165
close(pdes[0]);
166
close(pdes[1]);
167
goto pfree;
168
/* NOTREACHED */
169
case 0: /* child */
170
if (*type == 'r') {
171
if (pdes[1] != STDOUT_FILENO) {
172
dup2(pdes[1], STDOUT_FILENO);
173
close(pdes[1]);
174
}
175
if(do_stderr)
176
dup2(STDOUT_FILENO, STDERR_FILENO);
177
close(pdes[0]);
178
} else {
179
if (pdes[0] != STDIN_FILENO) {
180
dup2(pdes[0], STDIN_FILENO);
181
close(pdes[0]);
182
}
183
close(pdes[1]);
184
}
185
execv(gargv[0], gargv);
186
gargv[0] = argv[0];
187
execv(gargv[0], gargv);
188
_exit(1);
189
}
190
/* parent; assume fdopen can't fail... */
191
if (*type == 'r') {
192
iop = fdopen(pdes[0], type);
193
close(pdes[1]);
194
} else {
195
iop = fdopen(pdes[1], type);
196
close(pdes[0]);
197
}
198
pids[fileno(iop)] = pid;
199
200
pfree:
201
for (argc = 1; gargv[argc] != NULL; argc++)
202
free(gargv[argc]);
203
204
205
return (iop);
206
}
207
208
int
209
ftpd_pclose(FILE *iop)
210
{
211
int fdes, status;
212
pid_t pid;
213
sigset_t sigset, osigset;
214
215
/*
216
* pclose returns -1 if stream is not associated with a
217
* `popened' command, or, if already `pclosed'.
218
*/
219
if (pids == 0 || pids[fdes = fileno(iop)] == 0)
220
return (-1);
221
fclose(iop);
222
sigemptyset(&sigset);
223
sigaddset(&sigset, SIGINT);
224
sigaddset(&sigset, SIGQUIT);
225
sigaddset(&sigset, SIGHUP);
226
sigprocmask(SIG_BLOCK, &sigset, &osigset);
227
while ((pid = waitpid(pids[fdes], &status, 0)) < 0 && errno == EINTR)
228
continue;
229
sigprocmask(SIG_SETMASK, &osigset, NULL);
230
pids[fdes] = 0;
231
if (pid < 0)
232
return (pid);
233
if (WIFEXITED(status))
234
return (WEXITSTATUS(status));
235
return (1);
236
}
237
238