#!/usr/bin/perl
#
#############################################################
# Name :     Ray Mahon                                      #
# Date :     02/02/05                                       #
#############################################################
#                      Description                          #
#############################################################
#  Extract and manipulate availability data.                #
#  Format into a Detail/Summary report.                     #
#  Also email specified addresses within file attachment.   #
# NB:                                                       #
#    You are only allow to select one period at a time, i.e #
#    (Daily or Weekly or Monthly).                          #
#                                                           #
# Areas reported on are:                                    #
#  (1) Nodes matched (Up and Down).                         #
#  (2) Discovered nodes.                                    #
#  (3) Node status not matches.                             #
#  (4) Detail % unavailable (Daily, Weekly, Monthly)        #
#  (5) Summary % unavailable (Daily, Weekly, Monthly)       #
#  (6) Summary No. of downs (Daily, Weekly, Monthly)        #
#############################################################
# Syntax:                                                   #
# Example                                                   #
# ./NV_Avail.pl -e -d -n -s -v -f /path/filename (Day)      #
# ./NV_Avail.pl -e -w -n -s -v -f /path/filename (week)     #
# ./NV_Avail.pl -e -m -n -s -v -f /path/filename (Month)    #
# Minimum required.                                         #
# ./NV_Avail.pl -d or -w or -m  To produce detail/sumary    #
#                               using the default file.     #
#                               (/usr/OV/databases)         #
#                                                           #
#############################################################
# Modification:                                             #
# The following Subroutines need to be merged into one.     #
#                  proce_daily_dta                          #
#                  proce_weekly_dta                         #
#                  proce_monthly_dta                        #
#############################################################
#   
use Time::Local;            # Add standard perl routine.
%node_hash = ();
%node_daily_hash = ();           # Daily hash        
%node_weekly_hash = ();          # Weekly hash
%node_monthly_hash = ();         # monthly hash
%tot_down_traps_per_ip = ();     # record count by ip-address of down events (-1

# Check options, output usage message if required and exit
   if(! &Getopts('dmnswef:v')){
      print "Usage:  conv_ip.pl [-d] [-e] [-f data filelist] [-m]  [-n] [-s] [-w] [-v]
                        -d Daily Report.
                        -w Weekly Report.
                        -m Monthly Report.
                        -s Summary.
                        -n Newly Discovered devices.
                        -e Email (email addresses within file email.txt)
                        -f Data file
                        -v Verbose (listing no matches)\n";
      exit 1;
   }

# Make sure that only one time period is selected i.e. (Daily, weekly, monthly)
  if ( $opt_d && $opt_w && $opt_m || $opt_d && $opt_w || $opt_d && $opt_m ) {
      print "\nUsage: -d or -w or -m (At the same time is not allowed.  Select either Daily or Weekly or Monthly only)
                     Please try again.\n";
      exit 1;
   }
  if ( $opt_w && $opt_d && $opt_m || $opt_w && $opt_d || $opt_w && $opt_m ) {
      print "\nUsage: -d or -w or -m (At the same time is not allowed.  Select either Daily or Weekly or Monthly only)
                     Please try again.\n";
      exit 1;
   }
  if ( $opt_m && $opt_d && $opt_w || $opt_m && $opt_w || $opt_m && $opt_d ) {
      print "\nUsage: -d or -w or -m (At the same time is not allowed.  Select either Daily or Weekly or Monthly only)
                     Please try again.\n";
      exit 1;
   }

# Check if file is supplied else use default(/usr/OV/databases/availData_*)
  if ( $opt_f ) { $avail_file=$opt_f; }
                else
                {
                 $avail_file="/usr/OV/databases/wrk_fle";
                 `cat /usr/OV/databases/availData_* > $avail_file`;
              }
