menuentry can pass parameters to its definition

This commit is contained in:
BVK Chaitanya 2010-07-22 21:15:14 +05:30
parent 639cc5ab44
commit 1767f7096c
6 changed files with 91 additions and 48 deletions

View file

@ -51,12 +51,13 @@ static struct
variable data slot `menu'). As the configuration file is read, the script variable data slot `menu'). As the configuration file is read, the script
parser calls this when a menu entry is to be created. */ parser calls this when a menu entry is to be created. */
static grub_err_t static grub_err_t
add_menu_entry (int argc, const char **args, char **classes, append_menu_entry (int argc, const char **args, char **classes,
const char *users, const char *hotkey, const char *users, const char *hotkey,
const char *sourcecode) const char *sourcecode)
{ {
unsigned i; unsigned i;
int menu_hotkey = 0; int menu_hotkey = 0;
char **menu_args = NULL;
char *menu_users = NULL; char *menu_users = NULL;
char *menu_title = NULL; char *menu_title = NULL;
char *menu_sourcecode = NULL; char *menu_sourcecode = NULL;
@ -120,7 +121,18 @@ add_menu_entry (int argc, const char **args, char **classes,
if (! menu_title) if (! menu_title)
goto fail; goto fail;
/* XXX: pass args[1..end] as parameters to block arg. */ /* Save argc, args to pass as parameters to block arg later. */
menu_args = grub_malloc (sizeof (char*) * (argc + 1));
if (! menu_args)
goto fail;
for (i = 0; args[i]; 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. */ /* Add the menu entry at the end of the list. */
while (*last) while (*last)
@ -136,6 +148,8 @@ add_menu_entry (int argc, const char **args, char **classes,
if (menu_users) if (menu_users)
(*last)->restricted = 1; (*last)->restricted = 1;
(*last)->users = menu_users; (*last)->users = menu_users;
(*last)->argc = argc;
(*last)->args = menu_args;
(*last)->sourcecode = menu_sourcecode; (*last)->sourcecode = menu_sourcecode;
menu->size++; menu->size++;
@ -147,6 +161,11 @@ add_menu_entry (int argc, const char **args, char **classes,
for (i = 0; menu_classes && menu_classes[i].name; i++) for (i = 0; menu_classes && menu_classes[i].name; i++)
grub_free (menu_classes[i].name); grub_free (menu_classes[i].name);
grub_free (menu_classes); grub_free (menu_classes);
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_users);
grub_free (menu_title); grub_free (menu_title);
return grub_errno; return grub_errno;
@ -170,9 +189,9 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
ch = src[len - 1]; ch = src[len - 1];
src[len - 1] = '\0'; src[len - 1] = '\0';
r = add_menu_entry (argc - 1, (const char **) args, r = append_menu_entry (argc - 1, (const char **) args,
ctxt->state[0].args, ctxt->state[1].arg, ctxt->state[0].args, ctxt->state[1].arg,
ctxt->state[2].arg, src + 1); ctxt->state[2].arg, src + 1);
src[len - 1] = ch; src[len - 1] = ch;
args[argc - 1] = src; args[argc - 1] = src;

View file

@ -47,6 +47,10 @@ struct grub_menu_entry
/* The sourcecode of the menu entry, used by the editor. */ /* The sourcecode of the menu entry, used by the editor. */
const char *sourcecode; const char *sourcecode;
/* Parameters to be passed to menu definition. */
int argc;
char **args;
int hotkey; int hotkey;
/* The next element. */ /* The next element. */

View file

@ -303,6 +303,7 @@ grub_err_t grub_script_execute_cmdwhile (struct grub_script_cmd *cmd);
/* Execute any GRUB pre-parsed command or script. */ /* Execute any GRUB pre-parsed command or script. */
grub_err_t grub_script_execute (struct grub_script *script); grub_err_t grub_script_execute (struct grub_script *script);
grub_err_t grub_script_execute_sourcecode (const char *source, int argc, char **args);
/* This variable points to the parsed command. This is used to /* This variable points to the parsed command. This is used to
communicate with the bison code. */ communicate with the bison code. */

View file

@ -142,44 +142,6 @@ get_and_remove_first_entry_number (const char *name)
return entry; return entry;
} }
static void
grub_menu_execute_entry_real (grub_menu_entry_t entry)
{
const char *source;
auto grub_err_t getline (char **line, int cont);
grub_err_t getline (char **line, int cont __attribute__ ((unused)))
{
const char *p;
if (!source)
{
*line = 0;
return 0;
}
p = grub_strchr (source, '\n');
if (p)
*line = grub_strndup (source, p - source);
else
*line = grub_strdup (source);
source = p ? p + 1 : 0;
return 0;
}
source = entry->sourcecode;
while (source)
{
char *line;
getline (&line, 0);
grub_normal_parse_line (line, getline);
grub_free (line);
}
}
/* Run a menu entry. */ /* Run a menu entry. */
void void
grub_menu_execute_entry(grub_menu_entry_t entry) grub_menu_execute_entry(grub_menu_entry_t entry)
@ -197,8 +159,7 @@ grub_menu_execute_entry(grub_menu_entry_t entry)
} }
grub_env_set ("chosen", entry->title); grub_env_set ("chosen", entry->title);
grub_script_execute_sourcecode (entry->sourcecode, entry->argc, entry->args);
grub_menu_execute_entry_real (entry);
if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ()) if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
/* Implicit execution of boot, only if something is loaded. */ /* Implicit execution of boot, only if something is loaded. */

View file

@ -268,6 +268,62 @@ grub_script_function_call (grub_script_function_t func, int argc, char **args)
return ret; return ret;
} }
/* Execute a source script. */
grub_err_t
grub_script_execute_sourcecode (const char *source, int argc, char **args)
{
grub_err_t ret = 0;
struct grub_script *parsed_script;
struct grub_script_scope new_scope;
struct grub_script_scope *old_scope;
auto grub_err_t getline (char **line, int cont);
grub_err_t getline (char **line, int cont __attribute__ ((unused)))
{
const char *p;
if (! source)
{
*line = 0;
return 0;
}
p = grub_strchr (source, '\n');
if (p)
*line = grub_strndup (source, p - source);
else
*line = grub_strdup (source);
source = p ? p + 1 : 0;
return 0;
}
new_scope.argv.argc = argc;
new_scope.argv.args = args;
old_scope = scope;
scope = &new_scope;
while (source)
{
char *line;
getline (&line, 0);
parsed_script = grub_script_parse (line, getline);
if (! parsed_script)
{
ret = grub_errno;
break;
}
ret = grub_script_execute (parsed_script);
grub_free (line);
}
scope = old_scope;
return ret;
}
/* Execute a single command line. */ /* Execute a single command line. */
grub_err_t grub_err_t
grub_script_execute_cmdline (struct grub_script_cmd *cmd) grub_script_execute_cmdline (struct grub_script_cmd *cmd)

View file

@ -95,6 +95,7 @@ void
grub_script_free (struct grub_script *script) grub_script_free (struct grub_script *script)
{ {
struct grub_script *s; struct grub_script *s;
struct grub_script *t;
if (!script) if (!script)
return; return;
@ -104,8 +105,9 @@ grub_script_free (struct grub_script *script)
s = script->children; s = script->children;
while (s) { while (s) {
s = s->siblings; t = s->siblings;
grub_script_put (s); grub_script_put (s);
s = t;
} }
grub_free (script); grub_free (script);
} }