#!/var/opt/STORtools/bin/perl 

require  "subroutines.pm";
&st_globals();

####################################################################
# storconfig
#  take snapshots of fcal configurations / state (Golden Snapshot)
#  compare the Golden snapshot to the current snapshot
# 
# Copyright (c) 1998  Sun Microsystems Computer Corporation, Inc.
####################################################################
$PROGNAME = "storconfig";

# Format the date command so that no SCCS expansion takes place
$cmd = "/usr/bin/date +%Y"."%m"."%d"."_"."%H"."%M";
chomp($DATE = `$cmd`);

$GOLDLOG    = "Golden_Snapshot_${DATE}";
$TEMPGOLD   = "Temp_" . $GOLDLOG;
$SNAPSHOT   = "Current_Snapshot";
$ERROR_LOG  = "${LOGDIR}/${PROGNAME}_error_log";

$SIG{INT} = 'int';

sub int {
    print "\nInterrupted\n";
    system("/usr/bin/rm -f $GOLD_PATH/$TEMPGOLD");
    exit;
}

&check_root_access( $PROGNAME );

# Turn on $VERBOSE output if the env variable DEBUG is defined
# and not 0 or not the null string.
if ($ENV{'DEBUG'}) {
	$VERBOSE = "TRUE";
}

&proc_cli;

open(MAIL, ">${ERROR_LOG}") or die "Unable to open mail log : $ERROR_LOG\n";
@header_msg = &st_header( "log" );
print MAIL "@header_msg";

# If we are saving a snapshot (golden log)
if ($SAVE) {

    &show_config if ($SHOW_CONF eq "TRUE");
    printf("Creating Configuration Snapshot File\n");
    &open_logfile($TEMPGOLD, $GOLD_PATH);
    &take_snapshot;
    &close_logfile;
    &move_gold_file( "${GOLD_PATH}/${TEMPGOLD}", "${GOLD_PATH}/${GOLDLOG}" );
    print "Golden Snapshot: ${GOLD_PATH}/${GOLDLOG}\n";

# If we are comparing snapshots
} elsif ($CMP) {

    &compare_files;
} elsif ($DISKMAP) {

    &show_disk_map;
}

# If we are sending mail close the file and send it
    close(MAIL);	

if ($MAIL_RECIPIENT && $ERROR_FLAG) {
    if(!mail_message($MAIL_RECIPIENT,  "$PRODUCT:storconfig:$STORAGE_DEVICE: Errors detected!", $ERROR_LOG)) {
		printf("Warining:  Mail message to $MAIL_RECIPIENT cannot be gererated\n");
    }
}

#
# BugTraq #4280945
# Remove the error log, if it exists
# otherwise terminate gracefully
# Added -f option to suppress error message if error log does not exist
#
`/usr/bin/rm -f $ERROR_LOG`;

exit(0);

#####################################################
#
#		 Subroutines
#
####################################################
####################################################
# show configuration prior to saving
####################################################
sub show_config {
    my ($resp);
    my ($yorn);
    $resp = "y";
    while (1) {
       print "Would you like to see a storage summary now?  [<y>, n]: ";
       $resp = &get_response;
       if (!(($resp =~/^n/i) | ($resp =~ /^y/i) | ($resp eq ""))) {
          print "\n '$resp' is an invalid choice.  Please try again.\n\n";
       } else {
         last;
       }
    }

    if ($resp =~/^n/i) {
       exit;
    }elsif (($resp =~ /^y/i) | ($resp eq "")) {
       $rc = 0xffff & system "${BINDIR}/cdmenu -live -do";
       if ($rc == 512) {
          # 
          # cdmenu received interrupt (ctrl-c)
          #
          exit;
       }

       $yorn = "y";
       while (1) {
          print "\n\nIs this configuration correct?  [<y = create snapshot>, n]: ";
          $yorn = &get_response;
          if ($yorn =~ /^n/i) {
             print "Please make the necessary corrections to ensure all loops and storage \n";
             print "are online.  Then Create Configuration Snapshot File. \n";
	     exit(1);
	  } elsif (($yorn =~ /^y/i) | ($yorn eq "")) {
	     # this will enable the user to take advantage of the fact 
	     # that a live config was just taken.  use this file instead
	     # of doing the probe again.
	     $RDMP_FILE = "TRUE";
             # this next line shouldn't be hardcoded
	     $RD_INFILE = $TMP_RAW;
             last;
	  } else {
             print "\n '$yorn' is an invalid choice.  Please try again.\n\n";
             }
       }
    } else {
       print "show_config: Code Error\n";
      }
}

sub compare_files {

    $CHANGES_DETECTED = "FALSE";

    $golden_log = &get_golden_snapshot;

    if (! ${golden_log}) {
        print "There is no golden snapshot available to compare with!\n";
	print "Please verify the system is configured correctly and \n";
	die   "then run '${PROGNAME} -save' for future comparisons.\n";
    }

    # Get the current snapshot
    &open_logfile($SNAPSHOT, $GOLD_PATH);
    &take_snapshot;
    &close_logfile;
    &compare_section_lines($golden_log, $SNAPSHOT, "STORSTAT:");
    &compare_packages($golden_log, $SNAPSHOT, "PKGINFO:");
    &compare_patches ($golden_log, $SNAPSHOT, "PATCHES:");

    &smart_compare($golden_log, $SNAPSHOT);
    &vm_compare($golden_log, $SNAPSHOT);
    if ($CHANGES_DETECTED eq "FALSE") {
        #
        # BugTraq # 4280943
        # Report that no changes were detected
        # if -mail option specified,
        #    then disable notification
        #
        if ( $MAIL_RESULTS ne "TRUE" ){
            print "No changes detected between system snapshots!\n";
        }
    }

}


