popen.c revision 45369
12311Sjkh/* 22311Sjkh * Copyright (c) 1988 The Regents of the University of California. 32311Sjkh * All rights reserved. 42311Sjkh * 52311Sjkh * This code is derived from software written by Ken Arnold and 62311Sjkh * published in UNIX Review, Vol. 6, No. 8. 72311Sjkh * 82311Sjkh * Redistribution and use in source and binary forms are permitted 92311Sjkh * provided that the above copyright notice and this paragraph are 102311Sjkh * duplicated in all such forms and that any documentation, 112311Sjkh * advertising materials, and other materials related to such 122311Sjkh * distribution and use acknowledge that the software was developed 132311Sjkh * by the University of California, Berkeley. The name of the 142311Sjkh * University may not be used to endorse or promote products derived 152311Sjkh * from this software without specific prior written permission. 162311Sjkh * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 172311Sjkh * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 182311Sjkh * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 192311Sjkh * 202311Sjkh */ 212311Sjkh 222311Sjkh/* this came out of the ftpd sources; it's been modified to avoid the 232311Sjkh * globbing stuff since we don't need it. also execvp instead of execv. 242311Sjkh */ 252311Sjkh 262311Sjkh#ifndef lint 2729452Scharnier#if 0 282311Sjkhstatic char sccsid[] = "@(#)popen.c 5.7 (Berkeley) 2/14/89"; 2929452Scharnier#endif 3029452Scharnierstatic const char rcsid[] = 3145369Speter "$Id: popen.c,v 1.5 1997/09/15 06:39:07 charnier Exp $"; 322311Sjkh#endif /* not lint */ 332311Sjkh 342311Sjkh#include "cron.h" 352311Sjkh#include <sys/signal.h> 3645369Speter#include <fcntl.h> 372311Sjkh 382311Sjkh 3920573Spst#define MAX_ARGS 100 402311Sjkh#define WANT_GLOBBING 0 412311Sjkh 422311Sjkh/* 432311Sjkh * Special version of popen which avoids call to shell. This insures noone 442311Sjkh * may create a pipe to a hidden program as a side effect of a list or dir 452311Sjkh * command. 462311Sjkh */ 472311Sjkhstatic PID_T *pids; 482311Sjkhstatic int fds; 492311Sjkh 502311SjkhFILE * 512311Sjkhcron_popen(program, type) 522311Sjkh char *program, *type; 532311Sjkh{ 542311Sjkh register char *cp; 552311Sjkh FILE *iop; 562311Sjkh int argc, pdes[2]; 572311Sjkh PID_T pid; 5820573Spst char *argv[MAX_ARGS + 1]; 592311Sjkh#if WANT_GLOBBING 602311Sjkh char **pop, *vv[2]; 612311Sjkh int gargc; 622311Sjkh char *gargv[1000]; 632311Sjkh extern char **glob(), **copyblk(); 642311Sjkh#endif 652311Sjkh 6629452Scharnier if ((*type != 'r' && *type != 'w') || type[1]) 672311Sjkh return(NULL); 682311Sjkh 692311Sjkh if (!pids) { 702311Sjkh if ((fds = getdtablesize()) <= 0) 712311Sjkh return(NULL); 722311Sjkh if (!(pids = (PID_T *)malloc((u_int)(fds * sizeof(PID_T))))) 732311Sjkh return(NULL); 742311Sjkh bzero((char *)pids, fds * sizeof(PID_T)); 752311Sjkh } 762311Sjkh if (pipe(pdes) < 0) 772311Sjkh return(NULL); 782311Sjkh 792311Sjkh /* break up string into pieces */ 8020573Spst for (argc = 0, cp = program; argc < MAX_ARGS; cp = NULL) 812311Sjkh if (!(argv[argc++] = strtok(cp, " \t\n"))) 822311Sjkh break; 832311Sjkh 842311Sjkh#if WANT_GLOBBING 852311Sjkh /* glob each piece */ 862311Sjkh gargv[0] = argv[0]; 872311Sjkh for (gargc = argc = 1; argv[argc]; argc++) { 882311Sjkh if (!(pop = glob(argv[argc]))) { /* globbing failed */ 892311Sjkh vv[0] = argv[argc]; 902311Sjkh vv[1] = NULL; 912311Sjkh pop = copyblk(vv); 922311Sjkh } 932311Sjkh argv[argc] = (char *)pop; /* save to free later */ 942311Sjkh while (*pop && gargc < 1000) 952311Sjkh gargv[gargc++] = *pop++; 962311Sjkh } 972311Sjkh gargv[gargc] = NULL; 982311Sjkh#endif 992311Sjkh 1002311Sjkh iop = NULL; 1012311Sjkh switch(pid = vfork()) { 1022311Sjkh case -1: /* error */ 1032311Sjkh (void)close(pdes[0]); 1042311Sjkh (void)close(pdes[1]); 1052311Sjkh goto pfree; 1062311Sjkh /* NOTREACHED */ 1072311Sjkh case 0: /* child */ 1082311Sjkh if (*type == 'r') { 10945369Speter /* Do not share our parent's stdin */ 11045369Speter (void)close(0); 11145369Speter (void)open("/dev/null", O_RDWR); 1122311Sjkh if (pdes[1] != 1) { 1132311Sjkh dup2(pdes[1], 1); 1142311Sjkh dup2(pdes[1], 2); /* stderr, too! */ 1152311Sjkh (void)close(pdes[1]); 1162311Sjkh } 1172311Sjkh (void)close(pdes[0]); 1182311Sjkh } else { 1192311Sjkh if (pdes[0] != 0) { 1202311Sjkh dup2(pdes[0], 0); 1212311Sjkh (void)close(pdes[0]); 1222311Sjkh } 12345369Speter /* Hack: stdout gets revoked */ 12445369Speter (void)close(1); 12545369Speter (void)open("/dev/null", O_RDWR); 12645369Speter (void)close(2); 12745369Speter (void)open("/dev/null", O_RDWR); 1282311Sjkh (void)close(pdes[1]); 1292311Sjkh } 1302311Sjkh#if WANT_GLOBBING 1312311Sjkh execvp(gargv[0], gargv); 1322311Sjkh#else 1332311Sjkh execvp(argv[0], argv); 1342311Sjkh#endif 1352311Sjkh _exit(1); 1362311Sjkh } 1372311Sjkh /* parent; assume fdopen can't fail... */ 1382311Sjkh if (*type == 'r') { 1392311Sjkh iop = fdopen(pdes[0], type); 1402311Sjkh (void)close(pdes[1]); 1412311Sjkh } else { 1422311Sjkh iop = fdopen(pdes[1], type); 1432311Sjkh (void)close(pdes[0]); 1442311Sjkh } 1452311Sjkh pids[fileno(iop)] = pid; 1462311Sjkh 1472311Sjkhpfree: 1482311Sjkh#if WANT_GLOBBING 1492311Sjkh for (argc = 1; argv[argc] != NULL; argc++) { 1502311Sjkh/* blkfree((char **)argv[argc]); */ 1512311Sjkh free((char *)argv[argc]); 1522311Sjkh } 1532311Sjkh#endif 1542311Sjkh return(iop); 1552311Sjkh} 1562311Sjkh 1572311Sjkhint 1582311Sjkhcron_pclose(iop) 1592311Sjkh FILE *iop; 1602311Sjkh{ 1612311Sjkh register int fdes; 1622311Sjkh int omask; 1632311Sjkh WAIT_T stat_loc; 1642311Sjkh PID_T pid; 1652311Sjkh 1662311Sjkh /* 1672311Sjkh * pclose returns -1 if stream is not associated with a 1682311Sjkh * `popened' command, or, if already `pclosed'. 1692311Sjkh */ 1702311Sjkh if (pids == 0 || pids[fdes = fileno(iop)] == 0) 1712311Sjkh return(-1); 1722311Sjkh (void)fclose(iop); 1732311Sjkh omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 1742311Sjkh while ((pid = wait(&stat_loc)) != pids[fdes] && pid != -1) 1752311Sjkh ; 1762311Sjkh (void)sigsetmask(omask); 1772311Sjkh pids[fdes] = 0; 1782311Sjkh return (pid == -1 ? -1 : WEXITSTATUS(stat_loc)); 1792311Sjkh} 180