/* env.c - Environment variables */ /* * VAS_EBOOT -- GRand Unified Bootloader * Copyright (C) 2003,2005,2006,2007,2008,2009 Free Software Foundation, Inc. * * VAS_EBOOT is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * VAS_EBOOT is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with VAS_EBOOT. If not, see . */ #include #include #include #include #include #include #include struct menu_pointer { VasEBoot_menu_t menu; struct menu_pointer *prev; }; static struct menu_pointer initial_menu; static struct menu_pointer *current_menu = &initial_menu; void VasEBoot_env_unset_menu (void) { current_menu->menu = NULL; } VasEBoot_menu_t VasEBoot_env_get_menu (void) { return current_menu->menu; } void VasEBoot_env_set_menu (VasEBoot_menu_t nmenu) { current_menu->menu = nmenu; } static VasEBoot_err_t VasEBoot_env_new_context (int export_all) { struct VasEBoot_env_context *context; int i; struct menu_pointer *menu; context = VasEBoot_zalloc (sizeof (*context)); if (! context) return VasEBoot_errno; menu = VasEBoot_zalloc (sizeof (*menu)); if (! menu) { VasEBoot_free (context); return VasEBoot_errno; } context->prev = VasEBoot_current_context; VasEBoot_current_context = context; menu->prev = current_menu; current_menu = menu; /* Copy exported variables. */ for (i = 0; i < HASHSZ; i++) { struct VasEBoot_env_var *var; for (var = context->prev->vars[i]; var; var = var->next) if (var->global || export_all) { if (VasEBoot_env_set (var->name, var->value) != VAS_EBOOT_ERR_NONE) { VasEBoot_env_context_close (); return VasEBoot_errno; } VasEBoot_env_export (var->name); VasEBoot_register_variable_hook (var->name, var->read_hook, var->write_hook); } } return VAS_EBOOT_ERR_NONE; } VasEBoot_err_t VasEBoot_env_context_open (void) { return VasEBoot_env_new_context (0); } int VasEBoot_extractor_level = 0; VasEBoot_err_t VasEBoot_env_extractor_open (int source) { VasEBoot_extractor_level++; return VasEBoot_env_new_context (source); } VasEBoot_err_t VasEBoot_env_context_close (void) { struct VasEBoot_env_context *context; int i; struct menu_pointer *menu; if (! VasEBoot_current_context->prev) return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, "cannot close the initial context"); /* Free the variables associated with this context. */ for (i = 0; i < HASHSZ; i++) { struct VasEBoot_env_var *p, *q; for (p = VasEBoot_current_context->vars[i]; p; p = q) { q = p->next; VasEBoot_free (p->name); VasEBoot_free (p->value); VasEBoot_free (p); } } /* Restore the previous context. */ context = VasEBoot_current_context->prev; VasEBoot_free (VasEBoot_current_context); VasEBoot_current_context = context; menu = current_menu->prev; if (current_menu->menu) VasEBoot_normal_free_menu (current_menu->menu); VasEBoot_free (current_menu); current_menu = menu; return VAS_EBOOT_ERR_NONE; } VasEBoot_err_t VasEBoot_env_extractor_close (int source) { VasEBoot_menu_t menu = NULL; VasEBoot_menu_entry_t *last; VasEBoot_err_t err; if (source) { menu = VasEBoot_env_get_menu (); VasEBoot_env_unset_menu (); } err = VasEBoot_env_context_close (); if (source && menu) { VasEBoot_menu_t menu2; menu2 = VasEBoot_env_get_menu (); last = &menu2->entry_list; while (*last) last = &(*last)->next; *last = menu->entry_list; menu2->size += menu->size; } VasEBoot_extractor_level--; return err; } static VasEBoot_command_t export_cmd; static VasEBoot_err_t VasEBoot_cmd_export (struct VasEBoot_command *cmd __attribute__ ((unused)), int argc, char **args) { int i; if (argc < 1) return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, N_("one argument expected")); for (i = 0; i < argc; i++) VasEBoot_env_export (args[i]); return 0; } void VasEBoot_context_init (void) { export_cmd = VasEBoot_register_command ("export", VasEBoot_cmd_export, N_("ENVVAR [ENVVAR] ..."), N_("Export variables.")); } void VasEBoot_context_fini (void) { VasEBoot_unregister_command (export_cmd); }