Submenu default support.

* grub-core/normal/menu.c (grub_menu_execute_entry): New parameter
	auto_boot. All users updated.
	Declared static.
	Handle chosen and default with submenus.
	(grub_menu_execute_with_fallback): Declared static.
	Don't notify failure if autobooted. Upper level does it.
	(menuentry_eq): New function.
	(get_entry_number): Use menuentry_eq.
	(show_menu): New parameter "autobooted". All users updated.
	(grub_show_menu): Likewise.
	* include/grub/normal.h (grub_show_menu): Likewise.
	* include/grub/menu.h (grub_menu_execute_entry): Removed.
	(grub_menu_execute_with_fallback): Likewise.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-01-10 23:27:58 +01:00
parent 6fef99b4e4
commit dcb883b162
7 changed files with 137 additions and 24 deletions

View file

@ -154,12 +154,15 @@ get_and_remove_first_entry_number (const char *name)
}
/* Run a menu entry. */
void
grub_menu_execute_entry(grub_menu_entry_t entry)
static void
grub_menu_execute_entry(grub_menu_entry_t entry, int auto_boot)
{
grub_err_t err = GRUB_ERR_NONE;
int errs_before;
grub_menu_t menu;
char *optr, *buf, *oldchosen = NULL, *olddefault = NULL;
const char *ptr, *chosen, *def;
grub_size_t sz = 0;
if (entry->restricted)
err = grub_auth_check_authentication (entry->users);
@ -173,6 +176,9 @@ grub_menu_execute_entry(grub_menu_entry_t entry)
errs_before = grub_err_printed_errors;
chosen = grub_env_get ("chosen");
def = grub_env_get ("default");
if (entry->submenu)
{
grub_env_context_open ();
@ -180,9 +186,64 @@ grub_menu_execute_entry(grub_menu_entry_t entry)
if (! menu)
return;
grub_env_set_menu (menu);
if (auto_boot)
grub_env_set ("timeout", "0");
}
grub_env_set ("chosen", entry->title);
for (ptr = entry->title; *ptr; ptr++)
sz += (*ptr == '>') ? 2 : 1;
if (chosen)
{
oldchosen = grub_strdup (chosen);
if (!oldchosen)
grub_print_error ();
}
if (def)
{
olddefault = grub_strdup (def);
if (!olddefault)
grub_print_error ();
}
sz++;
if (chosen)
sz += grub_strlen (chosen);
sz++;
buf = grub_malloc (sz);
if (!buf)
grub_print_error ();
else
{
optr = buf;
if (chosen)
{
optr = grub_stpcpy (optr, chosen);
*optr++ = '>';
}
for (ptr = entry->title; *ptr; ptr++)
{
if (*ptr == '>')
*optr++ = '>';
*optr++ = *ptr;
}
*optr = 0;
grub_env_set ("chosen", buf);
grub_env_export ("chosen");
grub_free (buf);
}
for (ptr = def; *ptr; ptr++)
{
if (ptr[0] == '>' && ptr[1] == '>')
{
ptr++;
continue;
}
if (ptr[0] == '>')
break;
}
if (ptr[0] && ptr[1])
grub_env_set ("default", ptr + 1);
else
grub_env_unset ("default");
grub_script_execute_sourcecode (entry->sourcecode, entry->argc, entry->args);
if (errs_before != grub_err_printed_errors)
@ -196,20 +257,30 @@ grub_menu_execute_entry(grub_menu_entry_t entry)
{
if (menu && menu->size)
{
grub_show_menu (menu, 1);
grub_show_menu (menu, 1, auto_boot);
grub_normal_free_menu (menu);
}
grub_env_context_close ();
}
if (oldchosen)
grub_env_set ("chosen", oldchosen);
else
grub_env_unset ("chosen");
if (olddefault)
grub_env_set ("default", olddefault);
else
grub_env_unset ("default");
grub_env_unset ("timeout");
}
/* Execute ENTRY from the menu MENU, falling back to entries specified
in the environment variable "fallback" if it fails. CALLBACK is a
pointer to a struct of function pointers which are used to allow the
caller provide feedback to the user. */
void
static void
grub_menu_execute_with_fallback (grub_menu_t menu,
grub_menu_entry_t entry,
int autobooted,
grub_menu_execute_callback_t callback,
void *callback_data)
{
@ -217,7 +288,7 @@ grub_menu_execute_with_fallback (grub_menu_t menu,
callback->notify_booting (entry, callback_data);
grub_menu_execute_entry (entry);
grub_menu_execute_entry (entry, 1);
/* Deal with fallback entries. */
while ((fallback_entry = get_and_remove_first_entry_number ("fallback"))
@ -228,14 +299,15 @@ grub_menu_execute_with_fallback (grub_menu_t menu,
entry = grub_menu_get_entry (menu, fallback_entry);
callback->notify_fallback (entry, callback_data);
grub_menu_execute_entry (entry);
grub_menu_execute_entry (entry, 1);
/* If the function call to execute the entry returns at all, then this is
taken to indicate a boot failure. For menu entries that do something
other than actually boot an operating system, this could assume
incorrectly that something failed. */
}
callback->notify_failure (callback_data);
if (!autobooted)
callback->notify_failure (callback_data);
}
static struct grub_menu_viewer *viewers;
@ -309,11 +381,35 @@ grub_menu_register_viewer (struct grub_menu_viewer *viewer)
viewers = viewer;
}
static int
menuentry_eq (const char *title, const char *spec)
{
const char *ptr1, *ptr2;
ptr1 = title;
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)
{
char *val;
const char *val;
int entry;
val = grub_env_get (name);
@ -334,7 +430,7 @@ get_entry_number (grub_menu_t menu, const char *name)
for (i = 0; e; i++)
{
if (grub_strcmp (e->title, val) == 0)
if (menuentry_eq (e->title, val))
{
entry = i;
break;
@ -590,7 +686,7 @@ static struct grub_menu_execute_callback execution_callback =
};
static grub_err_t
show_menu (grub_menu_t menu, int nested)
show_menu (grub_menu_t menu, int nested, int autobooted)
{
while (1)
{
@ -609,22 +705,26 @@ show_menu (grub_menu_t menu, int nested)
grub_cls ();
if (auto_boot)
grub_menu_execute_with_fallback (menu, e, &execution_callback, 0);
grub_menu_execute_with_fallback (menu, e, autobooted,
&execution_callback, 0);
else
grub_menu_execute_entry (e);
grub_menu_execute_entry (e, 0);
if (autobooted)
break;
}
return GRUB_ERR_NONE;
}
grub_err_t
grub_show_menu (grub_menu_t menu, int nested)
grub_show_menu (grub_menu_t menu, int nested, int autoboot)
{
grub_err_t err1, err2;
while (1)
{
err1 = show_menu (menu, nested);
err1 = show_menu (menu, nested, autoboot);
autoboot = 0;
grub_print_error ();
if (grub_normal_exit_level)