#!/usr/bin/perl

###############################################################################
#                                                                             #
# Filename: dmnERA                                                            #
#                                                                             #
# Description:                                                                #
#                                                                             #
###############################################################################
###############################################################################
#                                                                             #
#  Copyright  2000 - 2001 Intel Corporation.                                 #
#  Intel Corporation All Rights Reserved.                                     #
#                                                                             #
#  The source code contained or described herein and all documents related to #
#  the source code ("Material") are owned by Intel Corporation or its         #
#  suppliers or licensors.  Title to the Material remains with Intel          #
#  Corporation or its suppliers and licensors.  The Material contains trade   #
#  secrets and proprietary and confidential information of Intel or its       #
#  suppliers and licensors.  The Material is protected by worldwide copyright #
#  and trade secret laws and treaty provisions.  No part of the Material may  #
#  be used, copied, reproduced, modified, published, uploaded, posted,        #
#  transmitted, distributed, or disclosed in any way without Intel's prior    #
#  express written permission.                                                #
#                                                                             #
#  No license under any patent, copyright, trade secret or other intellectual #
#  property right is granted to or conferred upon you by disclosure or        #
#  delivery of the Materials, either expressly, by implication, inducement,   #
#  estoppel or otherwise. Any license under such intellectual property rights #
#  must be express and approved by Intel in writing.                          #
#                                                                             #
###############################################################################

$MOUNT="/bin/mount";
$GREP="/bin/grep";
$CAT="/bin/cat";
$CP='/bin/cp';
$RM='/bin/rm';
$LOGGER="/usr/bin/logger";
$ASM_CONF='/etc/asm/asm.conf';
$SENSORS_CONF='/etc/asm/asm.conf';
$TMP_COPY='/tmp/temp.copy';
$OUTPUT_DEST=STDERR;
$DF='/bin/df';
$KILLALL="/usr/bin/killall";
# Set files
if( -d "/proc/sys/dev/sensors/ds1780-i2c-0-2d")
{
	$PROC_DIR                        = "/proc/sys/dev/sensors/ds1780-i2c-0-2d/";
}else{
	$PROC_DIR                        = "/proc/sys/dev/sensors/adm9240-i2c-0-2d/";
}
$BBU_PROC_DIR = "/proc/sys/dev/sensors/smart_battery-i2c-0-0b/";

$ASM_BIN_DIR="/usr/ins/intel/bin/asm/";
$FANMUX=$ASM_BIN_DIR."sysFanMux";
$SMBIOS=$ASM_BIN_DIR."sysSMBIOS";
$EMAILALERT=$ASM_BIN_DIR."bakEmailAlert";
$WRITETOSEL=$ASM_BIN_DIR."sysWriteToSEL";
$WRITETOLCD=$ASM_BIN_DIR."sysWriteToLCD";
$LANALERT=$ASM_BIN_DIR."sysLANAlert";
$BEEP=$ASM_BIN_DIR."sysBeep";
$CLEARTEXT=$ASM_BIN_DIR."sysClearText";
$CLEARICON=$ASM_BIN_DIR."sysClearIcon";
$SENDTONEPAGE=$ASM_BIN_DIR."sysSendTonePage";

$STATUS_FAN1				 = $PROC_DIR."fan1";
$STATUS_FAN2				 = $PROC_DIR."fan2";
$STATUS_BBU 				 = $BBU_PROC_DIR."status";

$FAN_OUTPUT_DIR				 = "/var/local/";
$FANMUX_DELAY = 2;

##require $REQ_LIB_COMMON; 

################### Global Varibles ###################
$SystemType = ReadAsmConf("ASM_MODE");
$BBUInstalled = ReadAsmConf("BBU_INSTALLED");

@CPUTemperatureThresholds=split(',',ReadAsmConf('TEMPERATURE_THRESHOLDS'));
@CPUTemperatureCriticalThresholds=split(',',ReadAsmConf('TEMPERATURE_CRITICAL_THRESHOLDS'));

@V0_Thresholds=split(',',ReadAsmConf('V0_THRESHOLDS'));
@V0_CriticalThresholds=split(',',ReadAsmConf('V0_CRITICAL_THRESHOLDS'));

@V1_Thresholds=split(',',ReadAsmConf('V1_THRESHOLDS'));
@V1_CriticalThresholds=split(',',ReadAsmConf('V1_CRITICAL_THRESHOLDS'));

@V2_Thresholds=split(',',ReadAsmConf('V2_THRESHOLDS'));
@V2_CriticalThresholds=split(',',ReadAsmConf('V2_CRITICAL_THRESHOLDS'));

@V3_Thresholds=split(',',ReadAsmConf('V3_THRESHOLDS'));
@V3_CriticalThresholds=split(',',ReadAsmConf('V3_CRITICAL_THRESHOLDS'));

@V4_Thresholds=split(',',ReadAsmConf('V4_THRESHOLDS'));
@V4_CriticalThresholds=split(',',ReadAsmConf('V4_CRITICAL_THRESHOLDS'));

# Try to get the processor family...
if ($ProcessorFamily = uc(GetSMBIOSData('PROCESSOR_FAMILY') || ''))
{
	# Clean up the data.
	$ProcessorFamily =~ s/ /_/g;
	$ProcessorFamily =~ s/^(.*)_{1}PROCESSOR(.*)/$1$2/;
	$ProcessorFamily = '_' . $ProcessorFamily;
}
@V5_Thresholds=split(',',ReadAsmConf('V5_THRESHOLDS' . $ProcessorFamily));
@V5_CriticalThresholds=split(',',ReadAsmConf('V5_CRITICAL_THRESHOLDS' . $ProcessorFamily));

