From 66c5b12dbf85142eea257ba6047191d7c0ee43f3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 8 Feb 2011 05:07:02 +0100 Subject: ash: fix TMOUT not restoring tty attributes function old new delta pgetc 420 500 +80 readtoken1 3202 3239 +37 read_line_input 3316 3337 +21 udhcpc_main 2610 2630 +20 file_get 266 272 +6 expandarg 958 963 +5 localcmd 257 259 +2 addLines 85 87 +2 read_line 94 95 +1 ed_main 2540 2541 +1 timed_out 1 - -1 lineedit_read_key 256 255 -1 alrm_sighandler 44 - -44 cmdloop 539 434 -105 ------------------------------------------------------------------------------ (add/remove: 0/2 grow/shrink: 10/2 up/down: 175/-151) Total: 24 bytes text data bss dec hex filename 887379 936 17200 905515 dd12b busybox_old 887411 936 17192 905539 dd143 busybox_unstripped Signed-off-by: Denys Vlasenko --- editors/ed.c | 6 ++--- include/libbb.h | 5 ++-- libbb/lineedit.c | 12 ++++----- shell/ash.c | 73 ++++++++++++++++++++---------------------------------- shell/hush.c | 2 +- util-linux/fdisk.c | 2 +- 6 files changed, 39 insertions(+), 61 deletions(-) diff --git a/editors/ed.c b/editors/ed.c index 859668406..b1b6a8d27 100644 --- a/editors/ed.c +++ b/editors/ed.c @@ -129,7 +129,7 @@ static void doCommands(void) * 0 on ctrl-C, * >0 length of input string, including terminating '\n' */ - len = read_line_input(": ", buf, sizeof(buf), NULL); + len = read_line_input(NULL, ": ", buf, sizeof(buf), /*timeout*/ -1); if (len <= 0) return; endbuf = &buf[len - 1]; @@ -227,7 +227,7 @@ static void doCommands(void) } if (!dirty) return; - len = read_line_input("Really quit? ", buf, 16, NULL); + len = read_line_input(NULL, "Really quit? ", buf, 16, /*timeout*/ -1); /* read error/EOF - no way to continue */ if (len < 0) return; @@ -541,7 +541,7 @@ static void addLines(int num) * 0 on ctrl-C, * >0 length of input string, including terminating '\n' */ - len = read_line_input("", buf, sizeof(buf), NULL); + len = read_line_input(NULL, "", buf, sizeof(buf), /*timeout*/ -1); if (len <= 0) { /* Previously, ctrl-C was exiting to shell. * Now we exit to ed prompt. Is in important? */ diff --git a/include/libbb.h b/include/libbb.h index dd82e9754..78b390611 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1403,12 +1403,11 @@ line_input_t *new_line_input_t(int flags) FAST_FUNC; * 0 on ctrl-C (the line entered is still returned in 'command'), * >0 length of input string, including terminating '\n' */ -/* NB: ash has timeout code which can be moved into read_line_input, if needed */ -int read_line_input(const char* prompt, char* command, int maxsize, line_input_t *state) FAST_FUNC; +int read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout) FAST_FUNC; #else #define MAX_HISTORY 0 int read_line_input(const char* prompt, char* command, int maxsize) FAST_FUNC; -#define read_line_input(prompt, command, maxsize, state) \ +#define read_line_input(state, prompt, command, maxsize, timeout) \ read_line_input(prompt, command, maxsize) #endif diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 5dd835cca..afd28b75c 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -1809,10 +1809,9 @@ static void win_changed(int nsig) errno = sv_errno; } -static int lineedit_read_key(char *read_key_buffer) +static int lineedit_read_key(char *read_key_buffer, int timeout) { int64_t ic; - int timeout = -1; #if ENABLE_UNICODE_SUPPORT char unicode_buf[MB_CUR_MAX + 1]; int unicode_idx = 0; @@ -1917,7 +1916,7 @@ static int isrtl_str(void) * 0 on ctrl-C (the line entered is still returned in 'command'), * >0 length of input string, including terminating '\n' */ -int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, line_input_t *st) +int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout) { int len; #if ENABLE_FEATURE_TAB_COMPLETION @@ -1991,7 +1990,6 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li new_settings.c_cc[VINTR] = _POSIX_VDISABLE; tcsetattr_stdin_TCSANOW(&new_settings); - /* Now initialize things */ previous_SIGWINCH_handler = signal(SIGWINCH, win_changed); win_changed(0); /* do initial resizing */ #if ENABLE_USERNAME_OR_HOMEDIR @@ -2033,7 +2031,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li int32_t ic, ic_raw; fflush_all(); - ic = ic_raw = lineedit_read_key(read_key_buffer); + ic = ic_raw = lineedit_read_key(read_key_buffer, timeout); #if ENABLE_FEATURE_EDITING_VI newdelflag = 1; @@ -2194,7 +2192,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li case 'd'|VI_CMDMODE_BIT: { int nc, sc; - ic = lineedit_read_key(read_key_buffer); + ic = lineedit_read_key(read_key_buffer, timeout); if (errno) /* error */ goto return_error_indicator; if (ic == ic_raw) { /* "cc", "dd" */ @@ -2258,7 +2256,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li break; case 'r'|VI_CMDMODE_BIT: //FIXME: unicode case? - ic = lineedit_read_key(read_key_buffer); + ic = lineedit_read_key(read_key_buffer, timeout); if (errno) /* error */ goto return_error_indicator; if (ic < ' ' || ic > 255) { diff --git a/shell/ash.c b/shell/ash.c index bdc64790c..aaf21cd6f 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -102,8 +102,7 @@ //config: default n //config: depends on ASH //config: help -//config: Enables bash-like auto-logout after "$TMOUT" seconds -//config: of idle time. +//config: Enables bash-like auto-logout after $TMOUT seconds of idle time. //config: //config:config ASH_JOB_CONTROL //config: bool "Job control" @@ -408,6 +407,9 @@ static const char *var_end(const char *var) /* ============ Interrupts / exceptions */ + +static void exitshell(void) NORETURN; + /* * These macros allow the user to suspend the handling of interrupt signals * over a period of time. This is similar to SIGHOLD or to sigblock, but @@ -9573,10 +9575,21 @@ preadfd(void) if (!iflag || g_parsefile->pf_fd != STDIN_FILENO) nr = nonblock_safe_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1); else { + int timeout = -1; +# if ENABLE_ASH_IDLE_TIMEOUT + if (iflag) { + const char *tmout_var = lookupvar("TMOUT"); + if (tmout_var) { + timeout = atoi(tmout_var) * 1000; + if (timeout <= 0) + timeout = -1; + } + } +# endif # if ENABLE_FEATURE_TAB_COMPLETION line_input_state->path_lookup = pathval(); # endif - nr = read_line_input(cmdedit_prompt, buf, IBUFSIZ, line_input_state); + nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout); if (nr == 0) { /* Ctrl+C pressed */ if (trap[SIGINT]) { @@ -9587,9 +9600,17 @@ preadfd(void) } goto retry; } - if (nr < 0 && errno == 0) { - /* Ctrl+D pressed */ - nr = 0; + if (nr < 0) { + if (errno == 0) { + /* Ctrl+D pressed */ + nr = 0; + } +# if ENABLE_ASH_IDLE_TIMEOUT + else if (errno == EAGAIN && timeout > 0) { + printf("\007timed out waiting for input: auto-logout\n"); + exitshell(); + } +# endif } } #else @@ -12056,23 +12077,6 @@ evalcmd(int argc UNUSED_PARAM, char **argv) return exitstatus; } -#if ENABLE_ASH_IDLE_TIMEOUT -static smallint timed_out; - -static void alrm_sighandler(int sig UNUSED_PARAM) -{ - /* Close stdin, making interactive command reading stop. - * Otherwise, timeout doesn't trigger until is pressed. - */ - int sv = errno; - close(0); - open("/dev/null", O_RDONLY); - errno = sv; - - timed_out = 1; -} -#endif - /* * Read and execute commands. * "Top" is nonzero for the top level command loop; @@ -12089,20 +12093,6 @@ cmdloop(int top) TRACE(("cmdloop(%d) called\n", top)); for (;;) { int skip; -#if ENABLE_ASH_IDLE_TIMEOUT - int tmout_seconds = 0; - - if (top && iflag) { - const char *tmout_var = lookupvar("TMOUT"); - if (tmout_var) { - tmout_seconds = atoi(tmout_var); - if (tmout_seconds > 0) { - signal(SIGALRM, alrm_sighandler); - alarm(tmout_seconds); - } - } - } -#endif setstackmark(&smark); #if JOBS @@ -12115,14 +12105,6 @@ cmdloop(int top) chkmail(); } n = parsecmd(inter); -#if ENABLE_ASH_IDLE_TIMEOUT - if (timed_out) { - printf("\007timed out waiting for input: auto-logout\n"); - break; - } - if (tmout_seconds > 0) - alarm(0); -#endif #if DEBUG if (DEBUG > 2 && debug && (n != NODE_EOF)) showtree(n); @@ -12850,7 +12832,6 @@ ulimitcmd(int argc UNUSED_PARAM, char **argv) /* * Called to exit the shell. */ -static void exitshell(void) NORETURN; static void exitshell(void) { diff --git a/shell/hush.c b/shell/hush.c index e857e7464..00ef361cd 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -1902,7 +1902,7 @@ static void get_user_input(struct in_str *i) G.flag_SIGINT = 0; /* buglet: SIGINT will not make new prompt to appear _at once_, * only after . (^C will work) */ - r = read_line_input(prompt_str, G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1, G.line_input_state); + r = read_line_input(G.line_input_state, prompt_str, G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1, /*timeout*/ -1); /* catch *SIGINT* etc (^C is handled by read_line_input) */ check_and_run_traps(0); } while (r == 0 || G.flag_SIGINT); /* repeat if ^C or SIGINT */ diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c index 02785ab85..0b93c22cc 100644 --- a/util-linux/fdisk.c +++ b/util-linux/fdisk.c @@ -548,7 +548,7 @@ read_line(const char *prompt) { int sz; - sz = read_line_input(prompt, line_buffer, sizeof(line_buffer), NULL); + sz = read_line_input(NULL, prompt, line_buffer, sizeof(line_buffer), /*timeout*/ -1); if (sz <= 0) exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */ -- cgit v1.2.3