summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko2011-02-04 17:53:59 +0100
committerDenys Vlasenko2011-02-04 17:53:59 +0100
commit046341e8bd91a2a2c0d44b40217fa1c5ce1dd949 (patch)
tree855422f962f9aab6727f96559c2cc3e52b2b397d
parent8c52f803976c79812a75b9317107cc0a8fb94c7f (diff)
downloadbusybox-046341e8bd91a2a2c0d44b40217fa1c5ce1dd949.zip
busybox-046341e8bd91a2a2c0d44b40217fa1c5ce1dd949.tar.gz
ash: optional support for $TMOUT variable
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--include/libbb.h4
-rw-r--r--shell/ash.c47
2 files changed, 50 insertions, 1 deletions
diff --git a/include/libbb.h b/include/libbb.h
index a0e2369..6358e65 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1393,12 +1393,14 @@ enum {
};
line_input_t *new_line_input_t(int flags) FAST_FUNC;
/* So far static: void free_line_input_t(line_input_t *n) FAST_FUNC; */
-/* maxsize must be >= 2.
+/*
+ * maxsize must be >= 2.
* Returns:
* -1 on read errors or EOF, or on bare Ctrl-D,
* 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;
#else
#define MAX_HISTORY 0
diff --git a/shell/ash.c b/shell/ash.c
index 0e27a07..bdc6479 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -97,6 +97,14 @@
//config: help
//config: Enable bash-compatible extensions.
//config:
+//config:config ASH_IDLE_TIMEOUT
+//config: bool "Idle timeout variable"
+//config: default n
+//config: depends on ASH
+//config: help
+//config: Enables bash-like auto-logout after "$TMOUT" seconds
+//config: of idle time.
+//config:
//config:config ASH_JOB_CONTROL
//config: bool "Job control"
//config: default y
@@ -12048,6 +12056,23 @@ 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;
@@ -12064,6 +12089,20 @@ 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
@@ -12076,6 +12115,14 @@ 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);