]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Save 314 bytes on not handling contexts in core
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sun, 20 Dec 2009 01:52:39 +0000 (02:52 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sun, 20 Dec 2009 01:52:39 +0000 (02:52 +0100)
17 files changed:
conf/any-emu.rmk
conf/common.rmk
conf/i386-coreboot.rmk
conf/i386-efi.rmk
conf/i386-ieee1275.rmk
conf/i386-pc.rmk
conf/powerpc-ieee1275.rmk
conf/sparc64-ieee1275.rmk
conf/x86_64-efi.rmk
include/grub/env.h
include/grub/env_private.h [new file with mode: 0644]
include/grub/normal.h
kern/corecmd.c
kern/env.c
kern/main.c
normal/context.c [new file with mode: 0644]
normal/main.c

index fb97de0a0203501073c436f05643e84328539af9..066bb52ba4390f951d0b6dc06a639cdf6c974cae 100644 (file)
@@ -27,7 +27,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c   \
        normal/handler.c normal/auth.c normal/autofs.c                  \
        normal/completion.c normal/main.c normal/color.c                \
        normal/menu.c normal/menu_entry.c normal/menu_viewer.c          \
-       normal/menu_text.c                                              \
+       normal/menu_text.c normal/context.c                             \
        script/main.c script/execute.c script/function.c                \
        script/lexer.c script/script.c grub_script.tab.c                \
        partmap/amiga.c partmap/apple.c partmap/msdos.c partmap/sun.c   \
index 1ed30a404c912998115b1a4f99dd482bc00349a3..74e2b5bc4481e453aa6d66f81f5899491f2ba999 100644 (file)
@@ -543,7 +543,7 @@ normal_mod_SOURCES = normal/main.c normal/cmdline.c normal/dyncmd.c \
        normal/auth.c normal/autofs.c normal/handler.c \
        normal/color.c normal/completion.c normal/datetime.c normal/menu.c \
        normal/menu_entry.c normal/menu_text.c normal/menu_viewer.c \
-       normal/misc.c
+       normal/misc.c normal/context.c
 normal_mod_CFLAGS = $(COMMON_CFLAGS)
 normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
index e597328e7b5e51e44d9dc41cdd569457c0fb90f0..1efea8afb2042969d2a64ed5379c39a09af7b5ff 100644 (file)
@@ -35,7 +35,8 @@ kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
        env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
        partition.h msdos_partition.h reader.h symbol.h term.h time.h types.h \
        machine/boot.h machine/console.h machine/init.h \
-       machine/memory.h machine/loader.h list.h handler.h command.h i18n.h
+       machine/memory.h machine/loader.h list.h handler.h command.h i18n.h \
+       env_private.h
 kernel_img_CFLAGS = $(COMMON_CFLAGS)
 kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
 kernel_img_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,$(GRUB_KERNEL_MACHINE_LINK_ADDR),-Bstatic
index 261fe40920bc14dc6e0d822cc38ee462e4f9e25c..2de0e9304b0449ddd9386db057a88032ed166acb 100644 (file)
@@ -51,7 +51,8 @@ kernel_img_SOURCES = kern/i386/efi/startup.S kern/main.c kern/device.c \
 kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
        env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
        partition.h msdos_partition.h reader.h symbol.h term.h time.h types.h \
-       efi/efi.h efi/time.h efi/disk.h i386/pit.h list.h handler.h command.h i18n.h
+       efi/efi.h efi/time.h efi/disk.h i386/pit.h list.h handler.h command.h \
+       i18n.h env_private.h
 kernel_img_CFLAGS = $(COMMON_CFLAGS)
 kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
 kernel_img_LDFLAGS = $(COMMON_LDFLAGS)
index 8d95778443669e21c687348b3fcf595b8c519af7..08c6c8f375782faee0062a786bb495dc5d4b8198 100644 (file)
@@ -33,7 +33,7 @@ kernel_img_HEADERS = cache.h device.h disk.h dl.h elf.h elfload.h \
        env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
        partition.h msdos_partition.h reader.h symbol.h term.h time.h types.h \
        ieee1275/ieee1275.h machine/kernel.h machine/loader.h machine/memory.h \
-       list.h handler.h command.h i18n.h
+       list.h handler.h command.h i18n.h env_private.h
 kernel_img_CFLAGS = $(COMMON_CFLAGS)
 kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
 kernel_img_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x10000,-Bstatic
index 046c71641e11b92659952fed582d2e8f90c0261c..8cec19f19c00054ef1913331ef2c6fc2cbc11384 100644 (file)
@@ -64,7 +64,8 @@ kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
        partition.h msdos_partition.h reader.h symbol.h term.h time.h types.h \
        machine/biosdisk.h machine/boot.h machine/console.h machine/init.h \
        machine/memory.h machine/loader.h machine/vga.h machine/vbe.h \
-       machine/kernel.h machine/pxe.h i386/pit.h list.h handler.h command.h i18n.h
+       machine/kernel.h machine/pxe.h i386/pit.h list.h handler.h command.h \
+       i18n.h env_private.h
 kernel_img_CFLAGS = $(COMMON_CFLAGS)  $(TARGET_IMG_CFLAGS)
 kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
 kernel_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)$(GRUB_KERNEL_MACHINE_LINK_ADDR) $(COMMON_CFLAGS)
