diff options
author | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2010-09-14 12:41:32 +1000 |
---|---|---|
committer | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2010-09-14 12:41:32 +1000 |
commit | 30c62e541a1484fedc3d689d62f96d246a28b147 (patch) | |
tree | b2eda45f794a5bf7e8910f885be21544bf637cc9 | |
parent | e77e395efda0c0ab5bf9c951627c4fcf65c2e32e (diff) | |
parent | 08d8b3cee1329d390f91bce419e2b4dadf484952 (diff) | |
download | busybox-w32-30c62e541a1484fedc3d689d62f96d246a28b147.tar.gz busybox-w32-30c62e541a1484fedc3d689d62f96d246a28b147.tar.bz2 busybox-w32-30c62e541a1484fedc3d689d62f96d246a28b147.zip |
Merge branch 'origin/master' (early part)
Conflicts:
shell/ash.c
-rw-r--r-- | shell/ash.c | 35 | ||||
-rw-r--r-- | shell/ash_test/ash-signals/signal5.right | 4 | ||||
-rwxr-xr-x | shell/ash_test/ash-signals/signal5.tests | 2 |
3 files changed, 28 insertions, 13 deletions
diff --git a/shell/ash.c b/shell/ash.c index 913f40f12..dcaac1fd8 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -1119,7 +1119,7 @@ ash_vmsg(const char *msg, va_list ap) | |||
1119 | if (commandname) { | 1119 | if (commandname) { |
1120 | if (strcmp(arg0, commandname)) | 1120 | if (strcmp(arg0, commandname)) |
1121 | fprintf(stderr, "%s: ", commandname); | 1121 | fprintf(stderr, "%s: ", commandname); |
1122 | if (!iflag || g_parsefile->fd) | 1122 | if (!iflag || g_parsefile->fd > 0) |
1123 | fprintf(stderr, "line %d: ", startlinno); | 1123 | fprintf(stderr, "line %d: ", startlinno); |
1124 | } | 1124 | } |
1125 | vfprintf(stderr, msg, ap); | 1125 | vfprintf(stderr, msg, ap); |
@@ -5353,15 +5353,26 @@ static int is_hidden_fd(struct redirtab *rp, int fd) | |||
5353 | 5353 | ||
5354 | if (fd == -1) | 5354 | if (fd == -1) |
5355 | return 0; | 5355 | return 0; |
5356 | /* Check open scripts' fds */ | ||
5356 | pf = g_parsefile; | 5357 | pf = g_parsefile; |
5357 | while (pf) { | 5358 | while (pf) { |
5358 | if (fd == pf->fd) { | 5359 | /* We skip fd == 0 case because of the following case: |
5360 | * $ ash # running ash interactively | ||
5361 | * $ . ./script.sh | ||
5362 | * and in script.sh: "exec 9>&0". | ||
5363 | * Even though top-level fd _is_ 0, | ||
5364 | * it's still ok to use it: "read" builtin uses it, | ||
5365 | * why should we cripple "exec" builtin? | ||
5366 | */ | ||
5367 | if (pf->fd > 0 && fd == pf->fd) { | ||
5359 | return 1; | 5368 | return 1; |
5360 | } | 5369 | } |
5361 | pf = pf->prev; | 5370 | pf = pf->prev; |
5362 | } | 5371 | } |
5372 | |||
5363 | if (!rp) | 5373 | if (!rp) |
5364 | return 0; | 5374 | return 0; |
5375 | /* Check saved fds of redirects */ | ||
5365 | fd |= COPYFD_RESTORE; | 5376 | fd |= COPYFD_RESTORE; |
5366 | for (i = 0; i < rp->pair_count; i++) { | 5377 | for (i = 0; i < rp->pair_count; i++) { |
5367 | if (rp->two_fd[i].copy == fd) { | 5378 | if (rp->two_fd[i].copy == fd) { |
@@ -5374,9 +5385,7 @@ static int is_hidden_fd(struct redirtab *rp, int fd) | |||
5374 | /* | 5385 | /* |
5375 | * Process a list of redirection commands. If the REDIR_PUSH flag is set, | 5386 | * Process a list of redirection commands. If the REDIR_PUSH flag is set, |
5376 | * old file descriptors are stashed away so that the redirection can be | 5387 | * old file descriptors are stashed away so that the redirection can be |
5377 | * undone by calling popredir. If the REDIR_BACKQ flag is set, then the | 5388 | * undone by calling popredir. |
5378 | * standard output, and the standard error if it becomes a duplicate of | ||
5379 | * stdout, is saved in memory. | ||
5380 | */ | 5389 | */ |
5381 | /* flags passed to redirect */ | 5390 | /* flags passed to redirect */ |
5382 | #define REDIR_PUSH 01 /* save previous values of file descriptors */ | 5391 | #define REDIR_PUSH 01 /* save previous values of file descriptors */ |
@@ -5422,13 +5431,15 @@ redirect(union node *redir, int flags) | |||
5422 | } | 5431 | } |
5423 | 5432 | ||
5424 | do { | 5433 | do { |
5434 | int right_fd = -1; | ||
5425 | fd = redir->nfile.fd; | 5435 | fd = redir->nfile.fd; |
5426 | if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) { | 5436 | if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) { |
5427 | int right_fd = redir->ndup.dupfd; | 5437 | right_fd = redir->ndup.dupfd; |
5438 | //bb_error_msg("doing %d > %d", fd, right_fd); | ||
5428 | /* redirect from/to same file descriptor? */ | 5439 | /* redirect from/to same file descriptor? */ |
5429 | if (right_fd == fd) | 5440 | if (right_fd == fd) |
5430 | continue; | 5441 | continue; |
5431 | /* echo >&10 and 10 is a fd opened to the sh script? */ | 5442 | /* "echo >&10" and 10 is a fd opened to a sh script? */ |
5432 | if (is_hidden_fd(sv, right_fd)) { | 5443 | if (is_hidden_fd(sv, right_fd)) { |
5433 | errno = EBADF; /* as if it is closed */ | 5444 | errno = EBADF; /* as if it is closed */ |
5434 | ash_msg_and_raise_error("%d: %m", right_fd); | 5445 | ash_msg_and_raise_error("%d: %m", right_fd); |
@@ -5450,7 +5461,10 @@ redirect(union node *redir, int flags) | |||
5450 | #endif | 5461 | #endif |
5451 | if (need_to_remember(sv, fd)) { | 5462 | if (need_to_remember(sv, fd)) { |
5452 | /* Copy old descriptor */ | 5463 | /* Copy old descriptor */ |
5453 | i = copyfd(fd, 10); | 5464 | /* Careful to not accidentally "save" |
5465 | * to the same fd as right side fd in N>&M */ | ||
5466 | int minfd = right_fd < 10 ? 10 : right_fd + 1; | ||
5467 | i = copyfd(fd, minfd); | ||
5454 | /* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds | 5468 | /* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds |
5455 | * are closed in popredir() in the child, preventing them from leaking | 5469 | * are closed in popredir() in the child, preventing them from leaking |
5456 | * into child. (popredir() also cleans up the mess in case of failures) | 5470 | * into child. (popredir() also cleans up the mess in case of failures) |
@@ -13548,8 +13562,9 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
13548 | * Ensure we don't falsely claim that 0 (stdin) | 13562 | * Ensure we don't falsely claim that 0 (stdin) |
13549 | * is one of stacked source fds. | 13563 | * is one of stacked source fds. |
13550 | * Testcase: ash -c 'exec 1>&0' must not complain. */ | 13564 | * Testcase: ash -c 'exec 1>&0' must not complain. */ |
13551 | if (!sflag) | 13565 | // if (!sflag) g_parsefile->fd = -1; |
13552 | g_parsefile->fd = -1; | 13566 | // ^^ not necessary since now we special-case fd 0 |
13567 | // in is_hidden_fd() to not be considered "hidden fd" | ||
13553 | evalstring(minusc, 0); | 13568 | evalstring(minusc, 0); |
13554 | } | 13569 | } |
13555 | 13570 | ||
diff --git a/shell/ash_test/ash-signals/signal5.right b/shell/ash_test/ash-signals/signal5.right index 162f56bbc..7cfd4110e 100644 --- a/shell/ash_test/ash-signals/signal5.right +++ b/shell/ash_test/ash-signals/signal5.right | |||
@@ -1,5 +1,5 @@ | |||
1 | sleeping for 3 sec | 1 | Sleeping |
2 | sleeping for 2 sec | 2 | Sleeping |
3 | Waiting | 3 | Waiting |
4 | 2 sec passed, sending USR1 to parent | 4 | 2 sec passed, sending USR1 to parent |
5 | USR1 received | 5 | USR1 received |
diff --git a/shell/ash_test/ash-signals/signal5.tests b/shell/ash_test/ash-signals/signal5.tests index 371120e95..179bcdd80 100755 --- a/shell/ash_test/ash-signals/signal5.tests +++ b/shell/ash_test/ash-signals/signal5.tests | |||
@@ -1,6 +1,6 @@ | |||
1 | trap "echo USR1 received" USR1 | 1 | trap "echo USR1 received" USR1 |
2 | stub() { | 2 | stub() { |
3 | echo "sleeping for $1 sec" | 3 | echo "Sleeping" |
4 | sleep $1 | 4 | sleep $1 |
5 | echo "$1 sec passed, sending USR1 to parent" | 5 | echo "$1 sec passed, sending USR1 to parent" |
6 | kill -USR1 $$ | 6 | kill -USR1 $$ |