#!/usr/bin/perl
###############################################################################
#                                                                             #
# Weber - 0.5                                                                 #
# Check the files created by BigBen, and create the proper WEB pages          #
#                                                                             #
# $Id: Weber,v 1.22 1998/01/13 21:03:32 cesare Exp cesare $                   #
###############################################################################

$revision="0.5";
$internal_revision="1.22";

### Signal catch ###
$SIG{"HUP"}='trap_signal';
$SIG{"INT"}='trap_signal';
$SIG{"QUIT"}='trap_signal';
$SIG{"TERM"}='trap_signal';

### Some variables to set-up environment ###
$file_conf="./Weber.conf";
$sleep=30;
$workdir="./store";

### Log file name ###
$logfile="/tmp/Weber.log";
$log_event=1;

### Init associative arrays ###
$gif{"E"}="redball.gif";
$gif{"W"}="yellowba.gif";
$gif{"O"}="greenbal.gif";
$mex{"E"}="ERROR";
$mex{"W"}="WARNING";
$mex{"O"}="OK";

### Declare other associative arrays ###
%pause;
%name;
%wait;

print "Weber $revision - by Pizzi Cesare\n";
print "Type Weber -h to see the available options\n";

### Read command line options ###
&parse_options();

###################################
### Read the configuration file ###
###################################
&read_conf($file_conf);

&build_main();

### Build the working directory for each system ###
&build_index();

### Fork the process ###
if (($child=fork()) == 0) {

	### Son process ###

	### Unlink the process from the terminal ###
	setpgrp();

	### Main check loop ###
	while (1) {

		&global_check();
	}

	exit;
}


##############################################################################
#                                                                            #
# SUBROUTINES                                                                #
#                                                                            #
##############################################################################

########################################################################
### Main routine to perform the systems check. It calls check_system ###
########################################################################
sub global_check {

	local $timemod,$now;
	local $body,old_body;
	local $result;
	local $file;

	$timemod=localtime();

	foreach $check_sys (keys pause) {

		$now=time();
		if (($now-$wait{"$check_sys"}) > $pause{"$check_sys"}) {

			### It's time to check ###
			$result=&check_system($name{"$check_sys"},$check_sys);

			#######################
			### Manipulate body ###
			#######################

			### Open input file ###
			if (open(INFILE,"$workdir/main.html")) {

				### Load the file in a variable (don't worry, it's little) ###
				$file="";
				while (<INFILE>) {
					$file.=$_;
				}
				close(INFILE);
			} else {

				### Unable to open the main page ###
				&log_message("ERROR: $!") if $log_event == 1;
			}

			### Update time ###
			$file=~s/(Last update: )(.*)/$1$timemod/;

			### Update systems status ###
			$body="\n<TR>\n<TD><A HREF=\"./$check_sys/index.html\">\n<FONT COLOR=\"#33FF33\">$name{$check_sys}</FONT></A></TD>\n<TD ALIGN=CENTER>$mex{$result}</TD>\n<TD ALIGN=CENTER><IMG SRC=\"$gif{$result}\"></TD>\n</TR>";

			$old_body="\n<TR>\n<TD><A HREF=\"./$check_sys/index.html\">\n<FONT COLOR=\"#33FF33\">$name{$check_sys}</FONT></A></TD>\n<TD ALIGN=CENTER>\\w*</TD>\n<TD ALIGN=CENTER><IMG SRC=\"\\w*.\\w*\"></TD>\n</TR>";

			$file=~s/$old_body/$body/;

			### Rewrite the new main.html file ###
			if (open(OUTFILE,">$workdir/main.html")) {

				### Write the file ###
				print OUTFILE $file;
				close(OUTFILE);
			} else {

				### Unable to open the main page ###
				&log_message("ERROR: $!") if $log_event == 1;
			}

			### Refresh the last-check time ###
			$wait{"$check_sys"}=time();
		}
	}


	### Pause between two checks ###
	sleep($sleep);
}

