diff --git a/ChangeLog b/ChangeLog index ec7b556d6..9bf245ef4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2012-02-09 Vladimir Serbinenko + + Fix `help' with unloaded modules. + + * include/grub/normal.h (grub_dyncmd_get_cmd): New proto. + * grub-core/normal/dyncmd.c (grub_dyncmd_get_cmd): New function. + (grub_dyncmd_dispatcher): Small stylistic fix. + * grub-core/commands/help.c (grub_cmd_help): Load missing modules when + explicit help is requested. + 2012-02-09 Vladimir Serbinenko * grub-core/fs/cpio.c (grub_cpio_dir): Fix a bug with multiple listing. diff --git a/grub-core/commands/help.c b/grub-core/commands/help.c index 82f3200c7..f33e55635 100644 --- a/grub-core/commands/help.c +++ b/grub-core/commands/help.c @@ -47,7 +47,7 @@ grub_cmd_help (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc, char *command_help; grub_uint32_t *unicode_command_help; grub_uint32_t *unicode_last_position; - + command_help = grub_xasprintf ("%s %s", cmd->name, summary_translated); if (!command_help) break; @@ -99,28 +99,37 @@ grub_cmd_help (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc, else { int i; - grub_command_t cmd; + grub_command_t cmd_iter, cmd; for (i = 0; i < argc; i++) { currarg = args[i]; - FOR_COMMANDS(cmd) + FOR_COMMANDS(cmd_iter) { - if (cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) - { - if (! grub_strncmp (cmd->name, currarg, grub_strlen (currarg))) - { - if (cnt++ > 0) - grub_printf ("\n\n"); + if (!(cmd_iter->prio & GRUB_PRIO_LIST_FLAG_ACTIVE)) + continue; - if ((cmd->flags & GRUB_COMMAND_FLAG_EXTCMD) && - ! (cmd->flags & GRUB_COMMAND_FLAG_DYNCMD)) - grub_arg_show_help ((grub_extcmd_t) cmd->data); - else - grub_printf ("%s %s %s\n%s\n", _("Usage:"), cmd->name, _(cmd->summary), - _(cmd->description)); - } + if (grub_strncmp (cmd_iter->name, currarg, + grub_strlen (currarg)) != 0) + continue; + if (cmd_iter->flags & GRUB_COMMAND_FLAG_DYNCMD) + cmd = grub_dyncmd_get_cmd (cmd_iter); + else + cmd = cmd_iter; + if (!cmd) + { + grub_print_error (); + continue; } + if (cnt++ > 0) + grub_printf ("\n\n"); + + if ((cmd->flags & GRUB_COMMAND_FLAG_EXTCMD) && + ! (cmd->flags & GRUB_COMMAND_FLAG_DYNCMD)) + grub_arg_show_help ((grub_extcmd_t) cmd->data); + else + grub_printf ("%s %s %s\n%s\n", _("Usage:"), cmd->name, + _(cmd->summary), _(cmd->description)); } } } diff --git a/grub-core/normal/dyncmd.c b/grub-core/normal/dyncmd.c index fcc636aec..de45b58d6 100644 --- a/grub-core/normal/dyncmd.c +++ b/grub-core/normal/dyncmd.c @@ -27,6 +27,32 @@ #include #include +grub_command_t +grub_dyncmd_get_cmd (grub_command_t cmd) +{ + grub_extcmd_t extcmd = cmd->data; + char *modname; + char *name; + grub_dl_t mod; + + modname = extcmd->data; + mod = grub_dl_load (modname); + if (!mod) + return NULL; + + grub_free (modname); + grub_dl_ref (mod); + + name = (char *) cmd->name; + grub_unregister_extcmd (extcmd); + + cmd = grub_command_find (name); + + grub_free (name); + + return cmd; +} + static grub_err_t grub_dyncmd_dispatcher (struct grub_extcmd_context *ctxt, int argc, char **args) @@ -36,36 +62,33 @@ grub_dyncmd_dispatcher (struct grub_extcmd_context *ctxt, grub_err_t ret; grub_extcmd_t extcmd = ctxt->extcmd; grub_command_t cmd = extcmd->cmd; + char *name; modname = extcmd->data; mod = grub_dl_load (modname); - if (mod) + if (!mod) + return grub_errno; + + grub_free (modname); + grub_dl_ref (mod); + + name = (char *) cmd->name; + grub_unregister_extcmd (extcmd); + + cmd = grub_command_find (name); + if (cmd) { - char *name; - - grub_free (modname); - grub_dl_ref (mod); - - name = (char *) cmd->name; - grub_unregister_extcmd (extcmd); - - cmd = grub_command_find (name); - if (cmd) - { - if (cmd->flags & GRUB_COMMAND_FLAG_BLOCKS && - cmd->flags & GRUB_COMMAND_FLAG_EXTCMD) - ret = grub_extcmd_dispatcher (cmd, argc, args, ctxt->script); - else - ret = (cmd->func) (cmd, argc, args); - } + if (cmd->flags & GRUB_COMMAND_FLAG_BLOCKS && + cmd->flags & GRUB_COMMAND_FLAG_EXTCMD) + ret = grub_extcmd_dispatcher (cmd, argc, args, ctxt->script); else - ret = grub_errno; - - grub_free (name); + ret = (cmd->func) (cmd, argc, args); } else ret = grub_errno; + grub_free (name); + return ret; } diff --git a/include/grub/normal.h b/include/grub/normal.h index 84e387242..b6b7d288d 100644 --- a/include/grub/normal.h +++ b/include/grub/normal.h @@ -132,4 +132,7 @@ void grub_normal_free_menu (grub_menu_t menu); void grub_normal_auth_init (void); void grub_normal_auth_fini (void); +grub_command_t +grub_dyncmd_get_cmd (grub_command_t cmd); + #endif /* ! GRUB_NORMAL_HEADER */