#    Big Sister network monitor
#    Copyright (C) 1998  Thomas Aeby
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU 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 General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#

package rules;

#use strict;

use Socket;
use FileHandle;
use cfgfile;
use Platforms;

local( %args, %memory );
my %defaultargs = ( "_INTERN" => {} );
my %describeargs = ();

$rules::grouping_stat = 0;
$rules::config_stat = 0;

my $grouping_cfg = new cfgfile( "grouping" );
my $uxmon_cfg;

# the procedure rules::config is called each time the file is read
sub config {
    my( $chk );
    my( $config ) = "$BigSister::common::fs{'adm'}";
    my( $host, @attr, $attr, $alias );
    my( $localhost, $fh );

    %memory = ();
    undef $rules::ping;
    %rules::memory = %rules::args = ();

    # read file adm/grouping
    {
	my( $name, $realname, @groups );
	my $count = 0;

	&uxmon::drop_all_groups;
	$grouping_cfg->rewind();
	while( $_ = $grouping_cfg->nextline() ) {
	    chomp;
	    $realname = "";
	    if( /\((.*)\)/ ) {
		$realname = $1;
		$_ = $`.$';
	    }
	    ($name,@groups) = split( /[\s\t]+/ );
	    $name =~ s/\./$BigSister::common::domain_encode/g;
	    if( $name eq "localhost" ) {
	        $name = $BigSister::common::hostname;
 	    }
	    &uxmon::join_group( $name, @groups ) if( @groups );
	    &uxmon::displayname( $name, $realname ) if( $realname );
	    $count++;
	}
	if( $count ) { &uxmon::leave_on_exit(1); }
    }
		
    # read config from uxmon-net if present
    $localhost = 0;

    unless( $uxmon_cfg ) { 
	my $cfg = $uxmon::configfile;
	unless( $cfg ) { $cfg = "uxmon-net"; }
	$uxmon_cfg = new cfgfile( $cfg );
    }

    {
	$uxmon_cfg->rewind();
	while( $_ = $uxmon_cfg->nextline() ) {
	    chomp;
	    s/#.*//;
	    next if( /^$/ );
	    ($host, @attr) = BigSister::common::parse( $_ );
	    next unless( $host );
	    $alias = "";
	    if( $host =~ /^(.*)\((.*)\)/ ) {
		$host = $1;
		$alias = $2;
	    }
	    if( $host eq "localhost" ) {
	        $host = $uxmon::hostname;
	    }
	    else {
		$alias = $host unless( $alias );
	    }
	    if( $defaultargs{"_INTERN"}->{"localhost"} = 
		($host eq $uxmon::hostname) ) {
		$localhost++;
	    }
	    $defaultargs{"_INTERN"}->{"host"} = $host;
	    $defaultargs{"_INTERN"}->{"alias"} = $alias;
	    %args = ();
	    foreach $attr (@attr) {
		&execute( $attr );
	    }
	}
    }

    # if no display server was configured use host 'bsdisplay' as a default
    unless( @uxmon::reporters ) {
	$args{"host"} = "bsdisplay";
	&execute( "bsdisplay" );
    }
}


sub execute {
    my( $attr ) = @_;

    $args{"cmd"} = $attr;
    my $host = $defaultargs{"_INTERN"}->{"host"};
    print "uxmon-rules.pl: executing $attr for host $host\n" if( $BigSister::common::dl>1 );
    unless( grep($host eq $_, "DEFAULT", "DESCR", "DESCRIBE") || inet_aton($host) ) {
	print STDERR "$BigSister::common::prog: WARNING: host $host appearing in uxmon config is unresolvable\n";
    }
    $attr =~ s/^(http):.*/$1/;
    if( $attr =~ /^(.*?)=(.*)/s ) {
	$args{$1} = $2;
	return 1;
    }
    elsif( $host eq "DEFAULT" ) {
	my %ta = %args;
	return if( $attr eq "_INTERN" );
	$defaultargs{$attr} = \%ta;
	%args = ();
	return 1;
    }
    elsif( ($host eq "DESCRIBE") || ($host eq "DESCR") ) {
	$attr = $uxmon::hostname if( $attr eq "localhost" );
	my %ta = %args;
	return if( $attr eq "_INTERN" );
	$describeargs{$attr} = \%ta;
	%args = ();
	return 1;
    }


    slurpin( \%args, $describeargs{$host} );
    slurpin( \%args, $defaultargs{$attr} );
    slurpin( \%args, $defaultargs{"ALL"} );
    slurpin( \%args, $defaultargs{"_INTERN"} );

    unless( $args{"alias"} ) {
        my $fqdn = $args{"fqdn"} =~ /^(y|Y|1|on)/;
	if( $fqdn ) {
	    $args{"alias"} = Platform::hostname(1);
	}
	else {
	    $args{"alias"} = $args{"host"};
	}
    }
    if( $BigSister::common::dl > 8 ) {
	print STDERR "args: \n";
	my( $key, $val );
	while( ($key,$val) = each %args ) {
	    print STDERR "  $key = $val\n";
	}
    }
    %rules::args = %args;

    my $ok = 0;
    if( (defined $args{"features"}) && ($attr ne "tester") ) {
	eval {
	    chdir( "$BigSister::common::fs{'uxmon'}/Config" );
	    (do "./tester") && ($ok = 1);
	};
	if( $ok ) {
	    %args = ();
	    return;
	}
    }

    eval {
	if( -f "$BigSister::common::fs{'adm'}/Config/$attr" ) {
	    chdir( "$BigSister::common::fs{'adm'}/Config" );
	    (do "./$attr") && ($ok = 1);
	}
	elsif( -f "$BigSister::common::fs{'uxmon'}/Config/$attr" ) {
	    chdir( "$BigSister::common::fs{'uxmon'}/Config" );
	    (do "./$attr") && ($ok = 1);
	}
	else {
	    (do "$attr") && ($ok = 1);
	}
    };
    BigSister::common::log( "warn", "check $attr failed to start up - ignored" ) unless( $ok );
    %args = ();
}


sub slurpin {
    my( $args, $defaults ) = @_;

    return() if( ! $defaults );
    my( $key, $val );
    while( ($key, $val) = each %$defaults ) {
	next if( defined $args->{$key} );
	$args->{$key} = $val;
    }
}



sub reload {
    my $file;
    if(
	(! $uxmon_cfg)
	|| ($file = $uxmon_cfg->has_changed())
	|| ($file = $grouping_cfg->has_changed())
    ) {
	BigSister::common::log( "notice", "config file $file has changed - reloading" ) if( $file );
	return 1;
    }
    return 0;
}


1;
