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
This commit is contained in:
Denis Vlasenko
2007-11-22 08:16:57 +00:00
parent 705eaf8b40
commit 7d75a96b15
5 changed files with 169 additions and 16 deletions

View File

@@ -4567,6 +4567,7 @@ stoppedjobs(void)
*/
#define EMPTY -2 /* marks an unused slot in redirtab */
#define CLOSED -3 /* marks a slot of previously-closed fd */
#ifndef PIPE_BUF
# define PIPESIZE 4096 /* amount of buffering in a pipe */
#else
@@ -4791,7 +4792,7 @@ redirect(union node *redir, int flags)
int i;
int fd;
int newfd;
int *p;
nullredirs++;
if (!redir) {
return;
@@ -4799,15 +4800,13 @@ redirect(union node *redir, int flags)
sv = NULL;
INT_OFF;
if (flags & REDIR_PUSH) {
struct redirtab *q;
q = ckmalloc(sizeof(struct redirtab));
q->next = redirlist;
redirlist = q;
q->nullredirs = nullredirs - 1;
sv = ckmalloc(sizeof(*sv));
sv->next = redirlist;
redirlist = sv;
sv->nullredirs = nullredirs - 1;
for (i = 0; i < 10; i++)
q->renamed[i] = EMPTY;
sv->renamed[i] = EMPTY;
nullredirs = 0;
sv = q;
}
n = redir;
do {
@@ -4817,9 +4816,14 @@ redirect(union node *redir, int flags)
continue; /* redirect from/to same file descriptor */
newfd = openredirect(n);
if (fd == newfd)
if (fd == newfd) {
/* Descriptor wasn't open before redirect.
* Mark it for close in the future */
if (sv && sv->renamed[fd] == EMPTY)
sv->renamed[fd] = CLOSED;
continue;
if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
}
if (sv && sv->renamed[fd] == EMPTY) {
i = fcntl(fd, F_DUPFD, 10);
if (i == -1) {
@@ -4831,7 +4835,7 @@ redirect(union node *redir, int flags)
/* NOTREACHED */
}
} else {
*p = i;
sv->renamed[fd] = i;
close(fd);
}
} else {
@@ -4840,7 +4844,7 @@ redirect(union node *redir, int flags)
dupredirect(n, newfd);
} while ((n = n->nfile.next));
INT_ON;
if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
if ((flags & REDIR_SAVEFD2) && sv && sv->renamed[2] >= 0)
preverrout_fd = sv->renamed[2];
}
@@ -4858,6 +4862,11 @@ popredir(int drop)
INT_OFF;
rp = redirlist;
for (i = 0; i < 10; i++) {
if (rp->renamed[i] == CLOSED) {
if (!drop)
close(i);
continue;
}
if (rp->renamed[i] != EMPTY) {
if (!drop) {
close(i);
@@ -10994,7 +11003,7 @@ exitcmd(int argc, char **argv)
static int
echocmd(int argc, char **argv)
{
return bb_echo(argv);
return bb_echo(argc, argv);
}
#endif

View File

@@ -0,0 +1 @@
TEST

View File

@@ -0,0 +1,6 @@
# test: closed fds should stay closed
exec 1>&-
echo TEST >TEST
echo JUNK # lost: stdout is closed
cat TEST >&2
rm TEST