/* env.c - Environment variables */
/*
 *  GRUB  --  GRand Unified Bootloader
 *  Copyright (C) 2003,2005,2006,2007,2008,2009  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
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <grub/env.h>
#include <grub/env_private.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/command.h>
#include <grub/normal.h>
#include <grub/i18n.h>

struct menu_pointer
{
  grub_menu_t menu;
  struct menu_pointer *prev;
};

static struct menu_pointer initial_menu;
static struct menu_pointer *current_menu = &initial_menu;

void
grub_env_unset_menu (void)
{
  current_menu->menu = NULL;
}

grub_menu_t
grub_env_get_menu (void)
{
  return current_menu->menu;
}

void
grub_env_set_menu (grub_menu_t nmenu)
{
  current_menu->menu = nmenu;
}

static grub_err_t
grub_env_new_context (int export_all)
{
  struct grub_env_context *context;
  int i;
  struct menu_pointer *menu;

  context = grub_zalloc (sizeof (*context));
  if (! context)
    return grub_errno;
  menu = grub_zalloc (sizeof (*menu));
  if (! menu)
    {
      grub_free (context);
      return grub_errno;
    }

  context->prev = grub_current_context;
  grub_current_context = context;

  menu->prev = current_menu;
  current_menu = menu;

  /* Copy exported variables.  */
  for (i = 0; i < HASHSZ; i++)
    {
      struct grub_env_var *var;

      for (var = context->prev->vars[i]; var; var = var->next)
	if (var->global || export_all)
	  {
	    if (grub_env_set (var->name, var->value) != GRUB_ERR_NONE)
	      {
		grub_env_context_close ();
		return grub_errno;
	      }
	    grub_env_export (var->name);
	    grub_register_variable_hook (var->name, var->read_hook, var->write_hook);
	  }
    }

  return GRUB_ERR_NONE;
}

grub_err_t
grub_env_context_open (void)
{
  return grub_env_new_context (0);
}

int grub_extractor_level = 0;

grub_err_t
grub_env_extractor_open (int source)
{
  grub_extractor_level++;
  return grub_env_new_context (source);
}

grub_err_t
grub_env_context_close (void)
{
  struct grub_env_context *context;
  int i;
  struct menu_pointer *menu;

  if (! grub_current_context->prev)
    return grub_error (GRUB_ERR_BAD_ARGUMENT,
		       "cannot close the initial context");

  /* Free the variables associated with this context.  */
  for (i = 0; i < HASHSZ; i++)
    {
      struct grub_env_var *p, *q;

      for (p = grub_current_context->vars[i]; p; p = q)
	{
	  q = p->next;
          grub_free (p->name);
	  grub_free (p->value);
	  grub_free (p);
	}
    }

  /* Restore the previous context.  */
  context = grub_current_context->prev;
  grub_free (grub_current_context);
  grub_current_context = context;

  menu = current_menu->prev;
  if (current_menu->menu)
    grub_normal_free_menu (current_menu->menu);
  grub_free (current_menu);
  current_menu = menu;

  return GRUB_ERR_NONE;
}

grub_err_t
grub_env_extractor_close (int source)
{
  grub_menu_t menu = NULL;
  grub_menu_entry_t *last;
  grub_err_t err;

  if (source)
    {
      menu = grub_env_get_menu ();
      grub_env_unset_menu ();
    }
  err = grub_env_context_close ();

  if (source && menu)
    {
      grub_menu_t menu2;
      menu2 = grub_env_get_menu ();
      
      last = &menu2->entry_list;
      while (*last)
	last = &(*last)->next;
      
      *last = menu->entry_list;
      menu2->size += menu->size;
    }

  grub_extractor_level--;
  return err;
}

static grub_command_t export_cmd;

static grub_err_t
grub_cmd_export (struct grub_command *cmd __attribute__ ((unused)),
		 int argc, char **args)
{
  int i;

  if (argc < 1)
    return grub_error (GRUB_ERR_BAD_ARGUMENT,
		       N_("one argument expected"));

  for (i = 0; i < argc; i++)
    grub_env_export (args[i]);

  return 0;
}

void
grub_context_init (void)
{
  export_cmd = grub_register_command ("export", grub_cmd_export,
				      N_("ENVVAR [ENVVAR] ..."),
				      N_("Export variables."));
}

void
grub_context_fini (void)
{
  grub_unregister_command (export_cmd);
}
