]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
2006-04-29 Marco Gerards <marco@gnu.org>
authormarco_g <marco_g@localhost>
Sat, 29 Apr 2006 20:29:42 +0000 (20:29 +0000)
committermarco_g <marco_g@localhost>
Sat, 29 Apr 2006 20:29:42 +0000 (20:29 +0000)
* commands/configfile.c (grub_cmd_configfile): Execute the
configfile within its own context.

* include/grub/env.h (grub_env_context_open): New prototype.
(grub_env_context_close): Likewise.

* kern/env.c (grub_env): Removed.
(grub_env_sorted): Likewise.
(grub_env_context): New variable.
(grub_env_var_context): Likewise.
(grub_env_find): Search both the active context and the global
context.
(grub_env_context_open): New function.
(grub_env_context_close): Likewise.
(grub_env_insert): Likewise.
(grub_env_remove): Likewise.
(grub_env_export): Likewise.
(grub_env_set): Changed to use helper functions to avoid code
duplication.
(grub_env_iterate): Rewritten so both the current context and the
global context are being used.

* normal/command.c (export_command): New function.
(grub_command_init): Register the `export' function.

ChangeLog
commands/configfile.c
include/grub/env.h
kern/env.c
normal/command.c

index 5e6cef0a9a5d4197726805f2bc85935e39286641..51398844457c2815e935f4d99e1d6e9a3c5fcee1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+2006-04-29  Marco Gerards  <marco@gnu.org>
+
+       * commands/configfile.c (grub_cmd_configfile): Execute the
+       configfile within its own context.
+
+       * include/grub/env.h (grub_env_context_open): New prototype.
+       (grub_env_context_close): Likewise.
+
+       * kern/env.c (grub_env): Removed.
+       (grub_env_sorted): Likewise.
+       (grub_env_context): New variable.
+       (grub_env_var_context): Likewise.
+       (grub_env_find): Search both the active context and the global
+       context.
+       (grub_env_context_open): New function.
+       (grub_env_context_close): Likewise.
+       (grub_env_insert): Likewise.
+       (grub_env_remove): Likewise.
+       (grub_env_export): Likewise.
+       (grub_env_set): Changed to use helper functions to avoid code
+       duplication.
+       (grub_env_iterate): Rewritten so both the current context and the
+       global context are being used.
+
+       * normal/command.c (export_command): New function.
+       (grub_command_init): Register the `export' function.
+
 2006-04-26  Yoshinori K. Okuji  <okuji@enbug.org>
 
        * util/i386/pc/grub-mkimage.c (compress_kernel): Cast arguments
index 2561cd127a664e76e45e994f9261844dea2be9a1..a411399cddb51de835c805fd7e47a18d3c15654d 100644 (file)
@@ -1,7 +1,7 @@
 /* configfile.c - command to manually load config file  */
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2005  Free Software Foundation, Inc.
+ *  Copyright (C) 2005,2006  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
@@ -33,7 +33,9 @@ grub_cmd_configfile (struct grub_arg_list *state __attribute__ ((unused)),
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
 
   grub_cls ();
+  grub_env_context_open ();
   grub_normal_execute (args[0], 1);
+  grub_env_context_close ();
 
   return 0;
 }
index f687cccb3568ef165fd66a35f3aeec7e925c9546..e554188d98fbead4fb8915d0eea350cb624583ac 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2003,2005  Free Software Foundation, Inc.
+ *  Copyright (C) 2003,2005,2006  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
@@ -50,5 +50,7 @@ void EXPORT_FUNC(grub_env_iterate) (int (* func) (struct grub_env_var *var));
 grub_err_t EXPORT_FUNC(grub_register_variable_hook) (const char *var,
                                                     grub_env_read_hook_t read_hook,
                                                     grub_env_write_hook_t write_hook);
+grub_err_t EXPORT_FUNC(grub_env_context_open) (void);
+grub_err_t EXPORT_FUNC(grub_env_context_close) (void);
 
 #endif /* ! GRUB_ENV_HEADER */
index 29a2121ce02dc24cd0af30d9374d8f008d373a3e..60d2797ac65f96c6298dff777d66f0a7dcc5eacf 100644 (file)
@@ -1,7 +1,7 @@
 /* env.c - Environment variables */
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2003,2005  Free Software Foundation, Inc.
+ *  Copyright (C) 2003,2005,2006  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
 #define        HASHSZ  13
 
 /* A hashtable for quick lookup of variables.  */
