variable data slot `menu'). As the configuration file is read, the script
parser calls this when a menu entry is to be created. */
static grub_err_t
-add_menu_entry (int argc, const char **args, char **classes,
- const char *users, const char *hotkey,
- const char *sourcecode)
+append_menu_entry (int argc, const char **args, char **classes,
+ const char *users, const char *hotkey,
+ const char *sourcecode)
{
unsigned i;
int menu_hotkey = 0;
+ char **menu_args = NULL;
char *menu_users = NULL;
char *menu_title = NULL;
char *menu_sourcecode = NULL;
if (! menu_title)
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. */
while (*last)
if (menu_users)
(*last)->restricted = 1;
(*last)->users = menu_users;
+ (*last)->argc = argc;
+ (*last)->args = menu_args;
(*last)->sourcecode = menu_sourcecode;
menu->size++;
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);
+
grub_free (menu_users);
grub_free (menu_title);
return grub_errno;
ch = src[len - 1];
src[len - 1] = '\0';
- r = add_menu_entry (argc - 1, (const char **) args,
- ctxt->state[0].args, ctxt->state[1].arg,
- ctxt->state[2].arg, src + 1);
+ r = append_menu_entry (argc - 1, (const char **) args,
+ ctxt->state[0].args, ctxt->state[1].arg,
+ ctxt->state[2].arg, src + 1);
src[len - 1] = ch;
args[argc - 1] = src;
/* The sourcecode of the menu entry, used by the editor. */
const char *sourcecode;
+ /* Parameters to be passed to menu definition. */
+ int argc;
+ char **args;
+
int hotkey;
/* The next element. */
/* Execute any GRUB pre-parsed command or 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
communicate with the bison code. */
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. */
void
grub_menu_execute_entry(grub_menu_entry_t entry)
}
grub_env_set ("chosen", entry->title);
-
- grub_menu_execute_entry_real (entry);
+ grub_script_execute_sourcecode (entry->sourcecode, entry->argc, entry->args);
if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
/* Implicit execution of boot, only if something is loaded. */
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. */
grub_err_t
grub_script_execute_cmdline (struct grub_script_cmd *cmd)
grub_script_free (struct grub_script *script)
{
struct grub_script *s;
+ struct grub_script *t;
if (!script)
return;
s = script->children;
while (s) {
- s = s->siblings;
+ t = s->siblings;
grub_script_put (s);
+ s = t;
}
grub_free (script);
}