#! /bin/ksh
#
# ident "@(#)scinstall_interactive.ksh	1.38	04/06/18 SMI"
#
# Copyright 1999-2004 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#

####################################################
#
# interactive_help_install_centralized()
#
#	Print the help message associated with
#	main menu install option.
#
#	This function always returns zero.
#
####################################################
interactive_help_install_centralized()
{
	typeset sctxt_p1="$(gettext '
		This option is used to install and configure a new
		cluster with a set of two or more member nodes.
	')"
	typeset sctxt_p2="$(gettext '
		If either remote shell (see rsh(1)) or secure shell
		(see ssh(1)) root access is enabled to all of the
		new member nodes from this node, the Sun Cluster
		framework software will be installed on each node.
		Otherwise, the Sun Cluster software must already
		be pre-installed on each node with the "remote
		configuration" option enabled.
	')"
	typeset sctxt_p3="$(gettext '
		The Sun Cluster installation wizard (see installer(1M))
		can be used to install the Sun Cluster framework
		software with the "remote configuration" option
		enabled.  Since the installation wizard does not yet
		include support for cluster configuration, you must
		still use scinstall to complete the configuration
		process.
	')"

	echo
	sc_print_para "${sctxt_p1}"
	sc_print_para "${sctxt_p2}"
	sc_print_para "${sctxt_p3}"

	return 0
}

####################################################
#
# interactive_help_install_installnode()
#
#	Print the help message associated with
#	main menu install node option.
#
#	This function always returns zero.
#
####################################################
interactive_help_install_installnode()
{
	typeset sctxt_p1="$(gettext '
		This option is used to establish a new cluster using
		this machine as the first node in that cluster.
	')"
	typeset sctxt_p2="$(gettext '
		Once the cluster framework software is installed, you
		will be asked for the name of the cluster.  Then, you
		will have the opportunity to run sccheck(1M) to test
		this machine for basic Sun Cluster pre-configuration
		requirements.
	')"
	typeset sctxt_p3="$(gettext '
		After sccheck(1M) passes, you will be asked for the
		names of the other nodes which will initially be
		joining that cluster.  In addition, you will be asked
		to provide certain cluster transport configuration
		information.
	')"

	echo
	sc_print_para "${sctxt_p1}"
	sc_print_para "${sctxt_p2}"
	sc_print_para "${sctxt_p3}"

	return 0
}

####################################################
#
# interactive_help_install_addnode()
#
#	Print the help message associated with
#	main menu odd node option.
#
#	This function always returns zero.
#
####################################################
interactive_help_install_addnode()
{
	typeset sctxt_p1="$(gettext '
		This option is used to add this machine as a node in an
		already established cluster.   If this is an initial
		cluster install, there may only be a single node which
		has established itself in the new cluster.
	')"
	typeset sctxt_p2="$(gettext '
		Once the cluster framework software is installed, you
		will be asked to provide both the name of the cluster
		and the name of one of the nodes already in the
		cluster.  Then, sccheck(1M) is run to test this machine
		for basic Sun Cluster pre-configuration requirements.
	')"
	typeset sctxt_p3="$(gettext '
		After sccheck(1M) passes, you may be asked to provide
		certain cluster transport configuration information.
	')"

	echo
	sc_print_para "${sctxt_p1}"
	sc_print_para "${sctxt_p2}"
	sc_print_para "${sctxt_p3}"

	return 0
}

####################################################
#
# interactive_help_main_install()
#
#	Print the help message associated with
#	main menu install option.
#
#	This function always returns zero.
#
####################################################
interactive_help_main_install()
{
	typeset sctxt_p1="$(gettext '
		This option is used to select the cluster installation
		menu.
	')"
	typeset sctxt_p2="$(gettext '
		The menu options on the installation menu allow
		you to install an entire cluster, to install just
		the first node of a cluster, or to add nodes to
		an existing cluster.
	')"

	echo
	sc_print_para "${sctxt_p1}"
	sc_print_para "${sctxt_p2}"

	return 0
}

####################################################
#
# interactive_help_main_jumpstart()
#
#	Print the help message associated with
#	main menu custom JumpStart option.
#
#	This function always returns zero.
#
####################################################
interactive_help_main_jumpstart()
{
	typeset sctxt_p1="$(gettext '
		This option is used to configure each node in a
		cluster to be JumpStarted from this Solaris install
		server.  Before this option can be used, this server
		must already be set up as a Solaris install server and
		configured to JumpStart each node as a Solaris install
		client.   Refer to the Solaris documentation for more
		information on how to set up a Solaris install server,
		Solaris install clients, and a custom JumpStart
		directory.
	')"
	typeset sctxt_p2="$(gettext '
		You will be asked to provide all of the information
		usually needed to directly add each node to a cluster.
		This information will be stored for later use under
		whatever custom JumpStart directory you specify.  The
		rules file will be updated to point to both default
		Solaris install profile and a special custom JumpStart
		finish script.
	')"

	echo
	sc_print_para "${sctxt_p1}"
	sc_print_para "${sctxt_p2}"

	return 0
}

####################################################
#
# interactive_help_main_adddataservice()
#
#	Print the help message associated with
#	main menu add data service option.
#
#	This function always returns zero.
#
####################################################
interactive_help_main_adddataservice()
{
	typeset sctxt_p1="$(gettext '
		This option is used to install data services software.
	')"

	echo
	sc_print_para "${sctxt_p1}"

	return 0
}

####################################################
#
# interactive_help_main_printrelease()
#
#	Print the help message associated with
#	main menu print release option.
#
#	This function always returns zero.
#
####################################################
interactive_help_main_printrelease()
{
	typeset sctxt_p1="$(gettext '
		This option is only available after the machine has been
		fully installed as a Sun Cluster node.  Release and package
		information is printed.
	')"

	echo
	sc_print_para "${sctxt_p1}"

	return 0
}

####################################################
#
# interactive_printlogmsg logfile [nodename]
#
#	logfile		- the name of the logfile
#	nodename	- node on which the logfile is found
#
#	Print a message instructing users to refer to the log file
#	for more information.
#
#	This function always returns zero.
#
####################################################
interactive_printlogmsg()
{
	typeset logfile=${1}
	typeset nodename=${2}

	echo | logmsg
	if [[ -n "${nodename}" ]]; then
		printf "$(gettext 'Refer to the log file on \"%s\" for details.')\n" "${nodename}"
	else
		printf "$(gettext 'Refer to the log file for details.')\n"
	fi
	printf "$(gettext 'The name of the log file is %s.')\n\n\a" "${logfile}"

	return 0
}

####################################################
#
# interactive_cleanup_logfiles logfile removeflag nodenames...
#
#	logfile		- the name of the logfile
#	removeflag	- if set to non-NULL, remove the unused log file
#	nodenames	- list of nodes
#
#	Clean up individual log files of the name "<logfile>.<nodename>"
#	by appending their contents to the "logfile".   If the
#	"removeflag" is set, the "<logfile>.<nodename>" file is
#	removed.
#
#	This function always returns zero.
#
####################################################
interactive_cleanup_logfiles()
{
	typeset logfile=${1}
	typeset removeflag=${2}
	shift 2
	typeset nodenames="${*}"

	typeset node

	# Clean up log files
	for node in ${nodenames}
        do
		# Append log file data to main log file
		if [[ -s "${logfile}.${node}" ]]; then
			echo ${SC_LINE} >>${logfile}
			echo ${node} >>${logfile}
			echo ${SC_LINE} >>${logfile}
			cat ${logfile}.${node} >>${logfile} 2>/dev/null
                	echo >>${logfile}
		fi

		# Remove the appended temp file
		if [[ -n "${removeflag}" ]]; then
                	rm -f ${logfile}.${node} 2>/dev/null
		fi
	done
	echo ${SC_LINE} >>${logfile}
	echo >>${logfile}

	# Done
	return 0
}

####################################################
#
# interactive_install_typical_or_custom() iflag
#
#	Prompt for typical or custom mode.   On success,
#	print "typical" or "custom".
#
#	iflag 4		- centralized install
#
#	Return values:
#		1	- Typical
#		2	- Custom
#		3	- return to main menu
#
####################################################
interactive_install_typical_or_custom()
{
	integer iflag=${1}

	typeset sctxt_title="$(gettext '
		>>> Type of Installation <<<
	')"
	typeset sctxt_title_help="$(gettext '>>> Help Screen - Type of Installation <<<')"
	typeset sctxt_p1="$(gettext '
		There are two options for proceeding with cluster
		installation.  For most clusters, a Typical
		installation is recommended.   However, you might need to
		select the Custom option if not all of the Typical
		defaults can be applied to your cluster.
	')"
	typeset sctxt_p2="$(gettext '
		For more information about the differences between
		the Typical and Custom installation methods, select
		the Help option from the menu.
	')"

	typeset sctxt_help_p1="${sctxt_p1}"
	typeset sctxt_help_p2="$(gettext '
		A Custom install must be selected if your cluster does
		not use Ethernet for the cluster transport.
	')"
	typeset sctxt_help_p3="$(gettext '
		If a Typical install is selected, you will not be able
		to override the defaults described below for the
		private cluster transport, the names of the global
		devices file systems, install-time security options,
		or patch installation options.
	')"
	typeset sctxt_help_p4="$(gettext '
		The default network address for the private cluster
		transport is 172.16.0.0.
	')"
	typeset sctxt_help_p5="$(gettext '
		The default names assigned to the Ethernet switches
		used in the private cluster transport are \"switch1\" and
		\"switch2\".   These names have no meaning outside of
		a Sun Cluster configuration.
	')"
	typeset sctxt_help_p6="$(gettext '
		The default name for each of the global devices file
		systems is "/globaldevices".   This file system must
		be present on each of the new nodes before running 
		scinstall.
	')"
	typeset sctxt_help_p7="$(gettext '
		By default, nodes attempting to join the cluster at
		install time are not authenticated using DES.
	')"
	typeset sctxt_help_p8="$(gettext '
		By default, a patch download directory of either
		"/var/cluster/patches" or "/var/patches" is used.  If the
		"/var/cluster/patches" directory exists, "/var/patches"
		is ignored.
	')"
	typeset sctxt_help_p9="$(gettext '
		A list of patches for installation may be included
		in the patch download directory.   By default,
		this list of patches may be included in the patch
		download directory as a file called "patchlist".
		The "patchlist" file uses the same format as the
		"patch_list" file used by patchadd(1m).
	')"

	typeset sctxt_title_2="$(gettext 'Please select from one of the following options:')"
	typeset sctxt_option_001="$(gettext 'Typical')"
	typeset sctxt_option_002="$(gettext 'Custom')"
	typeset sctxt_option_help="$(gettext 'Help')"
	typeset sctxt_option_return_install="$(gettext 'Return to the Main Menu')"

	typeset option

	#
	# Print help and Check iflag
	#
	case ${iflag} in
	'4')
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"
		;;

	*)    # invalid argument
		return 2
		;;
	esac

	# Process the menu options
	while true
	do
		# Get the option
		option=$(sc_get_menuoption \
			"T2+++${sctxt_title_2}" \
			"D+0+1+${sctxt_option_001}" \
			"S+0+2+${sctxt_option_002}" \
			"R+++" \
			"S+0+\?+${sctxt_option_help}" \
			"S+0+q+${sctxt_option_return_install}" \
		)

		# Switch
		case ${option} in
		'1')	return 1 ;;
		'2')	return 2 ;;
		'q')	return 3 ;;

		'?'|*)	# Help

			clear
			(
				sc_print_title "${sctxt_title_help}"
				sc_print_para "${sctxt_help_p1}"
				sc_print_para "${sctxt_help_p2}"
				sc_print_para "${sctxt_help_p3}"
				sc_print_para "${sctxt_help_p4}"
				sc_print_para "${sctxt_help_p5}"
				sc_print_para "${sctxt_help_p6}"
				sc_print_para "${sctxt_help_p7}"
				sc_print_para "${sctxt_help_p8}"
				sc_print_para "${sctxt_help_p9}"
			) | more
			sc_prompt_pause || return 3
			;;
		esac
	done

	return 3
}

