1 /* @(#)popen.c 4.5 (Berkeley) 07/06/84 */ 2 3 #include <stdio.h> 4 #include <signal.h> 5 6 #define tst(a,b) (*mode == 'r'? (b) : (a)) 7 #define RDR 0 8 #define WTR 1 9 10 static int popen_pid[20]; 11 12 FILE * 13 popen(cmd,mode) 14 char *cmd; 15 char *mode; 16 { 17 int p[2]; 18 int myside, hisside, pid; 19 20 if (pipe(p) < 0) 21 return (NULL); 22 myside = tst(p[WTR], p[RDR]); 23 hisside = tst(p[RDR], p[WTR]); 24 if ((pid = fork()) == 0) { 25 /* myside and hisside reverse roles in child */ 26 close(myside); 27 if (hisside != tst(0, 1)) { 28 dup2(hisside, tst(0, 1)); 29 close(hisside); 30 } 31 execl("/bin/sh", "sh", "-c", cmd, 0); 32 _exit(1); 33 } 34 if (pid == -1) { 35 close(myside); 36 close(hisside); 37 return (NULL); 38 } 39 popen_pid[myside] = pid; 40 close(hisside); 41 return (fdopen(myside, mode)); 42 } 43 44 pclose(ptr) 45 FILE *ptr; 46 { 47 int child, pid, status, omask; 48 49 child = popen_pid[fileno(ptr)]; 50 fclose(ptr); 51 #define mask(s) (1 << ((s)-1)) 52 omask = sigblock(mask(SIGINT)|mask(SIGQUIT)|mask(SIGHUP)); 53 while ((pid = wait(&status)) != child && pid != -1) 54 ; 55 (void) sigsetmask(omask); 56 return (pid == -1 ? -1 : status); 57 } 58