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

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

$PROGNAME = "sedr";

#$DEBUG = "TRUE";
$SIG{INT} = 'clean_up';
$MONITOR = "FALSE";

####################################################################
# StorEdgeDr main()
####################################################################

    &check_root_access( $PROGNAME );
    &proc_cli();
    my $input = "";

    while ($input !~ /Q|q/) {
        $input = &get_input;

        if ($input == 1) {
            &system_clear();
            &sedr();
        } elsif ($input == 2) {
            &log_manager;
        } elsif ($input ne "q") {
            print "\n";
            print "$input is an invalid option!\n";
        }
    }    

###############################################################
# clean up all log files
###############################################################
sub clean_logs {
    while (1) {
        print "\nWould you like to remove all log files? [y, <n>]: ";
        $ans = &get_response("n");
        if ($ans =~ /y/i) {
            system "/usr/bin/ksh -c '/usr/bin/rm ${LOGSEDR}/sedr.* 2>/dev/null'"; 
            system "/usr/bin/ksh -c '/usr/bin/rm ${LOGSEDR}/dex.messages 2>/dev/null'";
            last;
        } elsif ( $ans =~ /n/i) {
            last;
        } else {
            print"\n";
            print"$ans is an ivalid option!\n";
        }
    }
    &continue;
}

###############################################################
# show mess_sum
###############################################################
sub show_mess_sum {
    $dexlog = "${LOGSEDR}/dex.messages";
    &print_banner;
    if (-e $dexlog) {
        system "${BINDIR}/mess_sum -$HBA -$STORAGE -f $dexlog | more";
    } else {
        print "\nLog file $dexlog does not exist.";
    }
    &continue;
}

###############################################################
# display the installation verification submenus and take input
###############################################################
sub get_input{
    &print_banner;
    print " [1] Start StorEdgeDr\n";
    print " [2] StorEdgeDr Log Manager\n";
    print "\n";
    print " [q] Quit\n";
    print "\nSelect an operation to perform: ";
    chop($stdin=<STDIN>);
    return $stdin;
}

###############################################################
# display the installation verification submenus and take input
###############################################################
sub log_manager {
    my $input = "";

    while ($input !~ /Q|q/) {
        $input = &print_logscreen;
        if ($input == 1) {
            &show_mess_sum;
        } elsif ( ( $input == 2 ) && ( $HBA eq "S" ) ) {
            &show_full_logs();
        } elsif ( ( $input == 3 ) && ( $HBA eq "S" ) ) {
            &show_summary();
        } elsif ($input == 4){
            &show_diskx();
        } elsif ( ( $input == 5 ) && ( $HBA eq "P" ) ) {
            &show_2100_hba();
        } elsif ($input == 6){
            &clean_logs;
        } elsif ( $input ne "q" ) {
            print "\n";
            print "$input is an invalid option!\n";
        }
    }
}


###############################################################
# get the file_id
###############################################################
sub get_fileid {
   $all_lbf = `/usr/bin/ksh -c '/bin/ls -1t ${LOGSEDR}/sedr.log.*.str.lbf* 2>/dev/null'`;
    @arr_allfiles = split(/\n/,$all_lbf);

    if ($#arr_allfiles < 0) {
        return -1; 
    } else {
        $match = $arr_allfiles[0];
        ($latest_id) = $match =~ /sedr.log.(\d+)/;
        return $latest_id;
    }
}
###############################################################
# get the dfile_id
###############################################################
sub get_dfileid {
   $all_dex = `/usr/bin/ksh -c '/bin/ls -1t ${LOGSEDR}/sedr.log.*.str.dex* 2>/dev/null'`;
    @arr_allfiles = split(/\n/,$all_dex);

    if ($#arr_allfiles < 0) {
        return -1; 
    } else {
        $match = $arr_allfiles[0];
        ($latest_id) = $match =~ /sedr.log.(\d+)/;
        return $latest_id;
    }
}

###############################################################
# choose_cnum
###############################################################
sub choose_cnum {
    my @cur_menu;
    my @allcnums = &get_cnums;
    my $x = 0;
    my $ans;
    foreach $cnum (@allcnums) {
       $x++;
       @cur_menu = (@cur_menu, "  [$x] $cnum\n");
    }
    if ($x == 0) {
        print "Log Files Do Not Exist.\n";
        return "q";
    } 
    @cur_menu = (@cur_menu,
                 "\n  [a] All\n",
                 "  [q] Quit\n",
                 "\nSelect [ 1 - $x, a or <q> ]: ");
choose_cnum_start:
    print @cur_menu;
    $ans = &get_response("q");
    if ($ans =~ /^q/i) { return "q"; }
    if ($ans =~ /^a/i) { return "a"; }
    if ($ans lt 1 or $ans gt $x) {
        print "\n$ans is an invalid option!\n";
        goto choose_cnum_start;
    }
    return $allcnums[$ans - 1];
}

sub get_cnums {
    my %cnames;

     open CNAMES, "ls $LOGSEDR |";
     while (<CNAMES>) {
         chomp;
         $cnames{$1} = $cnames{$1} + 1 if /sedr.log.\d+\.str.lbf.(c\d+)/;
     }
     return sort (keys %cnames);
}


