#
# Copyright EMC Corporation, 2005
#
# For:                Toolkit Installer
# Platform:           Windows 2003
# AAM Version:        5.1.2
# Script Version:     1.1
#
# ************************************************************************
# Audit Trail
#
# Version	Date		Description		Author
# -------	----------	-----------		-----------------
# V1.1     	05-04-2006  Q01365351		Wilfred Gaube
#						Q01365360
# V1.0     	09-27-2005  Original		Eduardo Figueredo
#            
# ************************************************************************

## ------------------------------------------------------------------------------
##  GLOBAL CONST
## -------------------------------------------------------------------------------

$TK_TYPE_ARRAY = "ARRAY";
$TK_TYPE_VALIDNODE = "VALIDNODE";
$TK_TYPE_VALIDNODELIST = "VALIDNODELIST";
$TK_TYPE_PATHTESTIPADDRESS = "PATHTESTIPADDRESS";
$TK_TYPE_PATHTESTIPADDRESSLIST = "PATHTESTIPADDRESSLIST";
$TK_TYPE_ISOLATIONIPADDRESSLIST = "ISOLATIONIPADDRESSLIST";
$TK_TYPE_NICGROUPTESTIPADDRESSLIST = "NICGROUPTESTIPADDRESSLIST";

$TK_YES = "Y";

## ------------------------------------------------------------------------------
##  GLOBAL VAR
## -------------------------------------------------------------------------------

@nodes = ();
@isolationIPAddresses = ();
@toolkits = ();

$toolkitName = "";
$templateDefFile = "";
$outputDefFile   = "";

## -------------------------------------------------------------------------------
##  MAIN BEGIN
## -------------------------------------------------------------------------------

&checkUsage();
&intro();

#&dumpVars();

&createModulesDir();
&copyFiles();
&runCommands();

#$yn= &askYesNo("Would you like to run the toolkit configurator?");
#if ($yn) {
	$redo = 1;
	while ($redo)   {
		&initialize();
		&getInput();
		&displayResponses();
		$redo = &askRedo("Would you like to continue with the above responses?");
	} # redo

	&outputToDef();
	
	# May 4, 2006 gaubew Q01365351
	# We do not want the user to import the definition file now so remove the option.
	#&importDef();
	
	&done();
#} # yes

exit 0;

## -------------------------------------------------------------------------------
##  MAIN END
## -------------------------------------------------------------------------------

sub initialize() {
	@nodes = ();
	@isolationIPAddresses = ();

	for ($t = 0; $t <= $#tokens; $t++) {
		*tokenDef = @tokens[$t];
		if ($tokenDef{type} eq $TK_TYPE_VALIDNODE) {
			$limit = $#nodes + 1;
			@nodes[$limit] = $tokenDef{answer};			
		} # VALIDNODE		

		if ($tokenDef{type} eq $TK_TYPE_VALIDNODELIST) {
			*itemList = @tokenDef{answer};
			foreach $item (@itemList) {
				$limit = $#nodes + 1;
				@nodes[$limit] = $item;			
			} # item
		} # VALIDNODELIST

		if ($tokenDef{type} eq $TK_TYPE_NICGROUPTESTIPADDRESSLIST) {
			*itemList = @tokenDef{answer};
			foreach $item (@itemList) {
				$limit = $#isolationIPAddresses + 1;
				@isolationIPAddresses[$limit] = $item;			
			} # item
		} # NICGROUPTESTIPADDRESSLIST
	} # tokens
} # initialize

########################################################################
###                                                                  ###
###                              checkUsage                          ###
###                                                                  ###
###  description:  								   ###
###                                                                  ###
########################################################################

