1 /* popen.c: A "safe" pipe open routine.
3 %%% portions-copyright-cmetz-96
4 Portions of this software are Copyright 1996-1999 by Craig Metz, All Rights
5 Reserved. The Inner Net License Version 2 applies to these portions of
7 You should have received a copy of the license with this software. If
8 you didn't get a copy, you may request one from <license@inner.net>.
10 Portions of this software are Copyright 1995 by Randall Atkinson and Dan
11 McDonald, All Rights Reserved. All Rights under this copyright are assigned
12 to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
13 License Agreement applies to this software.
17 Modified by cmetz for OPIE 2.31. Merged in some 4.4BSD-Lite fixes.
18 Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
19 Removed useless string. ifdef around some headers.
20 Modified at NRL for OPIE 2.1. Optimized for only one pipe at a time.
21 Added minimal version of sigprocmask(). Moved some pid_t
22 dancing to the config headers.
23 Modified at NRL for OPIE 2.0.
26 $FreeBSD: head/contrib/opie/popen.c 117501 2003-07-13 05:59:50Z kris $
29 * Copyright (c) 1988, 1993, 1994
30 * The Regents of the University of California. All rights reserved.
32 * This code is derived from software written by Ken Arnold and
33 * published in UNIX Review, Vol. 6, No. 8.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 * 3. All advertising materials mentioning features or use of this software
44 * must display the following acknowledgement:
45 * This product includes software developed by the University of
46 * California, Berkeley and its contributors.
47 * 4. Neither the name of the University nor the names of its contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67 #include <sys/types.h>
71 #endif /* HAVE_SIGNAL_H */
73 #include <sys/signal.h>
74 #endif /* HAVE_SYS_SIGNAL_H */
77 #endif /* HAVE_UNISTD_H */
81 #endif /* HAVE_STDLIB_H */
84 #endif /* HAVE_STRING_H */
88 #define MAXUSRARGS 100
89 #define MAXGLOBARGS 1000
91 char **ftpglob
__P((register char *));
92 char **copyblk
__P((char **));
93 VOIDRET blkfree
__P((char **));
96 * Special version of popen which avoids call to shell. This ensures noone
97 * may create a pipe to a hidden program as a side effect of a list or dir
100 static pid_t child_pid
= -1;
103 extern char **environ
;
105 FILE *ftpd_popen
FUNCTION((program
, type
), char *program AND
char *type
)
109 int argc
, gargc
, pdes
[2];
110 char **pop
, *argv
[MAXUSRARGS
], *gargv
[MAXGLOBARGS
], *vv
[2];
112 if ((*type
!= 'r' && *type
!= 'w') || type
[1])
118 /* break up string into pieces */
119 for (argc
= 0, cp
= program
; argc
< MAXUSRARGS
-1; cp
= NULL
) {
120 if (!(argv
[argc
++] = strtok(cp
, " \t\n")))
123 argv
[argc
- 1] = NULL
;
125 /* glob each piece */
127 for (gargc
= argc
= 1; argv
[argc
] && gargc
< (MAXGLOBARGS
-1); argc
++) {
128 if (!(pop
= (char **) ftpglob(argv
[argc
]))) {
129 /* globbing failed */
132 pop
= (char **) copyblk(vv
);
134 argv
[argc
] = (char *) pop
; /* save to free later */
135 while (*pop
&& gargc
< MAXGLOBARGS
-1)
136 gargv
[gargc
++] = *pop
++;
141 switch (child_pid
= fork()) {
151 dup2(pdes
[1], 2); /* stderr, too! */
163 execv(gargv
[0], gargv
);
167 /* parent; assume fdopen can't fail... */
169 iop
= fdopen(pipe_fd
= pdes
[0], type
);
172 iop
= fdopen(pipe_fd
= pdes
[1], type
);
176 pfree
: for (argc
= 1; argv
[argc
] != NULL
; argc
++) {
177 blkfree((char **) argv
[argc
]);
178 free((char *) argv
[argc
]);
183 int ftpd_pclose
FUNCTION((iop
), FILE *iop
)
187 sigset_t omask
, mask
;
190 sigaddset(&mask
, SIGINT
);
191 sigaddset(&mask
, SIGQUIT
);
192 sigaddset(&mask
, SIGHUP
);
194 /* pclose returns -1 if stream is not associated with a `popened' command,
195 or, if already `pclosed'. */
196 if ((child_pid
< 0) || (fileno(iop
) != pipe_fd
))
200 sigprocmask(SIG_BLOCK
, &mask
, &omask
);
202 while ((pid
= wait(&status
)) != child_pid
&& (pid
!= -1));
203 sigprocmask(SIG_SETMASK
, &omask
, NULL
);
208 #if defined(WEXITSTATUS) && defined(WIFEXITED)
209 if ((pid
> 0) && WIFEXITED(status
))
210 return WEXITSTATUS(status
);
213 #else /* defined(WEXITSTATUS) && defined(WIFEXITED) */
214 return (pid
== -1 ? -1 : status
.w_status
);
215 #endif /* defined(WEXITSTATUS) && defined(WIFEXITED) */