1*35675Sbostic /* 2*35675Sbostic * Copyright (c) 1988 The Regents of the University of California. 3*35675Sbostic * All rights reserved. 4*35675Sbostic * 5*35675Sbostic * This code is derived from software written by Ken Arnold and 6*35675Sbostic * published in UNIX Review, Vol. 6, No. 8. 7*35675Sbostic * 8*35675Sbostic * Redistribution and use in source and binary forms are permitted 9*35675Sbostic * provided that the above copyright notice and this paragraph are 10*35675Sbostic * duplicated in all such forms and that any documentation, 11*35675Sbostic * advertising materials, and other materials related to such 12*35675Sbostic * distribution and use acknowledge that the software was developed 13*35675Sbostic * by the University of California, Berkeley. The name of the 14*35675Sbostic * University may not be used to endorse or promote products derived 15*35675Sbostic * from this software without specific prior written permission. 16*35675Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17*35675Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18*35675Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19*35675Sbostic * 20*35675Sbostic * static char sccsid[] = "@(#)popen.c 5.7 (Berkeley) 9/1/88"; 21*35675Sbostic */ 22*35675Sbostic 23*35675Sbostic #ifndef lint 24*35675Sbostic static char sccsid[] = "@(#)popen.c 5.1 (Berkeley) 09/22/88"; 25*35675Sbostic #endif /* not lint */ 26*35675Sbostic 27*35675Sbostic #include <sys/param.h> 28*35675Sbostic #include <sys/signal.h> 29*35675Sbostic #include <sys/wait.h> 30*35675Sbostic #include <stdio.h> 31*35675Sbostic 32*35675Sbostic static uid_t *pids; 33*35675Sbostic static int fds; 34*35675Sbostic 35*35675Sbostic FILE * 36*35675Sbostic popen(program, type) 37*35675Sbostic char *program, *type; 38*35675Sbostic { 39*35675Sbostic FILE *iop; 40*35675Sbostic int pdes[2], pid; 41*35675Sbostic char *malloc(); 42*35675Sbostic 43*35675Sbostic if (*type != 'r' && *type != 'w' || type[1]) 44*35675Sbostic return(NULL); 45*35675Sbostic 46*35675Sbostic if (!pids) { 47*35675Sbostic if ((fds = getdtablesize()) <= 0) 48*35675Sbostic return(NULL); 49*35675Sbostic if (!(pids = 50*35675Sbostic (uid_t *)malloc((u_int)(fds * sizeof(uid_t))))) 51*35675Sbostic return(NULL); 52*35675Sbostic bzero(pids, fds * sizeof(uid_t)); 53*35675Sbostic } 54*35675Sbostic if (pipe(pdes) < 0) 55*35675Sbostic return(NULL); 56*35675Sbostic switch(pid = vfork()) { 57*35675Sbostic case -1: /* error */ 58*35675Sbostic (void)close(pdes[0]); 59*35675Sbostic (void)close(pdes[1]); 60*35675Sbostic return(NULL); 61*35675Sbostic /* NOTREACHED */ 62*35675Sbostic case 0: /* child */ 63*35675Sbostic if (*type == 'r') { 64*35675Sbostic if (pdes[1] != 1) { 65*35675Sbostic dup2(pdes[1], 1); 66*35675Sbostic (void)close(pdes[1]); 67*35675Sbostic } 68*35675Sbostic (void)close(pdes[0]); 69*35675Sbostic } else { 70*35675Sbostic if (pdes[0] != 0) { 71*35675Sbostic dup2(pdes[0], 0); 72*35675Sbostic (void)close(pdes[0]); 73*35675Sbostic } 74*35675Sbostic (void)close(pdes[1]); 75*35675Sbostic } 76*35675Sbostic execl("/bin/sh", "sh", "-c", program, NULL); 77*35675Sbostic _exit(127); 78*35675Sbostic /* NOTREACHED */ 79*35675Sbostic } 80*35675Sbostic /* parent; assume fdopen can't fail... */ 81*35675Sbostic if (*type == 'r') { 82*35675Sbostic iop = fdopen(pdes[0], type); 83*35675Sbostic (void)close(pdes[1]); 84*35675Sbostic } else { 85*35675Sbostic iop = fdopen(pdes[1], type); 86*35675Sbostic (void)close(pdes[0]); 87*35675Sbostic } 88*35675Sbostic pids[fileno(iop)] = pid; 89*35675Sbostic return(iop); 90*35675Sbostic } 91*35675Sbostic 92*35675Sbostic pclose(iop) 93*35675Sbostic FILE *iop; 94*35675Sbostic { 95*35675Sbostic register int fdes; 96*35675Sbostic long omask; 97*35675Sbostic int stat_loc; 98*35675Sbostic pid_t waitpid(); 99*35675Sbostic 100*35675Sbostic /* 101*35675Sbostic * pclose returns -1 if stream is not associated with a 102*35675Sbostic * `popened' command, or, if already `pclosed'. 103*35675Sbostic */ 104*35675Sbostic if (pids[fdes = fileno(iop)] == 0) 105*35675Sbostic return(-1); 106*35675Sbostic (void)fclose(iop); 107*35675Sbostic omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 108*35675Sbostic stat_loc = waitpid(pids[fdes], &stat_loc, 0) == -1 ? 109*35675Sbostic -1 : WEXITSTATUS(stat_loc); 110*35675Sbostic (void)sigsetmask(omask); 111*35675Sbostic pids[fdes] = 0; 112*35675Sbostic return(stat_loc); 113*35675Sbostic } 114