####################################################
#
# interactive_install_jumpstartdir() iflag
#
#	Set SC_ARGVAR_JUMPSTARTDIR,
#	then add them to the response log.
#
#	iflag 3		- custom JumpStart client set up
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_jumpstartdir()
{
	integer iflag=${1}

	typeset sctxt_title="$(gettext '
		>>> Custom JumpStart Directory <<<
	')"
	typeset sctxt_p1="$(gettext '
		In order to set up an install server to install and
		configure Sun Cluster nodes using custom JumpStart,
		each node must already be set up in the usual way for
		Solaris JumpStart installation.  In particular, you
		must have already run add_install_client(1M) with a -c
		option specifying a JumpStart directory on this install
		server.  In addition, this JumpStart directory must
		already exist and must contain the "check" utility.
		However, it is not necessary to create a "rules" file;
		scinstall will create or update this file with the
		necessary install rules for each cluster node.
	')"
	typeset sctxt_p2="$(gettext '
		For more information regarding JumpStart and setting
		up a Solaris install client, please refer to the
		install_scripts(1M) man page and the Solaris installation
		documentation.
	')"

	typeset answer

	#
	# Print help and Check iflag
	#
	case ${iflag} in
	'3')
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"
		;;

	*)    # invalid argument
		return 1
		;;
	esac


	# Get the name of the JumpStart directory
	while true
	do
		# Get the JumpStart dir
		answer=$(sc_prompt "$(gettext 'What is your JumpStart directory name?')" "${SC_ARGVAR_JUMPSTARTDIR}") || return 1

		# Directory name must begin with /
		if [[ "${answer}" != /* ]]; then
			printf "$(gettext 'The directory name must begin with slash (/).')\n\n\a"
			continue
		fi

		# Make sure it is a directory
		if [[ ! -d "${answer}" ]]; then
			printf "$(gettext 'Cannot find directory \"%s\".')\n\n\a" "${answer}"
			continue
		fi

		# Make sure there is a check program
		if [[ ! -x "${answer}/${SC_CHECK}" ]]; then
			printf "$(gettext 'This is not a JumpStart directory.')\n"
			printf "$(gettext 'There is no executable \"%s\" utility.')\n\n\a" "${SC_CHECK}"
			continue
		fi

		# Okay
		break
	done
	SC_ARGVAR_JUMPSTARTDIR=${answer}

	# append SC_ARGVAR_JUMPSTARTDIR to response log
	argvar_append_tofile_jumpstartdir ${SC_ILOG}

	return 0
}

####################################################
#
# interactive_install_sponsornode() iflag [nohelp]
#
#	Set SC_ARGVAR_SPONSORNODE for this node,
#	then add them to the response log.
#
#	iflag 2		- add this machine to an established cluster
#	nohelp		- don't print help
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_sponsornode()
{
	integer iflag=${1}
	typeset nohelp=${2}

	typeset sctxt_title="$(gettext '
		>>> Sponsoring Node <<<
	')"
	typeset sctxt_p1="$(gettext '
		For any machine to join a cluster, it must identify a
		node in that cluster willing to \"sponsor\" its
		membership in the cluster.  When configuring a new
		cluster, this \"sponsor\" node is typically the first
		node used to build the new cluster.  However, if the
		cluster is already established, the \"sponsoring\" node
		can be any node in that cluster.
	')"
	typeset sctxt_p2="$(gettext '
		Already established clusters can keep a list of
		hosts which are able to configure themselves as new
		cluster members.  This machine should be in the
		join list of any cluster which it tries to join.  If the
		list does not include this machine, you may need
		to add it using scconf(1M) or other tools.
	')"
	typeset sctxt_p3="$(gettext '
		And, if the target cluster uses DES to authenticate
		new machines attempting to configure themselves as
		new cluster members, the necessary encryption keys
		must be configured before any attempt to join.
	')"

	typeset answer

	#
	# Print help and Check iflag
	#
	case ${iflag} in
	'2')
		if [[ -z "${nohelp}" ]]; then
			clear
			sc_print_title "${sctxt_title}"
			sc_print_para "${sctxt_p1}"
			sc_print_para "${sctxt_p2}"
			sc_print_para "${sctxt_p3}"
		fi
		;;

	*)    # invalid argument
		return 1
		;;
	esac


	# Get the name of the sponsor node;  it may not be this node
	while true
	do
		# Get the sponsoring node
		answer=$(sc_prompt "$(gettext 'What is the name of the sponsoring node?')" "${SC_ARGVAR_SPONSORNODE[SC_IDX]}") || return 1

		# Make sure it is not this node
		if [[ "${answer}" = "${SC_ARGVAR_NODENAME[SC_IDX]}" ]]; then
			printf "$(gettext 'A node cannot \"sponsor\" itself.')\n\n\a"
			continue
		fi

		# Verify that it is a known hostname
		if [[ -x /usr/bin/perl ]]; then
        		/usr/bin/perl -s -e '
				use Socket;
				gethostbyname($ARGV[0]) || exit(1);
				exit(0);
			' ${answer}
			if [[ $? -eq 1 ]]; then
				printf "$(gettext 'Unknown host.')\n\n\a"
				continue
			fi
		fi

		# Okay
		break
	done
	SC_ARGVAR_SPONSORNODE[SC_IDX]=${answer}

	# append SC_ARGVAR_SPONSORNODE to response log
	argvar_append_tofile_sponsornode "${SC_IDX}" ${SC_ILOG}

	return 0
}

####################################################
#
# interactive_install_makecontact() sponsornode [clustername]
#
#	Attempt to establish contact with the cluster.  If "clustername"
#	is given, also verify the cluster name.
#
#	If contact is made, the following variable is set to non-NULL:
#
#		SC_DISCOVER_MADECONTACT
#
#	Return values:
#		0	- proceed - contact made
#		1	- return to main menu
#		2	- proceed - no contact made
#		3	- proceed - contact made, but bad cluster name
#
####################################################
interactive_install_makecontact()
{
	typeset sponsornode=${1}
	typeset clustername=${2}

	typeset answer

	integer result

	# Reset global
	SC_DISCOVER_MADECONTACT=

	#
	# Loop until we make contact or give up
	#
	while true
	do
		# Try to contact sponsor
		printf "    $(gettext 'Attempting to contact \"%s\" ... ')" "${sponsornode}"
		scrconf_static -x 10 -N ${sponsornode} >${tmperrs} 2>&1
		let result=$?
		if [[ ${result} -eq ${SC_SCCONF_ETIMEDOUT} ]]; then
			printf "$(gettext 'timed out')\n\n"
			printf "$(gettext 'Unable to contact \"%s\" at this time.')\n\n\a" "${sponsornode}"
		elif [[ ${result} -ne 0 ]]; then
			printf "%s\n" "${SC_FAILED}"
			if [[ -s "${tmperrs}" ]]; then
				cat ${tmperrs}
			fi
			printf "$(gettext 'Failed to communicate with \"%s\".')\n\n\a" "${sponsornode}"
		else
			printf "%s\n\n" "${SC_DONE}"
		fi

		# Remove error file
		rm -f ${tmperrs}

		if [[ ${result} -ne 0 ]]; then
			prompt="$(gettext 'Do you want to try again?')"
			answer=$(sc_prompt_yesno "${prompt}" "${YES}") || return 2
			if [[ "${answer}" != "yes" ]]; then
				return 2
			fi

			# Try again
			continue
		fi

		# We made contact
		SC_DISCOVER_MADECONTACT=1

		# Verify that we are talking to the right cluster
		if [[ -n "${clustername}" ]]; then
                	scrconf_static -a -N ${sponsornode} -C ${clustername} 2>${tmperrs}
                	let result=$?
			if [[ ${result} -ne 0 ]]; then
				case ${result} in
				${SC_SCCONF_ENOCLUSTER})
                        		printf "$(gettext '\"%s\" does not belong to cluster \"%s\".')\n" "${sponsornode}" "${clustername}"
					;;

				${SC_SCCONF_ENOEXIST})
                        		printf "$(gettext 'The cluster to which \"%s\" belongs does not have a name.')\n" "${sponsornode}"
					;;

				${SC_SCCONF_EAUTH})
                        		printf "$(gettext 'RPC authentication error.')\n"
                        		printf "$(gettext 'Not authorized to communicate with \"%s\".')\n" "${sponsornode}"
					;;

				*)
                        		if [[ -s "${tmperrs}" ]]; then
                                		cat ${tmperrs}
					fi
					;;
				esac

                        	printf "$(gettext 'Cluster name verification failed.')\n\n\a"
				SC_ARGVAR_CLUSTERNAME=
				argvar_append_tofile_clustername ${SC_ILOG}
				sc_prompt_pause || return 1
				return 3
			fi

			# We made contact and clustername is okay
			printf "    $(gettext 'Cluster name \"%s\" is correct.')\n" ${clustername}
			SC_DISCOVER_MADECONTACT=2
		fi

		# Contact made
		sc_prompt_pause || return 1
		return 0
	done
}

####################################################
#
# interactive_check_oe()
#
#	SC_OE_SCINSTALLDIR is set from the <operating_environment>
#	dircetory name component on the install CD (scinstalldir).
#	If SC_OE_SCINSTALLDIR is not NULL, make sure that it matches
#	up with SC_OS_VERSION (set from uname -r).
#
#	If there is a mis-match, print an error and return non-zero.
#	
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_check_oe()
{
	typeset solaris_name

	# If SC_OE_SCINSTALLDIR was never set, we are done
	if [[ -z "${SC_OE_SCINSTALLDIR}" ]]; then
		return 0
	fi

	# Compare OE to OS
	check_oe_os_match ${SC_OE_SCINSTALLDIR} ${SC_OS_VERSION}
	if [[ $? -ne 0 ]]; then
		solaris_name=$(get_name_from_oe ${SC_OE_SCINSTALLDIR})
		printf "$(gettext '%s for %s cannot be installed on %s %s.')\n\n\a" "Sun Cluster" "${solaris_name}" "SunOS" "${SC_OS_VERSION}"
		sc_prompt_pause
		return 1
	fi

	return 0
}

####################################################
#
# interactive_install_framework()
#
#	Install framework packages.
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_framework()
{
	typeset sctxt_title="$(gettext '
		>>> Software Package Installation <<<
	')"

	typeset sctxt_p1="$(gettext '
		Installation of the Sun Cluster framework software packages
		will take a few minutes to complete.
	')"

	typeset answer
	integer result

	#
	# If the framework packages are already known to be installed, skip
	#
	if [[ -f ${SC_INSTALLED_FILE} ]]; then
		return 0
	fi

	#
	# Print title and help text
	#
	clear
	sc_print_title "${sctxt_title}"
	sc_print_para "${sctxt_p1}"

	# Continue?
	answer=$(sc_prompt_yesno "$(gettext 'Is it okay to continue?')" "${YES}") || return 1
	if [[ $? -ne 0 ]] || [[ "${answer}" != "yes" ]]; then
		return 1
	fi

	#
	# Install
	#
	main -i
	if [[ $? -ne 0 ]]; then
		print_errorexit_msg beep
		sc_prompt_pause || return 1
		if [[ -z "${SC_DEBUG}" ]]; then
			return 1
		fi
	fi
	sc_prompt_pause || return 1

	return 0
}

####################################################
#
# interactive_get_sccheckfailed_menuoption() [noreview]
#
#	Print the sccheck failed menu, and return the selected option.
#
#	If the "noreview" is non-NULL, there is no option to
#	review reports.
#
#	This function always returns zero.
#
####################################################
interactive_get_sccheckfailed_menuoption()
{
	typeset noreview=${1}

	typeset option

	typeset sctxt_title_2="$(gettext 'What would you like to do?')"
	typeset sctxt_option_proceed="$(gettext 'Proceed with the installation anyway')"
	typeset sctxt_option_noproceed="$(gettext 'Do not continue with the installation')"
	typeset sctxt_option_review="$(gettext 'Review failed checks report')"
	typeset sctxt_option_retry="$(gettext 'Retry sccheck')"
	typeset sctxt_option_return="$(gettext 'Return to the Main Menu')"

	if [[ -n "${noreview}" ]]; then
		option=$(sc_get_menuoption \
			"T2+++${sctxt_title_2}" \
			"S+0+1+${sctxt_option_proceed}" \
			"S+0+2+${sctxt_option_noproceed}" \
			"S+0+3+${sctxt_option_retry}" \
		)
	else
		option=$(sc_get_menuoption \
			"T2+++${sctxt_title_2}" \
			"S+0+1+${sctxt_option_proceed}" \
			"S+0+2+${sctxt_option_review}" \
			"S+0+3+${sctxt_option_retry}" \
			"R+++" \
			"S+0+q+${sctxt_option_return}" \
		)
	fi

	echo "${option}"

	return 0
}

####################################################
#
# interactive_install_sccheck() iflag [sponsornode]
#
#	Run sccheck(1M).   If it fails, the user can either ignore the
#	failure or abort.
#
#	iflag 1		- establish new cluster w/ this machine
#	iflag 2		- add this machine to an established cluster
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_sccheck()
{
	integer iflag=${1}
	typeset sponsornode=${2}

	typeset sctxt_title="$(gettext '
		>>> Check <<<
	')"
	typeset sctxt_p1="$(gettext '
		This step allows you to run sccheck(1M) to verify that
		certain basic hardware and software pre-configuration
		requirements have been met.  If sccheck(1M) detects
		potential problems with configuring this machine as a
		cluster node, a report of failed checks is prepared
		and available for display on the screen. Data
		gathering and report generation can take several
		minutes, depending on system configuration.
	')"

	typeset sctxt_warning_p1="$(gettext '
		Some error and warning messages can be safely ignored,
		as new configurations are constantly being qualified
		for use with Sun Cluster.  Unless you have been
		notified that a message can be ignored, do not continue
		with the installation until all potential problems have
		been corrected.
	')"

	typeset sctxt_allpassed_p1="$(gettext '
		All %s tests passed.
	')"
	sctxt_allpassed_p1="$(printf "${sctxt_passed_p1}" "sccheck")"
	typeset sctxt_failedchecks_p1="$(gettext '
		A copy of the following report of failed checks is in
		the install log as well as %s.
	')"
	sctxt_failedchecks_p1="$(printf "${sctxt_failedchecks_p1}" "${SC_SCCHECK_RPTDIR}")"
	typeset sctxt_failedcmd_p1="$(gettext '
		If certain required utilities are installed in
		non-standard places you can provide their locations in %s.
	')"
	sctxt_failedcmd_p1="$(printf "${sctxt_failedcmd_p1}" "${SC_SCCHECK_DFLTFILE}")"

	typeset answer
	typeset prompt
	typeset cmd
	integer status

	#
	# Print help and check iflag
	#
	clear
	sc_print_title "${sctxt_title}"
	sc_print_para "${sctxt_p1}"

	# Ask if user wants to run sccheck or skip it
	prompt=$(printf "$(gettext 'Do you want to run %s?')" "sccheck")
	answer=$(sc_prompt_yesno "${prompt}" "${YES}") || return 1
	if [[ "${answer}" != "yes" ]]; then
		return 0
	fi

	#
	# Run sccheck
	#
	while true
	do
		/usr/bin/rm -rf ${SC_SCCHECK_RPTDIR}

		# execute the command
		cmd=${SC_SCCHECK}
		printf "    $(gettext 'Running %s ... ')\n\n" "sccheck" | logmsg
		${cmd} 2>&1
		status=$?

		# no failed checks
		if [[ ${status} -eq 0 ]]; then

			echo | logmsg
			sc_print_para "${sctxt_allpassed_p1}" | logmsg
			sc_prompt_pause || return 1
			return 0

		# some failed checks
		elif [[ ${status} -lt 100 ]]; then

			printf "\n$(gettext 'The %s utility has detected potential problems.')\n\n" "sccheck" | logmsg
			echo "\a\c"
		    	sc_print_para "${sctxt_failedchecks_p1}" | logmsg
		    	cat ${SC_SCCHECK_RPTDIR}/*.txt >>${install_log}
		    	sc_prompt_pause || return 1
		    	interactive_page_sccheck_report

		# sccheck didn't run correctly
		else
			printf "\n$(gettext 'The %s command was unable to run correctly.')\n\n" "sccheck" | logmsg
			echo "\a\c"
		    	sc_print_para "${sctxt_failedcmd_p1}" | logmsg

		fi

		# continue anyway?
		sc_print_para "${sctxt_warning_p1}"
		while true
		do
			case $(interactive_get_sccheckfailed_menuoption) in
			'1')	return 0 ;;
			'2')	interactive_page_sccheck_report ;;
			'3')	break ;;
			'q')	return 1 ;;
			esac
		done
	done

	# We should not get here
	return 1
}

####################################################
#
# interactive_page_sccheck_report
#
#	Page the sccheck report to stdout.
#
#	No inputs, or return value
#
#	No-op if ${SC_SCCHECK_RPTDIR}
#	non-existent or empty
#
####################################################
interactive_page_sccheck_report()
{
	cat ${SC_SCCHECK_RPTDIR}/*.txt 2> /dev/null | more -w
}


####################################################
#
# interactive_install_sccheck_centralized()
#
#	Run sccheck(1M) on each of the nodes during a "centralized" install.
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_sccheck_centralized()
{
	typeset answer
	typeset prompt
	typeset pid
	typeset pids
	typeset node
	typeset nodes
	typeset runlist
	typeset msg

	integer i
	integer errcount
	integer nodecount
	integer first

	typeset sctxt_warning_p1="$(gettext '
		Some error and warning messages can be safely ignored,
		but others should be corrected as soon as possible.
	')"

	# Initialize the run list to all nodes
	runlist=${SC_ARGVAR_NODENAME[*]}
	let nodecount=$(set -- ${runlist}; echo $#)

	#
	# Loop until done
	#
	while [[ -n "${runlist}" ]]
	do
		# Set nodes list
		set -A nodes ${runlist}
		set -A pids

		# Start sccheck running on each node
		let i=0
		for node in ${nodes[*]}
		do
			#
			# Do cmd_sccheck
			#
			(
				# Use temporary install log
				install_log=${install_log}.${node}
				rm -f ${install_log}   

				# Run sccheck
				interactive_install_cmd ${node} "sccheck" >/dev/null 2>&1
				return $?
			) &
			pids="${pids} $!"

			# Print message
			msg="$(printf "$(gettext 'Started %s on \"%s\".')" "sccheck" ${node})"
			printf "    %s\n" "${msg}" | logmsg

		done
		echo | logmsg

		#
		# Clear the runlist.   If errors are found, a new
		# runlist will be generated for the next time through
		#
		runlist=

		# Wait for each process to finish
		let i=0
		for pid in ${pids}
		do
			node=${nodes[i]}

			wait ${pid}
			result=$?
			case ${result} in
			0)    # Finished
				msg="$(printf "$(gettext '%s completed with no errors or warnings for \"%s\".')" "sccheck" "${node}")"
				;;

			*)    # Errors or warnings
				msg="$(printf "$(gettext '%s failed for \"%s\".')" "sccheck" "${node}")"
				runlist="${runlist} ${node}"
				;;
			esac
			printf "    %s\n" "${msg}" | logmsg

			# Next
			((i += 1))
		done
		echo | logmsg

		# Clean up log files
		interactive_cleanup_logfiles "${install_log}" "" ${nodes[*]}

		# If there were no errors, we are done
		if [[ -z "${runlist}" ]]; then
			for node in ${nodes[*]}
			do
				rm -f ${install_log}.${node}
			done
			break
		fi

		# Get the error count
		let errcount=$(set -- ${runlist}; echo $#)

		# Print message
		if [[ ${errcount} -eq ${nodecount} ]]; then
			if [[ ${nodecount} -eq 2 ]]; then
				printf "$(gettext 'The %s command failed on both of the nodes.')\n" "sccheck" | logmsg
			else
				printf "$(gettext 'The %s command failed on all of the nodes.')\n" "sccheck" | logmsg
			fi
		else
			printf "$(gettext 'The %s command failed on %d of the nodes.')\n" "sccheck" ${errcount} | logmsg
		fi

		# If we are not to interrupt on sccheck errors, we are done
		if [[ -z "${SC_SCCHECK_INTR}" ]]; then
			interactive_printlogmsg "${install_log}"
			for node in ${nodes[*]}
			do
				rm -f ${install_log}.${node}
			done
			break
		fi

		# Ask if they want to see the log
		echo | logmsg
		sc_print_para "${sctxt_warning_p1}"
		let first=1
                typeset -L errnode=${runlist}
		while true
		do
			if [[ ${errcount} -eq 1 ]]; then
				prompt="$(printf "$(gettext 'Do you want to see the log file for \"%s\"?')" "${errnode}")"
				answer=$(sc_prompt_yesno "${prompt}" "${YES}") || return 1
				if [[ "${answer}" != "yes" ]]; then
					break
				fi
				answer=${errnode}
			else
				if [[ ${first} -eq 1 ]];  then
					let first=0
					prompt="$(printf "$(gettext 'Would you like to see the log file for one of the nodes?')")"
					answer=$(sc_prompt_yesno "${prompt}" "${YES}") || return 1
					if [[ "${answer}" != "yes" ]]; then
						break
					fi
				fi
				prompt="$(gettext 'Select the node whose log file you would like to inspect:')"
				answer="$(
					    sc_get_scrolling_menuoptions    \
						"${prompt}"		    \
						"" ""			    \
						0 1 0			    \
						${runlist}
				)"
				if [[ -z "${answer}" ]]; then
					break
				fi
               		fi
			(
				echo ${SC_LINE}
				echo ${answer}
				echo ${SC_LINE}
				cat ${install_log}.${answer}
			) | more
			echo
			echo "------------------------------------------------------------------------------"
			echo "\n"
		done

		# Remove the log files
		for node in ${nodes[*]}
		do
			rm -f ${install_log}.${node}
		done
				
		# Continue?
		case $(interactive_get_sccheckfailed_menuoption noreview) in
		'1')	return 0 ;;
		'2')	return 1 ;;
		'3')	;;
		esac

		# Blank line
		echo | logmsg
	done

	# Done
	return 0
}

####################################################
#
# interactive_install_clustername() iflag [sponsornode]
#
#	Set SC_ARGVAR_CLUSTERNAME to the cluster name,
#	then add to the response log.
#
#	iflag 1		- establish new cluster w/ this machine
#	iflag 2		- add this machine to an established cluster
#	iflag 3		- custom JumpStart client set up
#	iflag 4		- centralized install
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_clustername()
{
	integer iflag=${1}
	typeset sponsornode=${2}

	typeset sctxt_title="$(gettext '
		>>> Cluster Name <<<
	')"
	typeset sctxt_i1_p1="$(gettext '
		Each cluster has a name assigned to it.  The name can
		be made up of any characters other than whitespace.
		Each cluster name should be unique within the
		namespace of your enterprise.
	')"
	typeset sctxt_i2_p1="$(gettext '
		Each cluster has a name assigned to it.  When adding
		a node to the cluster, you must identify the name of
		the cluster you are attempting to join.  A sanity check
		is performed to verify that the \"sponsoring\" node
		is a member of that cluster.
	')"
	typeset sctxt_i3_p1="${sctxt_i1_p1}"
	typeset sctxt_i4_p1="${sctxt_i1_p1}"

	typeset answer
	integer result

	#
	# Print help and check iflag
	#
	case ${iflag} in
	'1')  # new cluster
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_i1_p1}"
		;;

	'2')  # add node
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_i2_p1}"
		;;

	'3')  # JumpStart
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_i3_p1}"
		;;

	'4')  # centralized install
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_i4_p1}"
		;;

	*)    # invalid argument
		return 1
		;;
	esac

	# Prompt user and get response
	while true
	do
		case ${iflag} in
		'2')
			answer=$(sc_prompt "$(gettext 'What is the name of the cluster you want to join?')" "${SC_ARGVAR_CLUSTERNAME}") || return 1
			;;

		*)
			answer=$(sc_prompt "$(gettext 'What is the name of the cluster you want to establish?')" "${SC_ARGVAR_CLUSTERNAME}") || return 1
			;;
		esac

		# The cluster name may be any string <= 256 characters
		if [[ ${#answer} -ge 256 ]]; then
			printf "$(gettext 'The name is too long.')\n\n\a"
			continue
		fi

		# If we are adding a node, try to make contact now
		if [[ ${iflag} -eq 2 ]] && [[ -n "${sponsornode}" ]]; then
			interactive_install_makecontact ${sponsornode} ${answer}
			let result=$?
			case ${result} in
			'0')	;;
			'1')	return 1 ;;
			'2' | '3')
				# Change the sponsor node?
				answer=$(sc_prompt_yesno "$(gettext 'Do you want to try a different sponsoring node?')" "${NO}") || return 1
				if [[ "${answer}" == "yes" ]]; then
					SC_ARGVAR_SPONSORNODE[0]=
					interactive_install_sponsornode ${iflag} "nohelp" || return 1
					sponsornode=${SC_ARGVAR_SPONSORNODE[SC_IDX]}
					continue
				fi

				# Nope, don't change the node
				case ${result} in
				'2')	return 0 ;;
				'3')	continue ;;
				esac

				;;
			esac
		fi
		break
	done
	SC_ARGVAR_CLUSTERNAME=${answer}

	# append SC_ARGVAR_CLUSTERNAME to the response log
	argvar_append_tofile_clustername ${SC_ILOG}

	return 0
}

####################################################
#
# interactive_install_jmp_exists()
#
#	jumpstart_dir	- already established jumpstart directory
#	clustername	- already established cluster name
#
#	If the cluster already exists in this jumpstart dir,
#	reset defaults to use this.
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_jmp_exists()
{
	typeset saved_jumpstart_dir=${SC_ARGVAR_JUMPSTARTDIR}
	typeset saved_clustername=${SC_ARGVAR_CLUSTERNAME}
	typeset saved_authlist="${SC_ARGVAR_AUTHLIST}"
	typeset clustdir
	typeset node
	typeset nodelist
	typeset nodedir
	typeset tmpfile
	typeset answer

	integer index

	typeset sctxt_title="$(gettext '
		>>> Custom JumpStart Directory Exists <<<
	')"
	typeset sctxt_p1="$(gettext '
		One or more custom JumpStart directories seem to
		already exist for this cluster.
	')"

	# Set the clustdir
	clustdir=${saved_jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/../clusters/${saved_clustername}

	# If the clustdir does not exist, we are done
	if [[ ! -d ${clustdir} ]]; then
		return 0
	fi

	# Reset everything
	argvar_clear_all_argvars
	rm -f ${SC_ILOG}

	# First pass - look for initial settings
	for nodedir in ${clustdir}/*
	do
		if [[ ! -f ${nodedir}/${SC_AUTOSCDATA} ]] ||
		    [[ ! -r ${nodedir}/${SC_AUTOSCDATA} ]]; then
			continue
		fi
		. ${nodedir}/${SC_AUTOSCDATA}
		if [[ -n "${SC_ARGVAR_JUMPSTARTDIR}" ]] &&
		    [[ "${SC_ARGVAR_JUMPSTARTDIR}" != "${saved_jumpstart_dir}" ]]; then
			argvar_clear_all_argvars
			return 0
		fi
		if [[ -n "${SC_ARGVAR_CLUSTERNAME}" ]] &&
		    [[ "${SC_ARGVAR_CLUSTERNAME}" != "${saved_clustername}" ]]; then
			argvar_clear_all_argvars
			return 0
		fi
		if [[ -z "${saved_authlist}" ]]; then
			saved_authlist="${SC_ARGVAR_AUTHLIST}"
		elif [[ -n "${SC_ARGVAR_AUTHLIST}" ]] &&
		    [[ "${SC_ARGVAR_AUTHLIST}" != "${saved_authlist}" ]]; then
			argvar_clear_all_argvars
			return 0
		fi
	done
	argvar_clear_all_argvars

	# Construct new defaults in tmpfile
	tmpfile=${saved_jumpstart_dir}/${SC_ILOGBASE}.tmp
	rm -f ${tmpfile}
	if [[ -n "${saved_authlist}" ]]; then
		nodelist="${saved_authlist}"
	else
		nodelist="$(cd ${clustdir};  echo *)"
	fi

	nodedir=${saved_jumpstart_dir}/${SC_AUTOSCCONFIGDIR}
	let index=0
	for node in ${nodelist}
	do
		if [[ ! -f ${nodedir}/${node}/${SC_AUTOSCDATA} ]] ||
		    [[ ! -r ${nodedir}/${node}/${SC_AUTOSCDATA} ]]; then
			argvar_clear_all_argvars
			return 0
		fi
		sed \
			-e '/..*=""/d'			\
			-e '/..*=[ 	]/d'		\
			-e '/..*=$/d'			\
			-e 's/\[0\]/\['${index}'\]/'	\
		    ${nodedir}/${node}/${SC_AUTOSCDATA} >>${tmpfile} 2>/dev/null
		((index += 1))
	done

	# If nothing none of the nodes are configured, just return
	if [[ ! -s "${tmpfile}" ]]; then
		argvar_clear_all_argvars
		return 0
	fi

	# Otherwise, source in the tmpfile
	. ${tmpfile}

	# Make sure there is still a cluster name and jmpstart dir
	if [[ -z "${SC_ARGVAR_CLUSTERNAME}" ]]; then
		SC_ARGVAR_CLUSTERNAME=${saved_clustername}
	fi
	if [[ -z "${SC_ARGVAR_JUMPSTARTDIR}" ]]; then
		SC_ARGVAR_JUMPSTARTDIR=${saved_jumpstart_dir}
	fi

	# Set indices
	argvar_set_indices

	# Append to the log
	argvar_append_all_tofile "${SC_INDICES}" ${SC_ILOG}

	#
	# Print help
	#
	clear
	sc_print_title "${sctxt_title}"
	sc_print_para "${sctxt_p1}"

	# Show current config?
	while true
	do
		answer=$(sc_prompt_yesno "$(gettext 'Do you want to inspect this configuration?')" "${YES}") || return 1
		if [[ "${answer}" = "yes" ]]; then
		    (
			for index in ${SC_INDICES}
			do
				argvar_print_SC_ARGVARS "${index}" "scinstall -c ${SC_ARGVAR_JUMPSTARTDIR} -h ${SC_ARGVAR_NODENAME[index]}" ""
			done
		    ) | more

			# Pause until they press Enter
			sc_prompt_pause || return 1
			break
		else
			break
		fi
	done

	# Okay to continue?
	answer=$(sc_prompt_yesno "$(gettext 'Do you want to make changes?')" "${YES}") || return 1
	if [[ "${answer}" != "yes" ]]; then
		return 1
	fi

	# Done
	return 0
}

####################################################
#
# interactive_install_authlist() iflag
#
#	Set SC_ARGVAR_AUTHLIST to the list
#	of nodes able to join the cluster,
#	then add to the response log.
#
#	iflag 1		- establish new cluster w/ this machine
#	iflag 3		- custom JumpStart client set up
#	iflag 4		- centralized install
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_authlist()
{
	integer iflag=${1}

	typeset sctxt_title="$(gettext '
		>>> Cluster Nodes <<<
	')"
	typeset sctxt_p1="$(gettext '
		This Sun Cluster release supports a total
		of up to %d nodes.
	')"
	typeset sctxt_p1="$(printf "${sctxt_p1}" ${SC_MAXNODES})"
	typeset sctxt_i1_p2="$(gettext '
		Please list the names of the other nodes planned
		for the initial cluster configuration.  List one
		node name per line.  When finished, type Control-D:
	')"
	typeset sctxt_i3_p2="$(gettext '
		Please list the names of all cluster nodes planned
		for the initial cluster configuration.  You must
		enter at least two nodes.  List one node name per line.
		When finished, type Control-D:
	')"
	typeset sctxt_i4_p2="${sctxt_i1_p2}"
	typeset sctxt_p2=
	typeset sctxt_p3="$(gettext '
		This is the complete list of nodes:
	')"
	typeset sctxt_node_prompt1="$(gettext 'Node name:')"
	typeset sctxt_node_prompt2="$(gettext 'Node name (Control-D to finish):')"
	typeset sctxt_node_prompt

	integer i
	integer count
	typeset nodename
	typeset answer
	typeset answers
	typeset checkhostname=
	typeset pinghost=
	typeset foo

	#
	# Check iflag
	#
	case ${iflag} in
	'1')  # Install
		sctxt_p2="${sctxt_i1_p2}"
		checkhostname=1
		;;

	'3')  # JumpStart
		sctxt_p2="${sctxt_i3_p2}"
		;;

	'4')  # centralized install
		sctxt_p2="${sctxt_i4_p2}"
		checkhostname=1
		pinghost=1
		;;

	*)    # invalid argument
		return 1
		;;
	esac

	# Prompt user and get response
	while true
	do
		answers=

		# prompt
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"

		# count list
		let i=$(set -- ${SC_ARGVAR_AUTHLIST}; echo $#)
		if [[ ${i} -lt 2 ]]; then
			SC_ARGVAR_AUTHLIST=
		fi

		#
		# If there is already a set install node which is not
		# already in the AUTHLIST, clear that list.
		#
		if [[ -n "${SC_ARGVAR_NODENAME[SC_IDX]}" ]]; then
			let i=0
			for nodename in ${SC_ARGVAR_AUTHLIST}
			do
				if [[ "${SC_ARGVAR_NODENAME[SC_IDX]}" = "${nodename}" ]]; then
					((i += 1))
				fi
			done
			if [[ ${i} -ne 1 ]]; then
				SC_ARGVAR_AUTHLIST=
			fi
		fi

		# if more than ${SC_MAXNODES} nodes, clear the list
		if [[ $(set -- ${SC_ARGVAR_AUTHLIST}; echo $#) -gt ${SC_MAXNODES} ]]; then
			SC_ARGVAR_AUTHLIST=
		fi
			
		# if authlist is set, just print it
		if [[ -n "${SC_ARGVAR_AUTHLIST}" ]]; then
			let count=0
			answers="${SC_ARGVAR_AUTHLIST}"
			for answer in ${SC_ARGVAR_AUTHLIST}
			do
				if [[ ${count} -lt 2 ]]; then
					sctxt_node_prompt="${sctxt_node_prompt1}"
				else
					sctxt_node_prompt="${sctxt_node_prompt2}"
				fi
				printf "$(sc_print_prompt "${sctxt_node_prompt}")${answer}\n"
				((count += 1))
			done
			printf "$(sc_print_prompt "${sctxt_node_prompt2}")^D\n"

		# otherwise, get it
		else
			if [[ ${iflag} -eq 1 ]] ||
			    [[ ${iflag} -eq 4 ]]; then
				let count=1
			else
				let count=0
			fi
			answers=
			while true
			do

				# Prompt
				if [[ ${count} -lt 2 ]]; then
					sctxt_node_prompt="${sctxt_node_prompt1}"
				else
					sctxt_node_prompt="${sctxt_node_prompt2}"
				fi
				answer=$(sc_prompt "${sctxt_node_prompt}" "" "nonl")

				# Can't use Control-D until we have two nodes
				if [[ -z "${answer}" ]]; then
					if [[ ${count} -lt 2 ]]; then
						continue
					else
						break
					fi
				fi

				# node name must begin with alpha
				# and may not include : or @
				if [[ "${answer}" = [!a-zA-Z]* ]] ||
				    [[ "${answer}" = *[@:]* ]]; then
					printf "\n$(gettext 'Invalid node name.')\n\n\a"
					continue
				fi

				# node name must be <= 256 characters
				if [[ ${#answer} -gt 256 ]]; then
					printf "\n$(gettext 'Node name is too long.')\n\n\a"
					continue
				fi

				# duplicate entry - error
				for foo in ${answers}
				do
					if [[ "${answer}" = "${foo}" ]]; then
						printf "\n$(gettext '\"%s\" already entered.')\n\n\a" "${answer}"
						continue 2
					fi
				done

				# see if hostname is known
				if [[ -n "${checkhostname}" ]] &&
				    [[ -x /usr/bin/perl ]]; then
        				/usr/bin/perl -s -e '
						use Socket;
						gethostbyname($ARGV[0]) || exit(1);
						exit(0);
					' ${answer}
					if [[ $? -eq 1 ]]; then
						printf "\n$(gettext 'Unknown host.')\n\n\a"
						continue
					fi
				fi

				# OKAY - add to list of answers
				answers="${answers} ${answer}"

				# if not this node, increase count
				if [[ ${iflag} -eq 3 ]] ||
				    [[ "${answer}" != "${SC_ARGVAR_NODENAME[SC_IDX]}" ]]; then
					((count += 1))
				fi

				# if we have ${SC_MAXNODES}, we are done
				if [[ ${count} -eq ${SC_MAXNODES} ]]; then
					break
				fi
			done
		fi
		echo
	
		# put this node at the top of the answers list
		foo=
		for answer in ${answers}
		do
			if [[ "${answer}" != "${SC_ARGVAR_NODENAME[SC_IDX]}" ]]; then 
				foo="${foo} ${answer}"
			fi
		done
		answers="${SC_ARGVAR_NODENAME[SC_IDX]} ${foo}"

		# the answers list must contain at least two nodes
		let count=$(set -- ${answers}; echo $#)
		if [[ ${count} -lt 2 ]]; then
			answers=
			continue
		fi

		# set SC_ARGVAR_AUTHLIST
		SC_ARGVAR_AUTHLIST="${answers}"

		# verify that the list is correct
		echo
		sc_print_para "${sctxt_p3}"
		for foo in ${SC_ARGVAR_AUTHLIST}
		do
			printf "\t${foo}\n"
		done
		echo
		answer=$(sc_prompt_yesno "$(gettext 'Is it correct?')" "${YES}") || return 1
		if [[ "${answer}" != "yes" ]]; then
			SC_ARGVAR_AUTHLIST=
			continue
		fi

		# Make sure we can contact everyone, if we need to
		while [[ -n "${pinghost}" ]]
		do
			let errors=0
			echo
			for foo in ${SC_ARGVAR_AUTHLIST}
			do
				# Skip myself
				if [[ "${foo}" == "${SC_ARGVAR_NODENAME[SC_IDX]}" ]]; then
					continue
				fi

				sc_print_line "$(printf "$(gettext 'Attempting to contact \"%s\" ... ')" "${foo}")" | logmsg
				echo >>${install_log}
				echo "ping ${foo}" >${tmperrs}
				ping ${foo} >>${tmperrs} 2>&1
				if [[ $? -eq 0 ]]; then
					printf "%s\n" ${SC_DONE}
				else
					printf "%s\n" ${SC_FAILED}
					if [[ -s ${tmperrs} ]]; then
						echo >>${install_log}
						cat ${tmperrs} >>${install_log}
						echo >>${install_log}
					fi
					((errors += 1))
				fi
				rm -f ${tmperrs}
			done
			echo
			if [[ ${errors} -eq 0 ]]; then
				break
			else
				if [[ ${count} -eq 2 ]]; then
					printf "$(gettext 'Unable to contact the other node.')\n\n\a"
				else
					printf "$(gettext 'Unable to contact %d of the other nodes.')\n\n\a" "${errors}"
				fi
				answer=$(sc_prompt_yesno "$(gettext 'Do you want to try again?')" "${NO}") || return 1
				if [[ "${answer}" != "yes" ]]; then
					SC_ARGVAR_AUTHLIST=
					continue 2
				fi
			fi
		done
		break
	done

	# append SC_ARGVAR_AUTHLIST to the response log
	argvar_append_tofile_authlist ${SC_ILOG}

	return 0
}

####################################################
#
# interactive_install_remote_method
#
#	Determine the best remote install method for centralized
#	install.   All nodes must use the same method.
#
#	The order of prefence is scrcmd, then ssh, then rsh.
#
#	Upon success, this function sets both SC_REMOTE_METHOD and
#	SC_ARGVAR_REMOTE_METHOD to "scrcmd", "ssh", or "rsh".
#
#	Uses ${tmpfile2} and ${tmperrs2}.
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_remote_method()
{
	typeset sctxt_scrcmd="$(gettext '
		The Sun Cluster framework software is already installed
		on each of the new nodes of this cluster.  And, it is
		able to complete the configuration process without
		remote shell access.
	')"
	typeset sctxt_rsh="$(gettext '
		The remote shell (see rsh(1)) will be used to install
		and configure this cluster.
	')"
	typeset sctxt_ssh="$(gettext '
		The secure shell (see ssh(1)) will be used to install
		and configure this cluster.
	')"

	integer i

	typeset node
	typeset cmd
	typeset result
	typeset flag
	typeset scrcmd_list=
	typeset rsh_list=
	typeset ssh_list=

	# Reset remote install method
	SC_REMOTE_METHOD=
	SC_ARGVAR_REMOTE_METHOD=
	argvar_append_tofile_remote_method ${SC_ILOG}

	# Print message
	echo >>${install_log}
	sc_print_line "$(gettext 'Searching for a remote install method ... ')" | logmsg
	echo >>${install_log}

	# Look at each node
	for node in ${SC_ARGVAR_NODENAME[*]}
	do
		# Skip this node
		if [[ "${node}" == "${mynodename}" ]]; then
			continue;
		fi

		# Try scrcmd
		result=107
		if [[ -x /usr/cluster/lib/sc/scrcmd ]] &&
		    [[ -f "${SC_REMOTECONFIG_FILE}" ]] &&
		    [[ -f "${SC_INSTALLED_FILE}" ]]; then
			cmd="scrcmd -N ${node} test isfullyinstalled"
			echo >>${install_log}
			echo ${cmd} >>${install_log}
			eval ${cmd} >>${install_log} 2>&1
			result=$?
			printf "$(gettext '%s to \"%s\" - return status %d.')\n" "scrcmd" ${node} ${result} >>${install_log}
		fi
		if [[ ${result} == "1" ]]; then
			scrcmd_list="${scrcmd_list} 1"
		else
			scrcmd_list="${scrcmd_list} 0"
		fi

		# Try rsh
		result=1
		if [[ -x /usr/bin/rsh ]]; then
			cmd="rsh ${node} -n \"/bin/sh -c '/bin/true;  /bin/echo SC_COMMAND_STATUS=\\\$?'\""
			echo >>${install_log}
			echo ${cmd} >>${install_log}
			eval ${cmd} >${tmpfile2} 2>${tmperrs2}
			result=$(sed -n 's/^SC_COMMAND_STATUS=\(.*\)/\1/p' ${tmpfile2})
			if [[ -z "${result}" ]]; then
				result=107
			fi
			cat ${tmpfile2} >>${install_log}
			cat ${tmperrs2} >>${install_log}
			rm -f ${tmpfile2}
			rm -f ${tmperrs2}
			if [[ "${result}" != "0" ]]; then
				printf "$(gettext '%s to \"%s\" failed.')\n" "rsh" ${node} >>${install_log}
			else
				printf "$(gettext '%s to \"%s\" - return status %d.')\n" "rsh" ${node} ${result} >>${install_log}
			fi
		fi
		if [[ ${result} == "0" ]]; then
			rsh_list="${rsh_list} 1"
		else
			rsh_list="${rsh_list} 0"
		fi

		# Try ssh
		result=1
		if [[ -x /usr/bin/ssh ]]; then
			cmd="ssh root@${node} -o \"BatchMode yes\" -o \"StrictHostKeyChecking yes\" -n \"/bin/sh -c '/bin/true;  /bin/echo SC_COMMAND_STATUS=\\\$?'\""
			echo >>${install_log}
			echo ${cmd} >>${install_log}
			eval ${cmd} >${tmpfile2} 2>${tmperrs2}
			result=$(sed -n 's/^SC_COMMAND_STATUS=\(.*\)/\1/p' ${tmpfile2})
			if [[ -z "${result}" ]]; then
				result=107
			fi
			cat ${tmpfile2} >>${install_log}
			cat ${tmperrs2} >>${install_log}
			rm -f ${tmpfile2}
			rm -f ${tmperrs2}
			if [[ "${result}" != "0" ]]; then
				printf "$(gettext '%s to \"%s\" failed.')\n" "ssh" ${node} >>${install_log}
			else
				printf "$(gettext '%s to \"%s\" - return status %d.')\n" "ssh" ${node} ${result} >>${install_log}
			fi
		fi
		if [[ ${result} == "0" ]]; then
			ssh_list="${ssh_list} 1"
		else
			ssh_list="${ssh_list} 0"
		fi
	done
	echo >>${install_log}

	# See if we can use the scrcmd
	let i=1
	for flag in ${scrcmd_list}
	do
		if [[ "${flag}" == "0" ]]; then
			let i=0
		fi
	done
	if [[ ${i} -eq 1 ]]; then
		printf "%s\n\n" ${SC_DONE}
		sc_print_para "${sctxt_scrcmd}" | logmsg
		sc_prompt_pause || return 1
		SC_REMOTE_METHOD=scrcmd
		SC_ARGVAR_REMOTE_METHOD=${SC_REMOTE_METHOD}
		argvar_append_tofile_remote_method ${SC_ILOG}
		return 0
	fi

	# Try ssh next
	let i=1
	for flag in ${ssh_list}
	do
		if [[ "${flag}" == "0" ]]; then
			let i=0
		fi
	done
	if [[ ${i} -eq 1 ]]; then
		printf "%s\n\n" ${SC_DONE}
		sc_print_para "${sctxt_ssh}" | logmsg
		sc_prompt_pause || return 1
		SC_REMOTE_METHOD=ssh
		SC_ARGVAR_REMOTE_METHOD=${SC_REMOTE_METHOD}
		argvar_append_tofile_remote_method ${SC_ILOG}
		return 0
	fi

	# Try rsh next
	let i=1
	for flag in ${rsh_list}
	do
		if [[ "${flag}" == "0" ]]; then
			let i=0
		fi
	done
	if [[ ${i} -eq 1 ]]; then
		printf "%s\n\n" ${SC_DONE}
		sc_print_para "${sctxt_rsh}" | logmsg
		sc_prompt_pause || return 1
		SC_REMOTE_METHOD=rsh
		SC_ARGVAR_REMOTE_METHOD=${SC_REMOTE_METHOD}
		argvar_append_tofile_remote_method ${SC_ILOG}
		return 0
	fi

	# Everything failed
	printf "%s\n\n" ${SC_FAILED}
	printf "$(gettext 'Remote access attempts to one or more of the other nodes failed.')\n" | logmsg
	interactive_printlogmsg "${install_log}"
	sc_prompt_pause

	return 1
}

####################################################
#
# interactive_install_cmd nodename command [method] [noprepend]
#
#	Run a "command" for centralized install on the given
#	"nodename".  If "nodename" is null or is this node,
#	the command is run locallay;   otherwise, a remote command
#	is issued.
#
#	The "method" argument is only considered if a remote command
#	is to be run.  If "method" is not given, the method found
#	in SC_REMOTE_METHOD is used.
#
#	If the "noprepend" flag is not given, "command" does not begin
#	with '/' and the method is not a remote "scrcmd" method, the command is
#	prefixed with "/usr/cluster/lib/scadmin/lib/cmd_".
#
#	Uses ${tmpfile2}.<node> and ${tmperrs2}.<node>.
#
#	Return values:
#
#		107	- failed to run the remote command (same as scrcmd)
#		others	- command exit code
#
####################################################
interactive_install_cmd()
{
	typeset nodename=${1}
	typeset command="${2}"
	typeset method=${3}
	typeset noprepend=${4}

	typeset result=107
	typeset cmd

	typeset mytmpfile=${tmpfile2}.${nodename}
	typeset mytmperrs=${tmperrs2}.${nodename}

	# Check command argument
	if [[ -z "${command}" ]]; then
		return 107
	fi

	# If method is not given, use SC_REMOTE_METHOD
	if [[ -z "${method}" ]]; then
		method=${SC_REMOTE_METHOD}
	fi

	# Check to see if it is local
	if [[ -z "${nodename}" ]] ||
	    [[ "${nodename}" == "${mynodename}" ]]; then
		method="local"
	fi

	# Run the command
	case ${method} in
	rsh|ssh)
		# Prepend prefix?
		if [[ -z "${noprepend}" ]] &&
		    [[ "${command}" != /* ]]; then
			command=/usr/cluster/lib/scadmin/lib/cmd_${command}
		fi

		# Set the cmd
		case ${method} in
		rsh)   # rsh
			cmd="rsh ${nodename} -n \"/bin/sh -c '${command};  /bin/echo SC_COMMAND_STATUS=\\\$?'\""
			;;

		ssh)   # ssh
			cmd="ssh root@${nodename} -o \"BatchMode yes\" -n \"/bin/sh -c '${command};  /bin/echo SC_COMMAND_STATUS=\\\$?'\""
			;;
		esac

		# Run the cmd
		echo >>${install_log}
		echo ${cmd} >>${install_log}
		eval ${cmd} >${mytmpfile} 2>${mytmperrs}
		result=$(sed -n 's/^SC_COMMAND_STATUS=\(.*\)/\1/p' ${mytmpfile})
		if [[ -z "${result}" ]]; then
			result=107
		fi
		cat ${mytmpfile} >>${install_log}
		grep -v ^SC_COMMAND_STATUS ${mytmpfile}
		cat ${mytmperrs} | logmsg
		rm -f ${mytmpfile}
		rm -f ${mytmperrs}
		;;

	local)
		# Prepend prefix?
		if [[ -z "${noprepend}" ]] &&
		    [[ "${command}" != /* ]]; then
			command=/usr/cluster/lib/scadmin/lib/cmd_${command}
		fi

		# Set the cmd
		cmd="${command}"

		# Run the cmd
		echo >>${install_log}
		echo ${cmd} >>${install_log}
		eval ${cmd} >${mytmperrs} 2>&1
		result=$?
		cat ${mytmperrs} | logmsg
		rm -f ${mytmperrs}
		;;

	scrcmd)
		# Set the cmd
		cmd="scrcmd -N ${nodename} ${command}"

		# Run the cmd
		echo >>${install_log}
		echo ${cmd} >>${install_log}
		eval ${cmd} >${mytmperrs} 2>&1
		result=$?
		cat ${mytmperrs} | logmsg
		rm -f ${mytmperrs}
		;;
	*)
		result=107
		;;
	esac

	return ${result}
}

####################################################
#
# interactive_install_authtype() iflag
#
#	Set SC_ARGVAR_AUTHTYPE of nodes able to join the cluster,
#	then add to the response log.
#
#	iflag 1		- establish new cluster w/ this machine
#	iflag 3		- custom JumpStart client set up
#	iflag 4		- centralized install
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_authtype()
{
	integer iflag=${1}

	typeset sctxt_title="$(gettext '
		>>> Authenticating Requests to Add Nodes <<<
	')"
	typeset sctxt_p1="$(gettext '
		Once the first node establishes itself as a single node
		cluster, other nodes attempting to add themselves to
		the cluster configuration must be found on the list of
		nodes you just provided.  You can modify this list
		using scconf(1M) or other tools once the cluster has
		been established.
	')"
	typeset sctxt_p2="$(gettext '
		By default, nodes are not securely authenticated as
		they attempt to add themselves to the cluster
		configuration.  This is generally considered adequate,
		since nodes which are not physically connected to the
		private cluster interconnect will never be able to
		actually join the cluster.  However, DES authentication
		is available.  If DES authentication is selected, you
		must configure all necessary encryption keys before any
		node will be allowed to join the cluster (see
		keyserv(1M), publickey(4)).
	')"

	typeset answer
	typeset dflt_answer

	#
	# Check iflag
	#
	case ${iflag} in
	'1' | '3' | '4')
		;;

	*)    # invalid argument
		return 1
		;;
	esac

	# If custom mode, prompt user and get response
	while [[ ${SC_TYPICAL_INSTALL} -ne 1 ]]
	do
		# Print help
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"

		# set default answer - yes or no
		if [[ "${SC_ARGVAR_AUTHTYPE}" = "des" ]]; then
			dflt_answer="${YES}"
		else
			dflt_answer="${NO}"
		fi

		# Prompt user and get yes or no response
		answer=$(sc_prompt_yesno "$(gettext 'Do you need to use DES authentication?')" "${dflt_answer}") || return 1

		# If okay, use "sys"
		if [[ "${answer}" != "yes" ]]; then
			SC_ARGVAR_AUTHTYPE="sys"

		# otherwise, verify "des"
		else
			answer=$(sc_prompt_yesno "$(gettext 'Are the necessary keys configured for all nodes?')") || return 1
			if [[ "${answer}" != "yes" ]]; then
				continue
			fi

			SC_ARGVAR_AUTHTYPE="des"
		fi

		# Okay - done
		break
	done

	# Otherwise, if typical mode, use defaults
	if [[ ${SC_TYPICAL_INSTALL} -eq 1 ]]; then
		SC_ARGVAR_AUTHTYPE="sys"
	fi

	# append SC_ARGVAR_AUTHTYPE to the response log
	argvar_append_tofile_authtype ${SC_ILOG}

	return 0
}

####################################################
#
# interactive_install_snoop() adapter
#
#	Look for packets on the given adapter.
#
#	Return values:
#		0		- Okay to use this adapter
#		non-zero	- Do not use this adapter
#
####################################################
interactive_install_snoop()
{
	typeset -r adapter=${1}

	typeset allnet_ladapters
	typeset arg_adaptypes
	typeset adap
	typeset line
	typeset answer
	typeset prompt
	typeset foo

	integer found
	integer result
	integer count
	integer recvto=10

	# Set the list of known adaptertypes for use w/ scrconf
	arg_adaptypes=
	if [[ -n "${SC_DFLT_KNOWN_ETHERNET_ADAPTERS}" ]]; then
		arg_adaptypes=",adaptypes=$(new_separator : ${SC_DFLT_KNOWN_ETHERNET_ADAPTERS})"
	fi

	# Make sure it is a known net adapter
	allnet_ladapters="$(scrconf_static -n cmd=print_adapters${arg_adaptypes})"
	let found=0
	for adap in ${allnet_ladapters}
	do
		if [[ "${adapter}" == "${adap}" ]]; then
			let found=1
			break
		fi
	done

	# If it is not known to be a network adapter, do not snoop
	if [[ ${found} -eq 0 ]]; then
		return 0
	fi

	# Print message
	sc_print_line "$(printf "$(gettext 'Searching for any unexpected network traffic on \"%s\" ... ')" "${adapter}")"

	# Snoop
	scrconf_static -n cmd=discover_snoop,adapters=${adapter},recvto=${recvto},nowait >${tmpfile} 2>${tmperrs}
	let result=$?

	# Inspect output for errors
	let count=0
	while read line
	do
		foo="${line}"
		((count += 1))
	done <${tmpfile}
	if [[ ${result} -ne 0 ]] ||
	    [[ -s ${tmperrs} ]] ||
	    [[ ${count} -ne 2 ]] ||
	    [[ "${foo}" != "quit" ]]; then
		printf "%s\n" ${SC_FAILED}
		cat ${tmperrs}
		let result=1
	else
		printf "%s\n" ${SC_DONE}
	fi

	# Make sure that we got the expected output
	if [[ ${result} -eq 0 ]]; then
		read line <${tmpfile}
		if [[ "${line}" != ${adapter}:* ]]; then
			printf "$(gettext 'Unexpected probe results for \"%s\".')\n\n\a" "${adapter}"
			let result=1
		fi
	fi

	# See if we found any traffic
	if [[ ${result} -eq 0 ]]; then
		if [[ "${line}" != ${adapter}:0 ]]; then
			printf "$(gettext 'Unexpected network traffic was seen on \"%s\".')\n" "${adapter}"
			printf "$(gettext '\"%s\" may be cabled to a public network.')\n\n\a" "${adapter}"
			let result=1
		fi
	fi

	# Cleanup
	rm -f ${tmperrs}
	rm -f ${tmpfile}

	# If no traffic, print verification message
	if [[ ${result} -eq 0 ]]; then
		prompt="$(printf "$(gettext 'Verification completed.  No traffic was detected over a %d second sample period.')" ${recvto})"
		sc_print_para "${prompt}"

	# Traffic or errors, use it anyway?
	else
		prompt="$(printf "$(gettext 'Do you want to use \"%s\" anyway?')" "${adapter}")"
		answer=$(sc_prompt_yesno "${prompt}" "${NO}") || return 1
		if [[ "${answer}" == "yes" ]]; then
			let result=0
		fi
	fi

	return ${result}
}

####################################################
#
# interactive_install_autodiscover() sponsornode clustername
#
#	Auto discovery for Ethernet.
#
#	The following variables should already be set before this
#	function is called:
#
#		SC_IDX
#		SC_ILOG
#
#	The following global variable is set:
#
#		SC_DISCOVER_DOAUTO	# if non-zero, do full discovery
#
#	If SC_DISCOVER_DOAUTO is set, the following SC_ARGVAR variables
#	will also be set/reset by this function:
#
#		SC_ARGVAR_TWONODES
#		SC_ARGVAR_DIRECT
#		SC_ARGVAR_ADAPTERS[SC_IDX]
#		SC_ARGVAR_JUNCTIONS[SC_IDX]
#		SC_ARGVAR_JUNCTYPES[SC_IDX]
#		SC_ARGVAR_ETHERADAP[SC_IDX]
#		SC_ARGVAR_TRTYPES[SC_IDX]
#		SC_ARGVAR_E2CABLES[SC_IDX]
#		SC_ARGVAR_E1PORTS[SC_IDX]
#		SC_ARGVAR_E2PORTS[SC_IDX]
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_autodiscovery()
{
	typeset sponsornode=${1}
	typeset clustername=${2}

	typeset sctxt_title="$(gettext '
		>>> Autodiscovery of Cluster Transport <<<
	')"
	typeset sctxt_p1="$(gettext '
		If you are using Ethernet adapters as your cluster
		transport adapters, autodiscovery is the best method for
		configuring the cluster transport.
	')"
	typeset sctxt_alreadyrun_p1="$(gettext '
		However, it appears that scinstall has already been run
		at least once before on this machine.  You can either
		attempt to autodiscover or continue with the answers
		that you gave the last time you ran scinstall.
	')"
	typeset sctxt_configured_p1="$(gettext '
		This machine (\"%s\") is configured on \"%s\" as a
		cluster node.   Autodiscovery cannot be run.  Please
		refer to the user documentation for installation
		troubleshooting tips or procedures regarding the
		removal of a node from the cluster.
	')"
	sctxt_configured_p1="$(printf "${sctxt_configured_p1}" ${mynodename} ${sponsornode})"
	typeset sctxt_only1_p1="$(gettext '
		Probes were sent out from all transport adapters configured
		for cluster node \"%s\".   But, they were only received on
		one of the network adapters on this machine (\"%s\").  This
		may be due to any number of reasons, including improper
		cabling, an improper configuration for \"%s\", or a switch
		which was confused by the probes.
	')"
	sctxt_only1_p1="$(printf "${sctxt_only1_p1}" ${sponsornode} ${mynodename} ${sponsornode})"
	typeset sctxt_none_p1="$(gettext '
		Probes were sent out from all transport adapters
		configured for cluster node \"%s\".   But, none of
		those probes were received on any of the network
		adapters on this machine (\"%s\").  This may be due to
		any number of reasons, including improper cabling, an
		improper configuration for \"%s\", or a switch which
		was confused by the probes.
	')"
	sctxt_none_p1="$(printf "${sctxt_none_p1}" ${sponsornode} ${mynodename} ${sponsornode})"
	typeset sctxt_correction_p1="$(gettext '
		You can either attempt to correct the problem and try the
		probes again or try to manually configure the transport.
		Correcting the problem may involve re-cabling, changing
		the configuration for \"%s\", or fixing hardware.
	')"
	sctxt_correction_p1="$(printf "${sctxt_correction_p1}" ${sponsornode})"
	typeset sctxt_toomany_p1="$(gettext '
		More than two connections were discovered.   And, all of
		these connections could be added to the cluster
		transport configuration.   However, this form of
		scinstall currently supports only the configuration of
		the first two of these connections.   The others can be
		added later using scsetup(1M), or other tools.
	')"

	typeset prompt
	typeset answer
	typeset available_ladapters	# all available local adapters
	typeset allnet_radapters	# all remote network adapters
	typeset arg_adaptypes
	typeset node
	typeset nodes
	typeset radapters		# array - remote adapters in CCR config
	typeset ladapters		# array - local adaps matching radapters
	typeset switches		# array - switch matching radapters
	typeset radapterlist		# colon seperated list - send probe
	typeset ladapterlist		# colon seperated list - receive probe
	typeset foo
	typeset f1_node
	typeset f2_trtype
	typeset f3_adap
	typeset f4_switch
	typeset line
	typeset f1_ladap
	typeset f2_rhost
	typeset f3_radap
	typeset -l lnode
	typeset -l lsponsor
	typeset -l lmyname

	typeset token=suncluster_${clustername}

	integer result
	integer found
	integer nodecount
	integer adaptercount
	integer count
	integer i
	integer j

	integer -r recvto=20
	integer -r sendcount=15

	# Reset our glabal variable
	SC_DISCOVER_DOAUTO=

	# Make sure sponsor node is set
	if [[ -z "${sponsornode}" ]]; then
		return 0
	fi

	# Initialize lower case unqualified sponsor node name
	lsponsor=$(IFS=. ; set -- ${sponsornode}; echo $1)

	# Initialize my lower case unqualified node name
	lmyname=$(IFS=. ; set -- ${mynodename}; echo $1)

	# Print help
	clear
	sc_print_title "${sctxt_title}"
	sc_print_para "${sctxt_p1}"

	# Use autodiscovery?
	if [[ -n "${SC_ARGVAR_ADAPTERS[SC_IDX]}" ]]; then

		# Do they want to autodiscover even though there are defaults?
		sc_print_para "${sctxt_alreadyrun_p1}"
		prompt="$(gettext 'Do you want to use autodiscovery anyway?')"
		answer=$(sc_prompt_yesno "${prompt}" "${NO}") || return 1
		if [[ "${answer}" != "yes" ]]; then
			return 0
		fi
	else
		# Do they want to autodiscover?
		prompt="$(gettext 'Do you want to use autodiscovery?')"
		answer=$(sc_prompt_yesno "${prompt}" "${YES}") || return 1
		if [[ "${answer}" != "yes" ]]; then
			return 0
		fi
	fi

	# Set the list of known adaptertypes for use w/ scrconf
	arg_adaptypes=
	if [[ -n "${SC_DFLT_KNOWN_ETHERNET_ADAPTERS}" ]]; then
		arg_adaptypes=",adaptypes=$(new_separator : ${SC_DFLT_KNOWN_ETHERNET_ADAPTERS})"
	fi

	# Loop until done
	while true
	do
		# Get the list of available adapters on this machine
		available_ladapters="$(scrconf_static -n cmd=print_adapters_available${arg_adaptypes})"
		if [[ $? -ne 0 ]]; then
			printf "$(gettext 'Cannot get list of available adapters on \"%s\".')\n\n\a" "${mynodename}"
			sc_prompt_pause || return 1
			return 0
		fi

		# No available adapters
		if [[ -z "${available_ladapters}" ]]; then
			printf "$(gettext 'There are no available adapters on \"%s\".')\n\n\a" "${mynodename}"
			sc_prompt_pause || return 1
			return 0
		fi

		# Only one available adapter?
		let i=$(set -- ${available_ladapters};  echo $#)
		if [[ ${i} -eq 1 ]]; then
			printf "$(gettext '\"%s\" is the only available adapter on \"%s\".')\n\n\a" "${available_ladapters}" "${mynodename}"
			sc_prompt_pause || return 1
			return 0
		fi

		# Set ladapterlist
		ladapterlist="$(new_separator : ${available_ladapters})"

		# Try to contact sponsor, if not already done
		if [[ -z "${SC_DISCOVER_MADECONTACT}" ]]; then
			interactive_install_makecontact ${sponsornode} ${clustername}
			case $? in
			'0')	;;
			'1')	return 1 ;;
			'2')	return 0 ;;
			'3')	return 0 ;;
			esac
			return 1
		fi

		#
		# Get a copy of the transport config
		#
		allnet_radapters=
		scrconf_static -N "${sponsornode}" -n print_transport_config >${tmpfile}
		result=$?
		if [[ ${result} -eq 0 ]]; then
			allnet_radapters="$(scrconf_static -N "${sponsornode}" -n cmd=print_adapters${arg_adaptypes})"
			result=$?
		fi
		if [[ ${result} -ne 0 ]] || [[ -z "${allnet_radapters}" ]]; then
			printf "$(gettext 'Unable to get configuration data from \"%s\".')\n\n\a" "${sponsornode}"
			sc_prompt_pause || return 1
			return 0
		fi

		#
		# Parse the transport config
		#
		# The "nodes" array will contain a list of all the nodes.
		#
		# The "radapters" array will contain a list of all sponsornode
		# adapters.
		#
		# The "switches" array will contain the switches to which
		# the sponsornode adapters are cabled.
		#
		let i=0
		let j=0
		set -A nodes
		set -A radapters
		set -A switches
		radapterlist=
		while read f1_node f2_trtype f3_adap f4_switch
		do
			# Lower case unqualified sponsor node name
			lnode=$(IFS=. ; set -- ${f1_node}; echo $1)

			# Make sure each node in the "nodes" array is only
			# listed once.
			if [[ -z "${nodes[i]}" ]]; then
				nodes[i]=${f1_node}
			else
				let found=0
				for node in ${nodes[*]}
				do
					if [[ "${node}" == "${f1_node}" ]]; then
						let found=1
						break
					fi
				done
				if [[ ${found} -eq 0 ]]; then
					((i += 1))
					nodes[i]=${f1_node}
				fi
			fi

			# Make sure we are not already configured
			if [[ "${lnode}" == "${lmyname}" ]]; then
				rm -f ${tmpfile}
				printf "$(gettext '\"%s\" is already configured.')\n\n\a" "${mynodename}"
				sc_print_para "${sctxt_configured_p1}"
				sc_prompt_pause </dev/tty || return 1
				if [[ -z "${SC_DEBUG}" ]]; then
					return 1
				fi
			fi

			#
			# We are not really interested in anyone
			# other than the sponsor
			#
			if [[ "${lnode}" != "${lsponsor}" ]]; then
				continue
			fi

			# Make sure everything is dlpi
			if [[ "${f2_trtype}" != "dlpi" ]]; then
				rm -f ${tmpfile}
				printf "$(gettext 'Autodiscovery cannot be used with transport type \"%s\".')\n\n\a" "${f2_trtype}"
				sc_prompt_pause </dev/tty || return 1
				return 0
			fi

			# Make sure adapters is a known network adapter type
			let found=0
			for foo in ${allnet_radapters}
			do
				if [[ "${foo}" == "${f3_adap}" ]]; then
					let found=1
					break
				fi
			done
			if [[ ${found} -eq 0 ]]; then
				rm -f ${tmpfile}
				printf "$(gettext 'Autodiscovery can only be used with Ethernet adapter types.')\n"
				printf "$(gettext '\"%s\" appears to be configured with an unrecognized adapter.')\n\n\a" "${sponsornode}"
				sc_prompt_pause </dev/tty || return 1
				return 0
			fi

			# Add adapter to radapterlist and radapters array
			if [[ -z "${radapterlist}" ]]; then
				radapterlist=${f3_adap}
			else
				radapterlist=${radapterlist}:${f3_adap}
			fi
			radapters[j]=${f3_adap}

			#
			# Make sure there is no mixture of switches and
			# direct-connect crossover cables.
			#
			if [[ -z "${f4_switch}" ]]; then
				f4_switch="-"
			fi
			if [[ ${j} -gt 0 ]] &&
			    [[ "${switches[0]}" == "-" ]] &&
			    [[ "${f4_switch}" != "-" ]]; then
				rm -f ${tmpfile}
				printf "$(gettext 'Autodiscovery cannot be used with a mixture of direct-connect and switches.')\n\n\a"
				sc_prompt_pause </dev/tty || return 1
				return 0
			fi

			# Add switch to switchs array
			switches[j]=${f4_switch}

			# Next
			((j += 1))
		
		done <${tmpfile}
		rm -f ${tmpfile}
		let nodecount=$((i + 1))
		let adaptercount=${j}

		# Start message with dots
		echo
		(
			integer dotcount=$((recvto + 10))

			sc_print_line "$(gettext 'Probing ')"
			while [[ ${dotcount} -gt 0 ]]
			do
				echo ".\c"
				sleep 1
				((dotcount -= 1))
			done
			echo
			return 0
		) &

		# Start the probes from the other machine as a background job
		(
			integer loopcount=$(((recvto / sendcount) + 1))

			# Give the receiver some time to initialize
			sleep 3

			# Tell rpc.scadmd to send us packets every second
			while [[ ${loopcount} -gt 0 ]]
			do
				#
				# Don't make the sendcount too high!
				# Packets are sent at 1 second intervals, and
				# rpc.scadmd is not multi-threaded.
				#
				scrconf_static -N ${sponsornode} -n cmd=discover_send,adapters=${radapterlist},token=${token},sendcount=${sendcount} >/dev/null
				if [[ $? -ne 0 ]]; then
					return 1
				fi
				((loopcount -= 1))
			done
			return 0
		) &

		# Look for incoming probes on this machine
		scrconf_static -n cmd=discover_receive,adapters=${ladapterlist},token=${token},recvto=${recvto},nowait,waitcount=${adaptercount} >${tmpfile}
		result=$?

		# Stop the background processes, and finish up with a ping
		kill %- 2>/dev/null
		kill %% 2>/dev/null
		sleep 1
		scrconf_static -N ${sponsornode} -n broadcast_ping
		echo
		echo

		# Parse output
		let count=0
		set -A ladapters
		while read line
		do 
			# Get the three expected fields
			line="$(IFS=: ; set -- ${line}; echo $*)"
			echo ${line} | read f1_ladap f2_rhost f3_radap

			# Skip "quit" or other junk
			if [[ -z "${f2_rhost}" ]]; then
				continue
			fi

			# Find the remote and local adapters
			let j=0
			while [[ ${j} -lt ${adaptercount} ]]
			do
				if [[ "${radapters[j]}" == "${f3_radap}" ]] &&
				    [[ -z "${ladapters[j]}" ]]; then
					ladapters[j]=$f1_ladap
					((count += 1))
					break
				fi
				((j += 1))
			done
		done <${tmpfile}
		rm -f ${tmpfile}

		if [[ ${count} -gt 0 ]]; then
			# List connection(s)
			if [[ ${count} -eq 1 ]]; then
				sc_print_para "$(gettext 'The following connection was discovered:')"
			else
				sc_print_para "$(gettext 'The following connections were discovered:')"
			fi
			let j=0
			while [[ ${j} -lt ${adaptercount} ]]
			do
				if [[ -z "${ladapters[j]}" ]]; then
					((j += 1))
					continue
				fi
				printf "\t%s:%s  %s  %s:%s\n" \
				    "${sponsornode}" \
				    "${radapters[j]}" \
				    "${switches[j]}" \
				    "${mynodename}" \
				    "${ladapters[j]}"
				((j += 1))
			done
			echo
		fi
		case ${count} in
		0)	# no probes received
			sc_print_para "${sctxt_none_p1}"
			sc_print_para "${sctxt_correction_p1}"
			prompt="$(gettext 'Do you want to try again?')"
			answer=$(sc_prompt_yesno "${prompt}" "${YES}") || return 1
			if [[ "${answer}" != "yes" ]]; then
				return 0
			fi
			continue
			;;

		1)	# only one received
			sc_print_para "${sctxt_only1_p1}"
			sc_print_para "${sctxt_correction_p1}"
			prompt="$(gettext 'Do you want to try again?')"
			answer=$(sc_prompt_yesno "${prompt}" "${YES}") || return 1
			if [[ "${answer}" != "yes" ]]; then
				return 0
			fi
			continue
			;;

		*)	# two or more received
			if [[ ${count} -gt 2 ]]; then
				sc_print_para "${sctxt_toomany_p1}"
				prompt="$(gettext 'Is it okay to configure the first two connections?')"
			else
				prompt="$(gettext 'Is it okay to add these connections to the configuration?')"
			fi

			answer=$(sc_prompt_yesno "${prompt}" "${YES}") || return 1
			if [[ "${answer}" != "yes" ]]; then
				prompt="$(gettext 'Do you want to retry the autodiscovery probes?')"
				answer=$(sc_prompt_yesno "${prompt}" "${NO}") || return 1
				if [[ "${answer}" == "yes" ]]; then
					continue
				fi
			fi
			if [[ "${answer}" != "yes" ]]; then
				prompt="$(gettext 'Do you want to return to the main menu?')"
				answer=$(sc_prompt_yesno "${prompt}" "${YES}") || return 1
				if [[ "${answer}" != "yes" ]]; then
					return 0
				else
					return 1
				fi
			fi
			SC_DISCOVER_DOAUTO=${SC_TRUE}
			;;

		esac
		if [[ -n "${SC_DISCOVER_DOAUTO}" ]]; then
			break
		fi
	done

	#
	# Set SC_ARGVARs
	#

	# SC_ARGVAR_DIRECT
	if [[ "${switches[0]}" == "-" ]]; then
		SC_ARGVAR_TWONODES=1
		SC_ARGVAR_DIRECT=1
	else
		SC_ARGVAR_DIRECT=0
	fi

	# SC_ARGVAR_ETHERADAP is always yes
	SC_ARGVAR_ETHERADAP[SC_IDX]=1

	# SC_ARGVAR_JUNCTYPES are always switch
	SC_ARGVAR_JUNCTYPES[SC_IDX]="switch switch"

	# SC_ARGVAR_TRTYPES are always dlpi
	SC_ARGVAR_TRTYPES[SC_IDX]="dlpi dlpi"

	# SC_ARGVAR_E1PORTS and SC_ARGVAR_E1PORTS are always default
	SC_ARGVAR_E1PORTS[SC_IDX]="@ @"
	SC_ARGVAR_E2PORTS[SC_IDX]="@ @"

	# SC_ARGVAR_ADAPTERS and SC_ARGVAR_JUNCTIONS and SC_ARGVAR_E2CABLES
	SC_ARGVAR_ADAPTERS[SC_IDX]=
	SC_ARGVAR_JUNCTIONS[SC_IDX]=
	SC_ARGVAR_E2CABLES[SC_IDX]=
	let i=0
	let j=0
	while [[ ${i} -lt 2 ]] && [[ ${j} -lt ${adaptercount} ]]
	do
		if [[ -n "${ladapters[j]}" ]]; then
			SC_ARGVAR_ADAPTERS[SC_IDX]="${SC_ARGVAR_ADAPTERS[SC_IDX]} ${ladapters[j]}"
			if [[ "${SC_ARGVAR_DIRECT}" == 1 ]]; then
				SC_ARGVAR_E2CABLES[SC_IDX]="${SC_ARGVAR_E2CABLES[SC_IDX]} ${sponsornode}:${radapters[j]}"
			else
				SC_ARGVAR_JUNCTIONS[SC_IDX]="${SC_ARGVAR_JUNCTIONS[SC_IDX]} ${switches[j]}"
				SC_ARGVAR_E2CABLES[SC_IDX]="${SC_ARGVAR_E2CABLES[SC_IDX]} ${switches[j]}"
			fi
			((i += 1))
		fi
		((j += 1))
	done

	# Get rid of any leading spaces
	SC_ARGVAR_ADAPTERS[SC_IDX]="$(echo ${SC_ARGVAR_ADAPTERS[SC_IDX]})"
	SC_ARGVAR_JUNCTIONS[SC_IDX]="$(echo ${SC_ARGVAR_JUNCTIONS[SC_IDX]})"
	SC_ARGVAR_E2CABLES[SC_IDX]="$(echo ${SC_ARGVAR_E2CABLES[SC_IDX]})"

	# Add variables
	argvar_append_tofile_directconnect ${SC_ILOG}
	argvar_append_tofile_junctions "${SC_IDX}" ${SC_ILOG}
	argvar_append_tofile_adapters "${SC_IDX}" ${SC_ILOG}
	argvar_append_tofile_etheradap "${SC_IDX}" ${SC_ILOG}
	argvar_append_tofile_trtypes "${SC_IDX}" ${SC_ILOG}
	argvar_append_tofile_cables "${SC_IDX}" ${SC_ILOG}
	argvar_append_tofile_ports "${SC_IDX}" ${SC_ILOG}

	return 0
}

####################################################
#
# interactive_install_autodiscovery_centralized() clustername
#
#	Auto discovery for Ethernet.
#
#	This version of interactive_install_autodiscover is used
#	with centralized install when SC_DISCOVER_DOAUTO is set.
#
#	The following SC_ARGVAR variables may be set/reset
#	by this function:
#
#		SC_ARGVAR_ADAPTERS[*]
#		SC_ARGVAR_JUNCTIONS[*]
#		SC_ARGVAR_JUNCTYPES[*]
#		SC_ARGVAR_ETHERADAP[*]
#		SC_ARGVAR_TRTYPES[*]
#		SC_ARGVAR_E2CABLES[*]
#		SC_ARGVAR_E1PORTS[*]
#		SC_ARGVAR_E2PORTS[*]
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_autodiscovery_centralized()
{
	typeset clustername=${1}

	typeset sctxt_none_p1="$(gettext '
		Probes were sent out from all transport adapters
		configured for this node (\"%s\").  But, they were not
		seen by any of the other nodes.  This may be due to any
		number of reasons, including improper cabling or a
		switch which was confused by the probes.
	')"
	sctxt_none_p1="$(printf "${sctxt_none_p1}" ${sponsornode} ${mynodename} ${sponsornode})"
	typeset sctxt_notenough_p1="$(gettext '
		Probes were sent out from all transport adapters
		configured for this node (\"%s\").  But, they were not
		seen by all of the other nodes.  This may be due to any
		number of reasons, including improper cabling or a
		switch which was confused by the probes.
	')"
	sctxt_notenough_p1="$(printf "${sctxt_notenough_p1}" ${mynodename})"
	typeset sctxt_correction_p1="$(gettext '
		You can either attempt to correct the problem and try the
		probes again or try to manually configure the transport.
		Correcting the problem may involve re-cabling, changing
		the configuration, or fixing hardware.
	')"
	typeset sctxt_toomany_p1="$(gettext '
		More than two connections were discovered.   And, all of
		these connections could be added to the cluster
		transport configuration.   However, this form of
		scinstall currently supports only the configuration of
		the first two of these connections.   The others can be
		added later using scsetup(1M), or other tools.
	')"

	typeset -r token=suncluster_${clustername}
	integer -r adaptercount=2
	integer -r recvto=30
	integer -r sendcount=30

	# each of the following is an array of matching known data
	typeset configured_ladapters	# array of local transport adapters
	typeset configured_switches	# array of local matching switches

	# each of following is an array of matching discovered data
	typeset switches		# switches
	typeset ladapters		# local adapters
	typeset rnodes			# remote nodes
	typeset radapters		# remoteadapters

	integer i
	integer j
	integer k
	integer first
	integer flag
	integer count
	integer sendpid

	typeset answer
	typeset prompt
	typeset msg
	typeset pid
	typeset pids
	typeset node
	typeset nodes
	typeset counts
	typeset cmd
	typeset line
	typeset f1_ladap
	typeset f2_rhost
	typeset f3_radap
	typeset -l lrhost
	typeset -l lmyname

	# Make sure that autodiscovery is set
	if [[ -z "${SC_DISCOVER_DOAUTO}" ]]; then
		return 0
	fi

	# Set the lists of adapters and switches configured for this machine
	set -A configured_ladapters ${SC_ARGVAR_ADAPTERS[0]}
	if [[ "${SC_ARGVAR_DIRECT}" == 1 ]]; then
		set -A configured_switches"- -"
	else
		if [[ -n "${SC_ARGVAR_E2CABLES[0]}" ]]; then
			set -A configured_switches ${SC_ARGVAR_E2CABLES[0]}
		else
			set -A configured_switches ${SC_ARGVAR_JUNCTIONS[0]}
		fi
	fi

	# Initialize my lower case unqualified node name
	lmyname=$(IFS=. ; set -- ${mynodename}; echo $1)

	# Set ladapterlist
	ladapterlist="$(new_separator : ${configured_ladapters[*]})"

	# Print message
	sc_print_para "$(gettext 'Starting discovery of the cluster transport configuration.')" | logmsg

	# Loop until done
	let first=1
	while true
	do
		# Blank line?
		if [[ ${first} -eq 1 ]]; then
			let first=0
		else
			echo
		fi

		# Start looking for probes from the other machines
		pids=
		nodes=
		for node in ${SC_ARGVAR_NODENAME[*]}
		do
			# if this node, skip
			if [[ "${mynodename}" == "${node}" ]]; then
				continue
			fi

			#
			# Do receive
			#
			(
				# Use temporary install log
				install_log=${install_log}.${node}
				rm -f ${install_log}   

				# Use special tmp file
				tmpfile=${tmpfile}.${node}
				rm -f ${tmpfile}

				# Start the autodiscovery command
				interactive_install_cmd ${node} "autodiscovery ${token} ${adaptercount} ${recvto}" >${tmpfile}
				return $?
			) &
			pids="${pids} $!"
			nodes="${nodes} ${node}"
		done
        	set -A nodes ${nodes}

		# Start sending probes from this machine
		(
			# Use temporary install log
			install_log=${install_log}.${mynodename}
			rm -f ${install_log}   

			cmd="scrconf -n cmd=discover_send,adapters=${ladapterlist},token=${token},sendcount=${sendcount}"
			echo "${cmd}" >>${install_log}
			exec ${cmd} >/dev/null 2>>${install_log}
		) &
		let sendpid=$!

		# Wait for each receive process to finish
		let i=0
        	for pid in ${pids}
        	do
                	node=${nodes[i]}
                	wait ${pid}
                	result=$?
			if [[ ${result} -ne 0 ]]; then
				printf "$(gettext 'Remote command failed to \"%s\".')\n\n" "${node}" >>${install_log}
			fi

			# Next
			((i += 1))
		done

		# Kill the send process
		kill -1 ${sendpid} >/dev/null 2>&1

		# Finish up with a ping
		sleep 2
		scrconf -n broadcast_ping

		# Clean up log files
		interactive_cleanup_logfiles "${install_log}" "1" ${SC_ARGVAR_NODENAME[*]}

		# Parse output for each node, initializing our set of arrays
		set -A counts		# aligns with $nodes
		set -A switches
		set -A ladapters
		set -A rnodes
		set -A radapters
		let i=0
		for node in ${nodes[*]}
		do
			let count=0

			# Make sure that there is a tmpfile
			if [[ ! -s ${tmpfile}.${node} ]]; then
				printf "$(gettext 'No autodiscovery results returned from node \"%s\".')\n\n" "${node}" >>${install_log}
				rm -f ${tmpfile}.${node}
				counts="${counts} ${count}"
				continue
			fi

			# Read the file for this node
			while read line
			do
				# Get the three expected fields
				line="$(IFS=: ; set -- ${line}; echo $*)"
				echo ${line} | read f1_ladap f2_rhost f3_radap

				# Skip "quit" or other junk
				if [[ -z "${f2_rhost}" ]]; then
					continue
				fi

				# We are the only one expected to send probes
				lrhost=$(IFS=. ; set -- ${f2_rhost}; echo $1)
				if [[ "${lrhost}" != "${lmyname}" ]]; then
					printf "$(gettext '\"%s\" found an expected probe from \"%s\".')\n\n" "${node}" "${f2_rhost}" >>${install_log}
					continue
				fi

				#
				# From the perspective of the remote node,
				# out local adapters are it's remote
				# adapters.   So, look for its remote
				# adapters in our local list.
				#
				let j=0
				while [[ -n "${configured_ladapters[j]}" ]]
				do
					if [[ "${f3_radap}" == "${configured_ladapters[j]}" ]]; then
						switches[i]="${configured_switches[j]}"
						break
					fi
					((j += 1))
				done
				if [[ -z "${switches[i]}" ]]; then
					printf "$(gettext '\"%s\" probe returned \"-- %s --\" which does not match any of the adapters on \"%s\".')\n\n" "${node}" "${line}" "${mynodename}" >>${install_log}
					continue
				fi

				# initialize the rest of our array variables
				ladapters[i]=${f3_radap}
				rnodes[i]=${node}
				radapters[i]=${f1_ladap}

				# Next
				((count += 1))
				((i += 1))
			done <${tmpfile}.${node}

			# Add the count for this node to the list of counts
			counts="${counts} ${count}"

			# Remove the tmpfile
			rm -f ${tmpfile}.${node}
		done
		set -A counts ${counts}

		# Print connections, grouped by switch
		if [[ -n "${ladapters[0]}" ]]; then

			# List connection(s)
			if [[ -z "${ladapters[1]}" ]]; then
				sc_print_para "$(gettext 'The following connection was discovered:')" | logmsg
			else
				sc_print_para "$(gettext 'The following connections were discovered:')" | logmsg
			fi
			let i=0
			while [[ -n "${configured_switches[i]}" ]]
			do
				let j=0
				while [[ -n "${ladapters[j]}" ]]
				do
					if [[ "${configured_switches[i]}" != "${switches[j]}" ]]; then
						((j += 1))
						continue
					fi

					printf "\t%s:%s  %s  %s:%s\n" \
					    "${mynodename}" \
					    "${ladapters[j]}" \
					    "${switches[j]}" \
					    "${rnodes[j]}" \
					    "${radapters[j]}" | logmsg
					((j += 1))
				done
				((i += 1))
			done
			echo | logmsg
		fi

		#
		# Set the flag as follows:
		#
		#	0 - two connections for each node
		#	1 - no connections discovered
		#	2 - not enough connections
		#	3 - more than enough connections
		#
		let flag=0
		if [[ -z "${ladapters[0]}" ]]; then
			let flag=1

		else
			let i=0
			for node in ${nodes[*]}
			do
				let count=${counts[i]}
				case ${count} in
				0)    # no connections
					printf "$(gettext 'No connections were found for \"%s\".')\n\n" "${node}" >>${install_log}
					let flag=1
					;;

				1)    # not enough connections
					printf "$(gettext 'Only one connection was found for \"%s\".')\n\n" "${node}" >>${install_log}
					let flag=2
					;;

				2)    # just right
					;;

				*)    # too many connections
					printf "$(gettext '%d connections were found for \"%s\".')\n\n" "${count}" "${node}" >>${install_log}
					if [[ ${flag} -eq 0 ]]; then
						let flag=3
					fi
					;;
				esac

				# Next
				((i += 1))
			done
		fi

		# If errors, print message to try again
		case ${flag} in
		1|2)  # not enough connections
			if [[ ${flag} -eq 1 ]]; then
				msg="${sctxt_none_p1}"
			else
				msg="${sctxt_notenough_p1}"
			fi
			sc_print_para "${msg}" | logmsg
			sc_print_para "${sctxt_correction_p1}" | logmsg
			prompt="$(gettext 'Do you want to try again?')"
			answer=$(sc_prompt_yesno "${prompt}" "${YES}") || return 1
			if [[ "${answer}" != "yes" ]]; then
				return 1
			fi
			continue
			;;

		3)    # too many
			sc_print_para "${sctxt_toomany_p1}" | logmsg
			prompt="$(gettext 'Is it okay to continue using just the first two?')"
			answer=$(sc_prompt_yesno "${prompt}" "${YES}") || return 1
			if [[ "${answer}" != "yes" ]]; then
				prompt="$(gettext 'Do you want to retry the autodiscovery probes?')"
				answer=$(sc_prompt_yesno "${prompt}" "${NO}") || return 1
				if [[ "${answer}" == "yes" ]]; then
					continue
				fi
				return 1
			fi
			;;
		esac

		# Done
		break
	done

	# Print message
	sc_print_para "$(gettext 'Completed discovery of the cluster transport configuration.')" | logmsg

	#
	# Set SC_ARGVARs
	#

	let i=0
	for node in ${SC_ARGVAR_NODENAME[*]}
	do
		# if this node, skip
		if [[ "${mynodename}" == "${node}" ]]; then
			((i += 1))
			continue
		fi

		# SC_ARGVAR_ETHERADAP is always yes
		SC_ARGVAR_ETHERADAP[i]=1

		# SC_ARGVAR_JUNCTYPES are always switch
		SC_ARGVAR_JUNCTYPES[i]="switch switch"

		# SC_ARGVAR_TRTYPES are always dlpi
		SC_ARGVAR_TRTYPES[i]="dlpi dlpi"

		# SC_ARGVAR_E1PORTS and SC_ARGVAR_E1PORTS are always default
		SC_ARGVAR_E1PORTS[i]="@ @"
		SC_ARGVAR_E2PORTS[i]="@ @"

		# SC_ARGVAR_ADAPTERS, SC_ARGVAR_JUNCTIONS, SC_ARGVAR_E2CABLES
		SC_ARGVAR_ADAPTERS[i]=
		SC_ARGVAR_JUNCTIONS[i]=
		SC_ARGVAR_E2CABLES[i]=
		let j=0			# discovery array table index
		let k=0			# drop anything more than two
		while [[ ${k} -lt 2 ]] && [[ -n "${ladapters[j]}" ]]
		do
			if [[ "${rnodes[j]}" != "${node}" ]]; then
				((j += 1))
				continue
			fi
			((k += 1))

			SC_ARGVAR_ADAPTERS[i]="${SC_ARGVAR_ADAPTERS[i]} ${radapters[j]}"

			if [[ "${SC_ARGVAR_DIRECT}" == 1 ]]; then
				SC_ARGVAR_E2CABLES[i]="${SC_ARGVAR_E2CABLES[i]} ${mynodename}:${ladapters[j]}"
			else
				SC_ARGVAR_JUNCTIONS[i]="${SC_ARGVAR_JUNCTIONS[i]} ${switches[j]}"
				SC_ARGVAR_E2CABLES[i]="${SC_ARGVAR_E2CABLES[i]} ${switches[j]}"
			fi
			((j += 1))
		done

		# Get rid of any leading spaces
		SC_ARGVAR_ADAPTERS[i]="$(echo ${SC_ARGVAR_ADAPTERS[i]})"
		SC_ARGVAR_JUNCTIONS[i]="$(echo ${SC_ARGVAR_JUNCTIONS[i]})"
		SC_ARGVAR_E2CABLES[i]="$(echo ${SC_ARGVAR_E2CABLES[i]})"

		# Add variables
		argvar_append_tofile_directconnect ${SC_ILOG}
		argvar_append_tofile_junctions "${i}" ${SC_ILOG}
		argvar_append_tofile_adapters "${i}" ${SC_ILOG}
		argvar_append_tofile_etheradap "${i}" ${SC_ILOG}
		argvar_append_tofile_trtypes "${i}" ${SC_ILOG}
		argvar_append_tofile_cables "${i}" ${SC_ILOG}
		argvar_append_tofile_ports "${i}" ${SC_ILOG}

		# Next
		((i += 1))
	done

	return 0
}

####################################################
#
# interactive_install_netaddr() iflag
#
#	Set SC_ARGVAR_NETADDR and SC_ARGVAR_NETMASK,
#	then add to the response log.
#
#	iflag 1		- establish new cluster w/ this machine
#	iflag 3		- custom JumpStart client set up
#	iflag 4		- centralized install
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_netaddr()
{
	integer iflag=${1}

	typeset sctxt_title="$(gettext '
		>>> Network Address for the Cluster Transport <<<
	')"
	typeset sctxt_p1="$(gettext '
		The private cluster transport uses a default network
		address of 172.16.0.0.  But, if this network address is
		already in use elsewhere within your enterprise, you
		may need to select another address from the range of
		recommended private addresses (see RFC 1597 for
		details).
	')"
	typeset sctxt_p2="$(gettext '
		If you do select another network address, bear
		in mind that the Sun Cluster software requires
		that the rightmost two octets always be zero.
	')"
	typeset sctxt_p3="$(gettext '
		The default netmask is 255.255.0.0.  You can select
		another netmask, as long as it minimally masks all bits
		given in the network address.
	')"

	typeset dflt_answer
	typeset answer
	typeset foo

	#
	# Print help and check iflag
	#
	case ${iflag} in
	'1' | '3' | '4')
		if [[ ${SC_TYPICAL_INSTALL} -ne 1 ]]; then
			clear
			sc_print_title "${sctxt_title}"
			sc_print_para "${sctxt_p1}"
			sc_print_para "${sctxt_p2}"
			sc_print_para "${sctxt_p3}"
		fi
		;;

	*)    # invalid argument
		return 1
		;;
	esac

	# Netaddr
	while [[ ${SC_TYPICAL_INSTALL} -ne 1 ]]
	do
		# set default answer - yes or no
		if [[ -n "${SC_ARGVAR_NETADDR}" ]] &&
		    [[ "${SC_ARGVAR_NETADDR}" != "${SC_DFLT_NETADDR}" ]]; then
			dflt_answer="${NO}"
		else
			dflt_answer="${YES}"
		fi

		# Prompt user and get yes or no response
		answer=$(sc_prompt_yesno "$(gettext 'Is it okay to accept the default network address?')" "${dflt_answer}") || return 1
		if [[ "${answer}" = "yes" ]]; then
			SC_ARGVAR_NETADDR=${SC_DFLT_NETADDR}
		else
			# Get the netaddr
			answer=$(sc_prompt "$(gettext 'What network address do you want to use?')" "${SC_ARGVAR_NETADDR}") || return 1

			#
			# If network name is not used, check IP
			# Additional checking is done in scrconf
			#
			if [[ "${answer}" = [0-9]* ]]; then
				set -A foo $(echo "${answer}" | sed -n 's/\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.0*\.0*/\1 \2/p')
				if [[ -z "${foo[0]}" ]] ||
			  	  [[ ${foo[0]} -lt 1 ]] ||
			  	  [[ ${foo[0]} -gt 255 ]]; then
					printf "$(gettext 'Invalid network address.')\n\n\a"
					continue
				fi
				if [[ -z "${foo[1]}" ]] ||
			  	  [[ ${foo[1]} -gt 255 ]]; then
					printf "$(gettext 'Invalid network address.')\n\n\a"
					continue
				fi
			fi

			# Set netaddr
			SC_ARGVAR_NETADDR="${answer}"
		fi

		# Done
		break
	done
	if [[ ${SC_TYPICAL_INSTALL} -eq 1 ]]; then
		SC_ARGVAR_NETADDR=${SC_DFLT_NETADDR}
	fi

	# Netmask
	while [[ ${SC_TYPICAL_INSTALL} -ne 1 ]]
	do
		# set default answer - yes or no
		if [[ -n "${SC_ARGVAR_NETMASK}" ]] &&
		    [[ "${SC_ARGVAR_NETMASK}" != "${SC_DFLT_NETMASK}" ]]; then
			dflt_answer="${NO}"
		else
			dflt_answer="${YES}"
		fi

		# Prompt user and get yes or no response
		answer=$(sc_prompt_yesno "$(gettext 'Is it okay to accept the default netmask?')" "${dflt_answer}") || return 1
		if [[ "${answer}" = "yes" ]]; then
			SC_ARGVAR_NETMASK=${SC_DFLT_NETMASK}
		else
			# Get the netmask
			answer=$(sc_prompt "$(gettext 'What netmask do you want to use?')" "${SC_ARGVAR_NETMASK}") || return 1

			#
			# Check IP
			# Additional checking is done in scrconf
			#
			set -A foo $(echo "${answer}" | sed -n 's/\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.0*\.0*/\1 \2/p')
			if [[ -z "${foo[0]}" ]] ||
			    [[ ${foo[0]} -lt 1 ]] ||
			    [[ ${foo[0]} -gt 255 ]]; then
				printf "$(gettext 'Invalid netmask.')\n\n\a"
				continue
			fi
			if [[ -z "${foo[1]}" ]] ||
			    [[ ${foo[0]} -lt 1 ]] ||
			    [[ ${foo[1]} -gt 255 ]]; then
				printf "$(gettext 'Invalid network address.')\n\n\a"
				continue
			fi

			# Set netmask
			SC_ARGVAR_NETMASK="${answer}"
		fi

		# Done
		break
	done
	if [[ ${SC_TYPICAL_INSTALL} -eq 1 ]]; then
		SC_ARGVAR_NETMASK=${SC_DFLT_NETMASK}
	fi

	# append SC_ARGVAR_NETADDR and SC_ARGVAR_NETMASK to response log
	argvar_append_tofile_netaddr ${SC_ILOG}

	return 0
}

####################################################
#
# interactive_install_directconnect() iflag
#
#	Set SC_ARGVAR_TWONODES and SC_ARGVAR_DIRECT,
#	then add to the response log.
#
#	SC_ARGVAR_TWONODES - set to 1 if two-node cluster;  otherwise, 0
#	SC_ARGVAR_DIRECT   - set to 1 if direct connect;  otherwise, 0
#
#	If this is a two node cluster, SC_OTHERNODE
#	is also set.
#
#	iflag 1		- establish new cluster w/ this machine
#	iflag 2		- add this machine to an established cluster
#	iflag 3		- custom JumpStart client set up
#	iflag 4		- centralized install
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_directconnect()
{
	integer iflag=${1}

	typeset sctxt_title="$(gettext '
		>>> Point-to-Point Cables <<<
	')"
	typeset sctxt_p1="$(gettext '
		The two nodes of a two-node cluster may use a
		directly-connected interconnect.  That is, no cluster
		transport junctions are configured.  However, when
		there are greater than two nodes, this interactive form
		of scinstall assumes that there will be exactly two
		cluster transport junctions.
	')"
	typeset sctxt_p2="$(gettext '
		Since this is not a two-node cluster, you will be asked to
		configure two transport junctions.
	')"

	integer numnodes
	typeset nodename
	typeset answer
	typeset dflt_answer

	#
	# Print help and check iflag
	#
	case ${iflag} in
	'1' | '2' | '3' | '4')
		if [[ ${SC_TYPICAL_INSTALL} -ne 1 ]]; then
			clear
			sc_print_title "${sctxt_title}"
			sc_print_para "${sctxt_p1}"
		fi
		;;

	*)    # invalid argument
		return 1
		;;
	esac

	# If SC_ARGVAR_AUTHLIST is set, determine number of nodes from that
	if [[ -n "${SC_ARGVAR_AUTHLIST}" ]]; then
		let numnodes=$(set -- ${SC_ARGVAR_AUTHLIST}; echo $#)
		if [[ ${numnodes} -eq 2 ]]; then
			SC_ARGVAR_TWONODES=1
			for nodename in ${SC_ARGVAR_AUTHLIST}
			do
				if [[ "${nodename}" != "${SC_ARGVAR_NODENAME[SC_IDX]}" ]]; then
					SC_OTHERNODE=${nodename}
					break
				fi
			done
		else
			SC_ARGVAR_TWONODES=0
			SC_OTHERNODE=
		fi

	# Otherwise, if SC_TYPICAL_INSTALL, use defaults
	elif [[ ${SC_TYPICAL_INSTALL} -eq 1 ]]; then
		SC_ARGVAR_TWONODES=0
		SC_OTHERNODE=

	# Otherwise, ask the user if this is a two node cluster
	else
		# Set the default answer
		if [[ -n "${SC_ARGVAR_TWONODES}" ]]; then
			if [[ ${SC_ARGVAR_TWONODES} -eq 1 ]]; then
				dflt_answer="${YES}"
			else
				dflt_answer="${NO}"
			fi
		else
			dflt_answer="${YES}"
		fi

		# Prompt the user and get the response
		answer=$(sc_prompt_yesno "$(gettext 'Is this a two-node cluster?')" "${dflt_answer}") || return 1

		# Set SC_ARGVAR_TWONODES
		if [[ "${answer}" = "yes" ]]; then
			SC_ARGVAR_TWONODES=1

			# If adding a node, the sponsor node is the other node
			if [[ ${iflag} -eq 2 ]]; then
				SC_OTHERNODE=${SC_ARGVAR_SPONSORNODE[SC_IDX]}
			else
				SC_OTHERNODE=
			fi

			# Otherwise, prompt the user for the other node
			while [[ -z "${SC_OTHERNODE}" ]]
			do
				# Get the name of the other node
				answer=$(sc_prompt "$(gettext 'What is the name of the other node in the cluster?')") || return 1

				# Make sure it is not this nodename
				if [[ "${answer}" = "${SC_ARGVAR_NODENAME[SC_IDX]}" ]]; then
					printf "$(gettext 'That is the name of this node.')\n\n\a"
					continue
				fi

				# node name must begin with alpha
				# and may not include : or @
				if [[ "${answer}" = [!a-zA-Z]* ]] ||
				    [[ "${answer}" = *[@:]* ]]; then
					printf "$(gettext 'Invalid node name.')\n\n\a"
					continue
				fi

				# node name must be <= 256 characters
				if [[ ${#answer} -gt 256 ]]; then
					printf "$(gettext 'Node name is too long.')\n\n\a"
					continue
				fi

				# Set SC_OTHERNODE
				SC_OTHERNODE=${answer}
			done
		else
			SC_ARGVAR_TWONODES=0
			SC_OTHERNODE=
		fi
	fi

	# If this is a typical install, use defaults
	if [[ ${SC_TYPICAL_INSTALL} -eq 1 ]]; then
		SC_ARGVAR_DIRECT=0

	# Otherwise, prompt
	else

		# If this is not a two node cluster, set SC_ARGVAR_DIRECT to 0
		if [[ ${SC_ARGVAR_TWONODES} -ne 1 ]]; then
			# Set SC_ARGVAR_DIRECT
			SC_ARGVAR_DIRECT=0

			# Print additional help
			sc_print_para "${sctxt_p2}"

			# Pause until they press Enter
			sc_prompt_pause || return 1

		# Otherwise, if two node, ask the user if it is direct connect
		else
			# Set the default answer
			if [[ -n "${SC_ARGVAR_DIRECT}" ]]; then
				if [[ ${SC_ARGVAR_DIRECT} -eq 0 ]]; then
					dflt_answer="${YES}"
				else
					dflt_answer="${NO}"
				fi
			else
				dflt_answer="${YES}"
			fi

			# Prompt the user and get the response
			answer=$(sc_prompt_yesno "$(gettext 'Does this two-node cluster use transport junctions?')" "${dflt_answer}") || return 1

			# Set SC_ARGVAR_DIRECT
			if [[ "${answer}" = "yes" ]]; then
				SC_ARGVAR_DIRECT=0
			else
				SC_ARGVAR_DIRECT=1
			fi
		fi
	fi

	# append SC_ARGVAR_TWONODES and SC_ARGVAR_DIRECT to response log
	argvar_append_tofile_directconnect ${SC_ILOG}

	return 0
}

####################################################
#
# interactive_install_junctions() iflag
#
#	Set SC_ARGVAR_JUNCTIONS for this node to
#	the list of junctions to which it is connected.
#	Then, add it to the response log.
#
#	iflag 1		- establish new cluster w/ this machine
#	iflag 2		- add this machine to an established cluster
#	iflag 3		- custom JumpStart client set up
#	iflag 4		- centralized install
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_junctions()
{
	integer iflag=${1}

	typeset sctxt_title="$(gettext '
		>>> Cluster Transport Junctions <<<
	')"
	typeset sctxt_p1="$(gettext '
		All cluster transport adapters in this cluster must
		be cabled to a transport junction, or \"switch\".
		And, each adapter on a given node must be cabled to a
		different junction.  Interactive scinstall requires that
		you identify two switches for use in the cluster and
		the two transport adapters on each node to which they
		are cabled.
	')"
	typeset sctxt_prompt[0]="$(gettext '
		What is the name of the first junction in the cluster?')"
	typeset sctxt_prompt[1]="$(gettext '
		What is the name of the second junction in the cluster?')"

	typeset answer
	typeset junction
	typeset dflt_juncs
	typeset indices

	integer i

	#
	# Print help and check iflag
	#
	case ${iflag} in
	'1' | '2' | '3' | '4')
		if [[ ${SC_TYPICAL_INSTALL} -ne 1 ]]; then
			clear
			sc_print_title "${sctxt_title}"
			sc_print_para "${sctxt_p1}"
		fi
		;;

	*)    # invalid argument
		return 1
		;;
	esac

	# Junction types are fixed in this release
	SC_ARGVAR_JUNCTYPES[SC_IDX]="${SC_DFLT_JUNCTION_TYPE} ${SC_DFLT_JUNCTION_TYPE}"

	# If custom mode, prompt user and get response
	if [[ ${SC_TYPICAL_INSTALL} -ne 1 ]]; then

		# Initialize the defaults
		set -A dflt_juncs ${SC_ARGVAR_JUNCTIONS[SC_IDX]}
		if [[ -z "${dflt_juncs[0]}" ]] || [[ -z "${dflt_juncs[1]}" ]]; then
			set -A dflt_juncs ${SC_DFLT_JUNCTION_NAME1} ${SC_DFLT_JUNCTION_NAME2} 
		fi
		SC_ARGVAR_JUNCTIONS[SC_IDX]=

		# Prompt user for both junction names
		let i=0
		while [[ ${i} -lt 2 ]] 
		do
			# Get the junction name
			answer=$(sc_prompt "${sctxt_prompt[i]}" "${dflt_juncs[i]}") || return 1

			# Make sure it is not already given
			for junction in ${SC_ARGVAR_JUNCTIONS[SC_IDX]}
			do
				if [[ "${answer}" = "${junction}" ]]; then
					printf "$(gettext 'Junction name already given.')\n\n\a"
					continue 2
				fi
			done

			# Junc name must begin with alpha and
			# may not include : or @
			if [[ "${answer}" = [!a-zA-Z]* ]] ||
			    [[ "${answer}" = *[@:]* ]]; then
				printf "$(gettext 'Invalid junction name.')\n\n\a"
				continue
			fi

			# Junc name must be <= 256 characters
			if [[ ${#answer} -gt 256 ]]; then
				printf "$(gettext 'Junction name is too long.')\n\n\a"
				continue
			fi

			# okay - add it to the list
			SC_ARGVAR_JUNCTIONS[SC_IDX]="${SC_ARGVAR_JUNCTIONS[SC_IDX]} ${answer}"
			((i += 1))
		done

	# Otherwise, if typical mode, use defaults
	else
		SC_ARGVAR_JUNCTIONS[SC_IDX]="${SC_DFLT_JUNCTION_NAME1} ${SC_DFLT_JUNCTION_NAME2}"
	fi

	# append SC_ARGVAR_JUNCTIONS to response log
	argvar_append_tofile_junctions "${SC_IDX}" ${SC_ILOG}

	return 0
}

####################################################
#
# interactive_install_adapters() iflag
#
#	Set SC_ARGVAR_ADAPTERS, SC_ARGVAR_TRTYPE,
#	and SC_ARGVAR_E2CABLES for this node.
#	Then, add them to the response log.
#
#	iflag 1		- establish new cluster w/ this machine
#	iflag 2		- add this machine to an established cluster
#	iflag 3		- custom JumpStart client set up
#	iflag 4		- centralized install
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_adapters()
{
	integer iflag=${1}

	typeset sctxt_title="$(gettext '
		>>> Cluster Transport Adapters and Cables <<<
	')"
	typeset sctxt_p1_adap_standard="$(gettext '
		You must configure at least two cluster transport
		adapters for each node in the cluster.   These are the
		adapters which attach to the private cluster
		interconnect.
	')"
	typeset sctxt_p1_adap="${sctxt_p1_adap_standard}"
	typeset sctxt_p1_adap_auto="$(gettext '
		You must identify the two cluster transport adapters
		which attach this node to the private cluster
		interconnect.
	')"

	typeset sctxt_prompt_adapmenu4
	set -A sctxt_prompt_adapmenu4
	sctxt_prompt_adapmenu4[0]="$(gettext 'Select the first cluster transport adapter for \"%s\":')"
	sctxt_prompt_adapmenu4[0]="$(printf "${sctxt_prompt_adapmenu4[0]}" "${mynodename}")"
	sctxt_prompt_adapmenu4[1]="$(gettext 'Select the second cluster transport adapter for \"%s\":')"
	sctxt_prompt_adapmenu4[1]="$(printf "${sctxt_prompt_adapmenu4[1]}" "${mynodename}")"

	typeset sctxt_prompt_adapmenu
	set -A sctxt_prompt_adapmenu
	sctxt_prompt_adapmenu[0]="$(gettext 'Select the first cluster transport adapter:')"
	sctxt_prompt_adapmenu[1]="$(gettext 'Select the second cluster transport adapter:')"

	typeset sctxt_prompt_adap
	set -A sctxt_prompt_adap
	sctxt_prompt_adap[0]="$(gettext '
		What is the name of the first cluster transport adapter')"
	sctxt_prompt_adap[1]="$(gettext '
		What is the name of the second cluster transport adapter')"

	typeset sctxt_p1_trtype="$(gettext '
		All transport adapters support the \"dlpi\" transport
		type.  Ethernet adapters are supported only with the
		\"dlpi\" transport;  however, other adapter types may
		support other types of transport.  For more information
		on which transports are supported with which adapters,
		please refer to the scconf_transp_adap family of man
		pages (scconf_transp_adap_hme(1M), ...).
	')"

	typeset sctxt_prompt_adaptype="$(gettext '
		Is \"%s\" an Ethernet adapter?')"
	typeset sctxt_p1_adaptype="$(gettext '
		Adapter \"%s\" is a WCI transport adapter.
	')"
	typeset sctxt_p2_adaptype="$(gettext '
		Adapter \"%s\" is an Ethernet adapter.
	')"
	typeset sctxt_p1_setdlpi="$(gettext '
		The \"dlpi\" transport type will be set for this cluster.
	')"
	typeset sctxt_prompt_trtype="$(gettext '
		What type of transport should be used by this cluster?')"

	typeset sctxt_prompt_otheradap
	set -A sctxt_prompt_otheradap
	sctxt_prompt_otheradap[0]="$(gettext '
		Name of adapter on \"%s\" to which \"%s\" is connected?')"
	sctxt_prompt_otheradap[1]="${sctxt_prompt_otheradap[0]}"

	typeset sctxt_prompt_junc
	set -A sctxt_prompt_junc
	sctxt_prompt_junc[0]="$(gettext '
		Name of the junction to which \"%s\" is connected?')"
	sctxt_prompt_junc[1]="${sctxt_prompt_junc[0]}"

	typeset sctxt_p1_dfltport="$(gettext '
		Each adapter is cabled to a particular port on a
		transport junction.  And, each port is assigned a
		name.  You can explicitly assign a name to each port.
		Or, for Ethernet switches, you can choose to allow scinstall
		to assign a default name for you.   The default port
		name assignment sets the name to the node number of the
		node hosting the transport adapter at the other end of
		the cable.
	')"
	typeset sctxt_p2_dfltport="$(gettext '
		For more information regarding port naming
		requirements, refer to the scconf_transp_jct family of
		man pages (e.g., scconf_transp_jct_dolphinswitch(1M)).
	')"

	typeset sctxt_prompt_dfltport
	set -A sctxt_prompt_dfltport
	sctxt_prompt_dfltport[0]="$(gettext '
		Use the default port name for the \"%s\" connection?')"
	sctxt_prompt_dfltport[1]="${sctxt_prompt_dfltport[0]}"

	typeset sctxt_prompt_portname
	set -A sctxt_prompt_portname
	sctxt_prompt_portname[0]="$(gettext '
		What is the name of the port you want to use?')"
	sctxt_prompt_portname[1]="${sctxt_prompt_portname[0]}"

	typeset sctxt_nodename=" $(gettext 'For node \"%s\",')\n"
	typeset sctxt_p1_autodiscover="$(gettext '
		Autodiscovery is the best method for configuring the
		cluster transport.   However, you can choose to manually
		configure the remaining adapters and cables.
	')"

	typeset answer
	typeset dflt_answer
	typeset thisadapter
	typeset thisadapterdriver
	typeset thisadapterinst
	typeset otheradapters
	typeset prompt
	typeset text
	typeset trtype
	typeset adapter
	typeset adapterdriver
	typeset adaptertype
	typeset adapters
	typeset available_adapters
	typeset initial_available_adapters
	typeset used_adapters
	typeset junction
	typeset junc2
	typeset junc3
	typeset dflt_adaps
	typeset dflt_trtypes
	typeset dflt_cables
	typeset dflt_ports
	typeset foo
	typeset arg_adaptypes

	integer i
	integer skipit
	integer index
	integer firsti
	integer found
	integer first
	integer isknownether
	integer do_pause=0

	#
	# Check iflag
	#
	case ${iflag} in
	'1' | '2' | '3')
		;;

	'4')  # Centralized install
		# Clear our autodiscovery global variable
		SC_DISCOVER_DOAUTO=

		# If typical install, use alternate help text
		if [[ ${SC_TYPICAL_INSTALL} -eq 1 ]]; then
			sctxt_p1_adap="${sctxt_p1_adap_auto}"
		fi
		;;

	*)    # invalid argument
		return 1
		;;
	esac

	#
	# Get list of known used and available Ethernet adapters for this node.
	#
	if [[ ${iflag} -eq 1 ]] ||
	    [[ ${iflag} -eq 2 ]] ||
	    [[ ${iflag} -eq 4 ]];  then

		# Set the list of known adaptertypes for use w/ scrconf
		arg_adaptypes=
		for foo in ${SC_DFLT_KNOWN_ETHERNET_ADAPTERS}
		do
			if [[ -z "${arg_adaptypes}" ]]; then
				arg_adaptypes=",adaptypes=${foo}"
			else
				arg_adaptypes="${arg_adaptypes}:${foo}"
			fi
		done

		# Get available adapters, sorted
		available_adapters="$(
			for adapter in $(scrconf_static -n cmd=print_adapters_available${arg_adaptypes} 2>/dev/null)
			do
				echo ${adapter}
			done | sort
		)"
		initial_available_adapters="${available_adapters}"

		# Get used adapters
		used_adapters="$(scrconf_static -n print_adapters_active)"
	fi

	#
	# For each node, configure adapters and cables.
	#
	# Unless this is a JumpStart install, the first node in the
	# list will be this node.
	#
	let first=1
	adaptertype=
	for index in ${SC_INDICES}
	do
		# If first time through, initialize index of first node
		if [[ ${first} -eq 1 ]]; then
			let firsti=${index}

		# If not first time through, clear the adapters lists
		else
			available_adapters=
			used_adapters=
		fi

		# Initialize the adapter defaults
		set -A dflt_adaps ${SC_ARGVAR_ADAPTERS[index]}
		if [[ -z "${dflt_adaps[0]}" ]] || [[ -z "${dflt_adaps[1]}" ]]; then
			set -A dflt_adaps
		fi
		SC_ARGVAR_ADAPTERS[index]=

		# Initialize the trtype defaults
		set -A dflt_trtypes ${SC_ARGVAR_TRTYPES[index]}
		if [[ -z "${dflt_trtypes[0]}" ]] || [[ -z "${dflt_trtypes[1]}" ]]; then
			set -A dflt_trtypes
		fi
		SC_ARGVAR_TRTYPES[index]=

		# Initialize the cable defaults
		if [[ -n "${SC_ARGVAR_E2CABLES[index]}" ]]; then
			set -A foo ${SC_ARGVAR_E2CABLES[index]}
		else
			set -A foo ${SC_ARGVAR_JUNCTIONS[index]}
		fi
		set -A dflt_cables 
		let i=0
		while [[ ${i} -lt 2 ]]
		do
			# If junctions, there is no host, no colon (:)
			if [[ ${SC_ARGVAR_DIRECT} -eq 0 ]] &&
			    [[ "${foo[i]}" != *:* ]]; then
				dflt_cables[i]=${foo[i]}

			# Otherwise, if direct connect, strip host portion
			elif [[ ${SC_ARGVAR_DIRECT} -eq 1 ]] &&
			    [[ "${foo[i]}" = *:* ]]; then
				dflt_cables[i]=$(echo "${foo[i]}" | sed -n 's/.*:\(.*\)/\1/p')
			fi
			((i += 1))
		done
		SC_ARGVAR_E2CABLES[index]=

		# Initialize E2 port defaults
		set -A dflt_ports ${SC_ARGVAR_E2PORTS[index]}
		if [[ -z "${dflt_ports[0]}" ]] ||
		    [[ -z "${dflt_ports[1]}" ]]; then
			set -A dflt_ports @ @
		fi
		SC_ARGVAR_E2PORTS[index]=

		# First time through, print help message
		if [[ ${first} -eq 1 ]]; then
			clear
			sc_print_title "${sctxt_title}"
			sc_print_para "${sctxt_p1_adap}"
		fi

		# If direct connect, no need to go around a second time
		if [[ ${SC_ARGVAR_DIRECT} -eq 1 ]] &&
		    [[ ${first} -ne 1 ]]; then

			# Our adapters were specified first time through
			SC_ARGVAR_ADAPTERS[index]="${otheradapters}"

			# We don't let the user specify adapter ports
			SC_ARGVAR_E1PORTS[index]="@ @"

			# Dup the type from the first time through
			SC_ARGVAR_TRTYPES[index]="${SC_ARGVAR_TRTYPES[firsti]}"

			# Set the cable from the first time through
			for adapter in ${SC_ARGVAR_ADAPTERS[firsti]}
			do
				SC_ARGVAR_E2CABLES[index]="${SC_ARGVAR_E2CABLES[index]} ${SC_ARGVAR_NODENAME[firsti]}:${adapter}"
			done

			# skip the adapter and cable setup below
			let skipit=1
		else
			set -A otheradapters
			let skipit=0
		fi

		# For each of the two adapters and cables ...
		let i=0
		let isknownether=0
		adaptertype=
		while [[ ${skipit} -eq 0 ]] && [[ ${i} -lt 2 ]] 
		do
			# Adapters
			thisadapter=
			thisadapterdriver=
			thisadapterinst=
			while true
			do
				adaptertype=
				thisadapter=
				thisadapterdriver=
				thisadapterinst=

				# If iflag is 3 or 4, print the nodename
				if [[ ${iflag} -eq 3 || ${iflag} -eq 4 ]] &&
				    [[ -z "${available_adapters}" ||
				       -n "${dflt_adaps[i]}" ]]; then
					printf "${sctxt_nodename}" "${SC_ARGVAR_NODENAME[index]}"
				fi

				# Adjust avaliable adapters
				foo=
				adapters=
				for adapter in ${available_adapters}
				do
					let found=0
					for foo in ${SC_ARGVAR_ADAPTERS[index]}
					do
						if [[ "${adapter}" == "${foo}" ]];  then
							let found=1
							break
						fi
					done
					if [[ ${found} -eq 0 ]]; then
						adapters="${adapters} ${adapter}"
					fi
				done
				available_adapters="${adapters}"

				# If no defaults, use menu to get adapater
				answer=
				if [[ -n "${available_adapters}" ]] &&
				    [[ -z "${dflt_adaps[i]}" ]]; then
					if [[ ${iflag} -eq 4 ]]; then
						prompt="${sctxt_prompt_adapmenu4[i]}"
					else
						prompt="${sctxt_prompt_adapmenu[i]}"
					fi
					answer="$(
					    sc_get_scrolling_menuoptions    \
						"${prompt}"		    \
						"" ""			    \
						1 1 1			    \
						${initial_available_adapters} \
						"Other"			    \
					)"
					if [[ -z "${answer}" ]]; then
						return 1
					fi
					if [[ "${answer}" == "Other" ]]; then
						answer=
					fi
				fi

				# Otherwise, use prompt to get adapter name
				while [[ -z "${answer}" ]]
				do
					prompt="${sctxt_prompt_adap[i]}"
					if [[ -n "${available_adapters}" ]]; then
						prompt="${prompt} $(gettext '(help)')"
					fi
					prompt="${prompt}?"
					answer=$(sc_prompt "${prompt}" "${dflt_adaps[i]}") || return 1
					if [[ "${answer}" == "help" ]] ||
					    [[ "${answer}" == "?" ]]; then
						if [[ -z "${available_adapters}" ]]; then
							printf "$(gettext 'Cannot determine list of possible available adapters.')\n\n\a"
						else
							for foo in ${available_adapters}
							do
								printf "\t${foo}\n"
							done
							echo
						fi
						answer=
					fi
				done

				# Adapter name must be
				#         <device_name><device_instance>
				# where <device_instance> is numeric
				if [[ "${answer}" = *:* ]] ||
				    [[ $(expr "${answer}" : '[a-z][a-z0-9]*[0-9][0-9]*') -ne ${#answer} ]]; then
					printf "$(gettext 'Invalid adapter name.')\n\n\a"
					continue
				fi

				# Make sure it is not already given
				for adapter in ${SC_ARGVAR_ADAPTERS[index]}
				do
					if [[ "${answer}" == "${adapter}" ]]; then
						printf "$(gettext '\"%s\" has already been used.')\n" "${adapter}"
						printf "$(gettext 'Try again ... ')\n\n\a"
						continue 2
					fi
				done

				# Make sure it is not already used
				for adapter in ${used_adapters}
				do
					if [[ "${answer}" == "${adapter}" ]]; then
						printf "$(gettext 'Adapter \"%s\" is already in use as a public network adapter.')\n\n\a" "${adapter}"
						continue 2
					fi
				done

				# Set adapter variables
				thisadapter=${answer}
				thisadapterdriver=$(expr ${answer} : '\([a-z0-9]*[a-z]\)')
				thisadapterinst=$(expr ${answer} : '[a-z0-9]*[a-z]\([0-9]*\)')

				#
				# Try to determine adapter type, print message
				#

				# Wildcat?
				if [[ "${thisadapterdriver}" == "${SC_DFLT_KNOWN_WILDCAT_ADAPTER}" ]]; then
					# Print message regarding type
					text="$(printf "${sctxt_p1_adaptype}" "${thisadapter}")"
					sc_print_para "${text}"

					# Cannot be used with JumpStart
					if [[ ${iflag} -eq 3 ]]; then
						printf "$(gettext 'WCI transport adapters cannot be installed using JumpStart.')\n\n\a"
						continue
					fi

					#
					# Can't support direct connect with
					# Wildcat.  First time through,
					# we can still override it.
					#
					if [[ ${SC_ARGVAR_DIRECT} -eq 1 ]]; then
						printf "$(gettext 'WCI transport adapters cannot be configured without junctions.')\n\a"
						printf "$(gettext 'Type Control-D to start over and enter junction names.')\n\n\a"
						continue
					fi

					# set adaptertype
					adaptertype=wildcat

					# Print message regarding switch name
					text="$(printf "$(gettext 'Adapter \"%s\" is connected to virtual switch \"%s\".')" "${thisadapter}" "${SC_DFLT_KNOWN_WILDCAT_JUNCTION}${thisadapterinst}")"
					sc_print_para "${text}"

					#
					# If the adapter name is "wrsmN",
					# then the switch name must be
					# "sw_wrsmN".
					#

					# See if the switch is known
					let found=0
					for junction in ${SC_ARGVAR_JUNCTIONS[index]}
					do
						if [[ "${junction}" == "${SC_DFLT_KNOWN_WILDCAT_JUNCTION}${thisadapterinst}" ]]; then
							let found=1
							break
						fi
					done

					# If not, add it
					if [[ ${found} -ne 1 ]]; then
						text="$(printf "$(gettext 'Virtual switch \"%s\" has been added to the list of junctions.')" "${SC_DFLT_KNOWN_WILDCAT_JUNCTION}${thisadapterinst}")"
						sc_print_para "${text}"
						SC_ARGVAR_JUNCTIONS[index]="${SC_ARGVAR_JUNCTIONS[index]} ${SC_DFLT_KNOWN_WILDCAT_JUNCTION}${thisadapterinst}"
					fi

					# No port data for Wildcat
					SC_ARGVAR_E2PORTS[index]="${SC_ARGVAR_E2PORTS[index]} @"

					# Now, add the endpoint information
					SC_ARGVAR_E2CABLES[index]="${SC_ARGVAR_E2CABLES[index]} ${SC_DFLT_KNOWN_WILDCAT_JUNCTION}${thisadapterinst}"

				fi

				# Ethernet?
				if [[ -z "${adaptertype}" ]]; then
					for adapterdriver in ${SC_DFLT_KNOWN_ETHERNET_ADAPTERS}
					do
						if [[ "${adapterdriver}" = "${thisadapterdriver}" ]]; then
							# Print message
							if [[ ${SC_TYPICAL_INSTALL} -ne 1 ]]; then
								text="$(printf "${sctxt_p2_adaptype}" "${thisadapter}")"
								sc_print_para "${text}"
							fi

							adaptertype="ethernet"
							break
						fi
					done
				fi

				#
				# Make sure transport type is not already set
				# to something other than dlpi
				#
				if [[ "${adaptertype}" == "ethernet" ]] &&
				    [[ -n "${SC_ARGVAR_TRTYPES[index]}" ]] &&
				    [[ "${SC_ARGVAR_TRTYPES[index]}" != "dlpi dlpi" ]]; then
					printf "$(gettext 'Ethernet adapters are only supported with the dlpi transport type.')\n\n\a"
					continue
				fi

				#
				# If this is the first node, see if there
				# is traffic.
				#
				if [[ ${iflag} -eq 1 || ${iflag} -eq 4 ]] &&
				    [[ ${first} -eq 1 ]] &&
				    [[ "${adaptertype}" == "ethernet" ]]; then
					interactive_install_snoop ${thisadapter}
					if [[ $? -ne 0 ]]; then
						continue
					fi
				fi

				# okay - increment isknownether, if ethernet
				if [[ "${adaptertype}" == "ethernet" ]]; then
					((isknownether += 1))
				fi

				# okay - add it to the list
				SC_ARGVAR_ADAPTERS[index]="${SC_ARGVAR_ADAPTERS[index]} ${thisadapter}"

				# Done
				break
			done

			# We don't let the user specify adapter ports
			SC_ARGVAR_E1PORTS[index]="@ @"

			# First time through, get transport type
			if [[ ${first} -eq 1 ]] && [[ ${i} -eq 0 ]]; then

				# Print help
				if [[ -z "${adaptertype}" ]]; then
					sc_print_para "${sctxt_p1_trtype}"
				fi

				#
				# If we don't yet know what kind of adapter
				# this is, ask if it is Ethernet.
				#
				answer=
				if [[ -z "${adaptertype}" ]]; then
					# If iflag is 3 or 4, print the nodename
					if [[ ${iflag} -eq 3 ]] ||
					    [[ ${iflag} -eq 4 ]]; then
						printf "${sctxt_nodename}" "${SC_ARGVAR_NODENAME[index]}"
					fi

					# Set default - Ethernet adapter?
					dflt_answer=
					set -A foo ${SC_ARGVAR_ETHERADAP[index]}
					if [[ "${foo[0]}" = "${thisadapter}" ]] && [[ "${foo[1]}" = "1" ]]; then
						dflt_answer="${YES}"
					else
						dflt_answer="${NO}"
					fi

					# Ethernet adapter?
					prompt="$(printf "${sctxt_prompt_adaptype}" "${thisadapter}")"
					answer=$(sc_prompt_yesno "${prompt}" "${dflt_answer}") || return 1
					if [[ "${answer}" == "yes" ]]; then
						adaptertype="ethernet"
					fi
				fi

				# If Ethernet, force to dlpi
				if [[ "${adaptertype}" == "ethernet" ]]; then
					# Set SC_ARGVAR_ETHERADAP to "yes"
					SC_ARGVAR_ETHERADAP[index]="${thisadapter} 1"
					if [[ ${SC_TYPICAL_INSTALL} -ne 1 ]]; then
						sc_print_para "${sctxt_p1_setdlpi}"
					fi
					SC_ARGVAR_TRTYPES[index]="dlpi dlpi"

				# Otherwise, ask user if dlpi
				else
					# Set SC_ARGVAR_ETHERADAP to "no"
					SC_ARGVAR_ETHERADAP[index]="${thisadapter} 0"
					# Transport types
					while true
					do
						# Get the transport type
						answer=$(sc_prompt "${sctxt_prompt_trtype}" "${dflt_trtypes[0]}") || return 1

						# Must be known transport type
						let found=0
						for trtype in ${SC_DFLT_KNOWN_TRTYPES}
						do
							if [[ "${answer}" = "${trtype}" ]]; then
								let found=1
								break
							fi
						done
						if [[ ${found} -ne 1 ]]; then
							printf "$(gettext 'Unknown transport type.')\n\n\a"
							continue
						fi

						# okay - add it to the list
						SC_ARGVAR_TRTYPES[index]="${answer} ${answer}"
						break
					done
				fi

                        # Otherwise, dup the type from the first time
			elif [[ ${first} -ne 1 ]]; then
				SC_ARGVAR_TRTYPES[index]="${SC_ARGVAR_TRTYPES[firsti]}"
			fi

			# If this is Wildcat, we can finish up here.
			if [[ "${adaptertype}" == "wildcat" ]]; then

				# Go do the next cable
				((i += 1))
				continue
			fi

			#
			# If direct connect and not a new cluster,
			# get the other adapter.
			#
			if [[ ${SC_ARGVAR_DIRECT} -eq 1 ]] &&
			    [[ -n "${SC_OTHERNODE}" ]] &&
			    [[ ${iflag} -ne 1 ]]; then

				# Adapter at other end of cable
				while true
				do
					# Get the name of the other adapter
					prompt="$(printf "${sctxt_prompt_otheradap[i]}" "${SC_OTHERNODE}" "${thisadapter}")"
					answer=$(sc_prompt "${prompt}" "${dflt_cables[i]}") || return 1

					# Make sure it is not already given
					for adapter in ${SC_ARGVAR_E2CABLES[index]}
					do
						adapter=$(echo "${adapter}" | sed -n 's/.*:\(.*\)/\1/p')
						if [[ "${answer}" = "${adapter}" ]]; then
							printf "$(gettext 'Adapter name already given.')\n\n\a"
							continue 2
						fi
					done

					# Adapter name must be <alpha><numeric>
					if [[ "${answer}" = *:* ]] ||
					    [[ $(expr "${answer}" : '[a-z][a-z0-9]*[0-9][0-9]*') -ne ${#answer} ]]; then
						printf "$(gettext 'Invalid adapter name.')\n\n\a"
						continue
					fi

					# okay - add it to the list
					SC_ARGVAR_E2CABLES[index]="${SC_ARGVAR_E2CABLES[index]} ${SC_OTHERNODE}:${answer}"

					# also, save this adapter list
					otheradapters="${otheradapters} ${answer}"
					break
				done

			elif [[ ${SC_TYPICAL_INSTALL} -eq 1 ]] &&
			    [[ "${adaptertype}" == "ethernet" ]]; then
				SC_ARGVAR_E2CABLES[index]="${SC_ARGVAR_E2CABLES[index]} ${dflt_cables[i]}"
				SC_ARGVAR_E2PORTS[index]="${SC_ARGVAR_E2PORTS[index]} @"

			elif [[ ${SC_ARGVAR_DIRECT} -ne 1 ]]; then

				# Junction at other end of cable
				while true
				do
					# If iflag is 3 or 4, print the nodename
					if [[ ${iflag} -eq 3 ]] ||
					    [[ ${iflag} -eq 4 ]]; then
						printf "${sctxt_nodename}" "${SC_ARGVAR_NODENAME[index]}"
					fi

					# Get the name of the junction
					prompt="$(printf "${sctxt_prompt_junc[i]}" "${thisadapter}")"
					answer=$(sc_prompt "${prompt}" "${dflt_cables[i]}") || return 1

					# Make sure it is not already given
					for junction in ${SC_ARGVAR_E2CABLES[index]}
					do
						if [[ "${answer}" = "${junction}" ]]; then
							printf "$(gettext 'Junction name already given.')\n\n\a"
							continue 2
						fi
					done

					#
					# Make sure it is one of our
					# known junctions.
					#
					let found=0
					for junction in ${SC_ARGVAR_JUNCTIONS[index]}
					do
						if [[ "${answer}" = "${junction}" ]]; then
							let found=1
							break
						fi
					done
					if [[ ${found} -ne 1 ]]; then
						printf "$(gettext 'Unknown junction.')\n\n\a"
						continue
					fi

					# okay - add it to the list
					SC_ARGVAR_E2CABLES[index]="${SC_ARGVAR_E2CABLES[index]} ${answer}"
					break
				done

				# First time through, print default port help
				if [[ ${first} -eq 1 ]] &&
				    [[ ${i} -eq 0 ]]; then
					sc_print_para "${sctxt_p1_dfltport}"
					sc_print_para "${sctxt_p2_dfltport}"
				fi

				#
				# If Ethernet, get the default answer.
				#
				# Note that SC_ARGVAR_ETHERADAP only holds
				# information for the first configured
				# adapter on the first node.  So, it
				# really only provides a "hint" about
				# the other adapters.  However, for our
				# purposes here, this should be adequate.
				# It is not likely that people will be mixing
				# Ethernet with other adapter types.
				# And, if they do, we are, after all,
				# only setting the default for the
				# prompt here.
				#
				set -A foo ${SC_ARGVAR_ETHERADAP[firsti]}
				if [[ "${foo[1]}" = "1" ]]; then
					if [[ "${dflt_ports[i]}" = "@" ]]; then
						dflt_answer="${YES}"
					else
						dflt_answer="${NO}"
					fi
				else
					dflt_answer=
				fi

				# If iflag is 3 or 4, print the nodename
				if [[ ${iflag} -eq 3 ]] ||
				    [[ ${iflag} -eq 4 ]]; then
					printf "${sctxt_nodename}" "${SC_ARGVAR_NODENAME[index]}"
				fi

				#
				# If not Ethernet, then the user
				# may not request default port names;
				# they must be specified.
				#
				if [[ -z ${dflt_answer} ]]; then
					answer="no"
				else
					# Use default port names?
					prompt="$(printf "${sctxt_prompt_dfltport[i]}" "${thisadapter}")"
					answer=$(sc_prompt_yesno "${prompt}" "${dflt_answer}") || return 1
				fi

				# If answer is yes, set port to "@"
				if [[ "${answer}" = "yes" ]]; then
					answer="@"

				# otherwise, prompt for the name
				else
					if [[ ${dflt_ports[i]} != "@" ]]; then
						dflt_answer=${dflt_ports[i]}
					else
						dflt_answer=
					fi
					answer=$(sc_prompt "${sctxt_prompt_portname[i]}" "${dflt_answer}") || return 1
				fi
				SC_ARGVAR_E2PORTS[index]="${SC_ARGVAR_E2PORTS[index]} ${answer}"
			fi

			# Next
			((i += 1))
		done

		# append SC_ARGVAR_ADAPTERS to response log
		argvar_append_tofile_adapters "${index}" ${SC_ILOG}

		# append SC_ARGVAR_ETHERADAP to response log
		argvar_append_tofile_etheradap "${index}" ${SC_ILOG}

		# append SC_ARGVAR_TRTYPES to response log
		argvar_append_tofile_trtypes "${index}" ${SC_ILOG}

		# append SC_ARGVAR_E1PORTS/SC_ARGVAR_E2PORTS to response log
		argvar_append_tofile_ports "${index}" ${SC_ILOG}

		# append SC_ARGVAR_E2PORTS to response log
		argvar_append_tofile_ports "${index}" "${SC_ILOG}" 2

		#
		# If centralized install and direct connect, don't
		# worry about autodiscovery.
		#
		if [[ ${iflag} -eq 4 ]] &&
		    [[ ${SC_ARGVAR_DIRECT} -eq 1 ]]; then
			let first=0
			continue
		fi

		#
		# If centralized install and adapters are known,
		# allow autodiscovery.
		#
		if [[ ${first} -eq 1 ]] &&
		    [[ ${iflag} -eq 4 ]] &&
		    [[ ${isknownether} -eq 2 ]]; then

			SC_DISCOVER_DOAUTO=

			# Do they want to autodiscover?
			if [[ ${SC_TYPICAL_INSTALL} -eq 1 ]]; then
				SC_DISCOVER_DOAUTO=${SC_TRUE}
			else
				printf " $(gettext 'For all other nodes,')\n"
				sc_print_para "${sctxt_p1_autodiscover}"
				prompt="$(gettext 'Is it okay to use autodiscovery for the other nodes?')"
				answer=$(sc_prompt_yesno "${prompt}" "${YES}") || return 1
				if [[ "${answer}" == "yes" ]]; then
					SC_DISCOVER_DOAUTO=${SC_TRUE}
				fi
			fi
			if [[ -n "${SC_DISCOVER_DOAUTO}" ]]; then
				break
			fi
		fi

		# next time will not be first time through
		let first=0

	# Done with each node
	done

	# If the last adaptertype was Wildcat, we need to do a pause
	if [[ "${adaptertype}" == "wildcat" ]]; then
		((do_pause += 1))
	fi

	# Remove any unused junctions
	for index in ${SC_INDICES}
	do
		foo=
		for junction in ${SC_ARGVAR_JUNCTIONS[index]}
		do
			let found=0
			for junc2 in ${SC_ARGVAR_E2CABLES[*]}
			do
				if [[ "${junc2}" == "${junction}" ]]; then
					let found=1
					break
				fi
			done
			if [[ ${found} -eq 1 ]]; then

				# if it is already in the list, don't
				# add it again
				if [[ -n "${foo}" ]]; then
					for junc3 in ${foo}
					do
						if [[ "${junc3}" == "${junction}" ]]; then
							continue 2
						fi
					done
				fi
				foo="${foo} ${junction}"
			else
				# Print message - ignoring junction
				printf "$(gettext 'Unused junction \"%s\" will be ignored.')\n\a" "${junction}"
				((do_pause += 1))
			fi
		done

		SC_ARGVAR_JUNCTIONS[index]="${foo}"

		# append SC_ARGVAR_JUNCTIONS to response log
		argvar_append_tofile_junctions "${index}" ${SC_ILOG}
	done

	# Pause until they press Enter
	if [[ ${do_pause} -ne 0 ]]; then
		sc_prompt_pause || return 1
	fi

	return 0
}

####################################################
#
# interactive_install_globaldev_check iflag type globaldev [nodename]
#
#	Check the given "globaldev" on the given "nodename".  The
#	"type" must be either "fs" or "device".
#
#	iflag 1		- establish new cluster w/ this machine
#	iflag 2		- add this machine to an established cluster
#	iflag 4		- centralized install
#
#	Uses ${tmperrs}.
#
#	The return values are the same as for is_globalfs_okay() and
#	is_globalcspecial_okay() (depending on given "type").
#
####################################################
interactive_install_globaldev_check()
{
	integer iflag=${1}
	typeset type=${2}
	typeset globaldev=${3}
	typeset nodename=${4}

	typeset file1=scinstall_common
	typeset file2=cmd_chk_globaldev
	typeset installed_dir=/usr/cluster/lib/scadmin/lib
	typeset cdrom_dir=${SC_PACKAGESDIR}/SUNWscu/reloc${installed_dir}

	integer result=0
	typeset dir
	typeset file
	typeset cmd

	#
	# Check iflag
	#
	case ${iflag} in
	'1' | '2')
		# nodename is only needed for centralized install
		nodename=
		;;

	'4')  # centralized install
		;;

	*)    # invalid argument
		return 10
		;;
	esac

	#
	# Check other arguments
	#
	if [[ "${type}" != "fs" ]] &&
	    [[ "${type}" != "device" ]]; then
		return 10
	fi
	if [[ -z "${globaldev}" ]]; then
		return 10
	fi

	# local install only
	if [[ -z "${nodename}" ]]; then
		if [[ "${type}" == "fs" ]]; then
			is_globalfs_okay "${globaldev}" 3
			result=$?
		else
			is_globalcspecial_okay "${globaldev}" 3
			result=$?
		fi
		if [[ ${result} -ne 0 ]]; then
			printf "$(gettext 'Cannot use \"%s\".')\n\n\a" "${globaldev}"
		fi

	# centralized install - local node
	elif [[ "${nodename}" == "${mynodename}" ]];  then
		sc_print_line "$(printf "$(gettext 'Testing for \"%s\" on \"%s\" ... ')" "${globaldev}" "${nodename}")" | logmsg
		echo >>${install_log}
		if [[ "${type}" == "fs" ]]; then
			is_globalfs_okay "${globaldev}" 3 >${tmperrs}
			result=$?
		else
			is_globalcspecial_okay "${globaldev}" 3 >${tmperrs}
			result=$?
		fi
		if [[ ${result} -ne 0 ]]; then
			printf "%s\n" ${SC_FAILED}
			echo | logmsg
			if [[ -s ${tmperrs} ]]; then
				cat ${tmperrs} | logmsg
			fi
			printf "$(gettext 'Cannot use \"%s\" on \"%s\".')\n\n" "${globaldev}" "${nodename}" | logmsg
			echo "\a\c"
		else
			printf "%s\n" ${SC_DONE}
		fi
		rm -f ${tmperrs}

	# centralized install - remote node
	else
		rm -f ${tmperrs}
		sc_print_line "$(printf "$(gettext 'Testing for \"%s\" on \"%s\" ... ')" "${globaldev}" "${nodename}")" | logmsg
		echo >>${install_log}
		case ${SC_REMOTE_METHOD} in
		rsh|ssh)

			#
			# Two files must be copied to /var/cluster/run
			# on the remote machine, cmd_chk_globaldev and
			# scinstall_common.
			#
			if [[ -f "${installed_dir}/${file1}" ]] &&
			    [[ -f "${installed_dir}/${file2}" ]]; then
				dir=${installed_dir}

			elif [[ -f "${cdrom_dir}/${file1}" ]] &&
			    [[ -f "${cdrom_dir}/${file2}" ]]; then
				dir=${cdrom_dir}

			else
				printf "%s\n" ${SC_FAILED}
				echo | logmsg
				printf "$(gettext 'Unable to check \"%s\" on \"%s\".')\n\n" "${globaldev}" "${nodename}" | logmsg
				echo "\a\c"
				return 10
			fi

			# Create /var/cluster, if it does not exist
			interactive_install_cmd ${nodename} "umask 0; /usr/bin/mkdir -m 0755 /var/cluster /var/cluster/run" "" "noprepend" >/dev/null 2>&1
			interactive_install_cmd ${nodename} "/usr/bin/chgrp sys /var/cluster /var/cluster/run" >/dev/null 2>&1

			# Copy the files to /var/cluster/run
			for file in ${file1} ${file2}
			do
				if [[ "${SC_REMOTE_METHOD}" == "rsh" ]]; then
					cmd="rcp ${dir}/${file} ${nodename}:/var/cluster/run/${file}"
				else
					cmd="scp -Bq ${dir}/${file} root@${nodename}:/var/cluster/run/${file}"
				fi

				echo >>${install_log}
				echo ${cmd} >>${install_log}
				eval ${cmd} >>${install_log} 2>&1
				result=$?
				if [[ ${result} -ne 0 ]]; then
					interactive_install_cmd ${nodename} "/usr/bin/rm -f /var/cluster/run/${file1} /var/cluster/run/${file2}" >/dev/null 2>&1
					printf "%s\n" ${SC_FAILED}
					echo | logmsg
					printf "$(gettext 'Unable to check \"%s\" on \"%s\" due to failed remote copy.')\n\n" "${globaldev}" "${nodename}" | logmsg
					echo "\a\c"
					return 10
				fi

				# Set permissions
				interactive_install_cmd ${nodename} "/usr/bin/chmod 0555 /var/cluster/run/${file}" >/dev/null 2>&1
			done

			# Run the command
			interactive_install_cmd ${nodename} "/var/cluster/run/cmd_chk_globaldev ${type} ${globaldev}" >${tmperrs} 2>&1
			result=$?

			# Remove the files from /var/cluster/run
			interactive_install_cmd ${nodename} "/usr/bin/rm -f /var/cluster/run/${file1} /var/cluster/run/${file2}" >/dev/null 2>&1
			;;

		scrcmd)
			interactive_install_cmd ${nodename} "chk_globaldev ${type} ${globaldev}" >${tmperrs} 2>&1
			result=$?
			;;

		*)
			printf "%s\n" ${SC_FAILED}
			echo | logmsg
			printf "$(gettext 'Unable to check \"%s\" on \"%s\" due to internal error.')\n\n" "${globaldev}" "${nodename}" | logmsg
			echo "\a\c"
			return 10
			;;

		esac
		echo >>${install_log}

		# Check the result
		if [[ ${result} -eq 0 ]]; then
			printf "%s\n" ${SC_DONE}
		else
			printf "%s\n" ${SC_FAILED}
			echo | logmsg
			if [[ -s ${tmperrs} ]]; then
				cat ${tmperrs} | logmsg
			fi

			if [[ ${result} -ge 99 ]]; then
				printf "$(gettext 'Unable to check \"%s\" on \"%s\" due to failed remote command.')\n\n" "${globaldev}" "${nodename}" | logmsg
				echo "\a\c"
			else
				printf "$(gettext 'Cannot use \"%s\" on \"%s\".')\n\n" "${globaldev}" "${nodename}" | logmsg
				echo "\a\c"
			fi
		fi
		rm -f ${tmperrs}
	fi

	return ${result}
}

