122347Spst/* popen.c: A "safe" pipe open routine. 222347Spst 329964Sache%%% portions-copyright-cmetz-96 492906SmarkmPortions of this software are Copyright 1996-1999 by Craig Metz, All Rights 522347SpstReserved. The Inner Net License Version 2 applies to these portions of 622347Spstthe software. 722347SpstYou should have received a copy of the license with this software. If 822347Spstyou didn't get a copy, you may request one from <license@inner.net>. 922347Spst 1022347SpstPortions of this software are Copyright 1995 by Randall Atkinson and Dan 1122347SpstMcDonald, All Rights Reserved. All Rights under this copyright are assigned 1222347Spstto the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and 1322347SpstLicense Agreement applies to this software. 1422347Spst 1522347Spst History: 1622347Spst 1729964Sache Modified by cmetz for OPIE 2.31. Merged in some 4.4BSD-Lite fixes. 1822347Spst Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. 1922347Spst Removed useless string. ifdef around some headers. 2022347Spst Modified at NRL for OPIE 2.1. Optimized for only one pipe at a time. 2122347Spst Added minimal version of sigprocmask(). Moved some pid_t 2222347Spst dancing to the config headers. 2322347Spst Modified at NRL for OPIE 2.0. 2422347Spst Originally from BSD. 2522347Spst 26117501Skris$FreeBSD$ 2722347Spst*/ 2822347Spst/* 2929964Sache * Copyright (c) 1988, 1993, 1994 3029964Sache * The Regents of the University of California. All rights reserved. 3122347Spst * 3222347Spst * This code is derived from software written by Ken Arnold and 3322347Spst * published in UNIX Review, Vol. 6, No. 8. 3422347Spst * 3522347Spst * Redistribution and use in source and binary forms, with or without 3622347Spst * modification, are permitted provided that the following conditions 3722347Spst * are met: 3822347Spst * 1. Redistributions of source code must retain the above copyright 3922347Spst * notice, this list of conditions and the following disclaimer. 4022347Spst * 2. Redistributions in binary form must reproduce the above copyright 4122347Spst * notice, this list of conditions and the following disclaimer in the 4222347Spst * documentation and/or other materials provided with the distribution. 4322347Spst * 3. All advertising materials mentioning features or use of this software 4422347Spst * must display the following acknowledgement: 4522347Spst * This product includes software developed by the University of 4622347Spst * California, Berkeley and its contributors. 4722347Spst * 4. Neither the name of the University nor the names of its contributors 4822347Spst * may be used to endorse or promote products derived from this software 4922347Spst * without specific prior written permission. 5022347Spst * 5122347Spst * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 5222347Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 5322347Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 5422347Spst * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 5522347Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 5622347Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 5722347Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 5822347Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 5922347Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 6022347Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 6122347Spst * SUCH DAMAGE. 6222347Spst * 6322347Spst */ 6422347Spst 6522347Spst#include "opie_cfg.h" 6622347Spst 6722347Spst#include <sys/types.h> 6822347Spst#include <sys/wait.h> 6922347Spst#if HAVE_SIGNAL_H 7022347Spst#include <signal.h> 7122347Spst#endif /* HAVE_SIGNAL_H */ 7222347Spst#if HAVE_SYS_SIGNAL_H 7322347Spst#include <sys/signal.h> 7422347Spst#endif /* HAVE_SYS_SIGNAL_H */ 7522347Spst#if HAVE_UNISTD_H 7622347Spst#include <unistd.h> 7722347Spst#endif /* HAVE_UNISTD_H */ 7822347Spst#include <stdio.h> 7922347Spst#if HAVE_STDLIB_H 8022347Spst#include <stdlib.h> 8122347Spst#endif /* HAVE_STDLIB_H */ 8222347Spst#if HAVE_STRING_H 8322347Spst#include <string.h> 8422347Spst#endif /* HAVE_STRING_H */ 8522347Spst 8622347Spst#include "opie.h" 8722347Spst 88117501Skris#define MAXUSRARGS 100 89117501Skris#define MAXGLOBARGS 1000 90117501Skris 9122347Spstchar **ftpglob __P((register char *)); 9222347Spstchar **copyblk __P((char **)); 9322347SpstVOIDRET blkfree __P((char **)); 9422347Spst 9522347Spst/* 9629964Sache * Special version of popen which avoids call to shell. This ensures noone 9722347Spst * may create a pipe to a hidden program as a side effect of a list or dir 9822347Spst * command. 9922347Spst */ 10022347Spststatic pid_t child_pid = -1; 10122347Spststatic int pipe_fd; 10222347Spst 10329964Sacheextern char **environ; 10429964Sache 10522347SpstFILE *ftpd_popen FUNCTION((program, type), char *program AND char *type) 10622347Spst{ 10729964Sache char *cp; 10822347Spst FILE *iop; 10922347Spst int argc, gargc, pdes[2]; 110117501Skris char **pop, *argv[MAXUSRARGS], *gargv[MAXGLOBARGS], *vv[2]; 11122347Spst 11222347Spst if ((*type != 'r' && *type != 'w') || type[1]) 11322347Spst return (NULL); 11422347Spst 11522347Spst if (pipe(pdes) < 0) 11622347Spst return (NULL); 11722347Spst 11822347Spst /* break up string into pieces */ 119117501Skris for (argc = 0, cp = program; argc < MAXUSRARGS-1; cp = NULL) { 12022347Spst if (!(argv[argc++] = strtok(cp, " \t\n"))) 12122347Spst break; 122117501Skris } 123117501Skris argv[argc - 1] = NULL; 12422347Spst 12522347Spst /* glob each piece */ 12622347Spst gargv[0] = argv[0]; 127117501Skris for (gargc = argc = 1; argv[argc] && gargc < (MAXGLOBARGS-1); argc++) { 12822347Spst if (!(pop = (char **) ftpglob(argv[argc]))) { 12922347Spst /* globbing failed */ 13022347Spst vv[0] = argv[argc]; 13122347Spst vv[1] = NULL; 13222347Spst pop = (char **) copyblk(vv); 13322347Spst } 13422347Spst argv[argc] = (char *) pop; /* save to free later */ 135117501Skris while (*pop && gargc < MAXGLOBARGS-1) 13622347Spst gargv[gargc++] = *pop++; 13722347Spst } 13822347Spst gargv[gargc] = NULL; 13922347Spst 14022347Spst iop = NULL; 14122347Spst switch (child_pid = fork()) { 14222347Spst case -1: /* error */ 14322347Spst close(pdes[0]); 14422347Spst close(pdes[1]); 14522347Spst goto pfree; 14622347Spst /* NOTREACHED */ 14722347Spst case 0: /* child */ 14822347Spst if (*type == 'r') { 14922347Spst if (pdes[1] != 1) { 15022347Spst dup2(pdes[1], 1); 15122347Spst dup2(pdes[1], 2); /* stderr, too! */ 15222347Spst close(pdes[1]); 15322347Spst } 15422347Spst close(pdes[0]); 15522347Spst } else { 15622347Spst if (pdes[0] != 0) { 15722347Spst dup2(pdes[0], 0); 15822347Spst close(pdes[0]); 15922347Spst } 16022347Spst close(pdes[1]); 16122347Spst } 16229964Sache environ = NULL; 16322347Spst execv(gargv[0], gargv); 16422347Spst _exit(1); 16522347Spst } 16622347Spst 16722347Spst /* parent; assume fdopen can't fail... */ 16822347Spst if (*type == 'r') { 16922347Spst iop = fdopen(pipe_fd = pdes[0], type); 17022347Spst close(pdes[1]); 17122347Spst } else { 17222347Spst iop = fdopen(pipe_fd = pdes[1], type); 17322347Spst close(pdes[0]); 17422347Spst } 17522347Spst 17622347Spstpfree: for (argc = 1; argv[argc] != NULL; argc++) { 17722347Spst blkfree((char **) argv[argc]); 17822347Spst free((char *) argv[argc]); 17922347Spst } 18022347Spst return (iop); 18122347Spst} 18222347Spst 18322347Spstint ftpd_pclose FUNCTION((iop), FILE *iop) 18422347Spst{ 18522347Spst int status; 18622347Spst pid_t pid; 18722347Spst sigset_t omask, mask; 18822347Spst 18922347Spst sigemptyset(&mask); 19022347Spst sigaddset(&mask, SIGINT); 19122347Spst sigaddset(&mask, SIGQUIT); 19222347Spst sigaddset(&mask, SIGHUP); 19322347Spst 19422347Spst /* pclose returns -1 if stream is not associated with a `popened' command, 19522347Spst or, if already `pclosed'. */ 19622347Spst if ((child_pid < 0) || (fileno(iop) != pipe_fd)) 19722347Spst return (-1); 19822347Spst 19922347Spst fclose(iop); 20022347Spst sigprocmask(SIG_BLOCK, &mask, &omask); 20122347Spst 20222347Spst while ((pid = wait(&status)) != child_pid && (pid != -1)); 20322347Spst sigprocmask(SIG_SETMASK, &omask, NULL); 20422347Spst 20522347Spst child_pid = -1; 20622347Spst pipe_fd = -1; 20722347Spst 20829964Sache#if defined(WEXITSTATUS) && defined(WIFEXITED) 20929964Sache if ((pid > 0) && WIFEXITED(status)) 21029964Sache return WEXITSTATUS(status); 21129964Sache 21229964Sache return -1; 21329964Sache#else /* defined(WEXITSTATUS) && defined(WIFEXITED) */ 21422347Spst return (pid == -1 ? -1 : status.w_status); 21529964Sache#endif /* defined(WEXITSTATUS) && defined(WIFEXITED) */ 21622347Spst} 217