home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / permissions / part01 / in.ftpd / popen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-22  |  3.4 KB  |  141 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.  */
  17.  
  18. #ifndef lint
  19. static char sccsid[] = "@(#)popen.c 1.1 90/03/23 SMI"; /* from UCB 5.4 12/7/88 */
  20. #endif /* not lint */
  21.  
  22. #include <sys/types.h>
  23. #include <sys/signal.h>
  24. #include <sys/wait.h>
  25. #include <stdio.h>
  26.  
  27. /*
  28.  * Special version of popen which avoids call to shell.  This insures noone
  29.  * may create a pipe to a hidden program as a side effect of a list or dir
  30.  * command.
  31.  */
  32. static int *pids;
  33. static int fds;
  34.  
  35. FILE *
  36. ftpd_popen(program, type)
  37.     char *program, *type;
  38. {
  39.     register char *cp;
  40.     FILE *iop;
  41.     int argc, gargc, pdes[2], pid;
  42.     char **pop, *argv[100], *gargv[1000], *vv[2];
  43.     extern char **glob(), **copyblk(), *strtok(), *malloc();
  44.  
  45.     if (*type != 'r' && *type != 'w' || type[1])
  46.         return(NULL);
  47.  
  48.     if (!pids) {
  49.         if ((fds = getdtablesize()) <= 0)
  50.             return(NULL);
  51.         if ((pids = (int *)malloc((u_int)(fds * sizeof(int)))) == NULL)
  52.             return(NULL);
  53.         bzero((char *)pids, fds * sizeof(int));
  54.     }
  55.     if (pipe(pdes) < 0)
  56.         return(NULL);
  57.  
  58.     /* break up string into pieces */
  59.     for (argc = 0, cp = program;; cp = NULL)
  60.         if (!(argv[argc++] = strtok(cp, " \t\n")))
  61.             break;
  62.  
  63.     /* glob each piece */
  64.     gargv[0] = argv[0];
  65.     for (gargc = argc = 1; argv[argc]; argc++) {
  66.         if (!(pop = glob(argv[argc]))) {    /* globbing failed */
  67.             vv[0] = argv[argc];
  68.             vv[1] = NULL;
  69.             pop = copyblk(vv);
  70.         }
  71.         argv[argc] = (char *)pop;        /* save to free later */
  72.         while (*pop && gargc < 1000)
  73.             gargv[gargc++] = *pop++;
  74.     }
  75.     gargv[gargc] = NULL;
  76.  
  77.     iop = NULL;
  78.     switch(pid = vfork()) {
  79.     case -1:            /* error */
  80.         (void)close(pdes[0]);
  81.         (void)close(pdes[1]);
  82.         goto free;
  83.         /* NOTREACHED */
  84.     case 0:                /* child */
  85.         if (*type == 'r') {
  86.             if (pdes[1] != 1) {
  87.             /*
  88.              * Need to grab stderr too for new ls
  89.              */
  90.                 dup2(pdes[1], 2);
  91.                 dup2(pdes[1], 1);
  92.                 (void)close(pdes[1]);
  93.             }
  94.             (void)close(pdes[0]);
  95.         } else {
  96.             if (pdes[0] != 0) {
  97.                 dup2(pdes[0], 0);
  98.                 (void)close(pdes[0]);
  99.             }
  100.             (void)close(pdes[1]);
  101.         }
  102.         execv(gargv[0], gargv);
  103.         _exit(1);
  104.     }
  105.     /* parent; assume fdopen can't fail...  */
  106.     if (*type == 'r') {
  107.         iop = fdopen(pdes[0], type);
  108.         (void)close(pdes[1]);
  109.     } else {
  110.         iop = fdopen(pdes[1], type);
  111.         (void)close(pdes[0]);
  112.     }
  113.     pids[fileno(iop)] = pid;
  114.  
  115. free:    for (argc = 1; argv[argc] != NULL; argc++)
  116.         blkfree((char **)argv[argc]);
  117.     return(iop);
  118. }
  119.  
  120. ftpd_pclose(iop)
  121.     FILE *iop;
  122. {
  123.     register int fdes;
  124.     int omask;
  125.     union wait stat_loc;
  126.     int pid;
  127.  
  128.     /*
  129.      * pclose returns -1 if stream is not associated with a
  130.      * `popened' command, or, if already `pclosed'.
  131.      */
  132.     if (pids == 0 || pids[fdes = fileno(iop)] == 0)
  133.         return(-1);
  134.     (void)fclose(iop);
  135.     omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
  136.     while ((pid = wait(&stat_loc)) != pids[fdes] && pid != -1);
  137.     (void)sigsetmask(omask);
  138.     pids[fdes] = 0;
  139.     return(pid == -1 ? -1 : stat_loc.w_status);
  140. }
  141.