#!/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,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 = "@(#)62   1.9   src/rsct/rm/LPRM/cli/bin/lslprsacl.perl, LPRM, rsct_rady, rady2035a 11/12/15 16:38:37"
######################################################################
#                                                                    #
# Module: lslprsacl                                                  #
#                                                                    #
# Purpose:                                                           #
#   lslprsacl  - List the Resource Shared ACL for the LPRM class.    #
#                                                                    #
# Syntax:                                                            #
#   lslprsacl [-a|-n host1[,host2,...]] [-l|-t|-d|-D delimiter]      #
#   [-E] [-p] [-x] [-h] [-TV]                                        #
#                                                                    #
#   lslprsacl [-n host] -i [-E] [-h] [-TV]                           #
#                                                                    #
#                                                                    #
# Flags:                                                             #
#   -a      Lists the Resource Shared ACLs on all nodes in the       #
#           domain.                                                  #
#   -d      Displays information using delimiters. The default       #
#           delimiter is a pipe (|). Use -D the select a delimiter.  #
#   -D delimiter                                                     #
#           Displays information using the specified delimiter.      #  
#   -E      Displays permission in long form.  "r" for read is       #
#           displayed using the permissions that comprise it, "e",   #
#           "l", "q", and "v", and "w" for write is displayed using  #
#           the permissions that comprise it, "c", "d", "o", and "s".#
#   -i      Generates a template in a form that can be used, after   #
#           editing, as file input to the chlpclacl command.         #
#   -l      Displays information on separate lines (long format).    #
#   -n host1[,host2,...]                                             #
#           Lists the Resource Shared ACLs on the nodes specified    #
#           in the domain.                                           #
#   -p      Displays the peer domain name in which the LPRM class    #
#           is defined.                                              #
#   -t      Displays information in separate columns (table format). #
#           This is the default format.                              #
#   -x      Excludes the header (suppresses the header printing).    #
#   -h      Help. Writes the command's usage statement to standard   #
#           output.                                                  #
#   -T      Trace. Writes the command's trace messages to standard   #
#           error. For your software-service organization's use only.#
#   -V      Verbose. Writes the command's verbose messages to        #
#           standard output.                                         #
#                                                                    #
# Parameters:                                                        #
#   None.                                                            #
#                                                                    #
# Description:                                                       #
#   The lplprsacl command lists the Resource Shared ACL for the      #
#   LPRM class. The LPRM Resource Shared ACL can be used for the     #
#   Resource ACL or Resource Initial ACL to share its ACL.           #
#                                                                    #
# Exit Values:                                                       #
#   0  LPRM_CLI_SUCCESS      Command completed successfully.         #
#   1  LPRM_CLI_RMC_ERROR    Command terminated due to an underlying #
#                            RMC error.                              #
#   2  LPRM_CLI_ERROR        Command terminated due to an underlying #
#                            error in the command script.            #
#   3  LPRM_CLI_BAD_FLAG     Command terminated due to user          #
#                            specifying an invalid flag.             #
#   4  LPRM_CLI_BAD_OPERAND  Command terminated due to user          #
#                            specifying a bad operand.               #
#   5  LPRM_CLI_USER_ERROR   Command terminated due to a user error, #
#                            for example specifying a name that      #
#                            already exists.                         #
#                                                                    #
# Examples:                                                          #
#   1. To list the accesses defined in the Resource Shared ACL, run: #
#      lslprsacl                                                     #
#                                                                    #
# Man Page:                                                          #
#   For the most current detailed description of this command see    #
#   the chlpclacl man page in /opt/rsct/man.                    #
#                                                                    #
#--------------------------------------------------------------------#
# Inputs:                                                            #
#   /opt/rsct/msgmaps/lprmcli.lslprsacl.map -                   # 
#       message mapping                                              #
#                                                                    #
# Outputs:                                                           #
#   stdout - none.                                                   #
#   stderr - any error message.                                      #
#                                                                    #
# External Ref:                                                      #
#   Commands: ctdspmsg                                               #
#   Modules:  LPRM_cli_utils.pm, LPRM_cli_rc.pm,                     #
#             LPRM_cli_include.pm, CT_cli_utils.pm                   #
#   Perl library routines: Getopt::Std                               #
#                                                                    #
# Tab Settings:                                                      #
#   4 and tabs should be expanded to spaces before saving this file. #
#   in vi:  (:set ts=4  and   :%!expand -4)                          #
#                                                                    #
# Change Activity:                                                   #
#   050107 JAC 112254: Initial design & write.                       #
#   050122 JAC 116808: Minor changes to output.                      #
#   050130 JAC 117312: Some minor changes for -i.                    #
#   050203 JAC 117535: Change call to process_api_error.             #
#   050228 JAC 118165: Make the display formats exclusive.           #
#   050307 JAC 118052: Return correct rc.                            #
#   071029 JAC 142726: set delimiters for calling -api commands.     #
######################################################################

