#!/usr/bin/perl # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # # # Licensed Materials - Property of IBM # # (C) COPYRIGHT International Business Machines Corp. 2001,2020 # 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 = "@(#)65 1.19.1.29 src/rsct/rm/ER/cli/bin/lsresponse.perl, errmcli, rsct_rady, rady2035a 3/27/20 03:20:47" ###################################################################### # # # Module: lsresponse # # # # Purpose: # # lsresponse - list actions for one or more response resources # # # # Current Syntax: # # lsresponse [-h] [-A] [-C|-l|-t|-d|-D Delimiter] [-b] # # [-q] [-x] [-U] [-TV] [Response [Response...]:Node_name] # # # # Flags: # # -A Displays all of the attributes associated with the # # response names. # # -C The output of the command is the mkresponse command # # that could be used to create the response. If more # # than one response is listed, every response appears # # on a separate line. # # -d Delimiter-formatted output. The default delimiter is a # # colon (:). Use the -D flag if you wish to change the # # default delimiter. # # -D Delimiter # # Delimiter-formatted output that uses the specified # # delimiter. Use this flag to specify something other # # than the default colon (:). An example is when the data # # to be displayed contains colons. Use this flag to # # specify a delimiter of one or more characters. # # -h Help. Writes this command's usage statement to stdout. # # -l Long formatted output. The response information is # # displayed on separate lines. # # -a All. List response information for all nodes in the # # cluster. # # -b Batching. List the responses that support event # # batching. # # -q Quiet. Does not return an error when the Condition # # specified does not exist. # # -t Tabular formatted output. The response information is # # displayed in separate columns. # # -U Displays whether the resource is locked or not # # -T Trace. IBM Support Center use only. # # -V Verbose. # # -x Exlude header. Suppress header printing. # # # # Operands: # # Response The name of the response whose actions are # # to be listed. Node_name specifies where the # # responses are defined. # # # # Description: # # The lsresponse command is used to list information about # # defined responses. # # # # 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. To list all responses, run the following command: # # lsresponse # # Output is similar to: # # Name # # "E-mail root anytime" # # "E-mail root first shift" # # "Critical notifications" # # 2. To list general information about the response # # "Critical notifications" in long format, run the # # following command: # # lsresponse "Critical notifications" # # Output is similar to: # # Name = "Critical notifications" # # Action = "Log Critical Event" # # DaysOfWeek = 1+2+7 # # TimeOfDay = 0000-2400 # # ActionScript = "/opt/rsct/bin/logevent \ # # /tmp/criticalEvents" # # ReturnCode = 0 # # CheckReturnCode = "y" # # EventType = "b" # # StandardOut = "y" # # EnvironmentVars = "Lang=UsEn" # # UndefRes = "n" # # # # Action = "E-mail root" # # DaysOfWeek = 6+2,6+2,6+5 # # TimeOfDay = 1700-2400,0000-0800,0000-2400 # # ActionScript = "/opt/rsct/bin/notifyevent root" # # ReturnCode = 0 # # CheckReturnCode = "y" # # EventType = "b" # # StandardOut = "y" # # EnvironmentVars = "" # # UndefRes = "n" # # # # 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.lsresponse.map - message mapping # # # # Outputs: # # stdout - display information on the response. # # stderr - any error message. # # # # External Ref: # # Commands: ctdspmsg # # Modules: ERRM_cli_utils.pm, ERRM_cli_rc.pm # # CT_cli_utils.pm # # Extensions: MC.pm, MCerr.pm, CT.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: # # 010120 GTM 67471: Initial design & write. # # 010212 GTM 71293: Enhance -TV processing. # # 010222 JAC 71460: Replace LIKE with ?= in selection string. # # 010226 JAC 71382: Quiet flag (-q) should exit with 0 when name # # not found and error should be user error. # # 010227 JAC 71402: Remove extra quotes in -C display header. # # 010305 JAC 71362: Make display flag precedence C,l,t,d,D. # # 010308 JAC 72121: Change selecetion string to work for quotes. # # 010311 JAC 72226: Correct -d,-D precedence (-d overrides). # # 010507 JAC 73620: Check for RMC CLI user error (rc=5) and # # return ERRM user error for this case. # # 011118 JAC 78513: Change parse on colon to use $DELIMITER # # 011120 JAC 77597: Distributed RMC. Check for node locator. # # 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. # # 020107 JAC 79091: Use correct response variable for lsrsrc. # # 020121 JAC 79558: Fix selection string for locating resources. # # 020121 JAC 78997: Fix if-statement to correct display format. # # 020207 JAC 71888: Add verbose messages to message file. # # 020208 JAC 71728: Add NLS support for headers and xlating values.# # 020212 JAC 77598: Allow responses with no Actions to be shown. # # 020215 JAC 78996: Add new display columns and fix some formats. # # 020221 JAC 80506: Allow for multiple locators (sep by commas). # # 020301 JAC 80764: Fix for showing UndefRes when no actions. # # 020305 JAC 80805: Fix to continue if partial output from lsrsrc. # # 020417 JAC 81754: Use xxx-api where possible. # # 020424 JAC 81488: Change how if in cluster is determined. # # 020523 JAC 83318: If location displayed, use 1st NodeNameList val# # 020603 JAC 83363: Save environment before calling in_cluster. # # 020719 JAC 84425: Add $rc to process_api_error call. # # 020725 JAC 85139: Return proper rc when no responses found. # # 020730 JAC 85061: Use 4 (DM/SR/local) for scope if locator used # # or -a used and scope not set. -a is new. # # 040211 JAC 103750: Add -U flag to show Locked attribute. # # 040428 JAC 108194: Use escape_selstr for response names and use # # LIKE in select string. # # 071026 JAC 146726: set delimiters for -api commands. # # 081103 JAC 154299: fix for nested foreach on same variable. # # 081103 JAC 153203: add error event handling. # # 081113 JAC 153204: add event batching support. # ###################################################################### #--------------------------------------------------------------------# # General Program Flow/Logic: # # # # A. Parse command line flags and operands, determine which flavor # # of this command we are actually invoking. # # This command allows a user to list actions of defined # # responses. # # - print usage if -h specified # # - set $Opt variables according to flags specified # # B. Call RMC command lsrsrc. Also pass along -TV if necessary. # # - if no response names, call lsrsrc once to get all defined # # response names # # - if no response names and -A, call lsrsrc once with attr # # names "Name" and "Actions" # # - if at least one response is specified, call lsrsrc for each # # response with attr names "Name" and "Actions" # # C. Do post processing on raw lsrsrc output. # # - convert Actions SDArray to display-friendly data and insert # # into 2D array # # - the following action elements must be converted: # # DaysOfWeek (subroutine) # # TimeOfDay (subroutine) # # CheckReturnCode, EventType, StandardOut (character swap) # # D. Format and display output. # # - if at least one response's worth of output was obtained, # # execute display code # # - if -C display example mkresponse commands for each response # # - otherwise call CT_cli_display_utils::set_display to format # # and display output # # # #--------------------------------------------------------------------# #--------------------------------------------------------------------# # Included Libraries and Extensions # #--------------------------------------------------------------------# use lib "/opt/rsct/pm"; use locale; use Getopt::Long; use CT_cli_utils qw(printIMsg printEMsg); use CT_cli_display_utils qw(set_display); 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 get_locator_node process_api_error process_exit_code remove_api_error in_cluster set_orig_rmc_scope check_set_cluster_scope getIMsg escape_selstr $CTDIR $CTBINDIR $DELIMITERI $DELIMITERO $SEVCRIT $SEVWARN $SEVINFO $GARBAGE $MKCNDCRIT $MKCNDWARN $MKCNDINFO $RMC_CLI_USER_ERROR $RMC_CLI_RSRC_NOT_FOUND $LSNOTFND $LSRSRC $MKRSRC $RSCEVRS); #--------------------------------------------------------------------# # Global Constants # #--------------------------------------------------------------------# Getopt::Long::Configure ("bundling", "no_auto_abbrev", "no_ignore_case", "require_order", "prefix_pattern=(--|-)"); # lsrsrc attribute names $Attr_Name = "Name"; $Attr_NodeNameList = "NodeNameList"; $Attr_Actions = "Actions"; $Attr_Locked = "Locked"; $Attr_Batching = "EventBatching"; # Action element names #$Resp_Name = "ResponseName"; #$Act_Name = "Action"; #$Act_DofW = "DaysOfWeek"; #$Act_TofD = "TimeOfDay"; #$Act_Script = "ActionScript"; #$Act_RetCd = "ReturnCode"; #$Act_CkRetCd = "CheckReturnCode"; #$Act_EvType = "EventType"; #$Act_StdOut = "StandardOut"; #$Act_EnvList = "EnvironmentVars"; #$Act_UndefRes = "UndefRes"; #--------------------------------------------------------------------# # Global Variables # #--------------------------------------------------------------------# $TRUE = 1; $FALSE = 0; $Scope_orig_set = $FALSE; # default - no CT_MANAGEMENT_SCOPE $Scope_orig_value = 0; # default - scope value $Trace = $FALSE; # default - trace off # -T flag $Verbose = $FALSE; # default - verbose turned off # -V flag $Opt_All_Attrs = $TRUE; # default - all attributes # -A flag $Opt_Mkresp_Ex = $FALSE; # default - do not display # mkresponse example # -C flag $Opt_Delm_Format = $FALSE; # default - no delimited output # -d, -D flags $Opt_Delm_Str = ":"; # default - delimiter character # can be overridden with -D flag $Opt_Long_Format = $TRUE; # default - long formatted output $Opt_Quiet = $FALSE; # default - do not supress display # of error when non-existent # response is specified # -q flag $Opt_Table_Format = $FALSE; # default - do not display in # tabular format # -t flag $Opt_No_HDR = $FALSE; # default - do not supress heading # output # -x flag $Opt_All_Nodes = $FALSE; # default - cluster display $Opt_Show_Locked = $FALSE; # default - don't show Locked $Opt_Batching = $FALSE; # default - don't show only # event batching responses $PROGNAME = "lsresponse"; # Program Name for messages $MSGCAT = "errmcli.cat"; # msg catalogue for this cmd #$CTDIR = "/opt/rsct"; # RSCT root directory #$CTBINDIR = "$CTDIR/bin"; # Cluster Bin directory path $LSMSG = "$CTBINDIR/ctdspmsg"; # list / display message rtn. $ENV{'MSGMAPPATH'} = "$CTDIR/msgmaps"; # msg maps used by $LSMSG #--------------------------------------------------------------------# # Variables # #--------------------------------------------------------------------# $sARGV = 0; # size of @ARGV $lsr_attr_names = ""; # attr names to pass to lsrsrc #$lsr_opts = " -x -D $DELIMITERO"; # format options for lsrsrc $lsr_dbg_opts = ""; # trace/verbose opts for lsrsrc @Lof_lsr_output = (); # lsrsrc raw output array @Lof_resps = (); # 2D array of response data to # be displayed my $locator = ""; # where to look for the response my @Resp_list = (); # copy of ARGV without locator my @heading = (); # heading for the listed data my @lockedstatustext = (); # text to use for locked status my @tmp_output = (); # lsclcfg output my $cluster_env = $FALSE; # in a cluster? my $junk = ""; # for garbage #--------------------------------------------------------------------# #--------------------------------------------------------------------# # Main Code # #--------------------------------------------------------------------# #--------------------------------------------------------------------# my $rc = 0; my $errmcli_rc = 0; # # parse the command line, exit if there are errors # # if no cmdline args, force -t #unless (scalar(@ARGV)) { $Opt_Table_Format = $TRUE; } ($rc, $locator, @Resp_list) = &parse_cmd_line; ($rc == 0) || error_exit($rc); if ($Verbose) { printIMsg("IMsglsresponseStart51D");} # if there are multiple locators, add some quotes $locator =~ s/,/\\\",\\\"/g; # # call lsrsrc based on input data # # handle debug options if ($Trace || $Verbose) { $lsr_dbg_opts = $lsr_dbg_opts." -"; } if ($Trace) { $lsr_dbg_opts = $lsr_dbg_opts."T"; } if ($Verbose) { $lsr_dbg_opts = $lsr_dbg_opts."V"; } # 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}; } # decide if in cluster or not. if in cluster, get NodeNameList if (in_cluster) { $cluster_env = $TRUE; } # set CT_MANAGEMENT_SCOPE to original setting, in case it was used set_orig_rmc_scope; # set cluster scope if locator used or -a used if ( ($locator ne "") || ($Opt_All_Nodes) ) { check_set_cluster_scope; } # build attr names to be passed to lsrsrc $lsr_attr_names = $Attr_Name . "${DELIMITERI}"; if ($cluster_env) { $lsr_attr_names .= $Attr_NodeNameList . "${DELIMITERI}";} $lsr_attr_names .= $Attr_Actions; # add EventBatching attribute $lsr_attr_names .= "${DELIMITERI}" . $Attr_Batching; # add Locked attribute if -U used if ($Opt_Show_Locked) { $lsr_attr_names .= "${DELIMITERI}" . $Attr_Locked; } # call lsrsrc if ($Trace) {print STDERR "$PROGNAME: calling $LSRSRC to get response data\n";} # if no response args, force -t if (($#Resp_list<0) && (!$Opt_All_Attrs)) { $Opt_Table_Format = $TRUE; } #if ($sARGV) { # responses given as input if ($#Resp_list >=0 ) { # responses given as input my @tmp_lsr_output = (); my $resp_name = ""; my $resp_name_orig = ""; # my $lsr_selstr = "-s 'Name ?= " . "\"ERRMCLI\"" . "'"; # my $lsr_selstr = "-s \"Name ?= \\\"ERRMCLI\\\"\""; # my $lsr_selstr = "\"Name ?= \\\"ERRMCLI\\\"\""; my $lsr_selstr = "\"Name LIKE \\\"ERRMCLI\\\"\""; # check to see if node locator is needed if ($locator ne "") { # $lsr_selstr = "-s \"Name ?= \\\"ERRMCLI\\\" && NodeNameList|<{\\\"$locator\\\"}\""; # $lsr_selstr = "\"Name ?= \\\"ERRMCLI\\\" && NodeNameList|<{\\\"$locator\\\"}\""; $lsr_selstr = "\"Name LIKE \\\"ERRMCLI\\\" && NodeNameList|<{\\\"$locator\\\"}\""; } # issue lsrsrc command for each response provided as input foreach $resp_name (@Resp_list) { $resp_name_orig = $resp_name; $resp_name = escape_selstr($resp_name); # $lsr_selstr =~ s/ERRMCLI/$resp_name/; $lsr_selstr =~ s/ERRMCLI/%${resp_name}%/; # issue the lsrsrc command with the correct flags/operands # @tmp_lsr_output = `$CTBINDIR/$LSRSRC $lsr_selstr $lsr_opts $lsr_dbg_opts $RSCEVRS $lsr_attr_names`; $ENV{CT_CLI_QUOTE_STRING} = 1; @tmp_lsr_output = `$CTBINDIR/lsrsrc-api -I $DELIMITERI -D $DELIMITERO -s ${RSCEVRS}${DELIMITERI}${lsr_selstr}${DELIMITERI}${DELIMITERI}${DELIMITERI}${lsr_attr_names} 2>&1`; $rc = $?; $rc = &process_exit_code($rc); if ($Trace) { print STDERR "lsrsrc-api results:\n"; print STDERR "@tmp_lsr_output"; print STDERR "$PROGNAME: lsrsrc-api returned $rc\n"; } # show any errors if there was a bad rc except for not found if ($rc != 0) { process_api_error($DELIMITERO,$rc,@tmp_lsr_output); } # remove the error messages @tmp_lsr_output = remove_api_error(@tmp_lsr_output); # if lsrsrc command failed due to RMC CLI user error 73620 # set ERRM CLI user error and go to next response if ($rc == $RMC_CLI_USER_ERROR) { $errmcli_rc = ERRM_CLI_USER_ERROR; } # check for other things else { # save any other RMC CLI error if (($rc != 0) && ($rc != $RMC_CLI_RSRC_NOT_FOUND)) { $errmcli_rc = ERRM_CLI_RMC_ERROR; } # else rc=0, worked but may not have found anything else { # check for not found rc if ($rc == $RMC_CLI_RSRC_NOT_FOUND) { unless ($Opt_Quiet) { printEMsg("EMsglsresponseResponseNotFound", $resp_name_orig); $errmcli_rc = ERRM_CLI_USER_ERROR; # 71382 } } } } if ($#tmp_lsr_output >= 0) { chomp(@tmp_lsr_output); push(@Lof_lsr_output, @tmp_lsr_output); } # reset selection string template # $lsr_selstr = "-s 'Name ?= " . "\"ERRMCLI\"" . "'"; # $lsr_selstr = "-s \"Name ?= \\\"ERRMCLI\\\"\""; # $lsr_selstr = "\"Name ?= \\\"ERRMCLI\\\"\""; $lsr_selstr = "\"Name LIKE \\\"ERRMCLI\\\"\""; # check to see if node locator is needed if ($locator ne "") { # $lsr_selstr = "-s \"Name ?= \\\"ERRMCLI\\\" && NodeNameList|<{\\\"$locator\\\"}\""; # $lsr_selstr = "\"Name ?= \\\"ERRMCLI\\\" && NodeNameList|<{\\\"$locator\\\"}\""; $lsr_selstr = "\"Name LIKE \\\"ERRMCLI\\\" && NodeNameList|<{\\\"$locator\\\"}\""; } } } else { # no response names given unless ($Opt_All_Attrs) { # use short list of attr names $lsr_attr_names = $Attr_Name; if ($cluster_env) { $lsr_attr_names .= "${DELIMITERI}".$Attr_NodeNameList;} # add EventBatching attribute $lsr_attr_names .= "${DELIMITERI}" . $Attr_Batching; # add Locked attribute if -U used if ($Opt_Show_Locked) { $lsr_attr_names .= "${DELIMITERI}" . $Attr_Locked; } } # check to see if node locator is needed if ($locator ne "") { # $lsr_selstr = "-s \"NodeNameList|<{\\\"$locator\\\"}\""; $lsr_selstr = "-s ${RSCEVRS}${DELIMITERI}\"NodeNameList|<{\\\"$locator\\\"}\""; } # else get them all else { # $lsr_selstr = ""; $lsr_selstr = "-o ${RSCEVRS}"; } # issue the lsrsrc command # @Lof_lsr_output = `$CTBINDIR/$LSRSRC $lsr_opts $lsr_dbg_opts $lsr_selstr $RSCEVRS $lsr_attr_names`; $ENV{CT_CLI_QUOTE_STRING} = 1; @Lof_lsr_output = `$CTBINDIR/lsrsrc-api -I $DELIMITERI -D $DELIMITERO ${lsr_selstr}${DELIMITERI}${DELIMITERI}${DELIMITERI}${lsr_attr_names} 2>&1`; $rc = $?; $rc = &process_exit_code($rc); if ($Trace) { print STDERR "lsrsrc-api results:\n"; print STDERR "@Lof_lsr_output"; print STDERR "$PROGNAME: lsrsrc-api returned $rc\n"; } # show any errors if there was a bad rc except for not found if ($rc != 0) { process_api_error($DELIMITERO,$rc,@Lof_lsr_output); } # remove the error messages @Lof_lsr_output = remove_api_error(@Lof_lsr_output); # check for RMC errors if ($rc != 0) { # continue if there's partial output if ($#Lof_lsr_output >=0) { # return ERRM CLI user error if it's an RMC CLI user error if ($rc == $RMC_CLI_USER_ERROR) { $errmcli_rc = ERRM_CLI_USER_ERROR;} # or it's some rmc error else { $errmcli_rc = ERRM_CLI_RMC_ERROR; } } # there's an error and no output, just exit else { ($rc == $RMC_CLI_USER_ERROR) && ( error_exit(ERRM_CLI_USER_ERROR) ); # ($rc == $RMC_CLI_RSRC_NOT_FOUND) && ( error_exit(ERRM_CLI_USER_ERROR) ); ($rc == $RMC_CLI_RSRC_NOT_FOUND) && ( exit(0) ); # 100936 error_exit(ERRM_CLI_RMC_ERROR); } } chomp(@Lof_lsr_output); } if ($Trace) {print STDERR "$PROGNAME: $LSRSRC returned response data\n";} # # post-process raw lsrsrc oputput # if ($Trace) {print STDERR "$PROGNAME: formatting response data for display\n";} my $i = 1; my $j = 0; my $line = ""; my $attr_val = ""; my $attr_name = ""; my $resp_name = ""; my $act_rawstr = ""; my $act_line = ""; my $act_disp_elt = ""; my @attr_vals = ""; my @attr_names = (); my @action_SDs = (); my @act_display = (); my $nodenamelst_idx = 1; my $batching_idx = 0; my $locked_idx = 3; my @uheading = (); # set up "attribute" names #push(@attr_names, $Resp_Name); #if ($Opt_All_Attrs) { # # build array of names # push(@attr_names, $Act_Name); # push(@attr_names, $Act_DofW); # push(@attr_names, $Act_TofD); # push(@attr_names, $Act_Script); # push(@attr_names, $Act_RetCd); # push(@attr_names, $Act_CkRetCd); # push(@attr_names, $Act_EvType); # push(@attr_names, $Act_StdOut); # push(@attr_names, $Act_EnvList); # push(@attr_names, $Act_UndefRes); #} # get heading from message file based on long or short version if ($Opt_All_Attrs) { @heading = getIMsg("IMsglsresponseLHeading2");} else { @heading = getIMsg("IMsglsresponseSHeading");} if ($Opt_All_Attrs) { if ($cluster_env) { @heading = getIMsg("IMsglsresponseLCHeading2");} else { @heading = getIMsg("IMsglsresponseLHeading2");} } else { if ($cluster_env) { @heading = getIMsg("IMsglsresponseSCHeading");} else { @heading = getIMsg("IMsglsresponseSHeading");} } # see if Locked heading is needed if ($Opt_Show_Locked) { @uheading = getIMsg("IMsglsresponseUHeading"); $heading[0] .= "::" . $uheading[0]; # also fill in text to use while we're here # get from message file what to use for locked status @lockedstatustext = getIMsg("IMsglsresponseNoYes"); @lockedstatustext = split(/::/,$lockedstatustext[0]); } # form the heading @attr_names = split(/::/,$heading[0]); # put raw data into 2D array format suitable for use by # CT_cli_display_utils::set_display # # set up row 0 of the array - column headings # must leave 0th column of 0th row blank $Lof_resps[0][0] = ""; foreach $attr_name (@attr_names) { $Lof_resps[0][$i] = $attr_name; $i++; } # create rows of data $i = 1; if ($Opt_All_Attrs) { foreach $line (@Lof_lsr_output) { # full response-action data if ($Trace) {print STDERR "$PROGNAME: formatting action data\n";} # put response data into array @attr_vals = split(/$DELIMITERO/, $line); # determine where the Locked attr is, in case it's there # (needs to be done after the split. too bad it's in a loop $locked_idx = $#attr_vals; $resp_name = $attr_vals[0]; # change locked status from integer to string for display if ($Opt_Show_Locked) { if ($attr_vals[$locked_idx] <=1) { $attr_vals[$locked_idx] = $lockedstatustext[$attr_vals[$locked_idx]]; } else { $attr_vals[$locked_idx] = $lockedstatustext[2]; } # add quotes $attr_vals[$locked_idx] = "\"".$attr_vals[$locked_idx]."\""; } # determine where the EventBatching attr is # (needs to be done after the split. too bad it's in a loop) if ($Opt_Show_Locked) { $batching_idx = $#attr_vals -1; } else { $batching_idx = $#attr_vals; } # if -b was used, only show those responses that support event batching if ($Opt_Batching) { if ($attr_vals[$batching_idx] ==0) { next; } } # change event batching status from integer to string for display if ($attr_vals[$batching_idx] eq "0") { $attr_vals[$batching_idx] = "\"n\""; } else { $attr_vals[$batching_idx] = "\"y\""}; # get actions and set up index based on cluster or not if ($cluster_env) { $act_rawstr = $attr_vals[2]; $act_start_idx = 3; $act_end_idx = 12; $attr_vals[1] =~ s/{//; $attr_vals[1] =~ s/}//; } else { $act_rawstr = $attr_vals[1]; $act_start_idx = 2; $act_end_idx = 11; } # gotta keep the quote police happy unless ( $resp_name =~ /"/ ) { $resp_name = "\"" . $resp_name . "\""; } # fill in nulls for the action if there's no actions if (($act_rawstr eq "{}") || ($act_rawstr eq "{[]}")) { $Lof_resps[$i][0]=""; $Lof_resps[$i][1]=$resp_name; if ($cluster_env) { $Lof_resps[$i][2]=$attr_vals[1]; } for ($j=$act_start_idx;$j<=$act_end_idx;$j++){ $Lof_resps[$i][$j]=""; } $i++; $j=0; } else { # now we need to process raw action data to make it suitable for display # - discard leading/trailing grouping characters $act_rawstr =~ s/^{\[//; $act_rawstr =~ s/\]}$//; # - put each action SD in its own array element @action_SDs = split(/\],\[/, $act_rawstr); # - convert each action line to displayable format and load # into the 2D display array foreach $act_line (@action_SDs) { # special case: 0th elt must be empty $Lof_resps[$i][$j] = ""; $j++; # special case: 1st elt must be response name $Lof_resps[$i][$j] = $resp_name; $j++; # add the nodename if in a cluster if ($cluster_env) { $Lof_resps[$i][$j] = $attr_vals[1]; $j++; } # call processing routine process_action_data($act_line, \@act_display); # load 2D display array foreach $act_disp_elt (@act_display) { # transfer the display-ready action elements $Lof_resps[$i][$j] = $act_disp_elt; $j++; } # add the event batching information $Lof_resps[$i][$j] = $attr_vals[$batching_idx]; $j++; # add the locked information if needed if ($Opt_Show_Locked) { $Lof_resps[$i][$j] = $attr_vals[$locked_idx]; $j++; } $i++; $j = 0; } } } } else { # response names only and maybe nodename $i = 1; $j = 1; foreach $line (@Lof_lsr_output) { # put response data into array @attr_vals = split(/$DELIMITERO/, $line); # determine where the Locked attr is, in case it's there # (needs to be done after the split. too bad it's in a loop) $locked_idx = $#attr_vals; # determine where the EventBatching attr is # (needs to be done after the split. too bad it's in a loop) if ($Opt_Show_Locked) { $batching_idx = $#attr_vals -1; } else { $batching_idx = $#attr_vals; } # if -b was used, only show those responses that support event batching if ($Opt_Batching) { if ($attr_vals[$batching_idx] ==0) { next; } } # drop braces from nodenamelist if ($cluster_env) { $attr_vals[$nodenamelst_idx] =~ s/{//; $attr_vals[$nodenamelst_idx] =~ s/}//; # use first node name in NodeNameList ($attr_vals[$nodenamelst_idx],$junk) = split /,/,$attr_vals[$nodenamelst_idx]; } # change locked status from integer to string for display if ($Opt_Show_Locked) { if ($attr_vals[$locked_idx] <=1) { $attr_vals[$locked_idx] = $lockedstatustext[$attr_vals[$locked_idx]]; } else { $attr_vals[$locked_idx] = $lockedstatustext[2]; } # add quotes $attr_vals[$locked_idx] = "\"".$attr_vals[$locked_idx]."\""; } # load the field elements into display array foreach $attr_val (@attr_vals) { $Lof_resps[$i][$j] = $attr_val; $j++; } $j = 1; $i++; } } # end if ($Opt_All_Attrs) # # display output # my $row_count = $#Lof_resps; # set_display expects 0-origin row count if ( $row_count ) { # be sure there's data to display if ($Opt_Mkresp_Ex) { # -C: display mkresponse example if ($Trace) {print STDERR "$PROGNAME: calling display_cmd_ex to display response data\n";} display_cmd_ex(\@Lof_resps); } else { # standard display if ($Trace) {print STDERR "$PROGNAME: calling set_display to display response data\n";} unless ($Opt_No_HDR) { printIMsg("IMsglsresponseOut"); } my $display_type = ""; my $col_count = scalar(@{$Lof_resps[0]}); # 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"); $rc = set_display($display_type, $Opt_No_HDR, $row_count, $col_count, \@Lof_resps, $Opt_Delm_Str); } if ($Trace) {print STDERR "$PROGNAME: returned from display routine\n";} } if ($Verbose) { printIMsg("IMsglsresponseEnd51D");} if ($errmcli_rc == 0) { exit($rc);} else { exit($errmcli_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. # # # # Global Variables Modified: # # $Verbose output True (-V) turn Verbose mode on # # $Trace output True (-T) turn Trace mode on # # $Opt_All_Attrs output True (-A) requests all attrs # # $Opt_Mkresp_Ex output True (-C) example mkresponse cmd # # $Opt_Delm_Format output True (-d) delimited output # # $Opt_Delm_Str output True (-D) delimited output with user # # delimiter string # # $Opt_Long_Format output True (-l) long-format output # # $Opt_Quiet output True (-q) no undef response errors # # $Opt_Table_Format output True (-t) tabular output # # $Opt_No_HDR output True (-x) no headings displayed # # $Opt_All_Nodes output True (-a) display all nodes # # $Opt_Show_Locked output True (-U) display Locked # # $Opt_Batching output True (-b) display batching responses # #--------------------------------------------------------------------# sub parse_cmd_line { my %opts = (); my $locator = ""; my $temp_name = ""; my @responses = (); # Process the command line... if (!GetOptions( \%opts, 'h' , 'A' , 'C' , 'l' , 't' , 'd' , 'D=s' , 'a' , 'b' , 'q' , 'x' , 'U' , 'V' , 'T',)) {# Gather options; # if errors &print_usage; # display proper usage return ERRM_CLI_BAD_FLAG; # return bad rc - bad flag } $sARGV = scalar(@ARGV); unless ($sARGV) { $Opt_Long_Format = $FALSE; # though long is normally default $Opt_Table_Format = $TRUE; # format, if there are no resps } # then set to tabular @responses = @ARGV; if ($sARGV) { # responses and/or locator given as input # extract the locator from the last response name ($temp_name, $locator) = get_locator_node($responses[$sARGV-1]); if(containSplChar($temp_name) ) { exit(ERRM_CLI_USER_ERROR); } # put back response name without locator if ($locator ne "") { # fix response when it's only a locator (:Node) if ($temp_name eq "") { $#responses--; } else { $responses[$sARGV-1] = $temp_name; } } } $sARGV = scalar(@responses); # 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{A}) { # -A list all attrs unless ($sARGV) { # a little unusual - turn off $Opt_All_Attrs = $FALSE; # only when no responses and } # no -A flag specified } if (defined $opts{A}) { # -A list all attrs $Opt_All_Attrs = $TRUE; # make sure all attrs enabled $Opt_Long_Format = $TRUE; # turn on long format $Opt_Table_Format = $FALSE; # turn off tabular format } if (defined $opts{D}) { # -D delimited output with specified $Opt_Delm_Format = $TRUE; # delimiter $Opt_Delm_Str = $opts{D}; $Opt_Long_Format = $FALSE; } if (defined $opts{d}) { # -d delimited output $Opt_Delm_Format = $TRUE; $Opt_Delm_Str = ":"; $Opt_Long_Format = $FALSE; } if (defined $opts{t}) { # -t table formatted output $Opt_Table_Format = $TRUE; $Opt_Mkresp_Ex = $FALSE; $Opt_Long_Format = $FALSE; $Opt_Delm_Format = $FALSE; } if (defined $opts{l}) { # -l long formatted output $Opt_Long_Format = $TRUE; $Opt_Mkresp_Ex = $FALSE; $Opt_Table_Format = $FALSE; $Opt_Delm_Format = $FALSE; } if (defined $opts{C}) { # -C example mkresponse cmd if ($sARGV) { $Opt_Mkresp_Ex = $TRUE; } else { unless ($Opt_All_Attrs) { $Opt_Long_Format = $FALSE; # turn off default long format $Opt_Table_Format = $TRUE; # turn on tabular format } } } if (defined $opts{a}) { # -a display all nodes in cluster $Opt_All_Nodes = $TRUE; } if (defined $opts{q}) { # -q quiet mode - supress undefined $Opt_Quiet = $TRUE; # response errors } if (defined $opts{x}) { # -x supress headings $Opt_No_HDR = $TRUE; } if (defined $opts{U}) { # -U show locked $Opt_Show_Locked = $TRUE; } if (defined $opts{b}) { # -b show event batching only $Opt_Batching = $TRUE; } if (defined $opts{T}) { # -T turn trace on $Trace = $TRUE; } if (defined $opts{V}) { # -V turn verbose mode on $Verbose = $TRUE; } return(0, $locator, @responses); # success } # end parse_cmd_line #--------------------------------------------------------------------# # process_action_data - convert raw action SD to array of # # displayable action elements # # # # Input parameters: # # $raw_actdata a single action SD string with outer brackets # # removed # # # # Output parameters: # # $r_act_output reference to a single dimension array of # # formatted action elements # #--------------------------------------------------------------------# sub process_action_data { my($raw_actdata, $r_act_output) = @_; my $i = 0; my $start_pos = 0; my $cur_pos = 0; my $end_pos = length($raw_actdata); my $ss_len = 0; my $end_envlist = 0; my $temp_str = ""; my $raw_time = ""; my $raw_dow = ""; my @temp_arr = (); my @start_time = (); my @end_time = (); my @dow = (); if ($Trace) {print STDERR "$PROGNAME: entering process_action_data\n";} # save action name (no conversion needed) $cur_pos = index($raw_actdata, "{"); $temp_str = substr($raw_actdata, $start_pos, $cur_pos - 1); if ( $temp_str =~ /"/ ) { ${$r_act_output}[0] = $temp_str; } else { ${$r_act_output}[0] = "\"" . $temp_str . "\""; } # get DaysOfWeek data (conversion needed) $start_pos = $cur_pos + 1; $cur_pos = index($raw_actdata, "}"); $ss_len = $cur_pos - $start_pos; $temp_str = substr($raw_actdata, $start_pos, $ss_len); @temp_arr = split(/,/, $temp_str); foreach $raw_dow (@temp_arr) { push(@dow, cvt_dow($raw_dow)); } # save DaysOfWeek display data ${$r_act_output}[1] = $dow[0]; for ($i = 1; $i <= $#dow; $i++) { ${$r_act_output}[1] .= "," . $dow[$i]; } # get StartTime data (conversion needed) $start_pos = index($raw_actdata, "{", $cur_pos) + 1; $cur_pos = index($raw_actdata, "}", $start_pos); $ss_len = $cur_pos - $start_pos; $temp_str = substr($raw_actdata, $start_pos, $ss_len); @temp_arr = split(/,/, $temp_str); foreach $raw_time (@temp_arr) { push(@start_time, cvt_tod($raw_time)); } # get EndTime data (conversion needed) $start_pos = index($raw_actdata, "{", $cur_pos) + 1; $cur_pos = index($raw_actdata, "}", $start_pos); $ss_len = $cur_pos - $start_pos; $temp_str = substr($raw_actdata, $start_pos, $ss_len); @temp_arr = split(/,/, $temp_str); foreach $raw_time (@temp_arr) { push(@end_time, cvt_tod($raw_time)); } # save TimeOfDay data ${$r_act_output}[2] = $start_time[0] . "-" . $end_time[0]; for( $i = 1; $i <= $#start_time; $i++ ) { ${$r_act_output}[2] .= "," . $start_time[$i] . "-" . $end_time[$i]; } # save action script string (no conversion needed) $start_pos = index($raw_actdata, ",", $cur_pos) + 1; $cur_pos = index($raw_actdata, ",", $start_pos); $ss_len = $cur_pos - $start_pos; $temp_str = substr($raw_actdata, $start_pos, $ss_len); if ( $temp_str =~ /"/ ) { ${$r_act_output}[3] = $temp_str; } else { ${$r_act_output}[3] = "\"" . $temp_str . "\""; } # save EventType, CheckReturnCode, ReturnCode, StandardOut $start_pos = $cur_pos + 1; $temp_str = substr($raw_actdata, $start_pos, $end_pos); @temp_arr = split(/,/, $temp_str); # display order does not match stored order ${$r_act_output}[4] = $temp_arr[2]; # ReturnCode ${$r_act_output}[5] = $temp_arr[1]; # CheckReturnCode ${$r_act_output}[6] = $temp_arr[0]; # EventType ${$r_act_output}[7] = $temp_arr[3]; # StandardOut # change numeric values to strings for display if (${$r_act_output}[5] eq "0") { #CheckReturnCode ${$r_act_output}[5] = "\"n\""; } else { ${$r_act_output}[5] = "\"y\""; } if (${$r_act_output}[6] eq "1") { #EventType ${$r_act_output}[6] = "\"a\""; } elsif (${$r_act_output}[6] eq "2") { ${$r_act_output}[6] = "\"r\""; } elsif (${$r_act_output}[6] eq "3") { ${$r_act_output}[6] = "\"b\""; } elsif (${$r_act_output}[6] eq "4") { ${$r_act_output}[6] = "\"e\""; } elsif (${$r_act_output}[6] eq "5") { ${$r_act_output}[6] = "\"ae\""; } elsif (${$r_act_output}[6] eq "6") { ${$r_act_output}[6] = "\"re\""; } elsif (${$r_act_output}[6] eq "7") { ${$r_act_output}[6] = "\"A\""; } else { ${$r_act_output}[6] = "\"?\""; } if (${$r_act_output}[7] eq "0") { #StandardOut ${$r_act_output}[7] = "\"n\""; } else { ${$r_act_output}[7] = "\"y\""; } # get the EnvList info $start_pos = index($raw_actdata,"{",$start_pos); $end_envlist = index($raw_actdata,"},",$start_pos); $ss_len = $end_envlist-$start_pos-1; ${$r_act_output}[8] = substr($raw_actdata,$start_pos+1,$ss_len); # for EnvList, remove {} around the array #${$r_act_output}[8] =~ s/\}$//; #${$r_act_output}[8] =~ s/^\{//; # if it has imbedded double quotes, surround EnvList with single quotes if (index(${$r_act_output}[8],"\"")>=0) { ${$r_act_output}[8] = "'" . ${$r_act_output}[8] . "'"; } # else put double quotes around EnvList else { ${$r_act_output}[8] = "\"" . ${$r_act_output}[8] . "\""; } # get UndefResFlag $start_pos = $end_envlist+2; ${$r_act_output}[9] = substr($raw_actdata,$start_pos,1); # change numeric values to strings for display if (${$r_act_output}[9] eq "0") { #UndefResFlag ${$r_act_output}[9] = "\"n\""; } else { ${$r_act_output}[9] = "\"y\""; } if ($Trace) {print STDERR "$PROGNAME: leaving process_action_data\n";} } # end sub process_action_data #--------------------------------------------------------------------# # cvt_dow - convert raw DaysOfWeek data to display format # # # # Return: $dow_str display-friendly DaysOfWeek string # # # # Input parameters: # # $raw_dow_str raw DaysOfWeek data # #--------------------------------------------------------------------# sub cvt_dow{ my $raw_dow_str = shift; my $raw_dow = 0; my $dow_str = ""; my $i = 0; my $range_ct = 0; my @day_arr = ( $FALSE, $FALSE, $FALSE, $FALSE, $FALSE, $FALSE, $FALSE ); if ($Trace) {print STDERR "$PROGNAME: entering cvt_dow\n";} $raw_dow += $raw_dow_str; # special case: 0 and 127 both mean days 1-7 ($raw_dow == 0) && ($raw_dow = 127); # figure out which days are specified if ($raw_dow >= 64) { $raw_dow -= 64; $day_arr[6] = $TRUE; } if ($raw_dow >= 32) { $raw_dow -= 32; $day_arr[5] = $TRUE; } if ($raw_dow >= 16) { $raw_dow -= 16; $day_arr[4] = $TRUE; } if ($raw_dow >= 8) { $raw_dow -= 8; $day_arr[3] = $TRUE; } if ($raw_dow >= 4) { $raw_dow -= 4; $day_arr[2] = $TRUE; } if ($raw_dow >= 2) { $raw_dow -= 2; $day_arr[1] = $TRUE; } if ($raw_dow == 1) { $day_arr[0] = $TRUE; } # now build the DaysOfWeek display string for( $i = 1; $i < 8; $i++ ) { if (!$day_arr[$i-1]) { # this day was not selected, so zero out range counter # and loop again $range_ct = 0; next; } else { # this day was selected if ($dow_str eq "") { # first day selected - copy to output, bump range counter $dow_str = $i; $range_ct++; next; } else { if ($range_ct > 0) { if ($range_ct > 1) { if ($range_ct > 2) { # range of 3 or more days already exists # delete last day number and replace with this one chop($dow_str); $dow_str .= $i; $range_ct++; next; } else { # matched 3rd day in range - delete "+x" and # replace with "-y" to denote range chop($dow_str); chop($dow_str); $dow_str .= "-" . $i; $range_ct++; next; } # end if ($range_ct > 2) } else { # matched 2nd day in range - just add "+x" to # existing string $dow_str .= "+" . $i; $range_ct++; next; } # end if ($range_ct > 1) } else { # discontiguous day matched $dow_str .= "+" . $i; $range_ct++; next; } # end if ($range_ct > 0) } # end if ($dow_str eq "") } # end if (!$day_arr[$i-1]) } # end for loop if ($Trace) {print STDERR "$PROGNAME: leaving cvt_dow\n";} return($dow_str); } # end sub cvt_dow #--------------------------------------------------------------------# # cvt_tod - convert raw TimeOfDay data to display format # # - used for both start and end time data # # # # Return: $tod_str TimeOfDay string in HHMM format # # # # Input parameters: # # $raw_tod_str raw TimeOfDay data # #--------------------------------------------------------------------# sub cvt_tod{ my $raw_tod_str = shift; my $tod_str = ""; my $time_hrs = 0; my $time_mins = 0; if ($Trace) {print STDERR "$PROGNAME: entering cvt_tod\n";} use integer; $time_hrs = $raw_tod_str / 3600; $time_mins = ($raw_tod_str - $time_hrs * 3600) / 60; # if hours or minutes in single digits, add leading 0 to # provide HHMM format if ($time_hrs < 10) { $time_hrs = "0" . $time_hrs; } if ($time_mins < 10) { $time_mins = "0" . $time_mins; } $tod_str = $time_hrs . $time_mins; no integer; if ($Trace) {print STDERR "$PROGNAME: leaving cvt_tod\n";} return($tod_str); } # end sub cvt_tod #--------------------------------------------------------------------# # display_cmd_ex - print example mkresponse command to stdout # # # # Return: none # # # # Input parameters: # # $r_resps reference to two-dimensional array containing # # response data formatted for output # #--------------------------------------------------------------------# sub display_cmd_ex { my $r_resps = shift; my $r_resp_row = 0; my $act_name = ""; my $dow = ""; my $tod = ""; my $act_scrpt = ""; my $ret_code = ""; my $ev_type = ""; my $resp_name = ""; my $resp_name_msg = ""; # 71402 my $act_name_msg = ""; # 71402 my $batch = ""; my $i = 0; my $aname_idx = 2; my $date_idx = 3; my $time_idx = 4; my $ascr_idx = 5; my $rtcd_idx = 6; my $evtp_idx = 8; my $evbc_idx = 12; # reset index if in cluster if ($cluster_env) { $aname_idx = 3; $date_idx = 4; $time_idx = 5; $ascr_idx = 6; $rtcd_idx = 7; $evtp_idx = 9; $evbc_idx = 13; } foreach $r_resp_row (@$r_resps) { if ($i == 0) { # skip row 0 - it contains column headings $i++; next; } # extract data from output array $act_name = ${$r_resp_row}[$aname_idx]; $dow = ${$r_resp_row}[$date_idx]; $tod = ${$r_resp_row}[$time_idx]; $act_scrpt = ${$r_resp_row}[$ascr_idx]; $ret_code = ${$r_resp_row}[$rtcd_idx]; $ev_type = ${$r_resp_row}[$evtp_idx]; chop($ev_type); $ev_type =~ s/\"//; $resp_name = ${$r_resp_row}[1]; $resp_name_msg = $resp_name; # 71402 $resp_name_msg =~ s/\"//g; # 71402 $act_name_msg = $act_name; # 71402 $act_name_msg =~ s/\"//g; # 71402 if (${$r_resp_row}[$evbc_idx] =~ /y/) {$batch=" -b ";} # display the example command unless ($Opt_No_HDR) { printIMsg("IMsglsresponseMkrespEx", $resp_name_msg, $act_name_msg); } printf "mkresponse -n %s -d %s -t %s -s %s -e %s -r %s %s %s\n", $act_name, $dow, $tod, $act_scrpt, $ev_type, $ret_code, $batch, $resp_name; print "\n"; } } # end display_cmd_ex #--------------------------------------------------------------------# # print_usage : print the usage statement (syntax) to stdout. # #--------------------------------------------------------------------# sub print_usage { &printIMsg("IMsglsresponseUsageB"); } # end print_usage #-------------------------------------------------------------------# # containSplChar : returns with error msg if the string has spl char# #-------------------------------------------------------------------# 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("EMsglsresponseInvalidResponseName",$specialCharString{$code}); return 1; } } return 0; }