-static struct grub_env_var *grub_env[HASHSZ];
+struct grub_env_context
+{
+  struct grub_env_var *vars[HASHSZ];
+  
+  struct grub_env_var *sorted;
+
+  /* One level deeper on the stack.  */
+  struct grub_env_context *next;
+};
+
+/* The global context for environment variables.  */
+static struct grub_env_context grub_env_context;
 
-/* The variables in a sorted list.  */
-static struct grub_env_var *grub_env_sorted;
+/* The nested contexts for regular variables.  */
+static struct grub_env_context *grub_env_var_context = &grub_env_context;
 
 /* Return the hash representation of the string S.  */
 static unsigned int grub_env_hashval (const char *s)
@@ -49,20 +60,139 @@ grub_env_find (const char *name)
   struct grub_env_var *var;
   int idx = grub_env_hashval (name);
 
-  for (var = grub_env[idx]; var; var = var->next)
+  /* Look for the variable in the current context.  */
+  for (var = grub_env_var_context->vars[idx]; var; var = var->next)
     if (! grub_strcmp (var->name, name))
       return var;
+
+  /* Look for the variable in the environment context.  */
+  for (var = grub_env_context.vars[idx]; var; var = var->next)
+    if (! grub_strcmp (var->name, name))
+      return var;
+
   return 0;
 }
 
 grub_err_t