####################################################
#
# interactive_install_globaldir() iflag
#
#	Set SC_ARGVAR_GDIR for this node.
#	Then, add them to the response log.
#
#	iflag 1		- establish new cluster w/ this machine
#	iflag 2		- add this machine to an established cluster
#	iflag 3		- custom JumpStart client set up
#	iflag 4		- centralized install
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_globaldir()
{
	integer iflag=${1}

	typeset sctxt_title="$(gettext '
		>>> Global Devices File System <<<
	')"
	typeset sctxt_p1="$(gettext '
		Each node in the cluster must have a local file system
		mounted on /global/.devices/node@<nodeID> before it can
		successfully participate as a cluster member.  Since
		the "nodeID" is not assigned until scinstall is run,
		scinstall will set this up for you.
	')"
	typeset sctxt_p2="$(gettext '
		You must supply the name of either an already-mounted
		file system or raw disk partition which scinstall can
		use to create the global devices file system.  This
		file system or partition should be at least 512 MB in
		size.
	')"
	typeset sctxt_p3="$(gettext '
		If an already-mounted file system is used, the file
		system must be empty.   If a raw disk partition is used,
		a new file system will be created for you.
	')"
	typeset sctxt_p4="$(gettext '
		The default is to use /globaldevices.
	')"
	typeset sctxt_err_p1="$(gettext '
		To continue, you must either correct the problem or
		select a custom installation.  A custom installation
		allows you to specify a different file system
		for global devices.
	')"
	typeset sctxt_nodename=" $(gettext 'For node \"%s\",')\n"

	typeset answer
	typeset dflt_answer
	integer argvar_is_partition
	integer index

	#
	# Print help and check iflag
	#
	case ${iflag} in
	'1' | '2' | '3' | '4')
		if [[ ${SC_TYPICAL_INSTALL} -ne 1 ]]; then
			clear
			sc_print_title "${sctxt_title}"
			sc_print_para "${sctxt_p1}"
			sc_print_para "${sctxt_p2}"
			sc_print_para "${sctxt_p3}"
			sc_print_para "${sctxt_p4}"
		fi
		;;

	*)    # invalid argument
		return 1
		;;
	esac

	# For each node
	for index in ${SC_INDICES}
	do
		# Set the is partition variable
		let argvar_is_partition=0
		if [[ "${SC_ARGVAR_GDIR[index]}" == /dev/* ]]; then
			let argvar_is_partition=1
		fi

		# Set default default response
		if [[ -z "${SC_ARGVAR_GDIR[index]}" ]] ||
		    [[ "${SC_ARGVAR_GDIR[index]}" == "${SC_DFLT_GDIR}" ]]; then
			dflt_answer="${YES}"
		else
			dflt_answer="${NO}"
		fi

		#
		# If iflag is 3 (JumpStart) or 4 (centralized) and this
		# is a custom install, print the nodename.
		#
		if [[ ${iflag} -eq 3 || ${iflag} -eq 4 ]] &&
		    [[ ${SC_TYPICAL_INSTALL} -ne 1 ]]; then
			printf "${sctxt_nodename}" "${SC_ARGVAR_NODENAME[index]}"
		fi

		# If this is a "typical" install, just use the default
		if [[ ${SC_TYPICAL_INSTALL} -eq 1 ]]; then

			# Set it to the default
			SC_ARGVAR_GDIR[index]="${SC_DFLT_GDIR}"

			# If not JumpStart, check it
			if [[ ${iflag} -eq 1 ]] ||
			    [[ ${iflag} -eq 2 ]] ||
			    [[ ${iflag} -eq 4 ]];  then
				interactive_install_globaldev_check ${iflag} "fs" "${SC_DFLT_GDIR}" ${SC_ARGVAR_NODENAME[index]}
				if [[ $? -ne 0 ]]; then
					sc_print_para "${sctxt_err_p1}"
					sc_prompt_pause
					return 1
				fi
			fi

			# append SC_ARGVAR_GDIR to the response log
			argvar_append_tofile_globaldir "${index}" ${SC_ILOG}

			# Next
			continue
		fi

		# Okay to use default?
		answer=$(sc_prompt_yesno "$(gettext 'Is it okay to use this default?')" "${dflt_answer}") || return 1

		# If default, use /globaldevices
		if [[ "${answer}" = "yes" ]]; then
			if [[ ${iflag} -eq 1 ]] ||
			    [[ ${iflag} -eq 2 ]] ||
			    [[ ${iflag} -eq 4 ]];  then
				interactive_install_globaldev_check ${iflag} "fs" "${SC_DFLT_GDIR}" ${SC_ARGVAR_NODENAME[index]}
				if [[ $? -ne 0 ]]; then
					# Use another file system
					answer=$(sc_prompt_yesno "$(gettext 'Do you want to select another file system?')" "${YES}") || return 1
					if [[ "${answer}" != "yes" ]]; then
						return 1
					fi
					answer="no"
				else
					[[ ${iflag} -eq 4 ]] && echo
					SC_ARGVAR_GDIR[index]="${SC_DFLT_GDIR}"
				fi
			else
				SC_ARGVAR_GDIR[index]="${SC_DFLT_GDIR}"
			fi
		fi

		# Otherwise, let the user set it
		if [[ "${answer}" == "no" ]]; then

			# Set default response
			if [[ ${argvar_is_partition} -eq 1 ]]; then
				dflt_answer="${NO}"
			else
				dflt_answer="${YES}"
			fi

			# Use file system name?
			answer=$(sc_prompt_yesno "$(gettext 'Do you want to use an already existing file system?')" "${dflt_answer}") || return 1

			# If file system, get answer
			if [[ "${answer}" = "yes" ]]; then

				# Loop until we get the answer
				while true
				do
					# Set default response
					if [[ ${argvar_is_partition} -eq 0 ]]; then
						dflt_answer="${SC_ARGVAR_GDIR[index]}"
					else
						dflt_answer=
					fi

					# Get the name of the file system
					answer=$(sc_prompt "$(gettext 'What is the name of the file system?')" "${dflt_answer}") || return 1

					# File system name must begin with /
					if [[ "${answer}" != /* ]]; then
						printf "$(gettext 'The name must begin with slash (/).')\n\n\a"
						if [[ "${answer}" == "${SC_ARGVAR_GDIR[index]}" ]]; then
							SC_ARGVAR_GDIR[index]=
						fi
						continue
					fi

					# Must not be partition
					if [[ "${answer}" = /dev/* ]];  then
						printf "$(gettext 'Not a file system name.')\n\n\a"
						if [[ "${answer}" == "${SC_ARGVAR_GDIR[index]}" ]]; then
							SC_ARGVAR_GDIR[index]=
						fi
						continue
					fi

					# If not jumpstart, do other checks
					if [[ ${iflag} -eq 1 ]] ||
					    [[ ${iflag} -eq 2 ]] ||
					    [[ ${iflag} -eq 4 ]]; then
						interactive_install_globaldev_check ${iflag} "fs" "${answer}" ${SC_ARGVAR_NODENAME[index]}
						if [[ $? -ne 0 ]]; then
							if [[ "${answer}" == "${SC_ARGVAR_GDIR[index]}" ]]; then
								SC_ARGVAR_GDIR[index]=
							fi
							continue
						fi
						[[ ${iflag} -eq 4 ]] && echo
					fi

					# Done
					break
				done

			# otherwise, it appears to be a partition
			else

				# Loop until we get the answer
				while true
				do
					# Is it?
					if [[ "${SC_ARGVAR_GDIR[index]}" = /dev/dsk/* ]] ||
				    	    [[ "${SC_ARGVAR_GDIR[index]}" = /dev/rdsk/* ]]; then
						dflt_answer=${YES}
					else
						dflt_answer=${NO}
					fi
					answer=$(sc_prompt_yesno "$(gettext 'Okay to create a new file system on an unused partition?')" "${dflt_answer}") || return 1
					if [[ "${answer}" != "yes" ]]; then
						return 1
					fi

					# Set default response
					if [[ "${dflt_answer}" == "yes" ]]; then
						dflt_answer="${SC_ARGVAR_GDIR[index]}"
					else
						dflt_answer=
					fi

					# Get the name of the partition
					answer=$(sc_prompt "$(gettext 'What is the name of the disk partition you want to use?')" "${dflt_answer}") || return 1

					# Must be a partition
					if [[ "${answer}" != /dev/dsk/* ]] &&
				    	[[ "${answer}" != /dev/rdsk/* ]]; then
						printf "$(gettext 'Not a raw disk partition.')\n\n\a"
						continue
					fi

					# If not jumpstart, do other checks
					if [[ ${iflag} -eq 1 ]] ||
					    [[ ${iflag} -eq 2 ]] ||
					    [[ ${iflag} -eq 4 ]]; then
						interactive_install_globaldev_check ${iflag} "device" "${answer}" ${SC_ARGVAR_NODENAME[index]}
						if [[ $? -ne 0 ]]; then
							if [[ "${answer}" == "${SC_ARGVAR_GDIR[index]}" ]]; then
								SC_ARGVAR_GDIR[index]=
							fi
							continue
						fi
						[[ ${iflag} -eq 4 ]] && echo
					fi

					# Done
					break
				done

			fi

			# Use answer
			SC_ARGVAR_GDIR[index]="${answer}"
		fi

		# append SC_ARGVAR_GDIR to the response log
		argvar_append_tofile_globaldir "${index}" ${SC_ILOG}

	done

	return 0
}

####################################################
#
# interactive_install_autoreboot() iflag
#
#	Set SC_REBOOT to NULL for no automatic reboot.
#	Otherwise, set it to non-NULL. 
#
#	iflag 1		- establish new cluster w/ this machine
#	iflag 2		- add this machine to an established cluster
#	iflag 3		- custom JumpStart client set up
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_autoreboot()
{
	integer iflag=${1}

	typeset sctxt_title="$(gettext '
		>>> Automatic Reboot <<<
	')"
	typeset sctxt_i1_p1="$(gettext '
		Once scinstall has successfully installed and
		initialized the Sun Cluster software for this machine,
		it will be necessary to reboot.  After the reboot, this
		machine will be established as the first node in the
		new cluster.
	')"
	typeset sctxt_i2_p1="$(gettext '
		Once scinstall has successfully installed and
		initialized the Sun Cluster software for this machine,
		it will be necessary to reboot.  The reboot
		will cause this machine to join the cluster for the
		first time.
	')"
	typeset sctxt_p2="$(gettext '
		You will need to manually reboot this node in \"cluster
		mode\" after scinstall successfully completes.
	')"

	typeset answer

	#
	# Print help and check iflag
	#
	case ${iflag} in
	'1')  # new cluster
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_i1_p1}"
		;;

	'2')  # add node
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_i2_p1}"
		;;

	*)    # invalid argument
		return 1
		;;
	esac

	# Auto reboot?
	answer=$(sc_prompt_yesno "$(gettext 'Do you want scinstall to reboot for you?')" "${YES}") || return 1

	if [[ "${answer}" = "yes" ]]; then
		SC_REBOOT=1
	else
		SC_REBOOT=
		sc_print_para "${sctxt_p2}"
		sc_prompt_pause || return 1
	fi

	return 0
}

#####################################################
#
# interactive_install_patches_check_dirname dirname install_flag
#
#	dirname        - user supplied directory name
#	install_flag   - install option
#
# Perform basic sanity checking on a user provided 
# directory name
#
#	Returns 0 if the user specified a valid 
#	directory
#	Returns >0 if invalid directory was entered
#
#####################################################
interactive_install_patches_check_dirname()
{

	typeset -r dirname=$1
	typeset -r install_flag=$2
	typeset parsed_dir

	# Directory name must begin with /
	if [[ "${dirname}" != /* ]]; then
		printf "$(gettext 'The directory name must begin with slash (/).')\n\n\a"
		return 1
	fi
	
	# Make sure it is a directory
	if [[ ! -d "${dirname}" ]]; then
		printf "$(gettext 'Cannot find directory \"%s\".')\n\n\a" "${dirname}"
		return 1
	fi

	# If jumpstart setup, check that the directory is mountable
	if [[ ${install_flag} -eq 3 ]]; then
		set -A parsed_dir $(autoclient_fs ${dirname} ${mynodename})
		if [[ -z "${parsed_dir[0]}" ]] || [[ -z "${parsed_dir[1]}" ]]; then
			printf "$(gettext 'Invalid directory \"%s\".')\n\n\a" "${dirname}"
			return 1
		fi
		mkdir -m 0755 ${tmp_mntpnt}
		if [[ $? -ne 0 ]]; then
			printf "$(gettext 'Internal error, cannot create directory \"%s\".')\n\n\a" "${tmp_mntpnt}"
			return 1
		fi

		mount -F nfs -o ro ${parsed_dir[0]}:${parsed_dir[1]} ${tmp_mntpnt} >/dev/null 2>&1
		if [[ $? -ne 0 ]]; then
			printf "$(gettext 'Cannot NFS mount \"%s:%s\", please provide a directory that can be NFS mounted.')\n\n\a" "${parsed_dir[0]}" "${parsed_dir[1]}"
			rm -rf ${tmp_mntpnt}
			return 1
		fi
		umount ${tmp_mntpnt}
		rm -rf ${tmp_mntpnt}
	fi
	
	return 0
}

#####################################################
#
# interactive_install_patches_check_filename dirname filename 
#
#	dirname - preset patch directory 
#	filename - user supplied patch list file 
#
# Perform basic sanity checking on a user provided 
# patch list file
#
#	Returns 0 if the user specified a valid 
#	patch list file
#	Returns >0 if invalid file was entered
#
#####################################################
interactive_install_patches_check_filename()
{

	typeset -r dirname=$1
	typeset -r filename=$2

	typeset bad_entries=

	# file name must not contain /
	if [[ "${filename}" = */* ]]; then
		printf "$(gettext 'The file name must not contain any slash (/).')\n\n\a"
		return 1
	fi
	
	# Make sure it is a readable file
	if [[ ! -r "${dirname}/${filename}" ]]; then
		printf "$(gettext 'Cannot access file \"%s\".')\n\n\a" "${filename}"
		return 1
	fi

	# Make sure there is only one entry per line
	bad_entries="$(cat ${dirname}/${filename} | /usr/bin/nawk '{print $2}')"
	if [[ -n ${bad_entries} ]]; then
		printf "$(gettext 'More than one entry per line specified in \"%s\".')\n\n\a" "${filename}"
		return 1
	fi
		
	return 0
}