#--------------------------------------------------------------------#
# General Program Flow/Logic:                                        #
#                                                                    #
# 1. Parse command line flags and operands.                          #
# 2. Print usage if -h specified.                                    #
# 3. Set the appropriate management scope.                           #
# 4. Call RMC command lprsrcacl. Also pass along -VT if necessary.   #
# 5. Return back any errors.                                         #
#                                                                    #
#--------------------------------------------------------------------#

#--------------------------------------------------------------------#
# Included Libraries and Extensions                                  #
#--------------------------------------------------------------------#
use lib "/opt/rsct/pm";
use locale;
use Getopt::Std;

use CT_cli_utils qw(printIMsg
                    printEMsg);

use CT_cli_display_utils qw(set_display);

use LPRM_cli_rc qw(LPRM_CLI_SUCCESS LPRM_CLI_RMC_ERROR
                   LPRM_CLI_ERROR LPRM_CLI_BAD_FLAG
                   LPRM_CLI_BAD_OPERAND LPRM_CLI_USER_ERROR);
use LPRM_cli_utils qw(error_exit
                      printCIMsg
                      printCEMsg
                      getIMsg
                      process_api_error
                      remove_api_error
                      process_exit_code);
use LPRM_cli_include qw($TRUE $FALSE
                       $RMC_LOCAL_SCOPE $RMC_LOCAL2_SCOPE
                       $RMC_DM_SR_LOCAL_SCOPE
                       $DELIMITERI $DELIMITERO
                       $CTBINDIR $CTDIR);

#--------------------------------------------------------------------#
# Global Variables                                                   #
#--------------------------------------------------------------------#
$Trace = $FALSE;                        # default - trace off
$Verbose = $FALSE;                      # default - verbose turned off

$Opt_AllNodes = $FALSE;                 # default - not all nodes      
$Opt_NodeList = $FALSE;                 # default - not node list       

$Opt_Delm_Format = $FALSE;              # default - no delim output
$Opt_Delm_Str = "|";                    # default - pipe
$Opt_Long_Format = $FALSE;              # default - not long format
$Opt_Table_Format = $TRUE;              # default - use tabular format
$Opt_No_HDR = $FALSE;                   # default - no exclude header
$Opt_LS_Input_File = $FALSE;            # default - no file output
$Opt_ExpandPerm = $FALSE;               # default - don't expand perms
$Opt_PeerDomain = $FALSE;               # default - don't show peer domain

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

#--------------------------------------------------------------------#
# Variables                                                          #
#--------------------------------------------------------------------#
my $node_list = "";                     # node list from -n
my $cmd_opts = "";                      # lsrsrcacl-api options
my $cmd_parms = "";                     # lsrsrcacl-api parameters
my @cmd_out = ();                       # lsrsrcacl-api output
my @lsacl_out = ();                     # output from lsrsrcacl-api
my @heading = ();                       # output heading
my @col_headings = ();                  # individual heading
my $col_heading_name = "";              # heading for parsing
my @lof_acls = ();                      # 2D array to be displayed      
my $i = 0;                              # loop counter
my $j = 0;                              # loop counter
my $k = 0;                              # loop counter
my @NoAclText = ();                     # text for No Acl
my @acl_entries = ();                   # returned acl entries 
my $acl_entry = "";                     # acl entry
my $node_str = "";                      # use for long output
my $pd_str = "";                        # use for long output

#--------------------------------------------------------------------#
# Main Code                                                          #
#--------------------------------------------------------------------#
my $rc = 0;
my $p_rc = 0;

# parse the command line, exit if there are errors 
($rc, $node_list) = &parse_cmd_line;
($rc == 0) || error_exit($rc);

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

