[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.13 and 1.27

version 1.13, 1997/07/13 19:16:07 version 1.27, 2003/08/07 16:42:55
Line 15 
Line 15 
  * 2. Redistributions in binary form must reproduce the above copyright   * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the   *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.   *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software   * 3. Neither the name of the University nor the names of its contributors
  *    must display the following acknowledgement:  
  *      This product includes software developed by the University of  
  *      California, Berkeley and its contributors.  
  * 4. Neither the name of the University nor the names of its contributors  
  *    may be used to endorse or promote products derived from this software   *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.   *    without specific prior written permission.
  *   *
Line 39 
Line 35 
 #include <sys/cdefs.h>  #include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)  #if defined(LIBC_SCCS) && !defined(lint)
 #if 0  #if 0
 static char sccsid[] = "@(#)popen.c     8.1 (Berkeley) 6/4/93";  static char sccsid[] = "@(#)popen.c     8.3 (Berkeley) 5/3/95";
 #else  #else
 __RCSID("$NetBSD$");  __RCSID("$NetBSD$");
 #endif  #endif
 #endif /* LIBC_SCCS and not lint */  #endif /* LIBC_SCCS and not lint */
   
   #include "namespace.h"
 #include <sys/param.h>  #include <sys/param.h>
 #include <sys/wait.h>  #include <sys/wait.h>
   #include <sys/socket.h>
   
 #include <signal.h>  #include <assert.h>
 #include <errno.h>  #include <errno.h>
 #include <unistd.h>  #include <paths.h>
   #include <signal.h>
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
 #include <paths.h>  #include <unistd.h>
   #include "reentrant.h"
   
   #ifdef __weak_alias
   __weak_alias(popen,_popen)
   __weak_alias(pclose,_pclose)
   #endif
   
   #ifdef _REENTRANT
   extern rwlock_t __environ_lock;
   #endif
   
 static struct pid {  static struct pid {
         struct pid *next;          struct pid *next;
Line 63  static struct pid {
Line 72  static struct pid {
 } *pidlist;  } *pidlist;
   
 FILE *  FILE *
 popen(program, type)  popen(command, type)
         const char *program;          const char *command, *type;
         const char *type;  
 {  {
         struct pid *cur;          struct pid *cur, *old;
         FILE *iop;          FILE *iop;
         int pdes[2], pid;          int pdes[2], pid, twoway, serrno;
   
           _DIAGASSERT(command != NULL);
           _DIAGASSERT(type != NULL);
   
 #ifdef __GNUC__  #ifdef __GNUC__
         (void) &cur;          /* This outrageous construct just to shut up a GCC warning. */
           (void) &cur; (void) &twoway; (void) &type;
 #endif  #endif
   
         if ((*type != 'r' && *type != 'w') || type[1]) {          if (strchr(type, '+')) {
                 errno = EINVAL;                  twoway = 1;
                 return (NULL);                  type = "r+";
                   if (socketpair(AF_LOCAL, SOCK_STREAM, 0, pdes) < 0)
                           return (NULL);
           } else  {
                   twoway = 0;
                   if ((*type != 'r' && *type != 'w') || type[1] ||
                       (pipe(pdes) < 0)) {
                           errno = EINVAL;
                           return (NULL);
                   }
         }          }
   
         if ((cur = malloc(sizeof(struct pid))) == NULL)          if ((cur = malloc(sizeof(struct pid))) == NULL) {
                 return (NULL);                  (void)close(pdes[0]);
                   (void)close(pdes[1]);
         if (pipe(pdes) < 0) {                  errno = ENOMEM;
                 free(cur);  
                 return (NULL);                  return (NULL);
         }          }
   
           rwlock_rdlock(&__environ_lock);
         switch (pid = vfork()) {          switch (pid = vfork()) {
         case -1:                        /* Error. */          case -1:                        /* Error. */
                   serrno = errno;
                   rwlock_unlock(&__environ_lock);
                   free(cur);
                 (void)close(pdes[0]);                  (void)close(pdes[0]);
                 (void)close(pdes[1]);                  (void)close(pdes[1]);
                 free(cur);                  errno = serrno;
                 return (NULL);                  return (NULL);
                 /* NOTREACHED */                  /* NOTREACHED */
         case 0:                         /* Child. */          case 0:                         /* Child. */
                   /* 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 (old = pidlist; old; old = old->next)
                           close(fileno(old->fp)); /* don't allow a flush */
   
                 if (*type == 'r') {                  if (*type == 'r') {
                           (void)close(pdes[0]);
                         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]);                          if (twoway)
                                   (void)dup2(STDOUT_FILENO, STDIN_FILENO);
                 } else {                  } else {
                           (void)close(pdes[1]);
                         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]);  
                 }                  }
   
                 /* POSIX.2 B.3.2.2 "popen() shall ensure that any streams                  execl(_PATH_BSHELL, "sh", "-c", command, NULL);
                    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);  
                 _exit(127);                  _exit(127);
                 /* NOTREACHED */                  /* NOTREACHED */
         }          }
           rwlock_unlock(&__environ_lock);
   
         /* Parent; assume fdopen can't fail. */          /* Parent; assume fdopen can't fail. */
         if (*type == 'r') {          if (*type == 'r') {
Line 147  int
Line 175  int
 pclose(iop)  pclose(iop)
         FILE *iop;          FILE *iop;
 {  {
         register struct pid *cur, *last;          struct pid *cur, *last;
         int pstat;          int pstat;
         pid_t pid;          pid_t pid;
   
         (void)fclose(iop);          _DIAGASSERT(iop != NULL);
   
         /* Find the appropriate file pointer. */          /* Find the appropriate file pointer. */
         for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)          for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
Line 160  pclose(iop)
Line 188  pclose(iop)
         if (cur == NULL)          if (cur == NULL)
                 return (-1);                  return (-1);
   
           (void)fclose(iop);
   
         do {          do {
                 pid = waitpid(cur->pid, &pstat, 0);                  pid = waitpid(cur->pid, &pstat, 0);
         } while (pid == -1 && errno == EINTR);          } while (pid == -1 && errno == EINTR);

Legend:
Removed from v.1.13  
changed lines
  Added in v.1.27

CVSweb <webmaster@jp.NetBSD.org>