122101Smckusick /* 235451Sbostic * Copyright (c) 1988 The Regents of the University of California. 335451Sbostic * All rights reserved. 435451Sbostic * 5*35458Sbostic * This code is derived from software written by Ken Arnold and 6*35458Sbostic * 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*35458Sbostic static char sccsid[] = "@(#)popen.c 5.7 (Berkeley) 09/01/88"; 2335451Sbostic #endif /* LIBC_SCCS and not lint */ 2422101Smckusick 25*35458Sbostic #include <sys/param.h> 26*35458Sbostic #include <sys/signal.h> 27*35458Sbostic #include <sys/wait.h> 282024Swnj #include <stdio.h> 2916676Ssam 30*35458Sbostic static uid_t *pids; 31*35458Sbostic static int fds; 322024Swnj 332024Swnj FILE * 3435451Sbostic popen(program, type) 35*35458Sbostic char *program, *type; 362024Swnj { 37*35458Sbostic FILE *iop; 3835451Sbostic int pdes[2], pid; 39*35458Sbostic char *malloc(); 402024Swnj 41*35458Sbostic if (*type != 'r' && *type != 'w' || type[1]) 42*35458Sbostic return(NULL); 43*35458Sbostic 44*35458Sbostic if (!pids) { 45*35458Sbostic if ((fds = getdtablesize()) <= 0) 46*35458Sbostic return(NULL); 47*35458Sbostic if (!(pids = 48*35458Sbostic (uid_t *)malloc((u_int)(fds * sizeof(uid_t))))) 49*35458Sbostic return(NULL); 50*35458Sbostic bzero(pids, fds * sizeof(uid_t)); 51*35458Sbostic } 5235451Sbostic if (pipe(pdes) < 0) 53*35458Sbostic return(NULL); 54*35458Sbostic switch(pid = vfork()) { 55*35458Sbostic case -1: /* error */ 56*35458Sbostic (void)close(pdes[0]); 57*35458Sbostic (void)close(pdes[1]); 58*35458Sbostic return(NULL); 59*35458Sbostic /* NOTREACHED */ 60*35458Sbostic case 0: /* child */ 6135451Sbostic if (*type == 'r') { 62*35458Sbostic if (pdes[1] != 1) { 63*35458Sbostic dup2(pdes[1], 1); 64*35458Sbostic (void)close(pdes[1]); 65*35458Sbostic } 66*35458Sbostic (void)close(pdes[0]); 67*35458Sbostic } else { 68*35458Sbostic if (pdes[0] != 0) { 69*35458Sbostic dup2(pdes[0], 0); 70*35458Sbostic (void)close(pdes[0]); 71*35458Sbostic } 72*35458Sbostic (void)close(pdes[1]); 7314718Ssam } 7435451Sbostic execl("/bin/sh", "sh", "-c", program, NULL); 75*35458Sbostic _exit(127); 7635451Sbostic /* NOTREACHED */ 772024Swnj } 78*35458Sbostic /* parent; assume fdopen can't fail... */ 79*35458Sbostic if (*type == 'r') { 80*35458Sbostic iop = fdopen(pdes[0], type); 81*35458Sbostic (void)close(pdes[1]); 82*35458Sbostic } else { 83*35458Sbostic iop = fdopen(pdes[1], type); 84*35458Sbostic (void)close(pdes[0]); 8515073Skarels } 86*35458Sbostic pids[fileno(iop)] = pid; 87*35458Sbostic return(iop); 882024Swnj } 892024Swnj 9035451Sbostic pclose(iop) 91*35458Sbostic FILE *iop; 922024Swnj { 93*35458Sbostic register int fdes; 94*35458Sbostic long omask; 95*35458Sbostic int stat_loc; 96*35458Sbostic pid_t waitpid(); 972024Swnj 98*35458Sbostic /* 99*35458Sbostic * pclose returns -1 if stream is not associated with a 100*35458Sbostic * `popened' command, or, if already `pclosed'. 101*35458Sbostic */ 102*35458Sbostic if (pids[fdes = fileno(iop)] == 0) 103*35458Sbostic return(-1); 104*35458Sbostic (void)fclose(iop); 105*35458Sbostic omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 106*35458Sbostic stat_loc = waitpid(pids[fdes], &stat_loc, 0) == -1 ? 107*35458Sbostic -1 : WEXITSTATUS(stat_loc); 108*35458Sbostic (void)sigsetmask(omask); 109*35458Sbostic pids[fdes] = 0; 110*35458Sbostic return(stat_loc); 1112024Swnj } 112