#!/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 = "@(#)75   1.18.1.19   src/rsct/rm/ER/cli/bin/mkresponse.perl, errmcli, rsct_rady, rady2035a 11/12/15 16:39:40"
######################################################################
#                                                                    #
# Module: mkresponse                                                 #
#                                                                    #
# Purpose:                                                           #
#   mkresponse - make an event response resource                     #
#                                                                    #
# Syntax:                                                            #
#   mkresponse [-h] [-n ActionName [-d DaysOfWeek ...]               #
#              [-t TimeOfDay ...] -s ActionScript [-r ReturnCode]    #
#              [-e a|r|b|e|A] [-o] [-p Node_name] [-b]               #
#              [-E Env_var=Value[,Env_var=Value,...]] [-u]]          #
#              [-TV] Response                                        #
#                                                                    #
#   mkresponse [-h] -c ExistingResponse:[Node_name]                  # 
#              [-p Node_name] [-TV] Response                         #
# Flags:                                                             #
#   -h      help - writes this command's usage statement to stdout   #
#   -b      Specifies that the response and all actions to be defined#
#           in this response support event batching. The -b flag     #
#           cannot be specified with the -e flag.                    #
#   -c      ExistingResponse to copy to a new Response. Node_name    #
#           specified where it is defined.                           #
#   -n      ActionName.  The name of the first action to create in   #
#           this response.                                           #
#   -d      DaysOfWeek.  The days that this action is allowed to be  #
#           used. 1=Sunday, 2=Monday, etc.  Use +'s between dates    #
#           and -'s for ranges (ex:1+7 or 2-6).  More than one       #
#           DaysOfWeek can be specified and is separated by (,)      #
#           comma.  Number of DaysOfWeek must match number of        #
#           TimeOfDay. Default is everyday (1-7).                    #
#   -t      TimeOfDay.  The time that this action is allowed to be   #
#           used for the corresponding DaysOfWeek. It is specified   #
#           in 24 hour format as HHMM (ex:1700 for 5pm). More than   #
#           one TimeOfDay can be specified and is separated by (,)   #
#           comma.  Number of DaysOfWeek must match number of        #
#           TimeOfDay. Default is all day (0000-2400).               # 
#   -s      ActionScript.  The script or command that is executed    #
#           for this action.                                         #
#   -r      ReturnCode.  The expected return code for ActionScript.  #
#           If specified, the actual return code is compared to this #
#           expected return code and the result is written to the    #
#           AuditLog.  The default is not to check the return code.  #
#   -e      a|r|b|e|A.  Determines if the action is for an arm event,#
#           a rearm event, or both, or for an error event, or for    #
#           any type of event. Default is a.                         #
#   -o      Specifying -o saves the standard out output of the       #
#           ActionScript to the Audit Log.  Default is not to save   # 
#           the standard out.                                        #
#   -p      Specifies the node on which the response is defined.     #
#   -E      Env_var=Value.  Specifies any environment variables to   #
#           be set prior to running the Action script.               #
#   -u      Specifies that the action is to be run when a monitored  #
#           resource becomes undefined.                              #
#   -T      Trace. IBM Support Center use only.                      #
#   -V      Verbose.                                                 #
#                                                                    #
# Operands:                                                          #
#   Response        The name of the new response to be created.      #
#                                                                    #
# Description:                                                       #
#   The mkresponse command creates a new response definition with    #
#   the name specified by the Response operand.  Actions define      #
#   commands to be run when the response is used with a condition    #
#   and the condition occurs. The action defines days of the week    #
#   when the action can be used, the time of day for those days of   #
#   of the week, the script or command to run, what type of event    #
#   causes the command to be run, the expected return code of the    #
#   script or command, and whether to keep standard output.  The     #
#   days and times are paired so that different times can be         #
#   specified for different days.                                    #
#                                                                    #
#   The chresponse command can be used to add actions to a response  #
#   or to remove actions from a response.  Monitoring can be started #
#   by using the startcondresp command.  The startcondresp command   #
#   links a response to a condition if they are not already linked.  #
#                                                                    #
# Exit Values:                                                       #
#   0  ERRM_CLI_SUCCESS      Command completed successfully.         #
#   1  ERRM_CLI_RMC_ERROR    Command terminated due to an underlying #
#                            RMC error.                              #
#   2  ERRM_CLI_ERROR        Command terminated due to an underlying #
#                            error in the command script.            #
#   3  ERRM_CLI_BAD_FLAG     Command terminated due to user          #
#                            specifying an invalid flag.             #
#   4  ERRM_CLI_BAD_OPERAND  Command terminated due to user          #
#                            specifying a bad operand.               #
#   5  ERRM_CLI_USER_ERROR   Command terminated due to a user error. #
#                            For example specifying a name that      #
#                            already exists.                         #
#                                                                    #
# Examples:                                                          #
#   1. Define a response with the name "E-mail root anytime" that    #
#      has an action named "E-mail root", to be used anytime Saturday#
#      and Sunday, uses the command "/opt/rsct/bin/notifyevent  #
#      root", for both arm and rearm events:                         #
#      mkresponse -n "E-mail root" -d 1+7       \                    #
#           -s "/opt/rsct/bin/notifyevent root" -e b     \      #
#           "E-mail root anytime"                                    #
#   2. Define a response with the name "E-mail root anytime" that    #
#      has an action named "E-mail root", to be used anytime Saturday#
#      and Sunday, but only 8am to 5pm Monday through Friday, uses   #
#      the command  "/opt/rsct/bin/notifyevent root" for        #
#      arm events:                                                   #
#      mkresponse -n "E-mail root" -d 1+7,2-6      \                 #
#           -t 0000-2400,0800-1700                 \                 #
#           -s "/opt/rsct/bin/notifyevent root" -e a     \      #
#           "E-mail root anytime"                                    #
#   3. Define a response with the name "E-mail root first shift" that#
#      has an action named "E-mail root", Monday through Friday,     #
#      8am to 6pm, uses the command  "/opt/rsct/bin/notifyevent #
#      root" for rearm events, and saves the standard output in the  #
#      Audit Log, expecting a return code of 5:                      #
#      mkresponse -n "E-mail root" -d 2-6 -t 0800-1800      \        #
#           -s "/opt/rsct/bin/notifyevent root" -e r -o   \     #
#           -r 5  "E-mail root first shift"                          #
#   4. Define a response with the name "Critical notifications" as a #
#      copy of "Warning notifications":                              #
#      mkresponse -c "Warning notifications" "Critical notifications"#
#                                                                    #
# Man Page:                                                          #
#   For the most current detailed description of this command see    #
#   the mkresponse man page in /opt/rsct/man.                   #
#                                                                    #
#--------------------------------------------------------------------#
# Inputs:                                                            #
#   /opt/rsct/msgmaps/errmcli.mkresponse.map - message mapping  #
#                                                                    #
# Outputs:                                                           #
#   stdout - none.                                                   #
#   stderr - any error message.                                      #
#                                                                    #
# External Ref:                                                      #
#   Commands: ctdspmsg                                               #
#   Modules:  ERRM_cli_utils.pm, ERRM_cli_rc.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:                                                   #
#   001102 JAC 67469: Initial design & write.                        #
#   001228 JAC 67470: Completed mkresponse command.                  #
#   010103 JAC 70296: Make TRUE/FALSE come from utils.               #
#   010122 JAC 70355: Update messages from final command doc.        #
#   010125 JAC 70882: Modify mkrsrc calls for string parsing.        #
#   010129 JAC 70951: Shift rc after RMC calls if error occurs.      #
#   010212 JAC 71203: Process default date and time properly.        #
#   010308 JAC 71005: Escape some special characters in strings.     #
#   010501 JAC 73619: Do not send any RMC CLI std err to garbage.    #
#   010507 JAC 73620: Check for RMC CLI user error (rc=5) and        #
#                     return ERRM user error for this case.          #
#   010615 JAC 72970: use alternate form to call mkrsrc              #
#   011130 JAC 77597: Add distributed RMC changes                    #
#   011128 JAC 77599: Add processing for new EnvList in Actions.     #
#   011203 JAC 78058: Add processing for new UndefResFlag in Actions.#
#   011206 JAC 78841: Fix selection string for locating resources.   #
#   020121 JAC 79558: Fix selection string for locating resources.   #
#   020128 JAC 79559: Change how destination/locator node is used.   #
#   020212 JAC 77598: Allow Actions to be optional.                  #
#   020411 JAC 81754: Fix exit code check and Switch to xxx-api cmds.#
#   020719 JAC 84425: Add $rc to process_api_error call.             #
#   020729 JAC 85061: Use 4 (DM/SR/local) for scope if locator used  #
#                     or -p used and scope not set.                  #
#   040407 JAC 105863: Use escape_chars for "\" searches.            #
#   071026 JAC 146726: set delimiter for -api commands.              #
#   080104 JAC 148354: remove reference to resolve_node.             #
#   081031 JAC 153203: add error events.                             #
#   081111 JAC 153204: add event batching.                           #
######################################################################

#--------------------------------------------------------------------#
# General Program Flow/Logic:                                        #
#                                                                    #
# 1. Parse command line flags and operands, determine which flavor   #
#    of this command we are actually invoking.                       #
#    This command allows a user to create responses                  #
# 2. Print usage if -h specified                                     #
# 3. Make sure one and only one response is specified and make sure  #
#    it doesn't exist.                                               #
# 4. If -c for copy is specified, list the response to get the       #
#    attribute information.                                          #
# 5. Translate flags into attribute names for RMC mkrsrc command.    #
# 6. Call RMC command mkrsrc. Also pass along -VT if necessary.      #
# 7. Return back any errors.                                         #
#                                                                    #
#--------------------------------------------------------------------#

#--------------------------------------------------------------------#
# 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
                    find_resource_name get_source_node
                    get_locator_node
                    parse_days_string
                    parse_time_string
                    set_orig_rmc_scope check_set_cluster_scope
                    process_exit_code
                    process_api_error
                    $TRUE $FALSE
                    $DELIMITERI $DELIMITERO
                    $CTDIR $CTBINDIR
                    $RMC_CLI_USER_ERROR $RMC_CLI_RSRC_NOT_FOUND
                    $RMC_LOCAL_SCOPE
                    $EVENT_BATCHING_ON $EVENT_BATCHING_OFF
                    @EVENTTYPE @EVENTTPCD
                    $MKRSRC $LSRSRC $RSCEVRS);

#--------------------------------------------------------------------#
# Global Variables                                                   #
#--------------------------------------------------------------------#
Getopt::Long::Configure ("bundling", "no_auto_abbrev",
                         "no_ignore_case", "require_order",
                         "prefix_pattern=(--|-)");

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

$Scope_orig_set = $FALSE;               # default - no CT_MANAGEMENT_SCOPE
$Scope_orig_value = 0;                  # default - scope value

$Opt_Actions = $FALSE;                  # default - no actions 
$Opt_DaysOfWeek = $FALSE;               # default - no days
$Opt_TimeOfDay = $FALSE;                # default - no time
$Opt_ReturnCode = $FALSE;               # default - no return code
$Opt_RetCodeCheck = $FALSE;             # default - no ret code check
$Opt_EventType = $FALSE;                # default - no event type
$Opt_StdOut = $FALSE;                   # default - no std out
$Opt_CopyResp = $FALSE;                 # default - no copy from
$Opt_Put_Node = $FALSE;                 # default - no put node
$Opt_EnvList = $FALSE;                  # default - no env vars
$Opt_UndefRes = $FALSE;                 # default - no undefres
$Opt_Batching = $FALSE;                 # default - no event batching

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

#--------------------------------------------------------------------#
# Variables                                                          #
#--------------------------------------------------------------------#
my $response = "";                      # Response to make
my $copyresp_name = "";                 # response name to copy for -c
my $action_name = "";                   # action name to create for -n
my $days_of_week = "";                  # expression for -d
my $days_coded = "";                    # days to pass to RMC CLI
my $ndays_coded = 0;                    # number of days to pass along
my $time_of_day = "";                   # expression for -t
my $st_time_coded = "";                 # start times for RMC CLI
my $end_time_coded = "";                # end times for RMC CLI
my $ntimes_coded = 0;                   # number of times to pass along
my $action_script = "";                 # action command from -s
my $env_vars = "";                      # environment vars from -E
my $return_code = 0;                    # return code for -r 
my $ret_code_flag = 0;                  # default ret code check
my $undefres_flag = 0;                  # default undefres flag 
my $event_type = "";                    # event type for -e
my $std_out = 0;                        # description for -o
my $put_node = "";                      # where to define condition -p
my $passopts = "";                      # options to pass to RMC
my $other_opts = "";                    # options to pass to RMC
my $event_part = $EVENTTPCD[0];         # event part of Actions
my $rc_part = "";                       # the rc part of Actions
my $stdout_part = 0;                    # the stdout part of Actions
my $i = 0;                              # loop counter
my @cmdout = ();                        # for error messages
my $event_batching = $EVENT_BATCHING_OFF; # no event batching 

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

# save original rmc management scope value, in case it's changed later
if (defined $ENV{CT_MANAGEMENT_SCOPE}) {
   $Scope_orig_set = $TRUE;
   $Scope_orig_value = $ENV{CT_MANAGEMENT_SCOPE};
}

# parse the command line, exit if there are errors 
($rc, $response, $action_name, $days_of_week, $time_of_day, 
 $action_script, $return_code, $event_type, $event_batching,
 $copyresp_name, $put_node, $env_vars) = &parse_cmd_line;
($rc == 0) || error_exit($rc);

if ($Verbose) { printIMsg("IMsgmkresponseStart",$response); }

if ($Trace) { $passopts = $passopts." -T"; }

if ($Verbose) { $passopts = $passopts." -V"; }

# check if copy flag was specified.  If so, process copy.
if ($Opt_CopyResp) {

   # get response information for the response to be copied
   $copy_action = get_response_info($copyresp_name);

   # set CT_MANAGEMENT_SCOPE to original setting, in case it was used
   set_orig_rmc_scope;

   # if the put node (-p, or destination node) was not specified,
   # this is a local definition.  Make sure rmc scope is set to
   # local scope.
   if (!$Opt_Put_Node) {                # put node not present
      $ENV{CT_MANAGEMENT_SCOPE} = $RMC_LOCAL_SCOPE;
   }
   else {                               # put node present
      # specify where to put the response
#     $other_opts = $other_opts." NodeNameList='{$put_node}'";
      $other_opts = $other_opts."${DELIMITERI}NodeNameList${DELIMITERI}{$put_node}";

      # use DM/SR/Local scope if scope not set
      check_set_cluster_scope;
   }

   if ($Trace) { print STDERR "$PROGNAME: calling mkrsrc-api\n";}

   # call RMC mkrsrc to create the response resource
#  `$CTBINDIR/$MKRSRC $passopts $RSCEVRS Name="$response" Actions='$copy_action' $other_opts`;
   @cmd_out=`$CTBINDIR/mkrsrc-api -I $DELIMITERI -D $DELIMITERO "${RSCEVRS}${DELIMITERI}Name${DELIMITERI}${response}${DELIMITERI}Actions${DELIMITERI}$copy_action${other_opts}" 2>&1`;

   $rc = $?;
   }   # end copy response

# else copy flag not specified. Create new response.
# see if there is an action
elsif ($Opt_Actions) {

#  # set up date
#  if (!$Opt_DaysOfWeek) {$days_of_week = "1-7";} # default - all days 
#  ($ndays_coded,$days_coded) = parse_days_string($days_of_week);
#
#  # set up time
#  if (!$Opt_TimeOfDay) {$time_of_day = "0000-2400";} # default - all day 
#  ($ntimes_coded,$st_time_coded, $end_time_coded) = parse_time_string($time_of_day);

   # check to see if -d and/or -t was specified.  Make sure that
   # if one or the other wasn't specified, the number of default
   # values set matches what was specified.   (71203)
 
   # check to see if -d was not specified
   if (!$Opt_DaysOfWeek) {

      # check to see if -t was specified
      if ($Opt_TimeOfDay) {

         # process the times specified
         ($ntimes_coded,$st_time_coded, $end_time_coded) = parse_time_string($time_of_day);

         # make enough default dates to match
         $days_of_week = "1-7";
         for ($i=2;$i<=$ntimes_coded;$i++){
             $days_of_week = $days_of_week.",1-7";
             }

         # process the default dates
         ($ndays_coded,$days_coded) = parse_days_string($days_of_week);
         }   # end of -t specified (but no -d)

      else {  # no -t (and no -d)
         # set the default for days and times
         $days_of_week = "1-7";
         $time_of_day = "0000-2400";

         # process the days and times
         ($ndays_coded,$days_coded) = parse_days_string($days_of_week);
         ($ntimes_coded,$st_time_coded, $end_time_coded) = parse_time_string($time_of_day);
         
         }    # end of no -t and no -d

      }    # end of no -d specified

   else  {  # -d specified 

      # check to see if -t was specified
      if ($Opt_TimeOfDay) {

         # process the days and times
         ($ndays_coded,$days_coded) = parse_days_string($days_of_week);
         ($ntimes_coded,$st_time_coded, $end_time_coded) = parse_time_string($time_of_day);
         }   # end of -t specified (with -d)
         
      else {  # no -t (but -d)

         # process the dates specified
         ($ndays_coded,$days_coded) = parse_days_string($days_of_week);

         # make enough default times to match
         $time_of_day = "0000-2400";
         for ($i=2;$i<=$ndays_coded;$i++){
             $time_of_day = $time_of_day.",0000-2400";
             }

         # process the default times
         ($ntimes_coded,$st_time_coded, $end_time_coded) = parse_time_string($time_of_day);

         }    # end of no -t with -d
      }    # end of -d specified

   # check number of days/times. error if not the same 
   if ($ndays_coded != $ntimes_coded) {
       printEMsg("EMsgmkresponseNumDaysTimesDiff");
       exit(ERRM_CLI_USER_ERROR);
       }

   if ($Opt_EventType) { $event_part = $event_type; } # -e was specified         
   if ($Opt_StdOut) { $stdout_part = 1; }             # -o was specified         
   if ($Opt_RetCodeCheck) { $ret_code_flag = 1; }     # -r was specified         
   if (!$Opt_ReturnCode) { $return_code = 0; }        # -r not specified         
   if ($Opt_UndefRes) { $undefres_flag = 1; }         # -u was specified        
   if ($Opt_Put_Node) {                               # -p was specified
#     $other_opts = $other_opts." NodeNameList='{$put_node}'";
      $other_opts = $other_opts."${DELIMITERI}NodeNameList${DELIMITERI}{$put_node}";
   } 
   if ($Opt_Batching) {                               # -b was specified
      $other_opts = $other_opts."${DELIMITERI}EventBatching${DELIMITERI}${event_batching}";
   }

   # scan for special characters in env_vars, 1st \ then "
   #$env_vars =~ s/\\/\\\\/g;
   #$env_vars =~ s/\"/\\\"/g;
   $env_vars = escape_chars($env_vars);

   # scan for special charactes in action_script, including $
   $action_script = escape_chars($action_script);
   $action_script =~ s/\$/\\\$/g;

   # set CT_MANAGEMENT_SCOPE to original setting, in case it was used
   set_orig_rmc_scope;

   # if the put node (-p, or destination node) was not specified,
   # this is a local definition.  Make sure rmc scope is set to
   # local scope.
   if (!$Opt_Put_Node) {                   # put node not present
      $ENV{CT_MANAGEMENT_SCOPE} = $RMC_LOCAL_SCOPE;
   }

   else {
      # use DM/SR/Local scope if scope not set
      check_set_cluster_scope;
   }

   if ($Trace) { print STDERR "$PROGNAME: calling mkrsrc-api\n";}

   # call RMC mkrsrc to create the response resource
#  `$CTBINDIR/$MKRSRC $passopts $RSCEVRS Name="$response" Actions="{[\\\"$action_name\\\",{$days_coded},{$st_time_coded},{$end_time_coded},\\\"$action_script\\\",$event_part,$ret_code_flag,$return_code,$stdout_part,{$env_vars},$undefres_flag]}" $other_opts`;

   $mkrsrcapi_cmd="${RSCEVRS}${DELIMITERI}Name${DELIMITERI}${response}${DELIMITERI}Actions${DELIMITERI}{[$action_name,{$days_coded},{$st_time_coded},{$end_time_coded},$action_script,$event_part,$ret_code_flag,$return_code,$stdout_part,{$env_vars},$undefres_flag]}${other_opts} ";

   @cmd_out=`$CTBINDIR/mkrsrc-api -I $DELIMITERI -D $DELIMITERO \"$mkrsrcapi_cmd\" 2>&1`;

   $rc = $?;
   }   # end create response with action (copy not specified)

# the only thing left is that it's a response with no actions
else {

   # set CT_MANAGEMENT_SCOPE to original setting, in case it was used
   set_orig_rmc_scope;

   # if the put node (-p, or destination node) was not specified,
   # this is a local definition.  Make sure rmc scope is set to
   # local scope.
   if ($Opt_Batching) {                               # -b was specified
      $other_opts = $other_opts."${DELIMITERI}EventBatching${DELIMITERI}${event_batching}";
   }
   if (!$Opt_Put_Node) {                   # put node not present
      $ENV{CT_MANAGEMENT_SCOPE} = $RMC_LOCAL_SCOPE;
   }
   else {
      $other_opts = $other_opts."${DELIMITERI}NodeNameList${DELIMITERI}{$put_node}";

      # use DM/SR/Local scope if scope not set
      check_set_cluster_scope;
   }

   if ($Trace) { print STDERR "$PROGNAME: calling mkrsrc-api\n";}

   # call RMC mkrsrc to create the response resource
#  `$CTBINDIR/$MKRSRC $passopts $RSCEVRS Name="$response" $other_opts`;
   @cmd_out=`$CTBINDIR/mkrsrc-api -I $DELIMITERI -D $DELIMITERO "${RSCEVRS}${DELIMITERI}Name${DELIMITERI}${response}${other_opts}" 2>&1`;

   $rc = $?;
   }   # end create response with no action 

$rc = &process_exit_code($rc);

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

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

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

# return ERRM CLI user error if it's an RMC CLI user error    73620
($rc == $RMC_CLI_USER_ERROR) && ( error_exit(ERRM_CLI_USER_ERROR) );

# if mkrsrc command failed, print RMC error message and exit
if ($rc != 0) {
#  printCEMsg("EMsgERRMcliUnExpectRMCrc",$rc);
   exit(ERRM_CLI_RMC_ERROR);
}

if ($Verbose) { printIMsg("IMsgmkresponseEnd",$response); }

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.   #
#         ERRM_CLI_BAD_FLAG  Command line contained a bad flag.      #
#   $resource                Name of resource to be removed.         #
#                                                                    #
# Global Variables Modified:                                         #
#   $Verbose           output   True (-V) turn Verbose mode on.      #
#   $Trace             output   True (-T) turn Trace mode on.        #
#   $Opt_Actions       output   True (-n) action specified           #
#   $Opt_DaysOfWeek    output   True (-d) days specified             #
#   $Opt_TimeOfDay     output   True (-t) times specified            #
#   $Opt_ReturnCode    output   True (-r) return code specified      # 
#   $Opt_RetCodeCheck  output   True (-r) return code specified      # 
#   $Opt_EventType     output   True (-e) event type specified       # 
#   $Opt_StdOut        output   True (-o) std out specified          #
#   $Opt_CopyResp      output   True (-c) copy specified             #
#   $Opt_Put_Node      output   True (-p) put node specified         #
#   $Opt_EnvList       output   True (-E) environment vars defined   #
#   $Opt_UndefRes      output   True (-u) undefine resource specified#
#   $Opt_Batching      output   True (-b) event batching specified   #
#--------------------------------------------------------------------#
sub parse_cmd_line 
{
my(@original_argv) = @ARGV;
my $reponse_name = "";                  # response name    
my $copyfrom_name = "";                 # response to copy
my $action_name = "";                   # action name                
my $days_str = "";                      # days as specified
my $time_str = "";                      # time as specified   
my $command = "";                       # action script 
my $envlist = "";                       # environment vars list
my $ret_code_val = "";                  # expected return code    
my $event_type = "";                    # event type
my $event_code = "";                    # coded event type 
my $copyfrom_name2 = "";                # copy of response for copy
my $put_node = "";                      # put node from -p
my $locator = "";                       # locates the response to copy
my %opts = ();
my $i = 0;
my $j = 0;
my $Code_Found = $FALSE;                # flag for finding event    
my $temp_event = "";
my %event_spec = ();                    # indicate the event types specified
my $event_batching = $EVENT_BATCHING_OFF; # no event batching

# Process the command line...
if (!GetOptions(\%opts,
	'h' ,
	'b' ,
	'c=s' ,
	'n=s' ,
	'd=s' ,
	't=s' ,
	's=s' ,
	'r=s' ,
	'e=s' ,
	'p=s' ,
	'E=s' ,
	'u' ,
	'o' ,
	'V' ,
	'T' ))
{# Gather options; 
                                        # if errors
    &print_usage;                       # display proper usage
    return ERRM_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;
}

# check for where to define (put) response (not required)
if (defined $opts{p}) {                 # -p for put response
    $put_node = $opts{p};
    $Opt_Put_Node = $TRUE;              # opt flag specified
    if ($put_node eq ""){               # no text for -p
       printCEMsg("EMsgERRMcliMissingRequiredFlagOperand","-p");
       &print_usage;
       return ERRM_CLI_BAD_OPERAND;
    }
}

# Get the arguments...
# Operands:  resource (only one resource allowed)
if ($#ARGV == 0) {                      # index 0 is last one
    $response_name = shift @ARGV;       # user specified resources

    # make sure the response doesn't contain any colon characters
    if ($response_name =~ /:/)
    {
        printEMsg("EMsgmkresponseInvalidResponseName");
        exit(ERRM_CLI_USER_ERROR);
    }
    if(containSplChar($response_name) )
    {
        exit(ERRM_CLI_USER_ERROR);
    }

    # make sure response doesn't already exist
    $rc = find_resource_name($response_name,$RSCEVRS,$put_node);
    if ($rc == $RMC_CLI_USER_ERROR) {
       exit(ERRM_CLI_USER_ERROR);
    }
    if ($rc == 0) {                     # response name found
       printEMsg("EMsgmkresponseResponseExists",$response_name);
       return ERRM_CLI_USER_ERROR;
    }
}

else {            
    # no resource or too many resources specified 
    printCEMsg("EMsgERRMcliInvalidNumberOfOperands");
    &print_usage;
    return ERRM_CLI_BAD_OPERAND;
}

if (defined $opts{c}) {                 # -c for copy response
    $copyfrom_name = $opts{c};
    $Opt_CopyResp = $TRUE;              # -c flag specified
    if ($copyfrom_name eq ""){          # no name for -c
       printCEMsg("EMsgERRMcliMissingRequiredFlagOperand","-c");
       &print_usage;
       return ERRM_CLI_BAD_OPERAND;
    }
    else {
       # extract the locator if it exists
       ($temp_name, $locator) = get_locator_node($copyfrom_name);
       # copy the response name
       $copyfrom_name2 = $copyfrom_name;
       # put back response name without locator
       if ($locator ne "") { $copyfrom_name2 = $temp_name;}

       # make sure the response to be copied already exists
       $rc = find_resource_name($copyfrom_name2,$RSCEVRS,$locator);
       if ($rc != 0) {                  # response name not found
          if ($rc != $RMC_CLI_USER_ERROR) {
             printEMsg("EMsgmkresponseResponseNotFound",$copyfrom_name);
          }
          return ERRM_CLI_USER_ERROR;
       }
    }
}

if (defined $opts{n}) {                 # -n for action name   
    if ($Opt_CopyResp) {                # no -n with -c
       printCEMsg("EMsgERRMcliImproperUsageCombination","-c","-n");
       &print_usage;
       return ERRM_CLI_BAD_FLAG;
    }
    $Opt_Actions = $TRUE;
    $action_name = $opts{n};
    if ($action_name eq ""){            # no action name for -n
    printCEMsg("EMsgERRMcliMissingRequiredFlagOperand","-n");
    &print_usage;
    return ERRM_CLI_BAD_OPERAND;
    }
}
#else {
#    # -n not specified and is required when no -c for copy
#    if (!$Opt_CopyResp) {
#       printCEMsg("EMsgERRMcliMissingRequiredFlag","-n");
#       &print_usage;
#       return ERRM_CLI_BAD_FLAG;
#    }
#}

if (defined $opts{s}) {                 # -s for command string
    if ($Opt_CopyResp) {                # no -s with -c
       printCEMsg("EMsgERRMcliImproperUsageCombination","-c","-s");
       &print_usage;
       return ERRM_CLI_BAD_FLAG;
    }
    if (!$Opt_Actions) {                # no -n with -s
       printCEMsg("EMsgERRMcliMissingRequiredFlag","-n");
       &print_usage;
       return ERRM_CLI_BAD_FLAG;
    }
    $command = $opts{s};
    if ($command eq ""){                # no command for -s
    printCEMsg("EMsgERRMcliMissingRequiredFlagOperand","-s");
    &print_usage;
    return ERRM_CLI_BAD_OPERAND;
    }
}
else {
    # -s not specified and is required when -n used 
    if ($Opt_Actions) {
       printCEMsg("EMsgERRMcliMissingRequiredFlag","-s");
       &print_usage;
       return ERRM_CLI_BAD_FLAG;
    }
}

if (defined $opts{d}) {                 # -d for days
    if ($Opt_CopyResp) {                # no -d with -c
       printCEMsg("EMsgERRMcliImproperUsageCombination","-c","-d");
       &print_usage;
       return ERRM_CLI_BAD_FLAG;
    }
    if (!$Opt_Actions) {                # no -n with -d
       printCEMsg("EMsgERRMcliMissingRequiredFlag","-n");
       &print_usage;
       return ERRM_CLI_BAD_FLAG;
    }
    $days_str = $opts{d};         
    $Opt_DaysOfWeek = $TRUE;            # -d flag specified
    if ($days_str eq ""){               # no days for -d     
       printCEMsg("EMsgERRMcliMissingRequiredFlagOperand","-d");
       &print_usage;
       return ERRM_CLI_BAD_OPERAND;
    }
}

if (defined $opts{t}) {                 # -t for times
    if ($Opt_CopyResp) {                # no -t with -c
       printCEMsg("EMsgERRMcliImproperUsageCombination","-c","-t");
       &print_usage;
       return ERRM_CLI_BAD_FLAG;
    }
    if (!$Opt_Actions) {                # no -n with -t
       printCEMsg("EMsgERRMcliMissingRequiredFlag","-n");
       &print_usage;
       return ERRM_CLI_BAD_FLAG;
    }
    $time_str = $opts{t};         
    $Opt_TimeOfDay = $TRUE;             # -t flag specified
    if ($time_str eq ""){               # no times for -t     
       printCEMsg("EMsgERRMcliMissingRequiredFlagOperand","-t");
       &print_usage;
       return ERRM_CLI_BAD_OPERAND;
    }
}

if (defined $opts{r}) {                 # -r for return code
    if ($Opt_CopyResp) {                # no -r with -c
       printCEMsg("EMsgERRMcliImproperUsageCombination","-c","-r");
       &print_usage;
       return ERRM_CLI_BAD_FLAG;
    }
    if (!$Opt_Actions) {                # no -n with -r
       printCEMsg("EMsgERRMcliMissingRequiredFlag","-n");
       &print_usage;
       return ERRM_CLI_BAD_FLAG;
    }
    $ret_code_val = $opts{r};         
    $Opt_ReturnCode = $TRUE;            # -r flag specified
    $Opt_RetCodeCheck = $TRUE;          # no good w/o the check 
    if ($ret_code_val eq ""){           # no rc for -r     
       printCEMsg("EMsgERRMcliMissingRequiredFlagOperand","-r");
       &print_usage;
       return ERRM_CLI_BAD_OPERAND;
    }
}

if (defined $opts{e}) {                 # -e for event type
    if ($Opt_CopyResp) {                # no -e with -c
       printCEMsg("EMsgERRMcliImproperUsageCombination","-c","-e");
       &print_usage;
       return ERRM_CLI_BAD_FLAG;
    }
    if (!$Opt_Actions) {                # no -n with -e
       printCEMsg("EMsgERRMcliMissingRequiredFlag","-n");
       &print_usage;
       return ERRM_CLI_BAD_FLAG;
    }
    $event_type = $opts{e};         
    $Opt_EventType = $TRUE;             # -e flag specified
    if ($event_type eq ""){             # no event type for -e     
       printCEMsg("EMsgERRMcliMissingRequiredFlagOperand","-e");
       &print_usage;
       return ERRM_CLI_BAD_OPERAND;
    }

    # verify its a valid event type
    for ($j=0;$j<length($event_type);$j++) {
        # look at each event type specified
        $Code_Found = $FALSE;
        $tmp_event = substr($event_type,$j,1);

        # verify each type specified
        for ($i=0;$i<=$#EVENTTYPE;$i++) {
            if ($tmp_event eq $EVENTTYPE[$i]) {
               if (defined $event_spec{$tmp_event}) {
                  printEMsg("EMsgmkresponseInvalidEvent","-e",$event_type);
                  return ERRM_CLI_USER_ERROR;
               }
               else {
                  $event_code = $event_code | $EVENTTPCD[$i];
                  $Code_Found = $TRUE;
                  $event_spec{$tmp_event} = $TRUE;
               }
            }
        }
        if (!$Code_Found){
           printEMsg("EMsgmkresponseInvalidEvent","-e",$event_type);
           return ERRM_CLI_USER_ERROR;
        }
    }
}

if (defined $opts{o}) {                 # -o for std out
    if ($Opt_CopyResp) {                # no -o with -c
       printCEMsg("EMsgERRMcliImproperUsageCombination","-c","-o");
       &print_usage;
       return ERRM_CLI_BAD_FLAG;
    }
    if (!$Opt_Actions) {                # no -n with -o
       printCEMsg("EMsgERRMcliMissingRequiredFlag","-n");
       &print_usage;
       return ERRM_CLI_BAD_FLAG;
    }
    $Opt_StdOut = $TRUE;                # opt flag specified
#   if ($opts{o} ne ""){                # text for -o
#   print "opts for o .. ", $opts{o}, "\n";
#   printEMsg("EMsgmkresponseNoOperNeeded","-o");
#   &print_usage;
#   return ERRM_CLI_USER_ERROR;
#   }
}

#   if ($opts{o} ne ""){                # text for -o
#   print "opts for o .. ", $opts{o}, "\n";
#   printEMsg("EMsgmkresponseNoOperNeeded","-o");
#   &print_usage;
#   return ERRM_CLI_USER_ERROR;
#   }
#}

if (defined $opts{E}) {                 # -E for environment vars
    if ($Opt_CopyResp) {                # no -E with -c
       printCEMsg("EMsgERRMcliImproperUsageCombination","-c","-E");
       &print_usage;
       return ERRM_CLI_BAD_FLAG;
    }
    if (!$Opt_Actions) {                # no -n with -E
       printCEMsg("EMsgERRMcliMissingRequiredFlag","-n");
       &print_usage;
       return ERRM_CLI_BAD_FLAG;
    }
    $Opt_EnvList = $TRUE;               # opt flag specified
    $envlist = $opts{E};
    if ($envlist eq ""){                # no command for -E
    printCEMsg("EMsgERRMcliMissingRequiredFlagOperand","-E");
    &print_usage;
    return ERRM_CLI_BAD_OPERAND;
    }
}

if (defined $opts{u}) {                 # -u for undefres flag
    if ($Opt_CopyResp) {                # no -u with -c
       printCEMsg("EMsgERRMcliImproperUsageCombination","-c","-u");
       &print_usage;
       return ERRM_CLI_BAD_FLAG;
    }
    if (!$Opt_Actions) {                # no -n with -u
       printCEMsg("EMsgERRMcliMissingRequiredFlag","-n");
       &print_usage;
       return ERRM_CLI_BAD_FLAG;
    }
    $Opt_UndefRes = $TRUE;              # -u flag specified
}

if (defined $opts{b}) {                 # -b for event batching
    if ($Opt_CopyResp) {                # no -b with -c
       printCEMsg("EMsgERRMcliImproperUsageCombination","-c","-b");
       &print_usage;
       return ERRM_CLI_BAD_FLAG;
    }
    if ($Opt_EventType) {               # no -b with -e
       printCEMsg("EMsgERRMcliImproperUsageCombination","-e","-b");
       &print_usage;
       return ERRM_CLI_BAD_FLAG;
    }
#    if (!$Opt_Actions) {                # no -n with -b
 #      printCEMsg("EMsgERRMcliMissingRequiredFlag","-n");
  #     &print_usage;
   #    return ERRM_CLI_BAD_FLAG;
   # }
    $Opt_Batching = $TRUE;              # -b flag specified
    $event_batching = $EVENT_BATCHING_ON;
}

return(0, $response_name, $action_name, $days_str, $time_str,
       $command, $ret_code_val, $event_code, $event_batching,
       $copyfrom_name, $put_node, $envlist);   # success
}   # end parse_cmd_line


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

#--------------------------------------------------------------------#
# get_response_info : Uses the list resource RMC CLI command to      #
#   list the response to get the action attribute.                   #
#                                                                    #
# Paramaters:                                                        #
#   $response_name   the response to list                            #
#                                                                    #
# Returns:                                                           #
#   $action_val      action attribute value of the response          #
#                                                                    #
# Global Variables modified:                                         #
#   None.                                                            #
#--------------------------------------------------------------------#
sub get_response_info
{
my $response_name = shift(@_);
my $action_val = "";
my @action_vals = ();
my $pos = 0;
my $i = 0;
my $trace_opt = "";
my $locator  = "";
my $temp_name = "";
my $node_select = "";
my $rc = 0;

# extract the locator if it exists
($temp_name, $locator) = get_locator_node($response_name);
# put back response name without locator
if ($locator ne "") { $response_name = $temp_name;}

# re-establish original CT_MANAGEMENT_SCOPE
set_orig_rmc_scope;

# check to see if resource name has a Node_name to locate it.
# if not, set rmc local scope.  if it does, use it in select string.
if ($locator eq "") {
   # set CT_MANAGEMENT_SCOPE to local for query
   $ENV{CT_MANAGEMENT_SCOPE} = $RMC_LOCAL_SCOPE;
}
# else use location is select string
else {
   $node_select = " && NodeNameList |< {\\\"$locator\\\"}";

   # use DM/SR/Local scope if scope not set
   check_set_cluster_scope;
}

$main::Trace && print STDERR "$main::PROGNAME: calling lsrsrc-api\n";
$main::Trace && ($trace_opt = " -T ");

# list response using the RMC CLI list command to get the action attribute
#@action_vals = `$CTBINDIR/$LSRSRC $trace_opt -x -s "Name == \\\"$response_name\\\" $node_select" $RSCEVRS Actions`;
@action_vals = `$CTBINDIR/lsrsrc-api -I $DELIMITERI -D $DELIMITERO -s ${RSCEVRS}${DELIMITERI}\"Name==\\\"$response_name\\\"$node_select\"${DELIMITERI}${DELIMITERI}${DELIMITERI}Actions 2>&1`;
$rc = $?;
$rc = &process_exit_code($rc);
$main::Trace && print STDERR "lsrsrc-api results:\n";
$main::Trace && print STDERR "@action_vals";
$main::Trace && print STDERR "$main::PROGNAME: lsrsrc-api returned $rc\n";

# show any errors if there was a bad rc except for not found
if (($rc != 0) && ($rc != $RMC_CLI_RSRC_NOT_FOUND)) {
   process_api_error($DELIMITERO,$rc,@action_vals);
}

($rc == $RMC_CLI_USER_ERROR) && ( error_exit(ERRM_CLI_USER_ERROR) );

# if list command failed, print RMC error message and exit
if ($rc != 0) {
#   printCEMsg("EMsgERRMcliUnExpectRMCrc",$rc);
    exit(ERRM_CLI_RMC_ERROR);
    }

# get the actions attribute
$action_val = $action_vals[0];

chomp($action_val);

return ($action_val);
}

# Check if given name contains controls characters, if yes return 1 else retuirn 0
sub containSplChar ($)
{
local %specialCharString = (
    '\cA' => "^A",
    '\cB' => "^B",
    '\cC' => "^C",
    '\cD' => "^D",
    '\cE' => "^E",
    '\cF' => "^F",
    '\cG' => "^G",
    '\cH' => "^H",
    '\cI' => "^I",
    '\n' => "\\n",
    '\cK' => "^K",
    '\f' => "\\f",
    '\r' => "\\r",
    '\cN' => "^N",
    '\cO' => "^O",
    '\cP' => "^P",
    '\cQ' => "^Q",
    '\cR' => "^R",
    '\cS' => "^S",
    '\cT' => "^T",
    '\cU' => "^U",
    '\cV' => "^V",
    '\cW' => "^W",
    '\cX' => "^X",
    '\cY' => "^Y",
    '\cZ' => "^Z",
    '\c[' => "^[",
    '\c[\\]' => "^\\",
    '\c]' => "^]",
    '\c^' => "^^",
    '\c_' => "^_",
);
    my $resource=shift(@_);

    foreach $code (keys %specialCharString) {
        if ($resource =~ /$code/) {
            printEMsg("EMsgmkconditionInvalidResponseName1",$specialCharString{$code});
            return 1;
        }
    }
    return 0;
}