home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / archival / ftp / ftpd / popen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-02-14  |  3.6 KB  |  144 lines

  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. #ifndef lint
  23. static char sccsid[] = "@(#)popen.c    5.7 (Berkeley) 2/14/89";
  24. #endif /* not lint */
  25.  
  26. #include <sys/types.h>
  27. #include <sys/signal.h>
  28. #include <sys/wait.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.  */
  36. static int *pids;
  37. static int fds;
  38.  
  39. FILE *
  40. ftpd_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(), *malloc();
  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 = (int *)malloc((u_int)(fds * sizeof(int)))) == NULL)
  56.             return(NULL);
  57.         bzero((char *)pids, fds * sizeof(int));
  58.     }
  59.     if (pipe(pdes) < 0)
  60.         return(NULL);
  61.  
  62.     /* break up string into pieces */
  63.     for (argc = 0, cp = program;; cp = NULL)
  64.         if (!(argv[argc++] = strtok(cp, " \t\n")))
  65.             break;
  66.  
  67.     /* glob each piece */
  68.     gargv[0] = argv[0];
  69.     for (gargc = argc = 1; argv[argc]; argc++) {
  70.         if (!(pop = glob(argv[argc]))) {    /* globbing failed */
  71.             vv[0] = argv[argc];
  72.             vv[1] = NULL;
  73.             pop = copyblk(vv);
  74.         }
  75.         argv[argc] = (char *)pop;        /* save to free later */
  76.         while (*pop && gargc < 1000)
  77.             gargv[gargc++] = *pop++;
  78.     }
  79.     gargv[gargc] = NULL;
  80.  
  81.     iop = NULL;
  82.     switch(pid = vfork()) {
  83.     case -1:            /* error */
  84.         (void)close(pdes[0]);
  85.         (void)close(pdes[1]);
  86.         goto pfree;
  87.         /* NOTREACHED */
  88.     case 0:                /* child */
  89.         if (*type == 'r') {
  90.             if (pdes[1] != 1) {
  91.                 dup2(pdes[1], 1);
  92.                 dup2(pdes[1], 2);    /* stderr, too! */
  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.  
  116. pfree:    for (argc = 1; argv[argc] != NULL; argc++) {
  117.         blkfree((char **)argv[argc]);
  118.         free((char *)argv[argc]);
  119.     }
  120.     return(iop);
  121. }
  122.  
  123. ftpd_pclose(iop)
  124.     FILE *iop;
  125. {
  126.     register int fdes;
  127.     int omask;
  128.     union wait stat_loc;
  129.     int pid;
  130.  
  131.     /*
  132.      * pclose returns -1 if stream is not associated with a
  133.      * `popened' command, or, if already `pclosed'.
  134.      */
  135.     if (pids == 0 || pids[fdes = fileno(iop)] == 0)
  136.         return(-1);
  137.     (void)fclose(iop);
  138.     omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
  139.     while ((pid = wait(&stat_loc)) != pids[fdes] && pid != -1);
  140.     (void)sigsetmask(omask);
  141.     pids[fdes] = 0;
  142.     return(pid == -1 ? -1 : stat_loc.w_status);
  143. }
  144.