####################################################
#
# interactive_install_patches() iflag
#
#	Set SC_ARGVAR_PATCHDIR and SC_ARGVAR_PATCHFILE
#	then add to the response log.
#
#	iflag 1		- establish new cluster w/ this machine
#	iflag 2		- add this machine to an established cluster
#	iflag 3		- custom JumpStart client set up
#	iflag 4		- centralized install
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_patches()
{
	integer iflag=${1}

	typeset sctxt_title="$(gettext '
		>>> Software Patch Installation <<<
	')"
	typeset sctxt_p1="$(gettext '
		If there are any Solaris or Sun Cluster patches that need to be
		added as part of this Sun Cluster installation, scinstall can 
		add them for you.   All patches that need to be added must 
		first be downloaded into a common patch directory. Patches can 
		be downloaded into the patch directory either as individual 
		patches or as patches grouped together into one or more tar, 
		jar, or zip files.
	')"
	typeset sctxt_p2="$(gettext '
		If a patch list file is provided in the patch directory, only 
		those patches listed in the patch list file are installed. 
		Otherwise, all patches found in the directory will be 
		installed. Refer to the patchadd(1M) man page for more 
		information regarding patch list files.
	')"

	typeset answer
	typeset dflt_answer
	typeset trial_file
	typeset dflt_patchdir
	typeset dir
	typeset dirs

	#
	# Print help and check iflag
	#
	case ${iflag} in
	'1' | '2' | '3' | '4')
		;;

	*)    # invalid argument
		return 1
		;;
	esac

	#
	# Set the dflt_patchdir from SC_DFLT_PATCHDIRS 
	#
	dflt_patchdir=
	if [[ -n "${SC_DFLT_PATCHDIRS}" ]]; then
		dirs="$(IFS=: ; set -- ${SC_DFLT_PATCHDIRS}; echo $*)"
		for dir in ${dirs}
		do
			if [[ -d "${dir}" ]]; then
				dflt_patchdir=${dir}
				break
			fi
		done
	fi

	#
	# If this is a typical install, default to installing patches and return
	#
	if [[ ${SC_TYPICAL_INSTALL} -eq 1 ]]; then

		# Initialize
		SC_ARGVAR_PATCHDIR=
		SC_ARGVAR_RESPONSE_PATCHDIR=
		SC_ARGVAR_PATCHFILE=

		# If the default patch directory exists, try to install patches.
		if [[ -n "${dflt_patchdir}" ]]; then
			SC_ARGVAR_PATCHDIR=${dflt_patchdir}

			# Use a patch list file?
			if [[ -f ${SC_ARGVAR_PATCHDIR}/${SC_DFLT_PATCHFILE} ]]; then
				SC_ARGVAR_PATCHFILE=${SC_DFLT_PATCHFILE}
			fi
		fi

		# append SC_ARGVAR_PATCHDIR to the response log
		argvar_append_tofile_patchdir ${SC_ILOG}

		# append SC_ARGVAR_PATCHFILE to the response log
		argvar_append_tofile_patchfile ${SC_ILOG}

		return 0
	fi

	#
	# Print help
	#
	clear
	sc_print_title "${sctxt_title}"
	sc_print_para "${sctxt_p1}"
	sc_print_para "${sctxt_p2}"

	# Install patches?
	answer=$(sc_prompt_yesno "$(gettext 'Do you want scinstall to install patches for you?')" "${YES}") || return 1
	if [[ "${answer}" != "yes" ]]; then

		# clear patch variables
		SC_ARGVAR_PATCHDIR=
		SC_ARGVAR_RESPONSE_PATCHDIR=
		SC_ARGVAR_PATCHFILE=

		# append SC_ARGVAR_PATCHDIR to the response log
		argvar_append_tofile_patchdir ${SC_ILOG}

		# append SC_ARGVAR_PATCHFILE to the response log
		argvar_append_tofile_patchfile ${SC_ILOG}

		return 0
	fi

	if [[ ${iflag} -eq 3 ]]; then
		dflt_answer=
		if [[ -d "${SC_ARGVAR_RESPONSE_PATCHDIR}" ]]; then
			dflt_answer="${SC_ARGVAR_RESPONSE_PATCHDIR}"
		fi
		if [[ -z "${dflt_answer}" ]]; then
			if [[ -d ${SC_ARGVAR_JUMPSTARTDIR}/patches ]]; then
				dflt_answer=${SC_ARGVAR_JUMPSTARTDIR}/patches
			fi
		fi	
		while true
		do
			answer=$(sc_prompt "$(gettext 'What is the name of the patch directory?')" "${dflt_answer}") || return 1
			interactive_install_patches_check_dirname "${answer}" ${iflag}
			if [[ $? -eq 0 ]]; then
				SC_ARGVAR_PATCHDIR="${answer}"
				SC_ARGVAR_RESPONSE_PATCHDIR="${answer}"
		
				break
			else
				dflt_answer=
				continue
			fi
		done

		sc_print_para "${sctxt_p2}"

		dflt_answer=
		if [[ -n "${SC_ARGVAR_PATCHFILE}" ]]; then
			dflt_answer="${SC_ARGVAR_PATCHFILE}"
		else
			trial_file=$(ls -1 ${SC_ARGVAR_PATCHDIR}/*list* 2>/dev/null | /usr/bin/head -1)
			if [[ -n ${trial_file} ]]; then
				/usr/bin/file ${trial_file} | /usr/bin/grep -i text >/dev/null 2>&1
				if [[ $? -eq 0 ]]; then
					dflt_answer=${trial_file##*/}
				fi
			fi
		fi
			
		while true
		do
			if [[ -n "${dflt_answer}" ]]; then
				answer=$(sc_prompt_yesno "$(gettext 'Do you want scinstall to use a patch list file?')" "${YES}") || return 1
			else
				answer=$(sc_prompt_yesno "$(gettext 'Do you want scinstall to use a patch list file?')" "${NO}") || return 1
			fi
					
			if [[ "${answer}" != "yes" ]]; then
				SC_ARGVAR_PATCHFILE=
				break
			fi
					
			answer=$(sc_prompt "$(gettext 'What is the name of the patch list file?')" "${dflt_answer}") || return 1
			interactive_install_patches_check_filename "${SC_ARGVAR_PATCHDIR}" "${answer}" 
			if [[ $? -ne 0 ]]; then
				dflt_answer=
				continue
			else
				SC_ARGVAR_PATCHFILE="${answer}"
				break
			fi
		done
	else
		if [[ -d ${SC_ARGVAR_PATCHDIR} ]]; then
			dflt_answer="${SC_ARGVAR_PATCHDIR}"
		elif [[ -n "${dflt_patchdir}" ]]; then
			dflt_answer="${dflt_patchdir}"
		else
			dflt_answer=
		fi
			
		while true
		do
			answer=$(sc_prompt "$(gettext 'What is the name of the patch directory?')" "${dflt_answer}") || return 1
			interactive_install_patches_check_dirname "${answer}" ${iflag}
			if [[ $? -eq 0 ]]; then
				SC_ARGVAR_PATCHDIR="${answer}"
				break
			else
				continue
			fi
		done
		
		sc_print_para "${sctxt_p2}"

		dflt_answer=
		if [[ -n "${SC_ARGVAR_PATCHFILE}" ]]; then
			dflt_answer="${SC_ARGVAR_PATCHFILE}"
		else
			trial_file=$(ls -1 ${SC_ARGVAR_PATCHDIR}/*list* 2>/dev/null | /usr/bin/head -1)
			if [[ -n ${trial_file} ]]; then
				/usr/bin/file ${trial_file} | /usr/bin/grep -i text >/dev/null 2>&1
				if [[ $? -eq 0 ]]; then
					dflt_answer=${trial_file##*/}
				fi
			fi
		fi
		while true
		do
			if [[ -n "${dflt_answer}" ]]; then
				answer=$(sc_prompt_yesno "$(gettext 'Do you want scinstall to use a patch list file?')" "${YES}") || return 1
			else
				answer=$(sc_prompt_yesno "$(gettext 'Do you want scinstall to use a patch list file?')" "${NO}") || return 1
			fi
					
			if [[ "${answer}" != "yes" ]]; then
				SC_ARGVAR_PATCHFILE=
				break
			fi
			answer=$(sc_prompt "$(gettext 'What is the name of the patch list file?')" "${dflt_answer}") || return 1
			interactive_install_patches_check_filename "${SC_ARGVAR_PATCHDIR}" "${answer}"
			if [[ $? -ne 0 ]]; then
				continue
			else
				SC_ARGVAR_PATCHFILE="${answer}"
				break
			fi
		done
	fi

	# append SC_ARGVAR_PATCHDIR to the response log
	argvar_append_tofile_patchdir ${SC_ILOG}

	# append SC_ARGVAR_PATCHFILE to the response log
	argvar_append_tofile_patchfile ${SC_ILOG}

	return 0
}

