home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume26 / tulp-3.0.3 / part01 / popen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-15  |  3.8 KB  |  166 lines

  1. /* $Id: popen.c,v 1.11 92/12/04 09:16:30 wolf Exp $
  2.  *
  3.  * Derived from the original!  Mod by Wolf & Kim
  4.  *
  5.  * Copyright (c) 1988 The Regents of the University of California.
  6.  * All rights reserved.
  7.  *
  8.  * This code is derived from software written by Ken Arnold and
  9.  * published in UNIX Review, Vol. 6, No. 8.
  10.  *
  11.  * Redistribution and use in source and binary forms are permitted
  12.  * provided that the above copyright notice and this paragraph are
  13.  * duplicated in all such forms and that any documentation,
  14.  * advertising materials, and other materials related to such
  15.  * distribution and use acknowledge that the software was developed
  16.  * by the University of California, Berkeley.  The name of the
  17.  * University may not be used to endorse or promote products derived
  18.  * from this software without specific prior written permission.
  19.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  20.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  21.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  22.  *
  23.  */
  24.  
  25. /* $Log:    popen.c,v $
  26.  * Revision 1.11  92/12/04  09:16:30  wolf
  27.  * Updates syslog defines
  28.  * 
  29.  * Revision 1.10  92/11/17  19:55:19  wolf
  30.  * Changed Debug handling
  31.  * 
  32.  * Revision 1.9  92/06/28  19:31:35  wolf
  33.  * Replaced wait with waitpid (Posix compliant) in order to avoid the
  34.  * defuncts.
  35.  * 
  36.  * Revision 1.8  92/06/12  07:11:31  listserv
  37.  * Initial 2.00 release
  38.  * 
  39.  */
  40.  
  41. #ifndef lint
  42. static char sccsid[] = "@(#)popen.c    5.7 (Berkeley) 2/14/89";
  43. #endif /* not lint */
  44.  
  45. #include "conf.h"
  46. #include <sys/types.h>
  47. #include <string.h>
  48. #include <signal.h>
  49. #include <unistd.h>
  50. #include <sys/wait.h>
  51. #include <stdio.h>
  52. #include <stdlib.h>
  53. #ifdef FAKESYSLOG
  54. # include "fakesyslog.h"
  55. #else
  56. # include <syslog.h>
  57. #endif
  58.  
  59. /*
  60.  * Special version of popen which avoids call to shell.  This insures noone
  61.  * may create a pipe to a hidden program as a side effect of a list or dir
  62.  * command.
  63.  */
  64.  
  65. #define WINSZ    6
  66. static int win=0;
  67.  
  68. static int *pids=NULL;
  69. static int fds;
  70.  
  71. extern int Debug;
  72.  
  73. void reapchild()
  74. {
  75.    while (waitpid(-1, NULL, WNOHANG) > 0)
  76.      win--;
  77. }
  78.  
  79. void winInc(void)
  80. {
  81.    win++;
  82. }
  83.  
  84. FILE * l_popen(char *program, char *type)
  85. {
  86.   register char *cp;
  87.   FILE *iop;
  88.   int argc, pdes[2], pid;
  89.   char *argv[100];
  90.  
  91.   if (*type != 'r' && *type != 'w' || type[1])
  92.     return(NULL);
  93.  
  94.   if (!pids) {
  95.     if ((fds = sysconf(_SC_OPEN_MAX)) <= 0)
  96.       return(NULL);
  97.     if ((pids = (int *)malloc((u_int)(fds * sizeof(int)))) == NULL)
  98.       return(NULL);
  99.     memset((char *)pids, 0, fds * sizeof(int));
  100.   }
  101.   if (pipe(pdes) < 0)
  102.     return(NULL);
  103.  
  104.   /* break up string into pieces */
  105.   for (argc = 0, cp = program;; cp = NULL)
  106.     if (!(argv[argc++] = strtok(cp, " \t\n")))
  107.       break;
  108.  
  109.   iop = NULL;
  110.   switch(pid = fork()) {
  111.   case -1:            /* error */
  112.     (void)close(pdes[0]);
  113.     (void)close(pdes[1]);
  114.     goto pfree;
  115.     /* NOTREACHED */
  116.   case 0:            /* child */
  117.     if (*type == 'r') {
  118.       if (pdes[1] != 1) {
  119.     dup2(pdes[1], 1);
  120.     dup2(pdes[1], 2);    /* stderr, too! */
  121.     (void)close(pdes[1]);
  122.       }
  123.       (void)close(pdes[0]);
  124.     } else {
  125.       if (pdes[0] != 0) {
  126.     dup2(pdes[0], 0);
  127.     (void)close(pdes[0]);
  128.       }
  129.       (void)close(pdes[1]);
  130.     }
  131.     execv(argv[0], argv);
  132.     _exit(1);
  133.   }
  134.   /* parent; assume fdopen can't fail...  */
  135.   if (*type == 'r') {
  136.     iop = fdopen(pdes[0], type);
  137.     (void)close(pdes[1]);
  138.   } else {
  139.     iop = fdopen(pdes[1], type);
  140.     (void)close(pdes[0]);
  141.   }
  142.   pids[fileno(iop)] = pid;
  143.   win++;
  144.  
  145. pfree:    
  146.   return(iop);
  147. }
  148.  
  149. l_pclose(FILE *iop)
  150. {
  151.   register int fdes;
  152.  
  153.   /*
  154.    * pclose returns -1 if stream is not associated with a
  155.    * `popened' command, or, if already `pclosed'.
  156.    */
  157.   if (pids == 0 || pids[fdes = fileno(iop)] == 0)
  158.     return(-1);
  159.   (void)fclose(iop);
  160.    if (Debug != 0)
  161.      fprintf(stderr, "l_pclose: win is %d", win);
  162.   while (win > WINSZ) sleep(30);
  163.   pids[fdes] = 0;
  164.   return(0);
  165. }
  166.