Path: blob/main/crypto/heimdal/appl/ftp/ftpd/popen.c
34914 views
/*1* Copyright (c) 1988, 1993, 19942* The Regents of the University of California. All rights reserved.3*4* This code is derived from software written by Ken Arnold and5* published in UNIX Review, Vol. 6, No. 8.6*7* Redistribution and use in source and binary forms, with or without8* modification, are permitted provided that the following conditions9* are met:10* 1. Redistributions of source code must retain the above copyright11* notice, this list of conditions and the following disclaimer.12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15* 3. All advertising materials mentioning features or use of this software16* must display the following acknowledgement:17* This product includes software developed by the University of18* California, Berkeley and its contributors.19* 4. Neither the name of the University nor the names of its contributors20* may be used to endorse or promote products derived from this software21* without specific prior written permission.22*23* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND24* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE25* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE26* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE27* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL28* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS29* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)30* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT31* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY32* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF33* SUCH DAMAGE.34*35*/3637#ifdef HAVE_CONFIG_H38#include <config.h>39RCSID("$Id$");40#endif4142#include <sys/types.h>43#ifdef TIME_WITH_SYS_TIME44#include <sys/time.h>45#include <time.h>46#elif defined(HAVE_SYS_TIME_H)47#include <sys/time.h>48#else49#include <time.h>50#endif51#ifdef HAVE_SYS_RESOURCE_H52#include <sys/resource.h>53#endif54#include <sys/wait.h>5556#include <errno.h>57#include <glob.h>58#include <signal.h>59#include <stdio.h>60#include <stdlib.h>61#include <string.h>62#include <unistd.h>63#include <roken.h>64#include "extern.h"656667/*68* Special version of popen which avoids call to shell. This ensures69* no one may create a pipe to a hidden program as a side effect of a70* list or dir command.71*/72static int *pids;73static int fds;7475/* return path prepended with ~ftp if that file exists, otherwise76* return path unchanged77*/7879const char *80ftp_rooted(const char *path)81{82static char home[MaxPathLen] = "";83static char newpath[MaxPathLen];84struct passwd *pwd;8586if(!home[0])87if((pwd = k_getpwnam("ftp")))88strlcpy(home, pwd->pw_dir, sizeof(home));89snprintf(newpath, sizeof(newpath), "%s/%s", home, path);90if(access(newpath, X_OK))91strlcpy(newpath, path, sizeof(newpath));92return newpath;93}949596#define MAXARGS 10097#define MAXGLOBS 10009899FILE *100ftpd_popen(char *program, char *type, int do_stderr, int no_glob)101{102char *cp;103FILE *iop;104int argc, gargc, pdes[2], pid;105char **pop, *argv[MAXARGS], *gargv[MAXGLOBS];106char *foo;107108if (strcmp(type, "r") && strcmp(type, "w"))109return (NULL);110111if (!pids) {112113/* This function is ugly and should be rewritten, in114* modern unices there is no such thing as a maximum115* filedescriptor.116*/117118fds = getdtablesize();119pids = (int*)calloc(fds, sizeof(int));120if(!pids)121return NULL;122}123if (pipe(pdes) < 0)124return (NULL);125126/* break up string into pieces */127foo = NULL;128for (argc = 0, cp = program; argc < MAXARGS - 1; cp = NULL) {129if (!(argv[argc++] = strtok_r(cp, " \t\n", &foo)))130break;131}132argv[MAXARGS - 1] = NULL;133134gargv[0] = (char*)ftp_rooted(argv[0]);135/* glob each piece */136for (gargc = argc = 1; argv[argc] && gargc < MAXGLOBS - 1; argc++) {137glob_t gl;138int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE139|140#ifdef GLOB_MAXPATH141GLOB_MAXPATH142#else143GLOB_LIMIT144#endif145;146147memset(&gl, 0, sizeof(gl));148if (no_glob ||149glob(argv[argc], flags, NULL, &gl) ||150gl.gl_pathc == 0)151gargv[gargc++] = strdup(argv[argc]);152else153for (pop = gl.gl_pathv;154*pop && gargc < MAXGLOBS - 1;155pop++)156gargv[gargc++] = strdup(*pop);157globfree(&gl);158}159gargv[gargc] = NULL;160161iop = NULL;162switch(pid = fork()) {163case -1: /* error */164close(pdes[0]);165close(pdes[1]);166goto pfree;167/* NOTREACHED */168case 0: /* child */169if (*type == 'r') {170if (pdes[1] != STDOUT_FILENO) {171dup2(pdes[1], STDOUT_FILENO);172close(pdes[1]);173}174if(do_stderr)175dup2(STDOUT_FILENO, STDERR_FILENO);176close(pdes[0]);177} else {178if (pdes[0] != STDIN_FILENO) {179dup2(pdes[0], STDIN_FILENO);180close(pdes[0]);181}182close(pdes[1]);183}184execv(gargv[0], gargv);185gargv[0] = argv[0];186execv(gargv[0], gargv);187_exit(1);188}189/* parent; assume fdopen can't fail... */190if (*type == 'r') {191iop = fdopen(pdes[0], type);192close(pdes[1]);193} else {194iop = fdopen(pdes[1], type);195close(pdes[0]);196}197pids[fileno(iop)] = pid;198199pfree:200for (argc = 1; gargv[argc] != NULL; argc++)201free(gargv[argc]);202203204return (iop);205}206207int208ftpd_pclose(FILE *iop)209{210int fdes, status;211pid_t pid;212sigset_t sigset, osigset;213214/*215* pclose returns -1 if stream is not associated with a216* `popened' command, or, if already `pclosed'.217*/218if (pids == 0 || pids[fdes = fileno(iop)] == 0)219return (-1);220fclose(iop);221sigemptyset(&sigset);222sigaddset(&sigset, SIGINT);223sigaddset(&sigset, SIGQUIT);224sigaddset(&sigset, SIGHUP);225sigprocmask(SIG_BLOCK, &sigset, &osigset);226while ((pid = waitpid(pids[fdes], &status, 0)) < 0 && errno == EINTR)227continue;228sigprocmask(SIG_SETMASK, &osigset, NULL);229pids[fdes] = 0;230if (pid < 0)231return (pid);232if (WIFEXITED(status))233return (WEXITSTATUS(status));234return (1);235}236237238