#!/usr/bin/perl
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 2006,2019 
# 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 
# sccsid = "@(#)69   1.16   src/rsct/rm/ER/cli/bin/lsevent.perl, errmcli, rsct_rady, rady2035a 11/12/15 16:39:02"
#--------------------------------------------------------------------#
# Included Libraries and Extensions                                  #
#--------------------------------------------------------------------#
use lib "/opt/rsct/pm";
use locale;
use Getopt::Long;

use CT_cli_utils qw(printIMsg
                    printEMsg);
use CT_cli_input_utils qw(escape_chars);

use ERRM_cli_rc qw(ERRM_CLI_SUCCESS ERRM_CLI_RMC_ERROR
                   ERRM_CLI_ERROR ERRM_CLI_BAD_FLAG
                   ERRM_CLI_BAD_OPERAND ERRM_CLI_USER_ERROR);
use ERRM_cli_utils qw(error_exit
                    printCIMsg
                    printCEMsg
                    process_exit_code
                    remove_api_error
                    $TRUE $FALSE
                    $CTBINDIR $CTDIR
                    $DELIMITERI $DELIMITERO
                    $RMC_CLI_USER_ERROR);

#--------------------------------------------------------------------#
# Global Variables                                                   #
#--------------------------------------------------------------------#
Getopt::Long::Configure ("bundling", "no_auto_abbrev", 
                         "no_ignore_case", "require_order",
                         "prefix_pattern=(--|-)");
$Verbose = $FALSE;                      # default - verbose turned off

$Opt_Cluster = $FALSE;                  # default - see -a
$Opt_Event= $FALSE;                     # default - see -e
$Opt_Status= $FALSE;                    # default - see -i
$Opt_Nodes= $FALSE;                     # default - see -n
$Opt_Entries= $FALSE;                   # default - see -O
$Opt_Start_Time= $FALSE;                # default - see -B
$Opt_End_Time= $FALSE;                  # default - see -E
$Opt_rR= $FALSE;                        # default - see -r or -R
$Opt_A= $FALSE;                         # default - see -A

$PROGNAME = "lsevent";                  # Program Name for messages
$MSGCAT = "errmcli.cat";                # msg catalogue for this cmd
$LSMSG = "$CTBINDIR/ctdspmsg";          # list / display message rtn
$ENV{'MSGMAPPATH'} = "$CTDIR/msgmaps";  # msg maps used by $LSMSG

#--------------------------------------------------------------------#
# Variables                                                          #
#--------------------------------------------------------------------#

my $nodes= "";
my $node;
my @w_nodes;
my $entries;
my $condition= "";
my @responses= ();
my @output = ();
my $cmd;
my $rc= 0;
my $i;
my $common= "";
my $ResponseNames= "";
my $Etype;
my @queries= ();
my %event_spec = ();                    # indicate the event types specified
my %etype_spec = ();                    # indicate the event types specified
my $valid_opte = "AaBber";
my $valid_opte_simple = "abr";

#--------------------------------------------------------------------#
# Main Code                                                          #
#--------------------------------------------------------------------#

# parse the command line, exit if there are errors
($rc, $Start_Time, $End_Time, $nodes, $node, $entries, $event_type, $condition,
 @responses) = &parse_cmd_line;;
($rc == 0) || error_exit($rc);

if ($Verbose)
{ 
    printIMsg("IMsglseventStart");
}

# if -a or -n was specified, make sure CT_MANAGEMENT_SCOPE
# is set.  If it isn't, set it to 4, DM/SR/Local 
if ($Opt_Cluster || $Opt_Nodes)
{
    if (!defined $ENV{CT_MANAGEMENT_SCOPE})
    {
        $ENV{CT_MANAGEMENT_SCOPE} = 4;
    }
}
else
{
    $ENV{CT_MANAGEMENT_SCOPE} = 1; 
}

# set the -n or -a
if ($Opt_Nodes) 
{
    $nodes= "-n $nodes ";
}   
elsif ($Opt_Cluster)
{
    $nodes= "-a ";
}

# Get the LastSeqNumber
if ($Opt_Entries)
{
    $cmd = qq($CTBINDIR/lsrsrc-api -I $DELIMITERI -D $DELIMITERO -s IBM.AuditLog${DELIMITERI}"Name=='ERRM'"${DELIMITERI}LastSeqNumber 2>&1);
    @output = `$cmd`;
    $rc= $?;

    $rc = &process_exit_code($rc);

    # show any errors if there was a bad rc
    if ($rc != 0)
    {
        process_api_error($DELIMITERO,$rc,@output);
        # remove any error messages from the output to display
        @output = remove_api_error($DELIMITERO, @output);
    }

    $start= $output[0] - $entries;
    if ($start > 0)
    {
        $common= $common . "SequenceNumber>$start && ";
    }
    if ($Trace)
    {
        print STDERR "- LastSeqNumber= $output[0]\n";
    }
}

