grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Use submenus for 10_linux


From: Colin Watson
Subject: Re: [PATCH] Use submenus for 10_linux
Date: Sun, 5 Dec 2010 00:54:49 +0000
User-agent: Mutt/1.5.18 (2008-05-17)

On Tue, Nov 30, 2010 at 01:36:15PM +0000, Žika wrote:
> I like the idea. But how are we to set default kernel, other than
> first, to boot automatically, now...? Old-school method doesn't
> work...

The following patch should fix handling of default='title' for entries
within submenus.  I haven't bothered defining a way to select submenu
entries by number.

Review welcome!  I'd particularly like confirmation from Vladimir that I'm
using the new extractor interface correctly, as I don't see any other
significant use of it in trunk at the moment beyond the extract_* commands
which nothing seems to be using yet.

2010-12-05  Colin Watson  <address@hidden>

        Fix defaults within submenus.

        * grub-core/normal/main.c (new_menu): New function.  Handles
        propagating `default', `fallback', and `timeout' variables to
        submenu contexts.
        (grub_normal_new_menu_context): Likewise.
        (grub_normal_new_menu_extractor): Likewise.
        * include/grub/normal.h (grub_normal_new_menu_context): Add
        prototype.
        (grub_normal_new_menu_extractor): Likewise.
        * grub-core/normal/menu.c (grub_menu_execute_entry): Use
        grub_normal_new_menu_context.  Unset `default', `fallback', and
        `timeout' if we fall off the end of the menu, to allow escape from a
        failed boot.
        (get_entry_number): Recursively scan submenus.
        (run_menu): Automatically traverse into a submenu if it contains the
        default entry.
        (show_menu): Initialise auto_boot to 0.
        * grub-core/script/execute.c (grub_script_execute_cmdline): Silence
        error messages for commands not valid when extracting menu entries
        (otherwise, if nothing else, we always get errors about setparams).

=== modified file 'grub-core/normal/main.c'
--- grub-core/normal/main.c     2010-09-20 22:47:49 +0000
+++ grub-core/normal/main.c     2010-12-05 00:36:28 +0000
@@ -123,6 +123,62 @@ grub_file_getline (grub_file_t file)
   return cmdline;
 }
 
+/* Open a new nested menu, propagating environment variables to the new
+   context as necessary.  */
+static grub_menu_t
+new_menu (int extractor)
+{
+  const char *default_val, *fallback_val, *timeout_val;
+  grub_menu_t menu;
+
+  default_val = grub_env_get ("default");
+  fallback_val = grub_env_get ("fallback");
+  timeout_val = grub_env_get ("timeout");
+
+  if (extractor)
+    grub_env_extractor_open (0);
+  else
+    grub_env_context_open ();
+
+  menu = grub_zalloc (sizeof (*menu));
+  if (!menu)
+    {
+      if (extractor)
+       grub_env_extractor_close (0);
+      else
+       grub_env_context_close ();
+      return NULL;
+    }
+  grub_env_set_menu (menu);
+
+  if (default_val)
+    {
+      /* Only propagate string defaults.  */
+      (void) grub_strtoul (default_val, 0, 0);
+      if (grub_errno == GRUB_ERR_BAD_NUMBER)
+       grub_env_set ("default", default_val);
+      grub_errno = GRUB_ERR_NONE;
+    }
+  if (fallback_val)
+    grub_env_set ("fallback", fallback_val);
+  if (timeout_val)
+    grub_env_set ("timeout", timeout_val);
+
+  return menu;
+}
+
+grub_menu_t
+grub_normal_new_menu_context (void)
+{
+  return new_menu (0);
+}
+
+grub_menu_t
+grub_normal_new_menu_extractor (void)
+{
+  return new_menu (1);
+}
+
 void
 grub_normal_free_menu (grub_menu_t menu)
 {

=== modified file 'grub-core/normal/menu.c'
--- grub-core/normal/menu.c     2010-09-20 22:47:49 +0000
+++ grub-core/normal/menu.c     2010-12-05 00:43:40 +0000
@@ -175,11 +175,9 @@ grub_menu_execute_entry(grub_menu_entry_
 
   if (entry->submenu)
     {
-      grub_env_context_open ();
-      menu = grub_zalloc (sizeof (*menu));
+      menu = grub_normal_new_menu_context ();
       if (! menu)
        return;
-      grub_env_set_menu (menu);
     }
 
   grub_env_set ("chosen", entry->title);
@@ -201,6 +199,11 @@ grub_menu_execute_entry(grub_menu_entry_
        }
       grub_env_context_close ();
     }
+
+  /* If we reach here, previous first-time defaults no longer make sense.  */
+  grub_env_unset ("default");
+  grub_env_unset ("fallback");
+  grub_env_unset ("timeout");
 }
 
 /* Execute ENTRY from the menu MENU, falling back to entries specified
@@ -311,7 +314,7 @@ grub_menu_register_viewer (struct grub_m
 
 /* Get the entry number from the variable NAME.  */
 static int
-get_entry_number (grub_menu_t menu, const char *name)
+get_entry_number (grub_menu_t menu, const char *name, int *in_submenu)
 {
   char *val;
   int entry;
@@ -323,6 +326,7 @@ get_entry_number (grub_menu_t menu, cons
   grub_error_push ();
 
   entry = (int) grub_strtoul (val, 0, 0);
+  *in_submenu = 0;
 
   if (grub_errno == GRUB_ERR_BAD_NUMBER)
     {
@@ -330,20 +334,43 @@ get_entry_number (grub_menu_t menu, cons
       grub_menu_entry_t e = menu->entry_list;
       int i;
 
+      entry = -1;
       grub_errno = GRUB_ERR_NONE;
 
-      for (i = 0; e; i++)
+      for (i = 0; e && entry == -1; i++)
        {
          if (grub_strcmp (e->title, val) == 0)
+           entry = i;
+         else if (e->submenu)
            {
-             entry = i;
-             break;
+             /* To make this work with submenus, we need to extract entries
+                from the submenu, then return the entry number of the
+                submenu itself if one of its entries (recursively) matches;
+                when the submenu is executed for real, it will then have to
+                call this function again one level down.  This is not going
+                to be very efficient with a deep menu stack, but it seems
+                unlikely that many people will bother with more than a
+                couple of levels.  */
+             grub_menu_t submenu;
+
+             submenu = grub_normal_new_menu_extractor ();
+             if (submenu)
+               {
+                 grub_script_execute_sourcecode (e->sourcecode,
+                                                 e->argc, e->args);
+                 if (get_entry_number (submenu, name, in_submenu) != -1)
+                   {
+                     entry = i;
+                     *in_submenu = 1;
+                   }
+
+                 grub_normal_free_menu (submenu);
+                 grub_env_extractor_close (0);
+               }
            }
+
          e = e->next;
        }
-
-      if (! e)
-       entry = -1;
     }
 
   if (grub_errno != GRUB_ERR_NONE)
@@ -369,16 +396,21 @@ static int
 run_menu (grub_menu_t menu, int nested, int *auto_boot)
 {
   grub_uint64_t saved_time;
-  int default_entry, current_entry;
+  int default_entry = -1, current_entry;
+  int in_submenu = 0;
   int timeout;
 
-  default_entry = get_entry_number (menu, "default");
+  default_entry = get_entry_number (menu, "default", &in_submenu);
 
   /* If DEFAULT_ENTRY is not within the menu entries, fall back to
      the first entry.  */
   if (default_entry < 0 || default_entry >= menu->size)
     default_entry = 0;
 
+  /* If a submenu was automatically selected, traverse into it.  */
+  if (in_submenu)
+    return default_entry;
+
   /* If timeout is 0, drawing is pointless (and ugly).  */
   if (grub_menu_get_timeout () == 0)
     {
@@ -596,7 +628,7 @@ show_menu (grub_menu_t menu, int nested)
     {
       int boot_entry;
       grub_menu_entry_t e;
-      int auto_boot;
+      int auto_boot = 0;
 
       boot_entry = run_menu (menu, nested, &auto_boot);
       if (boot_entry < 0)

=== modified file 'grub-core/script/execute.c'
--- grub-core/script/execute.c  2010-11-07 10:43:14 +0000
+++ grub-core/script/execute.c  2010-12-04 23:58:02 +0000
@@ -628,7 +628,7 @@ grub_script_execute_cmdline (struct grub
 
   if (invert)
     {
-      if (ret == GRUB_ERR_TEST_FAILURE)
+      if (ret == GRUB_ERR_TEST_FAILURE || ret == GRUB_ERR_EXTRACTOR)
        grub_errno = ret = GRUB_ERR_NONE;
       else if (ret == GRUB_ERR_NONE)
        ret = grub_error (GRUB_ERR_TEST_FAILURE, "false");
@@ -642,7 +642,7 @@ grub_script_execute_cmdline (struct grub
   /* Free arguments.  */
   grub_script_argv_free (&argv);
 
-  if (grub_errno == GRUB_ERR_TEST_FAILURE)
+  if (grub_errno == GRUB_ERR_TEST_FAILURE || grub_errno == GRUB_ERR_EXTRACTOR)
     grub_errno = GRUB_ERR_NONE;
 
   grub_print_error ();

=== modified file 'include/grub/normal.h'
--- include/grub/normal.h       2010-09-20 22:47:49 +0000
+++ include/grub/normal.h       2010-12-05 00:36:26 +0000
@@ -125,6 +125,8 @@ grub_normal_add_menu_entry (int argc, co
 grub_err_t
 grub_normal_set_password (const char *user, const char *password);
 
+grub_menu_t grub_normal_new_menu_context (void);
+grub_menu_t grub_normal_new_menu_extractor (void);
 void grub_normal_free_menu (grub_menu_t menu);
 
 void grub_normal_auth_init (void);

-- 
Colin Watson                                       address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]