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 * 835451Sbostic * Redistribution and use in source and binary forms are permitted 935451Sbostic * provided that the above copyright notice and this paragraph are 1035451Sbostic * duplicated in all such forms and that any documentation, 1135451Sbostic * advertising materials, and other materials related to such 1235451Sbostic * distribution and use acknowledge that the software was developed 1335451Sbostic * by the University of California, Berkeley. The name of the 1435451Sbostic * University may not be used to endorse or promote products derived 1535451Sbostic * from this software without specific prior written permission. 1635451Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1735451Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1835451Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1922101Smckusick */ 2016676Ssam 2126575Sdonn #if defined(LIBC_SCCS) && !defined(lint) 22*40870Skarels static char sccsid[] = "@(#)popen.c 5.13 (Berkeley) 04/10/90"; 2335451Sbostic #endif /* LIBC_SCCS and not lint */ 2422101Smckusick 2535458Sbostic #include <sys/param.h> 2635458Sbostic #include <sys/signal.h> 2735458Sbostic #include <sys/wait.h> 2840829Sbostic #include <errno.h> 292024Swnj #include <stdio.h> 3039651Sbostic #include <unistd.h> 3139261Sbostic #include <paths.h> 3216676Ssam 3336302Skarels static pid_t *pids; 342024Swnj 352024Swnj FILE * 3635451Sbostic popen(program, type) 3735458Sbostic char *program, *type; 382024Swnj { 3935458Sbostic FILE *iop; 40*40870Skarels int pdes[2], fds, pid; 4135458Sbostic char *malloc(); 422024Swnj 4335458Sbostic if (*type != 'r' && *type != 'w' || type[1]) 44*40870Skarels return (NULL); 4535458Sbostic 4636302Skarels if (pids == NULL) { 4735458Sbostic if ((fds = getdtablesize()) <= 0) 48*40870Skarels return (NULL); 4936302Skarels if ((pids = (pid_t *)malloc((u_int)(fds * sizeof(int)))) == NULL) 50*40870Skarels return (NULL); 5136302Skarels bzero((char *)pids, fds * sizeof(pid_t)); 5235458Sbostic } 5335451Sbostic if (pipe(pdes) < 0) 54*40870Skarels return (NULL); 5536302Skarels switch (pid = vfork()) { 5635458Sbostic case -1: /* error */ 57*40870Skarels (void) close(pdes[0]); 58*40870Skarels (void) close(pdes[1]); 59*40870Skarels return (NULL); 6035458Sbostic /* NOTREACHED */ 6135458Sbostic case 0: /* child */ 6235451Sbostic if (*type == 'r') { 6339651Sbostic if (pdes[1] != STDOUT_FILENO) { 64*40870Skarels (void) dup2(pdes[1], STDOUT_FILENO); 65*40870Skarels (void) close(pdes[1]); 6635458Sbostic } 67*40870Skarels (void) close(pdes[0]); 6835458Sbostic } else { 6939651Sbostic if (pdes[0] != STDIN_FILENO) { 70*40870Skarels (void) dup2(pdes[0], STDIN_FILENO); 71*40870Skarels (void) close(pdes[0]); 7235458Sbostic } 73*40870Skarels (void) close(pdes[1]); 7414718Ssam } 7539261Sbostic execl(_PATH_BSHELL, "sh", "-c", program, NULL); 7635458Sbostic _exit(127); 7735451Sbostic /* NOTREACHED */ 782024Swnj } 7935458Sbostic /* parent; assume fdopen can't fail... */ 8035458Sbostic if (*type == 'r') { 8135458Sbostic iop = fdopen(pdes[0], type); 82*40870Skarels (void) close(pdes[1]); 8335458Sbostic } else { 8435458Sbostic iop = fdopen(pdes[1], type); 85*40870Skarels (void) close(pdes[0]); 8615073Skarels } 8735458Sbostic pids[fileno(iop)] = pid; 88*40870Skarels return (iop); 892024Swnj } 902024Swnj 9135451Sbostic pclose(iop) 9235458Sbostic FILE *iop; 932024Swnj { 9440829Sbostic extern int errno; 9535458Sbostic register int fdes; 9636302Skarels int omask; 9736309Sbostic union wait pstat; 9836309Sbostic pid_t pid, waitpid(); 992024Swnj 10035458Sbostic /* 10135458Sbostic * pclose returns -1 if stream is not associated with a 10236309Sbostic * `popened' command, if already `pclosed', or waitpid 10336309Sbostic * returns an error. 10435458Sbostic */ 10536302Skarels if (pids == NULL || pids[fdes = fileno(iop)] == 0) 106*40870Skarels return (-1); 107*40870Skarels (void) fclose(iop); 10835458Sbostic omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 10940829Sbostic do { 11040829Sbostic pid = waitpid(pids[fdes], &pstat, 0); 11140829Sbostic } while (pid == -1 && errno == EINTR); 112*40870Skarels (void) sigsetmask(omask); 11335458Sbostic pids[fdes] = 0; 114*40870Skarels return (pid == -1 ? -1 : pstat.w_status); 1152024Swnj } 116