ash: optional support for $TMOUT variable
authorDenys Vlasenko <vda.linux@googlemail.com>
Fri, 4 Feb 2011 16:53:59 +0000 (17:53 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Fri, 4 Feb 2011 16:53:59 +0000 (17:53 +0100)
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
include/libbb.h
shell/ash.c

index a0e23697c01e02b7f0dcbdd98018e97ef69de36b..6358e654ab0b6fd295d5f6f743f5c8a80868184e 100644 (file)
@@ -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
index 0e27a073ce4509b02537ce7f709b034823c25fda..bdc64790cf0c3204669cecdde225b86dae07e30c 100644 (file)
 //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);