122101Smckusick /* 235451Sbostic * Copyright (c) 1988 The Regents of the University of California. 335451Sbostic * All rights reserved. 435451Sbostic * 535458Sbostic * This code is derived from software written by Ken Arnold and 635458Sbostic * published in UNIX Review, Vol. 6, No. 8. 735451Sbostic * 8*42625Sbostic * %sccs.include.redist.c% 922101Smckusick */ 1016676Ssam 1126575Sdonn #if defined(LIBC_SCCS) && !defined(lint) 12*42625Sbostic static char sccsid[] = "@(#)popen.c 5.14 (Berkeley) 06/01/90"; 1335451Sbostic #endif /* LIBC_SCCS and not lint */ 1422101Smckusick 1535458Sbostic #include <sys/param.h> 1635458Sbostic #include <sys/signal.h> 1735458Sbostic #include <sys/wait.h> 1840829Sbostic #include <errno.h> 192024Swnj #include <stdio.h> 2039651Sbostic #include <unistd.h> 2139261Sbostic #include <paths.h> 2216676Ssam 2336302Skarels static pid_t *pids; 242024Swnj 252024Swnj FILE * 2635451Sbostic popen(program, type) 2735458Sbostic char *program, *type; 282024Swnj { 2935458Sbostic FILE *iop; 3040870Skarels int pdes[2], fds, pid; 3135458Sbostic char *malloc(); 322024Swnj 3335458Sbostic if (*type != 'r' && *type != 'w' || type[1]) 3440870Skarels return (NULL); 3535458Sbostic 3636302Skarels if (pids == NULL) { 3735458Sbostic if ((fds = getdtablesize()) <= 0) 3840870Skarels return (NULL); 3936302Skarels if ((pids = (pid_t *)malloc((u_int)(fds * sizeof(int)))) == NULL) 4040870Skarels return (NULL); 4136302Skarels bzero((char *)pids, fds * sizeof(pid_t)); 4235458Sbostic } 4335451Sbostic if (pipe(pdes) < 0) 4440870Skarels return (NULL); 4536302Skarels switch (pid = vfork()) { 4635458Sbostic case -1: /* error */ 4740870Skarels (void) close(pdes[0]); 4840870Skarels (void) close(pdes[1]); 4940870Skarels return (NULL); 5035458Sbostic /* NOTREACHED */ 5135458Sbostic case 0: /* child */ 5235451Sbostic if (*type == 'r') { 5339651Sbostic if (pdes[1] != STDOUT_FILENO) { 5440870Skarels (void) dup2(pdes[1], STDOUT_FILENO); 5540870Skarels (void) close(pdes[1]); 5635458Sbostic } 5740870Skarels (void) close(pdes[0]); 5835458Sbostic } else { 5939651Sbostic if (pdes[0] != STDIN_FILENO) { 6040870Skarels (void) dup2(pdes[0], STDIN_FILENO); 6140870Skarels (void) close(pdes[0]); 6235458Sbostic } 6340870Skarels (void) close(pdes[1]); 6414718Ssam } 6539261Sbostic execl(_PATH_BSHELL, "sh", "-c", program, NULL); 6635458Sbostic _exit(127); 6735451Sbostic /* NOTREACHED */ 682024Swnj } 6935458Sbostic /* parent; assume fdopen can't fail... */ 7035458Sbostic if (*type == 'r') { 7135458Sbostic iop = fdopen(pdes[0], type); 7240870Skarels (void) close(pdes[1]); 7335458Sbostic } else { 7435458Sbostic iop = fdopen(pdes[1], type); 7540870Skarels (void) close(pdes[0]); 7615073Skarels } 7735458Sbostic pids[fileno(iop)] = pid; 7840870Skarels return (iop); 792024Swnj } 802024Swnj 8135451Sbostic pclose(iop) 8235458Sbostic FILE *iop; 832024Swnj { 8440829Sbostic extern int errno; 8535458Sbostic register int fdes; 8636302Skarels int omask; 8736309Sbostic union wait pstat; 8836309Sbostic pid_t pid, waitpid(); 892024Swnj 9035458Sbostic /* 9135458Sbostic * pclose returns -1 if stream is not associated with a 9236309Sbostic * `popened' command, if already `pclosed', or waitpid 9336309Sbostic * returns an error. 9435458Sbostic */ 9536302Skarels if (pids == NULL || pids[fdes = fileno(iop)] == 0) 9640870Skarels return (-1); 9740870Skarels (void) fclose(iop); 9835458Sbostic omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 9940829Sbostic do { 10040829Sbostic pid = waitpid(pids[fdes], &pstat, 0); 10140829Sbostic } while (pid == -1 && errno == EINTR); 10240870Skarels (void) sigsetmask(omask); 10335458Sbostic pids[fdes] = 0; 10440870Skarels return (pid == -1 ? -1 : pstat.w_status); 1052024Swnj } 106