diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-11-22 08:16:57 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-11-22 08:16:57 +0000 |
commit | 7d75a96b15327050a294b1f54981781ce6e551e2 (patch) | |
tree | df8a1fcb74b6bd7869fe60af461c11f0684df043 /shell | |
parent | 705eaf8b403555741cf6313a76da8597ae54d324 (diff) | |
download | busybox-w32-7d75a96b15327050a294b1f54981781ce6e551e2.tar.gz busybox-w32-7d75a96b15327050a294b1f54981781ce6e551e2.tar.bz2 busybox-w32-7d75a96b15327050a294b1f54981781ce6e551e2.zip |
ash: fix bug where redirection of closed fd was leaving it open afterwards.
redirect 983 1024 +41
bb_echo 276 301 +25
popredir 118 132 +14
evalcommand 1163 1176 +13
bbunpack 358 366 +8
echocmd 13 5 -8
echo_main 13 5 -8
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 5/2 up/down: 101/-16) Total: 85 bytes
text data bss dec hex filename
774999 962 9236 785197 bfb2d busybox_old
775084 962 9236 785282 bfb82 busybox_unstripped
Diffstat (limited to 'shell')
-rw-r--r-- | shell/ash.c | 35 | ||||
-rw-r--r-- | shell/ash_test/ash-redir/redir.right | 1 | ||||
-rw-r--r-- | shell/ash_test/ash-redir/redir.tests | 6 |
3 files changed, 29 insertions, 13 deletions
diff --git a/shell/ash.c b/shell/ash.c index bb930f55f..4113ce8e2 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -4567,6 +4567,7 @@ stoppedjobs(void) | |||
4567 | */ | 4567 | */ |
4568 | 4568 | ||
4569 | #define EMPTY -2 /* marks an unused slot in redirtab */ | 4569 | #define EMPTY -2 /* marks an unused slot in redirtab */ |
4570 | #define CLOSED -3 /* marks a slot of previously-closed fd */ | ||
4570 | #ifndef PIPE_BUF | 4571 | #ifndef PIPE_BUF |
4571 | # define PIPESIZE 4096 /* amount of buffering in a pipe */ | 4572 | # define PIPESIZE 4096 /* amount of buffering in a pipe */ |
4572 | #else | 4573 | #else |
@@ -4791,7 +4792,7 @@ redirect(union node *redir, int flags) | |||
4791 | int i; | 4792 | int i; |
4792 | int fd; | 4793 | int fd; |
4793 | int newfd; | 4794 | int newfd; |
4794 | int *p; | 4795 | |
4795 | nullredirs++; | 4796 | nullredirs++; |
4796 | if (!redir) { | 4797 | if (!redir) { |
4797 | return; | 4798 | return; |
@@ -4799,15 +4800,13 @@ redirect(union node *redir, int flags) | |||
4799 | sv = NULL; | 4800 | sv = NULL; |
4800 | INT_OFF; | 4801 | INT_OFF; |
4801 | if (flags & REDIR_PUSH) { | 4802 | if (flags & REDIR_PUSH) { |
4802 | struct redirtab *q; | 4803 | sv = ckmalloc(sizeof(*sv)); |
4803 | q = ckmalloc(sizeof(struct redirtab)); | 4804 | sv->next = redirlist; |
4804 | q->next = redirlist; | 4805 | redirlist = sv; |
4805 | redirlist = q; | 4806 | sv->nullredirs = nullredirs - 1; |
4806 | q->nullredirs = nullredirs - 1; | ||
4807 | for (i = 0; i < 10; i++) | 4807 | for (i = 0; i < 10; i++) |
4808 | q->renamed[i] = EMPTY; | 4808 | sv->renamed[i] = EMPTY; |
4809 | nullredirs = 0; | 4809 | nullredirs = 0; |
4810 | sv = q; | ||
4811 | } | 4810 | } |
4812 | n = redir; | 4811 | n = redir; |
4813 | do { | 4812 | do { |
@@ -4817,9 +4816,14 @@ redirect(union node *redir, int flags) | |||
4817 | continue; /* redirect from/to same file descriptor */ | 4816 | continue; /* redirect from/to same file descriptor */ |
4818 | 4817 | ||
4819 | newfd = openredirect(n); | 4818 | newfd = openredirect(n); |
4820 | if (fd == newfd) | 4819 | if (fd == newfd) { |
4820 | /* Descriptor wasn't open before redirect. | ||
4821 | * Mark it for close in the future */ | ||
4822 | if (sv && sv->renamed[fd] == EMPTY) | ||
4823 | sv->renamed[fd] = CLOSED; | ||
4821 | continue; | 4824 | continue; |
4822 | if (sv && *(p = &sv->renamed[fd]) == EMPTY) { | 4825 | } |
4826 | if (sv && sv->renamed[fd] == EMPTY) { | ||
4823 | i = fcntl(fd, F_DUPFD, 10); | 4827 | i = fcntl(fd, F_DUPFD, 10); |
4824 | 4828 | ||
4825 | if (i == -1) { | 4829 | if (i == -1) { |
@@ -4831,7 +4835,7 @@ redirect(union node *redir, int flags) | |||
4831 | /* NOTREACHED */ | 4835 | /* NOTREACHED */ |
4832 | } | 4836 | } |
4833 | } else { | 4837 | } else { |
4834 | *p = i; | 4838 | sv->renamed[fd] = i; |
4835 | close(fd); | 4839 | close(fd); |
4836 | } | 4840 | } |
4837 | } else { | 4841 | } else { |
@@ -4840,7 +4844,7 @@ redirect(union node *redir, int flags) | |||
4840 | dupredirect(n, newfd); | 4844 | dupredirect(n, newfd); |
4841 | } while ((n = n->nfile.next)); | 4845 | } while ((n = n->nfile.next)); |
4842 | INT_ON; | 4846 | INT_ON; |
4843 | if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0) | 4847 | if ((flags & REDIR_SAVEFD2) && sv && sv->renamed[2] >= 0) |
4844 | preverrout_fd = sv->renamed[2]; | 4848 | preverrout_fd = sv->renamed[2]; |
4845 | } | 4849 | } |
4846 | 4850 | ||
@@ -4858,6 +4862,11 @@ popredir(int drop) | |||
4858 | INT_OFF; | 4862 | INT_OFF; |
4859 | rp = redirlist; | 4863 | rp = redirlist; |
4860 | for (i = 0; i < 10; i++) { | 4864 | for (i = 0; i < 10; i++) { |
4865 | if (rp->renamed[i] == CLOSED) { | ||
4866 | if (!drop) | ||
4867 | close(i); | ||
4868 | continue; | ||
4869 | } | ||
4861 | if (rp->renamed[i] != EMPTY) { | 4870 | if (rp->renamed[i] != EMPTY) { |
4862 | if (!drop) { | 4871 | if (!drop) { |
4863 | close(i); | 4872 | close(i); |
@@ -10994,7 +11003,7 @@ exitcmd(int argc, char **argv) | |||
10994 | static int | 11003 | static int |
10995 | echocmd(int argc, char **argv) | 11004 | echocmd(int argc, char **argv) |
10996 | { | 11005 | { |
10997 | return bb_echo(argv); | 11006 | return bb_echo(argc, argv); |
10998 | } | 11007 | } |
10999 | #endif | 11008 | #endif |
11000 | 11009 | ||
diff --git a/shell/ash_test/ash-redir/redir.right b/shell/ash_test/ash-redir/redir.right new file mode 100644 index 000000000..2a02d41ce --- /dev/null +++ b/shell/ash_test/ash-redir/redir.right | |||
@@ -0,0 +1 @@ | |||
TEST | |||
diff --git a/shell/ash_test/ash-redir/redir.tests b/shell/ash_test/ash-redir/redir.tests new file mode 100644 index 000000000..7a1a66806 --- /dev/null +++ b/shell/ash_test/ash-redir/redir.tests | |||
@@ -0,0 +1,6 @@ | |||
1 | # test: closed fds should stay closed | ||
2 | exec 1>&- | ||
3 | echo TEST >TEST | ||
4 | echo JUNK # lost: stdout is closed | ||
5 | cat TEST >&2 | ||
6 | rm TEST | ||