MINI MINI MANI MO

Path : /opt/oracle/product/18c/dbhomeXE/lib/
File Upload :
Current File : //opt/oracle/product/18c/dbhomeXE/lib/asmcmdaudit.pm

###############################################################################
# Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved.
#
#    NAME
#      asmcmdaudit - ASM CoMmanD line interface AUDIT operations
#
#    DESCRIPTION
#      This file contains the ASMCMD interface to use the DBMS_AUDIT_MGMT
#      procedures implemented in 'rdbms/src/server/security/audit/dbmsamgt.sql'
#      for the ASM instance
#
#    MODIFIED  (MM/DD/YY)
#    smurdia    03/23/17  - Bug-20266009: Argument for AUDIT_TRAIL should be
#                           lower case.
#    diguzman   05/30/16  - 19654070: Little change at _no_instance_cmd routine
#    pvenkatr   02/25/14  - Bug #18294879 - replaced numbers with strings in 
#                           select queries (for lsaudXXX commands)
#    pvenkatr   06/05/13  - Initial version from gssshan code
#
#
#############################################################################
#
############################ Functions List #################################
#
# Top Level Command Processing Routines
#   asmcmdaudit_int
#   asmcmdaudit_process_cmd
#   asmcmdaudit_process_audcleanaudittrail
#   asmcmdaudit_process_audclearproperty
#   asmcmdaudit_process_audcleartimestamp
#   asmcmdaudit_process_audcreatejob
#   asmcmdaudit_process_auddropjob
#   asmcmdaudit_process_audloaduniauditfiles
#   asmcmdaudit_process_audsettraillocation
#   asmcmdaudit_process_audsetproperty
#   asmcmdaudit_process_audsetdebug
#   asmcmdaudit_process_audsettimestamp
#   asmcmdaudit_process_audsetjobinterval
#   asmcmdaudit_process_audsetjobstatus
#   asmcmdaudit_process_lsaudcleanevents
#   asmcmdaudit_process_lsaudcleanupjobs
#   asmcmdaudit_process_lsaudconfigparams
#   asmcmdaudit_process_audshowtimestamp
#
# Parameter Parsing Routines
#   asmcmdaudit_parse_int_args
#   asmcmdaudit_is_cmd
#   asmcmdaudit_is_wildcard_cmd
#   asmcmdaudit_is_no_instance_cmd
#
# Error Routines
#   asmcmdaudit_syntax_error
#
# Help Routines
#   asmcmdaudit_get_asmcmd_cmds
#############################################################################

package asmcmdaudit;
require Exporter;
our @ISA    = qw(Exporter);
our @EXPORT = qw(asmcmdaudit_init
                 asmcmdaudit_process_help
                 asmcmdaudit_process_cmd
                 asmcmdaudit_is_cmd
                 asmcmdaudit_parse_int_args
                 asmcmdaudit_is_no_instance_cmd
                 asmcmdaudit_is_wildcard_cmd
                 asmcmdaudit_syntax_error
                 asmcmdaudit_get_asmcmd_cmds
                 );

use strict;
use DBI;
use Getopt::Std;
use DBI qw(:sql_types);
use asmcmdglobal;
use asmcmdshare;
use asmcmdbase;
use asmcmdparser;
use XML::Parser;
use asmcmdexceptions;
use asmcmdxmlexceptions;

#####################  Global Constants  ######################################
## NOTE:  These constants are defined in dbmsamgt.sql/dbmsasma.sql file(s).
## Constants
my ($AUDIT_TRAIL_OS)          = 4  ;    # Audit Trail type - OS
my ($AUDIT_TRAIL_UNI)         = 51 ;    # Audit Trail type - UNI
my ($AUDIT_TRACE_LEVEL_DEBUG) = 1  ;    # Audit Debug Trace level - debug
my ($AUDIT_TRACE_LEVEL_ERROR) = 2  ;    # Audit Debug Trace Level - error
my ($AUDIT_PURGE_JOB_ENABLE)  = 31 ;    # Audit Purge job status - enable
my ($AUDIT_PURGE_JOB_DISABLE) = 32 ;    # Audit Purge job status - disable
my ($AUDIT_OS_FILE_MAX_SIZE)  = 16 ;    # Audit File Configuration - Max size
my ($AUDIT_OS_FILE_MAX_AGE)   = 17 ;    # Audit File Configuration - Max age.

# string contstants
my ($AUDIT_TRAIL_OS_STR)   = "OS_AUDIT_TRAIL" ;      # AUDIT TRAIL TYPE - OS
my ($AUDIT_TRAIL_UNI_STR)  = "UNIFIED_AUDIT_TRAIL" ; # AUDIT TRAIL TYPE - UNI

my ($ASMCMDAUDIT_HDR_INSTID)       = 'Instance';
my ($ASMCMDAUDIT_HDR_TRAILTYPE)    = 'Type';
my ($ASMCMDAUDIT_HDR_LASTARCHTIME) = 'Last Archived';
my ($ASMCMDAUDIT_HDR_CLEANUPTIME)  = 'Cleanup Time';
my ($ASMCMDAUDIT_HDR_DELETED)      = 'Deleted';
my ($ASMCMDAUDIT_HDR_FORCED)       = 'Forced';
my ($ASMCMDAUDIT_HDR_JOBNAME)      = 'Name';
my ($ASMCMDAUDIT_HDR_JOBSTATUS)    = 'Status';
my ($ASMCMDAUDIT_HDR_JOBFREQ)      = 'Frequency';
my ($ASMCMDAUDIT_HDR_PARAMNAME)    = 'Parameter Name';
my ($ASMCMDAUDIT_HDR_PARAMVALUE)   = 'Parameter Value';



#  The following list is used primarily for is_cmd.  All other data come from
#  XML file.
###############################################################################