index 85b1fa21116ee4978b32069a4adaf27588ba27fe..9c16299d161c166fda60b3cb153ba43c4d11b1a5 100644 (file)
@@ -17,7 +17,7 @@ kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
        env.h err.h file.h fs.h kernel.h misc.h mm.h net.h parser.h reader.h \
        symbol.h term.h time.h types.h powerpc/libgcc.h loader.h partition.h \
        msdos_partition.h ieee1275/ieee1275.h machine/kernel.h handler.h list.h \
-       command.h i18n.h
+       command.h i18n.h env_private.h
 
 symlist.c: $(addprefix include/grub/,$(kernel_img_HEADERS)) config.h gensymlist.sh
        /bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
index d19e927a5a76c8387e18640510456184b823a11b..d34adeb3cb8f3c88282df1c11120bdf25d9de76a 100644 (file)
@@ -31,7 +31,7 @@ kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
        partition.h msdos_partition.h reader.h symbol.h term.h time.h types.h \
        list.h handler.h command.h i18n.h \
        sparc64/libgcc.h ieee1275/ieee1275.h machine/kernel.h \
-       sparc64/ieee1275/ieee1275.h
+       sparc64/ieee1275/ieee1275.h env_private.h
 kernel_img_SOURCES = kern/sparc64/ieee1275/crt0.S kern/ieee1275/cmain.c        \
        kern/ieee1275/ieee1275.c kern/main.c kern/device.c              \
        kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c          \
index 0d1289c6f0191c0706a744aa782dff95b25a52b7..f5f0db25e7688b79b930e1cf50ef2b787eb51700 100644 (file)
@@ -51,7 +51,7 @@ kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
        env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
        partition.h msdos_partition.h reader.h symbol.h term.h time.h types.h \
        efi/efi.h efi/time.h efi/disk.h machine/loader.h i386/pit.h list.h \
-       handler.h command.h i18n.h
+       handler.h command.h i18n.h env_private.h
 kernel_img_CFLAGS = $(COMMON_CFLAGS)
 kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
 kernel_img_LDFLAGS = $(COMMON_LDFLAGS)
index 440185a59d78871665fb56c67d27e9922328fae6..ae4fd8745a5bfa8192244f42aedbe9914e0c04a8 100644 (file)
@@ -22,6 +22,7 @@
 #include <grub/symbol.h>
 #include <grub/err.h>
 #include <grub/types.h>
+#include <grub/menu.h>
 
 struct grub_env_var;
 
