# -*-perl-*-

# $Id: Sysctl.plm,v 1.2 2003/12/15 16:28:35 thomas Exp $

# What package to handle inittab files

# $Log: Sysctl.plm,v $
# Revision 1.2  2003/12/15 16:28:35  thomas
# check-in for 0.1.1
#
# Revision 1.1.1.1  2003/12/02 14:47:35  thomas
# Initial version before export to 0.1.1
#

=head1 NAME

What::Node::Sysctl - manage /etc/sysctl.conf

=head1 DESCRIPTION

This B<What> configuration package controls the content of the file
B</etc/sysctl.conf>.

B<sysctl> nodes are represented in the configuration language in their
tree form.  That is, all the B<fs> B<sysctl> nodes are placed under
the B<Sysctl/fs> subtree.  The B<sysctl> variable
B<net.ipv4.ip_forward> corresponds to the B<what> node
B<Sysctl/net/ipv4/ip_forward>, and so on.

Each node has the following attributes:

=over 4

B<value> -- contains the value of the variable.

B<comment> -- A comment that will be placed above the entry in the
B<sysctl.conf> file.

=back

The root B<Sysctl> node can also have several attributes.  These are:

=over 4

B<minimum_size> -- provides a sanity-check for new
inittabs.  If the generated inittab is smaller than the value of the
B<minimum_size> attribute, the new inittab will not be installed.

B<sysctl_path> -- This attribute provides the name of the inittab
file to be generated.  It defaults to B</etc/sysctl.conf>.

=back

In addition, any triggers associated with the root B<Sysctl> node will
be exected whenever the configuration is updated.  The typical trigger
would execute B</sbin/sysctl -p> to load the new values into the
running kernel.

=head1 EXAMPLES

Enable the B<sysrq> function.

<node path="/Sysctl/kernel/sysrq" value="1" comment="Enable the magic-sysrq key" />

Increase the maximum number of open files on the system.

<node path="/Sysctl/fs/file-max" value="32768" comment="per [CSL #62379]" />

Set up an external trigger to cause the new contents of the file to be
processed via B</sbin/sysctl>.

<node path="/Sysctl" >
  <trigger path="/external/sysctl" />
</node>
<node path="/Triggers/external/sysctl" external-command="/sbin/sysctl" args="-p" />


=cut

package What::Node::Sysctl;

use strict;
use FileHandle;
use Data::Dumper;
use File::stat;
use File::MkTemp;

use base qw(What::Node);

our %opts = ();

# Set the priority for this module in $::
$::module_priority{'Sysctl'} = 20;

###############################################################################
# Apply the current configuration

sub apply {
  my $class = shift;
  my $section = shift;
  my $what = shift;
  my $sname = shift;
  my $cname = shift;

  my ($minimum_size, $sysctl_path) = (0, '/etc/sysctl.conf');
  my $rootattrs = $class->getattrs ($section);
  exists ($rootattrs->{minimum_size}) and
    $minimum_size = $rootattrs->{minimum_size};
  exists ($rootattrs->{sysctl_path}) and
    $sysctl_path = $rootattrs->{sysctl_path};

  my $newctl = <<__Eof__
###
# This sysctl was generated automatically by What::Node::Sysctl
# Hand-made changes will be lost!!
###


__Eof__
  ;

  $newctl .= $class->apply_r ($section, $what, '');

  if ($class->check_and_replace_content ($sysctl_path,
					 $newctl,
					 $minimum_size,
					 1
					)) {
    $class->run_triggers ($section, $what, $cname);
    return 1;
  }
  return 0;
}


sub apply_r {
  my $node = shift;
  my $section = shift;
  my $what = shift;
  my $name = shift;

  my ($attrs, $children);
  my $config = '';

  # See if this is a config node
  $attrs = $node->getattrs ($section);
  if (exists ($attrs->{value}) && defined ($attrs->{value})) {
    if (exists ($attrs->{comment}) && defined ($attrs->{comment})) {
      $config .= "# $attrs->{comment}\n";
    }
    $config .= "$name = $attrs->{value}\n\n";
    return $config;
  }

  $children = $node->getchildren ($section);
  length ($name) and $name .= '.';
  foreach (sort keys %$children) {
    $config .= $children->{$_}->apply_r ($section, $what, "$name$_");
  }
  return $config;
}

###############################################################################

1;