####################################################
#
# interactive_install_confirmation() iflag
#
#	Confirmation.
#
#	iflag 1		- establish new cluster w/ this machine
#	iflag 2		- add this machine to an established cluster
#	iflag 3		- custom JumpStart client set up
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_confirmation()
{
	integer iflag=${1}

	typeset sctxt_title="$(gettext '
		>>> Confirmation <<<
	')"
	typeset sctxt_p1="$(gettext '
		Your responses indicate the following options to scinstall:
	')"
	typeset sctxt_prompt_exists_1="$(gettext '
		JumpStart configuration data already exists for this node.')"
	typeset sctxt_prompt_exists_2="$(gettext '
		Is it okay to update it?')"
	typeset sctxt_prompt_opts="$(gettext '
		Are these the options you want to use?')"
	typeset sctxt_line="-----------------------------------------"
	typeset sctxt_nodename=" $(gettext 'For node \"%s\",')\n"

	integer index
	typeset answer
	typeset new_indices

	# Check iflag
	case ${iflag} in
	'1' | '2' | '3')
		;;

	*)    # invalid argument
		return 1
		;;
	esac

	# Print heading
	clear
	sc_print_title "${sctxt_title}"
	sc_print_para "${sctxt_p1}"

	# For each node, print command
	new_indices=
	for index in ${SC_INDICES}
	do

		case ${iflag} in 
		'1' | '2') 
			# Just print the command 
			argvar_print_SC_ARGVARS "${index}" "scinstall -ik" ""
			new_indices="${new_indices} ${index}"
			;; 
 
		'3')
			# Print the nodename, then the command 
			printf "${sctxt_line}\n\n"
			printf "${sctxt_nodename}" "${SC_ARGVAR_NODENAME[index]}"                        
			argvar_print_SC_ARGVARS "${index}" "scinstall -c ${SC_ARGVAR_JUMPSTARTDIR} -h ${SC_ARGVAR_NODENAME[index]}" ""

			# If already configured, okay to skip it?
			if [[ -s ${SC_ARGVAR_JUMPSTARTDIR}/${SC_AUTOSCCONFIGDIR}/${SC_ARGVAR_NODENAME[index]}/${SC_AUTOSCDATA} ]]; then
				sc_print_prompt "${sctxt_prompt_exists_1}"
				printf "\n"
				answer=$(sc_prompt_yesno "${sctxt_prompt_exists_2}" "${YES}") || return 1
				if [[ "${answer}" != "yes" ]]; then
					continue
				fi
			fi
			new_indices="${new_indices} ${index}"
			;; 

		*)    # invalid argument                         
			return 1 
			;; 
		esac

		# Confirm options
		answer=$(sc_prompt_yesno "${sctxt_prompt_opts}" "${YES}") || return 1
		if [[ "${answer}" != "yes" ]]; then
			return 1
		fi
	done

	# The "new_indices" are the ones we do NOT want to skip
	SC_INDICES="${new_indices}"

	# Are we done?
	if [[ -z "${SC_INDICES}" ]]; then
		return 1
	fi

	# Prompt - okay to continue?
	case ${iflag} in
	'1' | '2')
		answer=$(sc_prompt_yesno "$(gettext 'Do you want to continue with the install?')" "${YES}") || return 1
		;;

	'3')  # custom JumpStart
		printf "${sctxt_line}\n\n"
		answer=$(sc_prompt_yesno "$(gettext 'Do you want to continue with JumpStart set up?')" "${YES}") || return 1
		;;

	*)    # invalid option
		return 1
		;;
	esac

	# Okay to continue?
	if [[ "${answer}" != "yes" ]]; then
		return 1
	fi

	# Yes, continue with install or JumpStart set up
	return 0
}