@@ -30,18 +31,6 @@ typedef char *(*grub_env_read_hook_t) (struct grub_env_var *var,
 typedef char *(*grub_env_write_hook_t) (struct grub_env_var *var,
                                        const char *val);
 
-enum grub_env_var_type
-  {
-    /* The default variable type which is local in current context.  */
-    GRUB_ENV_VAR_LOCAL,
-
-    /* The exported type, which is passed to new contexts.  */
-    GRUB_ENV_VAR_GLOBAL,
-
-    /* The data slot type, which is used to store arbitrary data.  */
-    GRUB_ENV_VAR_DATA
-  };
-
 struct grub_env_var
 {
   char *name;
@@ -50,23 +39,24 @@ struct grub_env_var
   grub_env_write_hook_t write_hook;
   struct grub_env_var *next;
   struct grub_env_var **prevp;
-  enum grub_env_var_type type;
+  int global;
 };
 
 grub_err_t EXPORT_FUNC(grub_env_set) (const char *name, const char *val);
 char *EXPORT_FUNC(grub_env_get) (const char *name);
 void EXPORT_FUNC(grub_env_unset) (const char *name);
 void EXPORT_FUNC(grub_env_iterate) (int (*func) (struct grub_env_var *var));
+struct grub_env_var *EXPORT_FUNC(grub_env_find) (const char *name);
 grub_err_t EXPORT_FUNC(grub_register_variable_hook) (const char *name,
                                                     grub_env_read_hook_t read_hook,
                                                     grub_env_write_hook_t write_hook);
-grub_err_t EXPORT_FUNC(grub_env_context_open) (int export);
-grub_err_t EXPORT_FUNC(grub_env_context_close) (void);
-grub_err_t EXPORT_FUNC(grub_env_export) (const char *name);
 
-grub_err_t EXPORT_FUNC(grub_env_set_data_slot) (const char *name,
-                                               const void *ptr);
-void *EXPORT_FUNC(grub_env_get_data_slot) (const char *name);
-void EXPORT_FUNC(grub_env_unset_data_slot) (const char *name);
+grub_err_t grub_env_context_open (int export);
+grub_err_t grub_env_context_close (void);
+grub_err_t grub_env_export (const char *name);
+
+void grub_env_unset_menu (void);
+grub_menu_t grub_env_get_menu (void);
+void grub_env_set_menu (grub_menu_t nmenu);
 
 #endif /* ! GRUB_ENV_HEADER */
diff --git a/include/grub/env_private.h b/include/grub/env_private.h
new file mode 100644 (file)
index 0000000..bb00153
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2005,2006,2007,2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_ENV_PRIVATE_HEADER
+#define GRUB_ENV_PRIVATE_HEADER        1
+
+#include <grub/env.h>
+
+/* The size of the hash table.  */
+#define        HASHSZ  13
+
+/* A hashtable for quick lookup of variables.  */
+struct grub_env_context
+{
+  /* A hash table for variables.  */
+  struct grub_env_var *vars[HASHSZ];
+
+  /* One level deeper on the stack.  */
+  struct grub_env_context *prev;
+};
+
+/* This is used for sorting only.  */
+struct grub_env_sorted_var
+{
+  struct grub_env_var *var;
+  struct grub_env_sorted_var *next;
+};
+
+extern struct grub_env_context *EXPORT_VAR(grub_current_context);
+
+#endif /* ! GRUB_ENV_PRIVATE_HEADER */
index feebc85b11524a7189bd295fea9bed34b626594e..15f4671d29df200b8313cb5f8c09f225f0067c9a 100644 (file)
@@ -84,6 +84,8 @@ void read_command_list (void);
 /* Defined in `autofs.c'.  */
 void read_fs_list (void);
 
+void grub_context_init (void);
+void grub_context_fini (void);
 
 #ifdef GRUB_UTIL
 void grub_normal_init (void);
index 03944f2df5b3b95f0ba5a1058cee1b0d960c31fe..7e8a3b4f66cedc1332993c6a537c6d77f5089c59 100644 (file)
@@ -73,18 +73,6 @@ grub_core_cmd_unset (struct grub_command *cmd __attribute__ ((unused)),
   return 0;
 }
 
-static grub_err_t
-grub_core_cmd_export (struct grub_command *cmd __attribute__ ((unused)),
-                     int argc, char **args)
-{
-  if (argc < 1)
-    return grub_error (GRUB_ERR_BAD_ARGUMENT,
-                      "no environment variable specified");
-
-  grub_env_export (args[0]);
-  return 0;
-}
-
 /* insmod MODULE */
 static grub_err_t
 grub_core_cmd_insmod (struct grub_command *cmd __attribute__ ((unused)),
@@ -193,8 +181,6 @@ grub_register_core_commands (void)
                         "set [ENVVAR=VALUE]", "set an environment variable");
   grub_register_command ("unset", grub_core_cmd_unset,
                         "unset ENVVAR", "remove an environment variable");
-  grub_register_command ("export", grub_core_cmd_export,
-                        "export ENVVAR", "Export a variable.");
   grub_register_command ("ls", grub_core_cmd_ls,
                         "ls [ARG]", "list devices or files");
   grub_register_command ("insmod", grub_core_cmd_insmod,
index 750902af8f1767899dff36641c3afa9eba2c4867..fdb3c9a34d1ad373ba857cf6025594ff54c39351 100644 (file)
  */
 
 #include <grub/env.h>
+#include <grub/env_private.h>
 #include <grub/misc.h>
 #include <grub/mm.h>
 
-/* The size of the hash table.  */
-#define        HASHSZ  13
-
-/* A hashtable for quick lookup of variables.  */
-struct grub_env_context
-{
-  /* A hash table for variables.  */
-  struct grub_env_var *vars[HASHSZ];
-
-  /* One level deeper on the stack.  */
-  struct grub_env_context *prev;
-};
-
-/* This is used for sorting only.  */
-struct grub_env_sorted_var
-{
-  struct grub_env_var *var;
-  struct grub_env_sorted_var *next;
-};
-
 /* The initial context.  */
 static struct grub_env_context initial_context;
 
 /* The current context.  */
-static struct grub_env_context *current_context = &initial_context;
+struct grub_env_context *grub_current_context = &initial_context;
 
 /* Return the hash representation of the string S.  */
 static unsigned int
@@ -60,87 +41,20 @@ grub_env_hashval (const char *s)
   return i % HASHSZ;
 }
 
-static struct grub_env_var *
+struct grub_env_var *
 grub_env_find (const char *name)
 {
   struct grub_env_var *var;
   int idx = grub_env_hashval (name);
 
   /* Look for the variable in the current context.  */
-  for (var = current_context->vars[idx]; var; var = var->next)
+  for (var = grub_current_context->vars[idx]; var; var = var->next)
     if (grub_strcmp (var->name, name) == 0)
       return var;
 
   return 0;
 }
 
-grub_err_t
-grub_env_context_open (int export)
-{
-  struct grub_env_context *context;
-  int i;
-
-  context = grub_zalloc (sizeof (*context));
-  if (! context)
-    return grub_errno;
-
-  context->prev = current_context;
-  current_context = context;
-
-  /* Copy exported variables.  */
-  for (i = 0; i < HASHSZ; i++)
-    {
-      struct grub_env_var *var;
-
-      for (var = context->prev->vars[i]; var; var = var->next)
-       {
-         if (export && var->type == GRUB_ENV_VAR_GLOBAL)
-           {
-             if (grub_env_set (var->name, var->value) != GRUB_ERR_NONE)
-               {
-                 grub_env_context_close ();
-                 return grub_errno;
-               }
-             grub_register_variable_hook (var->name, var->read_hook, var->write_hook);
-           }
-       }
-    }
-
-  return GRUB_ERR_NONE;
-}
-
-grub_err_t
-grub_env_context_close (void)
-{
-  struct grub_env_context *context;
-  int i;
-
-  if (! current_context->prev)
-    grub_fatal ("cannot close the initial context");
-
-  /* Free the variables associated with this context.  */
-  for (i = 0; i < HASHSZ; i++)
-    {
-      struct grub_env_var *p, *q;
-
-      for (p = current_context->vars[i]; p; p = q)
-       {
-         q = p->next;
-          grub_free (p->name);
-          if (p->type != GRUB_ENV_VAR_DATA)
-            grub_free (p->value);
-         grub_free (p);
-       }
-    }
-
-  /* Restore the previous context.  */
-  context = current_context->prev;
-  grub_free (current_context);
-  current_context = context;
-
-  return GRUB_ERR_NONE;
-}
-
 static void
 grub_env_insert (struct grub_env_context *context,
                 struct grub_env_var *var)
@@ -164,18 +78,6 @@ grub_env_remove (struct grub_env_var *var)
     var->next->prevp = var->prevp;
 }
 
