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 #include "ftp_var.h"
41
42 #ifndef sigmask
43 #define sigmask(m) (1 << ((m)-1))
44 #endif
45
46 #define set2mask(setp) ((setp)->__sigbits[0])
47 #define mask2set(mask, setp) \
48 ((mask) == -1 ? sigfillset(setp) : (((setp)->__sigbits[0]) = (mask)))
49
50
51 static int
sigsetmask(int mask)52 sigsetmask(int mask)
53 {
54 sigset_t oset;
55 sigset_t nset;
56
57 (void) sigprocmask(0, (sigset_t *)0, &nset);
58 mask2set(mask, &nset);
59 (void) sigprocmask(SIG_SETMASK, &nset, &oset);
60 return (set2mask(&oset));
61 }
62
63 static int
sigblock(int mask)64 sigblock(int mask)
65 {
66 sigset_t oset;
67 sigset_t nset;
68
69 (void) sigprocmask(0, (sigset_t *)0, &nset);
70 mask2set(mask, &nset);
71 (void) sigprocmask(SIG_BLOCK, &nset, &oset);
72 return (set2mask(&oset));
73 }
74
75 #define signal(s, f) sigset(s, f)
76
77 #define tst(a, b) (*mode == 'r'? (b) : (a))
78 #define RDR 0
79 #define WTR 1
80 #define NOFILES 20 /* just in case */
81
82 static pid_t *popen_pid;
83 static rlim_t nfiles = 0;
84
85 FILE *
mypopen(char * cmd,char * mode)86 mypopen(char *cmd, char *mode)
87 {
88 int p[2];
89 pid_t pid;
90 int myside, remside, i;
91 struct rlimit rl;
92
93 if (nfiles <= 0) {
94 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
95 nfiles = rl.rlim_max;
96 else
97 nfiles = NOFILES;
98 }
99 if (popen_pid == NULL) {
100 popen_pid = (pid_t *)malloc((unsigned)nfiles *
101 sizeof (*popen_pid));
102 if (popen_pid == NULL)
103 return (NULL);
104 for (i = 0; i < nfiles; i++)
105 popen_pid[i] = (pid_t)-1;
106 }
107 if (pipe(p) < 0)
108 return (NULL);
109 myside = tst(p[WTR], p[RDR]);
110 remside = tst(p[RDR], p[WTR]);
111 if ((pid = vfork()) == 0) {
112 /* myside and remside reverse roles in child */
113 (void) close(myside);
114 if (remside != tst(0, 1)) {
115 (void) dup2(remside, tst(0, 1));
116 (void) close(remside);
117 }
118 execl("/bin/sh", "sh", "-c", cmd, (char *)NULL);
119 _exit(127);
120 }
121 if (pid == (pid_t)-1) {
122 (void) close(myside);
123 (void) close(remside);
124 return (NULL);
125 }
126 popen_pid[myside] = pid;
127 (void) close(remside);
128 return (fdopen(myside, mode));
129 }
130
131 /*ARGSUSED*/
132 static void
pabort(int sig)133 pabort(int sig)
134 {
135 extern int mflag;
136
137 mflag = 0;
138 }
139
140 int
mypclose(FILE * ptr)141 mypclose(FILE *ptr)
142 {
143 pid_t child, pid;
144 int omask;
145 void (*istat)();
146 int status;
147
148 child = popen_pid[fileno(ptr)];
149 popen_pid[fileno(ptr)] = (pid_t)-1;
150 (void) fclose(ptr);
151 if (child == (pid_t)-1)
152 return (-1);
153 istat = signal(SIGINT, pabort);
154 omask = sigblock(sigmask(SIGQUIT)|sigmask(SIGHUP));
155 while ((pid = wait(&status)) != child && pid != (pid_t)-1)
156 ;
157 (void) sigsetmask(omask);
158 (void) signal(SIGINT, istat);
159 return (pid == (pid_t)-1 ? -1 : 0);
160 }
161