]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
menuentry can pass parameters to its definition
authorBVK Chaitanya <bvk.groups@gmail.com>
Thu, 22 Jul 2010 15:45:14 +0000 (21:15 +0530)
committerBVK Chaitanya <bvk.groups@gmail.com>
Thu, 22 Jul 2010 15:45:14 +0000 (21:15 +0530)
commands/menuentry.c
include/grub/menu.h
include/grub/script_sh.h
normal/menu.c
script/execute.c
script/script.c

index 6b7214d629fd069e172285e2ee7cb3bbe1bda5bd..be4fa3347eceb190a90fbbfd4f31f6097680d589 100644 (file)
@@ -51,12 +51,13 @@ static struct
    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;
@@ -120,7 +121,18 @@ add_menu_entry (int argc, const char **args, char **classes,
   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)
@@ -136,6 +148,8 @@ add_menu_entry (int argc, const char **args, char **classes,
   if (menu_users)
     (*last)->restricted = 1;
   (*last)->users = menu_users;
+  (*last)->argc = argc;
+  (*last)->args = menu_args;
   (*last)->sourcecode = menu_sourcecode;
 
   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++)
     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;
@@ -170,9 +189,9 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
   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;
index e5e5fb11074ad874a73b7be883368caeb04109af..9dc257ab76298928091aa2bf77d46cf14c54910d 100644 (file)
@@ -47,6 +47,10 @@ struct grub_menu_entry
   /* 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.  */
index 122d898623f3a9bd5613f7537103435dc7fe8ae0..7869a4680768f4424d18771ef5a715f5bd3792d1 100644 (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.  */
 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.  */
index b57990b0d17c15b899936bf19a916de0ef877a27..f483349e4ffe539d29575e4817b484ead220bbcd 100644 (file)
@@ -142,44 +142,6 @@ get_and_remove_first_entry_number (const char *name)
   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)
@@ -197,8 +159,7 @@ 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.  */
index 4b906b06ff666d6f4600d5aca57647d50067991a..43a8bd1d715ede1eed6d3f217e7b0e3ae5c249f3 100644 (file)
@@ -268,6 +268,62 @@ grub_script_function_call (grub_script_function_t func, int argc, char **args)
   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)
index c1b5cf8cdfe811f0b15f1c865b6cf4adc226329c..6da4b72cda4a1b5b71b9842b5bc8c59a77b1833e 100644 (file)
@@ -95,6 +95,7 @@ void
 grub_script_free (struct grub_script *script)
 {
   struct grub_script *s;
+  struct grub_script *t;
 
   if (!script)
     return;
@@ -104,8 +105,9 @@ grub_script_free (struct grub_script *script)
 
   s = script->children;
   while (s) {
-    s = s->siblings;
+    t = s->siblings;
     grub_script_put (s);
+    s = t;
   }
   grub_free (script);
 }