-grub_err_t
-grub_env_export (const char *name)
-{
-  struct grub_env_var *var;
-
-  var = grub_env_find (name);
-  if (var)
-    var->type = GRUB_ENV_VAR_GLOBAL;
-
-  return GRUB_ERR_NONE;
-}
-
 grub_err_t
 grub_env_set (const char *name, const char *val)
 {
@@ -207,9 +109,8 @@ grub_env_set (const char *name, const char *val)
   if (! var)
     return grub_errno;
 
-  /* This is not necessary, because GRUB_ENV_VAR_LOCAL == 0. But leave
-     this for readability.  */
-  var->type = GRUB_ENV_VAR_LOCAL;
+  /* This is not necessary. But leave this for readability.  */
+  var->global = 0;
 
   var->name = grub_strdup (name);
   if (! var->name)
@@ -219,7 +120,7 @@ grub_env_set (const char *name, const char *val)
   if (! var->value)
     goto fail;
 
-  grub_env_insert (current_context, var);
+  grub_env_insert (grub_current_context, var);
 
   return GRUB_ERR_NONE;
 
@@ -263,8 +164,7 @@ grub_env_unset (const char *name)
   grub_env_remove (var);
 
   grub_free (var->name);
-  if (var->type != GRUB_ENV_VAR_DATA)
-    grub_free (var->value);
+  grub_free (var->value);
   grub_free (var);
 }
 
