#!/usr/bin/perl
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 2000,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 = "@(#)28   1.25   src/rsct/rm/SensorRM/cli/bin/lssensor.perl, sensorcli, rsct_rady, rady2035a 11/12/15 16:37:17"

# Lists resources from the RMC IBM.Sensor class

use strict;
use locale;
BEGIN
  {
	# this enables us to redirect where it looks for other RSCT files during development
	$::rsctroot = $ENV{'RSCT_ROOT'} || '/opt/rsct';
	$::rsctpm = "$::rsctroot/pm";
	$::rsctmsgmaps = "$::rsctroot/msgmaps";
  }

use lib $::rsctpm;
use Getopt::Long;
use CT_cli_utils qw(printIMsg printEMsg);
use CT_cli_display_utils qw(set_display);
use CT_cli_input_utils qw(
    check_input_file
    unescape_chars
);
use MC_cli_utils qw(
     read_from_Stdin
     process_api_error
     remove_api_error
);

$main::PROGNAME = 'lssensor';
$main::MSGCAT = 'sensorcli.cat';
$main::LSMSG = '/opt/rsct/bin/ctdspmsg';

# For the usage, see sensorcli.msg
#sub usage { printIMsg('IMsgLssensorUsage2');  exit (scalar(@_) ? $_[0] : 1); }
#sub usage { printIMsg('IMsgLssensorUsage3');  exit (scalar(@_) ? $_[0] : 1); }
sub usage { printIMsg('IMsgLssensorUsage4');  exit (scalar(@_) ? $_[0] : 1); }

Getopt::Long::Configure ("bundling", "no_auto_abbrev",
                         "no_ignore_case", "require_order",
                         "prefix_pattern=(--|-)");
                         
# Parse the cmd line args and check them
if(!GetOptions( 'h|help|version' ,
                'A' ,
                'a' ,
                'd' ,
                'l' ,
                'm' ,
                't' ,
                'v' ,
                'V' ,
                'x' ,
                'D=s' ,
                'n=s',
                'N=s' ))
{
    &usage;
}
if ($::opt_h) { &usage(0); }
if ((scalar(@ARGV)>0 && $::opt_A) ||
    (defined($::opt_n) && defined($::opt_N)) ||
    ($::opt_a && defined($::opt_N)) ||
    ($::opt_a && defined($::opt_n)))
{
    &usage;
}

if ($::opt_V) { $::opt_v = 1; }

# determine the class to use
my $CLASSNAME = "IBM.Sensor";
if ($::opt_m) { $CLASSNAME = "IBM.MicroSensor"; }

my $options = '';
my $selectstr = '';
my $attr = '';
my $format = "column";
my $delim= "";
my $No_HDR= 0;
my $node_file_flag = 0;                    # node_file_flag =1         if -N was specified.
my $node_file_name = "";                   # node_file_name
my $node_file_from_stdin = 0;              # node_file_from_stdin = 1  if -N '-'
my @dcount =();
my @output_wmsgs = ();
my $name = '';

# set -api command delimiters
my $DELIMITERI = "tvitvitvi";
my $DELIMITERO = "tvotvotvo";


if ($::opt_A)       # show everything
{
    $options = "-I $DELIMITERI -D $DELIMITERO -n -i";
    $attr = "'*b0x0020'";
    $format = "old_long";
}
elsif (scalar(@ARGV) >= 1)       # show all attributes of this sensor
{
    $options = "-I $DELIMITERI -D $DELIMITERO -n";
    $attr = "'*b0x0020'";
    $name = join("','",@ARGV);
    $selectstr = q/Name IN ('/ . join("','",@ARGV) . q/')/;
    $format = "old_long";
}
else           # show all sensor names
{
    $options = "-I $DELIMITERI -D $DELIMITERO -n -i";
    $attr = 'Name';
    if ($::opt_a || defined($::opt_n)||defined($::opt_N)) { $attr .= "${DELIMITERI}NodeNameList"; }
}

if ($::opt_l)
{   
#   if (!$No_HDR)
#   {
        $format= "long";
#   }
}
elsif ($::opt_t)
{
    $format = "column";
    $delim= $DELIMITERO;
}
elsif($::opt_d)
{
    $format = "delim";
    $delim= ":";
}
elsif ($::opt_D)
{
    $format= "delim"; 
    $delim= "$::opt_D";
}

if ($::opt_x)
{
    $No_HDR= 1;
}


if ($::opt_a || defined($::opt_n) || defined($::opt_N))
{
    if ($ENV{CT_MANAGEMENT_SCOPE}!=2 && $ENV{CT_MANAGEMENT_SCOPE}!=3)
    {
        $ENV{CT_MANAGEMENT_SCOPE}=4;
    }
}

if (defined($::opt_n))
  {
	my @nodes = split(/[, ]+/,$::opt_n);
	if (length($selectstr)) { $selectstr .= ' && '; }
	$selectstr .= q/NodeNameList IN ('/ . join("','",@nodes) . q/')/;
  }

