[syslinux:elflink] elflink: Fix TIMEOUT and TOTALTIMEOUT handling

syslinux-bot for Matt Fleming matt.fleming at intel.com
Fri May 4 12:15:05 PDT 2012


Commit-ID:  b6f8015f2335da9ce400b84787ca5721bf1bf867
Gitweb:     http://www.syslinux.org/commit/b6f8015f2335da9ce400b84787ca5721bf1bf867
Author:     Matt Fleming <matt.fleming at intel.com>
AuthorDate: Thu, 3 May 2012 13:19:52 +0100
Committer:  Matt Fleming <matt.fleming at intel.com>
CommitDate: Thu, 3 May 2012 13:50:14 +0100

elflink: Fix TIMEOUT and TOTALTIMEOUT handling

Paulo reported that his default command line wasn't being executed
when the timeout specified in his config file elapsed. This is because
mygetkey() wasn't correctly applying the timeout when waiting for
input.

Furthermore, it seems the ONTIMEOUT parsing was also broken.

Reported-by: Paulo Alcantara <pcacjr at zytor.com>
Signed-off-by: Matt Fleming <matt.fleming at intel.com>

---
 com32/elflink/ldlinux/cli.c        |   65 ++++++++++++++++-------------------
 com32/elflink/ldlinux/config.h     |    1 +
 com32/elflink/ldlinux/ldlinux.c    |   24 +++++++------
 com32/elflink/ldlinux/readconfig.c |    7 +++-
 com32/include/menu.h               |    1 +
 5 files changed, 50 insertions(+), 48 deletions(-)

diff --git a/com32/elflink/ldlinux/cli.c b/com32/elflink/ldlinux/cli.c
index 498644e..211a796 100644
--- a/com32/elflink/ldlinux/cli.c
+++ b/com32/elflink/ldlinux/cli.c
@@ -19,8 +19,6 @@
 #include "cli.h"
 #include "config.h"
 
-static jmp_buf timeout_jump;
-
 static struct list_head cli_history_head;
 
 void clear_screen(void)
@@ -29,46 +27,37 @@ void clear_screen(void)
     fputs("\033e\033%@\033)0\033(B\1#0\033[?25l\033[2J", stdout);
 }
 
