1 /* env.c - Environment variables */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2003,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
21 #include <grub/env_private.h>
22 #include <grub/misc.h>
25 /* The initial context. */
26 static struct grub_env_context initial_context
;
28 /* The current context. */
29 struct grub_env_context
*grub_current_context
= &initial_context
;
31 /* Return the hash representation of the string S. */
33 grub_env_hashval (const char *s
)
37 /* XXX: This can be done much more efficiently. */
44 static struct grub_env_var
*
45 grub_env_find (const char *name
)
47 struct grub_env_var
*var
;
48 int idx
= grub_env_hashval (name
);
50 /* Look for the variable in the current context. */
51 for (var
= grub_current_context
->vars
[idx
]; var
; var
= var
->next
)
52 if (grub_strcmp (var
->name
, name
) == 0)
59 grub_env_insert (struct grub_env_context
*context
,
60 struct grub_env_var
*var
)
62 int idx
= grub_env_hashval (var
->name
);
64 /* Insert the variable into the hashtable. */
65 var
->prevp
= &context
->vars
[idx
];
66 var
->next
= context
->vars
[idx
];
68 var
->next
->prevp
= &(var
->next
);
69 context
->vars
[idx
] = var
;
73 grub_env_remove (struct grub_env_var
*var
)
75 /* Remove the entry from the variable table. */
76 *var
->prevp
= var
->next
;
78 var
->next
->prevp
= var
->prevp
;
82 grub_env_set (const char *name
, const char *val
)
84 struct grub_env_var
*var
;
86 /* If the variable does already exist, just update the variable. */
87 var
= grub_env_find (name
);
90 char *old
= var
->value
;
93 var
->value
= var
->write_hook (var
, val
);
95 var
->value
= grub_strdup (val
);
104 return GRUB_ERR_NONE
;
107 /* The variable does not exist, so create a new one. */
108 var
= grub_zalloc (sizeof (*var
));
112 var
->name
= grub_strdup (name
);
116 var
->value
= grub_strdup (val
);
120 grub_env_insert (grub_current_context
, var
);
122 return GRUB_ERR_NONE
;
125 grub_free (var
->name
);
126 grub_free (var
->value
);
133 grub_env_get (const char *name
)
135 struct grub_env_var
*var
;
137 var
= grub_env_find (name
);
142 return var
->read_hook (var
, var
->value
);
148 grub_env_unset (const char *name
)
150 struct grub_env_var
*var
;
152 var
= grub_env_find (name
);
156 if (var
->read_hook
|| var
->write_hook
)
158 grub_env_set (name
, "");
162 grub_env_remove (var
);
164 grub_free (var
->name
);
165 grub_free (var
->value
);
169 struct grub_env_var
*
170 grub_env_update_get_sorted (void)
172 struct grub_env_var
*sorted_list
= 0;
175 /* Add variables associated with this context into a sorted list. */
176 for (i
= 0; i
< HASHSZ
; i
++)
178 struct grub_env_var
*var
;
180 for (var
= grub_current_context
->vars
[i
]; var
; var
= var
->next
)
182 struct grub_env_var
*p
, **q
;
184 for (q
= &sorted_list
, p
= *q
; p
; q
= &((*q
)->sorted_next
), p
= *q
)
186 if (grub_strcmp (p
->name
, var
->name
) > 0)
190 var
->sorted_next
= *q
;
199 grub_register_variable_hook (const char *name
,
200 grub_env_read_hook_t read_hook
,
201 grub_env_write_hook_t write_hook
)
203 struct grub_env_var
*var
= grub_env_find (name
);
207 if (grub_env_set (name
, "") != GRUB_ERR_NONE
)
210 var
= grub_env_find (name
);
211 /* XXX Insert an assertion? */
214 var
->read_hook
= read_hook
;
215 var
->write_hook
= write_hook
;
217 return GRUB_ERR_NONE
;
221 grub_env_export (const char *name
)
223 struct grub_env_var
*var
;
225 var
= grub_env_find (name
);
230 err
= grub_env_set (name
, "");
233 var
= grub_env_find (name
);
237 return GRUB_ERR_NONE
;