From: Marco Gerards <mgerards@xs4all.nl>
To: The development of GRUB <grub-devel@gnu.org>
Subject: Variable context
Date: Sat, 29 Apr 2006 22:05:14 +0200 [thread overview]
Message-ID: <87d5f0i1vp.fsf@xs4all.nl> (raw)
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 <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.
(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 ();
}
next reply other threads:[~2006-04-29 20:03 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-04-29 20:05 Marco Gerards [this message]
2006-04-30 21:10 ` Variable context Marco Gerards
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87d5f0i1vp.fsf@xs4all.nl \
--to=mgerards@xs4all.nl \
--cc=grub-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.