aboutsummaryrefslogtreecommitdiff
path: root/shell/ash.c
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2024-07-13 08:29:09 +0100
committerRon Yorston <rmy@pobox.com>2024-07-13 08:29:09 +0100
commitb18891bba511d4fc4fcd0a6ff5cd2df31a086f1b (patch)
treeef78f9ecc339d6ab95eed03f787f058f270b8772 /shell/ash.c
parent684dabdb8452b3d33d5d6265f3d7ef32c10f5307 (diff)
parent23da5c4b716b92524240c6f81c2e2474c1825cfc (diff)
downloadbusybox-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.c40
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
760static int 760static int
761isdigit_str9(const char *str) 761isdigit_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 */
6393static int 6395static int
6394dup_CLOEXEC(int fd, int avoid_fd) 6396dup_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;