if (defined($::opt_N))
{
    $node_file_name = $::opt_N;
    $node_file_flag = 1;

    if ( $node_file_name eq "-" )
    {
        $node_file_from_stdin = 1;
    } else
    {
        if ( check_input_file($node_file_name) )
        {
            exit(1);
        }
    }
}
if (length($selectstr)) { $selectstr = qq("$selectstr"); }

# setup lsrsrc-api cmdline.
my $cmd = '';

if ( $node_file_flag == 0 )
{
    $cmd = qq(/usr/bin/lsrsrc-api $options -s ${CLASSNAME}${DELIMITERI}${selectstr}${DELIMITERI}$attr 2>&1);
} else
{
    if ($node_file_from_stdin != 0)
    {
        $node_file_name = read_from_Stdin();
    }
    $cmd = qq(/usr/bin/lsrsrc-api $options -w ${CLASSNAME}${DELIMITERI}${selectstr}${DELIMITERI}${node_file_name}${DELIMITERI}$attr 2>&1);
}
if ($::opt_v) { printIMsg('IMsgRmcCmd', $cmd); }

my @output = `$cmd`;

my $rc = $? >> 8;
# remove temp node file if it is from STDIN
if ($node_file_from_stdin != 0)
{
    unlink($node_file_name);
}
#if ($rc)
#{
#    #if (!$::opt_v) { $output[0] =~ s/.*:\|:.*:\|:.*:\|:.*:\|:.*:\|://; }
#    #print @output;
#    #exit $rc;
#    process_api_error(':\|:', $rc, @output);
#    @output = remove_api_error(':\|:', @output);
#}
@output_wmsgs = @output;
@output = remove_api_error($DELIMITERO, @output);
my $lsrc = $rc;
chop(@output);

# add in any dynamic attrs that aren't monitored
if ( ! ($attr =~ /^Name$/) ) { &reformatOutput; }

# show any error messages from original output
# suppress "dyn attr not monitored" msg, unless verbose
$lsrc = &process_api_most_error($DELIMITERO, $lsrc, @output_wmsgs);

