Annotation of 43BSDReno/libexec/ftpd/popen.c, revision 1.1.1.1

1.1       root        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: (1) source distributions retain this entire copyright
                     10:  * notice and comment, and (2) distributions including binaries display
                     11:  * the following acknowledgement:  ``This product includes software
                     12:  * developed by the University of California, Berkeley and its contributors''
                     13:  * in the documentation or other materials provided with the distribution
                     14:  * and in all advertising materials mentioning features or use of this
                     15:  * software. Neither the name of the University nor the names of its
                     16:  * contributors may be used to endorse or promote products derived
                     17:  * from this software without specific prior written permission.
                     18:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     19:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     20:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     21:  *
                     22:  */
                     23: 
                     24: #ifndef lint
                     25: static char sccsid[] = "@(#)popen.c    5.8 (Berkeley) 6/1/90";
                     26: #endif /* not lint */
                     27: 
                     28: #include <sys/types.h>
                     29: #include <sys/signal.h>
                     30: #include <sys/wait.h>
                     31: #include <stdio.h>
                     32: 
                     33: /*
                     34:  * Special version of popen which avoids call to shell.  This insures noone
                     35:  * may create a pipe to a hidden program as a side effect of a list or dir
                     36:  * command.
                     37:  */
                     38: static int *pids;
                     39: static int fds;
                     40: 
                     41: FILE *
                     42: ftpd_popen(program, type)
                     43:        char *program, *type;
                     44: {
                     45:        register char *cp;
                     46:        FILE *iop;
                     47:        int argc, gargc, pdes[2], pid;
                     48:        char **pop, *argv[100], *gargv[1000], *vv[2];
                     49:        extern char **glob(), **copyblk(), *strtok(), *malloc();
                     50: 
                     51:        if (*type != 'r' && *type != 'w' || type[1])
                     52:                return(NULL);
                     53: 
                     54:        if (!pids) {
                     55:                if ((fds = getdtablesize()) <= 0)
                     56:                        return(NULL);
                     57:                if ((pids = (int *)malloc((u_int)(fds * sizeof(int)))) == NULL)
                     58:                        return(NULL);
                     59:                bzero((char *)pids, fds * sizeof(int));
                     60:        }
                     61:        if (pipe(pdes) < 0)
                     62:                return(NULL);
                     63: 
                     64:        /* break up string into pieces */
                     65:        for (argc = 0, cp = program;; cp = NULL)
                     66:                if (!(argv[argc++] = strtok(cp, " \t\n")))
                     67:                        break;
                     68: 
                     69:        /* glob each piece */
                     70:        gargv[0] = argv[0];
                     71:        for (gargc = argc = 1; argv[argc]; argc++) {
                     72:                if (!(pop = glob(argv[argc]))) {        /* globbing failed */
                     73:                        vv[0] = argv[argc];
                     74:                        vv[1] = NULL;
                     75:                        pop = copyblk(vv);
                     76:                }
                     77:                argv[argc] = (char *)pop;               /* save to free later */
                     78:                while (*pop && gargc < 1000)
                     79:                        gargv[gargc++] = *pop++;
                     80:        }
                     81:        gargv[gargc] = NULL;
                     82: 
                     83:        iop = NULL;
                     84:        switch(pid = vfork()) {
                     85:        case -1:                        /* error */
                     86:                (void)close(pdes[0]);
                     87:                (void)close(pdes[1]);
                     88:                goto pfree;
                     89:                /* NOTREACHED */
                     90:        case 0:                         /* child */
                     91:                if (*type == 'r') {
                     92:                        if (pdes[1] != 1) {
                     93:                                dup2(pdes[1], 1);
                     94:                                dup2(pdes[1], 2);       /* stderr, too! */
                     95:                                (void)close(pdes[1]);
                     96:                        }
                     97:                        (void)close(pdes[0]);
                     98:                } else {
                     99:                        if (pdes[0] != 0) {
                    100:                                dup2(pdes[0], 0);
                    101:                                (void)close(pdes[0]);
                    102:                        }
                    103:                        (void)close(pdes[1]);
                    104:                }
                    105:                execv(gargv[0], gargv);
                    106:                _exit(1);
                    107:        }
                    108:        /* parent; assume fdopen can't fail...  */
                    109:        if (*type == 'r') {
                    110:                iop = fdopen(pdes[0], type);
                    111:                (void)close(pdes[1]);
                    112:        } else {
                    113:                iop = fdopen(pdes[1], type);
                    114:                (void)close(pdes[0]);
                    115:        }
                    116:        pids[fileno(iop)] = pid;
                    117: 
                    118: pfree: for (argc = 1; argv[argc] != NULL; argc++) {
                    119:                blkfree((char **)argv[argc]);
                    120:                free((char *)argv[argc]);
                    121:        }
                    122:        return(iop);
                    123: }
                    124: 
                    125: ftpd_pclose(iop)
                    126:        FILE *iop;
                    127: {
                    128:        register int fdes;
                    129:        int omask;
                    130:        union wait stat_loc;
                    131:        int pid;
                    132: 
                    133:        /*
                    134:         * pclose returns -1 if stream is not associated with a
                    135:         * `popened' command, or, if already `pclosed'.
                    136:         */
                    137:        if (pids == 0 || pids[fdes = fileno(iop)] == 0)
                    138:                return(-1);
                    139:        (void)fclose(iop);
                    140:        omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
                    141:        while ((pid = wait(&stat_loc)) != pids[fdes] && pid != -1);
                    142:        (void)sigsetmask(omask);
                    143:        pids[fdes] = 0;
                    144:        return(pid == -1 ? -1 : stat_loc.w_status);
                    145: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.