#!/usr/bin/env perl
#-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-

# Boot manager configurator. Designed to be architecture and distribution independent.
#
# Copyright (C) 2000-2001 Ximian, Inc.
#
# Authors: Tambet Ingo <tambet@ximian.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Library General Public License as published
# by the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program 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 Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.

# Best viewed with 100 columns of width.

# Configuration files affected:
#
# /etc/lilo.conf

# Running programs affected:
#
# /sbin/lilo


require "/usr/share/ximian-setup-tools/scripts/general.pl";
require "/usr/share/ximian-setup-tools/scripts/platform.pl";
require "/usr/share/ximian-setup-tools/scripts/util.pl";
require "/usr/share/ximian-setup-tools/scripts/file.pl";
require "/usr/share/ximian-setup-tools/scripts/xml.pl";
require "/usr/share/ximian-setup-tools/scripts/parse.pl";
require "/usr/share/ximian-setup-tools/scripts/boot.pl";


# --- Tool information --- #

$name = "boot";
$version = "0.1.0";
@platforms = ("redhat-5.2", "redhat-6.0", "redhat-6.1", "redhat-6.2", "redhat-7.0");

$description =<<"end_of_description;";
       Configures Boot manager (Only LILO at the moment).
end_of_description;


# Find the tools

$tool_lilo = &xst_locate_tool ("lilo");


# --- XML parsing ---

# Scan XML from standard input to an internal tree.


sub xml_parse
{
  my $tree, %hash;
  # Scan XML to tree.

  $tree = &xst_xml_scan;

  # Walk the tree recursively and extract configuration parameters.
  # This is the top level - find and enter the "boot" tag.

  while (@$tree)
  {
    if ($$tree[0] eq "boot") { &xml_parse_boot ($$tree[1], \%hash); }

    shift @$tree;
    shift @$tree;
  }

  return(\%hash);
}


sub xml_parse_boot
{
  my $tree = $_[0];
  my $hash = $_[1];
  my @images;

  shift @$tree;  # Skip attributes.

  while (@$tree)
  {
    if    ($$tree[0] eq "prompt") { $$hash{"prompt"} = &xst_xml_get_word ($$tree[1]); }
    elsif ($$tree[0] eq "lba32") { $$hash{"lba32"} = &xst_xml_get_word ($$tree[1]); }
    elsif ($$tree[0] eq "root") { $$hash{"root"} = &xst_xml_get_word ($$tree[1]); }
    elsif ($$tree[0] eq "delay") { $$hash{"delay"} = &xst_xml_get_word ($$tree[1]); }
    elsif ($$tree[0] eq "timeout") { $$hash{"timeout"} = &xst_xml_get_word ($$tree[1]); }
    elsif ($$tree[0] eq "default") { $$hash{"default"} = &xst_xml_get_word ($$tree[1]); }
    elsif ($$tree[0] eq "append") { $$hash{"append"} = &xst_xml_get_text ($$tree[1]); }
    elsif ($$tree[0] eq "boot") { $$hash{"boot"} = &xst_xml_get_word ($$tree[1]); }
    elsif ($$tree[0] eq "map") { $$hash{"map"} = &xst_xml_get_word ($$tree[1]); }
    elsif ($$tree[0] eq "install") { $$hash{"install"} = &xst_xml_get_word ($$tree[1]); }

    elsif ($$tree[0] eq "entry") { &xml_parse_image ($$tree[1], \@images); }

    shift @$tree;
    shift @$tree;
  }

  $$hash{"images"} = \@images; # unless scalar keys %image == 0;
}


sub xml_parse_image
{
  my $tree = $_[0];
  my $image = $_[1];
  my %hash;
  my $buf;

  shift @$tree;

  while (@$tree)
  {
    $hash{$$tree[0]} = &xst_xml_get_text ($$tree[1]);

    shift @$tree;
    shift @$tree;
  }

  push @$image, \%hash;
}
		   

# --- XML printing --- #
sub xml_print_global_kws
{
  my $h = $_[0];
  my @tags = ('prompt', 'lba32', 'compact', 'linear', 'lock');
  my $i;

  while ($i = shift @tags)
  {
    &xst_xml_print ("<$i/>\n") if exists $$h{$i};
  }
}


sub xml_print_globals
{
  my $h = $_[0];
  my @tags = ('boot', 'default', 'delay', 'install', 'map', 'message', 'timeout', 'verbose',
              'append', 'root');
  
  my $i, $val;

  while ($i = shift @tags)
  {
    $val = &xst_xml_quote ($$h{$i});

    &xst_xml_print ("<$i>$val</$i>\n") if (exists $$h{$i});
  }
}


sub xml_print_images
{
  my ($h, $image) = @_;
  my $i, $val, $array;

  $array = $$h{$image};

  foreach $entry (@$array)
  {
    &xst_xml_vspace ();
    &xst_xml_print ("<entry>\n");
    &xst_xml_enter ();
    
    foreach $i (keys %$entry)
    {
      $val = &xst_xml_quote ($$entry{$i});

      if ($val eq "") { &xst_xml_print ("<$i/>\n"); }
      else { &xst_xml_print ("<$i>$val</$i>\n"); }
    }
    
    &xst_xml_leave ();
    &xst_xml_print ("</entry>\n");
  }
  
  &xst_xml_vspace ();
}


sub xml_print
{
  my $h = $_[0];
  
  print "<?xml version='1.0' encoding='ISO-8859-1' standalone='yes'?>\n";
  print "<!DOCTYPE boot []>\n\n";
  print "<boot>\n";
  &xst_xml_vspace ();
  &xst_xml_enter ();

  &xst_xml_vspace ();
  &xst_xml_print ("<!-- Configuration starts here -->\n");
  &xst_xml_vspace ();

  &xml_print_global_kws ($h);
  &xml_print_globals ($h);
  &xml_print_images ($h, 'images');
  
  &xst_xml_vspace ();
  &xst_xml_print ("<!-- End of configuration -->\n");
  &xst_xml_vspace ();

  &xst_xml_leave ();
  &xst_xml_print ("</boot>\n");
}
  

# Top-level actions.

sub get
{
  my $hash;

  &xst_begin ();

  # Get information from .conf file
  $hash = &xst_boot_conf_get ();

  &xst_end();
  &xml_print ($hash);
}


# --- Set (write) config --- #


sub set_immediate
{
  if (&xst_run("lilo"))
  {
    &xst_report_warning(3, "Failed to run lilo");
  }
  else
  {
    &xst_report_info(1, "Succesfully executed lilo");
  }
}


sub set
{
  my $hash;
  
  &xst_begin ();

#  $xst_input_file = "aaa";
  $hash = &xml_parse ();

  &xst_boot_conf_set ($hash);

  if ($xst_do_immediate)
  {
    &set_immediate;
  }
  
  &xst_end ();
}


# --- Filter config: XML in, XML out --- #

sub filter
{
  my $hash;
  
  &xst_begin ();
  $hash = &xml_parse ();
  &xst_end ();
  &xml_print ($hash);
}


# --- Main --- #

&xst_init ($name, $version, $description, @ARGV);
&xst_platform_ensure_supported (@platforms);

# Do our thing.

if    ($xst_operation eq "get")    { &get; }
elsif ($xst_operation eq "set")    { &set; }
elsif ($xst_operation eq "filter") { &filter; }