#------------------------------------------------------------------------------#
#                                 M A I N                                      #
#------------------------------------------------------------------------------#
#
#-----------------------------------------#
# Open and read in data file.             #
#-----------------------------------------#
 print "Reading .";            # Processing
  open(NVLIST,"$avail_file") || die "Could not open excluded endpoints file ($avail_file).\n";
  foreach(<NVLIST>){
                    print ".";            # Processing
                    ($node_ip,$status,$tmp_stamp)= split;             # split into fields.
                    $node_ip=&int2quad($node_ip);                     # Convert back to IP Address.

                    # filter data, change status to text.
                      if ( $status eq "-1" ) { $status="Down"; &store_node();}   # Build hashs.
                      if ( $status eq "1" ) { $status="Up"; &store_node();}      # Build hashs.
                      if ( $status eq "Down" || $status eq "Up" ) {
                              $xx=1;}
                          else {
                             # Discoverd Node.
                               $discoverydate=scalar(localtime($tmp_stamp));                                 # Get date .
                               $len_pos=40;&formt_dta($status,$len_pos);$dis_node_pad=$status.$space_b;      # Pad nod with blanks.
                               $len_pos=17;&formt_dta($node_ip,$len_pos);$dis_ip_pad=$node_ip.$space_b;      # Pad IP with blanks.
                               push(@NODE_DIS, " $dis_node_pad $dis_ip_pad $discoverydate\n");}
                               
                  }
  close(NVLIST);

# Generate required data.
  &gen_rpt_detail();

 # Print Detail Header.
   if ($opt_d || $opt_w || $opt_s || $opt_m) {&Detail_head();}

 # Print Summary Header.
   if ($opt_s ) {&Summary_head();}

 # Write gathered data to defined files.
   &wrt_col_dat();

# Email report.
  if ($opt_e) { 
      &snd_info();    # sendmail
   }
