1*22101Smckusick /* 2*22101Smckusick * Copyright (c) 1980 Regents of the University of California. 3*22101Smckusick * All rights reserved. The Berkeley software License Agreement 4*22101Smckusick * specifies the terms and conditions for redistribution. 5*22101Smckusick */ 616676Ssam 7*22101Smckusick #ifndef lint 8*22101Smckusick static char sccsid[] = "@(#)popen.c 5.2 (Berkeley) 06/05/85"; 9*22101Smckusick #endif not lint 10*22101Smckusick 112024Swnj #include <stdio.h> 122024Swnj #include <signal.h> 1317345Slepreau #include <sys/param.h> 1416676Ssam 152024Swnj #define tst(a,b) (*mode == 'r'? (b) : (a)) 162024Swnj #define RDR 0 172024Swnj #define WTR 1 182024Swnj 1918246Sserge extern char *malloc(); 2016676Ssam 2118246Sserge static int *popen_pid; 2218246Sserge static int nfiles; 2318246Sserge 242024Swnj FILE * 252024Swnj popen(cmd,mode) 2616676Ssam char *cmd; 2716676Ssam char *mode; 282024Swnj { 292024Swnj int p[2]; 3016676Ssam int myside, hisside, pid; 312024Swnj 3218246Sserge if (nfiles <= 0) 3318246Sserge nfiles = getdtablesize(); 3418246Sserge if (popen_pid == NULL) { 3518246Sserge popen_pid = (int *)malloc(nfiles * sizeof *popen_pid); 3618246Sserge if (popen_pid == NULL) 3718246Sserge return (NULL); 3818246Sserge for (pid = 0; pid < nfiles; pid++) 3918246Sserge popen_pid[pid] = -1; 4018246Sserge } 4116676Ssam if (pipe(p) < 0) 4216676Ssam return (NULL); 432024Swnj myside = tst(p[WTR], p[RDR]); 442024Swnj hisside = tst(p[RDR], p[WTR]); 4518246Sserge if ((pid = vfork()) == 0) { 462024Swnj /* myside and hisside reverse roles in child */ 472024Swnj close(myside); 4814718Ssam if (hisside != tst(0, 1)) { 4914718Ssam dup2(hisside, tst(0, 1)); 5014718Ssam close(hisside); 5114718Ssam } 5218246Sserge execl("/bin/sh", "sh", "-c", cmd, (char *)NULL); 5318246Sserge _exit(127); 542024Swnj } 5516676Ssam if (pid == -1) { 5615073Skarels close(myside); 5715073Skarels close(hisside); 5816676Ssam return (NULL); 5915073Skarels } 602024Swnj popen_pid[myside] = pid; 612024Swnj close(hisside); 6216676Ssam return (fdopen(myside, mode)); 632024Swnj } 642024Swnj 652024Swnj pclose(ptr) 6616676Ssam FILE *ptr; 672024Swnj { 6816676Ssam int child, pid, status, omask; 692024Swnj 7016676Ssam child = popen_pid[fileno(ptr)]; 7118246Sserge popen_pid[fileno(ptr)] = -1; 722024Swnj fclose(ptr); 7318246Sserge if (child == -1) 7418246Sserge return (-1); 7518246Sserge omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 7616676Ssam while ((pid = wait(&status)) != child && pid != -1) 772024Swnj ; 7816676Ssam (void) sigsetmask(omask); 7916676Ssam return (pid == -1 ? -1 : status); 802024Swnj } 81