read_line_input: fix it to not do any fancy editing if echoing is disabled.
authorDenis Vlasenko <vda.linux@googlemail.com>
Sat, 20 Oct 2007 18:30:38 +0000 (18:30 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Sat, 20 Oct 2007 18:30:38 +0000 (18:30 -0000)
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
shell/ash.c

index c44a2284376229857af2cf2774fe24ace16879f4..f65e852b164330cc9224e391f8f6d4c915520b33 100644 (file)
@@ -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 */
index 52cf41ab5832f56eb353eaf8296148e86d01659f..58527bf9b28f8c941fc80311079edf0d8e3978a5 100644 (file)
@@ -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