From 037576d77b62186551ad07b10eb46a73144b9f84 Mon Sep 17 00:00:00 2001
From: Denis Vlasenko <vda.linux@googlemail.com>
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
---
 shell/ash.c | 45 ++++++++++++++++++++++++---------------------
 1 file changed, 24 insertions(+), 21 deletions(-)

(limited to 'shell')

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-55-g6feb