@CPUTemperatureUpperCriticalAction=split(',',ReadAsmConf('TEMP_UPPER_CRITICAL_ACTIONS'));
@CPUTemperatureUpperNonCriticalAction=split(',',ReadAsmConf('TEMP_UPPER_ACTIONS'));
@CPUTemperatureNormalAction=split(',',ReadAsmConf('TEMP_NORMAL_ACTIONS'));
@CPUTemperatureLowerNonCriticalAction=split(',',ReadAsmConf('TEMP_LOWER_ACTIONS'));
@CPUTemperatureLowerCriticalAction=split(',',ReadAsmConf('TEMP_LOWER_CRITICAL_ACTIONS'));

@voltageUpperCriticalAction=split(',',ReadAsmConf('VOLT_UPPER_CRITICAL_ACTIONS'));
@voltageUpperNonCriticalAction=split(',',ReadAsmConf('VOLT_UPPER_ACTIONS'));
@voltageNormalAction=split(',',ReadAsmConf('VOLT_NORMAL_ACTIONS'));
@voltageLowerNonCriticalAction=split(',',ReadAsmConf('VOLT_LOWER_ACTIONS'));
@voltageLowerCriticalAction=split(',',ReadAsmConf('VOLT_LOWER_CRITICAL_ACTIONS'));

@intrusionOpenActions=split(',',ReadAsmConf('INTRUSIONS_OPEN_ACTIONS'));
@intrusionCloseActions=split(',',ReadAsmConf('INTRUSIONS_CLOSE_ACTIONS'));

$Fan0_Threshold=ReadAsmConf('FAN0_THRESHOLD');
$Fan0_CriticalThreshold=ReadAsmConf('FAN0_CRITICAL_THRESHOLD');
$Fan1_Threshold=ReadAsmConf('FAN1_THRESHOLD');
$Fan1_CriticalThreshold=ReadAsmConf('FAN1_CRITICAL_THRESHOLD');
$Fan2_Threshold=ReadAsmConf('FAN2_THRESHOLD');
$Fan2_CriticalThreshold=ReadAsmConf('FAN2_CRITICAL_THRESHOLD');
$Fan3_Threshold=ReadAsmConf('FAN3_THRESHOLD');
$Fan3_CriticalThreshold=ReadAsmConf('FAN3_CRITICAL_THRESHOLD');
$Fan4_Threshold=ReadAsmConf('FAN4_THRESHOLD');
$Fan4_CriticalThreshold=ReadAsmConf('FAN4_CRITICAL_THRESHOLD');

@FanNormalAction=split(',',ReadAsmConf('FAN_NORMAL_ACTIONS'));
@FanNonCriticalAction=split(',',ReadAsmConf('FAN_LOWER_ACTIONS'));
@FanCriticalAction=split(',',ReadAsmConf('FAN_LOWER_CRITICAL_ACTIONS'));

@BBUInsertedAction=split(',',ReadAsmConf('BBU_INSERTED_ACTIONS'));
@BBURemovedAction=split(',',ReadAsmConf('BBU_REMOVED_ACTIONS'));
@BBUPowerlossAction=split(',',ReadAsmConf('BBU_POWERLOSS_ACTIONS'));
@BBUOverheatedAction=split(',',ReadAsmConf('BBU_OVERHEATED_ACTIONS'));
@BBUMissingAction=split(',',ReadAsmConf('BBU_MISSING_ACTIONS'));

$snmpTrapDestination = ReadAsmConf("SNMP_DESTINATION");

$previousTemperatureReturn=0;
$previous12VReturn=0;
$previousMinus12VReturn=0;
$previous5VReturn = 0;
$previous2_5VReturn=0;
$previous33VReturn=0;
$previousVCoreReturn=0;
$previousIntrusion=0;
$previousBBU=0;
@previousFan = (0, 0, 0, 0, 0);

$old_user_ticks = 0;
$old_nice_ticks = 0;
$old_system_ticks = 0;
$old_idle_ticks = 0;

$initState=3;

## Last state variables.
$NORMAL 				= 0;
$LOWER 					= 1;
$LOWER_CRITICAL 		= 2;
$UPPER 					= 3;
$UPPER_CRITICAL 		= 4;

## Disk Variables
$Disk_OverallAlertState = "GREEN";  
ReadSensorParameterArray('DISKS',\@Disks);
@DiskStatus = ();
@Disk_NormalActions      = split(",", ReadSensorParameter('DISK_NORMAL_ACTIONS'));
@Disk_NonCriticalActions = split(",", ReadSensorParameter('DISK_LOWER_ACTIONS'));
@Disk_CriticalActions    = split(",", ReadSensorParameter('DISK_LOWERCRITICAL_ACTIONS'));

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

($x, $x, $x, $x, $x, $x, $x, $x, $x, $lastModDate, $x, $x, $x, $x) = stat($SENSORS_CONF);


while ($initState == 3)
{
	CheckTemperatureStats();
	
	CheckPlus12Stats();
	CheckMinus12Stats();
	CheckVIOStats();
	CheckPlus5Stats();
	CheckPlus3_3Stats();
	CheckVcoreStats();

	if($SystemType =~ "SAGEBRUSH")
	{
		CheckIntrusionState();
	}

	if($SystemType =~ "CHARDONNAY")
	{
		CheckFanStats();
	}

	if($BBUInstalled == 1)
	{
		CheckBBUState();
	}

	CheckCPUMemoryUsage();

	ManageDisks();
	CheckDiskStats();
	
	sleep(2);
	# ### See if we should reload asm.conf.
	($x, $x, $x, $x, $x, $x, $x, $x, $x, $thisModDate, $x, $x, $x, $x) = stat($SENSORS_CONF);
	if( $thisModDate != $lastModDate )
	{
		# asm.conf changed so re-read values.
		$lastModDate = $thisModDate;
		$SystemType = ReadAsmConf("ASM_MODE");
		$BBUInstalled = ReadAsmConf("BBU_INSTALLED");
		
		@CPUTemperatureThresholds=split(',',ReadAsmConf('TEMPERATURE_THRESHOLDS'));
		@CPUTemperatureCriticalThresholds=split(',',ReadAsmConf('TEMPERATURE_CRITICAL_THRESHOLDS'));

		@V0_Thresholds=split(',',ReadAsmConf('V0_THRESHOLDS'));
		@V0_CriticalThresholds=split(',',ReadAsmConf('V0_CRITICAL_THRESHOLDS'));

		@V1_Thresholds=split(',',ReadAsmConf('V1_THRESHOLDS'));
		@V1_CriticalThresholds=split(',',ReadAsmConf('V1_CRITICAL_THRESHOLDS'));

		@V2_Thresholds=split(',',ReadAsmConf('V2_THRESHOLDS'));
		@V2_CriticalThresholds=split(',',ReadAsmConf('V2_CRITICAL_THRESHOLDS'));

		@V3_Thresholds=split(',',ReadAsmConf('V3_THRESHOLDS'));
		@V3_CriticalThresholds=split(',',ReadAsmConf('V3_CRITICAL_THRESHOLDS'));

		@V4_Thresholds=split(',',ReadAsmConf('V4_THRESHOLDS'));
		@V4_CriticalThresholds=split(',',ReadAsmConf('V4_CRITICAL_THRESHOLDS'));

		# Try to get the processor family...
		if ($ProcessorFamily = uc(GetSMBIOSData('PROCESSOR_FAMILY') || ''))
		{
			# Clean up the data.
			$ProcessorFamily =~ s/ /_/g;
			$ProcessorFamily =~ s/^(.*)_{1}PROCESSOR(.*)/$1$2/;
			$ProcessorFamily = '_' . $ProcessorFamily;
		}
		@V5_Thresholds=split(',',ReadAsmConf('V5_THRESHOLDS' . $ProcessorFamily));
		@V5_CriticalThresholds=split(',',ReadAsmConf('V5_CRITICAL_THRESHOLDS' . $ProcessorFamily));

		@CPUTemperatureUpperCriticalAction=split(',',ReadAsmConf('TEMP_UPPER_CRITICAL_ACTIONS'));
		@CPUTemperatureUpperNonCriticalAction=split(',',ReadAsmConf('TEMP_UPPER_ACTIONS'));
		@CPUTemperatureNormalAction=split(',',ReadAsmConf('TEMP_NORMAL_ACTIONS'));
		@CPUTemperatureLowerNonCriticalAction=split(',',ReadAsmConf('TEMP_LOWER_ACTIONS'));
		@CPUTemperatureLowerCriticalAction=split(',',ReadAsmConf('TEMP_LOWER_CRITICAL_ACTIONS'));

		@voltageUpperCriticalAction=split(',',ReadAsmConf('VOLT_UPPER_CRITICAL_ACTIONS'));
		@voltageUpperNonCriticalAction=split(',',ReadAsmConf('VOLT_UPPER_ACTIONS'));
		@voltageNormalAction=split(',',ReadAsmConf('VOLT_NORMAL_ACTIONS'));
		@voltageLowerNonCriticalAction=split(',',ReadAsmConf('VOLT_LOWER_ACTIONS'));
		@voltageLowerCriticalAction=split(',',ReadAsmConf('VOLT_LOWER_CRITICAL_ACTIONS'));

		@intrusionOpenActions=split(',',ReadAsmConf('INTRUSIONS_OPEN_ACTIONS'));
		@intrusionCloseActions=split(',',ReadAsmConf('INTRUSIONS_CLOSE_ACTIONS'));

		$snmpTrapDestination = ReadAsmConf("SNMP_DESTINATION");

		$Fan0_Threshold=ReadAsmConf('FAN0_THRESHOLD');
		$Fan0_CriticalThreshold=ReadAsmConf('FAN0_CRITICAL_THRESHOLD');
		$Fan1_Threshold=ReadAsmConf('FAN1_THRESHOLD');
		$Fan1_CriticalThreshold=ReadAsmConf('FAN1_CRITICAL_THRESHOLD');
		$Fan2_Threshold=ReadAsmConf('FAN2_THRESHOLD');
		$Fan2_CriticalThreshold=ReadAsmConf('FAN2_CRITICAL_THRESHOLD');
		$Fan3_Threshold=ReadAsmConf('FAN3_THRESHOLD');
		$Fan3_CriticalThreshold=ReadAsmConf('FAN3_CRITICAL_THRESHOLD');
		$Fan4_Threshold=ReadAsmConf('FAN4_THRESHOLD');
		$Fan4_CriticalThreshold=ReadAsmConf('FAN4_CRITICAL_THRESHOLD');

		@FanNormalAction=split(',',ReadAsmConf('FAN_NORMAL_ACTIONS'));
		@FanNonCriticalAction=split(',',ReadAsmConf('FAN_LOWER_ACTIONS'));
		@FanCriticalAction=split(',',ReadAsmConf('FAN_LOWER_CRITICAL_ACTIONS'));

		@Disks = @Disk_NormalActions = @Disk_NonCriticalActions = @Disk_CriticalActions = ();
		ReadSensorParameterArray('DISKS',\@Disks);
		@Disk_NormalActions      = split(",", ReadSensorParameter('DISK_NORMAL_ACTIONS'));
		@Disk_NonCriticalActions = split(",", ReadSensorParameter('DISK_LOWER_ACTIONS'));
		@Disk_CriticalActions    = split(",", ReadSensorParameter('DISK_LOWERCRITICAL_ACTIONS'));
	}
}

## Wait for pager to stop.
## Kill asm process checker so that...
system("$KILLALL dmnASMCheck");
## Predictive failure can be killed so that..
system("$KILLALL dmnPFMonitor");
## We don't have another process trying to send a page.
$done = 0;
$startTime = time();
while(!$done)
{
	$pagerfound = 0;
	open(INPUT, "/bin/ps -e |");
	while( <INPUT> )
	{
		($x,$x,$x,$name) = split(" ", $_, 4);
		chomp($name);
		if($name eq "sysSendTonePage")
		{
			$pagerfound = 1;
			last;
		}
	}
	close(INPUT);
	if($pagerfound)
	{
		sleep(5);
	}else{
		$done = 1;
	}
 	if( (time() - $startTime) > 300)
	{
		## Get out of here if we've been waiting for 5 minutes.
		$done = 1;
	}
}

system("/sbin/init $initState");
exit 0;

##
## [CheckFanStats]
##
## Check fan statistics on Chardonnay systems.
##
sub CheckFanStats
{
	if($SystemType ne "CHARDONNAY")
	{
		return;
	}

	OutputFanStats();

	$previousFan0Return = CheckFanStatsIndividual(0, "Fan1", 
			$previousFan0Return, $Fan0_Threshold, $Fan0_CriticalThreshold);
	$previousFan1Return = CheckFanStatsIndividual(1, "Fan2", 
			$previousFan1Return, $Fan1_Threshold, $Fan1_CriticalThreshold);
	$previousFan2Return = CheckFanStatsIndividual(2, "Fan3", 
			$previousFan2Return, $Fan2_Threshold, $Fan2_CriticalThreshold);
	$previousFan3Return = CheckFanStatsIndividual(3, "Fan4", 
			$previousFan3Return, $Fan3_Threshold, $Fan3_CriticalThreshold);
	$previousFan4Return = CheckFanStatsIndividual(4, "Fan5", 
			$previousFan4Return, $Fan4_Threshold, $Fan4_CriticalThreshold);

}

##
## [OutputFanStats]
##
## Create files containing individual fan data
sub OutputFanStats
{
	my $i, $benefits;
	my ($x, $speed1, $speed2);
	my ($tmpfile, $fanfile);

	for($i = 0; $i < 3; $i++)
	{
		for($benefits = 0; $benefits < 5; $benefits++)
		{
			## Because of issues surrounding reading fan values,
			## give everyone the benefit of 5 tries if the
			## reported value is 0 or less.
			system("$FANMUX $i");
			##sleep $FANMUX_DELAY;
			sleep $FANMUX_DELAY;
		
			$tmpfile = $FAN_OUTPUT_DIR . ".fan" . ($i + 1);
			$fanfile = $FAN_OUTPUT_DIR . "fan" . ($i + 1);
			open(IN, "<$STATUS_FAN1");
			($x, $speed1) = split(' ', <IN>);
			close(IN);
			open(OUT, ">$tmpfile");
			print OUT "$speed1\n";
			close(OUT);
			rename( $tmpfile, $fanfile );

			if($i < 2)
			{
				$tmpfile = $FAN_OUTPUT_DIR . ".fan" . ($i + 4);
				$fanfile = $FAN_OUTPUT_DIR . "fan" . ($i + 4);
				open(IN, "<$STATUS_FAN2");
				($x, $speed2) = split(' ', <IN>);
				close(IN);
				open(OUT, ">$tmpfile");
				print OUT "$speed2\n";
				close(OUT);
				rename( $tmpfile, $fanfile );
			}

			## If speed is not 0 or a negative number, it's
			## legit.
			last if( ($speed1 > 0)  && ($speed2 > 0) );
		}
	}
}

##
## [CheckFanStatsIndividual]
##
## Get individual fan statistics.
sub CheckFanStatsIndividual
{
	my ($sensor, $id, $previous, $nonCritical, $critical) = @_;
	my $speed;

	if( open(IN, $FAN_OUTPUT_DIR . "fan" . ($sensor + 1) ) )
	{
		$speed = <IN>;
		close(IN);
		chomp($speed);
	}
	else
	{
		$speed = 0;
	}

	## Check Thresholds 
	$return = 0;
	if ($speed <= $nonCritical)
	{
		if ($speed <= $critical)
		{
			$return = 2;
			##
			open(FILE, ">>/tmp/fan.dbg");
			print FILE ($sensor + 1)." = $speed\n";
			close(FILE);
		}else{
			$return = 1;
		}
	}
	
	if ($return != $previousFan[$sensor])
	{
		## Changed so perform action.
		if ($return == 0)
		{
			PerformActions($id, '$id is normal', 'xxx', '1', @FanNormalAction);
		}elsif ($return == 1)
		{
			PerformActions($id, "$id crossed warning threshold", 'xxx','5',@FanNonCriticalAction);
		}elsif ($return == 2)
		{
			PerformActions($id, "$id crossed critical threshold", 'xxx','4',@FanCriticalAction);
		}
		$previousFan[$sensor] = $return;
	}
	
	return $return;
}

sub CheckBBUState() {
	my ($currentstate);

	if ($BBUInstalled eq '0') {
		return;
	}

	if (!(-e $STATUS_BBU)) {
		$currentstate = 4;
	}
	else {
		# *sigh*...FIXME
		$currentstate = 0;
	}

	if ($currentstate != $previousBBU) {
		## Changed, perform action.
		if ($currentstate == 0) {
			PerformActions("BBUInserted", "Battery was inserted", 'xxx', '0', @BBUInsertedAction);
		}
		elsif ($currentstate == 1) {
			PerformActions("BBURemoved", "Battery was removed", 'xxx', '0', @BBURemovedAction);
		}
		elsif ($currentstate == 2) {
			PerformActions("BBULossofAC", "Power was lost", 'xxx', '0', @BBUPowerlossAction);
		}
		elsif ($currentstate == 3) {
			PerformActions("BBUOverheat", "Battery is overheated", 'xxx', '0', @BBUOverheatedAction);
		}
		elsif ($currentstate == 4) {
			PerformActions("BBUMissing", "Battery is missing", 'xxx', '0', @BBUMissingAction);
		}

		$previousBBU = $currentstate;
	}
}

sub ReadAsmConf
{
	my($look) = @_;
	my ($line, $param);

	$line = ReadFileLine($ASM_CONF,$look);
	($x, $param) = split(/=/,$line,2);
	return($param);
}

sub ManageDisks
{
	my ($line, @currentDisks, $howMany, $thisDisk, $foundIt);
	my ($x, @newDisks, $needToReWrite);
	my ($oldDevice, $oldMount, $oldFS, $oldNC, $oldCritical, $oldLastState);
	my ($newDevice, $newMount, $newFS, $newNC, $newCritical, $newLastState);


	## Old Disk Data is in @Disks
	## Get New Disk Data
	open(INPUT, "$MOUNT |");
	while ( defined($line = <INPUT>)) {
		chomp($line);
		($device, $x, $mount, $x, $fileSystem, $x) = split(/ /,$line,6);
		## Ignore "none" partitions, nfs mounts, and peripheral mounts via '/mnt/...'.
		next if (($device eq "none") || ($fileSystem eq "nfs") || ($mount =~ /^\/mnt/) || ($mount eq '/emergency'));
		push(@currentDisks,$device.":".$mount.":".$fileSystem."::");
	}
	close (INPUT);

	## Check to see if we have new mount data that is not in @Disks
	$needToReWrite = 0;
	while (defined($newDisk=shift(@currentDisks))) {
		$foundIt = 0;
		($newDevice, $newMount, $newFS, $newNC, $newCritical) = split(':',$newDisk,5);

		## Make a working copy of @Disks so we don't destry it
		@oldDiskList = @Disks;

		## Run through the old disks and look for match to current /proc/mounts line
		while ( (defined($oldDisk=shift(@oldDiskList))) && (! $foundIt) ) {
			($oldDevice, $oldMount, $oldFS, $oldNC, $oldCritical) = split(':',$oldDisk,5);
			if ( "$newDevice" =~ "$oldDevice" ) {
				$foundIt = 1;
				if ( "$newMount" !~ "$oldMount") { $needToReWrite = 1; }
				if ( "$newFS" !~ "$oldFS") { $needToReWrite = 1; }
				push(@newDisks,$newDevice.":".$newMount.":".$newFS.":".$oldNC.":".$oldCritical);
			}
		}

		## if it wasn't in our old list, build a new entry
		if (! $foundIt ) {
			$needToReWrite = 1;
			push(@newDisks,$newDevice.":".$newMount.":".$newFS.":10240:5120");
		}
	}

	## Only update our data if it has changed
	if ( $needToReWrite ) {
		DeleteSensorParameter('DISKS');
		$howMany = WriteSensorParameterArray('DISKS',@newDisks);

		## Need to make sure we are working with the correct data for the next functions
		ReadSensorParameterArray('DISKS',\@Disks);
	}
	
	my $dsi = $#DiskStatus;
	if($dsi)
	{
		## No disk status array.  Create and make them all normal.
		for( $i = 0; $i <= $#Disks; $i++)
		{
			$dsi++;
			$#DiskStatus = $dsi;
			$DiskStatus[$dsi] = $NORMAL;
		}
	}
	
}

sub CheckDiskStats
{
	my ($line, $device, $mount, $fileSystem, $NCThresh, $CThresh, $lastState);
	my ($free, $trigger, $normalAction, $nonCriticalAction, $criticalAction);
	my ($oldDiskLine, $newDiskLine, $mostSevereState, $updatedDisk);

	$mostSevereState = "GREEN";
	$updatedDisk = 0;

	## Check our thresholds 
	for($i = 0; $i <= $#Disks; $i++)
	{
		($device, $mount, $fileSystem, $NCThresh, $CThresh) = split(':',$Disks[$i],5);

		##***********************************************************************/
		## Get disk usage in the following format                               */
		## Filesystem           1k-blocks      Used Available Use% Mounted on   */
		## /dev/hda1                31689      2587     27466   9% /boot        */
		##***********************************************************************/
		open(INPUT, "$DF $mount --block-size=1024 |");
		$line = <INPUT>; ## Throw away header line
		$line = <INPUT>;
		close (INPUT);
		($x,$x,$x,$free,$x,$x) = split(/ +/,$line);

		## Get current status.
		if ( $free > $NCThresh ) 
		{ 
			$status = $NORMAL;
		} elsif ( $free <= $CThresh ) 
		{ 
			$status= $LOWER_CRITICAL;
		} else { 
			$status = $LOWER;
		}
	
		## Compare current status to old status.
		if($DiskStatus[$i] != $status)
		{
			$DiskStatus[$i] = $status;
			if( $status == $NORMAL)
			{
				PerformActions("Disk", 'Disk entered normal state', 'xxx', '1', @Disk_NormalActions);
			}
			elsif( $status == $LOWER )
			{
				PerformActions("Disk", 'Disk entered warning state', 'xxx', '5', @Disk_NonCriticalActions);
			}
			elsif( $status == $LOWER_CRITICAL )
			{
				PerformActions("Disk", 'Disk entered critical state', 'xxx', '4', @Disk_CriticalActions);
			}
		}
	}
}


#################
## 	CheckThresholds
##	
## Return Values:
##	0 - Within normal parameters
##	1 - Under lower warning threshold, but not under critical threshold
##	2 - Under lower warning and critical thresholds
##	3 - Over upper warning threshold, but not over critical threshold
##	4 - Over upper warning and critical thresholds
#################

sub CheckThresholds
{
	my ($current, $lowerNonCritical, $upperNonCritical, $lowerCritical, $upperCritical) = @_;

	if ($current < $lowerNonCritical)
	{
		if ($current < $lowerCritical)
		{
			return(2);
		}
		else
		{
			return(1);			
		}
	}
	elsif ($current > $upperNonCritical)
	{
		if ($current > $upperCritical)
		{
			return(4);
		}
		else
		{
			return(3);
		}
	}
	return (0);
}

sub CheckTemperatureStats
{

	## Read CPU Temp
	open(INPUT, "$CAT ".$PROC_DIR."temp |");
	$temperature = <INPUT>;
	($x, $x, $temperature) = split (/ /, $temperature);
	chomp($temperature);
	close (INPUT);

	$return = CheckThresholds($temperature, $CPUTemperatureThresholds[0], $CPUTemperatureThresholds[1], $CPUTemperatureCriticalThresholds[0], $CPUTemperatureCriticalThresholds[1]);

	if ($return != $previousTemperatureReturn)
	{
		if ($return == 0)
		{
			PerformActions('CPUTemp', 'CPU Temperature is normal', 'xxx', '1', @CPUTemperatureNormalAction);
		}
		elsif ($return == 1)
		{
			PerformActions('CPUTemp', 'CPU Temperature crossed warning threshold', 'xxx', '5', @CPUTemperatureLowerNonCriticalAction);
		}	
		elsif ($return == 2)
		{
			PerformActions('CPUTemp', 'CPU Temperature crossed critical threshold', 'xxx', '4', @CPUTemperatureLowerCriticalAction);
		}
		elsif ($return == 3)
		{
			PerformActions('CPUTemp', 'CPU Temperature crossed warning threshold', 'xxx', '3', @CPUTemperatureUpperNonCriticalAction);
		}
		elsif ($return == 4)
		{
			PerformActions('CPUTemp', 'CPU Temperature crossed critical threshold', 'xxx', '2', @CPUTemperatureUpperCriticalAction);
		}
	}

	$previousTemperatureReturn = $return;
}

sub CheckPlus12Stats
{

	## Read +12 Volts (V0)
	open(INPUT, "$CAT ".$PROC_DIR."12V |");
	$v0 = <INPUT>;
	($x, $x, $v0) = split (/ /,$v0);
	chomp($v0);
	close (INPUT);
	
	$return = CheckThresholds($v0, $V0_Thresholds[0], $V0_Thresholds[1], $V0_CriticalThresholds[0], $V0_CriticalThresholds[1]);
	if ($return != $previous12VReturn)
	{
		ActionCheck($return, '+12v');
	}

	$previous12VReturn = $return;
}

sub CheckMinus12Stats
{

	## Read -12 Volts (V1)
	open(INPUT, "$CAT ".$PROC_DIR."Vccp2 |");
	$vccp2 = <INPUT>;
	($x, $x, $vccp2) = split (/ /,$vccp2);
	chomp($vccp2);
	close (INPUT);
	$v1 = ((($vccp2 * (192 / 270)) * (-1200 / 192)) + 23.12) * -1;
	
	$return = CheckThresholds($v1, $V1_Thresholds[0], $V1_Thresholds[1], $V1_CriticalThresholds[0], $V1_CriticalThresholds[1]);
	if ($return != $previousMinus12VReturn)
	{
		ActionCheck($return, '-12v');
	}

	$previousMinus12VReturn = $return;
}

sub CheckVIOStats
{
	## Check VIO stats.
	open(INPUT, "$CAT ".$PROC_DIR."2.5V |");
	$v1 = <INPUT>;
	($x, $x, $v1) = split(/ /, $v1);
	chomp($v1);
	close (INPUT);

	$return = CheckThresholds($v1, $V4_Thresholds[0], $V4_Thresholds[1], $V4_CriticalThresholds[0], $V4_CriticalThresholds[1]);
	if ($return != $previous2_5VReturn)
	{
		ActionCheck($return, '+Vio');
	}
	
	$previous2_5VReturn = $return;

}

sub CheckPlus5Stats
{
	
	## Read +5 Volts (V2)
	open(INPUT, "$CAT ".$PROC_DIR."5V |");
	$v2 = <INPUT>;
	($x, $x, $v2) = split(/ /, $v2);
	chomp($v2);
	close (INPUT);

	$return = CheckThresholds($v2, $V2_Thresholds[0], $V2_Thresholds[1], $V2_CriticalThresholds[0], $V2_CriticalThresholds[1]);
	if ($return != $previous5VReturn)
	{
		ActionCheck($return, '+5v');
	}
	
	$previous5VReturn = $return;
}

sub CheckPlus3_3Stats
{

	## Read +3.3 Volts (V3)
	open(INPUT, "$CAT ".$PROC_DIR."3.3V |");
	$v3 = <INPUT>;
	($x, $x, $v3) = split(/ /,$v3);
	chomp($v3);
	close (INPUT);

	$return = CheckThresholds($v3, $V3_Thresholds[0], $V3_Thresholds[1], $V3_CriticalThresholds[0], $V3_CriticalThresholds[1]);

	if ($return != $previous33VReturn)
	{
		ActionCheck($return, '+3.3v');
	}
	
	$previous33VReturn = $return;
}

sub CheckVcoreStats
{
	## Read CPU core voltage.
	open(INPUT, "$CAT ".$PROC_DIR."Vccp1 |");
	$v4 = <INPUT>;
	($x, $x, $v4) = split(/ /,$v4);
	chomp($v4);
	close (INPUT);
	
	$return = CheckThresholds($v4, $V5_Thresholds[0], $V5_Thresholds[1], $V5_CriticalThresholds[0], $V5_CriticalThresholds[1]);

	if ($return != $previousVCoreReturn)
	{
		ActionCheck($return, '+Vcore');
	}

	$previousVCoreReturn = $return;
}

sub ActionCheck
{
	my ($return, $sensor) = @_;
	
	if ($return == 0)
	{
		PerformActions($sensor, 'Voltage is normal', 'xxx', '1', @voltageNormalAction);
	}
	elsif ($return == 1)
	{
		PerformActions($sensor, "$sensor crossed warning threshold", 'xxx','5',@voltageLowerNonCriticalAction);
	}
	elsif ($return == 2)
	{
		PerformActions($sensor, "$sensor crossed critical threshold", 'xxx','4',@voltageLowerCriticalAction);
	}
	elsif ($return == 3)
	{
		PerformActions($sensor, "$sensor crossed warning threshold", 'xxx','3',@voltageUpperNonCriticalAction);
	}
	elsif ($return == 4)
	{
		PerformActions($sensor, "$sensor crossed critical threshold", 'xxx','2',@voltageUpperCriticalAction);	
	}
}

sub CheckIntrusionState
{

	## Read Intrusion state
	open(INPUT, "$CAT ".$PROC_DIR."alarms |");
	$intrusion = <INPUT>;
	chomp($intrusion);
	$intrusion = $intrusion + 0;
	$intrusion = $intrusion & 0x1000;
	close (INPUT);

	if ($intrusion != $previousIntrusion)
	{
		if ($intrusion)
		{
			PerformActions('Int', 'Chassis is set', 'xxx', '2', @intrusionOpenActions);
		}
		else
		{
			PerformActions('Int', 'Chassis is cleared', 'xxx', '1', @intrusionCloseActions);
		}
	}

	$previousIntrusion = $intrusion;
}

sub PerformActions
{
	my ($sensor, $description, $LCDCode, $type, @actions) = @_;
	my ($action);

	$action = pop(@actions);
	
	#ERA Defaults
	system("$WRITETOSEL \"$sensor\" $type > /dev/null"); 
	system("$LOGGER -- \"$description\" > /dev/null");
	if ($type == 1)
	{
		#system("$CLEARTEXT > /dev/null");
		#system("$CLEARICON 5 > /dev/null");
	}

	while ($action)
	{
		if ($action eq 'LANAlert')
		{
			system("$LANALERT \"$sensor\" $type > /dev/null");
		}
		elsif ($action eq 'WriteToLCD')
		{
 			system("$WRITETOLCD \"$sensor\" $type > /dev/null");
		}
		elsif ($action eq 'Beep')
		{
			system("$BEEP > /dev/null");
		}
		elsif ($action eq 'Shutdown')
		{
			$initState = 0;
		}
		elsif ($action eq 'Reboot')
		{
			$initState = 6;
		}
		elsif ($action eq 'Page')
		{
			SendPage($sensor, $type);
		}
		elsif ($action eq 'Email')
		{
			system("$EMAILALERT ERA $sensor $type > /dev/null");
		}
		elsif ($action eq 'SNMP' &&
		      ( -e "/usr/ins/intel/bin/asm/bakSNMPTrap"))
		{
			system("/usr/ins/intel/bin/asm/bakSNMPTrap ERA$sensor $type $snmpTrapDestination > /dev/null");
		}
		$action = pop(@actions);
	}
}

sub SendPage
{
	my ($sensor, $type) = @_;
	my (%scode_map, $scode);
	my ($callnumber, $sendnumber);
	my $forcePage = "No";
	my $level;
	my $cmd;

	%scode_map=(	'CPUTemp',	1,
			'+12v',		2,
			'-12v',		2,
			'+Vio',	2,
			'+5v',		2,
			'+3.3v',	2,
			'+Vcore',	2,
			'Fan1',		3,
			'Fan2',		3,
			'Fan3',		3,
			'Fan4',		3,
			'Fan5',		3,
			'Int',		4,
			'Disk',		6 );
	$scode = $scode_map{$sensor};
	$callnumber = ReadAsmConf('PAGER_NUMBER');
	$sendnumber = ReadAsmConf('PAGER_STRING') . $scode . $type;
	$forcePage  = ReadAsmConf('PAGER_FORCE_IMMEDIATE');
	$level = ($forcePage eq 'Yes') ? 0 : 1;
	$cmd = "$SENDTONEPAGE -n ";
	$cmd .= "-l $level " if $level;
	$cmd .= "-p $callnumber " if $callnumber;
	$cmd .= "$sendnumber " if $sendnumber;
	$cmd .= "> /dev/null &";
	system($cmd);
}

sub ReadFileLine
{
        my ($file,$look) = @_;
        my ($len,$line,$retrLine);

        $retrLine = '';
        ## open the file
        if (open(FILE,"<$file") == 0)
        {
                return(TIFileError('ReadFileLine',$file,$OUTPUT_DEST));
        }
        else
        {
                ## save lines until we find the until string
                $len = length($look);
                while (defined($line = <FILE>))
                {
                        if (substr($line,0,$len) eq $look)
                        {
                                chomp($line);
                                $retrLine = $line;
                                last;
                        }
                }
                close(FILE);
        }
        return($retrLine);
}               


sub CheckCPUMemoryUsage {
	
	open (STAT, "/proc/stat") || return;
	my $line = <STAT>;
	close (STAT) || return;

	my @cpuarray = split (/ /, $line);
	my ($user_ticks, $nice_ticks, $system_ticks, $idle_ticks) = @cpuarray[2..5];

	my ($user_diff, $nice_diff, $system_diff, $idle_diff) =
		($user_ticks - $old_user_ticks,
		$nice_ticks - $old_nice_ticks,
		$system_ticks - $old_system_ticks,
		$idle_ticks - $old_idle_ticks);

	# Calculate CPU usage
	my $CPUUsage = ( ($user_diff + $nice_diff + $system_diff) / 
		($idle_diff + $user_diff + $nice_diff + $system_diff) )
		* 100;

	# Save current values for next calculation
	($old_user_ticks, $old_nice_ticks, $old_system_ticks, $old_idle_ticks) = ($user_ticks, $nice_ticks, $system_ticks, $idle_ticks);

	open (MEMFILE, "/proc/meminfo") || return;
	<MEMFILE>;		# Throw away the first line
	$line = <MEMFILE>;
	$swapline = <MEMFILE>;
	close (MEMFILE) || return;

	my @memarray = split (' ', $line);
	my $real_total = $memarray[1];
	my $real_used  = $memarray[2];
	my @swaparray = split (' ', $swapline);
	my $swap_total = $swaparray[1];
	my $swap_used = $swaparray[2];

	my $MemoryUsage = ( ($real_used + $swap_used) / ($real_total + $swap_total) ) * 100;
	
	# Send it to the file
	open (CPUMEM, ">/var/tmp/cpumemstat.asm");
	print CPUMEM "$CPUUsage $MemoryUsage\n";
	close (CPUMEM);
}

sub ReadSensorParameterArray
{
      my ($look,$lines) = @_;
      my ($len,$line,$x,$param,$howMany);

      $howMany = 0;
      if (open(FILE,"<$SENSORS_CONF") == 0)
      {
            return(TIFileError('ReadSensorParameterArray',$SENSORS_CONF,$OUTPUT_DEST));
      }
      else
      {
            ## save all lines matching the $look, in the referenced array
            $look = $look.'=';
            $len = length($look);
            while (defined($line = <FILE>))
            {
                  if (substr($line,0,$len) eq $look)
                  {
                        ## This will chop off everything after the =
                        ($x,$param) = split(/=/,$line,2);
                        chomp($param);
                        push(@$lines,$param);
                        $howMany++;
                  }
            }
            close(FILE);
            return($howMany);
      }
}

sub DeleteSensorParameter
{
      my ($paramName) = @_;
      my ($line,@newLines,$howMany, $time);

      $howMany = 0;
      if (open(FILE,"<$SENSORS_CONF") == 0)
      {
            return(TIFileError('DeleteSensorParameter:READ',$SENSORS_CONF,$OUTPUT_DEST));
      }
      else
      {
            $len = length($paramName.'=');
            while (defined($line = <FILE>))
            {
                  if (substr($line,0,$len) eq $paramName.'=')
                  {
                        $howMany++;
                  }
                  else
                  {
                        push(@newLines,$line);
                  }
            }
      }
      close(FILE);

      $time = time();

      if (open(FILE,">$TMP_COPY.$time") == 0)
      {
            return(TIFileError('DeleteSensorParameter:WRITE',"$TMP_COPY.$time",$OUTPUT_DEST));
      }
      else
      {
            while (defined($line = shift(@newLines)))
            {
                  print FILE $line;
            }
            close(FILE);
      }
      system("$CP $TMP_COPY.$time $SENSORS_CONF");
      system("$RM -f $TMP_COPY.$time");
      return($howMany);
}

sub WriteSensorParameterArray
{
       ## The array I get should have no \n in it's elements

      my ($arrayType,@inLines) = @_;
      my ($howMany,$line,$myLine,@newLines,$time);

      $howMany = 0;
      ## open the file
      if (open(FILE,"<$SENSORS_CONF") == 0)
      {
            return(TIFileError('WriteSensorParameterArray:READ',$SENSORS_CONF,$OUTPUT_DEST));
      }
      else
      {
            ## save lines until we find the $ArrayType
            while (defined($line = <FILE>))
            {
                  if ( $line eq ('BEGIN_'.$arrayType."\n"))
                  {
                        push(@newLines,$line);
                        while (defined($myLine = shift(@inLines)))
                        {
                              if ($myLine eq ''){}
                              else
                              {
                                    $myLine = $arrayType.'='.$myLine."\n";
                                    push(@newLines,$myLine);
                                    $howMany++;
                              }
                        }
                  }
                  else
                  {
                        push(@newLines,$line);
                  }
            }
            close(FILE);
      }

      $time = time();

      ## now re-write the file
      ## open the file for writing
      if (open(FILE,">$TMP_COPY.$time") == 0)
      {
            return(TIFileError('WriteSensorParameterArray:WRITE', "$TMP_COPY.$time", $OUTPUT_DEST));
      }
      else
      {
            while (defined($line = shift(@newLines)))
            {
                  print FILE $line;
            }
            close(FILE);
      }
      system("$CP $TMP_COPY.$time $SENSORS_CONF");
      system("$RM -f $TMP_COPY.$time");
      return($howMany);
}

sub ReadSensorParameter
{
      my ($look) = @_;
      my ($theLine,$x,$param);

      $theLine = ReadFileLine($SENSORS_CONF,$look.'=');
      ($x,$param) = split(/=/,$theLine,2);
      return($param);
}

sub WriteSensorParameter
{
      my ($look,$newValue) = @_;
      ReplaceFileLine($SENSORS_CONF,$look.'=',$look.'='.$newValue);
}

sub ReplaceFileLine
{
      my ($file,$look,$newLine) = @_;
      my ($len,$line,@newLines,$time);

      ## open the file
      if (open(FILE,"<$file") == 0)
      {
            return(TIFileError('ReplaceFileLine:READ',$file,$OUTPUT_DEST));
      }
      else
      {
            ## save lines until we find the until string
            $len = length($look);
            while (defined($line = <FILE>))
            {
                  if (substr($line,0,$len) eq $look)
                  {
                        push(@newLines,$newLine."\n");
                  } else
                  {
                        push(@newLines,$line);
                  }
            }
            close(FILE);
      }

      $time = time();

      ## now re-write the file
      ## open the file for writing
      if (open(FILE,">$TMP_COPY.$time") == 0)
      {
            return(TIFileError('ReplaceFileLine:WRITE',"$TMP_COPY.$time",$OUTPUT_DEST));
      }
      else
      {
            while (defined($line = shift(@newLines)))
            {
                  print FILE $line;
            }
            close(FILE);
      }
      system("$CP $TMP_COPY.$time $file");
      system("$RM -f $TMP_COPY.$time");
      return(0);
}

###############################################################################
# GetSMBIOSData
###############################################################################

sub GetSMBIOSData
{
	my ($Key)			= @_;
	my $SMBIOSDataRaw	= `/usr/ins/intel/bin/asm/sysSMBIOS dump`;
	my @SMBIOSData		= split(/^/m, $SMBIOSDataRaw);
	my $KeyTemp;
	my $Value			= '';
	my $Line;

	# Convert to lower case.
	$Key = lc($Key);

	# Run through the data...
	foreach $Line (@SMBIOSData)
	{
		# If the line has an equal sign...
		if ($Line =~ /=/)
		{
			# Break out the key and value.
			($KeyTemp, $Value) = split(/=/, $Line);

			# Clear out the leading/trailing whitespace.
			$KeyTemp =~ s/^\s*(.*?)\s*$/$1/;

			# If the keys match...
			if ($Key eq lc($KeyTemp))
			{
				# Clear out the leading/trailing whitespace.
				$Value =~ s/^\s*(.*?)\s*$/$1/;
				last;
			}
			else
			{
				# Clean out the value.
				$Value = '';
			}
		}
	}

	return $Value;
}
