#! /bin/ksh
#
# ident "@(#)scinstall_interactive.ksh 1.22     03/01/27 SMI"
#
# Copyright 1999-2003 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#

####################################################
#
# interactive_help_main_installnode()
#
#	Print the help message associated with
#	main menu install node option.
#
#	This function always returns zero.
#
####################################################
interactive_help_main_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, sccheck(1M) is run 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_main_addnode()
#
#	Print the help message associated with
#	main menu odd node option.
#
#	This function always returns zero.
#
####################################################
interactive_help_main_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_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 add support for data services
		to a node already configured as a Sun Cluster cluster
		node.
	')"
	typeset sctxt_p2="$(gettext '
		You will be asked to supply both the location of the
		media and a list of identifiers for the data services
		you want to install.
	')"

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

	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_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
#
#	Set SC_ARGVAR_SPONSORNODE for this node,
#	then add them to the response log.
#
#	iflag 2		- add this machine to an established cluster
#
#	Return values:
#		0	- proceed
#		1	- return to main menu
#
####################################################
interactive_install_sponsornode()
{
	integer iflag=${1}

	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')
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"
		sc_print_para "${sctxt_p3}"
		;;

	*)    # 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 -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" "${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 -a -N ${sponsornode} -C ${clustername} 2>${tmperrs}
                	let result=$?
	                if [[ ${result} -eq ${SC_SCCONF_ENOCLUSTER} ]]; then
                        	printf "$(gettext '\"%s\" does not belong to cluster \"%s\".')\n" "${sponsornode}" "${clustername}"

                	elif [[ ${result} -eq ${SC_SCCONF_ENOEXIST} ]]; then
                        	printf "$(gettext 'The cluster to which \"%s\" belongs does not have a name.')\n" "${sponsornode}"

                	elif [[ ${result} -ne 0 ]]; then
                        	if [[ -s "${tmperrs}" ]]; then
                                	cat ${tmperrs}
				fi
                        fi
			rm -f ${tmperrs}
			if [[ ${result} -ne 0 ]]; then
                        	printf "$(gettext '\"%s\" is not the correct name for this cluster.')\n\n\a" "${clustername}"
				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_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

	#
	# If the framework packages are already known to be installed, skip
	#
	if [[ ${SC_FRAMEWORK_INSTALLED} -eq 1 ]]; 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 (SC_FRAMEWORK_INSTALLED is set to 1 on success)
	#
	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()
#
#	Print the sccheck failed menu, and return the selected option.
#
#	This function always returns zero.
#
####################################################
interactive_get_sccheckfailed_menuoption()
{
	typeset option

	typeset sctxt_title_2="$(gettext 'What would you like to do?')"
	typeset sctxt_option_001="$(gettext 'Proceed with the installation anyway')"
	typeset sctxt_option_002="$(gettext 'Retry sccheck')"
	typeset sctxt_option_return="$(gettext 'Return to the main menu')"

	option=$(sc_get_menuoption \
		"T2+++${sctxt_title_2}" \
		"S+0+1+${sctxt_option_001}" \
		"S+0+2+${sctxt_option_002}" \
		"S+0+q+${sctxt_option_return}" \
	)

	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 runs 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 list
		of warnings is printed.
	')"

	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 answer
	typeset prompt
	typeset cmd

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

	# Pause until they hit ENTER
	sc_prompt_pause || return 1

	#
	# Run sccheck
	#
	while true
	do
		cmd=${SC_SCCHECK}
		#
		# (Remote checks are not yet available)
		#if [[ ${iflag} -eq 2 ]] && [[ -n "${sponsornode}" ]]; then
		#	cmd="${cmd} -h ${mynodename},${sponsornode}"
		#fi
		#
		printf "$(gettext '    Running %s ... ')" "sccheck"
		echo "${prompt}\c" >>${install_log}
		${cmd} >${tmperrs} 2>&1
		printf "%s\n" ${SC_DONE} | logmsg
		if [[ ! -s ${tmperrs} ]]; then
			prompt="$(printf "$(gettext 'All %s tests passed.')" "sccheck")"
			echo "${prompt}" >>${install_log}
			sc_print_para "${prompt}"
			sc_prompt_pause || return 1
			return 0
		fi

		# sccheck printed errors/warnings
		printf "\n$(gettext 'The %s utility has detected the following potential problems:')\n\n" "sccheck" | logmsg
		cat ${tmperrs} >>${install_log}
		more ${tmperrs}
		echo | logmsg
		sc_prompt_pause || return 1

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

####################################################
#
# 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
#
#	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.  It
		may be up to 256 characters in length.  And, you may
		want to assign a cluster name which will be the same as
		one of the failover logical host names in the cluster.
		Create each cluster name to 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 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}"
		;;

	'3')  # JumpStart
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_i3_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}
			case $? in
			'0')	;;
			'1')	return 1 ;;
			'2')	return 0 ;;
			'3')	continue ;;
			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 hit 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
