#!/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 = "@(#)58   1.11   src/rsct/rm/LPRM/cli/bin/chlpriacl.perl, LPRM, rsct_rady, rady2035a 11/12/15 16:38:42"
######################################################################
#                                                                    #
# Module: chlpriacl                                                  #
#                                                                    #
# Purpose:                                                           #
#   chlpriacl  - Change the access controls for the LPRM Resource    #
#                Initial ACL.                                        #
#                                                                    #
# Syntax:                                                            #
#   To add one or more accesses to the LPRM Resource Initial ACL:    #
#   chlpriacl [-a|-n host1[,host2,...]] [-o] [-h] [-TV] Id Perm [Id  #
#   Perm ...]                                                        #
#                                                                    #
#   To add one or more accesses to the LPRM Resource Initial ACL     #
#   using the same permissions:                                      #
#   chlpriacl [-a|-n host1[,host2,...]] -l [-o] [-h] [-TV]  Id       #
#   [Id...] Perm                                                     #
#                                                                    #
#   To delete one or more accesses from the LPRM Resource Initial    #
#   ACL:                                                             #
#   chlpriacl [-a|-n host1[,host2,...]] -d [-h] [-TV]  Id [Id...]    #
#                                                                    #
#   To add or delete accesses to the LPRM Resource Initial ACL with  #
#   the accesses specified in a file:                                #
#   chlpriacl [-a|-n host1[,host2,...]] [-o|-d] -f File_name [-h]    #
#   [-TV]                                                            # 
#                                                                    #
#   To set the LPRM Resource Initial ACL to deny all accesses or to  #
#   use the Resource Shared ACL:                                     #
#   chlpriacl [-a|-n host1[,host2,...]] {-b|-x} [-h] [-TV]           #
#                                                                    #
#                                                                    #
# Flags:                                                             #
#   -a      Changes the LPRM Resource Initial ACLs on all nodes in   #
#           the domain.                                              #
#   -b      Set the LPRM Resource Initial ACL to use the Resource    #
#           Shared ACL.                                              #
#   -d      The ACL entry for the Id specified is deleted from the   #
#           LPRM Resource Initial ACL.                               #
#   -f      The accesses are specified in a file. Each line of the   #
#           file will be an Id and permission for that ID.  If -d    #
#           is used with -f, only the id is used.  Anything else     #
#           is ignored.                                              #
#   -l      There is a list of Ids followed by a single permission.  #
#   -n host1[,host2,...]                                             #
#           Changes the LPRM Resource Initial ACLs on the nodes      #
#           specified in the domain.                                 #
#   -o      Overwrite any existing ACL entries.                      #
#   -x      Set the LPRM Resource Initial ACL to deny all accesses.  #
#   -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:                                                        #
#   Id      The network identity of the user.                        #
#   Perm    The permission the ID is to have.                        #
#                                                                    #
# Description:                                                       #
#   The chlpriacl command changes the LPRM Resource Initial ACL.     #
#   This command allows an access to be added to or deleted  from    #
#   the LPRM Resource Initial ACL.  The LPRM Resource Initial ACL is #
#   is copied to the LPRM Resource ACL of a newly created LPRM       #
#   resource.  There is one LPRM Resource Initial ACL on each node.  #
#                                                                    #
# 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 allow user joe on nodeA to have write permission to the    #
#      LPRM Resource Initial ACL on nodeA, run on nodeA:             #
#      chlpriacl joe@LOCALHOST w                                     #
#                                                                    #
# Man Page:                                                          #
#   For the most current detailed description of this command see    #
#   the chlpriacl man page in /opt/rsct/man.                    #
#                                                                    #
#--------------------------------------------------------------------#
# Inputs:                                                            #
#   /opt/rsct/msgmaps/lprmcli.lslpriacl.mapi, -                 # 
#       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.                       #
#   050126 JAC 117175: Fix for -b and -x not working.                #
#   050128 JAC 117280: Fix for -l not working.                       #
#   050128 JAC 117199: Display error when no parameters specified.   #
#   050203 JAC 117535: Change call to process_api_error.             #
#   050210 JAC 117760: Don't allow -o and -d.                        #
#   050224 JAC 118185: Add additional checking of number of inputs.  #
#   071028 JAC 146726: 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 chrsrcacl. 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 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
                      process_api_error
                      process_exit_code
                      get_ids_perms_from_file
                      get_ids_from_file
                      ispermvalid);
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_Deny = $FALSE;                     # default - no deny all access
$Opt_Shared = $FALSE;                   # default - don't use shared acl
$Opt_AllNodes = $FALSE;                 # default - not all nodes      
$Opt_NodeList = $FALSE;                 # default - not node list       
$Opt_Overwrite = $FALSE;                # default - no overwrite
$Opt_IDlist = $FALSE;			# default - not ID ID Perm 
$Opt_Delete = $FALSE;			# default - not delete
$Opt_Filename = $FALSE;         	# default - no filename

