redir.c revision 1.46 1 /* $NetBSD: redir.c,v 1.46 2016/05/09 20:50:08 kre Exp $ */
2
3 /*-
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Kenneth Almquist.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
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
20 * without specific prior written permission.
21 *
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
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
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
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
32 * SUCH DAMAGE.
33 */
34
35 #include <sys/cdefs.h>
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95";
39 #else
40 __RCSID("$NetBSD: redir.c,v 1.46 2016/05/09 20:50:08 kre Exp $");
41 #endif
42 #endif /* not lint */
43
44 #include <sys/types.h>
45 #include <sys/param.h> /* PIPE_BUF */
46 #include <signal.h>
47 #include <string.h>
48 #include <fcntl.h>
49 #include <errno.h>
50 #include <unistd.h>
51 #include <stdlib.h>
52
53 /*
54 * Code for dealing with input/output redirection.
55 */
56
57 #include "main.h"
58 #include "shell.h"
59 #include "nodes.h"
60 #include "jobs.h"
61 #include "options.h"
62 #include "expand.h"
63 #include "redir.h"
64 #include "output.h"
65 #include "memalloc.h"
66 #include "error.h"
67
68
69 #define EMPTY -2 /* marks an unused slot in redirtab */
70 #define CLOSED -1 /* fd was not open before redir */
71 #ifndef PIPE_BUF
72 # define PIPESIZE 4096 /* amount of buffering in a pipe */
73 #else
74 # define PIPESIZE PIPE_BUF
75 #endif
76
77
78 MKINIT
79 struct renamelist {
80 struct renamelist *next;
81 int orig;
82 int into;
83 };
84
85 MKINIT
86 struct redirtab {
87 struct redirtab *next;
88 struct renamelist *renamed;
89 };
90
91
92 MKINIT struct redirtab *redirlist;
93
94 /*
95 * We keep track of whether or not fd0 has been redirected. This is for
96 * background commands, where we want to redirect fd0 to /dev/null only
97 * if it hasn't already been redirected.
98 */
99 STATIC int fd0_redirected = 0;
100
101 /*
102 * And also where to put internal use fds that should be out of the
103 * way of user defined fds (normally)
104 */
105 STATIC int big_sh_fd = 0;
106
107 STATIC const struct renamelist *is_renamed(const struct renamelist *, int);
108 STATIC void fd_rename(struct redirtab *, int, int);
109 STATIC void free_rl(struct redirtab *, int);
110 STATIC void openredirect(union node *, char[10], int);
111 STATIC int openhere(const union node *);
112 STATIC void find_big_fd(void);
113
114 STATIC const struct renamelist *
115 is_renamed(const struct renamelist *rl, int fd)
116 {
117 while (rl != NULL) {
118 if (rl->orig == fd)
119 return rl;
120 rl = rl->next;
121 }
122 return NULL;
123 }
124
125 STATIC void
126 free_rl(struct redirtab *rt, int reset)
127 {
128 struct renamelist *rl, *rn = rt->renamed;
129
130 while ((rl = rn) != NULL) {
131 rn = rl->next;
132 if (rl->orig == 0)
133 fd0_redirected--;
134 if (reset) {
135 if (rl->into < 0)
136 close(rl->orig);
137 else
138 movefd(rl->into, rl->orig);
139 }
140 ckfree(rl);
141 }
142 rt->renamed = NULL;
143 }
144
145 STATIC void
146 fd_rename(struct redirtab *rt, int from, int to)
147 {
148 struct renamelist *rl = ckmalloc(sizeof(struct renamelist));
149
150 rl->next = rt->renamed;
151 rt->renamed = rl;
152
153 rl->orig = from;
154 rl->into = to;
155 }
156
157 /*
158 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
159 * old file descriptors are stashed away so that the redirection can be
160 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
161 * standard output, and the standard error if it becomes a duplicate of
162 * stdout, is saved in memory.
163 */
164
165 void
166 redirect(union node *redir, int flags)
167 {
168 union node *n;
169 struct redirtab *sv = NULL;
170 int i;
171 int fd;
172 char memory[10]; /* file descriptors to write to memory */
173
174 for (i = 10 ; --i >= 0 ; )
175 memory[i] = 0;
176 memory[1] = flags & REDIR_BACKQ;
177 if (flags & REDIR_PUSH) {
178 /* We don't have to worry about REDIR_VFORK here, as
179 * flags & REDIR_PUSH is never true if REDIR_VFORK is set.
180 */
181 sv = ckmalloc(sizeof (struct redirtab));
182 sv->renamed = NULL;
183 sv->next = redirlist;
184 redirlist = sv;
185 }
186 for (n = redir ; n ; n = n->nfile.next) {
187 fd = n->nfile.fd;
188 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
189 n->ndup.dupfd == fd) {
190 /* redirect from/to same file descriptor */
191 fcntl(fd, F_SETFD, 0); /* make sure it stays open */
192 continue;
193 }
194
195 if ((flags & REDIR_PUSH) && !is_renamed(sv->renamed, fd)) {
196 INTOFF;
197 if (big_sh_fd < 10)
198 find_big_fd();
199 if ((i = fcntl(fd, F_DUPFD, big_sh_fd)) == -1) {
200 switch (errno) {
201 case EBADF:
202 i = CLOSED;
203 break;
204 case EMFILE:
205 case EINVAL:
206 find_big_fd();
207 i = fcntl(fd, F_DUPFD, big_sh_fd);
208 if (i >= 0)
209 break;
210 /* FALLTHRU */
211 default:
212 i = errno;
213 INTON; /* XXX not needed here ? */
214 error("%d: %s", fd, strerror(i));
215 /* NOTREACHED */
216 }
217 }
218 if (i >= 0)
219 (void)fcntl(i, F_SETFD, FD_CLOEXEC);
220 fd_rename(sv, fd, i);
221 INTON;
222 }
223 if (fd == 0)
224 fd0_redirected++;
225 openredirect(n, memory, flags);
226 }
227 if (memory[1])
228 out1 = &memout;
229 if (memory[2])
230 out2 = &memout;
231 }
232
233
234 STATIC void
235 openredirect(union node *redir, char memory[10], int flags)
236 {
237 struct stat sb;
238 int fd = redir->nfile.fd;
239 char *fname;
240 int f;
241 int eflags, cloexec;
242
243 /*
244 * We suppress interrupts so that we won't leave open file
245 * descriptors around. This may not be such a good idea because
246 * an open of a device or a fifo can block indefinitely.
247 */
248 INTOFF;
249 if (fd < 10)
250 memory[fd] = 0;
251 switch (redir->nfile.type) {
252 case NFROM:
253 fname = redir->nfile.expfname;
254 if (flags & REDIR_VFORK)
255 eflags = O_NONBLOCK;
256 else
257 eflags = 0;
258 if ((f = open(fname, O_RDONLY|eflags)) < 0)
259 goto eopen;
260 if (eflags)
261 (void)fcntl(f, F_SETFL, fcntl(f, F_GETFL, 0) & ~eflags);
262 break;
263 case NFROMTO:
264 fname = redir->nfile.expfname;
265 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
266 goto ecreate;
267 break;
268 case NTO:
269 if (Cflag) {
270 fname = redir->nfile.expfname;
271 if ((f = open(fname, O_WRONLY)) == -1) {
272 if ((f = open(fname, O_WRONLY|O_CREAT|O_EXCL,
273 0666)) < 0)
274 goto ecreate;
275 } else if (fstat(f, &sb) == -1) {
276 int serrno = errno;
277 close(f);
278 errno = serrno;
279 goto ecreate;
280 } else if (S_ISREG(sb.st_mode)) {
281 close(f);
282 errno = EEXIST;
283 goto ecreate;
284 }
285 break;
286 }
287 /* FALLTHROUGH */
288 case NCLOBBER:
289 fname = redir->nfile.expfname;
290 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
291 goto ecreate;
292 break;
293 case NAPPEND:
294 fname = redir->nfile.expfname;
295 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
296 goto ecreate;
297 break;
298 case NTOFD:
299 case NFROMFD:
300 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
301 if (fd < 10 && redir->ndup.dupfd < 10 &&
302 memory[redir->ndup.dupfd])
303 memory[fd] = 1;
304 else
305 copyfd(redir->ndup.dupfd, fd, 1, (flags &
306 (REDIR_PUSH|REDIR_KEEP)) == REDIR_PUSH);
307 } else
308 close(fd);
309 INTON;
310 return;
311 case NHERE:
312 case NXHERE:
313 f = openhere(redir);
314 break;
315 default:
316 abort();
317 }
318
319 cloexec = fd > 2 && (flags & REDIR_KEEP) == 0;
320 if (f != fd) {
321 copyfd(f, fd, 1, cloexec);
322 close(f);
323 } else if (cloexec)
324 (void)fcntl(f, F_SETFD, FD_CLOEXEC);
325
326 INTON;
327 return;
328 ecreate:
329 exerrno = 1;
330 error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
331 eopen:
332 exerrno = 1;
333 error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
334 }
335
336
337 /*
338 * Handle here documents. Normally we fork off a process to write the
339 * data to a pipe. If the document is short, we can stuff the data in
340 * the pipe without forking.
341 */
342
343 STATIC int
344 openhere(const union node *redir)
345 {
346 int pip[2];
347 int len = 0;
348
349 if (pipe(pip) < 0)
350 error("Pipe call failed");
351 if (redir->type == NHERE) {
352 len = strlen(redir->nhere.doc->narg.text);
353 if (len <= PIPESIZE) {
354 xwrite(pip[1], redir->nhere.doc->narg.text, len);
355 goto out;
356 }
357 }
358 if (forkshell(NULL, NULL, FORK_NOJOB) == 0) {
359 close(pip[0]);
360 signal(SIGINT, SIG_IGN);
361 signal(SIGQUIT, SIG_IGN);
362 signal(SIGHUP, SIG_IGN);
363 #ifdef SIGTSTP
364 signal(SIGTSTP, SIG_IGN);
365 #endif
366 signal(SIGPIPE, SIG_DFL);
367 if (redir->type == NHERE)
368 xwrite(pip[1], redir->nhere.doc->narg.text, len);
369 else
370 expandhere(redir->nhere.doc, pip[1]);
371 _exit(0);
372 }
373 out:
374 close(pip[1]);
375 return pip[0];
376 }
377
378
379
380 /*
381 * Undo the effects of the last redirection.
382 */
383
384 void
385 popredir(void)
386 {
387 struct redirtab *rp = redirlist;
388
389 INTOFF;
390 free_rl(rp, 1);
391 redirlist = rp->next;
392 ckfree(rp);
393 INTON;
394 }
395
396 /*
397 * Undo all redirections. Called on error or interrupt.
398 */
399
400 #ifdef mkinit
401
402 INCLUDE "redir.h"
403
404 RESET {
405 while (redirlist)
406 popredir();
407 }
408
409 SHELLPROC {
410 clearredir(0);
411 }
412
413 #endif
414
415 /* Return true if fd 0 has already been redirected at least once. */
416 int
417 fd0_redirected_p(void)
418 {
419 return fd0_redirected != 0;
420 }
421
422 /*
423 * Discard all saved file descriptors.
424 */
425
426 void
427 clearredir(int vforked)
428 {
429 struct redirtab *rp;
430 struct renamelist *rl;
431
432 for (rp = redirlist ; rp ; rp = rp->next) {
433 if (!vforked)
434 free_rl(rp, 0);
435 else for (rl = rp->renamed; rl; rl = rl->next)
436 if (rl->into >= 0)
437 close(rl->into);
438 }
439 }
440
441
442
443 /*
444 * Copy a file descriptor to be >= to. Returns -1
445 * if the source file descriptor is closed, EMPTY if there are no unused
446 * file descriptors left.
447 */
448
449 int
450 copyfd(int from, int to, int equal, int cloexec)
451 {
452 int newfd;
453
454 if (cloexec && to > 2) {
455 if (equal)
456 newfd = dup3(from, to, O_CLOEXEC);
457 else
458 newfd = fcntl(from, F_DUPFD_CLOEXEC, to);
459 } else {
460 if (equal)
461 newfd = dup2(from, to);
462 else
463 newfd = fcntl(from, F_DUPFD, to);
464 }
465 if (newfd < 0) {
466 if (errno == EMFILE)
467 return EMPTY;
468 else
469 error("%d: %s", from, strerror(errno));
470 }
471 return newfd;
472 }
473
474 int
475 movefd(int from, int to)
476 {
477 if (from == to)
478 return to;
479
480 (void) close(to);
481 if (copyfd(from, to, 1, 0) != to)
482 error("Unable to make fd %d", to);
483 (void) close(from);
484
485 return to;
486 }
487
488 STATIC void
489 find_big_fd(void)
490 {
491 int i, fd;
492
493 for (i = (1 << 10); i >= 10; i >>= 1) {
494 if ((fd = fcntl(0, F_DUPFD, i - 1)) >= 0) {
495 close(fd);
496 break;
497 }
498 }
499
500 fd = (i / 5) * 4;
501 if ((i - fd) > 100)
502 fd = i - 100;
503 else if (fd < 10)
504 fd = 10;
505
506 big_sh_fd = fd;
507 }
508
509 int
510 to_upper_fd(int fd)
511 {
512 int i;
513
514 if (big_sh_fd < 10)
515 find_big_fd();
516 do {
517 i = fcntl(fd, F_DUPFD_CLOEXEC, big_sh_fd);
518 if (i >= 0) {
519 if (fd != i)
520 close(fd);
521 return i;
522 }
523 if (errno != EMFILE)
524 break;
525 find_big_fd();
526 } while (big_sh_fd > 10);
527
528 /*
529 * If we wamted to move this fd to some random high number
530 * we certainly do not intend to pass it through exec, even
531 * if the reassignment failed.
532 */
533 (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
534 return fd;
535 }
536