if ($Trace) { $cmd_opts = $cmd_opts." -T"; }
if ($Verbose) { $cmd_opts = $cmd_opts." -V"; }

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

# if -a and -n were not specified, set local RMC scope
if ( (!$Opt_AllNodes) && (!$Opt_NodeList)) {
   $ENV{CT_MANAGEMENT_SCOPE} = $RMC_LOCAL_SCOPE;
}
# set DM/SR scope is scope is not set
else {

   # if CT_MANAGEMENT_SCOPE is not defined, set it to 4 for DM/SR/Local scope
   if (!defined $ENV{CT_MANAGEMENT_SCOPE}) {
      $ENV{CT_MANAGEMENT_SCOPE} = $RMC_DM_SR_LOCAL_SCOPE;
   }

   # if it's defined, it shouldn't be local.  If it's local, set it
   # to 4 for DM/SR/Local scope
   else {
      if ($ENV{CT_MANAGEMENT_SCOPE} == $RMC_LOCAL_SCOPE ||
          $ENV{CT_MANAGEMENT_SCOPE} == $RMC_LOCAL2_SCOPE) {
             $ENV{CT_MANAGEMENT_SCOPE} = $RMC_DM_SR_LOCAL_SCOPE;
      }
   }
}

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

# process the command

# set expand permissions if -E specified
if ($Opt_ExpandPerm) { $cmd_opts = $cmd_opts . " -E "; }

# set display peer domains if -p specified
if ($Opt_PeerDomain) { $cmd_opts = $cmd_opts . " -u "; }

# call lsrsrcacl-api
if ($Verbose) { printIMsg("IMsglslprsaclListAcl"); }
if ($Trace) { print STDERR "$PROGNAME: calling lsrsrcacl-api\n";}

@lsacl_out=`$CTBINDIR/lsrsrcacl-api -I ${DELIMITERI} -D ${DELIMITERO} $cmd_opts -nb IBM.LPCommands${DELIMITERI}${node_list}${cmd_parms} 2>&1`;

# capture the return code from lsrsrcacl-api
$rc = $?;
$rc = process_exit_code($rc);

if ($Trace) { print STDERR "lsrsrcacl-api results:\n";
              print STDERR "@lsacl_out";}

if ($Trace) { print STDERR "$PROGNAME: lsrsrcacl-api returned $rc\n";}

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

# show any errors if there was a bad rc
if ($rc != 0) {
   process_api_error($DELIMITERO,$rc,@lsacl_out);
   @lsacl_out = remove_api_error(@lsacl_out);
}

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

# form 2D array to pass to display utils

# get heading from message file
if ($Opt_PeerDomain) { @heading = getIMsg("IMsglslprsaclHeadingPD"); }
else { @heading = getIMsg("IMsglslprsaclHeading"); }

# form heading
@col_headings = split(/::/,$heading[0]);
$i = 1;
foreach $col_heading_name (@col_headings) {
   $lof_acls[0][$i] = $col_heading_name;
   $i++;
}

# get from message file what to use for "No Acl" (no access)
@NoAclText = getIMsg("IMsglslprsaclNoAcl");

