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

Revision 6088, 4.0 KB checked in by cfields, 33 years ago (diff)
Added setuid support for popen. (Not sure if this is still used in the code. It may be possible to back that out.) Also modified popen for the RS/6000.
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
31/*
32 * Special version of popen which avoids call to shell.  This insures noone
33 * may create a pipe to a hidden program as a side effect of a list or dir
34 * command.
35 */
36static unsigned int *pids;
37static int fds;
38#ifdef ATHENA
39uid_t athena_setuid = 0;
40gid_t athena_setgid = 0;
41#endif
42
43FILE *
44ftpd_popen(program, type)
45        char *program, *type;
46{
47        register char *cp;
48        FILE *iop;
49        int argc, gargc, pdes[2], pid;
50        char **pop, *argv[100], *gargv[1000], *vv[2];
51        extern char **glob(), **copyblk(), *strtok();
52
53        if (*type != 'r' && *type != 'w' || type[1])
54                return(NULL);
55
56        if (!pids) {
57                if ((fds = getdtablesize()) <= 0)
58                        return(NULL);
59                if (!(pids =
60                    (unsigned int *)malloc((u_int)(fds * sizeof(unsigned int)))))
61                        return(NULL);
62                bzero(pids, fds * sizeof(unsigned int));
63        }
64        if (pipe(pdes) < 0)
65                return(NULL);
66
67        /* break up string into pieces */
68        for (argc = 0, cp = program;; cp = NULL)
69                if (!(argv[argc++] = strtok(cp, " \t\n")))
70                        break;
71
72        /* glob each piece */
73        gargv[0] = argv[0];
74        for (gargc = argc = 1; argv[argc]; argc++) {
75                if (!(pop = glob(argv[argc]))) {        /* globbing failed */
76                        vv[0] = argv[argc];
77                        vv[1] = NULL;
78                        pop = copyblk(vv);
79                }
80                argv[argc] = (char *)pop;               /* save to free later */
81                while (*pop && gargc < 1000)
82                        gargv[gargc++] = *pop++;
83        }
84        gargv[gargc] = NULL;
85
86        iop = NULL;
87        switch(pid = vfork()) {
88        case -1:                        /* error */
89                (void)close(pdes[0]);
90                (void)close(pdes[1]);
91                goto free;
92                /* NOTREACHED */
93        case 0:                         /* child */
94#ifdef ATHENA
95                if (athena_setgid)
96#ifdef _IBMR2
97                  setgid_rios(athena_setgid);
98#else
99                  setgid(athena_setgid);
100#endif
101                if (athena_setuid)
102#ifdef _IBMR2
103                  setuid_rios(athena_setuid);
104#else
105                  setuid(athena_setuid);
106#endif
107#endif
108                if (*type == 'r') {
109                        if (pdes[1] != 1) {
110                                dup2(pdes[1], 1);
111                                (void)close(pdes[1]);
112                        }
113                        (void)close(pdes[0]);
114                } else {
115                        if (pdes[0] != 0) {
116                                dup2(pdes[0], 0);
117                                (void)close(pdes[0]);
118                        }
119                        (void)close(pdes[1]);
120                }
121                execv(gargv[0], gargv);
122                _exit(1);
123        }
124        /* parent; assume fdopen can't fail...  */
125        if (*type == 'r') {
126                iop = fdopen(pdes[0], type);
127                (void)close(pdes[1]);
128        } else {
129                iop = fdopen(pdes[1], type);
130                (void)close(pdes[0]);
131        }
132        pids[fileno(iop)] = pid;
133
134free:   for (argc = 1; argv[argc] != NULL; argc++)
135                blkfree((char **)argv[argc]);
136        return(iop);
137}
138
139pclose(iop)
140        FILE *iop;
141{
142        register int fdes;
143        long omask;
144        int pid, stat_loc;
145        u_int waitpid();
146
147        /*
148         * pclose returns -1 if stream is not associated with a
149         * `popened' command, or, if already `pclosed'.
150         */
151        if (pids[fdes = fileno(iop)] == 0)
152                return(-1);
153        (void)fclose(iop);
154        omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
155#ifdef _IBMR2
156        signal(SIGCHLD, SIG_DFL);
157        while ((pid = waitpid(pids[fdes], &stat_loc, 0))
158               != pids[fdes] && pid != -1);
159        signal(SIGCHLD, SIG_IGN);
160#else
161        while ((pid = wait(&stat_loc)) != pids[fdes] && pid != -1);
162#endif
163        (void)sigsetmask(omask);
164        pids[fdes] = 0;
165        return(stat_loc);
166}
Note: See TracBrowser for help on using the repository browser.