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
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to