my (%asmcmdaudit_cmds) = (
    audcleanaudittrail   => {},     # To deletes audit trail records
    audclearproperty     => {},     # Clear Property
    audcleartimestamp    => {},     # Clear the Timestamp
    audcreatejob         => {},     # Create Audit Purge Job
    auddropjob           => {},     # Drop Audit Purge Job
    audloaduniauditfiles => {},     # To move from OS to DG.
    audsettraillocation  => {},     # To set the Audit Trail location
    audsetproperty       => {},     # Set Property
    audsetdebug          => {},     # Set the Debug level
    audsettimestamp      => {},     # Set Timestamp
    audsetjobinterval    => {},     # Set Audit Purge Job Interval
    audsetjobstatus      => {},     # Set Audit Purge Job Status
    lsaudcleanevents     => {},     # to fetch and display audit clean events
    lsaudcleanupjobs     => {},     # to fetch and display cleanup job details
    lsaudconfigparams    => {},     # to fetch and display config parameters
    audshowtimestamp     => {}      # to fetch and display last archive ts.
    );

########
# NAME
#   asmcmdaudit_init
#
# DESCRIPTION
#   This function initializes the asmcmdaudit module.  It
#   registers its callbacks with the asmcmdglobal module.
#
# PARAMETERS
#   None
#
# RETURNS
#   Null
#
# NOTES
#   Only asmcmdcore_main() calls this routine.
########
sub init
{
  # All of the arrays defined in the asmcmdglobal module must be 
  # initialized here.  Otherwise, an internal error will result.
  push (@asmcmdglobal_command_callbacks,     \&asmcmdaudit_process_cmd);
  push (@asmcmdglobal_help_callbacks,        \&asmcmdaudit_process_help);
  push (@asmcmdglobal_command_list_callbacks,\&asmcmdaudit_get_asmcmd_cmds);
  push (@asmcmdglobal_is_command_callbacks,  \&asmcmdaudit_is_cmd);
  push (@asmcmdglobal_is_wildcard_callbacks, \&asmcmdaudit_is_wildcard_cmd);
  push (@asmcmdglobal_syntax_error_callbacks,\&asmcmdaudit_syntax_error);
  push (@asmcmdglobal_no_instance_callbacks,
                                             \&asmcmdaudit_is_no_instance_cmd);

  %asmcmdglobal_cmds = (%asmcmdglobal_cmds, %asmcmdaudit_cmds);
  
  #Perform ASMCMD consistency check if enabled
  if($asmcmdglobal_hash{'consistchk'} eq 'y')
  {
    if(!asmcmdshare_check_option_consistency(%asmcmdaudit_cmds))
    {
      exit 1;
    }
  }
}

########
# NAME
#   asmcmdaudit_process_cmd
#
# DESCRIPTION
#   This routine calls the appropriate routine to process the command 
#   specified by $asmcmdglobal_hash{'cmd'}.
#
# PARAMETERS
#   dbh       (IN) - initialized database handle, must be non-null.
#
# RETURNS
#   1 if command is found in the asmcmdaudit module; 0 if not.
#
# NOTES
#   Only asmcmdcore_shell() calls this routine.
########
sub asmcmdaudit_process_cmd 
{
  my ($dbh) = @_;
  my ($succ) = 0;

  # Get current command from global value, which is set by 
  # asmcmdaudit_parse_asmcmd_args()and by asmcmdcore_shell().
  my ($cmd) = $asmcmdglobal_hash{'cmd'};

  # Declare and initialize hash of function pointers, each designating a 
  # routine that processes an ASMCMDAUDIT command.
  my (%cmdhash) = (
       audcleanaudittrail       => \&asmcmdaudit_process_audcleanaudittrail,
       audclearproperty         => \&asmcmdaudit_process_audclearproperty,
       audcleartimestamp        => \&asmcmdaudit_process_audcleartimestamp,
       audcreatejob             => \&asmcmdaudit_process_audcreatejob ,
       auddropjob               => \&asmcmdaudit_process_auddropjob,
       audloaduniauditfiles     => \&asmcmdaudit_process_audloaduniauditfiles,
       audsetdebug              => \&asmcmdaudit_process_audsetdebug,
       audsetjobinterval        => \&asmcmdaudit_process_audsetjobinterval,
       audsetjobstatus          => \&asmcmdaudit_process_audsetjobstatus,
       audsetproperty           => \&asmcmdaudit_process_audsetproperty,
       audsettimestamp          => \&asmcmdaudit_process_audsettimestamp,
       audsettraillocation      => \&asmcmdaudit_process_audsettraillocation,
       audshowtimestamp         => \&asmcmdaudit_process_audshowtimestamp,
       lsaudcleanevents         => \&asmcmdaudit_process_lsaudcleanevents,
       lsaudcleanupjobs         => \&asmcmdaudit_process_lsaudcleanupjobs,
       lsaudconfigparams        => \&asmcmdaudit_process_lsaudconfigparams
  );

  if (defined ( $cmdhash{ $cmd } ))
    {
      # If user specifies a known command, then call routine to process it. #
      $cmdhash{ $cmd }->($dbh);
      $succ = 1;
    }

  return $succ;
}

###############################################################################
sub is_asmcmd
{
  return 1;
}


########
# NAME
#   asmcmdaudit_process_help
#
# DESCRIPTION
#   This function is the help function for the ASMCMDAUDIT module.
#
# PARAMETERS
#   command     (IN) - display the help message for this command.
#
# RETURNS
#   1 if command found; 0 otherwise.
########
sub asmcmdaudit_process_help 
{
  my ($command) = shift;       # User-specified argument; show help on $cmd. #
  my ($syntax);                                   # Command syntax for $cmd. #
  my ($desc);                                # Command description for $cmd. #
  my ($succ) = 0;                         # 1 if command found, 0 otherwise. #

  if (asmcmdaudit_is_cmd ($command)) 
  {
    $desc = asmcmdshare_get_help_desc($command);
    asmcmdshare_print "$desc\n";
    $succ = 1;
  }

  return $succ;
}

########
# NAME
#   asmcmdaudit_is_cmd
#
# DESCRIPTION
#   This routine checks if a user-entered command is one of the known
#   ASMCMD internal commands that belong to the ASMCMDAUDIT module.
#
# PARAMETERS
#   arg   (IN) - user-entered command name string.
#
# RETURNS
#   True if $arg is one of the known commands, false otherwise.
########
sub asmcmdaudit_is_cmd 
{
  my ($arg) = shift;
  return defined($asmcmdaudit_cmds{$arg});
}

