source: trunk/athena/etc/ftpd/popen.c @ 8587

Revision 8587, 4.7 KB checked in by cfields, 28 years ago (diff)
Don't conditionalize inclusion of "strings.h" on POSIX. In fact, don't include it at all. Include string.h.
Line 
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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * static char sccsid[] = "@(#)popen.c  5.7 (Berkeley) 9/1/88";
21 */
22
23#ifndef lint
24static char sccsid[] = "@(#)popen.c     5.3 (Berkeley) 11/30/88";
25#endif /* not lint */
26
27#include <sys/types.h>
28#include <sys/signal.h>
29#include <stdio.h>
30#include <string.h>
31#include <unistd.h>
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 */
37static unsigned int *pids;
38static int fds;
39#ifdef ATHENA
40uid_t athena_setuid = 0;
41gid_t athena_setgid = 0;
42#endif
43
44FILE *
45ftpd_popen(program, type)
46        char *program, *type;
47{
48        register char *cp;
49        FILE *iop;
50        int argc, gargc, pdes[2], pid;
51        char **pop, *argv[100], *gargv[1000], *vv[2];
52        extern char **glob(), **copyblk(), *strtok();
53
54        if (*type != 'r' && *type != 'w' || type[1])
55                return(NULL);
56
57        if (!pids) {
58#ifndef POSIX
59                if ((fds = getdtablesize()) <= 0)
60#else
61                if ((fds = sysconf(_SC_OPEN_MAX)) <= 0)
62#endif
63                        return(NULL);
64                if (!(pids =
65                    (unsigned int *)malloc((u_int)(fds * sizeof(unsigned int)))))
66                        return(NULL);
67                bzero(pids, fds * sizeof(unsigned int));
68        }
69        if (pipe(pdes) < 0)
70                return(NULL);
71
72        /* break up string into pieces */
73        for (argc = 0, cp = program;; cp = NULL)
74                if (!(argv[argc++] = strtok(cp, " \t\n")))
75                        break;
76
77        /* glob each piece */
78        gargv[0] = argv[0];
79        for (gargc = argc = 1; argv[argc]; argc++) {
80                if (!(pop = glob(argv[argc]))) {        /* globbing failed */
81                        vv[0] = argv[argc];
82                        vv[1] = NULL;
83                        pop = copyblk(vv);
84                }
85                argv[argc] = (char *)pop;               /* save to free later */
86                while (*pop && gargc < 1000)
87                        gargv[gargc++] = *pop++;
88        }
89        gargv[gargc] = NULL;
90
91        iop = NULL;
92        switch(pid = vfork()) {
93        case -1:                        /* error */
94                (void)close(pdes[0]);
95                (void)close(pdes[1]);
96                goto free;
97                /* NOTREACHED */
98        case 0:                         /* child */
99#ifdef ATHENA
100                if (athena_setgid)
101#ifdef _IBMR2
102                  setgid_rios(athena_setgid);
103#else
104                  setgid(athena_setgid);
105#endif
106                if (athena_setuid)
107#ifdef _IBMR2
108                  setuid_rios(athena_setuid);
109#else
110                  setuid(athena_setuid);
111#endif
112#endif
113                if (*type == 'r') {
114                        if (pdes[1] != 1) {
115                                dup2(pdes[1], 1);
116                                (void)close(pdes[1]);
117                        }
118                        (void)close(pdes[0]);
119                } else {
120                        if (pdes[0] != 0) {
121                                dup2(pdes[0], 0);
122                                (void)close(pdes[0]);
123                        }
124                        (void)close(pdes[1]);
125                }
126                execv(gargv[0], gargv);
127                _exit(1);
128        }
129        /* parent; assume fdopen can't fail...  */
130        if (*type == 'r') {
131                iop = fdopen(pdes[0], type);
132                (void)close(pdes[1]);
133        } else {
134                iop = fdopen(pdes[1], type);
135                (void)close(pdes[0]);
136        }
137        pids[fileno(iop)] = pid;
138
139free:   for (argc = 1; argv[argc] != NULL; argc++)
140                blkfree((char **)argv[argc]);
141        return(iop);
142}
143
144pclose(iop)
145        FILE *iop;
146{
147        register int fdes;
148#ifdef POSIX
149        sigset_t omask, nmask;
150#else
151        long omask;
152#endif
153        int pid, stat_loc;
154        u_int waitpid();
155#ifdef POSIX
156        struct sigaction act;
157#endif
158        /*
159         * pclose returns -1 if stream is not associated with a
160         * `popened' command, or, if already `pclosed'.
161         */
162        if (pids[fdes = fileno(iop)] == 0)
163                return(-1);
164        (void)fclose(iop);
165#ifdef POSIX
166        sigemptyset(&nmask);
167        sigaddset(&nmask, SIGINT);
168        sigaddset(&nmask, SIGQUIT);
169        sigaddset(&nmask, SIGHUP);
170        sigprocmask(SIG_BLOCK, &nmask, &omask);
171#else
172        omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
173#endif
174#if defined(_IBMR2) || defined(SOLARIS)
175#ifdef POSIX
176        sigemptyset(&act.sa_mask);
177        act.sa_flags = 0;
178        act.sa_handler= (void (*)()) SIG_DFL;
179        (void) sigaction (SIGCHLD, &act, NULL);
180#else
181        signal(SIGCHLD, SIG_DFL);
182#endif
183        while ((pid = waitpid(pids[fdes], &stat_loc, 0))
184               != pids[fdes] && pid != -1);
185#ifdef POSIX
186        act.sa_handler= (void (*)()) SIG_IGN;
187        (void) sigaction (SIGCHLD, &act, NULL);
188#else
189        signal(SIGCHLD, SIG_IGN);
190#endif
191#else
192        while ((pid = wait(&stat_loc)) != pids[fdes] && pid != -1);
193#endif
194#ifdef POSIX
195        (void)sigprocmask(SIG_SETMASK, &omask, NULL);
196#else
197        (void)sigsetmask(omask);
198#endif
199        pids[fdes] = 0;
200        return(stat_loc);
201}
Note: See TracBrowser for help on using the repository browser.