135675Sbostic /* 235675Sbostic * Copyright (c) 1988 The Regents of the University of California. 335675Sbostic * All rights reserved. 435675Sbostic * 535675Sbostic * This code is derived from software written by Ken Arnold and 635675Sbostic * published in UNIX Review, Vol. 6, No. 8. 735675Sbostic * 835675Sbostic * Redistribution and use in source and binary forms are permitted 935675Sbostic * provided that the above copyright notice and this paragraph are 1035675Sbostic * duplicated in all such forms and that any documentation, 1135675Sbostic * advertising materials, and other materials related to such 1235675Sbostic * distribution and use acknowledge that the software was developed 1335675Sbostic * by the University of California, Berkeley. The name of the 1435675Sbostic * University may not be used to endorse or promote products derived 1535675Sbostic * from this software without specific prior written permission. 1635675Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1735675Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1835675Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1935675Sbostic * 2035675Sbostic * static char sccsid[] = "@(#)popen.c 5.7 (Berkeley) 9/1/88"; 2135675Sbostic */ 2235675Sbostic 2335675Sbostic #ifndef lint 24*36445Sbostic static char sccsid[] = "@(#)popen.c 5.6 (Berkeley) 12/19/88"; 2535675Sbostic #endif /* not lint */ 2635675Sbostic 2735676Sbostic #include <sys/types.h> 2835675Sbostic #include <sys/signal.h> 2936304Skarels #include <sys/wait.h> 3035675Sbostic #include <stdio.h> 3135675Sbostic 3235676Sbostic /* 3335676Sbostic * Special version of popen which avoids call to shell. This insures noone 3435676Sbostic * may create a pipe to a hidden program as a side effect of a list or dir 3535676Sbostic * command. 3635676Sbostic */ 3736304Skarels static int *pids; 3835675Sbostic static int fds; 3935675Sbostic 4035675Sbostic FILE * 4136276Sbostic ftpd_popen(program, type) 4235675Sbostic char *program, *type; 4335675Sbostic { 4435676Sbostic register char *cp; 4535675Sbostic FILE *iop; 4635676Sbostic int argc, gargc, pdes[2], pid; 4735676Sbostic char **pop, *argv[100], *gargv[1000], *vv[2]; 4836304Skarels extern char **glob(), **copyblk(), *strtok(), *malloc(); 4935675Sbostic 5035675Sbostic if (*type != 'r' && *type != 'w' || type[1]) 5135675Sbostic return(NULL); 5235675Sbostic 5335675Sbostic if (!pids) { 5435675Sbostic if ((fds = getdtablesize()) <= 0) 5535675Sbostic return(NULL); 5636304Skarels if ((pids = (int *)malloc((u_int)(fds * sizeof(int)))) == NULL) 5735675Sbostic return(NULL); 5836304Skarels bzero((char *)pids, fds * sizeof(int)); 5935675Sbostic } 6035675Sbostic if (pipe(pdes) < 0) 6135675Sbostic return(NULL); 6235676Sbostic 6335676Sbostic /* break up string into pieces */ 6435676Sbostic for (argc = 0, cp = program;; cp = NULL) 6535676Sbostic if (!(argv[argc++] = strtok(cp, " \t\n"))) 6635676Sbostic break; 6735676Sbostic 6835676Sbostic /* glob each piece */ 6935676Sbostic gargv[0] = argv[0]; 7035676Sbostic for (gargc = argc = 1; argv[argc]; argc++) { 7135676Sbostic if (!(pop = glob(argv[argc]))) { /* globbing failed */ 7235676Sbostic vv[0] = argv[argc]; 7335676Sbostic vv[1] = NULL; 7435676Sbostic pop = copyblk(vv); 7535676Sbostic } 7635676Sbostic argv[argc] = (char *)pop; /* save to free later */ 7735676Sbostic while (*pop && gargc < 1000) 7835676Sbostic gargv[gargc++] = *pop++; 7935676Sbostic } 8035676Sbostic gargv[gargc] = NULL; 8135676Sbostic 8235676Sbostic iop = NULL; 8335675Sbostic switch(pid = vfork()) { 8435675Sbostic case -1: /* error */ 8535675Sbostic (void)close(pdes[0]); 8635675Sbostic (void)close(pdes[1]); 8736434Sbostic goto pfree; 8835675Sbostic /* NOTREACHED */ 8935675Sbostic case 0: /* child */ 9035675Sbostic if (*type == 'r') { 9135675Sbostic if (pdes[1] != 1) { 9235675Sbostic dup2(pdes[1], 1); 93*36445Sbostic dup2(pdes[1], 2); /* stderr, too! */ 9435675Sbostic (void)close(pdes[1]); 9535675Sbostic } 9635675Sbostic (void)close(pdes[0]); 9735675Sbostic } else { 9835675Sbostic if (pdes[0] != 0) { 9935675Sbostic dup2(pdes[0], 0); 10035675Sbostic (void)close(pdes[0]); 10135675Sbostic } 10235675Sbostic (void)close(pdes[1]); 10335675Sbostic } 10435676Sbostic execv(gargv[0], gargv); 10535676Sbostic _exit(1); 10635675Sbostic } 10735675Sbostic /* parent; assume fdopen can't fail... */ 10835675Sbostic if (*type == 'r') { 10935675Sbostic iop = fdopen(pdes[0], type); 11035675Sbostic (void)close(pdes[1]); 11135675Sbostic } else { 11235675Sbostic iop = fdopen(pdes[1], type); 11335675Sbostic (void)close(pdes[0]); 11435675Sbostic } 11535675Sbostic pids[fileno(iop)] = pid; 11635676Sbostic 11736434Sbostic pfree: for (argc = 1; argv[argc] != NULL; argc++) { 11835676Sbostic blkfree((char **)argv[argc]); 11936434Sbostic free((char *)argv[argc]); 12036434Sbostic } 12135675Sbostic return(iop); 12235675Sbostic } 12335675Sbostic 12436304Skarels ftpd_pclose(iop) 12535675Sbostic FILE *iop; 12635675Sbostic { 12735675Sbostic register int fdes; 12836304Skarels int omask; 12936304Skarels union wait stat_loc; 13036304Skarels int pid; 13135675Sbostic 13235675Sbostic /* 13335675Sbostic * pclose returns -1 if stream is not associated with a 13435675Sbostic * `popened' command, or, if already `pclosed'. 13535675Sbostic */ 13636304Skarels if (pids == 0 || pids[fdes = fileno(iop)] == 0) 13735675Sbostic return(-1); 13835675Sbostic (void)fclose(iop); 13935675Sbostic omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 14035676Sbostic while ((pid = wait(&stat_loc)) != pids[fdes] && pid != -1); 14135675Sbostic (void)sigsetmask(omask); 14235675Sbostic pids[fdes] = 0; 14336304Skarels return(pid == -1 ? -1 : stat_loc.w_status); 14435675Sbostic } 145