From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Peter Jones <pjones@redhat.com> Date: Fri, 5 Sep 2014 10:07:04 -0400 Subject: [PATCH] Allow "fallback" to include entries by title, not just number. Resolves: rhbz#1026084 Signed-off-by: Peter Jones <pjones@redhat.com> --- grub-core/normal/menu.c | 85 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 27 deletions(-) diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c index 6a90e091f22..6444ee6f969 100644 --- a/grub-core/normal/menu.c +++ b/grub-core/normal/menu.c @@ -163,15 +163,40 @@ grub_menu_set_timeout (int timeout) } } +static int +menuentry_eq (const char *id, const char *spec) +{ + const char *ptr1, *ptr2; + ptr1 = id; + ptr2 = spec; + while (1) + { + if (*ptr2 == '>' && ptr2[1] != '>' && *ptr1 == 0) + return ptr2 - spec; + if (*ptr2 == '>' && ptr2[1] != '>') + return 0; + if (*ptr2 == '>') + ptr2++; + if (*ptr1 != *ptr2) + return 0; + if (*ptr1 == 0) + return ptr1 - id; + ptr1++; + ptr2++; + } + return 0; +} + /* Get the first entry number from the value of the environment variable NAME, which is a space-separated list of non-negative integers. The entry number which is returned is stripped from the value of NAME. If no entry number can be found, -1 is returned. */ static int -get_and_remove_first_entry_number (const char *name) +get_and_remove_first_entry_number (grub_menu_t menu, const char *name) { const char *val, *tail; int entry; + int sz = 0; val = grub_env_get (name); if (! val) @@ -181,9 +206,39 @@ get_and_remove_first_entry_number (const char *name) entry = (int) grub_strtoul (val, &tail, 0); + if (grub_errno == GRUB_ERR_BAD_NUMBER) + { + /* See if the variable matches the title of a menu entry. */ + grub_menu_entry_t e = menu->entry_list; + int i; + + for (i = 0; e; i++) + { + sz = menuentry_eq (e->title, val); + if (sz < 1) + sz = menuentry_eq (e->id, val); + + if (sz >= 1) + { + entry = i; + break; + } + e = e->next; + } + + if (sz > 0) + grub_errno = GRUB_ERR_NONE; + + if (! e) + entry = -1; + } + if (grub_errno == GRUB_ERR_NONE) { - /* Skip whitespace to find the next digit. */ + if (sz > 0) + tail += sz; + + /* Skip whitespace to find the next entry. */ while (*tail && grub_isspace (*tail)) tail++; grub_env_set (name, tail); @@ -346,7 +401,7 @@ grub_menu_execute_with_fallback (grub_menu_t menu, grub_menu_execute_entry (entry, 1); /* Deal with fallback entries. */ - while ((fallback_entry = get_and_remove_first_entry_number ("fallback")) + while ((fallback_entry = get_and_remove_first_entry_number (menu, "fallback")) >= 0) { grub_print_error (); @@ -464,30 +519,6 @@ grub_menu_register_viewer (struct grub_menu_viewer *viewer) viewers = viewer; } -static int -menuentry_eq (const char *id, const char *spec) -{ - const char *ptr1, *ptr2; - ptr1 = id; - ptr2 = spec; - while (1) - { - if (*ptr2 == '>' && ptr2[1] != '>' && *ptr1 == 0) - return 1; - if (*ptr2 == '>' && ptr2[1] != '>') - return 0; - if (*ptr2 == '>') - ptr2++; - if (*ptr1 != *ptr2) - return 0; - if (*ptr1 == 0) - return 1; - ptr1++; - ptr2++; - } -} - - /* Get the entry number from the variable NAME. */ static int get_entry_number (grub_menu_t menu, const char *name)