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

# Dhcpd server configurator. 
#
# Copyright (C) 2001 Ximian, Inc.
#
# Authors: Chema Celorio <chema@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.


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/dhcpd.pl$DOTIN";
}


# --- Tool information --- #
$name = "dhcpd";
$version = "1.4.2";
@platforms = ("redhat-7.0", "redhat-7.1");

$description =<<"end_of_description;";
       Configure dhcp server parameters
end_of_description;

# --- XML parsing --- #

# Scan XML from standard input to an internaltree.
sub xml_parse
{
  my ($file) = @_;
  my ($tree, %hash, $elem);
  my (%subnets);
  
  # Scan XML to tree.

  $tree = &gst_xml_scan ($file);

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

  while ($elem = shift @$tree)
  {
      if   ($elem eq "dhcpd") { &xml_parse_dhcpd (shift @$tree, \%hash); }
      else { &gst_report ("xml_unexp_tag", $elem); shift @$tree; }
  }

  return (\%hash);
}

sub xml_parse_dhcpd
{
  my ($tree, $hash) = @_;
  my ($elem, %subnets);
    
  shift @$tree;  # Skip attributes.
  
  while ($elem = shift @$tree)
  {
    if    ($elem eq "installed")    { $$hash{"installed"}  = &gst_xml_get_pcdata (shift @$tree); }
    elsif ($elem eq "configured")   { $$hash{"configured"} = &gst_xml_get_pcdata (shift @$tree); }
    elsif ($elem eq "active")       { $$hash{"active"}     = &gst_xml_get_pcdata (shift @$tree); }
    elsif ($elem eq "subnet")       { &gst_dhcpd_xml_parse_subnet (shift @$tree, \%subnets); }
    else  { &gst_report ("xml_unexp_tag", $elem); shift @$tree; }
  }

  $$hash{"subnets"} = \%subnets unless scalar keys %subnets == 0;
}

# --- XML printing --- #
sub gst_dhcpd_print_subnet
{
    my ($h) = @_;
    my %ranges, %hosts;
    my $range, $hosts;

    &gst_xml_container_enter ("subnet");

    # Options
    &gst_xml_print_hash ($$h{"options"});
    &gst_xml_print_vspace ();

    # Ranges
    &gst_xml_print_hash_hash ($$h{"ranges"}, "range");
    &gst_xml_print_vspace ();
    
    # Hosts
    &gst_xml_print_hash_hash ($$h{"hosts"}, "host");
    &gst_xml_print_vspace ();
    
    &gst_xml_container_leave ("subnet");

    return;
}

sub xml_print
{
  my ($h) = @_;
  my %subnets;
  my $subnet;
  my @scalar_keys = qw(installed active);

  &gst_xml_print_begin ();

  &gst_xml_print_scalars ($h, @scalar_keys);
  &gst_xml_print_vspace ();
  
  $subnets = $$h{"subnets"};
  foreach $subnet (keys %$subnets) {
      &gst_dhcpd_print_subnet ($$subnets{$subnet});
      &gst_xml_print_vspace ();
  }
  
  &gst_xml_print_end ();
  
}

# Main operations
sub get
{
  my $hash;

  $hash = &gst_dhcpd_conf_get ();

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


sub set
{
    my $hash;
    my $res;
    
    $hash = &xml_parse ();
    $res = &gst_dhcpd_conf_set ($hash);
    &gst_report_end ();

    if ($res eq -1) {
        printf STDERR "An error ocurred while setting configuration\n";
        printf STDERR "Implement error reporting while setting, (or find it)\n";
    }
}


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

  $hash = &xml_parse ();
  &gst_report_end ();
  &xml_print ($hash);
}

# --- Main --- #

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

$directives = {
  "get"            => [ \&get,    [], "" ],
  "set"            => [ \&set,    [], "" ]
    };

$tool = &gst_init ($name, $version, $description, $directives, @ARGV);
&gst_platform_ensure_supported ($tool, @platforms);
&gst_run ($tool);