####################################################
#
# interactive_install_confirmation_centralized()
#
#	Confirmation for centralized install.   Also, asks the
#	user if they want to interrupt the install on an sccheck
#	failure and sets SC_SCCHECK_INTR to non-null if the
#	answer is yes.
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_confirmation_centralized()
{
	typeset sctxt_title_installation="$(gettext '
		Installation and Configuration
	')"
	typeset sctxt_sccheck_p1="$(gettext '
		During the installation process, sccheck(1M) is run on
		each of the new cluster nodes.   If sccheck(1M) detects
		problems, you can either interrupt the installation
		process or check the log files after installation has
		completed.
	')"

	typeset answer
	typeset msg

	# Okay to start the installation?
	printf "\n\n"
	answer=$(sc_prompt_yesno "$(gettext 'Is it okay to begin the installation?')" "${YES}") || return 1
	if [[ "${answer}" != "yes" ]]; then
		return 1
	fi

	# Interrupt for sccheck messages?
	sc_print_para "${sctxt_sccheck_p1}"
	answer=$(sc_prompt_yesno "$(gettext 'Interrupt the installation for sccheck errors?')" "${NO}") || return 1
	if [[ "${answer}" == "yes" ]]; then
		SC_SCCHECK_INTR=1
	else
		SC_SCCHECK_INTR=
	fi

	# Start the install
	clear
	sc_print_title "${sctxt_title_installation}"
	msg="$(printf "$(gettext 'Log file - %s')" "${install_log}")"
	sc_print_para "${msg}"

	# Add message to install log
	echo "----------------------------------" >>${install_log}
	printf "- $(gettext 'Installation and Configuration') -\n" >>${install_log}
	echo "----------------------------------" >>${install_log}
	echo >>${install_log}

	# Done
	return 0
}

####################################################
#
# interactive_install_framework_centralized() iflag
#
#	Check the install status of each of the nodes.  If necessary,
#	generate download files for the framework CD image and for
#	patches.   Download the files to the other nodes.
#
#	Install core software on all of the cluster nodes, if necessary.
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_framework_centralized()
{
	typeset release_file=${SC_TOOLSDIR}/dot.release

	integer result
	integer i
	integer j
	integer use_gzip
	integer size
	integer installneeded
	integer installremote
	integer cdromsize
	integer zipfilesize
	integer errors
	integer abort

	typeset node
	typeset nodes
	typeset nodes2
	typeset installed_flags
	typeset configured_flags
	typeset isinstalling_flags
	typeset msg
	typeset foo
	typeset release
	typeset archivedir
	typeset zipfile
	typeset tmpzipfile
	typeset patch_zipfile
	typeset patch_tmpzipfile
	typeset cdimage
	typeset tmpcdimage
	typeset do_patches
	typeset patch_image
	typeset patch_tmpimage
	typeset toolsdir
	typeset cdimagebasedir
	typeset patchdir
	typeset oebasedir
	typeset path
	typeset cmd
	typeset pid
	typeset pids
	typeset pids2
	typeset flag
	typeset saved_logfilename

	# Arrays for packages and patches; packages first, patches second
	typeset zipfiles		# zip file names
	typeset tmpzipfiles		# temporary zip file names
	typeset imagedirs		# image directories
	typeset tmpimagedirs		# temporary image directories
	typeset basedirs		# base directories for creating zips
	typeset excludefiles		# exclude files for tars
	typeset zipsnotfound		# zip files not found
	typeset imagesnotfound		# images not found

	#
	# Reset globals.
	# Note that these globals will be NULL if the wizards ("scrcmd")
	# were used to install the Sun Cluster software.
	#
	SC_CDIMAGE=
	SC_TMPCDIMAGE=
	SC_PATCH_IMAGE=
	SC_PATCH_TMPIMAGE=
	SC_ZIPFILE=
	SC_TMPZIPFILE=
	SC_PATCH_ZIPFILE=
	SC_PATCH_TMPZIPFILE=

	# If we are using scrcmd, we must be fully installed on all nodes
	if [[ "${SC_REMOTE_METHOD}" == "scrcmd" ]]; then
		return 0
	fi

	# Set patchdir and do_patches flag
	patchdir=${SC_ARGVAR_PATCHDIR}
	if [[ -n "${patchdir}" ]] && [[ -d "${patchdir}" ]]; then
		do_patches=${SC_TRUE}
	else
		do_patches=
	fi

	#
	# See if all of the nodes are fully installed
	#

	# Print message
	echo >>${install_log}
	sc_print_line "$(gettext 'Checking installation status ... ')" | logmsg
	echo >>${install_log}

	# Look at each node
	installed_flags=
	configured_flags=
	isinstalling_flags=
	let installneeded=0
	let installremote=0
	let abort=0
	let use_gzip=1
	for node in ${SC_ARGVAR_NODENAME[*]}
	do
		# This node
		if [[ "${node}" == "${mynodename}" ]]; then

			# Check for installed
			if [[ -f "${SC_INSTALLED_FILE}" ]]; then
				installed_flags="${installed_flags} 1"

			else
				installed_flags="${installed_flags} 0"
				((installneeded += 1))
			fi

			#
			# This node cannot already be configured and
			# there cannot already be another scinstall process
			# running on this node;   we already checked for
			# these things on this node.
			#
			configured_flags="${configured_flags} 0"
			isinstalling_flags="${isinstalling_flags} 0"

			# Check for gzip
			if [[ ! -x /usr/bin/gzip ]]; then
				let use_gzip=0
			fi
			continue;
		fi

		#
		# Other nodes
		#

		# Is it installed?
		interactive_install_cmd ${node} "/usr/bin/test -f ${SC_INSTALLED_FILE}" >/dev/null 2>&1
		result=$?
		case ${result} in
		0)    # found install file
			installed_flags="${installed_flags} 1"

			# Lets see if scinstall is already running
			interactive_install_cmd ${node} "test isinstalling" >/dev/null 2>&1
			result=$?
			case ${result} in
			0)    # scinstall is NOT already running
				isinstalling_flags="${isinstalling_flags} 0"
				;;

			1)    # scinstall IS already running
				isinstalling_flags="${isinstalling_flags} 1"
				if [[ ${abort} -eq 0 ]]; then
					let abort=1
				fi
				;;

			*)    # error
				printf "%s\n\n" ${SC_FAILED}
				printf "$(gettext 'Remote commands to one or more of the other nodes failed.')\n" | logmsg
				interactive_printlogmsg "${install_log}"
				sc_prompt_pause
				return 1
				;;
			esac
			;;

		1)    # install file not found
			installed_flags="${installed_flags} 0"
			((installneeded += 1))
			((installremote += 1))

			#
			# We can't easily check to see if scinstall is
			# already running until "cmd_test" is installed.
			# But, if it is, this will be caught when the
			# install attempt fails.
			#
			isinstalling_flags="${isinstalling_flags} 0"
			;;

		*)    # error
			printf "%s\n\n" ${SC_FAILED}
			printf "$(gettext 'Remote commands to one or more of the other nodes failed.')\n" | logmsg
			interactive_printlogmsg "${install_log}"
			sc_prompt_pause
			return 1
			;;
		esac

		# Is it configured?
		interactive_install_cmd ${node} "/usr/bin/test -f ${SC_NODEID}" >/dev/null 2>&1
		result=$?
		case ${result} in
		0)    # found nodeid file
			configured_flags="${configured_flags} 1"
			let abort=2
			;;

		1)    # install file not found
			configured_flags="${configured_flags} 0"
			;;

		*)    # error
			printf "%s\n\n" ${SC_FAILED}
			printf "$(gettext 'Remote commands to one or more of the other nodes failed.')\n" | logmsg
			interactive_printlogmsg "${install_log}"
			sc_prompt_pause
			return 1
			;;
		esac

		# Make sure we can use gzip
		interactive_install_cmd ${node} "/usr/bin/test -x /usr/bin/gzcat" >/dev/null 2>&1
		if [[ $? -ne 0 ]]; then
			let use_gzip=0
		fi
	done

	# Get the size of the packages on the CD for this os release
	let cdromsize=0
	if [[ ${installremote} -gt 0 ]] &&
	    [[ -n "${SC_PACKAGESDIR}" ]] &&
	    [[ -d "${SC_PACKAGESDIR}" ]]; then

		# Packages
		cmd="du -ks ${SC_PACKAGESDIR}"
		echo >>${install_log}
		echo ${cmd} >>${install_log}
		foo="$(eval ${cmd} 2>>${install_log})"
		if [[ -n "${foo}" ]]; then
			let cdromsize=$(set -- ${foo}; echo $1)
		fi

		# Patches
		if [[ -n "${do_patches}" ]]; then
			cmd="du -ks ${patchdir}"
			echo >>${install_log}
			echo ${cmd} >>${install_log}
			foo="$(eval ${cmd} 2>>${install_log})"
			if [[ -n "${foo}" ]]; then
				let i=$(set -- ${foo}; echo $1)
				((cdromsize += i))
			fi
		fi

		# Check size
		if [[ ${cdromsize} -gt 0 ]]; then
			printf "$(gettext 'Disk space required for packages is %dKb.')\n" ${cdromsize} >>${install_log}

			# Adjust it by adding 10%
			i=$((cdromsize / 10))
			((cdromsize += i))
			printf "$(gettext 'Adjusted (by 10%%) disk space requirement for packages is %dKb.')\n" ${cdromsize} >>${install_log}
		else
			printf "%s\n\n" ${SC_FAILED}
			printf "$(gettext 'Unable to determine disk space required by Sun Cluster packages.')\n" | logmsg
			interactive_printlogmsg "${install_log}"
			sc_prompt_pause
			return 1
		fi
	fi

	# Done determining install status
	printf "%s\n\n" ${SC_DONE}
	echo >>${install_log}

	set -A SC_INSTALLFLAGS ${installed_flags}

	# Print status of each node
	let i=0
	set -A installed_flags ${installed_flags}
	set -A configured_flags ${configured_flags}
	set -A isinstalling_flags ${isinstalling_flags}
	for flag in ${installed_flags[*]}
	do
		if [[ "${isinstalling_flags[i]}" == "1" ]]; then
			msg="$(printf "$(gettext '%s is already running on \"%s\".')" ${PROG} ${SC_ARGVAR_NODENAME[i]})" 
		elif [[ "${configured_flags[i]}" == "1" ]]; then
			msg="$(printf "$(gettext '\"%s\" is already configured as a Sun Cluster node.')" ${SC_ARGVAR_NODENAME[i]})" 
		elif [[ "${installed_flags[i]}" == "0" ]]; then
			msg="$(printf "$(gettext 'The Sun Cluster software is not installed on \"%s\".')" ${SC_ARGVAR_NODENAME[i]})"
		else
			msg="$(printf "$(gettext 'The Sun Cluster software is already installed on \"%s\".')" ${SC_ARGVAR_NODENAME[i]})"
		fi
		printf "    %s\n" "${msg}" | logmsg
		((i += 1))
	done
	echo | logmsg

	#
	# If one of the nodes is already configured or if scinstall is
	# already running, we cannot proceed.   The only exception to
	# this would be as part of a "recovery", where we have some confidence
	# that any configured nodes were configured by us.
	#
	if [[ ${abort} -ne 0 ]]; then
		case ${abort} in 
		1)    # scinstall is already running somewhere
			printf "$(gettext 'Unable to continue as long as %s is already running.')\n\n" "${PROG}" | logmsg
			echo "\a\c"
			;;

		2)    # one of the nodes is already configured
			printf "$(gettext '%s cannot be used to re-configure already configured nodes.')\n\n" "${PROG}" | logmsg
			;;
		esac
		echo "\a\c"
		sc_prompt_pause
		return 1
	fi

	# Set the release name
	if [[ -f "${release_file}" ]]; then
		release=$(print_release "" ${release_file} 2>/dev/null)
	else
		release=$(print_release "" "" 2>/dev/null)
	fi
	if [[ -z "${release}" ]]; then
		release=generic
	fi
	if [[ -n "${SC_OE_SCINSTALLDIR}" ]]; then
		release=${release}_${SC_OE_SCINSTALLDIR}
	fi

	#
	# Set the directory names and zipfile names
	#
	# If gzip/gzcat is not installed, we just create a tar file,
	# rather than a zip file.
	#
	archivedir=/var/cluster/releases/suncluster/${release}
	cdimage=${archivedir}/suncluster_${release}.d
	tmpcdimage=${archivedir}/suncluster_${release}.tmp.d
	patch_image=${archivedir}/patches_${release}.d
	patch_tmpimage=${archivedir}/patches_${release}.tmp.d
	if [[ ${use_gzip} -eq 0 ]]; then
		zipfile=${archivedir}/suncluster_${release}.tar
		tmpzipfile=${archivedir}/tmp.tar
		patch_zipfile=${archivedir}/patches_${release}.tar
		patch_tmpzipfile=${archivedir}/patches_tmp.tar
	else
		zipfile=${archivedir}/suncluster_${release}.tgz
		tmpzipfile=${archivedir}/tmp.tgz
		patch_zipfile=${archivedir}/patches_${release}.tgz
		patch_tmpzipfile=${archivedir}/patches_tmp.tgz
	fi

	#
	# Set globals for later use in patch install and cleanup
	# Note that these variables will be NULL if the wizards ("scrcmd")
	# were used to install the Sun Cluster software.
	#
	SC_ZIPFILE=${zipfile}
	SC_TMPZIPFILE=${tmpzipfile}
	SC_PATCH_ZIPFILE=${patch_zipfile}
	SC_PATCH_TMPZIPFILE=${patch_tmpzipfile}

	SC_CDIMAGE=${cdimage}
	SC_TMPCDIMAGE=${tmpcdimage}
	SC_PATCH_IMAGE=${patch_image}
	SC_PATCH_TMPIMAGE=${patch_tmpimage}

	# Are we done?
	if [[ ${installneeded} -eq 0 ]]; then
		return 0
	fi

	#
	# Make sure we are being run from the CD
	#
	if [[ -z "${SC_PACKAGESDIR}" ]] ||
	    [[ ! -d "${SC_PACKAGESDIR}" ]]; then
		printf "$(gettext 'Since installation is required, scinstall must be run from the CDROM.')\n\n" | logmsg
		echo "\a\c"
		sc_prompt_pause
		return 1
	fi

	#
	# Initialize variables
	#

	# Set the CD image base directory
	cdimagebasedir=${SC_TOOLSDIR}
	while [[ "${cdimagebasedir}" != "/" ]]
	do
		if [[ -f ${cdimagebasedir}/${SC_CDTOC} ]]; then
			break
		fi
		cdimagebasedir=$(dirname ${cdimagebasedir})
	done
	if [[ ! -f ${cdimagebasedir}/${SC_CDTOC} ]]; then
		printf "$(gettext 'Unable to locate the \"%s\" file on the CDROM.')\n\n" "${SC_CDTOC}" | logmsg
		echo "\a\c"
		sc_prompt_pause
		return 1
	fi

	# Set arrays
	set -A zipfiles ${zipfile} ${patch_zipfile}
	set -A tmpzipfiles ${tmpzipfile} ${patch_tmpzipfile}
	set -A imagedirs ${cdimage} ${patch_image}
	set -A tmpimagedirs ${tmpcdimage} ${patch_tmpimage}
	set -A basedirs ${cdimagebasedir} ${patchdir}
	set -A excludefiles
	set -A imagesnotfound
	set -A zipsnotfound

	# Set the relative path to the Tools directory
	toolsdir=$(expr ${SC_TOOLSDIR} : ${cdimagebasedir}/'\(.*\)')

	#
	# If there are any remote installs, create the zip/tar file
	#
	oebasedir=
	if [[ ${installremote} -gt 0 ]] &&
	    [[ ! -f ${zipfile} || ! -f ${patch_zipfile} ]]; then

		# Create our archive directory
		if [[ ! -d ${archivedir} ]]; then
			openfile ${archivedir}/.foo
			if [[ $? -ne 0 ]]; then
				printf "$(gettext 'Failed to create %s.')\n\n" "${archivedir}" | logmsg
				echo "\a\c"
				sc_prompt_pause
				return 1
			fi
			rm -r ${archivedir}/.foo
		fi

		# Make sure we have plenty of room for our zip file
		foo=$(LC_ALL=C; export LC_ALL;  df -k ${archivedir} | grep -v ^Filesystem | nawk '{ print $4 }')
		if [[ -z "${foo}" ]]; then
			printf "$(gettext 'Unable to determine the amount of available space in %s.')\n\n" "${archivedir}" | logmsg
			echo "\a\c"
			sc_prompt_pause
			return 1
		fi
		let size=0
		let size=${foo}
		if [[ ${size} -lt ${cdromsize} ]]; then
			printf "$(gettext 'There is not enough disk space on %s to create %s.')\n" "${mynodename}" "${zipfile}" | logmsg
			interactive_printlogmsg "${install_log}"
			sc_prompt_pause
			return 1
		fi

		# Set the OE base directory
		if [[ -n "${SC_OE_SCINSTALLDIR}" ]]; then
			oebasedir=${SC_TOOLSDIR}
			while [[ "${oebasedir}" != "/" ]]
			do
				if [[ -d ${oebasedir}/${SC_OE_SCINSTALLDIR} ]]; then
					break
				fi
				oebasedir=$(dirname ${oebasedir})
			done
			if [[ ! -d ${oebasedir}/${SC_OE_SCINSTALLDIR} ]]; then
				oebasedir=
			fi
		fi

		# If there is an oe base directory, exclude all other oes
		if [[ -n "${oebasedir}" ]]; then

			# Use the tmpfile for exclude
			rm -f ${tmpfile}

			# Set the path relative to the cdimagebasedir
			path=$(expr ${oebasedir} : ${cdimagebasedir}/'\(.*\)')

			# Exclude all but ourselves
			for foo in ${SC_NAMES_OE_VERS}
			do
				if [[ ${foo} != ${SC_OE_SCINSTALLDIR} ]]; then
					echo ./${path}/${foo} >>${tmpfile}
				fi
			done

			# Set the excludefile
			if [[ -s ${tmpfile} ]]; then
				excludefiles[0]=${tmpfile}
			else
				rm -f ${tmpfile}
			fi
		fi
			
		# Print message
		echo >>${install_log}
		sc_print_line "$(gettext 'Generating the download files ... ')" | logmsg
		echo >>${install_log}

		# Create tar/zip files
		let j=0
		while [[ -n "${zipfiles[j]}" ]]
		do
			# If patches, make sure we are doing patches
			if [[ "${zipfiles[j]}" == "${patch_zipfile}" ]];then
				if [[ -z "${do_patches}" ]]; then
					((j += 1))
					continue
				fi
			fi

			# If the zipfile already exists, skip this
			if [[ -f "${zipfiles[j]}" ]]; then
				((j += 1))
				continue
			fi
				
			# Print message
			echo >>${install_log}
			printf "$(gettext 'Creating %s.')\n" "${zipfiles[j]}" >>${install_log}

			# Create the zip/tar
			create_zipfile "${basedirs[j]}" "${tmpzipfiles[j]}" "${use_gzip}" "${install_log}" "${excludefiles[j]}"
			result=$?
			if [[ -n "${excludefiles[j]}" ]]; then
				rm -f ${excludefiles[j]}
			fi
			if [[ ${result} -ne 0 ]]; then
				printf "%s\n\n" ${SC_FAILED}
				interactive_printlogmsg "${install_log}"
				sc_prompt_pause
				rm -f ${tmpzipfiles[j]}
				return 1
			fi

			# rename
			cmd="mv ${tmpzipfiles[j]} ${zipfiles[j]}"
			echo ${cmd} >>${install_log}
			eval ${cmd} >>${install_log} 2>&1 || return 1

			# Next
			((j += 1))
		done

		# Done
		printf "%s\n\n" ${SC_DONE}
	fi

	#
	# Calculate zipfile size
	#
	let zipfilesize=0
	let j=0
	while [[ -n "${zipfiles[j]}" ]]
	do

		# zipfile size
		if [[ -r "${zipfiles[j]}" ]]; then
			cmd="du -k ${zipfiles[j]}"
			foo="$(eval ${cmd} 2>>${install_log})"
			if [[ -n "${foo}" ]]; then
				let i=$(set -- ${foo}; echo $1)
				((zipfilesize += i))
			fi
		fi

		# Next
		((j += 1))
	done
	if [[ ${zipfilesize} -gt 0 ]]; then

		# Print zipfilesize to log
		echo >>${install_log}
		printf "$(gettext 'Disk space required for tar/gzip files is %dKb.')\n" ${zipfilesize} >>${install_log}

		# Adjust it by adding 10%
		i=$((zipfilesize / 10))
		((zipfilesize += i))
		printf "$(gettext 'Adjusted (by 10%%) disk space requirement for tar/gzip files is %dKb.')\n" ${zipfilesize} >>${install_log}
		echo >>${install_log}
	fi

	#
	# Begin download to each node
	#
	let i=0
	pids=
	set -A nodes
	for flag in ${installed_flags[*]}
	do
		# If already installed, skip it
		if [[ ${flag} == 1 ]]; then
			((i += 1))
			continue
		fi

		# Set node name
		node=${SC_ARGVAR_NODENAME[i]}

		# If this node, skip
		if [[ "${mynodename}" == "${node}" ]]; then
			((i += 1))
			continue
		fi

		#
		# Do download
		#
		# Return values from each background subprocess:
		#
		#	0 	- success
		#	1	- failure
		#	2	- download not required
		#
		(
			set -A imagesnotfound
			set -A zipsnotfound

			# Use temporary install log
			install_log=${install_log}.${node}
			rm -f ${install_log}

			#
			# See if we need to copy the zipfile
			#

			# Look for the installed images first
			let j=0
			while [[ -n "${imagedirs[j]}" ]]
			do

				# If patches, make sure we are doing patches
				if [[ "${zipfiles[j]}" == "${patch_zipfile}" ]];then
					if [[ -z "${do_patches}" ]]; then
						((j += 1))
						continue
					fi
				fi

				# check for image directory
				interactive_install_cmd ${node} "/usr/bin/test -d ${imagedirs[j]}" >/dev/null 2>&1
				result=$?
				case ${result} in
				0)    # found image
					;;

				1)    # no image
					imagesnotfound[j]=1
					;;

				*)    # error - return 1
					printf "$(gettext 'Remote command failed to %s.')\n" "${node}" >>${install_log}
					return 1
					;;
				esac

				# Next
				((j += 1))
			done

			#
			# If either the cdimage or patch image are missing,
			# we must continue.   Otherwise, we are done, since
			# we do not need the zip files if the images
			# are already unzipped.
			#
			if [[ -z "${imagesnotfound[*]}" ]]; then
				return 2
			fi

			# Look for the zip files next
			let j=0
			while [[ -n "${zipfiles[j]}" ]]
			do

				# If patches, make sure we are doing patches
				if [[ "${zipfiles[j]}" == "${patch_zipfile}" ]];then
					if [[ -z "${do_patches}" ]]; then
						((j += 1))
						continue
					fi
				fi

				# check for the zip file
				interactive_install_cmd ${node} "/usr/bin/test -f ${zipfiles[j]}" >/dev/null 2>&1
				result=$?
				case ${result} in
				0)    # found zipfile
					;;

				1)    # zipfile not found
					zipsnotfound[j]=1
					;;

				*)    # error - return 1
					printf "$(gettext 'Remote command failed to %s.')\n" "${node}" >>${install_log}
					return 1
					;;
				esac

				# Next
				((j += 1))
			done

			# If archive directory does not exist, create it
			interactive_install_cmd ${node} "/usr/bin/test -d ${archivedir}" >/dev/null 2>&1
			result=$?
			if [[ ${result} -eq 1 ]]; then
				interactive_install_cmd ${node} "umask 0; /usr/bin/mkdir -m 0755 /var/cluster /var/cluster/releases /var/cluster/releases/suncluster" "" "noprepend" >/dev/null 2>&1
				interactive_install_cmd ${node} "umask 0; /usr/bin/mkdir -m 0755 ${archivedir}" "" "noprepend" >/dev/null 2>&1
				if [[ $? -ne 0 ]]; then
					printf "$(gettext 'Unable to create %s on %s.')\n" "${archivedir}" "${node}" >>${install_log}
					return 1
				fi
				interactive_install_cmd ${node} "/usr/bin/chgrp sys /var/cluster /var/cluster/releases /var/cluster/releases/suncluster ${archivedir}" >/dev/null 2>&1
			fi

			# Remove any partial copies
			interactive_install_cmd ${node} "/usr/bin/rm -rf ${tmpzipfile} ${patch_tmpzipfile} ${tmpcdimage} ${patch_tmpimage}" >/dev/null 2>&1

			# Check available disk space for zipfile and cdimage
			foo=$(interactive_install_cmd ${node} "LC_ALL=C; export LC_ALL; /usr/bin/df -k ${archivedir}" "" "noprepend" 2>/dev/null | grep -v ^Filesystem | nawk '{ print $4 }')
			if [[ -z "${foo}" ]]; then
				printf "$(gettext 'Unable to determine the amount of available space in %s on %s.')\n" "${archivedir}" "${node}" >>${install_log}
				return 1
			fi
			let size=0
			let size=${foo}
			if [[ ${size} -lt $((cdromsize + zipfilesize)) ]]; then
				printf "$(gettext 'There is not enough available space on %s in %s to download the tar/gzip files.')\n" "${node}" "/var/cluster" >>${install_log}
				return 1
			fi

			# Download the zip files, as needed
			let j=0
			while [[ -n "${zipfiles[j]}" ]]
			do
				if [[ -z "${zipsnotfound[j]}" ]]; then
					((j += 1))
					continue
				fi

				# rcp or scp?
				if [[ "${SC_REMOTE_METHOD}" == "rsh" ]]; then
					cmd="rcp ${zipfiles[j]} ${node}:${tmpzipfiles[j]}"
				else
					cmd="scp -Bq ${zipfiles[j]} root@${node}:${tmpzipfiles[j]}"
				fi
				echo >>${install_log}
				echo ${cmd} >>${install_log}
				eval ${cmd} >>${install_log} 2>&1
				if [[ $? -ne 0 ]]; then
					printf "$(gettext 'Unable to copy %s to %s.')\n" "${zipfiles[j]}" "${node}" >>${install_log}
					return 1
				fi

				# Rename it
				interactive_install_cmd ${node} "/usr/bin/mv ${tmpzipfiles[j]} ${zipfiles[j]}" >/dev/null 2>&1
				if [[ $? -ne 0 ]]; then
					printf "$(gettext 'Unable to rename %s to %s on %s.')\n" "${tmpzipfiles[j]}" "${zipfiles[j]}" "${node}" >>${install_log}
					return 1
				fi

				# Next
				((j += 1))
			done

			# Expand the zip files, as needed
			let j=0
			while [[ -n "${zipfiles[j]}" ]]
			do
				if [[ -z "${imagesnotfound[j]}" ]]; then
					((j += 1))
					continue
				fi

				# Create the target directory
				interactive_install_cmd ${node} "umask 0; /usr/bin/mkdir -m 0755 ${tmpimagedirs[j]}" "" "noprepend" >/dev/null 2>&1
				interactive_install_cmd ${node} "/usr/bin/chgrp sys ${tmpimagedirs[j]}" >/dev/null 2>&1

				# Untar
				if [[ ${use_gzip} -eq 0 ]]; then
					cmd="/usr/bin/tar xf ${zipfiles[j]}"
				else
					cmd="/usr/bin/gzcat ${zipfiles[j]} | /usr/bin/tar xf -"
				fi
				interactive_install_cmd ${node} "cd ${tmpimagedirs[j]}; ${cmd}" "" "noprepend" >/dev/null 2>&1
				if [[ $? -ne 0 ]]; then
					printf "$(gettext 'Failed to expand %s on %s.')\n" "${zipfiles[j]}" "${node}" >>${install_log}
					return 1
				fi

				# Double-check CD copy
				if [[ "${zipfile}" == "${zipfiles[j]}" ]]; then
					interactive_install_cmd ${node} "/usr/bin/test -f ${tmpimagedirs[j]}/${SC_CDTOC}" >/dev/null 2>&1
					if [[ $? -ne 0 ]]; then
						printf "$(gettext 'Failed to expand %s on %s.')\n" "${tmpzipfile}" "${node}" >>${install_log}
						return 1
					fi
				fi

				# Identify this as ours
				interactive_install_cmd ${node} "/usr/bin/touch ${tmpimagedirs[j]}/${SC_CENTRALIZED_IDENTIFIER}" >/dev/null 2>&1

				# Rename the cd image
				interactive_install_cmd ${node} "/usr/bin/mv ${tmpimagedirs[j]} ${imagedirs[j]}" >/dev/null 2>&1
				if [[ $? -ne 0 ]]; then
					printf "$(gettext 'Unable to rename %s to %s on %s.')\n" "${tmpimagedirs[j]}" "${imagedirs[j]}" "${node}" >>${install_log}
					return 1
				fi

				# Delete the zip file
				interactive_install_cmd ${node} "/usr/bin/rm -f ${zipfiles[j]}" >/dev/null 2>&1

				# Next
				((j += 1))
			done
		) &
		pids="${pids} $!"
		nodes="${nodes} ${node}"

		# Print message
		msg="$(printf "$(gettext 'Started download of the Sun Cluster software to \"%s\".')" ${node})"
		printf "    %s\n" "${msg}" | logmsg

		# Next
		((i += 1))
	done
	echo | logmsg

	# Wait for each process to finish
	let i=0
	let errors=0
	set -A nodes ${nodes}
	for pid in ${pids}
	do
		node=${nodes[i]}

		wait ${pid}
		result=$?
		case ${result} in
		0)    # Finished
			msg="$(printf "$(gettext 'Finished download to \"%s\".')" "${node}")"
			;;

		2)    # Already downloaded
			msg="$(printf "$(gettext '\"%s\" was already downloaded.')" "${node}")"
			;;

		*)    # Error
			msg="$(printf "$(gettext 'Download failed to \"%s\".')" "${node}")"
			((errors += 1))
			;;
		esac
		printf "    %s\n" "${msg}" | logmsg

		# Next
		((i += 1))
	done
	echo | logmsg

	# Clean up log files
	interactive_cleanup_logfiles "${install_log}" "1" ${nodes[*]}

	# If there were any errors, we are done
	if [[ ${errors} -gt 0 ]]; then
		printf "$(gettext 'Failed to download the Sun Cluster software to all of the nodes.')\n" | logmsg
		interactive_printlogmsg "${install_log}"
		sc_prompt_pause
		return 1
	fi

	#
	# Begin to install each node
	#
	let i=0
	pids=
	set -A nodes
	saved_logfilename=${install_log}
	for flag in ${installed_flags[*]}
	do
		# If already installed, skip it
		if [[ ${flag} == 1 ]]; then
			((i += 1))
			continue
		fi

		# Set node name
		node=${SC_ARGVAR_NODENAME[i]}

		#
		# Do install of packages
		#
		(
			# Use temporary install log
			install_log=${install_log}.${node}
			rm -f ${install_log}

			# Launch scinstall
			if [[ "${mynodename}" == "${node}" ]]; then
				main -i >/dev/null 2>&1
				result=$?
			else
				interactive_install_cmd ${node} "cd ${cdimage}/${toolsdir}; SC_INSTALL_LOG=${saved_logfilename}; export SC_INSTALL_LOG; ./scinstall -i" "" "noprepend" >/dev/null 2>&1
				result=$?
			fi

			# install failed
			if [[ ${result} -ne 0 ]]; then
				printf "$(gettext 'Installation of the Sun Cluster sofware failed on \"%s\".')\n\n" "${node}" >>${install_log}
				printf "$(gettext 'Refer to \"%s\" on \"%s\" for details.')\n\n" "${saved_logfilename}" "${node}" >>${install_log}
			fi

			# done
			return ${result}
		) &
		pids="${pids} $!"
		nodes="${nodes} ${node}"

		# Print message
		msg="$(printf "$(gettext 'Started installation of the Sun Cluster software on \"%s\".')" ${node})"
		printf "    %s\n" "${msg}" | logmsg

		# Next
		((i += 1))
	done
	echo | logmsg

	# Wait for each process to finish
	let i=0
	let errors=0
	set -A nodes ${nodes}
	for pid in ${pids}
	do
		node=${nodes[i]}

		# Wait for the next process to complete
		wait ${pid}
		result=$?
		msg=
		case ${result} in
		0)    # Finished
			msg="$(printf "$(gettext 'Finished software installation on \"%s\".')" "${node}")"
			;;

		*)    # Error
			msg="$(printf "$(gettext 'Software installation failed on \"%s\".')" "${node}")"
			((errors += 1))
			;;
		esac
		if [[ -n "${msg}" ]]; then
			printf "    %s\n" "${msg}" | logmsg
		fi

		# Next
		((i += 1))
	done
	echo | logmsg

	# Clean up log files
	interactive_cleanup_logfiles "${install_log}" "1" ${nodes[*]}

	# If there were any errors from the install, return an error
	if [[ ${errors} -gt 0 ]]; then
		printf "$(gettext 'Failed to install the Sun Cluster software on one or more of the nodes.')\n" | logmsg
		interactive_printlogmsg "${install_log}"
		sc_prompt_pause
		return 1
	fi

	# Done
	return 0
}