########
# NAME
#   asmcmdaudit_is_wildcard_cmd
#
# DESCRIPTION
#   This routine determines if an ASMCMDAUDIT command allows the use 
#   of wild cards.
#
# PARAMETERS
#   arg   (IN) - user-entered command name string.
#
# RETURNS
#   True if $arg is a command that can take wildcards as part of its argument, 
#   false otherwise.
########
sub asmcmdaudit_is_wildcard_cmd 
{
  my ($arg) = shift;

  return defined ($asmcmdaudit_cmds{ $arg }) &&
    (asmcmdshare_get_cmd_wildcard($arg) eq "true" ) ;
}


########
# NAME
#   asmcmdaudit_is_no_instance_cmd
#
# DESCRIPTION
#   This routine determines if a command can run without an ASM instance.
#
# PARAMETERS
#   arg   (IN) - user-entered command name string.
#
# RETURNS
#   1 if $arg is a command that can run without an ASM instance or it does not
#   belong to this module
#   0 if $arg is a command that needs to connect to an ASM instance
#   -1 if $arg is a command that may use an ASM instance.
#
# NOTES
#   The asmcmdaudit module currently supports no command that can run 
#   without an ASM instance.
########
sub asmcmdaudit_is_no_instance_cmd 
{
  my ($arg) = shift;
  my ($rc);

  return 1 unless defined($asmcmdaudit_cmds{$arg});

  $rc = asmcmdshare_get_cmd_noinst($arg);
  if ($rc eq "true")
  {
    return 1;
  }
  elsif ($rc eq "undef")
  {
    return -1;
  }

  return 0;
}

########
# NAME
#   asmcmdaudit_parse_int_args
#
# DESCRIPTION
#   This routine parses the arguments for flag options for ASMCMDAUDIT 
#   internal commands.  
#
# PARAMETERS
#   cmd      (IN)  - user-entered command name string.
#   args_ref (OUT) - hash of user-specified flag options for a command, 
#                    populated by getopts().
#
# RETURNS
#   Zero on success; undefined on error.
#
# NOTES
#   $cmd must already be verified as a valid ASMCMDAUDIT internal command.
########
sub asmcmdaudit_parse_int_args 
{
  my ($cmd, $args_ref) = @_;
  my (@string);
  
  # Use asmcmdparser_parse_issued_command() from the asmcmdparser package
  # to parse arguments for internal commands.  These arguments are stored
  # in @ARGV.

  if (!asmcmdparser_parse_issued_command($cmd, $args_ref,\@string))
  {
    # Print correct command format if syntax error. #
    asmcmdaudit_syntax_error($cmd);
    return undef;
  }
  return 0;
}

########
# NAME
#   asmcmdaudit_syntax_error
#
# DESCRIPTION
#   This function prints the correct syntax for a command to STDERR, used 
#   when there is a syntax error.  This function is responsible for 
#   only ASMCMDAUDIT commands.
#
# PARAMETERS
#   cmd   (IN) - user-entered command name string.
#
# RETURNS
#   1 if the command belongs to this module; 0 if command not found.
#
# NOTES
#   These errors are user-errors and not internal errors.  They are of type
#   record, not signal.  
# 
#   N.B. Functions in this module can call this function directly, without
#   calling the asmcmdshare::asmcmdshare_syntax_error equivalent.  The
#   latter is used only by the asmcmdcore module.
########
sub asmcmdaudit_syntax_error 
{
  my ($cmd) = shift;
  my ($cmd_syntax);                               # Correct syntax for $cmd. #
  my ($succ) = 0;

  #display syntax only for commands in this module.
  if (asmcmdaudit_is_cmd($cmd))
    {
      $cmd_syntax = asmcmdshare_get_help_syntax($cmd); # Get syntax for $cmd. #
      $cmd_syntax = asmcmdshare_trim_str ($cmd_syntax);   # Trim blank spaces #

      asmcmdshare_printstderr 'usage: ' . $cmd_syntax . "\n";
      asmcmdshare_printstderr 'help:  help ' . $cmd . "\n";
      $succ = 1;

      if ($asmcmdglobal_hash{'mode'} eq 'n')
      {
        $asmcmdglobal_hash{'e'} = -1;
      }
    }
  return $succ;
}

########
# NAME
#   asmcmdaudit_get_asmcmd_cmds
#
# DESCRIPTION
#   This routine constructs a string that contains a list of the names of all 
#   ASMCMD internal commands and returns this string.
#
# PARAMETERS
#   None.
#
# RETURNS
#   A string contain a list of the names of all ASMCMD internal commands.
#
# NOTES
#   Used by the help command and by the error command when the user enters
#   an invalid internal command.
#
#   IMPORTANT: the commands names must be preceded by eight (8) spaces of
#              indention!  This formatting is mandatory.
########
sub asmcmdaudit_get_asmcmd_cmds 
{
  return asmcmdshare_filter_invisible_cmds (%asmcmdaudit_cmds);
}


###############################################################################
#  AUDIT Purge job command implementation
###############################################################################

###############################################################################
# NAME
#   asmcmdaudit_process_audcleanaudittrail
#
# DESCRIPTION
#   To delete audit trail records
#
# PARAMETERS
#   $trailtype      - OS or UNI
#   $usetimestamp   - Use LAST_ARCHIVE_TIMESTAMP value
#                If TRUE -> all records older than TIMESTAMP will be deleted
#                If FALSE - all records are deleted.
#
# RETURNS
#   -none-
#
###############################################################################
sub asmcmdaudit_process_audcleanaudittrail
{
  my ($dbh)          = shift ;
  my ($usetimestamp) = 0;
  my ($trailtype);
  my ($ret, $stmt);
  my (%args);

  $ret = asmcmdaudit_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined $ret;

  $trailtype = $AUDIT_TRAIL_OS      if (defined($args{'os'}));
  $trailtype = $AUDIT_TRAIL_UNI     if (defined($args{'uni'}));
  $usetimestamp =  1                if (defined($args{'useTimestamp'}));

  # To convert useTimestamp value to PL/SQL BOOLEAN
  $stmt = $dbh->prepare(<<END_SQL );
  DECLARE
    bool_val BOOLEAN;
  BEGIN
    IF :usetimestamp = 0 THEN
      bool_val := FALSE;
    ELSE 
      bool_val := TRUE;
    END IF;
  
    dbms_audit_mgmt.clean_audit_trail(:trailType, bool_val);
  END;
END_SQL

  $stmt->bind_param(":trailType",     $trailtype,      DBI::SQL_INTEGER);
  $stmt->bind_param(":usetimestamp",  $usetimestamp                    );

  $ret = $stmt->execute();

  if(!defined($ret))
  {
    if ($asmcmdglobal_hash{'mode'} eq 'n')
    {
      $asmcmdglobal_hash{'e'}= -1;
    }
    asmcmdshare_trace (1, "$DBI::errstr", 'y', 'y');
  }
}