#---------------------------------------------------#
# Store node data into hash.  Multiple entries are  #
# valid per node.                                   #
#---------------------------------------------------#
# Hash Structure:                                   #
#          Begintime -->                            #
#                        Node_IP --->               # 
#                                     Node_Value    #
#                                     Node_value    # 
#---------------------------------------------------#
sub store_node{

  $sep=",";
  $node_value=$tmp_stamp.$sep.$node_ip.$sep.$status;

 # Get begin (day,week,month)
   &get_begin_week();

 if ($opt_d || $opt_d && $opt_s) {
              # Build multiple entry hash (Daily).
                $node_value=$node_value.$sep.$begindaytime.$sep.$enddaytime;
                $node_daily_hash{$begindaytime}{$node_ip}{$node_value}=$node_value;
                }
 if ($opt_w || $opt_w && $opt_s) {
              # Build multiple entry hash (Weekly).
                $node_value=$node_value.$sep.$beginweek.$sep.$endofweek;
                $node_weekly_hash{$beginweek}{$node_ip}{$node_value}=$node_value;
              }
 if ($opt_m || $opt_m && $opt_s) {
              # Build multiple entry hash (Monthly).
                $node_value=$node_value.$sep.$beginmnttime.$sep.$endmonthtime;
                $node_monthly_hash{$beginmnttime}{$node_ip}{$node_value}=$node_value;
              }
}
#----------------------------#
# Generate report detail.    #
#----------------------------#
sub gen_rpt_detail{
           print "\nProcessing";            # Processing

if ($opt_d || $opt_s && $opt_d) {
             # Process daily data.
              &proce_daily_dta();
             } # End of if statement.

if ($opt_w || $opt_s && $opt_w) {
             # Process weekly data.
              &proce_weekly_dta();
             } # End of if statement.

if ($opt_m || $opt_s && $opt_m) {
             # Process monthly data.
              &proce_monthly_dta();
             } # End of if statement.
}
#------------------------------------#
# Process daily data.                #
#------------------------------------#
sub proce_daily_dta{
 # Get daily start time (hash key).
   foreach $begindaytime (sort keys %node_daily_hash){
     print ".";            # Processing
     $beginofday=scalar(localtime($begindaytime));                       # Get date .
     push(@DNODE_DTA, "Day: $beginofday\n");

     if ($opt_s ) { push(@SNODE_DTA, "\nDay: $beginofday\n");}           # Add date to summary report.

     # Get ip address from hash (hash key).
       foreach $rtn_node_ip (keys %{node_daily_hash->{ $begindaytime }} ) {
        $node_percent_dif=0;

         $prior_status="x";                                                   # reset prior status.

         # Get multiple values from that ip address.
           foreach $rtn_node_value (sort keys %{node_daily_hash->{ $begindaytime }->{$rtn_node_ip}} ) {
            ($tmp_stamp,$node_ip,$status,$start_time,$end_time)= split(/,/,$rtn_node_value);             # split into fields.
            if ( $status eq "Down" ) { $tot_down_traps_per_ip{$node_ip}++;}  # count IP down events (-1)

              # Check prior status.
                SWITCH: {
                         if ( $status eq "Down" && $prior_status ne "Down") { &proc_node_dta(); last SWITCH;}
                         if ( $status eq "Up" && $prior_status ne "Up" && $prior_status eq "Down") { &proc_node_dta(); last SWITCH;}

                        # Error up with no proir down.
                          $cvt_tmestamp=scalar(localtime($tmp_stamp));                                         # Get date .
                          $len_pos=17;&formt_dta($node_ip,$len_pos);$node_ip_pad=$node_ip.$space_b;            # Pad ip address.
                          $len_pos=26;&formt_dta($cvt_tmestamp,$len_pos);$cvt_tmestamp_pad=$cvt_tmestamp.$space_b;   # Pad date.
                          push(@NOMATCHNODE_DTA, " $node_ip_pad  $cvt_tmestamp_pad  has a status of $status with no partner status\n");
                       }  # End of Switch.
                $prior_status=$status;

                 }  # End of get value loop.

         # Error down with no proir up.
             if ( $down_time ne " " && $up_time eq " " && $node_ip ne " ") {
                $cvt_tmestamp=scalar(localtime($tmp_stamp));                       # Get date .
                $len_pos=17;&formt_dta($node_ip,$len_pos);$node_ip_pad=$node_ip.$space_b;     # Pad ip address.
                $len_pos=26;&formt_dta($cvt_tmestamp,$len_pos);$cvt_tmestamp_pad=$cvt_tmestamp.$space_b;   # Pad date.
                push(@NOMATCHNODE_DTA, " $node_ip_pad  $cvt_tmestamp_pad  has a status of $status with no partner status\n"); }

           $up_time=" ";
           $down_time=" ";

           # get percentage.
             &get_per_val();
        } # End of get IP Address loop.

             $prior_status="";

        } # End of begintime loop.
}
#------------------------------------#
# Process weekly data.               #
#------------------------------------#
sub proce_weekly_dta{
 # Get weekly start time (hash key).
               foreach $beginweek (sort keys %node_weekly_hash){
                 print ".";            # Processing
                 $beginofweek=scalar(localtime($beginweek));                       # Get date .
                 push(@DNODE_DTA, "Begin of Week: $beginofweek\n");
     
                 if ($opt_s ) {  push(@SNODE_DTA, "\nBegin of Week: $beginofweek\n");}           # Add date to summary report.

             # Get ip address from hash (hash key).
               foreach $rtn_node_ip (keys %{node_weekly_hash->{ $beginweek }} ) {
                $node_percent_dif=0;

                $prior_status="x";                                                   # reset prior status.

              # Get multiple values from that ip address.
                 foreach $rtn_node_value (sort keys %{node_weekly_hash->{ $beginweek }->{$rtn_node_ip}} ) {
                   ($tmp_stamp,$node_ip,$status,$start_time,$end_time)= split(/,/,$rtn_node_value);             # split into fields.
                   if ( $status eq "Down" ) { $tot_down_traps_per_ip{$node_ip}++;}  # count IP down events (-1)

               # Check prior status.
                 SWITCH: {
                          if ( $status eq "Down" && $prior_status ne "Down") { &proc_node_dta(); last SWITCH;}
                          if ( $status eq "Up" && $prior_status ne "Up" && $prior_status eq "Down") { &proc_node_dta(); last SWITCH;}

               # Error up with no proir down.
                 $cvt_tmestamp=scalar(localtime($tmp_stamp));                       # Get date .
                 $len_pos=17;&formt_dta($node_ip,$len_pos);$node_ip_pad=$node_ip.$space_b;     # Pad ip address.
                 $len_pos=26;&formt_dta($cvt_tmestamp,$len_pos);$cvt_tmestamp_pad=$cvt_tmestamp.$space_b;   # Pad date.
                 push(@NOMATCHNODE_DTA, " $node_ip_pad  $cvt_tmestamp_pad  has a status of $status with no partner status\n");

                         }  # End of Switch.
                $prior_status=$status;

                 }  # End of get value loop.

         # Error down with no proir up.
             if ( $down_time ne " " && $up_time eq " " && $node_ip ne " ") {
                $cvt_tmestamp=scalar(localtime($tmp_stamp));                       # Get date .
                $len_pos=17;&formt_dta($node_ip,$len_pos);$node_ip_pad=$node_ip.$space_b;     # Pad ip address.
                $len_pos=26;&formt_dta($cvt_tmestamp,$len_pos);$cvt_tmestamp_pad=$cvt_tmestamp.$space_b;   # Pad date.
                push(@NOMATCHNODE_DTA, " $node_ip_pad  $cvt_tmestamp_pad  has a status of $status with no partner status\n"); }

             $up_time=" ";
             $down_time=" ";
                # get percentage.
                 &get_per_val();

                } # End of get IP Address loop.

             $prior_status="";

                } # End of begintime loop.
}
#------------------------------------#
# Process monthly data.              #
#------------------------------------#
sub proce_monthly_dta{
 # Get monthly start time (hash key).
               foreach $beginmnttime (sort keys %node_monthly_hash){
                 print ".";            # Processing
                 $beginofmonth=scalar(localtime($beginmnttime));                       # Get date .
                 push(@DNODE_DTA, "Begin of Month: $beginofmonth \n");          
                 push(@SNODE_DTA, "Begin of Month: $beginofmonth\n");

             # Get ip address from hash (hash key).
               foreach $rtn_node_ip (keys %{node_monthly_hash->{ $beginmnttime }} ) {
                $node_percent_dif=0;

                $prior_status="x";                                                   # reset prior status.

              # Get multiple values from that ip address.
                 foreach $rtn_node_value (sort keys %{node_monthly_hash->{ $beginmnttime }->{$rtn_node_ip}} ) {
                   ($tmp_stamp,$node_ip,$status,$start_time,$end_time)= split(/,/,$rtn_node_value);             # split into fields.
                   if ( $status eq "Down" ) { $tot_down_traps_per_ip{$node_ip}++;}  # count IP down events (-1)

               # Check prior status.
                 SWITCH: {
                          if ( $status eq "Down" && $prior_status ne "Down") { &proc_node_dta(); last SWITCH;}
                          if ( $status eq "Up" && $prior_status ne "Up" && $prior_status eq "Down") { &proc_node_dta(); last SWITCH;}

               # Error up with no proir down.
                 $cvt_tmestamp=scalar(localtime($tmp_stamp));                       # Get date .
                 $len_pos=17;&formt_dta($node_ip,$len_pos);$node_ip_pad=$node_ip.$space_b;     # Pad ip address.
                 $len_pos=26;&formt_dta($cvt_tmestamp,$len_pos);$cvt_tmestamp_pad=$cvt_tmestamp.$space_b;   # Pad date.
                 push(@NOMATCHNODE_DTA, " $node_ip_pad  $cvt_tmestamp_pad  has a status of $status with no partner status\n");

                         }  # End of Switch.
                $prior_status=$status;

                 }  # End of get value loop.

         # Error down with no proir up.
             if ( $down_time ne " " && $up_time eq " " && $node_ip ne " ") {
                $cvt_tmestamp=scalar(localtime($tmp_stamp));                       # Get date .
                $len_pos=17;&formt_dta($node_ip,$len_pos);$node_ip_pad=$node_ip.$space_b;     # Pad ip address.
                $len_pos=26;&formt_dta($cvt_tmestamp,$len_pos);$cvt_tmestamp_pad=$cvt_tmestamp.$space_b;   # Pad date.
                push(@NOMATCHNODE_DTA, " $node_ip_pad  $cvt_tmestamp_pad  has a status of $status with no partner status\n"); }

             $up_time=" ";
             $down_time=" ";
                # get percentage.
                 &get_per_val();

                } # End of get IP Address loop.

             $prior_status="";

                } # End of begintime loop.
}
#------------------------------------#
# Process valid data.                #
#------------------------------------#
sub proc_node_dta{
   # Get difference between start and end dates.
     &chk_date_dif($start_time,$end_time);
     $per_date_dif=$percent_dif;                              # Numeric difference.
     $per_dif_time=$dif_time;                                 # Time difference.

   # Add count to down traps and change status to text value.  And pad fields.
     if ( $status eq "Up" && $down_time ne " ") {
         $up_time=$tmp_stamp;
         &chk_date_dif($up_time,$down_time);
         $node_percent_dif=$node_percent_dif+$percent_dif;
         $total_node_percent_dif=$total_node_percent_dif+$node_percent_dif;                  # Total value to this node.

         # Percentage.
           $node_percent_dif=$node_percent_dif/$per_date_dif*100;
           $_=$node_percent_dif;
           /(\d+).(\d+)/;                             # Strip out Status and Timestamp.
           $xx="$1."."$2";                            # cat strings
           $node_percent=sprintf("%.3f", $xx)." %";
           &pad_dta();

           push(@DNODE_DTA, " $node_ip_pad  $cvt_dtime_pad  $cvt_utime_pad  $dif_time_hr_pad    $node_percent\n");
    
           # Clear fields.
             $down_time=" ";
             $up_time=" ";
          }
           else { 
                 $down_time=$tmp_stamp;}
}
#-------------------------------#
# Get Percentage.               #
#-------------------------------#
sub get_per_val{
   $sum_total_node_percent_dif=$total_node_percent_dif;
   $total_node_percent_dif=$total_node_percent_dif/$per_date_dif*100;
   $_=$total_node_percent_dif;
   /(\d+).(\d+)/;                             # Strip out Status and Timestamp.
   $xx="$1."."$2";                            # cat strings
   $node_percent=sprintf("%.3f", $xx)." %";                  # round to three decimal places.
   $summary_node_tot=$tot_down_traps_per_ip{$node_ip};

   # Format summary data.
     if ( $summary_node_tot ne 0 ){
        # Summary
          &summary_format();
        }
    $tot_down_traps_per_ip{$node_ip}=0;            # zero value.
    $total_node_percent_dif=0;                     # zero value.
}
#---------------------------------#
# Summary format.                 #
# get percentage and pad fields.  #
#---------------------------------#
sub summary_format{
 # Summary times.
   $sum_difference=sprintf("%.0f", $sum_total_node_percent_dif);                  # round to three decimal places.
   $sum_seconds = $sum_difference % 60;
   $sum_difference = ($sum_difference - $sum_seconds) / 60;
   $sum_minutes = $sum_difference % 60;
   $sum_difference = ($sum_difference - $sum_minutes) / 60;
   $sum_hours = $sum_difference % 24;
   $sum_difference = ($sum_difference - $sum_hours) / 24;
   $sum_no_days = $sum_difference;
   $sum_days = $sum_difference % 7;
   $sum_weeks = ($sum_difference - $sum_days) / 7;

 # Pad reported data.
   $tot_time_hr="$sum_hours:$sum_minutes:$sum_seconds";
   $len_pos=10;&formt_dta($tot_time_hr,$len_pos);$tot_time_hr_pad=$tot_time_hr.$space_b;                            # Pad hours.
   $tot_time_dy="$sum_days"; $len_pos=2;&formt_dta($tot_time_dy,$len_pos);$tot_time_dy_pad=$tot_time_dy.$space_b;   # Pad Day.
   $tot_time_wk="$sum_weeks"; $len_pos=2;&formt_dta($tot_time_wk,$len_pos);$tot_time_wk_pad=$tot_time_wk.$space_b;  # Pad Week.
   $len_pos=17;&formt_dta($node_ip,$len_pos);$node_ip_pad=$node_ip.$space_b;                                        # Pad ip.
   $len_pos=4;&formt_dta($summary_node_tot,$len_pos);$summary_node_tot_pad=$summary_node_tot.$space_b;              # Pad No. Downs.
   $len_pos=12;&formt_dta($node_percent,$len_pos);$node_percent_pad=$node_percent.$space_b;                         # Pad percentage.
   $sum_dif_time_pad=$tot_time_hr_pad.$tot_time_dy_pad.$tot_time_wk_pad;
   push(@SNODE_DTA, " $node_ip_pad     $summary_node_tot_pad            $node_percent_pad         $sum_dif_time_pad\n");
}
#----------------------------#
# Get begin & End time for   #
# Day, week, month.          #
#----------------------------#
sub get_begin_week {

# Get date and time.
  ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime( $tmp_stamp );
  $mon=$mon+1;
  $year=$year+1900;

# Get the beginning time of day.
  $ss=0;$mm=00;$hh=00;$dd=$mday;$m=$mon-1;$yy=$year;
  $begindaytime = timegm($ss,$mm,$hh,$dd,$m,$yy);

# Get the end of day.
  $ss=59;$mm=59;$hh=23;$dd=$mday;$m=$mon-1;$yy=$year;
  $enddaytime = timegm($ss,$mm,$hh,$dd,$m,$yy);

# Get the beginning of the week.
  if ( $wday eq 1) { $beginweek=$begindaytime; }
  if ( $wday eq 0 && $wday ne 1 ) { $beginweek=$begindaytime-(6*86400); }
      else { $beginweek=$begindaytime-(($wday-1)*86400); }

# Get the End of the week.
  $endofweek=$beginweek+604799;

# Numeric End of month value.
  @EndofMonths = ('31', '28', '31', '30', '31', '30', '31', '31', '30', '31', '30', '31');

  # Get the Beginning of the month.
    $ss=0;$mm=00;$hh=00;$dd=1;$m=$mon-1;$yy=$year;
    $beginmnttime = timegm($ss,$mm,$hh,$dd,$m,$yy);

  # Get the ending of the month.
    $ss=59;$mm=59;$hh=23;$dd=$EndofMonths[$mon-1];$m=$mon-1;$yy=$year;
    $endmonthtime = timegm($ss,$mm,$hh,$dd,$m,$yy);
}
#-------------------------#
# check date difference   #
#-------------------------#
sub chk_date_dif {
   $utime_shift=shift;
   $dtime_shift=shift;

  # Dfference between dates
    $difference = $utime_shift - $dtime_shift;
    $percent_dif = $difference;                    # Used to obtain the percentage for detail and summary report.
    $seconds = $difference % 60;
    $difference = ($difference - $seconds) / 60;
    $minutes = $difference % 60;
    $difference = ($difference - $minutes) / 60;
    $hours = $difference % 24;
    $difference = ($difference - $hours) / 24;
    $no_days = $difference;
    $days = $difference % 7;
    $weeks = ($difference - $days) / 7;

  # Pad the difference fields.
    $dif_time="$hours:$minutes:$seconds   $days Days $weeks Weeks";
    $dif_time_hr="$hours:$minutes:$seconds";
    $dif_time_dy="$days";
    $dif_time_wk="$weeks";
    $len_pos=10;&formt_dta($dif_time_hr,$len_pos);$dif_time_hr_pad=$dif_time_hr.$space_b;     # Pad hours different.
    $len_pos=2;&formt_dta($dif_time_dy,$len_pos);$dif_time_dy_pad=$dif_time_dy.$space_b;      # Pad day different.
    $len_pos=3;&formt_dta($dif_time_wk,$len_pos);$dif_time_wk_pad=$dif_time_wk.$space_b;     # Pad week different.
    $dif_time_hr_pad=$dif_time_hr_pad.$dif_time_dy_pad.$dif_time_wk_pad;
}
#---------------------------------#
#           detail Header.        #
#---------------------------------#
sub Detail_head{
# Print Header.
push(@Dheader, "-----------------------------------------------------------------------------------------------------------------------\n");
push(@Dheader, "|                               D E T A I L   A V A I L A B I L T Y   R E P O R T                                     |\n");
push(@Dheader, "-----------------------------------------------------------------------------------------------------------------------\n");
push(@Dheader, "-----------------------------------------------------------------------------------------------------------------------\n");
push(@Dheader, " Node               Down Time                   Up Time                     Unavail Time        Percentage\n");
push(@Dheader, "                                                                            (Hour, Day, Week)\n");
push(@Dheader, "-----------------------------------------------------------------------------------------------------------------------\n");
push(@Dheadr2, "-----------------------------------------------------------------------------------------------------------------------\n");
push(@Dheadr2, "|                                       N O   M A T C H   T R A P S   R E P O R T                                     |\n");
push(@Dheadr2, "-----------------------------------------------------------------------------------------------------------------------\n");
}
#---------------------------------#
#          Summary Header.        #
#---------------------------------#
sub Summary_head{

# Print Header.
  push(@Sheader, " -------------------------------------------------------------------------------------------------------------------\n");
  push(@Sheader, "|                               S U M A R Y   A V A I L A B I L T Y   R E P O R T                                   |\n");
  push(@Sheader, "|-------------------------------------------------------------------------------------------------------------------|\n");
  push(@Sheader, "---------------------------------------------------------------------------------------------------------------------\n");
  push(@Sheader, " Node               Number of Downs   % Unavailable         Unavail Time\n");
  push(@Sheader, "                                                            (Hour, Day, Week)\n");
  push(@Sheader, "---------------------------------------------------------------------------------------------------------------------\n");

}
#---------------------------------#
#          Summary Header.        #
#---------------------------------#
sub Discovery_head{
# Print Header.
  push(@DISheader, " -------------------------------------------------------------------------------------------------------------------\n");
  push(@DISheader, "|                                             D I S C O V E R Y    R E P O R T                                      |\n");
  push(@DISheader, "|-------------------------------------------------------------------------------------------------------------------|\n");
  push(@DISheader, " Node                                     IP Address       Discovered Date\n");
  push(@DISheader, "---------------------------------------------------------------------------------------------------------------------\n");
}
#------------------------------------------#
# Write collected data to files.           #
#------------------------------------------#
#
sub wrt_col_dat{
# Open output files.

    push(@SPACER, "\n");

  # Top header.
   if ($opt_d || $opt_w || $opt_m) {
    chop($date_log= `date +"%h %d %H:%M:%S"`);
    push(@Hheader, "  Starting Time: $date_log\n");
    open(NODEDTA,">NV_Availability.log") || die "Could not open NODE_DTA data file NV_Availability.log.\n";
    print NODEDTA @Hheader;
    close(NODEDTA);
   }

 # Summary report.
   if ($opt_s ) {
    open(DEPLOY,">NV_Summary.log") || die "Could not open data file NV_Summary.log.\n";
    print DEPLOY @Sheader;
    print DEPLOY @SNODE_DTA;
    print DEPLOY @SPACER;
    close(DEPLOY);
   }

 # Daily/weekly Report.
   if ($opt_d || $opt_w || $opt_m) {
    open(DEPLOY,">>NV_Availability.log") || die "Could not open data file NV_Availability.log.\n";
    print DEPLOY @Dheader;
    print DEPLOY @DNODE_DTA;

    # List no matches if switch v selected.
    if ($opt_v) {
                print DEPLOY @Dheadr2;
                print DEPLOY @NOMATCHNODE_DTA;
                }
    close(DEPLOY);
   }
       print ". \nCompleted.\n";            # Processing
 
 # Discovered nodes report.
    if ($opt_n ) {
     # set header.
       &Discovery_head();
       open(DEPLOY,">>NV_Availability.log") || die "Could not open data file NV_Availability.log.\n";
       print DEPLOY @DISheader;
       print DEPLOY @NODE_DIS;
       print DEPLOY @SPACER;
       close(DEPLOY); }
}
#--------------------------------#
# Convert from IP to interger.   #
#--------------------------------#
sub quad2int {
      return unpack("N",pack("C4",split('\.',$_[0])));
   }
