[BACK]Return to popen.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libc / gen

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/lib/libc/gen/popen.c between version 1.1.1.1 and 1.12

version 1.1.1.1, 1993/03/21 09:45:37 version 1.12, 1996/06/29 00:51:49
Line 1 
Line 1 
   /*      $NetBSD$        */
   
 /*  /*
  * Copyright (c) 1988 The Regents of the University of California.   * Copyright (c) 1988, 1993
  * All rights reserved.   *      The Regents of the University of California.  All rights reserved.
  *   *
  * This code is derived from software written by Ken Arnold and   * This code is derived from software written by Ken Arnold and
  * published in UNIX Review, Vol. 6, No. 8.   * published in UNIX Review, Vol. 6, No. 8.
Line 35 
Line 37 
  */   */
   
 #if defined(LIBC_SCCS) && !defined(lint)  #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)popen.c     5.15 (Berkeley) 2/23/91";  #if 0
   static char sccsid[] = "@(#)popen.c     8.1 (Berkeley) 6/4/93";
   #else
   static char rcsid[] = "$NetBSD$";
   #endif
 #endif /* LIBC_SCCS and not lint */  #endif /* LIBC_SCCS and not lint */
   
 #include <sys/param.h>  #include <sys/param.h>
 #include <sys/signal.h>  
 #include <sys/wait.h>  #include <sys/wait.h>
   
   #include <signal.h>
 #include <errno.h>  #include <errno.h>
   #include <unistd.h>
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
 #include <unistd.h>  
 #include <paths.h>  #include <paths.h>
   
 static pid_t *pids;  static struct pid {
           struct pid *next;
           FILE *fp;
           pid_t pid;
   } *pidlist;
   
 FILE *  FILE *
 popen(program, type)  popen(program, type)
         const char *program;          const char *program;
         const char *type;          const char *type;
 {  {
           struct pid *cur;
         FILE *iop;          FILE *iop;
         int pdes[2], fds, pid;          int pdes[2], pid;
   
         if (*type != 'r' && *type != 'w' || type[1])          if (*type != 'r' && *type != 'w' || type[1]) {
                   errno = EINVAL;
                 return (NULL);                  return (NULL);
   
         if (pids == NULL) {  
                 if ((fds = getdtablesize()) <= 0)  
                         return (NULL);  
                 if ((pids = (pid_t *)malloc((u_int)(fds * sizeof(int)))) == NULL)  
                         return (NULL);  
                 bzero((char *)pids, fds * sizeof(pid_t));  
         }          }
         if (pipe(pdes) < 0)  
           if ((cur = malloc(sizeof(struct pid))) == NULL)
                 return (NULL);                  return (NULL);
   
           if (pipe(pdes) < 0) {
                   free(cur);
                   return (NULL);
           }
   
         switch (pid = vfork()) {          switch (pid = vfork()) {
         case -1:                        /* error */          case -1:                        /* Error. */
                 (void) close(pdes[0]);                  (void)close(pdes[0]);
                 (void) close(pdes[1]);                  (void)close(pdes[1]);
                   free(cur);
                 return (NULL);                  return (NULL);
                 /* NOTREACHED */                  /* NOTREACHED */
         case 0:                         /* child */          case 0:                         /* Child. */
                 if (*type == 'r') {                  if (*type == 'r') {
                         if (pdes[1] != STDOUT_FILENO) {                          if (pdes[1] != STDOUT_FILENO) {
                                 (void) dup2(pdes[1], STDOUT_FILENO);                                  (void)dup2(pdes[1], STDOUT_FILENO);
                                 (void) close(pdes[1]);                                  (void)close(pdes[1]);
                         }                          }
                         (void) close(pdes[0]);                          (void) close(pdes[0]);
                 } else {                  } else {
                         if (pdes[0] != STDIN_FILENO) {                          if (pdes[0] != STDIN_FILENO) {
                                 (void) dup2(pdes[0], STDIN_FILENO);                                  (void)dup2(pdes[0], STDIN_FILENO);
                                 (void) close(pdes[0]);                                  (void)close(pdes[0]);
                         }                          }
                         (void) close(pdes[1]);                          (void)close(pdes[1]);
                 }                  }
   
                   /* POSIX.2 B.3.2.2 "popen() shall ensure that any streams
                      from previous popen() calls that remain open in the
                      parent process are closed in the new child process. */
                   for (cur = pidlist; cur; cur = cur->next)
                           close(fileno(cur->fp));
   
                 execl(_PATH_BSHELL, "sh", "-c", program, NULL);                  execl(_PATH_BSHELL, "sh", "-c", program, NULL);
                 _exit(127);                  _exit(127);
                 /* NOTREACHED */                  /* NOTREACHED */
         }          }
         /* parent; assume fdopen can't fail...  */  
           /* Parent; assume fdopen can't fail. */
         if (*type == 'r') {          if (*type == 'r') {
                 iop = fdopen(pdes[0], type);                  iop = fdopen(pdes[0], type);
                 (void) close(pdes[1]);                  (void)close(pdes[1]);
         } else {          } else {
                 iop = fdopen(pdes[1], type);                  iop = fdopen(pdes[1], type);
                 (void) close(pdes[0]);                  (void)close(pdes[0]);
         }          }
         pids[fileno(iop)] = pid;  
           /* Link into list of file descriptors. */
           cur->fp = iop;
           cur->pid =  pid;
           cur->next = pidlist;
           pidlist = cur;
   
         return (iop);          return (iop);
 }  }
   
   /*
    * pclose --
    *      Pclose returns -1 if stream is not associated with a `popened' command,
    *      if already `pclosed', or waitpid returns an error.
    */
 int  int
 pclose(iop)  pclose(iop)
         FILE *iop;          FILE *iop;
 {  {
         register int fdes;          register struct pid *cur, *last;
         int omask;          int pstat;
         union wait pstat;  
         pid_t pid;          pid_t pid;
   
         /*          (void)fclose(iop);
          * pclose returns -1 if stream is not associated with a  
          * `popened' command, if already `pclosed', or waitpid          /* Find the appropriate file pointer. */
          * returns an error.          for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
          */                  if (cur->fp == iop)
         if (pids == NULL || pids[fdes = fileno(iop)] == 0)                          break;
           if (cur == NULL)
                 return (-1);                  return (-1);
         (void) fclose(iop);  
         omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));  
         do {          do {
                 pid = waitpid(pids[fdes], (int *) &pstat, 0);                  pid = waitpid(cur->pid, &pstat, 0);
         } while (pid == -1 && errno == EINTR);          } while (pid == -1 && errno == EINTR);
         (void) sigsetmask(omask);  
         pids[fdes] = 0;          /* Remove the entry from the linked list. */
         return (pid == -1 ? -1 : pstat.w_status);          if (last == NULL)
                   pidlist = cur->next;
           else
                   last->next = cur->next;
           free(cur);
   
           return (pid == -1 ? -1 : pstat);
 }  }

Legend:
Removed from v.1.1.1.1  
changed lines
  Added in v.1.12

CVSweb <webmaster@jp.NetBSD.org>