aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-07-24 12:42:17 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-07-24 12:42:17 +0200
commit621fc50e83f7446a060f0b9689dc8dc59ee0743a (patch)
tree7b40c2368fe3f7387ab44a1f0758d850cbd29929
parentb72f1ef17b97802d33f0ac522f64bea0f65442c5 (diff)
downloadbusybox-w32-621fc50e83f7446a060f0b9689dc8dc59ee0743a.tar.gz
busybox-w32-621fc50e83f7446a060f0b9689dc8dc59ee0743a.tar.bz2
busybox-w32-621fc50e83f7446a060f0b9689dc8dc59ee0743a.zip
hush: fix a case when redirect to a closed fd #1 is not restoring (closing) it
function old new delta setup_redirects 200 245 +45 append_squirrel - 41 +41 save_fds_on_redirect 256 221 -35 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/1 up/down: 86/-35) Total: 51 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/hush.c34
-rw-r--r--shell/hush_test/hush-redir/redir.right2
-rwxr-xr-xshell/hush_test/hush-redir/redir.tests6
3 files changed, 35 insertions, 7 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 309ed2139..20b092398 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -6643,8 +6643,18 @@ struct squirrel {
6643 /* moved_to = -1: fd was opened by redirect; close orig_fd after redir */ 6643 /* moved_to = -1: fd was opened by redirect; close orig_fd after redir */
6644}; 6644};
6645 6645
6646static struct squirrel *append_squirrel(struct squirrel *sq, int i, int orig, int moved)
6647{
6648 sq = xrealloc(sq, (i + 2) * sizeof(sq[0]));
6649 sq[i].orig_fd = orig;
6650 sq[i].moved_to = moved;
6651 sq[i+1].orig_fd = -1; /* end marker */
6652 return sq;
6653}
6654
6646static struct squirrel *add_squirrel(struct squirrel *sq, int fd, int avoid_fd) 6655static struct squirrel *add_squirrel(struct squirrel *sq, int fd, int avoid_fd)
6647{ 6656{
6657 int moved_to;
6648 int i = 0; 6658 int i = 0;
6649 6659
6650 if (sq) while (sq[i].orig_fd >= 0) { 6660 if (sq) while (sq[i].orig_fd >= 0) {
@@ -6664,15 +6674,12 @@ static struct squirrel *add_squirrel(struct squirrel *sq, int fd, int avoid_fd)
6664 i++; 6674 i++;
6665 } 6675 }
6666 6676
6667 sq = xrealloc(sq, (i + 2) * sizeof(sq[0]));
6668 sq[i].orig_fd = fd;
6669 /* If this fd is open, we move and remember it; if it's closed, moved_to = -1 */ 6677 /* If this fd is open, we move and remember it; if it's closed, moved_to = -1 */
6670 sq[i].moved_to = fcntl_F_DUPFD(fd, avoid_fd); 6678 moved_to = fcntl_F_DUPFD(fd, avoid_fd);
6671 debug_printf_redir("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, sq[i].moved_to); 6679 debug_printf_redir("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, moved_to);
6672 if (sq[i].moved_to < 0 && errno != EBADF) 6680 if (moved_to < 0 && errno != EBADF)
6673 xfunc_die(); 6681 xfunc_die();
6674 sq[i+1].orig_fd = -1; /* end marker */ 6682 return append_squirrel(sq, i, fd, moved_to);
6675 return sq;
6676} 6683}
6677 6684
6678/* fd: redirect wants this fd to be used (e.g. 3>file). 6685/* fd: redirect wants this fd to be used (e.g. 3>file).
@@ -6778,6 +6785,19 @@ static int setup_redirects(struct command *prog, struct squirrel **sqp)
6778 */ 6785 */
6779 return 1; 6786 return 1;
6780 } 6787 }
6788 if (openfd == redir->rd_fd && sqp) {
6789 /* open() gave us precisely the fd we wanted.
6790 * This means that this fd was not busy
6791 * (not opened to anywhere).
6792 * Remember to close it on restore:
6793 */
6794 struct squirrel *sq = *sqp;
6795 int i = 0;
6796 if (sq) while (sq[i].orig_fd >= 0)
6797 i++;
6798 *sqp = append_squirrel(sq, i, openfd, -1); /* -1 = "it was closed" */
6799 debug_printf_redir("redir to previously closed fd %d\n", openfd);
6800 }
6781 } else { 6801 } else {
6782 /* "rd_fd<*>rd_dup" or "rd_fd<*>-" cases */ 6802 /* "rd_fd<*>rd_dup" or "rd_fd<*>-" cases */
6783 openfd = redir->rd_dup; 6803 openfd = redir->rd_dup;
diff --git a/shell/hush_test/hush-redir/redir.right b/shell/hush_test/hush-redir/redir.right
new file mode 100644
index 000000000..4de5ec701
--- /dev/null
+++ b/shell/hush_test/hush-redir/redir.right
@@ -0,0 +1,2 @@
1hush: write error: Bad file descriptor
2TEST
diff --git a/shell/hush_test/hush-redir/redir.tests b/shell/hush_test/hush-redir/redir.tests
new file mode 100755
index 000000000..7a1a66806
--- /dev/null
+++ b/shell/hush_test/hush-redir/redir.tests
@@ -0,0 +1,6 @@
1# test: closed fds should stay closed
2exec 1>&-
3echo TEST >TEST
4echo JUNK # lost: stdout is closed
5cat TEST >&2
6rm TEST