#!/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,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 = "@(#)18   1.22   src/rsct/rm/ConfigRM/cli/bin/lscomg.perl, configrmcli, rsct_rady, rady2035a 11/12/15 16:41:03"
######################################################################
#                                                                    #
# Module: lscomg                                                     #
#                                                                    #
# Purpose:                                                           #
#   lscomg - lists information about the communication groups of a   #
#            cluster.                                                #
#                                                                    #
# Syntax:                                                            #
#   lscomg   [-h]  [-l|-t|-d|-D Delimiter] [-x] [-TV]                # 
#            [Communication_group]                                   #
#                                                                    #
# Flags:                                                             #
#   -h      Help. Writes the command's usage statement to standard   #
#           output.                                                  #
#   -l      Long formatted output.  The information is displayed on  #
#           separate lines.                                          #
#   -t      Tabular formatted output.  The information is displayed  #
#           in separate columns.                                     #
#   -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.           #
#   -x      Exlude header.  Suppress header printing.                #
#   -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.                                         #
#                                                                    #
# Operands:                                                          #
#   Communication_group    The name of the communication group to be #
#           listed. Communication_group may be a communication group #
#           name or a substring of a communication group name.  When #
#           it is a substring, any defined communication group  name #
#           that contains the substring will be listed.              #
#                                                                    #
# Description:                                                       #
#   The lscomg command lists information about the communication     #
#   groups defined to the online cluster where the command runs.     #
#   When a communication group is specified, the information is      #
#   limitted to that communication group information only.           #
#                                                                    #
#                                                                    #
# Exit Values:                                                       #
#   0  CRM_CLI_SUCCESS       Command completed successfully.         #
#   1  CRM_CLI_RMC_ERROR     Command terminated due to an underlying #
#                            RMC error.                              #
#   2  CRM_CLI_ERROR         Command terminated due to an underlying #
#                            error in the command script.            #
#   3  CRM_CLI_BAD_FLAG      Command terminated due to user          #
#                            specifying an invalid flag.             #
#   4  CRM_CLI_BAD_OPERAND   Command terminated due to user          #
#                            specifying a bad operand.               #
#   5  CRM_CLI_USER_ERROR    Command terminated due to a user error, #
#                            for example specifying a name that      #
#                            already exists.                         #
#                                                                    #
# Examples:                                                          #
#                                                                    #
# Man Page:                                                          #
#   For the most current detailed description of this command see    #
#   the lscomg man page in /opt/rsct/man.                       #
#                                                                    #
#--------------------------------------------------------------------#
# Inputs:                                                            #
#   /opt/rsct/msgmaps/configrmcli.lscomg.map -                  # 
#       message mapping                                              #
#                                                                    #
# Outputs:                                                           #
#   stdout - none.                                                   #
#   stderr - any error message.                                      #
#                                                                    #
# External Ref:                                                      #
#   Commands: ctdspmsg                                               #
#   Modules:  CRM_cli_utils.pm, CRM_cli_rc.pm,                       #
#             CRM_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:                                                   #
#   010806 JAC 75435: Initial design & write.                        #
#   011008 JAC 75442: Final version.                                 #
#   011130 JAC 77315: updates for final approved design.             #
#   020204 JAC 80023: update to use lsrsrc-api instead of lsrsrc.    #
#   020206 JAC 80077: Add NLS support for heading and xlate values.  #
#   020207 JAC 80121: Make printing of c-api results a trace msg.    #
#   020207 JAC 79346: Add NodeNameList to -i output.                 #
#   020207 JAC 80133: Issue not found message if a comg specified.   #
#   020214 JAC 80323: Remove braces around nodenamelist for -i.      #
#   020428 JAC 82316: Call process_exit_code to check $rc.           #
#   020503 JAC 82564: Set peer domain scope before calling lsrsrc-api#
#   040407 JAC 105863: Use escape_chars for "\" searches.            #
#   040422 JAC 108194: Use escape_selstr for comg name and use LIKE  #
#                      in select string.                             #
#   050406 JAC 119510: Add rc when calling process_api_error.        #
#   071210 JAC 147147: Use PeriodMillSec and add Grace.              #
######################################################################

#--------------------------------------------------------------------#
# General Program Flow/Logic:                                        #
#                                                                    #
# 1. Setup attributes to list with the command.                      #
# 2. Parse command line flags and operands.                          #
# 3. Print usage if -h specified                                     #
# 4. Setup a selection string if a node name operand was specified.  #
# 5. List the node information used the RMC lsrsrc command.          #
#    Also pass along -VT if necessary.                               #
# 6. Return back any errors from lsrsrc.                             #
# 7. Format the output into a 2D array so a utility can be used.     #
# 8. Set the type of output to display (long, table, ...).           #
# 9. Call the set_display utility to display the output.             #
#                                                                    #
#--------------------------------------------------------------------#

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

