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*36302Skarels static char sccsid[] = "@(#)popen.c 5.8 (Berkeley) 12/06/88"; 2335451Sbostic #endif /* LIBC_SCCS and not lint */ 2422101Smckusick 2535458Sbostic #include <sys/param.h> 2635458Sbostic #include <sys/signal.h> 2735458Sbostic #include <sys/wait.h> 282024Swnj #include <stdio.h> 2916676Ssam 30*36302Skarels static pid_t *pids; 3135458Sbostic static int fds; 322024Swnj 332024Swnj FILE * 3435451Sbostic popen(program, type) 3535458Sbostic char *program, *type; 362024Swnj { 3735458Sbostic FILE *iop; 3835451Sbostic int pdes[2], pid; 3935458Sbostic char *malloc(); 402024Swnj 4135458Sbostic if (*type != 'r' && *type != 'w' || type[1]) 4235458Sbostic return(NULL); 4335458Sbostic 44*36302Skarels if (pids == NULL) { 4535458Sbostic if ((fds = getdtablesize()) <= 0) 4635458Sbostic return(NULL); 47*36302Skarels if ((pids = (pid_t *)malloc((u_int)(fds * sizeof(int)))) == NULL) 4835458Sbostic return(NULL); 49*36302Skarels bzero((char *)pids, fds * sizeof(pid_t)); 5035458Sbostic } 5135451Sbostic if (pipe(pdes) < 0) 5235458Sbostic return(NULL); 53*36302Skarels switch (pid = vfork()) { 5435458Sbostic case -1: /* error */ 5535458Sbostic (void)close(pdes[0]); 5635458Sbostic (void)close(pdes[1]); 5735458Sbostic return(NULL); 5835458Sbostic /* NOTREACHED */ 5935458Sbostic case 0: /* child */ 6035451Sbostic if (*type == 'r') { 6135458Sbostic if (pdes[1] != 1) { 6235458Sbostic dup2(pdes[1], 1); 6335458Sbostic (void)close(pdes[1]); 6435458Sbostic } 6535458Sbostic (void)close(pdes[0]); 6635458Sbostic } else { 6735458Sbostic if (pdes[0] != 0) { 6835458Sbostic dup2(pdes[0], 0); 6935458Sbostic (void)close(pdes[0]); 7035458Sbostic } 7135458Sbostic (void)close(pdes[1]); 7214718Ssam } 7335451Sbostic execl("/bin/sh", "sh", "-c", program, NULL); 7435458Sbostic _exit(127); 7535451Sbostic /* NOTREACHED */ 762024Swnj } 7735458Sbostic /* parent; assume fdopen can't fail... */ 7835458Sbostic if (*type == 'r') { 7935458Sbostic iop = fdopen(pdes[0], type); 8035458Sbostic (void)close(pdes[1]); 8135458Sbostic } else { 8235458Sbostic iop = fdopen(pdes[1], type); 8335458Sbostic (void)close(pdes[0]); 8415073Skarels } 8535458Sbostic pids[fileno(iop)] = pid; 8635458Sbostic return(iop); 872024Swnj } 882024Swnj 8935451Sbostic pclose(iop) 9035458Sbostic FILE *iop; 912024Swnj { 9235458Sbostic register int fdes; 93*36302Skarels int omask; 9435458Sbostic int stat_loc; 9535458Sbostic pid_t waitpid(); 962024Swnj 9735458Sbostic /* 9835458Sbostic * pclose returns -1 if stream is not associated with a 9935458Sbostic * `popened' command, or, if already `pclosed'. 10035458Sbostic */ 101*36302Skarels if (pids == NULL || pids[fdes = fileno(iop)] == 0) 10235458Sbostic return(-1); 10335458Sbostic (void)fclose(iop); 10435458Sbostic omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 10535458Sbostic stat_loc = waitpid(pids[fdes], &stat_loc, 0) == -1 ? 10635458Sbostic -1 : WEXITSTATUS(stat_loc); 10735458Sbostic (void)sigsetmask(omask); 10835458Sbostic pids[fdes] = 0; 10935458Sbostic return(stat_loc); 1102024Swnj } 111