diff options
-rw-r--r-- | shell/ash.c | 52 |
1 files changed, 24 insertions, 28 deletions
diff --git a/shell/ash.c b/shell/ash.c index de1f8006d..8f3143669 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -4828,6 +4828,7 @@ openredirect(union node *redir) | |||
4828 | abort(); | 4828 | abort(); |
4829 | #endif | 4829 | #endif |
4830 | /* Fall through to eliminate warning. */ | 4830 | /* Fall through to eliminate warning. */ |
4831 | /* Our single caller does this itself */ | ||
4831 | // case NTOFD: | 4832 | // case NTOFD: |
4832 | // case NFROMFD: | 4833 | // case NFROMFD: |
4833 | // f = -1; | 4834 | // f = -1; |
@@ -4864,30 +4865,13 @@ copyfd(int from, int to) | |||
4864 | return newfd; | 4865 | return newfd; |
4865 | } | 4866 | } |
4866 | 4867 | ||
4867 | static void | 4868 | /* Struct def and variable are moved down to the first usage site */ |
4868 | dupredirect(union node *redir, int f) | ||
4869 | { | ||
4870 | int fd = redir->nfile.fd; | ||
4871 | |||
4872 | if (f < 0) { /* redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD */ | ||
4873 | if (redir->ndup.dupfd >= 0) { /* if not ">&-" */ | ||
4874 | copyfd(redir->ndup.dupfd, fd); | ||
4875 | } | ||
4876 | return; | ||
4877 | } | ||
4878 | if (f != fd) { | ||
4879 | copyfd(f, fd); | ||
4880 | close(f); | ||
4881 | } | ||
4882 | } | ||
4883 | |||
4884 | /**/ | ||
4885 | struct redirtab { | 4869 | struct redirtab { |
4886 | struct redirtab *next; | 4870 | struct redirtab *next; |
4887 | int renamed[10]; | 4871 | int renamed[10]; |
4888 | int nullredirs; | 4872 | int nullredirs; |
4889 | }; | 4873 | }; |
4890 | #define redirlist (G_var.redirlist ) | 4874 | #define redirlist (G_var.redirlist) |
4891 | 4875 | ||
4892 | /* | 4876 | /* |
4893 | * Process a list of redirection commands. If the REDIR_PUSH flag is set, | 4877 | * Process a list of redirection commands. If the REDIR_PUSH flag is set, |
@@ -4918,10 +4902,11 @@ redirect(union node *redir, int flags) | |||
4918 | sv->next = redirlist; | 4902 | sv->next = redirlist; |
4919 | redirlist = sv; | 4903 | redirlist = sv; |
4920 | sv->nullredirs = g_nullredirs - 1; | 4904 | sv->nullredirs = g_nullredirs - 1; |
4905 | g_nullredirs = 0; | ||
4921 | for (i = 0; i < 10; i++) | 4906 | for (i = 0; i < 10; i++) |
4922 | sv->renamed[i] = EMPTY; | 4907 | sv->renamed[i] = EMPTY; |
4923 | g_nullredirs = 0; | ||
4924 | } | 4908 | } |
4909 | |||
4925 | do { | 4910 | do { |
4926 | fd = redir->nfile.fd; | 4911 | fd = redir->nfile.fd; |
4927 | if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) { | 4912 | if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) { |
@@ -4943,26 +4928,37 @@ redirect(union node *redir, int flags) | |||
4943 | i = fcntl(fd, F_DUPFD, 10); | 4928 | i = fcntl(fd, F_DUPFD, 10); |
4944 | if (i == -1) { | 4929 | if (i == -1) { |
4945 | i = errno; | 4930 | i = errno; |
4946 | if (i != EBADF) { /* strange error */ | 4931 | if (i != EBADF) { |
4947 | close(newfd); | 4932 | /* Strange error (e.g. "too many files" EMFILE?) */ |
4933 | /*if (newfd >= 0)*/ close(newfd); | ||
4948 | errno = i; | 4934 | errno = i; |
4949 | ash_msg_and_raise_error("%d: %m", fd); | 4935 | ash_msg_and_raise_error("%d: %m", fd); |
4950 | /* NOTREACHED */ | 4936 | /* NOTREACHED */ |
4951 | } | 4937 | } |
4952 | /* it is not open - ok */ | 4938 | /* EBADF: it is not open - ok */ |
4953 | } else { | 4939 | } else { |
4954 | /* it is open, save its copy */ | 4940 | /* fd is open, save its copy */ |
4941 | //TODO: CLOEXEC the copy? currently these extra "saved" fds are closed | ||
4942 | // in popredir() in the child, preventing them from leaking into child. | ||
4943 | // (popredir() also cleans up the mess in case of failures) | ||
4955 | sv->renamed[fd] = i; | 4944 | sv->renamed[fd] = i; |
4956 | close(fd); | 4945 | close(fd); |
4957 | } | 4946 | } |
4958 | } else { | 4947 | } else { |
4959 | close(fd); | 4948 | close(fd); |
4960 | } | 4949 | } |
4961 | /* Here fd is closed */ | 4950 | /* At this point fd is closed */ |
4962 | /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */ | 4951 | if (newfd < 0) { |
4963 | /* else: move newfd to fd */ | 4952 | /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */ |
4964 | dupredirect(redir, newfd); | 4953 | if (redir->ndup.dupfd >= 0) { /* if not ">&-" */ |
4954 | copyfd(redir->ndup.dupfd, fd); | ||
4955 | } | ||
4956 | } else { /* move newfd to fd */ | ||
4957 | copyfd(newfd, fd); | ||
4958 | close(newfd); | ||
4959 | } | ||
4965 | } while ((redir = redir->nfile.next) != NULL); | 4960 | } while ((redir = redir->nfile.next) != NULL); |
4961 | |||
4966 | INT_ON; | 4962 | INT_ON; |
4967 | if ((flags & REDIR_SAVEFD2) && sv && sv->renamed[2] >= 0) | 4963 | if ((flags & REDIR_SAVEFD2) && sv && sv->renamed[2] >= 0) |
4968 | preverrout_fd = sv->renamed[2]; | 4964 | preverrout_fd = sv->renamed[2]; |