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
This commit is contained in:
Denis Vlasenko 2007-10-20 18:30:38 +00:00
parent 99014e8965
commit 037576d77b
2 changed files with 34 additions and 23 deletions

View 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 */

View 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
if (nch_flag || silent)
while (!n_flag || --nchars);
#else
while (1);
#endif
#if ENABLE_ASH_READ_NCHARS
if (n_flag || silent)
tcsetattr(0, TCSANOW, &old_tty);
#endif