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 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19:  *
  20:  */
  21: 
  22: #if !defined(lint) && defined(DOSCCS)
  23: static char sccsid[] = "@(#)popen.c	5.7.1 (2.11BSD) 1999/10/25";
  24: #endif
  25: 
  26: #include <sys/types.h>
  27: #include <sys/signal.h>
  28: #include <sys/wait.h>
  29: #include <stdio.h>
  30: #include <string.h>
  31: 
  32: /*
  33:  * Special version of popen which avoids call to shell.  This insures noone
  34:  * may create a pipe to a hidden program as a side effect of a list or dir
  35:  * command.
  36:  */
  37: static int *pids;
  38: static int fds;
  39: 
  40: FILE *
  41: ftpd_popen(program, type)
  42:     char *program, *type;
  43: {
  44:     register char *cp;
  45:     FILE *iop;
  46:     int argc, gargc, pdes[2], pid;
  47:     char **pop, *argv[100], *gargv[1000], *vv[2], **ppop, *endprogram;
  48:     extern char **glob(), **copyblk(), *malloc();
  49: 
  50:     if (*type != 'r' && *type != 'w' || type[1])
  51:         return(NULL);
  52: 
  53:     if (!pids) {
  54:         if ((fds = getdtablesize()) <= 0)
  55:             return(NULL);
  56:         if ((pids = (int *)malloc((u_int)(fds * sizeof(int)))) == NULL)
  57:             return(NULL);
  58:         bzero((char *)pids, fds * sizeof(int));
  59:     }
  60:     if (pipe(pdes) < 0)
  61:         return(NULL);
  62:     endprogram = program + strlen(program);
  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:         for (ppop = pop; *ppop != NULL; ppop++) {
  78:             if (*ppop >= program && *ppop <= endprogram) {
  79:                 cp = (char *) malloc(strlen(*ppop) + 1);
  80:                 strcpy(cp, *ppop);
  81:                 *ppop = cp;
  82:             }
  83:         }
  84:         argv[argc] = (char *)pop;       /* save to free later */
  85:         while (*pop && gargc < 1000)
  86:             gargv[gargc++] = *pop++;
  87:     }
  88:     gargv[gargc] = NULL;
  89: 
  90:     iop = NULL;
  91:     switch(pid = vfork()) {
  92:     case -1:            /* error */
  93:         (void)close(pdes[0]);
  94:         (void)close(pdes[1]);
  95:         goto pfree;
  96:         /* NOTREACHED */
  97:     case 0:             /* child */
  98:         if (*type == 'r') {
  99:             if (pdes[1] != 1) {
 100:                 dup2(pdes[1], 1);
 101:                 dup2(pdes[1], 2);   /* stderr, too! */
 102:                 (void)close(pdes[1]);
 103:             }
 104:             (void)close(pdes[0]);
 105:         } else {
 106:             if (pdes[0] != 0) {
 107:                 dup2(pdes[0], 0);
 108:                 (void)close(pdes[0]);
 109:             }
 110:             (void)close(pdes[1]);
 111:         }
 112:         execv(gargv[0], gargv);
 113:         _exit(1);
 114:     }
 115:     /* parent; assume fdopen can't fail...  */
 116:     if (*type == 'r') {
 117:         iop = fdopen(pdes[0], type);
 118:         (void)close(pdes[1]);
 119:     } else {
 120:         iop = fdopen(pdes[1], type);
 121:         (void)close(pdes[0]);
 122:     }
 123:     pids[fileno(iop)] = pid;
 124: 
 125: pfree:  for (argc = 1; argv[argc] != NULL; argc++) {
 126:         blkfree((char **)argv[argc]);
 127:         free((char *)argv[argc]);
 128:     }
 129:     return(iop);
 130: }
 131: 
 132: ftpd_pclose(iop)
 133:     FILE *iop;
 134: {
 135:     register int fdes;
 136:     sigset_t  set;
 137:     union wait stat_loc;
 138:     int pid;
 139: 
 140:     /*
 141: 	 * pclose returns -1 if stream is not associated with a
 142: 	 * `popened' command, or, if already `pclosed'.
 143: 	 */
 144:     if (pids == 0 || pids[fdes = fileno(iop)] == 0)
 145:         return(-1);
 146:     (void)fclose(iop);
 147:     sigemptyset(&set);
 148:     sigaddset(&set, SIGINT);
 149:     sigaddset(&set, SIGQUIT);
 150:     sigaddset(&set, SIGHUP);
 151:     (void)sigprocmask(SIG_BLOCK, &set, NULL);
 152:     while ((pid = wait(&stat_loc)) != pids[fdes] && pid != -1);
 153:     (void)sigprocmask(SIG_UNBLOCK, &set, NULL);
 154:     pids[fdes] = 0;
 155:     return(pid == -1 ? -1 : stat_loc.w_status);
 156: }

Defined functions

ftpd_pclose defined in line 132; used 5 times
ftpd_popen defined in line 40; used 3 times

Defined variables

fds defined in line 38; used 3 times
pids defined in line 37; used 8 times
sccsid defined in line 23; never used
Last modified: 1999-10-26
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 796
Valid CSS Valid XHTML 1.0 Strict