# set up Title text from column headings
$node_str = $col_headings[$#col_headings];
if ($Opt_PeerDomain) {
   $node_str = $col_headings[$#col_headings-1];
   $pd_str = $col_headings[$#col_headings];
}

if (!$Opt_No_HDR) { printIMsg("IMsglslprsaclTitle"); }

# form each line of output
$i = 1;
$k = 1;
foreach $line (@lsacl_out) {
   chomp($line);

   # parse the output
   @acl_entries = split(/$DELIMITERO/, $line);

   # put into array
   $lof_acls[$i][0] = "$node_str $acl_entries[0]";
   if ($Opt_PeerDomain) { $lof_acls[$i][0] .= ", $pd_str $acl_entries[1]"; }

   $j = 1;
   if ($Opt_PeerDomain) { $j = 2; }

   while ($j <= $#acl_entries) {

      # check for no ACL
      if ( $acl_entries[$j] eq "N" ){
         $lof_acls[$i][1] = $NoAclText[0]; 
         $lof_acls[$i][2] = ""; 
         $lof_acls[$i][3] = $acl_entries[0]; 
         if ($Opt_PeerDomain) { $lof_acls[$i][4] = $acl_entries[1]; }
      }

      else {
         # the 1st one is the ID and the 2nd is the permission
         $lof_acls[$i][1] = $acl_entries[$j]; 
         $lof_acls[$i][2] = $acl_entries[$j+1]; 
         $lof_acls[$i][3] = $acl_entries[0]; 
         if ($Opt_PeerDomain) { $lof_acls[$i][4] = $acl_entries[1]; }
      }
      $j = $j+2;
      $i++;
   }
   $k++;
}

# set how many rows of data there is
$row_count = $#lof_acls;
$col_count = scalar(@{$lof_acls[0]});
if ( $Opt_Long_Format ) { $col_count--; }
if ( $Opt_Long_Format && $Opt_PeerDomain ) { $col_count--; }

# use regular output methods
if (!$Opt_LS_Input_File) {

   # set formatting string needed by set_display
   ($Opt_Long_Format)  && ($display_type = "long");
   ($Opt_Table_Format) && ($display_type = "column");
   ($Opt_Delm_Format)  && ($display_type = "delim");

   # print out results, if any
   if ($row_count > 0) {
      $p_rc = set_display($display_type, $Opt_No_HDR, $row_count, $col_count,
                        \@lof_acls, $Opt_Delm_Str);
      if ($rc == 0) { $rc = $p_rc; }
   }
}

# else output id/perm for -i
else {

   # print the output 
   for ($i=1; $i<=$row_count; $i++){
      print ($lof_acls[$i][1],"\t", $lof_acls[$i][2],"\n");
   }
}

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

exit($rc); 

#--------------------------------------------------------------------#
# 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.   #
#         LPRM_CLI_BAD_FLAG  Command line contained a bad flag.      #
#   $node_list               List of nodes for -n.                   #
#                                                                    #
# Global Variables Modified:                                         #
#   $Verbose           output   True (-V) turn Verbose mode on.      #
#   $Trace             output   True (-T) turn Trace mode on.        #
#   $Opt_Delm_Format   output   True (-d,-D) delimited output        #
#   $Opt_Delm_Str      output   char (-D) delimiter character        #
#   $Opt_Long_Format   output   True (-l) long formatted output      #
#   $Opt_Table_Format  output   True (-t) tabular formatted output   #
#   $Opt_No_HDR        output   True (-x) supress heading            #
#   $Opt_LS_Input_File output   True (-i) file formatted output.     #
#   $Opt_AllNodes      output   True (-1) all nodes.                 #
#   $Opt_NodeList      output   True (-n) nodes listed.              #
#   $Opt_ExpandPerm    output   True (-E) nodes listed.              #
#   $Opt_PeerDomain    output   True (-p) show peer domain.          #
#--------------------------------------------------------------------#
sub parse_cmd_line 
{
my(@original_argv) = @ARGV;
my $node_list = "";                     # nodes for -n 
my %opts = ();

# Process the command line...
if (!&getopts('adD:Ehiln:ptxTV', \%opts)) {   # Gather options; 
                                        # if errors
    &print_usage;                       # display proper usage
    return LPRM_CLI_BAD_FLAG;           # return bad rc - bad flag 
}

# process h flag
if (defined $opts{h}) {                 # -h, help request
    &print_usage;                       # print usage statement
    exit(0);                            # all done with good return!
}

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

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

if (defined $opts{a}) {                 # -a for all nodes in domain
    $Opt_AllNodes = $TRUE;              # -a flag specified
}

if (defined $opts{n}) {                 # -n for list of nodes
    # error if -a is specified
    if ($Opt_AllNodes) {
       printCEMsg("EMsgLPRMcliImproperUsageCombination","-a","-n");
       &print_usage;
       return LPRM_CLI_BAD_FLAG;
    }
    $Opt_NodeList = $TRUE;              # -n flag specified
    $node_list = $opts{n};
}

if (defined $opts{E}) {                 # -E for expand permissions
    $Opt_ExpandPerm = $TRUE;            # -E flag specified
}

if (defined $opts{p}) {                 # -p for display peer domain
    $Opt_PeerDomain = $TRUE;            # -p flag specified
}

if (defined $opts{D}) {                 # -D delimited output with specified
    $Opt_Delm_Format = $TRUE;           #    delimiter
    $Opt_Delm_Str = $opts{D};
    $Opt_Long_Format = $FALSE;
    # error if -d is specified
    if (defined $opts{d}) {
       printCEMsg("EMsgLPRMcliImproperUsageCombination","-D","-d");
       &print_usage;
       return LPRM_CLI_BAD_FLAG;
    }
    # error if -l is specified
    if (defined $opts{l}) {
       printCEMsg("EMsgLPRMcliImproperUsageCombination","-D","-l");
       &print_usage;
       return LPRM_CLI_BAD_FLAG;
    }
    # error if -t is specified
    if (defined $opts{t}) {
       printCEMsg("EMsgLPRMcliImproperUsageCombination","-D","-t");
       &print_usage;
       return LPRM_CLI_BAD_FLAG;
    }
    # error if -i is specified
    if (defined $opts{i}) {
       printCEMsg("EMsgLPRMcliImproperUsageCombination","-D","-i");
       &print_usage;
       return LPRM_CLI_BAD_FLAG;
    }
}

if (defined $opts{d}) {                 # -d delimited output
    $Opt_Delm_Format = $TRUE;
    $Opt_Delm_Str = "|";
    $Opt_Long_Format = $FALSE;
    # error if -l is specified
    if (defined $opts{l}) {
       printCEMsg("EMsgLPRMcliImproperUsageCombination","-d","-l");
       &print_usage;
       return LPRM_CLI_BAD_FLAG;
    }
    # error if -t is specified
    if (defined $opts{t}) {
       printCEMsg("EMsgLPRMcliImproperUsageCombination","-d","-t");
       &print_usage;
       return LPRM_CLI_BAD_FLAG;
    }
    # error if -i is specified
    if (defined $opts{i}) {
       printCEMsg("EMsgLPRMcliImproperUsageCombination","-d","-i");
       &print_usage;
       return LPRM_CLI_BAD_FLAG;
    }
}

if (defined $opts{t}) {                 # -t table formatted output
    $Opt_Table_Format = $TRUE;
    $Opt_Long_Format = $FALSE;
    $Opt_Delm_Format = $FALSE;
    # error if -l is specified
    if (defined $opts{l}) {
       printCEMsg("EMsgLPRMcliImproperUsageCombination","-t","-l");
       &print_usage;
       return LPRM_CLI_BAD_FLAG;
    }
    # error if -i is specified
    if (defined $opts{i}) {
       printCEMsg("EMsgLPRMcliImproperUsageCombination","-t","-i");
       &print_usage;
       return LPRM_CLI_BAD_FLAG;
    }
}

if (defined $opts{l}) {                 # -l long formatted output
    $Opt_Long_Format = $TRUE;
    $Opt_Table_Format = $FALSE;
    $Opt_Delm_Format = $FALSE;
    # error if -i is specified
    if (defined $opts{i}) {
       printCEMsg("EMsgLPRMcliImproperUsageCombination","-l","-i");
       &print_usage;
       return LPRM_CLI_BAD_FLAG;
    }
}

if (defined $opts{x}) {                 # -x supress headings
    $Opt_No_HDR = $TRUE;
}

if (defined $opts{i}) {                 # -i input file format
    # error if -a is specified
    if ($Opt_AllNodes) {
       printCEMsg("EMsgLPRMcliImproperUsageCombination","-a","-i");
       &print_usage;
       return LPRM_CLI_BAD_FLAG;
    }
    # error if -n is specified and >1 node
    if ($Opt_NodeList) {
          if ( $node_list =~ /,/ ) {
              printCEMsg("EMsgLPRMcliImproperNumNodes");
              &print_usage;
              return LPRM_CLI_BAD_FLAG;
          }
    }
    $Opt_LS_Input_File = $TRUE;
    $Opt_No_HDR = $TRUE;                # don't print a header for -i
}

# Chaeck for arguments...  none needed
if ($#ARGV >= 0) {                      # any args?
   printCEMsg("EMsgLPRMcliInvalidNumberOfOperands");
   &print_usage;
   return LPRM_CLI_BAD_OPERAND;
}

return(0, $node_list);     # success

}   # end parse_cmd_line


#--------------------------------------------------------------------#
# print_usage : print the usage statement (syntax) to stdout.        #
#--------------------------------------------------------------------#
sub print_usage
{
&printIMsg("IMsglslprsaclUsage");
}   # end print_usage