aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--editors/ed.c6
-rw-r--r--include/libbb.h5
-rw-r--r--libbb/lineedit.c12
-rw-r--r--shell/ash.c73
-rw-r--r--shell/hush.c2
-rw-r--r--util-linux/fdisk.c2
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 <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)
{
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 <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 */
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 */