#!/usr/bin/env perl
$dist_pgmr = "";
#======================================================================
# orastat
#======================================================================
# Env:
#  - ORACLE_HOME and ORACLE_SID must be set
#  - PATH must include ORACLE_HOME/bin
#  - You must be running an ID with gid=dba
# Usage:
#  - Run 'orastat --' to view usage table
# Author:
#  - Bill Border 03/2000
# Changes:
#
#   Ver  Date    Programmer   Desc
#   ==== ======= ============ =========================================
#   1.29 18Aug00 Bill Border  Added -ad archive dest
#   1.30 22Aug00 Dean Riggio  Added -bp backup processes and
#                             -ss tablespace storage
#   1.31 08Nov00 Bill Border  orastat can only be run by someone in
#                             group 'dba'.
#   1.32 10Nov00 Bill Border  Added -ug
#   1.33 18Nov00 Bill Border  Renames -sc to -ti and added more data to
#                             the report.
#   1.34 01Feb01 Bill Border  Added -au
#   1.35 02Feb01 Bill Border  Added -tb and -vw
#   1.36 28Feb01 Bill Border  Added -vs
#                Craig Geier  Added -so
#                Craig Geier  Added -tu
#   1.37 18Apr01 Bill Border  Added -in (list indexes)
#   1.38 18Apr01 Bill Border  Added -op (OPS v$ping table)
#   1.39 19Apr01 Bill Border  Added -ba (List dbamon.backup_age contents)
#   1.40 02May01 Bill Border  Added -rp
#   1.41 18May01 Bill Border  Added -tt
#   1.42 22May01 Bill Border  Added DBID to orastat -
#   1.43 28May01 Bill Border  Added -sr
#   1.44 20Jun01 Bill Border  Added -ar
#   1.45 05Jul01 Dean Riggio  Updated -se to show SPID
#   1.46 31Jul01 Craig Geier  Updated - Fixed erroneous uptime for
#                                       version 7 and 8.0
#        31Jul01 Craig Geier  Updated - Added code to determine mount/open
#                                       status of a version 7 instance
#   1.47 11Aug01 Craig Geier  Added -bi
#   1.48 20Aug01 Craig Geier  Added -mv
#   1.49 30Aug01 Dean Riggio  Updated -lv to support non-standard systems
#                             for the phoenix application.
#   1.50 08Sep01 Bill Border  Added TS and DF counts to -ts and -df
#   1.51 13Sep01 Craig Geier  Added extents to -rb and removed owner
#                             also changed query
#   1.52 08Oct01 Bill Border  Added -er
#   1.53 17Oct01 Bill Border  Improved -ad to display dates
#
#   2.00 24Oct01 Bill Border  MAJOR CHANGE - Added oraSQL subroutine.
#     Since svrmgrl is going away in 9i, if you call this routine to
#     do the build the oraSQLout array, it will decide whether to use
#     svrmgrl and connect internal, or sqlplus internal. Any new functions
#     should use oraSQL instead of connect internal. See orastat -ad for
#     and example of how to call oraSQL.
#   2.01 27Oct01 Bill Border  orastat -pd now dipslays libcache and
#     dict cache hit ratios.
#   2.02 27Oct01 Bill Border  New -sc - sessions sort by cpu time used
#   2.02 01Nov01 Bill Border  New -ex - select from plan_table
#   2.03 01Nov02 Bill Border  New -ma - cat alert log
#   2.04 01Nov02 Bill Border  New -ub - data by schema
#   2.05 01Nov02 Bill Border  New -ut - data by schema and ts
#   2.06 01Nov08 Bill Border  New -ws - v$waitstat
#   2.07 19Nov08 Bill Border  Changed - to use oraSQL
#   2.08 19Nov08 Bill Border  New -al - Archived logs
#   2.09 26Nov08 Bill Border  Converted -df to oraSQL
#   2.10 27Nov08 Bill Border  The default for -df is now NOFSCHECK
#   2.11 27Nov08 Bill Border  Converted -sg and fixed bug in -ts where
#     SYSADM.* tables were not being displayed; converted -ba;
#     converted -l; converted -ta; converted -pd; converted -ar
#     converted -st; converted -sw; converted -in; converted -ra
#     converted -rb; converted -us
#   2.12 28Nov08 Bill Border  Fixed '-' to better handle 8.0 DB's
#     converted -sl
#   2.13 03Dec01 Bill Border  New -lo - table locks; New -ls
#     converted -au; converted -li; converted -lk; converted -rc/-rd
#     converted -rh; converted -rs; converted -rr; converted -iv
#     converted -lf/-rl; converted -cf; converted -so; converted -rp
#     converted -bp; converted -sb; converted -ss; converted -ug
#     converted -bi; converted -de
#   2.14 04Dec01 Bill Border  Converted -dc;
#     converted -ps; converted -tz; converted -ct; converted -tc
#     converted -ve; converted -ud; converted -ro; converted -op
#     converted -vs; converted -vw; converted -tb; converted -ti
#     converted -sn; converted -sr - DONE!!!
#   2.15 07Dec01 Bill Border  Added -br
#   2.16 11Dec01 Bill Border  Added -ck
#   2.17 19Dec01 Craig Geier  Added -v
#   2.18 20Dec01 Bill Border  Added status column to -se
#   2.19 20Dec01 Bill Border  Added -sp StatsPack data
#   2.20 08Jan02 Bill Border  Added -pf Freelist Waits
#   2.21 09Jan02 Bill Border  Renamed -ti to -an
#   2.22 10Jan02 Bill Border  Added -az, -ph and -lh
#   2.23 10Jan02 Bill Border  Added -az, -ph and -lh
#   2.24 24Jan02 Bill Border  Added -count optional parameter to -ti
#   2.25 28Jan02 Bill Border  Added status column to -in
#   2.26 29Jan02 Bill Border  Added columns to -az
#   2.27 30Jan02 Craig Geier  Added script_tbls
#                             Added script_tbs
#                             Added script_views
#   2.28 30Jan02 Bill Border  Added -qs
#   2.20 28Feb02 Bill Border  Added -wr and enhanced -az
#   2.29 07Mar02 Craig Geier  Added -civ
#   2.30 01Apr02 Bill Border  Added -bc
#   2.31 10Apr02 Bill Border  Added -ob
#   2.32 22Apr02 Bill Border  Added -af
#   2.33 01May02 Bill Border  Added -nl
#   2.34 01Jul02 Bill Border  Added -la
#   2.35 01Jul02 Bill Border  Changed -az to include latch wait details
#   2.36 03Jul02 Bill Border  Added -mf
#   2.37 03Jul02 Bill Border  Added -ht
#   2.38 18Jul02 Bill Border  Added -ap and made enhancements to -az
#   2.39 30Jul02 Bill Border  Added -po and enhanced -pd and -az
#   2.40 29Aug02 Bill Border  Changed -l to not use archv02, if it exists
#   2.41 24Sep02 Bill Border  Added -tm and -tr
#   2.42 24Sep02 Bill Border  Added -bm
#   2.43 18Nov02 Bill Border  Added -ln
#   2.44 20Dec02 Bill Border  Added -un & -bs
#   2.45 17Jan03 Bill Border  Added -sh
#   2.46 29Jan03 Bill Border  Enhancement to -tz (buffer pool stats)
#   2.47 30Jan03 Bill Border  Added -tp
#   2.48 08Feb03 Bill Border  Added -dh . Changed name of -civ to -cv
#   2.49 18Feb03 Dean Riggio  Added -pc to check for insecure passwords
#   2.50 26Feb03 Bill Border  Changed -pd to recognize invalid stats data
#   2.51 06Mar03 Bill Border  Changed -pd to display 9i cache stats
#   2.52 28Mar03 Bill Border  Improved -tr
#   2.53 10Apr03 Bill Border  Added -hd
#   2.54 16Apr03 Bill Border  Added -du
#   2.55 21Apr03 Bill Border  Added -pk
#   2.56 30Apr03 Bill Border  Added -sy
#   2.57 06Jun03 Bill Border  Changed -td ... It now counts rows in tables.
#   2.58 11Jun03 Bill Border  New -tj
#   2.59 11Jun03 Bill Border  Fix an arithmetic problem with -sg
#   2.60 12Aug03 Bill Border  Added -nf
#   2.61 02Sep03 Bill Border  Added -tq
#   2.62 19Sep03 Bill Border  Added -cb Controlfile Backup.
#   2.63 23Sep03 Bill Border  Added LEARN mode.
#   2.64 26Sep03 Bill Border  Solved a problem where -cb didn't work in 8.0 or 7.3
#   2.65 01Oct03 Bill Border  Changed -se to now display running jobs also
#   2.66 15Oct03 Bill Border  Added -ft
#   2.67 28Oct03 Bill Border  Enhanced -tq for work better with 9i
#   2.68 26Nov03 Bill Border  Enhanced -ta to add ALL parameter
#   2.69 10Feb04 Ralf Kannenberg added -df2 to sort by filesize desc
#   2.70 16Mar04 Bill Border  Added support for 10g (first phase of changes)
#   2.71 04May04 Bill Border  Added commented code to -sw
#   2.72 03Jun04 Bill Border  Added -rf
#   2.73 11Jun04 Bill Border  Changed -cb - Coded for oracle bug for trace bkup
#   2.74 11Jun04 Bill Border  Changed -al - Fix so that only ARCH created logs are displayed.
#   2.75 23Jun04 Bill Border  Added -su
#   2.76 25Jun04 Bill Border  Added -dn
#   2.77 29Jun04 Ralf Kannenberg Added -af9i
#   2.78 29Jul04 Bill Border  Fixed -af so that it works with 9i+. af91 is not
#     needed, but I will leave it until all calling programs are changed.
#   2.79 29Jul04 Scott Patton - Fixed orastat -cb to work on 9.0.1 databases
#   2.80 02Aug04 Bill Border  Fixed a bug in -af
#   2.81 02Sep04 Bill Border  Added logic to -cb for 10g
#   2.82 17Sep04 Bill Border  Added -rg
#   2.83 30Sep04 Bill Border  HOLY COW! There was a bug in -ts where a TS that is 100% full
#     would indicate 0% full. Fixed some misplaced nvl function calls.
#   2.84 22Oct04 Bill Border  Fixed -pd - db_cache_size was displayed wrong for big numbers
#   2.85 29Oct04 Bill Border  Added -bo (pretty cool)
#   2.86 01Nov04 Bill Border  Fixed -bc so that it works with 9i+
#   2.87 12Nov04 Bill Border  Added a sample of FREE BUFFERS to -az
#   2.88 16Nov04 Bill Border  Added diagnostics to -rh
#   2.89 06Jan05 Bill Border  Fixed -sg to work with >= 9i
#   2.90 13Jan05 Bill Border  Improved -pd to display cache hit ratio excluding RECYCLE pool
#   2.91 04Feb05 Bill Border  Added -mt
#   2.92 28Feb05 Bill Border  Fix to - for AIX
#   2.93 07Mar05 Bill Border  Added -cm
#   2.94 15Mar05 Bill Border  Change to -cb: if /var/opt/oracle/tmp exists, write bin cf there
#   2.95 22Mar05 Bill Border  Fixed -ln to be able to deal with null OWNER (Thanks Bob Simcock)
#   2.96 29Mar05 Ralf Kannenberg Fixed - -av to work with archv02 as well
#   2.97 06Apr05 Bill Border  Another fix to -ln
#   2.98 11Apr05 Bill Border  Enhanced -pi & -pj: They now read tempfile and tempstat
#   2.99 23Apr05 Bill Border  New -pa to analyze I/O load by tablespace
#   3.00 14Jul05 Ralf Kannenberg Fixed AGAIN(!!)- -av to work with archv02 as well
#   3.01 14Jul05 Bill Border  BREAKFIX -av - Rewrote to automatically figure out what the
#     correct destination name is. This should fix the problem where we were query multiple
#     destinations. New run_av function replaced old -av routine. -av has been rename to -avo.
#   3.02 18Jul05 Bill Border  New -lg Long Operation Progress
#   3.03 28Jul05 Bill Border  Enhancement to -lg; Added where time_remaining > 0
#     Thanks to Henrik Lehmann for the good suggestion.
#   3.04 06Aug04 Bill Border  Enhancement to -cb - we now remove all old cfbackups first
#   3.05 18Aug04 Bill Border  Fix to -ad: only replace with arcdirnew if it is non-null
#   3.06 08Sep05 Bill Border  New -fm
#   3.07 09Sep05 Bill Border  New -df3
#   3.08 09Oct05 Bill Border  New -dp
#   3.09 18Oct05 Bill Border  New -mr
#   3.10 20Oct05 Bill Border  Improved "-" ... added force logging...
#   3.11 08Nov05 Bill Border  Improved -us: added account status and improved format of create date
#   3.12 20Oct05 Bill Border  Improved "-" no more invalid column for 8.1
#   3.13 28Nov05 Bill Border  Rewrote -tt - It is now ACCURATE (it used v$sort_usage)
#   3.14 12Dec05 Bill Border  Improved -az added sga full measures
#   3.15 30Dec05 Bill Border  Added resetlogs_id to "-"
#   3.16 09Jan06 Bill Border  Improved -tz - The largest table and index are not displayed
#   3.17 20Jan06 Bill Border  Improved -lv
#   3.18 18Feb06 Bill Border  New -cc
#   3.19 10Mar06 Bill Border  Improved -az - added free memory collection
#   3.20 31Mar06 Bill Border  Fix to -se... It now reports sessions with a null osuser
#   3.21 19Jun06 Bill Border  New -sz
#   3.22 20Jun06 Bill Border  Added 'print if ORA' logic to -bm
#   3.23 27Jun06 Bill Border  Fix to -bm - retry if ORA-00235
#   3.24 13Jul06 Bill Border  Fix to -az for Linux
#   3.25 21Oct06 Bill Border  Fix to -cb - initial rm needed -f parm
#   3.26 22Dec06 Bill Border  Improved -av - New MAX total line
#   3.27 03Feb07 Bill Border  Added -pr
#   3.28 29Mar07 Larry Rush   Changed method for determining Oracle version due to strange problem on eprdhe1
#   3.29 03May07 Bill Border  New -fba and changes to -
#   3.30 11May07 Bill Border  Changed -cb to not remove all /tmp/*cb* files
#   3.31 27Jul07 Bill Border  Changed -rh - for 9i+ is now sets  workareasizepolicy to manual
#   3.32 09Aug07 Bill Border  New -amm and changes to -sg
#   3.33 09Aug07 Bill Border  Change to "-" for asm instance
#   3.34 09Aug07 Bill Border  New -asm
#   3.35 12Aug07 Bill Border  New -di
#   3.36 15Aug07 Bill Border  Some ASM changes to -tf
#   3.37 24Sep07 Bill Border  New -spf and new -rac alias for -ps
#   3.38 25Sep07 Bill Border  Added "alter session set optimizer_mode=rule;" to -dn
#   3.39 01Oct07 Bill Border  New -asm_op
#   3.40 14nov07 Bill Border  New -brm
#   3.41 17Apr08 LR           Fix to -az for multi-line default pool output (hitr_tot)
#   3.42 28May08 BB           DTV changes and improved -su
#   3.43 12Aug08 BB           New -dgl
#   3.44 02Apr09 BB           New -df5 (datafiles, but works on a MOUNTED DB)
#   3.45 20Apr09 BB           New -ser
#   3.46 26Jun09 BB           New -uns
#   3.50 05Apr10 BB           MAJOR - New "connect file" logic.
#   3.51 16Apr10 BB           New -unl, -emth, -emac, and -emah
#   3.52 30Aug10 BB           New -cdb
#   3.53 01Sep10 BB           New -pul
#======================================================================
$version = "3.53";

use Time::Local;
#------------------------------------------------------------------------------
#
# Subroutines
#
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
sub error
#------------------------------------------------------------------------------
{
  $emsg = $_[0];
  &msg("ERROR: $emsg");
  exit 1;

  $ENV{'ORACLE_SID'} = "$instance";
  $str1="${backup_type}: ($errnum) - $msg (${webserver}/oberr.html#${errnum})";
  $str2="DB: $instance";
  $str3="Backup Level: $backup_type";
  $str4="For more information see: ${webserver}/processes/oracle/ora_backup_errors.html#$errnum";
  &msg("Sending BLT ticket $str1 $str2 $str3 $str4");
  $progstring = "${P}[${errnum}]";
  $ENV{'BLT_SUBJECT'} = "${host}-${instance}|${backup_type} [$errnum] - $msg";

  system("$toolsdir/db_create_ticket $progstring \"$str1\" \"$str2\" \"$str3\" \"$str4\"");

  if ($errnum == -86 ||
      $errnum == -88 ||
      $errnum == -90 ||
      $errnum == -91)
  {
    #&blt_dcit;   comment this for now - the tickets aren't working anyway bb 09aug01
  }

  &msg("=============================================================");
  &msg("Fatal Error: $msg");
  &msg("=============================================================");
  &msg("Exiting rc=1");
  exit 1;
}

#------------------------------------------------------------------------------
sub oraSQL
#------------------------------------------------------------------------------
{
  $sql = $_[0];

  if ($ENV{'LEARN'} ne "")
  {
    print "\n#===========================================================#\n";
    &msg("LEARN Mode: SQL Being Executed: \n $sql");
    $sqlcnt++;
    system("echo '$date | LEARN Mode - Command: \"$P $arg\" - SQL #$sqlcnt Being Executed: \n $sql \n' >> /tmp/orastat_learn.txt");
    print "#===========================================================#\n";
  }

  if ($sqlcmd eq "sp")
  {
    $os_scmd = "sqlplus /NOLOG";
    $os_conn = "connect / as sysdba ";
    $os_set1 = "set linesize 9999";
    $os_set2 = "set numwidth 20";
    $os_set3 = "set long 2000000000";
    $os_set4 = "set pagesize 50000";
    $os_end  = "exit";
  }
  else
  {
    $os_scmd = "svrmgrl";
    $os_conn = "connect internal ";
    $os_set1 = "set numwidth 20";
    $os_set2 = "set echo on";
    $os_end  = "exit";
  }

  #---- Possible override
  $os_conn = $cf_connect_string if $cf_connect_string;

  ##&msg("os_scmd=$os_scmd os_conn=$os_conn");

  @oraSQLout = `$os_scmd <<!
    $os_conn;
    $os_set1
    $os_set2
    $os_set3
    $os_set4
    $sql
    $os_end
  !`;

  #open(RO,"$os_scmd <<!
  #  $os_conn;
  #  $os_set;
  #  $sql
  #  $os_end
  #  ;
  #!|") || die "Cannot run sql=$sql";
}

#------------------------------------------------------------------------------
sub alertLogFind
#------------------------------------------------------------------------------
{
  &msg("alertLogFind - Starting - Looking for alert log in all possible locations");
  #&msg("alertLogFind - Done - $alf_status");
  &msg("alertLogFind - Done");
}

#------------------------------------------------------------------------------
sub alertLogReformat
#------------------------------------------------------------------------------
{
  $alr_file  = $_[0];
  $alr_lines = $_[1];

  open(ALR, "$alr_file") || die "Cannot open input $alr_file - $!";

  $alr_buffer = "";
  $alr_seq = 0;

  %alr_month_hash = (
    "Jan" => "01",
    "Feb" => "02",
    "Mar" => "03",
    "Apr" => "04",
    "May" => "05",
    "Jun" => "06",
    "Jul" => "07",
    "Aug" => "08",
    "Sep" => "09",
    "Oct" => "10",
    "Nov" => "11",
    "Dec" => "12"
  );

  while(<ALR>)
  {
    my @words = split;
    if ($#words == 4 && $words[4] =~ /^2/)
    {
      $dom = $words[2];
      $dom = "0" . $dom if length($dom) < 2;
      $alr_ts = $words[4] . "/" . $alr_month_hash{$words[1]} . "/" . $dom . "-" . $words[3];
      $alr_seq = 0;
      next;
    }

    $alr_seq++;

    if ($alr_seq == 1)
    {
      $alr_line = "$alr_ts [$alr_seq] $_";
    }
    else
    {
      $alr_line = "$alr_ts [$alr_seq] - $_";
    }

    $alr_buffer .= $alr_line;
    push (@alr_array,$alr_line);
  }
  close(ALR);

  if (uc $alr_lines eq "A")
  {
    &msg("Displaying entire alert log ($#alr_array+1 lines)") unless $raw;
    print "\n" unless $raw;
    print $alr_buffer;
    print "\n" unless $raw;
  }
  if (uc $alr_lines eq "V")
  {
    &msg("vi-ing entire alert log ($#alr_array+1 lines)") unless $raw;
    $tmpfl = "/tmp/orastat_alr.txt";
    open(OUTDATA, ">$tmpfl") || die "Cannot open output orastat_alr.txt - $!";
    print OUTDATA $alr_buffer;
    close(OUTDATA);
    system("vi $tmpfl");
  }
  elsif ($alr_lines > 0 && $alr_lines < 99999999)
  {
    &msg("Displaying the last $alr_lines lines of alert log") unless $raw;
    print "\n" unless $raw;
    for ($i = ($#alr_array - $alr_lines); $i <= $#alr_array; $i++)
    {
      ##print "i=$i cnt=$#alr_array\n";
      print $alr_array[$i];
    }
    print "\n" unless $raw;
  }
}

#------------------------------------------------------------------------------
sub msg
#------------------------------------------------------------------------------
{
  $msgmsg = $_[0];
  chop($date = `date +%Y/%m/%d-%H:%M:%S`);
  print "$date ${P} | $msgmsg\n";
}

# ----------------------------------------------------------------------
sub formatNum
# ----------------------------------------------------------------------
{
  my $num_in = $_[0];

  $c_k   = 1024;
  $c_meg = 1024**2;
  $c_gig = 1024**3;

  if    ($num_in >= $c_gig) { $num_out = sprintf("%.1f",$num_in / $c_gig) . 'gb'; }
  elsif ($num_in >= $c_meg) { $num_out = sprintf("%.1f",$num_in / $c_meg) . 'mb'; }
  elsif ($num_in >= $c_k)   { $num_out = sprintf("%.1f",$num_in / $c_k)   . 'kb';  }
  else  { $num_out = $num_in; }

  return $num_out;
}

# ----------------------------------------------------------------------
sub checkDST
# ----------------------------------------------------------------------
{
  &msg("checkDST - DST2007 Logic");

  $dst_JVM = 0;
  $dst_col_sys = 0;
  $dst_col_nonsys = 0;

  #---- See if there are any tablespaces with NO datafiles
  $sql = "
    select
      'XA', owner, status, count(*) from all_objects
    where
      object_type like '%JAVA%' and
      owner in ('SYS','WMSYS')
    group by
      owner, status
    having
      count(*) > 9000;
    select
      'XB', c.owner, count(*)
    from
      dba_tab_cols c, dba_objects o
    where
      c.data_type like '%WITH TIME ZONE'
                  and c.owner=o.owner
                  and c.table_name = o.object_name
                  and o.object_type = 'TABLE'
    group by
      'XB', c.owner
    order by
      owner;
  ";
  &oraSQL($sql);
  foreach (@oraSQLout)
  {
    ##print;
    @words       = split();
    $verb        = $words[0];
    if ($verb eq "XA")
    {
      $dst_JVM = 1;
      $dst_jvm_installed = 1;
      &msg("  Schema SYS/WMSYS owns $words[3] JAVA objects - JVM is installed");
    }
    if ($verb eq "XB")
    {
      &msg("  Schema $words[1] owns $words[2] Tables with TIME ZONE columns");
      if ($words[1] eq 'SYS' || $words[1] eq 'WMSYS')
      {
        $dst_col_sys = 1;
      }
      else
      {
        $dst_col_nonsys = 1;
      }
    }
  }

  ##print "$P DST2007_JVM:           $dst_JVM\n";
  ##print "$P DST2007_TZ_COL_SYS:    $dst_col_sys\n";
  ##print "$P DST2007_TZ_COL_NONSYS: $dst_col_nonsys\n";

  if ($dst_col_sys)
  {
    &msg("This DB does have DST columns (SYS schemas)");
  }
  else
  {
    &msg("This DB does NOT have DST columns (SYS schemas)");
  }
  if ($dst_col_nonsys)
  {
    &msg("This DB does have DST columns (non-SYS schemas)");
  }
  else
  {
    &msg("This DB does NOT have DST columns (non-SYS schemas)");
  }
}

# --------------------------------------------------------------------
sub run_emth
# --------------------------------------------------------------------
{
  &msg("-emth: (EM) Alert Thresholds");

  $sql = "
    column object_name format a30
    column object_type format a20
    column metrics_name format a40
    column w_oper format a28
    column c_oper format a28
    column w_value format a28
    column c_value format a28

    select
      'Flag_X:',
      translate(metrics_name,' ','_'),
      nvl(object_type,'?'),
      nvl(object_name,'?'),
      translate(nvl(warning_operator, '?'),' ','_') as w_oper,
      translate(nvl(warning_value, '?'),' ','_') as w_value,
      translate(nvl(critical_operator, '?'),' ','_') as c_oper,
      translate(nvl(critical_value, '?'),' ','_') as c_value,
      status
    from
    dba_thresholds
    order by 2,3,4;
  ";
  &oraSQL($sql);

  print "\n";
  print "Metric Name                               Object Type       Object Name          MetricStatus Warning / Critical Thresholds\n";
  print "---------------------------------------- ------------------ -------------------- ------------ ----------------------------------------\n";

  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words   = split();

    $verb    = shift(@words);

    if ($verb eq "Flag_X:")
    {
      ##print;
      $metric      = shift(@words);
      $obj_type    = shift(@words);
      $obj_name    = shift(@words);
      $w_oper      = shift(@words);
      $w_val       = shift(@words);
      $c_oper      = shift(@words);
      $c_val       = shift(@words);
      $status      = shift(@words);

      $t_all = "Warning=$w_oper/$w_val Critical=$c_oper/$c_val";

      $thisline = sprintf("%-40s %-18s %-20s %-12s %-40s\n",
        $metric,$obj_type,$obj_name,$status,$t_all);
      print $thisline;
      $cnt++;
    }
  }
  print "\n";
  &msg("Total Metrics: $cnt");
}

# --------------------------------------------------------------------
sub run_cdb
# --------------------------------------------------------------------
{
  &msg("-cdb: List all running DBs on all nodes in this SG cluster");

  foreach (`cmviewcl -f line | grep ^node | grep id= | sort`)
  {
    ##print;
    $string = $_;
    $s1 = (split(/\:/,$string)) [1];
    $cdb_node = (split(/\|/,$s1)) [0];
    &msg("DBs Running on node: $cdb_node");
    system("ssh $cdb_node 'ps -ef | grep -v 'grep' | grep 'pmon_'");
  }
}

# --------------------------------------------------------------------
sub run_emac
# --------------------------------------------------------------------
{
  &msg("-emac: (EM) Alerts - Currently Outstanding DB Alerts");

  $sql = "
    column reason format a80
    column ts format a19

    select
      'Flag_X:',
      sequence_id,
      to_char(creation_time,'YYYY/MM/DD-HH24:MI:SS') ts,
      message_type,
      translate(metric_value,' ','#'),
      translate(object_type,' ','#'),
      translate(message_group,' ','#'),
      translate(reason,' ','#')
    from
      dba_outstanding_alerts
    order by
      2;
  ";
  &oraSQL($sql);

  print "\n";
  print "Seq#   Timestamp           Severity   Metric Value             Alert Reason\n";
  print "------ ------------------- ---------- ------------------------ --------------------------------------------------------------------------------\n";

  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words   = split();

    $verb    = shift(@words);

    if ($verb eq "Flag_X:")
    {
      ##print;
      $seq     = shift(@words);
      $ts      = shift(@words);
      $type    = shift(@words);
      $val     = shift(@words);
      $obj_type= shift(@words);
      $msg_grp = shift(@words);
      $reason  = shift(@words);

      $reason_out = "$obj_type $msg_grp - $reason";
      $reason_out =~ s/\#/ /g;

      $thisline = sprintf("%6s %-19s %-10s %-24s %-80s\n",
        $seq,$ts,$type,$val,$reason_out);
      print $thisline;
      $cnt++;
    }
  }
  print "\n";
  &msg("Total Outstanding Alerts: $cnt");
}

# --------------------------------------------------------------------
sub run_emah
# --------------------------------------------------------------------
{
  &msg("-emah: (EM) Alerts - Historical DB Alerts");

  $sql = "
    column reason format a80
    column ts format a19

    select
      'Flag_X:',
      sequence_id,
      to_char(creation_time,'YYYY/MM/DD-HH24:MI:SS') ts,
      message_type,
      translate(metric_value,' ','#'),
      translate(object_type,' ','#'),
      translate(message_group,' ','#'),
      translate(reason,' ','#')
    from
      dba_outstanding_alerts
    order by
      2;
  ";
  &oraSQL($sql);

  print "\n";
  print "Seq#   Timestamp           Severity   Metric Value             Alert Reason\n";
  print "------ ------------------- ---------- ------------------------ --------------------------------------------------------------------------------\n";

  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words   = split();

    $verb    = shift(@words);

    if ($verb eq "Flag_X:")
    {
      ##print;
      $seq     = shift(@words);
      $ts      = shift(@words);
      $type    = shift(@words);
      $val     = shift(@words);
      $obj_type= shift(@words);
      $msg_grp = shift(@words);
      $reason  = shift(@words);

      $reason_out = "$obj_type $msg_grp - $reason";
      $reason_out =~ s/\#/ /g;

      $thisline = sprintf("%6s %-19s %-10s %-24s %-80s\n",
        $seq,$ts,$type,$val,$reason_out);
      print $thisline;
      $cnt++;
    }
  }
  print "\n";
  &msg("Total Outstanding Alerts: $cnt");
}

# --------------------------------------------------------------------
sub run_pul
# --------------------------------------------------------------------
{
  $linelimit = 30;
  &msg("-pul: Purge - Display last $linelimit lines of DTVPURGE.P_JOB_LOGGING ");

  $sql = "
    column reason format a80
    column ts format a19

    select
      'Flag_X:',
      job_num,
      to_char(job_start,\'YYYY/MM/DD-HH24:MI:SS\'),
      to_char(job_end,\'YYYY/MM/DD-HH24:MI:SS\'),
      nvl( p_job_type , '?'),
      nvl( p_job_table , '?'),
      translate(p_job_criteria,\' \',\'!\'),
      nvl( p_job_batch , -1),
      nvl( p_job_commit , -1),
      nvl( p_job_threads , -1),
      translate(desc_text,\' \',\'!\')
    from
      dtvpurge.p_job_logging
    --where job_start > sysdate - 1/24
    order by job_start;
  ";
  &oraSQL($sql);

  print "\n";
  print "JOB_NUM JOB_START           JOB_END             JOB_TYPE JOB_TABLE       JOB_CRITERIA         JOB_BATCH/COMMIT/THREADS DESC_TEXT\n";
  print "------- ------------------- ------------------- -------- --------------- -------------------- ------------------------ -----------------------------\n";

  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words   = split();

    $verb    = shift(@words);

    if ($verb eq "Flag_X:")
    {
      ##print;
      $job_num     = shift(@words);
      $job_start     = shift(@words);
      $job_end     = shift(@words);
      $job_type     = shift(@words);
      $job_table     = shift(@words);
      $job_crit     = shift(@words);
      $job_batch     = shift(@words);
      $job_commit     = shift(@words);
      $job_threads     = shift(@words);
      $desc_text      = shift(@words);

      $desc_text =~ s/\!/ /g;
      $job_crit  =~ s/\!/ /g;

      $job_bct = "$job_batch / $job_commit / $job_threads";

      $thisline = sprintf("%7s %-19s %-19s %-8s %-15s %-20s %-24s %-40s\n",
        $job_num,$job_start,$job_end,$job_type,$job_table, $job_crit, $job_bct, $desc_text);
      push (@all_lines, $thisline);

    }
  }

  $num_lines = $#all_lines;
  $start_line = $num_lines - $linelimit + 2;

  foreach $this_line (@all_lines)
  {
    $cnt++;
    print $this_line if $cnt >= $start_line;
  }

  print "\n";
}

# --------------------------------------------------------------------
sub run_sed
# --------------------------------------------------------------------
{
  &msg("-sed: Session Details");

  &msg("Only lines matching (caseless) '$arg2' will be displayed") if $arg2;
  print "\n";

  $matchcnt = 0;
  $sesscnt = 0;

  print "Session      Ses    Ses      Wait    Wait       DB     OS                              Session             Last      Last                 +---Commit----+ Program\n";
  print "SID-Ser#     Type   Status   Class / Seq        Userid-Userid-PID-SPID-Term\@Server     Start Time          Call ET   SQL    SQL_ID        Count    /Sec   Identifier\n";
  print "------------ ------ -------- ------------------ -------------------------------------- ------------------- --------- ------ ------------- -------- ------ ------------------------\n";

  $sqlstmt = '
    select distinct \'Y\',
      sid
    from
      v\$mystat;
    select distinct \'X\',
      s.sid,
      s.serial#,
      nvl(p.spid,-1),
      s.type,
      translate(nvl(s.osuser,\'?\'),\' \',\'-\'),
      to_char(logon_time,\'YYYY/MM/DD-HH24:MI:SS\') logon_time,
      nvl(s.status,\'?\'),
      nvl(s.process,\'?\'),
      nvl(s.machine,\'?\'),
      nvl(s.username,\'?\'),
      substr(translate(nvl(sql.sql_text,\'?\'),\' \',\'_\'),1,20),
      translate(nvl(s.program,\'?\'),\' \',\'_\'),
      translate(nvl(p.program,\'\_\'),\' \',\'_\'),
      s.last_call_et,
      s.seq#,
      translate(s.wait_class,\' \',\'_\'),
      s.command,
      nvl(s.terminal,\'?\'),
      nvl(sta1.value,-1) commits,
      s.sql_id
    from
      v\$session s,
      v\$process p,
      v\$sql sql,
      (select
	vss.sid,
	vss.value
      from
	v\$sesstat vss,
	v\$statname vsn
      where
       vss.statistic#=vsn.statistic#
       and vsn.name = \'user commits\') sta1
    where
      p.addr = s.paddr
      and sql.address(+) = s.sql_address
      and sta1.sid(+) = s.sid
    order by
      2;
    ----
  ';

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words   = split();

    $verb    = $words[0];

    if ($verb eq "Y")
    {
      $mysid = $words[1];
    }

    if ($verb eq "X")
    {
      ##print;
      $sid     = $words[1];
      $ser     = $words[2];
      $shadow  = $words[3];
      $type    = $words[4];
      $user    = $words[5];
      $logtime = $words[6];
      $status  = $words[7];
      $process = $words[8];
      $machine = $words[9];
      $dbuser  = $words[10];
      $sqltext = uc $words[11];
      $s_prog  = $words[12];
      $p_prog  = $words[13];
      $lastet  = $words[14];
      $waitct  = $words[15];
      $waitcls = $words[16];
      #$command = $words[17];
      $terminal= $words[18];
      $commits = $words[19];
      $sqlid   = $words[20];

      if ($s_prog eq $p_prog) { $progstring = $s_prog; }
      else { $progstring = "$s_prog $p_prog"; }
      $s_prog = substr($s_prog,0,24) if length($s_prog) > 24;

      $comb = "$dbuser-$user-$process-${shadow}-$terminal\@$machine";
      $comb = substr($comb,0,38) if length($comb) > 38;

      $sidser = "$sid,$ser";

      $sesscnt++;
      $sescount{$status}++ if $type =~ /USER/;

      $type = "BG" if $type eq "BACKGROUND";

      $waitboth = "$waitcls/$waitct";

      ($sqlout = $sqltext) =~ s/\_/ /g;
      $sqlout =~ s/^\s+//;
      $sqlout = substr($sqlout,0,6);

      if ($user eq "") { $user = "."; }
      if ($sid == $mysid) { $type = "USER*"; }
      if ($sid == $mysid && $arg2) { next; }

      if ($lastet + 0 == $lastet)
      {
        if    ($lastet < 60)    { $lastet_out = $lastet . "_Sec"; }
        elsif ($lastet < 3600)  { $lastet_out = sprintf("%.1f",$lastet / 60)    . "_Min"; }
        elsif ($lastet < 86400) { $lastet_out = sprintf("%.1f",$lastet / 3600)  . "_Hrs"; }
        else                    { $lastet_out = sprintf("%.1f",$lastet / 86400) . "_Day"; }
      }

      $commitrt = "?";
      if ($lastet > 0 && $commits > 0)
      {
        $commitrt = int($commits / $lastet);
      }

      $thisline = sprintf("%-12s %-6s %-8s %-18s %-38s %-19s %9s %-6s %13s %8s %6s %-24s\n",
        $sidser,$type,$status,$waitboth,$comb,$logtime,$lastet_out,$sqlout,$sqlid,$commits,$commitrt,$s_prog);
      if ($arg2)
      {
        if ($arg2 ne "" && $thisline =~ /$arg2/i)
        {
          print $thisline;
          $matchcnt++;
          $commits_total += $commits;
          $commitrt_total += $commitrt;
          $lastet_total += $lastet;
        }
      }
      else
      {
        print $thisline;
      }
    }
  }
  print "\n";
  @sorted = sort keys %sescount;
  foreach (@sorted)
  {
    &msg("Count of USER session(s) in $_ status: $sescount{$_}");
  }
  &msg("There are $sesscnt total sessions (mysid=$mysid - denoted by *)");
  &msg("Sessions matching match string: $matchcnt") if $arg2;

  if ($commits_total > 0)
  {
    $rows_per_commit = 1;

    $z1 = int($commits_total / $lastet_total);
    $z2 = $commitrt_total;
    &msg("Matching Sessions - Total Commits=$commits_total AverageCommitRate=$z1 TotalCommitRate=$z2");
    $rows = ($commits_total * $rows_per_commit);
    $rate = ($z2 * $rows_per_commit * 3600);
    &msg("PURGE - RowsProcessed=$rows RowsPerHour=$rate ($rows_per_commit rows/commit)");
  }
}


# --------------------------------------------------------------------
sub run_ser
# --------------------------------------------------------------------
{
  &msg("-ser: Session Details");

  &msg("Only lines matching (caseless) '$arg2' will be displayed") if $arg2;
  print "\n";

  $matchcnt = 0;
  $sesscnt = 0;

  print "Session      Ses    Ses      Wait    Wait       DB     OS                              Session             Last      Last                 +-UserCommits-+ Rollback Program\n";
  print "SID-Ser#     Type   Status   Class / Seq        Userid-Userid-PID-SPID-Term\@Server     Start Time          Call ET   SQL    SQL_ID           Count   /Sec    Count Identifier\n";
  print "------------ ------ -------- ------------------ -------------------------------------- ------------------- --------- ------ ------------- -------- ------ -------- ------------------------\n";

  $sqlstmt = '
    select distinct \'Y\',
      sid
    from
      v\$mystat;
    select distinct \'X\',
      s.sid,
      s.serial#,
      nvl(p.spid,-1),
      s.type,
      translate(nvl(s.osuser,\'?\'),\' \',\'-\'),
      to_char(logon_time,\'YYYY/MM/DD-HH24:MI:SS\') logon_time,
      nvl(s.status,\'?\'),
      nvl(s.process,\'?\'),
      nvl(s.machine,\'?\'),
      nvl(s.username,\'?\'),
      substr(translate(nvl(sql.sql_text,\'?\'),\' \',\'_\'),1,20),
      translate(nvl(s.program,\'?\'),\' \',\'_\'),
      translate(nvl(p.program,\'\_\'),\' \',\'_\'),
      s.last_call_et,
      s.seq#,
      translate(s.wait_class,\' \',\'_\'),
      s.command,
      nvl(s.terminal,\'?\'),
      nvl(sta1.value,-1) commits,
      s.sql_id,
      nvl(sta2.value,-1) rollbacks
    from
      v\$session s,
      v\$process p,
      v\$sql sql,
      (select
	vss.sid,
	vss.value
      from
	v\$sesstat vss,
	v\$statname vsn
      where
       vss.statistic#=vsn.statistic#
       and vsn.name = \'user commits\') sta1,
      (select
	vss.sid,
	vss.value
      from
	v\$sesstat vss,
	v\$statname vsn
      where
       vss.statistic#=vsn.statistic#
       and vsn.name = \'transaction rollbacks\') sta2
    where
      p.addr = s.paddr
      and sql.address(+) = s.sql_address
      and sta1.sid(+) = s.sid
      and sta2.sid(+) = s.sid
    order by
      2;
    ----
  ';

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words   = split();

    $verb    = $words[0];

    if ($verb eq "Y")
    {
      $mysid = $words[1];
    }

    if ($verb eq "X")
    {
      ##print;
      $sid     = $words[1];
      $ser     = $words[2];
      $shadow  = $words[3];
      $type    = $words[4];
      $user    = $words[5];
      $logtime = $words[6];
      $status  = $words[7];
      $process = $words[8];
      $machine = $words[9];
      $dbuser  = $words[10];
      $sqltext = uc $words[11];
      $s_prog  = $words[12];
      $p_prog  = $words[13];
      $lastet  = $words[14];
      $waitct  = $words[15];
      $waitcls = $words[16];
      #$command = $words[17];
      $terminal= $words[18];
      $commits = $words[19];
      $sqlid   = $words[20];
      $rollbacks = $words[21];

      if ($s_prog eq $p_prog) { $progstring = $s_prog; }
      else { $progstring = "$s_prog $p_prog"; }
      $s_prog = substr($s_prog,0,24) if length($s_prog) > 24;

      $comb = "$dbuser-$user-$process-${shadow}-$terminal\@$machine";
      $comb = substr($comb,0,38) if length($comb) > 38;

      $sidser = "$sid,$ser";

      $sesscnt++;
      $sescount{$status}++ if $type =~ /USER/;

      $type = "BG" if $type eq "BACKGROUND";

      $waitboth = "$waitcls/$waitct";

      ($sqlout = $sqltext) =~ s/\_/ /g;
      $sqlout =~ s/^\s+//;
      $sqlout = substr($sqlout,0,6);

      if ($user eq "") { $user = "."; }
      if ($sid == $mysid) { $type = "USER*"; }
      if ($sid == $mysid && $arg2) { next; }

      if ($lastet + 0 == $lastet)
      {
        if    ($lastet < 60)    { $lastet_out = $lastet . "_Sec"; }
        elsif ($lastet < 3600)  { $lastet_out = sprintf("%.1f",$lastet / 60)    . "_Min"; }
        elsif ($lastet < 86400) { $lastet_out = sprintf("%.1f",$lastet / 3600)  . "_Hrs"; }
        else                    { $lastet_out = sprintf("%.1f",$lastet / 86400) . "_Day"; }
      }

      $commitrt = "?";
      if ($lastet > 0 && $commits > 0)
      {
        $commitrt = int($commits / $lastet);
      }
      $rollbacks = 0 if $rollbacks eq "";

      $thisline = sprintf("%-12s %-6s %-8s %-18s %-38s %-19s %9s %-6s %13s %8s %6s %8s %-24s\n",
        $sidser,$type,$status,$waitboth,$comb,$logtime,$lastet_out,$sqlout,$sqlid,$commits,$commitrt,$rollbacks,$s_prog);
      if ($arg2)
      {
        if ($arg2 ne "" && $thisline =~ /$arg2/i)
        {
          print $thisline;
          $matchcnt++;
          $commits_total += $commits;
          $commitrt_total += $commitrt;
          $lastet_total += $lastet;
        }
      }
      else
      {
        print $thisline;
      }
    }
  }
  print "\n";
  @sorted = sort keys %sescount;
  foreach (@sorted)
  {
    &msg("Count of USER session(s) in $_ status: $sescount{$_}");
  }
  &msg("There are $sesscnt total sessions (mysid=$mysid - denoted by *)");
  &msg("Sessions matching match string: $matchcnt") if $arg2;

  if ($commits_total > 0)
  {
    $rows_per_commit = 1;

    $z1 = int($commits_total / $lastet_total);
    $z2 = $commitrt_total;
    &msg("Matching Sessions - Total Commits=$commits_total AverageCommitRate=$z1 TotalCommitRate=$z2");
    $rows = ($commits_total * $rows_per_commit);
    $rate = ($z2 * $rows_per_commit * 3600);
    &msg("PURGE - RowsProcessed=$rows RowsPerHour=$rate ($rows_per_commit rows/commit)");
  }
}


#------------------------------------------------------------------------------
sub run_dst
#------------------------------------------------------------------------------
{
  &msg("-dst: Check for 2007 DST Patch");

  &checkDST;

  &msg("Test #1: Is DST patch for TZ columns applied:");
  $sql = "
    select case to_number(to_char(to_timestamp_tz
                ('20070311 00:00:00 US/EASTERN','YYYYMMDD HH24:MI:SS TZR')
                + to_dsinterval('0 08:00:00'),'HH24'))
                when 8 then 'DST Patch has not been applied to this ORACLE_HOME'
                when 9 then 'DST Patch has been applied correctly to this ORACLE_HOME'
                else 'Error' end \"TZTEST (RUN FROM DB HOME)\"
           from dual;
  ";
  &oraSQL($sql);

  $dst_col_patch_applied = 0;

  foreach (@oraSQLout)
  {
    print if /DST/;
    $dst_col_patch_applied = 1 if /DST Patch has been applied/;
  }
  ##&msg("dst_col_patch_applied=$dst_col_patch_applied");

  #---- Is JAVA VM installed
  if ($dst_JVM == 0)
  {
    &msg("Querying whether JVM is installed in this DB");
    $sql = " select comp_name from dba_registry where comp_name like '%JAVA Virtual Machine%' and status != 'REMOVED';";
    &oraSQL($sql);

    $dst_jvm_installed = 0;
    $dst_jvm_not_installed = 1;

    foreach (@oraSQLout)
    {
      next if /select/;
      if (/JAVA Virtual Machine/)
      {
        print;
        $dst_jvm_installed = 1;
        $dst_jvm_not_installed = 0;
      }
    }
    &msg("dst_jvm_installed=$dst_jvm_installed");
  }

  #---- Test JVM (If it is installed)
  if ($dst_jvm_installed)
  {
    &msg("Test #2: Is DST patch for JVM applied:");
    $sql = "
      create or replace java source named \"DBAmonOffsetFromStandard\" as
      import java.util.Calendar;
      import java.util.GregorianCalendar;
      import java.util.TimeZone;

      public class DBAmonOffsetFromStandard
      {
        public static int getDSTDBAmonOffset(
          String timezone,
          int year,
          int month,
          int mday,
          int hour,
          int min,
          int sec)
        {
          int RetVal = -360000000;
          String[] TZs = TimeZone.getAvailableIDs();
          for (int i = 0; i < TZs.length; i++)
          {
            if (timezone.equals(TZs[i]))
            {
              TimeZone tz = TimeZone.getTimeZone(timezone);
              GregorianCalendar c = new GregorianCalendar(tz);
              c.set(year, month-1, mday, hour, min, sec);
              RetVal = c.get(Calendar.DST_OFFSET);
            };
          }
          return RetVal;
        }
      }
/
      alter java class \"DBAmonOffsetFromStandard\" resolve
/
      CREATE OR REPLACE function get_dst_offset (timezone VARCHAR2,
                                                     year NUMBER,
                                                    month NUMBER,
                                                     mday NUMBER,
                                                     hour NUMBER,
                                                      min NUMBER,
                                                      sec NUMBER) RETURN NUMBER AS
      LANGUAGE JAVA NAME 'DBAmonOffsetFromStandard.getDSTDBAmonOffset (java.lang.String, int,
      int, int, int, int, int) return int';
/
      select 'DST_CHECK', get_dst_offset('America/Los_Angeles', 2007, 3, 11, 10, 0, 0)/(60*60*1000) as OFFSET_FROM_STANDARD_TIME from dual;
    ";

    ##&msg("sql=$sql");
    &oraSQL($sql);
    foreach (@oraSQLout)
    {
      ##print;
      $jvm_output .= $_;
      @words = split;
      $verb    = $words[0];
      if ($verb eq "DST_CHECK")
      {
        $dst_jvm_installed = 1;
        $dst_jvm_result = $words[1];
        &msg("dst_jvm_result=$dst_jvm_result");
      }
    }

    if ($jvm_output =~ /ORA-29547/ || $jvm_output =~ /ORA-29538/)
    {
      &msg("JVM Not installed");
      $dst_jvm_not_installed = 1;
      $dst_jvm_installed = 0;
    }

    if ($dst_jvm_result == 1)
    {
      $dst_jvm_patch_applied = 1;
    }

    ##print $jvm_output;
  }

  #---- Conclusion Logic START

  print "\n";
  &msg("Conclusion:");

  #---- DST Column Problem
  if (! $dst_col_nonsys && ! $dst_col_sys)
  {
    &msg("DST Column Patch NOT NEEDED since this instance does NOT have any DST columns (SYS or Non-SYS)");
  }
  elsif (($dst_col_nonsys || $dst_col_sys) && $dst_col_patch_applied)
  {
    &msg("DST Column Patch IS NEEDED AND ALREADY APPLIED");
  }
  elsif (($dst_col_nonsys || $dst_col_sys) && ! $dst_col_patch_applied)
  {
    &msg("DST Column Patching IS NEEDED since this instance does have DST columns (SYS or Non-SYS) and the patch is NOT applied");
    $dst_col_required = 1;
  }

  if ($dst_jvm_not_installed)
  {
    &msg("DST JVM Patch NOT NEEDED since this instance does NOT have JVM installed");
  }
  elsif ($dst_jvm_installed && $dst_jvm_patch_applied)
  {
    &msg("DST JVM Patch IS NEEDED AND ALREADY APPLIED");
  }
  elsif ($dst_jvm_installed && ! $dst_jvm_patch_applied)
  {
    &msg("DST JVM Patching IS NEEDED since this instance does have JVM enabled and the patch is NOT applied");
    $dst_jvm_required = 1;
  }

  #----
  if    ($dst_col_required)
  {
    &msg("DST Patch Missing and Required (DSTCOL)");
  }
  elsif ($dst_jvm_required)
  {
    &msg("DST Patch Missing and Required (JVM)");
  }
  print "\n";

  #---- Conclusion Logic END

  &msg("Done");
}

#------------------------------------------------------------------------------
sub run_spf
#------------------------------------------------------------------------------
{
  &msg("-spf: SPFILE Contents");

  #---- See if this instance has SPFILE specified
  chop($spfile = `orastat -cp | grep '^spfile ' | head -1 | awk '{ print \$2 }'`);
  &msg("Derived spfile=$spfile");

  if ($spfile eq "" || $spfile eq "()")
  {
    &msg("This instance does not have SPFILE specified - Exiting");
    exit;
  }

  chop($dbname = `orastat - | grep 'DBName:' | head -1 | awk '{ print \$NF }'`);
  &msg("Derived dbname=$dbname");

  if (-e "/opt/oracle/admin/$dbname") { $dir = "/opt/oracle/admin/$dbname"; }
  else                                { $dir = "/opt/oracle/admin/$os"; }

  $pfile = "$dir/pfile/pfile_${os}_bkup.txt";
  &msg("Copy of SPFILE will be written to $pfile");

  $sql = "create pfile='$pfile' from spfile;";
  &oraSQL($sql);
  foreach (@oraSQLout)
  {
    print;
  }

  &msg("SPFILE=$spfile contents");
  print "\n";
  print "=======================================================================\n";
  system("sort $pfile");
  print "=======================================================================\n";
  print "\n";
}

#------------------------------------------------------------------------------
sub run_srt
#------------------------------------------------------------------------------
{
  &msg("-srt: SQL Response Time (From v\$sqlstats)");

  $sql = "
    select
      'Flag_RT',
      sum(executions)                           executions_total,
      sum(elapsed_time)/1000                    elapsed_time_total_secs,
      (sum(elapsed_time)/sum(executions))/1000  average_exec_time_secs,
      (sum(cpu_time)/sum(executions))/1000      average_cpu_time_secs,
      count(*)
    from
      v\\\$sql
    where
      executions > 0;
  ";

  $srt_execs       = "?";
  $srt_total_time  = "?";
  $srt_avg_time    = "?";
  $srt_avg_cpu     = "?";

  # 'FLAG_R EXECUTIONS_TOTAL ELAPSED_TIME_TOTAL_SECS AVERAGE_EXEC_TIME_SECS AVERAGE_CPU_TIME_SECS
  # ------- ---------------- ----------------------- ---------------------- ---------------------
  # Flag_RT         73745426              77619125.7               1.052528            .939600318

  &oraSQL($sql);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "Flag_RT")
    {
      $dfcount++;
      $srt_execs       = sprintf("%.0f",$words[1]);
      $srt_total_time  = sprintf("%.0f",$words[2]);
      $srt_avg_time    = sprintf("%.8f",$words[3]);
      $srt_avg_cpu     = sprintf("%.8f",$words[4]);
      $stmt_cnt        = sprintf("%.0f",$words[5]);
    }
  }
  print "\n";
  &msg("Total_SQL_Execs:   $srt_execs");
  &msg("Total_SQL_Time:    $srt_total_time");
  &msg("SQL_Stmt_Count:    $stmt_cnt");
  &msg("SQL_Avg_CPU_Secs:  $srt_avg_cpu");
  &msg("SQL_Avg_Time_Secs: $srt_avg_time");

  print "\n";
  &msg("Done");
}

#------------------------------------------------------------------------------
sub run_uns
#------------------------------------------------------------------------------
{
  &msg("-uns: Undo Summary");

  $sql = "
    column gb format 999,999.9
    SELECT DISTINCT
      'Flag_M',
      STATUS,
      (SUM(BYTES) / (1024*1024*1024)) GB,
      COUNT(*)
    FROM
      DBA_UNDO_EXTENTS
    GROUP BY
      'Flag_M',
      STATUS;
  ";

  print "\n";
  print "Undo Extent  Total Size\n";
  print "Status             (GB)\n";
  print "------------ ----------\n";

  &oraSQL($sql);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "Flag_M")
    {
      $dfcount++;
      $cat  = $words[1];
      $gb   = sprintf("%.1f",$words[2]);
      printf("%-12s %10s\n",$cat,$gb);

      $total_gb += $gb;
    }
  }

  print "============ ==========\n";
  printf("%-12s %10s\n","Total:",$total_gb);

  print "\n";
  &msg("Run 'orastat -un' to view the current V\$UNDOSTATS values");
  &msg("Done");
}

#------------------------------------------------------------------------------
sub run_ses
#------------------------------------------------------------------------------
{
  &msg("-ses: DB Session Summary");

  $sql = "
    select
      'Flag_S1',
      status,
      count(*)
    from
      v\\\$session
    group by
      'Flag_S1',
      status
    order by
      2;
  ";
  &oraSQL($sql);

  print "\n";
  print "Session   Session\n";
  print "Status      Count\n";
  print "-------- --------\n";

  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "Flag_S1")
    {
      $status     = $words[1];
      $ses_count  = $words[2];
      printf("%-8s %8d\n",$status,$ses_count);

      $total_ses += $ses_count;
    }
  }
  print "======== ========\n";
  printf("%-8s %8d\n","Total:",$total_ses);

  $sql = "
    select
      'Flag_S1',
      nvl(username,\'(Null)\'),
      count(*)
    from
      v\\\$session
    group by
      'Flag_S1',
      nvl(username,\'(Null)\')
    order by
      3, 2;
  ";
  &oraSQL($sql);

  print "\n";
  print "Database                                  Session\n";
  print "Username                                    Count\n";
  print "---------------------------------------- --------\n";

  $total_ses = 0;
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "Flag_S1")
    {
      $user      = $words[1];
      $ses_count = $words[2];

      $total_ses += $ses_count;
      $id = "$user" ;
      printf("%-40s %8d\n",$id,$ses_count);
    }
  }
  print "======================================== ========\n";
  printf("%-40s %8d\n","Total:",$total_ses);

  print "\n";
  &msg("Done");
}

#------------------------------------------------------------------------------
sub run_df5
#------------------------------------------------------------------------------
{

  &msg("-df5 Datafiles");
  print "\n";
  print "Tablespace                   DF   Datafile                                                               Datafile  Datafile \n";
  print "Name                         Num  Path                                                                   Status    Size(MB) \n";
  print "---------------------------- ---- ---------------------------------------------------------------------- --------- ---------\n";

  #---- Old SQL
  #$sqlstmt = '
  #column file_name format a70
  #
  #select \'X\',
  #tablespace_name,
  #file_name,
  #nvl(bytes,0),
  #file_id,
  #nvl(status,\'?\')
  #from dba_data_files order by 4 desc, 3;
  #';

  #---- New SQL
  $sqlstmt = '
  column file_name format a70

  select
    \'X\',
    ts.name,
    df.name,
    nvl(df.bytes,0),
    df.file#,
    nvl(df.status,\'?\')
  from
    v\$datafile df,
    v\$tablespace ts
  where
    df.ts# = ts.ts#
  order by
    4 desc, 3;
  ';

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $dfcount++;
      $status = "";
      $ts     = $words[1];
      $df     = $words[2];
      $size   = $words[3]/1048576;
      $num    = $words[4];
      $status = $words[5];

      printf("%-28s %4d %-70s %-8s %9d\n",$ts,$num,$df,$status,$size);
    }
  }
  print "\n";
  &msg("Found $dfcount datafile(s)");
}

#------------------------------------------------------------------------------
sub run_da
#------------------------------------------------------------------------------
{
  &msg("-da: Datafile Autoextend Details");
  print "\n";
  print "Tablespace       DF   Datafile                                                Datafile  Datafile           Max       Incr  \n";
  print "Name             Num  Path                                                    Status    Size(MB)  AutoExt? Size(MB)  By(MB)\n";
  print "---------------- ---- ------------------------------------------------------- --------- --------- -------- --------- ---------\n";

  $sqlstmt = 'select \'X\',
  tablespace_name,
  file_name,
  nvl(bytes,0),
  file_id,
  nvl(status,\'?\'),
  autoextensible,
  maxbytes,
  increment_by
  from dba_data_files order by 2,4 desc;';

  $df_maxsize = 0;
  $autoext_count = 0;

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $dfcount++;
      $status = "";
      $ts     = $words[1];
      $df     = $words[2];
      $size   = $words[3]/1048576;
      $num    = $words[4];
      $status = $words[5];
      $autoext= $words[6];
      $maxsize= $words[7]/1048576;
      $incrby = $words[8]/1048576;

      ##print "num=$num \n";

      printf("%-16s %4d %-55s %-8s %9d %-8s %9d %9d\n",$ts,$num,$df,$status,$size,$autoext,$maxsize,$incrby);

      $autoext_count++ if $autoext eq "YES";
      $df_maxsize = $size if $size > $df_maxsize;
    }
  }
  print "\n";
  &msg("DatafileCount: $dfcount");
  &msg("DatafilesWithAutoextend: $autoext_count");
  &msg("DatafileMaxSize: $df_maxsize");
}

#------------------------------------------------------------------------------
sub run_pit
#------------------------------------------------------------------------------
{
  if ($arg2 ne "")
  {
    $where = "and t.name like '${arg2}%' ";
    $timestamp = "$date TS=";
  }
  else
  {
    $where = "";
    $timestamp = "";
  }

  &msg("-pit: Performance I/O - By Tablespace - where=$where");
  print "\n";
  print "Tablespace            Average I/O\n";
  print "Name                      RT (MS)\n";
  print "-------------------- ------------\n";

  $sqlstmt = "
    set linesize 150
    set pagesize 200
    set tab off
    select
      'X',
      t.name,
      avg(f.lstiotim*10)
    from
      v\\\$filestat f,
      v\\\$datafile d,
      v\\\$tablespace t
    where
      f.file# = d.file#
      and d.ts# = t.ts#
      and lstiotim != 65535 $where
    group by
      'X',
      t.name
    order by
      2;";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $tscount++;
      $ts      = $words[1];
      $avgiort = $words[2];

      printf("${timestamp}%-20s %12.2f\n",$ts,$avgiort);
    }
  }
  print "\n";
}

#------------------------------------------------------------------------------
sub run_dgl
#------------------------------------------------------------------------------
{
  &msg("-dgl: DataGuard Log Apply Lag - Last 2 Days");
  print "\n";
  print "LogSeq   Switch Timestamp    Applied  Delta vs. Now (Hrs)\n";
  print "-------- ------------------- -------- -------------------\n";

  $sqlstmt = "select 'X',
    sequence#,
    to_char(next_time,'MM/DD/YYYY-HH24:MI:SS') next_time,
    applied,
    round((sysdate-next_time) * 24,2) delta
  from
    v\\\$archived_log
  where
    dest_id = 2
    and next_time > (sysdate - 2)
  order by
    2;";

  $min_delta = 999999;

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb  = shift @words;
    if ($verb eq "X")
    {
      $seq       = shift @words;
      $next_time = shift @words;
      $applied   = shift @words;
      $delta     = sprintf("%.2f",shift(@words));

      printf("%8d %s %-8s %19.2f\n",$seq,$next_time,$applied,$delta);

      $min_delta = $delta if $applied eq "YES" && $delta < $min_delta;
    }
  }
  print "\n";
  &msg("AppliedLogMinDelta: $min_delta");
}

#------------------------------------------------------------------------------
sub run_brm
#------------------------------------------------------------------------------
{
  $days = $arg2;
  $days = 90 if ! $arg2;
  &msg("-brm: Backup Media List - Last $days days");
  print "\n";
  #      2007/11/14-01:24:02    19 44266/1    bk_45859_1_638586079    TAG20071114T010115       /vol/cs05_ora_41_2/bigdogb_1195027460_C1_F1
  print "Completion Time      Elap-Min Recid/Pc   Handle                           Tag                      Media\n";
  print "-------------------- -------- ---------- -------------------------------- ------------------------ ------------------------------\n";

  $sqlstmt = "select \'X\',
    recid,
    piece#,
    handle,
    media,
    tag,
    to_char(completion_time,\'YYYY/MM/DD-HH24:MI:SS\'),
    elapsed_seconds
  from
    v\\\$backup_piece
  where
    completion_time >= (sysdate - $days)
  order
    by 6;";

  $rowcount = 0;

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $rowcount++;

      $recid       = $words[1];
      $piece       = $words[2];
      $handle      = $words[3];
      $media       = $words[4];
      $tag         = $words[5];
      $comp_time   = $words[6];
      $elapsed_min = $words[7]/60;

      $recid_piece = "$recid/$piece";

      printf("%-20s %8d %-10s %-32s %-24s %-50s\n",
        $comp_time,
        $elapsed_min,
        $recid_piece,
        $handle,
        $tag,
        $media
      );

      #---- Decide media type
      if    (length($media) > 12)                   { $media_type = "D"; } #---- Disk (nearstore)
      elsif (length($media) == 6 && $media =~ /^V/) { $media_type = "V"; } #---- VTL (virtual tape library)
      else                                          { $media_type = "T"; } #---- Tape
    }
  }
  print "\n";
  &msg("Retrieved $rowcount rows");
  &msg("LastMediaType: $media_type");
}

# --------------------------------------------------------------------
sub run_di
# --------------------------------------------------------------------
{
  &msg("-di: Datafile Contents - DF#=$arg2 - Ordered by File#,Block_ID");
  if ($arg2 eq "")
  {
    &msg("Usage: $P -di datafile-number");
    exit;
  }

  $sql = "select /*+rule*/
     'X-Flag',
     file_id         ,
     BLOCK_ID        ,
     BLOCKS          ,
     SEGMENT_TYPE    ,
     OWNER           ,
     SEGMENT_NAME
    from
     dba_extents
    where
      file_id = $arg2
    order by
      2,3
      ;";

  print "\n";
  print "FIleNum     BlockID  BlockCnt SegType      SegmentName\n";
  print "----------- -------- -------- ------------ --------------------------------------------\n";

  $extents = 0;

  oraSQL($sql);
  foreach (@oraSQLout)
  {
    ##print;
    @words      = split();
    $verb       = shift(@words);
    if ($verb eq 'X-Flag')
    {
      $file_id  = shift(@words);
      $block_id = shift(@words);
      $blocks   = shift(@words);
      $segtype  = shift(@words);
      $segowner = shift(@words);
      $segname = shift(@words);

      $zobj = $segowner . "." . $segname;
      $zfile = "File=$file_id";

      printf "%-12s %8s %8s %-12s %-40s\n",
        $zfile,
        $block_id,
        $blocks,
        $segtype,
        $zobj
      ;
      $extents++;
    }
  }

  print "\n";
  &msg("Found $extents extents");
}

# --------------------------------------------------------------------
sub run_asm
# --------------------------------------------------------------------
{
  &msg("-asm: ASM Details & Status");

  $sql = "select \'X-Flag\', count(*) from  v\\\$asm_diskgroup; ";
  &oraSQL($sql);
  foreach (@oraSQLout)
  {
    ##print;
    @words      = split();
    $verb       = shift(@words);
    if ($verb eq 'X-Flag')
    {
      $dg_count = shift(@words);
    }
  }

  if ($dg_count == 0)
  {
    &msg("ASM Not running for this instance (V\$ASM_DISKGROUP is empty)");
    exit;
  }

  print "\n";
  &run_asm_dg;

  print "\n";
  &run_asm_dk;

  print "\n";
  &run_asm_op;
}

# --------------------------------------------------------------------
sub run_asm_dg
# --------------------------------------------------------------------
{
  &msg("-asm_dg: ASM Diskgroups");

  $onegig = "(1024*1024*1024)";

  $sql = "select \'X-Flag\',
      group_number,
      translate(name,\' \',\'_\'),
      sector_size,
      block_size,
      ALLOCATION_UNIT_SIZE,
      STATE,
      TYPE,
      TOTAL_MB / 1024,
      FREE_MB / 1024,
      USABLE_FILE_MB / 1024,
      OFFLINE_DISKS,
      UNBALANCED
    from
      \\\$asm_diskgroup ;
    order by
      3;
  ";

  print "\n";
  print "    Diskgroup        Grp# State      RedunType  Alloc Sec/Blk/Unit OfflDisks  Unbal? Size-GB  Free-GB   Used-GB  %Full \n";
  print "    ---------------- ---- ---------- ---------- ------------------ ---------- ------ -------- --------- -------- ------\n";

  &oraSQL($sql);
  foreach (@oraSQLout)
  {
    ##print;
    @words      = split();
    $verb       = shift(@words);
    if ($verb eq 'X-Flag')
    {
      $group_number = shift(@words);
      $name         = shift(@words);
      $sector_size  = shift(@words);
      $block_size   = shift(@words);
      $alloc_size   = shift(@words);
      $state        = shift(@words);
      $type         = shift(@words);
      $total_gb     = sprintf("%.2f",shift(@words));
      $free_gb      = sprintf("%.2f",shift(@words));
      $usable_gb    = sprintf("%.2f",shift(@words));
      $offline_disks= shift(@words);
      $unbalanced   = shift(@words);

      $usable_gb += 0;  #---- No more compile warnings

      $used_gb  = sprintf("%.2f",$total_gb - $free_gb);
      $pct_full = sprintf("%.2f", ($used_gb / $total_gb) * 100) if $total_gb > 0;
      $alloc = "$sector_size/$block_size/$alloc_size";

      printf "DG: %-16s %4s %-10s %-10s %18s %10s %-6s %8s %8s %8s %6s%%\n",
        $name,
        $group_number,
        $state,
        $type,
        $alloc,
        $offline_disks,
        $unbalanced,
        $total_gb,
        $free_gb,
        $used_gb,
        $pct_full;

      $t_total_gb += $total_gb;
      $t_free_gb += $free_gb;
      $t_used_gb += $used_gb;
    }
  }

  $t_pct_full = sprintf("%.2f", ($t_used_gb / $t_total_gb) * 100);
  print  "    ================ ==== ========== ========== ================== ========== ====== ======== ========= ======== ======\n";
  printf "    %-16s %4s %-10s %-10s %18s %10s %-6s %8s %8s %8s %6s%%\n",
        "DGTotals:",
        "",
        "",
        "",
        "",
        "",
        "",
        $t_total_gb,
        $t_free_gb,
        $t_used_gb,
        $t_pct_full;
}

# --------------------------------------------------------------------
sub run_asm_dk
# --------------------------------------------------------------------
{
  &msg("-asm_dk: ASM Disks");

  $onegig = "(1024*1024*1024)";

  $sql = "select \'X-Flag\',
      group_number,
      disk_number,
      translate(name,\' \',\'_\'),
      state,
      path,
      TOTAL_MB / 1024,
      FREE_MB / 1024,
      reads / (1024*1024),
      writes / (1024*1024),
      bytes_read / (1024*1024),
      bytes_written / (1024*1024),
      read_time*10,
      write_time*10
    from
      v\\\$asm_disk
    where
      group_number > 0
    order by
      name;
  ";

  print "\n";
  print "Disk             Grp# Dsk# State      Path                                 Size-GB  Free-GB  Used-GB  M-Reads  M-Writes   MB-R     MB-W   Avg-R-Ms Avg-W-Ms\n";
  print "---------------- ---- ---- ---------- ------------------------------------ -------- -------- -------- -------- -------- -------- -------- -------- --------\n";

  &oraSQL($sql);
  foreach (@oraSQLout)
  {
    ##print;
    @words      = split();
    $verb       = shift(@words);
    if ($verb eq 'X-Flag')
    {
      $group_number = shift(@words);
      $disk_number  = shift(@words);
      $name         = shift(@words);
      $state        = shift(@words);
      $path         = shift(@words);
      $total_gb     = sprintf("%.2f",shift(@words));
      $free_gb      = sprintf("%.2f",shift(@words));
      $reads         = sprintf("%.2f",shift(@words));
      $writes        = sprintf("%.2f",shift(@words));
      $bytes_read    = sprintf("%.0f",shift(@words));
      $bytes_written = sprintf("%.0f",shift(@words));
      $read_time     = shift(@words);
      $write_time    = shift(@words);

      $used_gb = sprintf("%.2f",$total_gb - $free_gb);

      $avg_read_time  = sprintf("%.2f",$read_time  / ($reads  * (1024*1024))) if $reads > 0;
      $avg_write_time = sprintf("%.2f",$write_time / ($writes * (1024*1024))) if $writes > 0;

      printf "%-16s %4s %4s %-10s %-36s %8s %8s %8s %8s %8s %8s %8s %8s %8s\n",
        $name,
        $group_number,
        $disk_number,
        $state,
        $path,
        $total_gb,
        $free_gb,
        $used_gb,
        $reads,
        $writes,
        $bytes_read,
        $bytes_written,
        #$read_time,
        #$write_time
        $avg_read_time,
        $avg_write_time
      ;

      $t_total_gb += $total_gb;
      $t_free_gb += $free_gb;
      $t_used_gb += $used_gb;
    }
  }
}

# --------------------------------------------------------------------
sub run_asm_op
# --------------------------------------------------------------------
{
  &msg("-asm_op: ASM Ongoing Rebalance Operations");

  # GROUP_NUMBER                                       NUMBER
  # OPERATION                                          VARCHAR2(5)
  # STATE                                              VARCHAR2(4)
  # POWER                                              NUMBER
  # ACTUAL                                             NUMBER
  # SOFAR                                              NUMBER
  # EST_WORK                                           NUMBER
  # EST_RATE                                           NUMBER
  # EST_MINUTES                                        NUMBER

  $sql = "select \'X-Flag\',
      group_number,
      operation,
      translate(state,\' \',\'?\'),
      power,
      actual,
      sofar,
      est_work,
      est_rate,
      est_minutes
    from
      v\\\$asm_operation
    order by
      2, 3;
  ";

  print "\n";
  print "Diskgrp#   Operation  State      Power      Actual     SoFar      EstWork    EstRate    EstMin   \n";
  print "---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n";

  &oraSQL($sql);
  foreach (@oraSQLout)
  {
    ##print;
    @words      = split();
    $verb       = shift(@words);
    if ($verb eq 'X-Flag')
    {
      $group_num = shift(@words);
      $oper      = shift(@words);
      $state     = shift(@words);
      $power     = shift(@words);
      $actual    = shift(@words);
      $sofar     = shift(@words);
      $est_work  = shift(@words);
      $est_rate  = shift(@words);
      $est_min   = shift(@words);

      printf "%10s %-10s %-10s %10s %10s %10s %10s %10s %10s\n",
        $group_num,
        $oper,
        $state,
        $power,
        $actual,
        $sofar,
        $est_work,
        $est_rate,
        $est_min
      ;

    }
  }
}

# --------------------------------------------------------------------
sub run_asm_fi
# --------------------------------------------------------------------
{
  &msg("asm_fi: ASM Files");
  $sql = 'select distinct \'Flag-InASM\', instance_name from v\$asm_client;';
  &oraSQL($sql);
  foreach (@oraSQLout)
  {
    ##print;
    @words      = split();
    $verb       = shift(@words);
    if ($verb eq 'Flag-InASM')
    {
      $asm_instance = shift(@words);
      last;
    }
  }

  if (! $asm_instance)
  {
    &msg("Error: Cannot determine ASM instance name from V\$ASM_CLIENT:instance_name");
    exit 1;
  }

  &msg("Querying ASM instance $asm_instance for list of files");

  print "\n";

  system("ssh $host '. $toolsdir/envora +ASM1; echo \"find \* \*\" | asmcmd | grep -v \'^ASMCMD\' | sort'");

  print "\n";

  &msg("Done");
}

# --------------------------------------------------------------------
sub run_amm
# --------------------------------------------------------------------
{
  &msg("-amm: Automatic Memory Management Status (pool sizes in MB)");

  $onegig = "(1024*1024*1024)";
  $onemeg = "(1024*1024)";

  $sql = "select \'X-Flag\',
            translate(component,\' \',\'_\'),
	    CURRENT_SIZE  / $onemeg         ,
	    MIN_SIZE       / $onemeg        ,
	    MAX_SIZE         / $onemeg      ,
	    USER_SPECIFIED_SIZE / $onemeg   ,
	    OPER_COUNT            ,
	    LAST_OPER_TYPE        ,
	    LAST_OPER_MODE        ,
            to_char(last_oper_time,\'YYYY/MM/DD-HH24:MI:SS\')
    from
	   v\\\$sga_dynamic_components
    where
           current_size > 0;";

  print "\n";
  print "SGA Component       Current Size  Min Size     Max Size     Spec'd Size  Resize Count Resize Type  Resize Mode  Resize Date\n";
  print "------------------- ------------- ------------ ------------ ------------ ------------ ------------ ------------ --------------------\n";

  &oraSQL($sql);
  foreach (@oraSQLout)
  {
    ##print;
    @words      = split();
    $verb       = shift(@words);
    if ($verb eq 'X-Flag')
    {
      $component     = shift(@words);
      $current_size  = sprintf("%.2f",shift(@words));
      $min_size      = sprintf("%.2f",shift(@words));
      $max_size      = sprintf("%.2f",shift(@words));
      $user_size     = sprintf("%.2f",shift(@words));
      $oper_count    = shift(@words);
      $oper_type     = shift(@words);
      $oper_mode     = shift(@words);
      $oper_time     = shift(@words);

      printf "%-20s %12s %12s %12s %12s %12s %-12s %-12s %-12s\n",
        $component,
        $current_size,
        $min_size,
        $max_size,
        $user_size,
        $oper_count,
        $oper_type,
        $oper_mode,
        $oper_time
    }
  }
}


# --------------------------------------------------------------------
sub run_up
# --------------------------------------------------------------------
{
  &msg("-up: DB User Password Info");
  $sql = "
    select
      'X-Flag',
      du.username,
      du.profile,
      du.account_status,
      nvl(to_char(du.lock_date,'YYYY/MM/DD-HH24:MI:SS'),'?') ,
      nvl(to_char(du.created,'YYYY/MM/DD-HH24:MI:SS') ,'?'),
      nvl(to_char(du.expiry_date,'YYYY/MM/DD-HH24:MI:SS') ,'?'),
      --nvl(du.expiry_date - sysdate, '?')
      du.expiry_date - sysdate
    from
      dba_users du
    order by
      2;
  ";
  print "\n";
  print "User                 Profile              Status                           Create Date         PW Expiry Date      Days Until PW Expires\n";
  print "-------------------- -------------------- -------------------------------- ------------------- ------------------- ---------------------\n";

  $sys_locked = 0;
  $sys_past = 0;
  $sys_min_days = 99999999999;

  &oraSQL($sql);
  foreach (@oraSQLout)
  {
    print if /ORA-/;
    @words      = split();
    $verb       = shift(@words);
    if ($verb eq 'X-Flag')
    {
      $user              = shift(@words);
      $profile           = shift(@words);
      $status            = shift(@words);
      $lock_date         = shift(@words);
      $create_date       = shift(@words);
      $expiry_date       = shift(@words);
      $days_until_expiry = shift(@words);

      $status .= "(Locked $lock_date)" if $status =~ /LOCKED/;
      $days_until_expiry = sprintf("%.2f",$days_until_expiry);

      if ($days_until_expiry eq "")
      {
        $days_out = "?";
      }
      elsif ($days_until_expiry >= 0)
      {
        $days_out = $days_until_expiry;
      }
      else
      {
        $days_out = "(Past)";
      }

      if (
          $user eq "SYS"      ||
          $user eq "SYSTEM"   ||
          $user eq "PERFSTAT" ||
          $user eq "DBSNMP"   ||
          $user eq "DBAMON"
         )
      {
        if ($status =~ /EXPIRED/ || $status =~ /LOCKED/) { $sys_locked++; }
        if ($days_out > 0 && $days_out < $sys_min_days) { $sys_min_days =$days_out; }
        if ($days_out =~ /Past/) { $sys_past++; }
      }

      printf "%-20s %-20s %-32s %-19s %-19s %-16s\n", $user, $profile, $status, $create_date, $expiry_date, $days_out;

      $rows++;
    }
  }

  print "\n";
  &msg("Users Found:             $rows");
  &msg("SYSUsers_Locked:         $sys_locked");
  &msg("SYSUsers_Past:           $sys_past");
  &msg("SYSUsers_Min_Days_Until: $sys_min_days");
}

# --------------------------------------------------------------------
sub run_fra
# --------------------------------------------------------------------
{
  &msg("-fra: Flash Recovery Area Status");

  $onegig = "(1024*1024*1024)";

  $sql = "select \'X-Flag\',
           name,
	   space_limit / $onegig,
           space_used / $onegig,
           space_reclaimable / $onegig,
           number_of_files
    from
	   v\\\$recovery_file_dest; ";
  print "\n";
  print "       Limit(gB)         Used(gB)  Reclaimable(gb)     Net Used(gB)       File Count\n";
  print "---------------- ---------------- ---------------- ---------------- ----------------\n";

  &oraSQL($sql);
  foreach (@oraSQLout)
  {
    @words      = split();
    $verb       = shift(@words);
    if ($verb eq 'X-Flag')
    {
      $franame     = shift(@words);
      $limit       = sprintf("%.2f",shift(@words));
      $used        = sprintf("%.2f",shift(@words));
      $reclaimable = sprintf("%.2f",shift(@words));
      $nofiles     = shift(@words);

      $netused     = sprintf("%.2f", $used - $reclaimable);

      printf "%16s %16s %16s %16s %16s\n", $limit, $used, $reclaimable, $netused, $nofiles;
    }
  }

  $sql = "select \'X-Flag\',
    FILE_TYPE,
    PERCENT_SPACE_USED,
    PERCENT_SPACE_RECLAIMABLE,
    NUMBER_OF_FILES
  from
    v\\\$flash_recovery_area_usage;
  order by 1";
  print "\n";
  print "File Type                  % Used    % Reclaimable       File Count\n";
  print "---------------- ---------------- ---------------- ----------------\n";

  &oraSQL($sql);
  foreach (@oraSQLout)
  {
    @words      = split();
    $verb       = shift(@words);
    if ($verb eq 'X-Flag')
    {
      $filetype    = shift(@words);
      $pctused     = sprintf("%.2f",shift(@words));
      $pctrec      = sprintf("%.2f",shift(@words));
      $nofiles     = shift(@words);

      ## &msg("DEBUG pctrec=$pctrec");

      printf "%-16s %16s %16s %16s\n", $filetype, $pctused, $pctrec, $nofiles;
    }
  }

  if ($franame)
  {
    $pctfull = sprintf("%.2f",( ($used - $reclaimable) / $limit) * 100 );
    print "\n";
    print "Flash db_recovery_file_dest File (FRAFILE): $franame\n";
    print "Flash Recovery Area Percent Full (FRAFULL): ${pctfull}%\n";
  }
  else
  {
    print "\n";
    &msg("Flash Recovery Area (db_recovery_file_dest) not configured");
  }
}

# --------------------------------------------------------------------
sub run_sz
# --------------------------------------------------------------------
{
  $sid = $arg2;
  if (! $arg2)
  {
    &msg("Usage: orastat -sz SID");
    return;
  }
  &msg("-sa: Session Statistics for session $sid");
  $sqlstmt = "select \'X\',
	   vss.value,
	   vsn.name
    from
	   v\\\$sesstat vss,
	   v\\\$statname vsn
    where (vss.statistic#=vsn.statistic#)
      AND vss.value <> 0
      and vss.sid = $arg2
    order by
      3;";

  print "Session Statistic                                                      Value\n";
  print "------------------------------------------------------------ ---------------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words      = split();
    $verb       = $words[0];
    if ($verb eq 'X')
    {
      $value      = $words[1];
      $text = "";
      for ($i = 2; $i <= $#words; $i++)
      {
	$text .= $words[$i];
	$text .= " ";
      }
      printf "%-60s %15s\n",$text,$value;
    }
  }
}

# --------------------------------------------------------------------
sub run_cc
# --------------------------------------------------------------------
{
  &msg("-cc: Client Connections - From other servers");
  $sqlstmt = "
    select
      \'Z\',
      machine,
      count(*)
    from
      v\\\$session
    where
      machine is not null
      and machine != '$host'
    group by
      \'Z\',
      machine;
  ";

  print "\n";
  print "Client Hostname                          Client IP Address Connection Count\n";
  print "---------------------------------------- ----------------- ----------------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    @words = split();
    $verb  = shift @words;
    if ($verb eq "Z")
    {
      $client = shift @words;
      $count  = shift @words;
      chop($ipaddr = `nslookup $client 2>/dev/null | grep 'Address:' | head -1 | awk '{ print \$2 }'`);

      $client_string = "Client: $client";
      printf("%-40s %-17s %16d\n",$client_string,$ipaddr,$count);

      $network  = (split(/\./,$ipaddr)) [0] ;
      $network_count{$network} += $count if $network ne "";
    }
  }
  close(RO);

  print "\n";
  print "Network         Connection Count\n";
  print "--------------- ----------------\n";

  foreach $network (sort keys %network_count)
  {
    $netstring = "Network: $network";
    printf("%-15s %16d\n",$netstring,$network_count{$network});
  }

  print "\n";
}

# --------------------------------------------------------------------
sub run_tt
# --------------------------------------------------------------------
{
  $tot_size = 0;
  $tot_free = 0;
  $tot_used = 0;
  $tot_df   = 0;

  $sql = "
    select \'Y\',
      value
      from v\\\$parameter
      where
      name in (\'db_block_size\');
    select \'X\',
          a.tablespace_name as tablespace_name,
          a.size_blocks,
          nvl(a.max_id,0),
          nvl(c.used_blocks,0),
          d.status,
          d.extent_management,
          d.allocation_type
     from
          ( select
              tablespace_name,
              sum(blocks) as size_blocks,
              count(1) max_id
            from
              dba_temp_files
            group by
              tablespace_name
          ) a,
          ( select
              tablespace_name,
	      sum(used_blocks) as used_blocks
	    from
              v\\\$sort_segment
	    group by
              tablespace_name
          ) c,
          dba_tablespaces d
    where
          a.tablespace_name = c.tablespace_name (+)
      and a.tablespace_name = d.tablespace_name (+); ";

  print "\n";
  print "TemporaryTablespace      Type Status   ExtentMgmt AllocTyp NumDF  Size(MB)  Free(MB)  Used(MB)    Pct\n";
  print "------------------------ ---- -------- ---------- -------- ----- --------- --------- --------- ------\n";

  &oraSQL($sql);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "Y")
    {
      $block_size = $words[1];
    }
    if ($verb eq "X")
    {
      &error("Something is wrong - block_size is NULL") if ! $block_size;

      $found = 1;

      $ts          = $words[1];
      $size_blocks = $words[2];
      $num_df      = $words[3];
      $used_blocks = $words[4];
      $status      = $words[5];
      $extmgmt     = $words[6];
      $alloctyp    = $words[7];

      $size = ($size_blocks * $block_size) / 1048576;
      $used = ($used_blocks * $block_size) / 1048576;
      $free = $size - $used;

      if ($size == 0)
      {
        $pct  = 0;
      }
      else
      {
        $pct  = ($used / $size) * 100;
      }

      $type = "TEMP";

      printf("%-24s %-4s %-8s %-10s %-8s %5d %9d %9d %9d %6.2f \n",$ts,$type,$status,$extmgmt,$alloctyp,$num_df,$size,$free,$used,$pct);

      $tot_size += $size;
      $tot_free += $free;
      $tot_used += $used;
      $tot_df   += $num_df;
    }
  }
  if (!$found)
  {
    print "$P | Something is wrong - query returned no rows\n";
    exit 1;
  }

  print "======================== ==== ======== ========== ======== ===== ========= ========= ========= ======\n";
  $ts = "Total:";
  $pct = ($tot_used / $tot_size) * 100;
  printf("%-24s                                   %5d %9d %9d %9d %6.2f\n",$ts,$tot_df,$tot_size,$tot_free,$tot_used,$pct);

  print "\n";
  &msg("NOTE: These numbers are COMPLETELY ACCURATE. They show");
  &msg("      v\$sort_usage and dba_temp_file data.");
}

# --------------------------------------------------------------------
sub run_mr
# --------------------------------------------------------------------
{
  $howmuch = $arg2;
  $raw     = $arg3;

  $sqlstmt = ' select \'Z\', value from v\$parameter where name =\'background_dump_dest\';';
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    @words = split();
    $verb  = $words[0];
    if ($verb eq "Z")
    {
      $fname = $words[1];
    }
  }
  close(RO);

  $fname =~ s/\?/$oh/g;
  &msg("Alert Log: $fname Reformatted") unless $raw;
  &msg("================================================================") unless $raw;
  if ($fname eq "")
  {
    &msg("ERROR: bdump Directory is BLANK - Something is Wrong - Assuming default filename") unless $raw;
    $fname = "/opt/oracle/admin/$os/bdump";
    &msg("Trying $fname") unless $raw;
  }

  $howmuch = 20 if ! $howmuch;

  &alertLogReformat("$fname/alert_$os.log",$howmuch);

  &msg("================================================================") unless $raw;
}

# --------------------------------------------------------------------
sub run_lg
# --------------------------------------------------------------------
{
  &msg("-lg: Long Operations Progress - Where time_remaining > 0");
  $sqlstmt = '
    select \'Z\',
      sid,
      serial#,
      context,
      sofar,
      totalwork,
      last_update_time - start_time,
      --round(sofar/totalwork*100,2) "PctComplete",
      to_char(start_time,\'YYYY/MM/DD-HH24:MI:SS\') ,
      to_char(last_update_time,\'YYYY/MM/DD-HH24:MI:SS\') ,
      opname
    from
      v\$session_longops
      where
        time_remaining > 0
    order by 8, 4;';

  print "SID-Ser#     Start               Last Updated        El. Mins Work Sofar Work Total Pct. Done  Desc.\n";
  print "------------ ------------------- ------------------- -------- ---------- ---------- ---------- ------------------------\n";

  &oraSQL("$sqlstmt");
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words   = split();
    $verb    = $words[0];
    $sid     = $words[1];
    $ser     = $words[2];
    #$context = $words[3];
    $sofar   = $words[4];
    $totalwk = $words[5];
    $etime   = sprintf("%5.1f",$words[6] * (24*60));
    $stime   = $words[7];
    $utime   = $words[8];
    $opname  = $words[9] . $words[10]  . $words[11]  . $words[12];

    if ($totalwk > 0) { $pctcomp = sprintf("%7.3f",($sofar/$totalwk)*100); }
    else              { $pctcomp = "*"; }

    $totalsize = $blocksize * $sofar;
    $gbrate = "?";

    $sidser = "$sid-$ser";

    if ($verb eq "Z")
    {
      printf "%-12s %-19s %-19s %8s %10s %10s %10s %-10s \n",$sidser,$stime,$utime,$etime, $sofar,$totalwk,$pctcomp,$opname;
    }
  }
  exit;
}

# --------------------------------------------------------------------
sub run_df4
# --------------------------------------------------------------------
{
  &msg("-df4 Datafiles which house S* tables with >= \$arg2 ($arg2) columns");

  $arg2 = 250 if ! $arg2;
  if ($arg2 < 0 || $arg2 > 1000) { &msg("Usage: $P -df4 <Column Count, Default=250>"); exit; }
  &msg("Column Count (arg2): $arg2");


  print "\n";
  print "Tablespace               DF   Datafile                                                               Datafile  Datafile \n";
  print "Name                     Num  Path                                                                   Status    Size(MB) \n";
  print "------------------------ ---- ---------------------------------------------------------------------- --------- ---------\n";

  $sqlstmt = "
    column nbytes format 999999999999
    column file_name format a60
    select
      'Flag_X',
      tablespace_name,
      file_name,
      nvl(bytes,0) nbytes,
      file_id,
      nvl(status,'?') dfstatus
    from
      dba_data_files
    where
      file_id in (
     select distinct file_id from dba_extents where segment_name in (
      select
	table_name
      from
	dba_tab_columns
      where
	table_name like 'S%'
	-- and owner = 'SIEBEL'
      having
	count(*) >= $arg2
      group by
	table_name)
    )
      order by 4 desc, 3;
  ";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "Flag_X")
    {
      $dfcount++;
      $status = "";
      $ts     = $words[1];
      $df     = $words[2];
      $size   = $words[3]/1048576;
      $num    = $words[4];
      $status = $words[5];

      ##print "num=$num \n";

      printf("%-24s %4d %-70s %-8s %9d\n",$ts,$num,$df,$status,$size);
    }
  }
  print "\n";
  &msg("Found $dfcount datafile(s)");
  exit;
}

# --------------------------------------------------------------------
sub run_df3
# --------------------------------------------------------------------
{
  &msg("-df3: Datafile list from v\$datafile");
  $sqlstmt = '
    select \'Z\',
      name
    from
      v\$datafile
    order by 2;';

  print "\nDatafile\n";
  print "-------------------------------------------------\n";

  $dfcount = 0;

  &oraSQL("$sqlstmt");
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words   = split();
    $verb    = $words[0];
    $df      = $words[1];

    if ($verb eq "Z")
    {
      printf "%-50s\n",$df;
      $dfcount++;
    }
  }
  print "\n";
  &msg("Found $dfcount datafiles");
  exit;
}

# --------------------------------------------------------------------
sub run_dp
# --------------------------------------------------------------------
{
  &msg("-dp: Datafile Properties from database_properties");
  $sqlstmt = '
    select \'Z\',
      property_name,
      property_value
    from
      database_properties
    order by 2;';

  print "\n";
  print "Name                           Value\n";
  print "------------------------------ ------------------\n";

  $dfcount = 0;

  &oraSQL("$sqlstmt");
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words   = split();
    $verb    = $words[0];

    if ($verb eq "Z")
    {
      $name   = $words[1];
      $val    = $words[2];
      printf "%-30s %-20s\n",$name, $val;
    }
  }
  exit;
}

# --------------------------------------------------------------------
sub run_pr
# --------------------------------------------------------------------
{
  &msg("-pr: Profiles");
  $sqlstmt = '
    select \'Z\',
      profile,
      resource_type,
      resource_name,
      limit
    from
      dba_profiles
    order by 2,3,4;';

  print "\n";
  print "Profile          ResourceType   ResourceName                 Limit\n";
  print "---------------- -------------- ---------------------------- ---------------------\n";

  $dfcount = 0;

  &oraSQL("$sqlstmt");
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words   = split();
    $verb    = $words[0];

    if ($verb eq "Z")
    {
      $prof   = $words[1];
      $rt     = $words[2];
      $rn     = $words[3];
      $li     = $words[4];
      printf "%-16s %-14s %-28s %-16s %-16s\n",$prof, $rt, $rn, $li;
    }
  }
  exit;
}

# --------------------------------------------------------------------
sub run_cd
# --------------------------------------------------------------------
{
  &msg("-cd: Controlfile Details (Sections)");
  $sqlstmt = '
    set linesize 999
    select \'Z\',
      translate(type,\' \',\'_\'),
      RECORD_SIZE,
      RECORDS_TOTAL,
      RECORDS_USED,
      FIRST_INDEX,
      LAST_INDEX,
      LAST_RECID
    from
      v\$controlfile_record_section
    order
      by 2;
  ';

  print "\n";
  print "Record Type               RecSize RecsTot  RecsUsed FirstNdx  LastNdx LstRecid\n";
  print "------------------------ -------- -------- -------- -------- -------- --------\n";

  $dfcount = 0;

  &oraSQL("$sqlstmt");
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words   = split();
    $verb    = $words[0];

    if ($verb eq "Z")
    {
      $type   = $words[1];
      $recsiz = $words[2];
      $rectot = $words[3];
      $recuse = $words[4];
      $indxfi = $words[5];
      $indxla = $words[6];
      $recila = $words[7];

      printf "%-24s %8s %8s %8s %8s %8s %8s\n",$type, $recsiz, $rectot, $recuse, $indxfi, $indxla, $recila;
    }
  }
  exit;
}

# --------------------------------------------------------------------
sub run_bb
# --------------------------------------------------------------------
{
  &msg("-bb: RMAN Backup Piece Summary - From v\$backup_piece");
  $sqlstmt = '
    select
      \'Z\',
      handle,
      max(to_char(completion_time,\'YYYY/MM/DD-HH24:MI:SS\')),
      max(elapsed_seconds),
      count(distinct media)
    from
      v\$backup_piece
    group by
      handle
    order by
      3 ;
  ';

  print "\n";
  print "Completion Timestamp Piece Handle              Elapsed-Min.   Media Cnt.\n";
  print "-------------------- ------------------------- ------------   ----------\n";
  $bkcount = 0;

  &oraSQL("$sqlstmt");
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words   = split();
    $verb    = $words[0];

    if ($verb eq "Z")
    {
      $handle   = $words[1];
      $comptime = $words[2];
      $mins     = int($words[3] / 60);
      $mediacnt = $words[4];

      printf "%-20s %-25s %12s %12s\n",$comptime, $handle, $mins, $mediacnt;

      $date = substr($comptime,0,10);
      $datetotal{$date} += $mins;

      $bkcount++;
    }
  }
  print "\n";
  &msg("Found $bkcount distinct backup pieces");

  print "\n";
  print "Date       Total Bkup Mins.\n";
  print "---------- ----------------\n";

  foreach (sort keys %datetotal)
  {
    $z = int($datetotal{$_} / 50);
    $banner = "*" x $z;
    printf "%-10s %16s %-50s\n",$_, $datetotal{$_}, $banner;
  }

  exit;
}

# --------------------------------------------------------------------
sub run_fm
# --------------------------------------------------------------------
{
  $file = $arg2;
  &msg("-fm: File status $file");

  if (! -e "$file")
  {
    &msg("File $file does not exist");
    exit;
  }

  $fileage_secs = time - ( stat "$file" ) [9];
  $fileage_hours = sprintf("%.2f",($fileage_secs / 3600));
  &msg("Hours_Since_Update: $fileage_hours");
  exit;
}

# --------------------------------------------------------------------
sub run_av
# --------------------------------------------------------------------
{
  $days = $arg2;
  $days = 30 if $days eq "";

  if ($arg3 eq "H")
  {
    $timestring = "YYYY/MM/DD-HH24";
    $num = 60;
  }
  else
  {
    $arg3 = "D";
    $timestring = "YYYY/MM/DD";
    $num = 1440;
  }

  if ($oraver_num < 8.1)
  {
    &msg("orastat -av Does not work on Oracle < 8.1");
    exit;
  }

  $days = $arg2;
  $days = 30 if $days eq "";

  $rows = 0;

  #---- 3.01 Determine "match string"
  $av_match = "%archv0%";   # default
  $sqlstmt = "
    select
      \'X\',
      destination
    from
      v\\\$archive_dest
    where
      destination is not null
    order by
      dest_id;";
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words   = split();
    $verb    = shift @words;
    if ($verb eq "X")
    {
      $dest     = shift @words;
      $av_match = "%$dest%";
      last;
    }
  }

  if ($dest =~ /^USE/)
  {
    $where = "dest_id = 10"
  }
  elsif ($oraver_num >= 10)
  {
    $where = "dest_id = 1"
  }
  else
  {
    $where = "name like '$av_match'";
  }

  &msg("-av: Archivelog Volume - For the last $days days - Mode=$arg3");
  &msg("     Destination where clause: $where");

  $sqlstmt = "
    select
      \'X\',
      to_char(completion_time,\'$timestring\'),
      sum(blocks * block_size),
      count(*)
    from
      v\\\$archived_log
    where
      completion_time > sysdate - $days
      and $where
    group by
      to_char(completion_time,\'$timestring\')
    order by
      2;";

  print "\n";
  print "              Archive    Archive    REDO Rate \n";
  print "Timestamp     Data (MB)  Log Count  (MB/Min)* \n";
  print "------------- ---------- ---------- ----------\n";

  $max_size  = -1;
  $max_count = -1;
  $max_mbmin = -1;

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $ts      = shift @words;
      $size    = int((shift @words) / 1000000);
      $count   = shift @words;
      $mbmin   = int($size / $num);

      printf "%-13s %10s %10s %10s\n",$ts,$size,$count,$mbmin;
      $rows++;
      $total_size  += $size;
      $total_count += $count;
      $total_mbmin += $mbmin;

      $max_size  = $size  if $size  > $max_size;
      $max_count = $count if $count > $max_count;
      $max_mbmin = $mbmin if $mbmin > $max_mbmin;
    }
  }

  # Average line
  $ts = "(Average)";
  $avg_size  = int($total_size  / $rows) if $rows > 0;
  $avg_count = int($total_count / $rows) if $rows > 0;
  $avg_mbmin = int($total_mbmin / $rows) if $rows > 0;

  print "------------- ---------- ---------- ----------\n";
  printf "%-13s %10s %10s %10s\n",$ts,$avg_size,$avg_count,$avg_mbmin;

  # Max line
  $ts = "(Max)";

  printf "%-13s %10s %10s %10s\n",$ts,$max_size,$max_count,$max_mbmin;

  # Total line
  $ts = "(Total)";
  $tot_size  = $total_size  ;
  $tot_count = $total_count ;
  $tot_mbmin = $total_mbmin ;
  printf "%-13s %10s %10s %10s\n",$ts,$tot_size,$tot_count,$tot_mbmin;

  print "\n";
  &msg("$rows Row(s) found - *: Average of a 24 hour period");
  exit;
}
# --------------------------------------------------------------------
sub run_cs
# --------------------------------------------------------------------
{
  &msg("-cs: Non-Default Active Parameters (from v\$parameter)");
  print "Parm                                     Value\n";
  print "---------------------------------------- ---------------------------------------\n";

  $sqlstmt = 'select
    \'X\',
    name,
    translate(value,\' \',\'_\')
  from
    v\$parameter
  where
    isdefault != \'TRUE\'
  order by
    2;';
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    @words  = split();
    $verb   = shift @words;
    if ($verb eq "X")
    {
      $name = shift @words;
      foreach (@words)
      {
        $value .= "$_ ";
      }
      printf "%-40s %-s\n",
        $name,
        $value;
      $value = "";
    }
  }
}

# --------------------------------------------------------------------
sub run_cm
# --------------------------------------------------------------------
{
  &msg("-cm: Active Parameters And Modifiable Settings (from v\$parameter)");
  print "Parm                                     IsDefault IsSesMod  IsSysMod  IsMod     IsAdj     Value\n";
  print "---------------------------------------- --------- --------- --------- --------- --------- ------------------------------\n";

  $sqlstmt = 'select
    \'X\',
    name,
    translate(value,\' \',\'_\'),
    isdefault,
    isses_modifiable,
    issys_modifiable,
    ismodified,
    isadjusted
  from
    v\$parameter
  order by
    2;';
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    @words  = split();
    $verb   = $words[0];
    $name   = $words[1];
    $value  = $words[2];
    $isdef  = $words[3];
    $isses  = $words[4];
    $issys  = $words[5];
    $ismod  = $words[6];
    $isadj  = $words[7];

    if ($verb eq "X")
    {
      printf "%-40s %-9s %-9s %-9s %-9s %-9s %-30s\n",
        $name,
        $isdef,
        $isses,
        $issys,
        $ismod,
        $isadj,
        $value;
    }
  }
}

# --------------------------------------------------------------------
sub run_su
# --------------------------------------------------------------------
{
  &msg("-su: System Utilization");
  &msg("Collecting CPU busy sample");

  #---- Old way
  #chop($cpuidle = `timex -s sleep 2 2>&1 | grep ":" | tail -1 | awk '{ print \$5 }'`);

  #---- New way
  chop($cpuidle = `vmstat 1 5 | tail -4 | awk '{total +=\$NF};END {print (total/4) }'`);

  $cpubusy = 100-$cpuidle;
  &msg("CPU(s) Busy: $cpubusy%");

}

# --------------------------------------------------------------------
sub run_dd
# --------------------------------------------------------------------
{
  &msg("-dd: Create DDL - Object=$arg3.$arg4 Type=$arg2");

  if ($oraver < 9)
  {
    &msg("orastat -dd Will only work with Oracle 9i");
    exit;
  }

  $arg2_uc = uc $arg2;
  $arg3_uc = uc $arg3;
  $arg4_uc = uc $arg4;

  $rows = 0;
  print "\n";

  $sqlstmt = "
    SELECT
      \'X\',
      dbms_metadata.get_ddl ('$arg2_uc','$arg4_uc','$arg3_uc')
    FROM
      dual;";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    print if $printflag && /^ /;
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $printflag = 1;
      $rows++;
    }
  }
  print "\n";
  &msg("Object $arg3.$arg4 type=$arg2 Not Found") if !$rows;
  exit;
}

#------------------------------------------------------------------------------
sub run_cfbl
#------------------------------------------------------------------------------
{
  &msg("-cfbl: List Controlfile Backups - arg2=$arg2");

  $cfdir = "/var/opt/oracle/bkup01/$os/ctrltrace";
  opendir(CFDIR,"$cfdir");
  @filenames = readdir(CFDIR);
  @filenamessorted = sort @filenames;
  closedir(CFDIR);
  print "\n";
  print "Archive Log File Name                                  CF Backup Create Time          Age(Secs) FileSize\n";
  print "------------------------------------------------------ ------------------------------ --------- ---------\n";
  $numlogs = 0;
  $totsize = 0;
  $age     = -1;
  foreach $file (@filenamessorted)
  {
    next if ($file !~ /^2/);
    if (system("grep '$os' $cfdir/$file > /dev/null") != 0)
    {
      next;
    }

    $cfmtime = ( stat "$cfdir/$file" ) [9];
    $cfsize  = ( stat "$cfdir/$file" ) [7];
    $cfctime = ( stat "$cfdir/$file" ) [10];
    $cfctime_fmt = &timeToText("$cfctime");

    $flag = "*Hit*" if $cfctime > $arg2 && $arg2;

    $age = time - $cfmtime;
    $oldest = $age if $age > $oldest;
    printf "%-54s %10s %19s %9s %9s %-5s\n","$cfdir/$file",$cfctime,$cfctime_fmt,$age,$cfsize,$flag;
    $numlogs++;
  }
  print "\n";
  &msg("Found $numlogs backups");
}

#------------------------------------------------------------------------------
#
# Main
#
#------------------------------------------------------------------------------

$arg  = $ARGV[0];
$arg2 = $ARGV[1];
$arg3 = $ARGV[2];
$arg4 = $ARGV[3];
#$arg5 = $ARGV[4];
$P = "orastat";
chop($PBASE = `basename $0`);
chop($toolsdir = `dirname $0`);
$| = 1;

$oh = $ENV{"ORACLE_HOME"};
$os = $ENV{"ORACLE_SID"};

chop($srvinfo = `uname -a`);

$dist_pgmr = qw(bill.border@hp.com);
chop($host = `hostname`);

$savedir = "";
if    (-e "/opt/oracle/adm/cronlog")      { $savedir = "/opt/oracle/adm/cronlog"; }
elsif (-e "/opt/oracle/admin/tools/logs") { $savedir = "/opt/oracle/admin/tools/logs"; }
##&error("Cannot find log dir") if ! $savedir;

$ENV{"ENV"} = "";
$ENV{"UNIX95"} = 1;
$ENV{"PATH"} = "$ENV{'PATH'}:/usr/sbin";     # To find nslookup

if ($oh eq "" || $os eq "")
{
  print "orastat | Env vars ORACLE_HOME and ORACLE_SID must be set\n";
  exit 1;
}

#---- Validate user/group
@z = getgrgid($));
$gname = $z[0];
chop($uname = `whoami`);
if ($gname ne "dba" && $uname ne "oracle")
{
  $homedir = (getpwuid($<))[7];
  $connect_file = "$homedir/.orastat_connect.txt";
  &msg("Effective user/group $uname/$gname Is not user=oracle or group=dba - Looking for orastat connect file: $connect_file");
  &msg("The connect file must contain 1 line with SQLPlus 'connect' syntax. Example: connect dbuserid/dbpw");
  &msg("This DB userid specified in the connect string must have the 'select any dictionary' system privilege.");

  ##system("echo ' ' | mailx -s '$P - $host/$os Non oracle/dba user' $dist_pgmr");

  #---- Look for homedir/.orastat_connect.txt
  &error("orastat Connect file ($connect_file) does not exist") if ! -e "$connect_file";
  #---- connect_file Does exist - check permission
  chop($cf_perm = `ll $connect_file | awk '{ print \$1 }'`);
  if ($cf_perm ne "-rw-------")
  {
    &msg("------------------------ Error -------------------------");
    &msg("orastat Connect file ($connect_file) has incorrect file permissions ($cf_perm)");
    &msg("File must be: you-writable, group-inaccessible and others-inaccessible (500)");
    &msg("To correct: chmod 600 $connect_file");
    &error("Exiting");
  }
  &msg("Connect file exists and permissions are OK - Reading file contents");

  foreach (`cat $connect_file | grep -v ^#`)
  {
    @words = split;
    if (uc $words[0] ne "CONNECT" || $#words > 1)
    {
      &error("The connect file can only contain non-comment lines with format: connect user/pw");
    }
    chop($cf_connect_string = $_);
  }

  ##&msg("DEBUG cf_connect_string=$cf_connect_string");

  &msg("NOTE: Although you can connect to the DB, files that are only accessible by the oracle OS ID or dba OS Group will still be inaccessible");
  ##system("echo ' ' | mailx -s '$P - $host/$os Non oracle/dba user - CF Found and read' $dist_pgmr");
  ##exit;
}

#---- Get company name
if ($srvinfo =~ /^Linux/)
{
  $compwork = `nslookup -sil $host | grep 'Name:' | awk '{ print \$2 }'`;
}
else
{
  $compwork = `nslookup $host | grep 'Name:' | awk '{ print \$2 }'`;
}
chop $compwork;
@words = split(/\./,$compwork);
$nexttolast = $#words - 1;
$company = $words[$nexttolast];

#$basetime = 1001607400;
#$nowtime = time;

#@banner = `$oh/bin/sqlplus -?`;  ### Old Method
@banner = `echo exit | $oh/bin/sqlplus /NOLOG`;
foreach $line (@banner)
{
   if ($line =~ /SQL/)
   {
      @words        = split(' ',$line);
      $oraver       = substr(${words[2]},0,5);
      $oraver_short = $words[2];
      #---- Chop the last 4 chars off (8.1.7.4.0 -> 8.1.7)
      $oraver_short =~ s/......$//g;
      $oraver_num   = $oraver_short + 0;
      last;
   }
}

if (substr($oraver,0,2) eq "3.")
{
  $_ = $oraver;
  s/3/7/;
  $oraver = $_;
}
#if (substr($oraver,0,2) lt "7.")
#{
#  $oraver = "";
#}

if ($oraver_num >= 8.1)
{
  $sqlcmd = "sp";
  $os_scmd = "sqlplus /NOLOG";
  $os_conn = "connect / as sysdba ";
}
else
{
  $sqlcmd = "sv";
  $os_scmd = "svrmgrl";
  $os_conn = "connect internal ";
}

#---- Possible override
$os_conn = $cf_connect_string if $cf_connect_string;

&msg("oraver=$oraver oraver_short=$oraver_short oraver_num=$oraver_num sqlcmd=$sqlcmd arg=$arg arg2=$arg2");


if ($srvinfo =~ /^Sun/)
{
  $bdfcmd = "df -k";
}
elsif ($srvinfo =~ /^HP-UX/)
{
  $bdfcmd = "bdf";
}
else
{
  $bdfcmd = "df -kP";
}

chop($date = `date +%Y/%m/%d-%H:%M:%S`);
print "$date $P | ORACLE_SID=$os ORACLE_HOME=$oh - $srvinfo \n";
print "$date $P | Version=$version Host=$host Company=$company\n";
##print "$date $P | pid=$$\n";

# See if it was invoked for usage
if (!$arg || $arg eq "\-\?")
{
  goto USAGE;
}

# See if this command is a subroutine
$subname = substr($arg,1);
$evalcmd = "\&run_$subname";
##print "evalcmd=$evalcmd\n";
eval "$evalcmd" ;
##print "at=$@\n";
if ($@ eq "")
{
  exit;
}

# --------------------------------------------------------------------
# -
# --------------------------------------------------------------------
if ($arg eq "-")
{
  &msg("- Instance Status (Primarily from v\$database)");

  #---- Old way - doesn't work on AIX
  # $numpmon = `ps -ef | grep 'ora_pmon_$os\$' | grep -v grep | grep -v '^\$' | wc -l`;

  #---- New way - don't care if you don't match on EOL
  # $numpmon = `ps -ef | grep 'ora_pmon_$os' | grep -v grep | grep -v '^\$' | wc -l`;

  #---- New logic for ASM
  if ($os =~ /^\+ASM/)
  {
    $numpmon = `ps -ef | grep 'asm_pmon_$os' | grep -v grep | grep -v '^\$' | wc -l`;
    &msg("This is an ASM instance - DB status of STARTED is normal");
  }
  else
  {
    $numpmon = `ps -ef | grep 'ora_pmon_$os' | grep -v grep | grep -v '^\$' | wc -l`;
  }

  # Clean up numpmon
  chomp ($numpmon);
  $numpmon =~ s/ //g;

  if ($numpmon < 1)
  {
    &msg("UX Process [ora/asm]_pmon_$os is Not Running (numpmon=$numpmon)");
    exit 1;
  }

  $shu = "?";
  $sta = "?";
  $ver = "?";
  $sts = "?";
  $ins = "?";
  $par = "?";
  $log = "?";
  $cha = "?";
  $scn = "?";
  $asc = "?";
  $cfm = "?";
  $dbid = "?";
  $dbnm = "?";

  # Determine Oracle version

  $sqlstmt = 'select \'V\', banner from v\$version;';
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @lines = split("\n");
    @words = split;
    $verb  = $words[0];
    if ($verb eq "ORA-01034:")
    {
      $sta = "(Oracle Not Available)";
    }
    elsif ($verb =~ "ORA-01012")
    {
      print "";
    }
    elsif ($verb =~ "ORA-")
    {
      print "\nERROR: ${lines[0]}\n\n";
    }
    if ($verb eq "V")
    {
      if (/10g/)
      {
        $ver = $words[7];
        if ($_ =~ /64b/)
        {
          $ver = $ver . " (64-bit)";
        }
      }
      if (/11g/)
      {
        $ver = $words[7];
        if ($_ =~ /64b/)
        {
          $ver = $ver . " (64-bit)";
        }
      }
      if (substr($words[1],0,7) eq "Oracle8")
      {
        $ver = $words[5];
        $z = substr($ver,length($ver)-1,1);
        if ($z eq "," || $_ =~ /64bit/)
        {
          chop($ver) if $z eq ",";
          $ver = $ver . " (64-bit)";
        }
      }
      if (substr($words[1],0,7) eq "Oracle9")
      {
        $ver = $words[5];
        $z = substr($ver,length($ver)-1,1);
        if ($z eq "," || $_ =~ /64bit/)
        {
          chop($ver) if $z eq ",";
          $ver = $ver . " (64-bit)";
        }
      }
      elsif (substr($words[1],0,7) eq "Oracle8" &&
          $words[5] eq "Production")
      {
        $ver = $words[3];
      }
      elsif (substr($words[1],0,7) eq "Oracle7")
      {
        $ver = $words[4];
      }
    }
  }

  if (substr($ver,0,1) eq "7")
  {
    $sqlstmt = 'select \'X\',
      name, checkpoint_change#, archive_change# from v\$database;
    select \'A\', value from v\$instance where key = \'RESTRICTED MODE\';
    select \'B\', value from v\$instance where key = \'SHUTDOWN PENDING\';
    select \'Z\', value from v\$nls_parameters where parameter = \'NLS_CHARACTERSET\';
    select \'C\',
      to_char(to_date(value,\'J\'),\'YYYY/MM/DD\'),
      sysdate - to_date(value,\'J\')
      from v\$instance where key = \'STARTUP TIME - JULIAN\';';
  }
  elsif ($ver =~ /^8.0/)
  {
    $sqlstmt = 'select \'X\',
    instance_name,
    to_char(startup_time,\'YYYY/MM/DD-HH24:MI:SS\') startup_time,
    version,
    status,
    shutdown_pending,
    nvl(parallel,\'?\'),
    logins,
    sysdate - startup_time
    from v\$instance;
    select \'W\', CHECKPOINT_CHANGE#, ARCHIVE_CHANGE#, CONTROLFILE_TYPE, dbid, name from v\$database;
    select \'Z\', value from  v\$nls_parameters where parameter = \'NLS_CHARACTERSET\';';
  }
  else
  {
    $sqlstmt = 'select \'X\',
    instance_name,
    to_char(startup_time,\'YYYY/MM/DD-HH24:MI:SS\') startup_time,
    version,
    status,
    shutdown_pending,
    nvl(parallel,\'?\'),
    logins,
    sysdate - startup_time,
    thread#
    from v\$instance;
    select \'J\',
      force_logging from v\$database;
    select \'V\',
      to_char(created,\'YYYY/MM/DD-HH24:MI:SS\'),
      log_mode from v\$database;
    select \'W\', CHECKPOINT_CHANGE#, ARCHIVE_CHANGE#, CONTROLFILE_TYPE, dbid, name, open_mode from v\$database;
    select \'Q\',
      database_role,
      flashback_on,
      translate(platform_name,\' \',\'_\')
    from v\$database;
    select \'Z\', value from  v\$nls_parameters where parameter = \'NLS_CHARACTERSET\';
    select \'ArcLogCnt\', count(*) from  v\$archived_log where completion_time > (sysdate - 1/24) and name like \'/%\';
    select \'RLID\', resetlogs_id from v\$database_incarnation where status = \'CURRENT\';
    select \'Flag-ASM\', count(*) from v\$datafile where name like \'+%\';
    select distinct \'Flag-InASM\', instance_name from v\$asm_client;
    ';
  }

  ##print "sqlstmt=$sqlstmt\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/ && $_ !~ /ORA-00904/ && $_ !~ /ORA-00942/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "ORA-01034:")
    {
      $sta = "(Oracle Not Available)";
    }
    if ($verb eq "ArcLogCnt")
    {
      $arclog_cnt = $words[1];
    }
    if ($verb eq "Flag-InASM")
    {
      $asm_instance = $words[1];
    }
    if ($verb eq "Flag-ASM")
    {
      $asmcount = $words[1];
      if ($asmcount > 0) { $asm_on = "YES"; }
      else               { $asm_on = "NO"; }
    }
    if ($verb eq "J")
    {
      $forclog = $words[1];
    }
    if ($verb eq "RLID")
    {
      $rlid = $words[1];
    }
    if ($verb eq "V")
    {
      $created = $words[1];
      $logmode = $words[2];
    }
    if ($verb eq "Q")
    {
      $dbrole      = $words[1];
      $flashback   = $words[2];
      $dbplatform  = $words[3];
    }
    if ($verb eq "W")
    {
      $scn = $words[1];
      $asc = $words[2];
      $cfm = $words[3];
      $dbid= $words[4];
      $dbnm= $words[5];
      $open= $words[6] . $words[7];
    }
    if ($verb eq "X")
    {
      if (substr($ver,0,1) eq "7")
      {
        $ins = $words[1];
        $scn = $words[2];
        $asc = $words[3];
        $dbid= $words[4];
        $sta = "(PMON Running)";
      }
      else
      {
        $ins = $words[1];
        $sts = $words[2];
        $sta = $words[4];
        $shu = $words[5];
        $par = $words[6];
        $log = $words[7];
        $upt = $words[8];
        $upt = $upt * 24;
        $thread = $words[9];
      }
    }

    if ($verb eq "A")
    {
      if ($words[1] eq "0") { $log = "ALLOWED"; }
                       else { $log = "RESTRICTED"; }
    }

    if ($verb eq "B")
    {
      if ($words[1] eq "0") { $shu = "NO"; }
                       else { $shu = "YES"; }
    }

    if ($verb eq "C")
    {
       $sts = $words[1];
       $upt = $words[2];
       if ($sta eq "?" && $upt ne "?")
       {
          $sta="NOMOUNT";
       }
       elsif ($sta eq "(PMON Running)" && $upt ne "?")
       {
          $sta = "MOUNTED";
          $sqlstmt = "select \'P\',user_id from dba_users;";
	  &oraSQL($sqlstmt);
	  foreach (@oraSQLout)
          {
             ##print;
             @words = split;
             $verb    = $words[0];
             if ($verb =~ "ORA-")
             {
                print "$verb\n";
             }
             if ($verb eq "P")
             {
                $sta = "OPEN";
             }
          }
        }
        #$cur_time=`date +%H:%M:%S`;
        open(PS, "ps -ef -oetime,comm |grep ora_pmon|") || die "can't run ps - $!";
        while(<PS>)
        {
           ##print;
           @words = split;
           $etime = $words[0];
           $comm  = $words[1];
           if ($comm eq "ora_pmon_$os")
           {
              @words = split ("-",$etime);
              $etime_0 = $words[0];
              $etime_1 = $words[1];
              if ($etime_1 eq "")
              {
                 @words = split (":",$etime_0);
		 if (${words[2]} eq "")
		  {
                     $hours = 0;
                     $mins = $words[0];
                     $secs = $words[1];
                     $upt = $hours + ($mins/60) + ($secs/60/60);
		  }
		 elsif (${words[1]} eq "" && ${words[2]} eq "")
		  {
                     $hours = 0;
                     $mins = 0;
                     $secs = $words[0];
                     $upt = $hours + ($mins/60) + ($secs/60/60);
		  }
                 else
		  {
                     $hours = $words[0];
                     $mins = $words[1];
                     $secs = $words[2];
                     $upt = $hours + ($mins/60) + ($secs/60/60);
		  }
              }
              else
              {
                 $days = $etime_0;
                 @words = split (":",$etime_1);
                 $hours = $words[0];
                 $mins = $words[1];
                 $secs = $words[2];
                 $upt = ($days * 24) + $hours + ($mins/60) + ($secs/60/60);
              }
           }
        }
        close(PS);
    }
    if ($verb eq "Z")
    {
      $cha = $words[1];
    }
  }

  #---- See if password function is on in DEFAULT profile
  #DEFAULT          PASSWORD       PASSWORD_VERIFY_FUNCTION     VERIFY_FUNCTION
  chop($dbpw_work = `$PBASE -pr | grep '^DEFAULT' | grep 'PASSWORD_VERIFY_FUNCTION' | awk '{ print \$NF}'`);
  if    ($dbpw_work eq "NULL") { $dbpw = "OFF"; }
  elsif ($dbpw_work =~ /\_/)   { $dbpw = "ON"; }
  else                         { $dbpw = "?"; }

  if ($upt > 0)
  {
    $daysup = sprintf("%.2f",($upt / 24));
  }

  print "orastat | Status:       $sta\n";
  print "orastat | OpenMode:     $open\n" if $open ne "";
  print "orastat | Started:      $sts\n";
  print "orastat | HoursUp:      $upt\n";
  print "orastat | DaysUp:       $daysup\n";
  print "orastat | Instance:     $ins\n";
  print "orastat | OracleVer:    $ver\n";
  print "orastat | ShutdownMode: $shu\n";
  print "orastat | Parallel:     $par\n";
  print "orastat | Thread#:      $thread\n" if $thread;
  print "orastat | Logins:       $log\n";
  print "orastat | Characterset: $cha\n";
  print "orastat | CkptSCN:      $scn\n";
  print "orastat | ArcSCN:       $asc\n";
  print "orastat | CF Mode:      $cfm\n";
  print "orastat | DBID:         $dbid\n";
  print "orastat | DBName:       $dbnm\n";
  print "orastat | Created:      $created\n" if $created;
  print "orastat | LogMode:      $logmode\n" if $logmode;
  print "orastat | ForceLogging: $forclog\n" if $forclog;
  print "orastat | ResetlogsID:  $rlid\n"    if $rlid;
  print "orastat | DBRole:       $dbrole\n"     if $dbrole;
  print "orastat | FlashbackOn:  $flashback\n"  if $flashback;
  print "orastat | DBPlatform:   $dbplatform\n" if $dbplatform;
  print "orastat | ComplexDBPW:  $dbpw (Function: $dbpw_work)\n" if $dbpw;
  print "orastat | ASM:          $asm_on\n" if $asm_on;
  print "orastat | ASMInstance:  $asm_instance\n" if $asm_instance;
  print "orastat | ArcLogRate:   $arclog_cnt (Local Arclogs Per Hour)\n" if $arclog_cnt ne "";

  exit;
}

# --------------------------------------------------------------------
# -ht
# --------------------------------------------------------------------
if ($arg eq "-ht")
{
  $rows = 0;

  if ($arg2 ne "")
  {
    $touches_threshold = $arg2;
  }
  else
  {
    $touches_threshold = 1000;
  }

  &msg("-ht: Hot Tables - Having Block Touches > $touches_threshold");
  $sqlstmt = "
    select \'Y\',
      name, value
      from v\\\$parameter
      where
      name in (\'db_block_size\');
    SELECT
      \'X\',
      bh.obj,
      ob.owner,
      ob.object_name,
      ob.object_type,
      COUNT(2) buffers,
      sum(bh.tch) sum
    FROM
      x\\\$bh bh,
      dba_objects ob
    where
      bh.obj = ob.object_id
    GROUP BY
      bh.obj,
      ob.owner,
      ob.object_name,
      ob.object_type
    HAVING
      sum(tch) > $touches_threshold
    order by
      7 desc;";

  print "\n";
  print "Name                                     Type          Buffers   Size(MB)    Touches\n";
  print "---------------------------------------- ---------- ---------- ---------- ----------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "Y")
    {
      $blocksize = $words[1];
      ##print "blocksize=$blocksize\n";
      next;
    }

    if ($verb eq "X")
    {
      $objid = "";

      $objid   = shift @words;
      $owner   = shift @words;
      $obj     = shift @words;
      $type    = shift @words;
      $buffers = shift @words;
      $touches = shift @words;

      $objname = "$owner.$obj";
      $objsize = int(($buffers * $blocksize) / 1000000);

      printf "%-40s %-10s %10s %10s %10s\n",$objname,$type,$buffers,$objsize,$touches;
      $rows++;
    }
  }
  print "\n";
  &msg("$rows Row(s) found");
  exit;
}

# --------------------------------------------------------------------
# -hd
# --------------------------------------------------------------------
if ($arg eq "-hd")
{
  $rows = 0;

  if ($arg2 ne "")
  {
    $touches_threshold = $arg2;
  }
  else
  {
    $touches_threshold = 1000;
  }

  &msg("-hd: Hot Tables - Having Block Touches > $touches_threshold");
  $sqlstmt = "
    select \'Y\',
      name, value
      from v\\\$parameter
      where
      name in (\'db_block_size\');
    SELECT
      \'X\',
      bh.obj,
      ob.owner,
      ob.object_name,
      ob.object_type,
      df.name,
      COUNT(2) buffers,
      sum(bh.tch) sum
    FROM
      x\\\$bh bh,
      dba_objects ob,
      v\\\$datafile df
    where
      bh.obj = ob.object_id
      and bh.file# = df.file#
    GROUP BY
      bh.obj,
      ob.owner,
      ob.object_name,
      ob.object_type,
      df.name
    HAVING
      sum(tch) > $touches_threshold
    order by
      8 desc;";

  print "\n";
  print "Name                                               Type       Datafile                                           Buffers    Size(MB)   Touches\n";
  print "-------------------------------------------------- ---------- -------------------------------------------------- ---------- ---------- ----------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "Y")
    {
      $blocksize = $words[1];
      ##print "blocksize=$blocksize\n";
      next;
    }

    if ($verb eq "X")
    {
      $objid = "";

      $objid   = shift @words;
      $owner   = shift @words;
      $obj     = shift @words;
      $type    = shift @words;
      $dfname = shift @words;
      $buffers = shift @words;
      $touches = shift @words;

      $objname = "$owner.$obj";
      $objsize = int(($buffers * $blocksize) / 1000000);

      printf "%-50s %-10s %-50s %10s %10s %10s\n",$objname,$type,$dfname,$buffers,$objsize,$touches;
      $rows++;
    }
  }
  print "\n";
  &msg("$rows Row(s) found");
  exit;
}

# --------------------------------------------------------------------
# -nf
# --------------------------------------------------------------------
if ($arg eq "-nf")
{
  #
  # Look for tables where the next extent will not fit in the largest
  #   freespace hole for their tablespace
  #
  &msg("Looking for tables whose next extent will not fit");
  $sqlstmt = '
    select
      \'X\',
      segment_owner,
      segment_name,
      segment_type,
      ts1,
      max_chunk,
      chunk_needed
    from
      (select
	 tablespace_name ts1,
	 max(bytes) as max_chunk
       from dba_free_space
       group by tablespace_name),
      (select
	 owner segment_owner,
	 segment_name,
	 segment_type,
	 tablespace_name ts2,
	 next_extent chunk_needed
	 from dba_segments)
    where
      ts1=ts2
      and chunk_needed> max_chunk;
    order by
      2,3
  ';
  &oraSQL($sqlstmt);

  $foundtbls = 0;
  $titleflag = 0;

  foreach (@oraSQLout)
  {
    ##print;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $owner           = $words[1];
      $sname           = $words[2];
      $stype           = $words[3];
      $ts              = $words[4];
      $ts_max_free     = $words[5];
      $s_next_size     = $words[6];

      $foundtbls++;
      $tbl = $owner . "." . $sname;

      if (!$titleflag)
      {
	print "\n";
	print "                          Object(s) Whose Next_Extent Will Not Fit\n";
	print "\n";
	print "Segment                                  Segment Tablespace               Object Next  TS Max Contig.\n";
	print "Name                                     Type    Name                     Extent Size      Free Space\n";
	print "---------------------------------------- ------- -------------------- --------------- ---------------\n";
	$titleflag = 1;
      }
      printf "%-40s %-7s %-20s %15i %15i\n",$tbl,$stype,$ts,$s_next_size,$ts_max_free;
      ##$newnext = int ( $ts_max_free / 1000000 );
      ##$newnext-- if $newnext > 2;
      $newnext = $ts_max_free - 1024;
      $newnext = 1024 if $newnext <= 0;
      $ddl .= "ALTER $stype $tbl STORAGE ( NEXT ${newnext} PCTINCREASE 0 );\n";
    }
  }
  print "\n";
  if ($foundtbls == 0)
  {
    &msg("No objects found whose NEXT EXTENT will not fit");
  }
  else
  {
    &msg("Found $foundtbls object(s) whose NEXT EXTENT will not fit");
    &msg("DDL to correct:\n");
    print "$ddl \n";
  }
  exit;

}

# --------------------------------------------------------------------
sub run_rg
# --------------------------------------------------------------------
{
  &msg("-rg: Contents of DBA_REGISTRY - DB Component Status");
  $sqlstmt = "
    SELECT
      'X',
      nvl(version,\'?\'),
      nvl(status,\'?\'),
      comp_name
    FROM
      dba_registry;
    order by
      1, 3
      ";

  print "\n";
  print "DB Component                             Version      Status\n";
  print "---------------------------------------- ------------ ------------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $rows++;
      $rg_component = "";

      $rg_version   = shift @words;
      $rg_status    = shift @words;
      foreach (@words)
      {
	$rg_component .= "$_ ";
      }

      printf "%-40s %-12s %-12s\n",$rg_component,$rg_version,$rg_status;
    }
  }
  exit;
}

# --------------------------------------------------------------------
sub run_mt
# --------------------------------------------------------------------
{
  &msg("-mt: MTS Overview");

  $sqlstmt = '
    SELECT
      \'X\',
      type,
      paddr,
      queued,
      decode(totalq,0,0,wait / totalq) avg_wait
    FROM
      v\$queue;
    order by
      2, 3
      ';

  print "\n";
  &msg("MTS Statistics");
  print "\n";

  print "Queue        PAddr            Ses Q'd  Avg Wait\n";
  print "------------ ---------------- -------- --------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $rows++;

      $mt_ptype    = shift @words;
      $mt_paddr    = shift @words;
      $mt_queued   = shift @words;
      $mt_avgwait  = sprintf("%.2f",shift @words);

      $mt_paddr = "" if $mt_paddr eq "00";

      printf "%-12s %-16s %8s %8s\n",$mt_ptype, $mt_paddr, $mt_queued, $mt_avgwait;
    }
  }

  $sqlstmt = '
    SELECT
      \'X\',
      d.name,
      s.username,
      c.status,
      c.queue,
      s.sid,
      s.serial#
    from
      v\$circuit c,
      v\$dispatcher d,
      v\$session s
    where
      c.dispatcher = d.paddr and
      c.saddr = s.saddr
    order by
      d.name,
      s.username;
  ';

  print "\n";
  &msg("Connected MTS Users");
  print "\n";

  print "Disp     User             Session# Serial#  Status       Queue\n";
  print "-------- ---------------- -------- -------- ------------ -----------------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $rows++;

      $mt_dname    = shift @words;
      $mt_user     = shift @words;
      $mt_status   = shift @words;
      $mt_queue    = shift @words;
      $mt_sid      = shift @words;
      $mt_ser      = shift @words;

      printf "%-8s %-16s %8s %8s %-12s %-12s\n",$mt_dname, $mt_user,  $mt_sid, $mt_ser, $mt_status, $mt_queue;
    }
  }

  $sqlstmt = '
    SELECT
      \'X\',
      name,
      busy / (busy + idle) * 100
    from
      v\$shared_server
    order by
      2;
  ';

  print "\n";
  &msg("Shared Server Process Utilization");
  print "\n";

  print "Server       Busy\n";
  print "-------- --------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $rows++;

      $mt_sname    = shift @words;
      $mt_busy     = sprintf("%.2f",shift @words);

      printf "%-8s %8s%%\n",$mt_sname, $mt_busy;
    }
  }

  $sqlstmt = '
    SELECT
      \'X\',
      name,
      busy / (busy + idle) * 100
    from
      v\$dispatcher
    order by
      2;
  ';

  print "\n";
  &msg("Dispatcher Process Utilization");
  print "\n";

  print "Server       Busy\n";
  print "-------- --------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $rows++;

      $mt_sname    = shift @words;
      $mt_busy     = sprintf("%.2f",shift @words);

      printf "%-8s %8s%%\n",$mt_sname, $mt_busy;
    }
  }

  exit;
}

# --------------------------------------------------------------------
sub run_zr
# --------------------------------------------------------------------
{
  &msg("-zr: Contents of DBA_REGISTRY - DB Component Status");
  $sqlstmt = "
    SELECT
      'X',
      ts,
      prihost,
      prisid,
      sbyhost,
      sbysid,
      tool
    FROM
      dbamon.standby_rebuild
    order by
      1, 2, 3;
      ";

  print "\n";
  print "DB Component                             Version      Status\n";
  print "---------------------------------------- ------------ ------------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $rows++;

      $ts      = shift @words;
      $prihost = shift @words;
      $prisid  = shift @words;
      $sbyhost = shift @words;
      $sbysid  = shift @words;
      $tool    = shift @words;

      printf "%s %-12s %-12s %-12s %-12s %s\n",$ts, $prihost, $prisid, $sbyhost, $sbysid, $tool;
    }
  }
}

# --------------------------------------------------------------------
sub run_bo
# --------------------------------------------------------------------
{
  &msg("-bo: Buffer Cache Overview (From v\$bh) - Note that this command will run for awhile (arg2=$arg2)");

  #---- #1 get blocksize
  $sqlstmt = 'select \'X\', value from v\$parameter where name = \'db_block_size\';';
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $db_block_size = shift @words;
    }
  }

  #---- #2 get blocksize
  $sqlstmt = 'select \'X\', count(*) from v\$bh;';
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $buffer_total_size = shift @words;
    }
  }
  ##print "bts=$buffer_total_size\n";

  #---- #1 group by status
  $sqlstmt = "
    SELECT
      'X',
      status,
      count(*)
    FROM
      v\\\$bh
    group by
      'X',
      status
    order by
      3 desc;
      ";

  print "\n";
  &msg("-bo: Block Status");
  print "\n";
  print "Block Status        Block Count       Size (mB)      % of Total\n";
  print "--------------- --------------- --------------- ---------------\n";

  &oraSQL($sqlstmt);

  $total_count = 0;

  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $rows++;

      $bh_status   = shift @words;
      $bh_count    = shift @words;

      $bh_mb  = ($db_block_size * $bh_count) / 1000000;
      $bh_pct = ($bh_count / $buffer_total_size) * 100 if $buffer_total_size > 0;

      printf "%-15s %15s %15.2f %15.2f%%\n","Status=$bh_status",$bh_count,$bh_mb,$bh_pct;

      $total_count += $bh_count;
    }
  }
  print "=============== =============== ===============\n";
  $total_mb = ($db_block_size * $total_count) / 1000000;
  printf "%-15s %15s %15.2f\n","Total:",$total_count, $total_mb;

  return if $arg2 eq "1";

  #---- #2 group by dirty
  $sqlstmt = "
    SELECT
      'X',
      dirty,
      count(*)
    FROM
      v\\\$bh
    group by
      'X',
      dirty
    order by
      3 desc;
      ";

  print "\n";
  &msg("-bo: Dirty Blocks");
  print "\n";
  print "Buffer Dirty        Block Count       Size (mB)      % of Total\n";
  print "--------------- --------------- --------------- ---------------\n";

  &oraSQL($sqlstmt);

  $total_count = 0;

  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $rows++;

      $bh_status   = shift @words;
      $bh_count    = shift @words;

      $bh_mb  = ($db_block_size * $bh_count) / 1000000;
      $bh_pct = ($bh_count / $buffer_total_size) * 100 if $buffer_total_size > 0;

      printf "%-15s %15s %15.2f %15.2f%%\n","Dirty=$bh_status",$bh_count,$bh_mb,$bh_pct;

      $total_count += $bh_count;
    }
  }
  print "=============== =============== ===============\n";
  $total_mb = ($db_block_size * $total_count) / 1000000;
  printf "%-15s %15s %15.2f\n","Total:",$total_count, $total_mb;

  #---- #3 group by temp
  $sqlstmt = "
    SELECT
      'X',
      temp,
      count(*)
    FROM
      v\\\$bh
    group by
      'X',
      temp
    order by
      3 desc;
      ";

  print "\n";
  &msg("-bo: Temp Blocks");
  print "\n";
  print "Buffer TEMP         Block Count       Size (mB)      % of Total\n";
  print "--------------- --------------- --------------- ---------------\n";

  &oraSQL($sqlstmt);

  $total_count = 0;

  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $rows++;

      $bh_status   = shift @words;
      $bh_count    = shift @words;

      $bh_mb  = ($db_block_size * $bh_count) / 1000000;
      $bh_pct = ($bh_count / $buffer_total_size) * 100 if $buffer_total_size > 0;

      printf "%-15s %15s %15.2f %15.2f%%\n","Temp=$bh_status",$bh_count,$bh_mb,$bh_pct;

      $total_count += $bh_count;
    }
  }
  print "=============== =============== ===============\n";
  $total_mb = ($db_block_size * $total_count) / 1000000;
  printf "%-15s %15s %15.2f\n","Total:",$total_count, $total_mb;

  #---- #4 group by TS
  $sqlstmt = "
    SELECT
      'X',
      ts.name,
      count(*)
    FROM
      v\\\$bh bh,
      v\\\$tablespace ts
    where
      bh.ts# = ts.ts#
    group by
      'X',
      ts.name
    order by
      3 desc;
      ";

  print "\n";
  &msg("-bo: Blocks By Tablespace - Top 10");
  print "\n";
  print "Tablespace          Block Count       Size (mB)      % of Total\n";
  print "--------------- --------------- --------------- ---------------\n";

  &oraSQL($sqlstmt);

  $total_count = 0;
  $rows = 0;

  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $rows++;

      $bh_ts       = shift @words;
      $bh_count    = shift @words;

      $bh_mb  = ($db_block_size * $bh_count) / 1000000;
      $bh_pct = ($bh_count / $buffer_total_size) * 100 if $buffer_total_size > 0;

      printf "%-15s %15s %15.2f %15.2f%%\n",$bh_ts,$bh_count,$bh_mb,$bh_pct;

      $total_count += $bh_count;

      last if $rows >= 10;
    }
  }
  print "=============== =============== ===============\n";
  $total_mb = ($db_block_size * $total_count) / 1000000;
  printf "%-15s %15s %15.2f\n","Total:",$total_count, $total_mb;


  #---- #5 group by DF
  $sqlstmt = "
    SELECT
      'X',
      df.name,
      count(*)
    FROM
      v\\\$bh bh,
      v\\\$datafile df
    where
      bh.file# = df.file#
    group by
      'X',
      df.name
    order by
      3 desc;
      ";

  print "\n";
  &msg("-bo: Blocks By Datafile - Top 10");
  print "\n";
  print "Datafile                                                    Block Count       Size (mB)      % of Total\n";
  print "------------------------------------------------------- --------------- --------------- ---------------\n";

  &oraSQL($sqlstmt);

  $total_count = 0;
  $rows = 0;

  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $rows++;

      $bh_df       = shift @words;
      $bh_count    = shift @words;

      $bh_mb  = ($db_block_size * $bh_count) / 1000000;
      $bh_pct = ($bh_count / $buffer_total_size) * 100 if $buffer_total_size > 0;

      printf "%-55s %15s %15.2f %15.2f%%\n",$bh_df,$bh_count,$bh_mb,$bh_pct;

      $total_count += $bh_count;

      last if $rows >= 10;
    }
  }
  print "======================================================= =============== ===============\n";
  $total_mb = ($db_block_size * $total_count) / 1000000;
  printf "%-55s %15s %15.2f\n","Total:",$total_count, $total_mb;


  #---- #6 group by object
  $sqlstmt = "
    SELECT
      'X',
      ob.owner,
      ob.object_name,
      translate(ob.object_type,\' \',\'_\'),
      count(*)
    FROM
      v\\\$bh bh,
      dba_objects ob
    where
      bh.objd = ob.object_id
    group by
      'X',
      ob.owner,
      ob.object_name,
      ob.object_type
    order by
      5 desc;
      ";

  print "\n";
  &msg("-bo: Blocks By Object - Top 25");
  print "\n";
  print "Object                                                      Block Count       Size (mB)      % of Total\n";
  print "------------------------------------------------------- --------------- --------------- ---------------\n";

  &oraSQL($sqlstmt);

  $total_count = 0;
  $rows = 0;

  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $rows++;

      $bh_owner    = shift @words;
      $bh_name     = shift @words;
      $bh_type     = shift @words;
      $bh_count    = shift @words;

      $this_object = "$bh_owner.$bh_name ($bh_type)";

      $bh_mb  = ($db_block_size * $bh_count) / 1000000;
      $bh_pct = ($bh_count / $buffer_total_size) * 100 if $buffer_total_size > 0;

      printf "%-55s %15s %15.2f %15.2f%%\n",$this_object,$bh_count,$bh_mb,$bh_pct;

      $total_count += $bh_count;

      last if $rows >= 25;
    }
  }
  print "======================================================= =============== ===============\n";
  $total_mb = ($db_block_size * $total_count) / 1000000;
  printf "%-55s %15s %15.2f\n","Total:",$total_count, $total_mb;

  exit;
}

# --------------------------------------------------------------------
sub run_rf
# --------------------------------------------------------------------
{
  &msg("-rf: Contents of V\$RECOVER_FILE - DB Recovery Required Start Time");
  &msg("Querying V\$RECOVER_FILE");

  $rows = 0;
  $min_time_c = "?";
  $min_time_n = "?";

  $sqlstmt = "
    SELECT
      \'X\',
      min(to_char(time,'YYYY/MM/DD-HH24:MI:SS'))
    FROM
      v\\\$recover_file;
      ";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $min_time_c = shift @words;
      $min_time_n = &timeToNum($min_time_c);

      $rows++;
    }
  }
  &msg("Minimum TIME Value From V\$RECOVER_FILE (Character): $min_time_c");
  &msg("Minimum TIME Value From V\$RECOVER_FILE (Numeric):   $min_time_n");
  exit;
}

# --------------------------------------------------------------------
# -sy
# --------------------------------------------------------------------
if ($arg eq "-sy")
{
  &msg("-sy: All Granted System Privileges");

  $rows = 0;

  $sqlstmt = "
    SELECT
      \'X\',
      grantee,
      translate(privilege,\' \',\'_\'),
      admin_option
    FROM
      dba_sys_privs
    order by
      2, 3;";

  print "\n";
  print "Grantee                  System Privilege                         Adm\n";
  print "------------------------ ---------------------------------------- ---\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $grantee = shift @words;
      $priv    = shift @words;
      $adm     = shift @words;

      printf "%-24s %-40s %-3s\n",$grantee,$priv,$adm;
      $rows++;
    }
  }
  print "\n";
  &msg("$rows Rows found");
  exit;
}

# --------------------------------------------------------------------
# -dd
# --------------------------------------------------------------------
if ($arg eq "-dd")
{
  &msg("-dd: Create DDL - Object=$arg3.$arg4 Type=$arg2");

  if ($oraver_num >= 9)
  {
    &msg("orastat -dd Will only work with Oracle 9i");
    exit;
  }

  $arg2_uc = uc $arg2;
  $arg3_uc = uc $arg3;
  $arg4_uc = uc $arg4;

  $rows = 0;
  print "\n";

  $sqlstmt = "
    SELECT
      \'X\',
      dbms_metadata.get_ddl ('$arg2_uc','$arg4_uc','$arg3_uc')
    FROM
      dual;";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    print if $printflag && /^ /;
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $printflag = 1;
      $rows++;
    }
  }
  print "\n";
  &msg("Object $arg3.$arg4 type=$arg2 Not Found") if !$rows;
  exit;
}

# --------------------------------------------------------------------
# -du
# --------------------------------------------------------------------
if ($arg eq "-du")
{
  &msg("-du: Datafile With Unrecoverable Changes");

  $rows = 0;

  $sqlstmt = "
    SELECT
      \'X\',
      df.name,
      df.unrecoverable_change#,
      to_char(unrecoverable_time,\'YYYY/MM/DD-HH24:MI:SS\')
    FROM
      v\\\$datafile df
    where
      df.unrecoverable_change# > 0
    order by
      2;";

  print "\n";
  print "Name                                               Unrec. Change#  Unrec. Date\n";
  print "-------------------------------------------------- --------------- -------------------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $objid = "";

      $dfname   = shift @words;
      $chgnum   = shift @words;
      $chgdat   = shift @words;

      printf "%-50s %-15s %-19s\n",$dfname,$chgnum,$chgdat;
      $rows++;

      $maxdat = $chgdat if $chgdat gt $maxdat;
    }
  }
  print "\n";
  &msg("$rows Datafile(s) with unrecoverable changes found");
  &msg("Most recent UNRECOVERABLE_TIME value found: $maxdat");
  exit;
}

# --------------------------------------------------------------------
# -cb
# --------------------------------------------------------------------
if ($arg eq "-cb")
{
  &msg("-cb: Controlfile Backup");

  if (-w "/var/opt/oracle/tmp/")
  {
    $cb_binary = "/var/opt/oracle/tmp/orastat_cfbinary_${os}_${$}.dbf";
    ##system("rm -f /var/opt/oracle/tmp/orastat_cfbinary_${os}_*.dbf 2>/dev/null");
  }
  else
  {
    $cb_binary = "/tmp/orastat_cfbinary_${os}_${$}.dbf";
    ##system("rm -f /tmp/orastat_cfbinary_${os}_*.dbf 2>/dev/null");
  }

  &msg("Binary CF backup filename cb_binary=$cb_binary");

  $sqlstmt = "
    SELECT
      \'X\',
      spid
    FROM
      v\\\$process a, v\\\$session b
    WHERE
      a.addr=b.paddr
      AND b.sid = (select min(sid) from v\\\$mystat) ;
    alter system checkpoint;
    alter database backup controlfile to trace;
    alter database backup controlfile to \'$cb_binary\';
    select
      \'Z\',
      value
    from v\\\$parameter where name = \'user_dump_dest\';
  ";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $spid   = shift @words;
    }
    if ($verb eq "Z")
    {
      $udd    = shift @words;
    }
  }

  $lcos = lc $os;

  $bug_cb_trace  = "$oh/rdbms/log/ora_${spid}.trc";
  $bug2_cb_trace = "$oh/rdbms/log/${lcos}_ora_${spid}.trc";

  # See if we are running 9i
  chop($oraver = `orastat - | grep OracleVer | awk '{ print \$4 }'`);

  if ($srvinfo =~ /^Sun/)
  {
    $cb_trace = "$udd/${lcos}_ora_${spid}.trc";
  }
  elsif ($srvinfo =~ /^Linux/ && $oraver =~ /^8/)
  {
    $cb_trace = "$udd/ora_${spid}.trc";
  }
  elsif ($srvinfo =~ /^Linux/ && $oraver =~ /^9/)
  {
    $cb_trace = "$udd/${lcos}_ora_${spid}.trc";
  }
  elsif ($oraver =~ /^9.0.1/)
  {
    $cb_trace = "$udd/ora_${spid}_${lcos}.trc";
  }
  elsif ($oraver =~ /^9/)
  {
    $cb_trace = "$udd/${lcos}_ora_${spid}.trc";
  }
  elsif ($oraver =~ /^11/)
  {
    $cb_trace = "$udd/${os}_ora_${spid}.trc";
  }
  elsif ($oraver =~ /^1/)
  {
    $cb_trace = "$udd/${lcos}_ora_${spid}.trc";
  }
  elsif ($oraver =~ /^8.1.5/)
  {
    $cb_trace = "$udd/ora_${spid}.trc";
  }
  elsif ($oraver =~ /^8.1/)
  {
    $cb_trace = "$udd/ora_${spid}_$lcos.trc";
  }
  else
  {
    $cb_trace = "$udd/ora_${spid}.trc";
  }

  ##&msg("spid=$spid udd=$udd cb_trace=$cb_trace");

  print "\n";

  if (-e $cb_trace)
  {
    print "Controlfile_Trace_Backup was successful to: $cb_trace\n";
    system("ls -l $cb_trace 2>&1");
  }
  elsif (-e $bug_cb_trace)
  {
    $cb_trace = $bug_cb_trace;
    &msg("ORACLE Bug Encountered - Trace file written to rdbms/log");
    print "Controlfile_Trace_Backup was successful to: $cb_trace\n";
    system("ls -l $cb_trace 2>&1");
  }
  elsif (-e $bug2_cb_trace)
  {
    $cb_trace = $bug2_cb_trace;
    &msg("ORACLE Bug Encountered - Trace file written to rdbms/log");
    print "Controlfile_Trace_Backup was successful to: $cb_trace\n";
    system("ls -l $cb_trace 2>&1");
  }
  else
  {
    &msg("ERROR: I could not find the trace backup file - cb_trace=$cb_trace");
    system("echo ' ' | mailx -s '$P - $host/$os Could not find trace CF backup' EMAIL_DUMMY ");
  }

  print "\n";

  if (-e $cb_binary)
  {
    print "Controlfile_Binary_Backup was successful to: $cb_binary\n";
    system("ls -l $cb_binary 2>&1");
  }
  else
  {
    &msg("ERROR: I could not find the binary backup file: $cb_binary");
    system("echo ' ' | mailx -s '$P - $host/$os Could not find binary CF backup' EMAIL_DUMMY ");
  }

  &msg("Done");
  exit;
}


# --------------------------------------------------------------------
# -un
# --------------------------------------------------------------------
if ($arg eq "-un")
{
  $rows = 0;

  &msg("-un: UNDO Statistics");
  $sqlstmt = '
    SELECT
      \'X\',
      to_char(begin_time,\'YYYY/MM/DD-HH24:MI:SS\') ,
      to_char(end_time,\'YYYY/MM/DD-HH24:MI:SS\') ,
      undotsn,
      undoblks,
      txncount,
      maxconcurrency,
      ssolderrcnt,
      nospaceerrcnt,
      tuned_undoretention
    FROM
      v\$undostat
    where
      begin_time >= sysdate - 1
    order by
      2, 4;';

  ##print "sqlstmt=$sqlstmt\n";
  print "\n";
  print "Start               End                     Blks       Trans.     Max. Conc. SS Old     No Spc     Tuned Undo\n";
  print "Time                Time                TS# Used       Count      Trans.     Errors     Errors     Retention\n";
  print "------------------- ------------------- --- ---------- ---------- ---------- ---------- ---------- ----------\n";

  $spaceflag = 0;
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $begin_time = shift @words;
      $end_time   = shift @words;
      $undotsn    = shift @words;
      $undoblks   = shift @words;
      $txncount   = shift @words;
      $maxcon     = shift @words;
      $ssolerr    = shift @words;
      $nospaceerr = shift @words;
      $undoret    = shift @words;

      ##print "sf=$spaceflag\n";

      $spaceflag = 1 if $nospaceerr gt "0";

      printf "%19s %19s %3s %10s %10s %10s %10s %10s %10s \n",
	$begin_time ,
	$end_time  ,
	$undotsn  ,
	$undoblks   ,
	$txncount  ,
	$maxcon     ,
	$ssolerr    ,
	$nospaceerr ,
	$undoret;

      $rows++;
      $total += $count;
    }
  }
  print "\n";

  if ($spaceflag == 1)
  {
    &msg("Since there were >=1 'SPACE ERROR' events, you need to add space to the UNDO TS");
  }
  else
  {
    &msg("Since there were no 'SPACE ERROR' events, you do not need to add space to the UNDO TS");
  }

  exit;
}

# --------------------------------------------------------------------
# -unl
# --------------------------------------------------------------------
if ($arg eq "-unl")
{
  $rows = 0;
  $onegig = 1024*1024*1024;

  #SQL> desc v$undostat
  #  Name                                      Null?    Type
  #    ----------------------------------------- -------- ----------------------------
  # BEGIN_TIME                                         DATE
  # END_TIME                                           DATE
  # UNDOTSN                                            NUMBER
  # UNDOBLKS                                           NUMBER
  # TXNCOUNT                                           NUMBER
  # MAXQUERYLEN                                        NUMBER
  # MAXQUERYID                                         VARCHAR2(13)
  # MAXCONCURRENCY                                     NUMBER
  # - UNXPSTEALCNT                                       NUMBER
  # - UNXPBLKRELCNT                                      NUMBER
  # - UNXPBLKREUCNT                                      NUMBER
  # - EXPSTEALCNT                                        NUMBER
  # - EXPBLKRELCNT                                       NUMBER
  # - EXPBLKREUCNT                                       NUMBER
  # SSOLDERRCNT                                        NUMBER
  # NOSPACEERRCNT                                      NUMBER
  # ACTIVEBLKS                                         NUMBER
  # UNEXPIREDBLKS                                      NUMBER
  # EXPIREDBLKS                                        NUMBER
  # TUNED_UNDORETENTION                                NUMBER

    &msg("-un: UNDO Statistics (Long)");
  $sqlstmt = '
    select \'Y\',
      value
      from v\$parameter
      where
      name in (\'db_block_size\');
    SELECT
      \'X\',
      to_char(begin_time,\'YYYY/MM/DD-HH24:MI:SS\') ,
      to_char(end_time,\'YYYY/MM/DD-HH24:MI:SS\') ,
      undotsn,
      undoblks,
      txncount,
      maxconcurrency,
      ssolderrcnt,
      nospaceerrcnt,
      tuned_undoretention,
      maxquerylen,
      nvl(maxqueryid,\'?\'),
      nvl(activeblks, -1),
      nvl(expiredblks,-1),
      nvl(unexpiredblks,-1),
      nvl(EXPSTEALCNT, -1) ,
      nvl(EXPBLKRELCNT, -1),
      nvl(EXPBLKREUCNT, -1),
      nvl(UNXPSTEALCNT, -1) ,
      nvl(UNXPBLKRELCNT, -1),
      nvl(UNXPBLKREUCNT, -1)
    FROM
      v\$undostat
    where
      begin_time >= sysdate - 1
    order by
      2, 4;';

  ##print "sqlstmt=$sqlstmt\n";

  $spaceflag = 0;
  $c = 9999;
  $mr_nonzero_ts = "(None)";
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    #print;
    print if /^ORA/;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "Y")
    {
      $block_size = shift @words;
      ## &msg("block_size=$block_size");
    }

    if ($verb eq "X")
    {
      $begin_time = shift @words;
      $end_time   = shift @words;
      $undotsn    = shift @words;
      $undoblks   = shift @words;
      $txncount   = shift @words;
      $maxcon     = shift @words;
      $ssolerr    = shift @words;
      $nospaceerr = shift @words;
      $undoret    = shift @words;
      $maxquerylen  = shift @words;
      $maxqueryid   = shift @words;
      $activeblks   = shift @words;
      $expblks      = shift @words;
      $unexpblks    = shift @words;
      $expstealcnt    = shift @words;
      $expblkrelcnt    = shift @words;
      $expblkreucnt    = shift @words;
      $unexpstealcnt    = shift @words;
      $unexpblkrelcnt    = shift @words;
      $unexpblkreucnt    = shift @words;

      ##print "sf=$spaceflag\n";

      $endts = substr($end_time,11,8);
      $maxqlenhrs = $maxquerylen / 3600;

      $spaceflag = 1 if $nospaceerr gt "0";

      $activeblks_gb = ($activeblks * $block_size) / $onegig;
      $expblks_gb = ($expblks * $block_size) / $onegig;
      $unexpblks_gb = ($unexpblks * $block_size) / $onegig;
      $undoblks_gb = ($undoblks * $block_size) / $onegig;

      $undoret_hrs = $undoret / 3600;

      if ( $expstealcnt > 0
          || $expblkrelcnt > 0
          || $expblkreucnt > 0
          || $unexpstealcnt > 0
          || $unexpblkrelcnt > 0
          || $unexpblkreucnt > 0) { $mr_nonzero_ts = $begin_time; }
      if (++$c >= 28)
      {
        print "\n";
	print "UNDOSTAT            UNDOSTAT     +------------Undo (GB)------------+ Total    Max              Tuned    +------MaxQuery----+ +-Expired Stealing-+ +-UnExp. Stealing--+\n";
	print "Start               End          Total    Total    Total    Consumed Trans.   Conc +-Errors--+ Undo     Length               Attmpt Blocks Blocks Attmpt Blocks Blocks\n";
	print "TS                  Time     TS# Active   Expired  UnExp.   ThisSamp Count    Tran SSold NoSpc Ret Hrs. Hours  SQLID         Count  Stolen Reused Count  Stolen Reused\n";
	print "------------------- -------- --- -------- -------- -------- -------- -------- ---- ----- ----- -------- ------ ------------- ------ ------ ------ ------ ------ ------\n";
        $c = 0;
      }

      printf "%19s %8s %3s %8.2f %8.2f %8.2f %8.2f %8s %4s %5s %5s %8.2f %6.2f %-13s %6s %6s %6s %6s %6s %6s\n",
	$begin_time ,
	$endts  ,
	$undotsn  ,
        $activeblks_gb ,
        $expblks_gb,
        $unexpblks_gb,
	$undoblks_gb   ,
	$txncount  ,
	$maxcon     ,
	$ssolerr    ,
	$nospaceerr ,
	$undoret_hrs,
        $maxqlenhrs,
        $maxqueryid,
        $expstealcnt,
        $expblkrelcnt,
        $expblkreucnt,
        $unexpstealcnt,
        $unexpblkrelcnt,
        $unexpblkreucnt
      ;

      $rows++;
      $total += $count;
    }
  }
  print "\n";
  &msg("Most recent sample with non-zero value for any of the rightmost 6 'steal' columns: $mr_nonzero_ts");

  exit;
}

# BEGIN_TIME                                         DATE
# END_TIME                                           DATE
# UNDOTSN                                            NUMBER
# UNDOBLKS                                           NUMBER
# TXNCOUNT                                           NUMBER
# MAXQUERYLEN                                        NUMBER
# MAXQUERYID                                         VARCHAR2(13)
# MAXCONCURRENCY                                     NUMBER
# UNXPSTEALCNT                                       NUMBER
# UNXPBLKRELCNT                                      NUMBER
# UNXPBLKREUCNT                                      NUMBER
# EXPSTEALCNT                                        NUMBER
# EXPBLKRELCNT                                       NUMBER
# EXPBLKREUCNT                                       NUMBER
# SSOLDERRCNT                                        NUMBER
# NOSPACEERRCNT                                      NUMBER
# ACTIVEBLKS                                         NUMBER
# UNEXPIREDBLKS                                      NUMBER
# EXPIREDBLKS                                        NUMBER
# TUNED_UNDORETENTION                                NUMBER


# --------------------------------------------------------------------
# -dh
# --------------------------------------------------------------------
if ($arg eq "-dh")
{
  $rows = 0;

  &msg("NOTE: !!! orastat -dn Runs MUCH FASTER");

  &msg("-dh: Datafile 'USED' High-Water-Mark");
  &msg("(This command will run for awhile on databases with many datafiles)");
  $sqlstmt = '
    SELECT
      \'X\',
      a.tablespace_name,
      a.file_name,
      a.bytes,
      (b.maximum+c.blocks-1)*d.db_block_size highwater
    from
      dba_data_files a,
      (select
        file_id,
        max(block_id) maximum
       from dba_extents
       group by file_id) b,
      dba_extents c,
      (select
        value db_block_size
        from v\$parameter
        where name=\'db_block_size\') d
    where
      a.file_id  = b.file_id
      and c.file_id  = b.file_id
      and c.block_id = b.maximum
    order by
      a.tablespace_name,a.file_name;
  ';


  ##print "sqlstmt=$sqlstmt\n";
  print "\n";
  print "Tablespace       Datafile                                                             Size     Used HWM      Savings Resize\n";
  print "---------------- ------------------------------------------------------------ ------------ ------------ ------------ ------\n";

  $spaceflag = 0;
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $ts = shift @words;
      $dfname   = shift @words;
      $bytes    = shift @words;
      $hwm      = shift @words;

      $safe = int(($hwm + 1000000)/1000000) . "M";

      $savings = $bytes - $hwm;
      $t_savings += $savings;

      $resize_cmds .= "ALTER DATABASE DATAFILE '$dfname' RESIZE $safe ;\n";

      printf "%-16s %-60s %12s %12s %12s %6s\n",
	$ts ,
	$dfname  ,
	$bytes ,
	$hwm ,
	$savings ,
        $safe
        ;

      $rows++;
      $total += $count;
    }
  }
  print "================ ============================================================ ============ ============ ============ ======\n";
  printf "%-16s %-60s %12s %12s %12s %6s\n",
    'Total:' ,
    ''  ,
    '' ,
    '' ,
    $t_savings ,
    ''
    ;

  print "\n";

  &msg("Resize Commands:");
  print "$resize_cmds\n";

  exit;
}

# --------------------------------------------------------------------
# -dn
# --------------------------------------------------------------------
if ($arg eq "-dn")
{
  $rows = 0;
  $resize_cmd_count = 0;

  $min_mb = $arg2;
  $min_mb = 10 if ! $arg2;
  $min_bytes = $min_mb * 1000000;

  &msg("-dn: Datafile 'USED' High-Water-Mark");
  &msg("(This command will run for awhile on databases with many datafiles)");
  $sqlstmt = '
    alter session set optimizer_mode=rule;
    select \'W\',
      value
    from
    v\$parameter
    where
      name = \'db_block_size\';
    drop table DBSNMP.ORASTAT_DH_1;
    create global temporary table DBSNMP.ORASTAT_DH_1
      as
        select
          file_id,
          max(block_id + blocks) highwater_blocks
        from
          dba_extents
        group by
          file_id;
    insert into DBSNMP.ORASTAT_DH_1
        select
          file_id,
          max(block_id + blocks) highwater_blocks
        from
          dba_extents
        group by
          file_id;
    -- select * from DBSNMP.ORASTAT_DH_1;
    SELECT
      \'X\',
      a.tablespace_name,
      a.file_name,
      a.bytes,
      b.highwater_blocks
    from
      dba_data_files a,
      DBSNMP.ORASTAT_DH_1 b
    where
      a.file_id  = b.file_id
    order by
      a.tablespace_name,
      a.file_name;
    drop table DBSNMP.ORASTAT_DH_1;
  ';

  ##print "sqlstmt=$sqlstmt\n";

  print "\n";
  print "Tablespace           Datafile                                                             Size     Used HWM      Savings Resize\n";
  print "-------------------- ------------------------------------------------------------ ------------ ------------ ------------ ------\n";

  $spaceflag = 0;
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/ && !/^ORA-00942/;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "W")
    {
      $block_size = shift @words;
    }

    if ($verb eq "X")
    {
      $ts = shift @words;
      $dfname     = shift @words;
      $bytes      = shift @words;
      $hwm_blocks = shift @words;

      $hwm        = $hwm_blocks * $block_size;
      $hwm_mb     = int($hwm / 1000000);

      $bytes_mb   = int($bytes / 1000000);

      $safe = int(($hwm + 1000000)/1000000) . "M";

      $savings = $bytes - $hwm;

      $savings_mb = int($savings / 1000000);
      $t_savings += $savings;

      if ($savings > $min_bytes)
      {
        $resize_cmds .= "ALTER DATABASE DATAFILE '$dfname' RESIZE $safe  -- Datafile_Size=${bytes_mb}M Data HWM=${hwm_mb}M Savings=${savings_mb}M ; \n";
        $resize_cmd_count++;
        $t_savings_cmd += $savings;
      }

      printf "%-20s %-60s %12s %12s %12s %6s\n",
	$ts ,
	$dfname  ,
	$bytes ,
	$hwm ,
	$savings ,
        $safe
        ;

      $rows++;
      $total += $count;
    }
  }
  print "==================== ============================================================ ============ ============ ============ ======\n";
  printf "%-20s %-60s %12s %12s %12s %6s\n",
    'Total:' ,
    ''  ,
    '' ,
    '' ,
    $t_savings ,
    ''
    ;

  print "\n";

  &msg("Now, you will see syntactically correct ALTER DATAFILE commands for all");
  &msg("  datafiles which can be resized to save at least 10M per datafile.\n");

  &msg("Resize Commands:");
  print "$resize_cmds\n";

  $t_savings_mb = int($t_savings_cmd / 1000000);
  $t_savings_gb = int($t_savings_cmd / 1000000000);

  &msg("If all $resize_cmd_count ALTER DATAFILE RESIZE commands are run:");
  &msg("  Total Savings (mB): $t_savings_mb");
  &msg("  Total Savings (gB): $t_savings_gb");

  exit;
}

# --------------------------------------------------------------------
# -tm
# --------------------------------------------------------------------
if ($arg eq "-tm")
{
  $rows = 0;

  &msg("-tm: Temporary Segments");
  $sqlstmt = '
    SELECT
      \'X\',
      owner,
      segment_name,
      count(*)
    FROM
      dba_extents
    where
      segment_type = \'TEMPORARY\'
    GROUP BY
      owner,
      segment_name;';


  print "sqlstmt=$sqlstmt\n";
  print "\n";
  print "Segment Name                                  Count\n";
  print "---------------------------------------- ----------\n";

  $total = 0;
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $owner   = shift @words;
      $segment = shift @words;
      $count   = shift @words;

      $objname = "$owner.$segment";

      printf "%-40s %10s \n",$objname,$count;
      $rows++;
      $total += $count;
    }
  }
  print "======================================== ==========\n";
  printf "%-40s %10s \n","Total:",$total;
  exit;
}

# --------------------------------------------------------------------
# -bs
# --------------------------------------------------------------------
if ($arg eq "-bs")
{
  &msg("-bs: Create DDL To Take All Datafiles Out Of Backup Mode");
  $sqlstmt = '
    alter session set sort_area_size          = 100000000;
    alter session set sort_area_retained_size = 100000000;
    SELECT
      \'X\',
      df.name
    from
      v\$datafile df,
      v\$backup bk
    where
      bk.file# = df.file#
      and bk.status = \'ACTIVE\'; ';

  print "\n";
  $total = 0;
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $dfname   = shift @words;
      $cmd = "ALTER DATABASE DATAFILE '$dfname' END BACKUP;";

      print "$cmd\n";
      $total++;
    }
  }
  print "\n";
  &msg("Created $total ALTER DATABASE statements");
  exit;
}

# --------------------------------------------------------------------
# -ln
# --------------------------------------------------------------------
if ($arg eq "-ln")
{
  $rows = 0;

  &msg("-ln: DB Links");
  $sqlstmt = '
    SELECT
      \'X\',
      nvl(owner,\'(Null)\'),
      db_link,
      created,
      nvl(username,\'(Null)\'),
      host
    FROM
      dba_db_links
    order by
      2, 3 ;';

  ##print "sqlstmt=$sqlstmt\n";
  print "\n";
  print "Owner        DB Link Name         Created      User Name    Host \n";
  print "------------ -------------------- ------------ ------------ ------------------------------------------\n";

  $total = 0;
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $owner    = shift @words;
      $dblink   = shift @words;
      $created  = shift @words;
      $username = shift @words;
      $host     = shift @words;

      printf "%-12s %-20s %-12s %-12s %s\n",$owner,$dblink,$created,$username,$host;
      $rows++;
    }
  }
  print "\n";
  &msg("Found $rows DB Links");
  exit;
}

# --------------------------------------------------------------------
# -bm_old
# --------------------------------------------------------------------
if ($arg eq "-bm_old")
{
  $rows = 0;

  &msg("-bm: Tablespaces/Datafiles in Backup Mode");

  &msg("NOTE: Tablespaces displayed here have AT LEAST ONE datafile in Backup Mode, but");
  &msg("      not neccessarily all datafiles are in Backup Mode");

  $sqlstmt = '
    alter session set sort_area_size          = 100000000;
    alter session set sort_area_retained_size = 100000000;
    select
      \'X\',
      ts.name,
      df.name
    from
      v\$backup ba,
      v\$datafile df,
      v\$tablespace ts
    where
      ba.status = \'ACTIVE\'
      and ba.file# = df.file#
      and df.ts# = ts.ts#
    order by
      2, 3;';

  ##print "sqlstmt=$sqlstmt\n";
  print "\n";
  print "    Tablespace           Datafile \n";
  print "    -------------------- ----------------------------------------\n";

  $total = 0;
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /ORA-/;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $ts = shift @words;
      $df = shift @words;

      printf "TS: %-20s %40s \n",$ts,$df;
      $total++;
    }
  }
  print "\n";
  &msg("Total of $total Datafiles in Backup Mode");
  exit;
}

# --------------------------------------------------------------------
# -bm
# --------------------------------------------------------------------
if ($arg eq "-bm")
{
  $rows = 0;

  &msg("-bm: Tablespaces/Datafiles in Backup Mode");

  &msg("NOTE: Tablespaces displayed here have AT LEAST ONE 1 datafile in Backup Mode, but");
  &msg("      not neccessarily all datafiles are in Backup Mode");

  $sqlstmt = '
    alter session set sort_area_size          = 100000000;
    alter session set sort_area_retained_size = 100000000;
    select
      \'X\',
      ts.name,
      df.name
    from
      v\$backup ba,
      v\$datafile df,
      v\$tablespace ts
    where
      ba.status = \'ACTIVE\'
      and ba.file# = df.file#
      and df.ts# = ts.ts#
    order by
      2, 3;';

  ##print "sqlstmt=$sqlstmt\n";
  print "\n";
  print "    Tablespace           Datafile \n";
  print "    -------------------- ----------------------------------------\n";

  BM_WHILE: while (1 == 1)
  {
    $total = 0;

    &oraSQL($sqlstmt);
    foreach (@oraSQLout)
    {
      ##print;

      if (/ORA-00235/)
      {
        &msg("Controlfile is busy (00235) - Sleeping 30 then retrying");
        sleep 30;
        next BM_WHILE;
      }

      print if /ORA-/;

      @words   = split();
      $verb    = shift @words;

      if ($verb eq "X")
      {
	$ts = shift @words;
	$df = shift @words;

	printf "TS: %-20s %40s \n",$ts,$df;
	$total++;
      }
    }

    last;  #---- If we are here then leave while forever
  }

  print "\n";
  &msg("Total of $total Datafiles in Backup Mode");
  exit;
}

# --------------------------------------------------------------------
# -tr
# --------------------------------------------------------------------
if ($arg eq "-tr")
{
  $rows = 0;

  &msg("-tr: Active Transactions");
  $sqlstmt = '
    select \'Y\',
      value
      from v\$parameter
      where
      name in (\'db_block_size\');
    SELECT
      \'X\',
      tr.addr,
      tr.start_time,
      tr.status,
      tr.used_ublk,
      tr.used_urec,
      se.sid,
      se.serial#,
      rn.name,
      se.username
    FROM
      v\$transaction tr,
      v\$session se,
      v\$rollname rn
    WHERE
      tr.xidusn = rn.usn
      and tr.ses_addr = se.saddr
    ORDER BY
      6;';


  ##print "sqlstmt=$sqlstmt\n";
  print "\n";
  print "Session,Serial#  Start Timestamp   Status   UndoBlks UndoRecs   UndoMB RBS Name     DB User\n";
  print "---------------- ----------------- -------- -------- -------- -------- ------------ ------------\n";

  $total = 0;
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "Y")
    {
      $blksize = shift @words;
    }

    if ($verb eq "X")
    {
      $addr   = shift @words;
      $start  = shift @words;
      $start .= "-" . shift @words;
      $status = shift @words;
      $ublk   = shift @words;
      $urec   = shift @words;
      $sid    = shift @words;
      $ser    = shift @words;
      $rbs    = shift @words;
      $user   = shift @words;

      $undo_mb = ($ublk * $blksize) / 1000000;
      $undo_mb = sprintf("%.2f",$undo_mb);

      $sidser = "$sid,$ser";
      $addr = "";

      printf "%-16s %-17s %-8s %8s %8s %8s %-12s %-12s\n",$sidser, $start, $status, $ublk, $urec, $undo_mb, $rbs, $user;
      $rows++;
      $totalrecs += $urec;
      $totalblks += $ublk;
      $totalmb   += $undo_mb;
    }
  }
  print "================ ================= ======== ======== ======== ======== ============ ============\n";
  $totalmb = sprintf("%.2f",$totalmb);
  printf "%-16s %-17s %-8s %8s %8s %8s \n\n","Total:", "", "", $totalblks, $totalrecs, $totalmb;
  &msg("Found $rows transactions");

  exit;
}

# --------------------------------------------------------------------
# -avo
# --------------------------------------------------------------------
if ($arg eq "-avo")
{
  $days = $arg2;
  $days = 30 if $days eq "";

  if ($arg3 eq "H")
  {
    $timestring = "YYYY/MM/DD-HH24";
    $num = 60;
  }
  else
  {
    $arg3 = "D";
    $timestring = "YYYY/MM/DD";
    $num = 1440;
  }

  $days = $arg2;
  $days = 30 if $days eq "";

  $rows = 0;

  &msg("-av: Archivelog Volume - For the last $days days - Mode=$arg3");
  # 2.96 and 3.00 changed line:    and name like '%archv01%'
  $sqlstmt = "
    select
      \'X\',
      to_char(completion_time,\'$timestring\'),
      sum(blocks * block_size),
      count(*)
    from
      v\\\$archived_log
    where
      completion_time > sysdate - $days
      and name like '%archv0%'
    group by
      to_char(completion_time,\'$timestring\');";

  print "\n";
  print "              Archive    Archive    REDO Rate \n";
  print "Timestamp     Data (MB)  Log Count  (MB/Min)* \n";
  print "------------- ---------- ---------- ----------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $ts      = shift @words;
      $size    = int((shift @words) / 1000000);
      $count   = shift @words;
      $mbmin   = int($size / $num);

      printf "%-13s %10s %10s %10s\n",$ts,$size,$count,$mbmin;
      $rows++;
      $total_size  += $size;
      $total_count += $count;
      $total_mbmin += $mbmin;
    }
  }

  # Average line
  $ts = "(Average)";
  $avg_size  = int($total_size  / $rows);
  $avg_count = int($total_count / $rows);
  $avg_mbmin = int($total_mbmin / $rows);

  print "------------- ---------- ---------- ----------\n";
  printf "%-13s %10s %10s %10s\n",$ts,$avg_size,$avg_count,$avg_mbmin;

  # Total line
  $ts = "(Total)";
  $tot_size  = $total_size  ;
  $tot_count = $total_count ;
  $tot_mbmin = $total_mbmin ;
  printf "%-13s %10s %10s %10s\n",$ts,$tot_size,$tot_count,$tot_mbmin;

  print "\n";
  &msg("$rows Row(s) found - *: Average of a 24 hour period");
  exit;
}

# --------------------------------------------------------------------
# -la
# --------------------------------------------------------------------
if ($arg eq "-la")
{
  &msg("-la: Latch Details - Where GETS>1000000 And MISSES>100");
  $sqlstmt = '
    select \'X\', GETS,
        MISSES,
        round(((GETS-MISSES)*100) / GETS , 2),
        IMMEDIATE_GETS,
        IMMEDIATE_MISSES,
        sleeps,
        spin_gets,
        addr,
        latch#,
        name
    from    v\$latch
    where MISSES > 0 and gets > 0
    --where   GETS > 1000000
    --and     MISSES > 100
    order   by ((GETS-MISSES) / GETS) desc;';

  print "Latch Name                                                           Gets         Misses    Immed. Gets  Immed. Misses         Sleeps      Spin Gets Get Hit%\n";
  print "---------------------------------------------------------- -------------- -------------- -------------- -------------- -------------- -------------- --------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    #print;
    print if /^ORA/;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $gets    = shift @words;
      $misses  = shift @words;
      $hitrat  = shift @words;
      $immgets = shift @words;
      $immmiss = shift @words;
      $sleeps  = shift @words;
      $spingets= shift @words;
      $latchnum= shift @words;
      $addr    = shift @words;
      $name    = "";
      foreach (@words)
      {
	$name .= "$_ ";
      }

      $nameaddr = "$name / $latchnum / $addr";
      printf "%-58s %14s %14s %14s %14s %14s %14s %7.2f%%\n",$nameaddr,$gets,$misses,$immgets,$immmiss,$sleeps,$spingets,$hitrat;
    }
  }
  exit;
}


# --------------------------------------------------------------------
# -ap
# --------------------------------------------------------------------
if ($arg eq "-ap")
{
  &msg("-ap: Archiver Processes");
  $sqlstmt = '
    select \'X\',
      process,
      status,
      log_sequence,
      state
    from v\$archive_processes
    order by 2;';

  print "Process  Status   Log Seq. State\n";
  print "-------- -------- -------- --------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    #print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $process = shift @words;
      $status  = shift @words;
      $logseq  = shift @words;
      $state   = shift @words;
      printf "%-8s %-8s %8s %-8s\n",$process,$status,$logseq,$state;
    }
  }
  exit;
}


# --------------------------------------------------------------------
# -ua
# --------------------------------------------------------------------
if ($arg eq "-ua")
{
  &msg("-ua: Users that need to be altered - Default TS=SYSTEM or Temp TS=SYSTEM");
  $sqlstmt = '
    select \'X\',
      username,
      default_tablespace,
      temporary_tablespace
    from
      dba_users
    where
      temporary_tablespace = \'SYSTEM\' or
      default_tablespace = \'SYSTEM\'
      and username not in ( \'SYSTEM\', \'SYS\', \'DBSNMP \', \'OUTLN \')
    order by 2;';

  print "\n";
  print "Userid       Dflt. TS Temp TS \n";
  print "------------ -------- --------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    #print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $user = shift @words;
      $dflt = shift @words;
      $temp = shift @words;

      next if $user eq "DBSNMP";
      next if $user eq "OUTLN";

      if ($dflt eq "SYSTEM") { $sqltorun .= "ALTER USER $user DEFAULT   TABLESPACE USERS;\n"; }
      if ($temp eq "SYSTEM") { $sqltorun .= "ALTER USER $user TEMPORARY TABLESPACE TEMP;\n"; }

      printf "%-12s %-8s %-8s \n",$user,$dflt,$temp;
    }
  }

  print "\n";
  &msg("SQL To alter these users:");
  print "\n";
  print "$sqltorun\n";
  exit;
}


# --------------------------------------------------------------------
# -pb
# --------------------------------------------------------------------
if ($arg eq "-pb")
{
  &msg("-pb: Performance: db_block_buffer Hit Ratio RIGHT NOW");

  #---- Create uniq string
  chop($thread = `orastat - | grep 'Thread#:' | head -1 | awk '{ print \$NF }'`);
  $uniq = "_${os}_T$thread";
  &msg("DEBUG uniq=$uniq");

  #---- Erase old spool file
  system("rm /tmp/orastat_pb$uniq.lst 2>/dev/null");

  &msg("A 20 second sample will be taken now");
  $sqlstmt = "
    spool /tmp/orastat_pb$uniq.lst
    set echo on
    drop table bhm_t$uniq;
    create table bhm_t$uniq
    (sample_date date,
     pr1 number,
     pr2 number,
     delta_pr number,
     cg1 number,
     cg2 number,
     delta_cg number,
     bg1 number,
     bg2 number,
     delta_bg number,
     cum_ratio number,
     delta_ratio number);

    CREATE OR REPLACE procedure bhm_p
    (sample_rate number, iterations number)
    as

    pr1 number;
    pr2 number;
    delta_pr number;
    cg1 number;
    cg2 number;
    delta_cg number;
    bg1 number;
    bg2 number;
    delta_bg number;

    procedure  wait (sample_rate number)
    is

    now        date;
    end_time   date;

    begin
      end_time := sysdate + sample_rate/(24*60*60);
      loop
      now := sysdate;
      if now > end_time then
	return;
      end if;
      end loop;
    end;

    begin

    select pr.value,
	   cg.value,
	   bg.value
      into pr1, cg1, bg1
      from v\\\$sysstat pr, v\\\$sysstat bg, v\\\$sysstat cg
     where pr.name = \'physical reads\'
       and bg.name = \'db block gets\'
       and cg.name = \'consistent gets\';

    insert into bhm_t$uniq
       (sample_date,pr1,cg1,bg2,cum_ratio)
       values
       (sysdate,pr1,cg1,bg1,round((1-(pr1/(bg1+cg1)))*100,2));

    wait (sample_rate);

    for i in 1 .. iterations loop

    pr2 := pr1;
    cg2 := cg1;
    bg2 := bg1;

    select pr.value,
	   cg.value,
	   bg.value
      into pr1, cg1, bg1
      from v\\\$sysstat pr, v\\\$sysstat bg, v\\\$sysstat cg
     where pr.name = \'physical reads\'
       and bg.name = \'db block gets\'
       and cg.name = \'consistent gets\';

    delta_pr := pr1-pr2;
    delta_cg := cg1-cg2;
    delta_bg := bg1-bg2;

    insert into bhm_t$uniq
       values
       (sysdate, pr1, pr2, delta_pr,
		 cg1, cg2, delta_cg,
		 bg1, bg2, delta_bg,
		 round((1-(pr1/(bg1+cg1)))*100,2),
		 round((1-(delta_pr/(delta_bg+delta_cg)))*100,2));
    commit;

    wait (sample_rate);
    end loop;
    end;
/

   -- Execute samples - 10 samples of 2 seconds
   execute bhm_p (5, 4);
   -- Run query of results
   alter session set nls_date_format=\'mm/dd/yy:hh24:mi:ss\';
   set linesize 5000;
   select \'X\',
pr1 ,
pr2 ,
delta_pr ,
cg1 ,
cg2 ,
delta_cg ,
bg1 ,
bg2 ,
delta_bg ,
cum_ratio ,
delta_ratio
     from bhm_t$uniq
     order by sample_date;
   -- Drop objects
   drop table bhm_t$uniq;
   drop procedure bhm_p;
  ";

  &oraSQL($sqlstmt);
  $ratio = "?";
  foreach (@oraSQLout)
  {
    ##print;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $ratio  = $words[10];
    }
  }
  printf "\nCurrent_db_block_buffer_Hit_Ratio: %-8s\n",$ratio;
  exit;
}

# --------------------------------------------------------------------
# -au
# --------------------------------------------------------------------
if ($arg eq "-au")
{
  &msg("-au: Audit Parameters");
  $sqlstmt = 'select \'X\',
    name, value, \'()\', description from v\$parameter
    where name like \'%aud%\' order by 2;';

  print "Parm                                     Value                               Desc.\n";
  print "---------------------------------------- ----------------------------------- ------------------------------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    @words  = split();
    $verb   = $words[0];
    $name   = $words[1];
    $value  = $words[2];
    $verb2  = $words[3];

    $ndx    = index($_,"()");
    $desc   = substr($_,$ndx+3,40);

    if ($verb eq "X")
    {
      printf "%-40s %-35s %-20s\n",$name,$value,$desc;
    }
  }

  &msg("Audit - What is being audited:");

  $sql = "
    prompt DBA_STMT_AUDIT_OPTS - SQL Statements being audited
     select * from SYS.DBA_STMT_AUDIT_OPTS order by audit_option;
    prompt DBA_PRIV_AUDIT_OPTS - Privileges Statements being audited
     select * from SYS.DBA_PRIV_AUDIT_OPTS order by privilege;
    prompt DBA_OBJ_AUDIT_OPTS - Objects being audited
     select * from SYS.DBA_OBJ_AUDIT_OPTS order by owner, object_name, object_type;
  ";
  &oraSQL($sql);
  foreach (@oraSQLout)
  {
    print;
  }

  exit;
}

# --------------------------------------------------------------------
# -ab
# --------------------------------------------------------------------
if ($arg eq "-ab")
{
  &msg("-ab: Archive Log RMAN Backups - Listed Chronologically");
  if ($arg2 ne "")
  {
    $where = "and r.sequence# = $arg2";
    &msg("For Archive Log #$arg2");
  }
  else
  {
    $where = "";
  }

  $sqlstmt = "
    select
      \'X\',
      r.thread#,
      r.sequence#,
      r.blocks*r.block_size archive_size,
      to_char(r.first_time,\'YYYY/MM/DD-HH24:MI:SS\') first_time,
      to_char(r.next_time,\'YYYY/MM/DD-HH24:MI:SS\') next_time,
      (sysdate - r.next_time)*24 archive_age_hrs,
      s.backup_type,
      to_char(s.completion_time,\'YYYY/MM/DD-HH24:MI:SS\'),
      (sysdate - s.completion_time)*24 backup_age_hrs,
      s.elapsed_seconds
    from
      v\\\$backup_redolog r,
      v\\\$backup_set s
    where
      r.set_stamp = s.set_stamp and
      r.set_count = s.set_count
      $where order by 5;
  ";
  ##print "sqlstmt=$sqlstmt\n";

  print "\n";
  print "Arc Thread \n";
  print "  Sequence       Size Redo Start Time     Redo End Time       ArcAge Backup End Time     BckAge BckTim\n";
  print "---------- ---------- ------------------- ------------------- ------ ------------------- ------ ------ \n";

  &oraSQL($sqlstmt);
  $arccount = 0;
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words  = split();
    $verb   = $words[0];
    if ($verb eq "X")
    {
      $thread     = $words[1];
      $seq        = $words[2];
      $size       = $words[3];
      $redostart  = $words[4];
      $redoend    = $words[5];
      $arcage     = $words[6];
      #$bcktype    = $words[7];
      $bckend     = $words[8];
      $bckage     = $words[9];
      $bckelapsed = $words[10];

      printf "%-1s %8s %10s %19s %19s %6.2f %19s %6.2f %6.0f \n",$thread,$seq,$size,$redostart,$redoend,$arcage,$bckend,$bckage,$bckelapsed;
      $arccount++;
    }
  }
  print "\n";
  &msg("$arccount Archive Log Backup(s) Listed");
  exit;
}



# --------------------------------------------------------------------
# -cp
# --------------------------------------------------------------------
if ($arg eq "-cp")
{
  &msg("-cp: Active Parameters (from v\$parameter)");
  print "Parm                                     Value                               Desc.\n";
  print "---------------------------------------- ----------------------------------- ------------------------------\n";

  $sqlstmt = 'select \'X\', name, value, \'()\', description from v\$parameter order by 2;';
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    @words  = split();
    $verb   = $words[0];
    $name   = $words[1];
    $value  = $words[2];
    $verb2  = $words[3];

    $ndx    = index($_,"()");
    $desc   = substr($_,$ndx+3,40);

    if ($verb eq "X")
    {
      printf "%-40s %-35s %-20s\n",$name,$value,$desc;
    }
  }
  exit;
}

# --------------------------------------------------------------------
# -bd
# --------------------------------------------------------------------
sub run_bd
{
  $rows = 0;

  &msg("-bd: Datafiles Backup Mode Status");

  $sqlstmt = '
    alter session set sort_area_size          = 100000000;
    alter session set sort_area_retained_size = 100000000;
    select
      \'X\',
      ts.name,
      df.name,
      translate(ba.status,\' \',\'_\')
    from
      v\$backup ba,
      v\$datafile df,
      v\$tablespace ts
    where
      ba.file# = df.file#
      and df.ts# = ts.ts#
    order by
      2, 3;';

  ##print "sqlstmt=$sqlstmt\n";
  print "\n";
  print "    Tablespace           Datafile \n";
  print "    -------------------- ----------------------------------------\n";

  $total = 0;
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    @words   = split();
    $verb    = shift @words;

    if ($verb eq "X")
    {
      $ts = shift @words;
      $df = shift @words;
      $st = shift @words;

      printf "BackupStatus: %-15s TS: %-20s DF: %-40s %-15s\n",$st,$ts,$df;
      $total++;
    }
  }
  print "\n";
  &msg("Total of $total Datafiles found in v\$backup ");
}

# --------------------------------------------------------------------
# -bc
# --------------------------------------------------------------------
sub run_bc
{
  &msg("-bc: Buffer Contents");

  chop($blocksize = `orastat -cp | grep block_size | awk '{ print \$2 }'`);
  &msg("blocksize=$blocksize");
  &msg("Only objects with >= 1.0 Meg in a pool will be displayed");

  &bcRun9;

  sub bcRun9
  {
    $tot = 0;

    #---- New way
    $bc_query = "select
      decode(pd.bp_id,
               1,'KEEP',
               2,'RECYCLE',
               3,'DEFAULT',
               4,'2K-SUBCACHE',
               5,'4K-SUBCACHE',
               6,'8K-SUBCACHE',
               7,'16K-SUBCACHE',
               8,'32K-SUBCACHE',
      'UNKNOWN') subcache,
      bh.owner#,
      bh.object_name,
      bh.blocks
    from
      x\\\$kcbwds ds,
      x\\\$kcbwbpd pd,
      (select /*+ use_hash(x) */
         set_ds,
         o.name object_name,
         o.owner#,
         count(*) BLOCKS
       from
         obj\\\$ o,
         x\\\$bh x
       where
         o.dataobj# = x.obj
         and x.state !=0
         --and x.state !=0 and o.owner# !=0
       group by
         set_ds,o.name, o.owner#) bh
    where
      ds.set_id >= pd.bp_lo_sid
      and ds.set_id <= pd.bp_hi_sid
      and pd.bp_size != 0
      and ds.addr=bh.set_ds";

    $sqlstmt = "
    drop table orastat_bc;
    create global temporary table orastat_bc as $bc_query;
    insert into orastat_bc $bc_query;
    --
    select count(*) from orastat_bc;
    select * from orastat_bc;
    select
      'X',
      bc.subcache,
      us.username,
      bc.object_name,
      sum(bc.blocks)
    from
      orastat_bc bc,
      dba_users us
    where
      bc.owner# = us.user_id
    group by
      bc.subcache,
      us.username,
      bc.object_name
    order by
      2, 5 desc;
    ";

    print "\n";
    print "Pool     Object                                     Tot-Blocks      Tot-Meg\n";
    print "-------- ---------------------------------------- ------------ ------------\n";
    &oraSQL($sqlstmt);
    foreach (@oraSQLout)
    {
      #print;
      #print if /^ORA/;
      @words  = split();
      $verb    = $words[0];
      $pool    = $words[1];
      $owner   = $words[2];
      $table   = $words[3];
      $blocks  = $words[4];

      $tbl = "$owner.$table";
      $meg = sprintf("%.2f",($blocks * $blocksize) / (1024*1024));

      next if $meg < 1.0;

      if ($verb eq "X")
      {
	printf "%-8s %-40s %12s %12s\n",$pool,,$tbl,$blocks,$meg;
	$tot += $blocks;
        $totmeg += $meg;
      }
    }
    print "======== ======================================== ============ ============\n";
    printf "%-8s %-40s %12s %12s\n","Total:","(These Objects)",$tot,$totmeg;
  }
}

# --------------------------------------------------------------------
# -bc
# --------------------------------------------------------------------
if ($arg eq "-bcold")
{
  &msg("-bc: Buffer Contents (only works in Oracle 8i+)");

  $gtot = 0;

  $bp = "DEFAULT"; &bcRun;
  $bp = "KEEP";    &bcRun;
  $bp = "RECYCLE"; &bcRun;

  print "\n";
  &msg("Total Blocks (All Buffers): $gtot");

  sub bcRun
  {
    print "\n";
    &msg("Buffer Pool: $bp");
    $tot = 0;
    $sqlstmt = "
      create or replace view v\\\$buffer_pool_lo_hi_bnum as
      select name ,
      min(START_BUF#) lo_bnum,
      max(END_BUF#) hi_bnum,
      max(END_BUF#)-min(START_BUF#) buffers
      from v\\\$buffer_pool v, x\\\$kcbwds s
      where (LO_SETID=SET_ID or HI_SETID=SET_ID) and buffers > 0
      group by name;

      select \'X\', d.owner, o.name, COUNT(buf#) BLOCKS
      from
	obj\\\$ o,
	x\\\$bh x,
	dba_objects d
      where o.dataobj# = x.obj
      and x.state != 0
      and o.owner# !=0
      and buf# >= (select lo_bnum from v\\\$buffer_pool_lo_hi_bnum where
      name = \'$bp\' and buffers > 0)
      and buf# <= (select hi_bnum from v\\\$buffer_pool_lo_hi_bnum where
      name = \'$bp\' and buffers > 0)
      and o.obj# = d.object_id
      group by d.owner, o.name
      order by 4; ";

    print "Buffer   Object                                         Blocks\n";
    print "-------- ---------------------------------------- ------------\n";
    &oraSQL($sqlstmt);
    foreach (@oraSQLout)
    {
      print if /^ORA/;
      @words  = split();
      $verb    = $words[0];
      $owner   = $words[1];
      $table   = $words[2];
      $blocks  = $words[3];

      $tbl = "$owner.$table";

      if ($verb eq "X")
      {
	printf "%-8s %-40s %12s\n",$bp,$tbl,$blocks;
	$tot += $blocks;
	$gtot += $blocks;
      }
    }
    print "======== ======================================== ============\n";
    printf "%-8s %-40s %12s\n","$bp","Total:",$tot;
  }

  exit;
}

# --------------------------------------------------------------------
# -li
# --------------------------------------------------------------------
if ($arg eq "-li")
{
  $sqlstmt = 'select \'X\',
    resource_name,
    INITIAL_ALLOCATION ,
    CURRENT_UTILIZATION ,
    MAX_UTILIZATION   ,
    LIMIT_VALUE
    from v\$resource_limit order by 2;';

  &msg("Resource Limits (from v\$resource_limit)");
  print "Resource                          Initial    Current    Maximum      Limit\n";
  print "Name                                Value      Value      Value      Value\n";
  print "------------------------------ ---------- ---------- ---------- ----------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    @words  = split();
    $verb   = $words[0];
    $name   = $words[1];
    $init   = $words[2];
    $curr   = $words[3];
    $max    = $words[4];
    $limit  = $words[5];

    if ($verb eq "X")
    {
      printf "%-30s %10s %10s %10s %10s\n",$name,$init,$curr,$max,$limit;
    }
  }
  exit;
}

# --------------------------------------------------------------------
# -ob
# --------------------------------------------------------------------
if ($arg eq "-ob")
{
  &msg("-ob: DB Objects");
  if ($arg2 ne "")
  {
    $z = uc $arg2;
    $where = "and owner = '$z'";
    &msg("For OWNER=$z");
  }

  $sqlstmt = "
select
  \'X\',
  owner,
  object_name,
  object_id,
  status,
  to_char(created,\'YYYY/MM/DD-HH24:MI:SS\'),
  to_char(last_ddl_time,\'YYYY/MM/DD-HH24:MI:SS\'),
  translate(object_type,\' \',\'_\')
from
  dba_objects
where
  owner not like \'SYS%\'
  and owner != \'PUBLIC\'  $where
order by
  2,3;";

  print "\n";
  print "Object                                   Status  ObjId-Dec Objid-Hex Created             LastDDL             ObjectType\n";
  print "---------------------------------------- ------- --------- --------- ------------------- ------------------- ----------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    @words  = split();
    $verb   = $words[0];

    if ($verb eq "X")
    {
      $owner  = $words[1];
      $name   = $words[2];
      $id     = $words[3];
      $status = $words[4];
      $credate = $words[5];
      $ddldate = $words[6];
      $type    = $words[7];

      $obj = "$owner.$name";

      printf "%-40s %-7s %-9s %-9X %s %s %s\n",$obj,$status,$id,$id,$credate,$ddldate,$type;
    }
  }
  exit;
}
# --------------------------------------------------------------------
# -ad
# --------------------------------------------------------------------
if ($arg eq "-ad")
{
  $sqlstmt = '
    select \'X\',
    DEST_ID      ,
    STATUS       ,
    BINDING      ,
    NAME_SPACE   ,
    REOPEN_SECS  ,
    TARGET       ,
    DESTINATION  ,
    to_char(FAIL_DATE,\'YYYY/MM/DD-HH24:MI:SS\') FAIL_DATE,
    sysdate - fail_date FAIL_AGO,
    FAIL_SEQUENCE,
    ERROR
    from v\$archive_dest order by 2;';

  #&msg("sqlstmt=$sqlstmt");
  &msg("Archive Destinations (from v\$archive_dest)\n");
  print "Num  Status   Binding    NameSpc  Reopen  Target   Destination/Errors\n";
  print "==== ======== ========== ======== ======= ======== ====================================\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    #print;
    print if (/^ORA/);
    @words  = split();
    $verb    = $words[0];
    $dest    = $words[1];
    $status  = $words[2];
    $binding = $words[3];
    $name    = $words[4];
    $reopen  = $words[5];
    $target  = $words[6];
    $dest2   = $words[7];
    $faildt  = $words[8];
    $failago = $words[9] * (24);
    #$failsq  = $words[10];
    $error1  = $words[11];
    $error2  = $words[12];
    $error3  = $words[13];
    $error4  = $words[14];
    $error5  = $words[15];

    $dest2   .= " " . $error1 . " " . $error2 . " " . $error3 . " " . $error4 . " " . $error5;
    $dest2   .= "\n                                                   Failed At: $faildt" if $faildt ne "0" && $faildt ne "";
    $dest2   .= "\n                                                   Failed $failago Hours Ago" if $failago ne "0" && $failago ne "";

    if ($verb eq "X")
    {
      printf "%-4s %-8s %-10s %-8s %-7s %-8s %-30s\n",
              $dest,$status,$binding,$name,$reopen,$target,$dest2;
    }
  }
  exit;
}

# --------------------------------------------------------------------
# -ws
# --------------------------------------------------------------------
if ($arg eq "-ws")
{
  &msg("-ws: Wait Statistics From v\$waitstat)");
  $sqlstmt = '
    select \'X\', count, time, class
    from v\$waitstat order by 2;';

  #&msg("sqlstmt=$sqlstmt");
  &msg("Wait Stats (from v\$waitstat)\n");
  print "Wait       Wait Time  Class\n";
  print "Count      1/100 Sec. Name\n";
  print "---------- ---------- --------------------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if (/^ORA/);
    @words  = split();
    $verb   = $words[0];
    if ($verb eq "X")
    {
      $count = $words[1];
      $time  = $words[2];
      $z = index($_,"$words[3]");
      $class = substr($_,$z);
      chop $class;
      printf "%10d %10d %-s\n",$count,$time,$class;
      $tot_count += $count;
      $tot_time  += $time;
    }
  }
  print "========== ==========\n";
  printf "%10d %10d %-s\n",$tot_count,$tot_time;
  exit;
}

# --------------------------------------------------------------------
# -ev
# --------------------------------------------------------------------
if ($arg eq "-ev")
{
  &msg("-ev: Wait Statistics From v\$system_event)");
  $sqlstmt = '
    select
      \'X\',
      translate(event,\' \',\'_\'),
      total_waits
    from v\$system_event order by 2;';

  #&msg("sqlstmt=$sqlstmt");
  print "Event                                         Count\n";
  print "---------------------------------------- ----------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if (/^ORA/);
    @words  = split();
    $verb   = $words[0];
    if ($verb eq "X")
    {
      $event = $words[1];
      $count = $words[2];
      printf "%-40s %10d \n",$event,$count;
    }
  }
  exit;
}

#--------------------------------------------------------------------
# -ub
# --------------------------------------------------------------------
if ($arg eq "-ub")
{
  $sqlstmt = '
    select \'X\', owner, sum(bytes)
    from dba_segments group by owner order by owner;';

  #&msg("sqlstmt=$sqlstmt");
  &msg("Total Object Size by Owner\n");
  print "Owner                 MBytes\n";
  print "---------------- -----------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    #print;
    print if (/^ORA/);
    @words  = split();
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $owner = $words[1];
      $bytes = $words[2];
      $mb = $bytes / 1000000;
      printf "%-16s %11.1f\n",
              $owner,$mb;
      $mb_total += $mb;
    }
  }
  print "                 ===========\n";
  printf "%-16s %11.1f\n",$null,$mb_total;
  exit;
}

#--------------------------------------------------------------------
# -ut
# --------------------------------------------------------------------
if ($arg eq "-ut")
{
  $sqlstmt = '
    select \'X\', owner, tablespace_name, sum(bytes)
    from dba_segments group by owner, tablespace_name order by 2, 3;';

  #&msg("sqlstmt=$sqlstmt");
  &msg("Total Object Size by Owner and Tablespace\n");
  print "Owner            Tablespace                MBytes\n";
  print "---------------- -------------------- -----------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    #print;
    print if (/^ORA/);
    @words  = split();
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $owner = $words[1];
      $ts    = $words[2];
      $bytes = $words[3];
      $mb = $bytes / 1000000;
      printf "%-16s %-20s %11.1f\n",
              $owner,$ts, $mb;
      $mb_total += $mb;
    }
  }
  print "                                      ===========\n";
  printf "%-16s %-20s %11.1f\n",$null,$null,$mb_total;
  exit;
}

# --------------------------------------------------------------------
# -ex
# --------------------------------------------------------------------
if ($arg eq "-ex")
{
  #$sqlstmt = '
  #  select \'X\',
  #  to_char(timestamp,\'YYYY/MM/DD-HH24:MI:SS\'),
  #  lpad(\' \',2*level) || operation || \'\' || options || \' \' || object_name
  #  from plan_table
  #  connect by prior id=parent_id
  #  start with id=1
  #  order by 2;';
  $sqlstmt = "
    set charwidth 16;
    select \'X\',
    to_char(timestamp,\'YYYY/MM/DD-HH24:MI:SS\'),
    replace(operation,   ' ','.'),
    replace(options,     ' ','.'),
    replace(object_owner,' ','.'),
    replace(object_name, ' ','.'),
    replace(object_type, ' ','.'),
    nvl(to_char(id),'.'),
    nvl(to_char(parent_id),'.')
    from plan_table
    order by 2, id;";

  #&msg("sqlstmt=$sqlstmt");
  &msg("Archive Destinations (from v\$archive_dest)\n");
  print "plan_table Explain Data\n";
  print "====================================\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    #print;
    print if (/^ORA/);
    @words  = split();
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $ts   = $words[1];
      $op   = $words[2];
      $opt  = $words[3];
      $obj  = $words[4] . '.' . $words[5];
      $typ  = $words[6];
      #print "ts=$ts op=$op opt=$opt \n";
      printf "%-s %-16s %-16s %-16s id=$words[7] parent_id=$words[8] \n", $ts, $op, $opt, $obj, $typ ;
    }
  }
  exit;
}

# --------------------------------------------------------------------
# -ph1
# --------------------------------------------------------------------
if ($arg eq "-ph1")
{
  $sqlstmt = '
    select \'X\',
    address      ,
    hash_value   ,
    buffer_gets  ,
    executions
    -- from v\$sqlarea
    from v\$sql
    where buffer_gets > 50000 and executions > 0
    order by 3;';

  #&msg("sqlstmt=$sqlstmt");
  &msg("Archive Destinations (from v\$archive_dest)\n");
  print "Address             BufGets          Execs BufGets/Exec\n";
  print "============ ============== ============== ============\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if (/^ORA/);
    @words  = split();
    $verb     = $words[0];
    $address  = $words[1];
    $bufgets  = $words[2];
    $execs    = $words[3];
    $getsexec = $bufgets / $execs if $execs > 0;

    if ($verb eq "X")
    {
     printf "%-12s %14.0f %14.0f %12.1f \n", $address,$bufgets,$execs,$getsexec;
    }
  }
  exit;
}

# --------------------------------------------------------------------
# -qs
# --------------------------------------------------------------------
if ($arg eq "-qs")
{
  $sqlstmt = '
    select
      \'Y\',
      sum(executions)
    from
      -- v\$sqlarea;
      v\$sql;
    select
      \'X\',
      command_type ,
      sum(users_executing) ,
      sum(executions)
    from
      -- v\$sqlarea
      v\$sql
    group by \'X\', command_type
    order by 4 desc;';

  #&msg("sqlstmt=$sqlstmt");
  &msg("-qs: SQL Statement Type Execution Counts Since Instance Start\n");
  print "SQL Statement Type    Executing Now     Total Executions\n";
  print "-------------------- -------------- -------------- -----\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if (/^ORA/);
    @words  = split();
    $verb     = $words[0];
    if ($verb eq "Y")
    {
      $grant_tot = $words[1];
    }
    if ($verb eq "X")
    {
      $cmd_type = $words[1];
      $exec_now = $words[2];
      $exec_tot = $words[3];
      if    ($cmd_type ==  2) { $sql_type = "INSERT"; }
      elsif ($cmd_type ==  3) { $sql_type = "SELECT"; }
      elsif ($cmd_type ==  6) { $sql_type = "UPDATE"; }
      elsif ($cmd_type ==  7) { $sql_type = "DELETE"; }
      elsif ($cmd_type ==  9) { $sql_type = "CREATE_INDEX"; }
      elsif ($cmd_type == 10) { $sql_type = "DROP_INDEX"; }
      elsif ($cmd_type == 11) { $sql_type = "ALTER_INDEX"; }
      elsif ($cmd_type == 12) { $sql_type = "DROP_INDEX"; }
      elsif ($cmd_type == 15) { $sql_type = "ALTER_TABLE"; }
      elsif ($cmd_type == 16) { $sql_type = "DROP_SEQUENCE"; }
      elsif ($cmd_type == 17) { $sql_type = "GRANT"; }
      elsif ($cmd_type == 18) { $sql_type = "REVOKE"; }
      elsif ($cmd_type == 19) { $sql_type = "CREATE_SYNONYM"; }
      elsif ($cmd_type == 26) { $sql_type = "LOCK_TABLE"; }
      elsif ($cmd_type == 28) { $sql_type = "RENAME"; }
      elsif ($cmd_type == 35) { $sql_type = "ALTER_DATABASE"; }
      elsif ($cmd_type == 39) { $sql_type = "CREATE_TABLESPACE"; }
      elsif ($cmd_type == 40) { $sql_type = "ALTER_TABLESPACE"; }
      elsif ($cmd_type == 41) { $sql_type = "DROP_TABLESPACE"; }
      elsif ($cmd_type == 42) { $sql_type = "ALTER_SESSION"; }
      elsif ($cmd_type == 44) { $sql_type = "COMMIT"; }
      elsif ($cmd_type == 47) { $sql_type = "PL/SQL_EXECUTE"; }
      elsif ($cmd_type == 48) { $sql_type = "SET_TRANSACTION"; }
      elsif ($cmd_type == 49) { $sql_type = "ALTER_SYS_SW_LOG"; }
      elsif ($cmd_type == 62) { $sql_type = "ANALYZE_TABLE"; }
      elsif ($cmd_type == 63) { $sql_type = "ANALYZE_INDEX"; }
      else                    { $sql_type = "OTHER-$cmd_type"; }
      $pctof = 100 * ($exec_tot / $grant_tot);
      printf "%-20s %14.0f %14.0f %4.1f%%\n", $sql_type,$exec_now,$exec_tot,$pctof;
      $t_now += $exec_now;
      $t_tot += $exec_tot;
    }
  }

  print "-------------------- -------------- -------------- -----\n";
  printf "%-20s %14.0f %14.0f %4.1f%%\n", $zzzz,$t_now,$t_tot,$zzzz;
  exit;
}

# --------------------------------------------------------------------
# -lk
# --------------------------------------------------------------------
if ($arg eq "-lk")
{
  &msg("TX Locks (Non-Row Locks) (Long Running)");
  $sqlstmt = '
    alter session set optimizer_goal=RULE;
    select \'X\',
        rpad(osuser, 9)||lpad(p.spid, 5) osuser,
	rpad(s.username,8)||lpad(s.sid, 4)||lpad(s.serial#, 5) username,
	decode(l.type,
		\'MR\', \'Media_Reco\',
		\'RT\', \'Redo_Thred\',
		\'UN\', \'User_Name\',
		\'TX\', \'Trans\',
		\'TM\', \'DML\',
		\'UL\', \'PL/SQL_Usr\',
		\'DX\', \'Dist._Tran\',
		\'CF\', \'Cntrl_File\',
		\'IS\', \'Inst_State\',
		\'FS\', \'File_Set\',
		\'IR\', \'Inst_Reco\',
		\'ST\', \'Disk_Space\',
		\'TS\', \'Temp_Seg\',
		\'IV\', \'Cache_Inv\',
		\'LS\', \'Log_Switch\',
		\'RW\', \'Row_Wait\',
		\'SQ\', \'Seq_Number\',
		\'TE\', \'Extend_Tbl\',
		\'TT\', \'Temp_Table\',
		l.type) locktype,
	\'.\' object_name,
	decode(lmode,1,Null,2,\'Row_Share\',3,\'Row_Excl\',4,\'Share\',
		5,\'Sh_Row_Ex\',6,\'Exclusive\',\' \') held,
	decode(request,1,Null,2,\'Row_Share\',3,\'Row_Excl\',4,\'Share\',
		5,\'Sh_Row_Ex\',6,\'Exclusive\',\' \') request
	from v\$lock l, v\$session s, v\$process p
	where s.sid = l.sid and
		s.username <> \' \' and
		s.paddr = p.addr and
		l.type <> \'TM\' and
		(l.type <> \'TX\' or l.type = \'TX\' and l.lmode <> 6)
union
select \'X\', rpad(osuser, 9)||lpad(p.spid, 5) osuser,
	rpad(s.username,8)||lpad(s.sid, 4)||lpad(s.serial#, 5) username,
	decode(l.type,
		\'MR\', \'Media_Reco\',
		\'RT\', \'Redo_Thred\',
		\'UN\', \'User_Name\',
		\'TX\', \'Trans\',
		\'TM\', \'DML\',
		\'UL\', \'PL/SQL_Usr\',
		\'DX\', \'Dist._Tran\',
		\'CF\', \'Cntrl_File\',
		\'IS\', \'Inst_State\',
		\'FS\', \'File_Set\',
		\'IR\', \'Inst_Reco\',
		\'ST\', \'Disk_Space\',
		\'TS\', \'Temp_Seg\',
		\'IV\', \'Cache_Inv\',
		\'LS\', \'Log_Switch\',
		\'RW\', \'Row_Wait\',
		\'SQ\', \'Seq_Number\',
		\'TE\', \'Extend_Tbl\',
		\'TT\', \'Temp_Table\',
		l.type) locktype,
	object_name,
	decode(lmode,1,NULL,2,\'Row_Share\',3,\'Row_Excl\',4,\'Share\',
		5,\'Sh_Row_Ex\',6,\'Exclusive\',NULL) held,
	decode(request,1,NULL,2,\'Row_Share\',3,\'Row_Excl\',4,\'Share\',
		5,\'Sh_Row_Ex\',6,\'Exclusive\',NULL) request
	from v\$lock l, v\$session s, v\$process p, sys.dba_objects o
	where s.sid = l.sid and
		o.object_id = l.id1 and
		l.type = \'TM\' and
		s.username <> \' \' and
		s.paddr = p.addr
union
select \'X\', rpad(osuser, 9)||lpad(p.spid, 5) osuser,
	rpad(s.username,8)||lpad(s.sid, 4)||lpad(s.serial#, 5) username,
	decode(l.type,
		\'MR\', \'Media_Reco\',
		\'RT\', \'Redo_Thred\',
		\'UN\', \'User_Name\',
		\'TX\', \'Trans\',
		\'TM\', \'DML\',
		\'UL\', \'PL/SQL_Usr\',
		\'DX\', \'Dist._Tran\',
		\'CF\', \'Cntrl_File\',
		\'IS\', \'Inst_State\',
		\'FS\', \'File_Set\',
		\'IR\', \'Inst_Reco\',
		\'ST\', \'Disk_Space\',
		\'TS\', \'Temp_Seg\',
		\'IV\', \'Cache_Inv\',
		\'LS\', \'Log_Switch\',
		\'RW\', \'Row_Wait\',
		\'SQ\', \'Seq_Number\',
		\'TE\', \'Extend_Tbl\',
		\'TT\', \'Temp_Table\',
		l.type) locktype,
	\'(Rollback=\'||rtrim(r.name)||\')\' object_name,
	decode(lmode,1,NULL,2,\'Row_Share\',3,\'Row_Excl\',4,\'Share\',
		5,\'Sh_Row_Ex\',6,\'Exclusive\',NULL) held,
	decode(request,1,NULL,2,\'Row_Share\',3,\'Row_Excl\',4,\'Share\',
		5,\'Sh_Row_Ex\',6,\'Exclusive\',NULL) request
	from v\$lock l, v\$session s, v\$process p, v\$rollname r
	where s.sid = l.sid and
		l.type = \'TX\' and
		l.lmode = 6 and
		trunc(l.id1/65536) = r.usn and
		s.username <> \' \' and
		s.paddr = p.addr
	order by 5, 6;';

  $locks = 0;

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words  = split();
    $verb   = $words[0];
    $osuser   = $words[1];
    $pid      = $words[2];
    $dbuser   = $words[3];
    $dbid     = $words[4];
    $dbser    = $words[5];
    $type     = $words[6];
    $obj      = $words[7];
    $held     = $words[8];
    $reqd     = $words[9];

    if ($verb eq "X")
    {
      if ($locks == 0)
      {
	print "OS User  PID   DB User  ID   Ser# Type       Object Name     Lock Held Lock Reqd\n";
	print "-------- ----- -------- ---- ---- ---------- --------------- --------- ---------\n";
      }
      printf "%-8s %-5s %-8s %4s %4s %-10s %-15s %-8s %-8s\n",
              $osuser,$pid,$dbuser,$dbid,$dbser,$type,$obj,$held,$reqd;
      $locks++;
    }
  }
  print "\n";
  &msg("$locks Locks Found");
  exit;
}

# --------------------------------------------------------------------
# sg
# --------------------------------------------------------------------
if ($arg eq "-sg")
{
  &msg("SGA Status");
  print "\n";
  $sqlstmt = '
    select \'X\', pool, name, bytes from v\$sgastat order by 2;
    select \'Y\', value from v\$parameter where name = \'shared_pool_size\';
    select \'Z\', value from v\$parameter where name = \'sga_target\';
  ';
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    $all    = $_;
    @words  = split();
    $verb   = $words[0];
    $pool1  = $words[1];
    $pool2  = $words[2];
    $word1  = $words[3];
    $word2  = $words[4];
    $word3  = $words[5];
    #$word4  = $words[6];
    $wordlast = $words[$#words];

    $ndx    = index($_,"()");
    $desc   = substr($_,$ndx+3,40);
    if ($verb eq "Z")
    {
      $sga_target = $words[1];
    }
    if ($verb eq "Y")
    {
      $shared_pool_size = $words[1];
      if ($shared_pool_size =~ /M$/)
      {
        chop($shared_pool_size);
        $shared_pool_size *= 2**20;
      }
    }
    if ($verb eq "X")
    {
      if ($pool1 eq "shared" && $pool2 eq "pool" && $word1 eq "free" && $word2 eq "memory")
      {
        $freemem = $word3;
      }
      elsif ($pool1 eq "large" && $pool2 eq "pool" && $word1 eq "free" && $word2 eq "memory")
      {
        $freememlarge = $word3;
      }
      elsif ($pool1 eq "java" && $pool2 eq "pool" && $word1 eq "free" && $word2 eq "memory")
      {
        $freememjava = $word3;
      }
      elsif ($pool1 eq "shared" && $pool2 eq "pool" && $word1 eq "sql" && $word2 eq "area")
      {
        $sqlarea = $word3;
      }
      elsif ($pool1 eq "shared" && $pool2 eq "pool" && $word1 eq "library" && $word2 eq "cache")
      {
        $libcache = $word3;
      }
      elsif ($all =~ /db_block_buffers/) { $dbblock = $wordlast; }
      elsif ($all =~ /buffer_cache/) { $dbblock = $wordlast; }
      elsif ($all =~ /log_buffer/) { $logbuf = $wordlast; }
      elsif ($all =~ /fixed_sga/) { $fixedsize = $wordlast; }
      elsif ($pool1 eq "shared" && $pool2 eq "pool")
      {
        $sharedtot += $wordlast;
      }
    }
  }

  $total = $sharedtot + $dbblock + $logbuf + $fixedsize + $sqlarea + $libcache + $freememlarge + $freememjava;
  $freesharedpct = 100 - ($freemem / $shared_pool_size * 100) if $shared_pool_size > 0;

  ##print "sps=$shared_pool_size\n";

  print  "SGA Pool                 Size(Bytes)   Size(MB)\n";
  print  "-------------------- --------------- ----------\n";

  printf "Shared Pool (Misc.)   %14s  %9.2f\n",$sharedtot,$sharedtot/1000000;
  printf "SQL Area              %14s  %9.2f\n",$sqlarea,$sqlarea/1000000;
  printf "Library Cache         %14s  %9.2f\n",$libcache,$libcache/1000000;
  printf "DB Block Buffer       %14s  %9.2f\n",$dbblock,$dbblock/1000000;
  printf "Redo Log Buffer       %14s  %9.2f\n",$logbuf,$logbuf/1000000;
  printf "Fixed SGA             %14s  %9.2f\n",$fixedsize,$fixedsize/1000000;
  printf "Large Pool Free       %14s  %9.2f   \n",$freememlarge,$freememlarge/1000000;
  printf "Java Pool Free        %14s  %9.2f   \n",$freememjava,$freememjava/1000000;

  print  "==================== =============== ==========\n";
  printf "SGA Total Used        %14s  %9.2f\n",$total,$total/1000000;
  printf "Shared Pool Free      %14s  %9.2f\n",$freemem,$freemem/1000000;
  print  "==================== =============== ==========\n";
  printf "Total Shared Memory   %14s  %9.2f\n",$total+$freemem,($total+$freemem)/1000000;
  print "\n";

  if ($sga_target > 0)
  {
    &msg("This instance uses AMM (sga_target=$sga_target)");
    &run_amm;
  }
  else
  {
    printf "shared_pool_size      %14s \n",$shared_pool_size;
    printf "Shared Pool Free      %14d \n",$freemem;
    printf "Shared Pool %% Full         %9.2f%% \n",$freesharedpct;
  }

  exit;
}

# --------------------------------------------------------------------
# rc, rd
# --------------------------------------------------------------------
if ($arg eq "-rc" || $arg eq "-rd")
{
  &msg("-rc: List and Shrink All Rollback Segments") if $arg eq "-rc";
  &msg("-rd: List and ALTER MAXEXENTS UNLIMITED All Rollback Segments") if $arg eq "-rd";

  $sqlstmt = 'select \'X\',
    SEGMENT_NAME,
    OWNER,
    TABLESPACE_NAME,
    SEGMENT_ID,
    INITIAL_EXTENT,
    NEXT_EXTENT,
    MIN_EXTENTS,
    MAX_EXTENTS,
    PCT_INCREASE,
    STATUS
    from dba_rollback_segs;';

  &msg("Rollback Segments");
  print "Name     Owner    Tablespace     X-Init   X-Next    X-Min    X-Max Status\n";
  print "-------- -------- ------------ -------- -------- -------- -------- ----------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words   = split();
    $verb    = $words[0];
    $name    = $words[1];
    $owner   = $words[2];
    $ts      = $words[3];
    $id      = $words[4];
    $xinit   = $words[5];
    $xnext   = $words[6];
    $xmin    = $words[7];
    $xmax    = $words[8];
    $xpct    = $words[9];
    $status  = $words[10];
    if ($verb eq "X")
    {
      if ($name =~ /SYSSMU/)
      {
        &msg("NOTE: The RB segment name $name indicates that this DB has SMU turned on");
        &msg("Exiting");
        exit;
      }

      printf "%-8s %-8s %-12s %8d %8d %8d %8d %-10s\n",
        $name,$owner,$ts,$xinit,$xnext,$xmin,$xmax,$status;
      if ($arg eq "-rc")
      {
        &msg("(Shrinking rollback segment: $name)");
	system("$os_scmd <<! 2>&1
	$os_conn
        !echo 'Issuing alter rollback segment $name shrink;';
	alter rollback segment $name shrink;
	!");
      }
      if ($arg eq "-rd")
      {
        &msg("(Altering rollback segment: $name MAXEXTENTS UNLIMITED)");
	system("$os_scmd <<! 2>&1
	$os_conn
	alter rollback segment $name storage ( maxextents unlimited );
	!");
      }
    }
  }
  exit;
}

# --------------------------------------------------------------------
# rb
# --------------------------------------------------------------------
if ($arg eq "-rb")
{
  &msg("Rollback Segments");
  print "\n";

  $sqlstmt = 'select \'X\',
s.SEGMENT_NAME,
s.OWNER,
s.TABLESPACE_NAME,
s.BYTES,
s.INITIAL_EXTENT,
s.NEXT_EXTENT,
s.MIN_EXTENTS,
s.MAX_EXTENTS,
s.PCT_INCREASE,
s.EXTENTS,
r.status,
r.owner
 from dba_segments s, dba_rollback_segs r
 where
 s.segment_type=\'ROLLBACK\' and
 s.segment_name=r.segment_name;';

  print "Name               Tablespace    Extents   X-Init   X-Next    X-Min      X-Max Status   PUBLIC/SYS\n";
  print "------------------ ------------ -------- -------- -------- -------- ---------- -------- ----------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words   = split();
    $verb    = $words[0];
    $name    = $words[1];
    $owner   = $words[2];
    $ts      = $words[3];
    $bytes   = $words[4];
    $xinit   = $words[5];
    $xnext   = $words[6];
    $xmin    = $words[7];
    $xmax    = $words[8];
    $xpct    = $words[9];
    $extents = $words[10];
    $status  = $words[11];
    $owner   = $words[12];
    if ($verb eq "X")
    {
      printf "%-18s %-12s %8d %8d %8d %8d %10d %-8s %-10s\n",
        $name,$ts,$extents,$xinit,$xnext,$xmin,$xmax,$status,$owner;
    }
  }
  exit;
}

# --------------------------------------------------------------------

# --------------------------------------------------------------------
# ra
# --------------------------------------------------------------------
if ($arg eq "-ra")
{
  $sqlstmt = 'select \'X\',
rn.NAME,
rs.EXTENTS,
rs.EXTENDS,
rs.RSSIZE,
rs.XACTS,
rs.GETS,
rs.HWMSIZE,
rs.WRAPS,
rs.AVEACTIVE,
rs.STATUS,
rs.WAITS,
rs.optsize
 from v\$rollstat rs, v\$rollname rn where rn.usn=rs.usn;';

  print "$P | Rollback Segments Statistics\n\n";
  print "RSSize  : Current rollback segment size in bytes\n";
  print "A Xn's  : Number of current transactions using the rollback segment\n";
  print "HWMSize : High Water Mark size in bytes\n";
  print "Wraps   : Cumulative # of times a X'n continues writing from one\n";
  print "          extents to another existing extent\n";
  print "Avg Actv: Avg # of bytes in active extents in the rbs measured over time\n\n";

  print "Name          Extents  Extends         RSSize   A Xn's      Gets         HWMSize  Wraps   Avg Actv  Status   Waits Optimal\n";
  print "------------ -------- -------- -------------- -------- ---------- -------------- ------  --------- -------- ------ -------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words     = split();
    $verb      = $words[0];
    $name      = $words[1];
    $extents   = $words[2];
    $extends   = $words[3];
    $rssize    = $words[4];
    $xacts     = $words[5];
    $num_gets  = $words[6];
    $hwmsize   = $words[7];
    $wraps     = $words[8];
    $aveactive = $words[9];
    $status    = $words[10];
    $waits     = $words[11];
    $optimal   = $words[12];
    if ($verb eq "X")
    {
      printf "%-12s %8d %8d %14d %8d %10d %14d %6s %10d %-8s %6d %-8s\n",
        $name,$extents,$extends,$rssize,$xacts,$num_gets,$hwmsize,$wraps,$aveactive,$status,$waits,$optimal;

      $t_waits += $waits;
      $t_gets  += $num_gets;
    }
    #if ($xacts > 1) { $xacts_flag = 1; }
    #if ($waits > 1) { $waits_flag = 1; }
  }

  print "\n";

  #if ($xacts_flag)
  #{
  #  &msg("Since at least one segment has >1 transaction running against it,");
  #  &msg("try increasing the number of rollback segments.");
  #}
  #if ($waits_flag)
  #{
  #  &msg("Since at least one segment has >=1 transaction(s) waiting for it,");
  #  &msg("try increasing the number of rollback segments.");
  #}

  $waits_gets_r = 100 * ($t_waits/$t_gets);
  $waits_gets_r = sprintf("%8.5f",$waits_gets_r);

  &msg("Total Waits:            $t_waits");
  &msg("Total Gets:             $t_gets");
  &msg("Ratio of Waits to Gets: $waits_gets_r%");

  if ($waits_gets_r > 1)
  {
    &msg("Because the ratio is > 1, add more rollback segments");

  }

  exit;
}

# --------------------------------------------------------------------
# se
# --------------------------------------------------------------------
if ($arg eq "-se" || $arg eq "-sd")
{
  &msg("Active Sessions");
  print "\n";

  $jobcnt = 0;
  $sesscnt = 0;

  sub seTitle
  {
    print "SID-Ser#     Sess. Type Status   OS:Userid-PID-Server       SPID  DB Userid        Session Start Time  Program\n";
    print "------------ ---------- -------- -------------------------- ----- ---------------- ------------------- --------------------\n";
  }
  &seTitle if $arg eq "-se";

  $sqlstmt = '
    select distinct \'Y\', sid from v\$mystat;
    select \'X\',
      s.sid,
      s.serial#,
      nvl(p.spid,-1),
      s.type,
      --translate(s.osuser,\' \',\'-\'),
      translate(nvl(s.osuser,\'?\'),\' \',\'-\'),
      to_char(logon_time,\'YYYY/MM/DD-HH24:MI:SS\') logon_time,
      nvl(s.status,\'?\'),
      nvl(s.process,\'?\'),
      nvl(s.machine,\'?\'),
      nvl(s.username,\'?\'),
      nvl(s.program,\'?\'),
      p.program
	from v\$session s, v\$process p
	where
        --osuser is not null and
	p.addr = s.paddr order by 2;
    select /*+ rule */ \'Z\',
      s.sid,
      s.serial#,
      s.type,
      to_char(logon_time,\'YYYY/MM/DD-HH24:MI:SS\') logon_time,
      s.status,
      s.username,
      j.job,
      o.what
	from
          v\$session s,
          dba_jobs_running j,
          dba_jobs o
	where
            j.sid = s.sid
        and j.job = o.job  order by 2;
  ';

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words   = split();

    $verb    = $words[0];

    if ($verb eq "Y")
    {
      $mysid = $words[1];
    }

    if ($verb eq "Z")
    {
      ##print;
      $sid     = $words[1];
      $ser     = $words[2];
      $type    = "JOB";
      $logtime = $words[4];
      $status  = $words[5];
      $dbuser  = $words[6];
      $jobnum  = "JobNum=$words[7]";
      $jobname = "JobName=$words[8]";

      $sidser = "$sid,$ser";
      $jobinfo = "$jobname $jobnum";

      $jobcnt++;

      ##print "dbuser=$dbuser\n";

      printf "%-12s %-10s %-8s %-26s %-5s %-16s %-19s %-20s\n",
        $sidser,$type,$status,"","",$dbuser,$logtime,$jobinfo;
    }

    if ($verb eq "X")
    {
      $sid     = $words[1];
      $ser     = $words[2];
      $shadow  = $words[3];
      $type    = $words[4];
      $user    = $words[5];
      $logtime = $words[6];
      $status  = $words[7];
      $process = $words[8];
      $machine = $words[9];
      $dbuser  = $words[10];
      $program = $words[11] . $words[12] . $words[13] . $words[14];
      $comb = "$user-$process-$machine";
      $comb = substr($comb,0,26) if length($comb) > 26;
      $sidser = "$sid,$ser";

      if ($arg eq "-sd")
      {
        print "==========================================================================================================\n";
        &seTitle;
      }
      $sesscnt++;
      $sescount{$status}++ if $type =~ /USER/;
      if ($user eq "") { $user = "."; }
      if ($sid == $mysid) { $type = "USER*"; }
      ###print "user=$user\n";
      printf "%-12s %-10s %-8s %-26s %-5s %-16s %-19s %-20s\n",
        $sidser,$type,$status,$comb,$shadow,$dbuser,$logtime,$program;

      if ($arg eq "-sd" && $type ne "BACKGROUND")
      {
        print "\n$P | SQL For Session $sid \n";
        &srSub($sid);
        print "\n$P | Waits For Session $sid \n\n";
        &swSub($sid);
        print "==========================================================================================================\n\n";
      }
    }
  }
  print "\n";
  @sorted = sort keys %sescount;
  foreach (@sorted)
  {
    &msg("Count of USER session(s) in $_ status: $sescount{$_}");
  }
  &msg("There are $sesscnt total sessions (mysid=$mysid - denoted by *)");
  &msg("There are $jobcnt total jobs running");
  exit;
}

# --------------------------------------------------------------------
# sw
# --------------------------------------------------------------------
if ($arg eq "-sw")
{
  sub swTitle
  {
    print "SID    DB-User          WaitType St WTSeq  Tmr WTTimSec Wait Event Details\n";
    print "------ ---------------- -------- -- ------ --- -------- -------------------------------------\n";
  }
  &msg("Session Waits");
  print "\n";
  &swTitle;
  &swSub;
  exit;
}

sub swSub
{
  $sqlstmt = 'select \'X\',
    sw.sid,
    sw.seq#,
    nvl(sw.wait_time, 0),
    nvl(sw.seconds_in_wait,0),
    nvl(se.username,\'.\'),
    nvl(se.status,\'.\'),
    sw.p1raw,
    sw.p2raw,
    sw.p3raw,
    sw.event,
    sw.state,
    sw.p1text,
    sw.p1,
    sw.p2text,
    sw.p2,
    sw.p3text,
    sw.p3
    from
      v\$session_wait sw,
      v\$session      se
    where
      sw.sid = se.sid
    order by 2;';
  &oraSQL($sqlstmt);
  @saveSQLout = @oraSQLout;

  $wait_idle_count = 0;
  $wait_real_count = 0;
  $total_sessions  = 0;

  foreach (@saveSQLout)
  {
    print if /^ORA/;
    @words   = split();
    $verb    = $words[0];
    $sidno   = $words[1];
    $seq     = $words[2];
    $waittime= $words[3];
    $sectimer= $words[4];
    $se_user = $words[5];
    $se_stat = substr($words[6],0,1);
    $p1raw   = $words[7];
    $p2raw   = $words[8];
    $p3raw   = $words[9];

    ##print "words=$#words\n";

    $rawtext = "P1Raw=$p1raw P2Raw=$p2raw P3Raw=$p3raw ";
    $text = $rawtext;

    for ($i = 10; $i <= $#words; $i++)
    {
      $text .= $words[$i];
      $text .= " ";
    }

    if ($verb eq "X")
    {
      $total_sessions++;

      $wait_type = "NoWait";

      if ($sectimer > 0)
      {
        if (
             $text =~ /SQL\*Net/ ||
             $text =~ /slave wait/ ||
             $text =~ /pmon timer/ ||
             $text =~ /smon timer/ ||
             $text =~ /wait for unread/ ||
             $text =~ /queue message/ ||
             $text =~ /waiting for/ ||
             $text =~ /idle wait/ ||
             $text =~ /rdbms ipc message/
           )
        {
          $wait_type = "IdleWait";
          $wait_idle_count++;
        }
        else
        {
          $wait_type = "RealWait";
          $wait_real_count++;
        }
      }

      ##print "sidno=$sidno sid=$sid \n";
      next if $sidno ne $sid && $arg eq "-sd";
      &swTitle if $arg eq "-sd";
      if ($user eq "") { $user = "."; }
      ##print "sectimer=$sectimer\n";
      printf "%-6d %-16s %-8s %2s %6d %3d %8d %-40s\n",
        $sidno,$se_user,$wait_type,$se_stat,$seq,$waittime,$sectimer,$text;

      #---- FUTURE
##	SELECT
##	  SID,
##	  USERNAME,
##	  TERMINAL,
##	  PROGRAM
##	FROM
##	  V$SESSION
##	WHERE
##	  SADDR in
##	  (
##	    SELECT
##	      KGLLKSES
##	    FROM
##	      X$KGLLK LOCK_A
##	    WHERE KGLLKREQ = 0
##	      AND EXISTS
##	    (SELECT LOCK_B.KGLLKHDL FROM X$KGLLK LOCK_B
##	       WHERE KGLLKSES = 'C000000089485210' /* BLOCKED SESSION */
##	       AND LOCK_A.KGLLKHDL = LOCK_B.KGLLKHDL
##	       AND KGLLKREQ > 0)   );

      #---- Analyze selected waits
      if ($text =~ /library cache pin/ && $p1raw)
      {
        print "       -------------------------------------------------------------------\n";
        print "       Wait analysis for [library cache pin] wait:\n";

        &oraSQL("
          SELECT
            'Z',
            kglnaown \"Owner\",
            kglnaobj \"Object\"
          FROM
            x\\\$kglob
          WHERE
            kglhdadr='$p1raw';
        ");
        @save2SQLout = @oraSQLout;
        foreach (@save2SQLout)
        {
          ##print;
	  @words2   = split();
	  $verb2    = $words2[0];
          if ($verb2 eq "Z")
          {
            $diag_obj_owner = $words2[1];
            $diag_obj_name  = $words2[2];

            print "         Object Being Latched: $diag_obj_owner.$diag_obj_name\n";
          }
        }

        &oraSQL("
          SELECT
            'Z',
            s.sid,
            kglpnmod \"Mode\",
            kglpnreq \"Req\"
          FROM
            x\\\$kglpn p,
            v\\\$session s
          WHERE
            p.kglpnuse=s.saddr
            AND kglpnhdl='$p1raw';
        ");
        @save2SQLout = @oraSQLout;
        foreach (@save2SQLout)
        {
          ##print;
	  @words2   = split();
	  $verb2    = $words2[0];
          if ($verb2 eq "Z")
          {
            $diag_sid  = $words2[1];
            $diag_mode = $words2[2];
            $diag_req  = $words2[3];

            if ($diag_mode == 0) { $diag_mode_long = "WAITING"; }
            if ($diag_mode == 2) { $diag_mode_long = "SHARED"; }
            if ($diag_mode == 3) { $diag_mode_long = "EXCLUSIVE"; }
            if ($diag_req  == 0) { $diag_req_long  = "NOT_WAITING"; }
            if ($diag_req  == 2) { $diag_req_long  = "SHARED"; }
            if ($diag_req  == 3) { $diag_req_long  = "EXCLUSIVE"; }

            print "         - Session $diag_sid is holding this resource in mode $diag_mode_long - Requesting mode $diag_req_long\n";
          }
        }

        print "       -------------------------------------------------------------------\n";
      }
    }
  }
  print "\n";
  &msg("Total Sessions=$total_sessions - Idle Waits=$wait_idle_count - Real Waits=$wait_real_count");
}

# --------------------------------------------------------------------
# sl
# --------------------------------------------------------------------
if ($arg eq "-sl")
{
  sub slTitle
  {
    print "SID    DB-User St SQL Text\n";
    print "------ ---------- --------------------------------------------------------------\n";
  }
  &msg("-sl: Session Latch Waits - SQL");
  print "\n";
  &slTitle;
  &slSub;
  exit;
}

sub slSub
{
  $sqlstmt = '

select \'X\',
    sw.sid,
    nvl(se.username,\'.\'),
    nvl(se.status,\'.\'),
    sq.sql_text
    from
      v\$session_wait sw,
      v\$session      se,
      v\$sqltext      sq
    where
      sw.sid = se.sid
      and se.sql_address = sq.address
      and se.sql_hash_value = sq.hash_value
      and sw.event = \'latch free\'
    order by 2, sq.piece;

';
  &oraSQL($sqlstmt);
  @saveSQLout = @oraSQLout;
  foreach (@saveSQLout)
  {
    ##print;
    print if /^ORA/;
    @words   = split();
    $verb    = $words[0];
    $sidno   = $words[1];
    $se_user = $words[2];
    $se_stat = substr($words[3],0,1);

    $sql = "";
    for ($i = 4; $i <= $#words; $i++)
    {
      $sql .= $words[$i];
      $sql .= " ";
    }

    if ($verb eq "X")
    {
      ##print "sidno=$sidno sid=$sid \n";
      next if $sidno ne $sid && $arg eq "-sd";
      &swTitle if $arg eq "-sd";
      if ($user eq "") { $user = "."; }
      ##print "sectimer=$sectimer\n";

      if ($sidno != $lastses)
      {
        printf "%-6d %-8s %1s %-40s\n", $sidno,$se_user,$se_stat,$sql;
      }
      else
      {
        printf "                  %-40s\n", $sql;
      }

      $lastses = $sidno;
    }
  }
}

# --------------------------------------------------------------------
# rh
# --------------------------------------------------------------------
if ($arg eq "-rh")
{
  &msg("-rh: Archive Log History");

  if ($oraver_num >= 9)
  {
    $zwasp = "alter session set workarea_size_policy=manual;";
  }
  else
  {
    $zwasp = "";
  }

  $sqlstmt = "
    $zwasp
    alter session set sort_area_size          = 500000000;
    alter session set sort_area_retained_size = 500000000;
    select \'X\',
    THREAD#,
    SEQUENCE#,
    FIRST_CHANGE#,
    switch_change#,
    to_char(first_time,\'MM/DD/YYYY-HH24:MI:SS\')
    from v\\\$loghist
    order by 5 ;";

  print "\n";
  print "Thread   ArcLog  First Chg. Num   Last Chg. Num Timestamp      \n";
  print "------ -------- --------------- --------------- ------------------------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    $diag .= $_;
    @words = split();
    $verb   = $words[0];
    $thread = $words[1];
    $seq    = $words[2];
    $fstchg = $words[3];
    $swchg  = $words[4];
    $fsttime= $words[5];
    if ($verb eq "X")
    {
      ##print "fsttime=$fsttime\n";
      printf "%6d %8d %15.0f %15.0f %-24s\n",
        $thread,$seq,$fstchg,$swchg,$fsttime;
      #last if ++$counter > 500;
      ++$counter;
    }
  }
  if ($counter < 1)
  {
    &msg("ERROR: No rows found");
    &msg("diag=$diag");
  }
  exit;
}

#------------------------------------------------------------------------------
sub timeToText
#------------------------------------------------------------------------------
{
  $zz_ts = $_[0];
  ($sec,$min,$hour,$mday,$mon,$year) = localtime($zz_ts);
  $year += 1900;
  $mon += 1;

  # Pad with 0's
  $yy = sprintf("%04d",$year);
  $mm = sprintf("%02d",$mon);
  $dd = sprintf("%02d",$mday);
  $hh = sprintf("%02d",$hour);
  $mi = sprintf("%02d",$min);
  $ss = sprintf("%02d",$sec);

  $date = "$yy/$mm/$dd-$hh:$mi:$ss";
  return $date;
}

#------------------------------------------------------------------------------
sub timeToNum
#------------------------------------------------------------------------------
{
  $zz_text = $_[0];
  $zz_text =~ s/-/\//g;
  $zz_text =~ s/:/\//g;
  ##print "zz_text=$zz_text\n";
  @words = split(/\//,$zz_text);

  if ($#words != 5)
  {
    &error("timeToNum() Input timestamp ($zz_text) should be in the format: YYYY/MM/DD-HH:MM:SS");
  }

  $zz_yyyy = $words[0];
  $zz_mon  = $words[1];
  $zz_dd   = $words[2];
  $zz_hh   = $words[3];
  $zz_mm   = $words[4];
  $zz_ss   = $words[5];
  ##print "zz_yyyy=$zz_yyyy zz_mon=$zz_mon zz_dd=$zz_dd zz_hh=$zz_hh zz_mm=$zz_mm zz_ss=$zz_ss\n";

  &error("timeToNum() - ($zz_text) YYYY must be 2002-2099") if ($zz_yyyy < 2002 || $zz_yyyy > 2099);
  &error("timeToNum() - ($zz_text) MON  must be 1-12     ") if ($zz_mon  <    1 || $zz_mon  >   12);
  &error("timeToNum() - ($zz_text) DD   must be 1-31     ") if ($zz_dd   <    1 || $zz_dd   >   31);
  &error("timeToNum() - ($zz_text) HH   must be 0-23     ") if ($zz_hh   <    0 || $zz_hh   >   23);
  &error("timeToNum() - ($zz_text) MM   must be 0-59     ") if ($zz_mm   <    0 || $zz_mm   >   59);
  &error("timeToNum() - ($zz_text) SS   must be 0-59     ") if ($zz_ss   <    0 || $zz_ss   >   59);

  @zz_date=($zz_ss,$zz_mm,$zz_hh,$zz_dd,--$zz_mon,$zz_yyyy);
  $zz_result = &timelocal(@zz_date);

  return $zz_result;
}




# --------------------------------------------------------------------
# al
# --------------------------------------------------------------------
if ($arg eq "-al")
{
  $where = "and sequence# = $arg2" if $arg2 ne "";
  $where = "and first_time >= (sysdate - $arg3)" if $arg3 ne "";

  &msg("-al: Archive Logs - arg2=$arg2 arg3=$arg3 arg4=$arg4");

  $sqlstmt = "select \'X\',
    THREAD#,
    SEQUENCE#,
    name,
    FIRST_CHANGE#,
    to_char(first_time,\'YYYY/MM/DD-HH24:MI:SS\'),
    blocks,
    block_size,
    to_char(completion_time,\'YYYY/MM/DD-HH24:MI:SS\')
  from
    v\\\$archived_log
  where
    creator != 'RMAN' and name is not null $where
  order by
    6  ;";

  ##print "sqlstmt=$sqlstmt\n";

  &msg("Archived Logs History - Sorted by 1stTimestamp");
  print "Thread   Seq. Archived Log File Name                                           1st SCN 1stTimestamp           File Size Completion Timestamp      \n";
  print "------ ------ ------------------------------------------------------- ---------------- ------------------- ------------ --------------------------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split();
    $verb   = $words[0];
    $thread = $words[1];
    $seq    = $words[2];
    $name   = $words[3];
    $fstchg = $words[4];
    $fsttime= $words[5];
    $blks   = $words[6];
    $blksize= $words[7];
    $cmptime= $words[8];

    if ($verb eq "X")
    {
      if ($arg4 eq "FINDIT")
      {
        next if $name =~ /STANDBY/;
        ##&msg("Looking for $name and $name.gzRMAN/bkRMAN");
        if (! -e "$name" && ! -e "$name.gzRMAN" && ! -e "$name.bkRMAN")
        {
          next;
        }
      }
      $ctime_num = "";
      $ctime_num = &timeToNum($cmptime) unless $cmptime eq "";
      $logsize = ($blks * $blksize) + 1024;
      ##print "fsttime=$fsttime\n";
      printf "%6d %6d %-56s %15s %-19s %12d %-19s %10d\n",
        $thread,$seq,$name,$fstchg,$fsttime,$logsize,$cmptime,$ctime_num;
      #last if ++$counter > 500;
      ++$counter;
    }
  }
  close(RO);
  if ($counter < 1)
  {
    print "$P | ERROR: No rows found\n";
  }
  exit;
}

# --------------------------------------------------------------------
# rs
# --------------------------------------------------------------------
if ($arg eq "-rs")
{
  &msg("REDO Logs - Status");
  $sqlstmt = 'select \'X\',
    GROUP#,
    THREAD#,
    SEQUENCE#,
    BYTES,
    MEMBERS,
    ARCHIVED,
    STATUS,
    FIRST_CHANGE#,
    to_char(first_time,\'YYYY/MM/DD-HH24:MI:SS\')
    from v\$log order by 3, 2;';

  print "Group Thread     Seq.      Bytes Mbrs. Archived Status     1st Chg.       1st Date           \n";
  print "----- ------ -------- ---------- ----- -------- ---------- -------------- -------------------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words = split();
    $verb   = $words[0];
    $group  = $words[1];
    $thread = $words[2];
    $seq    = $words[3];
    $bytes  = $words[4];
    $members= $words[5];
    $arched = $words[6];
    $status = $words[7];
    $fstchg = $words[8];
    $fsttime= $words[9];
    if ($verb eq "X")
    {
      ##print "fsttime=$fsttime\n";
      printf "%5d %6d %8d %10d %5d %-8s %-10s %14s %-16s\n",
        $group,$thread,$seq,$bytes,$members,$arched,$status,$fstchg,$fsttime;
    }
  }
  close(RO);
  exit;
}

# --------------------------------------------------------------------
# rr
# --------------------------------------------------------------------
if ($arg eq "-rr")
{
  &msg("REDO Log Recovery Report - CURRENT Online Redo Log Info");
  $sqlstmt = 'select \'X\',
    a.GROUP#,
    a.FIRST_CHANGE#,
    b.member,
    a.SEQUENCE#
  from
    v\$log a,
    v\$logfile b
  where a.group# = b.group#
    and a.status = \'CURRENT\';';

  print "Group 1stChange# Name                                                 Seq.\n";
  print "----- ---------- -------------------------------------------------- ------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words = split();
    $verb   = $words[0];
    $group  = $words[1];
    $fstchg = $words[2];
    $name   = $words[3];
    $seq    = $words[4];
    if ($verb eq "X")
    {
      ##print "fsttime=$fsttime\n";
      printf "%5d %10s %-50s %6d\n",
        $group,$fstchg,$name,$seq;
    }
  }
  exit;
}

# --------------------------------------------------------------------
# -iv
# --------------------------------------------------------------------
if ($arg eq "-iv")
{
  &msg("Invalid Objects");
  $sqlstmt = 'select \'X\',
    owner || \'.\' || object_name, status, object_type from dba_objects
    where status != \'VALID\' order by 1, 2;';

  print "Object Name                                        Object Type    Status\n";
  print "-------------------------------------------------- -------------- ------\n";

  $count = 0;

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    #print;
    @words = split();
    $verb   = $words[0];
    $object = $words[1];
    $status = $words[2];
    $type   = $words[3] . ' ' . $words[4];
    if ($verb eq "X")
    {
      printf "%-50s %-14s %-16s\n",$object,$type,$status;
      ++$count;
    }
  }
  print "\n";
  &msg("Found $count Invalid Objects");
  exit;
}

# --------------------------------------------------------------------
# -lf -rl
# --------------------------------------------------------------------
if ($arg eq "-lf" || $arg eq "-rl")
{
  &msg("$arg: REDO Logs - Files");
  $sqlstmt = ' select \'X\', group#, member, status from v\$logfile order by 1,2;';

  print "Group Name                                               Status\n";
  print "----- -------------------------------------------------- --------------------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split();
    $verb   = $words[0];
    $group  = $words[1];
    $member = $words[2];
    $status = $words[3];
    $fstchg = $words[4];
    if ($verb eq "X")
    {
      printf "%5d %-50s %-20s %-10s\n",$group,$member,$status,$fstchg;
    }
  }
  exit;
}

# --------------------------------------------------------------------
# -cf
# --------------------------------------------------------------------
if ($arg eq "-cf")
{
  &msg("Control Files");
  $sqlstmt = 'select \'X\', name, status from v\$controlfile;';

  print "Name                                               Status\n";
  print "-------------------------------------------------- --------------------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    @words = split();
    $verb = $words[0];
    $name = $words[1];
    $stat = $words[2];
    if ($verb eq "X")
    {
      printf "%-50s %-20s\n",$name,$status;
    }
  }
  exit;
}

# --------------------------------------------------------------------
# -st
# --------------------------------------------------------------------
if ($arg eq "-st")
{
  $sqlstmt = ' select \'X\', class, value, name from v\$sysstat order by 2 desc, 4;';
  &msg("System Statistics");
  print "\n";
  print "Class Statistic Name                                               Value\n";
  print "----- -------------------------------------------------- ---------------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    #print;
    @words = split();
    $verb  = $words[0];
    if ($verb eq "X")
    {
      $class = $words[1];
      $value = $words[2];
      $namet = $words[3];
      ##print "z=$z \n";
      chop($name = substr($_,index($_,$namet),50));

      if ($name eq "table scans (short tables)") { $scans_short = $value; }
      if ($name eq "table scans (long tables)")  { $scans_long  = $value; }
      if ($name eq "sorts (disk)")               { $sorts_disk  = $value; }
      if ($name eq "sorts (memory)")             { $sorts_mem   = $value; }

      printf "%5d %-50s %15s\n",$class,$name,$value;
    }
  }

  print "\nCalculated Statistics:\n";

  $scans_total = $scans_short + $scans_long;
  $scans_pct   = ($scans_long / $scans_total) * 100;
  $scans_pct   = sprintf("%8.5f",$scans_pct);
  printf "Long Table Scans / Total Table Scans:  %9s%%\n",$scans_pct;

  $sorts_total = $sorts_disk + $sorts_mem;
  $sorts_pct   = ($sorts_disk / $sorts_total) * 100;
  $sorts_pct   = sprintf("%8.5f",$sorts_pct);
  printf "Disk Sorts / Total Sorts:              %9s%%\n",$sorts_pct;

  exit;
}

# --------------------------------------------------------------------
# -ar Activity Rate
# --------------------------------------------------------------------
if ($arg eq "-ar")
{
  &msg("-ar: Current Activity Report");
  &msg("Collecting 'before' Sample");
  $sqlstmt = 'select \'X\', value, name from v\$sysstat where name like \'%user%\';';

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words = split();
    $verb  = $words[0];
    if ($verb eq "X")
    {
      $value = $words[1];
      $name1 = $words[2];
      $name2 = $words[3];
      if ($name1 eq "user" && $name2 eq "calls")   { $b4_calls   = $value; }
      if ($name1 eq "user" && $name2 eq "commits") { $b4_commits = $value; }
      $b4_time = time;
    }
  }

  &msg("Sleeping 10 seconds");
  sleep 10;
  &msg("Collecting 'after' Sample");

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words = split();
    $verb  = $words[0];
    if ($verb eq "X")
    {
      $value = $words[1];
      $name1 = $words[2];
      $name2 = $words[3];
      if ($name1 eq "user" && $name2 eq "calls")   { $af_calls   = $value; }
      if ($name1 eq "user" && $name2 eq "commits") { $af_commits = $value; }
      $af_time = time;
    }
  }

  $df_commits = $af_commits - $b4_commits;
  $df_calls   = $af_calls   - $b4_calls  ;
  $df_time    = $af_time    - $b4_time   ;

  $rt_calls   = $df_calls / $df_time;
  $rt_commits = $df_commits / $df_time;

  print "$P | Time Interval: $df_time seconds\n\n";
  print "                       Commit Count     Call Count \n";
  print "                       ------------   ------------ \n";
  printf "Sample #1:             %12d   %12d \n",$b4_commits,$b4_calls;
  printf "Sample #2:             %12d   %12d \n",$af_commits,$af_calls;
  print "                       ============   ============ \n";
  printf "Difference:            %12d   %12d \n",$df_commits,$df_calls;
  printf "Rate (Per Second):     %12.1f   %12.1f \n",$rt_commits,$rt_calls;
  exit;
}


# --------------------------------------------------------------------
# -az Activity Rate (logged)
# --------------------------------------------------------------------
if ($arg eq "-az")
{
  &msg("-az: Current Activity Report");

  &msg("Collecting 'before' Sample");
  $sqlstmt = 'select
    \'X\',
    value,
    name
  from
    v\$sysstat
  where
    name like \'%user%\' or
    name like \'%db block%\';';

  ##print "sqlstmt=$sqlstmt\n";
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words = split();
    $verb  = $words[0];
    if ($verb eq "X")
    {
      $value = $words[1];
      $name1 = $words[2];
      $name2 = $words[3];
      $name3 = $words[4];
      if ($name1 eq "user" && $name2 eq "calls")   { $b4_calls   = $value; }
      if ($name1 eq "user" && $name2 eq "commits") { $b4_commits = $value; }
      if ($name1 eq "db" && $name2 eq "block" && $name3 eq "gets"   ) { $b4_gets = $value; }
      if ($name1 eq "db" && $name2 eq "block" && $name3 eq "changes") { $b4_chgs = $value; }
      if ($name1 eq "table" && $name2 eq "scans" && $name3 eq "(long") { $b4_lscans = $value; }
      $b4_time = time;
    }
  }

  #Get latch detail samples
  chop($b4_lw_lc = `orastat -la | grep 'library cache' | awk '{ print \$4 }'`);
  chop($b4_lw_cb = `orastat -la | grep 'cache buffers chains' | awk '{ print \$5 }'`);

  &msg("Sleeping 10 seconds");
  sleep 10;

  &msg("Collecting 'after' Sample");

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words = split();
    $verb  = $words[0];
    if ($verb eq "X")
    {
      $value = $words[1];
      $name1 = $words[2];
      $name2 = $words[3];
      $name3 = $words[4];
      if ($name1 eq "user" && $name2 eq "calls")   { $af_calls   = $value; }
      if ($name1 eq "user" && $name2 eq "commits") { $af_commits = $value; }
      if ($name1 eq "db" && $name2 eq "block" && $name3 eq "gets"   ) { $af_gets = $value; }
      if ($name1 eq "db" && $name2 eq "block" && $name3 eq "changes") { $af_chgs = $value; }
      if ($name1 eq "table" && $name2 eq "scans" && $name3 eq "(long") { $af_lscans = $value; }
      $af_time = time;
    }
  }

  #Get latch detail samples
  chop($af_lw_lc = `orastat -la | grep 'library cache' | awk '{ print \$4 }'`);
  chop($af_lw_cb = `orastat -la | grep 'cache buffers chains' | awk '{ print \$5 }'`);

  $df_commits = $af_commits - $b4_commits;
  $df_calls   = $af_calls   - $b4_calls  ;
  $df_time    = $af_time    - $b4_time   ;

  $df_gets    = $af_gets    - $b4_gets   ;
  $df_chgs    = $af_chgs    - $b4_chgs   ;

  $df_lscans = $af_lscans   - $b4_lscans   ;

  $rt_calls   = $df_calls / $df_time;
  $rt_commits = $df_commits / $df_time;

  $rt_gets    = int($df_gets / $df_time);
  $rt_chgs    = int($df_chgs / $df_time);

  $rt_lw_lc   = int(($af_lw_lc - $b4_lw_lc) / $df_time);
  $rt_lw_cb   = int(($af_lw_cb - $b4_lw_cb) / $df_time);

  $rt_lscans  = int($df_lscans / $df_time);

  print "rt_gets=$rt_gets b4_gets=$b4_gets af_gets=$af_gets rt_lw_lc=$rt_lw_lc rt_lw_cb=$rt_lw_cb\n";

  print "$P | Time Interval: $df_time seconds\n\n";
  print "                       Commit Count     Call Count \n";
  print "                       ------------   ------------ \n";
  printf "Sample #1:             %12d   %12d \n",$b4_commits,$b4_calls;
  printf "Sample #2:             %12d   %12d \n",$af_commits,$af_calls;
  print "                       ============   ============ \n";
  printf "Difference:            %12d   %12d \n",$df_commits,$df_calls;
  printf "Rate (Per Second):     %12.1f   %12.1f \n",$rt_commits,$rt_calls;

  $cpuidle = "?";
  $cpubusy = "?";

  if (`uname` =~ /^Linux/)
  {
    $ENV{"TERM"} = "xterm";
    &msg("Collecting Linux CPU busy sample");
    foreach (`vmstat 5 2 | tail -1`)
    {
      print;   #---- DEBUG
      $cpuidle = (split) [14];
      $cpubusy = 100-$cpuidle;
      last;
    }
  }
  else
  {
    &msg("Collecting CPU busy sample");

    #---- Old way
    #chop($cpuidle = `timex -s sleep 2 2>&1 | grep ":" | tail -1 | awk '{ print \$5 }'`);
    #---- New way
    chop($cpuidle = `vmstat 1 5 | tail -4 | awk '{total +=\$NF};END {print (total/4) }'`);

    $cpubusy = 100-$cpuidle;
  }
  &msg("cpuidle=$cpuidle cpubusy=$cpubusy");

  #---- Collect mem free
  &msg("Collecting free memory sample");
  $tmp = "/tmp/${P}_$$.txt";
  unlink $tmp;

  if (`uname` =~ /^Linux/)
  {
    system("free >$tmp 2>&1");
  }
  else
  {
    system("top -d 1 -f $tmp >/dev/null 2>&1");
  }

  open(TOP, "$tmp") || &error("Cannot open input $tmp - $!");
  while(<TOP>)
  {
    if (/^Mem/)
    {
      if (`uname` =~ /^Linux/)
      {
	$memfree_raw = (split) [3];
        $memfree_raw .= "K";
      }
      else
      {
	$memfree_raw = (split) [7];
      }
      last;
    }
  }
  close(TOP);
  unlink $tmp;
  chop($memfree_mb = $memfree_raw);
  $memfree_mb = int($memfree_mb / 1024);
  &msg("memfree_mb=($memfree_raw) $memfree_mb");

  &msg("Collecting Session Count sample");
  @z = `orastat -se | tail -10 |  grep 'Count of' | grep ACTIVE | awk '{ print \$NF }'`;
  chop($ses_act   = $z[0]);
  $ses_act--;   # Subtract the orastat session
  chop($ses_inact = $z[1]);
  $ses_tot = $ses_act + $ses_inact;
  &msg("ses_act=$ses_act ses_tot=$ses_tot ses_inact=$ses_inact");

  &msg("Collecting FREE BUFFERS sample");
  chop($free_buffers = `orastat -bo 1 | grep 'Status=free' | awk '{ print \$2 }'`);
  $free_buffers = "0" if $free_buffers eq "";
  &msg("free_buffers=$free_buffers");

  &msg("Collecting Latch Wait sample");
  chop($ses_lw = `orastat -sw | grep 'latch' | wc -l`);
  &msg("ses_lw=$ses_lw");

  $usersqlfile = "/opt/oracle/admin/AZ.sql";
  $sql_time = "?";
  &msg("Looking for $usersqlfile");
  if (-e $usersqlfile)
  {
    &msg("Collecting user sql time (from $usersqlfile)");
    $tmp = "/tmp/${P}_$$.txt";
    system("cp $usersqlfile $tmp");
    system("echo 'exit' >> $tmp");
    chop($sql_time = `timex sqlplus internal \@$tmp 2>&1 | grep ^real | awk '{ print \$2 }'`);
    &msg("sql_time=$sql_time");
    system("rm $tmp");
  }

  # Most recent IO wait
  &msg("Collecting I/O wait sample (orastat -po)");
  chop($mr_io_wt = `orastat -po | grep '^Average' | awk '{ print \$2 }'`);

  # Hit ratio
  &msg("Collecting DB cache hit ratio (orastat -pb)");
  chop($hitr_tot = `orastat -pd | grep '^DB_BLOCK' | grep DEFAULT | head -1 | awk '{ print \$9 }'`);
  chop($hitr_now = `orastat -pb | grep '^Current' | awk '{ print \$NF }'`);

  # Sort disk/mem ratio
  chop($sort_disk = `orastat -st | grep 'sorts (disk)' | awk '{ print \$4 }'`);
  chop($sort_mem  = `orastat -st | grep 'sorts (memory)' | awk '{ print \$4 }'`);
  &msg("sort_disk=$sort_disk sort_mem=$sort_mem");
  $sort_ratio = 100 * ($sort_disk/$sort_mem);
  $sort_ratio = sprintf("%8.5f",$sort_ratio);
  &msg("sort_ratio=$sort_ratio");

  # Sample biggest wait
  chop($_ = `orastat -wx | tail -1`);
  @words = split();
  $wait_most_event = $words[0];
  $wait_most_count = $words[1];
  $wait_most_event = "?" if  $wait_most_event =~ /^-/;
  $wait_most_count = "?" if  $wait_most_count =~ /^-/;

  # Get archiver count
  chop($archiver_count = `orastat -ap | grep BUSY | wc -l`);
  $archiver_count =~ s/ //g;

  # Get arc fs full
  chop($arc_full = `orastat -l | grep 'Archive Dest FS Full' | awk '{ print \$NF }' | sed s/%//g`);

  #---- Get SGA pool free number
  chop($sgafree_sp = `orastat -sg | grep '^Shared Pool Free' | head -1 | awk '{ print \$NF }'`);
  chop($sgafree_lp = `orastat -sg | grep '^Large Pool Free'  | head -1 | awk '{ print \$NF }'`);
  chop($sgafree_jp = `orastat -sg | grep '^Java Pool Free'   | head -1 | awk '{ print \$NF }'`);

  &msg("DEBUG - rt_commits=$rt_commits rt_calls=$rt_calls cpubusy=$cpubusy sql_time=$sql_time archive_count=$archiver_count free_buffers=$free_buffers memfree_mb=$memfree_mb");

  chop($date = `date +%Y/%m/%d-%H:%M:%S`);
  &msg("Logging to $savedir/ora_activity_rate_$os.txt");

  $out = sprintf "$date [1] CommitRt: %5.0f DBCallRt: %5.0f CPUBusy%%: %5s SQLETime: %5s ArcsBusy: %5s FreeBufs: %5s FreeMemMB: %5s",$rt_commits,$rt_calls,$cpubusy,$sql_time,$archiver_count,$free_buffers,$memfree_mb;
  system("echo '$out' >> $savedir/ora_activity_rate_$os.txt");

  $out = sprintf "$date [2] BufGetRt: %5s BufChgRt: %5s ActivSes: %5s TotalSes: %5s LatWtSes: %5s SGAF-SLJ: %s",$rt_gets,$rt_chgs,$ses_act,$ses_tot,$ses_lw,"$sgafree_sp/$sgafree_lp/$sgafree_jp";
  system("echo '$out' >> $savedir/ora_activity_rate_$os.txt");

  $out = sprintf "$date [3] LW_DC_Rt: %5s LW_CB_Rt: %5s MaxWait: $wait_most_event/$wait_most_count",$rt_lw_lc,$rt_lw_cb;
  system("echo '$out' >> $savedir/ora_activity_rate_$os.txt");

  $out = sprintf "$date [4] MR_IO_Wt: %5s HitRaTot: %5s HitRaNow: %5s ArcFSFul: %5s SrtDskRt: %5s LngScnRt: %5s",$mr_io_wt,$hitr_tot,$hitr_now,$arc_full,$sort_ratio, $rt_lscans;
  system("echo '$out' >> $savedir/ora_activity_rate_$os.txt");

  ##system("echo '.' >> $savedir/ora_activity_rate_$os.txt");

  exit;
}

# --------------------------------------------------------------------
# -m
# --------------------------------------------------------------------
if ($arg eq "-m")
{
  $sqlstmt = ' select \'Z\', value from v\$parameter where name =\'background_dump_dest\';';
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    @words = split();
    $verb  = $words[0];
    if ($verb eq "Z")
    {
      $fname = $words[1];
    }
  }
  close(RO);

  $fname =~ s/\?/$oh/g;
  print "orastat | Alert Log: $fname\n";
  print "orastat | ================================================================\n";
  print "\n";

  if ($fname eq "")
  {
    print "$P | ERROR: bdump Directory is BLANK - Something is Wrong!\n";
    $fname = "/opt/oracle/admin/$os/bdump";
    print "$P | Trying $fname \n";
  }

  if (! -e "$fname/alert_$os.log")
  {
    print "$P | ERROR: Still cannot find $fname/alert_$os.log\n";
    chop ($cluster_name = $os);  #---- Try cutting off instance number
    $fname = "/opt/oracle/admin/$cluster_name/bdump";
    print "$P | Trying $fname \n";
  }

  if (! -e "$fname/alert_$os.log")
  {
    print "$P | ERROR: Still2 cannot find $fname/alert_$os.log\n";
    $fname = "/opt/oracle/diag/rdbms/$os/$os/trace";
    print "$P | Trying $fname \n";
  }

  if (! -e "$fname/alert_$os.log")
  {
    print "$P | ERROR: Still3 cannot find $fname/alert_$os.log\n";
    $fname = "/opt/oracle/admin/$os/diag/rdbms/$os/$os/trace";
    print "$P | Trying $fname \n";
  }

  if ($ENV{"LINES"} > 20)
  {
    $numlines = $ENV{"LINES"} - 11;
  }
  else
  {
    $numlines = 20;
  }

  &error("Alert Log file $fname/alert_$os.log Does not exist") if ! -e "$fname/alert_$os.log";
  &error("No READ permission on Alert Log file $fname/alert_$os.log") if ! -r "$fname/alert_$os.log";

  $cmd = "tail -$numlines $fname/alert_$os.log";
  system($cmd);
  print "\n";

  print "orastat | ================================================================\n";
  print "orastat | Command=$cmd\n";
  exit;
}

# --------------------------------------------------------------------
# -mv
# --------------------------------------------------------------------
if ($arg eq "-mv")
{
  $sqlstmt = ' select \'Z\', value from v\$parameter where name =\'background_dump_dest\';';
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    @words = split();
    $verb  = $words[0];
    if ($verb eq "Z")
    {
      $fname = $words[1];
    }
  }
  close(RO);

  $fname =~ s/\?/$oh/g;
  print "orastat | Alert Log: $fname\n";
  print "orastat | ================================================================\n";
  if ($fname eq "")
  {
    print "$P | ERROR: bdump Directory is BLANK - Something is Wrong!\n";
    $fname = "/opt/oracle/admin/$os/bdump";
    print "$P | Trying $fname \n";
  }
  $cmd = "view $fname/alert_$os.log";
  system($cmd);
  print "orastat | ================================================================\n";
  print "orastat | Command=$cmd\n";
  exit;
}

# --------------------------------------------------------------------
# -mf
# --------------------------------------------------------------------
if ($arg eq "-mf")
{
  $sqlstmt = ' select \'Z\', value from v\$parameter where name =\'background_dump_dest\';';
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    @words = split();
    $verb  = $words[0];
    if ($verb eq "Z")
    {
      $fname = $words[1];
    }
  }
  close(RO);

  $fname =~ s/\?/$oh/g;
  print "orastat | Alert Log: $fname\n";
  print "orastat | ================================================================\n";
  if ($fname eq "")
  {
    print "$P | ERROR: bdump Directory is BLANK - Something is Wrong!\n";
    $fname = "/opt/oracle/admin/$os/bdump";
    print "$P | Trying $fname \n";
  }
  $cmd = "tail -90f $fname/alert_$os.log";
  system($cmd);
  print "orastat | ================================================================\n";
  print "orastat | Command=$cmd\n";
  exit;
}

# --------------------------------------------------------------------
# -ma
# --------------------------------------------------------------------
if ($arg eq "-ma")
{
  $sqlstmt = ' select \'Z\', value from v\$parameter where name =\'background_dump_dest\';';
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    @words = split();
    $verb  = $words[0];
    if ($verb eq "Z")
    {
      $fname = $words[1];
    }
  }
  close(RO);

  $fname =~ s/\?/$oh/g;
  print "orastat | Alert Log: $fname\n";
  print "orastat | ================================================================\n";
  if ($fname eq "")
  {
    print "$P | ERROR: bdump Directory is BLANK - Something is Wrong!\n";
    $fname = "/opt/oracle/admin/$os/bdump";
    print "$P | Trying $fname \n";
  }
  $cmd = "cat $fname/alert_$os.log";
  system($cmd);
  print "orastat | ================================================================\n";
  print "orastat | Command=$cmd\n";
  exit;
}

# --------------------------------------------------------------------
# -c
# --------------------------------------------------------------------
if ($arg eq "-c")
{
  push(@zfiles,"$oh/dbs/init$os.ora");
  push(@zfiles,"$oh/dbs/spfile$os.ora");

  foreach $zfile (@zfiles)
  {
    &msg("Looking for init.ora/SPFile file: $zfile");
    if (-e "$zfile")
    {
      &msg("Contents of init.ora/SPFile file: $zfile");
      open(RO,"strings $zfile |") || die "Cannot OPEN $zfile - $!";
      $zflag = 1;
    }
    else
    {
      &msg("File: $zfile not found");
    }
  }
  die "Cannot find any init.ora/SPFiles\n" if ! $zflag;

  print "\n";
  while (<RO>)
  {
    @words = split;
    print;
    $linect++;
    if (substr($words[0],0,5) eq "ifile")
    {
      $ifile = $words[$#words];
      print "#**** Contents of ifile: $ifile *****\n";
      system("strings $ifile");
      print "#**** End of ifile: $ifile *****\n";
    }
  }
  close(RO);

  print "\n";
  &msg("Found $linect PFILE lines");
  exit;
}

# --------------------------------------------------------------------
# -ce
# --------------------------------------------------------------------
if ($arg eq "-ce")
{
  system("vi $oh/dbs/init$os.ora");
  exit;
}

# --------------------------------------------------------------------
# -ec
# --------------------------------------------------------------------
if ($arg eq "-ec")
{
  system("vi /opt/oracle/admin/$os/pfile/config$os.ora");
  exit;
}

# --------------------------------------------------------------------
# -ct
# --------------------------------------------------------------------
if ($arg eq "-ct")
{
  &msg("-ct: Coalesce TEMP Tablespace");
  $sqlstmt = '
    select \'X\',
	      a.tablespace_name as tablespace_name,
	      d.contents,
	      a.sum_bytes as bytes_avail,
	      a.max_id,
	      nvl(b.sum_bytes,0) as bytes_used,
	      nvl(c.sum_bytes,0) as bytes_free,
	      round(nvl(b.sum_bytes,0.00) / a.sum_bytes * 100.0, 2) as pct_used,
	      d.status
	 from
	      ( select
		  tablespace_name,
		  sum(bytes) sum_bytes,
		  count(1) max_id
		from
		  dba_data_files
		group by
		  tablespace_name
	      ) a,
	      ( select
		  tablespace_name,
		  sum(bytes) sum_bytes
		from
		  dba_extents
		group by
		  tablespace_name
	      ) b,
	      ( select
		  tablespace_name,
		  sum(bytes) sum_bytes
		from
		  dba_free_space
		group by
		  tablespace_name
	      ) c,
	      dba_tablespaces d
	where a.tablespace_name = b.tablespace_name (+)
	  and a.tablespace_name = c.tablespace_name (+)
	  and a.tablespace_name = d.tablespace_name (+)
      and d.contents = \'TEMPORARY\';';

  print "Tablespace           Type Status   NumDF  Size(MB)  Free(MB)  Used(MB)   Pct\n";
  print "-------------------- ---- -------- ----- --------- --------- --------- -----\n";

  $ts_count = -1;

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $ts_count+=1;
      $found = 1;
      $ts = $words[1];
      $type = substr($words[2],0,4);
      $size = $words[3]/1048576;
      $max = $words[4];
      $used = $words[5]/1048576;
      $free = $words[6]/1048576;
      $pct = $words[7];
      $status = $words[8];
      $temp_ts[$ts_count] = $ts;
      printf("%-20s %-4s %-8s %5d %9d %9d %9d %5.1f\n",$ts,$type,$status,$max,$size,$free,$used,$pct);
      $tot_size += $size;
      $tot_free += $free;
      $tot_used += $used;
      $tot_df   += $max;
    }
  }

  if (!$found)
  {
    &msg("Something is wrong - query returned no rows");
    exit 1;
  }

        ####   !echo 'Issuing coalesce statements;';
      foreach $temp_tablespace (@temp_ts)
        {
           print "\n";
           print "Coalescing $temp_tablespace tablespace...\n";
           system("$os_scmd <<! 2>&1
           $os_conn
           alter tablespace $temp_tablespace default storage (pctincrease 1);
           alter tablespace $temp_tablespace coalesce;
           alter tablespace $temp_tablespace coalesce;
           alter tablespace $temp_tablespace coalesce;
           alter tablespace $temp_tablespace coalesce;
           alter tablespace $temp_tablespace default storage (pctincrease 0);
           !");
         }

  print "\n";
  print "Tablespace           Type Status   NumDF  Size(MB)  Free(MB)  Used(MB)   Pct\n";
  print "-------------------- ---- -------- ----- --------- --------- --------- -----\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $found = 1;
      $ts = $words[1];
      $type = substr($words[2],0,4);
      $size = $words[3]/1048576;
      $max = $words[4];
      $used = $words[5]/1048576;
      $free = $words[6]/1048576;
      $pct = $words[7];
      $status = $words[8];
      printf("%-20s %-4s %-8s %5d %9d %9d %9d %5.1f\n",$ts,$type,$status,$max,$size,$free,$used,$pct);
      $tot_size += $size;
      $tot_free += $free;
      $tot_used += $used;
      $tot_df   += $max;
    }

    if (!$found)
    {
      print "$P | Something is wrong - query returned no rows\n";
      exit 1;
    }
  }
  exit;
}

# --------------------------------------------------------------------
# -ts
# --------------------------------------------------------------------
if ($arg eq "-ts")
{
  # If this is 8.1+, then also get extent mgmt ...
  #if (-s "$oh/install/unix.rgs")
  if ($oraver_num >= 8.1)
  {
    $where = ", d.extent_management, d.allocation_type"
  }
  else
  {
    $where = "";
  }
  ##print "w=$where \n";

  if ($arg3)
  {
    $where2 = "and a.tablespace_name like '${arg3}%' "
  }

  $sqlstmt = "
   select \'X\',
          a.tablespace_name as tablespace_name,
          d.contents,
          a.sum_bytes as bytes_avail,
          a.max_id,
          a.sum_bytes - nvl(c.sum_bytes,0) as bytes_used,
          nvl(c.sum_bytes,0) as bytes_free,
          round((a.sum_bytes - nvl(c.sum_bytes,0.00)) / a.sum_bytes * 100.0, 2) as pct_used,
          d.status $where
     from
          ( select
              tablespace_name,
              sum(bytes) sum_bytes,
              count(1) max_id
            from
              dba_data_files
            group by
              tablespace_name
          ) a,
          ( select
              tablespace_name,
	      sum(bytes) sum_bytes
	    from
              dba_free_space
	    group by
              tablespace_name
          ) c,
          dba_tablespaces d
    where
          a.tablespace_name = c.tablespace_name (+)  $where2
      and a.tablespace_name = d.tablespace_name (+) order by 2;
    select \'Y\', count(distinct tablespace_name) from dba_temp_files; ";

  print "\n";
  print "PermanentTablespace      Type Status   ExtentMgmt AllocTyp NumDF  Size(MB)  Free(MB)  Used(MB)    Pct\n";
  print "------------------------ ---- -------- ---------- -------- ----- --------- --------- --------- ------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/ && !/^ORA-00942/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "Y")
    {
      $found = 1;
      if ($words[1] > 0)
      {
        $foundtemp = 1;
        $counttemp = $words[1];
      }
    }
    if ($verb eq "X")
    {
      $tscount++;
      $found = 1;
      $ts = $words[1];
      $type = substr($words[2],0,4);
      $size = $words[3]/1048576;
      $max = $words[4];
      $used = $words[5]/1048576;
      $free = $words[6]/1048576;
      $pct = $words[7];
      $status = $words[8];
      $extmgmt  = $words[9];
      $alloctyp = $words[10];

      $extmgmt  = "." if $extmgmt eq "";
      $alloctyp = "." if $alloctyp eq "";

      $used = $size - $free;

      #---- Old
      #if ($arg2) { $z = "$date "; }
      #else       { $z = ""; }

      if ($arg2 && substr($ts,0,1) eq $arg2)
      {
        &msg("Skipping ts=$ts - arg2=$arg2");
        next;
      }

      printf("${z}%-24s %-4s %-8s %-10s %-8s %5d %9d %9d %9d %6.2f \n",$ts,$type,$status,$extmgmt,$alloctyp,$max,$size,$free,$used,$pct);

      $tot_size += $size;
      $tot_free += $free;
      $tot_used += $used;
      $tot_df   += $max;
    }
  }
  if (!$found)
  {
    print "$P | Something is wrong - query returned no rows\n";
    exit 1;
  }

  print "======================== ==== ======== ========== ======== ===== ========= ========= ========= ======\n";
  $ts = "Total: ($tscount TS)";
  $pct = ($tot_used / $tot_size * 100);
  printf("%-24s                                   %5d %9d %9d %9d %6.2f\n",$ts,$tot_df,$tot_size,$tot_free,$tot_used,$pct);

  print "\n";
  &msg("Found $tscount tablespace(s)\n");

  if ($foundtemp && ! $arg3)
  {
    print "Note: This DB also has $counttemp 8i+ Temporary TS(s) listed in dba_temp_files - invoking orastat -tt\n\n";
    &run_tt;
    exit;
  }
  else
  {
    exit;
  }
}

# --------------------------------------------------------------------
# -tt
# --------------------------------------------------------------------
if ($arg eq "-ttold")
{

  # If this is 8.1+, then also get extent mgmt ...
  #if (-r "$oh/install/unix.rgs")
  if ($oraver_num >= 8.1)
  {
    $where = ", d.extent_management, d.allocation_type"
  }
  else
  {
    $where = "";
  }
  ##print "w=$where \n";

  $tot_size = 0;
  $tot_free = 0;
  $tot_used = 0;
  $tot_df   = 0;

  $sqlstmt = "select \'X\',
          a.tablespace_name as tablespace_name,
          d.contents,
          a.sum_bytes as bytes_avail,
          nvl(a.max_id,0),
          nvl(a.sum_bytes-c.sum_bytes,0) as bytes_used,
          nvl(c.sum_bytes,0) as bytes_free,
          round(nvl((a.sum_bytes-c.sum_bytes),0.00) / a.sum_bytes * 100.0, 2) as pct_used,
          d.status $where
     from
          ( select
              tablespace_name,
              sum(bytes) sum_bytes,
              count(1) max_id
            from
              dba_temp_files
            group by
              tablespace_name
          ) a,
          ( select
              tablespace_name,
	      sum(bytes) sum_bytes
	    from
              dba_free_space
	    group by
              tablespace_name
          ) c,
          dba_tablespaces d
    where
          a.tablespace_name = c.tablespace_name (+)
      and a.tablespace_name = d.tablespace_name (+); ";

  print "TemporaryTablespace      Type Status   ExtentMgmt AllocTyp NumDF  Size(MB)  Free(MB)  Used(MB)   Pct\n";
  print "------------------------ ---- -------- ---------- -------- ----- --------- --------- --------- -----\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $found = 1;
      $ts = $words[1];
      $type = substr($words[2],0,4);
      $size = $words[3]/1048576;
      $max = $words[4];
      $used = $words[5]/1048576;
      $free = $words[6]/1048576;
      $pct = $words[7];
      $status = $words[8];
      $extmgmt  = $words[9];
      $alloctyp = $words[10];
      printf("%-24s %-4s %-8s %-10s %-8s %5d %9d %9d %9d %5.1f \n",$ts,$type,$status,$extmgmt,$alloctyp,$max,$size,$free,$used,$pct);
      $tot_size += $size;
      $tot_free += $free;
      $tot_used += $used;
      $tot_df   += $max;
    }
  }
  if (!$found)
  {
    print "$P | Something is wrong - query returned no rows\n";
    exit 1;
  }

  print "======================== ==== ======== ========== ======== ===== ========= ========= ========= =====\n";
  $ts = "Total:";
  $pct = ($tot_used / $tot_size * 100);
  printf("%-20s                                   %5d %9d %9d %9d %5.1f\n",$ts,$tot_df,$tot_size,$tot_free,$tot_used,$pct);

  print "\nNote: The 'Used' and 'Free' numbers above are not accurate. Run orastat -si for Sort Segment information\n";

  exit;
}

# --------------------------------------------------------------------
# -tc
# --------------------------------------------------------------------
if ($arg eq "-tc")
{
  &msg("-tc: Create SQL to count the rows in all permanent tables");

  $sqlstmt = '
  select \'X\', owner, segment_name, tablespace_name, blocks, extents, max_extents
    from dba_segments where segment_type = \'TABLE\'
    order by 2,3;';
  &oraSQL($sqlstmt);
  $count = 0;
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];

    if ($verb eq "X")
    {
      $owner = $words[1];
      $table = $words[2];
      $obj   = "$owner.$table";

      $outdata .= "select \'$obj\', count(*), to_char(sysdate,\'YYYY/MM/DD-HH24:MI:SS\') from $obj ;\n";
      $count++;
    }
  }

  open(OUTDATA, ">/tmp/orastat_tables.sql") || die "Cannot open output orastat_tables.sql - $!";
  print OUTDATA "$outdata";
  close(OUTDATA);

  &msg("Wrote $count SQL statements to /tmp/orastat_tables.sql");
  exit;
}

#===============================================================================
# -er Select from dba.errors
#===============================================================================
if ($arg eq "-er")
{
  &msg("-er: Display DBA_ERRORS");
  $sqlstmt = 'select \'X\',
    OWNER, NAME, TYPE, SEQUENCE, LINE, POSITION, trim(trailing \' \' from TEXT) from dba_errors ;';
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $text = substr($_,index($_,$words[7]));
      print "Owner=$words[1] Name=$words[2] Type=$words[3] Seq=$words[4] Line=$words[5] Position=$words[6] Text=$text";
      $count++;
    }
  }

  if ($count < 1) { &msg("No rows selected"); }
  exit;
}

#===============================================================================
# -de Create script to rm all datafiles, redo logs and control files
#===============================================================================
if ($arg eq "-de")
{
  &msg("All Datafiles, Online Redo Logs and Control Files");
  $sqlstmt = '
  select \'W\', file_name, tablespace_name from dba_temp_files
  union all
  select \'X\', file_name, tablespace_name from dba_data_files
  union all
  select \'Y\', member, \' \' from v\$logfile
  union all
  select \'Z\', name, \' \' from v\$controlfile
  order by 1, 2;';

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    $ts      = $words[2];
    if ($verb eq "W")
    {
      $f = $words[1];
      print "CMD $f  # Temp File (TS=$ts)\n";
    }
    if ($verb eq "X")
    {
      $f = $words[1];
      print "CMD $f  # DF (TS=$ts)\n";
    }
    if ($verb eq "Y")
    {
      $f = $words[1];
      print "CMD $f  # Online Redo Log\n";
    }
    if ($verb eq "Z")
    {
      $f = $words[1];
      print "CMD $f  # Control File\n";
    }
  }
  exit;
}

#===============================================================================
# -dc List Datafiles
#===============================================================================
if ($arg eq "-dc")
{
  $sqlstmt = 'select \'X\', tablespace_name, file_name, bytes, file_id from dba_data_files order by 1, 2;';

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $df = $words[2];
      $newdf = $df;
      $newdf =~ s/$os/NEWDBNAME/g;

      @words = split(/\//,$df);
      $lastnode = $words[$#words];
      ##print "1=$words[1] #=$#words\n";
      ##print "lastnode=$lastnode\n";
      $newdir = $df;
      $newdir =~ s/$lastnode//g;
      $newdir =~ s/$os/NEWDBNAME/g;

      printf("time mkdir -p %s\n", $newdir);
      printf("time cp %s      %s\n",$df, $newdf);
    }
  }
  exit;
}


#===============================================================================
# -df List Datafiles
#===============================================================================
if ($arg eq "-df")
{
  &msg("-df Datafiles");
  print "\n";
  print "Tablespace               DF   Datafile                                                               Datafile  Datafile  FS Free  \n";
  print "Name                     Num  Path                                                                   Status    Size(MB)  Space(MB)\n";
  print "------------------------ ---- ---------------------------------------------------------------------- --------- --------- ---------\n";

  $sqlstmt = 'column file_name format a80
  select \'X\',
  tablespace_name,
  file_name,
  nvl(bytes,0),
  file_id,
  nvl(status,\'?\')
  from dba_data_files order by 2, 5;';

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $dfcount++;
      $status = "";
      $ts     = $words[1];
      $df     = $words[2];
      $size   = $words[3]/1048576;
      $num    = $words[4];
      $status = $words[5];

      ##print "num=$num \n";

      if (-c $df)
      {
        $fs = "(Raw)";
      }
      else
      {
        if ($arg2 eq "FSCHECK")
        {
	  $fs = `$bdfcmd $df | awk '{ print \$4 }' | tail -1`;
	  $fs = sprintf("%9d",$fs / 1024);
        }
        else
        {
          $fs = ".";
        }
      }

      if ($ts eq $lastts)
      {
        #$tsout = '""';
        $tsout = $ts;
      }
      else
      {
        $tsout = $ts;
      }

      printf("%-24s %4d %-70s %-8s %9d %9s\n",$tsout,$num,$df,$status,$size,$fs);
      $lastts = $ts;
    }
  }
  print "\n";
  &msg("Found $dfcount datafile(s)");
  exit;
}

#===============================================================================
# -df2 List Datafiles by filesize desc
#===============================================================================
if ($arg eq "-df2")
{
  &msg("-df2 Datafiles");
  print "\n";
  print "Tablespace               DF   Datafile                                                               Datafile  Datafile  FS Free  \n";
  print "Name                     Num  Path                                                                   Status    Size(MB)  Space(MB)\n";
  print "------------------------ ---- ---------------------------------------------------------------------- --------- --------- ---------\n";

  $sqlstmt = '
  column file_name format a70
  select \'X\',
  tablespace_name,
  file_name,
  nvl(bytes,0),
  file_id,
  nvl(status,\'?\')
  from dba_data_files order by 4 desc, 3;';

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $dfcount++;
      $status = "";
      $ts     = $words[1];
      $df     = $words[2];
      $size   = $words[3]/1048576;
      $num    = $words[4];
      $status = $words[5];

      ##print "num=$num \n";

      if (-c $df)
      {
        $fs = "(Raw)";
      }
      else
      {
        if ($arg2 eq "FSCHECK")
        {
          $fs = `$bdfcmd $df | awk '{ print \$4 }' | tail -1`;
          $fs = sprintf("%9d",$fs / 1024);
        }
        else
        {
          $fs = ".";
        }
      }

      if ($ts eq $lastts)
      {
        #$tsout = '""';
        $tsout = $ts;
      }
      else
      {
        $tsout = $ts;
      }

      printf("%-24s %4d %-70s %-8s %9d %9s\n",$tsout,$num,$df,$status,$size,$fs);
      $lastts = $ts;
    }
  }
  print "\n";
  &msg("Found $dfcount datafile(s)");
  exit;
}





#===============================================================================
# -tf List Tempfiles
#===============================================================================
if ($arg eq "-tf")
{
  &msg("-tf Tempfiles");
  print "\n";
  print "Tablespace       DF   Tempfile                                                Tempfile  Tempfile  FS Free   Possible\n";
  print "Name             Num  Path                                                    Status    Size(MB)  Space(MB) Issue(s)\n";
  print "---------------- ---- ------------------------------------------------------- --------- --------- --------- ----------\n";

  $sqlstmt = 'select \'X\',
  tablespace_name,
  file_name,
  nvl(bytes,0),
  file_id,
  nvl(status,\'?\')
  from dba_temp_files order by 2, 5;';

  $sparsecnt = 0;
  $sparse = "";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $dfcount++;
      $status = "";
      $ts     = $words[1];
      $df     = $words[2];
      $size   = $words[3]/1048576;
      $num    = $words[4];
      $status = $words[5];

      ##print "num=$num \n";

      if (-c $df)
      {
        $fs = "(Raw)";
      }
      else
      {
        if ($arg2 eq "FSCHECK" && $df !~ /\+/)
        {
	  $fs = `$bdfcmd $df | awk '{ print \$4 }' | tail -1`;
	  $fs = sprintf("%9d",$fs / 1024);
        }
        else
        {
          $fs = ".";
        }
      }

      if ($ts eq $lastts)
      {
        #$tsout = '""';
        $tsout = $ts;
      }
      else
      {
        $tsout = $ts;
      }

      if ($df !~ /^\+/)
      {
        #---- See if this is a sparse file
        $spdev = "";
        $spmtime = "";
        $sprdev = "";
        $spmode = "";
        $spatime = "";
        $spgid = "";
        $spuid = "";
        $spino = "";
        $spnlink = "";
        $spctime = "";
        $sparse = "";

        ($spdev,$spino,$spmode,$spnlink,$spuid,$spgid,$sprdev,$spsize, $spatime,$spmtime,$spctime,$spblksize,$spblocks) = stat($df);

        $spblksize = 512;  #---- stat is wrong
        chop($spblocks = `ls -ls $df | awk '{ print \$1 }'`);
        $sizecalc = $spblocks * $spblksize;
        if ($spsize > 0 && $sizecalc > 0 && $sizecalc < ($spsize - (1024*1024)))
        {
          $sizecalc_mb = int($sizecalc / (1024 * 1024));
          ##$sparse = "(SPARSE - Filesize=${sizecalc_mb}MB sizecalc=$sizecalc spsize=$spsize spblocks=$spblocks spblksize=$spblksize)";
          $sparse = "(SPARSE - ActualFilesize=${sizecalc_mb}MB)";
          $sparsecnt++;
        }
        else
        {
          $sparse = "";
        }
      }

      printf("%-16s %4d %-55s %-8s %9d %9s %s\n",$tsout,$num,$df,$status,$size,$fs,$sparse);
      $lastts = $ts;
    }
  }
  print "\n";
  &msg("Found $dfcount tempfile(s)");
  &msg("SparseFileCnt: $sparsecnt");
  exit;
}


#===============================================================================
# -fs List freespace in Datafiles
#===============================================================================
if ($arg eq "-fs")
{
  &msg("Datafile Free Space");
  $sqlstmt = 'select \'X\',
    df.tablespace_name,
    df.file_name,
    df.file_id,
    nvl(df.bytes,0),
    nvl(sum(fs.bytes),0)
    from dba_data_files df, dba_free_space fs
    where df.file_id = fs.file_id
    group by \'X\', df.tablespace_name, df.file_name, df.file_id, df.bytes
    order by 2,4;';

  print "Tablespace       DF   Datafile                                                Datafile  Datafile  Datafile  \n";
  print "Name             Num  Path                                                    Alloc(Kb) Used(Kb)  Free(Kb)  \n";
  print "---------------- ---- ------------------------------------------------------- --------- --------- --------- \n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $dfcount++;
      $ts = $words[1];
      $df = $words[2];
      $num = $words[3];
      $size = $words[4]/1024;
      $free = $words[5]/1024;

      printf("%-16s %4d %-55s %9d %9d %9d\n",$ts,$num,$df,$size,$size-$free,$free);
    }
  }
  print "\n";
  &msg("Found $dfcount datafile(s) with free space.");
  exit;
}

#===============================================================================
# -ft List fast start recovery transactions
#===============================================================================
if ($arg eq "-ft")
{
  &msg("-ft: List Fast Start Transactions Being Rolled Back");
  $sqlstmt = '
    select \'Y\',
      name, value
      from v\$parameter
      where
      name in (\'db_block_size\');
    select \'X\',
      usn,
      slt,
      seq,
      state,
      undoblocksdone,
      undoblockstotal,
      cputime
      from v\$fast_start_transactions
      order by 2,3,4;';

  print "\n";
  print "Undo Seg/Slt/Inc Rollback State   CPU Time   Blks Done  Blks Total mB Done    mb Total   Pct.\n";
  print "---------------- ---------------- ---------- ---------- ---------- ---------- ---------- ----\n";

  $transcount = 0;

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "Y")
    {
      $blocksize  = $words[1];
    }
    if ($verb eq "X")
    {
      $transcount++;

      $usn    = $words[1];
      $slt    = $words[2];
      $seq    = $words[3];
      $state  = $words[4];
      $blks_d = $words[5];
      $blks_t = $words[6];
      $cputim = $words[7];

      $undo = "$usn/$slt/$seq";
      $pctdone = ($blks_d / $blks_t) * 100;
      $pctdone = sprintf("%.2f",$pctdone);

      $undo_t_mb = int(($blocksize * $blks_t) / 1000000);
      $undo_d_mb = int(($blocksize * $blks_d) / 1000000);

      printf("%-16s %-16s %10s %10s %10s %10s %10s %-4s\n",
        $undo,
        $state,
        $cputim,
        $blks_d,
        $blks_t,
        $undo_d_mb,
        $undo_t_mb,
        $pctdone);
    }
  }
  print "\n";
  &msg("Found $transcount Transactions being rolled back");
  exit;
}

# --------------------------------------------------------------------
# -us
# --------------------------------------------------------------------
if ($arg eq "-us")
{
  &msg("All Users");
  print "\n";

  if ($oraver_num < 8.0)
  {
    $sqlstmt = 'select
      \'X\',
      username,
      nvl(password,\'?\'),
      default_tablespace,
      temporary_tablespace,
      to_char(created, \'YYYY/MM/DD-HH24:MI:SS\'),
      nvl(profile,\'?\')
    from dba_users
    order by 2;';
  }
  else
  {
    $sqlstmt = 'select
      \'X\',
      username,
      nvl(password,\'?\'),
      default_tablespace,
      temporary_tablespace,
      to_char(created, \'YYYY/MM/DD-HH24:MI:SS\'),
      profile,
      translate(account_status,\' \',\'_\')
    from dba_users
    order by 2;';
  }

  print "User                       Password   Profile                          DefaultTS            TempTS     Created             AccountStatus\n";
  print "-------------------------- ---------- -------------------------------- -------------------- ---------- ------------------- --------------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $user    = $words[1];
      $pw      = $words[2];
      $ts      = $words[3];
      $temp    = $words[4];
      $crdate  = $words[5];
      $profile = $words[6];
      $status  = $words[7];

      if ($pw ne "EXTERNAL")
      {
        $pw = "(Set)";
      }

      printf("%-26s %-10s %-32s %-20s %-10s %-19s %-s\n",$user,$pw,$profile,$ts,$temp,$crdate,$status);

      $found++;
    }
  }
  print "\n";
  &msg("$found Total Users");
  exit;
}

# --------------------------------------------------------------------
# -ru
# --------------------------------------------------------------------
if ($arg eq "-ru")
{
  &msg("-ru: Rollback Usage - By Session");
  print "\n";

  $sqlstmt = 'select
    \'X\',
    s.username,
    s.sid,
    s.serial#,
    t.used_ublk,
    translate(t.start_time,\' \',\'-\')
  from
    v\$transaction t,
    v\$session s
  where
    t.addr = s.taddr
  order by 5 desc;';

  print "DBUserid     SID    Serial  Undo Blks Trans. Started   \n";
  print "------------ ------ ------ ---------- -----------------\n";

  &oraSQL($sqlstmt);
  $cnt = 0;
  foreach (@oraSQLout)
  {
    #3print;
    print if /^ORA/;
    @words = split;
    $verb  = shift(@words);
    if ($verb eq "X")
    {
      $user     = shift(@words);
      $sid      = shift(@words);
      $ser      = shift(@words);
      $blks     = shift(@words);
      $strttime = shift(@words);

      printf("%-12s %-6s %-6s %10s %-19s\n",$user,$sid,$ser,$blks,$strttime);

      $cnt++;
    }
  }
  print "\n";
  &msg("$cnt Total Active Transactions");
  exit;
}

# --------------------------------------------------------------------
# -tz
# --------------------------------------------------------------------
if ($arg eq "-tz")
{
  if ($arg2 eq "top")
  {
    $orderby = "5 desc";
  }
  else
  {
    $orderby = "2,3";
  }

  &msg("Non-SYS Tables (From DBA_TABLES)");
  &msg("Note: Totals are only valid if ANALYZE/dbms_stats Has Been Run");

  $sqlstmt = "
    select \'W\',
      sum(blocks)
      from dba_tables;
    select \'Y\',
      name, value
      from v\\\$parameter
      where
      name in (\'db_block_size\',\'db_block_buffers\');
    select \'X\',
      owner,
      table_name,
      nvl(tablespace_name,\'?\'),
      nvl(blocks,-1),
      nvl(num_rows,-1),
      nvl(buffer_pool,\'?\'),
      nvl(to_char(last_analyzed,\'MM/DD/YYYY-HH24\'),-1)
    from dba_tables
    order by $orderby ;";

  ##print "sqlstmt=$sqlstmt\n";

  print "\n";
  print "Owner.Table                         TableSpace     Rows      Last Analyzed Buf-Pool Blocks     MBytes %OfTot\n";
  print "----------------------------------- -------------- --------- ------------- -------- -------- -------- ------\n";

  $total_objs = 0;
  $total_anal = 0;

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];

    if ($verb eq "W")
    {
      $sumblocks = $words[1];
      ##print "sumblocks=$sumblocks\n";
    }

    if ($verb eq "Y")
    {
      if ($words[1] eq "db_block_size")
      {
        $bs = $words[2];
        ##print "bs=$bs\n";
      }
    }

    if ($verb eq "X")
    {
      $owner = $words[1];
      $table = $words[2];
      $ts    = $words[3];
      $blks  = $words[4];
      $rows  = $words[5];
      $bp    = $words[6];
      $la    = $words[7];

      $t = $owner . "." . $table;
      if ($owner ne "SYS" && $owner ne "SYSTEM")
      {
        $found_tables++;

	$total_objs++;
	$total_anal++ if $rows > -1;

        $mb = int(($bs * $blks) / 1000000);

        if ($mb > $top_table_mb)
        {
          $top_table_name = $owner . "." . $table;
          $top_table_mb   = $mb;
          $top_table_rows = $rows;
        }

        $pct = "";
        if ($blks > 0 && $sumblocks > 0)
        {
	  $pct = ($blks / $sumblocks) * 100;
	  $pct = sprintf("%4.1f",$pct);
          $total_pct += $pct;
        }

        printf("%-35s %-14s %9d %13s %-8s %8d %8d %6s\n",$t,$ts,$rows,$la,$bp,$blks,$mb,$pct);
	if    ($bp eq "DEFAULT") {  $def_total += $mb; }
	elsif ($bp eq "KEEP")    {  $kep_total += $mb; }
	elsif ($bp eq "RECYCLE") {  $rec_total += $mb; }
        $total_mb += $mb;

	if ($arg2 eq "top" && $found_tables >= $arg3)
	{
	  last;
	}

      }
    }
  }
  print "=================================== ============== ========= ============= ======== ======== ======== ======\n";
  printf("%-35s %-14s %9s %13s %-8s %8s %8d %6s\n","Total:","","","","","",$total_mb,$total_pct);

  print "\n";
  &msg("$found_tables Tables");
  print "\n";



  &msg("Non-SYS Indexes (From DBA_INDEXES)");
  &msg("Note: Totals are only valid if ANALYZE/dbms_stats Has Been Run");

  $sqlstmt = "
    select \'W\',
      sum(leaf_blocks)
      from dba_indexes;
    select \'X\',
      owner,
      index_name,
      nvl(tablespace_name,\'?\'),
      nvl(leaf_blocks,-1),
      nvl(num_rows,-1),
      nvl(buffer_pool,\'?\'),
      nvl(to_char(last_analyzed,\'MM/DD/YYYY-HH24\'),-1)
    from dba_indexes
    order by $orderby ;";

  ##print "sqlstmt=$sqlstmt\n";

  print "\n";
  print "Owner.Index                         TableSpace     Rows      Last Analyzed Buf-Pool Blocks     MBytes %OfTot\n";
  print "----------------------------------- -------------- --------- ------------- -------- -------- -------- ------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];

    if ($verb eq "W")
    {
      $sumblocks = $words[1];
      ##print "sumblocks=$sumblocks\n";
    }

    if ($verb eq "X")
    {
      $owner = $words[1];
      $table = $words[2];
      $ts    = $words[3];
      $blks  = $words[4];
      $rows  = $words[5];
      $bp    = $words[6];
      $la    = $words[7];

      $t = $owner . "." . $table;
      if ($owner ne "SYS" && $owner ne "SYSTEM")
      {
        $found_indexes++;

	$total_objs++;
	$total_anal++ if $rows != -1;

        $mb = int(($bs * $blks) / 1000000);

        if ($mb > $top_index_mb)
        {
          $top_index_name = $owner . "." . $table;
          $top_index_mb   = $mb;
          $top_index_rows = int($rows);
        }

        $pct = "";
        if ($blks > 0 && $sumblocks > 0)
        {
	  $pct = ($blks / $sumblocks) * 100;
	  $pct = sprintf("%4.1f",$pct);
          $total_pct += $pct;
        }

        printf("%-35s %-14s %9d %13s %-8s %8d %8d %6s\n",$t,$ts,$rows,$la,$bp,$blks,$mb,$pct);
	if    ($bp eq "DEFAULT") {  $def_total += $mb; }
	elsif ($bp eq "KEEP")    {  $kep_total += $mb; }
	elsif ($bp eq "RECYCLE") {  $rec_total += $mb; }
        $total_mb += $mb;

	if ($arg2 eq "top" && $found_indexes >= $arg3)
	{
	  last;
	}

      }
    }
  }
  print "=================================== ============== ========= ============= ======== ======== ======== ======\n";
  printf("%-35s %-14s %9s %13s %-8s %8s %8d %6s\n","Total:","","","","","",$total_mb,$total_pct);

  print "\n";
  &msg("$found_indexes Indexes");
  print "\n";

  $def_blks = int(($def_total*1000000) / $bs);
  $kep_blks = int(($kep_total*1000000) / $bs);
  $rec_blks = int(($rec_total*1000000) / $bs);

  $total_blks = $def_blks + $kep_blks + $rec_blks;

  &msg("Total Size By Buffer Pool (Sum of Sizes of Above Tables And Indexes):");
  print "\n";
  print "Buffer Pool Total Size (mB) Total Blks \n";
  print "----------- --------------- -----------\n";
  printf("%-11s %15d %11d\n","DEFAULT", $def_total, $def_blks);
  printf("%-11s %15d %11d\n","KEEP",    $kep_total, $kep_blks);
  printf("%-11s %15d %11d\n","RECYCLE", $rec_total, $rec_blks);
  print "=========== =============== ===========\n";
  printf("%-11s %15d %11d\n","Total:", $total_mb,$total_blks);

  print "\n";
  $total_pct = sprintf("%.2f",($total_anal/$total_objs)*100);
  &msg("Analyzed Objects: $total_anal/$total_objs (${total_pct}%)");

  if ($top_table_name)
  {
    &msg("Largest Table: $top_table_name ($top_table_rows Rows - ${top_table_mb} MB)");
  }
  if ($top_index_name)
  {
    &msg("Largest Index: $top_index_name ($top_index_rows Rows - ${top_index_mb} MB)");
  }

  exit;
}

# --------------------------------------------------------------------
# -tp
# --------------------------------------------------------------------
if ($arg eq "-tp")
{
  if ($arg2 eq "top")
  {
    $orderby = "6 desc";
  }
  else
  {
    $orderby = "2,3,4";
  }

  &msg("-tp: Largest Objects");
  &msg("Non-SYS Objects (From DBA_SEGMENTS)");

  $sqlstmt = "
    select \'W\',
      sum(blocks)
      from dba_segments
      where owner not in ('SYS','SYSTEM');
    select \'Y\',
      name, value
      from v\\\$parameter
      where
      name in (\'db_block_size\',\'db_block_buffers\');
    select \'X\',
      owner,
      segment_name,
      translate(segment_type,' ','_'),
      tablespace_name,
      nvl(blocks,-1),
      buffer_pool
    from dba_segments
      where owner not in ('SYS','SYSTEM')
    order by $orderby ;";

  ##print "sqlstmt=$sqlstmt\n";

  print "\n";
  print "Owner.Object                             ObjectType TableSpace     Buf-Pool    Blocks   MBytes %OfTot\n";
  print "---------------------------------------- ---------- -------------- -------- --------- -------- ------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];

    if ($verb eq "W")
    {
      $sumblocks = $words[1];
      ##print "sumblocks=$sumblocks\n";
    }

    if ($verb eq "Y")
    {
      if ($words[1] eq "db_block_size")
      {
        $bs = $words[2];
        ##print "bs=$bs\n";
      }
    }

    if ($verb eq "X")
    {
      $owner = $words[1];
      $name  = $words[2];
      $type  = $words[3];
      $ts    = $words[4];
      $blks  = $words[5];
      $bp    = $words[6];

      $type = "INDXPART" if $type eq "INDEX_PARTITION";
      $type = "TABLPART" if $type eq "TABLE_PARTITION";

      $obj = $owner . "." . $name;

      $found_obj++;

      $mb = int(($bs * $blks) / 1000000);

      $total_blks += $blks;

      $pct = "";
      if ($blks > 0 && $sumblocks > 0)
      {
	$pct = ($blks / $sumblocks) * 100;
	$pct = sprintf("%4.1f",$pct);
	$total_pct += $pct;
      }

      printf("%-40s %-10s %-14s %-8s %9d %8d %6s\n",$obj,$type,$ts,$bp,$blks,$mb,$pct);
      if    ($bp eq "DEFAULT")
      {
        $def_total += $mb;
        $def_blks  += $blks;
      }
      elsif ($bp eq "KEEP")
      {
        $kep_total += $mb;
        $kep_blks  += $blks;
      }
      elsif ($bp eq "RECYCLE")
      {
        $rec_total += $mb;
        $rec_blks  += $blks;
      }

      $total_mb += $mb;

      if ($arg2 eq "top" && $found_obj >= $arg3)
      {
	last;
      }
    }
  }
  print "======================================== ========== ============== ======== ========= ======== ======\n";
  printf("%-40s %-10s %-14s %-8s %9d %8d %6s\n","Total:","","","",$total_blks,$total_mb,$total_pct);

  print "\n";
  &msg("$found_obj Objects");
  print "\n";

  $total_blks = $def_blks + $kep_blks + $rec_blks;

  &msg("Total Size By Buffer Pool (Sum of Sizes of Above Tables And Indexes):");
  print "\n";
  print "Buffer Pool Total Size (mB) Total Blks \n";
  print "----------- --------------- -----------\n";
  printf("%-11s %15d %11d\n","DEFAULT", $def_total, $def_blks);
  printf("%-11s %15d %11d\n","KEEP",    $kep_total, $kep_blks);
  printf("%-11s %15d %11d\n","RECYCLE", $rec_total, $rec_blks);
  print "=========== =============== ===========\n";
  printf("%-11s %15d %11d\n","Total:", $total_mb,$total_blks);
  exit;
}

# --------------------------------------------------------------------
# -nl
# --------------------------------------------------------------------
if ($arg eq "-nl")
{
  &msg("-nl: NOLOGGING Objects - Where tablespace_name is not NULL");
  $found = 0;
  $sqlstmt = '
    select \'X\',
      t.owner,
      t.table_name,
      nvl(t.logging,\'(Null-L)\'),
      nvl(t.tablespace_name,\'(Null-TS)\'),
      o.object_type
    from
      dba_tables t,
      dba_objects o
    where
      t.table_name = o.object_name
      and t.owner  = o.owner
      and t.logging = \'NO\'
      and t.tablespace_name is not null
    order by 2,3;
    select \'X\',
      i.owner,
      i.index_name,
      nvl(i.logging,\'(Null-L)\'),
      nvl(i.tablespace_name,\'(Null-TS)\')
      -- o.object_type
    from
      dba_indexes i
      -- dba_objects o
    where
      -- i.index_name = o.object_name
      --and i.owner  = o.owner
      i.logging = \'NO\'
      and i.tablespace_name is not null
    order by 2,3;
  ';

  print "\n";
  print "Owner.Object                             Object Type          TS                   LOGGING \n";
  print "---------------------------------------- -------------------- -------------------- --------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $owner   = $words[1];
      $obj     = $words[2];
      $logging = $words[3];
      $ts      = $words[4];

      $objtype = "";
      for ($i = 5; $i <= $#words; $i++)
      {
        $objtype .= $words[$i];
        $objtype .= " ";
      }
      $objtype = "INDEX" if $objtype eq "";

      $both = $owner . "." . $obj;
      if ($owner ne "SYS" && $owner ne "SYSTEM")
      {
        printf("%-40s %-20s %-20s %-8s\n",$both,$objtype,$ts,$logging);
        $found++;
      }
    }
  }
  print "\n";
  &msg("Found $found NOLOGGING Objects");
  exit;
}


# --------------------------------------------------------------------
# -in
# --------------------------------------------------------------------
if ($arg eq "-in")
{
  $key = '{INDEX}' if $arg2 eq '-key';

  if ($arg3 ne "")
  {
    $z_owner = (split(/\./,$arg3))[0];
    $z_table = (split(/\./,$arg3))[1];
    $table_where = " and nx.table_owner = '$z_owner' and nx.table_name = '$z_table'";
  }

  &msg("All Indices (From DBA_SEGMENTS)");
  print "\n";
  $sqlstmt = "select \'Y\',
    name, value
    from v\\\$parameter
    where
    name in (\'db_block_size\',\'db_block_buffers\');
  select
    \'X\',
    sg.owner,
    sg.segment_name,
    sg.tablespace_name,
    sg.blocks,
    sg.extents,
    sg.max_extents,
    nx.status,
    nx.table_name
  from
    dba_segments sg,
    dba_indexes nx
  where
    segment_type = \'INDEX\'
    and sg.segment_name = nx.index_name
    and sg.owner  = nx.owner $table_where
  order by 2,3;";

  print "Owner.Index                               TableSpace   Blocks     MB Xtents  MaxXtnt Status\n";
  print "----------------------------------------- ------------ ------ ------ ------ -------- ----------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "Y")
    {
      if ($words[1] eq "db_block_size")
      {
        $bs = $words[2];
        ##print "bs=$bs\n";
      }
    }
    if ($verb eq "X")
    {
      $owner = $words[1];
      $table = $words[2];
      $ts    = $words[3];
      $blks  = $words[4];
      $exts  = $words[5];
      $maxx  = $words[6];
      $stat  = $words[7];
      $tbl   = $words[8];
      $mb   = ($blks * $bs) / (1024 * 1024);

      if ($maxx == 2147483645)
      {
        $maxx = "(Unlim)";
      }

      $t = $owner . "." . $table;
      if (substr($owner,0,3) ne "SYS")
      {
        printf("%-41s %-12s %6d %6d %6d %8s %-10s $key\n",$t,$ts,$blks,$mb,$exts,$maxx,$stat);
        $found++;
        $tot_mb += $mb;
        $tot_xt += $exts;
      }
    }
  }
  print  "========================================= ============ ====== ====== ====== ======== ==========\n";
  printf "(%6s Total Indexes)                                        %6d %6d\n\n",$found,$tot_mb,$tot_xt;
  exit;
}

# --------------------------------------------------------------------
# -ve
# --------------------------------------------------------------------
if ($arg eq "-ve")
{
  &msg("Running dbverify on all datafiles");
  $sqlstmt = '
    select \'Y\',
      name, value
      from v\$parameter
      where
      name in (\'db_block_size\');
    select \'W\', count(*)
      from dba_data_files;
    select \'X\', file_name
      from dba_data_files
      order by 2;';

  $num_ok = 0;
  $num_ng = 0;

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "W")
    {
      $datafiles_tot  = $words[1];
      &msg("Total datafiles=$datafiles_tot");
    }
    if ($verb eq "Y")
    {
      if ($words[1] eq "db_block_size")
      {
        $bs = $words[2];
        ##print "bs=$bs\n";
      }
    }
    if ($verb eq "X")
    {
      $dfname = $words[1];
      $dfcount++;
      $pct = int(($dfcount / $datafiles_tot) * 100);
      &msg("Running dbverify on datafile=$dfname  - $dfcount of $datafiles_tot - ${pct}%");
      $rc = system("dbv file=$dfname blocksize=$bs");
      $num_ok++ if $rc == 0;
      $num_ng++ if $rc != 0;
      if ($rc != 0)
      {
        push @failed,"dbv Failed for datafile=$dfname";
      }
    }
  }

  print "\n";
  &msg("Number of datafiles that Do exhibit dbv errors:     $num_ng ");
  &msg("Number of datafiles that Do Not exhibit dbv errors: $num_ok ");

  foreach (@failed)
  {
    &msg("dbv Errors seen for datafile=$_");
  }
  exit;
}

# --------------------------------------------------------------------
# -ba
# --------------------------------------------------------------------
if ($arg eq "-ba")
{
  &msg("Contents of DBAMON.BACKUP_AGE");
  print "\n";
  print "SID      Level      Timestamp             DBSize  Elapsed  Age(Days)\n";
  print "-------- ---------- ------------------- -------- -------- ----------\n";

  $now = time;

  $sqlstmt = 'select \'Y\', SID, BCKLEVEL, TSNUM, TSTEXT, DBSIZE, ELAPSED
    from dbamon.backup_age
    order by 5;';
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "Y")
    {
      $sid     = $words[1];
      $level   = $words[2];
      $tsnum   = $words[3];
      $tstext  = $words[4];
      $dbsize  = $words[5];
      $elapsed = $words[6];
      $age     = ($now - $tsnum) / (60*60*24);
      printf("%-8s %-10s %-16s %8d %8d %10d \n",$sid,$level,$tstext,$dbsize,$elapsed,$age);
    }
  }
  print "======== ========== =================== ======== ======== ==========\n";
  exit;
}

# --------------------------------------------------------------------
# -ta
# --------------------------------------------------------------------
if ($arg eq "-ta")
{
  $tablekey = '{TABLE}' if $arg2 eq '-key';

  if ($arg3 ne "")
  {
    $z_owner = (split(/\./,$arg3))[0];
    $z_table = (split(/\./,$arg3))[1];
    $table_where = " and owner = '$z_owner' and segment_name = '$z_table'";
  }

  &msg("All Tables (From DBA_SEGMENTS) Except SYS and SYSTEM Tables");
  print "\n";
  print "Owner.Table                               TableSpace   Blocks     MB Xtents  MaxXtnt\n";
  print "----------------------------------------- ------------ ------ ------ ------ --------\n";
  $sqlstmt = "select \'Y\',
    name, value
    from v\\\$parameter
    where
    name in (\'db_block_size\',\'db_block_buffers\');
  select \'X\', owner, segment_name, tablespace_name, blocks, extents, max_extents
    from dba_segments where segment_type = \'TABLE\' $table_where
    order by 2,3;";
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "Y")
    {
      if ($words[1] eq "db_block_size")
      {
        $bs = $words[2];
        ##print "bs=$bs\n";
      }
    }
    if ($verb eq "X")
    {
      $owner = $words[1];
      $table = $words[2];
      $ts    = $words[3];
      $blks  = $words[4];
      $exts  = $words[5];
      $maxx  = $words[6];
      $mb   = ($blks * $bs) / (1024 * 1024);

      if ($maxx == 2147483645)
      {
        $maxx = "(Unlim)";
      }

      $t = $owner . "." . $table;
      #if (substr($owner,0,3) ne "SYS")
      if (($owner eq "SYS" || $owner eq "SYSTEM") && $arg2 ne "ALL") { next; }

      printf("%-41s %-12s %6d %6d %6d %8s $tablekey\n",$t,$ts,$blks,$mb,$exts,$maxx);
      $found++;
      $tot_mb += $mb;
      $tot_xt += $exts;
    }
  }
  print  "========================================= ============ ====== ====== ====== ========\n";
  printf "(%6s Total Tables)                                         %6d %6d\n\n",$found,$tot_mb,$tot_xt;
  exit;
}

# --------------------------------------------------------------------
# -bk
# --------------------------------------------------------------------
if ($arg eq "-bk")
{
  open(BK,"grep -v '^#' /opt/oracle/adm/config/*.sched | grep $os |") || die "Cannot OPEN backup schedules";
  while (<BK>)
  {
    #print;
    $found = 1;
    @words = split(/:/);
    $sched    = $words[0];
    ###$thedb    = $words[1];
    $bkfiles  = $words[2];
    $when     = $words[3];
    print "Schedule:       $sched\n";
    print "Backup File(s): $bkfiles\n";
    print "When:           $when\n";
  }
  close(BK);
  if (!$found)
  {
    print "orastat | No Backup Definitions Found For ORACLE_SID=$os\n";
  }
  exit;
}

# --------------------------------------------------------------------
# -ud
# --------------------------------------------------------------------
if ($arg eq "-ud")
{
  &msg("Users granted the DBA role");
  $sqlstmt = 'select \'X\', grantee from dba_role_privs where granted_role = \'DBA\' order by 2;';

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $user = $words[1];
      print "$user\n";
    }
  }
  exit;
}

# --------------------------------------------------------------------
# -ro
# --------------------------------------------------------------------
if ($arg eq "-ro")
{
  &msg("Roles");
  $sqlstmt = 'select \'X\', role from dba_roles order by 1;';

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $role = $words[1];
      print "$role\n";
      $count++;
    }
  }
  &msg("Found $count roles");
  exit;
}

# --------------------------------------------------------------------
# -po
# --------------------------------------------------------------------
if ($arg eq "-po")
{
  &msg("Performance: I/O Stats");
  $sqlstmt = 'select \'X\', avg(lstiotim)*10 from v\$filestat where lstiotim != 65535;';

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $num = $words[1];
      $num = sprintf("%8.1f",$num);
      print "Average_Most_Recent_Datafile_I/O_Wait_Time: $num (MS)\n";
    }
  }
  exit;
}

# --------------------------------------------------------------------
# -pp
# --------------------------------------------------------------------
if ($arg eq "-pp")
{
  &msg("Performance: I/O Stats - Datafile/Tempfile I/O Service Time");

  print "                                                   MR I/O   \n";
  print "Datafile                                           Time (MS)\n";
  print "-------------------------------------------------- ---------\n";
  $sqlstmt = '
    select
      \'X\',
      d.name,
      f.lstiotim*10
    from
       v\$filestat f,
       v\$datafile d
    where
       f.file# = d.file#
       and lstiotim > 0
       and lstiotim != 65535
    union all
    select
      \'X\',
      d.name,
      f.lstiotim*10
    from
       v\$tempstat f,
       v\$tempfile d
    where
       f.file# = d.file#
       and lstiotim > 0
       and lstiotim != 65535
    order by
       3
     ;';

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $df  = $words[1];
      $num = $words[2];
      printf "%-50s %9s\n",$df,$num;
    }
  }
  exit;
}

# --------------------------------------------------------------------
# -pi
# --------------------------------------------------------------------
if ($arg eq "-pi")
{
  &msg("Performance - I/O Distribution");
  print "\n";

  $stars = "**********";
  $gt = 0;

  $sqlstmt = '
    select \'Y1\',
      sum(phyblkrd + phyblkwrt)
      from
      v\$filestat;
    select \'Y2\',
      sum(phyblkrd + phyblkwrt)
      from
      v\$tempstat;
    select \'X\',
      d.name filename,
      f.phyblkrd blocks_r,
      f.phyblkwrt block_w,
      f.phyblkrd + f.phyblkwrt total_io
      from
      v\$filestat f,
      v\$datafile d
    where
      f.file# = d.file#
    union all
    select \'X\',
      d.name filename,
      f.phyblkrd blocks_r,
      f.phyblkwrt block_w,
      f.phyblkrd + f.phyblkwrt total_io
      from
      v\$tempstat f,
      v\$tempfile d
    where
      f.file# = d.file#
    order by
      5 desc;
    ';

  print "                                                                                  Pct Of\n";
  print "                                                             1000's 1000's 1000's DB I/O\n";
  print "Datafile                                                      Reads Writes    R+W  Total\n";
  print "------------------------------------------------------------ ------ ------ ------ ------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "Y1" || $verb eq "Y2")
    {
      $gt += int($words[1]/1000);
    }
    if ($verb eq "X")
    {
      $df = $words[1];
      $r  = int($words[2]/1000);
      $w  = int($words[3]/1000);
      $t  = int($words[4]/1000);
      $pct = $t / $gt * 100;
      $pct1 = int($t / $gt * 10) + 1;
      $hist = substr($stars,0,$pct1);
      printf "%-60s %6d %6d %6d %5.2f%% %-10s\n",$df,$r,$w,$t,$pct,$hist;
      $t_r += $r;
      $t_w += $w;
      $t_t += $t;
    }
  }
  printf "                                                             ====== ====== ======\n";
  printf "(Total):                                                     %6d %6d %6d\n",$t_r, $t_w, $t_t;
  exit;
}

# --------------------------------------------------------------------
# -pa
# --------------------------------------------------------------------
if ($arg eq "-pa")
{
  &msg("Performance - I/O Distribution - By Tablespace");
  print "\n";

  $stars = "**********";
  $gt = 0;

  $sqlstmt = '

    select \'Y1\',
      sum(phyblkrd + phyblkwrt)
      from
      v\$filestat;

    select \'Y2\',
      sum(phyblkrd + phyblkwrt)
      from
      v\$tempstat;

    select \'X\',
      t.name,
      d.name,
      f.phyblkrd,
      f.phyblkwrt
    from
      v\$filestat f,
      v\$datafile d,
      v\$tablespace t
    where
      f.file# = d.file# and
      d.ts#   = t.ts#
    union all
    select \'X\',
      t.name,
      d.name,
      f.phyblkrd,
      f.phyblkwrt
    from
      v\$tempstat f,
      v\$tempfile d,
      v\$tablespace t
    where
      f.file# = d.file# and
      d.ts#   = t.ts#
    order by
      2, 1;

    ';

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "Y1" || $verb eq "Y2")
    {
      $gt += int($words[1]/1000);
    }
    if ($verb eq "X")
    {
      $ts = $words[1];
      $df = $words[2];
      $r  = int($words[3]/1000);
      $w  = int($words[4]/1000);

      if    ($ts =~ /X$/)     {  $tscat = "Index";  }
      elsif ($ts =~ /INDEX/)  {  $tscat = "Index";  }
      elsif ($ts =~ /SYSTEM/) {  $tscat = "System";  }
      elsif ($ts =~ /RBS/)    {  $tscat = "Undo";  }
      elsif ($ts =~ /UNDO/)   {  $tscat = "Undo";  }
      elsif ($ts =~ /TEMP/)   {  $tscat = "Temp";  }
      elsif ($ts =~ /^P/)     {  $tscat = "Purge";  }
      else                    {  $tscat = "Other";  }

      ##print "ts=$ts df=$df r=$r w=$w\n";

      $tstotal_r{$ts} += $r;
      $tstotal_w{$ts} += $w;
      $tstotal_cat{$ts} = $tscat;

      $cats_r{$tscat} += $r;
      $cats_w{$tscat} += $w;

      ##print "  tstotal_r{$ts}=$tstotal_r{$ts} tstotal_w{$ts}=$tstotal_w{$ts}\n";
      ##print "  cats_r{$tscat}=$cats_r{$tscat} cats_w{$tscat}=$cats_w{$tscat}\n";
    }
  }

  $t_r = 0;
  $t_w = 0;
  $t_t = 0;

  print "                                                 Pct Of\n";
  print "               1000's       1000's       1000's  DB I/O\n";
  print "Category        Reads       Writes          R+W   Total\n";
  print "-------- ------------ ------------ ------------ -------\n";

  foreach $tscat (sort keys %cats_r)
  {
    $t = $cats_r{$tscat} + $cats_w{$tscat};
    $pct = $t / $gt * 100;
    $pct1 = (int(($t / $gt) * 100)) / 5 + 1;
    $hist = '*' x $pct1;
    printf "%-8s %12d %12d %12d %6.2f%% %-10s\n",$tscat,$cats_r{$tscat},$cats_w{$tscat},$t,$pct,$hist;
    $t_r += $cats_r{$tscat};
    $t_w += $cats_w{$tscat};
    $t_t += $t;
  }

  print "         ============ ============ ============\n";
  printf "(Total): %12d %12d %12d\n",$t_r, $t_w, $t_t;

  $t_r = 0;
  $t_w = 0;
  $t_t = 0;

  print "\n";

  print "                                                                          Pct Of\n";
  print "                                        1000's       1000's       1000's  DB I/O\n";
  print "Tablespace               Category        Reads       Writes          R+W   Total\n";
  print "------------------------ -------- ------------ ------------ ------------ -------\n";

  foreach $ts (sort keys %tstotal_r)
  {
    $t = $tstotal_r{$ts} + $tstotal_w{$ts};
    $pct = $t / $gt * 100;
    $pct1 = (int(($t / $gt) * 100)) / 5 + 1;
    $hist = '*' x $pct1;
    printf "%-24s %-8s %12d %12d %12d %6.2f%% %-10s\n",$ts,$tstotal_cat{$ts},$tstotal_r{$ts},$tstotal_w{$ts},$t,$pct,$hist;
    $t_r += $tstotal_r{$ts};
    $t_w += $tstotal_w{$ts};
    $t_t += $t;
  }

  print "                                  ============ ============ ============\n";
  printf "(Total):                          %12d %12d %12d\n",$t_r, $t_w, $t_t;






  exit;
}

# --------------------------------------------------------------------
# -tj
# --------------------------------------------------------------------
if ($arg eq "-tj")
{
  $len = $arg2;
  $len = 22 if $len eq "";

  &msg("-tj: Datafile Bytes Allocated By Filesystem - len=$len");
  print "\n";

  $sqlstmt = "
  drop table orastat_tj;
  create global temporary table orastat_tj as
    select name, bytes from v\\\$datafile;
  insert into orastat_tj
    select name, bytes from v\\\$datafile;
  insert into orastat_tj
    select name, bytes from v\\\$tempfile;
  select \'X\',
       substr(name,1,$len),
       sum(bytes)
    from
       orastat_tj
    group by
      substr(name,1,$len)
    order by
      2 ;";

  ##print "sqlstmt=$sqlstmt\n";

  print "Filesystem                                                   mB Alloc.\n";
  print "------------------------------------------------------------ ---------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print if /^ORA/;
    ##print;
    @words = split;
    $verb  = $words[0];
    if ($verb eq "X")
    {
      $fs  = $words[1];
      $mb  = int($words[2]/1000000);
      printf "%-60s %9d\n",$fs,$mb;
      $t_mb += $mb;
    }
  }
  printf "                                                             =========\n";
  printf "(Total):                                                     %9d\n",$t_mb;
  exit;
}


# --------------------------------------------------------------------
# -pj
# --------------------------------------------------------------------
if ($arg eq "-pj")
{
  $len = $arg2;
  $len = 22 if $len eq "";

  &msg("-pj: Performance - I/O Distribution By Filesystem - len=$len");
  print "\n";

  $gt = 0;

  $stars = "**********";
  $sqlstmt = "
    select \'Y1\',
      sum(phyblkrd + phyblkwrt)
      from
      v\\\$filestat;
    select \'Y2\',
      sum(phyblkrd + phyblkwrt)
      from
      v\\\$tempstat;
    select \'X\',
      substr(d.name,1,$len),
      sum(f.phyblkrd),
      sum(f.phyblkwrt),
      sum(f.phyblkwrt + f.phyblkrd)
    from
      v\\\$filestat f,
      v\\\$datafile d
    where
      f.file# = d.file#
    group by
      substr(d.name,1,$len)
    union all
    select \'X\',
      substr(d.name,1,$len),
      sum(f.phyblkrd),
      sum(f.phyblkwrt),
      sum(f.phyblkwrt + f.phyblkrd)
    from
      v\\\$tempstat f,
      v\\\$tempfile d
    where
      f.file# = d.file#
    group by
      substr(d.name,1,$len)
    order by
      5 desc;
    ";

  print "                                                                                           Pct Of\n";
  print "                                                                1000's    1000's    1000's DB I/O\n";
  print "Filesystem                                                       Reads    Writes       R+W  Total\n";
  print "------------------------------------------------------------ --------- --------- --------- ------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "Y1" || $verb eq "Y2")
    {
      $gt += int($words[1]/1000);
    }
    if ($verb eq "X")
    {
      $fs = $words[1];
      $r  = int($words[2]/1000);
      $w  = int($words[3]/1000);
      $t  = int($words[4]/1000);

      $pct = $t / $gt * 100;
      $pct1 = int($t / $gt * 10) + 1;

      $hist = substr($stars,0,$pct1);

      printf "%-60s %9d %9d %9d %5.2f%% %-10s\n",$fs,$r,$w,$t,$pct,$hist;
      $t_r += $r;
      $t_w += $w;
      $t_t += $t;
    }
  }
  printf "                                                             ========= ========= =========\n";
  printf "(Total):                                                     %9d %9d %9d\n",$t_r, $t_w, $t_t;
  exit;
}

# --------------------------------------------------------------------
# -pk
# --------------------------------------------------------------------
if ($arg eq "-pk")
{
  &msg("-pk: Performance - I/O Distribution By Tablespace");
  print "\n";


  $stars = "**********";
  $sqlstmt = "

  select \'Y\',
       sum(phyblkrd + phyblkwrt),
       sum(phyblkrd),
       sum(phyblkwrt)
       from
       v\\\$filestat;

  select \'Z\',
       sum(phyblkrd + phyblkwrt),
       sum(phyblkrd),
       sum(phyblkwrt)
       from
       v\\\$tempstat;

  select \'X\',
       t.name,
       sum(f.phyblkrd),
       sum(f.phyblkwrt),
       sum(f.phyblkwrt + f.phyblkrd)
    from
       v\\\$filestat f,
       v\\\$datafile d,
       v\\\$tablespace t
    where
      f.file# = d.file#
      and d.ts# = t.ts#
    group by
      t.name
  union all
  select \'X\',
       t.name,
       sum(f.phyblkrd),
       sum(f.phyblkwrt),
       sum(f.phyblkwrt + f.phyblkrd)
    from
       v\\\$tempstat f,
       v\\\$tempfile d,
       v\\\$tablespace t
    where
      f.file# = d.file#
      and d.ts# = t.ts#
    group by
      t.name
    order by
      5 desc
  ;";

  print "                                                     % Of  % Of    % Of\n";
  print "                        1000's    1000's    1000's   Read  Write    R+W\n";
  print "Tablespace               Reads    Writes       R+W  Total  Total  Total\n";
  print "-------------------- --------- --------- --------- ------ ------ ------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "Y")
    {
      $gt   = int($words[1]/1000);
      $gt_r = int($words[2]/1000);
      $gt_w = int($words[3]/1000);
    }
    if ($verb eq "Z")
    {
      $gt   += int($words[1]/1000);
      $gt_r += int($words[2]/1000);
      $gt_w += int($words[3]/1000);
    }
    if ($verb eq "X")
    {
      ##print "gt_r=$gt_r gt_w=$gt_w gt=$gt\n";

      $ts = $words[1];
      $r  = int($words[2]/1000);
      $w  = int($words[3]/1000);
      $t  = int($words[4]/1000);

      $pct = $t / $gt * 100;
      $pct1 = int($t / $gt * 10) + 1;
      $hist = substr($stars,0,$pct1);

      $pct_r = $r / $gt_r * 100;
      $pct_w = $w / $gt_w * 100;


      printf "%-20s %9d %9d %9d %5.2f%% %5.2f%% %5.2f%% %-10s\n",$ts,$r,$w,$t,$pct_r,$pct_w,$pct,$hist;
      $t_r += $r;
      $t_w += $w;
      $t_t += $t;
    }
  }
  printf "                     ========= ========= =========\n";
  printf "(Total):             %9d %9d %9d\n",$t_r, $t_w, $t_t;
  exit;
}

# --------------------------------------------------------------------
# -pd
# --------------------------------------------------------------------
if ($arg eq "-pd")
{
  $sqlstmt = '
select \'X\',
       sum(decode(name, \'consistent gets\', value, 0)) consistent,
       sum(decode(name, \'db block gets\',   value, 0)) db_blockgets,
       sum(decode(name, \'physical reads\',  value, 0)) physical,
       round(((sum(decode(name, \'consistent gets\', value, 0)) +
               sum(decode(name, \'db block gets\',   value, 0)) -
               sum(decode(name, \'physical reads\',  value, 0))) /
              (sum(decode(name, \'consistent gets\', value, 0)) +
               sum(decode(name, \'db block gets\',   value, 0)))) * 100, 2)
  hitratio
from v\$sysstat;
  select \'Y\',
    name, value
    from v\$parameter
    where
    name in (\'db_block_size\',\'db_block_buffers\',\'db_cache_size\');
 select
    \'V\', round((sum(gethits) / sum(gets) * 100),2) from v\$librarycache;
 select
    \'U\', round((sum(gets) - sum(getmisses)) / sum(gets) * 100,2) from v\$rowcache;
 select
    \'W\',
    name,
    100* (1-(physical_reads / (DB_BLOCK_GETS + CONSISTENT_GETS))),
    set_msize
  from
    v\$buffer_pool_statistics
  where
    (db_block_gets + consistent_gets) > 0
  order by 1;
 select
    \'Z\',
    100* (1-(sum(physical_reads) / (sum(DB_BLOCK_GETS) + sum(CONSISTENT_GETS))))
  from
    v\$buffer_pool_statistics
  where
    (db_block_gets + consistent_gets) > 0
    and name != \'RECYCLE\'
  order by 1;
  ';

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "Z")
    {
      $cachehit_x_recycle = $words[1];
    }
    if ($verb eq "V")
    {
      printf "Library Cache Hit Ratio:    %7.2f%\n",$words[1];
    }
    if ($verb eq "U")
    {
      printf "Dictionary Cache Hit Ratio: %7.2f%\n\n",$words[1];
    }
    if ($verb eq "X")
    {
      &msg("Data Block Buffer Hit Ratio Data");
      print "\n";
      ##print "$words[1]\n";
      printf "Consistent Gets:   %15s\n",$words[1];
      printf "DB Block Gets:     %15s\n",$words[2];
      printf "Physical Reads:    %15s\n",$words[3];
      printf "\nData Block Buffer Hit Ratio:%7.2f%\n",$words[4];

      $db_block_gets = $words[2];
      if ($db_block_gets =~ /1844/)
      {
        print "\n";
        print "*****************************************************************************\n";
        print "  NOTE: db_block_gets value of $db_block_gets is invalid due to an\n";
        print "    Oracle bug. Therefore, the above Data Block Buffer Hit Ratio is\n";
        print "    invalid. The 8i+ Pool Hit Ratio numbers below are more accurate.\n";
        print "*****************************************************************************\n";
        print "\n";
      }
    }
    if ($verb eq "Y")
    {
      if ($words[1] eq "db_block_size")
      {
        $bs = $words[2];
      }
      if ($words[1] eq "db_block_buffers")
      {
        $bb = $words[2];
      }
      if ($words[1] eq "db_cache_size")
      {
        $bc = $words[2];
      }
    }
    if ($verb eq "W")
    {
      $pl = $words[1];
      $ph = sprintf("%6.2f",$words[2]);
      $ps = int(($words[3]*$bs) / 1000000);
      printf "DB_BLOCK_BUFFER Read Hit Ratio - Pool: %-8s  Hit_Ratio: %6.2f  Pool_Size: %5s (MB)\n",$pl,$ph,$ps;
    }
  }
  print "\n";

  printf "DB Block Size:          %10d\n",$bs;

  if ($bb > 0)
  {
    printf "DB Block Buffers:       %10d\n\n",$bb;
    $cache_mem = $bs*$bb/1000000;
  }
  elsif ($bc > 0)
  {
    printf "db_cache_size:          %10.0f\n\n",$bc;
    $cache_mem = $bc/1000000;
  }

  printf "Total DB Block Buffer Size:  %5d(MB) (This Oracle Instance)\n",$cache_mem;

  $shmused = `$toolsdir/shmem | grep '(Total)' | awk '{ print \$2 }'`;
  chop $shmused;
  $shmused = $shmused / 1000000;
  #$shmfree = 1700-$shmused;

  printf "Server Shared Memory Used:   %5d(MB) (Entire Server)\n",$shmused;
  printf "DB Cache Hit Ratio:           %7.2f%% (Excluding RECYCLE Pool)\n",$cachehit_x_recycle;

  #printf " Server Shared Memory Free: %5d(MB) (Approximate)\n\n",$shmfree;

  exit;
}

# --------------------------------------------------------------------
# -sh
# --------------------------------------------------------------------
if ($arg eq "-sh")
{
  &msg("-sh: Shared Pool Hit/Miss Info/Recommendations");
  $sqlstmt = '
  select \'Y\',
    name, value
    from v\$parameter
    where
    name in (\'db_block_size\',\'db_block_buffers\');
  select
    \'T\', sum(reloads) / sum(pins)  from v\$librarycache;
  select
    \'V\', sum(gethits) / sum(gets)  from v\$librarycache;
  select
    \'U\', sum(getmisses) / sum(gets) from v\$rowcache;
  ';

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "T")
    {
      $pin_miss_ratio = $words[1] * 100;
      $pin_miss_ratio = sprintf("%6.2f",$pin_miss_ratio);
      if ($pin_miss_ratio >= 1)
      {
        $rec .= " (LC) Since the Library Cache reloads/pins ratio of $pin_miss_ratio exceeds 1%, you should increase the init.ora shared_pool_size parameter.\n";
      }
    }

    if ($verb eq "V")
    {
      $lc_hit_ratio = $words[1] * 100;
      $lc_hit_ratio = sprintf("%6.2f",$lc_hit_ratio);
      if ($lc_hit_ratio < 90)
      {
        $rec .= " (LC) Since the Library Cache hit ratio $lc_hit_ratio is < 90%, you should increase the init.ora shared_pool_size parameter.\n";
      }
    }

    if ($verb eq "U")
    {
      $dc_miss_ratio = $words[1] * 100;
      $dc_miss_ratio = sprintf("%6.2f",$dc_miss_ratio);
      if ($dc_miss_ratio >= 15)
      {
        $rec .= " (DC) Since the Dictionary Cache hit ratio $dc_miss_ratio is >= 15%%, you should increase the init.ora shared_pool_size parameter.\n";
      }
    }

    if ($verb eq "Y")
    {
      if ($words[1] eq "db_block_size")
      {
        #$db_block_size = $words[2];
      }
      if ($words[1] eq "db_block_buffers")
      {
        #$db_block_buffers = $words[2];
      }
    }

  }
  print "\n";
  printf "Library Cache Reloads/Pins Ratio: %6s%% (S/B < 1%)\n",$pin_miss_ratio;
  printf "Library Cache Hit Ratio:          %6s%% (S/B >= 90%)\n",$lc_hit_ratio;
  printf "Dictionary Cache Miss Ratio:      %6s%% (S/B < 15%)\n",$dc_miss_ratio;

  print "\n";
  print "Recommendations:\n";
  print $rec;
  print "(None)" if $rec eq "";
  print "\n";
  exit;
}

# --------------------------------------------------------------------
# -l
# --------------------------------------------------------------------
if ($arg eq "-l")
{
  &msg("-l: Archive Log Status");
  &oraSQL("
set time off
host echo 'Running archive log list'
archive log list;
  ");
  print "\n";
  foreach (@oraSQLout)
  {
    s/SQL> //g;
    s/SVRMGR> //g;
    print if $_ !~ /^$/;
    @words = split;
    $verb    = $words[0];
    if (/Database log mode/)
    {
      $arclogmode = $words[3] . $words[4];
    }
    if (substr($_,0,18) eq "Automatic archival")
    {
      $arcauto    = $words[2];
    }
    if (substr($_,0,19) eq "Archive destination")
    {
      $arcdirraw  = $words[2];
    }
  }

  # Fix - bb - svrmgrl lists arcdest2 if it exists - we don't
  # want that, so we will get the first disk dest from orastat -ad
  chop($arcdirnew = `orastat -ad | grep ' /' | head -1 | awk '{ print \$NF }'`);
  ##print "arcdirnew=$arcdirnew\n";
  if ($arcdirraw ne $arcdirnew && $arcdirnew ne "" && $arcdirnew =~ /^\//)
  {
    &msg("Overriding arcdirraw=$arcdirraw with $arcdirnew");
    $arcdirraw = $arcdirnew;
  }

  # if the 1st char of arcdirraw is ?, then xlate it to oracle_home
  #if (substr($arcdirraw,0,1) eq "?")
  if ($arcdirraw =~ /\?/)
  {
    $arcdirraw =~ s/\?/$oh/;
    print "$P | arcdirraw Promoted from ?... to $arcdirraw \n";
  }

  # Cut off last level of (example) /oracle/PD1/saparch/PD1arch,
  # only if the last char is NOT a SLASH
  $lastchar = substr($arcdirraw,length($arcdirraw)-1);
  $z = -e $arcdirraw;

  ##print "lastchar=$lastchar z=$z\n";
  print "\n";

  if ($lastchar ne "/" && $z == 0)
  {
    @words = split(/\//,$arcdirraw);
    $numlevels = $#words - 1;
    $arcdir = "";
    for ($i = 1; $i <= $numlevels; $i++)
    {
      $arcdir = $arcdir . "/" . $words[$i];
    }
  }
  else
  {
    $arcdir = $arcdirraw;
  }

  if ($arcdirraw eq "USE_DB_RECOVERY_FILE_DEST")
  {
    &msg("arcdirraw=$arcdirraw - Archivelog Dest uses FRA");
    chop($arcfs      = `orastat -cp | grep -i 'DB_RECOVERY_FILE_DEST' | head -1 | awk '{ print \$2 }'`);
    chop($arcdirfull = `orastat -fra | grep 'FRAFULL' | head -1 | awk '{ print \$NF }'`);
    chop $arcdirfull;  #---- Remove %
    $arcdir = "?";
  }
  elsif ($arcdir =~ /^\+/)
  {
    &msg("arcdir=$arcdir uses ASM");
    $arcdirfull = "?";
    $arcfs = "?";
  }
  elsif ($arcdir ne "")
  {
    open(BDF, "$bdfcmd $arcdir | tail -1 |") || &error("Error running $bdfcmd");
    while(<BDF>)
    {
      ##print;
      @words = split;
      $arcdirfull = $words[$#words-1];
      $arcfs = $words[$#words];
      # Remove the % sign
      chop $arcdirfull;
    }
    close(BDF);
  }

  &msg("Archive Dest.:        $arcdirraw");
  &msg("Archive Log Mode:     $arclogmode");
  &msg("Auto Archive:         $arcauto");
  &msg("Archive Dest Dir.:    $arcdir");
  &msg("Archive Dest FS:      $arcfs");
  &msg("Archive Dest FS Full: $arcdirfull%");


  exit;
}

# --------------------------------------------------------------------
# -op
# --------------------------------------------------------------------
if ($arg eq "-op")
{
  &msg("OPS V\$PING Data - Lock Conversions");
  print "Name                       File      Class        XNC\n";
  print "-------------------- ---------- ---------- ----------\n";

  $sqlstmt = '
    select
       \'Z\',
       name, file#, class#,
       max(xnc)
       from v\$ping
       group by
       \'Z\', name, file#, class# order by 5;';

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "Z")
    {
      $name  = $words[1];
      $file  = $words[2];
      $class = $words[3];
      $xnc   = $words[4];
      printf("%-20s %10s %10s %10s\n",$name,$file,$class,$xnc);
      $total += $xnc
    }
  }
  print  "==================== ========== ========== ==========\n";
  printf("Total:                                      %9d\n",$total);
  exit;
}

# --------------------------------------------------------------------
# -vs
# --------------------------------------------------------------------
if ($arg eq "-vs")
{
  &msg("All Views");
  print "----------------------------------\n";
  $sqlstmt = '
    select
       \'Z\',
       owner,
       view_name
       from dba_views
       order by 2, 3;';

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "Z")
    {
      $owner = $words[1];
      $view  = $words[2];
      $name = "$owner.$view";
      print "$name \n";
      $total++;
    }
  }
  &msg("Total Number of Views: $total");
  exit;
}

# --------------------------------------------------------------------
# -vw
# --------------------------------------------------------------------
if ($arg eq "-vw")
{
  &msg("View Count By Schema");
  print "Schema             View Count\n";
  print "------------------ -----------\n";
  $sqlstmt = '
    select
       \'Z\',
       owner,
       count(*)
       from dba_views
       group by owner;';

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "Z")
    {
      $owner = $words[1];
      $tbls  = $words[2];
      printf("%-20s %9d\n",$owner,$tbls);
      $total += $tbls;
    }
  }
  print "================== ===========\n";
  printf("Total:               %9d\n",$total);
  exit;
}

# --------------------------------------------------------------------
# -tb
# --------------------------------------------------------------------
if ($arg eq "-tb")
{
  &msg("Table Count By Schema");
  print "Schema             Table Count\n";
  print "------------------ -----------\n";
  $sqlstmt = '
    select
       \'Z\',
       owner,
       count(*)
       from dba_tables
       group by owner;';

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "Z")
    {
      $owner = $words[1];
      $tbls  = $words[2];
      printf("%-20s %9d\n",$owner,$tbls);
      $total += $tbls;
    }
  }
  print "================== ===========\n";
  printf("Total:               %9d\n",$total);
  exit;
}

# --------------------------------------------------------------------
# -an
# --------------------------------------------------------------------
if ($arg eq "-an")
{
  @words = split(/\./,$arg2);
  $owner = uc $words[0];
  $table = uc $words[1];
  if ($owner eq "" || $table eq "")
  {
    print "$P | Usage: $P -an TABLE-OWNER.TABLE-NAME\n";
    exit 1;
  }
  print "Running ANALYZE TABLE for table $owner.$table\n\n";
  open(RO,"$os_scmd <<! 2>&1
$os_conn
analyze table $owner.$table compute statistics for table;
select \'Y\', avg_row_len, initial_extent, next_extent, num_rows
   from dba_tables
   where table_name = '$table' and owner = '$owner';
!|") || die "Cannot select from $table";
  while (<RO>)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $rows = $words[1];
    }
    if ($verb eq "Y")
    {
      $rowsize = $words[1];
      $initial = $words[2];
      $next    = $words[3];
      $rows    = $words[4];
      print "Current Row Count:              $rows\n";;
      print "Average Row Size (Bytes):       $words[1]\n";
      print "Initial Extent Size (Bytes):    $initial\n";
      print "Next Extent Size (Bytes):       $next\n";
    }
  }
  $bytes = ($rowsize * $rows) * 1.25;
  $meg = int($bytes / (1024*1024)) + 1;
  print "Calculated Space Reqd. (Bytes): $bytes\n";
  print "Calculated Space Reqd. (MB):    $meg\n";
  exit;
}


# --------------------------------------------------------------------
# -ti
# --------------------------------------------------------------------
if ($arg eq "-ti")
{
  @words = split(/\./,$arg2);
  $owner = uc $words[0];
  $table = uc $words[1];

  if ($owner eq "" || $table eq "")
  {
    print "$P | Usage: $P -ti TABLE-OWNER.TABLE-NAME\n";
    exit 1;
  }
  &msg("Table Info for $owner.$table");

  # optionally count rows
  if ($arg3 eq "-count")
  {
    $sqlstmt = "select \'X\', count(*) from $owner.$table;";
    ##print "sqlstmt=$sqlstmt\n";
    &oraSQL($sqlstmt);
    foreach (@oraSQLout)
    {
      ##print;
      print if /^ORA/;
      @words = split;
      $verb  = $words[0];
      if ($verb eq "X")
      {
	$rows_counted = $words[1];
      }
    }
  }


  $sqlstmt = "
      select \'Y\', value
        from v\\\$parameter where name = \'db_block_size\';
      select
      \'X\',
      tablespace_name,
      nvl(to_char(     num_rows),\'(Null)\'),
      nvl(to_char(last_analyzed,\'YYYY/MM/DD-HH24:MI:SS\'),\'(Null)\'),
      initial_extent,
      next_extent,
      min_extents,
      max_extents,
      pct_increase,
      buffer_pool,
      nvl(to_char(blocks),\'(Null)\'),
      freelists,
      pct_free,
      ini_trans,
      max_trans,
      nvl(to_char(freelist_groups),\'(Null)\'),
      nvl(logging,\'(Null)\'),
      avg_row_len
    from
      dba_tables
    where
      table_name = \'$table\'
      and owner  = \'$owner\';";
  ##print "sqlstmt=$sqlstmt\n";
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb  = $words[0];
    if ($verb eq "Y")
    {
      $blocksize = $words[1];
    }
    if ($verb eq "X")
    {
      $tblflag = 1;
      $ts       = $words[1];
      $numrows  = $words[2];
      $lastanal = $words[3];
      $extinit  = $words[4];
      $extnext  = $words[5];
      $extmin   = $words[6];
      $extmax   = $words[7];
      $pctincr  = $words[8];
      $bufpool  = $words[9];
      $blocks   = $words[10];
      $freel    = $words[11];
      $pctfree  = $words[12];
      $initrans = $words[13];
      $maxtrans = $words[14];
      $flgrps   = $words[15];
      $logging  = $words[16];
      $avgrowl  = $words[17];

      $mb       = int(($blocks * $blocksize) / 1000000);

      print "\nTable Data (from dba_tables)\n";
      print   "----------------------------\n";
      printf "Tablespace:      %-40s\n",$ts;
      printf "RowCount:        %-19s (From ANALYZE)\n",$numrows;
      printf "LastAnalyzed:    %-19s (From ANALYZE)\n",$lastanal;
      printf "Blocks:          %-19s (From ANALYZE)\n",$blocks;
      printf "TableMegBytes:   %-19s (From ANALYZE)\n",$mb;
      printf "AvgRowLen:       %-19s (From ANALYZE)\n",$avgrowl;
      printf "ActualRows:      %-19s (From SELECT COUNT(*))\n",$rows_counted if $rows_counted ne "";
      printf "InitialExtents:  %-15s\n",$extinit;
      printf "NextExtents:     %-15s\n",$extnext;
      printf "MinExtents:      %-15s\n",$extmin;
      printf "MaxExtents:      %-15s\n",$extmax;
      printf "PercentIncr:     %-15s\n",$pctincr;
      printf "BufferPool:      %-15s\n",$bufpool;
      printf "Freelists:       %-15s\n",$freel;
      printf "FreelistGroups:  %-15s\n",$flgrps;
      printf "PctFree:         %-15s\n",$pctfree;
      printf "IniTrans:        %-15s\n",$initrans;
      printf "MaxTrans:        %-15s\n",$maxtrans;
      printf "Logging:         %-15s\n",$logging;
    }
  }

  if (!$tblflag)
  {
    &msg("Table $owner.$table does not exist");
    exit 1;
  }

  # Column data

  print "\nColumn Data (from dba_tab_cols)\n";
  print   "-------------------------------\n";
  $sqlstmt = "select
      \'X\',
      column_id,
      column_name,
      data_type,
      data_length,
      nvl(to_char(data_precision),\'(Null)\'),
      nvl(to_char(data_scale),\'(Null)\'),
      nvl(nullable,\'(Null)\'),
      avg_col_len
    from
      dba_tab_columns
    where
      table_name = \'$table\'
      and owner  = \'$owner\'
    order by 2;";
  ##print "sqlstmt=$sqlstmt\n";
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb  = $words[0];
    if ($verb eq "X")
    {
      #$colflag = 1;
      $colid    = $words[1];
      $colname  = $words[2];
      $coltype  = $words[3];
      $collen   = $words[4];
      $colprec  = $words[5];
      #$colscale = $words[6];
      $colnull  = $words[7];
      #$avg_len  = $words[8];
      printf "Num: %-2s Name: %-12s Type: %-12s Length: %-4s Precision: %-3s Null: %-3s \n",$colid,$colname,$coltype,$collen,$colprec,$colnull;
    }
  }

  # Index data

  $index_counter= 0;

  print "\nIndex Data (from dba_indexes and dba_ind_columns)\n";
  print   "----------------------------\n";
  $sqlstmt = "select
      \'X\',
      owner,
      index_name,
      tablespace_name,
      nvl(to_char(last_analyzed, \'YYYY/MM/DD-HH24:MI:SS\'),\'(Null)\'),
      initial_extent,
      next_extent,
      min_extents,
      max_extents,
      pct_increase,
      buffer_pool,
      nvl(to_char(leaf_blocks),\'(Null)\'),
      status,
      freelists,
      pct_free,
      ini_trans,
      max_trans,
      nvl(to_char(freelist_groups),\'(Null)\'),
      nvl(logging,\'(Null)\')
    from
      dba_indexes
    where
          table_name = \'$table\'
      and table_owner  = \'$owner\';";
  ##print "sqlstmt=$sqlstmt\n";
  &oraSQL($sqlstmt);
  @oraSQLoutsave1 = @oraSQLout;
  $ndx_count = 0;
  foreach (@oraSQLoutsave1)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb = $words[0];
    if ($verb eq "X")
    {
      $ndx_count++;
      $ndx_owner  = $words[1];
      $ndx_name   = $words[2];
      $ts         = $words[3];
      $lastanal   = $words[4];
      $extinit    = $words[5];
      $extnext    = $words[6];
      $extmin     = $words[7];
      $extmax     = $words[8];
      $pctincr    = $words[9];
      $bufpool    = $words[10];
      $leafblks   = $words[11];
      $ndxstatus  = $words[12];
      $freelists  = $words[13];
      $pctfree    = $words[14];
      $initrans   = $words[15];
      $maxtrans   = $words[16];
      $flgrps     = $words[17];
      $logging    = $words[18];

      $ndx = "$ndx_owner.$ndx_name";
      $index_counter++;
      print "Index $index_counter: $ndx\n";
      printf "  IndexStatus:     %-40s\n",$ndxstatus;
      printf "  Tablespace:      %-40s\n",$ts;
      printf "  LastAnalyzed:    %-19s (From ANALYZE)\n",$lastanal;
      printf "  LeafBlocks:      %-19s (From ANALYZE)\n",$leafblks;
      printf "  InitialExtents:  %-15s\n",$extinit;
      printf "  NextExtents:     %-15s\n",$extnext;
      printf "  MinExtents:      %-15s\n",$extmin;
      printf "  MaxExtents:      %-15s\n",$extmax;
      printf "  PercentIncr:     %-15s\n",$pctincr;
      printf "  BufferPool:      %-15s\n",$bufpool;
      printf "  Freelists:       %-15s\n",$freelists;
      printf "  FreelistGroups:  %-15s\n",$flgrps;
      printf "  PctFree:         %-15s\n",$pctfree;
      printf "  IniTrans:        %-15s\n",$initrans;
      printf "  MaxTrans:        %-15s\n",$maxtrans;
      printf "  Logging:         %-15s\n",$logging;
      $sqlstmt = "select
	  \'X\',
	  column_position,
	  column_name,
	  column_length,
	  descend
	from
	  dba_ind_columns
	where
	  index_name = \'$ndx_name\'
	  and index_owner  = \'$ndx_owner\'
        order by 2;";
      ##print "sqlstmt=$sqlstmt\n";
      print "\n";
      &oraSQL($sqlstmt);
      @oraSQLoutsave2 = @oraSQLout;
      foreach (@oraSQLoutsave2)
      {
	##print;
	print if /^ORA/;
	@words = split;
	$verb  = $words[0];
	if ($verb eq "X")
	{
	  $colpos   = $words[1];
	  $colname  = $words[2];
	  $collen   = $words[3];
	  $coldesc  = $words[4];
	  printf "  Index Column - Number: %-4s  Name: %-15s  Length: %-4s  Descending: %-4s\n",$colpos,$colname, $collen, $coldesc;
	}
      }
    print "\n";
    }
  }
  &msg("Found $ndx_count Indexes");
  exit;
}

# --------------------------------------------------------------------
# -td
# --------------------------------------------------------------------
if ($arg eq "-td")
{
  if ($arg2 eq "")
  {
    print "$P | Usage: $P -td TABLE-OWNER.TABLE-NAME\n";
    exit 1;
  }
  &msg("Describe table $arg2");

  $sqlstmt = "
set linesize 80
desc $arg2;";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print;
  }
  exit;
}

# --------------------------------------------------------------------
# -ls
# --------------------------------------------------------------------
if ($arg eq "-ls")
{
  &msg("Listener Status");
  system("lsnrctl status 2>&1");
  system("lsnrctl dbsnmp_status 2>&1");
  exit;
}

# --------------------------------------------------------------------
# -sl
# --------------------------------------------------------------------
if ($arg eq "-sl")
{
  &msg("select * from $arg2");
  &oraSQL("select * from $arg2;");
  foreach (@oraSQLout)
  {
    print;
  }
  exit;
}

# --------------------------------------------------------------------
# -lo
# --------------------------------------------------------------------
if ($arg eq "-lo")
{
  &msg("-lo: Table Locks");
  $sqlstmt = '
    alter session set optimizer_goal=RULE;
    select \'X\',
            nvl(S.USERNAME,\'Internal\') username,
	    nvl(S.TERMINAL,\'None\') terminal,
	    L.SID||\',\'||S.SERIAL# Kill,
	    U1.NAME||\'.\'||substr(T1.NAME,1,20) tab,
	    decode(L.LMODE,1,\'No_Lock\',
		    2,\'Row_Share\',
		    3,\'Row_Exclusive\',
		    4,\'Share\',
		    5,\'Share_Row_Exclusive\',
		    6,\'Exclusive\',null) lmode,
	    decode(L.REQUEST,1,\'No_Lock\',
		    2,\'Row_Share\',
		    3,\'Row_Exclusive\',
		    4,\'Share\',
		    5,\'Share_Row_Exclusive\',
		    6,\'Exclusive\',null) request
    from    V\$LOCK L,
	    V\$SESSION S,
	    SYS.USER\$ U1,
	    SYS.OBJ\$ T1
    where	L.SID = S.SID
    and	T1.OBJ# = decode(L.ID2,0,L.ID1,L.ID2)
    and	U1.USER# = T1.OWNER#
    and	S.TYPE != \'BACKGROUND\'
    order by 2,3,6;';
  ##print "sqlstmt=$sqlstmt\n";
  print "\n";
  print "User         Term     Sess,Ser   Table                        Lock Held           Lock Reqd.\n";
  print "------------ -------- ---------- ---------------------------- ------------------- -----------------\n";
  &oraSQL("$sqlstmt");
  foreach (@oraSQLout)
  {
    ##print;
    @words = split;
    $verb = $words[0];
    if ($verb eq "X")
    {
      $user = $words[1];
      $term = $words[2];
      $sess = $words[3];
      $tabl = $words[4];
      $held = $words[5];
      $reqd = $words[6];

      printf "%-12s %-8s %-10s %-28s %-20s %-20s\n",
        $user,$term,$sess,$tabl,$held,$reqd;

      $count++;
    }
  }
  print "\n";
  if ($count < 1) { &msg("No table locks found"); }
  exit;
}

# --------------------------------------------------------------------
# -sq
# --------------------------------------------------------------------
if ($arg eq "-sq")
{
  shift @ARGV;
  foreach $arg (@ARGV)
  {
    $sql .= "$arg ";
  }

  $sql .= " ; ";

  &msg("Executing SQL Statement: $sql");

  &oraSQL("$sql");
  foreach (@oraSQLout)
  {
    print;
  }
  exit;
}

# --------------------------------------------------------------------
# -sn
# --------------------------------------------------------------------
if ($arg eq "-sn")
{
  print "-sn: Create Oracle Diagnostic SNAPSHOT - Data Saved In UDUMP\n";
  system("$os_scmd <<@  2>&1
$os_conn
alter session set max_dump_file_size=unlimited;
alter session set events 'immediate trace name systemstate level 10';
!echo 'orastat Sleeping 60'
!sleep 60
alter session set events 'immediate trace name systemstate level 10';
!echo 'orastat Sleeping 60'
!sleep 60
alter session set events 'immediate trace name systemstate level 10';
!echo 'orastat Done'
@");

  exit;
}

# --------------------------------------------------------------------
# -lv
# --------------------------------------------------------------------
if ($arg eq "-lv")
{
  if (lc $host eq "phxprd" || lc $host eq "phxdev" || lc $host eq "agmxsv13")
  {
    $nonstandard = 1;   ## Allow orastat -lv to run on phoenix systems.
  }

  # Save BDF list
  @fss = `$bdfcmd | grep "^/dev"`;

  open(RO,'vgdisplay -v | grep "LV Name" |') || die "Cannot run vgdisplay";
  while (<RO>)
  {
    ##print;
    @words = split;
    $verb = $words[0];
    $lvol = $words[2];
    push(@lvs,$lvol);
  }
  close(RO);

  # Get list of links in /var/opt/oracle/rdisk
  if ($nonstandard)
  {
    @dblinks = `find /oradata* -type l | xargs ll | sed 's/rlvol/lvol/g' | awk '{print \$NF " " \$9}'`;
  }
  else
  {
    @dblinks = `find /var/opt/oracle/rdisk -type l | xargs ll | sed 's/rlvol/lvol/g' | awk '{ print \$NF " " \$9 }'`;
  }

  # Get list of datafiles/redo/ctl
  @datafiles = `orastat -de | grep CMD | awk '{ print substr(\$0,5) }'`;

  foreach $lv (@lvs)
  {
    $size = `lvdisplay $lv | grep 'LV Size' | awk '{ print \$4 }'`;
    chop($size);
    $usage = "";
    # Is is used as a FS?
    foreach $fs (@fss)
    {
      if ($fs =~ /^$lv/)
      {
        chop($fsraw = substr($fs,49));
        $usage = "(FS:$fsraw)";
        $totals{"FS Used Space:"} += $size;
      }
    }

    # Is is used as a oracle link?
    foreach $dblink (@dblinks)
    {
      @splitlv = split('/',$lv);
      @splitlink = split('/',$dblink);

      $vg = $splitlv[2];

      if ("$dblink " =~ /^$lv / || ($splitlink[3] =~ "r$splitlv[3]" && $nonstandard))
      {
        ##print "##HIT## dblink=$dblink lv=$lv\n";
        $_ = $dblink;
	@words = split;
	$lvol = $words[0];
	$link = $words[1];

	# Is is used as a datafile
        $dbusage = "";
	foreach $datafile (@datafiles)
	{
          ##print "datafile=$datafile link=$link\n";
	  if ($datafile =~ /^$link/)
	  {
            $_ = $datafile;
	    @words = split;
	    $dbusage .= $words[2];
	    $dbusage .= $words[3];
	    $dbusage .= $words[4];
	  }
        }

        if ($dbusage eq "")
        {
          $dbusage = "DBUnused";
        }

        $usage = sprintf("(DBUsage=%-16s DBLink=%-40s)",$dbusage,$link);

        if ($link)
        {
          $vginstances{$vg} .= $splitlink[8] . " " if $vginstances{$vg} !~ /$splitlink[8]/;
        }

        if ($lv =~ /\/dev\/vg_ops_1/)
        {
          $totals{"DB Used Space - vg_ops_1*:"} += $size;
        }
        else
        {
          $totals{"DB Used Space - vg_Other: "} += $size;
        }
      }
    }

    if ($usage eq "")
    {
      $usage = "(LVUnused)";
      $totals{"Unused Space:    "} += $size;
      $vg_freespace{$vg} += $size;
    }

    $vg_total{$vg} += $size;

    printf "%-22s %6d %-30s\n",$lv,$size,$usage;

    $totals{"Total Space:    "} += $size;
  }

  print "\n";
  &msg("Totals:");
  @sorted = sort keys %totals;
  foreach (@sorted)
  {
    $key = $_;
    printf "%-22s %6d\n",$key,$totals{$key};
  }

  print "\n";
  print "Volume Group     Size     Used     Free Instance(s)\n";
  print "------------ -------- -------- -------- --------------------\n";

  foreach $thisvg (sort keys %vg_total)
  {
    $vgsize = $vg_total{$thisvg};
    $vgfree = $vg_freespace{$thisvg};
    $vgused = $vgsize - $vgfree;

    printf "%-12s %8d %8d %8d %-s\n",$thisvg,$vgsize,$vgused,$vgfree,$vginstances{$thisvg};

    $t_size += $vgsize;
    $t_free += $vgfree;
    $t_used += $vgfree;
  }

  print "============ ======== ======== ========\n";
  printf "%-12s %8d %8d %8d %-s\n","Total:",$t_size,$t_used,$t_free;

  exit;
}

# --------------------------------------------------------------------
# -lw
# --------------------------------------------------------------------
if ($arg eq "-lw")
{
  print "-lw: Create Sym Links for 'rdisk' Raw Logical Volumes\n";
  # Save BDF list
  @unusedvols = `orastat -lv | grep '(Unused)' | egrep -v 'vg00|vg01|vg02' | sort | awk '{ print \$1 }'`;
  #print "num=$#unusedvols\n";

  # Find 1st unused disknn name
  chop($l = `ll -d /var/opt/oracle/rdisk* 2>&1`);
  if ($l eq "/var/opt/oracle/rdisk* not found")
  {
    $highdisk = 0;
  }
  else
  {
    chop($l = `ll -d /var/opt/oracle/rdisk* | tail -1 | awk '{ print \$NF}'`);
    $highdisk = substr($l,length($l)-2);
  }
  #print "$P | l=$l highdisk=$highdisk\n";
  print "$P | Highest Existing rdisk Link=$highdisk\n\n";

  foreach $lv (@unusedvols)
  {
    chop $lv;
    ##print "$P | Found unused volume: $lv\n";
    $thisdisk = ++$highdisk;
    if (length($thisdisk) < 2)
    {
      $thisdisko = "0" . $thisdisk;
    }
    else
    {
      $thisdisko = $thisdisk;
    }
    $lv =~ s/lvol/rlvol/g;
    print "ln -s $lv /var/opt/oracle/rdisk$thisdisko\n";
  }
  exit;
}

# --------------------------------------------------------------------
# -ps & -rac
# --------------------------------------------------------------------
if ($arg eq "-ps" || $arg eq "-rac")
{
  &msg("-ps: RAC (OPS) Status");
  $sqlstmt = '
select \'X\', status, parallel from v\$instance;
select \'Y\', inst_number, inst_name from v\$active_instances;
select \'Z\', value, name from v\$dlm_misc;';

  &oraSQL("$sqlstmt");
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $status  = $words[1];
      $par     = $words[2];
      print "\nParallel Server On: $par  Instance Status: $status\n";
      print "\nInstances in Cluster:\n\n";
      print "Node     Name\n";
      print "======== ==================\n";
    }
    if ($verb eq "Y")
    {
      $num     = "Node:" . $words[1];
      $name    = $words[2];
      printf "%-7s  %-30s\n",$num,$name;
    }
    if ($verb eq "Z")
    {
      if (!$zflag)
      {
	print "\nDLM Statistics:\n\n";
	print "Name                                 Value\n";
	print "==================================== =========\n";
        $zflag = 1;
      }
      $value    = $words[1];
      $name     = $words[2] . " " . $words[3] . " " . $words[4] . " " . $words[5] . " " . $words[6];
      printf "%-36s %9d\n",$name,$value;
    }
  }
  exit;
}

# --------------------------------------------------------------------
# -sal
# --------------------------------------------------------------------
if ($arg eq "-sal")
{
  if ($arg2 eq "" )
  {
    print "$P | Usage: $P -sal SESSION_NUMBER\n";
    exit 1;
  }
  $ses = $arg2;

  #---- Get running SQL
  print "\nSession SQL:\n";
  system("orastat -sr $ses 2>&1 | grep -v 'orastat |'");

  #---- Get running SQL
  print "\nSession Current Wait State:\n";
  system("orastat -sw | head -7 | grep -v 'orastat |'");
  system("orastat -sw | grep '^$ses ' 2>&1");

  print "\nSession Stats:\n";
  system("orastat -sc $ses 2>&1 | grep -v 'orastat |'");

  print "\n";
  &msg("$P | -sal Done");
  exit;
}

# --------------------------------------------------------------------
# -sr
# --------------------------------------------------------------------
if ($arg eq "-sr")
{
  if ($arg2 eq "" )
  {
    print "$P | Usage: $P -sr SESSION_NUMBER\n";
    exit 1;
  }
  &msg("orastat -sr: SQL Session $arg2");

  $sql = "select \'X\', sql_hash_value, prev_hash_value
  from
    v\\\$session
  where
    sid = $arg2 ; ";
  ##&msg("sql=$sql");
  &oraSQL("$sql");
  $sql  = "";
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb  = shift(@words);
    if ($verb eq "X")
    {
      &msg("Session $arg2 - SQLHashValue: $words[0]  PrevHashValue: $words[1]");
    }
  }

  &msg("SQL Statement:");
  $z = "-" x 80;
  print "$z \n";

  &srSub($arg2);

  $z = "-" x 80;
  print "$z \n";
  exit;
}

# --------------------------------------------------------------------
sub srSub
# --------------------------------------------------------------------
{
  $sessionid = $_[0];

  $sql = "select
  \'Z\',
  sql_text
from
  --v\\\$sqltext_with_newlines
  v\\\$sqltext
where
  address =
  (select sql_address from v\\\$session where sid = $sessionid)
order by
  piece;
";
  #print "sql=$sql \n";

  &oraSQL("$sql");
  $sql  = "";
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb  = shift(@words);
    if ($verb eq "Z")
    {
      $foundsql = 1;
      foreach (@words)
      {
        ##print "inword >$_< \n";
        $sql .= $_ . " ";
        $inword = $_;
      }
      ##chop $sql;
      # In some cases, pad with a blank to prevent the last word being joined with the first word of the next line
      $z = uc $inword;
      ##print "z=$z \n";
      if ($z eq "FROM" || $z eq "AND")
      {
        $sql .= " ";
      }
      ##print "sql    >$sql< \n";
    }
  }
  # Massage
  $_ = $sql;
  s/\n//g;
  $sql = $_;

  ##&msg("DEBUG - sql=$sql");

  $_ = $sql;
  $sqlout = "";
  @sqlwords = split;
  foreach (@sqlwords)
  {
    $word = $_;
    ##print "word=$word \n";
    $worduc = uc $word;
    $newlineflag = 0;
    $newlineflag = 1 if $worduc eq "SELECT" || $worduc eq "FROM" || $worduc eq "ORDER" || $worduc eq "WHERE" || $worduc eq "GROUP" || $worduc eq "FROM" || $worduc eq "UNION";
    $sqlout .= "\n" if $newlineflag;
    $sqlout .= $word;
    $sqlout .= "\n " if $newlineflag;
    $sqlout .= " ";
  }

  print "$sqlout";
  print "\n";
  print "Executing SQL for Session: $sessionid Not Found\n" if ! $foundsql;
  print "\n";
}

# --------------------------------------------------------------------
# -ug
# --------------------------------------------------------------------
if ($arg eq "-ug")
{
  &msg("-ug: User Grants (Much Output)");

  chop($date = `date`);
  if ($arg2 ne "")
  {
    $where = "where grantee = '$arg2'";
  }
  &msg("Date=$date Where=$where");

  $sqlstmt = "
  select
    \'X\',
    grantee,
    owner,
    table_name,
    privilege,
    grantable
  from dba_tab_privs
  ${where}
  order by 1,2,3;";

  print "Grantee                Table                                    Privilege    Grantable?\n";
  print "---------------------- ---------------------------------------- ------------ ----------\n";

  $count = 0;

  &oraSQL("$sqlstmt");
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $found = 1;
      $grantee = $words[1];
      $owner   = $words[2];
      $tab     = $words[3];
      $priv    = $words[4];
      $gable   = $words[5];

      $table = $owner . "." . $tab;
      $count++;

      printf("%-22s %-40s %-12s %-8s\n",$grantee,$table,$priv,$gable);
    }
  }
  print "\n";
  &msg("$count Grants found");
  exit;
}


# --------------------------------------------------------------------
# -ss
# --------------------------------------------------------------------
if ($arg eq "-ss")
{
  &msg("-ss: Default Storage Setting - By Tablespace");
  $sqlstmt = 'select \'X\',
         tablespace_name,
         initial_extent,
         next_extent,
         min_extents,
         max_extents,
         pct_increase
    from dba_tablespaces
    order by tablespace_name;';

  print "\n";
  print "Tablespace              Initial       Next        Min         Max Pct Increase\n";
  print "-------------------- ---------- ---------- ---------- ----------- ------------\n";

  &oraSQL("$sqlstmt");
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words = split;
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $found = 1;
      $ts = $words[1];
      $initial = $words[2];
      $next = $words[3];
      $min = $words[4];
      $max = $words[5];
      $pct = $words[6];
      printf("%-20s %10d %10d %10d %11d %12d\n",$ts,$initial,$next,$min,$max,$pct);
    }
  }
  if (!$found)
  {
    &msg("Something is wrong - query returned no rows");
    exit 1;
  }
  exit;
}

# --------------------------------------------------------------------
# bp
# --------------------------------------------------------------------
if ($arg eq "-bp")
{
  &msg("RMAN Backup Sessions");
  $sqlstmt = 'select \'X\',
    to_char(logon_time, \'DD-MON-YY\'),
    to_char(logon_time, \'HH24:MM:SS\'),
    sid,serial#,process,status,module
    from v\$session
    where module like \'%backup%\';';

  print "Start Date Start Time  SID    Serial#  Process  Status     Module\n";
  print "---------- ---------- ------ --------- -------- ---------- --------------------------\n";

  &oraSQL("$sqlstmt");
  foreach (@oraSQLout)
  {
    @words   = split();
    $verb    = $words[0];
    $date    = $words[1];
    $time    = $words[2];
    $sid     = $words[3];
    $serial  = $words[4];
    $process = $words[5];
    if ($process eq "ACTIVE" | $process eq "INACTIVE")
    {
      $process = ".";
      $status = $words[5];
    }
    else {$status  = $words[6];}
    $module  = $words[7] . " " . $words[8] . " " . $words[9] . " " . $words[10];
    if ($verb eq "X")
    {
      printf "%9s %9s %8s %9s %8s %10s %s\n", $date, $time, $sid, $serial, $process, $status, $module;
    }
  }
  exit;
}

# --------------------------------------------------------------------
# sp
# --------------------------------------------------------------------
if ($arg eq "-sp")
{
  &msg("StatsPack Data");
  $sqlstmt = 'select \'X\',
    to_char(snap_time, \'YYYY/MM/DD-HH24:MI:SS\'),
    snap_id,
    snap_level,
    sysdate - snap_time
    from perfstat.stats\$snapshot
    order by 2;';

  print " Snap ID Snap Timestamp      Snap Lvl Snap Age (Days)\n";
  print "-------- ------------------- -------- ---------------\n";

  &oraSQL("$sqlstmt");
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words   = split();
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $ts  = $words[1];
      $num = $words[2];
      $lvl = $words[3];
      $age = $words[4];
      $age = sprintf("%5.3f",$age);
      printf "%8s %18s %8s %15.3f\n", $num, $ts, $lvl, $age;
    }
  }
  exit;
}


# --------------------------------------------------------------------
# lh
# --------------------------------------------------------------------
if ($arg eq "-lh" || $arg eq "-lc")
{
  &msg("$arg: Lock Holders/Waiters (?/rdbms/admin/catblock.sql Must Have Been Run)");
  $sqlstmt = '
  alter session set optimizer_goal=RULE;
  select \'X\',
    waiting_session,
    holding_session,
    lock_type,
    mode_held,
    mode_requested,
    lock_id1,
    lock_id2
  from
    dba_waiters
    order by 1;';

  print "\n";
  print " Waiting  Holding Lock         Mode         Mode         Lock\n";
  print " Session  Session Type         Holding      Reqd.        ID1 ID2\n";
  print "-------- -------- ------------ ------------ ------------ -------------------------\n";

  &oraSQL("$sqlstmt");
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    ##print;
    @words   = split();
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $ses_wt   = $words[1];
      $ses_hld  = $words[2];
      $lk_type  = $words[3];
      $mode_hld = $words[4];
      $mode_req = $words[5];
      $lock_id  = "$words[6] $words[7] $words[8] $words[9] $words[10]";
      $age = sprintf("%5.1f",$age);
      printf "%-8s %-8s %-12s %-12s %-12s %s %s \n", $ses_wt, $ses_hld, $lk_type, $mode_hld, $mode_req, $lock_id;
      $counter++;

      if ($arg eq "-lc")
      {
        print "\n";
        print "=== (Start) === Session Details of Holding and Waiting sessions =========\n";
        #---- Holding session
        &lc_display($ses_hld,"Holding");
        #---- Waiting session
        &lc_display($ses_wt,"Waiting");
        print "=== (End) ===============================================================\n";
        print "\n";
      }
    }
  }
  print "\n";
  if ($counter < 1)
  {
    &msg("No Lock Waiters Found");
  }
  else
  {
    &msg("$counter Lock Waiter(s) Found");
  }
  exit;
}

sub lc_display
{
  $this_sid  = $_[0];
  $this_what = $_[1];
  print "\n";
  &msg("SQL running now for $this_what session $this_sid");
  system("orastat -sr $this_sid");
  print "\n";
  &msg("Session Details of $this_what session $this_sid");
  system("orastat -se | head -7 | tail -3");
  system("orastat -se | grep '^$this_sid,'");
  print "\n";
  &msg("Wait Status of $this_what session $this_sid");
  system("orastat -sw | head -7 | tail -3");
  system("orastat -sw | grep '^$this_sid '");
  print "\n";
}

# --------------------------------------------------------------------
# sb
# --------------------------------------------------------------------
if ($arg eq "-sb")
{
  &msg("-sb: Standby DB Log Gaps");
  $sqlstmt = '
    SELECT \'X\', high.thread#, "LowGap#", "HighGap#"FROM(
	SELECT thread#, MIN(sequence#)-1 "HighGap#"    FROM    (
	    SELECT a.thread#, a.sequence#        FROM        (            SELECT
    *
		FROM v\$archived_log        ) a,        (
		SELECT thread#, MAX(next_change#)gap1            FROM
    v\$log_history
		GROUP BY thread#        ) b        WHERE a.thread# = b.thread#
	    AND a.next_change# > gap1    )    GROUP BY thread#) high,(
	SELECT thread#, MIN(sequence#) "LowGap#"    FROM    (
	    SELECT thread#, sequence#        FROM v\$log_history, v\$datafile
	    WHERE checkpoint_change# <= next_change#
	    AND checkpoint_change# >= first_change#    )    GROUP BY thread#)
    low
    WHERE low.thread# = high.thread# AND "LowGap#" < "LowGap#";';

  print "       <=Missing Log Range=>\n";
  print "Thread        Low       High\n";
  print "------ ---------- ----------\n";

  &oraSQL("$sqlstmt");
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words   = split();
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $thread  = $words[1];
      $lo      = $words[2];
      $hi      = $words[3];
      printf "%6s %10s %10s\n", $thread, $lo, $hi;
    }
  }
  exit;
}

# --------------------------------------------------------------------
# rp
# --------------------------------------------------------------------
if ($arg eq "-rp")
{
  &msg("-rp: RMAN Long Operation Progression");
  $sqlstmt = '
    select \'Y\', value from v\$parameter where name = \'db_block_size\';
    select \'Z\',
      sid,
      serial#,
      context,
      sofar,
      totalwork,
      last_update_time - start_time,
      --round(sofar/totalwork*100,2) "PctComplete",
      to_char(start_time,\'YYYY/MM/DD-HH24:MI:SS\') ,
      to_char(last_update_time,\'YYYY/MM/DD-HH24:MI:SS\') ,
      opname
    from
      v\$session_longops
    where
      opname like \'RMAN%\'
      and opname not like \'RMAN: aggregate%\'
      --and sofar <> totalwork
    order by 8, 4;';

  print "SID-Ser#  Start               Last Updated        El. Mins  GB/Hour Work Sofar Work Total Pct. Done  Desc.\n";
  print "--------- ------------------- ------------------- -------- -------- ---------- ---------- ---------- ------------------------\n";

  &oraSQL("$sqlstmt");
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words   = split();
    $verb    = $words[0];
    $sid     = $words[1];
    $ser     = $words[2];
    #$context = $words[3];
    $sofar   = $words[4];
    $totalwk = $words[5];
    $etime   = sprintf("%5.1f",$words[6] * (24*60));
    $stime   = $words[7];
    $utime   = $words[8];
    $opname  = $words[9] . $words[10]  . $words[11]  . $words[12];

    if ($totalwk > 0) { $pctcomp = sprintf("%7.3f",($sofar/$totalwk)*100); }
    else              { $pctcomp = "*"; }

    $totalsize = $blocksize * $sofar;
    $gbrate = int((($totalsize / $etime) * 60) / (1024 * 1024 * 1024)) if $etime > 0;

    $sidser = "$sid-$ser";
    if ($verb eq "Y")
    {
      $blocksize = $words[1];
    }
    if ($verb eq "Z")
    {
      printf "%-9s %-19s %-19s %8s %8s %10s %10s %10s %-10s \n",$sidser,$stime,$utime,$etime, $gbrate, $sofar,$totalwk,$pctcomp,$opname;
    }
  }
  exit;
}

# --------------------------------------------------------------------
# tu
# --------------------------------------------------------------------
if ($arg eq "-tu")
{
  print "\n";
  &msg("-tu: Temp Segment Usage By User (From v\$sort_usage)\n");
  $sqlstmt = '
    select \'Y\',
      value
      from v\$parameter
      where
      name in (\'db_block_size\');
    select
      \'X\',
      sid,
      serial#,
      v\$session.username,
      extents,
      contents,
      blocks
    from
      v\$session,
      v\$sort_usage
    where
      v\$session.saddr = v\$sort_usage.session_addr
      ;
    ';

  print "SID-Ser#     User             Extents  Blocks   MB       Contents\n";
  print "------------ ---------------- -------- -------- -------- -------------\n";

  $t_blocks = 0;
  $t_mb = 0;

  &oraSQL("$sqlstmt");
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words   = split();
    $verb    = $words[0];
    $sid     = $words[1];
    $ser     = $words[2];
    $user    = $words[3];
    $ex      = $words[4];
    $contents = $words[5];
    $blocks  = $words[6];
    $sidser = "$sid-$ser";

    if ($verb eq "Y")
    {
      $blocksize = $words[1];
      ##print "blocksize=$blocksize\n";
      next;
    }

    if ($verb eq "X")
    {
      if ($user eq "") { $user = "."; }
      $mb = int(($blocks * $blocksize) / 1000000);
      ###print "user=$user\n";
      printf "%-12s %-16s %8s %8s %8s %-20s\n",
        $sidser,$user,$ex,$blocks,$mb,$contents;
      $t_blocks += $blocks;
      $t_mb += $mb;
    }
  }

  print "\n";
  &msg("Total TEMP Blocks In Use: $t_blocks");
  &msg("Total TEMP mB In Use:     $t_mb");
  exit;
}

# --------------------------------------------------------------------
# si
# --------------------------------------------------------------------
if ($arg eq "-si")
{
  print "\n";
  $sqlstmt = '
    select \'Y\',
      value
      from v\$parameter
      where
      name in (\'db_block_size\');
    select
      \'X\',
      tablespace_name,
      current_users,
      total_blocks,
      used_blocks,
      free_blocks,
      max_blocks
    from
      v\$sort_segment
    order by
      1
      ;
    ';

  &msg("-si: Sort Segment Information (From v\$sort_segment)\n");
  print "Temp TS Name        Cur-Users  SegSize(mB)      Used(mB)    Free(mb)  MaxUsed(mB)\n";
  print "---------------- ------------ ------------ ------------ ------------ ------------\n";

  &oraSQL("$sqlstmt");
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words   = split();
    $verb    = $words[0];

    if ($verb eq "Y")
    {
      $blocksize = $words[1];
      ##print "blocksize=$blocksize\n";
      next;
    }


    if ($verb eq "X")
    {
      $ts      = $words[1];
      $cusers  = $words[2];
      $tblocks = $words[3];
      $ublocks = $words[4];
      $fblocks = $words[5];
      $mblocks = $words[6];

      $tsize = int(($tblocks * $blocksize) / 1000000);
      $usize = int(($ublocks * $blocksize) / 1000000);
      $fsize = int(($fblocks * $blocksize) / 1000000);
      $msize = int(($mblocks * $blocksize) / 1000000);

      ##print "tblocks=$tblocks\n";

      printf "%-16s %12s %12s %12s %12s %12s\n",
        $ts,$cusers,$tsize,$usize,$fsize,$msize;

      $t_cusers += $cusers;

      $t_tsize += $tsize;
      $t_usize += $usize;
      $t_fsize += $fsize;
      $t_msize += $msize;
    }
  }

  print "================ ============ ============ ============ ============ ============\n";
  printf "%-16s %12s %12s %12s %12s %12s\n",
        "",$t_cusers,$t_tsize,$t_usize,$t_fsize,$t_msize;
  print "\n";

  exit;
}

# --------------------------------------------------------------------
# pf
# --------------------------------------------------------------------
if ($arg eq "-pf")
{
  &msg("Instance Total Freelist Wait Percentage");

  $sqlstmt = 'select
    \'X\',
    (a.count/sum(b.value))*100 free_list
  from
    v\$waitstat a,
    v\$sysstat b
  where
    a.class = \'free list\'
    and b.name in (\'db block gets\',\'consistent gets\')
  group by
    a.count;';

  print "\n";
  print "% Of Data Requests That\n";
  print "  Waited for a Freelist\n";
  print "-----------------------\n";

  &oraSQL("$sqlstmt");
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words   = split();
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $pct = $words[1] + 0;
      $pct = sprintf("%7.2f",$pct);
      printf "%23s\n", $pct;
    }
  }
  print "\n";

  if ($pct < 1)
  {
    &msg("Since the percent of total request that encountered a freelist");
    &msg("wait is less than 1, you don't need to add freelists.");
  }
  if ($pct >= 1)
  {
    &msg("Since the percent of total request that encountered a freelist");
    &msg("wait is >= l, consider adding freelists.");
  }
  exit;
}

# --------------------------------------------------------------------
# ck
# --------------------------------------------------------------------
if ($arg eq "-ck")
{
  &msg("Checkpoint Data");
  $sqlstmt = 'select \'X\',
    min(sysdate - CHECKPOINT_TIME) from v\$datafile_header;';

  &oraSQL("$sqlstmt");
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words  = split();
    $verb = $words[0];
    if ($verb eq "X")
    {
      $minago = $words[1] * 24 * 60;
      $minago = '.' if $minago eq "";
      printf "\nLastCheckpoint: %10.2f (Minutes Ago)\n",
        $minago;
    }
  }
  exit;
}

# --------------------------------------------------------------------
# sc
# --------------------------------------------------------------------
if ($arg eq "-sc")
{
  $where_ses = " and vs.sid = $arg2 " if $arg2;

  $sqlstmt = "select \'X\',
       vs.sid,
      vs.serial#,
      vs.type,
      vs.osuser,
      sysdate - logon_time logon_time,
      vs.process,
      vs.machine,
      vs.username,
      vss.value,
      vs.program
from   v\\\$session vs,
       v\\\$sesstat vss,
       v\\\$statname vsn
where (vss.statistic#=vsn.statistic#) AND
      (vs.sid=vss.sid) AND
      (vsn.name = \'CPU used by this session\') $where_ses
AND vss.value <> 0
order by 10;";

  &msg("Sessions - Ordered By Session CPU Time\n");
  print "                                                           ------------------------------------------Session------------------------------------------\n";
  print "SID-Ser#  OS:Userid-PID-Server     DB:User    Program       Hours  CPUTm Commit PFBlks TScans  MemSorts DiskSorts Con+BuGet PhysReads RHRat  LokWaitTm\n";
  print "--------- ------------------------ ---------- ------------ ------ ------ ------ ------ ------ --------- --------- --------- --------- ------ ---------\n";

  &oraSQL($sqlstmt);
  @saveSQLout = @oraSQLout;
  foreach (@saveSQLout)
  {
    ##print;
    @words      = split();
    $verb       = $words[0];
    $sid        = $words[1];
    $serial     = $words[2];
    $type       = $words[3];
    $osuser     = $words[4];
    $sessdur    = $words[5];
    $process    = $words[6];
    $machine    = $words[7];
    $username   = $words[8];
    $sesscpu    = $words[9];
    $program = $words[10] . $words[11] . $words[12] . $words[13];

    $sesser = $sid . "," . $serial;
    $comb = "$osuser-$process-$machine";
    $comb = substr($comb,0,24) if length($comb) > 24;
    $sdur = $sessdur * 24;
    $program = substr($program,0,12) if length($program) > 12;

    ##print "$sessdur $sdur\n";

    if ($verb eq "X")
    {
      # convert stat names into statistic#'s
      if ($statnumbers eq "")
      {
	$substmt = "
	  select distinct 'X', statistic#, name from v\\\$statname where name in (
	    'user commits',
	    'prefetched blocks',
	    'transaction lock foreground wait time',
	    'db block gets',
	    'consistent gets',
	    'physical reads',
	    'sorts (memory)',
	    'sorts (disk)',
	    'table scans (short tables)',
	    'table scans (long tables)'
	  ) order by 2;";
	&oraSQL($substmt);
	foreach (@oraSQLout)
	{
	  ##print;
	  @words      = split();
	  $verb = $words[0];
	  if ($verb eq "X")
	  {
	    $statnumbers .= "$words[1],";

            $commits_code  = $words[1] if (/user commits/);
            $prefetch_code = $words[1] if (/prefetched blocks/);
            $locktime_code = $words[1] if (/transaction lock foreground wait time/);
            $blkgets_code  = $words[1] if (/db block gets/);
            $congets_code  = $words[1] if (/consistent gets/);
            $preads_code   = $words[1] if (/physical reads/);
            $sorts_m_code  = $words[1] if (/sorts \(memory\)/);
            $sorts_d_code  = $words[1] if (/sorts \(disk\)/);
            $scans_s_code  = $words[1] if (/table scans \(short tables\)/);
            $scans_l_code  = $words[1] if (/table scans \(long tables\)/);
	  }
	}
	chop $statnumbers;
	#print "statnumbers=$statnumbers\n";
	#print "blkgets_code=$blkgets_code\n";
	#print "prefetch_code=$prefetch_code\n";
	#print "locktime_code=$locktime_code\n";
	#print "congets_code=$congets_code\n";
	#print "preads_code=$preads_code\n";
	#print "sorts_m_code=$sorts_m_code\n";
	#print "sorts_d_code=$sorts_d_code\n";
	#print "scans_s_code=$scans_s_code\n";
	#print "scans_l_code=$scans_l_code\n";
      }

      # Get other stats
      #&scSub2($sid,"4,84,38,40,180,181,150,151");
      ##print "statnumbers=$statnumbers\n";
      &scSub2($sid,"$statnumbers");
      foreach(@scArray)
      {
        @subwords = split;
        #print "stat=$subwords[0] value=$subwords[1]\n";

	$s_locktime = $subwords[1] if $subwords[0] == $locktime_code;
	$s_commits  = $subwords[1] if $subwords[0] == $commits_code;
	$s_prefetch = $subwords[1] if $subwords[0] == $prefetch_code;
	$s_blkgets  = $subwords[1] if $subwords[0] == $blkgets_code;
	$s_congets  = $subwords[1] if $subwords[0] == $congets_code;
	$s_phreads  = $subwords[1] if $subwords[0] == $preads_code;
 	$s_sorts_m  = $subwords[1] if $subwords[0] == $sorts_m_code;
 	$s_sorts_d  = $subwords[1] if $subwords[0] == $sorts_d_code;
 	$s_scans_s  = $subwords[1] if $subwords[0] == $scans_s_code;
 	$s_scans_l  = $subwords[1] if $subwords[0] == $scans_l_code;

        #print "sc=$s_commits\n";
      }
      $s_scans = $s_scans_s + $s_scans_l;
      if ($s_congets + $s_blkgets > 0)
      {
        $rhrat = (($s_congets + $s_blkgets - $s_phreads) / ($s_congets + $s_blkgets) * 100);
      }
      else
      {
        $rhrat = ".";
      }
      $rhrat = "-1" if $rhrat < 1;

      $gets = $s_congets + $s_blkgets;
      ##print "cg=$s_congets bg=$s_blkgets \n";;

      #$s_commits  = &scSub($sid,4);
      #$s_prefetch = &scSub($sid,84);
      #$s_blkgets = &scSub($sid,38);
      #$s_phreads = &scSub($sid,40);
      #$s_sorts_m = &scSub($sid,180);
      #$s_sorts_d = &scSub($sid,181);
      #$s_scans_s = &scSub($sid,150);
      #$s_scans_l = &scSub($sid,151);
      #$s_scans = $s_scans_s + $s_scans_l;

      printf "%-9s %-24s %-10s %-12s %6.1f %6.0f %6.0f %6.0f %6.0f %9.0f %9.0f %9.0f %9.0f %6.1f %9.0f\n",
        $sesser, $comb, $username, $program, $sdur, $sesscpu, $s_commits, $s_prefetch, $s_scans, $s_sorts_m, $s_sorts_d, $gets, $s_phreads, $rhrat, $s_locktime;
    }
  }
  exit;
}

sub scSub
{
  $mysid  = $_[0];
  $mystat = $_[1];

  $sqlsub = "select \'X\', value
    from  v\\\$sesstat
    where sid = $mysid and statistic# = $mystat;";
  &oraSQL($sqlsub);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words   = split();
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $value = $words[1];
    }
  }
  return $value;
}

sub scSub2
{
  $mysid   = $_[0];
  $mystats = $_[1];

  $sqlsub = "select \'X\', statistic#, value
    from  v\\\$sesstat
    where sid = $mysid and statistic# in ($mystats);";

  ##print "sqlsub=$sqlsub\n";

  &oraSQL($sqlsub);
  foreach (@oraSQLout)
  {
    ##print;
    print if /^ORA/;
    @words   = split();
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $stat  = $words[1];
      $value = $words[2];
      push(@scArray,"$stat $value");
    }
  }
  return;
}

# --------------------------------------------------------------------
# so
# --------------------------------------------------------------------
if ($arg eq "-so")
{
  &msg("-so: Sorts By User");
  $sqlstmt = 'select \'X\',
	   vss.value,
	   substr(vsn.name,1,20) "Type of Sort",
	   substr(vs.osuser,1,20) "os user",
    substr(vs.username,1,20) "db user"
    from   v\$session vs,
	   v\$sesstat vss,
	   v\$statname vsn
    where (vss.statistic#=vsn.statistic#) AND
	  (vs.sid=vss.sid) AND
	  (vsn.name like \'%sort%\')
	  AND vss.value <> 0
    order by 2,3;';

  print "DB User    OS User    Sort Type            Value\n";
  print "---------- ---------- --------------- ----------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words      = split();
    $verb       = $words[0];
    $value      = $words[1];
    $s_type1    = $words[2];
    $s_type2    = $words[3];
    $osuser     = $words[4];
    $dbuser     = $words[5];

    $s_type="$s_type1 $s_type2";
    $_=$dbuser;
    s/ //g;
    $dbuser=$_;
    $_=$osuser;
    s/ //g;
    $osuser=$_;
    if ($verb eq "X")
    {
      if ($dbuser eq "") { $dbuser = "."; }
      if ($osuser eq "") { $osuser = "."; }
      printf "%-10s %-10s %-15s %10s\n",
        $dbuser,$osuser,$s_type,$value;
    }
  }
  exit;
}


# --------------------------------------------------------------------
# wx
# --------------------------------------------------------------------
if ($arg eq "-wx")
{
  &msg("-wx: Wait Reason - By Event Type (Idle Waits Excluded)");
  $sqlstmt = 'select \'X\',
      count(*),
      \'.\',
      translate(sw.event,\' \',\'_\')
    from
      v\$session se,
      v\$session_wait sw
    where
      sw.sid = se.sid
      and se.username >= \'A\'
      and sw.event not like \'PX Deq%\'
      and sw.event not like \'SQL*Net%\'
      and sw.event not like \'pipe get%\'
      and sw.event not like \'wait for unread message%\'
      and sw.event not like \'%waiting for messages%\'
      and sw.event not like \'queue messages%\'
      and sw.event not like \'latch free\'
    group by
      \' \',
      translate(sw.event,\' \',\'_\')
    union all
    select \'X\',
      count(*),
      translate(la.name,\' \',\'_\'),
      translate(sw.event,\' \',\'_\')
    from
      v\$session se,
      v\$session_wait sw,
      v\$latch la
    where
      sw.sid = se.sid
      and se.username >= \'A\'
      and sw.event = \'latch free\'
      and sw.p2 = la.latch#
    group by
      translate(la.name,\' \',\'_\'),
      translate(sw.event,\' \',\'_\')
    order by
      2;
  ';

  print "\n";
  print "Wait Event                               Sessions Waiting\n";
  print "---------------------------------------- ----------------\n";

  $count_tot = 0;

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /ORA-/;
    @words      = split();
    $verb       = $words[0];

    ##print "v=$verb wc=$#words w0=$words[0]  w1=$words[1]  w2=$words[2]  w3=$words[3] \n";

    if ($verb eq "X")
    {
      $count     = $words[1];
      $p2        = $words[2];
      $text      = $words[3];

      if ($text eq "latch_free")
      {
        $text .= "_$p2";
      }

      printf "%-40s %16s\n", $text,$count;

      $count_tot += $count;
    }
  }
  exit;
}

# --------------------------------------------------------------------
# wt
# --------------------------------------------------------------------
if ($arg eq "-wt")
{
  ## &msg("-wt: Waits - By Event Type (Idle and Network Waits Excluded) >= 10g Only");
  &msg("-wt: Waits - By Event Type (Idle Waits Excluded) Ordered By Descending Session Count >= 10g Only");

  if ($oraver < 10)
  {
    &msg("orastat -wt Only works with Oracle 10g or Higher");
    exit;
  }

  $sqlstmt = 'select \'X\',
      count(*),
      translate(sw.wait_class,\' \',\'_\'),
      translate(sw.event,\' \',\'_\')
    from
      v\$session se,
      v\$session_wait sw
    where
      sw.sid = se.sid
      -- and se.username >= \'A\'
      and sw.event is not null
      and sw.wait_class != \'Idle\'
    group by
      translate(sw.wait_class,\' \',\'_\'),
      translate(sw.event,\' \',\'_\')
    order by
      2 desc;
  ';

  print "\n";
  print "Wait Event                               Wait Class   Sessions Waiting\n";
  print "---------------------------------------- ------------ ----------------\n";

  $count_tot = 0;

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /ORA-/;
    @words      = split();
    $verb       = $words[0];

    ##print "v=$verb wc=$#words w0=$words[0]  w1=$words[1]  w2=$words[2]  w3=$words[3] \n";

    if ($verb eq "X")
    {
      $count     = $words[1];
      $wait_class= $words[2];
      $text      = $words[3];

      next if $text =~ /message_to_client/;

      printf "%-40s %-12s %16s\n", $text,$wait_class,$count;

      $count_tot += $count;
    }
  }
  print "\n";
  &msg("Total Sessions Waiting: $count_tot");
  exit;
}

# --------------------------------------------------------------------
# wr
# --------------------------------------------------------------------
if ($arg eq "-wr")
{
  &msg("-wr: Wait Reasons - By User and Event Type (Idle Waits Excluded)");
  $sqlstmt = 'select \'X\',
      se.username,
      count(*),
      sw.event
    from
      v\$session se,
      v\$session_wait sw
    where
      sw.sid = se.sid
      and se.username > \'A\'
      and sw.event not like \'SQL*Net%\'
      and sw.event not like \'PX Deq%\'
      -- and sw.event not like \'PX Deq: Table Q Normal%\'
      -- and sw.event not like \'PX Deq: Execution Msg%\'
      and sw.event not like \'pipe get%\'
      and sw.event not like \'queue message%\'
      and sw.event not like \'wait for unread%\'
      and sw.event not like \'%waiting for messages%\'
    group by
      se.username, sw.event;
  ';

  print "\n";
  print "DB User    Wait Event Type                          Sessions Waiting\n";
  print "---------- ---------------------------------------- ----------------\n";

  $count_tot = 0;

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    print if /ORA-/;
    @words      = split();
    $verb       = $words[0];
    if ($verb eq "X")
    {
      $user      = $words[1];
      $count     = $words[2];
      $text = "";
      for ($i = 3; $i <= $#words; $i++)
      {
	$text .= $words[$i];
	$text .= " ";
      }

      printf "%-10s %-40s %16s\n", $user,$text,$count;

      $count_tot += $count;
    }
  }
  print "\n";
  &msg("Total Session(s) Waiting: $count_tot");
  exit;
}

# --------------------------------------------------------------------
# sa
# --------------------------------------------------------------------
if ($arg eq "-sa")
{
  &msg("-sa: Session Statistics");
  $sqlstmt = 'select \'X\',
	   sum(vss.value),
           count(*),
	   --substr(vsn.name,1,20)
	   vsn.name
    from
	   v\$sesstat vss,
	   v\$statname vsn
    where (vss.statistic#=vsn.statistic#)
	  AND vss.value <> 0
    --group by substr(vsn.name,1,20)
    group by vsn.name
    order by 4;';

  print "Session Statistic                                                      Value Sessions     Per Session\n";
  print "------------------------------------------------------------ --------------- -------- ---------------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    ##print;
    @words      = split();
    $verb       = $words[0];
    if ($verb eq 'X')
    {
      $value      = $words[1];
      $count      = $words[2];

      ##print "count=$count\n";

      $perses     = "";
      $perses     = int($value / $count) if $count > 0;

      $text = "";
      for ($i = 3; $i <= $#words; $i++)
      {
	$text .= $words[$i];
	$text .= " ";
      }
      printf "%-60s %15s %8s %15s\n",$text,$value,$count,$perses;
    }

  }
  exit;
}

# --------------------------------------------------------------------
# -br
# --------------------------------------------------------------------
if ($arg eq "-br")
{
  &msg("-br: Backups");

  $sqlstmt = 'select \'X\', max(recid) from v\$backup_set where incremental_level = \'0\';';
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    @words = split;
    $verb = $words[0];
    if ($verb eq "X")
    {
      $l0_recid = $words[1];
    }
  }
  &msg("Most recent L0 recid=$l0_recid");

  $sqlstmt = "select \'X\',
    to_char(completion_time,\'YYYY/MM/DD-HH24:MI:SS\')
    from v\\\$backup_set where recid = $l0_recid;";
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    @words = split;
    $verb = $words[0];
    if ($verb eq "X")
    {
      $l0_ts = $words[1];
    }
  }
  &msg("Most recent L0 timestamp=$l0_ts");

  $sqlstmt = "select \'X\',
    to_char(completion_time,\'YYYY/MM/DD-HH24:MI:SS\'),
    media
    from v\\\$backup_piece where recid >= $l0_recid;";
  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    @words = split;
    $verb = $words[0];
    if ($verb eq "X")
    {
      $ts = $words[1];
      $tp = $words[2];
      ##print "$ts $tp\n";
      if (index($tplist,$tp) == -1)
      {
        $tplist .= "$tp,";
        $tphash{$tp} = 1;
      }
    }
  }
  &msg("List of backup media that have been written to since the most recent LVL0:");
  @sorted = sort keys %tphash;
  foreach (@sorted)
  {
    print "Media: $_\n";
    $cnt++;
  }
  &msg("Found $cnt tape(s)");

  exit;
}

# --------------------------------------------------------------------
# -bi
# --------------------------------------------------------------------
if ($arg eq "-bi")
{
  &msg("-bi: Backups");
  $sqlstmt = '
     select \'X\',
            nvl(p.handle,\'?\'),
            nvl(p.media,\'?\'),
            to_char(p.completion_time,\'YYYY/MM/DD-HH24:MI:SS\'),
            decode(s.backup_type,\'L\',\'ARC\',\'I\',\'LVL1\',\'D\',\'LVL0\'),
            p.set_stamp
            from
	        v\$backup_set s,
	        v\$backup_piece p
	    where p.set_count=s.set_count
	    and p.deleted != \'YES\'
	    order by s.completion_time ;';

     $cnt=-1;

     &oraSQL($sqlstmt);
     foreach (@oraSQLout)
     {
        ## print;
        print if /^ORA/;
        @words = split;
        $verb = $words[0];

        if ($verb eq "X")
        {
           $bkp_piece    = $words[1];
           $media_name   = $words[2];
           $end_date     = $words[3];
           $bkp_type     = $words[4];

           $cnt+=1;
           $b_pieces[$cnt] = $bkp_piece;
           $b_info{$bkp_piece}{"media_name"} = $media_name;
           $b_info{$bkp_piece}{"end_date"} = $end_date;
           $b_info{$bkp_piece}{"bkp_type"} = $bkp_type;
        }
     }

     if (uc($arg2) eq "SINCE")
     {
	$retry_cnt = 0;
	do
	{
           $invalid_date = "false";
	   print ("\n");
           print ("Enter PIT (YYYY/MM/DD-HH24:MI:SS)\n");
           print ("          (ex: 2001/08/12-18:05:00): ");
           $pit = <STDIN>;
           chop($pit);
           if (substr($pit,4,1) ne "/" ||
               substr($pit,7,1) ne "/" ||
               substr($pit,10,1) ne "-" ||
               substr($pit,13,1) ne ":" ||
               substr($pit,16,1) ne ":")
           {
              print "\nERROR: Invalid date format.\n";
              $invalid_date = "true";
	      $retry_cnt += 1;
           }
	   if ($retry_cnt == 3)
	   {
              print "       Unable to continue after $retry_cnt attempts.\n\n";
	      exit 1;
	   }
         } until ($invalid_date ne "true");
     }
     elsif (uc($arg2) eq "BETWEEN")
     {
	$retry_cnt = 0;
	do
	{
	   $invalid_date = "false";
	   print ("\n");
           print ("Enter end time (YYYY/MM/DD-HH24:MI:SS)\n");
           print ("               (ex: 2001/08/12-18:05:00): ");
           $e_time = <STDIN>;
           chop($e_time);
           if (substr($e_time,4,1) ne "/" ||
               substr($e_time,7,1) ne "/" ||
               substr($e_time,10,1) ne "-" ||
               substr($e_time,13,1) ne ":" ||
               substr($e_time,16,1) ne ":")
           {
              print "\nERROR: Invalid date format.\n";
              $invalid_date = "true";
	      $retry_cnt += 1;
           }
	   if ($retry_cnt == 3)
	   {
              print "       Unable to continue after $retry_cnt attempts.\n\n";
	      exit 1;
	   }
         } until ($invalid_date ne "true");

	$retry_cnt = 0;
	do
	{
	   $invalid_date = "false";
	   print ("\n");
           print ("Enter start time (YYYY/MM/DD-HH24:MI:SS)\n");
           print ("                 (ex: 2001/08/10-12:05:00): ");
           $s_time = <STDIN>;
           chop($s_time);
           if (substr($s_time,4,1) ne "/" ||
               substr($s_time,7,1) ne "/" ||
               substr($s_time,10,1) ne "-" ||
               substr($s_time,13,1) ne ":" ||
               substr($s_time,16,1) ne ":")
           {
              print "\nERROR: Invalid date format.\n";
              $invalid_date = "true";
	      $retry_cnt += 1;
           }
	   if ($retry_cnt == 3)
	   {
              print "       Unable to continue after $retry_cnt attempts.\n\n";
	      exit 1;
	   }
         } until ($invalid_date ne "true");

	 $retry_cnt = 0;
	 if ($stime gt $e_time)
	 {
	    $temp = $s_time;
	    $s_time = $e_time;
	    $e_time = $temp;
	 }
     }

     printf("\n");
     $end_date = "Date/Time";
     $bkp_type = "Type";
     $media_name = "Tape#";
     $bkp_piece = "Backup Piece";
     printf ("%-20s %-8s %-10s %-30s \n",$end_date,$bkp_type,$media_name,$bkp_piece);
     for ($i=0;$i<=68;$i++)
     {
        printf ("-");
     }
     printf("\n");

     $cnt=-1;
     #$bt_found = "ARC";
     #$print_cnt = 0;
     #$pit_cnt = -1;
     foreach $bkp_piece (@b_pieces)
     {
        $cnt+=1;
        $media_name = $b_info{$bkp_piece}{"media_name"};
        $end_date   = $b_info{$bkp_piece}{"end_date"};
        $bkp_type   = $b_info{$bkp_piece}{"bkp_type"};

        if (uc($arg2) eq "ALL" || $arg2 eq "")
        {
           printf ("%-20s %-8s %-10s %-30s \n",$end_date,$bkp_type,$media_name,$bkp_piece);
        }
        elsif (uc($arg2) eq "SINCE")
        {
           if ($pit le $end_date &&
               $pit gt ${b_info{$bkp_piece + 1}{"end_date"}})
           {
             printf ("%-20s %-8s %-10s %-30s \n",$end_date,$bkp_type,$media_name,$bkp_piece);
           }
        }
        elsif (uc($arg2) eq "BETWEEN")
        {
           if ($end_date le $e_time &&
               $end_date ge $s_time)
           {
             printf ("%-20s %-8s %-10s %-30s \n",$end_date,$bkp_type,$media_name,$bkp_piece);
           }
        }
	else
	{
	   print "\nERROR: Invalid option.\n\n";
	   exit 1;
	}
     }
     print "\n";
     exit;
}

# --------------------------------------------------------------------
# -v
# --------------------------------------------------------------------
if ($arg eq "-v")
{
  @banner = `$oh/bin/sqlplus -?`;
  foreach $line (@banner)
  {
     if ($line =~ "SQL")
     {
        @words = split(' ',$line);
        $oraver = $words[2];
     }
  }
  print "\nVersion: $oraver\n";

  $oramode=`file $oh/bin/oracle |grep 64`;
  if (length ($oramode))
  {
     print "Oracle Binary: 64-bit\n";
  }
  else
  {
     print "Oracle Binary: 32-bit\n";
  }
  exit;
}

# --------------------------------------------------------------------
# pc
# --------------------------------------------------------------------
if ($arg eq "-pc")
{
  &msg("Accounts where username=password");
  $sqlstmt = 'select \'X\', username
    from dba_users
    order by 2;';

  print "\nUser accounts with username=password\n";
  print "------------------------------------\n";

  &oraSQL($sqlstmt);
  foreach (@oraSQLout)
  {
    print if /^ORA/;
    @words      = split();
    $verb       = $words[0];
    $user       = $words[1];
    if ($verb eq 'X')
    {
      @mySQLout = `sqlplus $user/$user<<!
        select * from dual;
        exit;
      !`;
      foreach (@mySQLout)
      {
        @string = split();
        $result = $string[0];
        if ($result eq 'X')
        {
          print "$user\n";
        }
      }
    }
  }
  exit;
}

# --------------------------------------------------------------------
# ph
# --------------------------------------------------------------------
if ($arg eq "-ph")
{
  $num = 200;
  &msg("-ph: Hot Blocks - Latch Children with > $num Sleeps and > $num Block Hits");
  $sqlstmt = "select /*+ ordered */ \'X\',
      e.owner ||\'.\'|| e.segment_name  segment_name,
      e.extent_id  extent#,
      x.dbablk - e.block_id + 1  block#,
      x.tch,
      l.child#,
      l.sleeps
    from
      sys.v\\\$latch_children  l,
      sys.x\\\$bh  x,
      sys.dba_extents  e
    where
      l.name    = \'cache buffers chains\' and
      l.sleeps  > $num and
      x.tch     > $num and
      x.hladdr  = l.addr and
      e.file_id = x.file# and
      x.dbablk between e.block_id and e.block_id + e.blocks - 1
    order by
      7 desc, 5 desc;";

  ##print "sqlstmt=$sqlstmt\n";
  &oraSQL("$sqlstmt");

  print "\n";
  print "  Sleeps     Hits Extent   Block# Children Segment\n";
  print "-------- -------- ------ -------- -------- ------------------------------\n";

  @saveSQLout1 = @oraSQLout;
  foreach (@saveSQLout1)
  {
    ##print;
    print if /^ORA/;
    @words   = split();
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $segment  = $words[1];
      $extent   = $words[2];
      $blocknum = $words[3];
      $tch      = $words[4];
      $childnum = $words[5];
      $sleeps   = $words[6];
      printf("%8s %8s %6s %8s %8s %-50s\n",$sleeps,$tch,$extent,$blocknum,$childnum,$segment);
      $foundit = 1;
    }
  }
  exit;
}

# --------------------------------------------------------------------
# pt
# --------------------------------------------------------------------
if ($arg eq "-pt")
{
  &msg("-pt: Hot Blocks - Top 25 Most Frequently Touched Non-SYS Blocks");
  $sqlstmt = 'select /*+ ordered */ \'X\',
      e.owner ||\'.\'|| e.segment_name  segment_name,
      e.extent_id  extent#,
      x.dbablk - e.block_id + 1  block#,
      x.tch
    from
      sys.x\$bh  x,
      sys.dba_extents  e
    where
      e.file_id = x.file# and
      x.dbablk between e.block_id and e.block_id + e.blocks - 1
    order by
      5 desc;';

  &oraSQL("$sqlstmt");

  print "\n";
  print " Touches   Extent   Block# Segment\n";
  print "-------- -------- -------- ------------------------------\n";

  @saveSQLout1 = @oraSQLout;
  foreach (@saveSQLout1)
  {
    ##print;
    print if /^ORA/;
    @words   = split();
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $segment  = $words[1];
      $extent   = $words[2];
      $blocknum = $words[3];
      $tch      = $words[4];
      next if $segment =~ /^SYS\./;
      printf("%8s %8s %8s %-50s\n",$tch,$extent,$blocknum,$segment);
      $count++;
    }
    last if $count >= 25;
  }
  exit;
}

# --------------------------------------------------------------------
# tq
# --------------------------------------------------------------------
if ($arg eq "-tq")
{
  &msg("-tq: Tablespace Defaults/Details");
  $sqlstmt = 'select \'X\',
      TABLESPACE_NAME           ,
      INITIAL_EXTENT            ,
      nvl(NEXT_EXTENT,\'-1\')   ,
      MIN_EXTENTS               ,
      nvl(MAX_EXTENTS,\'-1\')   ,
      nvl(PCT_INCREASE,\'-1\')  ,
      MIN_EXTLEN                ,
      STATUS                    ,
      CONTENTS                  ,
      LOGGING                   ,
      EXTENT_MANAGEMENT         ,
      ALLOCATION_TYPE           ,
      PLUGGED_IN                ,
      segment_space_management
    from
      dba_tablespaces
    order by
      2;';

  &oraSQL("$sqlstmt");

  print "\n";
  print "                            Extent     Extent                              Extent                                                Plugged\n";
  print "Tablespace           Status Init       Next       ExtMin   MaxExt   PctInc Min        Contents   Logging    ExtMgmt-AllocType    In         ASSM\n";
  print "-------------------- ------ ---------- ---------- -------- -------- ------ ---------- ---------- ---------- -------------------- ---------- ----------\n";

  $count = 0;

  @saveSQLout1 = @oraSQLout;
  foreach (@saveSQLout1)
  {
    ##print;
    print if /^ORA/;
    @words   = split();
    $verb    = shift @words;
    if ($verb eq "X")
    {
      $count++;

      $ts       = shift @words;
      $extini   = shift @words;
      $extnex   = shift @words;
      $extmin   = shift @words;
      $extmax   = shift @words;
      $pctinc   = shift @words;
      $extminln = shift @words;
      $status   = shift @words;
      $contents = shift @words;
      $logging  = shift @words;
      $extmgmt  = shift @words;
      $alloctyp = shift @words;
      $plugged  = shift @words;
      $ssm      = shift @words;

      $extmax = "(Unlim.)" if $extmax == 2147483645;
      $extmax = "(N/A)"    if $extmax == -1;

      $extminln = &formatNum($extminln);
      $extnex = &formatNum($extnex);
      $extini = &formatNum($extini);

      $extnex = "(N/A)"    if $extnex < 1;
      $pctinc = "(N/A)"    if $pctinc == -1;

      $extmgmt .= "-$alloctyp" if $alloctyp;

      ##&msg("DEBUG - alloctyp=$alloctyp ssm=$ssm");

      printf("%-20s %-6s %10s %10s %8s %8s %6s %10s %-10s %-10s %-20s %-10s %-10s\n",
	$ts ,
        $status   ,
        $extini   ,
        $extnex   ,
        $extmin   ,
        $extmax   ,
        $pctinc   ,
        $extminln ,
        $contents ,
        $logging  ,
        $extmgmt  ,
        $plugged,
        $ssm
      );
    }
  }

  print "\n";
  &msg("Found $count tablespaces");

  exit;
}

# --------------------------------------------------------------------
# pm
# --------------------------------------------------------------------
if ($arg eq "-pm")
{
  @words = split(/\./,$arg2);
  $owner = uc $words[0];
  $table = uc $words[1];

  if ($owner eq "" || $table eq "")
  {
    print "$P | Usage: $P -ti TABLE-OWNER.TABLE-NAME\n";
    exit 1;
  }
  &msg("-pm: Table Block Map for $owner.$table");

  $sqlstmt = "select /*+ ordered */
      \'X\',
      e.extent_id                extent#,
      x.dbablk - e.block_id + 1  block#,
      x.tch                      touches
    from
      sys.dba_extents  e,
      sys.x\\\$bh      x
    where
          e.owner =        \'$owner\'
      and e.segment_name = \'$table\'
      and e.segment_type = \'TABLE\'
      and e.file_id = x.file#
      and x.dbablk between e.block_id and (e.block_id + e.blocks - 1)
    order by
      2, 3;";

  $sqlstmt = "select /*+ ordered */
      \'X\',
      e.extent_id,
      e.block_id,
      e.blocks,
      e.file_id
    from
      sys.dba_extents e
    where
          e.owner =        \'$owner\'
      and e.segment_name = \'$table\'
      and e.segment_type = \'TABLE\'
    order by
      2;";

  &oraSQL("$sqlstmt");

  print "\n";
  print "  Extent   DF StartBlk   Length\n";
  print "-------- ---- -------- --------\n";

  @saveSQLout1 = @oraSQLout;
  foreach (@saveSQLout1)
  {
    ##print;
    print if /^ORA/;
    @words   = split();
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $extent   = $words[1];
      $blockstr = $words[2];
      $blocks   = $words[3];
      $file     = $words[4];
      next if $segment =~ /^SYS\./;
      printf("%8s %4s %8s %8s %-30s\n",$extent,$file,$blockstr,$blocks);
      $count++;
    }
    last if $count >= 25;
  }

  $sqlstmt = "select
      \'X\',
      x.dbablk,
      x.dbarfil,
      sum(x.tch)
    from
      sys.dba_objects  e,
      sys.x\\\$bh      x
    where
          e.owner =        \'$owner\'
      and e.object_name = \'$table\'
      and e.data_object_id = x.obj
    group by
      x.dbablk,
      x.dbarfil
    order by
      2;";


  &oraSQL("$sqlstmt");

  print "\n";
  print "   Block   DF  Touches \n";
  print "-------- ---- -------- ------------------------------\n";

  @saveSQLout1 = @oraSQLout;
  foreach (@saveSQLout1)
  {
    ##print;
    print if /^ORA/;
    @words   = split();
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $block   = $words[1];
      $file    = $words[2];
      $touches = $words[3];
      next if $segment =~ /^SYS\./;
      printf("%8s %4s %8s %-30s\n",$block,$file,$touches);
      $count++;
    }
    last if $count >= 25;
  }






  exit;
}

# --------------------------------------------------------------------
# pw
# --------------------------------------------------------------------
if ($arg eq "-pw")
{
  &msg("Blocks Experiencing BUFFER BUSY WAITS");
  $sqlstmt = 'select distinct \'X\', p1, p2
  from v\$session_wait
  where
    event = \'buffer busy waits\';';

  &oraSQL("$sqlstmt");
  @saveSQLout1 = @oraSQLout;
  foreach (@saveSQLout1)
  {
    ##print;
    print if /^ORA/;
    @words   = split();
    $verb    = $words[0];
    if ($verb eq "X")
    {
      $filenum  = $words[1];
      $blocknum = $words[2];
      &msg("Found BUFFER BUSY WAIT - filenum=$filenum blocknum=$blocknum");
      $foundit = 1;

      # Find the table name
      &oraSQL("select \'X\', file_name, tablespace_name from dba_data_files where file_id = $filenum;");
      @saveSQLout2 = @oraSQLout;
      foreach (@saveSQLout2)
      {
	##print;
	print if /^ORA/;
	@words   = split();
	$verb    = $words[0];
	if ($verb eq "X")
	{
          $filename  = $words[1];
          $tsname   = $words[2];
          &msg("  Datafile=$filenum Tablespace=$tsname Filename=$filename");
        }
      }

      # Find the table name

      # TEST
      ##$filenum = 6; $blocknum = 35707;

      $sql = "select /*+ RULE */
        \'X\',
        owner,
        segment_name,
        segment_type,
        tablespace_name,
        block_id,
        blocks
      from
        dba_extents
      where
        file_id = $filenum
        and block_id <= $blocknum
        and $blocknum <= ((block_id + blocks) - 1);";
      ##print "sql=$sql\n";
      &oraSQL("$sql");
      @saveSQLout3 = @oraSQLout;
      foreach (@saveSQLout3)
      {
	##print;
	print if /^ORA/;
	@words   = split();
	$verb    = $words[0];
	if ($verb eq "X")
	{
          $owner   = $words[1];
          $segment = $words[2];
          $type    = $words[3];
          $ts      = $words[4];
          $blockid = $words[5];
          $blocks  = $words[6];
          &msg("  Segment=$owner.$segment Type=$type TS=$ts - block_id=$blockid blocks=$blocks");
        }
      }
    }
  }
  if (!$foundit) { &msg("No BUFFER BUSY WAITS found"); }
  exit;
}


# --------------------------------------------------------------------
# -cv
# --------------------------------------------------------------------
if ($arg eq "-cv")
{
  &msg("Generating syntax to recompile Invalid Objects");
  $sqlstmt = "select \'X\','alter ' || object_type || ' ' || owner ||
              '.' || object_name || ' compile;'
              from dba_objects where status='INVALID';";

  &oraSQL($sqlstmt);
  #$tbl_cnt=-1;
  print "\n";
  foreach (@oraSQLout)
  {
    ## print;
    print if /^ORA/;

    if ($_ =~ "X")
    {
      s/X//;
      s/\n//;

      if (/PACKAGE BODY/)
      {
        s/PACKAGE BODY/PACKAGE/;
        s/;$/ body;/;
      }
      print "$_\n";
    }
  }
  print "\n";
  exit;
}

# --------------------------------------------------------------------
# -af
# --------------------------------------------------------------------
if ($arg eq "-af")
{
  &msg("-af: Archive Log Files (arc* files in archive log dir)");

  open(EXT, "echo '
    $os_conn
    archive log list
    ' | $os_scmd 2>&1 |") || die "Error running svrmgrl";

  while(<EXT>)
  {
    ##print;
    @words = split;
    $verb    = $words[0];
    if (/Database log mode/)
    {
      $arclogmode = $words[4];
    }
    if (/^Automatic archival/)
    {
      $arcauto    = $words[2];
    }
    if (/^Archive destination/)
    {
      $arcdirraw  = $words[2];
    }
  }
  close(EXT);

  # Fix - bb - svrmgrl lists arcdest2 if it exists - we don't
  # want that, so we will get the first disk dest from orastat -ad
  chop($arcdirnew = `orastat -ad | grep ' /' | head -1 | awk '{ print \$NF }'`);
  ##print "arcdirnew=$arcdirnew\n";
  #---- 3.05 - only do this if arcdirnew is non-null
  if ($arcdirnew && $arcdirraw ne $arcdirnew)
  {
    &msg("Overriding arcdirraw=$arcdirraw with $arcdirnew");
    $arcdirraw = $arcdirnew;
  }

  # Cut off last level of (example) /oracle/PD1/saparch/PD1arch
  #---- ONLY IF arcdirraw ends with arch
  $arcdir = $arcdirraw;

  if ($arcdir =~ /arch$/)
  {
    @words = split(/\//,$arcdirraw);
    $numlevels = $#words - 1;
    $arcdir = "";
    for ($i = 1; $i <= $numlevels; $i++)
    {
      $arcdir = $arcdir . "/" . $words[$i];
    }
  }

  chop $arcdir if $arcdir =~ /\/$/;

  &msg("arcdir: $arcdir (arcdirraw=$arcdirraw)");

  opendir(ARCDIR,"$arcdir");
  @filenames = readdir(ARCDIR);
  @filenamessorted = sort @filenames;
  closedir(ARCDIR);
  print "\n";
  print "Archive Log File Name                                  MTime      Age(Secs) Size      MTime-Formatted     CTime-Formatted\n";
  print "------------------------------------------------------ ---------- --------- --------- ------------------- -------------------\n";
  $numlogs = 0;
  $totsize = 0;
  $age     = -1;
  foreach $file (@filenamessorted)
  {
    next if ($file !~ /^arc/);
    $arcmtime = ( stat "$arcdir/$file" ) [9];
    $arcsize  = ( stat "$arcdir/$file" ) [7];
    $arcctime = ( stat "$arcdir/$file" ) [10];

    $arcmtime_fmt = &timeToText($arcmtime);
    $arcctime_fmt = &timeToText($arcctime);

    $age = time - $arcmtime;
    $oldest = $age if $age > $oldest;

    ##printf "%-54s %10s %9s %9s arcmtime_fmt=$arcmtime_fmt arcctime_fmt=$arcctime_fmt\n","$arcdir/$file",$arcmtime,$age,$arcsize,$arcctime;
      printf "%-54s %10s %9s %9s %s %s\n","$arcdir/$file",$arcmtime,$age,$arcsize,$arcmtime_fmt,$arcctime_fmt;

    $numlogs++;
    $totsize += $arcsize;
  }

  $totsize /= 1000000;
  $agedays = $age / (24*60*60);
  $agedays = sprintf("%8.3f",$agedays);
  $olddays = $oldest / (24*60*60);
  $olddays = sprintf("%8.3f",$olddays);

  print "\n";
  &msg("Total number of archive logs: $numlogs");
  &msg("Total size   of archive logs: $totsize (MB)");
  &msg("Most recent archive log age:  $age (Seconds)");
  &msg("Most recent archive log age:  $agedays (Days)");
  &msg("Oldest archive log age:       $olddays (Days)");

  exit;
}

# --------------------------------------------------------------------
# -af9i
# --------------------------------------------------------------------
if ($arg eq "-af9i")
{
  &msg("-af9i: Archive Log Files (arc* files in archive log dir)");

  open(EXT, 'echo "
    connect / as sysdba
    archive log list
    " | sqlplus /NOLOG 2>&1 |') || die "Error running svrmgrl";

  while(<EXT>)
  {
    ##print;
    @words = split;
    $verb    = $words[0];
    if (substr($_,0,22) eq "SQL> Database log mode")
    {
      $arclogmode = $words[4];
    }
    if (substr($_,0,18) eq "Automatic archival")
    {
      $arcauto    = $words[2];
    }
    if (substr($_,0,19) eq "Archive destination")
    {
      $arcdirraw  = $words[2];
    }
  }
  close(EXT);

  # Fix - bb - svrmgrl lists arcdest2 if it exists - we don't
  # want that, so we will get the first disk dest from orastat -ad
  chop($arcdirnew = `orastat -ad | grep ' /' | head -1 | awk '{ print \$NF }'`);
  ##print "arcdirnew=$arcdirnew\n";
  if ($arcdirraw ne $arcdirnew)
  {
    &msg("Overriding arcdirraw=$arcdirraw with $arcdirnew");
    $arcdirraw = $arcdirnew;
  }

  # Cut off last level of (example) /oracle/PD1/saparch/PD1arch
  @words = split(/\//,$arcdirraw);
  $numlevels = $#words;
  $arcdir = "";
  for ($i = 1; $i <= $numlevels; $i++)
  {
    $arcdir = $arcdir . "/" . $words[$i];
  }
  &msg("arclogdir: $arcdir");

  opendir(ARCDIR,"$arcdir");
  @filenames = readdir(ARCDIR);
  @filenamessorted = sort @filenames;
  closedir(ARCDIR);
  print "\n";
  print "Archive Log File Name                                  MTime      Age(Secs) Size\n";
  print "------------------------------------------------------ ---------- --------- ---------\n";
  $numlogs = 0;
  $totsize = 0;
  $age     = -1;
  foreach $file (@filenamessorted)
  {
    next if ($file !~ /^arc/);
    $arcmtime = ( stat "$arcdir/$file" ) [9];
    $arcsize  = ( stat "$arcdir/$file" ) [7];
    $arcctime = ( stat "$arcdir/$file" ) [10];
    ($sec,$min,$hour,$mday,$mon,$year) = localtime($arcmtime);
    $arcmtime_fmt = "$year/$mon/$mday-$hour:$min:$sec";
    ($sec,$min,$hour,$mday,$mon,$year) = localtime($arcctime);
    $arcctime_fmt = "$year/$mon/$mday-$hour:$min:$sec";

    $age = time - $arcmtime;
    $oldest = $age if $age > $oldest;
    printf "%-54s %10s %9s %9s arcmtime_fmt=$arcmtime_fmt arcctime_fmt=$arcctime_fmt\n","$arcdir/$file",$arcmtime,$age,$arcsize,$arcctime;
    $numlogs++;
    $totsize += $arcsize;
  }

  $totsize /= 1000000;
  $agedays = $age / (24*60*60);
  $agedays = sprintf("%8.3f",$agedays);
  $olddays = $oldest / (24*60*60);
  $olddays = sprintf("%8.3f",$olddays);

  print "\n";
  &msg("Total number of archive logs: $numlogs");
  &msg("Total size   of archive logs: $totsize (MB)");
  &msg("Most recent archive log age:  $age (Seconds)");
  &msg("Most recent archive log age:  $agedays (Days)");
  &msg("Oldest archive log age:       $olddays (Days)");

  exit;
}

# --------------------------------------------------------------------
# Menu
# --------------------------------------------------------------------

USAGE:
print "orastat | Version $version Usage:\n";
print "   --    View This Help File\n";
print "   -     Check for PMON Running, Show Oracle Version, Instance Status\n";
print "   -ab   List Archive Log RMAN Backups [Option Archive Log Sequence Number]\n";
print "   -ad   List Archive Destinations (v\$archive_dest)\n";
print "   -af   List Archive Log Directory Contents\n";
print "   -al   Show All Archived Logs \n";
print "   -amm  AMM (Automatic Memory Management) (sga_target) Stats\n";
print "   -an   Analyze Table COMPUTE STATISTICS - '$P -an TABLE-OWNER.TABLE-NAME'\n";
print "   -ar   Show Current DB Activity Rate\n";
print "   -asm  ASM Details & Status\n";
print "   -asm_dg  ASM Diskgroups\n";
print "   -asm_dk  ASM Disks\n";
print "   -asm_fi  ASM Files\n";
print "   -asm_op  ASM Operations\n";
print "   -au   Show DB Audit Status\n";
print "   -av   Archive Log Volume - [D/H] [# of days]\n";
print "   -az   Show Current DB Activity Rate - Log to $savedir/db_activity_rate_<SID>.txt\n";
print "   -ba   List Contents of dbamon.backup_age Table\n";
print "   -bb   List Summary of all RMAN backup pieces - from v\$backup_piece\n";
print "   -bc   List Contents of buffer pool\n";
print "   -bd   Datafile backup mode status\n";
print "   -bi   List RMAN backup inventory -- [ALL|SINCE|BETWEEN]\n";
print "   -bm   List Tablespaces and Datafiles in Backup Mode (from v\$backup)\n";
print "   -bo   Buffer Cache Overview (Many Reports)\n";
print "   -bp   List running RMAN backup sessions (if any)\n";
print "   -br   Backups: List all media written to since the last RMAN LVL0 backup\n";
print "   -brm  Backup Media: List all backup media\n";
print "   -bs   Create DDL to take datafiles that are in backup mode out of backup mode\n";
print "   -c    Configuration: View init.ora File\n";
print "   -cb   Controlfile Backup: Trace and Binary\n";
print "   -cc   Client Connections\n";
print "   -cd   Controlfile Details (Sections)\n";
print "   -cdb  List all DBs running al all nodes in SG cluster\n";
print "   -ce   Configuration: Edit 'vi' init.ora File\n";
print "   -cf   List Control Files\n";
print "   -ck   List Time of Last Checkpoint (from v\$datafile_headers)\n";
print "   -cm   Configuration: View Contents of v\$parameter with modifiable flags\n";
print "   -cp   Configuration: View Contents of v\$parameter\n";
print "   -ct   Coalesce TEMP tablespace\n";
print "   -cv   Generate syntax to recompile INVALID Objects\n";
print "   -da   List Datafiles - Autoextend details\n";
print "   -dc   List Datafiles in 'cp' commands to copy all datafiles elsewhere\n";
print "   -dd   Reproduce Object DDL (9i+ Only)\n";
print "   -dd    DDL  Table:      orastat -dd TABLE SCOTT DEPT\n";
print "   -dd    DDL  Index:      orastat -dd INDEX SCOTT DEPT_X\n";
print "   -dd    DDL  Tablespace: orastat -dd TABLESPACE \"\" TSNAME\n";
print "   -dd    DDL  User:       orastat -dd USER \"\" SCOTT\n";
print "   -dd    DDL  DBLink:     orastat -dd USER \"\" LINKNAME\n";
print "   -de   List All Datafiles, Online Redo Logs and Control Files (For Destroying a DB)\n";
print "   -df   List Datafiles - Optional FSCHECK 2nd parm to bdf filesystem\n";
print "   -df2  List Datafiles - from dba_data_files (for scripts)\n";
print "   -df3  List Datafiles - from v\$datafile\n";
print "   -df4  List Datafiles - which house S* tables with >= $arg2 () columns\n";
print "   -dgl  DataGuard - Log Apply Lag\n";
print "   -dh   List Datafiles and their 'Used Blocks' High-Water-Mark - Creates RESIZE commands\n";
print "   -di   Datafiles Contents (extents) by Block address - Must supply DF#\n";
print "   -dn   A Better and Faster version of -dh\n";
print "   -dp   Database properties (from DATABASE_PROPERTIES)\n";
print "   -dst  DST Patch checking\n";
print "   -du   List Datafiles where UNRECOVERABLE_CHANGE# is not null\n";
print "   -ec   Configuration: Edit 'vi' config.ora File\n";
print "   -emth EM - Alert Thresholds\n";
print "   -emac EM - Alerts - Current (DBA_OUTSTANDING_ALERTS)\n";
print "   -emah EM - Alerts - Historical (DBA_ALERTS_HISTORY)\n";
print "   -er   Display contents of DBA_ERRORS\n";
print "   -ev   Select from v\$system_event\n";
print "   -ex   Select from plan_table\n";
print "   -fm   Display hours since file modification time - Requires ARG\n";
print "   -fra  Flash Recovery Area Status\n";
print "   -fs   Free Space in Each Datafile\n";
print "   -ft   List 'Fast Start' Transactions being rolled back\n";
print "   -hd   Hot Tables - With Datafile Name\n";
print "   -ht   Hot Tables\n";
print "   -in   List Indexes\n";
print "   -iv   List INVALID Objects\n";
print "   -l    List Archive Log Status\n";
print "   -la   Latch Details (from v\$latch)\n";
print "   -lf   List Redo Log Files\n";
print "   -lg   Longops: Long Operation Progress\n";
print "   -lh   Lock Holders/Waiter\n";
print "   -li   List Resource Limits (v\$resource_limit)\n";
print "   -lk   Locks - Current TX (Non-Row) Locks\n";
print "   -ln   List DB Links\n";
print "   -lo   List Current Table Locks\n";
print "   -ls   Listener Status\n";
print "   -lv   List LVOL's / Usage\n";
#rint "   -lw   List LVOL's / Usage - Create ln -s Commands\n";
print "   -m    View Last 20 Lines Of Alert Log\n";
print "   -ma   Cat entire Alert Log\n";
print "   -mf   Tail -90f Alert Log\n";
print "   -mr   Alert log - reformatted - Last 20 lines\n";
print "   -mr a Alert log - reformatted - entire file\n";
print "   -mr v Alert log - reformatted - 'vi' entire file\n";
print "   -mt   MTS Statistics\n";
print "   -mv   'vi' (read-only mode) Of Alert Log\n";
print "   -nf   List Objects whose NEXT EXTENT will not fit in the tablespace\n";
print "   -nl   List NOLOGGING Tables and Indices\n";
print "   -ob   Objects - With Decimal and Hex Object ID\n";
print "   -op   OPS: View V\$PING - Lock Conversions\n";
print "   -pb   Performance: Current Data Block Buffer Hit Ratio - RIGHT NOW\n";
print "   -pc   Password Check: Check for accounts where username=password\n";
print "   -pd   Performance: View Data Block Buffer Hit Ratio\n";
print "   -pf   Performance: View Total Cumulative Free List Waits\n";
print "   -ph   Performance: Hot Blocks - Block With Latch Sleeps\n";
print "   -pi   Performance: View Histogram of Datafile I/O\n";
print "   -pj   Performance: I/O Distribution By Filesystem\n";
print "   -pk   Performance: I/O Distribution By Tablespace\n";
print "   -pp   Performance: I/O Service Times\n";
print "   -pr   List Profiles\n";
print "   -ps   OPS (Parallel Server) Status\n";
print "   -pul  Purge: Report from P_JOB_LOGGING\n";
print "   -pw   Performance: Show segment names for tables with buffer waits\n";
print "   -qs   SQL Statment Count\n";
print "   -ra   List Rollback Segment Activity\n";
print "   -rac  RAC Status (the same as orastat -ps)\n";
print "   -rb   List Rollback Segments\n";
print "   -rc   List And SHRINK All Rollback Segments\n";
print "   -rd   List And ALTER MAXEXTENTS UNLIMITED All Rollback Segments\n";
print "   -rf   View Timestamps from V\$RECOVER_FILE\n";
print "   -rg   View DBA_REGISTRY\n";
print "   -rh   List REDO Logs - History\n";
print "   -rl   List REDO Logs - Files\n";
print "   -ro   List Roles\n";
print "   -rp   RMAN Long Operation Progress\n";
print "   -rs   List REDO Logs - Status\n";
print "   -ru   Rollback Usage - By Session\n";
print "   -sa   Session Statistics - All Sessions\n";
print "   -sal  Session Data (All) - '$P -sal SESSION_NUMBER'\n";
print "   -sb   Standby DB - Show log gaps\n";
print "   -sc   Sessions - By Session CPU Time\n";
print "   -sd   Sessions - Details - Sessions, Running SQL and Waits\n";
print "   -se   Sessions Detail\n";
print "   -sed  Sessions Detail - Improved - SQL Running, Wait Class, Commit Count, etc.\n";
print "   -ser  Sessions Detail - Improved #2 - SQL Running, Wait Class, Commit Count, Rollback Count, etc.\n";
print "   -ses  Sessions Summary\n";
print "   -sg   List SGA Usage\n";
print "   -sh   Shared Pool Usage & Tuning Recommendations\n";
print "   -sl   SELECT * from table - name supplied as 2nd parameter\n";
print "   -sn   SNAPSHOT - Run systemstate trace 3 times (for Oracle diagnostics)\n";
print "   -so   List sorts by user\n";
print "   -sp   List StatsPack Snapshot Data\n";
print "   -spf  Display SPFILE (if any)\n";
print "   -sq   Run SQL - Pass SQL as argument in single quotes\n";
print "   -sr   View Running SQL - '$P -sr SESSION_NUMBER'\n";
print "   -ss   List default storage clause for all TABLESPACES\n";
print "   -st   System Statistics - from v\$sysstat\n";
print "   -su   System Utilization\n";
print "   -sw   Session Wait Statistics\n";
print "   -sy   List All Granted System Privileged\n";
print "   -sz   Session statistics for one session - 2nd parm is SID\n";
print "   -ta   List All Tables - From DBA_SEGMENTS (Name, TS, Size, Extents, Maxextents) - 2nd Arg 'ALL' to include SYS* tables\n";
print "   -tb   Count Tables - By Schema\n";
print "   -tc   Create SQL to count all rows in all permanent tables\n";
print "   -td   describe table - name of table supplied as 2nd parameter\n";
print "   -ti   Table Info - '$P -ti TABLE-OWNER.TABLE-NAME [-count]'\n";
print "   -tj   Datafile Space Allocated - By Filesystem\n";
print "   -tm   List Temporary Segments\n";
print "   -tp   List Objects (from DBA_SEGMENTS) By BLOCKS and BUFFER_POOL - Show buffer pool stats\n";
print "   -tq   Tablespaces - Details and Defaults\n";
print "   -tr   List Transactions\n";
print "   -ts   List Tablespaces\n";
print "   -tt   List 8i+ TEMPORARY Locally Managed Tablespaces\n";
print "   -tu   Temp space usage by user\n";
print "   -tz   List Tables - From DBA_TABLES - Shows ANALYZE data/timestamp\n";
print "   -ua   List USERS with incorrect default/temp tablespace - Creates SQL to ALTER USERS\n";
print "   -ub   List the byte count of data, by User\n";
print "   -ud   List Users With DBA role\n";
print "   -ug   List Users Table Grants (Much Output) - 2nd Parm is optional grantee name\n";
print "   -un   Display UNDO Statistics\n";
print "   -unl  Display UNDO Statistics - LONG\n";
print "   -uns  Display SMU UNDO Summary - Block Usage\n";
print "   -up   User Password Information\n";
print "   -us   List All Users\n";
print "   -ut   List the byte count of data, by User and Tablespace\n";
print "   -v    List Oracle version and whether it is 32-bit or 64-bit\n";
print "   -vs   List All Views\n";
print "   -vw   Count Views - By Schema\n";
print "   -wr   Wait Reasons - By User and Wait Type\n";
print "   -ws   Wait Stats - from v\$waitstat\n";
print "   -zr   List contents of DBAMON.STANDBY_REBUILD\n";

if ($company eq "thatcompany")
{
  print "\n";
  print "--------------------------------------------------------------------\n";
  print "THATCOMPANY-Specific Commands:\n";
  print "   -cfbl List trace controlfile backup with create timestamp > [numeric timestamp]\n";
  print "--------------------------------------------------------------------\n";
}
exit 0;
