From fc55cc4c27ef976a9c4d0a9a19c7f87bd3a2400a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 21 Sep 2010 00:47:49 +0200 Subject: [PATCH] Support submenus. * grub-core/commands/menuentry.c (grub_normal_add_menu_entry): New parameter submenu. All users updated. * grub-core/normal/main.c (free_menu): Rename to ... (grub_normal_free_menu): ... this. Made global. * grub-core/normal/menu.c (grub_menu_execute_entry): Open new context if requested. * grub-core/normal/menu_entry.c (screen): New field submenu. (make_screen): Set submenu. (run): Open new context if requested. * include/grub/menu.h (grub_menu_entry): New field submenu. * include/grub/normal.h (grub_normal_free_menu): New proto. --- ChangeLog | 16 ++++++++++ grub-core/commands/legacycfg.c | 4 +-- grub-core/commands/menuentry.c | 56 +++++++++++++++++++++++----------- grub-core/normal/main.c | 6 ++-- grub-core/normal/menu.c | 20 ++++++++++++ grub-core/normal/menu_entry.c | 24 +++++++++++++++ include/grub/menu.h | 2 ++ include/grub/normal.h | 5 ++- 8 files changed, 109 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index df1e4541d..934e3c73a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2010-09-20 Vladimir Serbinenko + + Support submenus. + + * grub-core/commands/menuentry.c (grub_normal_add_menu_entry): New + parameter submenu. All users updated. + * grub-core/normal/main.c (free_menu): Rename to ... + (grub_normal_free_menu): ... this. Made global. + * grub-core/normal/menu.c (grub_menu_execute_entry): Open new context + if requested. + * grub-core/normal/menu_entry.c (screen): New field submenu. + (make_screen): Set submenu. + (run): Open new context if requested. + * include/grub/menu.h (grub_menu_entry): New field submenu. + * include/grub/normal.h (grub_normal_free_menu): New proto. + 2010-09-20 Vladimir Serbinenko Menu entries extractor. diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index d69dad75b..1b0e968c5 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -118,7 +118,7 @@ legacy_file (const char *filename) } args[0] = oldname; grub_normal_add_menu_entry (1, args, NULL, NULL, NULL, NULL, - entrysrc); + entrysrc, 0); grub_free (args); entrysrc[0] = 0; grub_free (oldname); @@ -168,7 +168,7 @@ legacy_file (const char *filename) return grub_errno; } args[0] = entryname; - grub_normal_add_menu_entry (1, args, NULL, NULL, NULL, NULL, entrysrc); + grub_normal_add_menu_entry (1, args, NULL, NULL, NULL, NULL, entrysrc, 0); grub_free (args); } diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c index f10e05dc3..9718d1eab 100644 --- a/grub-core/commands/menuentry.c +++ b/grub-core/commands/menuentry.c @@ -68,9 +68,9 @@ static struct grub_err_t grub_normal_add_menu_entry (int argc, const char **args, char **classes, const char *users, const char *hotkey, - const char *prefix, const char *sourcecode) + const char *prefix, const char *sourcecode, + int submenu) { - unsigned i; int menu_hotkey = 0; char **menu_args = NULL; char *menu_users = NULL; @@ -93,6 +93,7 @@ grub_normal_add_menu_entry (int argc, const char **args, char **classes, if (classes) { + int i; for (i = 0; classes[i]; i++); /* count # of menuentry classes */ menu_classes = grub_zalloc (sizeof (struct grub_menu_entry_class) * i); if (! menu_classes) @@ -116,6 +117,7 @@ grub_normal_add_menu_entry (int argc, const char **args, char **classes, if (hotkey) { + unsigned i; for (i = 0; i < ARRAY_SIZE (hotkey_aliases); i++) if (grub_strcmp (hotkey, hotkey_aliases[i].name) == 0) { @@ -141,13 +143,16 @@ grub_normal_add_menu_entry (int argc, const char **args, char **classes, if (! menu_args) goto fail; - for (i = 0; i < argc; i++) - { - menu_args[i] = grub_strdup (args[i]); - if (! menu_args[i]) - goto fail; - } - menu_args[argc] = NULL; + { + int i; + for (i = 0; i < argc; i++) + { + menu_args[i] = grub_strdup (args[i]); + if (! menu_args[i]) + goto fail; + } + menu_args[argc] = NULL; + } /* Add the menu entry at the end of the list. */ while (*last) @@ -166,6 +171,7 @@ grub_normal_add_menu_entry (int argc, const char **args, char **classes, (*last)->argc = argc; (*last)->args = menu_args; (*last)->sourcecode = menu_sourcecode; + (*last)->submenu = submenu; menu->size++; return GRUB_ERR_NONE; @@ -173,13 +179,19 @@ grub_normal_add_menu_entry (int argc, const char **args, char **classes, fail: grub_free (menu_sourcecode); - for (i = 0; menu_classes && menu_classes[i].name; i++) - grub_free (menu_classes[i].name); - grub_free (menu_classes); + { + int i; + for (i = 0; menu_classes && menu_classes[i].name; i++) + grub_free (menu_classes[i].name); + grub_free (menu_classes); + } - for (i = 0; menu_args && menu_args[i]; i++) - grub_free (menu_args[i]); - grub_free (menu_args); + { + int i; + for (i = 0; menu_args && menu_args[i]; i++) + grub_free (menu_args[i]); + grub_free (menu_args); + } grub_free (menu_users); grub_free (menu_title); @@ -259,7 +271,8 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args) return grub_normal_add_menu_entry (argc, (const char **) args, ctxt->state[0].args, ctxt->state[1].arg, ctxt->state[2].arg, 0, - ctxt->state[3].arg); + ctxt->state[3].arg, + ctxt->extcmd->cmd->name[0] == 's'); src = args[argc - 1]; args[argc - 1] = NULL; @@ -274,7 +287,8 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args) r = grub_normal_add_menu_entry (argc - 1, (const char **) args, ctxt->state[0].args, ctxt->state[1].arg, - ctxt->state[2].arg, prefix, src + 1); + ctxt->state[2].arg, prefix, src + 1, + ctxt->extcmd->cmd->name[0] == 's'); src[len - 1] = ch; args[argc - 1] = src; @@ -282,7 +296,7 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args) return r; } -static grub_extcmd_t cmd; +static grub_extcmd_t cmd, cmd_sub; void grub_menu_init (void) @@ -291,10 +305,16 @@ grub_menu_init (void) GRUB_COMMAND_FLAG_BLOCKS | GRUB_COMMAND_FLAG_EXTRACTOR, N_("BLOCK"), N_("Define a menuentry."), options); + cmd_sub = grub_register_extcmd ("submenu", grub_cmd_menuentry, + GRUB_COMMAND_FLAG_BLOCKS + | GRUB_COMMAND_FLAG_EXTRACTOR, + N_("BLOCK"), N_("Define a submenu."), + options); } void grub_menu_fini (void) { grub_unregister_extcmd (cmd); + grub_unregister_extcmd (cmd_sub); } diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c index f2e5eaf51..3bfbbeb72 100644 --- a/grub-core/normal/main.c +++ b/grub-core/normal/main.c @@ -123,8 +123,8 @@ grub_file_getline (grub_file_t file) return cmdline; } -static void -free_menu (grub_menu_t menu) +void +grub_normal_free_menu (grub_menu_t menu) { grub_menu_entry_t entry = menu->entry_list; @@ -289,7 +289,7 @@ grub_normal_execute (const char *config, int nested, int batch) { grub_show_menu (menu, nested); if (nested) - free_menu (menu); + grub_normal_free_menu (menu); } } } diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c index 9c0a2182f..807ad51e0 100644 --- a/grub-core/normal/menu.c +++ b/grub-core/normal/menu.c @@ -159,6 +159,7 @@ grub_menu_execute_entry(grub_menu_entry_t entry) { grub_err_t err = GRUB_ERR_NONE; int errs_before; + grub_menu_t menu; if (entry->restricted) err = grub_auth_check_authentication (entry->users); @@ -172,6 +173,15 @@ grub_menu_execute_entry(grub_menu_entry_t entry) errs_before = grub_err_printed_errors; + if (entry->submenu) + { + grub_env_context_open (); + menu = grub_zalloc (sizeof (*menu)); + if (! menu) + return; + grub_env_set_menu (menu); + } + grub_env_set ("chosen", entry->title); grub_script_execute_sourcecode (entry->sourcecode, entry->argc, entry->args); @@ -181,6 +191,16 @@ grub_menu_execute_entry(grub_menu_entry_t entry) if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ()) /* Implicit execution of boot, only if something is loaded. */ grub_command_execute ("boot", 0, 0); + + if (entry->submenu) + { + if (menu && menu->size) + { + grub_show_menu (menu, 1); + grub_normal_free_menu (menu); + } + grub_env_context_close (); + } } /* Execute ENTRY from the menu MENU, falling back to entries specified diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c index 82506fa6f..096600e09 100644 --- a/grub-core/normal/menu_entry.c +++ b/grub-core/normal/menu_entry.c @@ -71,6 +71,8 @@ struct screen /* The flag of a completion window. */ int completion_shown; + int submenu; + struct per_term_screen *terms; unsigned nterms; }; @@ -496,6 +498,8 @@ make_screen (grub_menu_entry_t entry) if (! screen) return 0; + screen->submenu = entry->submenu; + screen->num_lines = 1; screen->lines = grub_malloc (sizeof (struct line)); if (! screen->lines) @@ -1162,6 +1166,7 @@ run (struct screen *screen) int currline = 0; char *nextline; int errs_before; + grub_menu_t menu; auto grub_err_t editor_getline (char **line, int cont); grub_err_t editor_getline (char **line, int cont __attribute__ ((unused))) @@ -1197,6 +1202,15 @@ run (struct screen *screen) errs_before = grub_err_printed_errors; + if (screen->submenu) + { + grub_env_context_open (); + menu = grub_zalloc (sizeof (*menu)); + if (! menu) + return; + grub_env_set_menu (menu); + } + /* Execute the script, line for line. */ while (currline < screen->num_lines) { @@ -1212,6 +1226,16 @@ run (struct screen *screen) /* Implicit execution of boot, only if something is loaded. */ grub_command_execute ("boot", 0, 0); + if (screen->submenu) + { + if (menu && menu->size) + { + grub_show_menu (menu, 1); + grub_normal_free_menu (menu); + } + grub_env_context_close (); + } + if (grub_errno != GRUB_ERR_NONE) { grub_print_error (); diff --git a/include/grub/menu.h b/include/grub/menu.h index 608253863..5ff356beb 100644 --- a/include/grub/menu.h +++ b/include/grub/menu.h @@ -53,6 +53,8 @@ struct grub_menu_entry int hotkey; + int submenu; + /* The next element. */ struct grub_menu_entry *next; }; diff --git a/include/grub/normal.h b/include/grub/normal.h index 2fc289373..187567797 100644 --- a/include/grub/normal.h +++ b/include/grub/normal.h @@ -119,11 +119,14 @@ extern int grub_extractor_level; grub_err_t grub_normal_add_menu_entry (int argc, const char **args, char **classes, const char *users, const char *hotkey, - const char *prefix, const char *sourcecode); + const char *prefix, const char *sourcecode, + int submenu); grub_err_t grub_normal_set_password (const char *user, const char *password); +void grub_normal_free_menu (grub_menu_t menu); + void grub_normal_auth_init (void); void grub_normal_auth_fini (void);