@@ -280,14 +180,10 @@ grub_env_iterate (int (*func) (struct grub_env_var *var))
     {
       struct grub_env_var *var;
 
-      for (var = current_context->vars[i]; var; var = var->next)
+      for (var = grub_current_context->vars[i]; var; var = var->next)
        {
          struct grub_env_sorted_var *p, **q;
 
-         /* Ignore data slots.  */
-         if (var->type == GRUB_ENV_VAR_DATA)
-           continue;
-
          sorted_var = grub_malloc (sizeof (*sorted_var));
          if (! sorted_var)
            goto fail;
@@ -343,84 +239,3 @@ grub_register_variable_hook (const char *name,
 
   return GRUB_ERR_NONE;
 }
-
-static char *
-mangle_data_slot_name (const char *name)
-{
-  char *mangled_name;
-
-  mangled_name = grub_malloc (grub_strlen (name) + 2);
-  if (! mangled_name)
-    return 0;
-
-  grub_sprintf (mangled_name, "\e%s", name);
-  return mangled_name;
-}
-
-grub_err_t
-grub_env_set_data_slot (const char *name, const void *ptr)
-{
-  char *mangled_name;
-  struct grub_env_var *var;
-
-  mangled_name = mangle_data_slot_name (name);
-  if (! mangled_name)
-    goto fail;
-
-  /* If the variable does already exist, just update the variable.  */
-  var = grub_env_find (mangled_name);
-  if (var)
-    {
-      var->value = (char *) ptr;
-      return GRUB_ERR_NONE;
-    }
-
-  /* The variable does not exist, so create a new one.  */
-  var = grub_zalloc (sizeof (*var));
-  if (! var)
-    goto fail;
-
-  var->type = GRUB_ENV_VAR_DATA;
-  var->name = mangled_name;
-  var->value = (char *) ptr;
-
-  grub_env_insert (current_context, var);
-
-  return GRUB_ERR_NONE;
-
- fail:
-
-  grub_free (mangled_name);
-  return grub_errno;
-}
-
-void *
-grub_env_get_data_slot (const char *name)
-{
-  char *mangled_name;
-  void *ptr = 0;
-
-  mangled_name = mangle_data_slot_name (name);
-  if (! mangled_name)
-    goto fail;
-
-  ptr = grub_env_get (mangled_name);
-  grub_free (mangled_name);
-
- fail:
-
-  return ptr;
-}
-
-void
-grub_env_unset_data_slot (const char *name)
-{
-  char *mangled_name;
-
-  mangled_name = mangle_data_slot_name (name);
-  if (! mangled_name)
-    return;
-
-  grub_env_unset (mangled_name);
-  grub_free (mangled_name);
-}
index 9215d55e767f18238252c48126428303a7cf9ecd..b76d2d20e6dbeb6bea2e0fefedec82032020fa2d 100644 (file)
@@ -114,7 +114,6 @@ grub_set_root_dev (void)
   const char *prefix;
 
   grub_register_variable_hook ("root", 0, grub_env_write_root);
-  grub_env_export ("root");
 
   prefix = grub_env_get ("prefix");
 
@@ -164,7 +163,6 @@ grub_main (void)
   /* It is better to set the root device as soon as possible,
      for convenience.  */
   grub_machine_set_prefix ();
-  grub_env_export ("prefix");
   grub_set_root_dev ();
 
   grub_register_core_commands ();
diff --git a/normal/context.c b/normal/context.c
new file mode 100644 (file)
index 0000000..d9ad3b6
--- /dev/null
@@ -0,0 +1,172 @@
+/* env.c - Environment variables */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2005,2006,2007,2008,2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/env.h>
+#include <grub/env_private.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/command.h>
+
+struct menu_pointer
+{
+  grub_menu_t menu;
+  struct menu_pointer *prev;
+};
+
+struct menu_pointer initial_menu;
+struct menu_pointer *current_menu = &initial_menu;
+
+void
+grub_env_unset_menu (void)
+{
+  current_menu->menu = NULL;
+}
+
+grub_menu_t
+grub_env_get_menu (void)
+{
+  return current_menu->menu;
+}
+
+void
+grub_env_set_menu (grub_menu_t nmenu)
+{
+  current_menu->menu = nmenu;
+}
+
+grub_err_t
+grub_env_context_open (int export)
+{
+  struct grub_env_context *context;
+  int i;
+  struct menu_pointer *menu;
+
+  context = grub_zalloc (sizeof (*context));
+  if (! context)
+    return grub_errno;
+  menu = grub_zalloc (sizeof (*menu));
+  if (! menu)
+    return grub_errno;
+
+  context->prev = grub_current_context;
+  grub_current_context = context;
+
+  menu->prev = current_menu;
+  current_menu = menu;
+
+  /* Copy exported variables.  */
+  for (i = 0; i < HASHSZ; i++)
+    {
+      struct grub_env_var *var;
+
+      for (var = context->prev->vars[i]; var; var = var->next)
+       {
+         if (export && var->global)
+           {
+             if (grub_env_set (var->name, var->value) != GRUB_ERR_NONE)
+               {
+                 grub_env_context_close ();
+                 return grub_errno;
+               }
+             grub_register_variable_hook (var->name, var->read_hook, var->write_hook);
+           }
+       }
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_env_context_close (void)
+{
+  struct grub_env_context *context;
+  int i;
+  struct menu_pointer *menu;
+
+  if (! grub_current_context->prev)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                      "cannot close the initial context");
+
+  /* Free the variables associated with this context.  */
+  for (i = 0; i < HASHSZ; i++)
+    {
+      struct grub_env_var *p, *q;
+
+      for (p = grub_current_context->vars[i]; p; p = q)
+       {
+         q = p->next;
+          grub_free (p->name);
+         grub_free (p->value);
+         grub_free (p);
+       }
+    }
+
+  /* Restore the previous context.  */
+  context = grub_current_context->prev;
+  grub_free (grub_current_context);
+  grub_current_context = context;
+
+  menu = current_menu->prev;
+  grub_free (current_menu);
+  current_menu = menu;
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_env_export (const char *name)
+{
+  struct grub_env_var *var;
+
+  var = grub_env_find (name);
+  if (var)
+    var->global = 1;
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_command_t export_cmd;
+
+static grub_err_t
+grub_cmd_export (struct grub_command *cmd __attribute__ ((unused)),
+                int argc, char **args)
+{
+  if (argc < 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                      "no environment variable specified");
+
+  grub_env_export (args[0]);
+  return 0;
+}
+
+void
+grub_context_init (void)
+{
+  grub_env_export ("root");
+  grub_env_export ("prefix");
+
+  export_cmd = grub_register_command ("export", grub_cmd_export,
+                                     "export ENVVAR", "Export a variable.");
+}
+
+void
+grub_context_fini (void)
+{
+  grub_unregister_command (export_cmd);
+}
index f080a69713e8dfada5f65cb1dea5536d8415eb20..52581613a3e02d43b5566bb79120c4fb3a33f5d0 100644 (file)
@@ -133,7 +133,7 @@ free_menu (grub_menu_t menu)
     }
 
   grub_free (menu);
-  grub_env_unset_data_slot ("menu");
+  grub_env_unset_menu ();
 }
 
 static void
@@ -174,7 +174,7 @@ grub_normal_add_menu_entry (int argc, const char **args,
     return grub_errno;
   classes_tail = classes_head;
 
-  menu = grub_env_get_data_slot ("menu");
+  menu = grub_env_get_menu ();
   if (! menu)
     return grub_error (GRUB_ERR_MENU, "no menu context");
 
@@ -357,14 +357,14 @@ read_config_file (const char *config)
 
   grub_menu_t newmenu;
 
-  newmenu = grub_env_get_data_slot ("menu");
+  newmenu = grub_env_get_menu ();
   if (! newmenu)
     {
       newmenu = grub_zalloc (sizeof (*newmenu));
       if (! newmenu)
        return 0;
 
-      grub_env_set_data_slot ("menu", newmenu);
+      grub_env_set_menu (newmenu);
     }
 
   /* Try to open the config file.  */
@@ -562,6 +562,8 @@ grub_env_write_pager (struct grub_env_var *var __attribute__ ((unused)),
 
 GRUB_MOD_INIT(normal)
 {
+  grub_context_init ();
+
   /* Normal mode shouldn't be unloaded.  */
   if (mod)
     grub_dl_ref (mod);
@@ -589,6 +591,8 @@ GRUB_MOD_INIT(normal)
 
 GRUB_MOD_FINI(normal)
 {
+  grub_context_fini ();
+
   grub_set_history (0);
   grub_reader_unregister (&grub_normal_reader);
   grub_register_variable_hook ("pager", 0, 0);