if ( $#output <0 ) { exit ($lsrc); }

# Display output
if ($format eq "old_long") 
{ 
    &displayLong;
}
else
{
    my $divider= `$main::LSMSG $main::PROGNAME $main::MSGCAT IMsgLssensorDivider`;
    my $line;
    my $i;
    my $j= 1;
    my @Lof_conds=();

    # Create a Header
    $Lof_conds[0][0] = `$main::LSMSG $main::PROGNAME $main::MSGCAT IMsgLssensorOut`;
    if ($format eq "delim")
    {
        $Lof_conds[0][0]= $Lof_conds[0][0] . "\n";
    }

    $line = $output[0];
    my %attrnames = split(/$DELIMITERO/, $line);
    $j = 1;
    # $Lof_conds[0][$j]= "Name";  
    $Lof_conds[0][$j]= scalar(`$main::LSMSG $main::PROGNAME $main::MSGCAT IMsgLssensorNameHeading`);  
    delete $attrnames{Name};

    foreach my $attrname (sort keys %attrnames)
    {
        $j++;
        $Lof_conds[0][$j]= $attrname;
    }
    
    $j = 1;

    foreach $line (@output)
    {
      
     if ($j == 1) { $Lof_conds[$j][0] = "$divider $j:"; }
     else  { $Lof_conds[$j][0] = "\n$divider $j:"; }
      
      my %attrs = split(/$DELIMITERO/, $line);
       
      # Convert the value of TimeCommandRun to a user friendly one
      if ( defined($attrs{TimeCommandRun}) && ($attrs{TimeCommandRun} ne "") )
      {
          $attrs{TimeCommandRun}= localtime($attrs{TimeCommandRun});
      }
      if ( defined($attrs{LastQueryTime}) && ($attrs{LastQueryTime} ne "") )
      {
          $attrs{LastQueryTime}= localtime($attrs{LastQueryTime});
      }

      # Make sure the hostname is displayed 1st
      if (defined($attrs{Name}))
      {
          $Lof_conds[$j][1]= $attrs{Name};
          $i= 2;
          delete $attrs{Name};     # so we do not repeat it in the following loop
      }
      else
      {
          $i= 1;
      }

      foreach my $k (sort keys %attrs)
      {
        # Fill the Attributes values
        $Lof_conds[$j][$i]= $attrs{$k};
        $i++;
      }
      $j++;
    }
    
    my $row_count = $#Lof_conds;
    my $col_count = scalar(@{$Lof_conds[0]});
    $rc = set_display($format, $No_HDR, $row_count, $col_count, \@Lof_conds, $delim);
}

if ( $lsrc != 0) { exit ($lsrc); }



sub displayLong
{
my $firsttime = 1;
foreach my $l (@output)
  {
	if (!$firsttime) { print "-------------------\n"; }   # separate this resource from the previous
	else { $firsttime = 0; }

	# takes the alternating attrs and values and puts them in the hash correctly
	my %attrs = split(/$DELIMITERO/, $l);


	# Make sure the hostname is displayed 1st
	if (defined($attrs{Name}))
	  {
		print " Name = $attrs{Name}\n";
		delete $attrs{Name};          # so we do not repeat it in the following loop
	  }

        # Convert the value of TimeCommandRun to a user friendly one
        if ( defined($attrs{TimeCommandRun}) && ($attrs{TimeCommandRun} ne "") )
	    {
           $attrs{TimeCommandRun}= localtime($attrs{TimeCommandRun});
	    }
        if ( defined($attrs{LastQueryTime}) && ($attrs{LastQueryTime} ne "") )
	    {
           $attrs{LastQueryTime}= localtime($attrs{LastQueryTime});
	    }

	# Now display the rest of the attributes, sorted
	foreach my $k (sort keys %attrs)
        {
  	  print " $k = $attrs{$k}\n"; 
        }
  }
}

sub reformatOutput
# merge the output from lsrsrc-api and lsrsrcdef-api and reformat it 
# so it works with the existing display routines
{
  my @junk = ();
  my @dynattr = ();

  # get a list of dynamic attributes
  my $cmd2 = '';
  $cmd2 = qq(/usr/bin/lsrsrcdef-api -I $DELIMITERI -D $DELIMITERO -r ${CLASSNAME}${DELIMITERI}*d0x0020 2>&1);
  if ($::opt_v) { printIMsg('IMsgRmcCmd', $cmd2); }
  my @defoutput = `$cmd2`;
  my $rc2 = $? >> 8;
  process_api_error($DELIMITERO, $rc2, @defoutput);
  @defoutput = remove_api_error($DELIMITERO, @defoutput);

  # create array of dynamic attr names
  my $m=0;
  foreach my $l2 (@defoutput)
  {
     if  ( !( $l2 =~ /CT_NONE/ ) ) 
     { 
        ($dynattr[$m], @junk) =  split (/$DELIMITERO/, $l2);
        $m++;
     }
  }

  # loop through each resource
  my $i =0;
  for  ($i=0; $i<=$#output; $i++)
  {
     @dcount[$i]=0;
     my %attrs = split(/$DELIMITERO/, $output[$i]);
     # check to see if all dynamic attrs are in @output line
     foreach my $dattr (@dynattr)
     {
       if ( ! defined ($attrs{$dattr}) )
       {
          # add it to @output
          $output[$i] .= "$DELIMITERO${dattr}$DELIMITERO";
       }
       else
       {
          # count that we got a dyn attr from lsrsrc-api
          @dcount[$i]++;
       }
     }
  }
}


sub process_api_most_error
{
   my $delimiter = shift(@_);              # output delimiter
   my $api_rc    = shift(@_);              # rc from c-api call
   my @command_output = @_;                # command output to scan
   my $error_count = 0;                    # number of error messages
   my @error_parts = ();
   my $dyn_error_count = 0;                # number of error messages
   my $RMC_DYNATTR_NOTMONITORED_RC = 262177; # RMC rc if dynamic attr not monitored

   # scan each line for ERROR
   foreach my $line (@command_output) 
   {

      # does it start with ERROR?
      if ($line =~ /^ERROR.*/) 
      {

         # split it apart based on double colons
         # last one should be error message
         @error_parts = split /$delimiter/, $line;

  
         # replace any escaped new lines with new lines
         $error_parts[$#error_parts] =~ s/\\n/\n/g;

         # get rid of any beginning/ending quote that comes from
         # having CT_CLI_QUOTE_STRING turned on (sometimes)
         if ( defined $ENV{CT_CLI_QUOTE_STRING} && $ENV{CT_CLI_QUOTE_STRING}==1) 
         {
            $error_parts[$#error_parts] =~ s/^\"//;
            $error_parts[$#error_parts] =~ s/\"$//;
            #$error_parts[$#error_parts] =~ s/\\\"/\"/g;
            $error_parts[$#error_parts] = unescape_chars($error_parts[$#error_parts]);
         }
         if ( ($::opt_v) || ($error_parts[4] != $RMC_DYNATTR_NOTMONITORED_RC) )
         {
            # last one should be error message. print it to STDERR.
	     if($lsrc == 6)
            {
                if ($::opt_v) { print STDERR $error_parts[$#error_parts]; }
                printEMsg('EMsgResNotDefinedLs',$name);
            }
            else
            {
                print STDERR $error_parts[$#error_parts];
            }
         }
         if ($error_parts[4] == $RMC_DYNATTR_NOTMONITORED_RC) { $dyn_error_count++; }
         else { $error_count++; }
      }
   }

   # set the return code based on how many non-"dyn attr not monitored" msgs there are
   if ($error_count > 0)  
   {
      return ($api_rc);
   }
   else 
   # if only non-"dyn attr not monitored" msgs, reset rc to 0
   {
      return (0);
   }
}   #  end of process_api_most_error