###################################################
### Check the files store for a specific system ###
###################################################
sub check_system {

	### Get parameters ###
	local $name=shift;
	local $ip=shift;

	### Define local variables ###
	local $timemod,$process,$status,$message;
	local $field,@report,$warn;

	### Open output file ###
	if (open(OUTFILE,">$workdir/$ip/index.html")) {

		$timemod=localtime();

		select OUTFILE;
		$~="HEAD_DETAIL";
		write;
		select STDOUT;

		### Return value initialization ###
		$warn="O";

		### Open input file ###
		if (open(INFILE,"$workdir/$ip/data")) {

			$_=<INFILE>;

			@report=split(/###/,$_);

			foreach $field (@report) {

				($process,$status,$message)=split(/\^\^/,$field);

				select OUTFILE;
				$~="BODY_DETAIL";
				write;
				select STDOUT;

				### Force a value in $message if empty ###
				$message="O" if $message eq "";

				$warn=$message if ($warn ne "E" && $message ne "O");

			}
		} else {
			### Error opening file ###
			print OUTFILE "No data file available: ERROR";

			$warn="E";
		}

		select OUTFILE;
		$~="FOOT_DETAIL";
		write;
		select STDOUT;
		
		### Close files ###
		close(OUTFILE);
		close(INFILE);
	} else {

		### Unable to open output file ###
		&log_message("WARNING: $!") if $log_event == 1;
	}

	unlink("$workdir/$ip/data");

	return $warn;
}

##############################################
### Build the main Page for the first time ###
##############################################
sub build_main {

	local $timemod,$sys;

	if (open(OUTFILE,">$workdir/main.html")) {

		$timemod="First Run";

		select OUTFILE;
		$~="HEAD_MAIN";
		write;

		### Write a line for each system ###
		foreach $sys (keys pause) {

			$body="\n<TR>\n<TD><A HREF=\"./$sys/index.html\">\n<FONT COLOR=\"#33FF33\">$name{\"$sys\"}</FONT></A></TD>\n<TD ALIGN=CENTER>$mex{\"W\"}</TD>\n<TD ALIGN=CENTER><IMG SRC=\"yellowba.gif\"></TD>\n</TR>";

			print OUTFILE $body;

		}

		select OUTFILE;
		$~="FOOT_MAIN";
		write;

		close(OUTFILE);
	} else {

		### Unable to open main HTML file ###
		&log_message("ERROR: $!") if $log_event == 1;

		exit(1);
	}
}

############################################################################
### Build a working directory for each system to check, with a default   ###
### index file                                                           ###
############################################################################
sub build_index {

	local $sys;

	foreach $sys (keys pause) {

		### Create the working directory ###
		mkdir($workdir."/".$sys,0700);

		### Create the default index file ###
		if (open(INDEX,">$workdir/$sys/index.html")) {
			print INDEX "NO DATA RECEIVED YET. TRY LATER.\n";

			close(INDEX);
		} else {

			### Error opening the file ###
			&log_message("ERROR: $!") if $log_event == 1;

			exit(1);
		}
	}
}

##########################################################################
### Read the configuaration file where are stored the systems to check ###
##########################################################################
sub read_conf {

	### Get parameters ###
	local $file=shift;

	local $system_name,$pause,$system_ip;
	local $ip,$error;

	$error="Error parsing $file_conf: duplicated IP address found.\n";

	### Reset the associative arrays ###
	undef %pause;
	undef %name;
	undef %wait;

	### Open and read the file ###
	open(SYSTEMS,"$file") || die "Can't open $file: $!";

	while (<SYSTEMS>) {

		next if /^#/;           # Skip comment lines

		($system_name,$system_ip,$pause)=split(/\s+/,$_);

		### Check for duplicated IP address ###
		foreach $ip (keys pause) {
			if ($system_ip eq $ip) {
				print $error;
				&log_message("$error") if $log_event == 1;

				exit(1);
			}
		}

		### Load the arrays ###
		$pause{"$system_ip"}=$pause;
		$name{"$system_ip"}=$system_name;
		$wait{"$system_ip"}=time();
	}

	close(SYSTEMS);
}

#################################################
### Handle the signal received by the program ###
#################################################
sub trap_signal {

        local ($sig)=@_;

	#################################
	### Check the received signal ###
	#################################

	if ($sig eq 'HUP') {

		&log_message("Signal received: HUP. Configuration file reloaded") if $log_event == 1;

		### Read the configuration file ###
		&read_conf($file_conf);
		&build_main();

	} elsif ($sig eq 'INT' || $sig eq 'QUIT' || $sig eq 'TERM') {

		&log_message("Signal received: $sig. Exit") if $log_event == 1;
		&cleanup();

		exit(0);

	} else {
		### Unknown signal. Ignore it. ###
	}
}

######################################
### Parse the command line options ###
######################################
sub parse_options {

        while ($_=$ARGV[0],s/^-( ?)(.+)$/$2/ && shift(@ARGV)) {

		next if $_ eq '';

		### Help screen ###
		if (/^h/) { &usage(); }

		### Set the log file name ###
		if (/^l(.*)$/) {
			if ($1) {
				$logfile=$1;
			} else {
				$logfile=$ARGV[0];
				shift(@ARGV);
			}

			next;
		}

		### Set configuration file name ###
		if (/^c(.*)$/) {
			if ($1) {
				$file_conf=$1;
			} else {
				$file_conf=$ARGV[0];
				shift(@ARGV);
			}

			next;
		}

		### Disable logging ###
		if (/^nolog$/) {
			$log_event=0;

			next;
		}

		### Set working directory ###
		if (/^d(.*)$/) {
			if ($1) {
				$workdir=$1;
			} else {
				$workdir=$ARGV[0];
				shift(@ARGV);
			}

			next;
		}

		&usage();
	}
}

######################################
### Clean-up the working directory ###
######################################
sub cleanup {

	local $ip;

	unlink("$workdir/main.html");

	foreach $ip (keys pause) {

		### Remove files ###
		unlink <$workdir/$ip/*>;
		### Remove directory ###
		rmdir("$workdir/$ip");
	}
}

###################################
### Display the program options ###
###################################
sub usage {

	print "Usage: Weber [options]\n\n";
	print "\t-d xxx     Working directory (default: $workdir)\n";
	print "\t           WARNING: this MUST be the same set in BigBen\n";
	print "\t-c xxx     Configuration file (default: $file_conf)\n";
	print "\t-l xxx     Log file (default: $logfile)\n";
	print "\t-nolog     Disable logging\n";
	print "\t-h         This page\n";
	print "\n";

	exit(0);
}

#####################################################
### Log function. Open a log file and write in it ###
#####################################################
sub log_message {

	### Get the parameter ###
	local $message=shift;
	local $date;

	open(LOG,">>$logfile") || warn "Can't open log file: $!";

	chop($date=`/bin/date`);
	print LOG "$date: $message\n";

	close(LOG);
}

#############################################################################
#                                                                           #
# OUTPUT FORMATS for the WEB                                                #
#                                                                           #
#############################################################################

###################
### Main screen ###
###################

### Head for main screen ###

format HEAD_MAIN =

<HTML>
<HEAD>
	<TITLE>BigBen Main Page</TITLE>
	<META HTTP-EQUIV="REFRESH" CONTENT="30; URL=./main.html" TARGET=TOP>
</HEAD>
<BODY BACKGROUND="./bckgrd.jpg">

<CENTER>
<H1>BigBen - Watch your network</H1>
</CENTER>

<HR>
Last update: @<<<<<<<<<<<<<<<<<<<<<<<<
$timemod

<CENTER>
<P><IMG SRC="./gnu-type.jpg" BORDER=2></P>
</CENTER>

<CENTER>
<TABLE BORDER=7 CELLPADDING=5 CELL SPACING=5>

<TR>
<TH>Host</TH>
<TH>Status</TH>
<TH></TH>
</TR>
.

### Body for main screen ###

### Body format removed. I decided to use a string ###

### Foot for main screen ###

format FOOT_MAIN =

</TABLE>
</CENTER>

</BODY>
</HTML>
.

#####################
### Detail screen ###
#####################

### Head for detail screen ###

format HEAD_DETAIL =

<HTML>
<HEAD>
	<TITLE>@>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Page</TITLE>
$name
</HEAD>
<BODY BACKGROUND="../bckgrd.jpg">

<CENTER>
<H1>Status of @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< </H1>
$name
</CENTER>

<HR>
Last update: @<<<<<<<<<<<<<<<<<<<<<<<<
$timemod

<CENTER>
<TABLE BORDER=7 CELLPADDING=5 CELL SPACING=5>

<TR>
<TH>Process</TH>
<TH>Status/Number</TH>
<TH>Message</TH>
</TR>
.

### Body for detail screen ###

format BODY_DETAIL =

<TR>
<TD ALIGN=CENTER>@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< </TD>
$process
<TD ALIGN=CENTER>@<<<<<<<<<<<<<<<< </TD>
$status
<TD ALIGN=CENTER>@<<<<<<<<<<<<<<<< </TD>
$message
</TR>
.

### Foot for detail screen ###
format FOOT_DETAIL =

</TABLE>
</CENTER>

</BODY>
</HTML>
.
