#!/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>
#          Arturo Espinosa <arturo@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

# Distros 
#
# RedHat 7.1   - LILO version 21.4-4
# Mandrake 7.1 - LILO version 21.4-3
# Turbolinux 7.0 - LILO version 21.7.4-4
#
#
#

BEGIN {
  $SCRIPTSDIR = "/usr/share/setup-tool-backends/scripts";
  if ($SCRIPTSDIR =~ /^___scriptsdir__[_]/)
  {
      $SCRIPTSDIR = ".";
      $DOTIN = ".in";
  }
  
  require "$SCRIPTSDIR/general.pl$DOTIN";
  require "$SCRIPTSDIR/platform.pl$DOTIN";
  require "$SCRIPTSDIR/util.pl$DOTIN";
  require "$SCRIPTSDIR/file.pl$DOTIN";
  require "$SCRIPTSDIR/xml.pl$DOTIN";
  require "$SCRIPTSDIR/parse.pl$DOTIN";
  require "$SCRIPTSDIR/boot.pl$DOTIN";
  require "$SCRIPTSDIR/boot-lilo.pl$DOTIN";
  require "$SCRIPTSDIR/boot-grub.pl$DOTIN";
}


# --- Tool information --- #

$name = "boot";
$version = "0.11.0";
@platforms = ("redhat-5.2", "redhat-6.0", "redhat-6.1", "redhat-6.2", "redhat-7.0",
              "redhat-7.1", "redhat-7.2",

              "mandrake-7.1", "mandrake-7.2",

              "debian-2.2", "debian-woody",
              
              "suse-7.0", "turbolinux-7.0");

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


# Find the tools

$tool_lilo = &xst_file_locate_tool ("lilo");


# --- XML parsing ---

# Scan XML from standard input to an internal tree.


sub xml_parse
{
  my ($tree, %hash, $elem);
  # 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 ($elem = shift @$tree)
  {
    if ($elem eq "boot") { &xml_parse_boot (shift @$tree, \%hash); }
    else { &xst_report ("xml_unexp_tag", $elem); shift @$tree; }
  }

  return(\%hash);
}


sub xml_parse_boot
{
  my ($tree, $hash) = @_;
  my (@entries, $elem);

  shift @$tree;  # Skip attributes.

  $$hash{"timeout"} = -1;

  while ($elem = shift @$tree)
  {
    if    ($elem eq "prompt")    { $$hash{"prompt"}    = &xst_xml_get_pcdata (shift @$tree); }
    elsif ($elem eq "root")      { $$hash{"root"}      = &xst_xml_get_pcdata (shift @$tree); }
    elsif ($elem eq "timeout")   { $$hash{"timeout"}   = &xst_xml_get_pcdata (shift @$tree); }
    elsif ($elem eq "default")   { $$hash{"default"}   = &xst_xml_get_pcdata (shift @$tree); }
    elsif ($elem eq "append")    { $$hash{"append"}    = &xst_xml_get_pcdata (shift @$tree); }
    elsif ($elem eq "pixmap")    { $$hash{"pixmap"}    = &xst_xml_get_pcdata (shift @$tree); }
    elsif ($elem eq "pixmapsup") { $$hash{"pixmapsup"} = &xst_xml_get_pcdata (shift @$tree); }
    elsif ($elem eq "entry")     { &xml_parse_entry (shift @$tree, \@entries); }
    elsif ($elem eq "partition") { shift @$tree; } # Just skip it.
    else { &xst_report ("xml_unexp_tag", $elem); shift @$tree; }
  }

  $$hash{"entry"} = \@entries unless scalar @entries == 0;
}


sub xml_parse_entry
{
  my ($tree, $entries) = @_;
  my (%hash, $buf);

  shift @$tree;

  while ($elem = shift @$tree)
  {
    $hash{$elem} = &xst_xml_get_pcdata (shift @$tree);
  }

  push @$entries, \%hash;
}
		   

# --- XML printing --- #

sub xml_print
{
  my ($h) = @_;
  my @scalars = qw(default timeout pixmap pixmapsup prompt);

  &xst_xml_print_begin ();

  &xst_xml_print_hash_hash ($$h{"partition"}, "partition");
  &xst_xml_print_vspace ();
  &xst_xml_print_scalars ($h, @scalars);
  &xst_xml_print_structure ($$h{"entry"}, "entry");

  &xst_xml_print_end ();
}
  

# Top-level actions.
sub get
{
  my ($hash);

  $hash = &xst_boot_conf_get ();
  &xst_boot_fix ($hash);
  
  &xst_report_end ();
  &xml_print ($hash);
}


# --- Set (write) config --- #
sub set
{
  my ($hash);

  $hash = &xml_parse ();

  if ($hash)
  {
    &xst_boot_fix ($hash);
    &xst_boot_conf_set ($hash);
    &xst_file_run ($tool_lilo);
  }
  else
  {
    # TODO: report error.
    1;
  }
  
  &xst_report_end ();
}


# --- Filter config: XML in, XML out --- #
sub filter
{
  my $hash = &xml_parse;

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

sub verify_print
{
  my ($res) = @_;

  &xst_xml_print_begin ("verify");
  &xst_xml_print_structure ($res, "result");
  &xst_xml_print_end ("verify");
}

sub verify
{
  my ($tool, $key, @values) = @_;
  my ($i, $proc, $res, $loader);

  my %bootloader =
      (
       "lilo" => \&xst_boot_lilo_verify,
       "grub" => \&xst_boot_grub_verify
       );

  my %dist_map =
      (
       "lilo" => ["redhat-6.0", "redhat-6.1", "redhat-6.2" , "redhat-7.0", "redhat-7.1",
                  "mandrake-7.1", "debian-2.2", "debian-woody", "suse-7.0", "turbolinux-7.0"],
       "grub" => ["redhat-7.2", "mandrake-7.2"]
       );
  
  foreach $i (keys %dist_map)
  {
    $loader = $i if &xst_item_is_in_list ($$tool{"platform"}, @{$dist_map{$i}});
  }

  if ($loader eq undef)
  {
    &xst_report ("platform_no_table", $$tool{"platform"});
    &xst_report_end ();
  }
  else
  {
    $proc = $bootloader{$loader};
    $res = &$proc ($key, @values);
    &xst_report_end ();
    &verify_print ($res);
  }
}


# --- Main --- #

# get, set and filter are special cases that don't need more parameters than a ref to their function.
# Read general.pl.in:xst_run_directive to know about the format of this hash.

$directives = {
  "get"    => [ \&get,    [], "" ],
  "set"    => [ \&set,    [], "" ],
  "filter" => [ \&filter, [], "" ],
  "verify" => [ \&verify, [ "type", "value", "xtravalues*" ], "Verifies the values, depending on the type." ]
    };

$tool = &xst_init ($name, $version, $description, $directives, @ARGV);
&xst_platform_ensure_supported ($tool, @platforms);
&xst_run ($tool);
