redir.c revision 1.50 1 /* $NetBSD: redir.c,v 1.50 2017/02/02 20:00:40 christos 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.50 2017/02/02 20:00:40 christos Exp $");
41 #endif
42 #endif /* not lint */
43
44 #include <sys/types.h>
45 #include <sys/param.h> /* PIPE_BUF */
46 #include <sys/stat.h>
47 #include <signal.h>
48 #include <string.h>
49 #include <fcntl.h>
50 #include <errno.h>
51 #include <unistd.h>
52 #include <stdlib.h>
53
54 /*
55 * Code for dealing with input/output redirection.
56 */
57
58 #include "main.h"
59 #include "builtins.h"
60 #include "shell.h"
61 #include "nodes.h"
62 #include "jobs.h"
63 #include "options.h"
64 #include "expand.h"
65 #include "redir.h"
66 #include "output.h"
67 #include "memalloc.h"
68 #include "error.h"
69
70
71 #define EMPTY -2 /* marks an unused slot in redirtab */
72 #define CLOSED -1 /* fd was not open before redir */
73 #ifndef PIPE_BUF
74 # define PIPESIZE 4096 /* amount of buffering in a pipe */
75 #else
76 # define PIPESIZE PIPE_BUF
77 #endif
78
79
80 MKINIT
81 struct renamelist {
82 struct renamelist *next;
83 int orig;
84 int into;
85 };
86
87 MKINIT
88 struct redirtab {
89 struct redirtab *next;
90 struct renamelist *renamed;
91 };
92
93
94 MKINIT struct redirtab *redirlist;
95
96 /*
97 * We keep track of whether or not fd0 has been redirected. This is for
98 * background commands, where we want to redirect fd0 to /dev/null only
99 * if it hasn't already been redirected.
100 */
101 STATIC int fd0_redirected = 0;
102
103 /*
104 * And also where to put internal use fds that should be out of the
105 * way of user defined fds (normally)
106 */
107 STATIC int big_sh_fd = 0;
108
109 STATIC const struct renamelist *is_renamed(const struct renamelist *, int);
110 STATIC void fd_rename(struct redirtab *, int, int);
111 STATIC void free_rl(struct redirtab *, int);
112 STATIC void openredirect(union node *, char[10], int);
113 STATIC int openhere(const union node *);
114 STATIC int copyfd(int, int, int);
115 STATIC void find_big_fd(void);
116
117 STATIC const struct renamelist *
118 is_renamed(const struct renamelist *rl, int fd)
119 {
120 while (rl != NULL) {
121 if (rl->orig == fd)
122 return rl;
123 rl = rl->next;
124 }
125 return NULL;
126 }
127
128 STATIC void
129 free_rl(struct redirtab *rt, int reset)
130 {
131 struct renamelist *rl, *rn = rt->renamed;
132
133 while ((rl = rn) != NULL) {
134 rn = rl->next;
135 if (rl->orig == 0)
136 fd0_redirected--;
137 if (reset) {
138 if (rl->into < 0)
139 close(rl->orig);
140 else
141 movefd(rl->into, rl->orig);
142 }
143 ckfree(rl);
144 }
145 rt->renamed = NULL;
146 }
147
148 STATIC void
149 fd_rename(struct redirtab *rt, int from, int to)
150 {
151 struct renamelist *rl = ckmalloc(sizeof(struct renamelist));
152
153 rl->next = rt->renamed;
154 rt->renamed = rl;
155
156 rl->orig = from;
157 rl->into = to;
158 }
159
160 /*
161 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
162 * old file descriptors are stashed away so that the redirection can be
163 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
164 * standard output, and the standard error if it becomes a duplicate of
165 * stdout, is saved in memory.
166 */
167
168 void
169 redirect(union node *redir, int flags)
170 {
171 union node *n;
172 struct redirtab *sv = NULL;
173 int i;
174 int fd;
175 char memory[10]; /* file descriptors to write to memory */
176
177 for (i = 10 ; --i >= 0 ; )
178 memory[i] = 0;
179 memory[1] = flags & REDIR_BACKQ;
180 if (flags & REDIR_PUSH) {
181 /* We don't have to worry about REDIR_VFORK here, as
182 * flags & REDIR_PUSH is never true if REDIR_VFORK is set.
183 */
184 sv = ckmalloc(sizeof (struct redirtab));
185 sv->renamed = NULL;
186 sv->next = redirlist;
187 redirlist = sv;
188 }
189 for (n = redir ; n ; n = n->nfile.next) {
190 fd = n->nfile.fd;
191 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
192 n->ndup.dupfd == fd) {
193 /* redirect from/to same file descriptor */
194 /* make sure it stays open */
195 if (fcntl(fd, F_SETFD, 0) < 0)
196 error("fd %d: %s", fd, strerror(errno));
197 continue;
198 }
199
200 if ((flags & REDIR_PUSH) && !is_renamed(sv->renamed, fd)) {
201 INTOFF;
202 if (big_sh_fd < 10)
203 find_big_fd();
204 if ((i = fcntl(fd, F_DUPFD, big_sh_fd)) == -1) {
205 switch (errno) {
206 case EBADF:
207 i = CLOSED;
208 break;
209 case EMFILE:
210 case EINVAL:
211 find_big_fd();
212 i = fcntl(fd, F_DUPFD, big_sh_fd);
213 if (i >= 0)
214 break;
215 /* FALLTHRU */
216 default:
217 i = errno;
218 INTON; /* XXX not needed here ? */
219 error("%d: %s", fd, strerror(i));
220 /* NOTREACHED */
221 }
222 }
223 if (i >= 0)
224 (void)fcntl(i, F_SETFD, FD_CLOEXEC);
225 fd_rename(sv, fd, i);
226 INTON;
227 }
228 if (fd == 0)
229 fd0_redirected++;
230 openredirect(n, memory, flags);
231 }
232 if (memory[1])
233 out1 = &memout;
234 if (memory[2])
235 out2 = &memout;
236 }
237
238
239 STATIC void
240 openredirect(union node *redir, char memory[10], int flags)
241 {
242 struct stat sb;
243 int fd = redir->nfile.fd;
244 char *fname;
245 int f;
246 int eflags, cloexec;
247
248 /*
249 * We suppress interrupts so that we won't leave open file
250 * descriptors around. This may not be such a good idea because
251 * an open of a device or a fifo can block indefinitely.
252 */
253 INTOFF;
254 if (fd < 10)
255 memory[fd] = 0;
256 switch (redir->nfile.type) {
257 case NFROM:
258 fname = redir->nfile.expfname;
259 if (flags & REDIR_VFORK)
260 eflags = O_NONBLOCK;
261 else
262 eflags = 0;
263 if ((f = open(fname, O_RDONLY|eflags)) < 0)
264 goto eopen;
265 if (eflags)
266 (void)fcntl(f, F_SETFL, fcntl(f, F_GETFL, 0) & ~eflags);
267 break;
268 case NFROMTO:
269 fname = redir->nfile.expfname;
270 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
271 goto ecreate;
272 break;
273 case NTO:
274 if (Cflag) {
275 fname = redir->nfile.expfname;
276 if ((f = open(fname, O_WRONLY)) == -1) {
277 if ((f = open(fname, O_WRONLY|O_CREAT|O_EXCL,
278 0666)) < 0)
279 goto ecreate;
280 } else if (fstat(f, &sb) == -1) {
281 int serrno = errno;
282 close(f);
283 errno = serrno;
284 goto ecreate;
285 } else if (S_ISREG(sb.st_mode)) {
286 close(f);
287 errno = EEXIST;
288 goto ecreate;
289 }
290 break;
291 }
292 /* FALLTHROUGH */
293 case NCLOBBER:
294 fname = redir->nfile.expfname;
295 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
296 goto ecreate;
297 break;
298 case NAPPEND:
299 fname = redir->nfile.expfname;
300 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
301 goto ecreate;
302 break;
303 case NTOFD:
304 case NFROMFD:
305 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
306 if (fd < 10 && redir->ndup.dupfd < 10 &&
307 memory[redir->ndup.dupfd])
308 memory[fd] = 1;
309 else if (copyfd(redir->ndup.dupfd, fd,
310 (flags & REDIR_KEEP) == 0) < 0)
311 error("Redirect (from %d to %d) failed: %s",
312 redir->ndup.dupfd, fd, strerror(errno));
313 } else
314 (void) close(fd);
315 INTON;
316 return;
317 case NHERE:
318 case NXHERE:
319 f = openhere(redir);
320 break;
321 default:
322 abort();
323 }
324
325 cloexec = fd > 2 && (flags & REDIR_KEEP) == 0;
326 if (f != fd) {
327 if (copyfd(f, fd, cloexec) < 0) {
328 int e = errno;
329
330 close(f);
331 error("redirect reassignment (fd %d) failed: %s", fd,
332 strerror(e));
333 }
334 close(f);
335 } else if (cloexec)
336 (void)fcntl(f, F_SETFD, FD_CLOEXEC);
337
338 INTON;
339 return;
340 ecreate:
341 exerrno = 1;
342 error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
343 eopen:
344 exerrno = 1;
345 error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
346 }
347
348
349 /*
350 * Handle here documents. Normally we fork off a process to write the
351 * data to a pipe. If the document is short, we can stuff the data in
352 * the pipe without forking.
353 */
354
355 STATIC int
356 openhere(const union node *redir)
357 {
358 int pip[2];
359 int len = 0;
360
361 if (pipe(pip) < 0)
362 error("Pipe call failed");
363 if (redir->type == NHERE) {
364 len = strlen(redir->nhere.doc->narg.text);
365 if (len <= PIPESIZE) {
366 xwrite(pip[1], redir->nhere.doc->narg.text, len);
367 goto out;
368 }
369 }
370 if (forkshell(NULL, NULL, FORK_NOJOB) == 0) {
371 close(pip[0]);
372 signal(SIGINT, SIG_IGN);
373 signal(SIGQUIT, SIG_IGN);
374 signal(SIGHUP, SIG_IGN);
375 #ifdef SIGTSTP
376 signal(SIGTSTP, SIG_IGN);
377 #endif
378 signal(SIGPIPE, SIG_DFL);
379 if (redir->type == NHERE)
380 xwrite(pip[1], redir->nhere.doc->narg.text, len);
381 else
382 expandhere(redir->nhere.doc, pip[1]);
383 _exit(0);
384 }
385 out:
386 close(pip[1]);
387 return pip[0];
388 }
389
390
391
392 /*
393 * Undo the effects of the last redirection.
394 */
395
396 void
397 popredir(void)
398 {
399 struct redirtab *rp = redirlist;
400
401 INTOFF;
402 free_rl(rp, 1);
403 redirlist = rp->next;
404 ckfree(rp);
405 INTON;
406 }
407
408 /*
409 * Undo all redirections. Called on error or interrupt.
410 */
411
412 #ifdef mkinit
413
414 INCLUDE "redir.h"
415
416 RESET {
417 while (redirlist)
418 popredir();
419 }
420
421 SHELLPROC {
422 clearredir(0);
423 }
424
425 #endif
426
427 /* Return true if fd 0 has already been redirected at least once. */
428 int
429 fd0_redirected_p(void)
430 {
431 return fd0_redirected != 0;
432 }
433
434 /*
435 * Discard all saved file descriptors.
436 */
437
438 void
439 clearredir(int vforked)
440 {
441 struct redirtab *rp;
442 struct renamelist *rl;
443
444 for (rp = redirlist ; rp ; rp = rp->next) {
445 if (!vforked)
446 free_rl(rp, 0);
447 else for (rl = rp->renamed; rl; rl = rl->next)
448 if (rl->into >= 0)
449 close(rl->into);
450 }
451 }
452
453
454
455 /*
456 * Copy a file descriptor to be == to.
457 * cloexec indicates if we want close-on-exec or not.
458 * Returns -1 if any error occurs.
459 */
460
461 STATIC int
462 copyfd(int from, int to, int cloexec)
463 {
464 int newfd;
465
466 if (cloexec && to > 2)
467 newfd = dup3(from, to, O_CLOEXEC);
468 else
469 newfd = dup2(from, to);
470
471 return newfd;
472 }
473
474 /*
475 * rename fd from to be fd to (closing from).
476 * close-on-exec is never set on 'to' (unless
477 * from==to and it was set on from) - ie: a no-op
478 * returns to (or errors() if an error occurs).
479 *
480 * This is mostly used for rearranging the
481 * results from pipe().
482 */
483 int
484 movefd(int from, int to)
485 {
486 if (from == to)
487 return to;
488
489 (void) close(to);
490 if (copyfd(from, to, 0) != to) {
491 int e = errno;
492
493 (void) close(from);
494 error("Unable to make fd %d: %s", to, strerror(e));
495 }
496 (void) close(from);
497
498 return to;
499 }
500
501 STATIC void
502 find_big_fd(void)
503 {
504 int i, fd;
505
506 for (i = (1 << 10); i >= 10; i >>= 1) {
507 if ((fd = fcntl(0, F_DUPFD, i - 1)) >= 0) {
508 close(fd);
509 break;
510 }
511 }
512
513 fd = (i / 5) * 4;
514 if ((i - fd) > 100)
515 fd = i - 100;
516 else if (fd < 10)
517 fd = 10;
518
519 big_sh_fd = fd;
520 }
521
522 /*
523 * If possible, move file descriptor fd out of the way
524 * of expected user fd values. Returns the new fd
525 * (which may be the input fd if things do not go well.)
526 * Always set close-on-exec on the result, and close
527 * the input fd unless it is to be our result.
528 */
529 int
530 to_upper_fd(int fd)
531 {
532 int i;
533
534 if (big_sh_fd < 10)
535 find_big_fd();
536 do {
537 i = fcntl(fd, F_DUPFD_CLOEXEC, big_sh_fd);
538 if (i >= 0) {
539 if (fd != i)
540 close(fd);
541 return i;
542 }
543 if (errno != EMFILE)
544 break;
545 find_big_fd();
546 } while (big_sh_fd > 10);
547
548 /*
549 * If we wanted to move this fd to some random high number
550 * we certainly do not intend to pass it through exec, even
551 * if the reassignment failed.
552 */
553 (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
554 return fd;
555 }
556
557 static const struct {
558 const char *name;
559 uint32_t value;
560 } nv[] = {
561 #ifdef O_APPEND
562 { "append", O_APPEND },
563 #endif
564 #ifdef O_ASYNC
565 { "async", O_ASYNC },
566 #endif
567 #ifdef O_SYNC
568 { "sync", O_SYNC },
569 #endif
570 #ifdef O_NONBLOCK
571 { "nonblock", O_NONBLOCK },
572 #endif
573 #ifdef O_FSYNC
574 { "fsync", O_FSYNC },
575 #endif
576 #ifdef O_DSYNC
577 { "dsync", O_DSYNC },
578 #endif
579 #ifdef O_RSYNC
580 { "rsync", O_RSYNC },
581 #endif
582 #ifdef O_ALTIO
583 { "altio", O_ALT_IO },
584 #endif
585 #ifdef O_DIRECT
586 { "direct", O_DIRECT },
587 #endif
588 #ifdef O_NOSIGPIPE
589 { "nosigpipe", O_NOSIGPIPE },
590 #endif
591 #ifdef O_CLOEXEC
592 { "cloexec", O_CLOEXEC },
593 #endif
594 };
595 #define ALLFLAGS (O_APPEND|O_ASYNC|O_SYNC|O_NONBLOCK|O_DSYNC|O_RSYNC|\
596 O_ALT_IO|O_DIRECT|O_NOSIGPIPE|O_CLOEXEC)
597
598 static int
599 getflags(int fd, int p)
600 {
601 int c, f;
602
603 if ((c = fcntl(fd, F_GETFD)) == -1) {
604 if (!p)
605 return -1;
606 error("Can't get status for fd=%d (%s)", fd, strerror(errno));
607 }
608 if ((f = fcntl(fd, F_GETFL)) == -1) {
609 if (!p)
610 return -1;
611 error("Can't get flags for fd=%d (%s)", fd, strerror(errno));
612 }
613 if (c)
614 f |= O_CLOEXEC;
615 return f & ALLFLAGS;
616 }
617
618 static void
619 printone(int fd, int p, int verbose)
620 {
621 int f = getflags(fd, p);
622
623 if (f == -1)
624 return;
625
626 outfmt(out1, "%d:", fd);
627 for (size_t i = 0; i < __arraycount(nv); i++) {
628 if (f & nv[i].value) {
629 outfmt(out1, "%s%s", verbose ? "+" : "", nv[i].name);
630 f &= ~nv[i].value;
631 } else if (verbose)
632 outfmt(out1, "-%s", nv[i].name);
633 else
634 continue;
635 if (f || (verbose && i != __arraycount(nv) - 1))
636 outfmt(out1, ",");
637 }
638 outfmt(out1, "\n");
639 }
640
641 static int
642 parseflags(char *s, int *p, int *n)
643 {
644 int f = 0, *v;
645
646 *p = 0;
647 *n = 0;
648 for (s = strtok(s, ","); s; s = strtok(NULL, ",")) {
649 size_t i;
650 switch (*s) {
651 case '+':
652 v = p;
653 s++;
654 break;
655 case '-':
656 v = n;
657 s++;
658 break;
659 default:
660 v = &f;
661 break;
662 }
663
664 for (i = 0; i < __arraycount(nv); i++)
665 if (strcmp(s, nv[i].name) == 0) {
666 *v |= nv[i].value;
667 break;
668 }
669 if (i == __arraycount(nv))
670 error("Bad flag `%s'", s);
671 }
672 return f;
673 }
674
675 static void
676 setone(int fd, int pos, int neg, int verbose)
677 {
678 int f = getflags(fd, 1);
679 if (f == -1)
680 return;
681
682 int cloexec = -1;
683 if ((pos & O_CLOEXEC) && !(f & O_CLOEXEC))
684 cloexec = FD_CLOEXEC;
685 if ((neg & O_CLOEXEC) && (f & O_CLOEXEC))
686 cloexec = 0;
687
688 if (cloexec != -1 && fcntl(fd, F_SETFD, cloexec) == -1)
689 error("Can't set status for fd=%d (%s)", fd, strerror(errno));
690
691 pos &= ~O_CLOEXEC;
692 neg &= ~O_CLOEXEC;
693 f &= ~O_CLOEXEC;
694 int n = f;
695 n |= pos;
696 n &= ~neg;
697 if (n != f && fcntl(fd, F_SETFL, n) == -1)
698 error("Can't set flags for fd=%d (%s)", fd, strerror(errno));
699 if (verbose)
700 printone(fd, 1, verbose);
701 }
702
703 int
704 fdflagscmd(int argc, char *argv[])
705 {
706 char *num;
707 int verbose = 0, ch, pos = 0, neg = 0;
708 char *setflags = NULL;
709
710 optreset = 1; optind = 1; /* initialize getopt */
711 while ((ch = getopt(argc, argv, ":vs:")) != -1)
712 switch ((char)ch) {
713 case 'v':
714 verbose = 1;
715 break;
716 case 's':
717 setflags = optarg;
718 break;
719 case '?':
720 default:
721 msg:
722 error("Usage: fdflags [-v] [-s <flags>] [fd...]");
723 /* NOTREACHED */
724 }
725
726 argc -= optind, argv += optind;
727
728 if (setflags && parseflags(setflags, &pos, &neg))
729 error("Need + or - before flags");
730
731 if (argc == 0) {
732 if (setflags)
733 goto msg;
734 int maxfd = fcntl(0, F_MAXFD);
735 if (maxfd == -1)
736 error("Can't get max fd (%s)", strerror(errno));
737 for (int i = 0; i <= maxfd; i++)
738 printone(i, 0, verbose);
739 return 0;
740 }
741
742 while ((num = *argv++) != NULL) {
743 int e;
744 int fd = (int)strtoi(num, NULL, 0, 0, INT_MAX, &e);
745 if (e)
746 error("Can't parse `%s' (%s)", num, strerror(e));
747 if (setflags)
748 setone(fd, pos, neg, verbose);
749 else
750 printone(fd, 1, verbose);
751 }
752 return 0;
753 }
754