popen.c revision 117501
153813Simp/* popen.c: A "safe" pipe open routine. 2180314Simp 3100213Simp%%% portions-copyright-cmetz-96 452506SimpPortions of this software are Copyright 1996-1999 by Craig Metz, All Rights 552506SimpReserved. The Inner Net License Version 2 applies to these portions of 6140752Simpthe software. 752506SimpYou should have received a copy of the license with this software. If 852506Simpyou didn't get a copy, you may request one from <license@inner.net>. 952506Simp 1052506SimpPortions of this software are Copyright 1995 by Randall Atkinson and Dan 1152506SimpMcDonald, All Rights Reserved. All Rights under this copyright are assigned 1252506Simpto the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and 1352506SimpLicense Agreement applies to this software. 1452506Simp 1552506Simp History: 1652506Simp 1752506Simp Modified by cmetz for OPIE 2.31. Merged in some 4.4BSD-Lite fixes. 1852506Simp Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. 1952506Simp Removed useless string. ifdef around some headers. 2052506Simp Modified at NRL for OPIE 2.1. Optimized for only one pipe at a time. 2152506Simp Added minimal version of sigprocmask(). Moved some pid_t 2252506Simp dancing to the config headers. 2352506Simp Modified at NRL for OPIE 2.0. 2452506Simp Originally from BSD. 2552506Simp 2652506Simp$FreeBSD: head/contrib/opie/popen.c 117501 2003-07-13 05:59:50Z kris $ 2752506Simp*/ 2852506Simp/* 2952506Simp * Copyright (c) 1988, 1993, 1994 3052506Simp * The Regents of the University of California. All rights reserved. 3152506Simp * 3252506Simp * This code is derived from software written by Ken Arnold and 3352506Simp * published in UNIX Review, Vol. 6, No. 8. 34140752Simp * 35140752Simp * Redistribution and use in source and binary forms, with or without 36140752Simp * modification, are permitted provided that the following conditions 37140752Simp * are met: 38140752Simp * 1. Redistributions of source code must retain the above copyright 39140752Simp * notice, this list of conditions and the following disclaimer. 40140752Simp * 2. Redistributions in binary form must reproduce the above copyright 41140752Simp * notice, this list of conditions and the following disclaimer in the 42140752Simp * documentation and/or other materials provided with the distribution. 43140752Simp * 3. All advertising materials mentioning features or use of this software 44140752Simp * must display the following acknowledgement: 45140752Simp * This product includes software developed by the University of 46140752Simp * California, Berkeley and its contributors. 47140752Simp * 4. Neither the name of the University nor the names of its contributors 48140752Simp * may be used to endorse or promote products derived from this software 49140752Simp * without specific prior written permission. 50140752Simp * 51140752Simp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 52140752Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 53140752Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 54140752Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 55140752Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 56140752Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 57140752Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58140752Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 59140752Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 60140752Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 6152506Simp * SUCH DAMAGE. 62140749Simp * 63166788Simp */ 64140749Simp 65140749Simp#include "opie_cfg.h" 66140749Simp 67149869Simp#include <sys/types.h> 68149869Simp#include <sys/wait.h> 69149561Simp#if HAVE_SIGNAL_H 70166787Simp#include <signal.h> 71166787Simp#endif /* HAVE_SIGNAL_H */ 72166787Simp#if HAVE_SYS_SIGNAL_H 73166787Simp#include <sys/signal.h> 74149869Simp#endif /* HAVE_SYS_SIGNAL_H */ 75149869Simp#if HAVE_UNISTD_H 7652506Simp#include <unistd.h> 77140793Simp#endif /* HAVE_UNISTD_H */ 78189680Simp#include <stdio.h> 79140793Simp#if HAVE_STDLIB_H 8058545Simp#include <stdlib.h> 8152506Simp#endif /* HAVE_STDLIB_H */ 8265039Simp#if HAVE_STRING_H 8365039Simp#include <string.h> 84149869Simp#endif /* HAVE_STRING_H */ 8552506Simp 86140793Simp#include "opie.h" 87149869Simp 88149869Simp#define MAXUSRARGS 100 89149869Simp#define MAXGLOBARGS 1000 90149869Simp 91149869Simpchar **ftpglob __P((register char *)); 92149869Simpchar **copyblk __P((char **)); 93149869SimpVOIDRET blkfree __P((char **)); 94149869Simp 95149869Simp/* 96140793Simp * Special version of popen which avoids call to shell. This ensures noone 9752506Simp * may create a pipe to a hidden program as a side effect of a list or dir 9852506Simp * command. 9952506Simp */ 10052506Simpstatic pid_t child_pid = -1; 10158545Simpstatic int pipe_fd; 10252506Simp 10386455Simpextern char **environ; 10479270Simp 105107359SnonFILE *ftpd_popen FUNCTION((program, type), char *program AND char *type) 10652506Simp{ 10786269Simp char *cp; 10886455Simp FILE *iop; 109119225Simp int argc, gargc, pdes[2]; 11052506Simp char **pop, *argv[MAXUSRARGS], *gargv[MAXGLOBARGS], *vv[2]; 111140749Simp 11286455Simp if ((*type != 'r' && *type != 'w') || type[1]) 11358545Simp return (NULL); 114104854Simp 115140886Simp if (pipe(pdes) < 0) 11652506Simp return (NULL); 11786455Simp 11852506Simp /* break up string into pieces */ 11986455Simp for (argc = 0, cp = program; argc < MAXUSRARGS-1; cp = NULL) { 12053813Simp if (!(argv[argc++] = strtok(cp, " \t\n"))) 121148141Simp break; 122100213Simp } 12358545Simp argv[argc - 1] = NULL; 12489945Simp 12584514Simp /* glob each piece */ 126147872Simp gargv[0] = argv[0]; 12758545Simp for (gargc = argc = 1; argv[argc] && gargc < (MAXGLOBARGS-1); argc++) { 128119234Simp if (!(pop = (char **) ftpglob(argv[argc]))) { 12969138Speter /* globbing failed */ 130118634Simp vv[0] = argv[argc]; 131149561Simp vv[1] = NULL; 132172572Sremko pop = (char **) copyblk(vv); 13352506Simp } 13458545Simp argv[argc] = (char *) pop; /* save to free later */ 135140837Simp while (*pop && gargc < MAXGLOBARGS-1) 136140793Simp gargv[gargc++] = *pop++; 137140793Simp } 138147872Simp gargv[gargc] = NULL; 139140793Simp 140176868Srink iop = NULL; 14158545Simp switch (child_pid = fork()) { 14265039Simp case -1: /* error */ 14392471Simp close(pdes[0]); 144140793Simp close(pdes[1]); 145116207Simp goto pfree; 14684514Simp /* NOTREACHED */ 14779270Simp case 0: /* child */ 148140793Simp if (*type == 'r') { 149190476Simp if (pdes[1] != 1) { 15079270Simp dup2(pdes[1], 1); 151117438Simp dup2(pdes[1], 2); /* stderr, too! */ 152117602Simp close(pdes[1]); 153148141Simp } 154118895Simp close(pdes[0]); 155119240Simp } else { 156119240Simp if (pdes[0] != 0) { 157119240Simp dup2(pdes[0], 0); 158119240Simp close(pdes[0]); 15993620Simp } 16086455Simp close(pdes[1]); 161119240Simp } 162119240Simp environ = NULL; 163119240Simp execv(gargv[0], gargv); 164119240Simp _exit(1); 165119240Simp } 166140793Simp 167119240Simp /* parent; assume fdopen can't fail... */ 168141122Simp if (*type == 'r') { 169141122Simp iop = fdopen(pipe_fd = pdes[0], type); 170141122Simp close(pdes[1]); 171141122Simp } else { 172141122Simp iop = fdopen(pipe_fd = pdes[1], type); 173141122Simp close(pdes[0]); 174141122Simp } 175141122Simp 176145247Sdamienpfree: for (argc = 1; argv[argc] != NULL; argc++) { 177141122Simp blkfree((char **) argv[argc]); 178119240Simp free((char *) argv[argc]); 179119240Simp } 180140792Simp return (iop); 181140792Simp} 182141122Simp 183119240Simpint ftpd_pclose FUNCTION((iop), FILE *iop) 184190429Simp{ 185140793Simp int status; 18686455Simp pid_t pid; 18786455Simp sigset_t omask, mask; 18889945Simp 189149869Simp sigemptyset(&mask); 19053813Simp sigaddset(&mask, SIGINT); 191189679Simp sigaddset(&mask, SIGQUIT); 19271279Simp sigaddset(&mask, SIGHUP); 19371283Simp 194113667Ssanpei /* pclose returns -1 if stream is not associated with a `popened' command, 19553813Simp or, if already `pclosed'. */ 19652506Simp if ((child_pid < 0) || (fileno(iop) != pipe_fd)) 197140793Simp return (-1); 198140792Simp 199107359Snon fclose(iop); 20071283Simp sigprocmask(SIG_BLOCK, &mask, &omask); 20152506Simp 20252506Simp while ((pid = wait(&status)) != child_pid && (pid != -1)); 20386269Simp sigprocmask(SIG_SETMASK, &omask, NULL); 20486269Simp 20552506Simp child_pid = -1; 20653813Simp pipe_fd = -1; 20752506Simp 20865039Simp#if defined(WEXITSTATUS) && defined(WIFEXITED) 20986269Simp if ((pid > 0) && WIFEXITED(status)) 21086269Simp return WEXITSTATUS(status); 21186269Simp 212135002Semax return -1; 21386269Simp#else /* defined(WEXITSTATUS) && defined(WIFEXITED) */ 21452506Simp return (pid == -1 ? -1 : status.w_status); 21552506Simp#endif /* defined(WEXITSTATUS) && defined(WIFEXITED) */ 21652506Simp} 217180314Simp