#
#	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 release of Sun Cluster 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_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 (Ctrl-D to finish):')"
	typeset sctxt_node_prompt

	integer i
	integer count
	typeset nodename
	typeset answer
	typeset answers
	typeset foo

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

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

	*)    # 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 ]]; 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 Ctrl-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 [[ ${iflag} -eq 1 ]] && [[ -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} -ne 1 ]] ||
				    [[ "${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
		if [[ $(set -- ${answers}; echo $#) -lt 2 ]]; then
			answers=
		fi

		# if not set, continue
		if [[ -z "${answers}" ]]; then
			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=
		answer=$(sc_prompt_yesno "$(gettext 'Is it correct?')" "${YES}") || return 1
		if [[ "${answer}" != "yes" ]]; then
			SC_ARGVAR_AUTHLIST=
			continue
		fi
		break
	done

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

	return 0
}

####################################################
#
# interactive_install_authtype() iflag
#
#	Set SC_ARGVAR_AUTHTYPE to 
#	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
#
#	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.  The list can be modified once
		the cluster has been established using scconf(1M) or
		other tools.
	')"
	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')
		;;

	*)    # invalid argument
		return 1
		;;
	esac

	# Prompt user and get response
	while true
	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

	# 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 -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
	printf "$(gettext '    Searching for unexpected network traffic on \"%s\" ... ')" "${adapter}"

	# Snoop
	scrconf -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\".')\a\n\n" "${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.')\a\n\n" "${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

	# Blank line
	echo

	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 may 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 discoverd.   And, all of
		these connections could be added to the cluster
		transport configuration.   However, interactive
		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 - switche 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 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 variables
	SC_DISCOVER_DOAUTO=
	SC_DISCOVER_JUNCTIONS=

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

	# 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 -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 -N "${sponsornode}" -n print_transport_config >${tmpfile}
		result=$?
		if [[ ${result} -eq 0 ]]; then
			allnet_radapters="$(scrconf -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
			# 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 [[ "${f1_node}" == "${mynodename}" ]]; 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 [[ "${f1_node}" != "${sponsornode}" ]]; 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_prompt "$(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 -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 -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 -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 connections 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_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
#
#	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, please bear
		in mind that the Sun Clustering software requires
		that the rightmost two octets always be zero.
	')"
	typeset sctxt_p3="$(gettext '
		The default netmask is 255.255.0.0;  you may select
		another netmask, as long as it minimally masks all bits
		given in the network address and does not contain any
		"holes".
	')"

	typeset dflt_answer
	typeset answer
	typeset foo

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

	*)    # invalid argument
		return 1
		;;
	esac

	# Netaddr
	while true
	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

	# Netmask
	while true
	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

	# 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
#
#	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')
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		;;

	*)    # 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, 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 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 hit 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

	# 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
#
#	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')
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		;;

	*)    # invalid argument
		return 1
		;;
	esac

	# 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]=

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

	# 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

	# 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
