1 /* 2 * Copyright (c) 1995, by Sun Microsystems, Inc. 3 * All rights reserved. 4 */ 5 6 #pragma ident "%Z%%M% %I% %E% SMI" 7 /* from UCB 5.2 85/06/05 */ 8 9 /* 10 * Copyright (c) 1980 Regents of the University of California. 11 * All rights reserved. The Berkeley software License Agreement 12 * specifies the terms and conditions for redistribution. 13 */ 14 15 #include <stdio.h> 16 #include <signal.h> 17 #include <vfork.h> 18 19 #define tst(a,b) (*mode == 'r'? (b) : (a)) 20 #define RDR 0 21 #define WTR 1 22 23 extern char *malloc(); 24 extern int execl(), vfork(), pipe(), close(), fcntl(); 25 26 static int *popen_pid; 27 static int nfiles; 28 29 FILE * 30 popen(cmd,mode) 31 char *cmd; 32 char *mode; 33 { 34 int p[2]; 35 register int *poptr; 36 register int myside, hisside, pid; 37 38 if (nfiles <= 0) 39 nfiles = getdtablesize(); 40 if (popen_pid == NULL) { 41 popen_pid = (int *)malloc(nfiles * sizeof *popen_pid); 42 if (popen_pid == NULL) 43 return (NULL); 44 for (pid = 0; pid < nfiles; pid++) 45 popen_pid[pid] = -1; 46 } 47 if (pipe(p) < 0) 48 return (NULL); 49 myside = tst(p[WTR], p[RDR]); 50 hisside = tst(p[RDR], p[WTR]); 51 if ((pid = vfork()) == 0) { 52 /* myside and hisside reverse roles in child */ 53 int stdio; 54 55 /* close all pipes from other popen's */ 56 for (poptr = popen_pid; poptr < popen_pid+nfiles; poptr++) { 57 if(*poptr >= 0) 58 close(poptr - popen_pid); 59 } 60 stdio = tst(0, 1); 61 (void) close(myside); 62 if (hisside != stdio) { 63 (void) dup2(hisside, stdio); 64 (void) close(hisside); 65 } 66 (void) execl("/bin/sh", "sh", "-c", cmd, (char *)NULL); 67 _exit(127); 68 } 69 if (pid == -1) { 70 close(myside); 71 close(hisside); 72 return (NULL); 73 } 74 popen_pid[myside] = pid; 75 close(hisside); 76 return (fdopen(myside, mode)); 77 } 78 79 int 80 pclose(ptr) 81 FILE *ptr; 82 { 83 int child = -1; 84 int pid, status, omask; 85 86 if (popen_pid != NULL) { 87 child = popen_pid[fileno(ptr)]; 88 popen_pid[fileno(ptr)] = -1; 89 } 90 fclose(ptr); 91 if (child == -1) 92 return (-1); 93 omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 94 while ((pid = waitpid(child, &status, 0)) != child && pid != -1) 95 ; 96 (void) sigsetmask(omask); 97 return (pid == -1 ? -1 : status); 98 } 99