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

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