diff --git a/commands/extcmd.c b/commands/extcmd.c index 76cbe4e26..349e9bfc7 100644 --- a/commands/extcmd.c +++ b/commands/extcmd.c @@ -34,9 +34,20 @@ grub_extcmd_dispatcher (struct grub_command *cmd, int argc, char **args, struct grub_extcmd_context context; int maxargs = 0; grub_err_t ret; - grub_extcmd_t ext; + grub_extcmd_t ext = cmd->data; + + context.state = 0; + context.extcmd = ext; + context.script_params = scripts; + + /* Dynamic commands should not perform option parsing before + corresponding module gets loaded. */ + if (cmd->flags & GRUB_COMMAND_FLAG_DYNCMD) + { + ret = (ext->func) (&context, argc, args); + return ret; + } - ext = cmd->data; parser = (struct grub_arg_option *) ext->options; while (parser && (parser++)->doc) maxargs++; @@ -46,10 +57,7 @@ grub_extcmd_dispatcher (struct grub_command *cmd, int argc, char **args, if (grub_arg_parse (ext, argc, args, state, &new_args, &new_argc)) { - context.extcmd = ext; context.state = state; - context.script_params = scripts; - ret = (ext->func) (&context, new_argc, new_args); grub_free (new_args); } @@ -68,10 +76,11 @@ grub_extcmd_dispatch (struct grub_command *cmd, int argc, char **args) } grub_extcmd_t -grub_register_extcmd (const char *name, grub_extcmd_func_t func, - unsigned flags, const char *summary, - const char *description, - const struct grub_arg_option *parser) +grub_register_extcmd_prio (const char *name, grub_extcmd_func_t func, + unsigned flags, const char *summary, + const char *description, + const struct grub_arg_option *parser, + int prio) { grub_extcmd_t ext; grub_command_t cmd; @@ -81,7 +90,7 @@ grub_register_extcmd (const char *name, grub_extcmd_func_t func, return 0; cmd = grub_register_command_prio (name, grub_extcmd_dispatch, - summary, description, 1); + summary, description, prio); if (! cmd) { grub_free (ext); @@ -99,6 +108,16 @@ grub_register_extcmd (const char *name, grub_extcmd_func_t func, return ext; } +grub_extcmd_t +grub_register_extcmd (const char *name, grub_extcmd_func_t func, + unsigned flags, const char *summary, + const char *description, + const struct grub_arg_option *parser) +{ + return grub_register_extcmd_prio (name, func, flags, + summary, description, parser, 1); +} + void grub_unregister_extcmd (grub_extcmd_t ext) { diff --git a/hello/hello.c b/hello/hello.c index 118966291..183ee7798 100644 --- a/hello/hello.c +++ b/hello/hello.c @@ -26,29 +26,12 @@ #include #include -static struct grub_script *script; - static grub_err_t -grub_cmd_hello (grub_extcmd_context_t ctxt, - int argc, char **args __attribute__ ((unused))) +grub_cmd_hello (grub_extcmd_context_t ctxt __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) { - if (argc == 0 && script == 0) - grub_printf ("Hello World\n"); - - else if (argc == 0) - grub_script_execute (script); - - else - { - if (! ctxt->script_params || ! ctxt->script_params[0]) - return 1; - - if (script) - grub_script_put (script); - - script = grub_script_get (ctxt->script_params[0]); - } - + grub_printf ("Hello World\n"); return 0; } @@ -56,16 +39,11 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(hello) { - cmd = grub_register_extcmd ("hello", grub_cmd_hello, - GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_BLOCKS, - N_("[BLOCK]"), N_("Say \"Hello World\"."), 0); + cmd = grub_register_extcmd ("hello", grub_cmd_hello, GRUB_COMMAND_FLAG_BOTH, + 0, N_("Say \"Hello World\"."), 0); } GRUB_MOD_FINI(hello) { - if (script) - grub_script_put (script); - - script = 0; grub_unregister_extcmd (cmd); } diff --git a/include/grub/extcmd.h b/include/grub/extcmd.h index 54f0958fe..a5e4d18fe 100644 --- a/include/grub/extcmd.h +++ b/include/grub/extcmd.h @@ -62,6 +62,14 @@ grub_extcmd_t grub_register_extcmd (const char *name, const char *description, const struct grub_arg_option *parser); +grub_extcmd_t grub_register_extcmd_prio (const char *name, + grub_extcmd_func_t func, + unsigned flags, + const char *summary, + const char *description, + const struct grub_arg_option *parser, + int prio); + void grub_unregister_extcmd (grub_extcmd_t cmd); grub_err_t diff --git a/normal/dyncmd.c b/normal/dyncmd.c index a3cafa514..172baa44e 100644 --- a/normal/dyncmd.c +++ b/normal/dyncmd.c @@ -23,16 +23,21 @@ #include #include #include +#include +#include #include static grub_err_t -grub_dyncmd_dispatcher (struct grub_command *cmd, +grub_dyncmd_dispatcher (struct grub_extcmd_context *ctxt, int argc, char **args) { - char *modname = cmd->data; + char *modname; grub_dl_t mod; grub_err_t ret; + grub_extcmd_t extcmd = ctxt->extcmd; + grub_command_t cmd = extcmd->cmd; + modname = extcmd->data; mod = grub_dl_load (modname); if (mod) { @@ -42,11 +47,18 @@ grub_dyncmd_dispatcher (struct grub_command *cmd, grub_dl_ref (mod); name = (char *) cmd->name; - grub_unregister_command (cmd); + grub_unregister_extcmd (extcmd); cmd = grub_command_find (name); if (cmd) - 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_params); + else + ret = (cmd->func) (cmd, argc, args); + } else ret = grub_errno; @@ -81,13 +93,14 @@ read_command_list (const char *prefix) for (ptr = grub_command_list; ptr; ptr = next) { next = ptr->next; - if (ptr->func == grub_dyncmd_dispatcher) + if (ptr->flags & GRUB_COMMAND_FLAG_DYNCMD) { if (last) last->next = ptr->next; else grub_command_list = ptr->next; grub_free (ptr); + grub_free (ptr->data); /* extcmd struct */ } else last = ptr; @@ -96,7 +109,7 @@ read_command_list (const char *prefix) for (;; grub_free (buf)) { char *p, *name, *modname; - grub_command_t cmd; + grub_extcmd_t cmd; int prio = 0; buf = grub_file_getline (file); @@ -139,16 +152,19 @@ read_command_list (const char *prefix) continue; } - cmd = grub_register_command_prio (name, - grub_dyncmd_dispatcher, - 0, N_("not loaded"), prio); + cmd = grub_register_extcmd_prio (name, + grub_dyncmd_dispatcher, + GRUB_COMMAND_FLAG_BLOCKS + | GRUB_COMMAND_FLAG_EXTCMD + | GRUB_COMMAND_FLAG_DYNCMD, + 0, N_("not loaded"), 0, + prio); if (! cmd) { grub_free (name); grub_free (modname); continue; } - cmd->flags |= GRUB_COMMAND_FLAG_DYNCMD; cmd->data = modname; /* Update the active flag. */