diff -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp ../grub2/commands/read.c ./commands/read.c --- ../grub2/commands/read.c 2008-02-02 21:35:08.000000000 +0100 +++ ./commands/read.c 2008-03-03 23:13:24.000000000 +0100 @@ -23,13 +23,39 @@ #include #include #include +#include + +static const struct grub_arg_option options[] = + { + {"timeout", 't', 0, "timeout (in seconds)", 0, ARG_TYPE_INT}, + {"print-timeout", 'p', 0, "print timeout counter", 0, 0}, + {0, 0, 0, 0, 0, 0} + }; + +static grub_uint8_t x, y; + +static void +do_print (int n) +{ + grub_gotoxy (x, y); + /* NOTE: Do not remove the trailing space characters. + They are required to clear the line. */ + grub_printf ("%d ", n); +} static char * -grub_getline (void) +grub_getline (int timeout, int print_timeout) { int i; char *line; char *tmp; + grub_uint32_t end_at, print_at; + + if (timeout) + end_at = grub_get_rtc () + timeout * GRUB_TICKS_PER_SECOND; + + if (print_timeout) + print_at = grub_get_rtc (); i = 0; line = grub_malloc (1 + i + sizeof('\0')); @@ -38,27 +64,53 @@ grub_getline (void) while ((line[i - 1] != '\n') && (line[i - 1] != '\r')) { + /* If a timeout was requested, perform busy wait here so we can do other + things... */ + while (timeout && (grub_checkkey () == -1)) + { + /* ...such as printing the timeout, if applicable. */ + if (print_timeout && grub_get_rtc () > print_at) + { + do_print (grub_div_roundup (end_at - grub_get_rtc (), GRUB_TICKS_PER_SECOND)); + print_at += GRUB_TICKS_PER_SECOND; + } + /* ...or aborting when time is up. */ + if (grub_get_rtc () > end_at) + goto abort; + } + line[i] = grub_getkey (); if (grub_isprint (line[i])) grub_putchar (line[i]); i++; + tmp = grub_realloc (line, 1 + i + sizeof('\0')); if (! tmp) - { - grub_free (line); - return NULL; - } + goto abort; line = tmp; } line[i] = '\0'; return line; + +abort: + if (print_timeout) + do_print (0); + grub_free (line); + return NULL; } static grub_err_t -grub_cmd_read (struct grub_arg_list *state UNUSED, int argc, char **args) +grub_cmd_read (struct grub_arg_list *state, int argc, char **args) { - char *line = grub_getline (); + char *line; + grub_uint16_t xy; + + xy = grub_getxy (); + x = xy >> 8; + y = xy & 0xff; + + line = grub_getline ((state[0].set) ? grub_strtoul (state[0].arg, 0, 10) : 0, state[1].set); if (! line) return grub_errno; if (argc > 0) @@ -72,7 +124,7 @@ grub_cmd_read (struct grub_arg_list *sta GRUB_MOD_INIT(read) { grub_register_command ("read", grub_cmd_read, GRUB_COMMAND_FLAG_CMDLINE, - "read [ENVVAR]", "Set variable with user input", 0); + "read [ENVVAR]", "Set variable with user input", options); } GRUB_MOD_FINI(read)