Home | History | Annotate | Download | only in ftp
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*
     23  *	Copyright 1996 Sun Microsystems, Inc.  All rights reserved.
     24  *	Use is subject to license terms.
     25  */
     26 
     27 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
     28 /*	All Rights Reserved  	*/
     29 
     30 /*
     31  *	University Copyright- Copyright (c) 1982, 1986, 1988
     32  *	The Regents of the University of California
     33  *	All Rights Reserved
     34  *
     35  *	University Acknowledgment- Portions of this document are derived from
     36  *	software developed by the University of California, Berkeley, and its
     37  *	contributors.
     38  */
     39 
     40 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     41 
     42 #include "ftp_var.h"
     43 
     44 #ifndef sigmask
     45 #define	sigmask(m)	(1 << ((m)-1))
     46 #endif
     47 
     48 #define	set2mask(setp) ((setp)->__sigbits[0])
     49 #define	mask2set(mask, setp) \
     50 	((mask) == -1 ? sigfillset(setp) : (((setp)->__sigbits[0]) = (mask)))
     51 
     52 
     53 static int
     54 sigsetmask(int mask)
     55 {
     56 	sigset_t oset;
     57 	sigset_t nset;
     58 
     59 	(void) sigprocmask(0, (sigset_t *)0, &nset);
     60 	mask2set(mask, &nset);
     61 	(void) sigprocmask(SIG_SETMASK, &nset, &oset);
     62 	return (set2mask(&oset));
     63 }
     64 
     65 static int
     66 sigblock(int mask)
     67 {
     68 	sigset_t oset;
     69 	sigset_t nset;
     70 
     71 	(void) sigprocmask(0, (sigset_t *)0, &nset);
     72 	mask2set(mask, &nset);
     73 	(void) sigprocmask(SIG_BLOCK, &nset, &oset);
     74 	return (set2mask(&oset));
     75 }
     76 
     77 #define	signal(s, f)	sigset(s, f)
     78 
     79 #define	tst(a, b)	(*mode == 'r'? (b) : (a))
     80 #define	RDR		0
     81 #define	WTR		1
     82 #define	NOFILES		20	/* just in case */
     83 
     84 static	pid_t *popen_pid;
     85 static	rlim_t nfiles = 0;
     86 
     87 FILE *
     88 mypopen(char *cmd, char *mode)
     89 {
     90 	int p[2];
     91 	pid_t pid;
     92 	int myside, remside, i;
     93 	struct rlimit rl;
     94 
     95 	if (nfiles <= 0) {
     96 		if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
     97 			nfiles = rl.rlim_max;
     98 		else
     99 			nfiles = NOFILES;
    100 	}
    101 	if (popen_pid == NULL) {
    102 		popen_pid = (pid_t *)malloc((unsigned)nfiles *
    103 		    sizeof (*popen_pid));
    104 		if (popen_pid == NULL)
    105 			return (NULL);
    106 		for (i = 0; i < nfiles; i++)
    107 			popen_pid[i] = (pid_t)-1;
    108 	}
    109 	if (pipe(p) < 0)
    110 		return (NULL);
    111 	myside = tst(p[WTR], p[RDR]);
    112 	remside = tst(p[RDR], p[WTR]);
    113 	if ((pid = vfork()) == 0) {
    114 		/* myside and remside reverse roles in child */
    115 		(void) close(myside);
    116 		if (remside != tst(0, 1)) {
    117 			(void) dup2(remside, tst(0, 1));
    118 			(void) close(remside);
    119 		}
    120 		execl("/bin/sh", "sh", "-c", cmd, (char *)NULL);
    121 		_exit(127);
    122 	}
    123 	if (pid == (pid_t)-1) {
    124 		(void) close(myside);
    125 		(void) close(remside);
    126 		return (NULL);
    127 	}
    128 	popen_pid[myside] = pid;
    129 	(void) close(remside);
    130 	return (fdopen(myside, mode));
    131 }
    132 
    133 /*ARGSUSED*/
    134 static void
    135 pabort(int sig)
    136 {
    137 	extern int mflag;
    138 
    139 	mflag = 0;
    140 }
    141 
    142 int
    143 mypclose(FILE *ptr)
    144 {
    145 	pid_t child, pid;
    146 	int omask;
    147 	void (*istat)();
    148 	int status;
    149 
    150 	child = popen_pid[fileno(ptr)];
    151 	popen_pid[fileno(ptr)] = (pid_t)-1;
    152 	(void) fclose(ptr);
    153 	if (child == (pid_t)-1)
    154 		return (-1);
    155 	istat = signal(SIGINT, pabort);
    156 	omask = sigblock(sigmask(SIGQUIT)|sigmask(SIGHUP));
    157 	while ((pid = wait(&status)) != child && pid != (pid_t)-1)
    158 		;
    159 	(void) sigsetmask(omask);
    160 	(void) signal(SIGINT, istat);
    161 	return (pid == (pid_t)-1 ? -1 : 0);
    162 }
    163