| @@ -1,392 +1,392 @@ | | | @@ -1,392 +1,392 @@ |
1 | /* $NetBSD: redir.c,v 1.32.2.1 2012/04/17 00:01:38 yamt Exp $ */ | | 1 | /* $NetBSD: redir.c,v 1.32.2.2 2013/06/12 01:08:16 yamt Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1991, 1993 | | 4 | * Copyright (c) 1991, 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to Berkeley by | | 7 | * This code is derived from software contributed to Berkeley by |
8 | * Kenneth Almquist. | | 8 | * Kenneth Almquist. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright | | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the | | 16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. | | 17 | * documentation and/or other materials provided with the distribution. |
18 | * 3. Neither the name of the University nor the names of its contributors | | 18 | * 3. Neither the name of the University nor the names of its contributors |
19 | * may be used to endorse or promote products derived from this software | | 19 | * may be used to endorse or promote products derived from this software |
20 | * without specific prior written permission. | | 20 | * without specific prior written permission. |
21 | * | | 21 | * |
22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
32 | * SUCH DAMAGE. | | 32 | * SUCH DAMAGE. |
33 | */ | | 33 | */ |
34 | | | 34 | |
35 | #include <sys/cdefs.h> | | 35 | #include <sys/cdefs.h> |
36 | #ifndef lint | | 36 | #ifndef lint |
37 | #if 0 | | 37 | #if 0 |
38 | static char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95"; | | 38 | static char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95"; |
39 | #else | | 39 | #else |
40 | __RCSID("$NetBSD: redir.c,v 1.32.2.1 2012/04/17 00:01:38 yamt Exp $"); | | 40 | __RCSID("$NetBSD: redir.c,v 1.32.2.2 2013/06/12 01:08:16 yamt Exp $"); |
41 | #endif | | 41 | #endif |
42 | #endif /* not lint */ | | 42 | #endif /* not lint */ |
43 | | | 43 | |
44 | #include <sys/types.h> | | 44 | #include <sys/types.h> |
45 | #include <sys/param.h> /* PIPE_BUF */ | | 45 | #include <sys/param.h> /* PIPE_BUF */ |
46 | #include <signal.h> | | 46 | #include <signal.h> |
47 | #include <string.h> | | 47 | #include <string.h> |
48 | #include <fcntl.h> | | 48 | #include <fcntl.h> |
49 | #include <errno.h> | | 49 | #include <errno.h> |
50 | #include <unistd.h> | | 50 | #include <unistd.h> |
51 | #include <stdlib.h> | | 51 | #include <stdlib.h> |
52 | | | 52 | |
53 | /* | | 53 | /* |
54 | * Code for dealing with input/output redirection. | | 54 | * Code for dealing with input/output redirection. |
55 | */ | | 55 | */ |
56 | | | 56 | |
57 | #include "main.h" | | 57 | #include "main.h" |
58 | #include "shell.h" | | 58 | #include "shell.h" |
59 | #include "nodes.h" | | 59 | #include "nodes.h" |
60 | #include "jobs.h" | | 60 | #include "jobs.h" |
61 | #include "options.h" | | 61 | #include "options.h" |
62 | #include "expand.h" | | 62 | #include "expand.h" |
63 | #include "redir.h" | | 63 | #include "redir.h" |
64 | #include "output.h" | | 64 | #include "output.h" |
65 | #include "memalloc.h" | | 65 | #include "memalloc.h" |
66 | #include "error.h" | | 66 | #include "error.h" |
67 | | | 67 | |
68 | | | 68 | |
69 | #define EMPTY -2 /* marks an unused slot in redirtab */ | | 69 | #define EMPTY -2 /* marks an unused slot in redirtab */ |
70 | #ifndef PIPE_BUF | | 70 | #ifndef PIPE_BUF |
71 | # define PIPESIZE 4096 /* amount of buffering in a pipe */ | | 71 | # define PIPESIZE 4096 /* amount of buffering in a pipe */ |
72 | #else | | 72 | #else |
73 | # define PIPESIZE PIPE_BUF | | 73 | # define PIPESIZE PIPE_BUF |
74 | #endif | | 74 | #endif |
75 | | | 75 | |
76 | | | 76 | |
77 | MKINIT | | 77 | MKINIT |
78 | struct redirtab { | | 78 | struct redirtab { |
79 | struct redirtab *next; | | 79 | struct redirtab *next; |
80 | short renamed[10]; | | 80 | short renamed[10]; |
81 | }; | | 81 | }; |
82 | | | 82 | |
83 | | | 83 | |
84 | MKINIT struct redirtab *redirlist; | | 84 | MKINIT struct redirtab *redirlist; |
85 | | | 85 | |
86 | /* | | 86 | /* |
87 | * We keep track of whether or not fd0 has been redirected. This is for | | 87 | * We keep track of whether or not fd0 has been redirected. This is for |
88 | * background commands, where we want to redirect fd0 to /dev/null only | | 88 | * background commands, where we want to redirect fd0 to /dev/null only |
89 | * if it hasn't already been redirected. | | 89 | * if it hasn't already been redirected. |
90 | */ | | 90 | */ |
91 | int fd0_redirected = 0; | | 91 | int fd0_redirected = 0; |
92 | | | 92 | |
93 | STATIC void openredirect(union node *, char[10], int); | | 93 | STATIC void openredirect(union node *, char[10], int); |
94 | STATIC int openhere(union node *); | | 94 | STATIC int openhere(const union node *); |
95 | | | 95 | |
96 | | | 96 | |
97 | /* | | 97 | /* |
98 | * Process a list of redirection commands. If the REDIR_PUSH flag is set, | | 98 | * Process a list of redirection commands. If the REDIR_PUSH flag is set, |
99 | * old file descriptors are stashed away so that the redirection can be | | 99 | * old file descriptors are stashed away so that the redirection can be |
100 | * undone by calling popredir. If the REDIR_BACKQ flag is set, then the | | 100 | * undone by calling popredir. If the REDIR_BACKQ flag is set, then the |
101 | * standard output, and the standard error if it becomes a duplicate of | | 101 | * standard output, and the standard error if it becomes a duplicate of |
102 | * stdout, is saved in memory. | | 102 | * stdout, is saved in memory. |
103 | */ | | 103 | */ |
104 | | | 104 | |
105 | void | | 105 | void |
106 | redirect(union node *redir, int flags) | | 106 | redirect(union node *redir, int flags) |
107 | { | | 107 | { |
108 | union node *n; | | 108 | union node *n; |
109 | struct redirtab *sv = NULL; | | 109 | struct redirtab *sv = NULL; |
110 | int i; | | 110 | int i; |
111 | int fd; | | 111 | int fd; |
112 | int try; | | 112 | int try; |
113 | char memory[10]; /* file descriptors to write to memory */ | | 113 | char memory[10]; /* file descriptors to write to memory */ |
114 | | | 114 | |
115 | for (i = 10 ; --i >= 0 ; ) | | 115 | for (i = 10 ; --i >= 0 ; ) |
116 | memory[i] = 0; | | 116 | memory[i] = 0; |
117 | memory[1] = flags & REDIR_BACKQ; | | 117 | memory[1] = flags & REDIR_BACKQ; |
118 | if (flags & REDIR_PUSH) { | | 118 | if (flags & REDIR_PUSH) { |
119 | /* We don't have to worry about REDIR_VFORK here, as | | 119 | /* We don't have to worry about REDIR_VFORK here, as |
120 | * flags & REDIR_PUSH is never true if REDIR_VFORK is set. | | 120 | * flags & REDIR_PUSH is never true if REDIR_VFORK is set. |
121 | */ | | 121 | */ |
122 | sv = ckmalloc(sizeof (struct redirtab)); | | 122 | sv = ckmalloc(sizeof (struct redirtab)); |
123 | for (i = 0 ; i < 10 ; i++) | | 123 | for (i = 0 ; i < 10 ; i++) |
124 | sv->renamed[i] = EMPTY; | | 124 | sv->renamed[i] = EMPTY; |
125 | sv->next = redirlist; | | 125 | sv->next = redirlist; |
126 | redirlist = sv; | | 126 | redirlist = sv; |
127 | } | | 127 | } |
128 | for (n = redir ; n ; n = n->nfile.next) { | | 128 | for (n = redir ; n ; n = n->nfile.next) { |
129 | fd = n->nfile.fd; | | 129 | fd = n->nfile.fd; |
130 | try = 0; | | 130 | try = 0; |
131 | if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) && | | 131 | if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) && |
132 | n->ndup.dupfd == fd) | | 132 | n->ndup.dupfd == fd) |
133 | continue; /* redirect from/to same file descriptor */ | | 133 | continue; /* redirect from/to same file descriptor */ |
134 | | | 134 | |
135 | if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) { | | 135 | if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) { |
136 | INTOFF; | | 136 | INTOFF; |
137 | again: | | 137 | again: |
138 | if ((i = fcntl(fd, F_DUPFD, 10)) == -1) { | | 138 | if ((i = fcntl(fd, F_DUPFD, 10)) == -1) { |
139 | switch (errno) { | | 139 | switch (errno) { |
140 | case EBADF: | | 140 | case EBADF: |
141 | if (!try) { | | 141 | if (!try) { |
142 | openredirect(n, memory, flags); | | 142 | openredirect(n, memory, flags); |
143 | try++; | | 143 | try++; |
144 | goto again; | | 144 | goto again; |
145 | } | | 145 | } |
146 | /* FALLTHROUGH*/ | | 146 | /* FALLTHROUGH*/ |
147 | default: | | 147 | default: |
148 | INTON; | | 148 | INTON; |
149 | error("%d: %s", fd, strerror(errno)); | | 149 | error("%d: %s", fd, strerror(errno)); |
150 | /* NOTREACHED */ | | 150 | /* NOTREACHED */ |
151 | } | | 151 | } |
152 | } | | 152 | } |
153 | if (!try) { | | 153 | if (!try) { |
154 | sv->renamed[fd] = i; | | 154 | sv->renamed[fd] = i; |
155 | close(fd); | | 155 | close(fd); |
156 | } | | 156 | } |
157 | INTON; | | 157 | INTON; |
158 | } else { | | 158 | } else { |
159 | close(fd); | | 159 | close(fd); |
160 | } | | 160 | } |
161 | if (fd == 0) | | 161 | if (fd == 0) |
162 | fd0_redirected++; | | 162 | fd0_redirected++; |
163 | if (!try) | | 163 | if (!try) |
164 | openredirect(n, memory, flags); | | 164 | openredirect(n, memory, flags); |
165 | } | | 165 | } |
166 | if (memory[1]) | | 166 | if (memory[1]) |
167 | out1 = &memout; | | 167 | out1 = &memout; |
168 | if (memory[2]) | | 168 | if (memory[2]) |
169 | out2 = &memout; | | 169 | out2 = &memout; |
170 | } | | 170 | } |
171 | | | 171 | |
172 | | | 172 | |
173 | STATIC void | | 173 | STATIC void |
174 | openredirect(union node *redir, char memory[10], int flags) | | 174 | openredirect(union node *redir, char memory[10], int flags) |
175 | { | | 175 | { |
176 | int fd = redir->nfile.fd; | | 176 | int fd = redir->nfile.fd; |
177 | char *fname; | | 177 | char *fname; |
178 | int f; | | 178 | int f; |
179 | int oflags = O_WRONLY|O_CREAT|O_TRUNC, eflags; | | 179 | int oflags = O_WRONLY|O_CREAT|O_TRUNC, eflags; |
180 | | | 180 | |
181 | /* | | 181 | /* |
182 | * We suppress interrupts so that we won't leave open file | | 182 | * We suppress interrupts so that we won't leave open file |
183 | * descriptors around. This may not be such a good idea because | | 183 | * descriptors around. This may not be such a good idea because |
184 | * an open of a device or a fifo can block indefinitely. | | 184 | * an open of a device or a fifo can block indefinitely. |
185 | */ | | 185 | */ |
186 | INTOFF; | | 186 | INTOFF; |
187 | memory[fd] = 0; | | 187 | memory[fd] = 0; |
188 | switch (redir->nfile.type) { | | 188 | switch (redir->nfile.type) { |
189 | case NFROM: | | 189 | case NFROM: |
190 | fname = redir->nfile.expfname; | | 190 | fname = redir->nfile.expfname; |
191 | if (flags & REDIR_VFORK) | | 191 | if (flags & REDIR_VFORK) |
192 | eflags = O_NONBLOCK; | | 192 | eflags = O_NONBLOCK; |
193 | else | | 193 | else |
194 | eflags = 0; | | 194 | eflags = 0; |
195 | if ((f = open(fname, O_RDONLY|eflags)) < 0) | | 195 | if ((f = open(fname, O_RDONLY|eflags)) < 0) |
196 | goto eopen; | | 196 | goto eopen; |
197 | if (eflags) | | 197 | if (eflags) |
198 | (void)fcntl(f, F_SETFL, fcntl(f, F_GETFL, 0) & ~eflags); | | 198 | (void)fcntl(f, F_SETFL, fcntl(f, F_GETFL, 0) & ~eflags); |
199 | break; | | 199 | break; |
200 | case NFROMTO: | | 200 | case NFROMTO: |
201 | fname = redir->nfile.expfname; | | 201 | fname = redir->nfile.expfname; |
202 | if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0) | | 202 | if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0) |
203 | goto ecreate; | | 203 | goto ecreate; |
204 | break; | | 204 | break; |
205 | case NTO: | | 205 | case NTO: |
206 | if (Cflag) | | 206 | if (Cflag) |
207 | oflags |= O_EXCL; | | 207 | oflags |= O_EXCL; |
208 | /* FALLTHROUGH */ | | 208 | /* FALLTHROUGH */ |
209 | case NCLOBBER: | | 209 | case NCLOBBER: |
210 | fname = redir->nfile.expfname; | | 210 | fname = redir->nfile.expfname; |
211 | if ((f = open(fname, oflags, 0666)) < 0) | | 211 | if ((f = open(fname, oflags, 0666)) < 0) |
212 | goto ecreate; | | 212 | goto ecreate; |
213 | break; | | 213 | break; |
214 | case NAPPEND: | | 214 | case NAPPEND: |
215 | fname = redir->nfile.expfname; | | 215 | fname = redir->nfile.expfname; |
216 | if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0) | | 216 | if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0) |
217 | goto ecreate; | | 217 | goto ecreate; |
218 | break; | | 218 | break; |
219 | case NTOFD: | | 219 | case NTOFD: |
220 | case NFROMFD: | | 220 | case NFROMFD: |
221 | if (redir->ndup.dupfd >= 0) { /* if not ">&-" */ | | 221 | if (redir->ndup.dupfd >= 0) { /* if not ">&-" */ |
222 | if (memory[redir->ndup.dupfd]) | | 222 | if (memory[redir->ndup.dupfd]) |
223 | memory[fd] = 1; | | 223 | memory[fd] = 1; |
224 | else | | 224 | else |
225 | copyfd(redir->ndup.dupfd, fd, 1); | | 225 | copyfd(redir->ndup.dupfd, fd, 1); |
226 | } | | 226 | } |
227 | INTON; | | 227 | INTON; |
228 | return; | | 228 | return; |
229 | case NHERE: | | 229 | case NHERE: |
230 | case NXHERE: | | 230 | case NXHERE: |
231 | f = openhere(redir); | | 231 | f = openhere(redir); |
232 | break; | | 232 | break; |
233 | default: | | 233 | default: |
234 | abort(); | | 234 | abort(); |
235 | } | | 235 | } |
236 | | | 236 | |
237 | if (f != fd) { | | 237 | if (f != fd) { |
238 | copyfd(f, fd, 1); | | 238 | copyfd(f, fd, 1); |
239 | close(f); | | 239 | close(f); |
240 | } | | 240 | } |
241 | INTON; | | 241 | INTON; |
242 | return; | | 242 | return; |
243 | ecreate: | | 243 | ecreate: |
244 | exerrno = 1; | | 244 | exerrno = 1; |
245 | error("cannot create %s: %s", fname, errmsg(errno, E_CREAT)); | | 245 | error("cannot create %s: %s", fname, errmsg(errno, E_CREAT)); |
246 | eopen: | | 246 | eopen: |
247 | exerrno = 1; | | 247 | exerrno = 1; |
248 | error("cannot open %s: %s", fname, errmsg(errno, E_OPEN)); | | 248 | error("cannot open %s: %s", fname, errmsg(errno, E_OPEN)); |
249 | } | | 249 | } |
250 | | | 250 | |
251 | | | 251 | |
252 | /* | | 252 | /* |
253 | * Handle here documents. Normally we fork off a process to write the | | 253 | * Handle here documents. Normally we fork off a process to write the |
254 | * data to a pipe. If the document is short, we can stuff the data in | | 254 | * data to a pipe. If the document is short, we can stuff the data in |
255 | * the pipe without forking. | | 255 | * the pipe without forking. |
256 | */ | | 256 | */ |
257 | | | 257 | |
258 | STATIC int | | 258 | STATIC int |
259 | openhere(union node *redir) | | 259 | openhere(const union node *redir) |
260 | { | | 260 | { |
261 | int pip[2]; | | 261 | int pip[2]; |
262 | int len = 0; | | 262 | int len = 0; |
263 | | | 263 | |
264 | if (pipe(pip) < 0) | | 264 | if (pipe(pip) < 0) |
265 | error("Pipe call failed"); | | 265 | error("Pipe call failed"); |
266 | if (redir->type == NHERE) { | | 266 | if (redir->type == NHERE) { |
267 | len = strlen(redir->nhere.doc->narg.text); | | 267 | len = strlen(redir->nhere.doc->narg.text); |
268 | if (len <= PIPESIZE) { | | 268 | if (len <= PIPESIZE) { |
269 | xwrite(pip[1], redir->nhere.doc->narg.text, len); | | 269 | xwrite(pip[1], redir->nhere.doc->narg.text, len); |
270 | goto out; | | 270 | goto out; |
271 | } | | 271 | } |
272 | } | | 272 | } |
273 | if (forkshell(NULL, NULL, FORK_NOJOB) == 0) { | | 273 | if (forkshell(NULL, NULL, FORK_NOJOB) == 0) { |
274 | close(pip[0]); | | 274 | close(pip[0]); |
275 | signal(SIGINT, SIG_IGN); | | 275 | signal(SIGINT, SIG_IGN); |
276 | signal(SIGQUIT, SIG_IGN); | | 276 | signal(SIGQUIT, SIG_IGN); |
277 | signal(SIGHUP, SIG_IGN); | | 277 | signal(SIGHUP, SIG_IGN); |
278 | #ifdef SIGTSTP | | 278 | #ifdef SIGTSTP |
279 | signal(SIGTSTP, SIG_IGN); | | 279 | signal(SIGTSTP, SIG_IGN); |
280 | #endif | | 280 | #endif |
281 | signal(SIGPIPE, SIG_DFL); | | 281 | signal(SIGPIPE, SIG_DFL); |
282 | if (redir->type == NHERE) | | 282 | if (redir->type == NHERE) |
283 | xwrite(pip[1], redir->nhere.doc->narg.text, len); | | 283 | xwrite(pip[1], redir->nhere.doc->narg.text, len); |
284 | else | | 284 | else |
285 | expandhere(redir->nhere.doc, pip[1]); | | 285 | expandhere(redir->nhere.doc, pip[1]); |
286 | _exit(0); | | 286 | _exit(0); |
287 | } | | 287 | } |
288 | out: | | 288 | out: |
289 | close(pip[1]); | | 289 | close(pip[1]); |
290 | return pip[0]; | | 290 | return pip[0]; |
291 | } | | 291 | } |
292 | | | 292 | |
293 | | | 293 | |
294 | | | 294 | |
295 | /* | | 295 | /* |
296 | * Undo the effects of the last redirection. | | 296 | * Undo the effects of the last redirection. |
297 | */ | | 297 | */ |
298 | | | 298 | |
299 | void | | 299 | void |
300 | popredir(void) | | 300 | popredir(void) |
301 | { | | 301 | { |
302 | struct redirtab *rp = redirlist; | | 302 | struct redirtab *rp = redirlist; |
303 | int i; | | 303 | int i; |
304 | | | 304 | |
305 | for (i = 0 ; i < 10 ; i++) { | | 305 | for (i = 0 ; i < 10 ; i++) { |
306 | if (rp->renamed[i] != EMPTY) { | | 306 | if (rp->renamed[i] != EMPTY) { |
307 | if (i == 0) | | 307 | if (i == 0) |
308 | fd0_redirected--; | | 308 | fd0_redirected--; |
309 | close(i); | | 309 | close(i); |
310 | if (rp->renamed[i] >= 0) { | | 310 | if (rp->renamed[i] >= 0) { |
311 | copyfd(rp->renamed[i], i, 1); | | 311 | copyfd(rp->renamed[i], i, 1); |
312 | close(rp->renamed[i]); | | 312 | close(rp->renamed[i]); |
313 | } | | 313 | } |
314 | } | | 314 | } |
315 | } | | 315 | } |
316 | INTOFF; | | 316 | INTOFF; |
317 | redirlist = rp->next; | | 317 | redirlist = rp->next; |
318 | ckfree(rp); | | 318 | ckfree(rp); |
319 | INTON; | | 319 | INTON; |
320 | } | | 320 | } |
321 | | | 321 | |
322 | /* | | 322 | /* |
323 | * Undo all redirections. Called on error or interrupt. | | 323 | * Undo all redirections. Called on error or interrupt. |
324 | */ | | 324 | */ |
325 | | | 325 | |
326 | #ifdef mkinit | | 326 | #ifdef mkinit |
327 | | | 327 | |
328 | INCLUDE "redir.h" | | 328 | INCLUDE "redir.h" |
329 | | | 329 | |
330 | RESET { | | 330 | RESET { |
331 | while (redirlist) | | 331 | while (redirlist) |
332 | popredir(); | | 332 | popredir(); |
333 | } | | 333 | } |
334 | | | 334 | |
335 | SHELLPROC { | | 335 | SHELLPROC { |
336 | clearredir(0); | | 336 | clearredir(0); |
337 | } | | 337 | } |
338 | | | 338 | |
339 | #endif | | 339 | #endif |
340 | | | 340 | |
341 | /* Return true if fd 0 has already been redirected at least once. */ | | 341 | /* Return true if fd 0 has already been redirected at least once. */ |
342 | int | | 342 | int |
343 | fd0_redirected_p (void) { | | 343 | fd0_redirected_p (void) { |
344 | return fd0_redirected != 0; | | 344 | return fd0_redirected != 0; |
345 | } | | 345 | } |
346 | | | 346 | |
347 | /* | | 347 | /* |
348 | * Discard all saved file descriptors. | | 348 | * Discard all saved file descriptors. |
349 | */ | | 349 | */ |
350 | | | 350 | |
351 | void | | 351 | void |
352 | clearredir(int vforked) | | 352 | clearredir(int vforked) |
353 | { | | 353 | { |
354 | struct redirtab *rp; | | 354 | struct redirtab *rp; |
355 | int i; | | 355 | int i; |
356 | | | 356 | |
357 | for (rp = redirlist ; rp ; rp = rp->next) { | | 357 | for (rp = redirlist ; rp ; rp = rp->next) { |
358 | for (i = 0 ; i < 10 ; i++) { | | 358 | for (i = 0 ; i < 10 ; i++) { |
359 | if (rp->renamed[i] >= 0) { | | 359 | if (rp->renamed[i] >= 0) { |
360 | close(rp->renamed[i]); | | 360 | close(rp->renamed[i]); |
361 | } | | 361 | } |
362 | if (!vforked) | | 362 | if (!vforked) |
363 | rp->renamed[i] = EMPTY; | | 363 | rp->renamed[i] = EMPTY; |
364 | } | | 364 | } |
365 | } | | 365 | } |
366 | } | | 366 | } |
367 | | | 367 | |
368 | | | 368 | |
369 | | | 369 | |
370 | /* | | 370 | /* |
371 | * Copy a file descriptor to be >= to. Returns -1 | | 371 | * Copy a file descriptor to be >= to. Returns -1 |
372 | * if the source file descriptor is closed, EMPTY if there are no unused | | 372 | * if the source file descriptor is closed, EMPTY if there are no unused |
373 | * file descriptors left. | | 373 | * file descriptors left. |
374 | */ | | 374 | */ |
375 | | | 375 | |
376 | int | | 376 | int |
377 | copyfd(int from, int to, int equal) | | 377 | copyfd(int from, int to, int equal) |
378 | { | | 378 | { |
379 | int newfd; | | 379 | int newfd; |
380 | | | 380 | |
381 | if (equal) | | 381 | if (equal) |
382 | newfd = dup2(from, to); | | 382 | newfd = dup2(from, to); |
383 | else | | 383 | else |
384 | newfd = fcntl(from, F_DUPFD, to); | | 384 | newfd = fcntl(from, F_DUPFD, to); |
385 | if (newfd < 0) { | | 385 | if (newfd < 0) { |
386 | if (errno == EMFILE) | | 386 | if (errno == EMFILE) |
387 | return EMPTY; | | 387 | return EMPTY; |
388 | else | | 388 | else |
389 | error("%d: %s", from, strerror(errno)); | | 389 | error("%d: %s", from, strerror(errno)); |
390 | } | | 390 | } |
391 | return newfd; | | 391 | return newfd; |
392 | } | | 392 | } |