#!/usr/bin/perl
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 2004,2007 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
# @(#)33   1.6.1.1   src/csm/core/cmds/monerrorlog.perl, csmcore, csm_rfish, rfishs001b 4/25/07 08:20:13

#When first run (by the sensor) this script adds an entry to the AIX ODM
#or Linux syslog.conf file so that it will be notified when an error is
#logged (through a message queue on AIX and a named pipe on Linux). Then
#it checks for any logged errors. On all subsequent runs this script just
#checks for errors.

use strict;
use locale;

BEGIN
{

	# this enables us to redirect where it looks for other CSM files during development
	$::csmroot = $ENV{'CSM_ROOT'} ? $ENV{'CSM_ROOT'} : '/opt/csm';
	$::csmpm   = "$::csmroot/pm";
	$::csmbin  = "$::csmroot/bin";
}
use lib $::csmpm;
use Getopt::Std;
use NodeUtils;
use ServerUtils;
require NetworkUtils;
use IPC::SysV qw(IPC_STAT S_IRWXU IPC_PRIVATE IPC_CREAT S_IRUSR S_IWUSR );
use IPC::Msg;

$::MSGCAT     = 'nodecmds.cat';
$::MSGMAPPATH = "$::csmroot/msgmaps";
if (defined $ENV{'CSM_VERBOSE'}) { $::VERBOSE = 1; }

#Variable definitions
%::msOSDefs = ServerUtils->get_OSDefs();    #load global definitions
my $distroname = NodeUtils->get_DistributionName();
my $distroversion = NodeUtils->get_DistributionVersion();

my $dirname = "csm_err_mon";
my $vardir  =
  "/var/opt/$dirname"
  ;    #don't want it in /var/optcsm because it shouldn't be failed over
my $runfile    = "$vardir/.monerrorlog_run";
my $fifo       = "$vardir/syslog_fifo";
my ($syslogconf, $embedinfo);
if (($distroname eq "SLES") && ($distroversion eq "10")) 
{
	$syslogconf = "/etc/syslog-ng/syslog-ng.conf";
	$embedinfo = "destination warn_fifo { pipe(\\\"$fifo\\\" group(root) perm(0644)); };\nlog { source(src); filter(f_warn); destination(warn_fifo); };";
}
else
{
	$syslogconf = "/etc/syslog.conf";
	$embedinfo = "*.warn   |$fifo";
}
my $odmstanza  = "$vardir/odmstanza";

if (!-d $vardir) { mkdir($vardir); }

sub isRMrunning{
  my $resMan = $_[0];
  my @output = NodeUtils->runcmd("LANG=C /usr/bin/lssrc -s $resMan", -1);
  if ($::RUNCMD_RC) { return 0; }   # maybe we should try to catch real errors here
  my ($subsys, $group, $pid, $status) = split(' ', $output[1]);
  if (defined($status) && $status eq 'active') { 
    #now check to see if IBM.AuditRM is up
    return 1;
  }
  return 0;
}
#check to see if this is the first time this script has been run
if (!-e $runfile)
{      #first time
	if (NodeUtils->isLinux())
	{
		NodeUtils->runcmd("$::GREP $dirname $syslogconf", -1);
		if ($::RUNCMD_RC == 1)
		{    #grep did not find dirname
			    #update syslog.conf
			if (!-d $vardir) { mkdir($vardir); }
			NodeUtils->runcmd("/usr/bin/mkfifo $fifo");
			NodeUtils->runcmd("echo \"$embedinfo\" >> $syslogconf");
			my $cmd = NetworkUtils->service("syslog", "restart");
			NodeUtils->runcmd($cmd);
		}
		NodeUtils->touchFile($runfile);
	}
	elsif (NodeUtils->isAIX())
	{
		open(ODM, ">$odmstanza") or die $!;
		print ODM '
errnotify:
      en_pid = 0
      en_name = "csm_errlog_sensor"
      en_persistenceflg = 1
      en_method = "/opt/csm/csmbin/errmsgque sequence = $1 error_id = $2 class = $3 type = $4 alert_flags = $5 res_name = $6 res_type = $7 res_class = $8 label = $9"
';
		close ODM or die $!;
		NodeUtils->runcmd("/usr/bin/odmadd $odmstanza");
		NodeUtils->touchFile($runfile);
	}
	else
	{
		print "unknown platform\n";
		exit 1;
	}
}

#Check for errors

#see if at is running
NetworkUtils->verify_atd();    #TODO optimize this by not using at

if (NodeUtils->isLinux())
{
	local $SIG{ALRM} = sub { die "alarm\n" };
	eval {
		alarm 4;
		open(PIPE, $fifo) or die 
        MessageUtils->messageFromCat('csmInstall.cat', $::MSGMAPPATH, 
                                     'csminstall',     'E1', 
                                     'EMsgCANT_OPEN', $fifo
                                     ); 
		alarm 0;
	};
	if ($@ =~ /alarm/) { close PIPE; exit 0; }

	while (1)
	{
		my $line;
		eval {
			alarm 2;
			$line = <PIPE>;
			alarm 0;
		};
		if ($@ =~ /alarm/) { close PIPE; exit 0; }
		chomp($line);

		#print "String=\"$line\"\n";
		NodeUtils->runcmd(
			"echo \"/usr/bin/refsensor ErrorLogSensor String=\'$line\' 1>/dev/null 2>/dev/null\" | at now",
			0
		);
	}
	close PIPE;
}
elsif (NodeUtils->isAIX())
{
	# the monitoring is stopped
	if ($ENV{'SENSOR_MonitorStatus'} eq '2')
	{
		# stopsrc -s IBM.SensorRM will also 
		# set $ENV{'SENSOR_MonitorStatus'} to 2
		# should not do clean up when IBM.SensorRM is stopped
		if (&isRMrunning("IBM.SensorRM"))
		{
			NodeUtils->runcmd("/bin/odmdelete -o errnotify -q \" en_name=csm_errlog_sens\"", -1);
			if (-e $runfile)
			{
				unlink($runfile);
			}
		}
		exit 0;
	}

	my $m = ord('csm');
	my $key = IPC::SysV::ftok("/var/adm/ras/errlog", $m);
	my $buf;
	my $msg = new IPC::Msg($key, IPC_CREAT | S_IRUSR | S_IWUSR);
	local $SIG{ALRM} = sub { die "alarm\n" };
	while (1)
	{
		eval {
			alarm 2;
			my $rectype = $msg->rcv($buf, 256);
			alarm 0;
		};
		if ($@ =~ /alarm/) { close PIPE; exit 0; }
		NodeUtils->runcmd(
			"echo \"/usr/bin/refsensor ErrorLogSensor String=\'$buf\' 1>/dev/null 2>/dev/null\" | at now",
			0
		);
	}

	exit 0;
}

exit 0;

