1 /* @(#)popen.c 4.7 (Berkeley) 03/04/85 */ 2 3 #include <stdio.h> 4 #include <signal.h> 5 #include <sys/param.h> 6 7 #define tst(a,b) (*mode == 'r'? (b) : (a)) 8 #define RDR 0 9 #define WTR 1 10 11 extern char *malloc(); 12 13 static int *popen_pid; 14 static int nfiles; 15 16 FILE * 17 popen(cmd,mode) 18 char *cmd; 19 char *mode; 20 { 21 int p[2]; 22 int myside, hisside, pid; 23 24 if (nfiles <= 0) 25 nfiles = getdtablesize(); 26 if (popen_pid == NULL) { 27 popen_pid = (int *)malloc(nfiles * sizeof *popen_pid); 28 if (popen_pid == NULL) 29 return (NULL); 30 for (pid = 0; pid < nfiles; pid++) 31 popen_pid[pid] = -1; 32 } 33 if (pipe(p) < 0) 34 return (NULL); 35 myside = tst(p[WTR], p[RDR]); 36 hisside = tst(p[RDR], p[WTR]); 37 if ((pid = vfork()) == 0) { 38 /* myside and hisside reverse roles in child */ 39 close(myside); 40 if (hisside != tst(0, 1)) { 41 dup2(hisside, tst(0, 1)); 42 close(hisside); 43 } 44 execl("/bin/sh", "sh", "-c", cmd, (char *)NULL); 45 _exit(127); 46 } 47 if (pid == -1) { 48 close(myside); 49 close(hisside); 50 return (NULL); 51 } 52 popen_pid[myside] = pid; 53 close(hisside); 54 return (fdopen(myside, mode)); 55 } 56 57 pclose(ptr) 58 FILE *ptr; 59 { 60 int child, pid, status, omask; 61 62 child = popen_pid[fileno(ptr)]; 63 popen_pid[fileno(ptr)] = -1; 64 fclose(ptr); 65 if (child == -1) 66 return (-1); 67 omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 68 while ((pid = wait(&status)) != child && pid != -1) 69 ; 70 (void) sigsetmask(omask); 71 return (pid == -1 ? -1 : status); 72 } 73