void redirect(union node *redir, int flags) { union node *n; struct redirtab *sv = NULL; int i; int fd; char memory[10]; /* file descriptors to write to memory */ INTOFF; for (i = 10 ; --i >= 0 ; ) memory[i] = 0; memory[1] = flags & REDIR_BACKQ; if (flags & REDIR_PUSH) { empty_redirs++; if (redir != NULL) { sv = ckmalloc(sizeof (struct redirtab)); for (i = 0 ; i < 10 ; i++) sv->renamed[i] = EMPTY; sv->fd0_redirected = fd0_redirected; sv->empty_redirs = empty_redirs - 1; sv->next = redirlist; redirlist = sv; empty_redirs = 0; } } for (n = redir ; n ; n = n->nfile.next) { fd = n->nfile.fd; if (fd == 0) fd0_redirected = 1; if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) && n->ndup.dupfd == fd) continue; /* redirect from/to same file descriptor */ if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) { INTOFF; if ((i = fcntl(fd, F_DUPFD_CLOEXEC, 10)) == -1) { switch (errno) { case EBADF: i = CLOSED; break; default: INTON; error("%d: %s", fd, strerror(errno)); break; } } sv->renamed[fd] = i; INTON; } openredirect(n, memory); INTON; INTOFF; } if (memory[1]) out1 = &memout; if (memory[2]) out2 = &memout; INTON; }
void redirect(union node *redir, int flags) { union node *n; struct redirtab *sv = NULL; int i; int fd; char memory[10]; /* file descriptors to write to memory */ for (i = 10 ; --i >= 0 ; ) memory[i] = 0; memory[1] = flags & REDIR_BACKQ; if (flags & REDIR_PUSH) { /* We don't have to worry about REDIR_VFORK here, as * flags & REDIR_PUSH is never true if REDIR_VFORK is set. */ sv = ckmalloc(sizeof (struct redirtab)); for (i = 0 ; i < 10 ; i++) sv->renamed[i] = EMPTY; sv->next = redirlist; redirlist = sv; } for (n = redir ; n ; n = n->nfile.next) { fd = n->nfile.fd; if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) && n->ndup.dupfd == fd) continue; /* redirect from/to same file descriptor */ if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) { INTOFF; if ((i = fcntl(fd, F_DUPFD, 10)) == -1) { switch (errno) { case EBADF: i = CLOSED; break; default: INTON; error("%d: %s", fd, strerror(errno)); /* NOTREACHED */ } } else (void)fcntl(i, F_SETFD, FD_CLOEXEC); sv->renamed[fd] = i; INTON; } else { close(fd); } if (fd == 0) fd0_redirected++; openredirect(n, memory, flags); } if (memory[1]) out1 = &memout; if (memory[2]) out2 = &memout; }
void redirect(union node *redir, int flags) { union node *n; struct redirtab *sv = NULL; int i; int fd; char memory[10]; /* file descriptors to write to memory */ for (i = 10 ; --i >= 0 ; ) memory[i] = 0; memory[1] = flags & REDIR_BACKQ; if (flags & REDIR_PUSH) { /* We don't have to worry about REDIR_VFORK here, as * flags & REDIR_PUSH is never true if REDIR_VFORK is set. */ sv = ckmalloc(sizeof (struct redirtab)); sv->renamed = NULL; sv->next = redirlist; redirlist = sv; } for (n = redir ; n ; n = n->nfile.next) { fd = n->nfile.fd; if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) && n->ndup.dupfd == fd) { /* redirect from/to same file descriptor */ /* make sure it stays open */ if (fcntl(fd, F_SETFD, 0) < 0) error("fd %d: %s", fd, strerror(errno)); continue; } if ((flags & REDIR_PUSH) && !is_renamed(sv->renamed, fd)) { INTOFF; if (big_sh_fd < 10) find_big_fd(); if ((i = fcntl(fd, F_DUPFD, big_sh_fd)) == -1) { switch (errno) { case EBADF: i = CLOSED; break; case EMFILE: case EINVAL: find_big_fd(); i = fcntl(fd, F_DUPFD, big_sh_fd); if (i >= 0) break; /* FALLTHRU */ default: i = errno; INTON; /* XXX not needed here ? */ error("%d: %s", fd, strerror(i)); /* NOTREACHED */ } } if (i >= 0) (void)fcntl(i, F_SETFD, FD_CLOEXEC); fd_rename(sv, fd, i); INTON; } if (fd == 0) fd0_redirected++; openredirect(n, memory, flags); } if (memory[1]) out1 = &memout; if (memory[2]) out2 = &memout; }
void redirect(union node *redir, int flags) { union node *n; struct redirtab *sv; int i; int fd; int newfd; int *p; #if notyet char memory[10]; /* file descriptors to write to memory */ for (i = 10 ; --i >= 0 ; ) memory[i] = 0; memory[1] = flags & REDIR_BACKQ; #endif nullredirs++; if (!redir) { return; } sv = NULL; INTOFF; if (flags & REDIR_PUSH) { struct redirtab *q; q = ckmalloc(sizeof (struct redirtab)); q->next = redirlist; redirlist = q; q->nullredirs = nullredirs - 1; for (i = 0 ; i < 10 ; i++) q->renamed[i] = EMPTY; nullredirs = 0; sv = q; } n = redir; do { fd = n->nfile.fd; if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) && n->ndup.dupfd == fd) continue; /* redirect from/to same file descriptor */ newfd = openredirect(n); if (fd == newfd) continue; if (sv && *(p = &sv->renamed[fd]) == EMPTY) { int i = fcntl(fd, F_DUPFD, 10); if (i == -1) { i = errno; if (i != EBADF) { const char *m = strerror(i); close(newfd); sh_error("%d: %s", fd, m); /* NOTREACHED */ } } else { *p = i; close(fd); } } else { close(fd); } #ifdef notyet dupredirect(n, newfd, memory); #else dupredirect(n, newfd); #endif } while ((n = n->nfile.next)); INTON; #ifdef notyet if (memory[1]) out1 = &memout; if (memory[2]) out2 = &memout; #endif if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0) preverrout.fd = sv->renamed[2]; }