sub checkUsage  {

	#############################################################################
	# check for valid toolkit
	#############################################################################

	&getToolkits();

	if ( !$ARGV[0] ) {
		print "Error: Toolkit name not supplied.\n";
		&printUsage();
	}

        if ( ! (&isToolkit($ARGV[0])) ) {
		print "Error:  <$ARGV[0]> is not a valid toolkit name.\n";
		&printUsage();
	}

	$toolkitName = "$ARGV[0]";
	
	# May 4, 2006 gaubew Q01365360
	# Change the template file extension from .def to .tpl so that the end user is not
	# confused as to which should be imported later
	$templateDefFile = "$toolkitName-Template.tpl";
	$outputDefFile   = "$toolkitName.def";

	# check to see if toolkit pl file exists, kinda redundant
	if ( !(-e "$toolkitName.pl") )    {
   		print "Error:  $toolkitName.pl file does not exist.";
		exit 1;
	}

	# check to see if template file exists
	if ( !(-e "$templateDefFile") )    {
   		print "Error:  $templateDefFile file does not exist.";
		exit 1;
	}

	#############################################################################
	# check for FT_DIR
	#############################################################################
	if ( !$ARGV[1] ) {
		if ( !$ENV{FT_DOMAIN}) {
			print "Error:  Either the domain name must be supplied or\n";
			print "	   the environment variable FT_DOMAIN must be set.\n";
			&printUsage();
		}
	}
	else {
		$ENV{FT_DOMAIN} = $ARGV[1];
	}
	$FT_DOMAIN = $ENV{FT_DOMAIN};


	#############################################################################
	# check for FT_DOMAIN
	#############################################################################
	if ( !$ARGV[2] ) {
		if ( !$ENV{FT_DIR}) {
			print "Error:  Either the install directory must be supplied or\n";
			print "	   the environment variable FT_DIR must be set.\n";
			&printUsage();
		}
	}
	else {
		$ENV{FT_DIR} = $ARGV[2];
	}
	$FT_DIR = $ENV{FT_DIR};

	$nodeName = lc $ENV{COMPUTERNAME}; # windows only
	require "$toolkitName.pl";
} # checkUsage

sub printUsage {
	print "\n";
	print "Usage: install <toolkitName> [<domainName> [<installDir>]]\n";
	print "	If any of the arguements contains spaces they must be\n";
	print "	surrounded by double quotes.  If <domainName> is not\n";
	print "	supplied then FT_DOMAIN will be used.  If <installDir>\n";
	print "	is not supplied then FT_DIR will be used.  If\n";
	print "	<installDir> is supplied then <domainName> must also be\n";
	print "	supplied.\n\n";

	print "	Currently the following toolkits are available on your system:\n";
	foreach $t ( @toolkits ) {
		print "		$t\n";
	} # foreach
	exit 1;
} # printUsage

