diff options
author | Ron Yorston <rmy@pobox.com> | 2024-07-13 08:29:09 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2024-07-13 08:29:09 +0100 |
commit | b18891bba511d4fc4fcd0a6ff5cd2df31a086f1b (patch) | |
tree | ef78f9ecc339d6ab95eed03f787f058f270b8772 /shell/ash.c | |
parent | 684dabdb8452b3d33d5d6265f3d7ef32c10f5307 (diff) | |
parent | 23da5c4b716b92524240c6f81c2e2474c1825cfc (diff) | |
download | busybox-w32-b18891bba511d4fc4fcd0a6ff5cd2df31a086f1b.tar.gz busybox-w32-b18891bba511d4fc4fcd0a6ff5cd2df31a086f1b.tar.bz2 busybox-w32-b18891bba511d4fc4fcd0a6ff5cd2df31a086f1b.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'shell/ash.c')
-rw-r--r-- | shell/ash.c | 40 |
1 files changed, 29 insertions, 11 deletions
diff --git a/shell/ash.c b/shell/ash.c index 719f722a2..7a9f20ec0 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -758,10 +758,9 @@ static void trace_vprintf(const char *fmt, va_list va); | |||
758 | #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c))) | 758 | #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c))) |
759 | 759 | ||
760 | static int | 760 | static int |
761 | isdigit_str9(const char *str) | 761 | isdigit_str(const char *str) |
762 | { | 762 | { |
763 | int maxlen = 9 + 1; /* max 9 digits: 999999999 */ | 763 | while (isdigit(*str)) |
764 | while (--maxlen && isdigit(*str)) | ||
765 | str++; | 764 | str++; |
766 | return (*str == '\0'); | 765 | return (*str == '\0'); |
767 | } | 766 | } |
@@ -6386,10 +6385,13 @@ dup2_or_raise(int from, int to) | |||
6386 | newfd = (from != to) ? dup2(from, to) : to; | 6385 | newfd = (from != to) ? dup2(from, to) : to; |
6387 | if (newfd < 0) { | 6386 | if (newfd < 0) { |
6388 | /* Happens when source fd is not open: try "echo >&99" */ | 6387 | /* Happens when source fd is not open: try "echo >&99" */ |
6389 | ash_msg_and_raise_perror("%d", from); | 6388 | ash_msg_and_raise_perror("dup2(%d,%d)", from, to); |
6390 | } | 6389 | } |
6391 | return newfd; | 6390 | return newfd; |
6392 | } | 6391 | } |
6392 | /* The only possible error return is EBADF (fd wasn't open). | ||
6393 | * Transient errors retry, other errors raise exception. | ||
6394 | */ | ||
6393 | static int | 6395 | static int |
6394 | dup_CLOEXEC(int fd, int avoid_fd) | 6396 | dup_CLOEXEC(int fd, int avoid_fd) |
6395 | { | 6397 | { |
@@ -6404,6 +6406,16 @@ dup_CLOEXEC(int fd, int avoid_fd) | |||
6404 | goto repeat; | 6406 | goto repeat; |
6405 | if (errno == EINTR) | 6407 | if (errno == EINTR) |
6406 | goto repeat; | 6408 | goto repeat; |
6409 | if (errno != EBADF) { | ||
6410 | /* "echo >&9999" gets EINVAL trying to save fd 1 to above 9999. | ||
6411 | * We could try saving it _below_ 9999 instead (how?), but | ||
6412 | * this probably means that dup2(9999,1) to effectuate >&9999 | ||
6413 | * would also not work: fd 9999 can't exist. Gracefully bail out. | ||
6414 | * (This differs from "echo >&99" where saving works, but | ||
6415 | * subsequent dup2(99,1) fails if fd 99 is not open). | ||
6416 | */ | ||
6417 | ash_msg_and_raise_perror("fcntl(%d,F_DUPFD,%d)", fd, avoid_fd + 1); | ||
6418 | } | ||
6407 | } | 6419 | } |
6408 | return newfd; | 6420 | return newfd; |
6409 | } | 6421 | } |
@@ -6519,7 +6531,7 @@ save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq) | |||
6519 | new_fd = dup_CLOEXEC(fd, avoid_fd); | 6531 | new_fd = dup_CLOEXEC(fd, avoid_fd); |
6520 | sq->two_fd[i].moved_to = new_fd; | 6532 | sq->two_fd[i].moved_to = new_fd; |
6521 | TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd)); | 6533 | TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd)); |
6522 | if (new_fd < 0) /* what? */ | 6534 | if (new_fd < 0) /* EBADF? what? */ |
6523 | xfunc_die(); | 6535 | xfunc_die(); |
6524 | return 0; /* "we did not close fd" */ | 6536 | return 0; /* "we did not close fd" */ |
6525 | } | 6537 | } |
@@ -6534,8 +6546,7 @@ save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq) | |||
6534 | new_fd = dup_CLOEXEC(fd, avoid_fd); | 6546 | new_fd = dup_CLOEXEC(fd, avoid_fd); |
6535 | TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd)); | 6547 | TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd)); |
6536 | if (new_fd < 0) { | 6548 | if (new_fd < 0) { |
6537 | if (errno != EBADF) | 6549 | /* EBADF (fd is not open) */ |
6538 | xfunc_die(); | ||
6539 | /* new_fd = CLOSED; - already is -1 */ | 6550 | /* new_fd = CLOSED; - already is -1 */ |
6540 | } | 6551 | } |
6541 | sq->two_fd[i].moved_to = new_fd; | 6552 | sq->two_fd[i].moved_to = new_fd; |
@@ -10767,7 +10778,7 @@ expredir(union node *n) | |||
10767 | if (fn.list == NULL) | 10778 | if (fn.list == NULL) |
10768 | ash_msg_and_raise_error("redir error"); | 10779 | ash_msg_and_raise_error("redir error"); |
10769 | #if BASH_REDIR_OUTPUT | 10780 | #if BASH_REDIR_OUTPUT |
10770 | if (!isdigit_str9(fn.list->text)) { | 10781 | if (!isdigit_str(fn.list->text)) { |
10771 | /* >&file, not >&fd */ | 10782 | /* >&file, not >&fd */ |
10772 | if (redir->nfile.fd != 1) /* 123>&file - BAD */ | 10783 | if (redir->nfile.fd != 1) /* 123>&file - BAD */ |
10773 | ash_msg_and_raise_error("redir error"); | 10784 | ash_msg_and_raise_error("redir error"); |
@@ -13284,12 +13295,19 @@ fixredir(union node *n, const char *text, int err) | |||
13284 | if (!err) | 13295 | if (!err) |
13285 | n->ndup.vname = NULL; | 13296 | n->ndup.vname = NULL; |
13286 | 13297 | ||
13298 | if (LONE_DASH(text)) { | ||
13299 | n->ndup.dupfd = -1; | ||
13300 | return; | ||
13301 | } | ||
13302 | |||
13287 | fd = bb_strtou(text, NULL, 10); | 13303 | fd = bb_strtou(text, NULL, 10); |
13288 | if (!errno && fd >= 0) | 13304 | if (!errno && fd >= 0) |
13289 | n->ndup.dupfd = fd; | 13305 | n->ndup.dupfd = fd; |
13290 | else if (LONE_DASH(text)) | ||
13291 | n->ndup.dupfd = -1; | ||
13292 | else { | 13306 | else { |
13307 | /* This also fails on very large numbers | ||
13308 | * which overflow "int" - bb_strtou() does not | ||
13309 | * silently truncate results to word width. | ||
13310 | */ | ||
13293 | if (err) | 13311 | if (err) |
13294 | raise_error_syntax("bad fd number"); | 13312 | raise_error_syntax("bad fd number"); |
13295 | n->ndup.vname = makename(); | 13313 | n->ndup.vname = makename(); |
@@ -13975,7 +13993,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
13975 | if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>')) | 13993 | if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>')) |
13976 | && quotef == 0 | 13994 | && quotef == 0 |
13977 | ) { | 13995 | ) { |
13978 | if (isdigit_str9(out)) { | 13996 | if (isdigit_str(out)) { |
13979 | PARSEREDIR(); /* passed as params: out, c */ | 13997 | PARSEREDIR(); /* passed as params: out, c */ |
13980 | lasttoken = TREDIR; | 13998 | lasttoken = TREDIR; |
13981 | return lasttoken; | 13999 | return lasttoken; |