-int mygetkey(clock_t timeout)
+static int mygetkey_timeout(clock_t *kbd_to, clock_t *tto)
 {
-    clock_t t0, t;
-    clock_t tto, to;
+    clock_t t0, t1;
     int key;
 
-    //dprintf("enter");
-    if (!totaltimeout)
-	return get_key(stdin, 0);
-
-    for (;;) {
-	tto = min(totaltimeout, INT_MAX);
-	to = timeout ? min(tto, timeout) : tto;
+    t0 = times(NULL);
+    key = get_key(stdin, *kbd_to ? *kbd_to : *tto);
 
-	t0 = 0;
-	key = get_key(stdin, 0);
-	t = 0 - t0;
+    /* kbdtimeout only applies to the first character */
+    if (*kbd_to)
+	*kbd_to = 0;
 
-	if (totaltimeout <= t)
-	    longjmp(timeout_jump, 1);
+    t1 = times(NULL) - t0;
+    if (*tto) {
+	/* Timed out. */
+	if (*tto <= (long long)t1)
+	    key = KEY_NONE;
+	else {
+	    /* Did it wrap? */
+	    if (*tto > totaltimeout)
+		key = KEY_NONE;
 
-	totaltimeout -= t;
-
-	if (key != KEY_NONE) {
-		//dprintf("get key 0x%x", key);
-	    return key;
-	}
-
-	if (timeout) {
-	    if (timeout <= t) {
-		//dprintf("timeout");
-		return KEY_NONE;
-		}
-
-	    timeout -= t;
+	    *tto -= t1;
 	}
     }
+
+    return key;
 }
 
-static const char * cmd_reverse_search(int *cursor)
+static const char * cmd_reverse_search(int *cursor, clock_t *kbd_to,
+				       clock_t *tto)
 {
     int key;
     int i = 0;
@@ -83,7 +72,7 @@ static const char * cmd_reverse_search(int *cursor)
 
     eprintf("\033[1G\033[1;36m(reverse-i-search)`': \033[0m");
     while (1) {
-        key = mygetkey(0);
+	key = mygetkey_timeout(kbd_to, tto);
 
 	if (key == KEY_CTRL('C')) {
 	    return NULL;
@@ -140,6 +129,8 @@ const char *edit_cmdline(const char *input, int top /*, int width */ ,
     const char *ret;
     int width = 0;
     struct cli_command *comm_counter = NULL;
+    clock_t kbd_to = kbdtimeout;
+    clock_t tto = totaltimeout;
 
     if (!width) {
 	int height;
@@ -205,9 +196,13 @@ const char *edit_cmdline(const char *input, int top /*, int width */ ,
 	    redraw = 0;
 	}
 
-	key = mygetkey(0);
+	key = mygetkey_timeout(&kbd_to, &tto);
 
 	switch (key) {
+	case KEY_NONE:
+	    /* We timed out. */
+	    return NULL;
+
 	case KEY_CTRL('L'):
 	    redraw = 2;
 	    break;
@@ -381,7 +376,7 @@ const char *edit_cmdline(const char *input, int top /*, int width */ ,
 	          * Handle this case in another function, since it's 
 	          * a kind of special.
 	          */
-	        const char *p = cmd_reverse_search(&cursor);
+	        const char *p = cmd_reverse_search(&cursor, &kbd_to, &tto);
 	        if (p) {
 	            strcpy(cmdline, p);
 		    len = strlen(cmdline);
diff --git a/com32/elflink/ldlinux/config.h b/com32/elflink/ldlinux/config.h
index cab4c70..b15a082 100644
--- a/com32/elflink/ldlinux/config.h
+++ b/com32/elflink/ldlinux/config.h
@@ -35,6 +35,7 @@ extern short nohalt;		//idle.inc
 
 extern const char *default_cmd;	//"default" command line
 extern const char *onerror;	//"onerror" command line
+extern const char *ontimeout;	//"ontimeout" command line
 
 extern void cat_help_file(int key);
 extern struct menu_entry *find_label(const char *str);
diff --git a/com32/elflink/ldlinux/ldlinux.c b/com32/elflink/ldlinux/ldlinux.c
index 1891526..c9ec9ac 100644
--- a/com32/elflink/ldlinux/ldlinux.c
+++ b/com32/elflink/ldlinux/ldlinux.c
@@ -209,16 +209,12 @@ static void enter_cmdline(void)
 	/* Enter endless command line prompt, should support "exit" */
 	while (1) {
 		cmdline = edit_cmdline("syslinux$", 1, NULL, cat_help_file);
-		if (!cmdline)
-			continue;
-
-		/* return if user only press enter */
-		if (cmdline[0] == '\0') {
-			printf("\n");
-			continue;
-		}
 		printf("\n");
 
+		/* return if user only press enter or we timed out */
+		if (!cmdline || cmdline[0] == '\0')
+			return;
+
 		load_kernel(cmdline);
 	}
 }
@@ -226,6 +222,7 @@ static void enter_cmdline(void)
 int main(int argc __unused, char **argv __unused)
 {
 	const void *adv;
+	const char *cmdline;
 	size_t count = 0;
 	char *config_argv[2] = { NULL, NULL };
 
@@ -242,7 +239,6 @@ int main(int argc __unused, char **argv __unused)
 		 * We apparently have a boot-once set; clear it and
 		 * then execute the boot-once.
 		 */
-		const char *cmdline;
 		char *src, *dst;
 		size_t i;
 
@@ -270,12 +266,14 @@ int main(int argc __unused, char **argv __unused)
 	if (forceprompt)
 		goto cmdline;
 
+	cmdline = default_cmd;
+auto_boot:
 	/*
 	 * Auto boot
 	 */
 	if (defaultlevel || noescape) {
 		if (defaultlevel) {
-			load_kernel(default_cmd); /* Shouldn't return */
+			load_kernel(cmdline); /* Shouldn't return */
 		} else {
 			printf("No DEFAULT or UI configuration directive found!\n");
 
@@ -285,8 +283,12 @@ int main(int argc __unused, char **argv __unused)
 	}
 
 cmdline:
-	/* Should never return */
+	/* Only returns if the user pressed enter or input timed out */
 	enter_cmdline();
 
+	cmdline = ontimeoutlen ? ontimeout : default_cmd;
+
+	goto auto_boot;
+
 	return 0;
 }
diff --git a/com32/elflink/ldlinux/readconfig.c b/com32/elflink/ldlinux/readconfig.c
index 70fe346..885c81a 100644
--- a/com32/elflink/ldlinux/readconfig.c
+++ b/com32/elflink/ldlinux/readconfig.c
@@ -68,6 +68,7 @@ short nohalt = 1;		//idle.inc
 
 const char *default_cmd = NULL;	//"default" command line
 const char *onerror = NULL;	//"onerror" command line
+const char *ontimeout = NULL;	//"ontimeout" command line
 
 /* Empty refstring */
 const char *empty_string;
@@ -79,6 +80,7 @@ struct menu *root_menu, *start_menu, *hide_menu, *menu_list, *default_menu;
 int shiftkey = 0;		/* Only display menu if shift key pressed */
 int hiddenmenu = 0;
 long long totaltimeout = 0;
+unsigned int kbdtimeout = 0;
 
 /* Keep track of global default */
 static int has_ui = 0;		/* DEFAULT only counts if UI is found */
@@ -1081,11 +1083,12 @@ do_include:
 		//dprintf("got a kernel: %s, type = %d", ld.kernel, ld.type);
 	    }
 	} else if (looking_at(p, "timeout")) {
-	    m->timeout = (atoi(skipspace(p + 7)) * CLK_TCK + 9) / 10;
+	    kbdtimeout = (atoi(skipspace(p + 7)) * CLK_TCK + 9) / 10;
 	} else if (looking_at(p, "totaltimeout")) {
 	    totaltimeout = (atoll(skipspace(p + 13)) * CLK_TCK + 9) / 10;
 	} else if (looking_at(p, "ontimeout")) {
-	    m->ontimeout = refstrdup(skipspace(p + 9));
+	    ontimeout = refstrdup(skipspace(p + 9));
+	    ontimeoutlen = strlen(ontimeout);
 	} else if (looking_at(p, "allowoptions")) {
 	    m->allowedit = !!atoi(skipspace(p + 12));
 	} else if (looking_at(p, "ipappend")) {
diff --git a/com32/include/menu.h b/com32/include/menu.h
index 1db4d7c..ba6b9ce 100644
--- a/com32/include/menu.h
+++ b/com32/include/menu.h
@@ -187,6 +187,7 @@ extern int shiftkey;
 extern int hiddenmenu;
 extern int clearmenu;
 extern long long totaltimeout;
+extern clock_t kbdtimeout;
 extern const char *hide_key[KEY_MAX];
 
 void parse_configs(char **argv);


More information about the Syslinux-commits mailing list