sub getToolkits() {
	opendir MYDIR, ".";
	@contents = readdir MYDIR;
	closedir MYDIR;

	foreach $listitem ( @contents ) {
		$ext = substr($listitem, -3);
		$fileName = substr($listitem,0,length($listitem)-3);
		if (($ext eq ".pl") && ($fileName ne "install") ) {
			$toolkits[$#toolkits+1] = $fileName;
		}
	} # foreach	
} # getToolkits

sub isToolkit() {
	local ($t) = @_;

	foreach $listitem (@toolkits) {
		if ($t eq $listitem) {
			return 1;
		}
	} # foreach	
	return 0;
} # isToolkit

########################################################################
###                                                                  ###
###                              intro                               ###
###                                                                  ###
###  description:  Gives the general Introduction to the User        ###
###                                                                  ###
########################################################################

sub intro  {
	print "$toolkitName Setup Script\n";
	print "$toolkitVersion\n";
	print "Copyright 2006 EMC Corporation\n";
	print "\n";
} # intro

########################################################################
###                                                                  ###
###                       createModulesDir                           ###
###                                                                  ###
###                                                                  ###
###  description:  Create the modules\$toolkitName directory         ###
###                in $FT_DIR if they don't already exist            ###
###                                                                  ###
###       return:  none                                              ###
###                                                                  ###
########################################################################

sub createModulesDir   {
	if ( !(-e "$FT_DIR\\modules") )    {
   		system("mkdir \"$FT_DIR\\modules\"");
	}
      
	if ( !(-e "$FT_DIR\\modules\\$toolkitName") )    {
   		system("mkdir \"$FT_DIR\\modules\\$toolkitName\"");
	}

	if ( !(-e "$FT_DIR\\log") )    {
   		system("mkdir \"$FT_DIR\\log\"");
	}
      
	if ( !(-e "$FT_DIR\\log\\modules") )    {
   		system("mkdir \"$FT_DIR\\log\\modules\"");
	}

        if ( !(-e "$FT_DIR\\log\\modules\\$toolkitName") )    {
   		system("mkdir \"$FT_DIR\\log\\modules\\$toolkitName\"");
	}

	print "\n";
} # createModulesDir

########################################################################
###                                                                  ###
###                           copyFiles                              ###
###                                                                  ###
###  description:  if toolkit subdirectory detected, the ask user    ###
###			 if they wish to copy toolkit files to the modules ###
###                directory.  afterwards, ask user if they wish     ###
###                to continue with the configuration                ###
###                this allows for easy of installing just toolkit   ###
###                files on subsequent nodes                         ###
###                                                                  ###
########################################################################

sub copyFiles() {
	if (-e ".\\$toolkitName") {
		$yn = &askYesNo("Would you like to copy the $toolkitName toolkit files to $FT_DIR\\modules\\$toolkitName.");
		if ($yn) {
			# copy files
			system("copy \".\\$toolkitName\" \"$FT_DIR\\modules\\$toolkitName\"");
			$yn = &askYesNo("Would you like to continue with the toolkit configuration?");
                        if (!$yn) { exit 0; }
		} # yes 
	} # there are files to copy
} # copyFiles

########################################################################
###                                                                  ###
###                       runCommands				         ###
###                                                                  ###
###  description:  executes commands listed in @commands		   ###
###                                                                  ###
########################################################################

sub runCommands {
	if ( $#commands > -1 ) {
		print "\nRunning Commands...\n";

		foreach $cmd (@commands) {
			$yn = &askYesNo("Would you like to execute:\n\t<$cmd>\n");
			if ($yn) {
				print "Executing <$cmd>...\n";
				system($cmd);
				print "Done.\n\n";
			} # yes
		} # CMD
		print "\n\n";
	} # there are CMDs to execute
} # runCommands

########################################################################
###                                                                  ###
###                           getInput                               ###
###                                                                  ###
###  description:  Get input from the user                           ###
###                                                                  ###
########################################################################

sub printList() {
	local ($t) = @_;

	# print list if not empty, to deal with redo or default lists
     	*answerList = @tokenDef{answer};
	print "$tokenDef{displayName} = ";
	if ($#answerList > -1) {
          	foreach $a (@answerList) {
            	print "$a ";
		}
		print "\n";
	} # list not empty
	else {
		print "<Empty>\n";
	}
} # printList

sub getInput   {
	for ($t = 0; $t <= $#tokens; $t++) {
		*tokenDef = @tokens[$t];
		if ($tokenDef{skip} ne $TK_YES) {
             	if ($tokenDef{repeat} eq $TK_YES) { # Ask Multi-Response Question
			     	*answerList = @tokenDef{answer};

				# print list if not empty, to deal with redo or default lists
				&printList($t);
				
				while (1) {
					print "$tokenDef{question} (<ENTER> when finished, enter 'clear' to reset the list):  ";
					$answer = &getAnswer();
	
					# check if required field left blank
            			if ( !$answer && $#answerList == -1 && $tokenDef{required} ) {
						print "Error:  This field is required.\n\n";
						next;
					}
	
					# blank entry, must be last
					if ( !$answer ) {
						last;
					}

					if ( lc ($answer) eq "clear" ) {
						@answerList = ();
						&printList($t);
						next;	
					} # clear the list

					# check min length
					if ( $tokenDef{minLength} ) {
						if ( $tokenDef{minLength} > length($answer) ) {
							print "Error:  The value must be at least $tokenDef{minLength} characters in length.\n\n";
							next;
						}
					}

					# check max length
					if ( $tokenDef{maxLength} ) {
						if ( $tokenDef{maxLength} < length($answer) ) {
							print "Error:  The value must be no more than $tokenDef{maxLength} characters in length.\n\n";
							next;
						}
					}

      	            	$valid = &isValid($t, $answer);
            	    		if ( $valid ) {
						&assignRepeat($t, $answer, $#answerList+1);
					}

					next;
				} # while keep asking question
			} # multi
			else { # Ask Single Response Question
				while (1) {
					print "$tokenDef{question}";
					if ( $tokenDef{answer} ) {
						print " (Default: $tokenDef{answer})";
					}
					print ":  ";

					$answer = &getAnswer();

					# check if required field left blank
                    		if ( !$tokenDef{answer} && !$answer && $tokenDef{required} ) {
						print "Error:  This field is required.\n\n";
						next;
					}
	
					# use default
                    		if ( $tokenDef{answer} && !$answer ) {
						last;
					}

					# check min length
					if ( $tokenDef{minLength} ) {
						if ( $tokenDef{minLength} > length($answer) ) {
							print "Error:  The value must be at least $tokenDef{minLength} characters in length.\n\n";
							next;
						}
					}

					# check max length
					if ( $tokenDef{maxLength} ) {
						if ( $tokenDef{maxLength} < length($answer) ) {
							print "Error:  The value must be no more than $tokenDef{maxLength} characters in length.\n\n";
							next;
						}
					}

                    		if ( &isValid($t, $answer) ) {
						&assignSingle($t, $answer);
						last;
					}

					next;
				} # while keep asking question
			} # single
		} # skip
	} # foreach questions

} # getInput

########################################################################
###                                                                  ###
###                           isValid                                ###
###                                                                  ###
###  description:  validate the value provided                       ###
###                                                                  ###
###        input:  $t - token index                                  ###
###                $a - answer entered                               ###
###                                                                  ###
###       return:  0 for invalid, 1 for valid                        ###
########################################################################

sub isValid {
	local($t, $a) = @_;

    	*tokenDef = @tokens[$t];

	# first check for uniqueness in own list if a repeat type
	if ( $tokenDef{repeat} ) {
		*itemList = @tokenDef{answer};
		foreach $item (@itemList) {
			if ($item eq $a) {
				print "Error:  <$a> has already been entered in this list.  Enter a different value.\n";
				return 0;
			} # if
		} # item
	} # repeat

    	if ( $tokenDef{type} eq $TK_TYPE_VALIDNODELIST || $tokenDef{type} eq $TK_TYPE_VALIDNODE ) {
	# make sure node is not repeated
		foreach $node (@nodes) {
			if ($node eq $a) {
				print "Error:  Node <$a> has already been entered.  Enter a different node.\n";
				return 0;
			} # if
		} # for
		return 1;
	} # VALIDNODELIST or VALIDNODE
	
	if ($tokenDef{type} eq $TK_TYPE_NICGROUPTESTIPADDRESSLIST ) {
		foreach $isolationAddress (@isolationIPAddresses) {
			if ($isolationAddress eq $a) {
				print "Error:  NIC Testing Address <$a> has already been entered.  Enter a different address.\n";
				return 0;
			} # if
		} # for
		return 1;
	} # NICGROUPTESTIPADDRESSLIST 

	return 1;
} # isValid

########################################################################
###                                                                  ###
###                           assignSingle                           ###
###                                                                  ###
###  description:  assign single entry value to corresponding        ###
###                hash in %answers                                  ###
###                                                                  ###
###        input:  $t - token index                                  ###
###                $a - answer entered                               ###
###                                                                  ###
########################################################################

sub assignSingle {
	local($t, $a) = @_;

	*tokenDef = @tokens[$t];
    	$tokenDef{answer} = $a;

	if ($tokenDef{type} eq $TK_TYPE_VALIDNODE ) {
		$limit = $#nodes + 1;
		@nodes[$limit] = $a;
	} # VALIDNODE
} # assignSingle

########################################################################
###                                                                  ###
###                           assignRepeat                           ###
###                                                                  ###
###  description:  assign single entry value to corresponding        ###
###                item in array for corresponding hash in %answers  ###
###                                                                  ###
###        input:  $t - token name                                   ###
###                $a - answer entered                               ###
###                $i - index                                        ###
###                                                                  ###
########################################################################

sub assignRepeat {
	local($t, $a, $i) = @_;

	*tokenDef = @tokens[$t];
      *answerList = @tokenDef{answer};
	$answerList[$i] = $a;

	if ($tokenDef{type} eq $TK_TYPE_VALIDNODELIST ) {
		$limit = $#nodes + 1;
		@nodes[$limit] = $a;
	} # VALIDNODELIST

	# collect all NIC Testing IPs and use them for isolation testing
	if ($tokenDef{type} eq $TK_TYPE_NICGROUPTESTIPADDRESSLIST ) {
		$limit = $#isolationIPAddresses + 1;
		@isolationIPAddresses[$limit] = $a;
	} # NICGROUPTESTIPADDRESSLIST

} # assignRepeat

########################################################################
###                                                                  ###
###                              displayResponses                    ###
###                                                                  ###
###  description:  Echo users answers to questions before proceeding ###
###                                                                  ###
########################################################################

sub displayResponses {
   	print "\nAbout to create and import the AutoStart definition file for the \n";
	print "$toolkitName Configuration into the domain '$FT_DOMAIN'.\n\n";
	print "Using the following parameters:\n";

	for ($t = 0; $t <= $#tokens; $t++) {
		*tokenDef = @tokens[$t];
		if ($tokenDef{skip} ne $TK_YES) {
			if ($tokenDef{repeat} eq $TK_YES) {
				print "$tokenDef{displayName} = ";
                *answerList = @tokenDef{answer};
                foreach $a (@answerList) {
	                print "$a ";
				}
                print "\n";
			} # repeat
			else {
				print "$tokenDef{displayName} = $tokenDef{answer}\n";
			} # single
		} # skip
	} # foreach

} # displayResponses

########################################################################
###                                                                  ###
###                       outputToDef                                ###
###                                                                  ###
###  description:  reads module template def file, replaces tokens,  ###
###                and saves the new def file                        ###
###                                                                  ###
########################################################################

sub outputToDef {
	&readMasterTemplate();
	&substituteConfigInfo();
	&saveToDefFile();
} # outputToDef

########################################################################
###                                                                  ###
###                       readMasterTemplate				   ###
###                                                                  ###
###  description:  reads the module template def file into           ###
###                $DefTemplate variable, will exit if template      ###
###                is not found                                      ###
###                                                                  ###
########################################################################

sub readMasterTemplate
{
	if ( !open(FP, "<$templateDefFile")) {
    	print "Error:  Unable to open master definition file. $!";
		exit 1;
    }
	while (<FP>) {
		$DefTemplate .= $_;
    }
	close(FP);
}  # readMasterTemplate

########################################################################
###                                                                  ###
###                       substituteConfigInfo				   ###
###                                                                  ###
###  description:  find and replace tokens with answers              ###
###                                                                  ###
########################################################################

sub substituteConfigInfo() {
	# loop through list of tokens
	for ($t = 0; $t <= $#tokens; $t++) {
		# construct proper value format, especially used for lists
		*tokenDef = @tokens[$t];
		$val = getVal($t);
	   	$DefTemplate =~ s/$tokenDef{token}/${val}/g;   # Replace one string for another
   	}
} # substituteConfigInfo

sub getVal() {
	local ($t) = @_;

	*tokenDef = @tokens[$t];
	if ( $tokenDef{repeat} eq $TK_YES ) {
		if ($tokenDef{type} eq $TK_TYPE_VALIDNODELIST) {
			$v = "";
			*nodeList = @tokenDef{answer};
			foreach $node (@nodeList) {
				if ($v eq "") {
					$v = "\n{\n\t nodeName = $node\n}\n";
				}
				else {
					$v = $v . "{\n\t nodeName = $node\n}\n";
				}
			} # node
			return $v;
		} # VALIDNODELIST

		if ($tokenDef{type} eq $TK_TYPE_ARRAY) {
			$v = "";
			*itemList = @tokenDef{answer};
			foreach $item (@itemList) {
				if ($v eq "") {
					$v = "\"$item\"";
				}
				else {
					$v = $v . ", \"$item\"";
				}
			} # item
			$v = "( " . $v . " )";
			return $v;
		} # ARRAY

		if ($tokenDef{type} eq $TK_TYPE_ISOLATIONIPADDRESSLIST) {
			$v = "";
			*itemList = @tokenDef{answer};
			foreach $item (@itemList) {
				if ($v eq "") {
					$v = "\n{\n\t sourceType = isolation\n\t destination.addr = $item\n}";
				}
				else {
					$v = $v . "\n{\n\t sourceType = isolation\n\t destination.addr = $item\n}";
				}
			} # item
			$v = "isolationAddrs = {" . $v . "\n}\n\n";
			return $v;
		} # ISOLATIONIPADDRESSLIST 

		if ($tokenDef{type} eq $TK_TYPE_NICGROUPTESTIPADDRESSLIST) {
			$v = "";
			*itemList = @tokenDef{answer};
			foreach $item (@itemList) {
				if ($v eq "") {
					$v = "\n{\n\t addr = $item\n}\n";
				}
				else {
					$v = $v . "\n{\n\t addr = $item\n}\n";
				}
			} # item
			$v = "destinationList = {" . $v . "}\n\n";
			return $v;
		} # NICGROUPTESTIPADDRESSLIST

		if ($tokenDef{type} eq $TK_TYPE_PATHTESTIPADDRESSLIST ) {
			$v = "";
			*itemList = @tokenDef{answer};
			foreach $item (@itemList) {
				if ($v eq "") {
					$v = "\n{\n\t addr = $item\n}\n";
				}
				else {
					$v = $v . "\n{\n\t addr = $item\n}\n";
				}
			} # item
			$v = "testAddrs = {" . $v . "}\n\n";
			return $v;
		} # PATHTESTIPADDRESSLIST 
	} 
	else {
		return $tokenDef{answer};
	}
} # getVal

########################################################################
###                                                                  ###
###                       saveToDefFile					   ###
###                                                                  ###
###  description:  saves $DefTamplte to $outputDefFile def file      ###
###                                                                  ###
########################################################################

sub saveToDefFile() {
	unlink  $outputDefFile;

	# Open a temp file in local directory
	if ( !open(FP, ">$outputDefFile")) 
    	{
		print "Error:  Unable to create $outputDefFile definition file. $!\nEXITING\n\n";
		exit 1;
	}

	print FP $DefTemplate;
	close (FP);
} # saveToDefFile

########################################################################
###                                                                  ###
###                       importDef					         ###
###                                                                  ###
###  description:  imports $outputDefFile def file into domain       ###
###                                                                  ###
########################################################################

sub importDef {
	$yn = &askYesNo("Would you like to import the <$outputDefFile>?");
	if ($yn) {
		print "\nImporting the configuration into AutoStart domain $FT_DOMAIN...\n";
		# Start the ftcli and have it import the def file
		$cmd = "\"$FT_DIR\\bin\\ftcli\" -cmd \"import $outputDefFile\"";
		print "About to run '$cmd'\n";
		$output = `"$cmd"`;

		@lines = split( "\n", $output );
		foreach $line (@lines) {
			if ( $line =~ /Error/ ) {
				print "Failure on creation of AutoStart objects: $output \n";
				exit(105);
			}
		} # foreach line
		print "Module info imported successfully!\n\n";
	} # yes
} # importDef

########################################################################
###                                                                  ###
###                       done					         ###
###                                                                  ###
###  description:  reports to the user the script is done 		   ###
###                                                                  ###
########################################################################

sub done {
	print "\n";
	print "Operation complete, A .DEF file $outputDefFile has been created.\n";
	print "\n";
} # done

## ------------------------------------------------------------------------------
##  DEBUGGING ROUTINES BELOW
## -------------------------------------------------------------------------------

########################################################################
###                                                                  ###
###                              dumpNodes                           ###
###                                                                  ###
########################################################################

sub dumpNodes() {
	print "Valid Nodes = ";
	if ($#nodes > -1) {
          	foreach $a (@nodes) {
            	print "$a ";
		}
		print "\n";
	} # list not empty
	else {
		print "<Empty>\n";
	}
} # dumpNodes

########################################################################
###                                                                  ###
###                              dumpIsolationAddresses              ###
###                                                                  ###
########################################################################

sub dumpIsolationAddresses() {
	print "Isolation Testing Addresses = ";
	if ($#isolationIPAddresses > -1) {
          	foreach $a (@isolationIPAddresses) {
            	print "$a ";
		}
		print "\n";
	} # list not empty
	else {
		print "<Empty>\n";
	}
} # dumpIsolationAddresses

########################################################################
###                                                                  ###
###                              dumpVars                            ###
###                                                                  ###
########################################################################

sub dumpVars {
        foreach ($t = 0; $t <= $#tokens; $t++) {
		*tokenDef = @tokens[$t];
		print "	Token    = $tokenDef{token}\n";
		print "	Question = $tokenDef{question}\n";
		print "	Required = $tokenDef{required}\n";
		print "	Type     = $tokenDef{type}\n";
		print "	Repeat   = $tokenDef{repeat}\n";
		print "----------------------------------------------------\n";
	}
} # dumpVars

########################################################################
###                                                                  ###
###                              dumpAnswers                         ###
###                                                                  ###
########################################################################

sub dumpAnswers {
        for ($t = 0; $t <= $#tokens; $t++) {
		*tokenDef = @tokens[$t];
		print "Token tokenDef{token}\n";
		if ($tokenDef{repeat} eq $TK_YES) {
			print "	Answer List\n";
			print "	-----------\n";
			*answerList = @tokenDef{answer};
			foreach $a (@answerList) {
				print "	$a\n";
			}
		}
		else {
			print "	Answer   = $tokenDef{answer}\n";
		}
		print "----------------------------------------------------\n";
	}
} # dumpAnswers

## ------------------------------------------------------------------------------
##  GENERIC ROUTINES BELOW
## -------------------------------------------------------------------------------

########################################################################
###                                                                  ###
###                           getAnswer                              ###
###                                                                  ###
###  description:  requests user input from keybaord			   ###
###                                                                  ###
########################################################################

sub getAnswer	{
	$answer = <STDIN>;
	chomp $answer;
	return $answer;
} # getAnswer

########################################################################
###                                                                  ###
###                              askYesNo                            ###
###                                                                  ###
###  description:  ask question requiring yes no answer		   ###
###  			 Enter 'Y', return 1                               ###
###  			 Enter 'N', return 0		                     ###
###                                                                  ###
########################################################################

sub askYesNo {
	local($msg) = @_;

	while (1) {
   
		print "\n$msg  Enter (Y)es, (N)o:  ";
   
		$yn = &getAnswer();

		if ( $yn eq "Y" || $yn eq "y" ) {
			return 1;
		}     
		
		if ( $yn eq "N" || $yn eq "n" ) {
			return 0;
		}    

		print "\n\nPlease reply with Y, or N.\n\n";
		next;
	} # while
		
} # askYesNo

########################################################################
###                                                                  ###
###                              askRedo                             ###
###                                                                  ###
###  description:  ask the user if they wish to continue		   ###
###  			 Enter 'E' to Exit                                 ###
###  			 Enter 'R' to Redo, returns 1                      ###
###  			 Enter 'C' to Contiue, returns 0                   ###
###                                                                  ###
########################################################################

sub askRedo {
	local($msg) = @_;

	while (1) {
   
		print "\n$msg  Enter (R)edo, (C)ontiue, (E)xit:  ";
   
		$yn = &getAnswer();

		if ( $yn eq "E" || $yn eq "e" ) {
			exit;
		}     
		
		if ( $yn eq "C" || $yn eq "c" ) {
			$redo = 0;
			last;
		}    
 
		if ( $yn eq "R" || $yn eq "r") {
			$redo = 1;
			last;
		}

		print "\n\nPlease reply with C, R, or E.\n\n";
		next;
	} # while
		
	if ($redo eq 1)   {
		# reinitialize the local and remote Nodes arrays
		@nodes = ();
	}
		
	return $redo;
} # askRedo

