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

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

$PROGNAME = "iopmenu";
####################################################################
#
# make a menu to run the dex script
# 
# 
# 7/23/98 add a [all] option 
# 8/3/98  if no loops, exit
# 8/3/98  add menu questions, support sequential/random
# 8/23/98 remove write option from menu
# 9/11/98 do not use snapshot to build menu
# 11/21/98 convert from pp2 to dex32
# 11/21/98 convert from pp2 to dex32
# 12/08/98 added pci FC100 supprt
# Copyright (c) 1998  Sun Microsystems Computer Corporation, Inc.
####################################################################

# $DEBUG = "TRUE";
$| = 1;     # turn off STDOUT buffering


####################################################################
# dex scripts to call
#  these are all based on rw_dex
####################################################################
$KEEP = ""; # assume we don't want to keep file after file_dex creates it
$SEQ_DEX32_SCR  = "$BINDIR/seq_dex"; # S code
$RAN_DEX32_SCR  = "$BINDIR/ran_dex"; # R code
$FILE_DEX32_SCR = "$BINDIR/file_dex";# M code
$DEX_PARAMS = "Default Parameters";
@DEX_TEST_LIST = (
    "Sequential I/O Test", "S",
    "Random I/O Test", "R", 
    "Memory Mapped Sequential I/O Test", "M"
    );
$DEX_TEST = "0";
$RUN_TIME = "60m";
$default_dex_params = "-v -S1 8g 0 60m -x 128k -r -e 1000";
$current_dex_params = $default_dex_params;
$media_range = "8g";
$file_media_range = "10m";
$st_first_time = 1;

####################################################################
# inputs:
#   component   socal, sf, array
#   comp_name   
#
####################################################################

$SIG{"INT"} = 'interrupt';      # turn on interrupt

&check_root_access( $PROGNAME );

# process the inputs
&proc_cli;

# make a names list
&get_online_summary;