#--------------------------------#
# Convert from interger to IP.   #
#--------------------------------#
sub int2quad {
      return join('.',unpack('C4', pack("N", $_[0])));
   }
#---------------------------------------------------------#
#                Pad node data.                           #
#---------------------------------------------------------#
#
sub pad_dta {
  # Pad data and populate detail DNODE_DTA.
    $cvt_dtime=scalar(localtime($down_time));                       # Get date .
    $cvt_utime=scalar(localtime($up_time));                         # Get date.
    $len_pos=17;&formt_dta($node_ip,$len_pos);$node_ip_pad=$node_ip.$space_b;            # Pad ip address with blanks
    $len_pos=26;&formt_dta($cvt_dtime,$len_pos);$cvt_dtime_pad=$cvt_dtime.$space_b;      # Pad date with blanks.
    $len_pos=26;&formt_dta($cvt_utime,$len_pos);$cvt_utime_pad=$cvt_utime.$space_b;      # Pad  Date with blanks.
}
#---------------------------------------------------------#
#                Format data on output line.              #
#---------------------------------------------------------#
#
sub formt_dta {
  # Calculate string lenght and pad if needed.
    $str_val=shift;
    $str_no=shift;
    $length = length($str_val);
    $b_space = $str_no - $length;
    $cnt=0;
    $space_b="";
    while ( $cnt < $b_space) {
                     $space_b=$space_b." "; $cnt++;
    }
}
#------------------------------------------#
# getopts.pl - a better getopt.pl          #
#------------------------------------------#
# 
sub Getopts {
# Usage:
#      do Getopts('a:bc');  # -a takes arg. -b & -c not. Sets opt_* as a
#                           #  side effect.

    local($argumentative) = @_;
    local(@args,$_,$first,$rest);
    local($errs) = 0;
    local($[) = 0;
    @args = split( / */, $argumentative );
    while(@ARGV && ($_ = $ARGV[0]) =~ /^-(.)(.*)/) {
        ($first,$rest) = ($1,$2);
        $pos = index($argumentative,$first);
        if($pos >= $[) {
            if($args[$pos+1] eq ':') {
                shift(@ARGV);
                if($rest eq '') {
                    ++$errs unless @ARGV;
                    $rest = shift(@ARGV);
                }
                eval "\$opt_$first = \$rest;";
            }
            else {
                eval "\$opt_$first = 1";
                if($rest eq '') {
                    shift(@ARGV);
                }
                else {
                    $ARGV[0] = "-$rest";
                }
            }
        }
        else {
            print STDERR "Unknown option: $first\n";
            ++$errs;
            if($rest ne '') {
                $ARGV[0] = "-$rest";
            }
            else {
                shift(@ARGV);
            }
        }
    }
    $errs == 0;
}
#--------------------------------#
# Send report to email address.  #
#--------------------------------#
#
sub snd_info{
       # Open and read in email list file.
         open(MAILLIST,"email.txt") || die "Could not open email list file ($opt_m).\n";
          foreach(<MAILLIST>){
                              1 while $_ =~ s/\s$//g ;       # Remove trailing spaces
                              if ($opt_d || $opt_w || $opt_m) { 
                                       `mailx -s "Netview Availability Report" $_ NV_Availability.log`;
                              }
                              if ($opt_s) { 
                                       `mailx -s "Netview Summary Report" $_ NV_Summary.log`;
                              }
                             } # end of mail loop.
        close(MAILLIST);
}
exit 0