###############################################################################
# NAME
#   asmcmdaudit_process_audclearproperty
#
# DESCRIPTION
#   To clear the value of the given property
#
# PARAMETERS
#   property name         - trailtype (OS/UNI), max_sz, use_def
#
# RETURNS
#   -None-
#
###############################################################################
sub asmcmdaudit_process_audclearproperty
{
  my $dbh = shift;
  my %args;
  my ($trailtype, $propname, $use_def);
  my ($stmt, $ret);

  $ret = asmcmdaudit_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined $ret;

  $trailtype = $AUDIT_TRAIL_OS      if(defined($args{'os'}));
  $trailtype = $AUDIT_TRAIL_UNI   if(defined($args{'uni'}));

  $propname = $AUDIT_OS_FILE_MAX_SIZE  if(defined($args{'max_sz'}));
  $propname = $AUDIT_OS_FILE_MAX_SIZE  if(defined($args{'max_age'}));

  $use_def = 0;
  $use_def = 1 if defined($args{'use_def'});

  $stmt = $dbh -> prepare( <<END_SQL );
  DECLARE
    bool_val BOOLEAN;
  BEGIN
    IF :useDef = 0 THEN bool_val := FALSE;
  ELSE bool_val := TRUE;
  END IF;

    dbms_audit_mgmt.clear_audit_trail_property(:trailType,
                                               :prop,
                                               bool_val);
  END;
END_SQL

  $stmt->bind_param(":trailType", $trailtype);
  $stmt->bind_param(":prop", $propname);
  $stmt->bind_param(":useDef", $use_def);

  $ret = $stmt->execute();

  if(!defined($ret))
  {
    if ($asmcmdglobal_hash{'mode'} eq 'n')
    {
      $asmcmdglobal_hash{'e'}= -1;
    }
    asmcmdshare_trace (1, "$DBI::errstr", 'y', 'y');
  }
}


