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

# SysV services configurator. Designed to be architecture- and distribution independent.
#
# Copyright (C) 2000-2001 Ximian, Inc.
#
# Authors: Arturo Espinosa Aldama <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.

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/service.pl$DOTIN";
  require "$SCRIPTSDIR/print.pl$DOTIN";
}


# --- Tool information --- #

$name = "sysv";
$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 which services are to be started or stopped at which runlevels
       and with what priority. System V init script setup, in short.
end_of_description;


# --- 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 "networking" tag.

  while ($elem = shift @$tree)
  {
    if   ($elem eq "sysv") { &xml_parse_sysv (shift @$tree, \%hash); }
    else { &xst_report ("xml_unexp_tag", $elem); shift @$tree; }
  }

  return (\%hash);
}


sub xml_parse_sysv
{
  my ($tree, $hash) = @_;
  my ($elem, $runlevel);

  $runlevel = [];
  shift @$tree;  # Skip attributes.
  
  while ($elem = shift @$tree)
  {
      if    ($elem eq "runlevel") { push @$runlevel, &xml_parse_runlevel (shift @$tree); }
      elsif ($elem eq "services") { $$hash{"services"} = &xml_parse_services (shift @$tree); }
      else  { &xst_report ("xml_unexp_tag", $elem); shift @$tree; }
  }
  
  $$hash{"runlevel"} = $runlevel unless scalar @$runlevel == 0;
}


sub xml_parse_runlevel
{
  my ($tree) = @_;
  my ($elem, $hash, $service);

  $hash = {};
  $service = [];
  shift @$tree;  # Skip attributes.

  while ($elem = shift @$tree)
  {
      if    ($elem eq "level")   { $$hash{"level"} = &xst_xml_get_pcdata (shift @$tree); }
      elsif ($elem eq "service") { push @$service, &xml_parse_service (shift @$tree); }
      else  { &xst_report ("xml_unexp_tag", $elem); shift @$tree; }
  }

  $$hash{"service"} = $service;

  return $hash;
}


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

  $hash = {};
  shift @$tree;  # Skip attributes.

  while ($elem = shift @$tree)
  {
      if    ($elem eq "action")   { $$hash{"action"}   = &xst_xml_get_pcdata (shift @$tree); }
      elsif ($elem eq "name")     { $$hash{"name"}     = &xst_xml_get_pcdata (shift @$tree); }
      elsif ($elem eq "priority") { $$hash{"priority"} = &xst_xml_get_pcdata (shift @$tree); }
      else  { &xst_report ("xml_unexp_tag", $elem); shift @$tree; }
  }

  return $hash;
}


sub xml_parse_services
{
  my ($tree) = @_;
  my ($elem, $services);

  $services = [];
  shift @$tree;  # Skip attributes.

  while ($elem = shift @$tree)
  {
      if ($elem eq "service") { push @$services, &xst_xml_get_pcdata (shift @$tree); }
      else  { &xst_report ("xml_unexp_tag", $elem); shift @$tree; }
  }

  return $services;
}

# --- XML printing --- #


sub xml_print
{
  my ($h) = @_;

  &xst_xml_print_begin ();
  &xst_xml_print_structure ($$h{"runlevel"}, "runlevel");
  &xst_xml_print_structure ($$h{"services"}, "services");
  &xst_xml_print_end ();
}

# Main operations

sub get
{
  my %hash;

  $hash{"runlevel"} = &xst_service_sysv_get_tree ();
  $hash{"services"} = {"service" => &xst_service_sysv_list_available ()};

  &xst_report_end ();
  &xml_print (\%hash);
}

sub set
{
  my $hash;

  $hash = &xml_parse ();
#  &xst_sysv_conf_set ($hash);
  &xst_report_end ();
}


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


sub filter
{
  my $hash;

  $hash = &xml_parse ();
  &xst_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:xst_run_directive to know about the format of this hash.

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

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