#
#	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="$(gettext '
		You must configure at least two transport adapters on
		each node which serve as connection points to the
		private cluster transport.  More than two connection
		points are allowed, but this interactive form of
		scinstall assumes exactly two.
	')"
	typeset sctxt_p2_adap="$(gettext '
		Note that interactive scinstall does not allow you to
		specify any special transport adapter properties
		settings.  If your adapters have special properties
		which must be set, you may need to use non-interactive
		scinstall by specifying a complete set of command line
		options.  For more information, please refer to the man
		pages for your adapters in the scconf_transp_adap
		family of man pages (e.g., scconf_transp_adap_hme(1M)).
	')"
	typeset sctxt_prompt_adapmenu[0]="$(gettext 'Select the first cluster transport adapter to use:')"
	typeset sctxt_prompt_adapmenu[1]="$(gettext 'Select the second cluster transport adapter to use:')"
	typeset sctxt_prompt_adap0="$(gettext '
		What is the name of the first cluster transport adapter')"
	typeset sctxt_prompt_adap0_help="${sctxt_prompt_adap0} $(gettext '(help)')"
	typeset sctxt_prompt_adap1="$(gettext '
		What is the name of the second cluster transport adapter')"
	typeset sctxt_prompt_adap1_help="${sctxt_prompt_adap1} $(gettext '(help)')"
	if [[ ${iflag} -eq 3 ]]; then
		typeset sctxt_prompt_adap[0]="${sctxt_prompt_adap0}?"
		typeset sctxt_prompt_adap[1]="${sctxt_prompt_adap1}?"
	else
		typeset sctxt_prompt_adap[0]="${sctxt_prompt_adap0_help}?"
		typeset sctxt_prompt_adap[1]="${sctxt_prompt_adap1_help}?"
	fi

	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[0]="$(gettext '
		Name of adapter on \"%s\" to which \"%s\" is connected?')"
	typeset sctxt_prompt_otheradap[1]="${sctxt_prompt_otheradap[0]}"
	typeset sctxt_prompt_junc[0]="$(gettext '
		Name of the junction to which \"%s\" is connected?')"
	typeset 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 may explicitly assign a name to each port.
		Or, for ethernet switches, you may 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[0]="$(gettext '
		Use the default port name for the \"%s\" connection?')"
	typeset sctxt_prompt_dfltport[1]="${sctxt_prompt_dfltport[0]}"
	typeset sctxt_prompt_portname[0]="$(gettext '
		What is the name of the port you want to use?')"
	typeset sctxt_prompt_portname[1]="${sctxt_prompt_portname[0]}"
	typeset sctxt_nodename="$(gettext ' For node \"%s\",')\n"

	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 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 do_pause

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

	*)    # invalid argument
		return 1
		;;
	esac

	#
	# Get list of known used and available ethernet adapters.
	#
	if [[ ${iflag} -eq 1 ]] || [[ ${iflag} -eq 2 ]]; 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
		available_adapters="$(scrconf -n cmd=print_adapters_available${arg_adaptypes})"

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

	# For each node
	let first=1
	let do_pause=0
	adaptertype=
	for index in ${SC_INDICES}
	do
		# Initialize index of first node
		if [[ ${first} -eq 1 ]]; then
			let firsti=${index}
		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 dlpi dlpi
		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}"
			sc_print_para "${sctxt_p2_adap}"
			let do_pause=1
		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
		adaptertype=
		while [[ ${skipit} -eq 0 ]] && [[ ${i} -lt 2 ]] 
		do
			# Adapters
			thisadapter=
			thisadapterdriver=
			thisadapterinst=
			while true
			do
				adaptertype=
				thisadapter=
				thisadapterdriver=
				thisadapterinst=

				# If iflag is 3 (JumpStart), print the nodename
				if [[ ${iflag} -eq 3 ]]; 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 [[ ${do_pause} -eq 1 ]]; then
						let do_pause=0
						sc_prompt_pause || return 1
					fi
					prompt="${sctxt_prompt_adapmenu[i]}"
					answer="$(
					    sc_get_scrolling_menuoptions    \
						"${prompt}"		    \
						"" ""			    \
						1 1			    \
						${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
					answer=$(sc_prompt "${sctxt_prompt_adap[i]}" "${dflt_adaps[i]}") || return 1
					if [[ "${answer}" == "help" ]]; 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 <alpha><numeric>
				if [[ "${answer}" = *:* ]] ||
				    [[ $(expr "${answer}" : '[a-z][a-z]*[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 'Adapter name already given.')\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 is already in use as a public network adapter.')\n\n\a"
						continue 2
					fi
				done

				# Set adapter variables
				thisadapter=${answer}
				thisadapterdriver=$(expr ${answer} : '\([a-z]*\)')
				thisadapterinst=$(expr ${answer} : '[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 Ctrl-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
							text="$(printf "${sctxt_p2_adaptype}" "${thisadapter}")"
							sc_print_para "${text}"

							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 ]] &&
				    [[ "${adaptertype}" == "ethernet" ]]; then
					interactive_install_snoop ${thisadapter}
					if [[ $? -ne 0 ]]; then
						continue
					fi
				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
				sc_print_para "${sctxt_p1_trtype}"

				#
				# 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, print the nodename
					if [[ ${iflag} -eq 3 ]]; 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"
					sc_print_para "${sctxt_p1_setdlpi}"
					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-z]*[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_ARGVAR_DIRECT} -ne 1 ]]; then

				# Junction at other end of cable
				while true
				do
					#
					# If iflag is 3 (JumpStart),
					# print the nodename
					#
					if [[ ${iflag} -eq 3 ]]; 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 (JumpStart), print the nodename
				if [[ ${iflag} -eq 3 ]]; 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

		# 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
	let do_pause=0
	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 hit ENTER
	if [[ ${do_pause} -ne 0 ]]; then
		sc_prompt_pause || return 1
	fi

	return 0
}