###############################################################
# show the failures in the lbf log
###############################################################
sub show_full_logs {
    &print_banner;
    $file_id = &get_fileid;

    if ($file_id == -1) { 
        print "Log File Does Not Exist.\n"; 
    } else {
    my $cnum = &choose_cnum;
    if ($cnum eq "a") {
          $lbf_files = `/usr/bin/ksh -c '/bin/ls -1t ${LOGSEDR}/sedr.log.$file_id.str.lbf.c* 2>/dev/null'`;
    } elsif ($cnum eq "q") {    
        print "\nPress <return> to continue.";
        $cont = <STDIN>;
        return; 
    } else {
        $lbf_files = `/usr/bin/ksh -c '/bin/ls -1t ${LOGSEDR}/sedr.log.$file_id.str.lbf.$cnum 2>/dev/null'`;
    }
        @arr_files = split(/\n/,$lbf_files);
        print "\nChecking Latest Loop Integrity Logs:\n";
        foreach $lbf_file (@arr_files) {
            if (-e $lbf_file) {
                print "Press <return> to view $lbf_file";
                $cont = <STDIN>;
                system "/usr/bin/more $lbf_file";
                print "\n";
             }
        }
    }
    &continue;
}

sub show_summary {
    &print_banner;
    $file_id = &get_fileid;

    if ($file_id == -1) { 
        print "Log File Does Not Exist.\n"; 
    } else {
        my $cnum = &choose_cnum;
        if ($cnum eq "a") {
            $lbf_files = `/usr/bin/ksh -c '/bin/ls -1t ${LOGSEDR}/sedr.log.$file_id.str.lbf.c* 2>/dev/null'`;
        } elsif ($cnum eq "q") {
            print "\nPress <return> to continue.";
            $cont = <STDIN>;
            return;
        } else {
            $lbf_files = `/usr/bin/ksh -c '/bin/ls -1t ${LOGSEDR}/sedr.log.$file_id.str.lbf.$cnum 2>/dev/null'`;
        }
        @arr_files = split(/\n/,$lbf_files);
        print "\nChecking Latest Loop Integrity Logs:\n";
        foreach $lbf_file (@arr_files) {
            if (-e $lbf_file) {
                $failures = `/bin/grep -i fail $lbf_file`;
                print "Press <return> to view $lbf_file";
                $cont = <STDIN>;
                if ($failures eq "") {
                    print "No failures found.\n\n";
                } else {
                    system "/usr/bin/grep -i fail $lbf_file | more";
                    print "\n";
                }
            }
        }
    }
    &continue;
}

#########################################################
# display disk exerciser log file           #
#########################################################
sub show_2100_hba {
    &print_banner;
    $dfile_id = &get_dfileid;

    if ($dfile_id == -1) { 
        print "Log File Does Not Exist.\n"; 
    } else {
        $log_files = `/usr/bin/ksh -c '/bin/ls -1t ${LOGSEDR}/sedr.log.$dfile_id.str.hba_test.* 2>/dev/null'`;
        @arr_files = split(/\n/,$log_files);
        print "\nChecking Latest 2100 HBA test Log:\n";
        foreach $log_file (@arr_files) {
            if (-e $log_file) {
                print "Press <return> to view $log_file";
                $cont = <STDIN>;
                system "/usr/bin/more $log_file";
                print "\n";
            }
        }
    }
    &continue
}

#########################################################
# display disk exerciser log file           #
#########################################################
sub show_diskx {
    &print_banner;
    $dfile_id = &get_dfileid;

    if ($dfile_id == -1) { 
        print "Log File Does Not Exist.\n"; 
    } else {
        $log_files = `/usr/bin/ksh -c '/bin/ls -1t ${LOGSEDR}/sedr.log.$dfile_id.str.dex.* 2>/dev/null'`;
        @arr_files = split(/\n/,$log_files);
        print "\nChecking Latest Disk Exerciser Log:\n";
        foreach $log_file (@arr_files) {
            if (-e $log_file) {
                print "Press <return> to view $log_file";
                $cont = <STDIN>;
                system "/usr/bin/more $log_file";
                print "\n";
            }
        }
    }
    &continue
}

sub print_logscreen {
    &print_banner;
    print " [1] Storage Messages Summary\n";
    if ( $HBA eq "S" ) {
        print " [2] Fibre Loop Test - Full Logs\n";
        print " [3] Fibre Loop Test - Failures only\n";
    }
    print " [4] Disk Exerciser Logs\n";
    if ( $HBA eq "P" ) {
        print " [5] 2100 HBA Test Logs\n";
    }
    print " [6] Remove Log Files\n";
    print "\n";

    print " [q] Quit\n";
    print "\nSelect an operation to perform: ";
    chop($stdin=<STDIN>);
    return $stdin;
}

###############################################################
# cont_test
###############################################################
sub cont_test {
    $cont = 1;

    while($cont) {
        print "Would you like to continue: [y, <n>]: ";
        $tmp = &get_response('n');
        if ($tmp =~ /^n/i) {
            $cont = 0;
        } elsif ($tmp =~ /^y/i) {
            $cont = 0;
        } else {
            print "Please enter yes or no\n";
        }
    }
    return ($tmp); 
}

###############################################################
# continue
###############################################################
sub continue {
    print "\nPress <return> for previous menu ...";
    $cont = <STDIN>;
}


###############################################################
# prints the header banner for this program
###############################################################
sub print_banner {
    system_clear();
    &st_header();
    print "Menu: StorEdgeDr\n";
    print "----------------\n\n";
}


