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 <vda.linux@googlemail.com>
This commit is contained in:
parent
dd807c16f9
commit
66c5b12dbf
@ -129,7 +129,7 @@ static void doCommands(void)
|
|||||||
* 0 on ctrl-C,
|
* 0 on ctrl-C,
|
||||||
* >0 length of input string, including terminating '\n'
|
* >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)
|
if (len <= 0)
|
||||||
return;
|
return;
|
||||||
endbuf = &buf[len - 1];
|
endbuf = &buf[len - 1];
|
||||||
@ -227,7 +227,7 @@ static void doCommands(void)
|
|||||||
}
|
}
|
||||||
if (!dirty)
|
if (!dirty)
|
||||||
return;
|
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 */
|
/* read error/EOF - no way to continue */
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
return;
|
return;
|
||||||
@ -541,7 +541,7 @@ static void addLines(int num)
|
|||||||
* 0 on ctrl-C,
|
* 0 on ctrl-C,
|
||||||
* >0 length of input string, including terminating '\n'
|
* >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) {
|
if (len <= 0) {
|
||||||
/* Previously, ctrl-C was exiting to shell.
|
/* Previously, ctrl-C was exiting to shell.
|
||||||
* Now we exit to ed prompt. Is in important? */
|
* 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 on ctrl-C (the line entered is still returned in 'command'),
|
||||||
* >0 length of input string, including terminating '\n'
|
* >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(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout) FAST_FUNC;
|
||||||
int read_line_input(const char* prompt, char* command, int maxsize, line_input_t *state) FAST_FUNC;
|
|
||||||
#else
|
#else
|
||||||
#define MAX_HISTORY 0
|
#define MAX_HISTORY 0
|
||||||
int read_line_input(const char* prompt, char* command, int maxsize) FAST_FUNC;
|
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)
|
read_line_input(prompt, command, maxsize)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1809,10 +1809,9 @@ static void win_changed(int nsig)
|
|||||||
errno = sv_errno;
|
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;
|
int64_t ic;
|
||||||
int timeout = -1;
|
|
||||||
#if ENABLE_UNICODE_SUPPORT
|
#if ENABLE_UNICODE_SUPPORT
|
||||||
char unicode_buf[MB_CUR_MAX + 1];
|
char unicode_buf[MB_CUR_MAX + 1];
|
||||||
int unicode_idx = 0;
|
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 on ctrl-C (the line entered is still returned in 'command'),
|
||||||
* >0 length of input string, including terminating '\n'
|
* >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;
|
int len;
|
||||||
#if ENABLE_FEATURE_TAB_COMPLETION
|
#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;
|
new_settings.c_cc[VINTR] = _POSIX_VDISABLE;
|
||||||
tcsetattr_stdin_TCSANOW(&new_settings);
|
tcsetattr_stdin_TCSANOW(&new_settings);
|
||||||
|
|
||||||
/* Now initialize things */
|
|
||||||
previous_SIGWINCH_handler = signal(SIGWINCH, win_changed);
|
previous_SIGWINCH_handler = signal(SIGWINCH, win_changed);
|
||||||
win_changed(0); /* do initial resizing */
|
win_changed(0); /* do initial resizing */
|
||||||
#if ENABLE_USERNAME_OR_HOMEDIR
|
#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;
|
int32_t ic, ic_raw;
|
||||||
|
|
||||||
fflush_all();
|
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
|
#if ENABLE_FEATURE_EDITING_VI
|
||||||
newdelflag = 1;
|
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: {
|
case 'd'|VI_CMDMODE_BIT: {
|
||||||
int nc, sc;
|
int nc, sc;
|
||||||
|
|
||||||
ic = lineedit_read_key(read_key_buffer);
|
ic = lineedit_read_key(read_key_buffer, timeout);
|
||||||
if (errno) /* error */
|
if (errno) /* error */
|
||||||
goto return_error_indicator;
|
goto return_error_indicator;
|
||||||
if (ic == ic_raw) { /* "cc", "dd" */
|
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;
|
break;
|
||||||
case 'r'|VI_CMDMODE_BIT:
|
case 'r'|VI_CMDMODE_BIT:
|
||||||
//FIXME: unicode case?
|
//FIXME: unicode case?
|
||||||
ic = lineedit_read_key(read_key_buffer);
|
ic = lineedit_read_key(read_key_buffer, timeout);
|
||||||
if (errno) /* error */
|
if (errno) /* error */
|
||||||
goto return_error_indicator;
|
goto return_error_indicator;
|
||||||
if (ic < ' ' || ic > 255) {
|
if (ic < ' ' || ic > 255) {
|
||||||
|
73
shell/ash.c
73
shell/ash.c
@ -102,8 +102,7 @@
|
|||||||
//config: default n
|
//config: default n
|
||||||
//config: depends on ASH
|
//config: depends on ASH
|
||||||
//config: help
|
//config: help
|
||||||
//config: Enables bash-like auto-logout after "$TMOUT" seconds
|
//config: Enables bash-like auto-logout after $TMOUT seconds of idle time.
|
||||||
//config: of idle time.
|
|
||||||
//config:
|
//config:
|
||||||
//config:config ASH_JOB_CONTROL
|
//config:config ASH_JOB_CONTROL
|
||||||
//config: bool "Job control"
|
//config: bool "Job control"
|
||||||
@ -408,6 +407,9 @@ static const char *var_end(const char *var)
|
|||||||
|
|
||||||
|
|
||||||
/* ============ Interrupts / exceptions */
|
/* ============ Interrupts / exceptions */
|
||||||
|
|
||||||
|
static void exitshell(void) NORETURN;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These macros allow the user to suspend the handling of interrupt signals
|
* 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
|
* 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)
|
if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
|
||||||
nr = nonblock_safe_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
|
nr = nonblock_safe_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
|
||||||
else {
|
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
|
# if ENABLE_FEATURE_TAB_COMPLETION
|
||||||
line_input_state->path_lookup = pathval();
|
line_input_state->path_lookup = pathval();
|
||||||
# endif
|
# 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) {
|
if (nr == 0) {
|
||||||
/* Ctrl+C pressed */
|
/* Ctrl+C pressed */
|
||||||
if (trap[SIGINT]) {
|
if (trap[SIGINT]) {
|
||||||
@ -9587,9 +9600,17 @@ preadfd(void)
|
|||||||
}
|
}
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
if (nr < 0 && errno == 0) {
|
if (nr < 0) {
|
||||||
/* Ctrl+D pressed */
|
if (errno == 0) {
|
||||||
nr = 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
|
#else
|
||||||
@ -12056,23 +12077,6 @@ evalcmd(int argc UNUSED_PARAM, char **argv)
|
|||||||
return exitstatus;
|
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.
|
* Read and execute commands.
|
||||||
* "Top" is nonzero for the top level command loop;
|
* "Top" is nonzero for the top level command loop;
|
||||||
@ -12089,20 +12093,6 @@ cmdloop(int top)
|
|||||||
TRACE(("cmdloop(%d) called\n", top));
|
TRACE(("cmdloop(%d) called\n", top));
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int skip;
|
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);
|
setstackmark(&smark);
|
||||||
#if JOBS
|
#if JOBS
|
||||||
@ -12115,14 +12105,6 @@ cmdloop(int top)
|
|||||||
chkmail();
|
chkmail();
|
||||||
}
|
}
|
||||||
n = parsecmd(inter);
|
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
|
||||||
if (DEBUG > 2 && debug && (n != NODE_EOF))
|
if (DEBUG > 2 && debug && (n != NODE_EOF))
|
||||||
showtree(n);
|
showtree(n);
|
||||||
@ -12850,7 +12832,6 @@ ulimitcmd(int argc UNUSED_PARAM, char **argv)
|
|||||||
/*
|
/*
|
||||||
* Called to exit the shell.
|
* Called to exit the shell.
|
||||||
*/
|
*/
|
||||||
static void exitshell(void) NORETURN;
|
|
||||||
static void
|
static void
|
||||||
exitshell(void)
|
exitshell(void)
|
||||||
{
|
{
|
||||||
|
@ -1902,7 +1902,7 @@ static void get_user_input(struct in_str *i)
|
|||||||
G.flag_SIGINT = 0;
|
G.flag_SIGINT = 0;
|
||||||
/* buglet: SIGINT will not make new prompt to appear _at once_,
|
/* buglet: SIGINT will not make new prompt to appear _at once_,
|
||||||
* only after <Enter>. (^C will work) */
|
* 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) */
|
/* catch *SIGINT* etc (^C is handled by read_line_input) */
|
||||||
check_and_run_traps(0);
|
check_and_run_traps(0);
|
||||||
} while (r == 0 || G.flag_SIGINT); /* repeat if ^C or SIGINT */
|
} while (r == 0 || G.flag_SIGINT); /* repeat if ^C or SIGINT */
|
||||||
|
@ -548,7 +548,7 @@ read_line(const char *prompt)
|
|||||||
{
|
{
|
||||||
int sz;
|
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)
|
if (sz <= 0)
|
||||||
exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */
|
exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user