
# 
# This is a module designed to simplify writing Big Brother external scripts in PERL. 
# It's pretty ugly at this point, without an install or perldoc, but it will be
# cleaned up and completed shortly as time permits. For now, it needs to be placed
# in a directory available for your perl modules, most likely the BBHOME. Just by
# using this module, you will get all of the ENV settings needed from your bbdef.sh
# set into %ENV, and all of your %ENV set into local variables (I.E.:$BBHOME will
# be a reference to $ENV{BBHOME}, so you can use $BBHOME ect...
# A routine (BigBrother->Report($HostName,$function,$color,$status)) is supplied
# that performs the command to tell Big Brother the current status.
# An IsDown($string) is also supplied, that returns true if the file 
# $BBHOME/ext/down.cfg contains a line for $string,from,to that the current time
# falls between from and to. From and to are specified in the syntax of Date::Manip
# (see perldoc for it to see how to specify). 
# A few other routines are supplied, that I will doc soon, but it is more complicated
# than it really needed to be because I needed suport for a more complex BBHOST
# configureation. In particular, I needed to have oracle(sid,user=xxxx,pass=yyyy), and
# have it show in BB as host.sid, so don't be over critiacal, it will be cleaner soon. 
# I am also uploading the Oracle.pl that uses this module, and others soon.
#
# Joe Bryant
# HiUCImOn@Yahoo.com
#
package BigBrother;

sub import {
	my ($caller_package)=caller;
	if (!exists $ENV{BBHOME}) {
		my $work,$dir;					# we need local vars
		($work,$script)=$0=~/(.*?)\/?([^\/]*)$/;	# now strip out the dir and our name
		$work="$work/../";				# we assume a subdir of BBHOME
		chomp($dir=`pwd`);				# change to BBHOME
		chdir($work);					#   to get
		chomp($work=`pwd`);				#   the real dir name
		$ENV{BBHOME}=$work;				# now set BBHOME to something real
		chdir($dir);					# and retunr to our dir
	}
	$BBHOME=$ENV{BBHOME};
	if (!exists $ENV{BBTMP}) {				# only run if not set
		foreach (`cd $BBHOME;. etc/bbdef.sh;set`) {
			chomp;						# drop EOL
			($var,$val)=/^\s*(.*?)\s*=\s*(.*)/;		# get var and value
			$ENV{$var}=$val;				# and set
		}
	}
	foreach $env_key (keys %ENV) {
		next if ($env_key=~/^\s*$/sig);
		*{"${caller_package}::${env_key}"}=\$ENV{$env_key};
	}
	open(IN,"$ENV{BBHOSTS}");			# open bb-hosts
	foreach (<IN>) {				# read contents
		chomp;					# trim EOL
		next if (/^\s*#/);			# Skip comments
		($ip,$host,$pound,@parms)=split;	# Split into pieces
		$name=lc($host);			# force lower case to make finding easier
		next unless ($pound eq '#');		# Skip if token 3 isn't a '#'
		foreach $parm (@parms) {		# Process all the parms
			$bbhosts{"$name~$parm"}=$parm;	# and store as keys in %bbhosts "$name~$parm"
			$bbhost{"$name~$parm"}=$host;	# and store as keys in %bbhosts "$name~$parm"
			$bbhostsIP{"$ip~$parm"}=$parm;	# and store as keys in %bbhosts "$name~$parm"
		}
	}
	close(IN);					# and close
	foreach $key (keys %bbhosts) {			# We also need to parse parms
		if (($host,$function,$parms)=$key=~/^(.*)~(\w+)\((.*)\)/) {
		} else {
			($host,$function)=$key=~/^(.*)~(.*)/;	# so break it into host, function
			$parms=$function;
		}
		$name=$bbhost{"$key"};					# and retrieve the name
		%temp=();						# clear the work hash
		@positional=();
		foreach (split(/,/,$parms)) {				# split up and process each parm
			if (/=/) {					# two choices, positional or keyword
				($var,$val)=split(/=/);			# split it on the on the '='
				$var=lc($var);				# store as lower case to be sure it's unique
				$temp{$var}=$val;			# and save for when it is needed
			} else {					
				push @positional,$_;				# it is positional
			}
		}
		if (@positional) {
		} else {
			$positional[0]=$function;
		}
		$positional=join(':',@positional);
		$bbitems{"$bbhost{$key}.$positional[0]"}=$function;
		$positional{"$function"}.="$positional ";
		foreach (keys %temp) {
			$parms{"$positional~$function~$_"}=$temp{$_};
		}
	}
	$hosts=join(' ',keys %host);
	use Date::Manip qw(ParseDate DateCalc Date_Cmp);
	if (-r "$BBHOME/ext/down.cfg") {
		open(DOWN,"$BBHOME/ext/down.cfg");
		$now=ParseDate("now");
		foreach (<DOWN>) {
			chomp;
			s/#.*//sig;
			next if /^\s*$/sig;
			($name,$duration,$when)=split(',');
			$key="$name~".++$index{$name};
			$fromtime{$key}=ParseDate($when);
			$tilltime{$key}=DateCalc($when,$duration);
		}
	}
}

sub IsDown {
	my ($package,$key)=@_;
	foreach $temp (grep /^$key~/,keys %fromtime) {
		if ((Date_Cmp($fromtime{$temp},$now)<0) and (Date_Cmp($tilltime{$temp},$now)>0)) {
			return 1;
		}
	}
	return 0;
} 

sub Positional {
	($package,$forkey)=@_;
	my $hosts='';
	foreach (grep(/^$forkey$/,keys %positional)) {
		$hosts.=$positional{$_}.' ';
	}
	return $hosts;
}

sub Parms {
	my ($package,$key,$default)=@_;
	if (exists $parms{$key}) {
		return $parms{$key};
	} else {
		return $default;
	}
}

sub Items {
	($package,$forkey)=@_;
	my $items='';
	if ($forkey) {
		foreach (keys %bbitems) {
			next unless $bbitems{$_}=~/^$forkey$/;
			push @items,$_;
		}
		$items=join(' ',@items);
	} else {
		$items=join(' ',keys %bbitems);
	}
	return $items;
}

sub Report {
        my($package,$HostName, $inst, $color, $status) = @_ ;
        ($inst)=split(/\./,$inst);
        # Substitute dots by commas in the host name
        $HostName =~ s/\./,/g;
        # Build the command to report to Big Brother
        $color=lc($color);
        my $MyCmd= "$ENV{BB} $ENV{BBDISP} ".'"'."status $HostName.$inst $color ".localtime(time).' '.$status.'"';
        # For debugging purposes
        # Execute the command.
        # print "$MyCmd\n";
        `$MyCmd`;
}

1;