####################################################
#
# 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
#
#	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.  However, in order
		to do this, you must supply the name of either an
		already-mounted file system or raw disk partition at
		this time.  This file system or partition should be
		at least 100 MB in size.
	')"
	typeset sctxt_p2="$(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_p3="$(gettext '
		The default is to use /globaldevices.
	')"
	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')
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"
		sc_print_para "${sctxt_p3}"
		;;

	*)    # 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), print the nodename
		if [[ ${iflag} -eq 3 ]]; then
			printf "${sctxt_nodename}" "${SC_ARGVAR_NODENAME[index]}"
		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 ]]; then
				is_globalfs_okay "${SC_DFLT_GDIR}" 3
				if [[ $? -ne 0 ]]; then
					printf "$(gettext 'Cannot use \"%s\".')\n\n\a" "${SC_DFLT_GDIR}"
					# 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
					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 ]]; then
						is_globalfs_okay "${answer}" 3
						if [[ $? -ne 0 ]]; then
							printf "$(gettext 'Cannot use \"%s\".')\n\n\a" "${answer}"
							if [[ "${answer}" == "${SC_ARGVAR_GDIR[index]}" ]]; then
								SC_ARGVAR_GDIR[index]=
							fi
							continue
						fi
					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 ]]; then
						is_globalcspecial_okay "${answer}" 3
						if [[ $? -ne 0 ]]; then
							printf "$(gettext 'Cannot use \"%s\".')\n\n\a" "${answer}"
							if [[ "${answer}" == "${SC_ARGVAR_GDIR[index]}" ]]; then
								SC_ARGVAR_GDIR[index]=
							fi
							continue
						fi
					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_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_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_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 select_5

	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 'Establish a new cluster using this machine as the first node')"
	typeset sctxt_option_002="$(gettext 'Add this machine as a node in an established cluster')"
	typeset sctxt_option_003="$(gettext 'Configure a cluster to be JumpStarted from this install server')"
	typeset sctxt_option_004="$(gettext 'Add support for new data services to this cluster node')"
	typeset sctxt_option_005="$(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}" \
			"S+0+5+${sctxt_option_005}" \
			"R+++" \
			"S+0+q+${sctxt_option_return}" \
		)
	else
		#
		# Option 3 is selectable only if /tftpboot exists.
		#
		if [[ -d /tftpboot ]]; then
			select_3=S
		else
			select_3=N
		fi

		# Options 1 and 2 are selectable if the OS is cluster
		# aware, the node is not currently a member of the cluster,
		# and there is no nodeid file.
		#
		# Options 4 and 5 are selectable if SC 3.0 appears to
		# be configured.
		#
		select_1=S
		select_2=S
		select_4=S
		select_5=S

		#
		# If clinfo does not exist, the OS is not cluster aware.
		#
		if [[ ! -x /usr/sbin/clinfo ]]; then
			select_1=N
			select_2=N

		#
		# Make sure that we are not a member of the cluster
		#
		else
			is_cluster_member
			if [[ $? -eq ${SC_TRUE} ]]; then
				select_1=N
				select_2=N
			fi
		fi

		#
		# If the cluster is configured, allow 3 and 4, but not
		# 1 and 2.
		#
		if [[ -f "${SC_NODEID}" ]]; then
			select_1=N
			select_2=N
		else
			select_4=N
			select_5=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
			select_5=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}" \
				"${select_5}+1+5+${sctxt_option_005}" \
				"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}" \
				"N+1+4+${sctxt_option_004}" \
				"${select_5}+1+5+${sctxt_option_005}" \
				"R+++" \
				"S+1+?+${sctxt_option_help}" \
				"S+1+q+${sctxt_option_exit}" \
				"R+++" \
				"T2+++${sctxt_msg_notroot}" \
			)
		fi
	fi

	echo "${option}"

	return 0
}

