From 037576d77b62186551ad07b10eb46a73144b9f84 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Sat, 20 Oct 2007 18:30:38 +0000 Subject: read_line_input: fix it to not do any fancy editing if echoing is disabled. ash: make read handling both more correct and smaller read_line_input 4037 4101 +64 input_backward 140 139 -1 readcmd 1079 1070 -9 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/2 up/down: 65/-10) Total: 54 bytes text data bss dec hex filename 777575 1000 9532 788107 c068b busybox_old 777629 1000 9532 788161 c06c1 busybox_unstripped --- libbb/lineedit.c | 12 ++++++++++-- shell/ash.c | 45 ++++++++++++++++++++++++--------------------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index c44a22843..f65e852b1 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -1259,7 +1259,7 @@ static void win_changed(int nsig) * 0 on ctrl-C, * >0 length of input string, including terminating '\n' */ -int read_line_input(const char* prompt, char* command, int maxsize, line_input_t *st) +int read_line_input(const char *prompt, char *command, int maxsize, line_input_t *st) { int lastWasTab = FALSE; unsigned int ic; @@ -1270,6 +1270,15 @@ int read_line_input(const char* prompt, char* command, int maxsize, line_input_t smalluint prevc; #endif + getTermSettings(0, (void *) &initial_settings); + /* Happens when e.g. stty -echo was run before */ + if (!(initial_settings.c_lflag & ECHO)) { + parse_prompt(prompt); + fflush(stdout); + fgets(command, maxsize, stdin); + return strlen(command); + } + // FIXME: audit & improve this if (maxsize > MAX_LINELEN) maxsize = MAX_LINELEN; @@ -1287,7 +1296,6 @@ int read_line_input(const char* prompt, char* command, int maxsize, line_input_t command_ps = command; command[0] = '\0'; - getTermSettings(0, (void *) &initial_settings); memcpy(&new_settings, &initial_settings, sizeof(new_settings)); new_settings.c_lflag &= ~ICANON; /* unbuffered input */ /* Turn off echoing and CTRL-C, so we can trap it */ diff --git a/shell/ash.c b/shell/ash.c index 52cf41ab5..58527bf9b 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -11491,7 +11491,7 @@ readcmd(int argc, char **argv) int status; int i; #if ENABLE_ASH_READ_NCHARS - int nch_flag = 0; + int n_flag = 0; int nchars = 0; int silent = 0; struct termios tty, old_tty; @@ -11521,10 +11521,10 @@ readcmd(int argc, char **argv) break; #if ENABLE_ASH_READ_NCHARS case 'n': - nchars = strtol(optionarg, &p, 10); - if (*p) + nchars = bb_strtou(optionarg, NULL, 10); + if (nchars < 0 || errno) ash_msg_and_raise_error("invalid count"); - nch_flag = (nchars > 0); + n_flag = nchars; /* just a flag "nchars is nonzero" */ break; case 's': silent = 1; @@ -11532,14 +11532,15 @@ readcmd(int argc, char **argv) #endif #if ENABLE_ASH_READ_TIMEOUT case 't': - ts.tv_sec = strtol(optionarg, &p, 10); + ts.tv_sec = bb_strtou(optionarg, &p, 10); ts.tv_usec = 0; - if (*p == '.') { + /* EINVAL means number is ok, but not terminated by NUL */ + if (*p == '.' && errno == EINVAL) { char *p2; if (*++p) { int scale; - ts.tv_usec = strtol(p, &p2, 10); - if (*p2) + ts.tv_usec = bb_strtou(p, &p2, 10); + if (errno) ash_msg_and_raise_error("invalid timeout"); scale = p2 - p; /* normalize to usec */ @@ -11548,11 +11549,12 @@ readcmd(int argc, char **argv) while (scale++ < 6) ts.tv_usec *= 10; } - } else if (*p) { + } else if (ts.tv_sec < 0 || errno) { ash_msg_and_raise_error("invalid timeout"); } - if ( ! ts.tv_sec && ! ts.tv_usec) + if (!(ts.tv_sec | ts.tv_usec)) { /* both are 0? */ ash_msg_and_raise_error("invalid timeout"); + } break; #endif case 'r': @@ -11572,16 +11574,15 @@ readcmd(int argc, char **argv) if (ifs == NULL) ifs = defifs; #if ENABLE_ASH_READ_NCHARS - if (nch_flag || silent) { + if (n_flag || silent) { tcgetattr(0, &tty); old_tty = tty; - if (nch_flag) { + if (n_flag) { tty.c_lflag &= ~ICANON; tty.c_cc[VMIN] = nchars; } if (silent) { tty.c_lflag &= ~(ECHO|ECHOK|ECHONL); - } tcsetattr(0, TCSANOW, &tty); } @@ -11595,7 +11596,7 @@ readcmd(int argc, char **argv) i = select(FD_SETSIZE, &set, NULL, NULL, &ts); if (!i) { #if ENABLE_ASH_READ_NCHARS - if (nch_flag) + if (n_flag) tcsetattr(0, TCSANOW, &old_tty); #endif return 1; @@ -11606,12 +11607,7 @@ readcmd(int argc, char **argv) startword = 1; backslash = 0; STARTSTACKSTR(p); -#if ENABLE_ASH_READ_NCHARS - while (!nch_flag || nchars--) -#else - for (;;) -#endif - { + do { if (read(0, &c, 1) != 1) { status = 1; break; @@ -11645,8 +11641,15 @@ readcmd(int argc, char **argv) STPUTC(c, p); } } +/* end of do {} while: */ +#if ENABLE_ASH_READ_NCHARS + while (!n_flag || --nchars); +#else + while (1); +#endif + #if ENABLE_ASH_READ_NCHARS - if (nch_flag || silent) + if (n_flag || silent) tcsetattr(0, TCSANOW, &old_tty); #endif -- cgit v1.2.3