###############################################################################
# NAME
#   asmcmdaudit_process_audcleartimestamp
#
# DESCRIPTION
#   To clear the audit purge job timestamp
#
# PARAMETERS
#   $dbh                - ASM connection handle
#   $trailtype          - os/uni
#   $inst               - instance number
#
# RETURNS
#   none
###############################################################################
sub asmcmdaudit_process_audcleartimestamp
{
  my ($dbh) = shift;
  my ($trailtype, $inst);
  my (%args, $ret, $stmt) ;

  $ret = asmcmdaudit_parse_int_args ($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined($ret);

  $trailtype = $AUDIT_TRAIL_OS    if (defined ($args{'os'}));
  $trailtype = $AUDIT_TRAIL_UNI   if (defined ($args{'uni'}));

  $inst = $args{'ins'} if defined($args{'ins'});

  # if the audit trail type is OS, then instance number is required.
  if ( ($trailtype == $AUDIT_TRAIL_OS) && !defined ($inst))
  {
      asmcmdshare_error_msg (9501, undef);
      return;
  }

  # Bug-20266009: Should be :inst instead of $inst
  $stmt = $dbh->prepare(q{
    begin
      dbms_audit_mgmt.clear_last_archive_timestamp(:trailtype, :inst);
    end;
  });

  $stmt->bind_param(":trailtype", $trailtype);
  $stmt->bind_param(":inst", $inst);

  $ret = $stmt->execute();

  if (!defined ($ret))
  {
    if ($asmcmdglobal_hash{'mode'} eq 'n')
    {
      $asmcmdglobal_hash{'e'} = -1 ;
    }
    asmcmdshare_trace (1, "$DBI::errstr", 'y', 'y');
  }
}


###############################################################################
# NAME
#    asmcmdaudit_process_audcreatejob
#
# DESCRIPTION
#    This function creates the Audit Purge job
#
# PARAMETERS
#    $dbh  - ASM Connection handle
#
# RETURNS
#    -None-
#
###############################################################################
sub asmcmdaudit_process_audcreatejob
{
  my $dbh = shift;
  my %args;
  my ($jobName, $purge_interval, $trailtype, $usetimestamp);
  my ($stmt, $ret);

  # check the arguments
  $ret = asmcmdaudit_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined $ret;

  # check if Audit files are from OS
  $trailtype = $AUDIT_TRAIL_OS    if (defined ($args{'os'}));
  $trailtype = $AUDIT_TRAIL_UNI   if (defined ($args{'uni'}));

  # timestamp
  $usetimestamp = 1;
  $usetimestamp = 0  if(defined($args{'no_use'}));

  # job name
  $jobName  = $args{'name'};
  chomp($jobName);
  # purge interval
  $purge_interval  = $args{'int'};

  # To convert useTimestamp value to PL/SQL BOOLEAN
  $stmt = $dbh->prepare(<<END_SQL );
  DECLARE
    bool_val BOOLEAN;
  BEGIN
    IF :useTs = 0 THEN bool_val := FALSE;
    ELSE bool_val := TRUE;
    END IF;
  
    dbms_audit_mgmt.create_purge_job(:trailType, 
                                     :purgeInt,
                                     :jName,
                                     bool_val);
  END;
END_SQL

  $stmt->bind_param(":trailType", $trailtype,      DBI::SQL_INTEGER);
  $stmt->bind_param(":purgeInt",  $purge_interval, DBI::SQL_INTEGER);
  $stmt->bind_param(":jName",     $jobName,        DBI::SQL_VARCHAR);
  $stmt->bind_param(":useTs",     $usetimestamp                    );

  $ret = $stmt->execute();

  if(!defined($ret))
  {
    if ($asmcmdglobal_hash{'mode'} eq 'n')
    {
      $asmcmdglobal_hash{'e'}= -1;
    }
    asmcmdshare_trace (1, "$DBI::errstr", 'y', 'y');
  }
}

###############################################################################
# NAME
#   asmcmdaudit_process_auddropjob
#
# DESCRIPTION
#   To drop the sepcified Audit Purge Job.
#
# PARAMETERS
#   $jobName         - Audit Purge Job Name
#
# Returns
#   -None-
###############################################################################
sub asmcmdaudit_process_auddropjob
{
  my $dbh = shift;
  my %args;
  my ($jobName);
  my ($stmt, $ret);

  $ret = asmcmdaudit_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined $ret;

  # Job Name
  $jobName  = $args{'name'};

  $stmt = $dbh->prepare(q{
    begin
      dbms_audit_mgmt.drop_purge_job(:jobName);
    end;
  });

  $stmt->bind_param(":jobName", $jobName);

  $ret = $stmt->execute();

  if(!defined($ret))
  {
    if ($asmcmdglobal_hash{'mode'} eq 'n')
    {
      $asmcmdglobal_hash{'e'}= -1;
    }
    asmcmdshare_trace (1, "$DBI::errstr", 'y', 'y');
  }
}


###############################################################################
# NAME
#   asmcmdaudt_process_audloaduniauditfiles
#
# DESCRIPTION
#   To move the audit files stored in OS before SGA is initialized to DG.
#
# PARAMETERS
#   -None-
#
# RETURNS
#   -None-
#
###############################################################################
sub asmcmdaudit_process_audloaduniauditfiles
{
  my ($dbh) = shift;
  my ($stmt, $ret);

  $stmt = $dbh->prepare(q{
    begin
      dbms_audit_mgmt.load_unified_audit_files ();
    end;
    });

  $ret = $stmt->execute ();

  if (!defined ($ret))
  {
    if ($asmcmdglobal_hash{'mode'} eq 'n')
    {
      asmcmdglobal_hasn{'e'} = -1;
    }
    asmcmdshare_trace (1, "$DBI::errstr", 'y', 'y');
  }
}


###############################################################################
# NAME
#   asmcmdaudit_process_audsettraillocation
#
# DESCRIPTION
#   To move the audit trail location (one DG to another DG).
#
# PARAMETERS
#   $trailtype      -  OS or UNI
#   $traillocation  -  location of audit trail files
#
# RETURNS
#   -none-
#
# NOTE:  The target DG is assumed to have sufficient space for audit files
###############################################################################
sub asmcmdaudit_process_audsettraillocation
{
  my ($dbh) = shift;
  my ($trailtype) = $AUDIT_TRAIL_UNI;
  my ($traillocation);
  my (%args);
  my ($stmt, $ret);

  # check the arguments
  $ret = asmcmdaudit_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined $ret;

  ($traillocation) = shift (@{$args{'audsettraillocation'}});

  $stmt = $dbh->prepare (q{
    begin
      dbms_audit_mgmt.set_audit_trail_location ( :trailType, :traillocation);
    end;
  });

  #
  # In case of ASM, trail location is only on Diskgroup, and so
  # trailtype = OS is not applicable.  To keep the inferface same,
  # undefined is passed here.
  #
  
  $stmt->bind_param(":trailtype", $trailtype);
  $stmt->bind_param(":traillocation", $traillocation);

  $ret = $stmt->execute ();
  if (!defined($ret))
  {
    if ($asmcmdglobal_hash{'mode'} eq 'n')
    {
      asmcmdglobal_hash{'e'} = -1;
    }
    asmcmdshare_trace (1, "$DBI::errstr", 'y', 'y');
  }
}

###############################################################################
# NAME
#   asmcmdaudit_process_audsetjobstatus
#
# DESCRIPTION
#   To update the job status (enable/disable)
#
# PARAMETERS
#    $jobName             - Name of Audit Purge Job
#    $state               - State Enable/Disable
#
# RETURNS
#    -None-
#
###############################################################################
sub asmcmdaudit_process_audsetjobstatus
{
  my $dbh = shift;
  my %args;
  my ($jobName, $state);
  my ($stmt, $ret);

  $ret = asmcmdaudit_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined $ret;

  $jobName = $args{'name'};
  $state = $AUDIT_PURGE_JOB_ENABLE    if (defined($args{'enable'}));
  $state = $AUDIT_PURGE_JOB_DISABLE   if (defined($args{'disable'}));

  $stmt = $dbh->prepare(q{
    begin
      dbms_audit_mgmt.set_purge_job_status(:jName, :stat);
    end;
  });

  $stmt->bind_param(":jName", $jobName);
  $stmt->bind_param(":stat", $state);

  $ret = $stmt->execute();

  if(!defined($ret))
  {
    if ($asmcmdglobal_hash{'mode'} eq 'n')
    {
      $asmcmdglobal_hash{'e'}= -1;
    }
    asmcmdshare_trace (1, "$DBI::errstr", 'y', 'y');
  }
}

###############################################################################
# NAME
#   asmcmdaudit_process_audsetjobinterval
#
# DESCRIPTION
#   To specify the interval for the Audit Purge job
#
# PARAMETERS
#   $jobname      - name of the Audit Purge Job.
#   $interval     - duration
#
# RETURNS
#   -None-
###############################################################################
sub asmcmdaudit_process_audsetjobinterval
{
  my $dbh = shift;
  my %args;
  my ($jobName, $interval);
  my ($stmt, $ret);

  $ret = asmcmdaudit_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined $ret;

  $jobName   = $args{'name'};
  $interval  = $args{'int'};

  $stmt = $dbh->prepare(q{
    begin
      dbms_audit_mgmt.set_purge_job_interval(:jName, :purgeInt);
    end;
  });

  $stmt->bind_param(":jName",    $jobName);
  $stmt->bind_param(":purgeInt", $interval);

  $ret = $stmt->execute();

  if(!defined($ret))
  {
    if ($asmcmdglobal_hash{'mode'} eq 'n')
    {
      $asmcmdglobal_hash{'e'}= -1;
    }
    asmcmdshare_trace (1, "$DBI::errstr", 'y', 'y');
  }
}

###############################################################################
# NAME
#   asmcmdaudit_process_auditsetproperty
#
# DESCRIPTION
#   To update the properties
#
# PARAMETERS
#   $trailtype  - audit trail type - OS or UNI
#   $max_sz
#
# RETURNS
#   -none-
###############################################################################
sub asmcmdaudit_process_audsetproperty
{
  my $dbh = shift;
  my %args;
  my ($trailtype, $propname, $propvalue);
  my ($stmt, $ret);

  $ret = asmcmdaudit_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined $ret;

  # property value
  $propvalue  = $args{'val'};

  $trailtype = $AUDIT_TRAIL_OS       if (defined($args{'os'}));
  $trailtype = $AUDIT_TRAIL_UNI      if(defined($args{'uni'}));

  $propname = $AUDIT_OS_FILE_MAX_SIZE    if (defined($args{'max_sz'}));
  $propname = $AUDIT_OS_FILE_MAX_AGE     if (defined($args{'max_age'}));

  $stmt = $dbh->prepare(q{
    begin
      dbms_audit_mgmt.set_audit_trail_property(:trailType, :prop, :value);
    end;
  });

  $stmt->bind_param(":trailType",  $trailtype);
  $stmt->bind_param(":prop",       $propname);
  $stmt->bind_param(":value",      $propvalue);

  $ret = $stmt->execute();

  if(!defined($ret))
  {
    if ($asmcmdglobal_hash{'mode'} eq 'n')
    {
      $asmcmdglobal_hash{'e'}= -1;
    }
    asmcmdshare_trace (1, "$DBI::errstr", 'y', 'y');
  }
}



###############################################################################
# NAME
#   asmcmdaudit_process_audsetdebug
#
# DESCRIPTION
#   To set the debug level (debug/error).
#
# PARAMETERS
#   level         - debug/error
#
# RETURNS
#   -none-
###############################################################################
sub asmcmdaudit_process_audsetdebug
{
  my $dbh = shift;
  my %args;
  my ($ret, $stmt);
  my ($level);

  $ret = asmcmdaudit_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined $ret;
  $level = $AUDIT_TRACE_LEVEL_DEBUG       if (defined($args{'debug'}));
  $level = $AUDIT_TRACE_LEVEL_ERROR       if (defined($args{'error'}));

  $stmt = $dbh->prepare(q{
    begin
      dbms_audit_mgmt.set_debug_level(:level);
    end;
  });

  $stmt->bind_param(":level", $level);

  $ret = $stmt->execute();

  if(!defined($ret))
  {
    if ($asmcmdglobal_hash{'mode'} eq 'n')
    {
      $asmcmdglobal_hash{'e'}= -1;
    }
    asmcmdshare_trace (1, "$DBI::errstr", 'y', 'y');
  }
}

###############################################################################
# NAME
#   asmcmdaudit_process_audsettimestamp
#
# DESCRIPTION
#   To update the timestamp for Audit Purge jobs
#
# PARAMETERS
#   $trailtype       - os or uni
#   $instnumber      - instance number
#   $timestamp       - timestamp
#
# RETURNS
#  -none
###############################################################################
sub asmcmdaudit_process_audsettimestamp
{
  my $dbh = shift;
  my %args;
  my ($ret, $stmt);
  my ($trailtype, $timestamp, $inst_no);
  my ($date, $time);

  $ret = asmcmdaudit_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined $ret;

  $trailtype = $AUDIT_TRAIL_OS       if (defined($args{'os'}));
  $trailtype = $AUDIT_TRAIL_UNI      if(defined($args{'uni'}));

  $inst_no = 0;
  $inst_no = $args{'ins'} if(defined($args{'ins'}));

  # For OS Trail type, instance number is required.
  # For UNI trail type, instance number is ignored.
  if (($trailtype == $AUDIT_TRAIL_OS) && ($inst_no == 0 ))
  {
    asmcmdshare_error_msg (9502, undef);
    return;
  }
  
  ####
  my $arglist = join (',', @{$args{'audsettimestamp'}});
  
  if (defined($args{'audsettimestamp'}))
  {
    ($date) = shift (@{$args{'audsettimestamp'}});
  }
  if (defined($args{'audsettimestamp'}))
  {
    ($time) = shift (@{$args{'audsettimestamp'}});
  }
  if (defined ($date) && defined ($time))
  {
    $timestamp = "$date $time";
  }
  
  if ($timestamp =~ /=/)
  {
    $timestamp = s/=/ /g ;
  }

  $stmt = $dbh->prepare(q{
    begin
      dbms_audit_mgmt.set_last_archive_timestamp(:trailType,
                                                 :timestamp,
                                                 :inst_no);
    end;
  });

  $stmt->bind_param(":trailType", $trailtype);
  $stmt->bind_param(":timestamp", $timestamp);
  $stmt->bind_param(":inst_no",  $inst_no);

  $ret = $stmt->execute();
  if(!defined($ret))
  {
    if ($asmcmdglobal_hash{'mode'} eq 'n')
    {
      $asmcmdglobal_hash{'e'}= -1;
    }
    asmcmdshare_trace (1, "$DBI::errstr", 'y', 'y');
  }
}

###############################################################################
# NAME
#   asmcmdaudit_process_lsaudcleanevents
#
# DESCRIPTION
#   To print the histoyr of audit trail cleanup of purge events
#
# PARAMETERS
#   $dbh        - ASM Connection handle
#   $trailtype  - OS or UNI
#
# RETURNS
#   -none-
###############################################################################
sub asmcmdaudit_process_lsaudcleanevents
{
  my ($dbh) = shift;
  my ($qry, $sth, $row, $ret);
  my ($trailtype);
  my ($cleanuptime, $deletedcount, $forced);
  my ($format, $print_string, @rowvalues);
  my (%args);

  # Get the arguments
  $ret = asmcmdaudit_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined $ret;

  # trailtype
  # Bug-20266009: Argument for AUDIT_TRAIL should be in lower case.
  $trailtype = $AUDIT_TRAIL_OS_STR    if (defined($args{'os'})) ;
  $trailtype = $AUDIT_TRAIL_UNI_STR   if (defined($args{'uni'})) ;

  # Get last-archived-timestamp based on given or all trailtype(s)
  $qry  = 'SELECT AUDIT_TRAIL, CLEANUP_TIME, DELETE_COUNT, WAS_FORCED';
  $qry .= ' FROM V$ASM_AUDIT_CLEAN_EVENTS';
  $qry .= ' WHERE AUDIT_TRAIL =?' if (defined($trailtype));

  $format = "%-5s  %-13s  %-7s  %-6s\n";
  push (@rowvalues, $ASMCMDAUDIT_HDR_TRAILTYPE);
  push (@rowvalues, $ASMCMDAUDIT_HDR_CLEANUPTIME);
  push (@rowvalues, $ASMCMDAUDIT_HDR_DELETED);
  push (@rowvalues, $ASMCMDAUDIT_HDR_FORCED);
  $print_string = sprintf ($format, @rowvalues);
  asmcmdshare_print ($print_string);
  
  eval
  {
    $sth = asmcmdshare_do_prepare ($dbh, $qry);
    $sth->bind_param(1,$trailtype) if (defined($trailtype));
    asmcmdshare_do_execute($sth);
  };
  if (asmcmdexceptions::catch())
  {
    asmcmdshare_trace (1, $DBI::errstr, 'y', 'y');
  }

  while (defined ($row = asmcmdshare_fetch ($sth)))
  {
    @rowvalues = ();  # empty
    $trailtype = "OS"  if (defined($row->{'AUDIT_TRAIL'}) &&
                             $row->{'AUDIT_TRAIL'} == 1) ;
    $trailtype = "UNI"  if (defined($row->{'AUDIT_TRAIL'}) && 
                             $row->{'AUDIT_TRAIL'} == 51) ;
    $trailtype = "" if (!defined($trailtype));
    
    $cleanuptime = $row->{'CLEANUP_TIME'};
    $cleanuptime = "" if (!defined($cleanuptime));
    
    $deletedcount = $row->{'DELETE_COUNT'};
    $forced      = $row->{'WAS_FORCED'};
    $forced = "NO" if (!defined($forced));

    push (@rowvalues, $trailtype);
    push (@rowvalues, $cleanuptime);
    push (@rowvalues, $deletedcount);
    push (@rowvalues, $forced);
    $print_string = sprintf ($format, @rowvalues);
    asmcmdshare_print ($print_string);
  }
  asmcmdshare_finish($sth);
}

###############################################################################
# NAME
#   asmcmdaudit_process_lsaudcleanupjobs
#
# DESCRIPTION
#   To display information about the configured audit trail purge jobs.
#
# PARAMETERS
#   $dbh        - ASM connection handle
#   $trailtype  - OS or UNI
#
# RETURNS
#   -none-
###############################################################################
sub asmcmdaudit_process_lsaudcleanupjobs
{
  my ($dbh) = shift;
  my ($qry, $sth, $row, $ret);
  my ($trailtype);
  my ($name, $status, $freq);
  my ($format, $print_string, @rowvalues);
  my (%args);

  # Get the arguments
  $ret = asmcmdaudit_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined $ret;

  # trailtype
  # Bug-20266009: Arguments to AUDIT_TRAIL should be in lower case. 
  $trailtype = $AUDIT_TRAIL_OS_STR    if (defined($args{'os'})) ;
  $trailtype = $AUDIT_TRAIL_UNI_STR   if (defined($args{'uni'})) ;

  # Get last-archived-timestamp based on given or all trailtype(s)
  $qry  = 'SELECT JOB_NAME, JOB_STATUS, AUDIT_TRAIL, JOB_FREQUENCY';
  $qry .= ' FROM V$ASM_AUDIT_CLEANUP_JOBS';
  $qry .= ' WHERE AUDIT_TRAIL = ? ' if (defined($trailtype));

  $format = "%-5s  %-25s %-10s %-10s\n";
  push (@rowvalues, $ASMCMDAUDIT_HDR_TRAILTYPE);
  push (@rowvalues, $ASMCMDAUDIT_HDR_JOBNAME);
  push (@rowvalues, $ASMCMDAUDIT_HDR_JOBSTATUS);
  push (@rowvalues, $ASMCMDAUDIT_HDR_JOBFREQ);
  $print_string = sprintf ($format, @rowvalues);
  asmcmdshare_print ($print_string);

  eval
  {
    $sth = asmcmdshare_do_prepare ($dbh, $qry);
    $sth->bind_param (1, $trailtype) if (defined($trailtype));
    asmcmdshare_do_execute ($sth);
  };
  if (asmcmdexceptions::catch())
  {
    asmcmdshare_trace (1, $DBI::errstr, 'y', 'y');
  }

  while (defined ($row = asmcmdshare_fetch ($sth)))
  {
    @rowvalues = ();
    $trailtype = "OS"  if (defined($row->{'AUDIT_TRAIL'}) &&
                             $row->{'AUDIT_TRAIL'} eq $AUDIT_TRAIL_OS_STR) ;
    $trailtype = "UNI"  if (defined($row->{'AUDIT_TRAIL'}) && 
                             $row->{'AUDIT_TRAIL'} eq $AUDIT_TRAIL_UNI_STR) ;
    $trailtype = "" if (!defined($trailtype));
    $name  = $row->{'JOB_NAME'};
    $name = "" if (!defined($name));
    $status = $row->{'JOB_STATUS'};
    $status = "" if (!defined ($status));
    $freq  = $row->{'JOB_FREQUENCY'};
    $freq = "" if (!defined($freq));

    push (@rowvalues, $trailtype);
    push (@rowvalues, $name);
    push (@rowvalues, $status);
    push (@rowvalues, $freq);
    $print_string = sprintf ($format, @rowvalues);
    asmcmdshare_print ($print_string);
  }
  asmcmdshare_finish($sth);
}

###############################################################################
# NAME
#   asmcmdaudit_process_lsaudconfigparams
#
# DESCRIPTION
#   To display information about the currently configured audit trail 
#   properties.
#
# PARAMETERS
#   $dbh                   -  ASM Connection handle
#   $trailtype             -  OS or UNI
#
# RETURNS
#   -none-
###############################################################################
sub asmcmdaudit_process_lsaudconfigparams
{
  my ($dbh) = shift;
  my ($qry, $sth, $row, $ret);
  my ($trailtype);
  my ($name, $value);
  my ($format, $print_string, @rowvalues);
  my (%args);

  # Get the arguments
  $ret = asmcmdaudit_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined $ret;

  # trailtype
  # Bug-20266009: Arguments for AUDIT_TRAIL should be lower case. 
  $trailtype = $AUDIT_TRAIL_OS_STR    if (defined($args{'os'})) ;
  $trailtype = $AUDIT_TRAIL_UNI_STR   if (defined($args{'uni'})) ;

  # Get last-archived-timestamp based on given or all trailtype(s)
  $qry  = 'SELECT PARAMETER_NAME, PARAMETER_VALUE';
  $qry .= ' FROM V$ASM_AUDIT_CONFIG_PARAMS';
  $qry .= ' WHERE AUDIT_TRAIL = ?' if (defined($trailtype));

  $format = "%-5s  %-25s  %-25s\n";
  push (@rowvalues, $ASMCMDAUDIT_HDR_TRAILTYPE);
  push (@rowvalues, $ASMCMDAUDIT_HDR_PARAMNAME);
  push (@rowvalues, $ASMCMDAUDIT_HDR_PARAMVALUE);
  $print_string = sprintf ($format, @rowvalues);
  asmcmdshare_print ($print_string);

  eval
  {
    $sth = asmcmdshare_do_prepare ($dbh, $qry);
    $sth->bind_param (1, $trailtype) if (defined($trailtype));
    asmcmdshare_do_execute($sth);
  };
  if (asmcmdexceptions::catch())
  {
    asmcmdshare_trace (1, $DBI::errstr, 'y', 'y');
  }

  while (defined ($row = asmcmdshare_fetch ($sth)))
  {
    @rowvalues = ();  # empty the array.
    $trailtype = "";
    # Bug-20266009: The value of OS_AUDIT_TRAIL type is 4.
    $trailtype = "OS"  if (defined($row->{'AUDIT_TRAIL'}) &&
                             $row->{'AUDIT_TRAIL'} == 4) ;
    $trailtype = "UNI"  if (defined($row->{'AUDIT_TRAIL'}) && 
                             $row->{'AUDIT_TRAIL'} == 51) ;
    $name  = $row->{'PARAMETER_NAME'};
    $name = "" if (!defined($name));
    $value = $row->{'PARAMETER_VALUE'};
    $value = "" if (!defined($value));

    push (@rowvalues, $trailtype);
    push (@rowvalues, $name);
    push (@rowvalues, $value);
    $print_string = sprintf ($format, @rowvalues);
    asmcmdshare_print ($print_string);
  }
  asmcmdshare_finish($sth);
}


###############################################################################
# NAME
#   asmcmdaudit_process_audshowtimestamp
#
# DESCRIPTION
#   To fetch and display last archived time stamp for given or all trail types
#
# PARAMETERS
#   $dbh           -   ASM connection handle
#   $trailtype     -   OS or UNI
#
# RETURNS
#   -none-
###############################################################################
sub asmcmdaudit_process_audshowtimestamp
{
  my ($dbh) = shift;
  my ($qry, $sth, $row, $ret);
  my ($trailtype);
  my ($format, $print_string);
  my (@rowvalues);
  my (%args);
  my ($global) = 0;                       # iff -g option specified.
  my ($instid);

  # Get the arguments
  $ret = asmcmdaudit_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined $ret;

  # trailtype
  # Bug-20266009: AUDIT_TRAIL in V$ASM_AUDIT_LAST_ARCH_TS is of varchar type
  # hence trailtype should be a string instead of a number.
  $trailtype = $AUDIT_TRAIL_OS_STR    if (defined($args{'os'})) ;
  $trailtype = $AUDIT_TRAIL_UNI_STR   if (defined($args{'uni'})) ;

  # global
  $global = 1 if (defined($args{'g'}) && defined($args{'os'}));

  # Get last-archived-timestamp based on given or all trailtype(s)
  $qry = 'SELECT     AUDIT_TRAIL, LAST_ARCHIVE_TS'  if ($global == 0 );
  $qry = 'SELECT     INST_ID, AUDIT_TRAIL, LAST_ARCHIVE_TS' if ($global == 1);

  $qry .= ' FROM GV$ASM_AUDIT_LAST_ARCH_TS' if ($global == 1 );
  $qry .= ' FROM  V$ASM_AUDIT_LAST_ARCH_TS' if ($global == 0 );
  $qry .= ' WHERE AUDIT_TRAIL = ?' if (defined($trailtype));

  $format = "%-5s  %-13s\n"  if ($global == 0);   # Trail type & Timestamp
  $format = "%-10s  %-5s  %-13s\n" if ($global == 1);  # inst_id also.
  push (@rowvalues, $ASMCMDAUDIT_HDR_INSTID) if ($global == 1);
  push (@rowvalues, $ASMCMDAUDIT_HDR_TRAILTYPE);
  push (@rowvalues, $ASMCMDAUDIT_HDR_LASTARCHTIME);
  $print_string = sprintf ($format, @rowvalues);
 
  # print headers
  asmcmdshare_print ($print_string);

  eval
  {
    $sth = asmcmdshare_do_prepare ($dbh, $qry);
    $sth->bind_param (1, $trailtype) if (defined($trailtype));
    asmcmdshare_do_execute($sth);
  };
  if (asmcmdexceptions::catch())
  {
    asmcmdshare_trace (1, $DBI::errstr, 'y', 'y');
  }

  while (defined ($row = asmcmdshare_fetch ($sth)))
  {
    @rowvalues = () ;  #clear the arrary.

    # in case if timestamp is not set, we get a valid row with empty values.
    # Bug-20266009: INST_ID is only required in RAC configuration for OS 
    # trail type.
    if ( (defined($row->{'AUDIT_TRAIL'})) &&
         (defined ($row->{'LAST_ARCHIVE_TS'})))
    {
      $instid = $row->{'INST_ID'} if ($global == 1);  # only when -g specified
      push (@rowvalues, $instid) if ($global == 1);
      
      $trailtype = "OS"  if (defined($row->{'AUDIT_TRAIL'}) &&
                             $row->{'AUDIT_TRAIL'} eq $AUDIT_TRAIL_OS_STR) ;
      $trailtype = "UNI"  if (defined($row->{'AUDIT_TRAIL'}) && 
                             $row->{'AUDIT_TRAIL'} eq $AUDIT_TRAIL_UNI_STR) ;
      push (@rowvalues, $trailtype);
      push (@rowvalues, $row->{'LAST_ARCHIVE_TS'});
      $print_string = sprintf ($format, @rowvalues);
      asmcmdshare_print ($print_string);
    }
  }
  asmcmdshare_finish($sth);
}

1;

OHA YOOOO