####################################################
#
# 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_installnode()
{
	typeset answer
	integer iflag=1

	typeset sctxt_title="$(gettext '*** Establishing a New Cluster ***')"

	typeset saved_clustername

	# Clear all SC_ARGVARS
	argvar_clear_all_argvars

	# 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]=$(uname -n)
	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_main_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

	#
	# Install packages
	#
	interactive_install_framework || return 1

	#
	# Install patches and reload defaults
	#
	# interactive_install_patches || 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]=$(uname -n)
		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
	let SC_PATCHES_INSTALLED=0

	#
	# Pause until they hit 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_addnode()
{
	typeset answer
	typeset clustername
	typeset sponsornode
	integer iflag=2

	typeset sctxt_title="$(gettext '*** Adding a Node to an Established Cluster ***')"

	# Clear all SC_ARGVARS
	argvar_clear_all_argvars

	# 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]=$(uname -n)
	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_main_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

	#
	# Install packages
	#
	interactive_install_framework || return 1

	#
	# Install patches and reload defaults
	#
	# interactive_install_patches || 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}

	#
	# 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
	let SC_PATCHES_INSTALLED=0

	#
	#
	# Pause until they hit ENTER
	#
	sc_prompt_pause || return 1

	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

	#
	# 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

	#
	# 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 hit 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}"

	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 -l dataservice
	typeset dataservices
	typeset answer
	typeset cdromdir
	typeset pdir
	typeset pdirs
	typeset dstoken
	typeset dstokens
	typeset desc
	typeset args
	typeset foo
	typeset dstype
	typeset this_token_type
	typeset input_token_type

	integer i
	integer count
	integer pass
	integer found

	typeset dflt_ds="/cdrom/cdrom0"

	typeset sctxt_title="$(gettext '*** Adding Data Service Software ***')"

	typeset sctxt_p1="$(gettext '
		Please list all of the data services you want to add.
		List one data service identifier per line.  When
		finished, type Control-D:
	')"
	typeset sctxt_p2="$(gettext '
		This is the complete list of data services:
	')"

	# Get the data service information
	let pass=0
	while true
	do
		# If this is not the first pass, pause
		if [[ ${pass} -gt 0 ]]; then
			sc_prompt_pause || return 1
		fi
		((pass += 1))

		# 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"
			continue
		fi

		# Directory?
		if [[ ! -d "${cdromdir}" ]]; then
			printf "$(gettext 'Cannot find \"%s\".')\n\n\a" "${cdromdir}"
			continue
		fi

		# Cdtoc?
		if [[ ! -f "${cdromdir}/${SC_CDTOC}" ]]; then
               		printf "$(gettext 'Cannot find a \"%s\" file.')\n" "${SC_CDTOC}"
               		printf "$(gettext '%s has an unexpected layout.')\n\n\a" "${cdromdir}"
			continue
		fi

		# Get the Product directory paths
		pdirs="$(sed -n 's/^PRODDIR=\(.*\)/\1/p' ${cdromdir}/${SC_CDTOC})"
		if [[ -z "${pdirs}" ]]; then
			printf "$(gettext 'The \"%s\" file has no product nanes.')\n" "${SC_CDTOC}"
               		printf "$(gettext '%s has an unexpected layout.')\n\n\a" "${cdromdir}"
			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"
			continue
		fi

		# First time we print the dataservices that were qualified
		# at the time of the update, if "other" is selected, we
		# display the rest from the dataservices CD.
		dstype="supported"

		dataservices=
		while true
		do
			# List of data services
			(
				if [[ "${dstype}" == "supported" ]]; then
					sc_print_para "$(gettext 'This is the list of available data services qualified with the latest SunCluster release:')"
				else
					sc_print_para "$(gettext 'This is the list of available data services that were not qualified with the latest SunCluster release:')"
				fi
					
				printf "\t%-14s%s\n" "Identifier" "Description"
				echo

				let i=0
				for pdir in ${pdirs}
				do
					for dstoken in ${dstokens[i]}
					do
						interactive_get_support_info ${dstoken}
						if [[ $? == 0 ]]; then
							this_token_type="supported"
						else
							this_token_type="rest"
						fi
						if [[ "${dstype}" != "${this_token_type}" ]]; then
							continue
						fi
						desc="$(print_clustertoc ${cdromdir}/${pdir}/${SC_CLUSTERTOC} ${SC_SERVICE}${dstoken} "description" 2>/dev/null)"
						printf "\t%-14s%s\n" "${dstoken}" "${desc}"
					done
					((i += 1))
				done
				echo
				if [[ "${dstype}" == "supported" ]]; then
					printf "\t%-14s%s\n" "Other" "$(gettext 'Additional dataservices (non-qualified)')"
				else
					printf "\t%-14s%s\n" "Back" "$(gettext 'Initial list of dataservices')"
				fi

				echo
			) | more

			# Prompt to list all identifiers
			sc_print_para "${sctxt_p1}"

			# Get the identifiers
			while true
			do
				# Data service?
				dataservice=$(sc_prompt "$(gettext 'Data service identifier (Ctrl-D to finish):')" "" "nonl") || break 2

				if [[ "${dstype}" == "supported" ]]; then
					if [[ "${dataservice}" == "other" ]]; then
						dstype="rest"
						echo
						continue 2
					fi
				elif [[ "${dstype}" == "rest" ]]; then
					if [[ "${dataservice}" == "back" ]]; then
						dstype="supported"
						echo
						continue 2
					fi
				fi

				interactive_get_support_info ${dataservice}
				if [[ $? == 0 ]]; then
					input_token_type="supported"
				else
					input_token_type="rest"
				fi

				# Make sure it is valid
				let i=0
				let found=0
				for pdir in ${pdirs}
				do
					for dstoken in ${dstokens[i]}
					do
						if [[ "${dataservice}" = "${dstoken}" ]] && [[ "${input_token_type}" = "${dstype}" ]]; then
							let found=1
							break 2
						fi
					done
					((i += 1))
				done
				if [[ ${found} -eq 0 ]]; then
                        		printf "$(gettext '\"%s\" is not on the CD.')\n\n\a" "${dataservice}"
                        		continue
                		fi          

				# Okay, add to data services list
				dataservices="${dataservices} ${dataservice}"
			done
		done

		# make sure that there is at least one data service
		if [[ -z "${dataservices}" ]]; then
			return 0
		fi

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

		# Okay, done
		break
	done

	# Count data services and reformat with commas
	let count=0
	foo=
	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 hit ENTER
	sc_prompt_pause || return 1

	return 0
}

####################################################
#
# interactive_printrelease()
#
#	Print release information.
#
#	This function always returns zero.
#
####################################################
interactive_printrelease()
{
	# Print the release
	print_release verbose

	# Pause until they hit 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_installnode="$(gettext '*** Help Screen - Establishing a New Cluster ***')"
	typeset sctxt_title_help_addnode="$(gettext '*** Help Screen - Adding a Node to an Established Cluster ***')"
	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_installnode}"
			interactive_help_main_installnode
			;;

		'2')	# Option 2
			sc_print_title "${sctxt_title_help_addnode}"
			interactive_help_main_addnode
			;;

		'3')	# Option 3
			sc_print_title "${sctxt_title_help_jumpstart}"
			interactive_help_main_jumpstart
			;;

		'4')	# Option 4
			sc_print_title "${sctxt_title_help_adddataservice}"
			interactive_help_main_adddataservice
			;;

		'5')	# Option 5
			sc_print_title "${sctxt_title_help_printrelease}"
			interactive_help_main_printrelease
			;;

		'q')	# Return
			break
			;;
		esac

		echo
		sc_print_prompt "$(gettext 'Hit 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_installnode ;;
		'2')	interactive_addnode ;;
		'3')	interactive_jumpstart ;;
		'4')	interactive_adddataservice ;;
		'5')	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
}