# set the Start Time
if ($Opt_Start_Time)
{
    $common= $common . "Time>=#$Start_Time && ";
}

# set the End Time
if ($Opt_End_Time)
{
    $common= $common . "Time<=#$End_Time && ";
}

# set the condition
if ($condition ne "")
{
    $common= $common . "ConditionName=='$condition' && ";
}

# set the response
if (@responses)
{
    # set the response(s)
    if (@responses == 1)
    {
        $ResponseNames= "EventResponseName=='$responses[0]' && ";
    }
    else # if (@responses > 1)
    {
        $ResponseNames= "(" . join("||", map("EventResponseName=='$_'", @responses)) . ") && ";
    }
}

# set the Etype based on -e
if ($Opt_Event)
{
    $Etype = "(";
    $j = 0;
    if ($etype_spec{91} == $TRUE) {
        $Etype .= "Etype==91";
        $j++;
    }
    if ($etype_spec{92} == $TRUE) {
        if($j != 0) { $Etype .= " || ";}
        $Etype .= "Etype==92";
        $j++;
    }
    if ($etype_spec{118} == $TRUE) {
        if($j != 0) { $Etype .= " || ";}
        $Etype .= "Etype==118";
        $j++;
    }
    if ($etype_spec{121} == $TRUE) {
        if($j != 0) { $Etype .= " || ";}
        $Etype .= "Etype==121";
        $j++;
    }
    $Etype .= ") && ";
}
else
{
    $Etype= "(Etype==91 || Etype==121) && ";
}

# set the TemplateId
if ($Opt_rR)
{
    if ($Opt_Status)  # -i
    {
        push (@queries, "TemplateId>=39 && TemplateId<=51 && " . $Etype . $ResponseNames);
    }
    else
    {
        push (@queries, "TemplateId>=40 && TemplateId<=51 && " . $Etype . $ResponseNames);
    }
}
elsif ($Opt_A)
{
    if ($Opt_Status)  # -i
    {
        push (@queries, "TemplateId>=1 && TemplateId<=36 && ");
    
        if ($ResponseNames ne "")
        {    
            push (@queries, "(TemplateId==37 || TemplateId==38) && " . $Etype);
            push (@queries, "TemplateId>=39 && TemplateId<=51 && " . $Etype . $ResponseNames);
        }
        else
        {
            push (@queries, "TemplateId>=37 && TemplateId<=51 && " . $Etype);
        }
    }
    else
    {
        if ($ResponseNames ne "")
        {
            push (@queries, "(TemplateId==37 || TemplateId==38) && " . $Etype);
            push (@queries, "TemplateId>=40 && TemplateId<=51 && " . $Etype . $ResponseNames);
        }
        else
        {
            push (@queries, "TemplateId>=37 && TemplateId<=51 && TemplateId!=39 && " . $Etype);
        }
    }
}
else
{
    # multiple operand of -e is not acceptable without -rRA
    if (length($event_type) > 1 || $valid_opte_simple !~ /$event_type/) {
        printCEMsg("EMsgERRMcliImproperUsageOperand", $opts{e});
        &print_usage;
        exit ERRM_CLI_ERROR;
    }
    
    if ($Opt_Node)  # -w
    {
        @w_nodes= split(",", $node);
        $Nodes= "(" . join("||", map("Node=='$_'", @w_nodes)) . ") && ";
        
        push (@queries, "TemplateId==38 && " . $Nodes . $Etype);

        if ($Opt_Status)  # -i
        {
            push (@queries, "TemplateId>=32 && TemplateId<=34 && " . $Nodes);
        }
    }
    else
    {
        if ($Opt_Status)  # -i
        {
            push (@queries, "TemplateId>=1 && TemplateId<=36 && ");
        }
        push (@queries, "(TemplateId==37 || TemplateId==38) && " . $Etype); 
    }
}

for ($i=0; $i< @queries; $i++)
{
  $queries[$i]= $common . $queries[$i];
  $queries[$i]=~ s/ && $//;
  &get_records($nodes, $queries[$i]);
}

if ($Verbose) 
{ 
    printIMsg("IMsglseventEnd"); 
}

#--------------------------------------------------------------------#
# End Main Code                                                      #
#--------------------------------------------------------------------#