$PROGNAME = "chlpriacl";                # 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 @parameters = ();                    # input parameters 
my $node_list = "";                     # node list from -n
my $file_name = "";                     # file name from -f
my $id = "";                            # user id
my $perm = "";                          # user permission
my $cmd_opts = "";                      # chrsrcacl-api options
my $cmd_parms = "";                     # chrsrcacl-api parameters
my @cmd_out = ();                       # chrsrcacl-api output

my $i = 0;                              # loop counter

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

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

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

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

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

# 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("IMsgchlpriaclProcessOptions"); }

# process the input file if necessary
if ($Opt_Filename) {

   if ($Verbose) { printIMsg("IMsgchlpriaclProcessFileInput"); }
 
   # get the ids and permissions from the file
   if ($Opt_Delete) {
     
      @parameters = get_ids_from_file($file_name);
   }
   else {

      @parameters = get_ids_perms_from_file($file_name);
   }
}

# set up the call to chrsrcacl-api

# set deny access if -x specified
if ($Opt_Deny) { 
   $cmd_opts = $cmd_opts . " -X "; 
   $cmd_parms = ${DELIMITERI};
}

# use shared acl if -b specified
if ($Opt_Shared) { 
   $cmd_opts = $cmd_opts . " -S "; 
   $cmd_parms = ${DELIMITERI};
}

# set overwrite if -o specified
if ($Opt_Overwrite) { $cmd_opts = $cmd_opts . " -O "; }

# build id/permission string
if ($Opt_Delete) {
   # build list of ids with 'Z' permission for delete
   foreach $id (@parameters) {
      chomp($id);
      $cmd_parms = $cmd_parms . $DELIMITERI . $id . $DELIMITERI . "Z";
   }
}

