Okay here's a preliminar patch. We still need to define in which ways
can the user interrupt it. What do we do on '\n' ? and on ESC ?
--
Robert Millan
<GPLv2> I know my rights; I want my phone call!
<DRM> What use is a phone call… if you are unable to speak?
(as seen on /.)
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 <grub/normal.h>
#include <grub/term.h>
#include <grub/types.h>
+#include <grub/machine/time.h>
+
+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)
_______________________________________________
Grub-devel mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/grub-devel