@TEST_PORTS = @LD_DD_PORTS if ( $#LD_DD_PORTS >= 0 );

if ( $#LD_MB_PORTS >= 0 ) {
    # Onboard (Motherboard) internal drive ports are valid here.
    # so just add them to TEST_PORTS
    if ( $#LD_MB_PORTS >= 0 ) {
        @TEST_PORTS = ( @TEST_PORTS, @LD_MB_PORTS );
    }
}

@CN_TEST = @TEST_PORTS;  # assume all controllers to target
    foreach $port ( @CN_TEST ) {
        $SELECTED_DRIVES{ $port } = ();   # empty when using all drives
    }

MENU: while (1) {
    
    &pr_menu();
    if ( $#TEST_PORTS >= 0 ) {
        # &pr_menu();
    } else {
        print "\nNo loops found.\n\n";
        print "Press <return> to continue.\n";
        &get_response();
        exit;
    }
    $show = "";
    print "\n";
    if ($target_mode eq "raw") {
        if ($#CN_TEST >= 0) {
            foreach $path (@CN_TEST) {
                if ($SELECTED_DRIVES{$path} eq "") {
                    ################################################
                    # All drives on this loop targeted for testing.#
                    # If T300 drives are on this loop, then remove #
                    # alternate path if in primary mode.           #
                    ################################################
                    if ($T300_DRIVES{$path} ne "") {
                        ########################################
                        # T300 drives are on this loop. Remove #
                        # alternate path if in primary mode.   #
                        ########################################
                        $SELECTED_DRIVES{$path} = $T300_DRIVES{$path};
                        $SELECTED_DRIVES{$path} .= " $A5000_DRIVES{$path}" if ($A5000_DRIVES{$path} ne "");
                    }
                } 
                @drives = split / /, $SELECTED_DRIVES{ $path };
                $SELECTED_DRIVES{ $path } = "";
                foreach $drive ( @drives ) {
                     if (($T300{$drive} eq "p") && ($DUAL_PORT eq $PRIMARY)) {
                         ############################################
                         # Primary drive and we are in primary mode #
                         # so allow testing to it.                  #
                         ############################################
                         $SELECTED_DRIVES{ $path } .= $drive;
                         $SELECTED_DRIVES{ $path } .= " ";
                     } elsif (($T300{$drive} eq "a") && ($DUAL_PORT eq $ALTERNATE)) {
                         ################################################
                         # Alternate drive and we are in alternate mode #
                         # so allow testing to it.                      #
                         ################################################
                         $SELECTED_DRIVES{ $path } .= $drive;
                         $SELECTED_DRIVES{ $path } .= " ";
                     } elsif ($T300{$drive} eq "") {
                         ############################################
                         # Not a T300 drive, so allow testing to it #
                         ############################################
                         $SELECTED_DRIVES{ $path } .= $drive;
                         $SELECTED_DRIVES{ $path } .= " ";
                     } else {
                         print "Skipping drive $drive";
                         print " (primary T300 LUN)" if (($T300{$drive} eq "p") && ($DUAL_PORT eq $ALTERNATE));
                         print " (alternate T300 LUN)" if (($T300{$drive} eq "a") && ($DUAL_PORT eq $PRIMARY));
                         print "\n";
                     }
                }
                $show .= "$DEX_TEST_LIST[$DEX_TEST] $CNUM{$path} $RD_CHOICE $RUN_TIME $STORAGE_DEVICE $SELECTED_DRIVES{ $path }\n";
		if ($T300_DRIVES{$path} ne "") 
		{
		   @drives = split / /, $SELECTED_DRIVES{ $path };

                   if ( ! @drives ) 
    	           {
                      print "\n";
                       print "No drives or LUNs on $CNUM{$path} to test.\n";
    	               print "Could be an invalid mixture of Dual Port Mode and selected drives.\n";
    	               print "Please check that selected drives agree with selected Dual Port Mode. \n";
                       print "\nPress <return> for previous menu ...";
                       &get_response();
	    	       
	               goto MENU;
                    }
		 }
            }
	    
        }

        

        print "\nStart the following dex tests:\n\n";
        print $show;
    } else {
        print "\nStart the following dex tests:\n\n";
        print "    $DEX_TEST_LIST[$DEX_TEST] $TARGET_FILE $RD_CHOICE $RUN_TIME $STORAGE_DEVICE\n";
    }
RUN_TEST:
    print "\nWould you like to run these tests [<y>, n, q]:";
    $cmd = &get_response( "y" );
    if ( $cmd =~ /^y/i ) {
        system("/usr/bin/logger -p mail.crit -i -t \"Info:\" \"Starting dex32 from ${PRODUCT} ${PROGNAME} $RD_CHOICE\"");
        if ($target_mode eq "raw") {
            foreach $path (@CN_TEST) {
                ##############################
                # fire up dex to controllers #
                ##############################
                $cnumber = "$CNUM{$path}";
                $ENV{'DEX_ARGS'} = $current_dex_params;
                my $code = $DEX_TEST_LIST[$DEX_TEST + 1];
                if ($code eq 'S') {
                    $command_line = "$SEQ_DEX32_SCR";
                } elsif ($code eq 'R') {
                    $command_line = "$RAN_DEX32_SCR";
                } else {
                    print "Skipping $DEX_TEST_LIST[$DEX_TEST], not for raw mode\n";
                    next;
                }
                $command_line .= " $cnumber $RD_CHOICE $RUN_TIME $STORAGE_DEVICE $SELECTED_DRIVES{ $path }";
    
                print "Log file is $LOGDIAGS/dex.$cnumber.$$\n";
                if( ! -e "$LOGDIAGS/dex.$cnumber.$$") {
                    `touch $LOGDIAGS/dex.$cnumber.$$`;
                }

                system "/usr/bin/ksh -c '/usr/bin/date >> $LOGDIAGS/dex.$cnumber.$$'";
                system "/usr/bin/ksh -c '/usr/bin/echo $command_line >> $LOGDIAGS/dex.$cnumber.$$'";
                system ("/usr/bin/ksh -c '$command_line >> $LOGDIAGS/dex.$cnumber.$$ & /usr/bin/echo \$! > /tmp/pid_$$'");
                delete $ENV{'DEX_ARGS'};
                $pid =  `/usr/bin/cat /tmp/pid_$$`;
                chomp $pid;
                `/usr/bin/rm /tmp/pid_$$`;
                sleep 2;
                $lun_error_message = `/usr/bin/grep "unmounted or unlabeled" $LOGDIAGS/dex.$cnumber.$$`;
                if ( $lun_error_message ) {
                    print "\n$lun_error_message\n";
                } 
            }
        } else {
            if ($TARGET_FILE) {
                ######################################
                # fire up dex to file not controller #
                ######################################
                $ENV{'DEX_ARGS'} = $current_dex_params;
                $command_line = "$FILE_DEX32_SCR $KEEP $TARGET_FILE $RD_CHOICE $RUN_TIME $STORAGE_DEVICE";
                print "Log file is $LOGDIAGS/dex.$FILE_CN.$$\n";
                if( ! -e "$LOGDIAGS/dex.$FILE_CN.$$") {
                    `touch $LOGDIAGS/dex.$FILE_CN.$$`;
                }

                system "/usr/bin/ksh -c '/usr/bin/date >> $LOGDIAGS/dex.$FILE_CN.$$'";
                system "/usr/bin/ksh -c '/usr/bin/echo $command_line >> $LOGDIAGS/dex.$FILE_CN.$$'";
                system ("/usr/bin/ksh -c '$command_line >> $LOGDIAGS/dex.$FILE_CN.$$ & /usr/bin/echo \$! > /tmp/pid_$$'");
                delete $ENV{'DEX_ARGS'};
                $pid =  `/usr/bin/cat /tmp/pid_$$`;
                chomp $pid;
                `/usr/bin/rm /tmp/pid_$$`;
                sleep 2;
                $lun_error_message = `/usr/bin/grep "unmounted or unlabeled" $LOGDIAGS/dex.$FILE_CN.$$`;
                if ( $lun_error_message ) {
                    print "\n$lun_error_message\n";
                } 
            }
        }
        print "\nPress <return> for previous menu ...";
        &get_response();

    } elsif ( $cmd =~ /^n/i ) {
        next;
    } elsif ( $cmd =~ /^q/i ) {
        exit;
    } else {
        print "\n$cmd in an invalid choice!\n";
        goto RUN_TEST;
    }
}
&logexit;

####################################################################
#    SUBROUTINES
#
####################################################################
####################################################################
# log exit
####################################################################
sub logexit {
    print `/usr/bin/date`;
    print "  #### END OF PROGRAM ######\n" if ($DEBUG);
}
####################################################################
# interrupt routine
####################################################################
sub interrupt {
    &logexit;
    exit;
}
####################################################################
# print out a summary of the fibre channel components    
####################################################################
sub pr_menu {

    my $menu_ans = "";
    my $comp_choice;
    my $drive_choice;

    while ($menu_ans ne "r") {
        system_clear();
        if ($current_dex_params =~ /(-wr|-rw)/) {
            $dex_mode = $1;
            $RD_CHOICE = "rw";
            $test_mode = "Write and Read";
        } elsif ($current_dex_params =~ /(-w\/r|-r\/w)/) {
            $dex_mode = $1;
            $RD_CHOICE = "rw";
            $test_mode = "Write then Read";
        } elsif ($current_dex_params =~ /(-w)/) {
            $dex_mode = $1;
            $RD_CHOICE = "rw";
            $test_mode = "Write Only";
        } else {
            $dex_mode = "-r";
            $RD_CHOICE = "ro";
            $test_mode = "Read Only";
        }

        &st_header;
        if ($st_first_time) {
            $st_first_time = 0; # kludge
            $target_mode = "raw";
        }
        $KEEP = "" if ($target_mode eq "raw");

        print "Menu: Disk Exerciser (Online Components Only)\n";
        print "---------------------------------------------\n\n";
        print "Options                                Value\n";
        print "======================                 ====================\n";
        print "[c] Test Mode                          $test_mode\n";
        print "[f] File|Raw                           $target_mode";
        if ($KEEP) {
            print " (not deleted)\n";
        } else {
            print "\n";
        }
        print "[m] T300 Dual Port Mode                $DUAL_PORT\n" if $T300_PRESENT;
        print "[s] Select ";
        if ( $target_mode eq "raw" ) {
            if ( ${LUN_DISK} eq "LUN" ) {
                print "${LUN_DISK}s                        ";
            } else {
                print "${LUN_DISK}s                      ";
            }
        } elsif ( $target_mode eq "file" ) {
            print "File                        ";
        }
        if ($target_mode eq "raw") {
            if ($#CN_TEST >= 0) {
                foreach $e (@CN_TEST) {
                    print "$CNUM{$e} ";
                    my @temp_list = split / /, $SELECTED_DRIVES{$e};
                    if ( @temp_list ) {
                        my $drive_ctd;
                        my $drive_ctd_cnt = 0;
                        foreach $drive_ctd ( sort @temp_list ) {
                            $drive_ctd_cnt++;
                        }
                        print "($drive_ctd_cnt ${LUN_DISK}(s))";
                    }
                }
            }
        } else {
           if ( $TARGET_FILE ) {
               print "$TARGET_FILE ($media_range)";
           } else {
               print "<none>";
           }
        }
        print "\n";
        print "[t] Test Type                          $DEX_TEST_LIST[$DEX_TEST]\n";
        print "[u] Run Time                           ";
        print "$1 Seconds\n" if ($RUN_TIME =~ /(\d+)s$/);
        print "$1 Minutes\n" if ($RUN_TIME =~ /(\d+)m$/);
        print "$1 Hours\n" if ($RUN_TIME =~ /(\d+)h$/);
        # print "[d] Dex Parameters                     ";
        # if ($current_dex_params eq $default_dex_params) {
        #    print "Default dex Parameters\n";
        # } else {
        #     print "User Defined Parameters\n";
        # }
        print "\n[r] Run\n";
        print "[p] Processes Management\n";
        print "[q] Quit\n\n";
    
        print "Enter Selection: ";
        $menu_ans = &get_response();
        if ($menu_ans =~ /^q/i) {
            exit;
        } elsif ( $menu_ans =~ /^m/i ) {
            $DUAL_PORT = &select_dual_port_mode();

        } elsif ($menu_ans =~ /^r/i) {
            ##########################
            # test if we can run now #
            ##########################
            if ($target_mode eq 'file') {
                if ($TARGET_FILE eq '') {
                    print "\nFilename missing\n\n";
                    print "Press <return> to continue ";
                    &get_response();
                    $menu_ans = '';
                    next;
                } else {
                    # file name chosen, so verify there if read only #
                    if ((! -e $TARGET_FILE) and ($RD_CHOICE !~ "w")) {
                        print "\nFile $TARGET_FILE does not exist. Cannot start Read Only test.\n";
                        $menu_ans = '';
                        next;
                    }
                }
            }
        } elsif ($menu_ans =~ /^c/i) {
            #########################
            # toggle rw and ro mode #
            #########################
            #if (($RD_CHOICE eq "ro") and ($target_mode eq "file")) {
            if ($RD_CHOICE eq "ro") {
                $RD_CHOICE = "rw";
                $target_mode = "file";
                $test_mode = "Write and Read";
                if ( !defined $TARGET_FILE ) {
                   &select_file();
                }
                if ( !defined $TARGET_FILE ) {
                    $test_mode = "Read Only";
                    $target_mode = "raw";
                    $RD_CHOICE = "ro";
                    $current_dex_params =~ s/$dex_mode/-r/;
                } else {
                    $current_dex_params =~ s/$dex_mode/-wr/;
                }
            } else {
                $test_mode = "Read Only";
                $RD_CHOICE = "ro";
                $current_dex_params =~ s/$dex_mode/-r/;
            }
            #if ( ( $RD_CHOICE eq "rw" ) and ( $target_mode eq "raw" ) ) {
                #$RD_CHOICE = "ro";
                #print "'Read/Write' is not valid in raw mode\n";
                #print "Read Only selected\n\n";
                #print "Press <return> to continue ";
                #&get_response();
            #}
        } elsif ($menu_ans =~ /^t/i) {
            ########################################
            # increment to the next test in list & #
            # update dex options strings.          #
            ########################################
            my $temp = "-" . $DEX_TEST_LIST[$DEX_TEST+1];
            $DEX_TEST +=2;
            $DEX_TEST = 0 if ($DEX_TEST >= $#DEX_TEST_LIST);
            my $temp2 = "-" . $DEX_TEST_LIST[$DEX_TEST+1];
            $current_dex_params =~ s/$temp/$temp2/;
            $default_dex_params =~ s/$temp/$temp2/;
            if ($temp2 eq "-R") {
                ################################
                # Random test, change -x to 1k #
                # and -R1 to -R4               #
                ################################
                my $trans;
                if ($current_dex_params =~ /-x (\d+[gmkb])/) {
                    $trans = $1;
                    $trans = "-x $trans";
                    $current_dex_params =~ s/$trans/-x 1k/;
                    $default_dex_params =~ s/$trans/-x 1k/;
                }
                if ($current_dex_params =~ /-R(\d+) (\d+[gmk])/) {
                    $trans = "$1 $2";
                    $current_dex_params =~ s/-R$trans/-R4 200m/;
                    $default_dex_params =~ s/-R$trans/-R4 200m/;
                }
            } elsif (($temp2 eq "-S") or ($temp2 eq "-M")) {
                ######################################
                # Sequential test, change to -x 128k #
                ######################################
                my $trans;
                if ($current_dex_params =~ /-x (\d+[gmkb])/) {
                    $trans = $1;
                    $trans = "-x $trans";
                    $current_dex_params =~ s/$trans/-x 128k/;
                    $default_dex_params =~ s/$trans/-x 128k/;
                }
                if ($current_dex_params =~ /-S(\d+) (\d+[gmk])/) {
                    $trans = "$1 $2";
                    $current_dex_params =~ s/-S$trans/-S1 8g/;
                    $default_dex_params =~ s/-S$trans/-S1 8g/;
                } elsif ($current_dex_params =~ /-M(\d+) (\d+[gmk])/) {
                    $trans = "$1 $2";
                    $current_dex_params =~ s/-M$trans/-M1 8g/;
                    $default_dex_params =~ s/-M$trans/-M1 8g/;
                }
            }

        #} elsif ($menu_ans =~ /^d/i) {
            #####################################
            # Allow tweaking of all dex options #
            #####################################
            #$current_dex_params = &dexoptions($default_dex_params,$current_dex_params,"n", "y");
            #if ($current_dex_params =~ /-\w+\d+\s(\d+[gmk])\s/) {
                #$media_range = $1;
            #}
            #if ($current_dex_params eq $default_dex_params) {
                #$DEX_PARAMS = "Default Parameters";
            #} else {
                #$DEX_PARAMS = "User Defined Parameters";
            #}
            #########################
            # Re-establish RUN_TIME #
            #########################
            #my $temp = "-" . $DEX_TEST_LIST[$DEX_TEST+1];
            #$RUN_TIME = $1 if ($current_dex_params =~ /$temp.*\s+\d+\s+(\d+[smh])\s+/);

        } elsif ($menu_ans =~ /^u/i) {
            ##################################
            # Select the run time in minutes #
            ##################################
            print "Enter run time in minutes [<60>, 1-1440, q]: ";
            $cmd = &get_response();
            next if ($cmd =~ /^q/i);
            if ($cmd eq "") {
                $current_dex_params =~ s/$RUN_TIME/60m/;
                $RUN_TIME = "60m";
                next;
            } elsif ($cmd =~ /^\d+$/) {
                if (($cmd > 0) & ($cmd <= 1440)) {
                    $current_dex_params =~ s/$RUN_TIME/${cmd}m/;
                    $RUN_TIME = "${cmd}m";
                    next;
                }
            }
            print "\nIllegal Entry\n";
        } elsif ($menu_ans =~ /^p/i) {
            &pid_manager;
        } elsif ($menu_ans =~ /^s/i) {
            if ($target_mode eq "file") {
                &select_file();
            } elsif ($target_mode eq "raw") {
                $usr_ch = &make_arr_menu(@TEST_PORTS);
                if ($usr_ch =~ /^a/i) {
                    @CN_TEST = ();
                    foreach $ldprt (@TEST_PORTS) {
                        $SELECTED_DRIVES{ $ldprt } = ();
                        push @CN_TEST, $ldprt;
                    }
                    $target_mode = "raw"
                } elsif ( $usr_ch =~ /^q/i ) {
                } else {
                    &specific_loop;
                    if ($#CN_TEST >= 0) {
                        $target_mode = "raw";
                    }
                }
            }
        } elsif ($menu_ans =~ /^f/i) {
            if ($target_mode eq "raw") {
                $target_mode = "file";
                if ( $TARGET_FILE eq "" ) {
                    &select_file();
                }
                if ( !defined $TARGET_FILE ) {
                    $target_mode = "raw";
                }
            } else {
                $target_mode = "raw";
            }
            &switch_test;
        } elsif ($menu_ans =~ /^h/i) {
            # debugging
            print "Current: $current_dex_params\n";
            print "Default: $default_dex_params\n";
        } else {
            print "$menu_ans is an invalid selection!\n";
        }
    }
}

sub switch_test {
    ###########################################
    # Switch test to default for current mode #
    # MI = file mode default                  #
    # S = loops mode default                  #
    ###########################################

    if ($target_mode eq "raw") {
        my $origtest = "-" . $DEX_TEST_LIST[$DEX_TEST+1];
        $origtest .= "I" if ($current_dex_params =~ /${origtest}I\d+ /);
        $DEX_TEST = 0;
        my $newtest = "-" . $DEX_TEST_LIST[$DEX_TEST+1];
        $current_dex_params =~ s/$origtest/$newtest/;
        $default_dex_params =~ s/$origtest/$newtest/;
        $current_dex_params =~ s/$media_range/8g/;
        $default_dex_params =~ s/$media_range/8g/;
        $media_range = "8g";
        if ($current_dex_params =~ /-x (\d+[mkb])/) {
            my $xfersize = $1;
            $current_dex_params =~ s/$xfersize/128k/;
            $default_dex_params =~ s/$xfersize/128k/;
        }
        ###################################################
        # when switching to raw mode make sure no writing #
        ###################################################
        if ($current_dex_params =~ /(-wr|-rw|-w\/r|-r\/w)/) {
            my $old_dex_mode = $1;
            $new_dex_mode = "-r";
            $current_dex_params =~ s/$old_dex_mode/$new_dex_mode/;
        }
    } elsif (($target_mode eq "file") and ($DEX_TEST !=4)) {
        my $origtest = "-" . $DEX_TEST_LIST[$DEX_TEST+1];
        $origtest .= "I" if ($current_dex_params =~ /${origtest}I\d+ /);
        $DEX_TEST = 4;
        my $newtest = "-" . $DEX_TEST_LIST[$DEX_TEST+1];
        $newtest .= "I";
        $current_dex_params =~ s/$origtest/$newtest/;
        $default_dex_params =~ s/$origtest/$newtest/;
        if ($TARGET_FILE eq "") {
            $current_dex_params =~ s/$media_range/10m/;
            $default_dex_params =~ s/$media_range/10m/;
            $media_range = "10m";
        } elsif ($file_media_range ne "") {
            $current_dex_params =~ s/$media_range/$file_media_range/;
            $default_dex_params =~ s/$media_range/$file_media_range/;
            $media_range = $file_media_range;
        }
    }
}

sub select_file {

    ####################################################################
    # Check to see if there is enough free disk space to grow the file #
    ####################################################################

    my ($units, $diskspace, $rc);
    my $temp = "-" . $DEX_TEST_LIST[$DEX_TEST+1];
    my $temp2 = "-MI";
    $temp .= "I" if ($current_dex_params =~ /${temp}I\d+ /);
    if ($current_dex_params =~ /$temp\d+ (\d+)([gmk]) .*/) {
        $diskspace = $1;
        $units = $2;
        $media_range = "$diskspace$units";
        $diskspace = $diskspace * 1024 if ($units eq "m");
        $diskspace = $diskspace * 1024 * 1024 if ($units eq "g");
    }

    @DF_TEST = @TEST_PORTS;  # assume all controllers to target
    my $df_list = `/bin/df`;
    my @mount_points = split ('\n', $df_list);
    my @valid_mount_points;
    foreach $point ( @mount_points ) {
        foreach $path (@DF_TEST) {     # run dex32 with lbf
            print "CNUM $CNUM{$path}  $point\n" if ( $DEBUG );
            ($cnum_point) = $point =~ /\/dev\/dsk\/(c\d+)t\d+d\d+/;
            print "cnum_point $cnum_point\n" if ( $DEBUG );
            if ( $cnum_point eq $CNUM{$path} ) {
                $num_points++;
                push @valid_mount_points, $point;
                $valid_cnum{ $point } = $cnum_point;
            }
        }
    }
    if ( ! @valid_mount_points ) {
        print "\n";
        print "There are no mounted file systems on the selected storage.\n";
        print "\n";
        return;
    }

    print "Current Test Mode: $test_mode\n";
    print "Current Disk Space Requirement: $media_range\n" if ($RD_CHOICE !~ "w");
    # choose dex to a file
    my $valid_file = "FALSE";
    my $valid_point = "FALSE";
    while ( ( $valid_file eq "FALSE" ) || ( $valid_point eq "FALSE" ) ) {
        print "\nEnter file name with one of the following mount points:\n"
;
        foreach $point ( @valid_mount_points ) {
            print "$valid_cnum{ $point }: $point\n";
        }
        print "\n";
        print "\nEnter the full pathname or <q>: ";
        $target = &get_response("q");
        if ($target eq "q" ) {
            $target = "";
            return;
        }
        if ((-d $target) or ($target !~ /^\//)) {
            print "\nThe entire file path must be specified\n\n";
            $target = "";
            $valid_file = "FALSE";
            next;
        } elsif (($RD_CHOICE !~ "w") and (! -e $target)) {
            print "Read Only test error, $target does not exist\n";
            print "The path must exist for read testing.\n";
            $target = "";
            $valid_file = "FALSE";
            next;
        }
        foreach $point ( @valid_mount_points ) {
            my @temp = split ( ' ', $point );
            $point_path = $temp[0];
            print "point_path $point_path\n" if ( $DEBUG );
            if ( $target =~ /$point_path/ ) {
                $valid_point = "TRUE";
                $FILE_CN = $valid_cnum{ $point };
                print "FILE_CN $FILE_CN\n" if ( $DEBUG );
                last;
            }
        }
        if ( $valid_point ne "TRUE" ) {
            print "\nError: $target is not valid for selected storage mount points!\n";
            print "Enter a new file name.\n";
            $target = "";
            next;
        }
    #    if ( -e $target ) {
    #        # do NOT allow an existing file to be used
    #        # file is always removed after exiting the menu
    #        $valid_file = "FALSE";
    #        $target = "";
    #        print "\nError: $target exists!\n";
    #        print "Enter a new file name.\n";
    #        next;
    #    } else {
         $valid_file = "TRUE";
         next;
    #    }
    }
    {
        my ($ksize, $msize);
        $rc = '';
        if ($RD_CHOICE =~ /w/) {
            my ($units, $xfersize, $range_request);
            #####################################################
            # See if file system can accomodate range request   #
            #####################################################
            print "File size must be a number followed by g, m or k\n";
            print "Enter File Size <$media_range>: ";
            my $range = &get_response("$media_range");
            if ($range !~ /^\d+[gmk]$/) {
                $rc = "Size must be a number followed by g, m or k\n";
            } else {
                if ($current_dex_params =~ /-x (\d+[mkb])/) {
                    $xfersize = $1;
                    if ($xfersize =~ /(\d+)([gmk])/) {
                        $block_size = $1;
                        $units = $2;
                        $block_size = $block_size * 1024 if ($units =~ /^m$/i);
                        $block_size = $block_size * 1024 * 1024 if ($units =~ /^g$/i);
                    }
                    if ($range =~ /(\d+)([gmk])/) {
                        $range_request = $1;
                        $units = $2;
                        $range_request = $range_request * 1024 if ($units =~ /^m$/i);
                        $range_request = $range_request * 1024 * 1024 if ($units =~ /^g$/i);
                    }
                }
                if ($range_request <= $block_size) {
                    $rc = "File size must be larger than block transfer size of $xfersize\n";
                } else {
                    $media_range = $range;
                    $rc = &free_to_grow($target, $media_range);
                    if ($current_dex_params =~ /-\w+\d+\s(\d+[gmk])\s/) {
                        $current_dex_params =~ s/$1/$media_range/;
                    }
                }
            }
        } else {
            ##################################################
            # read only test on a specific file, adjust size #
            ##################################################
            my $filesize = `/usr/bin/ksh -c 'ls -goL $target 2>&1'`;
            chomp $filesize;
            if ($filesize =~ /No such file/) {
                $rc = "Read Only test error, $target does not exist";
            } else {
                my ($perm, $temp, $size) = split /\s+/, $filesize;
                $ksize = $size / 1024; # convert to kilobytes from bytes
                $ksize = int $ksize;
                ################################################
                # see if file is larger than i/o transfer size #
                ################################################
                my ($min_size, $letter);
                if ($current_dex_params =~ /-x (\d+)([gmkb])/) {
                    $min_size = $1;
                    $letter = $2;
                }
                $min_size = $min_size * 1024 if ($letter eq "m");
                $min_size = $min_size * 1024 * 1024 if ($letter eq "g");
                if ($ksize < $min_size) {
                    $rc = "File smaller than i/o transfer size ${min_size}k";
                    $rc .= "\nTry the Random i/o test for its 1k transfer size";
                } else {
                    if ($ksize > 1024) {
                        $msize = int($ksize / 1024);
                        $media_range = "${msize}m";
                    } else {
                        $media_range = "${ksize}k";
                    }
                    if ($current_dex_params =~ /-\w+\d+\s(\d+[gmk])\s/) {
                        $current_dex_params =~ s/$1/$media_range/;
                    }
                }
            }
        }
    }
    if ($rc ne '') {
        print "\n$rc\n\n";
        print "Press <return> to continue ";
        &get_response();
        return;
    }
    if (($DEX_TEST != 4) and ($one_time == 0)) {
        #####################################
        # change test to Memory Mapped Test #
        #####################################
        $one_time = 1; # force test switch only once
        $DEX_TEST = 4;
        $current_dex_params =~ s/$temp/$temp2/;
        $default_dex_params =~ s/$temp/$temp2/;
    }
    # 
    # BugTraq # 4281479
    #
    # Only remove current file if testing is done
    # or user selects a different file to test
    #
    if ( $RD_CHOICE eq "rw" ) {
        print "Delete the file after the test completes? (<y>, n): ";
        $KEEP = "";
        $k = &get_response("y");
        $KEEP = "-k" if ($k =~ /^n/i);
    }
    $TARGET_FILE = $target;
    $target_mode = "file";
    $file_media_range = $media_range;
}

sub pid_manager {
#####################################
# Allow management of dex processes #
#####################################
my $choice;
  while (1) {
    print "\nDex Process Management\n";
    print "----------------------\n\n";
    print "[s] Show all processes\n";
    print "[k] Kill all processes\n";
    print "[c] Kill processes by controller\n";
    print "\n";
    print "[q] Quit\n";
    print "\nEnter Choice: ";
    $choice = &get_response();

    if ($choice =~ /^k/i  || $choice =~ /^c/i ) {

        print "\n";
        $res = system("/usr/bin/ksh -c 'ps -ef  | fgrep dex32 | fgrep -v fgrep > /dev/null'");
        if ( ! $res  ) {  # in this instance false is true.
            system("/usr/bin/logger -p mail.crit -i -t \"Info:\" \"Stopping dex32 from ${PRODUCT} ${PROGNAME} $RD_CHOICE\"");
        }
        kill_pid_files($LOGDIR, $choice);  # in subroutines.pm
        print "\nPress <return> for previous menu ...";
        &get_response();
    } elsif ($choice =~ /^s/i) {
        print "\n";
        show_pid_files($LOGDIR);  # in subroutines.pm
        print "\nPress <return> for previous menu ...";
        &get_response();
    } elsif ($choice =~ /^q/i) {
        return;
    } else {
        print "\n$choice in an invalid choice!\n";
    }
  }
}

sub specific_loop {
    ####################################
    # Given a specific loop in $usr_ch #
    # allow user to pick drives        #
    ####################################
    if ($CNUM{$usr_ch} ne "") {
        @CN_TEST = ($usr_ch);
        # @CN_TEST = $CNUM{$usr_ch};
        # allow choosing of specific drives here
        # need to check for enclosure names. 
        my @encnames = &get_enclosure_names( $usr_ch );
        my @T300names = &get_T300_names( $usr_ch );
        if ($DDCNT{$usr_ch} == 0) {
            print "\nWarning: All drives are offline!\n";
            print "\nPress <return> to continue.";
            &get_response();
            return -1;
        }
        SELECT: {
            $SELECTED_DRIVES{ $usr_ch } = ();
            print "\nSelect disks To Exercise in $CNUM{$usr_ch}\n";
            print "-------------------------------\n";
            my $i = 0;
            if (( @encnames ) or (@T300names) ){
                foreach $encnames (@encnames) {
                    $i ++;
                    print " [$i] Specific drives in enclosure \'$encnames\'\n";
                } 
                foreach $T300names (@T300names) {
                    $i ++;
                    print " [$i] Specific LUNs in T300 \'$T300names\'\n";
                } 
                print "\n [a] All $DDCNT{$usr_ch} drives\n";
                print " [u] Update Online Loop Summary\n";
                print " [q] Quit\n";
                print "\nEnter Choice [<a>, 1 - $i, q]: ";
                $drive_choice = &get_response('a');
            }

            my ($front, $rear);
            for ( $drive_choice ) {
                if (/^q/i) { return -1; }
                if (/^u/i) { 
                    &get_online_summary; 
                    @encnames = &get_enclosure_names( $usr_ch );
                    @T300names = &get_T300_names( $usr_ch );
                    redo SELECT; # pick an enclosure again
                }
                if (/^a/i) { 
                    ###############################################
                    # "all drives on this loop" has been selected #
                    # remove T300 drives not on this dual path    #
                    ###############################################
                    $SELECTED_DRIVES{ $usr_ch } = "";
                    $SELECTED_DRIVES{ $usr_ch } .= "$A5000_DRIVES{$usr_ch} " if ($A5000_DRIVES{$usr_ch} ne "");
                    $SELECTED_DRIVES{ $usr_ch } .= "$T300_DRIVES{$usr_ch} " if ($T300_DRIVES{$usr_ch} ne "");
                    chop $SELECTED_DRIVES{ $usr_ch };
                    last SELECT; 
                }
                if (($_ > $i) or ($_ < 1)) { redo SELECT; }
                ########################################
                # user has chosen a specific enclosure #
                # or T300.                             #
                ########################################
                $i = $_ - 1;
                my @front_drive_list = ();
                my @rear_drive_list = ();
                my @allnames = (@encnames, @T300names);
                if ($#encnames < $i) {
                    ######################################
                    # user chose a T300 box, not A5k box #
                    ######################################
                    @front_drive_list = split / /, $T300_TARGETS{$allnames[$i]};
                } else {
                    ############################################################
                    # build list of front and rear drives for specific A5k box #
                    # by looping thru all disks on loop, taking only the drives#
                    # in this enclosure.                                       #
                    ############################################################
                    my @drive_list = sort (split / /, $A5000_DRIVES{$usr_ch}); # all A5k disks's on this loop
                    foreach $target (@drive_list) {
                        ($name, $pos, $wwn) = split /,/, $A5000_POSITION{$target};
                        next if ($name ne $encnames[$i]);
                        $front_drive_list[$1] = "$target,$wwn" if ($pos =~ /^f(\d+)/);
                        $rear_drive_list[$1] = "$target,$wwn" if ($pos =~ /^r(\d+)/);
                    }
                }
                SELECT2: {
                   my $l = substr "------------------------", 0, length($allnames[$i]);
                   my $spacecount;
                   my $dnum;

                   if ($i <= $#encnames) {
                       ###########
                       # A5k box #
                       ###########
                       print "\n\nSelect Drives To Exercise in $allnames[$i]\n";
                       print      "-----------------------------$l\n\n";
                       print "Front Drives                  Rear Drives\n\n";
                       for ($dnum = 0; $dnum <= $#front_drive_list; $dnum ++ ) {
                           $spacecount = 26 - length($front_drive_list[$dnum]);
                           $spacecount = pack "A$spacecount", " ";
                           print " $dnum\) $front_drive_list[$dnum] $spacecount" . ($dnum + $#front_drive_list +1) . ") $rear_drive_list[$dnum]\n";
                       }
                   } else {
                       ############
                       # T300 box #
                       ############
                       print "\n\nSelect LUNs To Exercise in T300 $allnames[$i]\n";
                       print      "---------------------------------$l\n\n";
                       for ($dnum = 0; $dnum <= $#front_drive_list; $dnum ++ ) {
                           print " $dnum\) $front_drive_list[$dnum] ";
                           print "primary\n" if ($T300{$front_drive_list[$dnum]} eq "p");
                           print "alternate\n" if ($T300{$front_drive_list[$dnum]} eq "a");
                       }
                   }
                   print "\n";

                   print "\n [a] All\n";
                   print " [q] Quit\n";
                   print "\nEnter Choice [<a>, 0 - " . ($dnum + $#rear_drive_list ) . ", q]: ";
                   my $ans = &get_response('a');
                   if ($ans =~ /^q/i) { redo SELECT; }
                   $ans =~ s/,/ /g;
                   $ans =~ s/\s+/ /g;
                   $SELECTED_DRIVES{ $usr_ch } = ();
                   my (@drives) = (@front_drive_list, @rear_drive_list);
                   if ($ans =~ /^a/i) {
                       # user wants all drives in this enclosure
                       my $cnumber; 
                       my $wwn;
                       foreach $ans (@drives) {
                          ($cnumber, $wwn) = split /,/, $ans;
                          if ($cnumber ne '') {
                              $SELECTED_DRIVES{ $usr_ch} .= $cnumber;
                              $SELECTED_DRIVES{ $usr_ch} .= " ";
                          }
                       }
                   } else {
                       my @ans = split / /, $ans;
                       # user entered a list of numbers
                       foreach $ans (@ans) {
                           if ($ans =~ /^\d+$/) {
                              if ($ans > $#drives) {
                                  print "\n$ans is an illegal choice\n";
                                  redo SELECT2;
                              }
                              my ($cnumber) = split /,/, $drives[$ans];
                              if ($cnumber eq '') {
                                  print "\n$ans is an illegal choice\n";
                                  redo SELECT2;
                              } else {
                                  $SELECTED_DRIVES{ $usr_ch} .= $cnumber;
                                  $SELECTED_DRIVES{ $usr_ch} .= " ";
                              }
                           } else {
                              print "\n$ans is an illegal choice\n";
                              redo SELECT2;
                           }
                       }
                   }
                } # end of SELECT2
            }
        } # end of SELECT
    } else {
        print "Controller not present.  Select from list.\n\n";
        print "Press <return> to continue\n";
    }
}



sub get_online_summary {

    print "\nGetting Loop Summary...\n\n";
    &make_port_list;

}

####################################################################
# make a menu out of an array
#   INPUT:  array of luxdiag port -n output
#   OUTPUT: choose 1 element or all of them
####################################################################
sub make_arr_menu {
    (@in_array) = @_;
    my (@encnames, $line, $target_cnum, $target_count);
    #&get_online_summary;

    while (1) {
        $count = 1;
        print "\nChoose a loop to run the test against:\n";
        foreach $e (@in_array) {
	   if ($T300_CNT{$e})
	   {
	     # T300s on this loop 
       	     print " [$count] ($CNUM{$e}) ($SOCNUM{$e}:Port $PORTNUM{$e}) ($SFNUM{$e}) ($e) ($DDCNT{$e} LUN(s))\n";
	   }
	   else
	   {
	     #no T300s on this loop
	     print " [$count] ($CNUM{$e}) ($SOCNUM{$e}:Port $PORTNUM{$e}) ($SFNUM{$e}) ($e) ($DDCNT{$e} disks(s))\n";
	   }

           $count++;
        }
      
        if ($count gt 1) {
            print "\n";
            print " [a] all\n";
            print " [u] Update Online Loop Summary\n";
            print "\n";
            print " [q] Quit\n";
            print "\nEnter Choice: ";
        } else {
            print "\n";
            print "No HBAs with drives attached.\n"; 
            print "\n";
            print " [q] Quit\n";
            print "\nEnter Choice: ";
        }

        $choice = &get_response();
        if ($choice =~ /^[qa]/i) {
            return $choice;
        } elsif ($choice =~ /^u/i) {
            &get_online_summary;
        } elsif ($choice !~ /^\d+/) {
            print "\nUndefined option! \n\n";
        } else {
            $max = $#in_array+1;
            if ( ($choice  > 0)  && ($choice <= $max)) {
                return $in_array[$choice-1];
            } else {
                print "\nUndefined option!\n\n";
            }
        }
    }
}

################################################################
# get the command line flags
################################################################
sub proc_cli {


    $usage[0] = "$PROGNAME \n";

    $DUAL_PORT = $PRIMARY;
    $arg = shift @ARGV;

    while($arg) {
        if ($arg =~ /help/)  {
            die @usage if ($arg =~ /help/);
        }
        # Get the next value.
        # The last command in the loop
        $arg = shift @ARGV;
    }
}

sub get_enclosure_names {
    my $c_idx = $_[0];
    return (split / /, $A5000_LIST{$c_idx});
}

sub get_T300_names {
    my ($loop) = @_;
    @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{$loop}/) {
           my ($cur_target, $cur_disk) =  $drive =~ /c\d+t(\d+)d(\d+)/;

           #if ( (($T300{$drive} eq "p") && ($DUAL_PORT eq $PRIMARY)) or (($T300{$drive} eq "a") && ($DUAL_PORT eq $ALTERNATE)) ) {
               $T300_TARGETS{"$CNUM{$loop}t$cur_target"} .= "$drive ";
           #}
       }
    }
    return (sort keys %T300_TARGETS);
}
