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