elsif ($Opt_IDlist){
   # build list using last one as permission
   $perm = $parameters[$#parameters];

   # is it a valid permission
   $rc = ispermvalid($perm);
   if ($rc !=0) {
      printCEMsg("EMsgLPRMcliBadPerm",$perm);
      exit(LPRM_CLI_USER_ERROR);
   }

   # form id/perm list
   for ($i=0; $i<$#parameters; $i++) { 
      $id = $parameters[$i];
      chomp($id);
      $cmd_parms = $cmd_parms . $DELIMITERI . $id . $DELIMITERI . $perm;
   }
}

else {  # it's a id/perm repeating list
   # must be an even number of parameters (remember 0 origin)
   if (($#parameters % 2) == 0) {
      printCEMsg("EMsgLPRMcliBadIdPermList");
      exit(LPRM_CLI_USER_ERROR);
   }

   # form id/perm list
   for ($i=0; $i<=$#parameters; $i=$i+2) { 
      $id = $parameters[$i];
      chomp($id);
      $perm = $parameters[$i+1];
      chomp($perm);

      # is it a valid permission
      $rc = ispermvalid($perm);
      if ($rc !=0) {
         printCEMsg("EMsgLPRMcliBadPerm",$perm);
         exit(LPRM_CLI_USER_ERROR);
      }
      $cmd_parms = $cmd_parms . $DELIMITERI . $id . $DELIMITERI . $perm;
   }
}

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

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

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

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

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

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

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

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

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.      #
#   $parameters              List of Ids and Permissions.            #
#   $node_list               List of nodes for -n.                   #
#   $file_name               File name for -f.                       #
#                                                                    #
# Global Variables Modified:                                         #
#   $Verbose           output   True (-V) turn Verbose mode on.      #
#   $Trace             output   True (-T) turn Trace mode on.        #
#   $Opt_Deny          output   True (-x) deny access specified.     #
#   $Opt_Shared        output   True (-b) use shared ACL.            #
#   $Opt_AllNodes      output   True (-a) all nodes specified.       #
#   $Opt_NodeList      output   True (-n) nodes listed.              #
#   $Opt_Overwrite     output   True (-o) overwrite specified.       #
#   $Opt_IDlist        output   True (-l) multi Ids w/1 permission.  #
#   $Opt_Delete        output   True (-d) delete specified.          #
#   $Opt_Filename      output   True (-f) filename specified.        #
#--------------------------------------------------------------------#
sub parse_cmd_line 
{
my(@original_argv) = @ARGV;
my @parameters = ();                    # Ids/permission list
my $node_list = "";                     # nodes for -n 
my $file_name = "";                     # file name for -f  
my %opts = ();

# Process the command line...
if (!&getopts('abdf:hln:oxTV', \%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{d}) {                 # -d to delete access
    $Opt_Delete = $TRUE;                # -d flag specified
}

if (defined $opts{f}) {                 # -f for file input
    if ($#ARGV >=0) {                   # can't have parameters for -f
       printCEMsg("EMsgLPRMcliInvalidNumberOfOperands");
       &print_usage;
       return LPRM_CLI_BAD_OPERAND;
    }
    $Opt_Filename = $TRUE;              # -f flag specified
    $file_name = $opts{f};
}

if (defined $opts{l}) {                 # -l for list of Ids
    # error if -d is specified
    if ($Opt_Delete) {
       printCEMsg("EMsgLPRMcliImproperUsageCombination","-l","-d");
       &print_usage;
       return LPRM_CLI_BAD_FLAG;
    }
    # error if -f is specified
    if ($Opt_Filename) {
       printCEMsg("EMsgLPRMcliImproperUsageCombination","-l","-f");
       &print_usage;
       return LPRM_CLI_BAD_FLAG;
    }
    $Opt_IDlist = $TRUE;                # -l flag specified
}

if (defined $opts{o}) {                 # -o to overwrite access
    # error if -d is specified
    if ($Opt_Delete) {
       printCEMsg("EMsgLPRMcliImproperUsageCombination","-o","-d");
       &print_usage;
       return LPRM_CLI_BAD_FLAG;
    }
    $Opt_Overwrite = $TRUE;             # -o flag specified
}

if (defined $opts{x}) {                 # -x for deny all access
    if ($#ARGV >=0) {                   # can't have parameters for -x
       printCEMsg("EMsgLPRMcliInvalidNumberOfOperands");
       &print_usage;
       return LPRM_CLI_BAD_OPERAND;
    }
    # error if -d is specified
    if ($Opt_Delete) {
       printCEMsg("EMsgLPRMcliImproperUsageCombination","-x","-d");
       &print_usage;
       return LPRM_CLI_BAD_FLAG;
    }
    # error if -f is specified
    if ($Opt_Filename) {
       printCEMsg("EMsgLPRMcliImproperUsageCombination","-x","-f");
       &print_usage;
       return LPRM_CLI_BAD_FLAG;
    }
    # error if -l is specified
    if ($Opt_IDlist) {
       printCEMsg("EMsgLPRMcliImproperUsageCombination","-x","-l");
       &print_usage;
       return LPRM_CLI_BAD_FLAG;
    }
    $Opt_Deny = $TRUE;                  # -x flag specified
}

if (defined $opts{b}) {                 # -b to use shared acl
    if ($#ARGV >=0) {                   # can't have parameters for -b
       printCEMsg("EMsgLPRMcliInvalidNumberOfOperands");
       &print_usage;
       return LPRM_CLI_BAD_OPERAND;
    }
    # error if -x is specified
    if ($Opt_Deny) {
       printCEMsg("EMsgLPRMcliImproperUsageCombination","-b","-x");
       &print_usage;
       return LPRM_CLI_BAD_FLAG;
    }
    # error if -d is specified
    if ($Opt_Delete) {
       printCEMsg("EMsgLPRMcliImproperUsageCombination","-b","-d");
       &print_usage;
       return LPRM_CLI_BAD_FLAG;
    }
    # error if -f is specified
    if ($Opt_Filename) {
       printCEMsg("EMsgLPRMcliImproperUsageCombination","-b","-f");
       &print_usage;
       return LPRM_CLI_BAD_FLAG;
    }
    # error if -l is specified
    if ($Opt_IDlist) {
       printCEMsg("EMsgLPRMcliImproperUsageCombination","-b","-l");
       &print_usage;
       return LPRM_CLI_BAD_FLAG;
    }
    $Opt_Shared = $TRUE;                 # -b flag specified
}

# Get the arguments...
# Operands:  Id perm Id perm OR Id Id perm or Id or nada
if ($#ARGV >= 0) {                      # Name and Ids and perms
   # if -d used, must be at least 1 argument unless -f also is used
   if ( $Opt_Delete ) {
      if ( $Opt_Filename ) {
         printCEMsg("EMsgLPRMcliInvalidNumberOfOperands");
         &print_usage;
         return LPRM_CLI_BAD_OPERAND;
      }
      else {
         if (! ($#ARGV >= 0) ) {
            printCEMsg("EMsgLPRMcliInvalidNumberOfOperands");
            &print_usage;
            return LPRM_CLI_BAD_OPERAND;
         }
      }
      @parameters = @ARGV;                 # get them all
   }
   # if -x or -f used, should be no parameters
   elsif ( $Opt_Deny || $Opt_Filename ) {
         printCEMsg("EMsgLPRMcliInvalidNumberOfOperands");
         &print_usage;
         return LPRM_CLI_BAD_OPERAND;
   }
   # else there must be at least 2 arguments
   elsif ( $#ARGV <= 0 ) {
      printCEMsg("EMsgLPRMcliInvalidNumberOfOperands");
      &print_usage;
      return LPRM_CLI_BAD_OPERAND;
   }
   else {
      @parameters = @ARGV;                 # get them all
   }
}
else {
   # if no args, display error unless -f|-x|-b used
   if (! ($Opt_Deny || $Opt_Filename || $Opt_Shared) ) {
      printCEMsg("EMsgLPRMcliInvalidNumberOfOperands");
      &print_usage;
      return LPRM_CLI_BAD_OPERAND;
   }
}

return(0, $node_list, $file_name, @parameters);     # success

}   # end parse_cmd_line


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