[BACK]Return to popen.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / libexec / ftpd

Annotation of src/libexec/ftpd/popen.c, Revision 1.3

1.1       cgd         1: /*
1.3     ! deraadt     2:  * Copyright (c) 1988, 1993, 1994
        !             3:  *     The Regents of the University of California.  All rights reserved.
1.1       cgd         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, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed by the University of
                     19:  *     California, Berkeley and its contributors.
                     20:  * 4. Neither the name of the University nor the names of its contributors
                     21:  *    may be used to endorse or promote products derived from this software
                     22:  *    without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  *
                     36:  */
                     37:
                     38: #ifndef lint
1.3     ! deraadt    39: static char sccsid[] = "@(#)popen.c    8.3 (Berkeley) 4/6/94";
        !            40: static char rcsid[] = "$Id: popen.c,v 1.2 1993/08/01 18:30:43 mycroft Exp $";
1.1       cgd        41: #endif /* not lint */
                     42:
                     43: #include <sys/types.h>
                     44: #include <sys/wait.h>
1.3     ! deraadt    45:
        !            46: #include <errno.h>
        !            47: #include <glob.h>
1.1       cgd        48: #include <signal.h>
                     49: #include <stdio.h>
                     50: #include <stdlib.h>
                     51: #include <string.h>
1.3     ! deraadt    52: #include <unistd.h>
        !            53:
        !            54: #include "extern.h"
1.1       cgd        55:
                     56: /*
1.3     ! deraadt    57:  * Special version of popen which avoids call to shell.  This ensures noone
1.1       cgd        58:  * may create a pipe to a hidden program as a side effect of a list or dir
                     59:  * command.
                     60:  */
                     61: static int *pids;
                     62: static int fds;
                     63:
                     64: FILE *
                     65: ftpd_popen(program, type)
                     66:        char *program, *type;
                     67: {
1.3     ! deraadt    68:        char *cp;
1.1       cgd        69:        FILE *iop;
                     70:        int argc, gargc, pdes[2], pid;
1.3     ! deraadt    71:        char **pop, *argv[100], *gargv[1000];
1.1       cgd        72:
                     73:        if (*type != 'r' && *type != 'w' || type[1])
1.3     ! deraadt    74:                return (NULL);
1.1       cgd        75:
                     76:        if (!pids) {
                     77:                if ((fds = getdtablesize()) <= 0)
1.3     ! deraadt    78:                        return (NULL);
1.1       cgd        79:                if ((pids = (int *)malloc((u_int)(fds * sizeof(int)))) == NULL)
1.3     ! deraadt    80:                        return (NULL);
        !            81:                memset(pids, 0, fds * sizeof(int));
1.1       cgd        82:        }
                     83:        if (pipe(pdes) < 0)
1.3     ! deraadt    84:                return (NULL);
1.1       cgd        85:
                     86:        /* break up string into pieces */
                     87:        for (argc = 0, cp = program;; cp = NULL)
                     88:                if (!(argv[argc++] = strtok(cp, " \t\n")))
                     89:                        break;
                     90:
                     91:        /* glob each piece */
                     92:        gargv[0] = argv[0];
                     93:        for (gargc = argc = 1; argv[argc]; argc++) {
1.3     ! deraadt    94:                glob_t gl;
        !            95:                int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
        !            96:
        !            97:                memset(&gl, 0, sizeof(gl));
        !            98:                if (glob(argv[argc], flags, NULL, &gl))
        !            99:                        gargv[gargc++] = strdup(argv[argc]);
        !           100:                else
        !           101:                        for (pop = gl.gl_pathv; *pop; pop++)
        !           102:                                gargv[gargc++] = strdup(*pop);
        !           103:                globfree(&gl);
1.1       cgd       104:        }
                    105:        gargv[gargc] = NULL;
                    106:
                    107:        iop = NULL;
                    108:        switch(pid = vfork()) {
                    109:        case -1:                        /* error */
                    110:                (void)close(pdes[0]);
                    111:                (void)close(pdes[1]);
                    112:                goto pfree;
                    113:                /* NOTREACHED */
                    114:        case 0:                         /* child */
                    115:                if (*type == 'r') {
1.3     ! deraadt   116:                        if (pdes[1] != STDOUT_FILENO) {
        !           117:                                dup2(pdes[1], STDOUT_FILENO);
1.1       cgd       118:                                (void)close(pdes[1]);
                    119:                        }
1.3     ! deraadt   120:                        dup2(STDOUT_FILENO, STDERR_FILENO); /* stderr too! */
1.1       cgd       121:                        (void)close(pdes[0]);
                    122:                } else {
1.3     ! deraadt   123:                        if (pdes[0] != STDIN_FILENO) {
        !           124:                                dup2(pdes[0], STDIN_FILENO);
1.1       cgd       125:                                (void)close(pdes[0]);
                    126:                        }
                    127:                        (void)close(pdes[1]);
                    128:                }
                    129:                execv(gargv[0], gargv);
                    130:                _exit(1);
                    131:        }
                    132:        /* parent; assume fdopen can't fail...  */
                    133:        if (*type == 'r') {
                    134:                iop = fdopen(pdes[0], type);
                    135:                (void)close(pdes[1]);
                    136:        } else {
                    137:                iop = fdopen(pdes[1], type);
                    138:                (void)close(pdes[0]);
                    139:        }
                    140:        pids[fileno(iop)] = pid;
                    141:
1.3     ! deraadt   142: pfree: for (argc = 1; gargv[argc] != NULL; argc++)
        !           143:                free(gargv[argc]);
        !           144:
        !           145:        return (iop);
1.1       cgd       146: }
                    147:
1.3     ! deraadt   148: int
1.1       cgd       149: ftpd_pclose(iop)
                    150:        FILE *iop;
                    151: {
1.3     ! deraadt   152:        int fdes, omask, status;
        !           153:        pid_t pid;
1.1       cgd       154:
                    155:        /*
                    156:         * pclose returns -1 if stream is not associated with a
                    157:         * `popened' command, or, if already `pclosed'.
                    158:         */
                    159:        if (pids == 0 || pids[fdes = fileno(iop)] == 0)
1.3     ! deraadt   160:                return (-1);
1.1       cgd       161:        (void)fclose(iop);
                    162:        omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
1.3     ! deraadt   163:        while ((pid = waitpid(pids[fdes], &status, 0)) < 0 && errno == EINTR)
        !           164:                continue;
1.1       cgd       165:        (void)sigsetmask(omask);
                    166:        pids[fdes] = 0;
1.3     ! deraadt   167:        if (pid < 0)
        !           168:                return (pid);
        !           169:        if (WIFEXITED(status))
        !           170:                return (WEXITSTATUS(status));
        !           171:        return (1);
1.1       cgd       172: }

CVSweb <webmaster@jp.NetBSD.org>