-grub_env_set (const char *var, const char *val)
+grub_env_context_open (void)
 {
-  int idx = grub_env_hashval (var);
+  struct grub_env_context *context;
+  int i;
+
+  context = grub_malloc (sizeof (*context));
+  if (! context)
+    return grub_errno;
+
+  for (i = 0; i < HASHSZ; i++)
+    context->vars[i] = 0;
+  context->next = grub_env_var_context;
+  context->sorted = 0;
+  
+  grub_env_var_context = context;
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_env_context_close (void)
+{
+  struct grub_env_context *context;
   struct grub_env_var *env;
+  struct grub_env_var *prev = 0;
+
+  context = grub_env_var_context->next;
+
+  /* Free the variables associated with this context.  */
+  for (env = grub_env_var_context->sorted; env; env = env->sort_next)
+    {
+      /* XXX: What if a hook is associated with this variable?  */
+      grub_free (prev);
+      prev = env;
+    }
+  grub_free (prev);
+
+  /* Restore the previous context.  */
+  grub_free (grub_env_var_context);
+  grub_env_var_context = context;
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+grub_env_insert (struct grub_env_context *context,
+                struct grub_env_var *env)
+{
+  struct grub_env_var **grub_env = context->vars;  
   struct grub_env_var *sort;
   struct grub_env_var **sortp;
-  
+  int idx = grub_env_hashval (env->name);
+
+  /* Insert it in the hashtable.  */
+  env->prevp = &grub_env[idx];
+  env->next = grub_env[idx];
+  if (grub_env[idx])
+    grub_env[idx]->prevp = &env->next;
+  grub_env[idx] = env;
+
+  /* Insert it in the sorted list.  */
+  sortp = &context->sorted;
+  sort = context->sorted;
+  while (sort)
+    {
+      if (grub_strcmp (sort->name, env->name) > 0)
+       break;
+      
+      sortp = &sort->sort_next;
+      sort = sort->sort_next;
+    }
+  env->sort_prevp = sortp;
+  env->sort_next = sort;
+  if (sort)
+    sort->sort_prevp = &env->sort_next;
+  *sortp = env;
+}
+
+
+static void
+grub_env_remove (struct grub_env_var *env)
+{
+  /* Remove the entry from the variable table.  */
+  *env->prevp = env->next;
+  if (env->next)
+    env->next->prevp = env->prevp;
+
+  /* And from the sorted list.  */
+  *env->sort_prevp = env->sort_next;
+  if (env->sort_next)
+    env->sort_next->sort_prevp = env->sort_prevp;
+}
+
+grub_err_t
+grub_env_export (const char *var)
+{
+  struct grub_env_var *env;
+  int idx = grub_env_hashval (var);
+
+  /* Look for the variable in the current context only.  */
+  for (env = grub_env_var_context->vars[idx]; env; env = env->next)
+    if (! grub_strcmp (env->name, var))
+      {
+       /* Remove the variable from the old context and reinsert it
+          into the environment.  */
+       grub_env_remove (env);
+       grub_env_insert (&grub_env_context, env);
+
+       return GRUB_ERR_NONE;
+      }
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_env_set (const char *var, const char *val)
+{
+  struct grub_env_var *env;
+
   /* If the variable does already exist, just update the variable.  */
   env = grub_env_find (var);
   if (env)
@@ -98,30 +228,8 @@ grub_env_set (const char *var, const char *val)
   env->value = grub_strdup (val);
   if (! env->value)
     goto fail;
-  
-  /* Insert it in the hashtable.  */
-  env->prevp = &grub_env[idx];
-  env->next = grub_env[idx];
-  if (grub_env[idx])
-    grub_env[idx]->prevp = &env->next;
-  grub_env[idx] = env;
-  
-  /* Insert it in the sorted list.  */
-  sortp = &grub_env_sorted;
-  sort = grub_env_sorted;
-  while (sort)
-    {
-      if (grub_strcmp (sort->name, var) > 0)
-       break;
-      
-      sortp = &sort->sort_next;
-      sort = sort->sort_next;
-    }
-  env->sort_prevp = sortp;
-  env->sort_next = sort;
-  if (sort)
-    sort->sort_prevp = &env->sort_next;
-  *sortp = env;
+
+  grub_env_insert (grub_env_var_context, env);
 
   return 0;
 
@@ -160,13 +268,7 @@ grub_env_unset (const char *name)
   if (env->read_hook || env->write_hook)
     return;
 
-  *env->prevp = env->next;
-  if (env->next)
-    env->next->prevp = env->prevp;
-
-  *env->sort_prevp = env->sort_next;
-  if (env->sort_next)
-    env->sort_next->sort_prevp = env->sort_prevp;
+  grub_env_remove (env);
 
   grub_free (env->name);
   grub_free (env->value);
@@ -177,11 +279,32 @@ grub_env_unset (const char *name)
 void
 grub_env_iterate (int (* func) (struct grub_env_var *var))
 {
-  struct grub_env_var *env;
+  struct grub_env_var *env = grub_env_context.sorted;
+  struct grub_env_var *var = grub_env_var_context->sorted;
+
+  /* Initially these are the same.  */
+  if (env == var)
+    var = 0;
   
-  for (env = grub_env_sorted; env; env = env->sort_next)
-    if (func (env))
-      return;
+  while (env || var)
+    {
+      struct grub_env_var **cur;
+
+      /* Select the first name to be printed from the head of two
+        sorted lists.  */
+      if (! env)
+       cur = &var;
+      else if (! var)
+       cur = &env;
+      else if (grub_strcmp (env->name, var->name) > 0)
+       cur = &var;
+      else
+       cur = &env;
+
+      if (func (*cur))
+       return;
+      *cur = (*cur)->sort_next;
+    }
 }
 
 grub_err_t
index 7cfac271aa7d8c959675fa52210e10dae1105fbc..43d1cf09def8deb5e0018270c09f786a4f9e6516 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2003,2005  Free Software Foundation, Inc.
+ *  Copyright (C) 2003,2005,2006  Free Software Foundation, Inc.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -283,6 +283,18 @@ unset_command (struct grub_arg_list *state __attribute__ ((unused)),
   return 0;
 }
 
+static grub_err_t
+export_command (struct grub_arg_list *state __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;
+}
+
 static grub_err_t
 insmod_command (struct grub_arg_list *state __attribute__ ((unused)),
                int argc, char **args)
@@ -367,6 +379,9 @@ grub_command_init (void)
   grub_register_command ("unset", unset_command, GRUB_COMMAND_FLAG_BOTH,
                         "unset ENVVAR", "Remove an environment variable.", 0);
 
+  grub_register_command ("export", export_command, GRUB_COMMAND_FLAG_BOTH,
+                        "export ENVVAR", "Export a variable.", 0);
+
   grub_register_command ("insmod", insmod_command, GRUB_COMMAND_FLAG_BOTH,
                         "insmod MODULE",
                         "Insert a module. The argument can be a file or a module name.",