####################################################
#
# interactive_remove_framework()
#
#	Remove framework packages.
#
#	This function always returns 0.
#
####################################################
interactive_remove_framework()
{
	typeset answer

	#
	# If the nodeid file exists, do not allow removal
	#
	if [[ -f "${SC_NODEID}" ]] ||
	    [[ ${SC_FRAMEWORK_INSTALLED} -eq 0 ]]; then
		return 0
	fi

	# Okay to remove packages?
	printf "\n"
	answer=$(sc_prompt_yesno "$(gettext 'Do you want to de-install the Sun Cluster software?')" "${NO}") || return 1
	if [[ "${answer}" != "yes" ]]; then
		return 0
	fi

	#
	# Remove packages (SC_FRAMEWORK_INSTALLED is set to 0 on success)
	#
	uninstallframework ${SC_DOT_CLUSTERTOC} ${SC_DOT_ORDER}
	sc_prompt_pause || return 1

	return 0
}

####################################################
#
# interactive_install_patchadd_centralized()
#
#	If we are configured to install patches, add patches to each
#	of the nodes.
#
#	Return values:
#		0	- success
#		1	- failure
#
####################################################
interactive_install_patchadd_centralized()
{
	typeset msg
	typeset node
	typeset nodes
	typeset pid
	typeset pids
	typeset patchdir
	typeset patcharg
	typeset logfilearg=
	typeset installed_nodes

	integer i
	integer errors
	integer result

	# Set patchdir
	patchdir=${SC_ARGVAR_PATCHDIR}

	#
	# If not configured for patch installation or if the patchdir
	# no longer exists, just return
	#
	if [[ -z "${patchdir}" ]]; then
		return 0
	fi

	# Set logfilearg
	if [[ -n "${SC_PATCH_INSTALL_LOG}" ]]; then
		logfilearg="-logfile ${SC_PATCH_INSTALL_LOG}"
	fi

	# Install patches on each of the nodes not yet patched
	pids=
	let i=0
	set -A nodes ${SC_ARGVAR_NODENAME[*]}
	installed_nodes=
	for node in ${nodes[*]}
	do
		# We do not want to install patches if we did not do a
		# install of sun cluster software on this node
		if [[ "${SC_INSTALLFLAGS[i]}" == "1" ]]; then
			(( i += 1))
			continue
		fi
		
		(( i += 1))

		# Set the patch argument
		if [[ "${node}" == "${mynodename}" ]] ||
		    [[ -z "${SC_PATCH_IMAGE}" ]]; then
			patcharg="-M patchdir=${patchdir}"
		else
			patcharg="-M patchdir=${SC_PATCH_IMAGE}"
		fi
		if [[ -n "${SC_ARGVAR_PATCHFILE}" ]]; then
			patcharg="${patcharg},patchlistfile=${SC_ARGVAR_PATCHFILE}"
		fi

		#
		# Do patch add
		#
		(
			# Use temporary install log
			install_log=${install_log}.${node}
			rm -f ${install_log}

			# Do it
			interactive_install_cmd ${node} "install ${patcharg} ${logfilearg}" >/dev/null 2>&1
			result=$?

			# done
			return ${result}
		) &
		pids="${pids} $!"
		installed_nodes="${installed_nodes} ${node}"

		# Print message
		msg="$(printf "$(gettext 'Started installation of patches on \"%s\".')" ${node})"
		printf "    %s\n" "${msg}" | logmsg
	done
	echo | logmsg

	# Wait for each process to finish
	let i=0
	let errors=0
	set -A installed_nodes ${installed_nodes}
	for pid in ${pids}
	do
		node=${installed_nodes[i]}

		# Wait for next process to complete
		wait ${pid}
		result=$?
		msg=
		case ${result} in
		0)    # Finished
			msg="$(printf "$(gettext 'Finished patch installation on \"%s\".')" ${node})"
			;;

		*)    # Error
			msg="$(printf "$(gettext 'Problems detected during extraction or installation of patches on \"%s\".')" ${node})"
			((errors += 1))
			;;
		esac
		if [[ -n "${msg}" ]]; then
			printf "    %s\n" "${msg}" | logmsg
		fi

		# Next
		((i += 1))
	done
	echo | logmsg

	# Clean up log files
	interactive_cleanup_logfiles "${install_log}" "1" ${nodes[*]}

	# If there were any errors from the install, return an error
        if [[ ${errors} -gt 0 ]]; then
		echo >>${install_log}
                printf "$(gettext 'Problems detected during extraction or installation of patches on one or more of the nodes.')\n" | logmsg
                interactive_printlogmsg "${install_log}"
		let result=1
	else
		let result=0
        fi

        # Done
        return ${result}           
}

####################################################
#
# interactive_install_cleanup_centralized()
#
#	Cleanup downloaded CD image and patch directories.
#
#	This function always returns 0.
#
####################################################
interactive_install_cleanup_centralized()
{
	typeset cdimage
	typeset patch_image
	typeset tmpcdimage
	typeset patch_tmpimage
	typeset imagedirs
	typeset tmpimagedirs

	typeset node
	typeset pid
	typeset pids

	#
	# Cleanup should not be necessary and does not work with
	# the "scrcmd" remote method
	#
	if [[ "${SC_REMOTE_METHOD}" == "scrcmd" ]]; then
		return 0
	fi

	# If the image global variables were not set, there is nothing to do
	if [[ -z "${SC_CDIMAGE}" ]] && [[ -z "${SC_PATCH_IMAGE}" ]]; then
		return 0
	fi

	#
	# Initialize variables
	#
	if [[ -n "${SC_CDIMAGE}" ]]; then
		cdimage=${SC_CDIMAGE}
		tmpcdimage=${SC_TMPCDIMAGE}
		if [[ -z "${tmpcdimage}" ]]; then
			tmpcdimage=${cdimage}.tmp.d
		fi
	fi
	if [[ -n "${SC_PATCH_IMAGE}" ]]; then
		patch_image=${SC_PATCH_IMAGE}
		patch_tmpimage=${SC_PATCH_TMPIMAGE}
		if [[ -z "${patch_tmpimage}" ]]; then
			patch_tmpimage=${patch_image}.tmp.d
		fi
	fi
	set -A imagedirs ${cdimage} ${patch_image}
	set -A tmpimagedirs ${tmpcdimage} ${patch_tmpimage}

	# Print message
	echo >>${install_log}
	sc_print_line "$(gettext 'Removing the downloaded files ... ')" | logmsg
	echo >>${install_log}

	# Cleanup each remote node, if necessary
	pids=
	for node in ${SC_ARGVAR_NODENAME[*]}
	do
		(
			# Don't bother to log anything
			install_log=/dev/null

			# If this node, just remove just the zip files
			if [[ "${node}" == "${mynodename}" ]]; then
				rm -rf ${SC_ZIPFILE} ${SC_TMPZIPFILE} ${SC_PATCH_ZIPFILE} ${SC_PATCH_TMPZIPFILE}
				return 0
			fi

			# Rename and remove
			let j=0
			while [[ -n "${imagedirs[j]}" ]]
			do

				# Check image, to see if is ours
				interactive_install_cmd ${node} "/usr/bin/test -f ${imagedirs[j]}/${SC_CENTRALIZED_IDENTIFIER}" >/dev/null 2>&1
				if [[ $? -ne 0 ]]; then
					((j += 1))
					continue
				fi

				# Rename
				interactive_install_cmd ${node} "/usr/bin/mv ${imagedirs[j]} ${tmpimagedirs[j]}" >/dev/null 2>&1

				# Remove it
				interactive_install_cmd ${node} "/usr/bin/rm -rf ${tmpimagedirs[j]}" >/dev/null 2>&1

				# Next
				((j += 1))
			done

			# Done
			return 0
		) &
		pids="${pids} $!"
	done

	# Wait for each process to complete
	for pid in ${pids}
	do
		# Don't care if it cleanup up successfully or not
		wait ${pid}
	done

	# Print done message
	printf "%s\n" ${SC_DONE}

	# Done
	return 0
}

####################################################
#
# interactive_install_recover_centralized()
#
#	Check to see if a prior installation already entered one of
#	the configuration states.   If it did, allow the user to
#	select recovery using previous options.   Once configuration
#	has started, it may not be possible to re-start a centralized
#	install until already configured nodes have been de-installed.
#
#	If recovery succeeds, this function does not return.   Rather,
#	we reboot this node on success.
#
#	Return values:
#		0		- proceed without the recovery option
#		1		- return to main menu
#		<noreturn>	- successful recovery
#
####################################################
interactive_install_recover_centralized()
{
	typeset sctxt_title="$(gettext '
		>>> Recovery <<<
	')"
	typeset sctxt_p1="$(gettext '
		It appears that a previous installation attempt
		failed to complete successfully.  You can
		try to either restart the failed attempt or to
		start over with a fresh installation.
	')"
	typeset sctxt_p2="$(gettext '
		If you try to restart the previously failed
		installation, you will not be able to change any
		configuration options.   The installation will attempt
		to resume at the point that it last failed.
	')"

	typeset answer
	typeset node
	typeset cmd

	integer state
	integer index
	integer found_state
	integer found_final_state
	integer numnodes
	integer waiting

	integer -r final_state=4

	# If there is no recover state, skip this screen
	let found_state=0
	let found_final_state=0
	let numnodes=0
	for index in ${SC_INDICES}
	do
		if [[ -n "${SC_ARGVAR_STATE[index]}" ]]; then
			let state=${SC_ARGVAR_STATE[index]}
			if [[ ${state} -gt 0 ]];  then
				((found_state += 1))
			fi
			if [[ ${state} -eq ${final_state} ]]; then
				((found_final_state += 1))
			fi
		fi
		((numnodes += 1))
	done
	if [[ ${found_state} -eq 0 ]] ||
	    [[ ${numnodes} -eq ${found_final_state} ]]; then
		return 0
	fi

	#
	# Print help
	#
	clear
	sc_print_title "${sctxt_title}"
	sc_print_para "${sctxt_p1}"
	sc_print_para "${sctxt_p2}"

	#
	# Want to try recovery?
	#
	answer=$(sc_prompt_yesno "$(gettext 'Do you want to try to restart the previous installation?')" "${YES}") || return 1

	#
	# Nope, clear the old state and return
	#
	if [[ "${answer}" != "yes" ]]; then
		
		# Make a copy of the state before erasing it
		cp ${SC_ILOG} ${SC_ILOG}.$(date +%m%d02/11/03M) 2>/dev/null

		# Zap the state data
		for index in ${SC_INDICES}
		do
			SC_ARGVAR_STATE[index]="0"
			argvar_append_tofile_state "${index}" ${SC_ILOG}
		done

		# Done
		return 0
	fi

	#
	# Make sure that we can contact everyone
	#
	echo | logmsg
	for node in ${SC_ARGVAR_NODENAME[*]}
	do
		# Skip me
		if [[ "${node}" == "${mynodename}" ]]; then
			continue
		fi

		# Ping
		let waiting=0
		while true
		do
			# If first time through, print message
			if [[ ${waiting} -eq 0 ]]; then
				sc_print_line "$(printf "$(gettext 'Attempting to contact \"%s\" ... ')" "${node}")" | logmsg
				let waiting=1
			fi

			# Ping the other machine
			echo >>${install_log}
			cmd="ping ${node} $((60 * 60))"
			echo ${cmd} >>${install_log}
			eval ${cmd} >>${install_log} 2>&1
			if [[ $? -eq 0 ]]; then
				printf "%s\n" ${SC_DONE}
				printf "$(gettext 'Contacted %s.')\n\n" "${node}" >>${install_log}
				let waiting=0
				break
			fi
		done
	done

	#
	# Check and set remote method
	#
	SC_REMOTE_METHOD=${SC_ARGVAR_REMOTE_METHOD}
	if [[ -z "${SC_REMOTE_METHOD}" ]]; then
		echo | logmsg
		interactive_install_remote_method || return 1
	fi

	#
	# Attempt to re-start recovery
	#
	interactive_install_createcluster_centralized || return 1

	#
	# We should never get here
	#
	return 1
}

####################################################
#
# interactive_install_createcluster_centralized()
#
#	Configure and boot each of the nodes, in reverse node list order.
#	This function checks and maintains state, so that the user
#	has the option of easy recovery.
#
#	States:
#
#		NULL	- same as state 0
#		0	- begin state, wait for any scinstalls to complete
#		1	- launch scinstall on unconfigured node
#		2	- node is configured
#		3	- waiting for reboot to complete
#		4	- final state
#
#	Return values:
#		0	- success
#		1	- failure
#
####################################################
interactive_install_createcluster_centralized()
{
	integer -r final_state=4

	typeset node
	typeset nodes
	typeset nodenames
	typeset nodeindices
	typeset sponsornode
	typeset cmd
	typeset cmd_args
	typeset msg
	typeset saved_patchdir
	typeset saved_rpatchdir
	typeset saved_logfilename

	integer i
	integer state
	integer result
	integer waiting

	# Initialize node names
	set -A nodenames ${SC_ARGVAR_NODENAME[*]}

	# Initialize the node indices in reverse order
	let i=0
	nodeindices=
	for node in ${nodenames[*]}
	do
		nodeindices="${i} ${nodeindices}"
		((i += 1))
	done
	sponsornode=${SC_ARGVAR_SPONSORNODE[0]}

	# Make sure that the sponsor node is in tact
	if [[ "${SC_ARGVAR_NODENAME[i - 1]}" != "${sponsornode}" ]]; then
		printf "$(gettext 'Recovery is not possible due to bad \"%s\" file.')\n\n" "${SC_ILOG}" | logmsg
		echo "\a\c"
		sc_prompt_pause
		return 1
	fi

	# Initialize states
	for i in ${nodeindices}
	do
		if [[ -z "${SC_ARGVAR_STATE[i]}" ]]; then
			SC_ARGVAR_STATE[i]="0"
			argvar_append_tofile_state "${i}" ${SC_ILOG}
		fi
	done

	#
	# Loop through the nodes
	#
	let waiting=0
	echo | logmsg
	for i in ${nodeindices}
	do
		# Get the node
		node=${nodenames[i]}

		# Set the initial state for this node
		let state=${SC_ARGVAR_STATE[i]}

		# Add node name to log
		echo >>${install_log}
		echo ${SC_LINE} >>${install_log}
		echo ${node} >>${install_log}
		echo ${SC_LINE} >>${install_log}
		echo >>${install_log}

		#
		# Loop through the states
		#
		while true
		do
			case ${state} in
			0)    # State 0 - begin state

				#
				# See if scinstall is already running
				#
				if [[ "${node}" == "${mynodename}" ]]; then
					let result=0
				else
					interactive_install_cmd ${node} "test isinstalling" >/dev/null 2>&1
					let result=$?
				fi
				case ${result} in
				0)    # scinstall is NOT already running

					# If waiting, print done
					if [[ ${waiting} -ne 0 ]]; then
						printf "%s\n" ${SC_DONE}
						let waiting=0
					fi
					;;
						
				1)    # scinstall IS already running

					# If not yet waiting, print message
					if [[ ${waiting} -eq 0 ]]; then
						echo >>${install_log}
						msg="$(printf "$(gettext 'Waiting for %s to complete on \"%s\" ... ')" "${PROG}" "${node}")"
						sc_print_line "${msg}" | logmsg
						echo >>${install_log}
						let waiting=1
					fi

					# Wait a while, then try again
					sleep 10
					continue
					;;

				*)    # Error

					# If waiting, print failed
					if [[ ${waiting} -ne 0 ]]; then
						printf "%s\n\n" ${SC_FAILED}
						let waiting=0
					fi

					# Print error
					echo | logmsg
					printf "$(gettext 'Unable to determine if %s is already running on \"%s\".')\n\n" "${PROG}" "${node}" | logmsg
					echo "\a\c"
					interactive_printlogmsg "${install_log}"
					sc_prompt_pause
					echo ${SC_LINE} >>${install_log}
					return 1
					;;
				esac

				# Continue to next state
				((state += 1))
				;;


			1)    # State 1 - launch scinstall if unconfigured

				#
				# See if the node is already configured
				#
				interactive_install_cmd ${node} "test isconfigured" >/dev/null 2>&1
				let result=$?
				case ${result} in
				0)    # not already configured
					;;

				1)    # node is already configured
					((state += 1))
					continue
					;;

				*)    # Error

					# Print error
					echo | logmsg
					printf "$(gettext 'Unable to determine if \"%s\" is already configured as a Sun Cluster node.')\n\n" "${node}" | logmsg
					echo "\a\c"
					interactive_printlogmsg "${install_log}"
					sc_prompt_pause
					echo ${SC_LINE} >>${install_log}
					return 1
					;;
				esac

				#
				# Run scinstall
				#
				echo >>${install_log}
				msg="$(printf "$(gettext 'Configuring \"%s\" ... ')" "${node}")"
				sc_print_line "${msg}" | logmsg
				echo >>${install_log}

				# Set scinstall -k arguments
				set -A SC_ARGVARS
				saved_patchdir=${SC_ARGVAR_PATCHDIR}
				saved_rpatchdir=${SC_ARGVAR_RESPONSE_PATCHDIR}
				SC_ARGVAR_PATCHDIR=
				SC_ARGVAR_RESPONSE_PATCHDIR=
				argvars_to_SC_ARGVARS ${i}
				SC_ARGVAR_PATCHDIR=saved_patchdir
				SC_ARGVAR_RESPONSE_PATCHDIR=saved_rpatchdir

				# Local node, we must bypass lock file
				if [[ "${node}" == "${mynodename}" ]]; then
					SC_LOCK_ISSET=1
					echo >>${install_log}
					echo "scinstall -ik ${SC_ARGVARS[*]}" >>${install_log}
					saved_logfilename=${install_log}
					install_log=/dev/null
					main -ik ${SC_ARGVARS[*]} >>${saved_logfilename} 2>&1
					let result=$?
					install_log=${saved_logfilename}

				# Remote node
				else
					interactive_install_cmd ${node} "install -logfile ${install_log} -k ${SC_ARGVARS[*]}" >/dev/null 2>&1
					let result=$?
				fi

				# Failed?
				if [[ ${result} -ne 0 ]]; then
					printf "%s\n\n" ${SC_FAILED}
					echo | logmsg
					printf "$(gettext 'Failed to configure \"%s\".')\n\n" "${node}" | logmsg
					echo "\a\c"
					interactive_printlogmsg "${install_log}"
					sc_prompt_pause
					echo ${SC_LINE} >>${install_log}
					return 1
				fi

				# Done
				printf "%s\n" ${SC_DONE}

				# Next
				((state += 1))
				;;


			2)    # State 2 - node is configured

				# Save this state for recovery
				SC_ARGVAR_STATE[i]=${state}
				argvar_append_tofile_state "${i}" ${SC_ILOG}

				#
				# Test for reboot
				#
				interactive_install_cmd ${node} "test hasbooted" >/dev/null 2>&1
				let result=$?
				case ${result} in
				0)    # has not booted as a cluster node
					;;

				1)    # has tried to boot as a cluster node

					#
					# Make sure it is a cluster member
					#
					interactive_install_cmd ${node} "test isclustermember" >/dev/null 2>&1
					let result=$?
					case ${result} in
					0)    # Booted, but not a cluster member

						# Print error
						echo | logmsg
						printf "$(gettext '\"%s\" is not a member of the cluster.')\n\n" "${node}" | logmsg
						echo "\a\c"
						interactive_printlogmsg "${install_log}"
						sc_prompt_pause
						echo ${SC_LINE} >>${install_log}
						return 1
						;;

					1)    # Booted as cluster member

						# Continue to the next state
						((state += 1))
						continue
						;;

					*)    # Error

						# Print error
						echo | logmsg
						printf "$(gettext 'Unable to determin if \"%s\" is a member of the cluster.')\n\n" "${node}" | logmsg
						echo "\a\c"
						interactive_printlogmsg "${install_log}"
						sc_prompt_pause
						echo ${SC_LINE} >>${install_log}
						return 1
						;;
					esac
					;;

				*)    # Error

					# Print error
					echo | logmsg
					printf "$(gettext 'Unable to determine if \"%s\" has already been booted.')\n\n" "${node}" | logmsg
					echo "\a\c"
					interactive_printlogmsg "${install_log}"
					sc_prompt_pause
					echo ${SC_LINE} >>${install_log}
					return 1
					;;
				esac

				#
				# Reboot
				#

				# Local node uses screboot to finalize cleanup
				if [[ "${node}" == "${mynodename}" ]]; then
					
					# Save the final state for this node
					let state=${final_state}
					SC_ARGVAR_STATE[i]=${state}
					argvar_append_tofile_state "${i}" ${SC_ILOG}

					# Reboot
					msg="$(printf "$(gettext 'Rebooting \"%s\" ... ')\n" "${node}")"
					sc_print_line "${msg}" | logmsg
					echo | logmsg
					SC_REBOOT=1
					screboot

				# Remote
				else
					msg="$(printf "$(gettext 'Rebooting \"%s\" ... ')" "${node}")"
					sc_print_line "${msg}" | logmsg
					echo >>${install_log}

					interactive_install_cmd ${node} "reboot" >/dev/null 2>&1
					let result=$?

					#
					# We are only worried about exit
					# code 2 from cmd_reboot.   All
					# others are assumed to be the
					# result of the reboot.
					# 
					if [[ ${result} -eq 2 ]]; then

						printf "%s\n\n" ${SC_FAILED}
						echo | logmsg
						printf "$(gettext 'Unable to boot \"%s\".')\n\n" "${node}" | logmsg
						echo "\a\c"
						interactive_printlogmsg "${install_log}"
						sc_prompt_pause
						echo ${SC_LINE} >>${install_log}
						return 1
					fi
				fi

				# Next
				let waiting=1
				((state += 1))
				;;

			3)    # State 3 - waiting for reboot to complete

				# Save this state for recovery
				SC_ARGVAR_STATE[i]=${state}
				argvar_append_tofile_state "${i}" ${SC_ILOG}

				#
				# If we are not here from the previous step,
				# print message
				#
				if [[ ${waiting} -eq 0 ]]; then
					echo | logmsg
					msg="$(printf "$(gettext 'Waiting for \"%s\" to become a cluster member ... ')" "${node}")"
					sc_print_line "${msg}" | logmsg
					echo >>${install_log}
					let waiting=1
				fi

				#
				# Run the command to wait
				#
				cmd="scrconf -x ${SC_WTIMEOUT} -N ${node}"
				echo >>${install_log}
				echo ${cmd} >>${install_log}
				eval ${cmd} >>${install_log} 2>&1
				let result=$?
				case ${result} in
				0)    # Next
					let state=${final_state}
					let waiting=0
					printf "%s\n" ${SC_DONE}
					echo | logmsg
					;;

				${SC_SCCONF_ETIMEDOUT}) # Timeout
					;;

				*)    # Error

					# Print error
					echo | logmsg
					printf "$(gettext 'Unable to determine if \"%s\" has joined the cluster.')\n\n" "${node}" | logmsg
					echo "\a\c"
					interactive_printlogmsg "${install_log}"
					sc_prompt_pause
					echo ${SC_LINE} >>${install_log}
					return 1
					;;
				esac

				;;
	
			4)    # State 4 - final state

				# Save this state for recovery
				SC_ARGVAR_STATE[i]=${state}
				argvar_append_tofile_state "${i}" ${SC_ILOG}

				# Done
				break

				;;

			*)    # Unknown state should never be reached

				# Print error
				echo | logmsg
				printf "$(gettext 'Unrecoverable error in \"%s\" for \"%s\".')\n\n" "${SC_ILOG}" "${node}" | logmsg
				echo "\a\c"
				interactive_printlogmsg "${install_log}"
				sc_prompt_pause
				echo ${SC_LINE} >>${install_log}
				return 1
			esac
		done
	done

	# We should never get here
	return 1
}

####################################################
#
# interactive_get_install_menuoption() [help]
#
#	help	- if given, print the install help menu
#
#	Print the install menu, and return the selected option.
#	If the "help" option is given, the menu is processed
#	as the install help menu.
#
#	This function always returns zero.
#
####################################################
interactive_get_install_menuoption()
{
	typeset help=${1}

	typeset option

	typeset sctxt_title_1="$(gettext '*** Install Menu ***')"
	typeset sctxt_title_2="$(gettext 'Please select from any one of the following options:')"
	typeset sctxt_title_1_help="$(gettext '*** Install Menu Help **')"
	typeset sctxt_title_2_help="$(gettext 'Please select from any one of the following HELP options:')"
	typeset sctxt_option_001="$(gettext 'Install all nodes of a new cluster')"
	typeset sctxt_option_002="$(gettext 'Install just this machine as the first node of a new cluster')"
	typeset sctxt_option_003="$(gettext 'Add this machine as a node in an existing cluster')"
	typeset sctxt_option_help="$(gettext 'Help with menu options')"
	typeset sctxt_option_return_install="$(gettext 'Return to the Install Menu')"
	typeset sctxt_option_return_main="$(gettext 'Return to the Main Menu')"

	if [[ -n "${help}" ]]; then
		option=$(sc_get_menuoption \
			"T1+++${sctxt_title_1_help}" \
			"T2+++${sctxt_title_2_help}" \
			"S+0+1+${sctxt_option_001}" \
			"S+0+2+${sctxt_option_002}" \
			"S+0+3+${sctxt_option_003}" \
			"R+++" \
			"S+0+q+${sctxt_option_return_install}" \
		)
	else
		option=$(sc_get_menuoption \
			"T1+++${sctxt_title_1}" \
			"T2+++${sctxt_title_2}" \
			"S+0+1+${sctxt_option_001}" \
			"S+0+2+${sctxt_option_002}" \
			"S+0+3+${sctxt_option_003}" \
			"R+++" \
			"S+0+\?+${sctxt_option_help}" \
			"S+0+q+${sctxt_option_return_main}" \
		)
	fi

	echo "${option}"

	return 0
}