use CT_cli_utils qw(printIMsg
                    printEMsg);
use CT_cli_input_utils qw(escape_chars);

use CT_cli_display_utils qw(set_display);

use CRM_cli_rc qw(CRM_CLI_SUCCESS CRM_CLI_RMC_ERROR
                  CRM_CLI_ERROR CRM_CLI_BAD_FLAG
                  CRM_CLI_COMG_NOT_FOUND
                  CRM_CLI_BAD_OPERAND CRM_CLI_USER_ERROR);
use CRM_cli_utils qw(error_exit
                     printCIMsg
                     printCEMsg
                     getIMsg
                     process_api_error
                     process_exit_code
                     escape_selstr
                     lookup_yesno
                     lookup_mediatype);
use CRM_cli_include qw($TRUE $FALSE
                       $RSCOMG $RMC_CLI_USER_ERROR
                       $DELIMITER $RSNETI $RSHBI
                       $PEER_DOMAIN_SCOPE
                       $RMC_CLI_RSRC_NOT_FOUND
                       $CTBINDIR $CTDIR);

my $delimiter = "#:#";
$DELIMITER = $delimiter; # override so utils don't choke on IPv6 "::"

#--------------------------------------------------------------------#
# Global Constants                                                   #
#--------------------------------------------------------------------#

# attribute names
$Attr_name = "Name";
$Attr_sensitivity = "Sensitivity";
$Attr_period = "PeriodMilliSec";
$Attr_priority = "Priority";
$Attr_broadcast = "UseBroadcast";
$Attr_sourcerte = "UseSourceRouting";
#$Attr_configch = "ConfigChanged";
$Attr_NIMpname = "NIMPathName";
$Attr_NIMparms = "NIMParameters";
$Attr_grace = "PingGracePeriodMilliSec";
$Attr_MediaType = "MediaType";
$Attr_UseForNodeMbrship = "UseForNodeMembership";

$lsr_attr_names = $Attr_name;
$lsr_attr_names .= "${delimiter}$Attr_sensitivity";
$lsr_attr_names .= "${delimiter}$Attr_period";
$lsr_attr_names .= "${delimiter}$Attr_priority";
$lsr_attr_names .= "${delimiter}$Attr_broadcast";
$lsr_attr_names .= "${delimiter}$Attr_sourcerte";
$lsr_attr_names .= "${delimiter}$Attr_NIMpname";
$lsr_attr_names .= "${delimiter}$Attr_NIMparms";
$lsr_attr_names .= "${delimiter}$Attr_grace";
$lsr_attr_names .= "${delimiter}$Attr_MediaType";
$lsr_attr_names .= "${delimiter}$Attr_UseForNodeMbrship";

# attribute names for -i flag (NetworkInterface)
$Attr_name = "Name";
$Attr_nodename = "NodeNameList";
$Attr_ipaddr = "IPAddress";
$Attr_subnet = "Subnet";
$Attr_subnetmsk = "SubnetMask";

$lsr_attr_names2 = $Attr_name;
$lsr_attr_names2 .= "${delimiter}$Attr_nodename";
$lsr_attr_names2 .= "${delimiter}$Attr_ipaddr";
$lsr_attr_names2 .= "${delimiter}$Attr_subnet";
$lsr_attr_names2 .= "${delimiter}$Attr_subnetmsk";

# attribute names for -i flag (HeartbeatInterface)
$Attr_deviceinfo = "DeviceInfo";
$lsr_attr_names3 = $Attr_name;
$lsr_attr_names3 .= "${delimiter}$Attr_nodename";
$lsr_attr_names3 .= "${delimiter}$Attr_deviceinfo";
$lsr_attr_names3 .= "${delimiter}$Attr_MediaType";

#--------------------------------------------------------------------#
# Global Variables                                                   #
#--------------------------------------------------------------------#
$Trace = $FALSE;                        # default - trace off
$Verbose = $FALSE;                      # default - verbose turned off
$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 = $FALSE;              # default - long formatted output
$Opt_Table_Format = $TRUE;              # default - tabular format 
$Opt_No_HDR = $FALSE;                   # default - do not supress heading
                                        # output, -x flag
$Opt_Display_i = $FALSE;                # default - no -i 

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