sub proc_cli {

    $HBA = "";
    $DUAL_PORT = $PRIMARY;
    $STORAGE = "T3";
    $LUN_DISK = "LUN";

    $usage[0] = "$PROGNAME [-help] [ -S | -P ] [ -A5 | -T3 ]\n";
    $usage[1] = "help - Display usage\n";
    $usage[2] = "S    - Select SBUS Host Adapters (default)\n";
    $usage[3] = "P    - Select PCI Host Adapters\n";
    $usage[4] = "A5   - Select A5K Series Storage (default)\n";
    $usage[5] = "T3   - Select T300 Series Storage\n";

    $arg = shift @ARGV;
    while($arg) {
        if ($arg =~ /help/)  {
            die @usage;
        } elsif ($arg =~ /^-S/) {
            $HBA = "S";
            check_bus_option( $HBA );
        } elsif ($arg =~ /^-P/) {
            $HBA = "P";
            check_bus_option( $HBA );
        } elsif ($arg =~ /^-A5/) {
            $STORAGE = "A5";
            $DUAL_PORT = $NONE;
            $LUN_DISK = "Drive";
        } elsif ($arg =~ /^-T3/) {
            $STORAGE = "T3";
            $DUAL_PORT = $PRIMARY;
            $LUN_DISK = "LUN";
        }

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

    if ( $HBA ne "P" && $HBA ne "S" ) {
        &get_fcal_hbas();
        &select_fcal_hbas();
    }

    print "HBA: $HBA\n" if ($DEBUG);
}


sub sedr {

    $ERRFILE_NAME = "sedr.log.$$.err";
    $LOGFILE = "$LOGSEDR/sedr.log.$$";
    $ERRFILE = "$LOGSEDR/$ERRFILE_NAME";

    &open_logfile($ERRFILE_NAME, $LOGSEDR);

    system "/usr/bin/touch $ERRFILE";

    $| = 1;         # turn off write buffer to print .

    # find the controllers present (list of c-names)

    &set_color( "ON" );
    &make_port_list( $HBA );

    #global variable used in subroutines
    if ( $STORAGE eq "A5" ) {
        $NUM_LOOPS = $#LD_A5_PORTS + 1;
    } elsif ( $STORAGE eq "T3" ) {
        $NUM_LOOPS = $#LD_T3_PORTS + 1;
    }

    if( -e $LOGFILE ) {

        print "$LOGFILE exists, overwrite( <y>, n = append ):";

        $resp = <STDIN>;

        if($resp =~ /^y/i) {
            open(LOGHAND, ">${LOGFILE}") or die "$LOGFILE failed to open: $!";
            print "\nCreating file $LOGFILE\n";
        } else  {
            open(LOGHAND, ">>${LOGFILE}") or die "$LOGFILE failed to open: $!";
            print "\nCreating file $LOGFILE\n";
        }
    }

    # Assign defaults all true, run all tests

    $LBF_ITERS = 1000;  
    $LBF_KBYTES = 64;

    $DEX_RUN_TIME = 10;
    if ( $HBA eq "S" ) {
        $LBF_ITERS = 1000;
        $HBA_MODE = "skip";
    } elsif ( $HBA eq "P" ) {
        $CON_RUN_TIME = 1;
        $HBA_MODE = "execute";
    }
    $RD_CHOICE = "ro";
    $FIRST = 1;
    $MIN_RUN_TIME = 1;     # min time 1 minute
    $MAX_RUN_TIME = 1440;  # max time 24 hours
    $SHOW_LOGS="verbose";
    $NO_LOGS="quiet";
    $VIEW_LOGS = $SHOW_LOGS;

    # get user responses

    $first = 1;
    while(1) {
        if(!$first) {
            print "\nPress any key to continue.....\n";
            <STDIN>
        }

        $res = display_menu();
        $first = 0; 

        if($res eq "std") {
            &sedr_test();
        } elsif ($res eq "exit") {
            last;
        }

    }
    close(LOGHAND);
    
}

sub display_menu {

    system_clear();
    &st_header();
    print "Menu: StorEdgeDr\n";
    print "----------------\n\n";
    print " \n";
    print "CAUTION: DO NOT run this test while other loop diagnostics\n";
    print "         or I/O are running on the loop to be tested.\n\n";

    if ( $FIRST ) {
        if ( $STORAGE eq "A5" ) {
            @TEST_LP_LIST = @LD_A5_PORTS;
        } elsif ( $STORAGE eq "T3" ) {
            @TEST_LP_LIST = @LD_T3_PORTS;
        }
        $FOREGROUND = 1;
        $TEST_ENVIRONMENT = "Foreground";
        $FIRST = 0;
        $ONLINE_TEST = "online";
        $OFFLINE_TEST = "offline";
        $TEST_MODE = $ONLINE_TEST;
    }

    while (1) {

        print ("\n\n");
        print ("Options                                Value\n");
        print ("===========================            ====================\n");
        print "[m] Dual Port Mode                     $DUAL_PORT\n";

        print "[p] Port(s) under test                 ";
        foreach $e (@TEST_LP_LIST) {
            print "$CNUM{$e} ";
        }
        print "\n";

        if ( $HBA eq "S" ) {
        print "[c] Data Path Pass Count               $LBF_ITERS pass(es)\n";
        } elsif ( $HBA eq "P" ) {
        print "[c] Data Path Run Time                 $CON_RUN_TIME minute(s)\n";
        }
        print "[d] dex Duration                       $DEX_RUN_TIME minute(s)\n";
        print "[h] HBA test                           $HBA_MODE\n";  
        print "[v] Verbose                            $VIEW_LOGS\n";  

        print "\n[r] Run\n";
        print "\n[q] Quit\n\n";

        print "Enter Selection [<r>,m,p,c,d,h,v,q]: ";
        $choice = &get_response("r");               # user response

        if($choice =~ /^q/i ) {         # Q or q : quit 
            return "exit";
        }

        if ( $choice =~ /^m/i ) {
            $DUAL_PORT = &select_dual_port_mode();
            next;
        }

        if($choice =~ /^p/i ) {      
            get_test_list();
            next;
        }

        if($choice =~ /^c/i ) {      
            if ( $HBA eq "S" ) {
                $LBF_ITERS = &get_iterations( $LBF_ITERS );
            } elsif ( $HBA eq "P" ) {
                $CON_RUN_TIME = &get_time( $CON_RUN_TIME );
            }
            next;
        }

        if($choice =~ /^d/i ) {      
            $DEX_RUN_TIME = &get_time( $DEX_RUN_TIME );
            next;
        }

        if($choice =~ /^h/i ) {      
            if ( $HBA_MODE eq "execute" ) { 
                $HBA_MODE = "skip";
            } else {
                $HBA_MODE = "execute";
            } 
            next;
        }

        if($choice =~ /^v/i ) {      
            if($VIEW_LOGS eq $SHOW_LOGS) {
                $VIEW_LOGS = $NO_LOGS;
            } else {
                $VIEW_LOGS = $SHOW_LOGS;
            }
            next;
        }

# Code to be implemented when we get the offline version of 2100 hba_test
# Brad DeRolf 06/23/99

        #if($choice =~ /^t/i ) {      
            #if($TEST_MODE eq $ONLINE_TEST) {
                #$TEST_MODE = $OFFLINE_TEST;
            #} else {
                #$TEST_MODE = $ONLINE_TEST;
            #}
            #next;
        #}

        if($choice =~ /^r/i ) {
            return "std";
        }

        print "\n";
        print "$choice is an invalid option!\n";
        
    }

}

####################################################################
# check iterations
####################################################################
sub get_iterations {

    my $run_time = $_[0];

    while ( 1 ) {
        print "Please enter iterations in decimal [between $MIN_RUN_TIME and $MAX_RUN_TIME, <$run_time>]: ";
        $run_time = &get_response( $run_time );
        chomp($run_time);
        if(($run_time < $MIN_RUN_TIME) || ($run_time > $MAX_RUN_TIME)) {
            print "$run_time is an invalid count!\n";
			$run_time = $_[0];
            next;
        }
        last;
    }
    return($run_time);

}
####################################################################
# check time
####################################################################
sub get_time {

    my $run_time = $_[0];

    while ( 1 ) {
        print "Please enter run-time in minutes [between $MIN_RUN_TIME and $MAX_RUN_TIME, <$run_time>]: ";
        $run_time = &get_response( $run_time );
        chomp($run_time);
        if(($run_time < $MIN_RUN_TIME) || ($run_time > $MAX_RUN_TIME)) {
            print "$run_time is an invalid time!\n";
			$run_time = $_[0];
            next;
        }
        last;
    }
    return($run_time);

}

# This will fork a process that will montior the log
# file passed as arg 1
# needs to get killed at end of test.

        
####################################################################
# run lbf and dex
# new logfile created, sedr.pid.lbfdex.cnum
####################################################################

sub sedr_test {

    my $test_name;
    my $verbose;
    my $expected_dma_errors;
    my $test_status = 0;
    my $start_date;

    &st_sync();

    if ( ( $HBA eq "S" ) && ( $HBA_MODE eq "execute" ) ) {

        # SBUS Host Bus Adapter Test
        # currently using lbf 
        # want to change to SUNvts test in future

        $test_name = "SBUS HBA test(lbf)";

        print "\nThe ${test_name} is an offline test.\n";
        print "Do you wish to run the ${test_name}? [<n>, y]: ";
        $cmd = &get_response("n");
        if ( $cmd !~ /^y/i ) { 
            goto TEST_DATA_PATH;
        }


        $DMA_ERRORS = &check_dma_errors( $expected_dma_errors, $verbose );

        print "\n";
        print LOGHAND "\n ======== Start of ${test_name}:   ";
        print LOGHAND `/bin/date`,"\n";
        system "/usr/bin/date >> $ERRFILE";
        &faux_logger("INFO", 2012, "start of ${test_name} from ${PROGNAME}");

        $SIG{INT} = 'IGNORE';

        # start up lbf 

        my $lbf_loop_cnt = 5;
        foreach $port (@TEST_LP_LIST) {
            print "\n*** Setting INTERNAL LOOPBACK for $port ***\n";
            `${BINDIR}/luxdiag int $port`;
            sleep 1;
        }
        for ( my $tc=0; $tc < $lbf_loop_cnt; $tc++ ) {
            foreach $port (@TEST_LP_LIST) {
                $lbf_cmd = "$BINDIR/lbf -q -t ffffffff -n 1000 -k 64 -c $port 2>>$ERRFILE >> $LOGFILE.str.lbf.$CNUM{$port}";
                print "$lbf_cmd\n" if ($DEBUG);
                system "/usr/bin/ksh -c '${lbf_cmd} & /bin/echo \$! > /tmp/pid_$$'";
                $lbf_cmd = "$BINDIR/lbf -q -t 00000000 -n 1000 -k 64 -c $port 2>>$ERRFILE >> $LOGFILE.str.lbf.$CNUM{$port}";
                print "$lbf_cmd\n" if ($DEBUG);
                system "/usr/bin/ksh -c '${lbf_cmd} & /bin/echo \$! > /tmp/pid_$$'";
                $pid = `/bin/cat /tmp/pid_$$`;  
                chomp $pid;
                push(@pidList, $pid);
                `/usr/bin/rm /tmp/pid_$$`;
                &make_pid_file($LOGDIR, $CNUM{$port}, $pid);
                $monPid = monitor_log("$LOGFILE.str.lbf.$CNUM{$port}");
                push(@MONITOR_PIDS, $monPid);
            }

            $SIG{INT} = 'clean_up';
        
            # wait for all to complete
            while(wait2comp(@pidList)) {   
                sleep 5;
                print ".";
            }
        } # end of 5 loop
        print "\n";
        killMonitor();
        if ( $VIEW_LOGS eq $SHOW_LOGS ) { 
            sleep 1;
            foreach $port (@TEST_LP_LIST) {
                system "/usr/bin/more $LOGFILE.str.lbf.$CNUM{$port}";
            }
        }
        foreach $port (@TEST_LP_LIST) {
            print "\n*** Resetting INTERNAL LOOPBACK for $port ***\n";
            `${BINDIR}/luxdiag nol $port`;
            sleep 1;
        }
        print LOGHAND " ======== End of ${test_name}:   ";
        print "\n";
        print LOGHAND `/bin/date`, "\n";
        system "/bin/date >> $ERRFILE";
        &faux_logger("INFO", 2013, "end of ${test_name} from ${PROGNAME}");
        `/usr/bin/ksh -c '/usr/bin/kill $tailPid 2>/dev/null'`;
        `/usr/bin/ksh -c '/usr/bin/rm $LOGDIR/pids/tail.$tailPid 2>/dev/null'`;
        print LOGHAND " ======== ${test_name} finished:   ";
        print LOGHAND `/bin/date`, "\n";
        system "/bin/date >> $ERRFILE";
        &faux_logger("INFO", 2013, "${test_name} from ${PROGNAME} finished");
        print "\n";
        $verbose = 1;
        $dma_errors = &check_dma_errors( $DMA_ERRORS, $verbose );
        if ( $dma_errors ) {
            print "${RED}A scan of /var/adm/messages detected $dma_errors DMA error
(s).${RC}\n";
            print "${RED}Replace offending FC100 HBA immediately.${RC}\n";
        }

        $test_status = &st_sum_test( "lbf", $test_name );

    } elsif ( ( $HBA eq "P" ) && ( $HBA_MODE eq "execute" ) ) {

        # PCI Host Bus Adapter Test

        $test_name = "PCI 2100 HBA test";

        print "\n";
        print LOGHAND "\n ======== Start of ${test_name}:   ";
        print LOGHAND `/bin/date`,"\n";
        system "/usr/bin/date >> $ERRFILE";
        &faux_logger("INFO", 2012, "start of ${test_name} from ${PROGNAME}");
        foreach $port (@TEST_LP_LIST) {
            $test_port = $port;
            if ( $test_port =~ /ifp/ ) {
                $test_port =~ s/ifp\@(\d),0:0/ifp\@$1:devctl/;
            } elsif ( $test_port =~ /scsi/ ) {
                $test_port =~ s/scsi\@(\d),0:0/scsi\@$1:devctl/;
            }
            print "$BINDIR/hba_test $test_port -k 2>>$ERRFILE >> $LOGFILE.str.hba_test.$CNUM{$port} &\n\n" if ($DEBUG);
            system "/usr/bin/ksh -c '$BINDIR/hba_test $test_port 2>>$ERRFILE >> $LOGFILE.str.hba_test.$CNUM{$port} & /bin/echo \$! > /tmp/pid_$$'";
        }
        $SIG{INT} = 'clean_up';
    
        # wait for all to complete
        while(wait2comp(@pidList)) {   
            sleep 5;
            print ".";
        }
        print "\n";
        killMonitor();
        if ( $VIEW_LOGS eq $SHOW_LOGS ) { 
            sleep 1;
            foreach $port (@TEST_LP_LIST) {
                system "/usr/bin/more $LOGFILE.str.hba_test.$CNUM{$port}";
            }
        }
        print LOGHAND " ======== End of ${test_name}:   ";
        print "\n";
        print LOGHAND `/bin/date`, "\n";
        system "/bin/date >> $ERRFILE";
        &faux_logger("INFO", 2013, "end of ${test_name} from ${PROGNAME}");
        `/usr/bin/ksh -c '/usr/bin/kill $tailPid 2>/dev/null'`;
        `/usr/bin/ksh -c '/usr/bin/rm $LOGDIR/pids/tail.$tailPid 2>/dev/null'`;
        print LOGHAND " ======== ${test_name} finished:   ";
        print LOGHAND `/bin/date`, "\n";
        system "/bin/date >> $ERRFILE";
        &faux_logger("INFO", 2013, "${test_name} from ${PROGNAME} finished");
        print "\n";
        $test_status = &st_sum_test( "hba_test", $test_name );

    }
    if ( $test_status != 0 ) {
        print "Test status: $test_status\n";
        print "Replace HBA and restart testing.\n";
        return;
    }

    &st_sync();
    undef @pidList;

TEST_DATA_PATH:

    $start_date = `/usr/bin/date '+%m/%d/%Y:%H:%M'`;
    chomp $start_date;

    if ( $HBA eq "S" ) {

        # SBUS Host data path test

LBF_DATA_PATH_TEST:

        $test_name = "SBUS Data Path test(lbf)";

        print "\n";
        print LOGHAND "\n ======== Start of ${test_name}:   ";
        print LOGHAND `/bin/date`,"\n";
        system "/usr/bin/date >> $ERRFILE";
        &faux_logger("INFO", 2012, "start of ${test_name} from ${PROGNAME}");

        $SIG{INT} = 'IGNORE';

        # start up lbf 

        foreach $port (@TEST_LP_LIST) {
            $lbf_cmd = "$BINDIR/lbf -q -a -k $LBF_KBYTES -n $LBF_ITERS $port 2>>$ERRFILE >> $LOGFILE.str.lbf.$CNUM{$port}";
            print "$lbf_cmd\n" if ($DEBUG);
            system "/usr/bin/ksh -c '${lbf_cmd} & /bin/echo \$! > /tmp/pid_$$'";
            $pid = `/bin/cat /tmp/pid_$$`;  
            chomp $pid;
            push(@pidList, $pid);
            `/usr/bin/rm /tmp/pid_$$`;
            &make_pid_file($LOGDIR, $CNUM{$port}, $pid);
            $monPid = monitor_log("$LOGFILE.str.lbf.$CNUM{$port}");
            push(@MONITOR_PIDS, $monPid);
        }

        $SIG{INT} = 'clean_up';
    
        # wait for all to complete
        while(wait2comp(@pidList)) {   
            sleep 5;
            print ".";
        }
        print "\n";
        killMonitor();
        if ( $VIEW_LOGS eq $SHOW_LOGS ) { 
            sleep 1;
            foreach $port (@TEST_LP_LIST) {
                system "/usr/bin/more $LOGFILE.str.lbf.$CNUM{$port}";
            }
        }
        print LOGHAND " ======== End of ${test_name}:   ";
        print "\n";
        print LOGHAND `/bin/date`, "\n";
        system "/bin/date >> $ERRFILE";
        &faux_logger("INFO", 2013, "end of ${test_name} test from ${PROGNAME}");
        `/usr/bin/ksh -c '/usr/bin/kill $tailPid 2>/dev/null'`;
        `/usr/bin/ksh -c '/usr/bin/rm $LOGDIR/pids/tail.$tailPid 2>/dev/null'`;
        print LOGHAND " ======== ${test_name} finished:   ";
        print LOGHAND `/bin/date`, "\n";
        system "/bin/date >> $ERRFILE";
        &faux_logger("INFO", 2013, "${test_name} from ${PROGNAME} finished");
        print "\n";
        print "Scanning message logs for errors.\n";
        $messages = `$BINDIR/mess_sum -$HBA -$STORAGE -q -s $start_date | grep errors`;
        if ( ! $messages ) {
            print "No errors detected in message logs.\n";
        }
        $test_status = &st_sum_test( "lbf", $test_name );
        if ( ( $test_status != 0 ) || ( $messages ) ) {
            if ( $test_status != 0 ) {
                print "   Test status: $test_status\n";
            } 
            if ( $messages ) {
               print "\nA scan of the systems logs detected errors.\n";
               print "Please inspect the log file to determine the cause of\n";
               print "error(s).\n";
               print "\nPlease press <return> to check system logs:";
               &get_response;
               system "$BINDIR/mess_sum -$HBA -$STORAGE -s $start_date";
            } else {
               print "\nA scan of the systems logs did not detect any errors.\n";
               print "Problem most likely a data path problem.\n";
            }
            &data_path_error();
            print "filtr -T3 is the best method for isolating data path FRUs.\n";
            print "Invoke T300 filtr [ <y>, n ]? ";
            $choice = &get_response( "y" );
            if ( $choice eq "y" ) {
                &get_test_list( "lbf" );
                foreach $port (@TEST_LP_LIST) {
                    system "${BINDIR}/filtr -T3 -sedr -m $port";
                }
            } else {
                print "filtr skipped.\n";
            }
            print "rerun data path test [ <y>, n ]? ";
            $choice = &get_response( "y" );
            if ( $choice eq "y" ) {
                goto LBF_DATA_PATH_TEST;
            }
            return;
        }

    } elsif ( $HBA eq "P" ) {

        # PCI Host data path test
        $test_name = "PCI Data Path test(dex)";

        print "\n";
        print LOGHAND "\n ======== Start of ${test_name}:   ";
        print LOGHAND `/bin/date`,"\n";
        system "/usr/bin/date >> $ERRFILE";

        &faux_logger("INFO", 2010, "start of ${test_name} $RD_CHOICE test from ${PROGNAME}");
        undef @pidList;
        $SIG{INT} = 'IGNORE';
        $dex_cnt = 0;

        #start up dex for each controller

        foreach $port (@TEST_LP_LIST) {
            if ( ( $DUAL_PORT eq $NONE ) || ( $DUAL_PORT eq $BOTH_AP ) ) {
                $dex_cmd = "$BINDIR/seq_dex $CNUM{$port} $RD_CHOICE $CON_RUN_TIME $STORAGE_DEVICE 2>>$ERRFILE >> $LOGFILE.str.dex.${dex_cnt}";
            } elsif ( ( $DUAL_PORT eq $PRIMARY ) || ( $DUAL_PORT eq $ALTERNATE ) ) {
                @drives = &get_dual_port_disks( $DUAL_PORT, $port );
                if ( ! @drives ) {
                    print "\n";
                    print "Program ERROR!\n";
                    print "Invalid Dual Port Mode: $DUAL_PORT for $CNUM{ $port}\n";
                    print "Press <return> to continue.\n";
                    &get_response();
                    exit(-1);
                }
                $dex_cmd = "$BINDIR/seq_dex $CNUM{$port} $RD_CHOICE $CON_RUN_TIME $STORAGE_DEVICE @drives 2>>$ERRFILE >> $LOGFILE.str.dex.${dex_cnt}";

            } else {
                print "Program ERROR!\n";
                print "Invalid Dual Port Mode: $DUAL_PORT\n";
                exit(-1);
            }
            print "$dex_cmd\n\n" if ( $DEBUG );
            system "/usr/bin/ksh -c '${dex_cmd} & /bin/echo \$! > /tmp/pid_$$'";
            $pid = `/bin/cat /tmp/pid_$$`;  
            push(@pidList, $pid);
            `/bin/rm /tmp/pid_$$`;
            chomp $pid;
            &make_pid_file($LOGDIR, $CNUM{$port}, $pid);
            $dex_cnt += 1;
        }

        $SIG{INT} = 'clean_up';

        # wait for all to complete
        while(wait2comp(@pidList)) {   
            sleep 5;
            print ".";
        }
        print "\n";
        killMonitor();
        if ( $VIEW_LOGS eq $SHOW_LOGS ) { 
            sleep 1;
            for ( $cnt=0; $cnt < $dex_cnt; $cnt++ ) {
                system "/usr/bin/more $LOGFILE.str.dex.${cnt}";
            }
        }
        print LOGHAND " ======== End of ${test_name}:   ";
        print LOGHAND `/bin/date`, "\n";
        system "/bin/date >> $ERRFILE";
        print "\n";
        &faux_logger("INFO", 2011, "end of ${test_name} $RD_CHOICE test from ${PROGNAME}");
        `/usr/bin/ksh -c '/usr/bin/kill $tailPid 2>/dev/null'`;
        `/usr/bin/ksh -c '/usr/bin/rm $LOGDIR/pids/tail.$tailPid 2>/dev/null'`;
        print LOGHAND " ======== ${test_name} finished:   ";
        print LOGHAND `/bin/date`, "\n";
        system "/bin/date >> $ERRFILE";
        &faux_logger("INFO", 2011, "${test_name} $RD_CHOICE test from ${PROGNAME} finished");
        print "\n";
        print "Scanning message logs for errors.\n";
        $messages = `$BINDIR/mess_sum -$HBA -$STORAGE -q -s $start_date | grep errors`;
        if ( ! $messages ) {
            print "No errors detected in message logs.\n";
        }
        $test_status = &st_sum_test( "dex", $test_name );
        if ( ( $test_status != 0 ) || ( $messages ) ) {
            if ( $test_status != 0 ) {
                print "   Test status: $test_status\n";
            } 
            if ( $messages ) {
               print "\nA scan of the system logs detected errors.\n";
               print "Please inspect the log file to determine the cause of\n";
               print "error(s). Possible ${STORAGE_DEVICE} problem.\n";
               print "\nPlease press <return> to check system logs:";
               &get_response;
               system "$BINDIR/mess_sum -$HBA -$STORAGE -s $start_date";
            } else {
               print "\nA scan of the system logs did not detect any errors.\n";
               print "Problem most likely a data path problem.\n";
               &data_path_error();
            }
            return;
        }

    }

    # Storage test for both SBUS and PCI

    &st_sync();

    $test_name = "Storage test(dex)";

    $start_date = `/usr/bin/date '+%m/%d/%Y:%H:%M'`;
    chomp $start_date;

    print "\n";
    print LOGHAND "\n ======== Start of ${test_name}:   ";
    print LOGHAND `/bin/date`,"\n";
    system "/usr/bin/date >> $ERRFILE";

    &faux_logger("INFO", 2010, "start of ${test_name} $RD_CHOICE test from ${PROGNAME}");
    undef @pidList;
    $SIG{INT} = 'IGNORE';
    $dex_cnt = 0;

    #start up dex for each controller

    foreach $port (@TEST_LP_LIST) {
        if ( ( $DUAL_PORT eq $NONE ) || ( $DUAL_PORT eq $BOTH_AP ) ) {
            $dex_cmd = "$BINDIR/seq_dex $CNUM{$port} $RD_CHOICE $DEX_RUN_TIME $STORAGE_DEVICE 2>>$ERRFILE >> $LOGFILE.str.dex.${dex_cnt}";
        } elsif ( ( $DUAL_PORT eq $PRIMARY ) || ( $DUAL_PORT eq $ALTERNATE ) ) {
            @drives = &get_dual_port_disks( $DUAL_PORT, $port );
            if ( ! @drives ) {
                print "\n";
                print "Program ERROR!\n";
                print "Invalid Dual Port Mode: $DUAL_PORT for $CNUM{ $port}\n";
                print "Press <return> to continue.\n";
                &get_response();
                exit(-1);
            }
            $dex_cmd = "$BINDIR/seq_dex $CNUM{$port} $RD_CHOICE $DEX_RUN_TIME $STORAGE_DEVICE @drives 2>>$ERRFILE >> $LOGFILE.str.dex.${dex_cnt}";

        } else {
            print "Program ERROR!\n";
            print "Invalid Dual Port Mode: $DUAL_PORT\n";
            exit(-1);
        }
        print "$dex_cmd\n\n" if ( $DEBUG );
        system "/usr/bin/ksh -c '${dex_cmd} & /bin/echo \$! > /tmp/pid_$$'";
        $pid = `/bin/cat /tmp/pid_$$`;  
        push(@pidList, $pid);
        `/bin/rm /tmp/pid_$$`;
        chomp $pid;
        &make_pid_file($LOGDIR, $CNUM{$port}, $pid);
        $dex_cnt += 1;
    }

    $SIG{INT} = 'clean_up';

    # wait for all to complete
    while(wait2comp(@pidList)) {   
        sleep 5;
        print ".";
    }
    print "\n";
    killMonitor();
    if ( $VIEW_LOGS eq $SHOW_LOGS ) { 
        sleep 1;
        for ( $cnt=0; $cnt < $dex_cnt; $cnt++ ) {
            system "/usr/bin/more $LOGFILE.str.dex.${cnt}";
        }
    }
    print LOGHAND " ======== End of ${test_name}:   ";
    print LOGHAND `/bin/date`, "\n";
    system "/bin/date >> $ERRFILE";
    print "\n";
    &faux_logger("INFO", 2011, "end of ${test_name} $RD_CHOICE test from ${PROGNAME}");
    `/usr/bin/ksh -c '/usr/bin/kill $tailPid 2>/dev/null'`;
    `/usr/bin/ksh -c '/usr/bin/rm $LOGDIR/pids/tail.$tailPid 2>/dev/null'`;
    print LOGHAND " ======== ${test_name} finished:   ";
    print LOGHAND `/bin/date`, "\n";
    system "/bin/date >> $ERRFILE";
    &faux_logger("INFO", 2011, "${test_name} $RD_CHOICE test from ${PROGNAME} finished");
    print "\n";
    print "Scanning message logs for errors.\n";
    $messages = `$BINDIR/mess_sum -$HBA -$STORAGE -q -s $start_date | grep errors`;
    if ( ! $messages ) {
        print "No errors detected in message logs.\n";
    }
    $test_status = &st_sum_test( "dex", $test_name );
    if ( ( $test_status != 0 ) || ( $messages ) ) {
        if ( $test_status != 0 ) {
            print "   Test status: $test_status\n";
        } 
        if ( $messages ) {
           print "\nA scan of the system logs detected errors.\n";
           print "Please inspect the log file to determine the cause of\n";
           print "error(s). Possible ${STORAGE_DEVICE} problem.\n";
           print "\nPlease press <return> to check system logs:";
           &get_response;
           system "$BINDIR/mess_sum -$HBA -$STORAGE -s $start_date";
        } else {
           print "\nA scan of the system logs did not detect any errors.\n";
           print "Problem most likely a data path problem.\n";
           &data_path_error();
        }
        return;
    }
    
}

sub monitor_log { 

    my $log = $_[0];

    # and can be tested elsewhere to ensure kills do not
    # do anything the parent should really do.

    if($pid = fork()) {
        return($pid);
    } else {

        $MONITOR = "TRUE";  # this variable will set this process copy as unique
        $SIG{INT} = 'clean_up';
        while( ! -e $log ) {
            sleep 5;
        }
        open(LOG, "$log") || die "sedr:  monitor_log cannot open [$log]";

        while ( 1 ) {
            if ( $line = <LOG> ) {
                if ( $line =~ /fail/i ) {
                    print "\n$line";
                }
            }
            sleep 1;
        }
        exit;

    }

    return(-1);

}
            

sub killMonitor {

    foreach $i ( @MONITOR_PIDS ) {
        `kill $i`;

    }

}

####################################################################
# control c interrupt handler
####################################################################

sub clean_up {

    if($MONITOR eq "TRUE" ) { 
    # don't do any cleanup.. This is just a monitor version
        # see monitor_log().
        exit;
    }
    if($FOREGROUND) {
        killMonitor();
        kill_pid_files($LOGDIR, "k", "TRUE");  # kill processes silently
    }
    exit;
}

####################################################################
# faux_logger to /var/adm/messages
# messages to var adm messages should have the form:
#  date: [A5000:DIAG:<status>:<error number>] error message
#   INPUTS:
#   $status     WARNING or ERROR or FAIL or INFO
#   $error-number   4 digit error code
#   $error-message  1 line message string
####################################################################

sub faux_logger {

    ($status, $error_number, $message) = @_;
    print "$status : $message\n";
    logger($status, $error_number, $message);

}

sub data_path_error {
print <<END;

  FC-AL connect to the $STORAGE_DEVICE failed.
  Check GBIC connections. Make sure that the bail is in the correct postion.
  Check MIA connection. If all are secure, replace one item at a time staring 
  with a single GBIC. Re-run the test.  If replacing the GBICs does not 
  correct the problem, change the MIA and re-start the test. If replacing
  the MIA does not correct the problem, replace the FC-AL cable and re-test.
  If the problem persists try replacing either the ${STORAGE_DEVICE} FC-AL
  board or the FC-AL HBA adapter. During each re-test always make sure the
  the error reported is consistent before changing a new part. For instance,
  if changing the GBIC consistently produces a 5A's pattern failure and the
  original GBIC consistantly produced a 7E's pattern failure, both GBIC may
  be faulty.
       
END
}