####################################################
#
# interactive_install_centralized()
#
#	This is the interactive install function.
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_centralized()
{
	integer iflag=4
	integer index
	integer i

	typeset answer
	typeset saved_nodenames
	typeset saved_clustername
	typeset node

	typeset sctxt_title="$(gettext '*** Installing all Nodes of a New Cluster ***')"

	# Clear all SC_ARGVARS
	argvar_clear_all_argvars

	# Initialize the log file
	install_log=${default_install_log}
	openlog
	printf "\n%s\n%s\n\n" "${sctxt_title}" "$(date)" >>${install_log}

	# make sure /var/cluster/... exists for our log
	if [[ ! -d ${SC_ILOGDIR} ]]; then
		openfile ${SC_ILOGDIR}/foo 2>/dev/null
		rm -f ${SC_ILOGDIR}/foo
	fi

        # create the temp directory, in case it is not there
	create_tmpdir

	# Read in the response log
	SC_ILOG=${SC_ILOGDIR}/${SC_ILOGBASE}.${iflag}
	if [[ -f "${SC_ILOG}" ]] && [[ -r "${SC_ILOG}" ]]; then
		. ${SC_ILOG}
	fi

	# Save clustername and nodenames
	saved_nodenames="${SC_ARGVAR_NODENAME[*]}"
	saved_clustername="${SC_ARGVAR_CLUSTERNAME}"

	# Set the index to zero and make sure that my nodename is first.
	SC_IDX=0
	if [[ "${SC_ARGVAR_NODENAME[SC_IDX]}" != "${mynodename}" ]]; then
		saved_nodenames=
		argvar_clear_all_argvars
		SC_ARGVAR_NODENAME[SC_IDX]=${mynodename}
		SC_ARGVAR_CLUSTERNAME=${saved_clustername}
		rm -f ${SC_ILOG}
		argvar_append_all_tofile "${SC_IDX}" ${SC_ILOG}
	fi

	# Also set SC_INDICES
	argvar_set_indices

	#
	# Print help screen
	#
	sc_print_title "${sctxt_title}"
	interactive_help_install_centralized
	sc_print_ctrld_message
	echo

	# Continue?
	answer=$(sc_prompt_yesno "$(gettext 'Do you want to continue?')" "${YES}") || return 1
	if [[ "${answer}" != "yes" ]]; then
		return 1
	fi

	#
	# Try recovery from a prior run
	#
	interactive_install_recover_centralized || return 1

	#
	# Typical or custom mode?
	#
	interactive_install_typical_or_custom ${iflag}
	case $? in
	1)	let SC_TYPICAL_INSTALL=1
		argvar_typical_argvars ${SC_ILOG}
		;;

	2)	let SC_TYPICAL_INSTALL=0 ;;
	*)	return 1;;
	esac

	#
	# Make sure that the OE in the scinstalldir path and the OS match up
	#
	interactive_check_oe || return 1

	#
	# SC_ARGVAR_CLUSTERNAME - establish the cluster name
	#
	interactive_install_clustername ${iflag} || return 1
	saved_clustername="${SC_ARGVAR_CLUSTERNAME}"

	#
	# SC_ARGVAR_AUTHLIST - establish the node names
	#
	interactive_install_authlist ${iflag} || return 1

	# Same names in the same order?   If not, reset everything
	if [[ -n "${saved_nodenames}" ]] &&
	    [[ -n "${SC_ARGVAR_AUTHLIST}" ]] &&
	    [[ "$(echo ${saved_nodenames})" != "$(echo ${SC_ARGVAR_AUTHLIST})" ]]; then
		saved_nodenames="${SC_ARGVAR_AUTHLIST}"
		argvar_clear_all_argvars
		SC_ARGVAR_CLUSTERNAME=${saved_clustername}
		SC_ARGVAR_AUTHLIST="${saved_nodenames}"
		rm -f ${SC_ILOG}
		argvar_append_all_tofile "${SC_IDX}" ${SC_ILOG}
	fi

	# Set the nodename list to the authlist
	set -A SC_ARGVAR_NODENAME ${SC_ARGVAR_AUTHLIST}

	#
	# Set SC_INDICES
	#
	argvar_set_indices

	#
	# Append all SC_ARGVAR_NODENAMEs to the file.
	#
	for index in ${SC_INDICES}
	do
		argvar_append_tofile_nodename "${index}" ${SC_ILOG}
	done

	#
	# Set the SC_ARGVAR_SPONSORNODE to the last node
	#
	i=$(set -- ${SC_INDICES}; shift $(($# - 1)); echo $1)
	for index in ${SC_INDICES}
	do
		SC_ARGVAR_SPONSORNODE[index]=${SC_ARGVAR_NODENAME[i]}
		argvar_append_tofile_sponsornode "${index}" ${SC_ILOG}
	done

	#
	# Check and set remote method
	#
	interactive_install_remote_method || return 1

	#
	# SC_ARGVAR_AUTHTYPE - set authentication type
	#
	interactive_install_authtype ${iflag} || return 1

	#
	# SC_ARGVAR_NETADDR - set cluster transport net addr
	# SC_ARGVAR_NETMASK - set cluster transport net mask
	#
	interactive_install_netaddr ${iflag} || return 1

	#
	# SC_ARGVAR_TWONODES - set to 1 if two-node cluster
	# SC_ARGVAR_DIRECT   - set to 1 if direct connect
	#
	interactive_install_directconnect ${iflag} || return 1

	#
	# SC_ARGVAR_JUNCTIONS - list of transport junctions
	#
	if [[ ${SC_ARGVAR_DIRECT} -ne 1 ]]; then
		interactive_install_junctions ${iflag} || return 1
		for index in ${SC_INDICES}
		do
			if [[ ${index} -eq ${SC_IDX} ]]; then
				continue
			fi
			SC_ARGVAR_JUNCTIONS[index]="${SC_ARGVAR_JUNCTIONS[SC_IDX]}"
			SC_ARGVAR_JUNCTYPES[index]="${SC_ARGVAR_JUNCTYPES[SC_IDX]}"
			argvar_append_tofile_junctions "${index}" ${SC_ILOG}
		done
	fi

	#
	# SC_ARGVAR_ADAPTERS - list of adapters for this node
	# SC_DISCOVER_DOAUTO - set to non-null for autodiscovery
	#
	interactive_install_adapters ${iflag} || return 1

	#
	# SC_ARGVAR_PATCHDIR - patch directory
	# SC_ARGVAR_PATCHFILE - patch list
	#
	# Centralized install should install patches only if any software
	# packages are installed by it
	#
	if [[ ${SC_REMOTE_METHOD} != "scrcmd" ]]; then
		interactive_install_patches ${iflag} || return 1
	fi

	#
	# SC_ARGVAR_GDIR - global devices file system
	# Confirmation to proceed
	#
	if [[ ${SC_TYPICAL_INSTALL} -eq 1 ]]; then
		interactive_install_confirmation_centralized || return 1
		interactive_install_globaldir ${iflag} || return 1
		echo | logmsg
	else
		interactive_install_globaldir ${iflag} || return 1
		interactive_install_confirmation_centralized || return 1
	fi

	#
	# Refresh the response log
	#
	rm -f ${SC_ILOG}
	let i=0
	for node in ${SC_ARGVAR_NODENAME[*]}
	do
		argvar_append_all_tofile "${i}" ${SC_ILOG}
		((i += 1))
	done

	#
	# Install core software
	#
	interactive_install_framework_centralized || return 1

	#
	# Add patches, if necessary;  failures are ignored.
	#
	interactive_install_patchadd_centralized

	#
	# Centralized transport auto discover
	#
	if [[ -n "${SC_DISCOVER_DOAUTO}" ]]; then
		interactive_install_autodiscovery_centralized ${SC_ARGVAR_CLUSTERNAME} || return 1
	fi

	#
	# Run sccheck on each node
	#
	interactive_install_sccheck_centralized || return 1

	#
	# Cleanup download files
	#
	interactive_install_cleanup_centralized

	#
	# Configure and boot all nodes into the cluster
	#
	interactive_install_createcluster_centralized || return 1

	#
	# We should never get here
	#
	return 1
}

####################################################
#
# interactive_installnode()
#
#	This is the interactive install node function.
#
#	This function does not always return.  But,
#	when it does, ...
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_installnode()
{
	typeset answer
	typeset saved_clustername
	integer iflag=1

	typeset sctxt_title="$(gettext '*** Installing just the First Node of a New Cluster ***')"

	# Clear all SC_ARGVARS
	argvar_clear_all_argvars

	# Initialize the log file
	install_log=${default_install_log}
	openlog
	printf "\n%s\n%s\n\n" "${sctxt_title}" "$(date)" >>${install_log}

	# make sure /var/cluster/... exists for our log
	if [[ ! -d ${SC_ILOGDIR} ]]; then
		openfile ${SC_ILOGDIR}/foo 2>/dev/null
		rm -f ${SC_ILOGDIR}/foo
	fi

	# Read in the response log
	SC_ILOG=${SC_ILOGDIR}/${SC_ILOGBASE}.${iflag}
	if [[ -f "${SC_ILOG}" ]] && [[ -r "${SC_ILOG}" ]]; then
		. ${SC_ILOG}
	fi

	# Set the index to zero
	SC_IDX=0
	set -A SC_ARGVAR_NODENAME
	SC_ARGVAR_NODENAME[SC_IDX]=${mynodename}
	argvar_append_tofile_nodename "${SC_IDX}" ${SC_ILOG}

	# Also set SC_INDICES
	argvar_set_indices

	# Set the sponsor node to this node
	SC_ARGVAR_SPONSORNODE[SC_IDX]=${SC_ARGVAR_NODENAME[SC_IDX]}
	argvar_append_tofile_sponsornode "${SC_IDX}" ${SC_ILOG}

	#
	# Print help screen
	#
	sc_print_title "${sctxt_title}"
	interactive_help_install_installnode
	sc_print_ctrld_message
	echo

	# Continue?
	answer=$(sc_prompt_yesno "$(gettext 'Do you want to continue?')" "${YES}") || return 1
	if [[ "${answer}" != "yes" ]]; then
		return 1
	fi

	#
	# Make sure that the OE in the scinstalldir path and the OS match up
	#
	interactive_check_oe || return 1

	#
	# Install packages
	#
	interactive_install_framework || return 1

	#
	# Install patches and reload defaults
	#
	interactive_install_patches ${iflag} || return 1

	if [[ -f ${SC_DEFAULTS_2} ]]; then
		. ${SC_DEFAULTS_2}
	fi

	#
	# SC_ARGVAR_CLUSTERNAME - establish the cluster name
	#
	saved_clustername="${SC_ARGVAR_CLUSTERNAME}"
	interactive_install_clustername ${iflag} || return 1

	# If the clustername has changed, clear the response log
	if [[ -n "${saved_clustername}" ]] &&
	    [[ "${saved_clustername}" != "${SC_ARGVAR_CLUSTERNAME}" ]]; then
		saved_clustername=${SC_ARGVAR_CLUSTERNAME}
		argvar_clear_all_argvars
		rm -f ${SC_ILOG}
		SC_ARGVAR_NODENAME[SC_IDX]=${mynodename}
		SC_ARGVAR_SPONSORNODE[SC_IDX]=${SC_ARGVAR_NODENAME[SC_IDX]}
		SC_ARGVAR_CLUSTERNAME=${saved_clustername}
		argvar_append_all_tofile "${SC_IDX}" ${SC_ILOG}
	fi

	#
	# Run sccheck
	#
	interactive_install_sccheck ${iflag} || return 1

	#
	# SC_ARGVAR_AUTHLIST - list of nodes authorized to join the cluster
	#
	interactive_install_authlist ${iflag} || return 1

	#
	# SC_ARGVAR_AUTHTYPE - set authentication type
	#
	interactive_install_authtype ${iflag} || return 1

	#
	# SC_ARGVAR_NETADDR - set cluster transport net addr
	# SC_ARGVAR_NETMASK - set cluster transport net mask
	#
	interactive_install_netaddr ${iflag} || return 1

	#
	# SC_ARGVAR_TWONODES - set to 1 if two-node cluster;  otherwise, 0
	# SC_ARGVAR_DIRECT   - set to 1 if direct connect;  otherwise, 0
	#
	interactive_install_directconnect ${iflag} || return 1

	#
	# SC_ARGVAR_JUNCTIONS - list of transport junctions for this node
	#
	if [[ ${SC_ARGVAR_DIRECT} -ne 1 ]]; then
		interactive_install_junctions ${iflag} || return 1
	fi

	#
	# SC_ARGVAR_ADAPTERS - list of adapters for this node
	#
	interactive_install_adapters ${iflag} || return 1

	#
	# SC_ARGVAR_GDIR - global devices file system
	#
	interactive_install_globaldir ${iflag} || return 1

	#
	# SC_REBOOT
	#
	interactive_install_autoreboot ${iflag} || return 1

	#
	# Refresh the response log
	#
	rm -f ${SC_ILOG}
	argvar_append_all_tofile "${SC_IDX}" ${SC_ILOG}

	#
	# Confirmation to proceed
	#
	interactive_install_confirmation ${iflag} || return 1

	#
	# Run the command
	#
	set -A SC_ARGVARS
	argvars_to_SC_ARGVARS "${SC_IDX}"
	main -ik ${SC_ARGVARS[*]} || print_errorexit_msg beep

	#
	# This is not a complete uninstall option.
	# It is no longer safe to remove patches or packages.
	#
	let SC_FRAMEWORK_INSTALLED=0

	#
	# Pause until they press Enter
	#
	sc_prompt_pause || return 1

	return 0
}

####################################################
#
# interactive_addnode()
#
#	This is the interactive add node function.
#
#	This function does not always return.  But,
#	when it does, ...
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_addnode()
{
	typeset answer
	typeset clustername
	typeset sponsornode
	integer iflag=2

	typeset sctxt_title="$(gettext '*** Adding a Node to an Existing Cluster ***')"

	# Clear all SC_ARGVARS
	argvar_clear_all_argvars

	# Initialize the log file
	install_log=${default_install_log}
	openlog
	printf "\n%s\n%s\n\n" "${sctxt_title}" "$(date)" >>${install_log}

	# make sure /var/cluster/... exists for our log
	if [[ ! -d ${SC_ILOGDIR} ]]; then
		openfile ${SC_ILOGDIR}/foo 2>/dev/null
		rm -f ${SC_ILOGDIR}/foo
	fi

	# Read in the response log
	SC_ILOG=${SC_ILOGDIR}/${SC_ILOGBASE}.${iflag}
	if [[ -f "${SC_ILOG}" ]] && [[ -r "${SC_ILOG}" ]]; then
		. ${SC_ILOG}
	fi

	# Set the index to zero
	SC_IDX=0
	set -A SC_ARGVAR_NODENAME
	SC_ARGVAR_NODENAME[SC_IDX]=${mynodename}
	argvar_append_tofile_nodename "${SC_IDX}" ${SC_ILOG}

	# Also set SC_INDICES
	argvar_set_indices

	#
	# Print help screen
	#
	sc_print_title "${sctxt_title}"
	interactive_help_install_addnode
	sc_print_ctrld_message
	echo

	# Continue?
	answer=$(sc_prompt_yesno "$(gettext 'Do you want to continue?')" "${YES}") || return 1
	if [[ $? -ne 0 ]] || [[ "${answer}" != "yes" ]]; then
		return 1
	fi

	#
	# Make sure that the OE in the scinstalldir path and the OS match up
	#
	interactive_check_oe || return 1

	#
	# Install packages
	#
	interactive_install_framework || return 1

	#
	# Install patches and reload defaults
	#
	interactive_install_patches ${iflag} || return 1

	if [[ -f ${SC_DEFAULTS_2} ]]; then
		. ${SC_DEFAULTS_2}
	fi

	#
	# SC_ARGVAR_SPONSORNODE - the sponsor
	#
	interactive_install_sponsornode ${iflag} || return 1
	sponsornode=${SC_ARGVAR_SPONSORNODE[SC_IDX]}

	#
	# SC_ARGVAR_CLUSTERNAME - identify the cluster name
	#
	interactive_install_clustername ${iflag} ${sponsornode} || return 1
	clustername=${SC_ARGVAR_CLUSTERNAME}
	sponsornode=${SC_ARGVAR_SPONSORNODE[SC_IDX]}

	#
	# Run sccheck
	#
	if [[ -n "${SC_DISCOVER_MADECONTACT}" ]]; then
		interactive_install_sccheck ${iflag} ${sponsornode} || return 1
	else
		interactive_install_sccheck ${iflag} || return 1
	fi

	#
	# Autodiscovery
	#
	SC_DISCOVER_DOAUTO=
	interactive_install_autodiscovery ${sponsornode} ${clustername} || return 1
	if [[ -z "${SC_DISCOVER_DOAUTO}" ]]; then

		#
		# SC_ARGVAR_TWONODES - set to 1 if two-node cluster
		# SC_ARGVAR_DIRECT   - set to 1 if direct connect
		#
		interactive_install_directconnect ${iflag} || return 1

		#
		# SC_ARGVAR_JUNCTIONS - list of transport junctions 
		#
		if [[ ${SC_ARGVAR_DIRECT} -ne 1 ]]; then
			interactive_install_junctions ${iflag} || return 1
		fi

		#
		# SC_ARGVAR_ADAPTERS - list of adapters for this node
		#
		interactive_install_adapters ${iflag} || return 1
	fi

	#
	# SC_ARGVAR_GDIR - global devices file system
	#
	interactive_install_globaldir ${iflag} || return 1

	#
	# SC_REBOOT
	#
	interactive_install_autoreboot ${iflag} || return 1

	#
	# Refresh the response log
	#
	rm -f ${SC_ILOG}
	argvar_append_all_tofile "${SC_IDX}" ${SC_ILOG}

	#
	# Confirmation to proceed
	#
	interactive_install_confirmation ${iflag} || return 1

	#
	# Run the command
	#
	set -A SC_ARGVARS
	argvars_to_SC_ARGVARS "${SC_IDX}"
	main -ik ${SC_ARGVARS[*]} || print_errorexit_msg beep

	#
	# This is not a complete uninstall option.
	# It is no longer safe to remove patches or packages.
	#
	let SC_FRAMEWORK_INSTALLED=0

	#
	#
	# Pause until they press Enter
	#
	sc_prompt_pause || return 1

	return 0
}

####################################################
#
# interactive_get_main_menuoption() [help]
#
#	help	- if given, print the main help menu
#
#	Print the main menu, and return the selected option.
#	If the "help" option is given, the menu is processed
#	as the main help menu.
#
#	This function always returns zero.
#
####################################################
interactive_get_main_menuoption()
{
	typeset help=${1}

	typeset option
	typeset select_1
	typeset select_2
	typeset select_3
	typeset select_4

	typeset sctxt_title_1_main="$(gettext '*** Main Menu ***')"
	typeset sctxt_title_2_main="$(gettext 'Please select from one of the following (*) options:')"
	typeset sctxt_title_1_help="$(gettext '*** Main Menu Help **')"
	typeset sctxt_title_2_help="$(gettext 'Please select from one of the following HELP options:')"
	typeset sctxt_option_001="$(gettext 'Install a cluster or cluster node')"
	typeset sctxt_option_002="$(gettext 'Configure a cluster to be JumpStarted from this install server')"
	typeset sctxt_option_003="$(gettext 'Add support for new data services to this cluster node')"
	typeset sctxt_option_004="$(gettext 'Print release information for this cluster node')"
	typeset sctxt_option_help="$(gettext 'Help with menu options')"
	typeset sctxt_option_exit="$(gettext 'Quit')"
	typeset sctxt_option_return="$(gettext 'Return to the Main Menu')"
	typeset sctxt_msg_notroot="$(gettext '** NOTE:  You must be root for most options **')"

	if [[ -n "${help}" ]]; then
		option=$(sc_get_menuoption \
			"T1+++${sctxt_title_1_help}" \
			"T2+++${sctxt_title_2_help}" \
			"S+0+1+${sctxt_option_001}" \
			"S+0+2+${sctxt_option_002}" \
			"S+0+3+${sctxt_option_003}" \
			"S+0+4+${sctxt_option_004}" \
			"R+++" \
			"S+0+q+${sctxt_option_return}" \
		)
	else
		#
		# Option 2 is selectable only if /tftpboot exists.
		#
		if [[ -d /tftpboot ]]; then
			select_2=S
		else
			select_2=N
		fi

		#
		# Option 1 is selectable if the OS is cluster
		# aware, the node is not currently a member of the cluster,
		# and there is no nodeid file.
		#
		# Options 3 and 4 are selectable if SC 3.0 appears to
		# be configured.
		#
		select_1=S
		select_3=S
		select_4=S

		#
		# If clinfo does not exist, the OS is not cluster aware.
		#
		if [[ ! -x /usr/sbin/clinfo ]]; then
			select_1=N

		#
		# Make sure that we are not a member of the cluster
		#
		else
			is_cluster_member
			if [[ $? -eq ${SC_TRUE} ]]; then
				select_1=N
			fi
		fi

		#
		# If the cluster is configured, do not allow 1 or 2.
		# If the cluster is not configured, do not allow 3.
		#
		if [[ -f "${SC_NODEID}" ]]; then
			select_1=N
			select_2=N
		else
			select_3=N
		fi

		# If SC_DEBUG, turn everything on
		if [[ -n "${SC_DEBUG}" ]]; then
			select_1=S
			select_2=S
			select_3=S
			select_4=S
		fi

		# Get the menu option
		if verify_isroot 2>/dev/null; then
			option=$(sc_get_menuoption \
				"T1+++${sctxt_title_1_main}" \
				"T2+++${sctxt_title_2_main}" \
				"${select_1}+1+1+${sctxt_option_001}" \
				"${select_2}+1+2+${sctxt_option_002}" \
				"${select_3}+1+3+${sctxt_option_003}" \
				"${select_4}+1+4+${sctxt_option_004}" \
				"R+++" \
				"S+1+\?+${sctxt_option_help}" \
				"S+1+q+${sctxt_option_exit}" \
			)
		else
			option=$(sc_get_menuoption \
				"T1+++${sctxt_title_1_main}" \
				"T2+++${sctxt_title_2_main}" \
				"N+1+1+${sctxt_option_001}" \
				"N+1+2+${sctxt_option_002}" \
				"N+1+3+${sctxt_option_003}" \
				"${select_4}+1+4+${sctxt_option_004}" \
				"R+++" \
				"S+1+\?+${sctxt_option_help}" \
				"S+1+q+${sctxt_option_exit}" \
				"R+++" \
				"T2+++${sctxt_msg_notroot}" \
			)
		fi
	fi

	echo "${option}"

	return 0
}

####################################################
#
# interactive_install_help()
#
#	Print help information for the install submenu.
#
####################################################
interactive_install_help()
{
	typeset sctxt_title_help_install="$(gettext '*** Help Screen - Installing all Nodes of a New Cluster ***')"
	typeset sctxt_title_help_installnode="$(gettext '*** Help Screen - Installing just the First Node of a New Cluster ***')"
	typeset sctxt_title_help_addnode="$(gettext '*** Help Screen - Adding a Node to an Existing Cluster ***')"

	while true
	do
		case $(interactive_get_install_menuoption help) in
		'1')	# Option 1
			sc_print_title "${sctxt_title_help_install}"
			interactive_help_install_centralized
			;;

		'2')	# Option 2
			sc_print_title "${sctxt_title_help_installnode}"
			interactive_help_install_installnode
			;;

		'3')	# Option 3
			sc_print_title "${sctxt_title_help_addnode}"
			interactive_help_install_addnode
			;;

		'q')	# Return
			break
			;;
		esac

		echo
		sc_print_prompt "$(gettext 'Press Enter to return to the previous menu:')"
		if [[ $? -ne 0 ]]; then
			return 1
		fi
		read
		echo
	done

	return 0
}

####################################################
#
# interactive_install()
#
#	This is the install submenu.
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install()
{
	# Loop around the main menu
	while true
	do
		case $(interactive_get_install_menuoption) in
		'1')	interactive_install_centralized || return 1 ;;
		'2')	interactive_install_installnode || return 1 ;;
		'3')	interactive_install_addnode || return 1 ;;
		'?')	interactive_install_help ;;
		'q')	break ;;
		esac
	done
	echo

	# Done
	return 0
}

####################################################
#
# interactive_jumpstart()
#
#	This is the interactive custom jumpstart client set up
#	function.
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_jumpstart()
{
	typeset answer
	typeset saved_jumpstart_dir
	typeset saved_nodenames
	typeset saved_clustername

	integer index
	integer i
	integer iflag=3

	typeset sctxt_title="$(gettext '*** Custom JumpStart ***')"

	# Clear all SC_ARGVARS
	argvar_clear_all_argvars

	# Initially set SC_ILOG to /dev/null
	SC_ILOG=/dev/null

	# Set the index to zero
	SC_IDX=0

	#
	# Print help screen
	#
	sc_print_title "${sctxt_title}"
	interactive_help_main_jumpstart
	sc_print_ctrld_message
	echo

	# Continue?
	answer=$(sc_prompt_yesno "$(gettext 'Do you want to continue?')" "${YES}") || return 1
	if [[ "${answer}" != "yes" ]]; then
		return 1
	fi

	#
	# SC_ARGVAR_JUMPSTARTDIR - jumpstart directory
	#
	interactive_install_jumpstartdir ${iflag} || return 1

	# append SC_ARGVAR_JUMPSTARTDIR to response log
	argvar_append_tofile_jumpstartdir ${SC_ILOG}

	# Save the jumpstart directory
	saved_jumpstart_dir=${SC_ARGVAR_JUMPSTARTDIR}

	#
	# If we are able to write to it, set the response log
	#
	touch ${SC_ARGVAR_JUMPSTARTDIR}/${SC_ILOGBASE}.${iflag} 2>/dev/null
	if [[ $? -eq 0 ]]; then
		SC_ILOG=${SC_ARGVAR_JUMPSTARTDIR}/${SC_ILOGBASE}.${iflag}
	fi

	# Read in the response log
	if [[ -f "${SC_ILOG}" ]] && [[ -r "${SC_ILOG}" ]]; then
		. ${SC_ILOG}
	fi

	#
	# SC_ARGVAR_CLUSTERNAME - establish the cluster name
	#
	saved_clustername=${SC_ARGVAR_CLUSTERNAME}
	interactive_install_clustername ${iflag} || return 1

	# If the clustername changed, clear everything
	if [[ "${saved_clustername}" != "${SC_ARGVAR_CLUSTERNAME}" ]]; then
		saved_clustername=${SC_ARGVAR_CLUSTERNAME}
		argvar_clear_all_argvars
		SC_ARGVAR_JUMPSTARTDIR=${saved_jumpstart_dir}
		SC_ARGVAR_CLUSTERNAME=${saved_clustername}
		rm -f ${SC_ILOG}
		argvar_append_all_tofile "${SC_IDX}" ${SC_ILOG}
	fi

	#
	# If the old cluster already exists, read in current data.
	#
	interactive_install_jmp_exists || return 1

	# In case argvars got cleaned up as a result of inconsistencies
	# detected inside the jumpstart directory, re-initiate what we
	# already know.
	if [[ "${saved_clustername}" != "${SC_ARGVAR_CLUSTERNAME}" ]]; then
		SC_ARGVAR_JUMPSTARTDIR=${saved_jumpstart_dir}
		SC_ARGVAR_CLUSTERNAME=${saved_clustername}
		rm -f ${SC_ILOG}
		argvar_append_all_tofile "${SC_IDX}" ${SC_ILOG}
	fi

	#
	# SC_ARGVAR_AUTHLIST - list of nodes authorized to join the cluster
	#
	saved_nodenames="${SC_ARGVAR_NODENAME[*]}"
	set -A SC_ARGVAR_NODENAME
	interactive_install_authlist ${iflag} || return 1

	# Same names in the same order?   If not, reset everything
	if [[ -n "${saved_nodenames}" ]] &&
	    [[ -n "${SC_ARGVAR_AUTHLIST}" ]] &&
	    [[ "$(echo ${saved_nodenames})" != "$(echo ${SC_ARGVAR_AUTHLIST})" ]]; then
		saved_nodenames="${SC_ARGVAR_AUTHLIST}"
		argvar_clear_all_argvars
		SC_ARGVAR_JUMPSTARTDIR=${saved_jumpstart_dir}
		SC_ARGVAR_CLUSTERNAME=${saved_clustername}
		SC_ARGVAR_AUTHLIST="${saved_nodenames}"
		rm -f ${SC_ILOG}
		argvar_append_all_tofile "${SC_IDX}" ${SC_ILOG}
	fi

	# Set the nodename list to the authlist
	set -A SC_ARGVAR_NODENAME ${SC_ARGVAR_AUTHLIST}

	#
	# Set SC_INDICES
	#
	argvar_set_indices

	#
	# Append all SC_ARGVAR_NODENAMEs to the file
	#
	for index in ${SC_INDICES}
	do
		argvar_append_tofile_nodename "${index}" ${SC_ILOG}
	done

	#
	# Set the SC_ARGVAR_SPONSORNODE to the first node
	#
	for index in ${SC_INDICES}
	do
		SC_ARGVAR_SPONSORNODE[index]=${SC_ARGVAR_NODENAME[SC_IDX]}
		argvar_append_tofile_sponsornode "${index}" ${SC_ILOG}
	done

	#
	# SC_ARGVAR_AUTHTYPE - set authentication type
	#
	interactive_install_authtype ${iflag} || return 1

	#
	# SC_ARGVAR_NETADDR - set cluster transport net addr
	# SC_ARGVAR_NETMASK - set cluster transport net mask
	#
	interactive_install_netaddr ${iflag} || return 1

	#
	# SC_ARGVAR_TWONODES - set to 1 if two-node cluster;  otherwise, 0
	# SC_ARGVAR_DIRECT   - set to 1 if direct connect;  otherwise, 0
	#
	interactive_install_directconnect ${iflag} || return 1

	#
	# SC_ARGVAR_JUNCTIONS - list of transport junctions for this node
	#
	if [[ ${SC_ARGVAR_DIRECT} -ne 1 ]]; then
		interactive_install_junctions ${iflag} || return 1
		for index in ${SC_INDICES}
		do
			if [[ ${index} -eq ${SC_IDX} ]]; then
				continue
			fi
			SC_ARGVAR_JUNCTIONS[index]="${SC_ARGVAR_JUNCTIONS[SC_IDX]}"
			argvar_append_tofile_junctions "${index}" ${SC_ILOG}
		done
	fi

	#
	# SC_ARGVAR_ADAPTERS - list of adapters for this node
	#
	interactive_install_adapters ${iflag} || return 1

	#
	# SC_ARGVAR_GDIR - global devices file system
	#
	interactive_install_globaldir ${iflag} || return 1

	#
	# Install patches and reload defaults
	#
	interactive_install_patches ${iflag} || return 1

	#
	# Refresh the response log
	#
	rm -f ${SC_ILOG}
	argvar_append_all_tofile "${SC_INDICES}" ${SC_ILOG}

	#
	# Confirmation to proceed
	#
	interactive_install_confirmation ${iflag} || return 1

	#
	# Run the command for each node
	#
	for index in ${SC_INDICES}
	do
		set -A SC_ARGVARS
		argvars_to_SC_ARGVARS "${index}"
		main -c ${SC_ARGVAR_JUMPSTARTDIR} -h ${SC_ARGVAR_NODENAME[index]} ${SC_ARGVARS[*]} || print_errorexit_msg beep
	done

	#
	# Pause until they press Enter
	#
	sc_prompt_pause || return 1

	return 0
}

####################################################
#
# interactive_get_support_info() [dstoken]
#
#	This is a helper routine for interactive add data service function.
#
#	This function returns
#		0 - if the passed token is found in the file listing
#			supported dataservices
#		1 - otherwise
#
#	Note: The passed token is assumed to be a vaild found on the CD.
####################################################
interactive_get_support_info()
{
	typeset dstok=${1}
	typeset ds_support_list="/usr/cluster/lib/rgm/rtsupport/${SC_SUNOS}"

	if [[ ! -s "${ds_support_list}" ]]; then
		return 0
	fi

	egrep "^${dstok}[: 	]"\|"^${dstok}"$ ${ds_support_list} > /dev/null
	if [[ $? -eq 0 ]]; then
		return 0
	else
		return 1
	fi
}

####################################################
#
# interactive_adddataservice()
#
#	This is the interactive add data service function.
#
#	This function always returns zero.
#
####################################################
interactive_adddataservice()
{
	typeset sctxt_title="$(gettext '*** Adding Data Service Software ***')"

	typeset sctxt_unqualified_p1="$(gettext '
		None of the data services on this CD were qualified
		for this release of the Solaris Operating Environment
		at the time that this Sun Cluster data services CD was
		released.   But, additional data services may have
		been qualified since the release of this CD.  Check
		with your sales office for an updated list of qualified
		data services.
	')"

	typeset sctxt_unqualified_menu_p1="$(gettext '
		The following menu lists data services which were not
		qualified for this release of the Solaris Operating
		Environment at the time that this Sun Cluster data
		services CD was released.  But, additional data
		services may have been qualified since the release of
		this CD.
	')"

	typeset sctxt_unqualified_menu_p2="$(gettext '
		Do not install any data services software from this CD
		which is not known to be qualified for this release
		of the Solaris Operating Environment.  Check with
		your sales office for an updated list of qualified
		data services.
	')"

	typeset -l dataservice
	typeset dataservices
	typeset answer
	typeset answers
	typeset cdromdir
	typeset pdir
	typeset pdirs
	typeset dstokens
	typeset desc
	typeset args
	typeset foo
	typeset foo2
	typeset dstype
	typeset all_supported
	typeset this_token_type
	typeset input_token_type
	typeset prompt
	typeset header1
	typeset header2
	typeset cdtoc_proddirs

	integer i
	integer count
	integer found
	integer switch_menu

	typeset dflt_ds="/cdrom/cdrom0"

	# Get the data service information
	while true
	do
		# Print help screen
		sc_print_title "${sctxt_title}"
		interactive_help_main_adddataservice

		# If the default directory does not exist, clear the default
		[[ ! -d "${dflt_ds}" ]] && dflt_ds=

		# Where?
		cdromdir=$(sc_prompt "$(gettext 'Where is the data services CD?')" "${dflt_ds}") || return 0

		# Begin with slash?
		if [[ "${cdromdir}" != /* ]]; then
			printf "$(gettext 'Must begin with slash (/).')\n\n\a"
			sc_prompt_pause || return 0
			continue
		fi

		# Directory?
		if [[ ! -d "${cdromdir}" ]]; then
			printf "$(gettext 'Cannot find \"%s\".')\n\n\a" "${cdromdir}"
			sc_prompt_pause || return 0
			continue
		fi

		# Cdtoc?
		if [[ ! -f "${cdromdir}/${SC_CDTOC}" ]]; then
               		printf "$(gettext 'Cannot find the \"%s\" file.')\n" "${SC_CDTOC}"
               		printf "$(gettext '\"%s\" does not appear to be a %s CD or CD image.')\n\n\a" "${cdromdir}" "Sun Cluster"
			sc_prompt_pause || return 0
			continue
		fi

		# Get the Product directory paths
		cdtoc_proddirs="$(sed -n 's/^PRODDIR=\(.*\)/\1/p' ${cdromdir}/${SC_CDTOC})"
		# Eliminate any product directory where the oe doesn't match
		pdirs=
		for pdir in ${cdtoc_proddirs}
		do
			oe=$(get_oe_from_proddir ${pdir})
			if [[ -n "${oe}" ]]; then
				check_oe_os_match ${oe} ${SC_OS_VERSION}
				if [[ $? -ne 0 ]]; then
					continue
				fi
			fi
			pdirs="${pdirs} ${pdir}"	
		done
	
		if [[ -z "${pdirs}" ]]; then
			printf "$(gettext 'The \"%s\" file has no product names.')\n" "${SC_CDTOC}"
               		printf "$(gettext '\"%s\" has an unexpected layout.')\n\n\a" "${cdromdir}"
			sc_prompt_pause || return 0
			continue
		fi

		# Make the names unique
		pdirs="$(for pdir in ${pdirs}; do echo ${pdir}; done | sort | uniq)"

		# Get the data service names (one array element for ea pdir)
		set -A dstokens
		let i=0
		for pdir in ${pdirs}
		do
			dstokens[i]="$(sed -n 's/^CLUSTER='${SC_SERVICE}'\([^       ]*\).*/\1/p' ${cdromdir}/${pdir}/${SC_CLUSTERTOC})"
			((i += 1))
		done

		# Make sure that there are some dataservices
		if [[ -z "${dstokens[*]}" ]]; then
			printf "$(gettext 'There are no data services on this CD.')\n\n\a"
			sc_prompt_pause || return 0
			continue
		fi

		# Initialize menu headings
		prompt="$(gettext 'Select the data services you want to install:')"
		header1="$(printf "%-14s %-50.50s" "$(gettext 'Identifier')" "$(gettext 'Description')")"

		# Create the lists of supported and unsupported dataservices
		rm -f ${tmp_ds_supported}
		rm -f ${tmp_ds_unsupported}
		let i=0
		for pdir in ${pdirs}
		do
			# Get description
			desc="$(print_clustertoc ${cdromdir}/${pdir}/${SC_CLUSTERTOC} ${SC_SERVICE}${dstokens[i]} "description" 2>/dev/null)"

			# Add to supported or unsupported list
			interactive_get_support_info ${dstokens[i]}
			if [[ $? -eq 0 ]]; then
				if [[ -n "${dstokens[i]}" ]]; then
					printf "%-14s %-50.50s\n" "${dstokens[i]}" "${desc}" >>${tmp_ds_supported}
				fi
				all_supported="${all_supported} ${dstokens[i]}"
			else
				if [[ -n "${dstokens[i]}" ]]; then
					printf "%-14s %-50.50s\n" "${dstokens[i]}" "${desc}" >>${tmp_ds_unsupported}
				fi
			fi

			# Next
			((i += 1))
		done

		# Add "All" to supported list
		if [[ -s ${tmp_ds_supported} ]]; then
			printf "%-14s %-50.50s\n" "All" "$(gettext 'All data services in this menu')" >>${tmp_ds_supported}
		fi

		#
		# If there are only unqualified data services, confirm
		# that this is the menu that the user wants.
		#
		if [[ ! -s ${tmp_ds_supported} ]] && 
		    [[ -s ${tmp_ds_unsupported} ]]; then
			sc_print_para "${sctxt_unqualified_p1}"
			answer=$(sc_prompt_yesno "$(gettext 'Do you want to see the list of unqualified data services?')" "${NO}") || return 0
			if [[ "${answer}" == "yes" ]]; then
				dstype=${tmp_ds_unsupported}
			else
				rm -f ${tmp_ds_supported}
				rm -f ${tmp_ds_unsupported}
				continue
			fi

		# Otherwise, start with qualified data services
		else
			dstype=${tmp_ds_supported}
		fi

		let switch_menu=${SC_FALSE}
		dataservices=
		while true
		do
			# Switch menu?
			if [[ ${switch_menu} -eq ${SC_TRUE} ]]; then
				if [[ ${dstype} == ${tmp_ds_supported} ]]; then
					dstype=${tmp_ds_unsupported}
				else
					dstype=${tmp_ds_supported}
				fi
				let switch_menu=${SC_FALSE}
			fi

			# If unsupported, print message
			if [[ ${dstype} == ${tmp_ds_unsupported} ]]; then
				sc_print_para "${sctxt_unqualified_menu_p1}"
				sc_print_para "${sctxt_unqualified_menu_p2}"
				sc_prompt_pause || return 0
			fi

			# Get data services
			answers="$(
			    sc_get_scrolling_menuoptions	\
				"${prompt}"			\
				"${header1}"			\
				""				\
				0 0 0				\
				:${dstype}			\
			)"

			# Add answers to data services
			for answer in ${answers}
			do
				if [[ ${answer} == "All" ]]; then
					dataservices="${dataservices} ${all_supported}"
				else
					dataservices="${dataservices} ${answer}"
				fi
			done

			# Do we want to switch menus?
			if [[ ${dstype} == ${tmp_ds_unsupported} ]] &&
			    [[ -s ${tmp_ds_supported} ]]; then
				answer=$(sc_prompt_yesno "$(gettext 'Return to the list of qualified data services?')" "${YES}") || break
				if [[ "${answer}" == "yes" ]]; then
					switch_menu=${SC_TRUE}
				fi
			elif [[ ${dstype} == ${tmp_ds_supported} ]] &&
			    [[ -s ${tmp_ds_unsupported} ]]; then
				answer=$(sc_prompt_yesno "$(gettext 'Do you want to see more data services?')" "${NO}") || break
				if [[ "${answer}" == "yes" ]]; then
					switch_menu=${SC_TRUE}
				fi
			fi

			if [[ ${switch_menu} -eq ${SC_FALSE} ]];  then
				break
			fi
		done
		rm -f ${tmp_ds_supported}
		rm -f ${tmp_ds_unsupported}

		# make sure that there is at least one data service
		if [[ -z "${dataservices}" ]]; then
			return 0
		fi

		# remove any dups
		foo=
		for dataservice in ${dataservices}
		do
			let found=0
			for foo2 in ${foo}
			do
				if [[ ${foo2} == ${dataservice} ]]; then
					let found=1
				fi
			done
			if [[ ${found} -eq 0 ]]; then
				foo="${foo} ${dataservice}"
			fi
		done
		dataservices=$(echo ${foo})
				
		# verify that the list is correct
		echo
		sc_print_para "$(gettext 'This is the complete list of data services you selected:')"
		for foo in ${dataservices}
		do
			printf "\t${foo}\n"
		done
		echo
		answer=$(sc_prompt_yesno "$(gettext 'Is it correct?')" "${YES}") || return 0
		if [[ "${answer}" != "yes" ]]; then
			dataservices=
			continue
		fi

		# Okay, done
		break
	done

	# reformat dataservices with commas
	foo=
	let count=0
	for dataservice in ${dataservices}
	do
		if [[ -z "${foo}" ]]; then
			foo=${dataservice}
		else
			foo="${foo},${dataservice}"
		fi
		((count += 1))
	done
	dataservices="${foo}"

	# Continue?
	case ${count} in
	0)
		return 0
		;;

	1)
		answer=$(sc_prompt_yesno "$(gettext 'Is it okay to add the software for this data service')" "${YES}") || return 0
		;;

	*)
		answer=$(sc_prompt_yesno "$(gettext 'Is it okay to add the software for these data services')" "${YES}") || return 0
		;;
	esac
	if [[ "${answer}" != "yes" ]]; then
		return 0
	fi

	# Set args
	args="-ik -s ${dataservices} -d ${cdromdir}"

	# Print command
	echo
	echo "scinstall ${args}"
	echo

	# Run command
	main ${args} || print_errorexit_msg beep

	# Pause until they press Enter
	sc_prompt_pause || return 0

	return 0
}

####################################################
#
# interactive_printrelease()
#
#	Print release information.
#
#	This function always returns zero.
#
####################################################
interactive_printrelease()
{
	# Print the release
	print_release verbose | more

	# Pause until they press Enter
	sc_prompt_pause || return 1

	return 0
}

####################################################
#
# interactive_main_help()
#
#	Print help information for the main menu.
#
####################################################
interactive_main_help()
{
	typeset sctxt_title_help_install="$(gettext '*** Help Screen - Install a Cluster or Cluster Node ***')"
	typeset sctxt_title_help_adddataservice="$(gettext '*** Help Screen - Adding Data Service Software ***')"
	typeset sctxt_title_help_jumpstart="$(gettext '*** Help Screen - Custom JumpStart ***')"
	typeset sctxt_title_help_printrelease="$(gettext '*** Help Screen - Print Release ***')"

	while true
	do
		case $(interactive_get_main_menuoption help) in
		'1')	# Option 1
			sc_print_title "${sctxt_title_help_install}"
			interactive_help_main_install
			;;

		'2')	# Option 2
			sc_print_title "${sctxt_title_help_jumpstart}"
			interactive_help_main_jumpstart
			;;

		'3')	# Option 3
			sc_print_title "${sctxt_title_help_adddataservice}"
			interactive_help_main_adddataservice
			;;

		'4')	# Option 4
			sc_print_title "${sctxt_title_help_printrelease}"
			interactive_help_main_printrelease
			;;

		'q')	# Return
			break
			;;
		esac

		echo
		sc_print_prompt "$(gettext 'Press Enter to return to the previous menu:')"
		if [[ $? -ne 0 ]]; then
			return 1
		fi
		read
		echo
	done

	return 0
}

####################################################
#
# interactive_main()
#
#	Interactive scinstall.
#
#	This function always returns zero.
#
####################################################
interactive_main()
{
	# We are interactive
	SC_INTERACTIVE=1

	# Loop around the main menu
	while true
	do
		case $(interactive_get_main_menuoption) in
		'1')	interactive_install ;;
		'2')	interactive_jumpstart ;;
		'3')	interactive_adddataservice ;;
		'4')	interactive_printrelease ;;
		'?')	interactive_main_help ;;
		'q')	break ;;
		esac

		#
		# If packages were installed by interactive_installnode()
		# or interactive_addnode(), but the configuration steps
		# did not proceed for some reason, then SC_FRAMEWORK_INSTALLED
		# will be set to "1".   If this is the case, the user
		# may remove these packages.
		#
		if [[ ${SC_FRAMEWORK_INSTALLED} -eq 1 ]]; then
			interactive_remove_framework
		fi
	done
	echo

	# Done
	return 0
}