#--------------------------------------------------------------------#
# Variables                                                          #
#--------------------------------------------------------------------#
my $comg_name = "";                     # communication group to list
my $comg_name_orig = "";                # communication group to list
my $name_select = "";                   # selection string for name
my @lsr_out = ();                       # output from lsrsrc            
my @lof_comgs = ();                     # 2D array to be displayed      
my $attr_name = "";                     # an attribute name
my @attr_names = ();                    # all attribute names
my $attr_val = "";                      # an attribute value
my @attr_vals = ();                     # all attribute values
my $line = "";                          # one line of output
my $i = 0;                              # array index
my $j = 0;                              # array index
my $row_count = 0;                      # number of display rows
my $col_count = 0;                      # number of display columns
my $display_type = "";                  # type of display call
my $broadcst_index = 5;                 # output index for broadcast
my $sourcert_index = 6;                 # output index for source rte
my $nodename_index = 2;                 # output index for nodename
my $period_index = 3;                   # output index for period
my $grace_index = 9;                    # output index for grace
my $mediatype_index = 10;               # output index for MediaType
my $mediatype_index_i = 4;              # output index for MediaType for -i flag
my $resource_class = "";                # class to list
my @heading = ();                       # heading for listing data
my $msg_ptr = "1X";                     # keep track of which msg
my @noyestext = ();                     # for translating no/yes
my @gracetext = ();                     # for translating 0/-1
my @mediatypetext = ();                 # for translating MediaType
my %media_types = ();                     # hash for MediaType descriptions

my $passopts = "";                      # TV options to pass to RMC CLI
my $other_opts = "";                    # parameters to pass to RMC CLI
#--------------------------------------------------------------------#
# Main Code                                                          #
#--------------------------------------------------------------------#
my $rc = 0;
my $config_rc = 0;

# set peer domain scope
$ENV{CT_MANAGEMENT_SCOPE} = $PEER_DOMAIN_SCOPE;

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

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

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

# Do some escaping on strings.  Do the escape character first
# for anything that's a string, escape any inner \
#$comg_name =~ s/\\/\\\\/g;

# for anything that's a string, escape any inner double quotes
#$comg_name =~ s/\"/\\\"/g;

$comg_name_orig = $comg_name;
$comg_name = escape_chars($comg_name);
$comg_name = escape_selstr($comg_name);

# if a comg name was entered, build a select clause
if ($comg_name ne "") {
   # $name_select = "-s ${RSCOMG}${delimiter}\"Name ?= \\\"$comg_name\\\"\"";
   $name_select = "-s ${RSCOMG}${delimiter}\"Name LIKE \\\"%${comg_name}%\\\"\"";
}
# for no name, use o flag for list
else {
   $name_select = "-o ${RSCOMG}";
}

# if -i specified, switch some things 
if ($Opt_Display_i) { 
   # Check MediaType
   @lsr_out = `$CTBINDIR/lsrsrc-api -I"$delimiter" -s ${RSCOMG}${delimiter}\"Name == \\\"$comg_name_orig\\\"\"${delimiter}MediaType 2>&1`;
   # capture the return code from lsrsrc-api
   $rc = $?;
   $rc = process_exit_code($rc);
   if ($Trace) { print STDERR "lsrsrc-api results:\n";
              print "@lsr_out";}
   if ($Trace) { print STDERR "$PROGNAME: lsrsrc-api returned $rc\n";}
   # show any errors if there was a bad rc
   if (($rc != 0) && ($rc != $RMC_CLI_RSRC_NOT_FOUND)) {
      process_api_error($DELIMITER,$rc,@lsr_out);
   }
   # return ConfigRM CLI user error if it's an RMC CLI user error
   if ($rc == $RMC_CLI_USER_ERROR) { exit(CRM_CLI_USER_ERROR);}
   if ($rc == $RMC_CLI_RSRC_NOT_FOUND) { 
       printEMsg("EMsglscomgComgNotFound",$comg_name_orig);
       exit(CRM_CLI_COMG_NOT_FOUND);
   }

   my $mediatype = $lsr_out[0];
   chomp($mediatype);
   # change the attribute names and selection string
   if ($mediatype == 1) {
       $lsr_attr_names = $lsr_attr_names2;
       $name_select = "-s ${RSNETI}${delimiter}\"CommGroup == \\\"$comg_name_orig\\\"\"";
       $msg_ptr = 2;
   } else {
       $lsr_attr_names = $lsr_attr_names3;
       $name_select = "-s ${RSHBI}${delimiter}\"CommGroup == \\\"$comg_name_orig\\\"\"";
       $msg_ptr = 3;
   }

}

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

#@lsr_out = `$CTBINDIR/lsrsrc -x -D $DELIMITER $passopts $name_select $RSCOMG $lsr_attr_names`;
#@lsr_out = `$CTBINDIR/lsrsrc -x -D $DELIMITER $passopts $name_select $resource_class $lsr_attr_names`;
@lsr_out = `$CTBINDIR/lsrsrc-api -D"$DELIMITER" -I"$delimiter" ${name_select}${delimiter}${delimiter}${delimiter}${lsr_attr_names} 2>&1`;

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

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

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

# show any errors if there was a bad rc
if (($rc != 0) && ($rc != $RMC_CLI_RSRC_NOT_FOUND)) {
   process_api_error($DELIMITER,$rc,@lsr_out);
}

# return ConfigRM CLI user error if it's an RMC CLI user error
if ($rc == $RMC_CLI_USER_ERROR) { exit(CRM_CLI_USER_ERROR);}

# return OK if resource not found error, unless comg name specified
if ($rc == $RMC_CLI_RSRC_NOT_FOUND) {
   if ($comg_name eq "") { exit(0);}
   else {
      if ($Opt_Display_i) {
         if ($msg_ptr == 2) {
            printEMsg("EMsglscomgNetiNotFound",$comg_name_orig);
         } else {
            printEMsg("EMsglscomgHbiiNotFound",$comg_name_orig);
         }
      }
      else { printEMsg("EMsglscomgComgNotFound",$comg_name_orig);}
      exit(CRM_CLI_COMG_NOT_FOUND);
   }
}

# if lsrsrc failed for something else, print RMC error message and exit
if ($rc != 0) {
#   printCEMsg("EMsgConfigRMcliUnExpectRMCrc",$rc);
    exit(CRM_CLI_RMC_ERROR);
    }

# form 2D array to pass to display utils

# get heading from message file
@heading = getIMsg("IMsglscomgHeading$msg_ptr");

# form heading
@attr_names = split(/::/,$heading[0]);
$i = 1;
foreach $attr_name (@attr_names) {
   $lof_comgs[0][$i] = $attr_name;
   $i++;
} 

# get from message file what to use for no/yes
@noyestext = getIMsg("IMsglscomgNoYes");
@noyestext = split(/::/,$noyestext[0]);

# get from message file what to use for Grace
@gracetext = getIMsg("IMsglscomgGraceValues");
@gracetext = split(/::/,$gracetext[0]);

# get from message file what to use for MediaType
@mediatypetext = getIMsg("IMsglscomgMediaType");
@mediatypetext = split(/::/,$mediatypetext[0]);

# fill in the hash for opstates
for ($mt_cnt=0;$mt_cnt<=$#mediatypetext;$mt_cnt=$mt_cnt+2) {
   $media_types{$mediatypetext[$mt_cnt]} = $mediatypetext[$mt_cnt+1];
}

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

   # parse the output
   @attr_vals = split(/$DELIMITER/, $line);

   # put into array
#  $lof_comgs[$i][0] = "\nnode $i:";
   $lof_comgs[$i][0] = " ";
   $j = 1;
   foreach $attr_val (@attr_vals) {
      # translate source routing and broadcast when not -i
      if ( !$Opt_Display_i && ($j == $broadcst_index) || ($j == $sourcert_index)) {
         $attr_val = lookup_yesno($attr_val,@noyestext);
      }

      # format the period and grace period output when not -i
      if ( !$Opt_Display_i && ($j == $period_index) || ($j == $grace_index)) {
         $attr_val = &format_period($attr_val);

         # translate grace values, if necessary
         if ( $j == $grace_index ) {
            $attr_val = lookup_grace($attr_val,@gracetext);
         }
      }

      # translate MediaType
      if ($Opt_Display_i) {
          if (($msg_ptr == 3) && ($j == $mediatype_index_i)) {
              $attr_val = lookup_mediatype($attr_val,%media_types);
          }
      } else {
          if ($j == $mediatype_index) {
              $attr_val = lookup_mediatype($attr_val,%media_types);
          }
      }

      # get rid of braces in nodenamelist when -i used
      if ( $Opt_Display_i && ($j == $nodename_index)) {
         $attr_val =~ s/{//g;
         $attr_val =~ s/}//g;
      }
     
      # put output into the output array 
      $lof_comgs[$i][$j] = $attr_val;
      $j++;
   }
   $i++;
}

# set how many rows of data there is
$row_count = $#lof_comgs; 
$col_count = scalar(@{$lof_comgs[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");

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

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

if ($config_rc == 0) { exit($rc); }
else { exit($config_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.   #
#         CRM_CLI_BAD_FLAG   Command line contained a bad flag.      #
#   $node_name               Name of node to list.                   #
#                                                                    #
# Global Variables Modified:                                         #
#   $Verbose           output   True (-V) turn Verbose mode on.      #
#   $Trace             output   True (-T) turn Trace mode on.        #
#   $Opt_Delm_Format   output   True (-d,-D) delimited output        #
#   $Opt_Delm_Str      output   char (-D) delimiter character        #
#   $Opt_Long_Format   output   True (-l) long formatted output      #
#   $Opt_Table_Format  output   True (-t) tabular formatted output   #
#   $Opt_No_HDR        output   True (-x) supress heading            #
#   $Opt_Display_i     output   True (-i) display interface resources#
#--------------------------------------------------------------------#
sub parse_cmd_line 
{
my(@original_argv) = @ARGV;
my $comg_name = "";                     # comunication name    
my %opts = ();

# Process the command line...
if (!&getopts('hltdD:xiVT', \%opts)) {  # Gather options; 
                                        # if errors
    &print_usage;                       # display proper usage
    return CRM_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{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_Long_Format = $FALSE;
    $Opt_Delm_Format = $FALSE;
}

if (defined $opts{l}) {                 # -l long formatted output
    $Opt_Long_Format = $TRUE;
    $Opt_Table_Format = $FALSE;
    $Opt_Delm_Format = $FALSE;
}

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

# Get the arguments...
# Operands:  comg name      
if ($#ARGV <= 0) {                      # comg name 
   if ($#ARGV == 0) {
      $comg_name = shift @ARGV;         # get comg name
   }
}

else {            
    # cluster name not specified or too many
    printCEMsg("EMsgConfigRMcliInvalidNumberOfOperands");
    &print_usage;
    return CRM_CLI_BAD_OPERAND;
}

if (defined $opts{i}) {                 # -i show interface resources
    $Opt_Display_i = $TRUE;   
    if ($comg_name eq "") {             # name required with -i
       printEMsg("EMsglscomgNameRequired","-i");
       return CRM_CLI_USER_ERROR;
    }
}

return(0, $comg_name);                  # success

}   # end parse_cmd_line


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


#--------------------------------------------------------------------#
# format_period: format the period from milliseconds to seconds.     #
#                                                                    #
# Parameters:                                                        #
#   $in_value        Milliseconds value.                             #
#                                                                    #
# Returns:                                                           #
#   $out_value       Formatted Seconds value.                        #
#                                                                    #
# Global Variables:                                                  #
#--------------------------------------------------------------------#
sub format_period
{
   my $in_value = shift(@_);
   my $out_value = $in_value;

   # format all values >0
   if ($in_value > 0) {

      # convert from milliseconds to seconds
      $out_value = $in_value / 1000;

      # format to 3 decimal places
      $out_value = sprintf "%0.3f",$out_value;

      # get rid of trailing 0's
      $out_value =~ s/0+$//;

      # get rid of an ending decimal point
      $out_value =~ s/\.$//;
   }

return ($out_value);
}   # format_period


#--------------------------------------------------------------------#
# lookup_grace : Translates the grace values to a text string, if    #
#   one exists for the particular grace value.                       #
#                                                                    #
# Parameters:                                                        #
#   $in_grace        Grace value to check and make substitute.       #
#                                                                    #
# Returns:                                                           #
#   $out_grace       The grace text to use for $in_grace, or just    #
#                    $in_grace if no substitution is done.           #
#                                                                    #
# Global Variables:                                                  #
#--------------------------------------------------------------------#
sub lookup_grace
{
my %grace_vals = ();                    # hash for grace descriptions
my $use_quotes = $FALSE;                # boolean flag
my $one_descr = "";                     # one from list of descriptions

# get inputs
my $in_grace = shift @_;
%grace_vals = @_;

#set default $out_grace
my $out_grace = $in_grace;

# figure out if quotes are needed around strings
if ( (defined $ENV{CT_CLI_QUOTE_STRING}) &&
    ($ENV{CT_CLI_QUOTE_STRING} == 1) ) {
    $use_quotes = $TRUE;
}

# see if grace value to find exists
if (defined $grace_vals{$in_grace}) {
   $out_grace = $grace_vals{$in_grace};

   # add quotes if necessary
   if ($use_quotes) {
      $out_grace = "\"".$out_grace."\"";
   }
}

return($out_grace);
}   #  end of lookup_grace