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 <[EMAIL PROTECTED]> * 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 (); } _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel