#
# osAlertlog.pl
# 
# Copyright (c) 2003, Oracle Corporation.  All rights reserved.  
#
#    NAME
#      osAlertlog.pl - scans an OS-specific alert log file for patterns
#
#    DESCRIPTION
#
#      Currently works only for SunOS, HP-UX and Linux.
#
#      Goes to an OS-specific alert log file, looks for specific
#      message types. Matching lines (since the last iteration)
#      are concatenated into one alert whose severity is the highest
#      among the messages concatenated. The key for the alert is
#      composed of the current time and the first and last lines
#      of the log file that were scanned for this alert. 
#
#    NOTES
#      (none)
#
#    MODIFIED   (MM/DD/YY)
#      subsunda  05/05/03 - Fix for bug 2922324
#      njagathe  04/23/03 - Fixes for bug 2922324
#      subsunda  04/23/03 - njagathe_bug-2922324
#      njagathe  04/16/03 - njagathe_bug-2907928
#      Subash    10/04/03 - Creation
#

# use/require appropriate libraries

use strict;

require "emd_common.pl";

# Patterns to look for and ignore, can be made into command line arguments
# If requiredPatternsList is enhanced / changed, the handling of the
# error codes has to be modified.
#

my @requiredPatternsList = ("POWERFAILED|EMCP:Mp|Error|ERROR|CRITICAL","NOTICE|WARNING|DOWN");
my @ignorePatternsList = ("MSU","file system full","autofs_link","nfs3_link","File system full","getpid: peer","Error checking child termination status","telnetd","INFORMATIONAL","PAM Error Message","PAM_ERROR_MSG","password has expired","dbchgrmpw");

# get target_name from environment

my $targetGuid = $ENV{EM_TARGET_GUID};

#Set the OS log file based on the OS

my $osLogFileName;
if (($^O eq "solaris") || ($^O eq "sunos"))
{
    $osLogFileName = "/var/adm/messages";
}
elsif (($^O eq "hpux"))
{
    $osLogFileName = "/var/adm/syslog/syslog.log";
}
elsif (($^O eq "linux"))
{
    $osLogFileName = "/var/log/messages";
}
else
{
    EMD_PERL_ERROR("target: $targetGuid; operating system alerts not supported for $^O");

#    print "em_result=||| \n";
    exit 0;
}

#
# Check the accessibility of the alert log.
#
if (!open(LOG,"< $osLogFileName"))
{
    EMD_PERL_ERROR("target: $targetGuid; unable to open alert log at $osLogFileName");

#    print "em_result=|||$osLogFileName\n";
    exit 0;
}

my $scannedFile = get_os_alert_log_filename();

#
# Build the fully qualified scanned file path.
#

my $separator = $^O =~ m/MSWin32/ ? "\\" : "\/";
my $emd_root = $ENV{EMDROOT};


#
# Location of the offsets state file is
#  $EMDROOT/sysman/emd/state/<TARGET_GUID>.<alert log filename>
#
$scannedFile = $emd_root.$separator."sysman".$separator."emd".$separator."state".$separator."$targetGuid.$scannedFile";


my $offset = 0;
my $line = 0;

#
# Open scanned file for reading (if scanned file does not exist, create it.)
#
open(SCANNED, "+>> $scannedFile") or die "em_error=Cannot open $scannedFile";

# seek to top of file

seek(SCANNED, 0, 0);

# file only contains a single line with two numbers:  an offset and line number
# get these and close the scanned file

while (<SCANNED>)
{
    my @pos = split(' ', $_);
    my $pos = \@pos;

    $offset = $pos->[0];
    $line = $pos->[1];
}

close(SCANNED);

use Time::gmtime;
my $currentTimeStamp = gmctime();

seek(LOG, 0, 2);
if($offset > tell(LOG))
{
    EMD_PERL_DEBUG("target $targetGuid; missing previous scan information for file $osLogFileName; starting from the begining of the file");
    $offset = 0;
    $line = 0;
}

seek(LOG, $offset, 0);
$currentTimeStamp = $currentTimeStamp . $line;

my $jumpToNextLine;
my $anIgnorePattern;
my $aRequiredPattern;
my $warningMsgString = "";
my $criticalMsgString = "";
my $msgSeperatorString = "+++";

while (<LOG>)
{
    $line++;
    #
    # Clean up the line (remove \n, leading, and trailing whitespace).
    #
    chop;
    $_ =~ s/^\s+//;
    $_ =~ s/\s+$//;

    $jumpToNextLine = 0;
    foreach $anIgnorePattern (@ignorePatternsList)
    {
        if ($_ =~ /$anIgnorePattern/)
        {
            $jumpToNextLine = 1;
            last;
	}
    }

    if ($jumpToNextLine == 1)
    {
        next;
    }

    foreach $aRequiredPattern (@requiredPatternsList)
    {
        if ($_ =~ /$aRequiredPattern/)
        {
            if ($aRequiredPattern eq "NOTICE|WARNING|DOWN")
            {
                $warningMsgString = $warningMsgString . $_ . $msgSeperatorString;
                last;
	    }
            else
            {
                $criticalMsgString = $criticalMsgString . $_ . $msgSeperatorString; 
                last;
	    }
	}
    }
}

my $compositeMsgString = $criticalMsgString . $warningMsgString;

my $emStatusCode;
if (length($compositeMsgString) > 0)
{
    if (length($criticalMsgString) > 0)
    {
        $emStatusCode = 1;
    }
    else
    {
        $emStatusCode = 2;
    }

    $currentTimeStamp = $currentTimeStamp . $line;

    if (length($compositeMsgString) > 1024)
    {
        $compositeMsgString = substr($compositeMsgString, 0, 1024);
    }

    my $outputLine;

    $outputLine = "em_result=$currentTimeStamp|$emStatusCode|$osLogFileName|$compositeMsgString";
    print $outputLine;
}
else
{
#    print "em_result=||| \n";
}

$offset = tell(LOG);

#
# Reopen scanned file and write out new offset (log size), line number
#
open (SCANNED, "+> $scannedFile") or die "em_error=Cannot open $scannedFile";
print SCANNED "$offset $line\n";
close(SCANNED);

close(LOG);


#
# subroutine get_os_alert_log_filename
#  Build the filename for the alert log.
#
#

sub get_os_alert_log_filename
{
    my $alert_log_filename;

    if ($^O =~ m/MSWin32/)
    {
        $alert_log_filename = "os_alrt.log";
    }
    else
    {
        $alert_log_filename = "os_alert.log";
    }

    return $alert_log_filename;
}

exit 0;