sub compare_packages {
    my ($golden_log, $current_log, $section_name) = @_;
    print "\n$section_name\n" if ($VERBOSE);

    # Initialize the hash arrays
    undef %current;
    undef %golden;
    my $change_flag = "";
    my ($found_section, $line);

    open(GOLDEN,  "${GOLD_PATH}/$golden_log") or
	die "Unable to open golden logfile : ${GOLD_PATH}/$golden_log\n";
    $found_section = "FALSE";
    while ($line=<GOLDEN>) {
	chomp $line;
	if ($line =~ /^${section_name}/) {
	     $found_section = "TRUE";
	     next;	
	}
        next if ($found_section eq "FALSE");
	next if ($line =~ /^\s*$/);
	next if ($line =~ /^\s*#/);
	last if ($line =~ /^============/);
        ($type,$package,$description) = $line =~ /^(\S+)\s+(\S+)\s+(.*)/;
        if ($found_section eq "TRUE") {
	    $golden{$package} = $description;
	}
    }
    close(GOLDEN);

    open(CURRENT, "${GOLD_PATH}/$current_log") or
	die "Unable to open current logfile : ${GOLD_PATH}/$current_log\n";
    $found_section = "FALSE";
    while ($line = <CURRENT>) {
	chomp $line;
	if ($line =~ /^${section_name}/) {
	     $found_section = "TRUE";
	     next;
	}
        next if ($found_section eq "FALSE");
	next if ($line =~ /^\s*$/);
	next if ($line =~ /^\s*#/);
	last if ($line =~ /^============/);
        ($type,$package,$description) = $line =~ /^(\S+)\s+(\S+)\s+(.*)/;
	if ($found_section eq "TRUE") {
	     $current{$package} = $description;
	}
    }
    close(CURRENT);
    print "Check for packages that have been deleted:\n" if ($VERBOSE);
    foreach $package (sort (keys %golden)) {
	# If the key is not defined in the current list
	# something has changed
	if (! defined $current{$package}) {
	    $change_flag = "TRUE";
	    &logit("WARNING", 3003, "Package deleted since last snapshot : ${package}");
	}
    }
    print "Check for packages that have been installed:\n" if ($VERBOSE);
    foreach $package (sort (keys %current)) {
	if (! defined $golden{$package}) {
	    $change_flag = "TRUE";
	    &logit("WARNING", 3004, "Package installed since the last snapshot : ${package}");
	}
    }
    $CHANGES_DETECTED = "TRUE" if ($change_flag eq "TRUE");
    print "*** Changes detected! ***\n" if ($change_flag && $VERBOSE);
}

sub compare_patches {
    my ($golden_log, $current_log, $section_name) = @_;
    print "\n$section_name\n" if ($VERBOSE);

    # Initialize the hash arrays
    undef %current;
    undef %golden;
    my $change_flag = "";
    my ($found_section, $line);

    open(GOLDEN,  "${GOLD_PATH}/$golden_log") or
	die "Unable to open golden logfile : ${GOLD_PATH}/$golden_log\n";
    $found_section = "FALSE";
    while ($line=<GOLDEN>) {
	chomp $line;
	if ($line =~ /^${section_name}/) {
	     $found_section = "TRUE";
	     next;	
	}
        next if ($found_section eq "FALSE");
	next if ($line !~ /\d{6,6}-\d{2,2}/);
	next if ($line =~ /^\s*#/);
	next if ($line =~ /^\s*$/);
	last if ($line =~ /^============/);
        ($patch,$revision) = split(/-/, $line);
        if ($found_section eq "TRUE") {
	    $golden{$patch} = $revision;
	}
    }
    close(GOLDEN);

    open(CURRENT, "${GOLD_PATH}/$current_log") or
	die "Unable to open current logfile : ${GOLD_PATH}/$current_log\n";
    $found_section = "FALSE";
    while ($line = <CURRENT>) {
	chomp $line;
	if ($line =~ /^${section_name}/) {
	     $found_section = "TRUE";
	     next;
	}
        next if ($found_section eq "FALSE");
	next if ($line !~ /\d{6,6}-\d{2,2}/);
	next if ($line =~ /^\s*#/);
	next if ($line =~ /^\s*$/);
	last if ($line =~ /^============/);
        ($patch,$revision) = split(/-/, $line);
	if ($found_section eq "TRUE") {
	     $current{$patch} = $revision;
	}
    }
    close(CURRENT);
    print "Check for patches that have been deleted:\n" if ($VERBOSE);
    foreach $patch (sort (keys %golden)) {
	# If the key is not defined in the current list
	# something has changed
	if (! defined $current{$patch}) {
	    $change_flag = "TRUE";
	    &logit("WARNING", 3005, "Patch has been deleted since last snapshot : $patch");
	}
    }
    print "Check for patches that have been installed:\n" if ($VERBOSE);
    foreach $patch (sort (keys %current)) {
	if (! defined $golden{$patch}) {
	    $change_flag = "TRUE";
	    &logit("WARNING", 3006, "Patch has been deleted since last snapshot : $patch");
	}
    }
    print "Check for patches that have been upgraded:\n" if ($VERBOSE);
    foreach $patch (sort (keys %current)) {
	# Skip the ones that are not in the current installation
	next if (! defined $current{$patch}); 
	# skip the ones that are not in the original (Golden) installation
	next if (! defined $golden{$patch}); 
	# skip the ones that are the same, we only want differences
	next if ($current{$patch} == $golden{$patch});
	if ($current{$patch} > $golden{$patch}) {
	    $change_flag = "TRUE";
	    &logit("WARNING", 3007, "Patch has been upgraded since last snapshot : $patch");
	}
    }
    print "Check for patches that have been downgraded:\n" if ($VERBOSE);
    foreach $patch (sort (keys %current)) {
	# Skip the ones that are not in the current installation
	next if (! defined $current{$patch}); 
	# skip the ones that are not in the original (Golden) installation
	next if (! defined $golden{$patch}); 
	# skip the ones that are the same, we only want differences
	next if ($current{$patch} == $golden{$patch});
	if ($current{$patch} < $golden{$patch}) {
	    $change_flag = "TRUE";
	    &logit("WARNING", 3008, "Patch has been upgraded since last snapshot : $patch");
	}
    }
    print "*** Changes detected! ***\n" if ($change_flag && $VERBOSE);
    $CHANGES_DETECTED = "TRUE" if ($change_flag eq "TRUE");
}

sub compare_section_lines {

    my ($golden_log, $current_log, $section_name) = @_;
    my (@golden_section, @current_section, @temp);
    my ($line, $gold_counter, $golden_key, $curr_counter, $current_key);
    print "\n$section_name\n" if ($VERBOSE);

    my $change_flag = "";
    my ($found_section);

    open(GOLDEN,  "${GOLD_PATH}/$golden_log") or
	die "Unable to open file : ${GOLD_PATH}/$golden_log\n";
    $found_section = "FALSE";

    while ($line=<GOLDEN>) {
        chomp $line;
        $found_section = "TRUE" if ($line =~ /^${section_name}/);
        next if ($found_section eq "FALSE");
        next if ($line =~ /^\s*$/);
        next if ($line =~ /^\s*#/);
        last if ($line =~ /^============/);
        push @golden_section, $line if ($found_section eq "TRUE");
    }
    close(GOLDEN);

    open(CURRENT, "${GOLD_PATH}/$current_log") or
        die "Unable to open current logfile : ${GOLD_PATH}/$current_log\n";
    $found_section = "FALSE";
    while ($line = <CURRENT>) {
        chomp $line;
        $found_section = "TRUE" if ($line =~ /^${section_name}/);
        next if ($found_section eq "FALSE");
        next if ($line =~ /^\s*$/);
        next if ($line =~ /^\s*#/);
        last if ($line =~ /^============/);
        push @current_section, $line if ($found_section eq "TRUE");
    }
    close(CURRENT);
    #
    # remove all common lines leaving differences
    #
    $gold_counter = 0;
    @temp = (@golden_section);
    foreach $golden_key (@temp) {
        $curr_counter = 0;
        $remove_golden = 0;
        foreach $current_key (@current_section) {
            if ($golden_key eq $current_key) {
                splice(@current_section, $curr_counter,1);
                $remove_golden = 1;
                last;
            } else { 
                $curr_counter ++;
            }
        }
        if ($remove_golden) {
            splice(@golden_section, $gold_counter, 1);
        } else { 
            $gold_counter ++; 
        }
    }

    return if ($#golden_section == -1) and ($#current_section == -1);
    if ($#current_section == -1) {
        ###############################################
        # old messages are gone from current snapshot #
        ###############################################
        my ($info, $lines, $name, @raw_strings);
        if ($section_name =~ /RAWDUMP/) {
            ############################################
            # make rawdump results more human readable #
            ############################################
            foreach $info (@golden_section) {
                chomp $info;
                @raw_strings = split /\s+/, $info;
                if ($raw_strings[7] eq "DD") {
                    if ($raw_strings[0] =~ /T300/) {
                        $lines .= "ERROR : T300 LUN ($raw_strings[3]) offline\n";
                    } else {
                        $lines .= "ERROR : $raw_strings[0] Disk ($raw_strings[3]) offline\n";
                    }
                } elsif ($raw_strings[7] =~ /HA/) {
                    $lines .= "ERROR : HA $raw_strings[8] Loop $raw_strings[9] ($raw_strings[10]) offline\n";
                } elsif ($raw_strings[7] =~ /IB/) {
                    my ($raw_enclosure, $raw_loop) = split /,/, $raw_strings[0];
                    $lines .= "ERROR : Enclosure $raw_enclosure (Loop $raw_loop) offline\n";
                }
            }
        } else {
            foreach $current_key (@golden_section) {
                $lines .= "  $current_key\n";
            }
        }

        $change_flag = "TRUE";
        &logit("ERROR", 4017, "Change detected, hardware offline or missing\n$lines");

    } elsif ($#golden_section == -1) {
        ##############################
        # new messages not in golden #
        ##############################
        $change_flag = "TRUE";
        my ($info, $lines, $name, @raw_strings);
        if ($section_name =~ /RAWDUMP/) {
            ############################################
            # make rawdump results more human readable #
            ############################################
            foreach $info (@current_section) {
                chomp $info;
                @raw_strings = split /\s+/, $info;
                if ($raw_strings[7] eq "DD") {
                    if ($raw_strings[0] =~ /T300/) {
                        $lines .= "WARNING : T300 LUN ($raw_strings[3]) online\n";
                    } else {
                        $lines .= "WARNING : $raw_strings[0] Disk ($raw_strings[3]) online\n";
                    }
                } elsif ($raw_strings[7] =~ /HA/) {
                    $lines .= "WARNING : HA $raw_strings[8] Loop $raw_strings[9] ($raw_strings[10]) online\n";
                } elsif ($raw_strings[7] =~ /IB/) {
                    my ($raw_enclosure, $raw_loop) = split /,/, $raw_strings[0];
                    $lines .= "WARNING : Enclosure $raw_enclosure (Loop $raw_loop) online\n";
                }
            }
        } else {
            foreach $current_key (@current_section) {
                $lines .= "  $current_key\n";
            }
        }
        &logit("WARNING", 3010, "Change detected, new hardware online, creating new snapshot recommended\n$lines");
    } else {
        ###################################
        # some different messages in each #
        ###################################
        my ($info, $lines, $name, @raw_strings);
        $change_flag = "TRUE";
        $lines .= " Current Configuration:\n";
        if ($section_name =~ /RAWDUMP/) {
            ############################################
            # make rawdump results more human readable #
            ############################################
            foreach $info (@current_section) {
                chomp $info;
                @raw_strings = split /\s+/, $info;
                if ($raw_strings[7] eq "DD") {
                    if ($raw_strings[0] =~ /T300/) {
                        $lines .= "WARNING : T300 LUN ($raw_strings[3]) offline\n";
                    } else {
                        $lines .= "WARNING : $raw_strings[0] Disk ($raw_strings[3]) offline\n";
                    }
                } elsif ($raw_strings[7] =~ /HA/) {
                    $lines .= "WARNING : HA $raw_strings[8] Loop $raw_strings[9] ($raw_strings[10]) offline\n";
                } elsif ($raw_strings[7] =~ /IB/) {
                    my ($raw_enclosure, $raw_loop) = split /,/, $raw_strings[0];
                    $lines .= "WARNING : Enclosure $raw_enclosure (Loop $raw_loop) offline\n";
                }
            }
        } else {
            foreach $current_key (@current_section) {
                $lines .= "  $current_key\n";
            }
        }
        $lines .= " Golden Configuration:\n";
        if ($section_name =~ /RAWDUMP/) {
            ############################################
            # make rawdump results more human readable #
            ############################################
            foreach $info (@golden_section) {
                chomp $info;
                @raw_strings = split /\s+/, $info;
                if ($raw_strings[7] eq "DD") {
                    if ($raw_strings[0] =~ /T300/) {
                        $lines .= "WARNING : T300 LUN ($raw_strings[3]) online\n";
                    } else {
                        $lines .= "WARNING : $raw_strings[0] Disk ($raw_strings[3]) online\n";
                    }
                } elsif ($raw_strings[7] =~ /HA/) {
                    $lines .= "WARNING : Host Adapter Loop ($raw_strings[10]) online\n";
                } elsif ($raw_strings[7] =~ /IB/) {
                    my ($raw_enclosure, $raw_loop) = split /,/, $raw_strings[0];
                    $lines .= "WARNING : Enclosure $raw_enclosure (Loop $raw_loop) online\n";
                }
            }
        } else {
            foreach $current_key (@golden_section) {
                $lines .= "  $current_key\n";
            }
        }
	print "WARNING : $lines\n";

        &logit("WARNING", 3010, "Change detected, analyze the messages\n");
    }
    print "*** Changes detected! ***\n" if ($change_flag && $VERBOSE);
    $CHANGES_DETECTED = "TRUE" if ($change_flag eq "TRUE");
}

sub close_logfile {

    close LOG;

}

sub move_gold_file {
    my ($fileone, $filetwo) = @_;
    system("/usr/bin/mv", $fileone, $filetwo);
}

sub take_snapshot {

    &header;
    &storstat;
    &disklist;
    &disk_inquiry;
    &rawdump;
    &port_summary;
    &pkginfo;
    &showrev;
    &volume_manager_summary;
    &luxadm_port;
    &luxadm_probe;
    &luxadm_sysdump;
}

sub pkginfo {
    print LOG "PKGINFO:\n\n";
    $pkginfo = `/bin/pkginfo`;
    print LOG $pkginfo;
    &print_field_seperator;
}

sub disklist {
    print LOG "DISKLIST:\n\n";
    $disklist = `/usr/bin/ksh -c '${BINDIR}/disklist 2>&1'`;
    if ($disklist =~ /not\s+found/i) {
	print "ERROR : ${BINDIR}/disklist not found!\n";
    }
    print LOG $disklist;
    &print_field_seperator;
}

sub disk_inquiry {
    print LOG "DISK INQUIRY:\n\n";
    $disk_inq = `/usr/bin/ksh -c '${BINDIR}/disk_inquiry -d -P -q 2>&1'`;
    if ($disk_inq =~ /not\s+found/i) {
	print "ERROR : ${BINDIR}/disk_inquiry not found!\n";
    }
    print LOG $disk_inq;
    &print_field_seperator;
}

sub luxadm_port {
    print LOG "LUXADM PORT:\n\n";
    $luxadm = `/usr/bin/ksh -c '/usr/sbin/luxadm -e port 2>&1'`;
    if ($luxadm =~ /not\s+found/i) {
	print "ERROR : luxadm not found!\n";
    }
    print LOG $luxadm;
    &print_field_seperator;
}

sub luxadm_probe {
    print LOG "LUXADM PROBE:\n\n";
    $luxadm = `/usr/bin/ksh -c '/usr/sbin/luxadm probe 2>&1'`;
    if ($luxadm =~ /not\s+found/i) {
	print "ERROR : luxadm not found!\n";
    }
    print LOG $luxadm;
    &print_field_seperator;
}

sub luxadm_sysdump {
    print LOG "LUXADM SYSDUMP:\n\n";
    $luxadm = `/usr/bin/ksh -c '/usr/sbin/luxadm sysdump 2>&1'`;
    if ($luxadm =~ /not\s+found/i) {
	print "ERROR : luxadm not found!\n";
    }
    print LOG $luxadm;
    &print_field_seperator;
}

sub rawdump {
    @rawdump = ();
    print LOG "RAWDUMP:\n\n";
    if ( $RDMP_FILE eq "TRUE" ) {
        open( RDMP, $RD_INFILE );
        while ( $line = <RDMP> ) {
            print LOG $line;
            @rawdump = ( @rawdump, $line );
        }
        close RDMP;
    } else {
        @rawdump = `/usr/bin/ksh -c '${BINDIR}/rawdump 2>&1'`;
        if ($rawdump[0] =~ /not\s+found/i) {
           print "ERROR : ${BINDIR}/rawdump not found!\n";
        }
        print LOG @rawdump;
    }
    &print_field_seperator;
}

sub port_summary {
    my ($max, $wwn, $line, @line, $encname, %sflist, @unique, %seen, $drive, @alldrives, @driveoutput, %drivemap, $mapkey, $curloop, $spacecount, @raw_loop, $rawline, @rawline, @unique_keys);
    my $scount = 0;
    my $pcount = 0;
    my $ecount = 0;
    my $sfcount = 0;
    my $sf = "";
    my $highestsf = 0;
    my $first_ha = "FALSE";

    @unique_keys = ();
    $T300s_found = 0;
    $T300_LUN_count = 0;
    $ddcount = 0; # disks in enclosures, doesn't count disks outside enclosures

    &make_port_list; # sets global variables
    push @rawdump, " ";
    foreach $rawline (@rawdump) {
        # go thru each section of the rawdump separated by a blank line.
        # each section is a single loop (sf)
        #
        (@rawline) = split(' ', $rawline);
        if (! $rawline[0] ) {
            ###################################################
            # blank line encountered, signals end of one loop #
            # process previous loop data                      #
            ###################################################
	    $first_ha = "FALSE";

	    # get all of the keys ( IB/enclosure info )
            foreach $line (@raw_loop) {
                (@line) = split(' ', $line);
                # find all the enclosures on a loop
                if ($line =~ /^(\S+),([AB])[01]/) {
                    ###########################
                    # found an enclosure line #
                    ###########################

                    $encname = $1;
                    $curloop = $2;
                    $mapkey = "$sf,$encname,$curloop";
                    if (!grep { /$mapkey/ } @unique_keys) {
                        push @unique_keys, $mapkey;
                    }
                    if (!grep { /$encname/ } @unique) {
                        $ecount += 1;
                        push @unique, $encname;
                    }
                    # a hash of lists (multivalues)
                    $a1 = grep {/$encname/} @{$sflist{$sf}};
                    push(@{$sflist{$sf}}, $encname) if (! $a1);
		} elsif ($line =~ /^T300,(\d+)/) {
                    ##################
                    # found T300 LUN #
                    ##################
                    
                    $LUN_found = $1;
                    if ($LUN_found == 0) { $T300s_found ++; }
                    $T300_LUN_count ++;
                }
	    }
	    # end of IB info loop

            # get all the disks drives per IB
            foreach $line (@raw_loop) {
                (@line) = split(' ', $line);
                if ($line[0] =~ /^(\S+,)([rf]\d+)/) {
                   # disk drive line found
                   $drive = "$2";
                   $drive .= $1 if ($line[3] =~ /(c\d+t\d+)/) ;
                   $drive .= ",$line[1]";  # wwn
		   $drive_wwn = "$line[1]";  # wwn
		   # keep a running count of unique drives per loop
                   if (!grep { /$drive_wwn/ } @alldrives) {
                       push @alldrives, $drive_wwn;
                       $ddcount +=1;
                   }
                   foreach $mapkey (@unique_keys) {
                      @mapkey = split(/,/, $mapkey);
                      @enc = split(/,/, $line);
		      if ( $mapkey[1] =~ /$enc[0]/ ) {
                         push(@{$drivemap{$mapkey}}, $drive);
	              }
		   }
                }

	    }
	    # end of drive loop

            @raw_loop = ();
	    @unique_keys = ();

        } elsif ($rawline[0] =~ /\*HA\*/) {
            # new host adapter line found
	    # save only the first HA found, others may be hanging on the loop
	    if ( $first_ha eq "FALSE" ) {
		$first_ha = "TRUE";
                my $cursfnum;
                $sf = $rawline[9];
                $cursfnum = substr $sf, 2, 3;
                $highestsf = $cursfnum if ($cursfnum > $highestsf);
	    } 
        } elsif ($rawline[0] =~ /\*Disk\*/) {
            ########################################
            # found an internal fiber channel disk #
            # these have no enclosure.             #
            ########################################

        } elsif (! ($rawline[0] =~ /\*Unknown Type\*/)) {
            # keep line for later processing
            push @raw_loop, $rawline;
        }
    }
    print LOG "LOOP SUMMARY:\n\n";

    @socals = ();
    $full_ddcount = 0;
    $scount = $#LD_DD_PORTS + 1;
    foreach $line (@LD_DD_PORTS) {
       my ($loop_T300_LUN_count, $loop_A5_disk_count);

       $loop_T300_LUN_count = $P_DDCNT{$line} + $A_DDCNT{$line};
       $current_ddcount = $A5_DDCNT{$line} + $OTHER_DDCNT{$line};
       $full_ddcount += $current_ddcount;
       $a1 = $#{$sflist{$SFNUM{$line}}} + 1;   # number of enclosures on the loop
       $output = sprintf("%-10s%-8s%-7s%-6s%-20s%-12s%-13s%-13s", "$SOCNUM{$line}", "Port $PORTNUM{$line}", "$SFNUM{$line}", "$CNUM{$line}", "$a1 enclosure(s)", "$current_ddcount disks", "$T300_CNT{$line} T300(s)", "$loop_T300_LUN_count LUN(s)");
       print LOG "$output  $line\n";
       
    }
    undef %seen;
    @unique = grep { ! $seen{$_} ++ } (values %SOCNUM);
    $pcount = scalar(values %PORTNUM);
    $sfcount = scalar(values %SFNUM);

    print LOG "\nENCLOSURES:\n\n";

    foreach $sf (sort(values %SFNUM)) {
        $sfcount++;
	$first_encname = "TRUE";
        $output = "";
        foreach $encname (sort @{$sflist{$sf}}) {
	    if ( $first_encname eq "TRUE" ) {
	       $first_encname = "FALSE";
               #print LOG "$sf: ";
               $output = "$sf: ";
	    }
            #print LOG "$encname ";
            $output .= "$encname ";
            foreach $curloop ("A", "B") {
                undef @alldrives;
                $mapkey = "$sf,$encname,$curloop";
                if (defined @{$drivemap{$mapkey}}) {
                    #
                    # separate drive list into front and rear lists
                    #
                    @alldrives = @{$drivemap{$mapkey}};
                    @front = ();
                    @rear = ();
                    foreach $line (@alldrives) {
                        $front[$1] = $2 if ($line =~ /^f(\d+)(c\d+t\d+.*)/);
                        $rear[$1] = $2 if ($line =~ /^r(\d+)(c\d+t\d+.*)/);
                    }
                    #
                    # put into 2 columns
                    #
                    if ($#front > $#rear) {
                        $max = $#front + 1;
                    } else {
                        $max = $#rear + 1;
                    }
                    $max = 7 if ($max < 7);
                    undef $alldrives;
                    for ($a1 = 0; $a1 < $max; $a1 ++) {
                        $front[$a1] = "-                         " if (!defined($front[$a1]));
                        $rear[$a1] = "-" if (!defined($rear[$a1]));
                        $spacecount = 26 - length($front[$a1]);
                        $front[$a1] .= pack "A$spacecount", " ";
                        $line = "$front[$a1] $rear[$a1]\n";
                        $alldrives .= $line;
                    }
                }
                push @driveoutput, "\n$sf\t$encname\tLoop $curloop\n$alldrives" if defined(@alldrives);
            }
        }
        print LOG "$output\n" if ($output ne "");
    }
    print LOG "\nDRIVE MAP:\n";
    print LOG @driveoutput;
    if ($T300_PRESENT) {
        &summarize_t300;
        print LOG "\nLUN MAP:\n\n";
        print LOG @T300_output;
    }

    print LOG "\n\nTotals: $pcount ports(s), $ecount enclosure(s), $full_ddcount disk(s), $T300s_found T300(s), $T300_LUN_count LUN(s)\n\n";

    print LOG "============================================================\n";
}

sub smart_compare {
    my ($file1, $file2) = @_;

    my @goldsum = &read_summary("$GOLD_PATH/$file1");
    my @cursum = &read_summary("$GOLD_PATH/$file2");
    my @cloops = &get_socals(@cursum);
    my @gloops = &get_socals(@goldsum);
    my @gold_enclosures = &get_enclosures(@goldsum);
    my @cur_enclosures = &get_enclosures(@cursum);
    my @gold_encl_map = &get_enclosure_map(@goldsum);
    my @cur_encl_map = &get_enclosure_map(@cursum);
    my @gold_LUN_map = &get_LUN_map(@goldsum);
    my @cur_LUN_map = &get_LUN_map(@cursum);
    my ($socal_line, $socal, $dummy, $portnum, $sfnum, $cnum, $encl_count, %cur_sflist, %gold_sflist, $i, $equal);
    my ($socal2, $portnum2, $sfnum2, $cnum2, $encl_count2);
    my ($encl_line, %gold_encl_names, %cur_encl_names, $encl_list, @all_cur_encl, %all_cur_enclosures, @all_gold_encl, %all_gold_encl);
    my $allenclosuresvisible = 0;
    my (@all_sfs, %gold_encl_by_loop, %cur_encl_by_loop);

    $equal = 1;
    for ($i = 0; $i <= $#goldsum; $i ++) {
        $equal = 0 if (!($goldsum[$i] eq $cursum[$i]));
        last if (!$equal);
    }
    return if $equal;
    $CHANGES_DETECTED = "TRUE";

    # build hash of enclosures per sf
    foreach $encl_line (@gold_enclosures) {
        ($sfnum, $encl_list) = split(/:/, $encl_line);
        chomp $encl_list;
        push(@all_gold_encl, split(/ /,$encl_list));
        $gold_encl_names{$sfnum} = $encl_list;
        $gold_encl_by_loop{$sfnum} = $encl_list;
        push @all_sfs, $sfnum;
    }
    @all_gold_encl = grep { ! $all_gold_enclosures{$_} ++ } (sort @all_gold_encl);

    foreach $encl_line (@cur_enclosures) {
        ($sfnum, $encl_list) = split(/:/, $encl_line); 
        chomp $encl_list;
        push(@all_cur_encl, split(/ /,$encl_list));
        $cur_encl_names{$sfnum} = $encl_list;
        $cur_encl_by_loop{$sfnum} = $encl_list;
        push @all_sfs, $sfnum;
    }
    @all_sfs = grep { ! $all_sfs{$_} ++ } (sort @all_sfs);
    @all_cur_encl = grep { ! $all_cur_enclosures{$_} ++ } (sort @all_cur_encl);
    $allenclosuresvisible = 1 if (@all_cur_encl eq @all_gold_encl);

    $equal = 1;
    for ($i = 0; $i <= $#gloops; $i ++) {
        $equal = 0 if (!($gloops[$i] eq $cloops[$i]));
        last if (!$equal);
    }
    if (!$equal) {
        # there are differences in the sf's, find out what they are
        # build a hash of sf numbers and begin comparing
        foreach $socal_line (sort @cloops) {
            ($socal, $x1, $portnum, $sfnum, $cnum, $encl_count, $x2, $disks, $x3, $t300s, $x4) = split(/\s+/, $socal_line);
            $cur_sflist{$sfnum} = $socal_line;
        }
        foreach $socal_line (sort @gloops) {

            ($socal, $x1, $portnum, $sfnum, $cnum, $encl_count, $x2, $disks, $x3, $t300s, $x4) = split(/\s+/, $socal_line);
            # if found an exact match, remove from hash so only ones left are new or modified loops
            if (!defined $cur_sflist{$sfnum}) {
                # found an old sf that does not exist anymore in current config, we don't
                # dont validate disks for this loop 
                $msg = "Missing online port: $sfnum on $socal Port $portnum, $encl_count A5K enclosures, $t300s T300s";
                &logit("ERROR", 4013, $msg);
            } elsif ($cur_sflist{$sfnum} eq $socal_line) {
                # found matching sf exactly, remove it from list
                delete($cur_sflist{$sfnum});  
            } else {
                # found changed sf save for later breakdown of what was changed
                $gold_sflist{$sfnum} = $socal_line;
            }
        }
        # go through current snapshot again looking for new sf's
        foreach $socal_line (sort values %cur_sflist) {
            ($socal, $x1, $portnum, $sfnum, $cnum, $encl_count, $x2, $disks, $x3, $t300s, $x4) = split(/\s+/, $socal_line);
            if (!defined $gold_sflist{$sfnum}) {
                # found a new sf that wasn't in gold snapshot at all, output message and remove
                # from hash, since we don't need it anymore. All that will be left is changes to 
                # existing sf's requiring examination.

                &logit("WARNING", 3012, "New online port detected: $sfnum on $socal Port $portnum, $encl_count enclosures, $t300s T300s");
                delete($cur_sflist{$sfnum});
            } else {
                # found an existing but changed sf, figure out what changed
                ($socal2, $x1, $portnum2, $sfnum2, $cnum2, $encl_count2, $x2, $disks, $x3, $t300s, $x4) = split(/\s+/, $gold_sflist{$sfnum});
                if ($socal ne $socal2) {
                    # sf moved from one socal card to another
                    &logit("WARNING", 3020, "Port has moved: $sfnum now on $socal Port $portnum ($cnum)");
                } elsif ($portnum ne $portnum2) {
                    # sf moved to different port on same socal card
                    &logit("WARNING", 3020, "Port has moved: $sfnum now on $socal Port $portnum ($cnum)");
                } 
            }
        }
    }
    
    if (!$allenclosuresvisible) {
        # some enclosures are not available at all, no loop redundancy at this time
        #
        foreach $encl_line (@all_gold_encl) {
          if (!exists $all_cur_enclosures{$encl_line}) {
              #&logit("ERROR", 4021, "Enclosure offline: $encl_line");
              delete($all_gold_enclosures{$encl_line}); # no need to check disks if offline
          }
        }
    }
    # see if enclosures moved around to different loops
    foreach $g_sf (sort @all_sfs) {
        next if ($gold_encl_by_loop{$g_sf} eq $cur_encl_by_loop{$g_sf});
        # enclosure list is different
        # 1 = golden only, 10 = current only, 11 = both
        my (%encl_list);
        foreach $e (split / /,$gold_encl_by_loop{$g_sf}) {
            next if ($e eq "");
            $encl_list{$e} += 1;
        }
        foreach $e (split / /,$cur_encl_by_loop{$g_sf}) {
            next if ($e eq "");
            $encl_list{$e} += 10;
        }
        foreach $e (keys %encl_list) {
            next if ($encl_list{$e} == 11);
            if ($encl_list{$e} == 1) {
                # enclosure is offline for this loop
                &logit("ERROR", 4021, "Enclosure offline: $e ($g_sf)");
            } else {
                # new enclosure is online for this loop
                &logit("WARNING", 3017, "Enclosure online: $e ($g_sf)");
            }
        }
    }

    #
    # check World Wide Numbers for all the drives for the enclosures
    foreach $encl_line (sort keys %all_gold_enclosures) {
        @gold_encl_map = &get_disk_map($encl_line, 'f', @goldsum);
        @cur_encl_map = &get_disk_map($encl_line, 'f', @cursum);
        
        for ($i = 0; $i < 15; $i ++) {
            $gold_encl_map[$i] = '-' if (!defined($gold_encl_map[$i]));
            $cur_encl_map[$i] = '-' if (!defined($cur_encl_map[$i]));
            if ($gold_encl_map[$i] ne $cur_encl_map[$i]) {
                ($cnum2, $wwn2) = split(/,/,$cur_encl_map[$i]);
                ($cnum, $wwn) = split(/,/,$gold_encl_map[$i]);
                if (($cnum2 eq '-') and ($cnum ne '-')) {
                    &logit("ERROR", 4014, "Disk drive offline: $encl_line, front slot $i"); 
                } elsif (($cnum eq '-') and ($cnum2 ne '-')) {
                    &logit("WARNING", 3014, "New disk drive detected: $encl_line, front slot $i");
                } elsif ($wwn2 ne $wwn) {
                    &logit("WARNING", 3014, "Disk drive replaced: $encl_line, front slot $i");
                }
            }
        }
        @gold_encl_map = &get_disk_map($encl_line, 'r', @goldsum);
        @cur_encl_map = &get_disk_map($encl_line, 'r', @cursum);
        for ($i = 0; $i < 15; $i ++) {
            $gold_encl_map[$i] = '-' if (!defined($gold_encl_map[$i]));
            $cur_encl_map[$i] = '-' if (!defined($cur_encl_map[$i]));
            if ($gold_encl_map[$i] ne $cur_encl_map[$i]) {
                ($cnum2, $wwn2) = split(/,/,$cur_encl_map[$i]);
                ($cnum, $wwn) = split(/,/,$gold_encl_map[$i]);
                if (($cnum2 eq '-') and ($cnum ne '-')) {
                    &logit("ERROR", 4014, "Disk drive offline: $encl_line, rear slot $i");
                } elsif (($cnum eq '-') and ($cnum2 ne '-')) {
                    &logit("WARNING", 3014, "New disk drive detected: $encl_line, rear slot $i");
                } elsif ($wwn2 ne $wwn) {
                    &logit("WARNING", 3014, "Disk drive replaced: $encl_line, rear slot $i");
                }
            }
        }
    }
    my (%gold_T300, $inside_T300, $name);

    $inside_T300 = 0;
    foreach $line (@gold_LUN_map) {
        $i = $line; # temp line, don't want to modify the array
        chomp $i;
        if ($i eq "") {
            $inside_T300 = 0;
            $name = "";
            next;
        }
        if ($i =~ /^T300\s+(\S+)\s+.*/) {
            $name = $1;
            $inside_T300 = 1;
            next;
        }
        $gold_T300{$name} .= "$i\n" if ($inside_T300);
    }

    $inside_T300 = 0;
    foreach $line (@cur_LUN_map) {
        $i = $line; # temp spot to do the chomp, don't wanna upset the array
        chomp $i;
        if ($i eq "") {
            $inside_T300 = 0;
            $name = "";
            next;
        }
        if ($i =~ /^T300\s+(\S+)\s+.*/) {
            $name = $1;
            $inside_T300 = 1;
            next;
        }
        $cur_T300{$name} .= "$i\n" if ($inside_T300);
    }
    my $off_lines = "";
    my $on_lines = "";
    foreach $name (sort keys %gold_T300) {
        if ($cur_T300{$name} eq "") {
            # T300 completely missing
            $off_lines .= "T300 $name offline or missing\n";
        } elsif ($cur_T300{$name} ne $gold_T300{$name}) {
            # T300 changed check what changed
            #######################################################
            # loop thru primary and alt targets, see what changed #
            # 11 = both, 10 = gold only, 1 = current only         #
            #######################################################
            my (%prim_targets, %alt_targets, $cline, $gline, $messages);

            foreach $cline (split /\n/, $cur_T300{$name}) {
                next if ($cline =~ /Primary/);
                next if ($cline =~ /T300/);
                if ($cline =~ /^(\S+)\s+(\S+)/) {
                    $prim_targets{$1} += 1;
                    $alt_targets{$2} += 1;
                } elsif ($cline =~ /^(\S+)/) {
                    $prim_targets{$1} += 1;
                } elsif ($cline =~ /^\s+(\S+)/) {
                    $alt_targets{$1} += 1;
                }
            }
            foreach $gline (split /\n/, $gold_T300{$name}) {
                next if ($gline =~ /^Primary/);
                next if ($gline =~ /^T300/);
                if ($gline =~ /^(\S+)\s+(\S+)/) {
                    $prim_targets{$1} += 10;
                    $alt_targets{$2} += 10;
                } elsif ($gline =~ /^(\S+)/) {
                    $prim_targets{$1} += 10;
                } elsif ($gline =~ /^\s+(\S+)/) {
                    $alt_targets{$1} += 10;
                }
            }
            #######################################
            # data assembled, find the errors now #
            # 1  = current snapshot only          #
            # 10 = golden snapshot only           #
            # 11 = appears in both snapshots      #
            #######################################
            foreach $cline (sort keys %prim_targets) {
                next if ($prim_targets{$cline} == 11); # same
                if ($prim_targets{$cline} == 10) {
                    $off_lines .= "T300 primary LUN $cline offline or missing\n";
                } elsif ($prim_targets{$cline} == 1) {
                    $on_lines .= "T300 primary LUN $cline online or new\n";
                }
            }
            foreach $cline (sort keys %alt_targets) {
                next if ($alt_targets{$cline} == 11); # same
                if ($alt_targets{$cline} == 10) {
                    $off_lines .= "T300 alternate LUN $cline offline or missing\n";
                } elsif ($alt_targets{$cline} == 1) {
                    $on_lines .= "T300 alternate LUN $cline online or new\n";
                }
            }
        }
    }

    foreach $name (sort keys %cur_T300) {
        #######################################################################
        # loop thru current T300 boxes, see if they appear in golden snapshot #
        # and if not then new box came online since last snapshot taken       #
        #######################################################################
        if ($gold_T300{$name} eq "") {
            # new T300 detected
            $on_lines .= "New T300 $name online\n";
        }
    }
    &logit("ERROR", 4021, "Change detected, hardware offline or missing\n$off_lines") if ($off_lines);
    &logit("WARNING", 3017, "Change detected\n$on_lines") if ($on_lines);
    print "*** Changes detected! ***\n" if ($CHANGES_DETECTED = "TRUE" && $VERBOSE);

}

sub get_socals {
    my (@goldsum) = @_;
    my $inside_section = 0;
    my ($line, @loops);

    foreach $line (@goldsum) {
        chomp $line;
        last if ($line =~ /^ENCLOSURES/);
        push @loops, $line if (($inside_section) and ($line));
        $inside_section = 1 if ($line =~ /^LOOP SUMMARY:/);
    }
    return @loops;
}

sub get_enclosures {
    my (@goldsum) = @_;
    my $inside_section = 0;
    my ($line, @loops);

    foreach $line (@goldsum) {
        chomp $line;
        last if ($line =~ /^DRIVE MAP:/);
        push @loops, $line if (($inside_section) and ($line));
        $inside_section = 1 if ($line =~ /^ENCLOSURES/);
    }
    return @loops;
}

sub get_enclosure_map {
    my (@goldsum) = @_;
    my $inside_section = 0;
    my ($line, @loops);

    foreach $line (@goldsum) {
        chomp $line;
        last if ($line =~ /^====================/);
        push @loops, $line if (($inside_section) and ($line =~ /^sf/));
        push @loops, $line if (($inside_section) and ($line =~ /^fp/));
        push @loops, $line if (($inside_section) and ($line =~ /^ifp/));
        push @loops, $line if (($inside_section) and ($line =~ /^qlc/));
        $inside_section = 1 if ($line =~ /^DRIVE MAP/);
    }
    return @loops;
}

sub get_disk_map {
    # retrieve the World Wide Numbers from a specific A5000 and
    # only get the front or rear info
    my ($encl_name, $backplane, @goldsum) = @_;
    my $inside_section = 0;
    my $foundbox = 0;
    my ($line, @loops);

    $backplane = 'f' if (!$backplane =~ /^f$|^r$/);
    foreach $line (@goldsum) {
        chomp $line;
        $line =~ s/\s+/ /g;
        $inside_section = 1 if ($line =~ /^DRIVE MAP/); # Herb moved up
        next if (!$inside_section); # Herb added
        last if ($line =~ /^====================/);
        if ($inside_section) {
            if ($line =~ /^sf\d+\s(.*)\sLoop\s+(.*)/) {
                last if $foundbox; # already did it
                $foundbox = 1 if ($encl_name eq $1);
                next;
            }
            if ($line =~ /^fp\d+\s(.*)\sLoop\s+(.*)/) {
                last if $foundbox; # already did it
                $foundbox = 1 if ($encl_name eq $1);
                next;
            }
            if ($line =~ /^ifp\d+\s(.*)\sLoop\s+(.*)/) {
                last if $foundbox; # already did it
                $foundbox = 1 if ($encl_name eq $1);
                next;
            }
            if ($line =~ /^qlc\d+\s(.*)\sLoop\s+(.*)/) {
                last if $foundbox; # already did it
                $foundbox = 1 if ($encl_name eq $1);
                next;
            }
        }
        if ($foundbox) {
            last if ($line eq ''); # Herb added key line here...
            ($front, $rear) = split(/ /, $line);
            push @loops, $front if (($backplane eq 'f') and ($front));
            push @loops, $rear if (($backplane eq 'r') and ($rear));
        }
   }
    return @loops;
}

sub show_disk_map {

    @rawdump = `/usr/bin/ksh -c '${BINDIR}/rawdump 2>&1'`;

    &open_logfile("temp_map");
    &port_summary;
    &close_logfile;
    print &read_summary("$LOGDIR/temp_map");

}

sub read_summary {
    ###########################################################
    # Open the file and read it looking for the Loop Summary
    # section. Pull it out, into an array and return it 
    ###########################################################
    my ($filename) = @_;
    my ($line, @loopsummary);
    open(GOLDEN,  "$filename") or die "Unable to open logfile : $filename\n";

    $found_section = "FALSE";
    while ($line=<GOLDEN>) {
        $found_section = "TRUE" if ($line =~ /^LOOP SUMMARY:/);
        next if ($found_section eq "FALSE");
        last if ($line =~ /^============/);
        # 
        # we are in the middle of our section in the snapshot
        #
        push @loopsummary, $line;
    }
    close(GOLDEN);
    print "\nWarning: LOOP SUMMARY section missing from snapshot. Please run '${PROGNAME} -save'\n" if ($found_section eq 'FALSE');
    return @loopsummary;
}

sub proc_cli {
    #Initialize state of variables prior to command line parsing
    # can't init CMP and SAVE because they are either set or not set
    my $do_something = "FALSE";

    undef $DISKMAP;
    $SHOW_CONF      = "FALSE";
    $RDMP_FILE      = "FALSE";

   # For every command line argument update the usage array
   # SBUS command line options
    $usage[0] = "$PROGNAME help | -save | -cmp | -log | -mail name | -v | -warn | -rd <file> | -sc | -map \n";
    $usage[1]  = "help - displays usage\n";
    $usage[2]  = "save - save the system state\n";
    $usage[3]  = "cmp  - compare the current system state with the saved system state\n";
    $usage[4]  = "log  - log to /var/adm/messages\n";
    $usage[5]  = "mail - mail errors to an admin\n"; 
    $usage[6]  = "v    - verbose\n";
    $usage[7]  = "warn - Mail warnings as well as errors\n";
    $usage[8]  = "rd <file>  - Uses the specified file for the rawdump entry\n";
    $usage[9]  = "sc   - Show the configuration prior to execution \n";
    $usage[10] = "map  - Show disk map details\n";

    if ($#ARGV<0) {

        print "options:\n";
        foreach $item (@usage) {print $item};
        print "\n";
        die "\n$PROGNAME requires arguments.\n";
    }

    $LUN_DISK = "Drive";
    $arg = shift @ARGV;
    while($arg) {
	if ($arg =~ /help/)  {
	    print "If you need help there is a manpage available.\n";
            die @usage if ($arg =~ /help/);
        } elsif ($arg =~ /-cmp/) {
            $CMP          = TRUE;
            $do_something = "TRUE";
        } elsif ($arg =~ /-save/) {
            $SAVE         = TRUE;
            $do_something = "TRUE";
        } elsif ($arg =~ /-log/) {
            $LOGGING      = TRUE;
        } elsif ($arg =~ /-mail/) {
            $MAIL_RESULTS   = TRUE;
	    $MAIL_RECIPIENT = shift @ARGV;
        } elsif ($arg =~ /-v/) {
            $VERBOSE      = TRUE;
        } elsif ($arg =~ /-sc/) {
            $SHOW_CONF = "TRUE";
        } elsif ($arg =~ /-rd/) {
            $RDMP_FILE = "TRUE";
	    $RD_INFILE = shift @ARGV;
        } elsif ($arg =~ /-warn/) {
            $WARN    = TRUE;
        } elsif ($arg =~ /-S/) {
        } elsif ($arg =~ /-P/) {
        } elsif ($arg =~ /-A5/) {
        } elsif ($arg =~ /-T3/) {
        } elsif ($arg =~ /-map/) {
            $DISKMAP = "TRUE";
            $do_something = "TRUE";
        }

        # Get the next value.
        # The last command in the loop
        $arg = shift @ARGV;
    }

    $GOLD_PATH  = "${LOGDIR}";

    if ($do_something eq "FALSE") {

        print "SBUS options:\n";
        foreach $item (@usage) {print $item};
        print "\n";
        die "\n$PROGNAME requires arguments.\n";
    }

#
    die @usage if ($do_something eq "FALSE");

# check for mail setup
    die @usage if (($MAIL_RESULTS) && (! $MAIL_RECIPIENT));
    if (($WARN) && (! $MAIL_RESULTS)) {
        print "You must specify mail with warn!\n";
        die @usage;
    }
}

sub showrev {
    print LOG "PATCHES:\n\n";
    $showrev = `/usr/bin/showrev -p | /usr/bin/awk '{print \$2}' | /usr/bin/ksh -c '/usr/bin/sort 2>&1'`;
    print LOG $showrev;
    &print_field_seperator;
}

sub print_field_seperator {
    print LOG "\n";
    print LOG "=" x 60;
    print LOG "\n";
}

sub header {
    print LOG "HEADER:\n\n";
    $header = `/usr/bin/uname -a`;
    print LOG $header;
    $date = `/usr/bin/date`;
    print LOG $date;
    &print_field_seperator;
}

sub storstat {
    print LOG "STORSTAT:\n\n";
    $storstat = `${BINDIR}/storstat -warn -all`; 
    print LOG $storstat;
    &print_field_seperator;
}

sub logit {
    # log errors and collect messages to mail to specified user
    #
    ($status, $error_number, $message) = @_;
    $error_number = "xxx" if (! $error_number);
    $status = "ERROR" if (! $status);
    $message = "Error occurred" if (! $message);

    # Define this global variable and send mail later
    if ($status eq "ERROR") {
        $ERROR_FLAG  = "TRUE";
        print MAIL "[$STORAGE_DEVICE:DIAG:$status:$error_number] $message\n";
    }
    if (($status eq "WARNING") && $WARN) {
        $ERROR_FLAG  = "TRUE";
        print MAIL "[$STORAGE_DEVICE:DIAG:$status:$error_number] $message\n";
    }

    print "$status : $message\n";
    &logger($status, $error_number, $message) if $LOGGING;
}

sub volume_manager_summary {
  # Record the volume manager summary for Veritas and/or SDS
  my $vmdata = &get_volume_manager_data;
 
  if ($vmdata) {
      print LOG "VOLUME MANAGER SUMMARY\n";
      print LOG "----------------------\n\n";
      print LOG "$vmdata\n";
      print LOG "=" x 60;
  }
}

sub vm_compare {
  # compare Veritas and/or SDS information for changes

  my ($golden_log, $current_log) = @_;
  my (@current_section, @golden_section, $line, $found_section, $has_veritas, $has_sds);
  my $section_name = "VOLUME MANAGER SUMMARY";
  my $subject = "Volume manager";

    open(GOLDEN,  "${GOLD_PATH}/$golden_log") or die "Unable to open file : ${GOLD_PATH}/$golden_log\n";

    $found_section = "FALSE";
    while ($line=<GOLDEN>) {
        chomp $line;
        $found_section = "TRUE" if ($line =~ /^${section_name}/);
        next if ($found_section eq "FALSE");
        next if ($line =~ /^\s*#/);
        last if ($line =~ /^============/);
        $has_veritas = 1 if ($line =~ /^VERITAS/);
        $has_sds = 1 if ($line =~ /^SOL/);
        push @golden_section, $line if ($found_section eq "TRUE");
    }
    close(GOLDEN);

    open(CURRENT, "${GOLD_PATH}/$current_log") or die "Unable to open current logfile : ${GOLD_PATH}/$current_log\n";

    $found_section = "FALSE";
    while ($line = <CURRENT>) {
        chomp $line;
        $found_section = "TRUE" if ($line =~ /^${section_name}/);
        next if ($found_section eq "FALSE");
        next if ($line =~ /^\s*#/);
        last if ($line =~ /^============/);
        push @current_section, $line if ($found_section eq "TRUE");
    }
    close(CURRENT);
    $subject = "Solstice Disk Suite" if (($has_sds) and (!$has_veritas));
    if ($#golden_section > $#current_section) {
        &logit("WARNING", 3009, "$subject summary has changed");
        $CHANGES_DETECTED = "TRUE";
        return;
    } elsif ($#golden_section < $#current_section) {
        &logit("WARNING", 3010, "$subject summary has changed");
        $CHANGES_DETECTED = "TRUE";
        return;
    }
    for ($i = 0; $i <= $#golden_section; $i ++) {
        if ($golden_section[$i] ne $current_section[$i]) {
            &logit("WARNING", 3009, "$subject summary has changed");
            $CHANGES_DETECTED = "TRUE";
            return;
        }
    }

}

sub summarize_t300 {

  @T300_output = ();
  foreach $e (@LD_DD_PORTS) {
    if ($T300_CNT{$e}) {
        my (@primary_drives, @alternate_drives, $drive_cnt, $dnum, %T300_TARGETS);

        @disklist = (keys %T300);
        undef @our_drives;  # drives only on this loop
        undef %T300_TARGETS;
        ################################################
        # collect all drives on this loop, then        #
        # separate by target id number. This           #
        # gives us separate lists of LUNs by T300 box. #
        ################################################
        foreach $drive (@disklist) {
           if ($drive =~ /$CNUM{$e}/) {
               my ($cur_target, $cur_disk) =  $drive =~ /c\d+t(\d+)d(\d+)/;
               $T300_TARGETS{$cur_target} .= "$drive "; # LUNs in this target T300 box
           }
        }
        ###############################
        # Loop once for each T300 box #
        ###############################
        foreach $target (sort (keys %T300_TARGETS)) {
            undef @primary_drives;
            undef @alternate_drives;
            chop $T300_TARGETS{$target}; # remove trailing space
            @our_drives = split / /, $T300_TARGETS{$target};
            $drive_cnt = 0;
            foreach $drive (@our_drives) {
               if ( $T300{$drive} eq "p" ) {
                   push @primary_drives, $drive;
               } elsif ( $T300{$drive} eq "a" ) {
                   push @alternate_drives, $drive;
               }
               $drive_cnt ++;
            }
            $show = sprintf "%-10s%-12s%-15s", "T300", "$CNUM{$e}t$target", "$drive_cnt LUN(s)";
            push @T300_output, "$show\n";
            $show = sprintf "%-22s%-22s", "Primary", "Alternate";
            push @T300_output, "$show\n";
            ##########################################
            # output a pretty display with 2 columns #
            ##########################################
            for ($dnum = 0; $dnum < $drive_cnt; $dnum ++ ) {
                last if (($primary_drives[$dnum] eq "") && ($alternate_drives[$dnum] eq ""));
                $show = sprintf "%-22s%-22s", "$primary_drives[$dnum]", "$alternate_drives[$dnum]";
                push @T300_output, "$show\n";
            }
            push @T300_output, "\n";
        }
    }
  }
}

sub get_LUN_map {
    #######################################
    # return with specific lines for T300 #
    #######################################
    my (@goldsum) = @_;
    my $inside_section = 0;
    my ($line, @loops);

    foreach $line (@goldsum) {
        $inside_section = 1 if ($line =~ /^LUN MAP:/);
        last if ($line =~ /^Totals/);
        push @loops, $line if (($inside_section));
    }
    return @loops;
}