#--------------------------------------------------------------------#
# parse_cmd_line - Parse the command line for options and operands.  #
#   Set appropriate global variables as outlined below, make sure we #
#   have a valid combination of arguments / options.                 #
#                                                                    #
# Return:                                                            #
#   $rc   0                  Command line parsed fine, no problem.   #
#         SR_CLI_BAD_FLAG    Command line contained a bad flag.      #
#   $Start_Time                                                      #
#   $End_Time                                                        #
#   $nodes                                                           #
#   $entries                                                         #
#   $event_type                                                      #
#   $condition                                                       #
#   @responses                                                       #
#                                                                    #
# Global Variables Modified:                                         #
#   $Opt_Cluster                   # see -a                          #
#   $Opt_Event                     # see -e                          #
#   $Opt_Status                    # see -i                          #
#   $Opt_Nodes                     # see -n                          #
#   $Opt_Node                      # see -w                          #
#   $Opt_Entries                   # see -O                          #
#   $Opt_Start_Time                # see -B                          #
#   $Opt_End_Time                  # see -E                          #
#   $Opt_rR                        # see -r or -R                    #
#--------------------------------------------------------------------#
sub parse_cmd_line
{
my $Start_Time;
my $End_Time;
my $nodes;
my $node;
my $entries;
my $event_type= "";
my $condition= "";
my @responses= ();
my %opts = ();

# Process the command line...
if (!GetOptions(\%opts,
                'h|help|version' ,
                'a' ,
                'A' ,
                'i' ,
                'r' ,
                'R' ,
                'T' ,
                'V' , 
                'B=s' ,
                'E=s' ,  
                'e=s' ,
                'n=s' ,
                'O=i' ,
                'w=s' ))
{
    &print_usage;                       # display proper usage
    return ERRM_CLI_BAD_FLAG;           # return bad rc - bad flag
}

# Always accept the -h help flag regardless of other flags or operands
if (defined $opts{h}) {                 # -h, help request
    &print_usage;                       # print usage statement
    exit(0);                            # all done with good return!
}

if (defined $opts{r})
{
    $Opt_rR= $TRUE;
    @responses= @ARGV;
}
elsif ($#ARGV >= 0)
{
    $condition= shift @ARGV;
    @responses= @ARGV;
}

if (defined $opts{R})
{
    if (defined $opts{A})
    {
        printCEMsg("EMsgERRMcliImproperUsageCombination", "-R", "-A");
        &print_usage;
        return ERRM_CLI_BAD_FLAG;
    }
    elsif (defined $opts{r})
    {
        printCEMsg("EMsgERRMcliImproperUsageCombination", "-R", "-r");
        &print_usage;
        return ERRM_CLI_BAD_FLAG;
    }
    elsif ($condition eq "")
    {
        printCEMsg("EMsgERRMcliPrereqed", "-R");
        &print_usage;
        return ERRM_CLI_BAD_FLAG;
    }
    $Opt_rR= $TRUE;
}
elsif (defined $opts{A})
{
    if (defined $opts{r})
    {
        printCEMsg("EMsgERRMcliImproperUsageCombination", "-A", "-r");
        &print_usage;
        return ERRM_CLI_BAD_FLAG;
    }
    elsif ($condition eq "")
    {
        printCEMsg("EMsgERRMcliPrereqed", "-A");
        &print_usage;
        return ERRM_CLI_BAD_FLAG;
    }
    $Opt_A= $TRUE;
}
elsif (!defined $opts{r} && $condition ne "" && @responses)
{
    $Opt_rR= $TRUE;
}

if (defined $opts{B}) 
{
    $Opt_Start_Time= $TRUE;
    $Start_Time= $opts{B};
}

if (defined $opts{E})
{
    $Opt_End_Time= $TRUE;
    $End_Time= $opts{E};
}

if (defined $opts{O})
{
    if ($opts{O} <= 0)
    {
        printEMsg("EMsglseventBadEntryValue");
        return ERRM_CLI_BAD_OPERAND;
    }
    elsif (defined $opts{a})
    {
        printCEMsg("EMsgERRMcliImproperUsageCombination", "-O", "-a");
        &print_usage;
        return ERRM_CLI_BAD_FLAG;
    }
    elsif(defined $opts{n})
    {
        printCEMsg("EMsgERRMcliImproperUsageCombination", "-O", "-n");
        &print_usage;
        return ERRM_CLI_BAD_FLAG;
    }
    $Opt_Entries= $TRUE;
    $entries= $opts{O};
}

if (defined $opts{e}) 
{
    $event_type= $opts{e};
    # verify its a valid event type
    for ($j=0;$j<length($event_type);$j++) {
        # look at each event type specified
        $tmp_event = substr($event_type,$j,1);
        if( ( $valid_opte !~ /$tmp_event/) || ($event_spec{$tmp_event} == $TRUE))
        {
            printCEMsg("EMsgERRMcliImproperUsageOperand", $opts{e});
            &print_usage;
            return ERRM_CLI_BAD_OPERAND;
        }
        $event_spec{$tmp_event} = $TRUE;
        $_ = $tmp_event;
        SWITCH: {
            if(/a/) {$etype_spec{91} = $TRUE; last SWITCH;}
            if(/r/) {$etype_spec{92} = $TRUE; last SWITCH;}
            if(/e/) {$etype_spec{118} = $TRUE; last SWITCH;}
            if(/b/) {$etype_spec{91} = $TRUE; $etype_spec{92} = $TRUE;last SWITCH;}
            if(/A/) {
                $etype_spec{91} = $TRUE; 
                $etype_spec{92} = $TRUE; 
                $etype_spec{118} = $TRUE; 
                last SWITCH;
            }
        }
    }
    $etype_spec{121} = $TRUE; 
    $Opt_Event= $TRUE;
}
                              

if (defined $opts{a})                   # -a, list all nodes
{
    if (defined $opts{n})
    {
        printCEMsg("EMsgERRMcliImproperUsageCombination", "-a", "-n");
        &print_usage;
        return ERRM_CLI_BAD_FLAG;    
    }
    $Opt_Cluster = $TRUE;
}

if (defined $opts{n})                   # -n, list nodes
{
    if ($opts{n} eq "")
    {
       printCEMsg("EMsgERRMcliMissingRequiredFlagOperand","-n");
       &print_usage; 
       return ERRM_CLI_BAD_OPERAND;     
    }
    $Opt_Nodes = $TRUE;
    $nodes= $opts{n};
}

if (defined $opts{i}) {                 # -i, list status
    $Opt_Status = $TRUE;
}

if (defined $opts{T}) {                 # -T, turn tracing on
    $Trace = $TRUE;
}

if (defined $opts{V}) {                 # -V, turn verbose mode on
    $Verbose = $TRUE;
}

if (defined $opts{w}) {                 # -w, node list
    if (defined $opts{r})
    {
        printCEMsg("EMsgERRMcliImproperUsageCombination", "-w", "-r");
        &print_usage;
        return ERRM_CLI_BAD_FLAG;
    }
    elsif (defined $opts{R})
    {
        printCEMsg("EMsgERRMcliImproperUsageCombination", "-w", "-R");
        &print_usage;
        return ERRM_CLI_BAD_FLAG;
    }
    elsif (defined $opts{A})
    {
        printCEMsg("EMsgERRMcliImproperUsageCombination", "-w", "-A");
        &print_usage;
        return ERRM_CLI_BAD_FLAG;
    }
    elsif (@responses)
    {
        printCEMsg("EMsgERRMcliBadCombination", "-w");
        &print_usage;
        return ERRM_CLI_BAD_FLAG;
    }
    $Opt_Node = $TRUE;
    $node= $opts{w};
}

# success
return(0, $Start_Time, $End_Time, $nodes, $node, $entries, $event_type, $condition, @responses);
}   # end parse_cmd_line


#--------------------------------------------------------------------#
# get_records:  get the records from the auditlog and display them   #
#--------------------------------------------------------------------#
sub get_records
{
my ($nodes, $opt_s)= @_;

if ($opt_s ne "")
{
    # escape double quotes
    $opt_s =~ s/"/\"/sg;
    # enclose the opts in quotes
    $opt_s= "-s \"$opt_s\"";
}

$cmd = qq(/usr/bin/lsaudrec -l -S ERRM $nodes$opt_s Time Category Message 2>&1);
@output = `$cmd`;
$rc= $?;

$rc = &process_exit_code($rc);

if ($Trace)
{
    print STDERR "- cmd:\n$cmd\n";
    print STDERR "- lsaudrec results:\n@output";
    print STDERR "- lsaudrec rc:\n$rc\n\n";
}

# lsaudrec exits with rc=5 when the time format is not valid
if ($rc)
{
    if ($rc == 5)
    {
        printEMsg("EMsglseventBadTimeFormat");
        &print_usage;
        exit ERRM_CLI_BAD_OPERAND;
    }
    print @output;
    exit $rc;
}

print @output;

# In case lsaudrec fails, but the rc=0
if ($output[0] =~ /^2639-105 lsaudrec:/)
{
    exit ERRM_CLI_ERROR;
}
}


#--------------------------------------------------------------------#
# print_usage : print the usage statement (syntax) to stdout.        #
#   See this command's prologue syntax section for current usage.    #
#--------------------------------------------------------------------#
sub print_usage
{
 printIMsg("IMsglseventUsage");
}   # end print_usage