ash: fix TMOUT not restoring tty attributes
No binary (build failed)
—
(log yok)
| @@ -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? */ | |
| @@ -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 | |
| @@ -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) { | |
| @@ -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 <Enter> 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) | |
| { | |
| @@ -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 <Enter>. (^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 */ | |
| @@ -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 */ | |