grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Variable context


From: Marco Gerards
Subject: Variable context
Date: Sat, 29 Apr 2006 22:05:14 +0200
User-agent: Gnus/5.1007 (Gnus v5.10.7) Emacs/21.4 (gnu/linux)

Hi,

Here is a patch for making variables dependant on the context.  Now
when the user uses configfile, another context is created.  Like in
bash you can make variables global by using `export'.

--
Marco


2006-04-29  Marco Gerards  <address@hidden>

        * 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.
        (grub_env_init): 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_init): 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.

        * kern/i386/pc/init.c (grub_machine_init): Call `grub_env_init'.

        * kern/powerpc/ieee1275/init.c (grub_machine_init): Likewise.

        * kern/sparc64/ieee1275/init.c (grub_machine_init): Likewise.

        * util/grub-emu.c (grub_machine_init): Likewise.

        * kern/efi/init.c (grub_efi_init): Likewise.

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


Index: commands/configfile.c
===================================================================
RCS file: /sources/grub/grub2/commands/configfile.c,v
retrieving revision 1.3
diff -u -p -u -p -r1.3 configfile.c
--- commands/configfile.c       13 Nov 2005 15:47:08 -0000      1.3
+++ commands/configfile.c       29 Apr 2006 20:02:17 -0000
@@ -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_lis
     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: include/grub/env.h
===================================================================
RCS file: /sources/grub/grub2/include/grub/env.h,v
retrieving revision 1.3
diff -u -p -u -p -r1.3 env.h
--- include/grub/env.h  20 Jul 2005 20:30:45 -0000      1.3
+++ include/grub/env.h  29 Apr 2006 20:02:17 -0000
@@ -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,8 @@ void EXPORT_FUNC(grub_env_iterate) (int 
 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);
+grub_err_t EXPORT_FUNC(grub_env_init) (void);
 
 #endif /* ! GRUB_ENV_HEADER */
Index: kern/env.c
===================================================================
RCS file: /sources/grub/grub2/kern/env.c,v
retrieving revision 1.5
diff -u -p -u -p -r1.5 env.c
--- kern/env.c  25 Dec 2005 17:21:52 -0000      1.5
+++ kern/env.c  29 Apr 2006 20:02:17 -0000
@@ -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
@@ -26,10 +26,21 @@
 #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;
 
 /* Return the hash representation of the string S.  */
 static unsigned int grub_env_hashval (const char *s)
@@ -49,20 +60,155 @@ 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;
+}
+
+grub_err_t
+grub_env_init (void)
+{
+  grub_err_t err;
+
+  /* Create the hashtable for the environment variables.  */
+  err = grub_env_context_open ();
+  if (err)
+    return err;
+
+  /* Use this one for environment variables only.  */
+  grub_env_context = grub_env_var_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 +244,8 @@ grub_env_set (const char *var, const cha
   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 +284,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 +295,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: kern/efi/init.c
===================================================================
RCS file: /sources/grub/grub2/kern/efi/init.c,v
retrieving revision 1.3
diff -u -p -u -p -r1.3 init.c
--- kern/efi/init.c     25 Apr 2006 20:08:31 -0000      1.3
+++ kern/efi/init.c     29 Apr 2006 20:02:17 -0000
@@ -38,6 +38,8 @@ grub_efi_init (void)
   /* Initialize the memory management system.  */
   grub_efi_mm_init ();
 
+  grub_env_init ();
+
   grub_efidisk_init ();
 }
 
Index: kern/i386/pc/init.c
===================================================================
RCS file: /sources/grub/grub2/kern/i386/pc/init.c,v
retrieving revision 1.12
diff -u -p -u -p -r1.12 init.c
--- kern/i386/pc/init.c 25 Apr 2006 20:08:31 -0000      1.12
+++ kern/i386/pc/init.c 29 Apr 2006 20:02:17 -0000
@@ -1,6 +1,6 @@
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
+ *  Copyright (C) 2002, 2003, 2004, 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
@@ -226,6 +226,8 @@ grub_machine_init (void)
   
   /* The memory system was initialized, thus register built-in devices.  */
   grub_biosdisk_init ();
+
+  grub_env_init ();
 }
 
 void
Index: kern/powerpc/ieee1275/init.c
===================================================================
RCS file: /sources/grub/grub2/kern/powerpc/ieee1275/init.c,v
retrieving revision 1.25
diff -u -p -u -p -r1.25 init.c
--- kern/powerpc/ieee1275/init.c        26 Apr 2006 02:20:12 -0000      1.25
+++ kern/powerpc/ieee1275/init.c        29 Apr 2006 20:02:17 -0000
@@ -1,7 +1,7 @@
 /*  init.c -- Initialize GRUB on the newworld mac (PPC).  */
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+ *  Copyright (C) 2003, 2004, 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
@@ -134,6 +134,8 @@ grub_machine_init (void)
     }
   grub_mm_init_region ((void *) grub_heap_start, grub_heap_len);
 
+  grub_env_init ();
+
   grub_ofdisk_init ();
 
   /* Process commandline.  */
Index: kern/sparc64/ieee1275/init.c
===================================================================
RCS file: /sources/grub/grub2/kern/sparc64/ieee1275/init.c,v
retrieving revision 1.2
diff -u -p -u -p -r1.2 init.c
--- kern/sparc64/ieee1275/init.c        25 Apr 2006 20:08:31 -0000      1.2
+++ kern/sparc64/ieee1275/init.c        29 Apr 2006 20:02:17 -0000
@@ -1,7 +1,7 @@
 /*  init.c -- Initialize GRUB on the Ultra Sprac (sparc64).  */
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+ *  Copyright (C) 2003, 2004, 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
@@ -156,6 +156,8 @@ grub_machine_init (void)
                   grub_heap_len);
   grub_mm_init_region ((void *) grub_heap_start, grub_heap_len);
 
+  grub_env_init ();
+
   grub_ofdisk_init ();
 
   /* Process commandline.  */
Index: normal/command.c
===================================================================
RCS file: /sources/grub/grub2/normal/command.c,v
retrieving revision 1.16
diff -u -p -u -p -r1.16 command.c
--- normal/command.c    16 Apr 2006 18:02:42 -0000      1.16
+++ normal/command.c    29 Apr 2006 20:02:17 -0000
@@ -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
@@ -284,6 +284,18 @@ unset_command (struct grub_arg_list *sta
 }
 
 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.",
Index: util/grub-emu.c
===================================================================
RCS file: /sources/grub/grub2/util/grub-emu.c,v
retrieving revision 1.29
diff -u -p -u -p -r1.29 grub-emu.c
--- util/grub-emu.c     26 Apr 2006 21:58:36 -0000      1.29
+++ util/grub-emu.c     29 Apr 2006 20:02:17 -0000
@@ -83,6 +83,7 @@ void
 grub_machine_init (void)
 {
   signal (SIGINT, SIG_IGN);
+  grub_env_init ();
   grub_console_init ();
 }
 





reply via email to

[Prev in Thread] Current Thread [Next in Thread]