Home | History | Annotate | Line # | Download | only in ftpd
popen.c revision 1.31.18.1
      1  1.31.18.1      yamt /*	$NetBSD: popen.c,v 1.31.18.1 2008/05/18 12:30:44 yamt Exp $	*/
      2       1.18     lukem 
      3       1.18     lukem /*-
      4       1.30     lukem  * Copyright (c) 1999-2004 The NetBSD Foundation, Inc.
      5       1.18     lukem  * All rights reserved.
      6       1.18     lukem  *
      7       1.18     lukem  * This code is derived from software contributed to The NetBSD Foundation
      8       1.18     lukem  * by Luke Mewburn.
      9       1.18     lukem  *
     10       1.18     lukem  * Redistribution and use in source and binary forms, with or without
     11       1.18     lukem  * modification, are permitted provided that the following conditions
     12       1.18     lukem  * are met:
     13       1.18     lukem  * 1. Redistributions of source code must retain the above copyright
     14       1.18     lukem  *    notice, this list of conditions and the following disclaimer.
     15       1.18     lukem  * 2. Redistributions in binary form must reproduce the above copyright
     16       1.18     lukem  *    notice, this list of conditions and the following disclaimer in the
     17       1.18     lukem  *    documentation and/or other materials provided with the distribution.
     18       1.18     lukem  *
     19       1.18     lukem  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20       1.18     lukem  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21       1.18     lukem  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22       1.18     lukem  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23       1.18     lukem  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24       1.18     lukem  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25       1.18     lukem  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26       1.18     lukem  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27       1.18     lukem  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28       1.18     lukem  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29       1.18     lukem  * POSSIBILITY OF SUCH DAMAGE.
     30       1.18     lukem  */
     31        1.5       cgd 
     32        1.1       cgd /*
     33        1.3   deraadt  * Copyright (c) 1988, 1993, 1994
     34        1.3   deraadt  *	The Regents of the University of California.  All rights reserved.
     35        1.1       cgd  *
     36        1.1       cgd  * This code is derived from software written by Ken Arnold and
     37        1.1       cgd  * published in UNIX Review, Vol. 6, No. 8.
     38        1.1       cgd  *
     39        1.1       cgd  * Redistribution and use in source and binary forms, with or without
     40        1.1       cgd  * modification, are permitted provided that the following conditions
     41        1.1       cgd  * are met:
     42        1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     43        1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     44        1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     45        1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     46        1.1       cgd  *    documentation and/or other materials provided with the distribution.
     47       1.29       agc  * 3. Neither the name of the University nor the names of its contributors
     48        1.1       cgd  *    may be used to endorse or promote products derived from this software
     49        1.1       cgd  *    without specific prior written permission.
     50        1.1       cgd  *
     51        1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     52        1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     53        1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     54        1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     55        1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     56        1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     57        1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     58        1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     59        1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     60        1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     61        1.1       cgd  * SUCH DAMAGE.
     62        1.1       cgd  *
     63        1.1       cgd  */
     64        1.1       cgd 
     65        1.8  christos #include <sys/cdefs.h>
     66        1.1       cgd #ifndef lint
     67        1.5       cgd #if 0
     68        1.3   deraadt static char sccsid[] = "@(#)popen.c	8.3 (Berkeley) 4/6/94";
     69        1.5       cgd #else
     70  1.31.18.1      yamt __RCSID("$NetBSD: popen.c,v 1.31.18.1 2008/05/18 12:30:44 yamt Exp $");
     71        1.5       cgd #endif
     72        1.1       cgd #endif /* not lint */
     73        1.1       cgd 
     74        1.1       cgd #include <sys/types.h>
     75       1.20     lukem #include <sys/param.h>
     76        1.1       cgd #include <sys/wait.h>
     77        1.3   deraadt 
     78        1.3   deraadt #include <errno.h>
     79        1.3   deraadt #include <glob.h>
     80        1.1       cgd #include <signal.h>
     81        1.1       cgd #include <stdio.h>
     82        1.1       cgd #include <stdlib.h>
     83        1.1       cgd #include <string.h>
     84       1.17     lukem #include <stringlist.h>
     85       1.14     lukem #include <syslog.h>
     86        1.3   deraadt #include <unistd.h>
     87       1.13  explorer 
     88       1.13  explorer #ifdef KERBEROS5
     89       1.16  christos #include <krb5/krb5.h>
     90       1.13  explorer #endif
     91        1.3   deraadt 
     92        1.3   deraadt #include "extern.h"
     93        1.1       cgd 
     94        1.8  christos #define INCR	100
     95        1.1       cgd /*
     96        1.9     lukem  * Special version of popen which avoids call to shell.  This ensures no-one
     97        1.1       cgd  * may create a pipe to a hidden program as a side effect of a list or dir
     98        1.1       cgd  * command.
     99        1.9     lukem  * If stderrfd != -1, then send stderr of a read command there,
    100        1.9     lukem  * otherwise close stderr.
    101        1.1       cgd  */
    102        1.1       cgd static int *pids;
    103        1.1       cgd static int fds;
    104        1.1       cgd 
    105       1.21     lukem extern int ls_main(int, char *[]);
    106       1.14     lukem 
    107        1.1       cgd FILE *
    108       1.27     lukem ftpd_popen(char *argv[], const char *ptype, int stderrfd)
    109        1.1       cgd {
    110       1.17     lukem 	FILE *iop;
    111       1.17     lukem 	int argc, pdes[2], pid, isls;
    112       1.17     lukem 	char **pop;
    113       1.17     lukem 	StringList *sl;
    114       1.17     lukem 
    115       1.17     lukem 	iop = NULL;
    116       1.14     lukem 	isls = 0;
    117       1.27     lukem 	if ((*ptype != 'r' && *ptype != 'w') || ptype[1])
    118        1.3   deraadt 		return (NULL);
    119        1.1       cgd 
    120        1.1       cgd 	if (!pids) {
    121        1.1       cgd 		if ((fds = getdtablesize()) <= 0)
    122        1.3   deraadt 			return (NULL);
    123        1.1       cgd 		if ((pids = (int *)malloc((u_int)(fds * sizeof(int)))) == NULL)
    124        1.3   deraadt 			return (NULL);
    125        1.3   deraadt 		memset(pids, 0, fds * sizeof(int));
    126        1.1       cgd 	}
    127        1.1       cgd 	if (pipe(pdes) < 0)
    128        1.3   deraadt 		return (NULL);
    129        1.1       cgd 
    130       1.17     lukem 	if ((sl = sl_init()) == NULL)
    131       1.17     lukem 		goto pfree;
    132        1.8  christos 
    133       1.17     lukem 					/* glob each piece */
    134       1.31  christos 	if (sl_add(sl, ftpd_strdup(argv[0])) == -1)
    135        1.8  christos 		goto pfree;
    136       1.17     lukem 	for (argc = 1; argv[argc]; argc++) {
    137        1.3   deraadt 		glob_t gl;
    138       1.24  christos 		int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_TILDE|GLOB_LIMIT;
    139        1.3   deraadt 
    140        1.3   deraadt 		memset(&gl, 0, sizeof(gl));
    141        1.8  christos 		if (glob(argv[argc], flags, NULL, &gl)) {
    142       1.31  christos 			if (sl_add(sl, ftpd_strdup(argv[argc])) == -1) {
    143       1.25  christos 				globfree(&gl);
    144        1.8  christos 				goto pfree;
    145       1.25  christos 			}
    146       1.25  christos 		} else {
    147        1.8  christos 			for (pop = gl.gl_pathv; *pop; pop++) {
    148       1.31  christos 				if (sl_add(sl, ftpd_strdup(*pop)) == -1) {
    149       1.25  christos 					globfree(&gl);
    150        1.8  christos 					goto pfree;
    151       1.25  christos 				}
    152        1.8  christos 			}
    153       1.25  christos 		}
    154        1.3   deraadt 		globfree(&gl);
    155        1.1       cgd 	}
    156       1.17     lukem 	if (sl_add(sl, NULL) == -1)
    157       1.17     lukem 		goto pfree;
    158        1.1       cgd 
    159       1.23     lukem #ifndef NO_INTERNAL_LS
    160       1.17     lukem 	isls = (strcmp(sl->sl_str[0], INTERNAL_LS) == 0);
    161       1.23     lukem #endif
    162       1.14     lukem 
    163       1.14     lukem 	pid = isls ? fork() : vfork();
    164       1.14     lukem 	switch (pid) {
    165        1.1       cgd 	case -1:			/* error */
    166        1.1       cgd 		(void)close(pdes[0]);
    167        1.1       cgd 		(void)close(pdes[1]);
    168        1.1       cgd 		goto pfree;
    169        1.1       cgd 		/* NOTREACHED */
    170        1.1       cgd 	case 0:				/* child */
    171       1.27     lukem 		if (*ptype == 'r') {
    172        1.3   deraadt 			if (pdes[1] != STDOUT_FILENO) {
    173        1.3   deraadt 				dup2(pdes[1], STDOUT_FILENO);
    174        1.1       cgd 				(void)close(pdes[1]);
    175        1.1       cgd 			}
    176        1.9     lukem 			if (stderrfd == -1)
    177        1.7     lukem 				(void)close(STDERR_FILENO);
    178        1.9     lukem 			else
    179        1.9     lukem 				dup2(stderrfd, STDERR_FILENO);
    180        1.1       cgd 			(void)close(pdes[0]);
    181        1.1       cgd 		} else {
    182        1.3   deraadt 			if (pdes[0] != STDIN_FILENO) {
    183        1.3   deraadt 				dup2(pdes[0], STDIN_FILENO);
    184        1.1       cgd 				(void)close(pdes[0]);
    185        1.1       cgd 			}
    186        1.1       cgd 			(void)close(pdes[1]);
    187       1.14     lukem 		}
    188       1.23     lukem #ifndef NO_INTERNAL_LS
    189       1.14     lukem 		if (isls) {	/* use internal ls */
    190       1.14     lukem 			optreset = optind = optopt = 1;
    191       1.14     lukem 			closelog();
    192       1.17     lukem 			exit(ls_main(sl->sl_cur - 1, sl->sl_str));
    193        1.1       cgd 		}
    194       1.23     lukem #endif
    195       1.23     lukem 
    196       1.17     lukem 		execv(sl->sl_str[0], sl->sl_str);
    197        1.1       cgd 		_exit(1);
    198        1.1       cgd 	}
    199        1.1       cgd 	/* parent; assume fdopen can't fail...  */
    200       1.27     lukem 	if (*ptype == 'r') {
    201       1.27     lukem 		iop = fdopen(pdes[0], ptype);
    202        1.1       cgd 		(void)close(pdes[1]);
    203        1.1       cgd 	} else {
    204       1.27     lukem 		iop = fdopen(pdes[1], ptype);
    205        1.1       cgd 		(void)close(pdes[0]);
    206        1.1       cgd 	}
    207        1.1       cgd 	pids[fileno(iop)] = pid;
    208        1.1       cgd 
    209       1.22     lukem  pfree:
    210       1.22     lukem 	if (sl)
    211       1.17     lukem 		sl_free(sl, 1);
    212        1.3   deraadt 	return (iop);
    213        1.1       cgd }
    214        1.1       cgd 
    215        1.3   deraadt int
    216       1.21     lukem ftpd_pclose(FILE *iop)
    217        1.1       cgd {
    218        1.6     lukem 	int fdes, status;
    219        1.3   deraadt 	pid_t pid;
    220       1.28    kleink 	sigset_t nsigset, osigset;
    221        1.1       cgd 
    222        1.1       cgd 	/*
    223        1.1       cgd 	 * pclose returns -1 if stream is not associated with a
    224        1.1       cgd 	 * `popened' command, or, if already `pclosed'.
    225        1.1       cgd 	 */
    226        1.1       cgd 	if (pids == 0 || pids[fdes = fileno(iop)] == 0)
    227        1.3   deraadt 		return (-1);
    228        1.1       cgd 	(void)fclose(iop);
    229       1.28    kleink 	sigemptyset(&nsigset);
    230       1.28    kleink 	sigaddset(&nsigset, SIGINT);
    231       1.28    kleink 	sigaddset(&nsigset, SIGQUIT);
    232       1.28    kleink 	sigaddset(&nsigset, SIGHUP);
    233       1.28    kleink 	sigprocmask(SIG_BLOCK, &nsigset, &osigset);
    234        1.3   deraadt 	while ((pid = waitpid(pids[fdes], &status, 0)) < 0 && errno == EINTR)
    235        1.3   deraadt 		continue;
    236        1.4   mycroft 	sigprocmask(SIG_SETMASK, &osigset, NULL);
    237        1.1       cgd 	pids[fdes] = 0;
    238        1.3   deraadt 	if (pid < 0)
    239        1.3   deraadt 		return (pid);
    240        1.3   deraadt 	if (WIFEXITED(status))
    241        1.3   deraadt 		return (WEXITSTATUS(status));
    242        1.3   deraadt 	return (1);
    243        1.1       cgd }
    244