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

Revision 6079, 3.5 KB checked in by cfields, 33 years ago (diff)
Initial revision
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
39FILE *
40ftpd_popen(program, type)
41        char *program, *type;
42{
43        register char *cp;
44        FILE *iop;
45        int argc, gargc, pdes[2], pid;
46        char **pop, *argv[100], *gargv[1000], *vv[2];
47        extern char **glob(), **copyblk(), *strtok();
48
49        if (*type != 'r' && *type != 'w' || type[1])
50                return(NULL);
51
52        if (!pids) {
53                if ((fds = getdtablesize()) <= 0)
54                        return(NULL);
55                if (!(pids =
56                    (unsigned int *)malloc((u_int)(fds * sizeof(unsigned int)))))
57                        return(NULL);
58                bzero(pids, fds * sizeof(unsigned int));
59        }
60        if (pipe(pdes) < 0)
61                return(NULL);
62
63        /* break up string into pieces */
64        for (argc = 0, cp = program;; cp = NULL)
65                if (!(argv[argc++] = strtok(cp, " \t\n")))
66                        break;
67
68        /* glob each piece */
69        gargv[0] = argv[0];
70        for (gargc = argc = 1; argv[argc]; argc++) {
71                if (!(pop = glob(argv[argc]))) {        /* globbing failed */
72                        vv[0] = argv[argc];
73                        vv[1] = NULL;
74                        pop = copyblk(vv);
75                }
76                argv[argc] = (char *)pop;               /* save to free later */
77                while (*pop && gargc < 1000)
78                        gargv[gargc++] = *pop++;
79        }
80        gargv[gargc] = NULL;
81
82        iop = NULL;
83        switch(pid = vfork()) {
84        case -1:                        /* error */
85                (void)close(pdes[0]);
86                (void)close(pdes[1]);
87                goto free;
88                /* NOTREACHED */
89        case 0:                         /* child */
90                if (*type == 'r') {
91                        if (pdes[1] != 1) {
92                                dup2(pdes[1], 1);
93                                (void)close(pdes[1]);
94                        }
95                        (void)close(pdes[0]);
96                } else {
97                        if (pdes[0] != 0) {
98                                dup2(pdes[0], 0);
99                                (void)close(pdes[0]);
100                        }
101                        (void)close(pdes[1]);
102                }
103                execv(gargv[0], gargv);
104                _exit(1);
105        }
106        /* parent; assume fdopen can't fail...  */
107        if (*type == 'r') {
108                iop = fdopen(pdes[0], type);
109                (void)close(pdes[1]);
110        } else {
111                iop = fdopen(pdes[1], type);
112                (void)close(pdes[0]);
113        }
114        pids[fileno(iop)] = pid;
115
116free:   for (argc = 1; argv[argc] != NULL; argc++)
117                blkfree((char **)argv[argc]);
118        return(iop);
119}
120
121pclose(iop)
122        FILE *iop;
123{
124        register int fdes;
125        long omask;
126        int pid, stat_loc;
127        u_int waitpid();
128
129        /*
130         * pclose returns -1 if stream is not associated with a
131         * `popened' command, or, if already `pclosed'.
132         */
133        if (pids[fdes = fileno(iop)] == 0)
134                return(-1);
135        (void)fclose(iop);
136        omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
137        while ((pid = wait(&stat_loc)) != pids[fdes] && pid != -1);
138        (void)sigsetmask(omask);
139        pids[fdes] = 0;
140        return(stat_loc);
141}
Note: See TracBrowser for help on using the repository browser.