#! /bin/ksh -p
#
# ident "@(#)scsetup.ksh 1.43     04/05/11 SMI"
#
# Copyright 1999-2004 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#

#####################################################
#
# Global constants which may be set from the environment
#
# SC_DEBUG can be set to non-NULL to turn on additional debug information.
#  And, if it is set to 2, assume installmode is disabled - init cluster.
#
# SC_MAXNODEID is the maximum node id;  it does not necessarily indicate
#  the maximum number of nodes supported in the cluster for this release.
#
# SC_SCADMINDIR can be set to to point to an alternate lib dir
#
# SCSETUP_LIBRARY can be set to non-NULL to use scsetup functions without
#  actually running scsetup.
#
# SCSETUP_DEBUG_RGM_CACHEFILE can be set to a file containing scrgadm(1M)
#  output constructed especially for debug purposes.
#
#####################################################
typeset -r SC_DEBUG=${SC_DEBUG:-}
typeset -r SC_MAXNODEID=${SC_MAXNODEID:-12}
typeset -r SC_SCADMINDIR=${SC_SCADMINDIR:-/usr/cluster/lib/scadmin}
typeset -r SCSETUP_LIBRARY=${SCSETUP_LIBRARY:-}
typeset SCSETUP_DEBUG_RGM_CACHEFILE=${SCSETUP_DEBUG_RGM_CACHEFILE:-}

# debugging
typeset PRINTDEBUG
if [[ -n "${SC_DEBUG}" ]]; then
	PRINTDEBUG="echo \n"
	PRINTFDEBUG="printf"
else
	PRINTDEBUG=:
	PRINTFDEBUG=:
fi

#####################################################
#
# I18N
#
#####################################################
typeset -rx TEXTDOMAIN=SUNW_SC_CMD
typeset -x TEXTDOMAINDIR=/usr/cluster/lib/locale

#####################################################
#
# Constant globals
#
#####################################################

# Set the PATH
typeset SC_BINDIRS=/usr/cluster/bin
PATH=${SC_BINDIRS}:${PWD}:/bin:/usr/bin:/sbin:/usr/sbin:/usr/cluster/lib/sc:${PATH}; export PATH

# Program name
typeset -r PROG=${0##*/}

# Global internationalized constant strings
typeset -r YES=$(gettext 'yes')		# I18N "yes"
typeset -r NO=$(gettext 'no')		# I18N "no"

# Libs
typeset -r SC_SCADMINLIBDIR=${SC_SCADMINDIR}/lib
typeset -r SC_LIB_SC=sc_common

# Device groups
typeset -r SCSETUP_DG_VXVM_SET=vxvm
typeset -r SCSETUP_DG_VXVM_LOOKUP=VxVM

# Cluster transport
typeset -r SCSETUP_WILDCAT_ADAPTER="wrsm"
typeset -r SCSETUP_WILDCAT_JUNCTION="sw_wrsm"

# RGM
typeset -r SCSETUP_RT_NOVERSION="<unset_version>"

# Other constants
typeset -r SC_SCCONF=scconf
typeset -r SC_SCRGADM=scrgadm
typeset -r SC_SCSWITCH=scswitch
typeset -r SC_SCSTAT=scstat
typeset -r SC_SUNOS=$(uname -r)

typeset -r SCHA_CLUSTER_GET=scha_cluster_get
typeset -r SCHA_RT_GET=scha_resourcetype_get
typeset -r SCHA_RG_GET=scha_resourcegroup_get
typeset -r SCHA_RS_GET=scha_resource_get

integer -r SCHA_ERR_RSRC=14

typeset -r RAC_SETUP=/usr/cluster/lib/ucmm/rac_setup

typeset -r SCSETUP_UID=`/usr/xpg4/bin/id -u -r`
typeset -r SCSETUP_EUID=`/usr/xpg4/bin/id -u`
typeset -r SCSETUP_PID=$$
typeset -r SCSETUP_PPID=`ps -o ppid= -p $$`
typeset -r SCSETUP_LOGNAME=`logname`
typeset -r SCSETUP_TTY=`tty`
typeset -r SCSETUP_OPT="$*"

# Temp directory
if [[ -n "${SC_DEBUG}" ]]; then
	typeset -r SCSETUP_TMPDIR=/tmp
else
	typeset -r SCSETUP_TMPDIR=/var/cluster/run/scsetup
fi

# Temp files
typeset -r SCSETUP_TMP_RGLIST=${SCSETUP_TMPDIR}/${PROG}.rglist.$$
typeset -r SCSETUP_TMP_RSLIST=${SCSETUP_TMPDIR}/${PROG}.rslist.$$
typeset -r SCSETUP_TMP_RSLIST_SORTED=${SCSETUP_TMPDIR}/${PROG}.rslist_sorted.$$
typeset -r SCSETUP_TMP_PROPLIST=${SCSETUP_TMPDIR}/${PROG}.proplist.$$
typeset -r SCSETUP_TMP_SCSTAT=${SCSETUP_TMPDIR}/${PROG}.scstat.$$
typeset -r SCSETUP_TMP_RGSTATE=${SCSETUP_TMPDIR}/${PROG}.rgstate.$$
typeset -r SCSETUP_TMP_CMDOUT=${SCSETUP_TMPDIR}/${PROG}.cmdout.$$
typeset -r SCSETUP_TMP_SUMMARY=${SCSETUP_TMPDIR}/${PROG}.summary.$$

# RGM cache file for scrgadm output
if [[ -n "${SCSETUP_DEBUG_RGM_CACHEFILE}" ]] &&
    [[ -r "${SCSETUP_DEBUG_RGM_CACHEFILE}" ]]; then
	typeset -r SCSETUP_RGM_CACHEFILE=${SCSETUP_DEBUG_RGM_CACHEFILE}
else
	typeset -r SCSETUP_RGM_CACHEFILE=${SCSETUP_TMPDIR}/${PROG}.rgm.cache.$$
    	SCSETUP_DEBUG_RGM_CACHEFILE=
fi

# Scsetup process ID list
typeset -r SCSETUP_PIDLIST=${SCSETUP_TMPDIR}/${PROG}_pidlist

# Default number of desired secondaries in a device group. Note that if
# we ever want to change this value, we have to review the messages printed
# also.
integer -r SC_DEFAULT_NUMSECONDARIES=1

#####################################################
#
# Variable globals
#
#####################################################
integer SC_LOADED_COMMON=0		# set to 1 when common libs loaded
integer SCSETUP_ISMEMBER=0		# set to 1, if we are in the cluster
typeset SCSETUP_CMD_LOG			# set to log file, if there is one
typeset SCSETUP_DO_CMDSET		# input to scsetup_do_cmdset()

####################################################
#
# Create descriptor 4 as a dup of the original stdout.
# Functions which want to print user visible output
# to the original stdout have the option of using
# descriptor 4.
#
####################################################
exec 4>&1

#####################################################
#####################################################
##
## General housekeeping and other useful functions
##
#####################################################
#####################################################

#####################################################
#
# generate_event()
#
#	Generate command execution event
#
#####################################################
generate_event() {
	sc_publish_event -c "ESC_cluster_cmd"      \
			 -p $1                     \
			 -s 0			   \
			 -i 2                      \
			 -x "cmd_uid"              \
			 -y SE_DATA_TYPE_UINT32    \
			 -z ${SCSETUP_UID}         \
			 -x "cmd_euid"             \
			 -y SE_DATA_TYPE_UINT32    \
			 -z ${SCSETUP_EUID}        \
			 -x "cmd_pid"              \
			 -y SE_DATA_TYPE_UINT32    \
			 -z ${SCSETUP_PID}         \
			 -x "cmd_ppid"             \
			 -y SE_DATA_TYPE_UINT32    \
			 -z ${SCSETUP_PPID}        \
			 -x "cmd_login"            \
			 -y SE_DATA_TYPE_STRING    \
			 -z ${SCSETUP_LOGNAME}     \
			 -x "cmd_tty_stdin"        \
			 -y SE_DATA_TYPE_STRING    \
			 -z ${SCSETUP_TTY}         \
			 -x "cmd_name"             \
			 -y SE_DATA_TYPE_STRING    \
			 -z ${PROG}                \
			 -x "cmd_opt"              \
			 -y SE_DATA_TYPE_STRING    \
			 -z "${SCSETUP_OPT}"       \
			 -x "cmd_res"              \
			 -y SE_DATA_TYPE_UINT32    \
			 -z $2
}

#####################################################
#
# print_usage()
#
#	Print usage message to stderr
#
#####################################################
print_usage()
{
	printf "$(gettext 'usage: %s [-f <logfile>]')\n" "${PROG}" >&2

	return 0
}

#####################################################
#
# cleanup [exitstatus]
#
#	Remove any remaining temp files.
#
#	If an "exitstatus" is given, exit with that status.
#
#####################################################
cleanup()
{
	typeset exitstatus=$1

	typeset file
	typeset pid
	typeset foo

	rm -f ${SCSETUP_TMP_RGLIST} ${SCSETUP_TMP_RSLIST} ${SCSETUP_TMP_RSLIST_SORTED} ${SCSETUP_TMP_PROPLIST} ${SCSETUP_TMP_SCSTAT} ${SCSETUP_TMP_CMDOUT} ${SCSETUP_TMP_SUMMARY}

	scsetup_rm_scrgadmfile ${SCSETUP_RGM_CACHEFILE}
	scsetup_rm_rgstatefile ${SCSETUP_TMP_RGSTATE}

	# Let's get any leftover stuff, too
	(
		cd ${SCSETUP_TMPDIR}
		for file in *
		do
			# only interested in scsetup tmp files
			if [[ ${file} != scsetup.* ]]; then
				continue
			fi

			# Get the PID suffix from the file
			pid=$(IFS=. ; set -- ${file};  shift $(($# - 1));  echo $1)
			if [[ $(expr "${pid}" : '[0-9]*') -ne ${#pid} ]]; then
				continue
			fi

			# If the process is still running, don't touch it
			if [[ -n "$(ptree ${pid})" ]]; then
				continue
			fi

			# Zap the file
			rm -f ${file}
		done
	)

	if [[ -n "${exitstatus}" ]]; then
		generate_event "cmd_end" ${exitstatus}
		exit ${exitstatus}
	fi

	return 0
}

#####################################################
#
# loadlib() libname flag
#
#	If the "flag" is not set to 1, load the
#	named include file.
#
#	Return:
#		zero		Success
#		non-zero	Failure
#
#####################################################
loadlib()
{
	typeset libname=$1
	typeset flag=$2

	# Check flag
	if [[ "${flag}" = 1 ]]; then
		return 0
	fi

	# Load the library
	. ${libname}
	if [[ $? -ne 0 ]]; then
		printf "$(gettext '%s:  Unable to load \"%s\"')\n" "${PROG}" "${libname}" >&2
		return 1
	fi
}

#####################################################
#
# scsetup_continue()
#
#	Is it okay to continue [yes]?
#
#	Return:
#		zero		continue
#		non-zero	do not continue		
#
#####################################################
scsetup_continue()
{
	typeset answer

	answer=$(sc_prompt_yesno "$(gettext 'Is it okay to continue?')" "${YES}") || return 1

	[[ "${answer}" != "yes" ]] && return 1

	return 0
}

#####################################################
#
# scsetup_do_cmdset() [noconfirm] [nopause] [commands]
#
#	noconfirm	- if given, do not re-confirm the update
#			- if 1, just run command
#			- if 2, don't run command, but may ask to log
#
#	nopause		- if given, do not pause after running command
#
#	commands	- if given, and "nopause" is not, messages
#				should act as though multiple commands
#				were issued.
#
#	Process the list of commands found in the
#	SCSETUP_DO_CMDSET array.
#
#	Return:
#		0		Completed
#		1		Failure occurred or user typed Ctrl-D
#		2		User decided not to update
#
#####################################################
scsetup_do_cmdset()
{
	typeset noconfirm=${1}
	typeset nopause=${2}
	typeset commands=${3}

	sctxt_p1_cmd="$(gettext '
		DEBUG: Please consider the following command:
	')"
	sctxt_p1_cmds="$(gettext '
		DEBUG: Please consider the following commands:
	')"

	typeset tmpout=${SCSETUP_TMP_CMDOUT}

	typeset answer

	integer index
	integer logthem=0
	integer retval

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

	# If DEBUG, print command list
	if [[ -n "${SC_DEBUG}" ]]; then

		# Print Messages
		if [[ -z "${SCSETUP_DO_CMDSET[1]}" ]]; then
			sc_print_para "${sctxt_p1_cmd}"
		else
			sc_print_para "${sctxt_p1_cmds}"
		fi

		# Print the command(s)
		let index=0
		while [[ -n "${SCSETUP_DO_CMDSET[index]}" ]]
		do
			printf "           %s\n" "${SCSETUP_DO_CMDSET[index]}"
			((index += 1))
		done
		echo
	fi

	# If we are a cluster member, see if command(s) should be run
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then

		# Okay to run?
		if [[ -n "${noconfirm}" ]]; then
			if [[ "${noconfirm}" == 2 ]]; then
				answer="no"
			else
				answer="yes"
			fi
		else
			answer=$(sc_prompt_yesno "$(gettext 'Is it okay to proceed with the update?')" "${YES}") || return 1
		fi
		if [[ "${answer}" = "yes" ]]; then

			# Run and log them
			let index=0
			while [[ -n "${SCSETUP_DO_CMDSET[index]}" ]]
			do
				# Run command
				echo "${SCSETUP_DO_CMDSET[index]}"
				eval ${SCSETUP_DO_CMDSET[index]} >${tmpout} 2>&1
				retval=$?

				# Messages?
				if [[ -s ${tmpout} ]]; then
					more ${tmpout}
				fi
				rm -f ${tmpout}

				# Check for command success
				if [[ ${retval} -ne 0 ]]; then
					echo
					printf "$(gettext 'Command failed.')\n\n\a"
					if [[ -z "${nopause}" ]]; then
						sc_prompt_pause
					fi
					return 1
				fi

				# If it succeeded, log it, if there is a log
				if [[ -n "${SCSETUP_CMD_LOG}" ]]; then
					echo "${SCSETUP_DO_CMDSET[index]}" >>${SCSETUP_CMD_LOG}
				fi

				# Next
				((index += 1))
			done

			# If we got this far, command(s) must have succeeded
			if [[ -z "${nopause}" ]]; then
				echo
				if [[ -z "${SCSETUP_DO_CMDSET[1]}" ]] &&
				    [[ -z "${commands}" ]]; then
					sc_print_para "$(gettext 'Command completed successfully.')"
				else
					sc_print_para "$(gettext 'Commands completed successfully.')"
				fi
			fi

		# Just log it/them?
		elif [[ -n "${SCSETUP_CMD_LOG}" ]]; then
			answer=$(sc_prompt_yesno "$(gettext 'Do you just want to add a commands record to the log?')" "${YES}") || return 1

			# Just log them
			if [[ "${answer}" = "yes" ]]; then
				let logthem=1
			else
				return 2
			fi
		else
			return 2
		fi
	elif [[ -n "${SCSETUP_CMD_LOG}" ]]; then
		# Debug mode, okay to log?
		if [[ -z "${SCSETUP_DO_CMDSET[1]}" ]]; then
			answer=$(sc_prompt_yesno "$(gettext 'DEBUG:  Do you want to log this command?')" "${YES}") || return 1
		else
			answer=$(sc_prompt_yesno "$(gettext 'DEBUG:  Do you want to log these commands?')" "${YES}") || return 1
		fi
		if [[ "${answer}" = "yes" ]]; then
			let logthem=1
		fi
	fi

	# Just log commands?
	if [[ ${logthem} -eq 1 ]] && [[ -n "${SCSETUP_CMD_LOG}" ]]; then
		let index=0
		while [[ -n "${SCSETUP_DO_CMDSET[index]}" ]]
		do
			# Log command
			echo "${SCSETUP_DO_CMDSET[index]}" >>${SCSETUP_CMD_LOG}

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

	# If "nopause" is set, do not pause for reconfirmation
	if [[ -z "${nopause}" ]]; then
		sc_prompt_pause || return 1
	fi

	return 0
}

#####################################################
#
# scsetup_prompt_nodename() "nodelist" "[prompt]"
#
#	Prompt for a node name, then verify that it is one
#	of the names in the "nodelist".  If "prompt" is not given,
#	a default prompt is used.
#
#	The prompt is printed on file descriptor 4, and the answer
#	is printed to stdout.  File descriptor 4 should be
#	dupped to the original stdout before this function is called.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_prompt_nodename()
{
	typeset nodelist="${1}"
	typeset prompt="${2}"

	typeset dflt_prompt="$(gettext 'Node name?')"
	integer found
	typeset answer
	typeset node

	# If no prompt is given, use the default
	if [[ -z "${prompt}" ]]; then
		prompt="${dflt_prompt}"
	fi

	#
	# The caller of this function should have already opened
	# descriptor 4 as a dup of the original stdout.
	#
	# Dup this function's stdout to descriptor 5.
	# Then, re-direct stdout to descriptor 4.
	#
	# So, the default stdout from this function will go to
	# the original stdout (probably the tty).  Descriptor 5
	# has the answer printed to it.
	#
	exec 5>&1
	exec 1>&4

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Get the node name
		answer=$(sc_prompt "${prompt}") || return 1

		# Make sure it is a known node
		let found=0
		for node in ${nodelist}
		do
			if [[ "${answer}" = "${node}" ]]; then
				let found=1
				break
			fi
		done

		# If there is a nodelist, but the node is not found, print err
		if [[ -n "${nodelist}" ]] && [[ ${found} -eq 0 ]]; then
			printf "$(gettext 'Unknown node name.')\n\n\a"
			continue
		fi

		# okay
		echo ${answer} >&5
		break
	done

	return 0
}

#####################################################
#####################################################
##
## Get config data functions
##
#####################################################
#####################################################

#####################################################
#
# scsetup_get_installmode()
#
#	This function prints 1 if installmode is set and
#	zero if it is not.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_installmode()
{
	typeset mode

	(
		LC_ALL=C; export LC_ALL
		mode="$(${SC_SCCONF} -p | sed -n 's/^Cluster install mode:[   ]*\([^ ]*\).*/\1/p')"
		if [[ -n "${mode}" ]] && [[ "${mode}" = "enabled" ]]; then
			echo 1
		else
			echo 0
		fi
	)

	return 0
}

#####################################################
#
# scsetup_get_nodelist()
#
#	Print the list of configured nodes.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_nodelist()
{
	${SCHA_CLUSTER_GET} -O all_nodenames

	return 0
}

#####################################################
#
# scsetup_get_adapterlist() nodename
#
#	Print the list of configured adapters for the given node.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_adapterlist()
{
	typeset nodename=${1}
	typeset list
	typeset item

	if [[ -z "${nodename}" ]]; then
		return 0
	fi

	list="$(
		LC_ALL=C; export LC_ALL;
		${SC_SCCONF} -pv | sed -n 's/^ *('${nodename}') Node transport adapters:[  ]*\(.*\)/\1/p'
	)"
	for item in ${list}
	do
		if [[ ${item} != "<NULL>" ]]; then
			echo ${item}
		fi
	done

	return 0
}

#####################################################
#
# scsetup_get_junctionlist()
#
#	Print the list of configured junctions.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_junctionlist()
{
	(
		LC_ALL=C; export LC_ALL;
		${SC_SCCONF} -p | sed -n 's/^ *Cluster transport junctions:[  ]*\(.*\)/\1/p'
	)

	return 0
}

#####################################################
#
# scsetup_get_trtypes()
#
#	Print the list of configured transport types.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_trtypes()
{
	typeset trtypes
	typeset trtype
	
	# Get the types
	trtypes="$(
		LC_ALL=C; export LC_ALL;
		${SC_SCCONF} -p | sed -n 's/^ *Adapter transport type:[  ]*\(.*\)/\1/p'
	)"

	# List each one only once
	for trtype in ${trtypes}
	do
		echo ${trtype}
	done | sort | uniq

	return 0
}

#####################################################
#
# scsetup_get_endpoints()
#
#	Print the list of configured transport cable endpoints.
#	Each pair of endpoints in the list identifies a cable.
#	Note that the port number is printed for each endpoint.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_endpoints()
{
	(
		LC_ALL=C; export LC_ALL;
		${SC_SCCONF} -p | sed -n 's/^ *Transport cable:[ 	]*\([^ ]*\) *\([^ ]*\).*/\1 \2/p'
	)

	return 0
}

#####################################################
#
# scsetup_get_devicegroup_type() groupname
#
#	Print the list device group type for the given "groupname".
#
#	This function always returns zero.
#
#####################################################
scsetup_get_devicegroup_type()
{
	typeset groupname=${1}

	# If name is not given, simply return
	if [[ -z "${groupname}" ]]; then
		return 0
	fi

	(
		LC_ALL=C; export LC_ALL;
		${SC_SCCONF} -pvv | nawk '{
			if ($1 == "('${groupname}')" &&
			    $2 == "Device" &&
			    $3 == "group" &&
			    $4 == "type:") {
				print $5
			}
		}'
	)

	return 0
}

#####################################################
#
# scsetup_get_devicegroup_nodes() groupname
#
#	Print the list device group nodes for the given "groupname".
#
#	This function always returns zero.
#
#####################################################
scsetup_get_devicegroup_nodes()
{
	typeset groupname=${1}
	typeset groupnodes
	typeset node

	# If name is not given, simply return
	if [[ -z "${groupname}" ]]; then
		return 0
	fi

	# Get the list of nodes
	groupnodes="$(
		LC_ALL=C; export LC_ALL;
		${SC_SCCONF} -pvv | nawk '{
			if ($1 == "('${groupname}')" &&
			    $2 == "Device" &&
			    $3 == "group" &&
			    $4 == "node" &&
			    $5 == "list:") {
				for (i = 6;  i <= NF;  i++) {
					split($i, node, ",");
					print node[1];
				}
			}
		}'
	)"

	# Strip out any commas
	for node in ${groupnodes}
	do
		(IFS=, ; echo ${node})
	done

	return 0
}

#####################################################
#
# scsetup_get_qdevlist()
#
#	Print the list of configured quorum devices.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_qdevlist()
{
	typeset list
	typeset item

	list="$(
		LC_ALL=C; export LC_ALL;
		${SC_SCCONF} -p | sed -n 's/^ *Quorum devices:[  ]*\(.*\)/\1/p'
	)"
	for item in ${list}
	do
		if [[ ${item} != "<NULL>" ]]; then
			echo ${item}
		fi
	done

	return 0
}

#####################################################
#
# scsetup_create_rgstatefile() file
#
#	Create the given rgstate "file".   Each line of the file
#	has the following format:
#
#		<rgname> <nodename> <state>
#
#	If there are any errors in creating the file, the file
#	will not be created at all.
#
#	This function always returns 0.
#
#####################################################
scsetup_create_rgstatefile()
{
	typeset file=${1}

	# Make sure we are a cluster member
	if [[ ${SCSETUP_ISMEMBER} -ne 1 ]];  then
		return 0
	fi

	# Remove the file, if it exists
	if [[ -f "${file}" ]]; then
		rm -f ${file}
	fi

	#
	# Use scstat to get the current state for all nodes.
	# Note that we add an underbar in the event that the state is
	# two words.
	#
	(
		LC_ALL=C; export LC_ALL;
		${SC_SCSTAT} -g | nawk '/^[ 	]*Group: / {
			if (NF > 4) {
				print $2, $3,  $4 "_" $5
			} else {
				print $2, $3,  $4
			}
		}' >${file} 2>/dev/null
		if [[ $? -ne 0 ]] || [[ ! -s ${file} ]]; then
			rm -f ${file}
		fi
	)

	return 0
}

#####################################################
#
# scsetup_rm_rgstatefile() file
#
#	Remove the the given rgstatefile "file".
#
#	This function always returns 0.
#
#####################################################
scsetup_rm_rgstatefile()
{
	typeset file=${1}

	# Make sure we are a cluster member
	if [[ ${SCSETUP_ISMEMBER} -ne 1 ]];  then
		return 0
	fi

	# Remove the file, if it exists
	if [[ -f "${file}" ]]; then
		rm -f ${file}
	fi

	return 0
}

#####################################################
#
# scsetup_create_scrgadmfile() file
#
#	Create the given scrgadm output "file".
#
#	Some of the RGM get functions take an optional "cache"
#	filename and will use that file for collecting data,
#	rather than re-running scrgadm each time.   It is the
#	caller's responsibility to manage the "files", and to
#	remove unused and obsolete files.
#
#	If there are any errors in creating the file, the file
#	will not be created at all.
#
#	This function always returns 0.
#
#####################################################
scsetup_create_scrgadmfile()
{
	typeset file=${1}

	# Make sure we are a cluster member
	if [[ ${SCSETUP_ISMEMBER} -ne 1 ]]; then
		return 0
	fi

	# If this is the debug file, do not alter it
	if [[ "${file}" == "${SCSETUP_DEBUG_RGM_CACHEFILE}" ]]; then
		return 0
	fi

	# Remove the file, if it exists
	if [[ -f "${file}" ]]; then
		rm -f ${file}
	fi

	# Create the "cache" file
	(
		LC_ALL=C; export LC_ALL;
		${SC_SCRGADM} -pvv >${file} 2>/dev/null
		if [[ $? -ne 0 ]] || [[ ! -s ${file} ]]; then
			rm -f ${file}
		fi
	)

	return 0
}

#####################################################
#
# scsetup_rm_scrgadmfile() file
#
#	Remove the the given scrgadm output "file", as long as
#	it is not the "debug" file.
#
#	This function always returns 0.
#
#####################################################
scsetup_rm_scrgadmfile()
{
	typeset file=${1}

	# Make sure we are a cluster member
	if [[ ${SCSETUP_ISMEMBER} -ne 1 ]]; then
		return 0
	fi

	# If this is the debug file, we are done
	if [[ "${file}" == "${SCSETUP_DEBUG_RGM_CACHEFILE}" ]]; then
		return 0
	fi

	# Remove the file, if it exists
	if [[ -f "${file}" ]]; then
		rm -f ${file}
	fi

	return 0
}

#####################################################
#
# scsetup_get_rglist() [rgname] [rgtype] [rstype] [cachefile]
#
#	if "rgname" is not null, only return the given "rgname",
#	if it exists and matches the optional "rgtype" and "rstype".
#
#	If "rgtype" is given, only return resource groups of the given
#	type.  And, if "rstype" is also given, only resource groups of the
#	given "rgtype" and "rstype" are returned.
#
#	If "cachefile" is given, it is searched, rather than current
#	scrgadm(1M) output.
#
#	Print the list of configured resource groups.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_rglist()
{
	typeset rgname=${1}
	typeset -l rgtype=${2}		# lower case
	typeset rstype=${3}
	typeset cachefile=${4}

	typeset list
	typeset rslist
	typeset item
	typeset -l itemtype		# lower case
	typeset itemresources
	typeset foo

	integer found

	if [[ -n "${cachefile}" ]] && [[ -r "${cachefile}" ]]; then
		list="$(sed -n 's/^ *Res Group name:[  ]*\(.*\)/\1/p' ${cachefile})"
	else
		list="$(${SCHA_CLUSTER_GET} -O all_resourcegroups)"
	fi
	for item in ${list}
	do
		if [[ ${item} = "<NULL>" ]]; then
			continue
		fi
		if [[ -n "${rgname}" ]] &&
		    [[ ${item} != ${rgname} ]]; then
			continue
		fi
		if [[ -n "${rgtype}" ]]; then
			if [[ -n "${cachefile}" ]] &&
			    [[ -r "${cachefile}" ]]; then
				itemtype="$(sed -n 's/^ *('${item}') Res Group mode:[ 	]*\(.*\)/\1/p' ${cachefile})"
			else
				itemtype="$(${SCHA_RG_GET} -G ${item} -O rg_mode)"
			fi
			if [[ "${itemtype}" != "${rgtype}" ]]; then
				continue
			fi
		fi
		if [[ -n "${rstype}" ]]; then
			if [[ -n "${cachefile}" ]] &&
			    [[ -r "${cachefile}" ]]; then
				itemresources="$(sed -n 's/^ *('${item}':.*) Res resource type:[ 	]*\(.*\)/\1/p' ${cachefile})"
			else
				rslist="$(${SCHA_RG_GET} -G ${item} -O resource_list)"
				itemresources=
				for foo in ${rslist}
				do
					itemresources="${itemresources} $(${SCHA_RS_GET} -G ${item} -R ${foo} -O type)"
				done
			fi
			let found=0
			for foo in ${itemresources}
			do
				if [[ ${foo} = ${rstype} ]] || [[ ${foo} = ${rstype}:* ]]; then
					let found=1
					break
				fi
			done
			if [[ ${found} -ne 0 ]]; then
				echo ${item}
			fi
		else
			echo ${item}
		fi
	done

	return 0
}

#####################################################
#
# scsetup_get_rgtype() rgname [cachefile]
#
#	Print the type of resource group, "failover" or "scalable".
#
#	If "cachefile" is given, it is searched, rather than current
#	scrgadm(1M) output.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_rgtype()
{
	typeset rgname=${1}
	typeset cachefile=${2}

	typeset -l rgtype		# lower case

	if [[ -n "${cachefile}" ]] && [[ -r "${cachefile}" ]]; then
		rgtype="$(sed -n 's/^ *('${rgname}') Res Group mode:[ 	]*\(.*\)/\1/p' ${cachefile})"
	else
		rgtype="$(${SCHA_RG_GET} -G ${rgname} -O rg_mode)"
	fi

	if [[ "${rgtype}" == "failover" ]] ||
	    [[ "${rgtype}" == "scalable" ]]; then
		echo ${rgtype}
	fi

	return 0
}

#####################################################
#
# scsetup_get_rgdescription() rgname [cachefile]
#
#	Print the rg description
#
#	If "cachefile" is given, it is searched, rather than current
#	scrgadm(1M) output.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_rgdescription()
{
	typeset rgname=${1}
	typeset cachefile=${2}

	typeset rgdescription

	if [[ -n "${cachefile}" ]] && [[ -r "${cachefile}" ]]; then
		rgdescription="$(sed -n 's/^ *('${rgname}') Res Group RG_description:[ 	]*\(.*\)/\1/p' ${cachefile})"
	else
		rgdescription="$(${SCHA_RG_GET} -G ${rgname} -O rg_description)"
	fi

	if [[ "${rgdescription}" != "<NULL>" ]]; then
		echo "${rgdescription}"
	fi

	return 0
}

#####################################################
#
# scsetup_get_rgpathprefix() rgname [cachefile]
#
#	Print the rg pathprefix
#
#	If "cachefile" is given, it is searched, rather than current
#	scrgadm(1M) output.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_rgpathprefix()
{
	typeset rgname=${1}
	typeset cachefile=${2}

	typeset rgpathprefix

	if [[ -n "${cachefile}" ]] && [[ -r "${cachefile}" ]]; then
		rgpathprefix="$(sed -n 's/^ *('${rgname}') Res Group Pathprefix:[ 	]*\(.*\)/\1/p' ${cachefile})"
	else
		rgpathprefix="$(${SCHA_RG_GET} -G ${rgname} -O pathprefix)"
	fi

	if [[ "${rgpathprefix}" != "<NULL>" ]]; then
		echo "${rgpathprefix}"
	fi

	return 0
}

#####################################################
#
# scsetup_get_rgstate() rgname [rgstatefile] [flag] [nodename]
#
#	Print the rg state, a list of rg states, or a list of nodes.
#
#	The "flag" argument may have the following settings:
#
#	online		- list nodenames of all nodes for "rgname" which
#			  are online or pending_online
#	offline		- list nodenames of all nodes for "rgname" which
#			  are offline or pending_offline
#	unmanaged	- list nodenames of all nodes for "rgname" which
#			  are unmanaged
#	not_offline	- list nodenames of all nodes for "rgname" which
#			  are managed and not offline
#	stop_failed	- list nodenames of all nodes for "rgname" which
#			  are stop_failed
#	allnodes	- list rgstates of all nodes
#		
#	If "nodename" is given, the state for the "rgname" on the given node
#	is printed.
#
#	It is not legal to supply both "flag" and "nodename".
#
#	If both "nodename" and "flag" are NULL, the list of all rg
#	states for all nodes is printed using the format
#	"<nodename>:<state> ...".
#
#	This function always returns zero.
#
#####################################################
scsetup_get_rgstate()
{
	typeset rgname=${1}
	typeset rgstatefile=${2}
	typeset flag=${3}
	typeset nodename=${4}

	typeset rgstatelist
	typeset -l lrgstate		# lower case

	integer created_file=0
	integer i

	# If not a cluster member, return "Unknown"
	if [[ ${SCSETUP_ISMEMBER} -ne 1 ]];  then
		if [[ -n "${nodename}" ]]; then
			echo "Unknown"
		fi
		return 0
	fi

	# Create the state file, if necessary
	if [[ -z "${rgstatefile}" ]] || [[ ! -f "${rgstatefile}" ]]; then
		rgstatefile=${SCSETUP_TMP_RGSTATE}
		scsetup_create_rgstatefile ${rgstatefile}
		if [[ ! -f "${rgstatefile}" ]]; then
			scsetup_create_rgstatefile() ${rgstatefile}
			if [[ -f "${rgstatefile}" ]];  then
				let created_file=1
			else
				return 0
			fi
		fi
	fi

	# Get state data for our "rgname"
	set -A rgstatelist $(nawk '/^'${rgname}' / { print $2, $3 }' <${rgstatefile})

	# If we created the rgstatefile, get rid of it now
	if [[ ${created_file} -gt 0 ]]; then
		scsetup_rm_rgstatefile ${rgstatefile}
	fi

	# If nodename is given, just print the state for the given node.
	if [[ -n "${nodename}" ]]; then
		let i=0
		while [[ -n "${rgstatelist[i]}" ]]
		do
			if [[ ${rgstatelist[i]} == ${nodename} ]]; then
				echo ${rgstatelist[i + 1]}
				break
			fi
			((i += 2))
		done

	# If a flag is given, take the indicated action
	elif [[ -n "${flag}" ]]; then
		let i=0
		while [[ -n "${rgstatelist[i]}" ]]
		do
			lrgstate=${rgstatelist[i + 1]}
			case ${flag} in
			online)
				if [[ "${lrgstate}" == "online" ]] ||
				    [[ "${lrgstate}" == "pending_online" ]]; then
					echo ${rgstatelist[i]}
				fi
				;;

			offline)
				if [[ "${lrgstate}" == "offline" ]] ||
				    [[ "${lrgstate}" == "pending_offline" ]]; then
					echo ${rgstatelist[i]}
				fi
				;;

			unmanaged)
				if [[ "${lrgstate}" == "unmanaged" ]]; then
					echo ${rgstatelist[i]}
				fi
				;;

			not_offline)
				if [[ "${lrgstate}" != "offline" ]] &&
				    [[ "${lrgstate}" != "unmanaged" ]]; then
					echo ${rgstatelist[i]}
				fi
				;;

			stop_failed)
				if [[ "${lrgstate}" == "error--stop_failed" ]]; then
					echo ${rgstatelist[i]}
				fi
				;;

			allnodes)
				echo ${rgstatelist[i + 1]}
				;;

			esac
			((i += 2))
		done

	# Neither a nodename or a flag was given, print everything
	else 
		let i=0
		while [[ -n "${rgstatelist[i]}" ]]
		do
			echo "${rgstatelist[i]}:${rgstatelist[i + 1]}"
			((i += 2))
		done
	fi

	return 0
}

#####################################################
#
# scsetup_rgstate_string() rgstate
#
#	Print a one-word message string for the given "rgstate".
#
#	This function is the inverse of scsetup_string_rgstate()
#
#	This function always returns zero.
#
#####################################################
scsetup_rgstate_string()
{
	typeset lrgstate=${1}

	case ${lrgstate} in
	unmanaged)		echo "Unmanaged" ;;
	online)			echo "Online" ;;
	pending_online)		echo "Pending_Online" ;;
	offline)		echo "Offline" ;;
	pending_offline)	echo "Pending_Offline" ;;
	error--stop_failed)	echo "Stop_Failed" ;;
	*)			echo "Unknown" ;;
	esac

	return 0
}

#####################################################
#
# scsetup_string_rgstate() string
#
#	Print the rgstate from the one-word messages state string.
#
#	This function is the inverse of scsetup_rgstate_string()
#
#	This function always returns zero.
#
#####################################################
scsetup_string_rgstate()
{
	typeset string=${1}

	case ${string} in
	Unmanaged)		echo "unmanaged" ;;
	Online)			echo "online" ;;
	Pending_Online)		echo "pending_online" ;;
	Offline)		echo "offline" ;;
	Pending_Offline)	echo "pending_offline" ;;
	Stop_Failed)		echo "error--stop_failed" ;;
	*)			echo "unknown" ;;
	esac

	return 0
}

#####################################################
#
# scsetup_get_rslist() [rsname] [rstype] [cachefile]
#
#	if "rsname" is not null, only return the given "rsname",
#	if it exists and matches the optional "rstype".
#
#	If "rstype" is also given, only resources of the
#	given "rstype" are returned.
#
#	If "cachefile" is given, it is searched, rather than current
#	scrgadm(1M) output.
#
#	Print the list of configured resource.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_rslist()
{
	typeset rsname=${1}
	typeset rstype=${2}		# lower case
	typeset cachefile=${3}

	typeset list
	typeset rglist
	typeset item
	typeset itemtype
	typeset foo

	integer found

	# Get the list
	if [[ -n "${cachefile}" ]] && [[ -r "${cachefile}" ]]; then
		if [[ -n "${rsname}" ]]; then
			list="$(sed -n 's/^ *('$(rsname)') Res name:[  ]*\(.*\)/\1/p' ${cachefile})"
		else
			list="$(sed -n 's/^ *(.*) Res name:[  ]*\(.*\)/\1/p' ${cachefile})"
		fi
	else
		rglist="$(${SCHA_CLUSTER_GET} -O all_resourcegroups)"
		list=
		for item in ${rglist}
		do
			list="${list} $(${SCHA_RG_GET} -G ${item} -O resource_list)"
		done
		if [[ -n "${rsname}" ]]; then
			let found=0
			for item in ${list}
			do
				if [[ "${item}" == "${rsname}" ]]; then
					let found=1
					break
				fi
			done
			list=
			if [[ ${found} -ne 0 ]]; then
				list=${rsname}
			fi
		fi
	fi
	for item in ${list}
	do
		if [[ ${item} == "<NULL>" ]]; then
			continue
		fi
		if [[ -n "${rstype}" ]]; then
			if [[ -n "${cachefile}" ]] &&
			    [[ -r "${cachefile}" ]]; then
				itemtype="$(sed -n 's/^ *(.*:'${item}') Res resource type:[ 	]*\(.*\)/\1/p' ${cachefile})"
			else
				itemtype="$(${SCHA_RS_GET} -R ${item} -O type)"
			fi
			if [[ ${itemtype} != ${rstype} ]] && [[ ${itemtype} != ${rstype}:* ]]; then
				continue
			fi
		fi

		# Okay
		echo ${item}
	done

	return 0
}

#####################################################
#
# scsetup_get_rs_props() rsname rsflavor rsstate cachefile
#
#	rsname		- Resource name
#
#	rsflavor	- Must be either "extension" or "standard"
#
#	rsstate		- Must be either "enabled" or disabled"
#
#	cachefile	- File containing output of scrgadm -pvv
#
#	Get resource property attributes for the given "rsname" which
#	are settable based on the current rsstate.
#
#	The following arrays for the given resource are set:
#
#	SCSETUP_RS_PROP_NAMES		- each element contains the name of
#						a resource property.
#	SCSETUP_RS_PROP_DESCS		- each element contains the description
#						of a corresponding rs property.
#	SCSETUP_RS_PROP_TYPES		- each element contains the type of
#						rs property.
#	SCSETUP_RS_PROP_VALUES		- each element contains the current
#						value of an rs property.
#
#	This function always returns 0.
#
#####################################################
scsetup_get_rs_props()
{
	typeset rsname=${1}
	typeset rsflavor=${2}
	typeset rsstate=${3}
	typeset cachefile=${4}

	typeset -l proptype			# lower case
	typeset value
	typeset values
	typeset foo

	integer i

	set -A SCSETUP_RS_PROP_NAMES
	set -A SCSETUP_RS_PROP_DESCS
	set -A SCSETUP_RS_PROP_TYPES
	set -A SCSETUP_RS_PROP_VALUES
	let i=0

	# Make sure we can read the scrgadm file
	if [[ ! -r "${cachefile}" ]]; then
		return 0
	fi

	################
	#
	# Perl script
	#
	################
	/usr/bin/perl -e '

	my $rsname=$ARGV[0];
	my $rsflavor=$ARGV[1];
	my $rsstate=$ARGV[2];
	my $filename=$ARGV[3];

	my $property;
	my $rstype;
	my $tunability;
	my $value;
	my @properties;
	my %allowable;

	my %prop_names;
	my %prop_descs;
	my %prop_types;
	my %prop_values;

	# Based on state, set allowable tunability values
	$allowable{"Anytime"} = 1;
	if ($rsstate eq "disabled") {
		$allowable{"When disabled"} = 1;
	}
		
	# Special handling
	if ($rsflavor eq "standard") {

		# Special handling - R_description
		$property = "R_description";
		push(@properties, $property);
		$prop_names{$property} = 1;
		$prop_descs{$property} = "Description";
		$prop_types{$property} = "String";

		# Special handling - Resource_dependencies
		$property = "Resource_dependencies";
		push(@properties, $property);
		$prop_names{$property} = 1;
		$prop_descs{$property} = "Strong resource dependencies";
		$prop_types{$property} = "Stringarray";

		# Special handling - Resource_dependencies_weak
		$property = "Resource_dependencies_weak";
		push(@properties, $property);
		$prop_names{$property} = 1;
		$prop_descs{$property} = "Weak resource dependencies";
		$prop_types{$property} = "Stringarray";

		# Special handling - Resource_dependencies_restart
		$property = "Resource_dependencies_restart";
		push(@properties, $property);
		$prop_names{$property} = 1;
		$prop_descs{$property} = "Resource restart dependencies";
		$prop_types{$property} = "Stringarray";
	}
		
	# Get all "extension" or "standard" properties for the resource
	open (FD, "<$filename") || exit(1);
	while (<FD>) {
		($property) = /^\W+\(.*:$rsname:(.*)\)\s+Res property class:\s+$rsflavor/i;
		if ($property) {
			push(@properties, $property);
			$prop_names{$property} = 1;
		}
		if (!$rstype) {
			($rstype) = /^\W+\(.*:$rsname\)\s+Res resource type:\s+(.*)/i;
		}
	}

	# Make sure we have a resource type
	if (!$rstype) {
		exit(1);
	}

	# Weed out the properties we cannot set because of state
	open (FD, "<$filename") || exit(1);
	while (<FD>) {
		($property, $tunability) = /^\W+\($rstype:([^:]*)\)\s+Res Type param tunability:\s+(.*)/i;
		if ($property && $tunability &&
		    $prop_names{$property} && !$allowable{$tunability}) {
			delete($prop_names{$property});
		}
	}

	# One more pass to get descriptions, types, and values
	open (FD, "<$filename") || exit(1);
	while (<FD>) {
		# Descriptions
		($property, $value) = /^\W+\(.*:$rsname:(.*)\)\s+Res property description:\s+(.*)/i;
		if ($property && $value && $prop_names{$property}) {
			$prop_descs{$property} = $value;
		}

		# Types
		($property, $value) = /^\W+\(.*:$rsname:(.*)\)\s+Res property type:\s+(.*)/i;
		if ($property && $value && $prop_names{$property}) {
			$prop_types{$property} = $value;
		}

		# Values
		($property, $value) = /^\W+\(.*:$rsname:(.*)\)\s+Res property value:\s+(.*)/i;
		if ($property && $value && $prop_names{$property}) {
			$prop_values{$property} = $value;
		}

		# Special handling - R_description
		($value) = /^\W+\(.*:$rsname\)\s+Res R_description:\s+(.*)/i;
		$property = "R_description";
		if ($value && $prop_names{$property}) {
			$prop_values{$property} = $value;
		}

		# Special handling - Resource_dependencies
		($value) = /^\W+\(.*:$rsname\)\s+Res strong dependencies:\s+(.*)/i;
		$property = "Resource_dependencies";
		if ($value && $prop_names{$property}) {
			$prop_values{$property} = $value;
		}

		# Special handling - Resource_dependencies_weak
		($value) = /^\W+\(.*:$rsname\)\s+Res weak dependencies:\s+(.*)/i;
		$property = "Resource_dependencies_weak";
		if ($value && $prop_names{$property}) {
			$prop_values{$property} = $value;
		}

		# Special handling - Resource_dependencies_restart
		($value) = /^\W+\(.*:$rsname\)\s+Res restart dependencies:\s+(.*)/i;
		$property = "Resource_dependencies_restart";
		if ($value && $prop_names{$property}) {
			$prop_values{$property} = $value;
		}
	}
	close (FD);

	# Fix descriptions, types and values
	foreach $property (keys(%prop_names)) {
		if (!$prop_descs{$property}) {
			$prop_descs{$property} = "-";
		}
		if (!$prop_types{$property}) {
			$prop_types{$property} = "-";
		}
		if (!$prop_values{$property}) {
			$prop_values{$property} = "-";
		}
	}

	# Print the list of properties
	foreach $property (@properties) {
		if (!$prop_names{$property}) {
			next;
		}
		print "$property\n";
		print "$prop_types{$property}\n";
		print "$prop_values{$property}\n";
		print "$prop_descs{$property}\n";
	}

	################
	#
	# End of Perl script
	#
	################
' ${rsname} ${rsflavor} ${rsstate} ${cachefile} | \
	while read SCSETUP_RS_PROP_NAMES[i]
	do
		# Types
		read SCSETUP_RS_PROP_TYPES[i]
		if [[ "${SCSETUP_RS_PROP_TYPES[i]}" == "-" ]];  then
			SCSETUP_RS_PROP_TYPES[i]=
		fi
		proptype=${SCSETUP_RS_PROP_TYPES[i]}

		# Values - insert commas as needed
		read values
		if [[ -n "${values}" ]] &&
		    [[ "${values}" != "-" ]];  then
			if [[ "${proptype}" == "stringarray" ]]; then
				foo=
				for value in ${values}
				do
					if [[ -z "${foo}" ]]; then
						foo="${value}"
					else
						foo="${foo},${value}"
					fi
				done
				SCSETUP_RS_PROP_VALUES[i]="${foo}"
			else
				SCSETUP_RS_PROP_VALUES[i]="${values}"
			fi
		fi

		# Descriptions
		read SCSETUP_RS_PROP_DESCS[i]
		if [[ "${SCSETUP_RS_PROP_DESCS[i]}" == "-" ]] ||
		    [[ "${SCSETUP_RS_PROP_DESCS[i]}" == "<NULL>" ]];  then
			SCSETUP_RS_PROP_DESCS[i]=
		fi

		# Next
		((i += 1))
	done

	return 0
}

#####################################################
#
# scsetup_get_rs_prop_index() ${propname}
#
#	Prin the index of the property in the SCSETUP_RS_PROP_NAMES array.
#
#	Case is ignored.
#
#	Return values:
#
#		-1		Unknown property
#		0		Success
#
#####################################################
scsetup_get_rs_prop_index()
{
	typeset -l propname=${1}		# lower case

	typeset -l name				# lower case
	integer index
	integer found

	# Get the index
	let index=0
	let found=0
	for name in ${SCSETUP_RS_PROP_NAMES[*]}
	do
		if [[ "${propname}" == "${name}" ]]; then
			let found=1
			break
		fi

		((index += 1))
	done

	# If we didn't find it, return -1
	if [[ ${found} -ne 1 ]]; then
		return 1
	fi

	# Print the index
	echo ${index}

	return 0
}

#####################################################
#
# scsetup_get_rs_prop_value() ${propname}
#
#	Print the property value of the given property using
#	the following arrays:
#
#	SCSETUP_RS_PROP_NAMES		- each element contains the name of
#						a resource property.
#	SCSETUP_RS_PROP_VALUES		- each element contains the value
#						of a corresponding rs property.
#
#	Case is ignored.
#
#	Return values:
#
#		-1		Unknown property
#		0		Success
#
#####################################################
scsetup_get_rs_prop_value()
{
	typeset -l propname=${1}		# lower case

	typeset index

	# Get the index
	index=$(scsetup_get_rs_prop_index ${propname})

	# Print the value
	if [[ -n "${index}" ]]; then
		echo ${SCSETUP_RS_PROP_VALUES[index]}
	else
		return 1
	fi

	return 0
}

#####################################################
#
# scsetup_get_rs_prop_type() ${propname}
#
#	Print the property type of the given property using
#	the following arrays:
#
#	SCSETUP_RS_PROP_NAMES		- each element contains the name of
#						a resource property.
#	SCSETUP_RS_PROP_TYPES		- each element contains the type
#						of a corresponding rs property.
#
#	Case is ignored.
#
#	Return values:
#
#		-1		Unknown property
#		0		Success
#
#####################################################
scsetup_get_rs_prop_type()
{
	typeset -l propname=${1}		# lower case

	typeset index

	# Get the index
	index=$(scsetup_get_rs_prop_index ${propname})

	# Print the value
	if [[ -n "${index}" ]]; then
		echo ${SCSETUP_RS_PROP_TYPES[index]}
	else
		return 1
	fi

	return 0
}

#####################################################
#
# scsetup_get_rs_prop_description() propname
#
#	Print the property description of the given property using
#	the following arrays:
#
#	SCSETUP_RS_PROP_NAMES		- each element contains the name of
#						a resource property.
#	SCSETUP_RS_PROP_DESC		- each element contains the descript
#						of a corresponding rs property.
#
#	Case is ignored.
#
#	Return values:
#
#		-1		Unknown property
#		0		Success
#
#####################################################
scsetup_get_rs_prop_description()
{
	typeset -l propname=${1}		# lower case

	typeset index

	# Get the index
	index=$(scsetup_get_rs_prop_index ${propname})

	# Print the value
	if [[ -n "${index}" ]]; then
		echo ${SCSETUP_RS_PROP_DESCS[index]}
	else
		return 1
	fi

	return 0
}

#####################################################
#
# scsetup_get_upgradeable_resources() [cachefile]
#
#	Set the following arrays:
#
#	SCSETUP_RS_NAMES_UPGD		- each element contains the name of
#						a resource.  If a resource
#						can be upgraded to more than
#						one version, there will be
#						an element for each version.
#	SCSETUP_RS_CVERS_UPGD		- each element contains the current
#						version of a corresponding
#						RS_NAME.
#	SCSETUP_RS_TYPE_UPGD		- each element contains the resource
#						type of the corresponding
#						rs_name, without version.
#	SCSETUP_RS_PVERS_UPGD		- each element contains a possible
#						version upgrade of a
#						corresponding rs_name.
#						Items in this array may be
#						NULL.
#	SCSETUP_RS_WHEN_UPGD		- each element contains the "when"
#						restriction of a
#						version upgrade of a
#						corresponding rs_name.
#						Items in this array may be
#						NULL.
#
#	Note that there will be at least one element in each array
#	for each resource, even if the resource has no upgradable options.
#
#	Also note that there will be multiple elements in each array
#	for those resources which can be upgraded to more than one version.
#
#	If "cachefile" is given, it is searched, rather than current
#	scrgadm(1M).
#
#	This function always returns zero.
#
#####################################################
scsetup_get_upgradeable_resources()
{
	typeset cachefile=${1}

	set -A SCSETUP_RS_NAMES_UPGD
	set -A SCSETUP_RS_CVERS_UPGD
	set -A SCSETUP_RS_TYPE_UPGD
	set -A SCSETUP_RS_PVERS_UPGD
	set -A SCSETUP_RS_WHEN_UPGD

	# Variables for call to scsetup_get_upgradeable_rstypes()
	typeset SCSETUP_RT_NAMES_UPGD		# RT names
	typeset SCSETUP_RT_VERS_UPGD		# RT versions
	typeset SCSETUP_RT_FROM_UPGD		# RT upgrade from versions
	typeset SCSETUP_RT_WHEN_UPGD		# RT upgrade when

	typeset rslist
	typeset rsnames
	typeset rsname
	typeset rstypes
	typeset rstype
	typeset rsversions
	typeset rsversion

	integer i1
	integer i2
	integer i3

	# If not a cluster member, we at least need a cachefile
	if [[ ${SCSETUP_ISMEMBER} -ne 1 ]] &&
	    [[ ! -r "${cachefile}" ]]; then
		return 0
	fi

	# Get the list of resources
	rslist="$(scsetup_get_rslist "" "" ${cachefile})"

	# For each resource, get the resource names, types, versions
	let i1=0
	set -A rsnames
	set -A rstypes
	set -A rsversions
	for rsname in ${rslist}
	do
		# Get the name of the resource type
		if [[ -n "${cachefile}" ]] &&
		    [[ -r "${cachefile}" ]]; then
			rstype="$(sed -n 's/^ *(.*:'${rsname}') Res resource type:[ 	]*\(.*\)/\1/p' ${cachefile})"
		else
			rstype="$(${SCHA_RS_GET} -R ${rsname} -O type)"
		fi
		if [[ -z "${rstype}" ]]; then
			continue
		fi

		# Strip the version from the rt name
		rstype=$(IFS=: ; set -- ${rstype};  echo ${1})

		# Get the rs version
		if [[ -n "${cachefile}" ]] &&
		    [[ -r "${cachefile}" ]]; then
			# If 3.1 or beyond, resource will have version
			rsversion="$(sed -n 's/^ *(.*:'${rsname}') Res type version:[ 	]*\(.*\)/\1/p' ${cachefile})"

			# Otherwise, it inherits from resource type
			if [[ -z "${rsversion}" ]]; then
				rsversion="$(sed -n 's/^ *('${rstype}') Res Type version:[ 	]*\(.*\)/\1/p' ${cachefile})"
			fi
		else
			# If 3.1 or beyond, resource will have version
			rsversion="$(${SCHA_RS_GET} -R ${rsname} -O rt_version)"

			# Otherwise, it inherits from resource type
			if [[ -z "${rsversion}" ]]; then
				rsversion="$(${SCHA_RT_GET} -T ${rstype} -O rt_version)"
			fi
		fi
		if [[ -z "${rsversion}" ]]; then
			# See if associated type has a version
			rsversion="${SCSETUP_RT_NOVERSION}"
		fi

		# Add to lists
		rsnames[i1]=${rsname}
		rstypes[i1]=${rstype}
		rsversions[i1]=${rsversion}

		# Next
		((i1 += 1))
	done

	# Get the rt upgrade data
	set -A SCSETUP_RT_NAMES_UPGD
	set -A SCSETUP_RT_VERS_UPGD
	set -A SCSETUP_RT_FROM_UPGD
	set -A SCSETUP_RT_WHEN_UPGD
	scsetup_get_upgradeable_rstypes ${cachefile}

	# Set up the exported arrays
	let i1=0
	let i2=0
	while [[ -n "${rsnames[i1]}" ]]
	do
		SCSETUP_RS_NAMES_UPGD[i2]=${rsnames[i1]}
		SCSETUP_RS_CVERS_UPGD[i2]=${rsversions[i1]}
		SCSETUP_RS_TYPE_UPGD[i2]=${rstypes[i1]}

		let i3=0
		while [[ -n "${SCSETUP_RT_NAMES_UPGD[i3]}" ]]
		do
			if [[ "${SCSETUP_RT_NAMES_UPGD[i3]}" != "${SCSETUP_RS_TYPE_UPGD[i2]}" ]] ||
			    [[ "${SCSETUP_RT_FROM_UPGD[i3]}" != "${SCSETUP_RS_CVERS_UPGD[i2]}" ]]; then
				# Next RT
				((i3 += 1))
				continue
			fi

			# Add another RS?
			if [[ -n "${SCSETUP_RS_PVERS_UPGD[i2]}" ]]; then
				((i2 += 1))
				SCSETUP_RS_NAMES_UPGD[i2]=${rsnames[i1]}
				SCSETUP_RS_CVERS_UPGD[i2]=${rsversions[i1]}
				SCSETUP_RS_TYPE_UPGD[i2]=${rstypes[i1]}
			fi

			# Add possible new version and when to RS
			SCSETUP_RS_PVERS_UPGD[i2]=${SCSETUP_RT_VERS_UPGD[i3]}
			SCSETUP_RS_WHEN_UPGD[i2]="${SCSETUP_RT_WHEN_UPGD[i3]}"

			# Next RT
			((i3 += 1))
		done

		# Next RS
		((i1 += 1))
		((i2 += 1))
	done

	return 0
}

#####################################################
#
# scsetup_get_upgradeable_rstypes() [cachefile]
#
#	Set the following arrays:
#
#	SCSETUP_RT_NAMES_UPGD		- each element contains the name of
#						an upgradeable resource type,
#						without version.
#	SCSETUP_RT_VERS_UPGD		- each element contains the version
#						of a corresponding rs type.
#	SCSETUP_RT_FROM_UPGD		- each element contains a
#						"from" version of a 
#						corresponding rs type.
#	SCSETUP_RT_WHEN_UPGD		- each element contains a
#						"when" corresponding rs
#						type can be upgraded to.
#
#	If "cachefile" is given, it is searched, rather than current
#	scrgadm(1M).
#
#	This function always returns zero.
#
#####################################################
scsetup_get_upgradeable_rstypes()
{
	typeset cachefile=${1}

	set -A SCSETUP_RT_NAMES_UPGD
	set -A SCSETUP_RT_VERS_UPGD
	set -A SCSETUP_RT_FROM_UPGD
	set -A SCSETUP_RT_WHEN_UPGD

	typeset cmd
	typeset rstype
	typeset version
	typeset from
	typeset when

	integer index

	# Get the types
	if [[ -n "${cachefile}" ]] && [[ -r "${cachefile}" ]]; then
		cmd="cat ${cachefile}"
	else
		cmd="${SC_SCRGADM} -pvv -t ."
	fi
	let index=0
	${cmd} | sed -n 's/^ *(\(.*\)) Res Type upgrade from \(.*\):[    ]*\(.*\)/\1 \2 \3/p' | while read rstype from when
	do
		if [[ -z "${rstype}" ]] ||
		    [[ -z "${from}" ]] ||
		    [[ -z "${when}" ]]; then
			continue
		fi

		(IFS=: ; set -- ${rstype}; echo $*) | read rstype version
		if [[ -z "${version}" ]]; then
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]];  then
				version="$(${SCHA_RT_GET} -T ${rstype} -O rt_version)"
			fi
			if [[ -z "${version}" ]]; then
				version="${SCSETUP_RT_NOVERSION}"
			fi
		fi
		SCSETUP_RT_NAMES_UPGD[index]=${rstype}
		SCSETUP_RT_VERS_UPGD[index]=${version}
		SCSETUP_RT_FROM_UPGD[index]=${from}
		SCSETUP_RT_WHEN_UPGD[index]="${when}"

		# Next
		((index += 1))
	done

	return 0
}

#####################################################
#
# scsetup_get_registered_rstypes() [no_nettypes] [cachefile]
#
#	Set the following arrays:
#
#	SCSETUP_RT_NAMES_REG		- each element contains the name of
#						a registered resource type.
#	SCSETUP_RT_DESCS_REG		- each element contains the description
#						of a corresponding rs type.
#	SCSETUP_RT_MODE_REG		- each element contains "failover" or
#						"scalable" for a corresponding
#						resource type.
#
#	If "no_nettypes" is given, do not return network resources.
#
#	If "cachefile" is given, it is searched, rather than current
#	scrgadm(1M) or scha command output.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_registered_rstypes()
{
	typeset no_nettypes=${1}
	typeset cachefile=${2}

	set -A SCSETUP_RT_NAMES_REG
	set -A SCSETUP_RT_DESCS_REG
	set -A SCSETUP_RT_MODE_REG

	integer index
	typeset rstype
	typeset rstypes
	typeset -l lmode		# lower case

	# Get the types
	if [[ -n "${cachefile}" ]] && [[ -r "${cachefile}" ]]; then
		set -A rstypes $(sed -n 's/^ *Res Type name:[  ]*\(.*\)/\1/p' ${cachefile})
	else
		set -A rstypes $(${SCHA_CLUSTER_GET} -O all_resourcetypes)
	fi

	# Set SCSETUP_RT_NAMES_REG, filtering out net resources, if needed
	if [[ -n "${no_nettypes}" ]]; then
		set -A SCSETUP_RT_NAMES_REG
		let index=0
		for rstype in ${rstypes[*]}
		do
			scsetup_is_network_rstype ${rstype} || continue
			SCSETUP_RT_NAMES_REG[index]=${rstype}
			((index += 1))
		done
	else
		set -A SCSETUP_RT_NAMES_REG ${rstypes[*]}
	fi

	# And, the descriptions and types
	let index=0
	for rstype in ${SCSETUP_RT_NAMES_REG[*]}
	do
		if [[ -n "${cachefile}" ]] && [[ -r "${cachefile}" ]]; then
			SCSETUP_RT_DESCS_REG[index]="$(sed -n 's/^ *('${rstype}') Res Type description:[  ]*\(.*\)/\1/p' ${cachefile})"
			lmode="$(sed -n 's/^ *('${rstype}') Res Type failover:[ 	]*\(.*\)/\1/p' ${cachefile})"
		else
			SCSETUP_RT_DESCS_REG[index]="$(${SCHA_RT_GET} -T ${rstype} -O rt_description)"
			lmode="$(${SCHA_RT_GET} -T ${rstype} -O failover)"
		fi

		# false is "scalable", true is "failover"
		if [[ "${lmode}" == "false" ]]; then
			SCSETUP_RT_MODE_REG[index]=scalable
		else
			SCSETUP_RT_MODE_REG[index]=failover
		fi

		# Next
		((index += 1))
	done

	return 0
}

#####################################################
#
# scsetup_get_unregistered_rstypes() [no_nettypes]
#
#	Set the following arrays:
#
#	SCSETUP_RT_NAMES_UNREG		- each element contains the name of
#						an unregistered type.
#	SCSETUP_RT_DESCS_UNREG		- each element contains the description
#						of a corresponding unreg. type.
#	SCSETUP_RT_MODE_UNREG		- each element contains "failover" or
#						"scalable" for a corresponding
#						resource type.
#
#	scsetup_get_registered_rstypes() should always be called first
#	to setup the _REG arrays.  Otherwise, all resource types will
#	be returned.
#
#	If "no_nettypes" is given, do not return network resources.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_unregistered_rstypes()
{
	typeset no_nettypes=${1}

	set -A SCSETUP_RT_NAMES_UNREG
	set -A SCSETUP_RT_DESCS_UNREG
	set -A SCSETUP_RT_MODE_UNREG

	integer index
	typeset rstype
	typeset file
	typeset key
	typeset vid
	typeset upgradeable
	typeset version
	typeset description
	typeset -l lmode		# lower case
	typeset foo

	# Get from files
	let index=0
	for file in /usr/cluster/lib/rgm/rtreg/*
	do
		# Use awk script to grab all variables of interest
		(
		    LC_ALL=C; export LC_ALL;
		    nawk -F= '
			BEGIN {
				len = 5;

				keys[1] = "vendor_id";
				keys[2] = "resource_type";
				keys[3] = "rt_version";
				keys[4] = "failover";
				keys[5] = "rt_description";

				values[1] = "-";
				values[2] = "-";
				values[3] = "-";
				values[4] = "-";
				values[5] = "-";

				upgrade = "-";
			}

			/#\$upgrade/ {
				upgrade = "true";
			}

			/[^#]*[=]/ {
				split($0, array, "=");
				gsub(/[	 ]*/, "", array[1]);
				key = tolower(array[1]);
				for (i = 1;  i <= len;  ++i) {
					if (key == keys[i]) {
						value=array[2];
						sub(/[ 	"]*/, "", value);
						sub(/[";].*/, "", value);
						values[i] = value;
					}
				}
			}

			END {
				printf("%s %s %s %s %s %s\n",
				    values[1], values[2], values[3],
				    values[4], upgrade, values[5]);
			}

		    ' <${file}
		) | read vid rstype version lmode upgradeable description

		# Clear any variables set to "-"
		if [[ "${vid}" == "-" ]]; then
			vid=
		fi
		if [[ "${rstype}" == "-" ]]; then
			rstype=
		fi
		if [[ "${version}" == "-" ]]; then
			version=
		fi
		if [[ "${lmode}" == "-" ]]; then
			lmode=
		fi
		if [[ "${upgradeable}" == "-" ]]; then
			upgradeable=
		fi
		if [[ "${description}" == "-" ]]; then
			description=
		fi

		# Name
		if [[ -z "${rstype}" ]]; then
			continue
		fi
		if [[ -n "${upgradeable}" ]] &&
		    [[ "${rstype}" != *:* ]] &&
		    [[ -n "${version}" ]]; then
			rstype=${rstype}:${version}
		fi
			
		# Pre-pend venor ID
		if [[ -n "${vid}" ]]; then
			rstype=${vid}.${rstype}
		fi

		# Check for net type
		if [[ -n "${no_nettypes}" ]]; then
			scsetup_is_network_rstype ${rstype} || continue
		fi

		# If it is already registered, skip it
		for foo in ${SCSETUP_RT_NAMES_REG[*]}
		do
			if [[ "${rstype}" == "${foo}" ]]; then
				continue 2
			fi
		done

		# Not registered, add to arrays
		SCSETUP_RT_NAMES_UNREG[index]=${rstype}

		# Description
		SCSETUP_RT_DESCS_UNREG[index]="${description}"

		# Failover or scalable?
		if [[ "${lmode}" == "true" ]]; then
			SCSETUP_RT_MODE_UNREG[index]="failover"
		else
			SCSETUP_RT_MODE_UNREG[index]="scalable"
		fi

		# Next
		((index += 1))
	done

	return 0
}

#####################################################
#
# scsetup_get_rstype_extprops() rstype_name cachefile
#
#	Set the following arrays for the given resource type name:
#
#	SCSETUP_RT_PROP_NAMES		- each element contains the name of
#						a resource property.
#	SCSETUP_RT_PROP_DESCS		- each element contains the description
#						of a corresponding rs property.
#	SCSETUP_RT_PROP_TYPES		- each element contains the type of
#						rs property.
#	SCSETUP_RT_PROP_DFLTS		- each element contains the default
#						value of an rs property.
#
#	We only look at registered resource types.
#
#	Note that we cannot use the scha_cmds(1ha) here, since there are
#	no options for getting resource type parameters.
#
#	If "cachefile" is given, it is searched, rather than current
#	scrgadm(1M) output.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_rstype_extprops()
{
	typeset rstype_name=${1}
	typeset cachefile=${2}

	integer i

	set -A SCSETUP_RT_PROP_NAMES
	set -A SCSETUP_RT_PROP_DESCS
	set -A SCSETUP_RT_PROP_TYPES
	set -A SCSETUP_RT_PROP_DFLTS
	let i=0

	# Make sure we can read the scrgadm file
	if [[ ! -r "${cachefile}" ]]; then
		return 0
	fi

	################
	#
	# Perl script
	#
	################
	/usr/bin/perl -e '

	my $rtname=$ARGV[0];
	my $filename=$ARGV[1];

	my $property;
	my $value;
	my @properties;

	my %prop_names;
	my %prop_descs;
	my %prop_types;
	my %prop_defaults;

	# Get all "extension" properties for the resource type
	open (FD, "<$filename") || exit(1);
	while (<FD>) {
		($property) = /^\W+\($rtname:([^:]*)\)\s+Res Type param extension:\s+True/i;
		if ($property) {
			push(@properties, $property);
			$prop_names{$property} = 1;
		}
	}

	# One more pass to get descriptions, types, and defaults
	open (FD, "<$filename") || exit(1);
	while (<FD>) {
		# Descriptions
		($property, $value) = /^\W+\($rtname:([^:]*)\)\s+Res Type param description:\s+(.*)/i;
		if ($property && $value && $prop_names{$property}) {
			$prop_descs{$property} = $value;
		}

		# Types
		($property, $value) = /^\W+\($rtname:([^:]*)\)\s+Res Type param type:\s+(.*)/i;
		if ($property && $value && $prop_names{$property}) {
			$prop_types{$property} = $value;
		}

		# Defaults
		($property, $value) = /^\W+\($rtname:([^:]*)\)\s+Res Type param default:\s+(.*)/i;
		if ($property && $value && $prop_names{$property}) {
			$prop_defaults{$property} = $value;
		}
	}
	close (FD);

	# Fix descriptions, types and values
	foreach $property (keys(%prop_names)) {
		if (!$prop_descs{$property}) {
			$prop_descs{$property} = "-";
		}
		if (!$prop_types{$property}) {
			$prop_types{$property} = "-";
		}
		if (!$prop_defaults{$property}) {
			$prop_defaults{$property} = "-";
		}
	}

	# Print the list of properties
	foreach $property (@properties) {
		if (!$prop_names{$property}) {
			next;
		}
		print "$property\n";
		print "$prop_types{$property}\n";
		print "$prop_descs{$property}\n";
		print "$prop_defaults{$property}\n";
	}

	################
	#
	# End of Perl script
	#
	################
' ${rstype_name} ${cachefile} | \
	while read SCSETUP_RT_PROP_NAMES[i]
	do
		# Types
		read SCSETUP_RT_PROP_TYPES[i]
		if [[ "${SCSETUP_RT_PROP_TYPES[i]}" == "-" ]] ||
		    [[ "${SCSETUP_RT_PROP_TYPES[i]}" == "<NULL>" ]];  then
			SCSETUP_RT_PROP_TYPES[i]=
		fi

		# Descriptions
		read SCSETUP_RT_PROP_DESCS[i]
		if [[ "${SCSETUP_RT_PROP_DESCS[i]}" == "-" ]] ||
		    [[ "${SCSETUP_RT_PROP_DESCS[i]}" == "<NULL>" ]];  then
			SCSETUP_RT_PROP_DESCS[i]=
		fi

		# Defaults
		read SCSETUP_RT_PROP_DFLTS[i]
		if [[ "${SCSETUP_RT_PROP_DFLTS[i]}" == "-" ]] ||
		    [[ "${SCSETUP_RT_PROP_DFLTS[i]}" == "<unset>" ]];  then
			SCSETUP_RT_PROP_DFLTS[i]=
		fi

		# Next
		((i += 1))
	done

	return 0
}

#####################################################
#
# scsetup_get_rstype_extprop_index() ${propname}
#
#	Prin the index of the property in the SCSETUP_RT_PROP_NAMES array.
#
#	Case is ignored.
#
#	Return values:
#
#		-1		Unknown property
#		0		Success
#
#####################################################
scsetup_get_rstype_extprop_index()
{
	typeset -l propname=${1}		# lower case

	typeset -l name				# lower case
	integer index
	integer found

	# Get the index
	let index=0
	let found=0
	for name in ${SCSETUP_RT_PROP_NAMES[*]}
	do
		if [[ "${propname}" == "${name}" ]]; then
			let found=1
			break
		fi

		((index += 1))
	done

	# If we didn't find it, return -1
	if [[ ${found} -ne 1 ]]; then
		return 1
	fi

	# Print the index
	echo ${index}

	return 0
}

#####################################################
#
# scsetup_get_rstype_extprop_type() propname
#
#	Print the extenstion property type of the given propname using
#	the following arrays:
#
#	SCSETUP_RT_PROP_NAMES		- each element contains the name of
#						a resource property.
#	SCSETUP_RT_PROP_TYPES		- each element contains the type
#						of a corresponding rs property.
#
#	Case is ignored.
#
#	Return values:
#
#		-1		Unknown property
#		0		Success
#
#####################################################
scsetup_get_rstype_extprop_type()
{
	typeset -l propname=${1}		# lower case

	typeset index

	# Get the index
	index=$(scsetup_get_rstype_extprop_index ${propname})

	# Print the value
	if [[ -n "${index}" ]]; then
		echo ${SCSETUP_RT_PROP_TYPES[index]}
	else
		return 1
	fi

	return 0
}

#####################################################
#
# scsetup_get_rstype_extprop_desc() propname
#
#	Print the extenstion property description of the given propname using
#	the following arrays:
#
#	SCSETUP_RT_PROP_NAMES		- each element contains the name of
#						a resource property.
#	SCSETUP_RT_PROP_DESCS		- each element contains the description
#						of a corresponding rs property.
#
#	Case is ignored.
#
#	Return values:
#
#		-1		Unknown property
#		0		Success
#
#####################################################
scsetup_get_rstype_extprop_desc()
{
	typeset -l propname=${1}		# lower case

	typeset index

	# Get the index
	index=$(scsetup_get_rstype_extprop_index ${propname})

	# Print the value
	if [[ -n "${index}" ]]; then
		echo ${SCSETUP_RT_PROP_DESCS[index]}
	else
		return 1
	fi

	return 0
}

#####################################################
#
# scsetup_get_rstype_extprop_dflt() propname
#
#	Print the extenstion property default of the given propname using
#	the following arrays:
#
#	SCSETUP_RT_PROP_NAMES		- each element contains the name of
#						a resource property.
#	SCSETUP_RT_PROP_DFLTS		- each element contains the description
#						of a corresponding rs property.
#
#	Case is ignored.
#
#	This function serves the same purpose as scsetup_get_prop_default(),
#	but can only be used when the indicated arrays have first been
#	properly initialized.
#
#	Return values:
#
#		-1		Unknown property
#		0		Success
#
#####################################################
scsetup_get_rstype_extprop_dflt()
{
	typeset -l propname=${1}		# lower case

	typeset index

	# Get the index
	index=$(scsetup_get_rstype_extprop_index ${propname})

	# Print the value
	if [[ -n "${index}" ]]; then
		echo ${SCSETUP_RT_PROP_DFLTS[index]}
	else
		return 1
	fi

	return 0
}

#####################################################
#
# scsetup_get_prop_default() rstype property [cachefile]
#
#	Test to see if the "property" exists for the given resource type.
#	If it does, print the default value.
#
#	Note that we cannot use the scha_cmds(1ha) here, since there are
#	no options for getting resource type parameters.
#
#	If "cachefile" is given, it is searched, rather than current
#	scrgadm(1M) output.
#
#	Return values:
#
#		-1		Unknown property
#		0		Success
#
#####################################################
scsetup_get_prop_default()
{
	typeset rstype=${1}
	typeset property=${2}
	typeset cachefile=${3}

	typeset item
	typeset list
	typeset default

	integer found

	# See if the property even exists for this resource type
	if [[ -n "${cachefile}" ]] && [[ -r "${cachefile}" ]]; then
		list="$(sed -n 's/^ *('${rstype}') Res Type param name:[ 	]*\(.*\)/\1/p' ${cachefile})"
	else
		list="$(
			LC_ALL=C; export LC_ALL;
			${SC_SCRGADM} -pvv -t ${rstype} 2>/dev/null | sed -n 's/^ *('${rstype}') Res Type param name:[ 	]*\(.*\)/\1/p'
		)"
	fi
	let found=0
	for item in ${list}
	do
		if [[ "${item}" == "${property}" ]]; then
			let found=1
			break
		fi
	done
	if [[ ${found} -eq 0 ]]; then
		return -1
	fi

	# If the property exists, print the default value
	if [[ -n "${cachefile}" ]] && [[ -r "${cachefile}" ]]; then
		default="$(sed -n 's/^ *('${rstype}:${property}') Res Type param default:[ 	]*\(.*\)/\1/p' ${cachefile})"
	else
		default="$(
			LC_ALL=C; export LC_ALL;
			${SC_SCRGADM} -pvv -t ${rstype} 2>/dev/null | sed -n 's/^ *('${rstype}:${property}') Res Type param default:[ 	]*\(.*\)/\1/p'
		)"
	fi

	if [[ -n "${default}" ]]; then
		echo "${default}"
	fi

	return 0
}

#####################################################
#
# scsetup_get_resource() rsname
#
#	Test to see if the resource exists. If it does, print the name.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_resource()
{
	typeset rsname=${1}

	${SCHA_RS_GET} -R ${rsname} -O type >/dev/null 2>&1
	if [[ $? -ne ${SCHA_ERR_RSRC} ]]; then
		echo "${rsname}"
	fi

	return 0
}

#####################################################
#
# scsetup_get_resource_dependencies() rsname
#
#	Print a list of all resources upon which "rsname" depends.
#	This includes both strong and weak dependencies, as well as
#	implied and explicit network dependencies.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_resource_dependencies()
{
	typeset rsname=${1}

	typeset rgname
	typeset deps
	typeset resources
	typeset resource
	typeset rstype
	typeset list
	typeset -l lfoo			# lower case
	typeset i
	typeset j

	integer found
	integer isnet
	integer isimplicit

	# Get the RG name
	rgname="$(${SCHA_RS_GET} -R ${rsname} -O group)" || return 0

	# See if we are a network resource
	let isnet=0
	rstype="$(${SCHA_RS_GET} -R ${rsname} -G ${rgname} -O type)"
	scsetup_is_network_rstype ${rstype}
	if [[ $? -ne 0 ]]; then
		let isnet=1
	fi

	# See if implicit network resource dependencies are in use
	let isimplicit=0
	lfoo="$(${SCHA_RG_GET} -G ${rgname} -O implicit_network_dependencies)"
	if [[ "${lfoo}" == "true" ]]; then
		let isimplicit=1
	fi

	# Strong
	deps="$(${SCHA_RS_GET} -R ${rsname} -G ${rgname} -O resource_dependencies)"

	# Weak
	deps="${deps} $(${SCHA_RS_GET} -R ${rsname} -G ${rgname} -O resource_dependencies_weak)"

	# Restart
	deps="${deps} $(${SCHA_RS_GET} -R ${rsname} -G ${rgname} -O resource_dependencies_restart)"

	# If this is not a network resource, collect net resource dependencies
	if [[ ${isnet} -eq 0 ]]; then

		# Explicit network
		deps="${deps} $(${SCHA_RS_GET} -R ${rsname} -G ${rgname} -O network_resources_used)"

		# Implied network
		if [[ ${isimplicit} -eq 1 ]]; then
			resources="$(${SCHA_RG_GET} -G ${rgname} -O resource_list)"
			for resource in ${resources}
			do
				if [[ "${resource}" == "${rsname}" ]]; then
					continue
				fi
				rstype="$(${SCHA_RS_GET} -R ${resource} -O type)"
				scsetup_is_network_rstype ${rstype}
				if [[ $? -ne 0 ]]; then
					deps="${deps} ${resource}"
				fi
			done
		fi
	fi

	# Filter out any duplicates
	list=
	for i in ${deps}
	do
		let found=0
		for j in ${list}
		do
			if [[ $i == $j ]]; then
				let found=1
				break
			fi
		done
		if [[ ${found} -eq 0 ]]; then
			list="${list} $i"
		fi
	done

	# Print the list of dependencies
	if [[ -n "${list}" ]]; then
		echo ${list}
	fi

	return 0
}

#####################################################
#
# scsetup_get_rg_dependencies() rgname [flag]
#
#	Print a list of all resource groups which depend upon "rgname".
#	If "flag" is set to "offline", only list those groups which are
#	offline.   If "flag" is set to "unmanaged", only list those groups
#	which are unmanaged.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_rg_dependencies()
{
	typeset rgname=${1}
	typeset flag=${2}

	typeset rgstatefile=${SCSETUP_TMP_RGSTATE}

	typeset dep
	typeset list
	typeset nodelist

	# If not a cluster member, just return
	if [[ ${SCSETUP_ISMEMBER} -ne 1 ]];  then
		return 0
	fi

	# Get the rg_dependencies
	list="$(${SCHA_RG_GET} -G ${rgname} -O rg_dependencies)"
	if [[ -z "${list}" ]]; then
		return 0
	fi

	# If no "flag" is given, list all RG_dependencies
	if [[ -z "${flag}" ]]; then
		deps="${list}"

	# Otherwise, list either "offline" or "unmanaged" dependencies
	else
		# Create the rgstate file
		scsetup_create_rgstatefile ${rgstatefile}

		# Get the dependencies list
		for dep in ${list}
		do
			# Update depended on list based on "flag"
			if [[ "${flag}" == "offline" ]]; then

				# If any node is online, do NOT add to the list
				nodelist=$(scsetup_get_rgstate ${dep} ${rgstatefile} "not_offline")
				if [[ -z "${nodelist}" ]]; then
					deps="${deps} ${dep}"
				fi
			elif [[ "${flag}" == "unmanaged" ]]; then

				# If any node is unmanaged, do add to the list
				nodelist=$(scsetup_get_rgstate ${dep} ${rgstatefile} "unmanaged")
				if [[ -n "${nodelist}" ]]; then
					deps="${deps} ${dep}"
				fi
			fi
		done

		# Done with rgstate file
		scsetup_rm_rgstatefile ${rgstatefile}
	fi

	# If there are any, print them
	if [[ -n "${deps}" ]]; then
		echo ${deps}
	fi

	return 0
}

#####################################################
#
# scsetup_get_resource_depended_ons() rsname [explicit] [net_res_used]
#
#	Print a list of all resources which depend upon "rsname".
#	This includes strong, weak and restart dependencies, as well as
#	implied and explicit network dependencies.
#
#	If "explicit" is specified, the list of strong, weak and restart
#	explicit dependencies is printed.   If "net_res_used" is
#	specified, the list of explicit network_resources_used is
#	printed.   If neither "explicit" nor "net_res_used" is
#	specified, everything is printed.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_resource_depended_ons()
{
	typeset rsname=${1}
	typeset explicit=${2}
	typeset net_res_used=${3}

	typeset printall=
	if [[ -z "${explicit}" ]] && [[ -z "${net_res_used}" ]]; then
		printall=true
	fi

	typeset rgname
	typeset rglist
	typeset deps
	typeset resources
	typeset resource
	typeset rstype
	typeset list
	typeset foo
	typeset -l lfoo			# lower case
	typeset i
	typeset j
	typeset tmprglist

	integer found
	integer isnet
	integer isimplicit
	integer doit

	# Get the RG name
	rgname="$(${SCHA_RS_GET} -R ${rsname} -O group)" || return 0

	# See if we are a network resource
	let isnet=0
	rstype="$(${SCHA_RS_GET} -R ${rsname} -G ${rgname} -O type)"
	scsetup_is_network_rstype ${rstype}
	if [[ $? -ne 0 ]]; then
		let isnet=1
	fi

	# See if implicit network resource dependencies are in use
	let isimplicit=0
	lfoo="$(${SCHA_RG_GET} -G ${rgname} -O implicit_network_dependencies)"
	if [[ "${lfoo}" == "true" ]]; then
		let isimplicit=1
	fi

	# Check for all the resources in all the resource groups for dependencies
	rglist="$(scsetup_get_rglist)"
	for tmprglist in ${rglist}
	do
		resources="$(${SCHA_RG_GET} -G ${tmprglist} -O resource_list)"
		for resource in ${resources}
		do
			# Skip myself
			if [[ "${resource}" == "${rsname}" ]]; then
				continue
			fi

			if [[ -n "${explicit}" ]] || [[ -n "${printall}" ]]; then
				# Strong
				foo="$(${SCHA_RS_GET} -R ${resource} -G ${rgname} -O resource_dependencies)"

				# Weak
				foo="${foo} $(${SCHA_RS_GET} -R ${resource} -G ${rgname} -O resource_dependencies_weak)"

				# Restart
				foo="${foo} $(${SCHA_RS_GET} -R ${resource} -G ${rgname} -O resource_dependencies_restart)"

				# See if we are in their strong, weak or restart dependency list
				for i in ${foo}
				do
					if [[ $i == ${rsname} ]]; then
						deps="${deps} ${resource}"
						break
					fi
				done
			fi

                        # If ours is a network resource and this one is not,
                        # then there is an implied dependency, if the flag
                        # is set implicit network dependencies only apply
                        # when the network resource and the data service
                        # resource are in the same resource group. The
                        # two resources might be in different groups in
                        # which case implicit dependency would not exist.
			if [[ -n "${printall}" ]] &&
			    [[ ${isnet} -eq 1 ]] &&
			    [[ ${isimplicit} -eq 1 ]] &&
				[[ "${tmprglist}" == "${rgname}" ]]; then
				rstype="$(${SCHA_RS_GET} -R ${resource} -O type)"
				scsetup_is_network_rstype ${rstype}
				if [[ $? -eq 0 ]]; then
					deps="${deps} ${resource}"
				fi
			fi
		done
	done

	# Check for expicit network dependencies
	let doit=0
	if [[ -n "${net_res_used}" ]] || [[ -n "${printall}" ]]; then
		let doit=1
	fi
	if [[ ${doit} -eq 1 ]] && [[ ${isnet} -eq 1 ]]; then
		rglist="$(scsetup_get_rglist)"
		for i in ${rglist}
		do
			resources="$(${SCHA_RG_GET} -G ${i} -O resource_list)"
			for resource in ${resources}
			do
				if [[ ${resource} == ${rsname} ]]; then
					continue
				fi
				foo="${deps} $(${SCHA_RS_GET} -R ${resource} -G ${i} -O network_resources_used)"
				for j in ${foo}
				do
					if [[ $j == ${rsname} ]]; then
						deps="${deps} ${resource}"
					fi
				done
			done
		done
	fi
			
	# Filter out any duplicates
	list=
	for i in ${deps}
	do
		let found=0
		for j in ${list}
		do
			if [[ $i == $j ]]; then
				let found=1
				break
			fi
		done
		if [[ ${found} -eq 0 ]]; then
			list="${list} $i"
		fi
	done

	# Print the list of dependencies which depend upon me
	if [[ -n "${list}" ]]; then
		echo ${list}
	fi

	return 0
}

#####################################################
#
# scsetup_get_rg_depended_ons() rgname [flag]
#
#	Print a list of all resource groups which depend upon "rgname".
#	If "flag" is set to "online", only list those groups which are online.
#	Otherwise, list all managed groups which depend on "rgname".
#
#	This function always returns zero.
#
#####################################################
scsetup_get_rg_depended_ons()
{
	typeset rgname=${1}
	typeset flag=${2}

	typeset rgstatefile=${SCSETUP_TMP_RGSTATE}

	typeset rglist
	typeset rg
	typeset list
	typeset foo
	typeset deps
	typeset nodelist

	# If not a cluster member, just return
	if [[ ${SCSETUP_ISMEMBER} -ne 1 ]];  then
		return 0
	fi

	# Create the rgstate file
	scsetup_create_rgstatefile ${rgstatefile}

	# Get the list of depended ons
	deps=
	rglist="$(scsetup_get_rglist)"
	for rg in ${rglist}
	do
		# If it is us, skip it
		if [[ "${rg}" == "${rgname}" ]]; then
			continue
		fi

		# Get the rg_dependencies
		list="$(${SCHA_RG_GET} -G ${rg} -O rg_dependencies)"
		if [[ -z "${list}" ]]; then
			continue
		fi

		# See if we are in the list
		for foo in ${list}
		do
			if [[ "${foo}" == "${rgname}" ]]; then

				# Update depended on list
				if [[ "${flag}" == "online" ]]; then
					nodelist=$(scsetup_get_rgstate ${rg} ${rgstatefile} "online")
					if [[ -n "${nodelist}" ]]; then
						deps="${deps} ${rg}"
					fi
				else
					nodelist=$(scsetup_get_rgstate ${rg} ${rgstatefile} "unmanaged")
					if [[ -z "${nodelist}" ]]; then
						deps="${deps} ${rg}"
					fi
				fi

				# Next
				break
			fi
		done
	done

	# Done with rgstate file
	scsetup_rm_rgstatefile ${rgstatefile}

	# If there are any, print them
	if [[ -n "${deps}" ]]; then
		echo ${deps}
	fi

	return 0
}

#####################################################
#
# scsetup_is_resource_enabled() rsname
#
#	Test to see if "rsname" is enabled.
#
#	Return values:
#
#		1	Yes, it is.
#		0	No,  it is not.
#		-1	Error, not set.
#
#####################################################
scsetup_is_resource_enabled()
{
	typeset rsname=${1}

	typeset -l state		# lower case

	# If not a cluster member, return not enabled
	if [[ ${SCSETUP_ISMEMBER} -ne 1 ]];  then
		return 0
	fi

	state=$(${SCHA_RS_GET} -R ${rsname} -O on_off_switch)
	if [[ "${state}" == "enabled" ]]; then
		return 1
	elif [[ "${state}" == "disabled" ]]; then
		return 0
	else
		return -1
	fi
}

#####################################################
#
# scsetup_enabled_resources() resource ...
#
#	Test to see if any "resources" in in the resource list
#	are enabled.   Print back the ones that are.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_enabled_resources()
{
	typeset resource

	# If not a cluster member, return with nothing enabled
	if [[ ${SCSETUP_ISMEMBER} -ne 1 ]];  then
		return 0
	fi

	for resource in $*
	do
		scsetup_is_resource_enabled ${resource}
		if [[ $? -eq 1 ]]; then
			echo ${resource}
		fi
	done

	return 0
}

#####################################################
#
# scsetup_is_resource_stop_failed() rsname
#
#	Test to see if "rsname" is is in the STOP_FAILED state
#	on any of the nodes.  If it is, a list of the nodes is
#	printed.
#
#	Return values:
#
#		1	Yes, it is.
#		0	No,  it is not.
#		-1	Error.
#
#####################################################
scsetup_is_resource_stop_failed()
{
	typeset rsname=${1}

	typeset rgname
	typeset nodelist
	typeset node
	typeset -l state		# lower case

	integer rstatus

	# If not a cluster member, return not enabled
	if [[ ${SCSETUP_ISMEMBER} -ne 1 ]];  then
		return 0
	fi

	# Get the nodelist for this resource
	rgname=$(${SCHA_RS_GET} -R ${rsname} -O group)
	nodelist="$(${SCHA_RG_GET} -G ${rgname} -O nodelist)"

	# Check for STOP_FAILED for each node
	let rstatus=0
	for node in ${nodelist}
	do
		state=$(${SCHA_RS_GET} -R ${rsname} -O resource_state_node ${node})
		if [[ "${state}" == "stop_failed" ]]; then
			echo ${node}
			let rstatus=1
		fi
	done

	return ${rstatus}
}

#####################################################
#
# scsetup_is_network_rstype() rstype
#
#	Test to see if this is a network resource type.
#
#	Return values:
#
#		1	Yes, it is.
#		0	No,  it is not.
#
#####################################################
scsetup_is_network_rstype()
{
	typeset rstype=${1}

	if [[ ${rstype} == SUNW.LogicalHostname ]] ||
	    [[ ${rstype} == SUNW.SharedAddress ]] ||
	    [[ ${rstype} == SUNW.LogicalHostname:* ]] ||
	    [[ ${rstype} == SUNW.SharedAddress:* ]] ||
	    [[ ${rstype} == LogicalHostname ]] ||
	    [[ ${rstype} == SharedAddress ]] ||
	    [[ ${rstype} == LogicalHostname:* ]] ||
	    [[ ${rstype} == SharedAddress:* ]]; then
		return 1
	fi

	return 0
}

#####################################################
#####################################################
##
## Main help text
##
#####################################################
#####################################################

#####################################################
#
# scsetup_help_main_quorum()
#
#	Print the main help message for quorum.
#
#	This function always returns zero.
#
#####################################################
scsetup_help_main_quorum()
{
	typeset sctxt_title="$(gettext '
		*** Help Screen - Quorum ***
	')"
	typeset sctxt_p1="$(gettext '
		A quorum disk is a disk connected to at least two
		nodes and configured to participate in computing the
		quorum for the cluster. Both nodes and quorum devices
		contribute votes to the quorum.  A simple majority of
		votes must be present in order to establish quorum
		and form a cluster.
	')"
	typeset sctxt_p2="$(gettext '
		Each cluster node has a default quorum vote count of
		one. If configured, each quorum device has a quorum
		vote count of N-1, where N is the number of
		disk-to-node paths configured for the disk. For
		example, a quorum device consisting of a disk with two
		disk-to-node paths has a quorum vote count of 1.
	')"
	typeset sctxt_p3="$(gettext '
		Both nodes and quorum devices may be placed
		in a quorum maintenance state.  This is achieved by
		setting their vote counts to zero.  Resetting this
		maintenance state restores vote counts to their default
		values.  Please refer to the scconf(1M) man page and
		other Sun Cluster documentation for information
		on changing the quorum maintenance state.
	')"
	typeset sctxt_p4="$(gettext '
		The minimum requirement for configuring quorum is
		that all two-node clusters have at least one quorum disk.
		For more information regarding disk layout, quorum topologies,
		and recommendations for configuring quorum, please refer
		to the Sun Cluster documentation.
	')"

	sc_print_title "${sctxt_title}"
	sc_print_para "${sctxt_p1}"
	sc_print_para "${sctxt_p2}"
	sc_print_para "${sctxt_p3}"
	sc_print_para "${sctxt_p4}"

	return 0
}

#####################################################
#
# scsetup_help_main_rgm()
#
#	Print the main help message for resource groups.
#
#	This function always returns zero.
#
#####################################################
scsetup_help_main_rgm()
{
	typeset sctxt_title="$(gettext '
		*** Help Screen - Resource Groups ***
	')"
	typeset sctxt_p1="$(gettext '
		The cluster uses resource groups to manage data service
		and network resources.   A resource group is a
		container into which resources of various types may be
		placed.   There are different types of resources,
		including the two network resources types and any
		number of data service resource types.   However, there
		are only two types of resource groups, failover and
		scalable.
	')"
	typeset sctxt_p2="$(gettext '
		The two types of network resources are LogicalHostname
		resources and SharedAddress resources.   Both of these
		network resource types are pre-registered with the
		cluster.  Each data service is also associated with its
		own data service resource type.  Data service resource
		types are not pre-registered and must be registered
		with the cluster after they have been installed.
	')"
	typeset sctxt_p3="$(gettext '
		A failover resource group typically contains one or
		more network resource type resources.  Usually, there
		is at least one network resource for each subnet.  In
		addition, each failover resource group may contain one
		or more data service resource.
	')"
	typeset sctxt_p4="$(gettext '
		A scalable resource group never contains network resources,
		but always depends upon a failover resource group that
		includes at least one SharedAddress resource.
	')"

	(
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"
		sc_print_para "${sctxt_p3}"
		sc_print_para "${sctxt_p4}"
	) | more

	return 0
}

#####################################################
#
# scsetup_help_main_transport()
#
#	Print the main help message for cluster interconnect.
#
#	This function always returns zero.
#
#####################################################
scsetup_help_main_transport()
{
	typeset sctxt_title="$(gettext '
		*** Help Screen - Cluster Interconnect ***
	')"
	typeset sctxt_p1="$(gettext '
		The cluster interconnect facilitates high speed private
		communications between nodes in the cluster.  One of
		the more important uses of the interconnect is the
		synchronization of cluster membership information.
	')"
	typeset sctxt_p2="$(gettext '
		There must be at least two points of connection to the
		cluster interconnect for each node in the cluster.
		Each such endpoint is connected to the interconnect by
		a cable.  In two-node clusters with interconnect
		hardware which supports direct-connect cabling, both
		endpoints of a transport cable may be directly attached
		to transport adapters.  But, all configurations support
		cabling with a cluster transport junction at one
		endpoint and a cluster transport adapter at the other.
	')"

	sc_print_title "${sctxt_title}"
	sc_print_para "${sctxt_p1}"
	sc_print_para "${sctxt_p2}"

	return 0
}

#####################################################
#
# scsetup_help_main_privatehosts()
#
#	Print the main help message for private hostnames.
#
#	This function always returns zero.
#
#####################################################
scsetup_help_main_privatehosts()
{
	typeset sctxt_title="$(gettext '
		*** Help Screen - Private Hostnames ***
	')"
	typeset sctxt_p1="$(gettext '
		Nodes may contact other nodes in the cluster 
		over the cluster interconnect by accessing them using
		their private hostnames.   Default private hostnames
		are assigned during cluster installation.
	')"
	typeset sctxt_p2="$(gettext '
		Note that private hostnames should never be stored
		in the hosts(4) or other naming services databases.
		A special nsswitch facility (see nsswitch.conf(4))
		performs all hostname lookups for private hostnames.
	')"
		
	sc_print_title "${sctxt_title}"
	sc_print_para "${sctxt_p1}"
	sc_print_para "${sctxt_p2}"

	return 0
}

#####################################################
#
# scsetup_help_main_devicegroups()
#
#	Print the main help message for device groups.
#
#	This function always returns zero.
#
#####################################################
scsetup_help_main_devicegroups()
{
	typeset sctxt_title="$(gettext '
		*** Help Screen - Device Groups ***
	')"
	typeset sctxt_p1="$(gettext '
		A device group is a group of devices which can
		be mastered as a single set.  The most common
		types of device groups are disk device groups.
	')"
	typeset sctxt_p2_sds="$(gettext '
		Every Solstice DiskSuite diskset is automatically
		registered as a Sun Cluster device group.   VxVM shared
		disk groups should also be registered as Sun Cluster
		device groups, but it is not done automatically.  Disks
		which do not belong to either SDS disksets or VxVM disk
		groups may be grouped together into their own
		Sun Cluster rawdisk device groups.
	')"
	typeset sctxt_p2_svm="$(gettext '
		Every Solaris Volume Manager diskset is automatically
		registered as a Sun Cluster device group.   VxVM shared
		disk groups should also be registered as Sun Cluster
		device groups, but it is not done automatically.  Disks
		which do not belong to either Solaris Volume Manager
		disksets or VxVM disk groups may be grouped together
		into their own Sun Cluster rawdisk device groups.
	')"
	typeset sctxt_p3_sds="$(gettext '
		Solstice DiskSuite is Sun Cluster aware,
		and most device group administration occurs
		automatically through the Solstice DiskSuite command
		set or GUI interface for DiskSuite disksets.
		However, since VxVM is not Sun Cluster aware, VxVM disk
		groups and volumes must each be registered with the
		cluster using either scsetup(1M) or scconf(1M).
	')"
	typeset sctxt_p3_svm="$(gettext '
		Solaris Volume Manager is Sun Cluster aware,
		and most device group administration occurs
		automatically through the Solaris Volume Manager command
		set or GUI interface for disksets.
		However, since VxVM is not Sun Cluster aware, VxVM disk
		groups and volumes must each be registered with the
		cluster using either scsetup(1M) or scconf(1M).
	')"

	sc_print_title "${sctxt_title}"
	sc_print_para "${sctxt_p1}"
	if [[ "${SC_SUNOS}" == "5.8" ]]; then
		sc_print_para "${sctxt_p2_sds}"
		sc_print_para "${sctxt_p3_sds}"
	else
		sc_print_para "${sctxt_p2_svm}"
		sc_print_para "${sctxt_p3_svm}"
	fi

	return 0
}

#####################################################
#
# scsetup_help_main_auth()
#
#	Print the main help message for managing authorization
#	for nodes which want to add themselves to the cluster.
#
#	This function always returns zero.
#
#####################################################
scsetup_help_main_auth()
{
	typeset sctxt_title="$(gettext '
		*** Help Screen - New Nodes ***
	')"
	typeset sctxt_p1="$(gettext '
		To be added as a cluster node, a machine must appear in
		the list of hosts that are permitted to install themselves
		into cluster configuration.  If this list is empty, any
		machine may add itself to the cluster configuration.
	')"
	typeset sctxt_p2="$(gettext '
		The identity of machines contacting the cluster over
		the public network for installation purposes may be
		confirmed using either standard UNIX or the more secure
		Diffie-Hellman, or DES, authentication.  However, DES
		authentication is not usually considered necessary for
		this purpose, since machines which are not physically
		connected to the private cluster interconnect will
		never be able to actually join the cluster membership
		anyway.
	')"
	typeset sctxt_p3="$(gettext '
		If DES authentication is selected, you must also configure
		all necessary encryption keys before a node can join
		(see keyserv(1M), publickey(4)).
	')"

	sc_print_title "${sctxt_title}"
	sc_print_para "${sctxt_p1}"
	sc_print_para "${sctxt_p2}"
	sc_print_para "${sctxt_p3}"

	return 0
}

#####################################################
#
# scsetup_help_main_other()
#
#	Print the main help message for other cluster properties.
#
#	This function always returns zero.
#
#####################################################
scsetup_help_main_other()
{
	typeset sctxt_title="$(gettext '
		*** Help Screen - Other Cluster Properties ***
	')"
	typeset sctxt_p1="$(gettext '
		Currently, the only other cluster-wide property
		which may be changed from scsetup is the name of
		the cluster.
	')"

	sc_print_title "${sctxt_title}"
	sc_print_para "${sctxt_p1}"

	return 0
}

#####################################################
#####################################################
##
## Quorum
##
#####################################################
#####################################################

#####################################################
#
# scsetup_menu_quorum_addev() [nohelp]
#
#	nohelp		- if this flag is given, do not
#			    clear screen, print title, print help,
#			    or ask for confirmation to continue
#
#	Add a quorum device to the cluster.
#
#	Note that the scsetup_initcluster() calls this function with "nohelp".
#	If it has it's own help information to print, it should do so
#	before calling this function.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_quorum_addev()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Add a Quorum Disk <<<
	')"
	typeset sctxt_p1="$(gettext '
		This option is used to add a quorum disk to the cluster
		configuration.  SCSI-2 disks can be used for
		dual-ported quorum devices.   However, SCSI-3 PGR disks
		must be used when there are more than two node-to-disk
		paths.  You can use a disk containing user data or one
		that is a member of a device group as a quorum device.
		For more information on supported quorum device
		topologies, see the Sun Cluster documentation.
	')"
	typeset sctxt_p2="$(gettext '
		Each quorum disk must be connected to at least two
		nodes.  Adding a quorum device automatically configures
		node-to-disk paths for all nodes attached to the disk.
		Later, if you add more nodes to the cluster, you might
		need to update these paths by removing then adding back
		the quorum device.
	')"

	typeset answer
	typeset globaldev

	# Unless nohelp is specified, print help and get confirmation
	if [[ -z "${nohelp}" ]]; then

		# Clear screen, print title and help
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Get the name of the global device
		answer=$(sc_prompt "$(gettext 'Which global device do you want to use (d<N>)?')") || return 1

		# Make sure they use the d<N> format
		if [[ $(expr "${answer}" : 'd[0-9][0-9]*') -ne ${#answer} ]]; then
			printf "$(gettext 'The global device name must be given as d<N>.')\n"
			if [[ "${answer}" = /* ]]; then
				printf "$(gettext 'It is not necessary to use the full pathname.')\n"
			fi
			printf "\n\a"

			# Retry from the top
			continue
		fi

		# Set the global device name
		globaldev=${answer}

		#
		# Set up the command set
		#

		# Initialize
		set -A SCSETUP_DO_CMDSET

		# Add the command
		SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -a -q globaldev=${globaldev}"

		# Attempt to issue the command
		scsetup_do_cmdset || return 1

		# Done
		break
	done

	return 0
}

#####################################################
#
# scsetup_menu_quorum_rmdev() [nohelp]
#
#	nohelp		- if this flag is given, do not
#			    clear screen, print title, print help,
#			    or ask for confirmation to continue
#
#	Remove a quorum device from the cluster.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_quorum_rmdev()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Remove a Quorum Disk <<<
	')"
	typeset sctxt_p1="$(gettext '
		This option is used to remove a quorum disk from the
		cluster configuration.  When a quorum disk is removed,
		it no longer participates in the voting to establish
		quorum.
	')"
	typeset sctxt_p2="$(gettext '
		Note that all two-node clusters require that at least
		one quorum device be configured.  So, if this is
		the last quorum disk on a two-node cluster, scconf(1M)
		will fail to remove the device from the configuration.
	')"

	typeset answer
	typeset globaldev

	# Unless nohelp is specified, print help and get confirmation
	if [[ -z "${nohelp}" ]]; then

		# Clear screen, print title and help
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Get the name of the global device
		answer=$(sc_prompt "$(gettext 'Which quorum disk do you want to remove (d<N>)?')") || return 1

		# Make sure they use the d<N> format
		if [[ $(expr "${answer}" : 'd[0-9][0-9]*') -ne ${#answer} ]]; then
			printf "$(gettext 'The global device name must be given as d<N>.')\n"
			if [[ "${answer}" = /* ]]; then
				printf "$(gettext 'It is not necessary to use the full pathname.')\n"
			fi
			printf "\n\a"

			# Retry from the top
			continue
		fi

		# Set the global device name
		globaldev=${answer}

		#
		# Set up the command set
		#

		# Initialize
		set -A SCSETUP_DO_CMDSET

		# Add the command
		SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -r -q globaldev=${globaldev}"

		# Attempt to issue the command
		scsetup_do_cmdset || return 1

		# Done
		break
	done

	return 0
}

#####################################################
#
# scsetup_help_quorum_menu()
#
#	Print help information from the quorum menu.
#	This is the same help information as is printed
#	from the MAIN help menu.  But, we ask for confirmation
#	before returning to the previous menu.
#
#	This function always returns zero.
#
#####################################################
scsetup_help_quorum_menu()
{
	clear
	scsetup_help_main_quorum
	sc_prompt_pause

	return 0
}

#####################################################
#
# scsetup_get_quorum_menuoption()
#
#	Print the quorum menu, and return the selected option.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_quorum_menuoption()
{
	typeset sctxt_title_1="$(gettext '*** Quorum Menu ***')"
	typeset sctxt_title_2="$(gettext 'Please select from one of the following options:')"
	typeset sctxt_option_001="$(gettext 'Add a quorum disk')"
	typeset sctxt_option_002="$(gettext 'Remove a quorum disk')"
	typeset sctxt_option_help="$(gettext 'Help')"
	typeset sctxt_option_return="$(gettext 'Return to the Main Menu')"

	typeset option

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

	echo "${option}"

	return 0
}

#####################################################
#
# scsetup_menu_quorum()
#
#	Quorum menu
#
#	This function always returns zero.
#
#####################################################
scsetup_menu_quorum()
{
	# Loop around the quorum menu
	while true
	do
		case $(scsetup_get_quorum_menuoption) in
		'1')    scsetup_menu_quorum_addev ;;
		'2')    scsetup_menu_quorum_rmdev ;;
		'?')    scsetup_help_quorum_menu ;;
		'q')    break ;;
                esac 
	done

	return 0
}

#####################################################
#####################################################
##
## Resource Group Management
##
#####################################################
#####################################################

#####################################################
#
# scsetup_menu_rgm_rg_create() [nohelp]
#
#	nohelp		- if this flag is given, do not
#			    clear screen, print title, print help,
#			    or ask for confirmation to continue
#
#	Create a resource group.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_rgm_rg_create()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Create a Resource Group <<<
	')"
	typeset sctxt_p1="$(gettext '
		Use this option to create a new resource group.  You
		can also use this option to create new resources for
		the new group.
	')"
	typeset sctxt_p2="$(gettext '
		A resource group is a container into which you can
		place resources of various types, such as network and
		data service resources.   The cluster uses resource
		groups to manage its resource types.  There are two
		types of resource groups, failover and scalable.
	')"
	typeset sctxt_p3="$(gettext '
		Only failover resource groups may contain network
		resources.  A network resource is either a
		LogicalHostname or SharedAddress resource.
	')"
	typeset sctxt_p4="$(gettext '
		It is important to remember that each scalable resource
		group depends upon a failover resource group which
		contains one or more SharedAddress network resources.
	')"

	typeset sctxt_p1_pprefix="$(gettext '
		Some types of resources (for example, HA for NFS)
		require the use of an area in a global file system for
		storing configuration data.  If any of the resources
		that will be added to this group require such support,
		you can specify the full directory path name now.
	')"
	typeset sctxt_p2_pprefix="$(gettext '
		Please remember that this directory must be located on
		a global file system.
	')"

	typeset sctxt_p1_scalable="$(gettext '
		Each scalable resource group has a tightly defined
		dependency on a failover resource group which contains
		one or more network resources of the SharedAddress resource
		type.
	')"
	typeset sctxt_p1_no_sharedaddr="$(gettext '
		However, there are no SharedAddress resources currently
		configured in the cluster.
	')"
	typeset sctxt_p2_no_sharedaddr="$(gettext '
		You must create a failover resource group with
		one or more SharedAddress network resources upon which
		a scalable resource group can depend, before you can
		create that scalable resource group.
	')"
	typeset sctxt_p1_2nodes="$(gettext '
		Because this cluster has two nodes, the new resource
		group will be configured to be hosted by both cluster
		nodes.
	')"
	typeset sctxt_p2_2nodes="$(gettext '
		At this time, you may select one node to be the
		preferred node for hosting this group.  Or, you may
		allow the system to select a preferred node on an
		arbitrary basis.
	')"
	typeset sctxt_p1_node_list="$(gettext "
		Each resource group is associated with a list of nodes which
		are capable of hosting it.   Also, the order in which nodes
		are found in a group's \"Nodelist\" reflects a preferred
		ordering for hosting a group.
	")"
	typeset sctxt_p2_node_list="$(gettext '
		You may either explicitly specify an ordered list of
		nodes for hosting a new group or let the system take
		the default \"Nodelist\".  The default is an
		arbitrarily ordered list of all of the nodes in the
		cluster.
	')"
	typeset sctxt_p1_network_rsl="$(gettext '
		If a failover resource group contains LogicalHostname
		resources, the most common configuration is to have one
		LogicalHostname resource for each subnet.
	')"
	typeset sctxt_p1_network_rss="$(gettext '
		If a failover resource group contains SharedAddress
		resources, the most common configuration is to have one
		SharedAddress resource for each subnet.
	')"
		
	typeset cachefile=${SCSETUP_RGM_CACHEFILE}
	typeset tmpfile=${SCSETUP_TMP_RGLIST}

	typeset foo
	typeset answer
	typeset prompt
	typeset node
	typeset nodelist
	typeset rglist
	typeset rgname
	typeset rgdescription
	typeset saddr_rglist
	typeset saddr_rgname
	typeset saddr_rgdes
	typeset -l rgtype			# lower case
	typeset rgdependency
	typeset rgnodelist
	typeset net_rstype
	typeset default

	integer i
	integer pass
	integer nodecount
	integer found
	integer listcount
	integer total
	integer index

	# Unless nohelp is specified, print help and get confirmation
	if [[ -z "${nohelp}" ]]; then

		# Clear screen, print title and help
		(
			sc_print_title "${sctxt_title}"
			sc_print_para "${sctxt_p1}"
			sc_print_para "${sctxt_p2}"
			sc_print_para "${sctxt_p3}"
			sc_print_para "${sctxt_p4}"
		) | more

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Get the RG type
	prompt="$(gettext 'Select the type of resource group you want to add:')"
	rgtype="$(
	    sc_get_scrolling_menuoptions	\
		"${prompt}"			\
		"" ""				\
		1 1 1				\
		"Failover Group"		\
		"Scalable Group"		\
	)"
	if [[ -z "${rgtype}" ]]; then
		return 1
	fi

	# Get the RG name
	while true
	do
		# Get the name of the resource group
		answer=$(sc_prompt "$(gettext 'What is the name of the group you want to add?')") || return 1

		# See if the group is already configured
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] &&
		    [[ -n "$(scsetup_get_rglist ${answer})" ]]; then
			printf "$(gettext 'Resource group \"%s\" is already configured.')\n\n\a" "${answer}"
			continue
		fi

		# Okay
		rgname=${answer}

		# Done
		break
	done

	# Get the RG description
	rgdescription=
	while true
	do
		# Add a description?
		answer=$(sc_prompt_yesno "$(gettext 'Do you want to add an optional description?')" "${YES}") || return 1

		# If so, get the description
		if [[ "${answer}" == "yes" ]]; then

			sc_print_prompt "$(gettext 'Description:')"
			read rgdescription || continue
			echo
		fi

		# Done
		break
	done

	# Scalable resource groups depend upon a failover RG
	rgdependency=
	if [[ "${rgtype}" = "scalable" ]]; then
		# Print message - scalable groups depend on failover groups
		sc_print_para "${sctxt_p1_scalable}"

		# Get the complete list of configured groups w/ shared addrs
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] ||
		    [[ -r "${cachefile}" ]];  then
			saddr_rglist="$(scsetup_get_rglist "" FAILOVER "SUNW.SharedAddress" ${cachefile})"
		else
			saddr_rglist="saddr_rg1 saddr_rg2 saddr_rg3 saddr_rg4 saddr_rg5 saddr_rg6 saddr_rg7 saddr_rg8 saddr_rg9 saddr_rg10 saddr_rg11 saddr_rg12"
		fi

		# Create a temp file which contains each RG with description
		rm -f ${tmpfile}
		for saddr_rgname in ${saddr_rglist}
		do
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] ||
			    [[ -r "${cachefile}" ]];  then
				saddr_rgdes="$(scsetup_get_rgdescription ${saddr_rgname} ${cachefile})"
			else
				saddr_rgdes="DEBUG:  this is a description"
			fi
			printf "%-20s %-10.10s %-30.30s" ${saddr_rgname} "Failover" "${saddr_rgdes}"
			if [[ ${#saddr_rgdes} -gt 30 ]]; then
				echo " ...\c"
			fi
			echo
		done >${tmpfile}

		# If there are no groups with shared address resources, abort
		if [[ -z "${saddr_rglist}" ]]; then
			sc_print_para "${sctxt_p1_no_sharedaddr}"
			sc_print_para "${sctxt_p2_no_sharedaddr}"
			sc_prompt_pause
			rm -f ${tmpfile}
			return 1
		fi

		# Have they configured the necessary group?
		answer=$(sc_prompt_yesno "$(gettext 'Have you already configured such a group?')" "${YES}") || return 1
		if [[ $? -ne 0 ]]; then
			rm -f ${tmpfile}
			return 1
		fi
		if [[ "${answer}" != "yes" ]]; then
			sc_print_para "${sctxt_p2_no_sharedaddr}"
			sc_prompt_pause
			rm -f ${tmpfile}
			return 1
		fi

		# Get the name of the group
		prompt="$(printf "$(gettext 'Select the group upon which \"%s\" depends:')" ${rgname})"
		header1="$(printf "%-20s %-10.10s %-30.30s" "$(gettext 'Group Name')" "$(gettext 'Type')" "$(gettext 'Description')")"
		header2="$(printf "%-20s %-10.10s %-30.30s" "==========" "====" "===========")"
		rgdependency="$(
		    sc_get_scrolling_menuoptions	\
			"${prompt}"			\
			"${header1}"			\
			"${header2}"			\
			0 1 1				\
			:${tmpfile}			\
		)"
		rm -f ${tmpfile}
		if [[ -z "${rgdependency}" ]]; then
			sc_print_para "${sctxt_p2_no_sharedaddr}"
			sc_prompt_pause
			return 1
		fi
	fi

	#
	# Establish the nodelist
	#
	rgnodelist=
	let listcount=0

	# Get the configured list of cluster nodes (nodelist)
	nodelist=
	let nodecount=0
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then

		# Get nodelist
		nodelist="$(scsetup_get_nodelist)"

		# Make sure we have a nodelist
		if [[ -z "${nodelist}" ]]; then
			printf "$(gettext 'Unable to establish the list of cluster nodes.')\n\n\a"
			sc_prompt_pause
			return 1
		fi

		# Set node count
		let nodecount=$(set -- ${nodelist}; echo $#)

	# If debug mode, generate a list of nodenames based on a specified count
	else
		while [[ ${nodecount} -eq 0 ]]
		do
			answer=$(sc_prompt "$(gettext 'DEBUG:  How many nodes in this debug cluster?')" "2") || continue
			if [[ $(expr "${answer}" : '[0-9]*') -ne ${#answer} ]]; then
				printf "$(gettext '\"%s\" is not numeric.')\n\n\a" "${answer}"
				continue
			fi
			if [[ ${answer} -lt 2 ]]; then
				printf "$(gettext 'There must be at least two nodes in the debug cluster.')\n\n\a"
				continue
			fi
			let nodecount=${answer}
		done

		nodelist="node1 node2"
		let i=2
		while [[ ${i} -lt ${nodecount} ]]
		do
			((i += 1))
			nodelist="${nodelist} node${i}"
		done
	fi

	# If this is a one-node cluster, we have the nodelist
	if [[ ${nodecount} -eq 1 ]]; then
		let listcount=1

	# If this is a two-node cluster, we have the nodelist
	elif [[ ${nodecount} -eq 2 ]]; then
		
		# Set the listcount
		let listcount=2

		# Print message - two nodes
		sc_print_para "${sctxt_p1_2nodes}"

		# If failover, do they want to specify the preferred node?
		answer=
		if [[ "${rgtype}" == "failover" ]];  then
			# reset rgnodelist
			rgnodelist=

			# Print additional message - two nodes
			sc_print_para "${sctxt_p2_2nodes}"

			# Okay to proceed?
			answer=$(sc_prompt_yesno "$(gettext 'Do you want to specify a preferred node?')" "${YES}") || return 1
		fi

		# If they want to specify preferred node, let them
		if [[ "${answer}" == "yes" ]]; then

			# Prompt from the list of two nodes
			prompt="$(gettext 'Select the preferred node for hosting this group:')"
			node="$(
			    sc_get_scrolling_menuoptions	\
				"${prompt}"			\
				"" ""				\
				1 1 1				\
				${nodelist}			\
			)"
			if [[ -z "${node}" ]]; then
				return -1
			fi

			# Set the nodelist
			set -A foo ${nodelist}
			if [[ "${foo[0]}" == "${node}" ]]; then
				rgnodelist="${foo[0]} ${foo[1]}"
			elif [[ "${foo[1]}" == "${node}" ]]; then
				rgnodelist="${foo[1]} ${foo[0]}"
			fi
		fi

	# otherwise, this is a multi-node cluster
	else
		# Print message
		sc_print_para "${sctxt_p1_node_list}"
		sc_print_para "${sctxt_p2_node_list}"

		# Do they want to specify the Nodelist?
		prompt="$(printf "$(gettext 'Do you want to explicitly specify the %s?')" "Nodelist")"
		answer=$(sc_prompt_yesno "${prompt}" "${YES}") || return 1

		# If so, let them
		if [[ "${answer}" == "yes" ]]; then

			# Set the menu title
			prompt="$(gettext 'Select an ordered list of two or more nodes:')"

			# Loop until list is confirmed
			rgnodelist=
			while [[ -z "${rgnodelist}" ]]
			do
				# Prompt for an ordered list of nodes
				rgnodelist="$(
				    sc_get_scrolling_menuoptions	\
				    "${prompt}"				\
				    "" ""				\
				    2 ${nodecount} 1			\
				    ${nodelist}				\
				)"
				if [[ -z "${rgnodelist}" ]]; then
					return -1
				fi

				# Print the list and verify that it is correct
				(
					echo
					sc_print_para "$(gettext 'This is the ordered list of nodes you entered:')"
					for node in ${rgnodelist}
					do
						printf "\t${node}\n"
					done
					echo
				) | more

				# Verify
				answer=$(sc_prompt_yesno "$(gettext 'Is it correct?')" "${YES}") || return 1
				if [[ "${answer}" != "yes" ]]; then
					rgnodelist=
				fi
			done

			# Set the list count
			let listcount=$(set -- ${rgnodelist}; echo $#)

		# Otherwise, the listcount is all nodes in the cluster
		else
			let listcount=${nodecount}
		fi
	fi

	# Get the pathprefix
	rgpathprefix=
	while true
	do
		# Print message
		sc_print_para "${sctxt_p1_pprefix}"

		# Add a pathprefix?
		answer=$(sc_prompt_yesno "$(gettext 'Do you want to specify such a directory now?')" "${NO}") || return 1

		# If not, we are done
		if [[ "${answer}" != "yes" ]]; then
			break
		fi

		# Get the directory name
		while [[ -z "${rgpathprefix}" ]]
		do
			# Set default
			default=
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] &&
			     [[ -d /global/${rgname} ]]; then
				default=/global/${rgname}
			fi

			# Print message
			sc_print_para "${sctxt_p2_pprefix}"

			# Get the name and verify
			while true
			do
				# Get the name
				answer=$(sc_prompt "$(gettext 'What is the name of the (\"Pathprefix\") directory?')" "${default}") || continue 2

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

				# If not in debug mode, make sure it is there
				if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] &&
				    [[ ! -d "${answer}" ]]; then
					printf "$(gettext 'Directory not found - %s.')\n\n\a" "${answer}"
					continue
				fi

				# Done
				break
			done

			rgpathprefix=${answer}
		done

		# Done
		break
	done

	#
	# Set up the command set
	#

	# Initialize
	set -A SCSETUP_DO_CMDSET

	#
	# Add the command
	#

	# Basic command
	SCSETUP_DO_CMDSET[0]="${SC_SCRGADM} -a -g ${rgname}"

	# RG nodelist
	if [[ -n "${rgnodelist}" ]]; then
		SCSETUP_DO_CMDSET[0]="${SCSETUP_DO_CMDSET[0]} -h "

		let count=0
		for node in ${rgnodelist}
		do
			if [[ ${count} -gt 0 ]]; then
				SCSETUP_DO_CMDSET[0]="${SCSETUP_DO_CMDSET[0]},"
			fi
			SCSETUP_DO_CMDSET[0]="${SCSETUP_DO_CMDSET[0]}${node}"
			((count += 1))
		done
	fi

	# RG type
	if [[ "${rgtype}" == "scalable" ]]; then
		SCSETUP_DO_CMDSET[0]="${SCSETUP_DO_CMDSET[0]} -y Maximum_primaries=${listcount} -y Desired_primaries=${listcount}"
	fi

	# RG dependencies
	if [[ -n "${rgdependency}" ]]; then
		SCSETUP_DO_CMDSET[0]="${SCSETUP_DO_CMDSET[0]} -y RG_dependencies=${rgdependency}"
	fi

	# Add-on change commands
	let index=1

	# RG pathprefix
	if [[ -n "${rgpathprefix}" ]]; then
		SCSETUP_DO_CMDSET[${index}]="${SC_SCRGADM} -c -g ${rgname}"
		SCSETUP_DO_CMDSET[${index}]="${SCSETUP_DO_CMDSET[${index}]} -y Pathprefix=${rgpathprefix}"
		((index += 1))
	fi

	# RG description
	if [[ -n "${rgdescription}" ]]; then
		SCSETUP_DO_CMDSET[${index}]="${SC_SCRGADM} -c -g ${rgname}"
		SCSETUP_DO_CMDSET[${index}]="${SCSETUP_DO_CMDSET[${index}]} -y RG_description=\"${rgdescription}\""
	fi

	# Attempt to issue the command
	scsetup_do_cmdset || return 1

	# If FAILOVER RG, add check for network resources
	net_rstype=
	let pass=1
	while [[ "${rgtype}" = "failover" ]]
	do
		net_rstype=

		# Add any network resources?
		if [[ ${pass} -eq 1 ]]; then
			answer=$(sc_prompt_yesno "$(gettext 'Do you want to add any network resources now?')" "${YES}") || return 1
		else
			answer=$(sc_prompt_yesno "$(gettext 'Do you want to add any additional network resources?')" "${NO}") || return 1
		fi

		# No, break out
		if [[ "${answer}" != "yes" ]]; then
			break
		fi

		# LogicalHostname or SharedAddress?
		prompt="$(gettext 'Select the type of network resource you want to add:')"
		net_rstype="$(
		    sc_get_scrolling_menuoptions	\
			"${prompt}"			\
			"" ""				\
			1 1 1				\
			"LogicalHostname"		\
			"SharedAddress"			\
		)"
		if [[ -z "${net_rstype}" ]]; then
			return 1
		fi

		# How many subnets/resources?
		if [[ "${net_rstype}" == "LogicalHostname" ]]; then
			sc_print_para "${sctxt_p1_network_rsl}"
		else
			sc_print_para "${sctxt_p1_network_rss}"
		fi
		answer=
		while [[ -z "${answer}" ]]
		do
			prompt="$(printf "$(gettext 'How many %s resources would you like to create?')" ${net_rstype})"
			answer="$(sc_prompt "${prompt}" "1")" || return 1
			if [[ $(expr "${answer}" : '[0-9]*') -ne ${#answer} ]]; then
				printf "$(gettext '\"%s\" is not numeric.')\n\n\a" "${answer}"
				answer=
				continue
			fi
		done
		let total=${answer}
		let count=1
		while [[ ${count} -le ${total} ]]
		do
			# Confirm, when more than one resource?
			if [[ ${total} -gt 1 ]]; then
				if [[ ${count} -eq 1 ]]; then
					foo="$(printf "$(gettext 'Okay to configure the first %s resource?')" "${net_rstype}")"
				else
					foo="$(printf "$(gettext 'Okay to configure the next %s resource?')" "${net_rstype}")"
				fi
				answer=$(sc_prompt_yesno "${foo}" "${YES}") || break
				if [[ "${answer}" != "yes" ]]; then
					answer="$(sc_prompt_yesno "$(gettext 'Are you sure?')")" || break
					if [[ "${answer}" == "yes" ]]; then
						break
					fi
				fi
			fi

			# Add resource with appropriate help text
			if [[ ${count} -eq 1 ]]; then
				foo="nohelp"
			else
				foo="NOHELP2"
			fi
			scsetup_menu_rgm_rs_addnet "${foo}" "${rgname}" "${rgtype}" "${net_rstype}" "1"
			if [[ $? -eq 0 ]]; then
				((count += 1))
			fi
		done
		
		# Done
		((pass+=1))
	done

	let count=0
	while true
	do
		# Add any data service resources?
		if [[ ${count} -eq 0 ]]; then
			answer=$(sc_prompt_yesno "$(gettext 'Do you want to add any data service resources now?')" "${YES}") || return 1
		else
			answer=$(sc_prompt_yesno "$(gettext 'Do you want to add any additional data service resources?')" "${NO}") || return 1
		fi

		# No, break out
		if [[ "${answer}" != "yes" ]]; then
			break
		fi

		# Add resource
		scsetup_menu_rgm_rs_addds "nohelp" "${rgname}" "${rgtype}" "1"

		# Next
		((count += 1))
	done

	# Bring it online?
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
		# Initialize
		set -A SCSETUP_DO_CMDSET
		SCSETUP_DO_CMDSET[0]="${SC_SCSWITCH} -Z -g ${rgname}"

		answer=$(sc_prompt_yesno "$(gettext 'Do you want to bring this resource group online now?')" "${YES}") || return 1
		if [[ "${answer}" == "yes" ]]; then

			# Do it, without re-confirming
			scsetup_do_cmdset 1 || return 1

		elif [[ -n "${SCSETUP_CMD_LOG}" ]]; then

			# Just ask if they want to log
			scsetup_do_cmdset 2 || return 1
		fi
	fi

	return 0
}

#####################################################
#
# scsetup_menu_rgm_rs_addnet() [nohelp rgname rgtype net_rstype [noenable]]
# scsetup_menu_rgm_rs_addnet() [nohelp]
#
#	nohelp		- if this flag is given, do not
#			    clear screen, print title, print help,
#			    or ask for confirmation to continue
#			- if the flag is set to "NOHELP2", do not print
#			    any help whatsoever
#
#	rgname		- the name of the resource group
#
#	rgtype		- if given, must be "failover"
#
#	net_rstype	- "LogicalHostname" or "SharedAddress"
#
#	Add a network resource to a resource group.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_rgm_rs_addnet()
{
	typeset nohelp=${1}
	typeset rgname=${2}
	typeset -l rgtype=${3}		# lower case
	typeset net_rstype=${4}
	typeset noenable=${5}

	typeset sctxt_title="$(gettext '
		>>> Add a Network Resource to a Resource Group <<<
	')"

	typeset sctxt_p1="$(gettext '
		Use this option to add a network resource to a resource
		group.
	')"
	typeset sctxt_p2="$(gettext '
		There are two types of network resources,
		LogicalHostname and SharedAddress.  Only failover
		resource groups may contain network resources.  A
		failover resource group typically contains one or more
		network resource type resources.  Usually, there is at
		least one network resource for each subnet.
	')"
	typeset sctxt_lhostname_p1="$(gettext '
		Each network resource manages a list of one or more
		logical hostnames for a single subnet.  This is true
		whether the resource is a LogicalHostname or
		SharedAddress resource type.  The most common
		configuration is to assign a single logical hostname to
		each network resource for each subnet.  Therefore,
		scsetup(1M) only supports this configuration.  If you
		need to support more than one hostname for a given
		subnet, add the additional support using scrgadm(1M).
	')"
	typeset sctxt_lhostname_p2="$(gettext '
		Before scsetup(1M) can create a network resource for
		any logical hostname, that hostname must be specified
		in the hosts(4) file on each node in the cluster.  In
		addition, the required network adapters must be
		actively available on each of the nodes.
	')"

	typeset cachefile=${SCSETUP_RGM_CACHEFILE}
	typeset tmpfile=${SCSETUP_TMP_RGLIST}

	typeset rsname
	typeset answer
	typeset rglist
	typeset prompt
	typeset header1
	typeset header2
	typeset rgdescription
	typeset rsdescription

	integer error
	integer count

	# Check arguments
	let error=0
	if [[ -n "${rgname}" ]]; then
		if [[ "${rgtype}" != "failover" ]]; then
			let error=1
		elif [[ "${net_rstype}" != "LogicalHostname" ]] &&
		    [[ "${net_rstype}" != "SharedAddress" ]]; then
			let error=1
		fi
		if [[ ${error} -ne 0 ]]; then
			printf "$(gettext 'Internal error.')\n\n\a"
			return -1
		fi
	fi

	# Unless nohelp is specified, print help and get confirmation
	if [[ -z "${nohelp}" ]]; then

		# Clear screen, print title and help
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Get the network resource type
	if [[ -z "${net_rstype}" ]]; then
		prompt="$(gettext 'Select the type of network resource you want to add:')"
		net_rstype="$(
		    sc_get_scrolling_menuoptions	\
			"${prompt}"			\
			"" ""				\
			1 1 1				\
			"LogicalHostname"		\
			"SharedAddress"			\
		)"
		if [[ -z "${net_rstype}" ]]; then
			return 1
		fi
	fi

	# Get the network resource name
	rsname=
	let count=0
	while [[ -z "${rsname}" ]]
	do
		if [[ ${count} -eq 0 ]] &&
		    [[ "${nohelp}" != "NOHELP2" ]]; then
			sc_print_para "${sctxt_lhostname_p1}"
			sc_print_para "${sctxt_lhostname_p2}"
			((count += 1))
		fi
		prompt="$(gettext 'What logical hostname do you want to add?')"
		answer=$(sc_prompt "${prompt}") || return 1
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			rsname="$(scsetup_get_resource ${answer})"
			if [[ -n "${rsname}" ]]; then
				printf "$(gettext '\"%s\" already exists.')\n\n\a" "${rsname}"
				rsname=
				continue
			fi
		fi

		# Done
		rsname=${answer}
	done

	# Get the rgname
	while [[ -z "${rgname}" ]]
	do
		# Get the complete list of configured FAILOVER groups
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] ||
		    [[ -r "${cachefile}" ]];  then
			rglist="$(scsetup_get_rglist "" FAILOVER "" ${cachefile})"
		else
			rglist="failover_rg1 failover_rg2 failover_rg3 failover_rg4 failover_rg5 failover_rg6 failover_rg7 failover_rg8 failover_rg9 failover_rg10 failover_rg11 failover_rg12"
		fi

		# Make sure we found at least one failover group
		if [[ -z "${rglist}" ]]; then
			echo
			printf "$(gettext 'There are no failover resource groups.')\n\n\a"
			sc_prompt_pause
			return -1
		fi

		# Create a temp file which contains each RG with description
		rm -f ${tmpfile}
		for rgname in ${rglist}
		do
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] ||
			    [[ -r "${cachefile}" ]];  then
				rgdescription="$(scsetup_get_rgdescription ${rgname} ${cachefile})"
			else
				rgdescription="DEBUG:  this is a description"
			fi
			printf "%-20s %-10.10s %-30.30s" ${rgname} "Failover" "${rgdescription}"
			if [[ ${#rgdescription} -gt 30 ]]; then
				echo " ...\c"
			fi
			echo
		done >${tmpfile}

		# Get the resource group name
		prompt="$(printf "$(gettext 'Select the resource group you want to use for \"%s\":')" "${rsname}")"
		header1="$(printf "%-20s %-10.10s %-30.30s" "$(gettext 'Group Name')" "$(gettext 'Type')" "$(gettext 'Description')")"
		header2="$(printf "%-20s %-10.10s %-30.30s" "==========" "====" "===========")"
		rgname="$(
		    sc_get_scrolling_menuoptions	\
			"${prompt}"			\
			"${header1}"			\
			"${header2}"			\
			1 1 1				\
			:${tmpfile}			\
		)"
		rm -f ${tmpfile}
		if [[ -z "${rgname}" ]]; then
			return 1
		fi
	done

	# Set the rgtype to failover
	rgtype=failover

	# Initialize
	set -A SCSETUP_DO_CMDSET

	# Basic command
	if [[ "${net_rstype}" = "LogicalHostname" ]]; then
		rsdescription="LogicalHostname resource for ${rsname}"
		SCSETUP_DO_CMDSET[0]="${SC_SCRGADM} -a -L -g ${rgname} -l ${rsname}"
	elif [[ "${net_rstype}" = "SharedAddress" ]]; then
		rsdescription="SharedAddress resource for ${rsname}"
		SCSETUP_DO_CMDSET[0]="${SC_SCRGADM} -a -S -g ${rgname} -l ${rsname}"
	fi

	# Add description
	SCSETUP_DO_CMDSET[1]="${SC_SCRGADM} -c -j ${rsname} -y R_description=\"${rsdescription}\""

	# Attempt to issue the command
	scsetup_do_cmdset || return 1

	# Bring this resource online?
	if [[ -z "${noenable}" ]]; then

		# Initialize
		set -A SCSETUP_DO_CMDSET
		SCSETUP_DO_CMDSET[0]="${SC_SCSWITCH} -e -j ${rsname}"
		SCSETUP_DO_CMDSET[1]="${SC_SCSWITCH} -e -M -j ${rsname}"

		# Enable it?
		answer=$(sc_prompt_yesno "$(gettext 'Do you want to enable this resource?')" "${YES}")
		if [[ "${answer}" == "yes" ]]; then

			# Do it, without re-confirming
			scsetup_do_cmdset 1 || return 1

		elif [[ -n "${SCSETUP_CMD_LOG}" ]]; then

			# Just ask if they want to log
			scsetup_do_cmdset 2 || return 1
		fi
	fi

	return 0
}

#####################################################
#
# scsetup_menu_rgm_rs_addds() [nohelp rgname rgtype [noenable]]
# scsetup_menu_rgm_rs_addds() [nohelp]
#
#	nohelp		- if this flag is given, do not
#			    clear screen, print title, print help,
#			    or ask for confirmation to continue
#
#	rgname		- the name of the resource group
#
#	rgtype		- if given, must be "failover" or "scalable"
#
#	noenable	- if set, do not ask about enabling the resource.
#
#	Add a data service resource to a resource group.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_rgm_rs_addds()
{
	typeset nohelp=${1}
	typeset rgname=${2}
	typeset -l rgtype=${3}		# lower case
	typeset noenable=${4}

	typeset sctxt_title="$(gettext '
		>>> Add a Data Service Resource to a Resource Group <<<
	')"

	typeset sctxt_p1="$(gettext '
		This option allows you to add a data service resource
		to a resource group.  If the resource type for the data
		service is not yet registered with the cluster, you
		will have the opportunity to register that type.
	')"
	typeset sctxt_reg_p1="$(gettext '
		The type of resource you selected is not yet
		registered.  Each resource type must be registered with
		the cluster before any resources of the selected type
		can be added to a resource group.
	')"
	typeset sctxt_reg_p2="$(gettext '
		Registration of a resource type updates the
		cluster-wide configuration with the resource type
		properties found in default rt_reg files (see
		rt_reg(4)) on this node.  It is important that the same
		resource type or data service software has been
		installed on each node in the cluster prior to
		registration.

	')"
	typeset sctxt_reg_p3="$(gettext '
		If you do not register the resource type now, you will
		not be able to add this resource.
	')"
	typeset sctxt_netused_p1="$(gettext '
		For scalable resources, you must specify a list of
		SharedAddress resources upon which the new resource
		depends.  Since network resources can only belong to
		failover resource groups, the SharedAddress resources
		that you name must live in a failover group.
	')"
	typeset sctxt_netused_p2="$(gettext '
		However, there are no SharedAddress resources currently
		configured in the cluster.
	')"
	typeset sctxt_portlist_p1="$(gettext '
		This data service uses the \"Port_list\" property.  The
		default \"Port_list\" for this data service is as
		follows:
	')"
	typeset sctxt_portlist_p2="$(gettext '
		This data service requires that you explicitly set the
		\"Port_list\" property.
	')"
	typeset sctxt_portlist_p3="$(gettext '
		Please check the man page for this resource type
		for more information on how the list should be set for
		this resource.
	')"
	typeset sctxt_portlist_prompt1="$(gettext 'Port number (Ctrl-D to finish):')"
	typeset sctxt_portlist_prompt2="$(gettext 'Is this a TCP port?')"

	typeset sctxt_loadbalance_title="$(gettext '
		Configure a load balancing policy
	')"
	typeset sctxt_loadbalance_p1="$(gettext '
		Sun Cluster supports three load balancing policies.
		Each scalable resource must have a policy assigned to
		it at creation time.  The policies are weighted,
		sticky, and wild.
	')"
	typeset sctxt_loadbalance_p2="$(gettext '
		A weighted load balancing policy distributes the load
		among the various nodes according to the weights set in
		a \"Load_balancing_weights\" property.
	')"
	typeset sctxt_loadbalance_p3="$(gettext '
		A sticky load balancing policy always returns a given
		client of a scalable resource to the same node and port
		of the cluster.
	')"
	typeset sctxt_loadbalance_p4="$(gettext '
		A wild load balancing policy always returns a given
		client of a scalable resource to the same node, but to
		any port on that node.
	')"
	typeset sctxt_loadbalance_p5="$(gettext '
		Please refer to your data services documentation for
		recommendations on how the load balancing policy should
		be set for this service.
	')"
	typeset sctxt_loadbalance_prompt1="$(gettext 'Okay to use the default \"weighted\" policy?')"
	typeset sctxt_loadbalance_prompt2="$(gettext 'Select the policy you want to use:')"

	typeset sctxt_extprops_p1="$(gettext '
		Some resource types require that you set certain
		extension properties.
	')"
	typeset sctxt_extprops_p2="$(gettext '
		Please check the man page for your data service to
		learn more about extension properties associated with
		the resource that you are adding.
	')"
	typeset sctxt_extprops_p3="$(gettext '
		This resource type does require that you set one or more
		extension properties.
	')"
	typeset sctxt_extprops_prompt1="    $(gettext 'Property name:       ')"
	typeset sctxt_extprops_prompt2="    $(gettext 'Property description:')"
	typeset sctxt_extprops_prompt3="    $(gettext 'Property type:       ')"
	typeset sctxt_extprops_prompt4="    $(gettext 'Property value:      ')"

	typeset SCSETUP_RT_NAMES_REG		# registered rt names
	typeset SCSETUP_RT_MODE_REG		# "failover" or "scalable"
	typeset SCSETUP_RT_DESCS_REG		# registered rt descripts
	typeset SCSETUP_RT_NAMES_UNREG		# UNregistered rt names
	typeset SCSETUP_RT_MODE_UNREG		# "failover" or "scalable"
	typeset SCSETUP_RT_DESCS_UNREG		# UNregistered rt descripts

	typeset SCSETUP_RT_PROP_NAMES		# Property names
	typeset SCSETUP_RT_PROP_DESCS		# Property descriptions
	typeset SCSETUP_RT_PROP_TYPES		# Property types
	typeset SCSETUP_RT_PROP_DFLTS		# Property defaults

	typeset rstypes

	typeset cachefile=${SCSETUP_RGM_CACHEFILE}
	typeset tmpfile1=${SCSETUP_TMP_RSLIST}
	typeset tmpfile1_sorted=${SCSETUP_TMP_RSLIST_SORTED}
	typeset tmpfile2=${SCSETUP_TMP_PROPLIST}

	typeset prompt
	typeset header1
	typeset header2
	typeset answer
	typeset name
	typeset answers
	typeset rgdescription
	typeset rsdescription
	typeset rglist
	typeset rglist_f
	typeset rglist_s
	typeset rsname
	typeset rsmode
	typeset rstype
	typeset rsdesc
	typeset rslist
	typeset rsscalable
	typeset rsloadpolicy
	typeset rsnetused
	typeset rsportlist
	typeset rsportlist_dflt
	typeset foo
	typeset foonetused
	typeset propname
	typeset propnames
	typeset -l proptype		# lower case
	typeset propvalue
	typeset -l lpropvalue		# lower case
	typeset propvalues
	typeset propdesc
	typeset proprequired

	integer i
	integer j
	integer index
	integer index_reg
	integer index_unreg
	integer counter
	integer rstype_register
	integer found
	integer registered
	integer error
	integer saved_mustset
	integer mustset
	integer rscount
	integer count

	# Check arguments
	let error=0
	if [[ -n "${rgname}" ]]; then
		if [[ "${rgtype}" != "failover" ]] &&
		    [[ "${rgtype}" != "scalable" ]]; then
			printf "$(gettext 'Internal error.')\n\n\a"
			return -1
		fi
	fi

	# Unless nohelp is specified, print help and get confirmation
	if [[ -z "${nohelp}" ]]; then

		# Clear screen, print title and help
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	#
	# Set up the following arrays:
	#
	#	SCSETUP_RT_NAMES_REG	# registered resource type names
	#	SCSETUP_RT_DESCS_REG	# registered resource descripts
	#	SCSETUP_RT_MODE_REG	# "failover" or "scalable"
	#
	#	SCSETUP_RT_NAMES_UNREG	# unregistered resource type names
	#	SCSETUP_RT_DESCS_UNREG	# unregistered resource descrips
	#	SCSETUP_RT_MODE_UNREG	# "failover" or "scalable"
	#
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
		scsetup_get_registered_rstypes "nonet" ${cachefile}
		scsetup_get_unregistered_rstypes "nonet"
	else
		if [[ -n "${cachefile}" ]] && [[ -r "${cachefile}" ]]; then
			scsetup_get_registered_rstypes "nonet" ${cachefile}
		fi
		if [[ -z "${SCSETUP_RT_NAMES_REG[0]}" ]]; then
			set -A SCSETUP_RT_NAMES_REG
			set -A SCSETUP_RT_DESCS_REG
			set -A SCSETUP_RT_MODE_REG

			set -A SCSETUP_RT_NAMES_UNREG
			set -A SCSETUP_RT_DESCS_UNREG
			set -A SCSETUP_RT_MODE_UNREG

			# Set some debug resource types
			SCSETUP_RT_NAMES_REG[0]=Debug1
			SCSETUP_RT_NAMES_REG[1]=Debug2
			SCSETUP_RT_DESCS_REG[0]="Failover resource type debug1"
			SCSETUP_RT_DESCS_REG[1]="Scalable resource type debug2"
			SCSETUP_RT_MODE_REG[0]="failover"
			SCSETUP_RT_MODE_REG[1]="scalable"

			SCSETUP_RT_NAMES_UNREG[0]=unreg_Debug3
			SCSETUP_RT_NAMES_UNREG[1]=unreg_Debug4
			SCSETUP_RT_DESCS_UNREG[0]="Failover resource type debug3"
			SCSETUP_RT_DESCS_UNREG[1]="Scalable resource type debug4"
			SCSETUP_RT_MODE_UNREG[0]="failover"
			SCSETUP_RT_MODE_UNREG[1]="scalable"
		fi
	fi

	# Get the resource type name
	rstype=
	while [[ -z "${rstype}" ]]
	do

		# Create a temp file which contains each res, with description
		rsdesc=
		let rstype_register=0
		let index_reg=0
		let index_unreg=0
		let counter=0
		set -A rstypes

		rm -f ${tmpfile1}
		while true
		do
			if [[ -n "${SCSETUP_RT_NAMES_REG[index_reg]}" ]]; then
				rstype=${SCSETUP_RT_NAMES_REG[index_reg]}
				rsdesc="${SCSETUP_RT_DESCS_REG[index_reg]}"
				rsmode=${SCSETUP_RT_MODE_REG[index_reg]}
				((index_reg += 1))
				if [[ "${rgtype}" == "scalable" ]] &&
				    [[ "${rsmode}" != "scalable" ]]; then
					continue
				fi
			elif [[ -n "${SCSETUP_RT_NAMES_UNREG[index_unreg]}" ]]; then
				rstype=${SCSETUP_RT_NAMES_UNREG[index_unreg]}
				rsdesc="${SCSETUP_RT_DESCS_UNREG[index_unreg]}"
				rsmode=${SCSETUP_RT_MODE_UNREG[index_unreg]}
				((index_unreg += 1))
				if [[ "${rgtype}" == "scalable" ]] &&
				    [[ "${rsmode}" != "scalable" ]]; then
					continue
				fi
			else
				# End of list
				break
			fi
			rstypes[counter]=${rstype}
			((counter += 1))
			printf "%-20s %-43.43s" "${rstype}" "${rsdesc}"
			if [[ ${#rsdesc} -gt 43 ]]; then
				echo " ...\c"
			fi
			echo
		done >${tmpfile1}

		# Sort it
		rm -f ${tmpfile1_sorted}
		sort ${tmpfile1} >${tmpfile1_sorted}
		rm -f ${tmpfile1}

		# Make sure we found something
		if [[ ${counter} -eq 0 ]]; then
			if [[ "${rgtype}" == "scalable" ]]; then
				printf "$(gettext 'Cannot find any scalable data service resource types.')\n\n\a"
			else
				printf "$(gettext 'Cannot find any data service resource types.')\n\n\a"
			fi
			rm -f ${tmpfile1_sorted}
			sc_prompt_pause
			return 1
		fi
		echo

		# Get the resource type
		prompt="$(gettext 'Select the type of resource you want to add:')"
		header1="$(printf "%-20s %-43.43s" "$(gettext 'Res Name')" "$(gettext 'Description')")"
		header2="$(printf "%-20s %-43.43s" "========" "===========")"
		rstype="$(
		    sc_get_scrolling_menuoptions	\
			"${prompt}"			\
			"${header1}"			\
			"${header2}"			\
			1 1 1				\
			:${tmpfile1_sorted}		\
		)"
		rm -f ${tmpfile1_sorted}
		if [[ -z "${rstype}" ]]; then
			return 1
		fi

		# Set the rsmode and registered flag, if it is registered
		rsmode=
		let registered=0
		let index_reg=0
		while [[ -n "${SCSETUP_RT_NAMES_REG[index_reg]}" ]]
		do
			if [[ "${SCSETUP_RT_NAMES_REG[index_reg]}" == "${rstype}" ]]; then
				rsmode=${SCSETUP_RT_MODE_REG[index_reg]}
				let registered=1
				break
			fi
			((index_reg += 1))
		done

		# If not registered, it should be unregistered 
		if [[ ${registered} -eq 0 ]]; then
			let index_unreg=0
			while [[ -n "${SCSETUP_RT_NAMES_UNREG[index_unreg]}" ]]
			do
				if [[ "${SCSETUP_RT_NAMES_UNREG[index_unreg]}" == "${rstype}" ]]; then
					rsmode=${SCSETUP_RT_MODE_UNREG[index_unreg]}
					break
				fi
				((index_unreg += 1))
			done
		fi

		# If unregistered, register it now?
		while [[ ${registered} -eq 0 ]]
		do
			# Print message
			sc_print_para "${sctxt_reg_p1}"
			sc_print_para "${sctxt_reg_p2}"

			# Is the software installed on each node?
			answer=$(sc_prompt_yesno "$(gettext 'Is the software for this service installed on each node?')" "${YES}") || return 1
			if [[ "${answer}" != "yes" ]]; then
				printf "$(gettext 'Please install the software on each node, then try again.')\n\n\a"
				return 1
			fi

			# Okay to register the data service
			answer=$(sc_prompt_yesno "$(gettext 'Is it okay to register this resource type now?')" "${YES}") || return 1
			if [[ "${answer}" != "yes" ]]; then
				
				# Print message
				sc_print_para "${sctxt_reg_p3}"

				# Confirm
				answer=$(sc_prompt_yesno "$(gettext 'Are you sure?')" "${NO}") || return 1
				if [[ "${answer}" != "yes" ]]; then
					printf "$(gettext 'Then you must select another resource type.')\n\n\a"
					sc_prompt_pause
					return 1
				fi
			fi

			# Okay to register
			let rstype_register=1

			# Done
			break
		done

		# Done
		break
	done

	# Register the resource type, if needed
	if [[ -n "${rstype}" ]] && [[ ${rstype_register} -ne 0 ]]; then

		# Initialize
		set -A SCSETUP_DO_CMDSET

		# Add the command
		SCSETUP_DO_CMDSET[0]="${SC_SCRGADM} -a -t ${rstype}"

		# Attempt to issue the command, without re-confirmation
		scsetup_do_cmdset 1 || return 1
	fi

	# Get the resource name
	rsname=
	while [[ -z "${rsname}" ]]
	do
		# Get the name of the resource
		answer="$(sc_prompt "$(gettext 'What is the name of the resource you want to add?')")" || return 1

		# If the resource already exists, print error
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			foo="$(scsetup_get_resource ${answer})"
			if [[ -n "${foo}" ]]; then
				printf "$(gettext 'Resource \"%s\" is already configured.')\n\n\a" "${answer}"
				continue
			fi
		fi

		# Done
		rsname=${answer}
	done

	# Get the rgname
	while [[ -z "${rgname}" ]]
	do
		rglist_f=
		rglist_s=

		# Get the failover and scalable RGs
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] ||
		    [[ -r "${cachefile}" ]]; then
			rglist_f="$(scsetup_get_rglist "" FAILOVER "" ${cachefile})"
			if [[ "${rsmode}" == "scalable" ]]; then
				rglist_s="$(scsetup_get_rglist "" SCALABLE "" ${cachefile})"
			fi
		else
			rglist_f="failover_rg1 failover_rg2 failover_rg3 failover_rg4 failover_rg5 failover_rg6 failover_rg7 failover_rg8 failover_rg9 failover_rg10 failover_rg11 failover_rg12 failover_rg13 failover_rg14"
			if [[ "${rsmode}" == "scalable" ]]; then
				rglist_s="scalable_rg1 scalable_rg2 scalable_rg3 scalable_rg4 scalable_rg5 scalable_rg6 scalable_rg7 scalable_rg8 scalable_rg9 scalable_rg10 scalable_rg11 scalable_rg12 scalable_rg13 scalable_rg14"
			fi
		fi

		# Make sure we found at least one group
		if [[ -z "${rglist_f}" ]] && [[ -z "${rglist_s}" ]]; then
			echo
			if [[ "${rsmode}" == "failover" ]]; then
				printf "$(gettext 'There are no failover resource groups configured.')\n\n\a"
			else
				printf "$(gettext 'There are no resource groups configured.')\n\n\a"
			fi
			sc_prompt_pause
			return -1
		fi

		# Create a temp file which contains each RG with description
		rm -f ${tmpfile1}
		rglist="${rglist_f}"
		foo="Failover"
		for j in 1 2
		do
			for rgname in ${rglist}
			do
				if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] ||
				    [[ -r "${cachefile}" ]];  then
					rgdescription="$(scsetup_get_rgdescription ${rgname} ${cachefile})"
				else
					rgdescription="DEBUG:  this is a description"
				fi

				printf "%-20s %-10.10s %-30.30s" ${rgname} "${foo}" "${rgdescription}"
				if [[ ${#rgdescription} -gt 30 ]]; then
					echo " ...\c"
				fi
				echo
			done
			rglist="${rglist_s}"
			foo="Scalable"
		done >${tmpfile1}

		# Get the resource group name
		prompt="$(printf "$(gettext 'Select the resource group you want to use for \"%s\":')" "${rsname}")"
		header1="$(printf "%-20s %-10.10s %-30.30s" "$(gettext 'Group Name')" "$(gettext 'Type')" "$(gettext 'Description')")"
		header2="$(printf "%-20s %-10.10s %-30.30s" "==========" "====" "===========")"
		rgname="$(
		    sc_get_scrolling_menuoptions	\
			"${prompt}"			\
			"${header1}"			\
			"${header2}"			\
			1 1 1				\
			:${tmpfile1}			\
		)"
		rm -f ${tmpfile1}
		if [[ -z "${rgname}" ]]; then
			return 1
		fi
	done

	# Get the rg type
	if [[ -z "${rgtype}" ]]; then
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			rgtype="$(scsetup_get_rgtype ${rgname})"
			if [[ -z "${rgtype}" ]]; then
				printf "$(gettext 'Unable to discover what type of resource group this is.')\n\n\a"
				sc_prompt_pause
				return 1
			fi
		else
			# Get the RG type from DEBUG mode
			rgtype=
			while [[ "${rgtype}" != "failover" ]] &&
			    [[ "${rgtype}" != "scalable" ]]
			do
				rgtype=$(sc_prompt "DEBUG:  What type of resource group is this (failover|scalable)?" "failover")
			done
		fi
	fi

	# Cache scrgadm output
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
		scsetup_create_scrgadmfile ${cachefile}
	fi

        # See if we must set the Scalable property
	rsscalable=
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
		scsetup_get_prop_default ${rstype} Scalable 2>/dev/null 1>&2      
		if [[ $? -eq 0 ]]; then
			rsscalable=doit
		fi
	elif [[ "${rgtype}" == "scalable" ]]; then
		rsscalable=doit
	fi
	if [[ -n "${rsscalable}" ]]; then
		if [[ "${rgtype}" == "scalable" ]]; then
			rsscalable=true
		else
			rsscalable=false
		fi
	fi

	# Get the network_resources_used list for scalable RGs, if required
	rsnetused=
	if [[ "${rgtype}" == "scalable" ]]; then

		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] ||
		    [[ -r "${cachefile}" ]];  then
			scsetup_get_prop_default ${rstype} Network_resources_used ${cachefile} 2>/dev/null 1>&2
			if [[ $? -eq 0 ]]; then
				rsnetused=doit
			fi
		else
			rsnetused=doit
		fi
	fi
	if [[ "${rsnetused}" == "doit" ]]; then
		rsnetused=

		# Print help
		sc_print_para "${sctxt_netused_p1}"

		# Get the list of SharedAddress resources
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] ||
		    [[ -r "${cachefile}" ]];  then
			rslist="$(scsetup_get_rslist "" "SUNW.SharedAddress" ${cachefile})"
		else
			rslist="saddr_res1 saddr_res2 saddr_res3 saddr_res4 saddr_res5 saddr_res5 saddr_res6 saddr_res7 saddr_res8 saddr_res9 saddr_res10"
		fi
		if [[ -z "${rslist}" ]]; then
			sc_print_para "${sctxt_netused_p2}"
			sc_prompt_pause
			return 1
		fi

		# Get the count
		rscount=$(set -- ${rslist};  echo $#)

		# Set the prompt
		prompt="$(gettext 'Select one or more SharedAddress resources:')" 
		# Get the rsnetused list
		while [[ -z "${rsnetused}" ]]
		do
			# Menu of SharedAddress resources
			rsnetused="$(
			    sc_get_scrolling_menuoptions		\
				"${prompt}"				\
				"" ""					\
				1 ${rscount} 1				\
				${rslist}				\
			)"
			if [[ -z "${rsnetused}" ]]; then
				return -1
			fi

			# Print the list and verify that the list is correct
			(
				sc_print_para "$(gettext 'This is the list you entered of SharedAddress resources used:')"
				for foo in ${rsnetused}
				do
					printf "\t${foo}\n"
				done
				echo
			) | more

			# Verify
			answer=$(sc_prompt_yesno "$(gettext 'Is it correct?')" "${YES}") || return 1
			if [[ "${answer}" != "yes" ]]; then
				rsnetused=
				continue
			fi        

			# Fix up rsnetused
			foonetused=
			for foo in ${rsnetused}
			do
				if [[ -z "${foonetused}" ]]; then
					foonetused="${foo}"
				else
					foonetused="${foonetused},${foo}"
				fi
			done
			rsnetused="${foonetused}"
		done
	fi

	# See if a portlist is required
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] || [[ -r "${cachefile}" ]];  then
		rsportlist_dflt="$(scsetup_get_prop_default ${rstype} Port_list ${cachefile})"
		# If Port_list is unknown, set dflt to "notused" for failover
		if [[ $? -ne 0 ]] && [[ "${rgtype}" == "failover" ]]; then
			rsportlist_dflt=notused
		fi

	# If debugging (and no cachefile) and "scalable", port list is required
	elif [[ "${rgtype}" == "scalable" ]]; then
		rsportlist_dflt=

	# If debugging (and no cachefile) and not "scalable", no port list
	else
		rsportlist_dflt=notused
	fi

	# Get the rsportlist, if required
	rsportlist=
	while [[ "${rsportlist_dflt}" != "notused" ]] &&
	    [[ -z "${rsportlist}" ]]
	do
		if [[ -n "${rsportlist_dflt}" ]]; then

			# Print help
			sc_print_para "${sctxt_portlist_p1}"

			# Print default setting
			for foo in ${rsportlist_dflt}
			do
				printf "\t${foo}\n"
			done
			echo

			# Print more help
			sc_print_para "${sctxt_portlist_p3}"

			# Override the default?
			answer=$(sc_prompt_yesno "$(gettext 'Do you want to override the default?')" "${NO}") || return 1
			if [[ "${answer}" != "yes" ]]; then
				break
			fi
		else
			# Print help
			sc_print_para "${sctxt_portlist_p2}"
			sc_print_para "${sctxt_portlist_p3}"
		fi

		# Get the list of ports
		answers=
		while true
		do
			# Get the port number
			answer=$(sc_prompt "${sctxt_portlist_prompt1}" "" "nonl") || break
			if [[ "${answer}" != [0-9]* ]]; then
				echo
				printf "$(gettext '\"%s\" is not numeric.')\n\n\a" "${answer}"
				continue
			fi
			let j=${answer}
			if [[ ${j} -lt 1 ]]; then
				echo
				printf "$(gettext 'The port number must be greater than zero.')\n\n\a"
				continue
			fi

			# TCP?
			foo=$(sc_prompt_yesno "${sctxt_portlist_prompt2}" "${YES}") || continue
			if [[ "${foo}" == "yes" ]]; then
				answer="${answer}/tcp"
			else
				answer="${answer}/udp"
			fi

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

			# Okay, add it to the list of answers
			answers="${answers} ${answer}"
		done

		# Did they enter anything?
		if [[ -z "${answers}" ]]; then
			continue
		fi

		# Verify that the list is correct
		echo
		sc_print_para "$(gettext 'This is the Port_list which you entered:')"
		for answer in ${answers}
		do
			printf "\t${answer}\n"
		done
		echo
		answer=$(sc_prompt_yesno "$(gettext 'Is it correct?')" "${YES}") || return 1
		if [[ "${answer}" != "yes" ]]; then
			continue
		fi        

		# Okay, set rsportlist
		for answer in ${answers}
		do
			if [[ -n "${rsportlist}" ]]; then
				rsportlist="${rsportlist},"
			fi
			rsportlist="${rsportlist}${answer}"
		done
	done

	# For scalable resources, get the Load_balancing_policy.
	rsloadpolicy=
	while [[ "${rsscalable}" == "true" ]] && [[ -z "${rsloadpolicy}" ]]
	do
		# Clear screen, print title and help
		sc_print_title "${sctxt_loadbalance_title}"

		# Print help
		sc_print_para "${sctxt_loadbalance_p1}"
		sc_print_para "${sctxt_loadbalance_p2}"
		sc_print_para "${sctxt_loadbalance_p3}"
		sc_print_para "${sctxt_loadbalance_p4}"
		sc_print_para "${sctxt_loadbalance_p5}"

		# Weighted?
		answer=$(sc_prompt_yesno "${sctxt_loadbalance_prompt1}" "${YES}") || return 1
		if [[ "${answer}" == "yes" ]]; then
			rsloadpolicy="Lb_weighted"
			break
		fi

		# Otherwise, select from menu
		rsloadpolicy="$(
		    sc_get_scrolling_menuoptions		\
			"${sctxt_loadbalance_prompt2}"		\
			"" ""					\
			1 1 1					\
			"Weighted"				\
			"Sticky"				\
			"Wild"					\
		)"

		# By default, select weighted.
		if [[ -z "${rsloadpolicy}" ]]; then
			rsloadpolicy="Weighted"
		fi

		# Confirm
		foo="$(printf "$(gettext 'Are you sure you want to use the \"%s\" policy?')" "${rsloadpolicy}")"
		echo
		answer=$(sc_prompt_yesno "${foo}" "${YES}") || return 1
		if [[ "${answer}" != "yes" ]]; then
			rsloadpolicy=
			continue
		fi

		# Reset rsloadpolicy
		case ${rsloadpolicy} in
		Weighted)	rsloadpolicy="Lb_weighted" ;;
		Sticky)		rsloadpolicy="Lb_sticky" ;;
		Wild)		rsloadpolicy="Lb_wild" ;;
		*)		rsloadpolicy= ;;
		esac
	done

	#
	# Get the extension properties for this resource type
	#
	#	SCSETUP_RT_PROP_NAMES	# names of all the properties
	#	SCSETUP_RT_PROP_DESCS	# description of each property in list
	#	SCSETUP_RT_PROP_TYPES	# type of each property in list
	#	SCSETUP_RT_PROP_DFLTS	# default values for each property
	#
	set -A SCSETUP_RT_PROP_NAMES
	set -A SCSETUP_RT_PROP_DESCS
	set -A SCSETUP_RT_PROP_TYPES
	set -A SCSETUP_RT_PROP_DFLTS

	# If not a cluster member, use the cache file, if available
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] || [[ -r "${cachefile}" ]];  then
		scsetup_get_rstype_extprops ${rstype} ${cachefile}

	# otherwise, fabricate debug data
	else
		set -A SCSETUP_RT_PROP_NAMES Prop_int Prop_string Prop_array Prop_other
		SCSETUP_RT_PROP_DESCS[0]="Integer property"
		SCSETUP_RT_PROP_DESCS[1]="String property"
		SCSETUP_RT_PROP_DESCS[2]="String array property"
		SCSETUP_RT_PROP_DESCS[3]="Other property"

		SCSETUP_RT_PROP_TYPES[0]=Int
		SCSETUP_RT_PROP_TYPES[1]=String
		SCSETUP_RT_PROP_TYPES[2]=Stringarray
		SCSETUP_RT_PROP_TYPES[3]=

		SCSETUP_RT_PROP_DFLTS[0]=20
		SCSETUP_RT_PROP_DFLTS[1]="hello"
		SCSETUP_RT_PROP_DFLTS[2]=
		SCSETUP_RT_PROP_DFLTS[3]=
	fi

	# Done with cache file, for now
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
		scsetup_rm_scrgadmfile ${cachefile}
	fi

	#
	# Get the extension property settings
	#

	# Initialize menu headings
	prompt="$(gettext 'Select a property you would like to set:')"
	header1="$(printf "%-30s %-18.18s %-18.18s" "$(gettext 'Property Name')" "$(gettext 'Default Setting')" "$(gettext 'Desired Setting')")"
	header2="$(printf "%-30s %-18.18s %-18.18s" "=============" "===============" "===============")"

	# Set propnames and propvalues arrays
	set -A propnames
	set -A propvalues
	while [[ -n "${SCSETUP_RT_PROP_NAMES[0]}" ]]
	do
		# First time through with property name selection?
		if [[ -z "${propnames[0]}" ]]; then

			# See if any properties must be set
			let i=0
			let saved_mustset=0
			for propname in ${SCSETUP_RT_PROP_NAMES[*]}
			do
				if [[ -z "${SCSETUP_RT_PROP_DFLTS[i]}" ]]; then
					((saved_mustset += 1))
				fi
				((i += 1))
			done

			# Print help
			(
				sc_print_para "${sctxt_extprops_p1}"
				sc_print_para "${sctxt_extprops_p2}"
				if [[ ${saved_mustset} -gt 0 ]]; then
					sc_print_para "${sctxt_extprops_p3}"
				fi
			) | more

		# Not the first time through
		else
			# Clear the old values?
			if [[ -n "${propvalues[*]}" ]]; then
				answer=$(sc_prompt_yesno "$(gettext 'Do you want to clear all the old property values?')" "${NO}")
				if [[ "${answer}" == "yes" ]]; then
					set -A propnames
					set -A propvalues
				fi
			else
				set -A propnames
			fi
		fi

		# Set count of properties that must be set
		let mustset=${saved_mustset}

		# Set any properties now?
		if [[ -z "${propnames[0]}" ]] &&
		    [[ ${mustset} -eq 0 ]]; then
			answer=$(sc_prompt_yesno "$(gettext 'Any extension properties you would like to set?')" "${YES}") || return 1
			if [[ "${answer}" != "yes" ]]; then
				break
			fi
		fi

		# Loop for all properties they want to set
		while true
		do
			# Setup the menu list
			rm -f ${tmpfile2}
			let i=0
			for propname in ${SCSETUP_RT_PROP_NAMES[*]}
			do
				# Set the default value
				propdflt="${SCSETUP_RT_PROP_DFLTS[i]}"

				# Set the desired value
				let j=0
				propvalue=
				while [[ -n "${propnames[j]}" ]]
				do
					if [[ "${propname}" == "${propnames[j]}" ]]; then
						propvalue="${propvalues[j]}"
						break
					fi

					# Next
					((j += 1))
				done

				# If no default and no value, set string
				if [[ -z "${propdflt}" ]] &&
				    [[ -z "${propvalue}" ]]; then
					propdflt="$(printf "<%s>" "$(gettext 'Needs Setting')")"
				fi

				# Add the line
				printf "%-30s %-18.18s %-18.18s\n" "${propname}" "${propdflt}" "${propvalue}"

				# Next
				((i += 1))
			done >${tmpfile2}

			# Get the name of the property to set
			propname="$(
			    sc_get_scrolling_menuoptions	\
				"${prompt}"			\
				"${header1}"			\
				"${header2}"			\
				0 1 1				\
				:${tmpfile2}			\
			)"
			rm -f ${tmpfile2}

			# Done?
			if [[ -z "${propname}" ]]; then

				# See if all required properties are set
				if [[ ${mustset} -gt 0 ]]; then
					echo
					printf "$(gettext 'Any property without a default value must be explicitly set.')\n\n\a"
					sc_prompt_pause
					continue
				fi

				# Are they done?
				answer=$(sc_prompt_yesno "$(gettext 'Are you done setting properties?')" "${YES}") || return 1
				if [[ "${answer}" == "yes" ]]; then
					break
				else
					continue
				fi
			fi

			# Set the index into propnames and propvalues
			let index=0
			while [[ -n "${propnames[index]}" ]]
			do
				if [[ "${propname}" == "${propnames[index]}" ]]; then
					break
				fi
				((index += 1))
			done

			# Print the name
			sc_print_prompt "${sctxt_extprops_prompt1}" "space"
			echo "${propname}"

			# Print the description
			sc_print_prompt "${sctxt_extprops_prompt2}" "space"
			propdesc="$(scsetup_get_rstype_extprop_desc ${propname})"
			echo "${propdesc}"

			# Print the property type
			sc_print_prompt "${sctxt_extprops_prompt3}" "space"
			proptype="$(scsetup_get_rstype_extprop_type ${propname})"
			echo "${proptype}"

			# See if we have to set this
			proprequired="$(scsetup_get_rstype_extprop_dflt ${propname})"
			[[ -z "${proprequired}" ]] && proprequired=1

			while true
			do
				propvalue=
				sc_print_prompt "${sctxt_extprops_prompt4}" "space"
				read propvalue

				# Ctrl-D?
				if [[ $? -ne 0 ]]; then
					echo
					continue 2
				fi

				# Compress ", " in stringarrays
				if [[ "${proptype}" == "stringarray" ]]; then
					propvalue="$(echo ${propvalue} | sed 's/, /,/g')"
				fi

				# Too many options?
				if [[ "${proptype}" != "string" ]];  then
					count=$(set -- ${propvalue};  echo $#)
					if [[ ${count} -gt 1 ]]; then
						echo "\a\c"
						continue
					fi
				fi

				# Newline
				echo

				# Nothing entered
				if [[ -z "${propvalue}" ]];  then

					# Clear the old value?
					if [[ -n "${propvalues[index]}" ]]; then
						answer=$(sc_prompt_yesno "$(gettext 'Do you want to clear the old property value?')" "${NO}")
						if [[ "${answer}" == "yes" ]]; then
							propvalues[index]=
							if [[ -n "${proprequired}" ]]; then
								((mustset += 1))
							fi
						fi
					fi
					continue 2
				fi

				#
				# Attempt to make sure the value is in some
				# kind of legal range.  Note that we currently
				# do not check for all value types.
				#
				case ${proptype} in
				int)
					if [[ $(expr "${propvalue}" : '[0-9]*') -ne ${#propvalue} ]]; then
						printf "$(gettext '\"%s\" is not numeric.')\n\n\a" "${propvalue}"
						continue
					fi
					;;

				boolean)
					lpropvalue=${propvalue}
					case ${lpropvalue} in
					true)	propvalue=TRUE ;;
					false)	propvalue=FALSE ;;
					*)
						printf "$(gettext '%s must be set to either \"%s\" or \"%s\".')\n\n\a" "Boolean" "TRUE" "FALSE"
						continue
						;;
					esac
					;;

				string|stringarray)
					;;

				*)
					if [[ "${propvalue}" == *,* ]]; then
						printf "$(gettext 'Stringarray is not expected.')\n\n\a"
						continue
					fi
					;;
				esac

				# Done
				break
			done

			# Set the name and value
			if [[ -z "${propnames[index]}" ]]; then
				propnames[index]=${propname}
			fi
			propvalues[index]=${propvalue}
			if [[ -n "${proprequired}" ]]; then
				((mustset -= 1))
			fi
		done

		# Verify that the list is correct
		echo
		sc_print_prompt "$(gettext 'Here is the list of extension properties you want to set:')"
		echo
		echo
		let index=0
		if [[ -n "${propvalues[*]}" ]]; then
			for propname in ${propnames[*]}
			do
				if [[ -n "${propvalues[index]}" ]]; then
					printf "\t${propname}=${propvalues[index]}\n"
				fi
				((index += 1))
			done | more
		else
			printf "\t<%s>\n" "$(gettext 'none')"
		fi
		echo
		answer=$(sc_prompt_yesno "$(gettext 'Is it correct?')" "${YES}") || return 1
		if [[ "${answer}" == "yes" ]]; then
			break
		fi
	done

	# Set the default description (in English)
	if [[ "${rsscalable}" == "true" ]]; then
		rsdescription="Scalable data service resource for ${rstype}"
	else
		rsdescription="Failover data service resource for ${rstype}"
	fi

	#
	# Add the resource
	#

	# Initialize
	set -A SCSETUP_DO_CMDSET

	# Basic command
	SCSETUP_DO_CMDSET[0]="${SC_SCRGADM} -a -j ${rsname}"
	SCSETUP_DO_CMDSET[0]="${SCSETUP_DO_CMDSET[0]} -g ${rgname}"
	SCSETUP_DO_CMDSET[0]="${SCSETUP_DO_CMDSET[0]} -t ${rstype}"

	# Add Scalable=true|false
	if [[ -n "${rsscalable}" ]]; then
		SCSETUP_DO_CMDSET[0]="${SCSETUP_DO_CMDSET[0]} -y Scalable=${rsscalable}"
	fi

	# Add Load_balancing_policy
	if [[ -n "${rsloadpolicy}" ]]; then
		SCSETUP_DO_CMDSET[0]="${SCSETUP_DO_CMDSET[0]} -y Load_balancing_policy=${rsloadpolicy}"
	fi

	# Add Network_resources_used
	if [[ -n "${rsnetused}" ]]; then
		SCSETUP_DO_CMDSET[0]="${SCSETUP_DO_CMDSET[0]} -y Network_resources_used=${rsnetused}"
	fi

	# Add the Port_list, if set
	if [[ -n "${rsportlist}" ]]; then
		SCSETUP_DO_CMDSET[0]="${SCSETUP_DO_CMDSET[0]} -y Port_list=${rsportlist}"
	fi

	# Add extension properties, if there are any
	let index=0
	for propname in ${propnames[*]}
	do
		if [[ -n "${propvalues[index]}" ]]; then
			SCSETUP_DO_CMDSET[0]="${SCSETUP_DO_CMDSET[0]} -x ${propname}=\"${propvalues[index]}\""
		fi
		((index += 1))
	done

	# Add the default description
	SCSETUP_DO_CMDSET[1]="${SC_SCRGADM} -c -j ${rsname} -y R_description=\"${rsdescription}\""

	# Attempt to issue the command
	scsetup_do_cmdset || return 1
	case $? in
	'0')	# Update and/or logging completed
		;;
	'2')	# User decided not to update OR log
		noenable=1
		;;
	*)	# Error
		return 1
		;;
	esac

	# Bring this resource online?
	if [[ -z "${noenable}" ]]; then

		# Initialize
		set -A SCSETUP_DO_CMDSET
		SCSETUP_DO_CMDSET[0]="${SC_SCSWITCH} -e -j ${rsname}"
		SCSETUP_DO_CMDSET[1]="${SC_SCSWITCH} -e -M -j ${rsname}"

		# Enable it?
		answer=$(sc_prompt_yesno "$(gettext 'Do you want to enable this resource?')" "${YES}")
		if [[ "${answer}" == "yes" ]]; then

			# Do it, without re-confirming
			scsetup_do_cmdset 1 || return 1

		elif [[ -n "${SCSETUP_CMD_LOG}" ]]; then

			# Just ask if they want to log
			scsetup_do_cmdset 2 || return 1
		fi
	fi

	return 0
}

#####################################################
#
# scsetup_menu_rgm_rt_registration()
#
#	Register one or more unregistered resource types found
#	on this node.   Or, unregister one or more unused resource
#	types.
#
#	This function always returns zero.
#
#####################################################
scsetup_menu_rgm_rt_registration()
{
	typeset sctxt_title="$(gettext '
		>>> Resource Type Registration <<<
	')"

	typeset sctxt_p1="$(gettext '
		This option allows you to register and unregister
		resource types.
	')"
	typeset sctxt_p2="$(gettext '
		Registration of a resource type updates the
		cluster-wide configuration with the resource type
		properties found in default rt_reg files (see
		rt_reg(4)) on this node.  It is important that the same
		resource type or data service software has been
		installed on each node in the cluster prior to
		registration.
	')"
	typeset sctxt_p3="$(gettext '
		A resource type, or version of a resource type, can only
		be unregistered as long as there are no resources still
		using it.
	')"
	typeset sctxt_p4="$(gettext '
		As a result of a data service upgrade, the versions
		of some resource types may be changed.   These resource
		types should be re-registered under their new versions.
		Resources may then be re-versioned to use the updated
		resource types.   Once an old version of a resource type
		is no longer used by any resources, that resource type
		can be unregistered.
	')"

	typeset sctxt_prompt_rtreg="$(gettext 'Make a selection:')"
	typeset sctxt_option_rtreg_001="$(gettext 'Register all resource types which are not yet registered')"
	typeset sctxt_option_rtreg_002="$(gettext 'Register selected resource types')"
	typeset sctxt_option_rtreg_003="$(gettext 'Unregister selected resource types')"
	typeset sctxt_option_rtreg_004="$(gettext 'Unregister all resource types which are not in use by resources')"
	typeset sctxt_option_return="$(gettext 'Return to the resource group menu')"

	typeset SCSETUP_RT_NAMES_REG		# registered rt names
	typeset SCSETUP_RT_MODE_REG		# "failover" or "scalable"
	typeset SCSETUP_RT_DESCS_REG		# registered rt descripts
	typeset SCSETUP_RT_NAMES_UNREG		# Unregistered rt names
	typeset SCSETUP_RT_MODE_UNREG		# "failover" or "scalable"
	typeset SCSETUP_RT_DESCS_UNREG		# UNregistered rs descripts

	typeset tmpfile1=${SCSETUP_TMP_RSLIST}
	typeset tmpfile1_sorted=${SCSETUP_TMP_RSLIST_SORTED}

	typeset option
	typeset task
	typeset line
	typeset prompt
	typeset header1
	typeset header2
	typeset rstype
	typeset inuse_rstypes
	typeset unreg_rstypes
	typeset rsname
	typeset rslist
	typeset foo

	integer index

	# Clear screen, print title and help
	sc_print_title "${sctxt_title}"
	sc_print_para "${sctxt_p1}"
	sc_print_para "${sctxt_p2}"
	sc_print_para "${sctxt_p3}"
	sc_print_para "${sctxt_p4}"

	# Okay to continue?
	scsetup_continue || return 1

	# Loop until done or Ctrl-D is typed
	while true
	do

		# Register or unregister?
		option=$(sc_get_menuoption \
			"T2+++${sctxt_prompt_rtreg}" \
			"S+0+1+${sctxt_option_rtreg_001}" \
			"S+0+2+${sctxt_option_rtreg_002}" \
			"S+0+3+${sctxt_option_rtreg_003}" \
			"S+0+4+${sctxt_option_rtreg_004}" \
			"R+++" \
			"S+0+q+${sctxt_option_return}" \
		)
		case ${option} in
		1)	task="registerall"	;;
		2)	task="register"		;;
		3)	task="unregister"	;;
		4)	task="unregisterall"	;;
		*)	return 0		;;
		esac

		# Common registration stuff
		if [[ ${task} == "register" ]] ||
		    [[ ${task} == "registerall" ]]; then
			#
			# Set up the following arrays for registration:
			#
			# SCSETUP_RT_NAMES_UNREG  # unregistered rt names
			# SCSETUP_RT_DESCS_UNREG  # unregistered rt descrips
			#
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
				scsetup_get_registered_rstypes "nonet"
				scsetup_get_unregistered_rstypes "nonet"
			else
				set -A SCSETUP_RT_NAMES_UNREG
				set -A SCSETUP_RT_DESCS_UNREG

				# Set some debug resource types
				SCSETUP_RT_NAMES_UNREG[0]=SUNW.unreg_Debug1
				SCSETUP_RT_NAMES_UNREG[1]=SUNW.unreg_Debug2
				SCSETUP_RT_DESCS_UNREG[0]="unreg_Debug1"
				SCSETUP_RT_DESCS_UNREG[1]="unreg_Debug2"
			fi

			# Create a temp file which contains each unreg type
			let index=0
			rm -f ${tmpfile1}
			while [[ -n "${SCSETUP_RT_NAMES_UNREG[index]}" ]]
			do
				printf "%-20s %-43.43s" "${SCSETUP_RT_NAMES_UNREG[index]}" "${SCSETUP_RT_DESCS_UNREG[index]}"
				if [[ ${#SCSETUP_RT_DESCS_UNREG[index]} -gt 43 ]]; then
					echo " ...\c"
				fi
				echo
				
				((index += 1))
			done >${tmpfile1}

		elif [[ ${task} == "unregister" ]] ||
		    [[ ${task} == "unregisterall" ]]; then
			#
			# Set up the following arrays for unregistration:
			#
			# SCSETUP_RT_NAMES_REG    # registered rt names
			# SCSETUP_RT_DESCS_REG    # registered rt descrips
			#
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
				scsetup_get_registered_rstypes "nonet"
			else
				set -A SCSETUP_RT_NAMES_REG
				set -A SCSETUP_RT_DESCS_REG

				# Set some debug resource types
				SCSETUP_RT_NAMES_REG[0]=SUNW.reg_Debug3
				SCSETUP_RT_NAMES_REG[1]=SUNW.reg_Debug4
				SCSETUP_RT_DESCS_REG[0]="reg_Debug3"
				SCSETUP_RT_DESCS_REG[1]="reg_Debug4"
			fi

			# Get the list of in-use resource types
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
				rslist="$(scsetup_get_rslist)"
				inuse_rstypes=
				for rsname in ${rslist}
				do
					rstype="$(${SCHA_RS_GET} -R ${rsname} -O type)"
					for foo in ${inuse_rstypes}
					do
						if [[ "${rstype}" == "${foo}" ]]; then
							continue 2
						fi
					done
					inuse_rstypes="${inuse_rstypes} ${rstype}"
				done
			else
				inuse_rstypes="SUNW.reg_Debug4"
			fi
					
			# Create a temp file which lists each unused unreg type
			let index=0
			rm -f ${tmpfile1}
			while [[ -n "${SCSETUP_RT_NAMES_REG[index]}" ]]
			do
				for foo in ${inuse_rstypes}
				do
					if [[ "${SCSETUP_RT_NAMES_REG[index]}" == "${foo}" ]]; then
						((index += 1))
						continue 2
					fi
				done
				unreg_rstypes="${unreg_rstypes} ${SCSETUP_RT_NAMES_REG[index]}"
				printf "%-20s %-43.43s" "${SCSETUP_RT_NAMES_REG[index]}" "${SCSETUP_RT_DESCS_REG[index]}"
				if [[ ${#SCSETUP_RT_DESCS_REG[index]} -gt 43 ]]; then
					echo " ...\c"
				fi
				echo
				
				((index += 1))
			done >${tmpfile1}

		fi

		# Sort the tmpfile created above
		rm -f ${tmpfile1_sorted}
		sort ${tmpfile1} >${tmpfile1_sorted}
		rm -f ${tmpfile1}

		# Initialize headers
		header1="$(printf "%-20s %-43.43s" "$(gettext 'Resource Type')" "$(gettext 'Description')")"
		header2="$(printf "%-20s %-43.43s" "$(gettext '=============')" "$(gettext '===========')")"

		case ${task} in
		registerall)		# Register all resource types

			# Print help
			sc_print_para "$(printf "$(gettext 'This option allows you to register all resource types which have %s files (see %s) in %s, but are not yet registered.')" "rt_reg" "rt_reg(4)" "/usr/cluster/lib/rgm/rtreg")"

			# Anything to register?
			if [[ ! -s "${tmpfile1_sorted}" ]]; then
				printf "$(gettext 'There are no unregistered resource types in %s.')\n\n\a" "/usr/cluster/lib/rgm/rtreg"
				sc_prompt_pause
				continue
			fi

			# Print list
			(
				sc_print_para "$(gettext 'The following resource types are unregistered:')"
				printf "%11.11s%s\n" "" "${header1}"
				printf "%11.11s%s\n" "" "${header2}"
				echo
				while read line
				do
					printf "%11.11s%s\n" "" "${line}"
				done <${tmpfile1_sorted}
				echo
			) | more -15

			# Okay to register?
			answer=$(sc_prompt_yesno "$(gettext 'Is it okay to register all of these?')" "${YES}") || continue
			if [[ "${answer}" != "yes" ]]; then
				continue
			fi

			# Set rstypes
			rstypes="${SCSETUP_RT_NAMES_UNREG[*]}"
			;;

		register)		# Register selected resource types

			# Print help
			sc_print_para "$(printf "$(gettext 'This option allows you to register resource types which are not yet registered, but which have %s files (see %s) in %s.')" "rt_reg" "rt_reg(4)" "/usr/cluster/lib/rgm/rtreg")"

			# Anything to register?
			if [[ ! -s "${tmpfile1_sorted}" ]]; then
				printf "$(gettext 'There are no unregistered resoure types in %s.')\n\n\a" "/usr/cluster/lib/rgm/rtreg"
				sc_prompt_pause
				continue
			fi

			# Get the resource types
			prompt="$(gettext 'Select the resource type(s) you want to register:')"
			rstypes="$(
			    sc_get_scrolling_menuoptions	\
				"${prompt}"			\
				"${header1}"			\
				"${header2}"			\
				0 0 1				\
				:${tmpfile1_sorted}		\
			)"
			rm -f ${tmpfile1_sorted}
			if [[ -z "${rstypes}" ]]; then
				continue
			fi

			# Print the list and verify
			(
				sc_print_para "$(gettext 'This is the list of resource types you selected for registration:')"
				for rstype in ${rstypes}
				do
					printf "\t${rstype}\n"
				done
				echo
			) | more

			# Okay to register?
			answer=$(sc_prompt_yesno "$(gettext 'Is it okay to register these?')" "${YES}") || continue
			if [[ "${answer}" != "yes" ]]; then
				continue
			fi
			;;

		unregister)		# Unegister selected resource types

			# Print help
			sc_print_para "$(gettext 'This option allows you to unregister resource types which are not already in use by resources.')"

			# Anything to unregister?
			if [[ -z "${SCSETUP_RT_NAMES_REG[0]}" ]]; then
				printf "$(gettext 'There are no registered resoure types to unregister.')\n\n\a"
				sc_prompt_pause
				continue
			fi
			if [[ ! -s "${tmpfile1_sorted}" ]]; then
				printf "$(gettext 'All registered resource types are in use by resources.')\n\n\a"
				sc_prompt_pause
				continue
			fi

			# Get the resource types
			prompt="$(gettext 'Select the resource type(s) you want to unregister:')"
			rstypes="$(
			    sc_get_scrolling_menuoptions	\
				"${prompt}"			\
				"${header1}"			\
				"${header2}"			\
				0 0 1				\
				:${tmpfile1_sorted}		\
			)"
			rm -f ${tmpfile1_sorted}
			if [[ -z "${rstypes}" ]]; then
				continue
			fi

			# Print the list and verify
			(
				sc_print_para "$(gettext 'This is the list of resource types you selected to unregister:')"
				for rstype in ${rstypes}
				do
					printf "\t${rstype}\n"
				done
				echo
			) | more

			# Okay to unregister?
			answer=$(sc_prompt_yesno "$(gettext 'Is it okay to unregister these?')" "${YES}") || continue
			if [[ "${answer}" != "yes" ]]; then
				continue
			fi
			;;

		unregisterall)		# Unregister all resource types

			# Print help
			sc_print_para "$(gettext 'This option allows you to unregister all resource types which are not already in use by resources.')"

			# Anything to unregister?
			if [[ -z "${SCSETUP_RT_NAMES_REG[0]}" ]]; then
				printf "$(gettext 'There are no registered resoure types to unregister.')\n\n\a"
				sc_prompt_pause
				continue
			fi
			if [[ ! -s "${tmpfile1_sorted}" ]]; then
				printf "$(gettext 'All registered resource types are in use by resources.')\n\n\a"
				sc_prompt_pause
				continue
			fi

			# Print list
			(
				sc_print_para "$(gettext 'The following resource types are registered, but not used:')"
				printf "%11.11s%s\n" "" "${header1}"
				printf "%11.11s%s\n" "" "${header2}"
				echo
				while read line
				do
					printf "%11.11s%s\n" "" "${line}"
				done <${tmpfile1_sorted}
				echo
			) | more -15

			# Okay to unregister?
			answer=$(sc_prompt_yesno "$(gettext 'Is it okay to unregister all of these?')" "${YES}") || continue
			if [[ "${answer}" != "yes" ]]; then
				continue
			fi

			# Set rstypes
			rstypes="${unreg_rstypes}"
			;;

		esac

		# Run the commands
		if [[ ${task} == "register" ]] ||
		    [[ ${task} == "registerall" ]]; then

			# Initialize the command set
			let index=0
			set -A SCSETUP_DO_CMDSET
			for rstype in ${rstypes}
			do
				SCSETUP_DO_CMDSET[index]="${SC_SCRGADM} -a -t ${rstype}"
				((index += 1))
			done

			# Do it, without re-confirming
			scsetup_do_cmdset 1 || continue

		elif [[ ${task} == "unregister" ]] ||
		    [[ ${task} == "unregisterall" ]]; then

			# Initialize the command set
			let index=0
			set -A SCSETUP_DO_CMDSET
			for rstype in ${rstypes}
			do
				SCSETUP_DO_CMDSET[index]="${SC_SCRGADM} -r -t ${rstype}"
				((index += 1))
			done

			# Do it, without re-confirming
			scsetup_do_cmdset 1 || continue
		fi

		# Done
		break
	done

	return 0
}

#####################################################
#
# scsetup_menu_rgm_rg_change_nodelist () rgname [help_only] [nohelp]
#
#	rgname		- name of the resource group to change.  If
#			    "help_only" is given, the rgname may be null.
#
#	help_only	- if this flag is given, just print the
#			    help message
#
#	nohelp		- if this flag is given, do not
#			    clear screen, print title, print help,
#			    or ask for confirmation to continue
#
#	Change the Nodelist property of a resource group.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_rgm_rg_change_nodelist()
{
	typeset rgname=${1}
	typeset help_only=${2}
	typeset nohelp=${3}

	typeset sctxt_title="$(gettext '
		>>> Change the Nodelist Resource Group Property <<<
	')"
	typeset sctxt_p1="$(gettext '
		The Nodelist of a resource group is an ordered list of
		nodes capable of mastering that group.  These nodes are
		the potential primaries for a resource group.  You can
		add nodes to a list, remove nodes from a list, or
		change the order of nodes in a list.
	')"
	typeset sctxt_remove1_p1="$(gettext '
		A node can only be removed from the Nodelist of a resource
		group as long as that node is not online for the group.
	')"
	typeset sctxt_remove2_p1="$(gettext '
		A node can only be removed from the Nodelist of a resource
		group as long as that node is not online for the group.
		Also, a node cannot be removed from the Nodelist if it would
		cause the node count to drop below the Desired_primaries
		setting.
	')"

	typeset sctxt_prompt_operation="$(printf "$(gettext 'Select the type of change you want to make to the %s:')" "Nodelist")"
	typeset sctxt_option_operation_001="$(printf "$(gettext 'Add a node to the top of the %s')" "Nodelist")"
	typeset sctxt_option_operation_002="$(printf "$(gettext 'Add a node to the bottom of the %s')" "Nodelist")"
	typeset sctxt_option_operation_003="$(printf "$(gettext 'Move a node to the top of the %s')" "Nodelist")"
	typeset sctxt_option_operation_004="$(printf "$(gettext 'Move a node to the bottom of the %s')" "Nodelist")"
	typeset sctxt_option_operation_005="$(printf "$(gettext 'Reorder all of the nodes in the %s')" "Nodelist")"
	typeset sctxt_option_operation_006="$(printf "$(gettext 'Remove a node from the %s')" "Nodelist")"
	typeset sctxt_option_operation_007="$(printf "$(gettext 'Swap the order of the two nodes in the %s')" "Nodelist")"
	typeset sctxt_option_done="$(gettext 'Done')"

	typeset rgstatefile=${SCSETUP_TMP_RGSTATE}

	typeset prompt
	typeset answer
	typeset rgnodelist
	typeset original_rgnodelist
	typeset clnodelist
	typeset nodelist
	typeset node
	typeset -l lrgstate			# lower case
	typeset option
	typeset task
	typeset foo
	typeset foo2

	integer rgnodelistcount
	integer clnodelistcount
	integer dprimaries
	integer changed
	integer i
	integer j

	# Unless nohelp is specified, print help
	if [[ -z "${nohelp}" ]] && [[ -z "${help_only}" ]]; then

		# Clear screen, print title
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"

		# Okay to continue?
		scsetup_continue || return 1

	elif [[ -n "${help_only}" ]]; then
		sc_print_para "${sctxt_p1}"
		return 0
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Get and list the Nodelist
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			rgnodelist="$(${SCHA_RG_GET} -G ${rgname} -O nodelist)"
			clnodelist="$(scsetup_get_nodelist)"
		else
			# Debug nodes in the RG nodelist
			let i=0
			let j=0
			rgnodelist=
			answer=$(sc_prompt "DEBUG:  How many nodes in the RG nodelist?")
			if [[ -n "${answer}" ]]; then
				let i=${answer}
			fi
			while [[ $j -lt $i ]]
			do
				((j += 1))
				rgnodelist="${rgnodelist} node${j}"
			done

			# Debug nodes in the cluster
			let i=0
			let j=0
			clnodelist=
			answer=$(sc_prompt "DEBUG:  How many nodes in the cluster?")
			if [[ -n "${answer}" ]]; then
				let i=${answer}
			fi
			while [[ $j -lt $i ]]
			do
				((j += 1))
				clnodelist="${clnodelist} node${j}"
			done
		fi
		rgnodelist=$(echo ${rgnodelist})
		original_rgnodelist="${rgnodelist}"
		clnodelist=$(echo ${clnodelist})
		clnodelistcount=$(set -- ${clnodelist}; echo $#)
		let changed=0

		# Loop until we have a complete Nodelist 
		while true
		do
			# Show the nodelist
			task=
			rgnodelistcount=$(set -- ${rgnodelist}; echo $#)
			case ${rgnodelistcount} in
			0)	# Error - No nodes in the nodelist

				echo
				printf "$(gettext 'The %s for \"%s\" is unexpectedly empty.')\n" "Nodelist" "${rgname}"
				printf "$(gettext 'Use the \"%s\" command to correct the problem.')\n\n\a" "scrgadm"
				sc_prompt_pause
				return 1
				;;

			1)	# Just one node in the nodelist

				echo
				sc_print_para "$(printf "$(gettext 'There is only one node in the %s:')" "Nodelist")"
				printf "\t${rgnodelist}\n"
				echo

				# Any nodes to add?
				if [[ ${clnodelistcount} -lt 2 ]]; then
					printf "$(gettext 'And, there are no nodes to add.')\n\n\a"
					sc_prompt_pause
					return 1
				fi

				# Add?
				option=$(sc_get_menuoption \
					"T2+++${sctxt_prompt_operation}" \
					"S+0+1+${sctxt_option_operation_001}" \
					"S+0+2+${sctxt_option_operation_002}" \
					"R+++" \
					"S+0+q+${sctxt_option_done}" \
				)
				case ${option} in
				1)	task="addt"	;;
				2)	task="addb"	;;
				*)	task="quit" ;;
				esac
				;;

			2)	# Just two nodes in the nodelist

				echo
				sc_print_para "$(printf "$(gettext 'The following two nodes are in the %s:')" "Nodelist")"
				for node in ${rgnodelist}
				do
					printf "\t${node}\n"
				done
				echo

				# Add/swap/remove?
				if [[ ${clnodelistcount} -gt ${rgnodelistcount} ]]; then
					# Add/swap/remove?
					option=$(sc_get_menuoption \
					"T2+++${sctxt_prompt_operation}" \
					"S+0+1+${sctxt_option_operation_001}" \
					"S+0+2+${sctxt_option_operation_002}" \
					"S+0+3+${sctxt_option_operation_007}" \
					"S+0+4+${sctxt_option_operation_006}" \
					"R+++" \
					"S+0+q+${sctxt_option_done}" \
					)
					case ${option} in
					1)	task="addt"	;;
					2)	task="addb"	;;
					3)	task="swap"	;;
					4)	task="remove"	;;
					*)	task="quit" ;;
					esac
				else
					# Swap/remove?
					option=$(sc_get_menuoption \
					"T2+++${sctxt_prompt_operation}" \
					"S+0+1+${sctxt_option_operation_007}" \
					"S+0+2+${sctxt_option_operation_006}" \
					"R+++" \
					"S+0+q+${sctxt_option_done}" \
					)
					case ${option} in
					1)	task="swap"	;;
					2)	task="remove"	;;
					*)	task="quit" ;;
					esac
				fi
				;;

			*)	# More than two nodes in the rgnodelist

				# Print the nodelist, if not yet changed
				if [[ ${changed} -eq 0 ]]; then
					(
						echo
						sc_print_para "$(printf "$(gettext 'Here is the ordered list of nodes in the %s for \"%s\":')" "Nodelist" "${rgname}")"
						for node in ${rgnodelist}
						do
							printf "\t${node}\n"
						done
						echo
					) | more
				fi

				# Add/remove/change?
				if [[ ${clnodelistcount} -gt ${rgnodelistcount} ]]; then
					# Add/remove/change?
					option=$(sc_get_menuoption \
					"T2+++${sctxt_prompt_operation}" \
					"S+0+1+${sctxt_option_operation_001}" \
					"S+0+2+${sctxt_option_operation_002}" \
					"S+0+3+${sctxt_option_operation_003}" \
					"S+0+4+${sctxt_option_operation_004}" \
					"S+0+5+${sctxt_option_operation_005}" \
					"S+0+6+${sctxt_option_operation_006}" \
					"R+++" \
					"S+0+q+${sctxt_option_done}" \
					)
					case ${option} in
					1)	task="addt"	;;
					2)	task="addb"	;;
					3)	task="movet"	;;
					4)	task="moveb"	;;
					5)	task="reorder"	;;
					6)	task="remove"	;;
					*)	task="quit" ;;
					esac
				else
					# Remove/change?
					option=$(sc_get_menuoption \
					"T2+++${sctxt_prompt_operation}" \
					"S+0+1+${sctxt_option_operation_003}" \
					"S+0+2+${sctxt_option_operation_004}" \
					"S+0+3+${sctxt_option_operation_005}" \
					"S+0+4+${sctxt_option_operation_006}" \
					"R+++" \
					"S+0+q+${sctxt_option_done}" \
					)
					case ${option} in
					1)	task="movet"	;;
					2)	task="moveb"	;;
					3)	task="reorder"	;;
					4)	task="remove"	;;
					*)	task="quit" ;;
					esac
				fi
				;;
			esac

			# Do it
			case ${task} in
			addt|addb)
				# Get the list of all cluster nodes
				if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
					foo="$(scsetup_get_nodelist)"
				else
					foo="node1 node2 node3 node4 node5 node6"
				fi 
	
				# Set "nodelist" to those not in "rgnodelist"
				nodelist=
				for node in ${foo}
				do
					for foo2 in ${rgnodelist}
					do
						if [[ "${node}" == "${foo2}" ]]; then
							continue 2
						fi
					done
					nodelist="${nodelist} ${node}"
				done
				nodelist=$(echo ${nodelist})

				# Available nodes left?
				if [[ -z "${nodelist}" ]]; then
					echo
					printf "$(gettext 'The %s for \"%s\" already includes all cluster nodes.')\n\n\a" "Nodelist" "${rgname}"
					sc_prompt_pause
					continue
				fi

				# Get the name of the node to add
				prompt="$(gettext 'Select the name of the node you want to add:')"
				node="$(
				    sc_get_scrolling_menuoptions	\
					"${prompt}"			\
					"" ""				\
					0 1 1				\
					${nodelist}			\
				)"
				if [[ -z "${node}" ]]; then
					return 1
				fi

				# Add it to the rgnodelist
				if [[ "${task}" == "addt" ]]; then
					rgnodelist="${node} ${rgnodelist}"
				else
					rgnodelist="${rgnodelist} ${node}"
				fi
				;;

			movet|moveb)

				# Get the name of the node to move
				if [[ "${task}" == "movet" ]]; then
					prompt="$(gettext 'Select the name of the node to move to the top of the list:')"
				else
					prompt="$(gettext 'Select the name of the node to move to the bottom of the list:')"
				fi

				node="$(
				    sc_get_scrolling_menuoptions	\
					"${prompt}"			\
					"" ""				\
					0 1 1				\
					${rgnodelist}			\
				)"
				if [[ -z "${node}" ]]; then
					return 1
				fi

				# Update the rgnodelist
				nodelist=
				for foo in ${rgnodelist}
				do
					if [[ "${node}" != "${foo}" ]]; then
						nodelist="${nodelist} ${foo}"
					fi
				done
				if [[ "${task}" == "movet" ]]; then
					nodelist="${node} ${nodelist}"
				else
					nodelist="${nodelist} ${node}"
				fi
				rgnodelist=$(echo ${nodelist})
				;;

			swap)
				# Swap the two nodes in the list
				nodelist=
				for node in ${rgnodelist}
				do
					nodelist="${node} ${nodelist}"
				done
				rgnodelist=$(echo ${nodelist})
				;;

			reorder)

				# Get the new list
				prompt="$(gettext 'Select all of the nodes in the desired order:')"

				while true
				do
					nodelist="$(
					    sc_get_scrolling_menuoptions \
						"${prompt}"		\
						"" ""			\
						${rgnodelistcount}	\
						${rgnodelistcount}	\
						1			\
						${rgnodelist}		\
					)"
					if [[ -z "${nodelist}" ]]; then
						return -1
					fi

					# Print the list and verify that
					# it is correct
					(
						echo
						sc_print_para "$(gettext 'This is the ordered list of nodes you entered:')"
						for node in ${nodelist}
						do
							printf "\t${node}\n"
						done
						echo
					) | more

					# Verify
					answer=$(sc_prompt_yesno "$(gettext 'Is it correct?')" "${YES}") || return 1                  
					if [[ "${answer}" == "yes" ]]; then
						break
					fi
				done

				# Update the rgnodelist
				rgnodelist=$(echo ${nodelist})
				;;

			remove)

				# Get desired primaries
				if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
					dprimaries="$(${SCHA_RG_GET} -G ${rgname} -O desired_primaries)"
				else
					let dprimaries=1
				fi

				# Print help
				if [[ ${dprimaries} -lt 2 ]]; then
					sc_print_para "${sctxt_remove1_p1}"
				else
					sc_print_para "${sctxt_remove2_p1}"
				fi

				# Get the list of offline nodes
				nodelist=
				scsetup_create_rgstatefile ${rgstatefile}
				for node in ${rgnodelist}
				do
					lrgstate=$(scsetup_get_rgstate ${rgname} ${rgstatefile} "" ${node})
					if [[ "${lrgstate}" == "offline" ]] ||
					    [[ "${lrgstate}" == "unmanaged" ]]; then
						nodelist="${nodelist} ${node}"
					fi
				done
				scsetup_rm_rgstatefile ${rgstatefile}

				# Make sure at least one node is offline
				if [[ -z "${nodelist}" ]]; then
					echo
					printf "$(gettext '\"%s\" is not offline on any of the nodes.')\n" "${rgname}"
					printf "$(gettext 'A node cannot be removed from the %s while still online for the group.')\n\n\a" "Nodelist"
					sc_prompt_pause
					continue
				fi

				# We can't drop below desired_primaries
				if [[ ${rgnodelistcount} -le ${dprimaries} ]]; then
					echo
					printf "$(gettext 'The %s property is set to %d.')\n" "Desired_primaries" ${dprimaries}
					printf "$(gettext 'And, there are only %d nodes in the %s'.)\n" ${rgnodelistcount} "Nodelist"
					printf "$(gettext 'Therefore, it is not possible to remove a node from the %s'.)\n" "Nodelist"
					echo
					printf "$(gettext 'The %s resource group property can be changed using %s'.)\n\n\a" "Desired_primaries" "scrgadm(1M)"
					sc_prompt_pause
					continue
				fi

				# Get the name of the node to remove
				prompt="$(gettext 'Select the name of the node to remove from the list:')"
				node="$(
				    sc_get_scrolling_menuoptions	\
					"${prompt}"			\
					"" ""				\
					0 1 1				\
					${nodelist}			\
				)"
				if [[ -z "${node}" ]]; then
					return 1
				fi

				# Update the rgnodelist
				nodelist=
				for foo in ${rgnodelist}
				do
					if [[ "${node}" != "${foo}" ]]; then
						nodelist="${nodelist} ${foo}"
					fi
				done
				rgnodelist=$(echo ${nodelist})
				;;

			quit)
				if [[ ${changed} -eq 0 ]]; then
					return 0
				fi
				;;

			esac

			# Print the nodelist and update, if changed
			if [[ "${rgnodelist}" != "${original_rgnodelist}" ]];  then
				((changed += 1))
			fi

			# Changes (either now or earlier), print list and update
			if [[ ${changed} -ne 0 ]]; then

				# Print the list
				(
					echo
					sc_print_para "$(printf "$(gettext 'Here is the new %s for \"%s\":')" "Nodelist" "${rgname}")"
					for node in ${rgnodelist}
					do
						printf "\t${node}\n"
					done
					echo
				) | more

				# Maybe they want to abort without a commit
				if [[ "${task}" == "quit" ]]; then
					prompt="$(printf "$(gettext 'Do you want to quit without updating the %s?')" "Nodelist")"
					answer=$(sc_prompt_yesno "${prompt}" "${NO}") || continue
					if [[ "${answer}" == "yes" ]]; then
						continue 2
					fi
				fi

				# Okay to continue?
				prompt="$(printf "$(gettext 'Are you ready to update the %s property now?')" "Nodelist")"
				answer=$(sc_prompt_yesno "${prompt}" "${YES}") || continue
				if [[ "${answer}" != "yes" ]]; then
					continue
				fi

				# Construct the new list
				nodelist=
				for node in ${rgnodelist}
				do
					if [[ -z "${nodelist}" ]]; then
						nodelist=${node}
					else
						nodelist="${nodelist},${node}"
					fi
				done

				# Initialize command set
				set -A SCSETUP_DO_CMDSET

				# Set nodelist
				SCSETUP_DO_CMDSET[0]="${SC_SCRGADM} -c -g ${rgname} -h ${nodelist}"

				# Doit
				scsetup_do_cmdset 1 

				# Done with this RG
				continue 2
			fi
		done
	done
	
	return 0
}

#####################################################
#
# scsetup_menu_rgm_rg_change_rgdescription () rgname [help_only] [nohelp]
#
#	rgname		- name of the resource group to change.  If
#			    "help_only" is given, the rgname may be null.
#
#	help_only	- if this flag is given, just print the
#			    help message
#
#	nohelp		- if this flag is given, do not
#			    clear screen, print title, print help,
#			    or ask for confirmation to continue
#
#	Change the RG_Description property of a resource group.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_rgm_rg_change_rgdescription()
{
	typeset rgname=${1}
	typeset help_only=${2}
	typeset nohelp=${3}

	typeset sctxt_title="$(gettext '
		>>> Change the RG_description Resource Group Property <<<
	')"
	typeset sctxt_p1="$(gettext '
		The RG_description property of a resource group is a
		user-defined description of the group.  Use the
		RG_description menu option to change that description.
	')"

	typeset cachefile=${SCSETUP_RGM_CACHEFILE}

	typeset prompt
	typeset answer
	typeset rgdescription

	integer isset

	# Unless nohelp is specified, print help
	if [[ -z "${nohelp}" ]] && [[ -z "${help_only}" ]]; then

		# Clear screen, print title
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"

		# Okay to continue?
		scsetup_continue || return 1

	elif [[ -n "${help_only}" ]]; then
		sc_print_para "${sctxt_p1}"
		return 0
	fi


	# Loop until done or Ctrl-D is typed
	while true
	do
		let isset=0

		# Get the RG_description
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] ||
		    [[ -r "${cachefile}" ]]; then
			rgdescription="$(scsetup_get_rgdescription "${rgname}" ${cachefile})"
		else
			rgdescription="DEBUG:  this is a description"
		fi

		# Print the current description
		echo
		if [[ -n "${rgdescription}" ]]; then
			let isset=1
			sc_print_para "$(printf "$(gettext 'The %s property for \"%s\" is currently set to the following:')" "RG_description" "${rgname}")"
			sc_print_prompt "$(gettext 'Description:')"
			echo "${rgdescription}"
			echo
		else
			sc_print_para "$(printf "$(gettext 'The %s property for \"%s\" is currently not set.')" "RG_description" "${rgname}")"
		fi

		# Get the new description
		sc_print_para "$(gettext 'Enter the new description.')"
		sc_print_prompt "$(gettext 'Description:')"
		read rgdescription || continue
		echo

		# If no description, confirm clearing it
		if [[ -z "${rgdescription}" ]]; then
			if [[ ${isset} -eq 0 ]]; then
				prompt="$(gettext 'Are you sure you do not want to set the description?')"
				answer=$(sc_prompt_yesno "${prompt}" "${YES}") || return 0
			else
				prompt="$(gettext 'Are you sure you want to clear the description?')"
				answer=$(sc_prompt_yesno "${prompt}" "${NO}") || return 0
			fi
			if [[ "${answer}" != "yes" ]]; then
				continue
			elif [[ ${isset} -eq 0 ]]; then
				return 0
			fi
		fi

		# Initialize command set
		set -A SCSETUP_DO_CMDSET

		# Set nodelist
		SCSETUP_DO_CMDSET[0]="${SC_SCRGADM} -c -g ${rgname} -y RG_description=\"${rgdescription}\""

		# Doit
		scsetup_do_cmdset

		# Done
		break
	done

	return 0
}

#####################################################
#
# scsetup_menu_rgm_rg_change_pathprefix () rgname [help_only] [nohelp]
#
#	rgname		- name of the resource group to change.  If
#			    "help_only" is given, the rgname may be null.
#
#	help_only	- if this flag is given, just print the
#			    help message
#
#	nohelp		- if this flag is given, do not
#			    clear screen, print title, print help,
#			    or ask for confirmation to continue
#
#	Change the pathprefix property of a resource group.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_rgm_rg_change_pathprefix()
{
	typeset rgname=${1}
	typeset help_only=${2}
	typeset nohelp=${3}

	typeset sctxt_title="$(gettext '
		>>> Change the Pathprefix Resource Group Property <<<
	')"
	typeset sctxt_p1="$(gettext '
		The Pathprefix property of a resource group specifies a
		directory in a global file system that resources in the
		group can use for essential administrative files and
		other data.   Some types of resource (for example, HA
		for NFS) require a valid Pathprefix property setting.
		Use the Pathprefix menu option to change the Pathprefix
		property of a resource group.
	')"

	typeset cachefile=${SCSETUP_RGM_CACHEFILE}

	typeset prompt
	typeset answer
	typeset rgpathprefix
	typeset foo

	integer isset

	# Unless nohelp is specified, print help
	if [[ -z "${nohelp}" ]] && [[ -z "${help_only}" ]]; then

		# Clear screen, print title
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"

		# Okay to continue?
		scsetup_continue || return 1

	elif [[ -n "${help_only}" ]]; then
		sc_print_para "${sctxt_p1}"
		return 0
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		let isset=0

		# Get the Pathprefix
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] ||
		    [[ -r "${cachefile}" ]]; then
			rgpathprefix="$(scsetup_get_rgpathprefix "${rgname}" ${cachefile})"
		else
			rgpathprefix=
		fi

		# Print the current Pathprefix
		echo
		if [[ -n "${rgpathprefix}" ]]; then
			let isset=1
			sc_print_para "$(printf "$(gettext 'The %s property for \"%s\" is currently set to the following:')" "Pathprefix" "${rgname}")"
			sc_print_prompt "$(gettext 'Pathprefix:')"
			echo "${rgpathprefix}"
			echo
		else
			sc_print_para "$(printf "$(gettext 'The %s property for \"%s\" is currently not set.')" "Pathprefix" "${rgname}")"
		fi

		# Get the new Pathprefix
		while true
		do
			sc_print_prompt "$(gettext 'What is the name of the new \"Pathprefix\" directory?')"
			read rgpathprefix foo || continue 2
			echo

			# If not set, confirm clearing it
			if [[ -z "${rgpathprefix}" ]]; then
				if [[ ${isset} -eq 0 ]]; then
					prompt="$(gettext 'Are you sure you do not want to set the the \"Pathprefix\"?')"
					answer=$(sc_prompt_yesno "${prompt}" "${YES}") || return 0
				else
					prompt="$(gettext 'Are you sure you want to clear the \"Pathprefix\"?')"
					answer=$(sc_prompt_yesno "${prompt}" "${NO}") || return 0
				fi
				if [[ "${answer}" != "yes" ]]; then
					continue 2
				elif [[ ${isset} -eq 0 ]]; then
					return 0
				else
					break
				fi
			fi

			# Make sure it is just one word
			if [[ -n "${foo}" ]]; then
				echo "\a\c"
				continue
			fi

			# Make sure it starts with "/"
			if [[ "${rgpathprefix}" != /* ]]; then
				printf "$(gettext 'The name of the directory must begin with /.')\n\n\a"
				continue
			fi

			# Make sure it exists
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] &&
			    [[ ! -d "${rgpathprefix}" ]]; then
				printf "$(gettext 'Directory not found - %s.')\n\n\a" "${rgpathprefix}"
				continue
			fi

			# Done
			break
		done

		# Initialize command set
		set -A SCSETUP_DO_CMDSET

		# Set nodelist
		SCSETUP_DO_CMDSET[0]="${SC_SCRGADM} -c -g ${rgname} -y Pathprefix=\"${rgpathprefix}\""

		# Doit
		scsetup_do_cmdset

		# Done
		break
	done

	return 0
}

#####################################################
#
# scsetup_get_rg_changeproperties_menuoption()
#
#	Print the resource group change-properties menu, and return
#	the selected option.
#
#	This function always returns zero.
#	
#####################################################
scsetup_get_rg_changeproperties_menuoption()
{
	typeset sctxt_title_2="$(gettext 'Select the property you want to change:')"
	typeset sctxt_option_001="Nodelist"
	typeset sctxt_option_002="RG_description"
	typeset sctxt_option_003="Pathprefix"
	typeset sctxt_option_help="$(gettext 'Help')"
	typeset sctxt_option_return="$(gettext 'Return to the resource group menu')"

	typeset option

	# Return
	option=$(sc_get_menuoption \
		"T2+++${sctxt_title_2}" \
		"S+0+1+${sctxt_option_001}" \
		"S+0+2+${sctxt_option_002}" \
		"S+0+3+${sctxt_option_003}" \
		"R+++" \
		"S+0+?+${sctxt_option_help}" \
		"S+0+q+${sctxt_option_return}" \
	)

	echo "${option}"

	return 0
}

#####################################################
#
# scsetup_menu_rgm_rg_changeproperties() [nohelp]
#
#	nohelp		- if this flag is given, do not
#			    clear screen, print title, print help,
#			    or ask for confirmation to continue
#
#	Change the selected properties of a resource group.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_rgm_rg_changeproperties()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Change Properties of a Resource Group <<<
	')"
	typeset sctxt_title_help="$(gettext '
		*** Help Screen - Change Properties of a Resource Group ***
	')"
	typeset sctxt_p1="$(gettext '
		Use this option to change certain properties of a
		resource group.   These properties are the resource
		group Nodelist, RG_description, and Pathprefix.  Other
		resource group properties can be changed using scrgadm(1M).
	')"

	typeset rgname
	typeset rglist
	typeset prompt

	# Unless nohelp is specified, print help and get confirmation
	if [[ -z "${nohelp}" ]]; then

		# Clear screen, print title and help
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Get the complete list of resource groups
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
		rglist="$(scsetup_get_rglist)"
	else
	    	rglist="rg1 rg2 rg3 rg4"
	fi

	# Make sure we have at least one group
	if [[ -z "${rglist}" ]]; then
		echo
		printf "$(gettext 'There are no resource groups configured.')\n\n\a"
		sc_prompt_pause
		break
	fi

	# Get the name of the group to change
	prompt="$(gettext 'Select the group whose property you want to change:')"
	rgname="$(
	    sc_get_scrolling_menuoptions	\
		"${prompt}"			\
		"" ""				\
		0 1 1				\
		${rglist}			\
	)"
	if [[ -z "${rgname}" ]]; then
		return 0
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Get the menu option
		case $(scsetup_get_rg_changeproperties_menuoption) in
		'1')	scsetup_menu_rgm_rg_change_nodelist ${rgname} ;;
		'2')	scsetup_menu_rgm_rg_change_rgdescription ${rgname} ;;
		'3')	scsetup_menu_rgm_rg_change_pathprefix ${rgname} ;;

		'?')	# Help
			clear
			(
				sc_print_title "${sctxt_title_help}"
				scsetup_menu_rgm_rg_change_nodelist "" "help"
				scsetup_menu_rgm_rg_change_rgdescription "" "help"
				scsetup_menu_rgm_rg_change_pathprefix "" "help"
			) | more
			sc_prompt_pause
			continue
			;;

		'q')	break ;;
		esac

		# Done
		break
	done

	return 0
}

#####################################################
#
# scsetup_menu_rgm_rg_delete() [delete] [nohelp]
#
#	nohelp		- if this flag is given, do not
#			    clear screen, print title, print help,
#			    or ask for confirmation to continue
#
#	Delete a resource group.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_rgm_rg_delete()
{
	typeset delete=${1}
	typeset nohelp=${2}

	typeset sctxt_title="$(gettext '
		>>> Remove a Resource Group <<<
	')"
	typeset sctxt_p1="$(gettext '
		Use this option to remove a resource group from the
		cluster.
	')"
	typeset sctxt_p2="$(gettext '
		Before a resource group can be deleted, all resources
		within that group must first be disabled and removed.
		Once any resource is removed, that resource is no
		longer available to clients.  Clients who depend on
		those resources will experience a loss of service.
	')"
	typeset sctxt_netdeps_p1="$(gettext '
		One or more of the network resources in this group are
		explicitly depended upon by the following resource(s):
	')"
	typeset sctxt_netdeps_p2="$(gettext '
		It is not possible to remove a resource for which
		explicit network dependencies exist.  In turn, it
		is not possible to modify the \"Network_resources_used\"
		property of a resource after that resource has been created.
		The only way to remove these dependencies is to remove the
		resources which make use of them.
	')"

	typeset tmpfile=${SCSETUP_TMP_RGLIST}
	typeset cachefile=${SCSETUP_RGM_CACHEFILE}

	typeset answer
	typeset prompt
	typeset prompt2
	typeset rglist
	typeset rgname
	typeset rgdes
	typeset online_nodelist
	typeset rslist
	typeset sorted_list
	typeset resource
	typeset resource2
	typeset deps
	typeset netdeps
	typeset foo
	typeset list
	typeset newlist
	typeset item

	integer commands=0
	integer index
	integer found
	integer count

	# Unless nohelp is specified, print help and get confirmation
	if [[ -z "${delete}" ]] && [[ -z "${nohelp}" ]]; then

		# Clear screen, print title and help
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Initialize
	prompt="$(gettext 'Select the resource group you want to remove:')"
	header1="$(printf "%-20s %-40.40s" "$(gettext 'Group Name')" "$(gettext 'Description')")"
	header2="$(printf "%-20s %-40.40s" "$(gettext '==========')" "$(gettext '===========')")"

	# Loop until done or Ctrl-D is typed
	while [[ -z "${delete}" ]]
	do
		# Get the list of resource groups
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] || [[ -r "${cachefile}" ]];  then
			rglist="$(scsetup_get_rglist "" "" "" ${cachefile})"
		else
			rglist="rg1 rg2 rg3 rg4 rg5 rg6 rg7 rg8 rg9 rg10 rg11 rg12 rg13 rg14"
		fi

		# Verify that there are some resource groups
		if [[ -z "${rglist}" ]]; then
			echo
			printf "$(gettext 'There are no resource groups configured.')\n"
			printf "$(gettext 'So, there is nothing to remove.')\n\n\a"
			sc_prompt_pause
			return 1
		fi

		# Create a temp file which contains each RG with description
		rm -f ${tmpfile}
		for rgname in ${rglist}
		do
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] ||
			    [[ -r "${cachefile}" ]];  then
				rgdes="$(scsetup_get_rgdescription ${rgname} ${cachefile})"
			else
				rgdes="DEBUG:  this is a description"
			fi
			printf "%-20s %-40.40s" ${rgname} "${rgdes}"
			if [[ ${#rgdes} -gt 40 ]]; then
				echo " ...\c"
			fi
			echo
		done >${tmpfile}

		# Get the name of the group
		rgname="$(
		    sc_get_scrolling_menuoptions	\
			"${prompt}"			\
			"${header1}"			\
			"${header2}"			\
			0 1 1				\
			:${tmpfile}			\
		)"
		rm -f ${tmpfile}
		if [[ -z "${rgname}" ]]; then
			return 0
		fi

		# Confirm
		prompt2="$(printf "$(gettext 'Are you sure you want to remove \"%s\"?')" "${rgname}")"
		answer=$(sc_prompt_yesno "${prompt2}" "${YES}") || return 1
		if [[ "${answer}" == "yes" ]]; then
			delete=${rgname}
		else
			prompt2="$(gettext 'Do you want to select a different group to remove?')"
			answer=$(sc_prompt_yesno "${prompt2}" "${NO}") || return 1
			if [[ "${answer}" != "yes" ]]; then
				return 1
			fi
		fi
	done

	# Get the resource list for this group
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
		rslist="$(${SCHA_RG_GET} -G ${delete} -O resource_list)"
	else
		rslist="${delete}res1 ${delete}res2 ${delete}res3 ${delete}res4"
	fi

	# See if any of the resources in this group have explicit net deps
	netdeps=
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
		for resource in ${rslist}
		do
			netdeps="${netdeps} $(scsetup_get_resource_depended_ons ${resource} "" "true")"
		done
	fi
	netdeps="$(echo ${netdeps})"
	if [[ -n "${netdeps}" ]]; then

		# Weed out the duplicates
		foo=
		for resource in ${netdeps}
		do
			for resource2 in ${foo}
			do
				if [[ "${resource2}" == "${resource}" ]]; then
					continue 2
				fi
			done
			foo="${foo} ${resource}"
		done
		netdeps="$(echo ${foo})"

		# Print the list
		(
			sc_print_para "${sctxt_netdeps_p1}"
			for resource in ${netdeps}
			do
				printf "\t${resource}\n"
			done
			echo
			sc_print_para "${sctxt_netdeps_p2}"
		) | more

		# Confirm
		sc_prompt_pause
		return 1
	fi

	# Disable all enabled resources in this group
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
		scsetup_disable_resources ${delete}
		if [[ $? -ne 0 ]]; then
			printf "$(gettext 'All resources must be disabled before they can be removed.')\n\n\a"
			printf "$(gettext 'And all resources must be removed from \"%s\" before it can be removed.')\n\n\a" "${delete}"
			sc_prompt_pause
			return 1
		fi
		echo
	fi

	#
	# Remove all resources
	#
	for resource in ${rslist}
	do
		# Remove the resource
		scsetup_menu_rgm_rs_delete ${resource}
		if [[ $? -ne 0 ]]; then
			echo
			printf "$(gettext 'All resources must be removed from \"%s\" before it can be removed.')\n\n\a" "${delete}"
			sc_prompt_pause
			return 1
		fi
	done

	# Cleanup RG_dependencies
	set -A SCSETUP_DO_CMDSET
	let index=0
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
		for rgname in ${rglist}
		do
			# We can skip ourselves
			if [[ "${rgname}" == "${delete}" ]]; then
				continue
			fi

			# RG_dependencies
			newlist=
			list="$(${SCHA_RG_GET} -G ${rgname} -O rg_dependencies)"
			let found=0
			for item in ${list}
			do
				if [[ "${item}" == "${delete}" ]]; then
					let found=1
					continue
				fi
				if [[ -n "${newlist}" ]]; then
					newlist="${newlist},"
				fi
				newlist="${newlist}${item}"
			done
			if [[ ${found} -eq 1 ]]; then
				SCSETUP_DO_CMDSET[index]="${SC_SCRGADM} -c -g ${rgname} -y RG_dependencies=${newlist}"
				((index += 1))
			fi

			# RG_affinities
			newlist=
			list="$(${SCHA_RG_GET} -G ${rgname} -O rg_affinities)"
			let found=0
			for item in ${list}
			do
				if [[ "${item}" == "+${delete}" ]]; then
					let found=1
					continue
				fi
				if [[ "${item}" == "++${delete}" ]]; then
					let found=1
					continue
				fi
				if [[ "${item}" == "+++${delete}" ]]; then
					let found=1
					continue
				fi
				if [[ "${item}" == "-${delete}" ]]; then
					let found=1
					continue
				fi
				if [[ "${item}" == "--${delete}" ]]; then
					let found=1
					continue
				fi
				if [[ -n "${newlist}" ]]; then
					newlist="${newlist},"
				fi
				newlist="${newlist}${item}"
			done
			if [[ ${found} -eq 1 ]]; then
				SCSETUP_DO_CMDSET[index]="${SC_SCRGADM} -c -g ${rgname} -y RG_affinities=${newlist}"
				((index += 1))
			fi


		done
	fi
	if [[ ${index} -gt 0 ]]; then
		# increment commands counter
		((commands += index))

		# Do not re-confirm.  Also, ignore return code
		scsetup_do_cmdset 1 1

		# Re-initialize
		set -A SCSETUP_DO_CMDSET
		let index=0
	fi

	# Let's see if the group is still online
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
		online_nodelist="$(scsetup_get_rgstate ${rg} "" "not_offline")"
	else
		online_nodelist=node1
	fi

	# If it is not already offline on all nodes, attempt to bring it offline
	if [[ -n "${online_nodelist}" ]]; then
		# increment commands counter
		((commands += 1))

		# Set up the comand to bring the group offline
		set -A SCSETUP_DO_CMDSET
		SCSETUP_DO_CMDSET[0]="${SC_SCSWITCH} -F -g ${delete}"

		# Do not re-confirm.  Also, ignore return code
		scsetup_do_cmdset 1 1
	fi


	# Add the command to remove the resource group
	SCSETUP_DO_CMDSET[index]="${SC_SCRGADM} -r -g ${delete}"

	# Do it!
	if [[ ${commands} -gt 0 ]]; then
		scsetup_do_cmdset 1 "" ${commands} || return 1
	else
		scsetup_do_cmdset 1 || return 1
	fi

	return 0
}

#####################################################
#
# scsetup_get_rg_online_offline_menuoption() rgname rgstate maxprimaries
#
#	rgname		- name of the resource group
#
#	rgstate		- overall state of the resource group
#
#	maxprimaries	- maximum number of primaries for the resource group
#
#	Print the resource group online-offline menu, and return the
#	selected option.
#
#	If "rgstate" is "unmanaged", the following menu is used:
#
#		1)	Put the group in the managed state
#
#	If "rgstate" is "offline", the following:
#
#		1)	Bring the group online
#		2)	Put the group into an unmanaged state
#
#	If "rgstate" is "error--stop_failed", the following:
#
#		1)	Bring the group offline from all cluster nodes
#
#	If "rgstate" is "online" & "maxprimaries" < 2
#
#		1)	Switch ownership of the group
#		2)	Bring the group offline from all cluster nodes
#		3)	Put the group into an unmanaged state
#
#	If "rgstate" is "online" & "maxprimaries" >= 2
#
#		1)	Change the set of current primaries
#		2)	Bring the group offline from all cluster nodes
#		3)	Put the group into an unmanaged state
#
#	Returned options are:
#
#		1)	Bring the group online
#		2)	Bring the group offline from all cluster nodes
#		3)	Put the group into an unmanaged state
#		4)	Switch ownership of the group
#		5)	Change the set of current primaries
#		6)	Put the group into a managed state
#
#	This function always returns zero.
#
#####################################################
scsetup_get_rg_online_offline_menuoption()
{
	typeset rgname=${1}
	typeset rgstate=${2}
	typeset maxprimaries=${3}

	typeset sctxt_title_2="$(gettext 'Please select from one of the following options:')"
	typeset sctxt_option_managed="$(gettext 'Put the group into a managed state')"
	typeset sctxt_option_unmanaged="$(gettext 'Put the group into an unmanaged state')"
	typeset sctxt_option_switch="$(gettext 'Switch ownership of the group')"
	typeset sctxt_option_change="$(gettext 'Change the set of current primaries')"
	typeset sctxt_option_offline="$(gettext 'Bring the group offline from all cluster nodes')"
	typeset sctxt_option_online="$(gettext 'Bring the group online')"

	typeset sctxt_option_quit="$(gettext 'Quit')"

	typeset option

	case ${rgstate} in
	unmanaged)
		option=$(sc_get_menuoption \
			"T2+++${sctxt_title_2}" \
			"S+0+1+${sctxt_option_managed}" \
			"R+++" \
			"S+0+q+${sctxt_option_quit}" \
		)
		case ${option} in
		1)	option=6 ;;
		esac
		;;

	offline)
		option=$(sc_get_menuoption \
			"T2+++${sctxt_title_2}" \
			"S+0+1+${sctxt_option_online}" \
			"S+0+2+${sctxt_option_unmanaged}" \
			"R+++" \
			"S+0+q+${sctxt_option_quit}" \
		)
		case ${option} in
		1)	option=1 ;;
		2)	option=3 ;;
		esac
		;;

	error--stop_failed)
		option=$(sc_get_menuoption \
			"T2+++${sctxt_title_2}" \
			"S+0+1+${sctxt_option_offline}" \
			"R+++" \
			"S+0+q+${sctxt_option_quit}" \
		)
		case ${option} in
		1)	option=2 ;;
		esac
		;;

	online)
		if [[ ${maxprimaries} -lt 2 ]]; then
			option=$(sc_get_menuoption \
				"S+0+1+${sctxt_option_switch}" \
				"S+0+2+${sctxt_option_offline}" \
				"S+0+3+${sctxt_option_unmanaged}" \
				"R+++" \
				"S+0+q+${sctxt_option_quit}" \
			)
			case ${option} in
			1)	option=4 ;;
			2)	option=2 ;;
			3)	option=3 ;;
			esac
		else
			option=$(sc_get_menuoption \
				"S+0+1+${sctxt_option_change}" \
				"S+0+2+${sctxt_option_offline}" \
				"S+0+3+${sctxt_option_unmanaged}" \
				"R+++" \
				"S+0+q+${sctxt_option_quit}" \
			)
			case ${option} in
			1)	option=5 ;;
			2)	option=2 ;;
			3)	option=3 ;;
			esac
		fi
		;;
	esac

	echo "${option}"

	return 0
}

#####################################################
#
# scsetup_menu_rgm_rg_online_offline() [nohelp]
#
#	nohelp		- if this flag is given, do not
#			    clear screen, print title, print help,
#			    or ask for confirmation to continue
#
#	Online/offline a resource group.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_rgm_rg_online_offline()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Online/Offline or Switchover a Resource Group <<<
	')"
	typeset sctxt_p1="$(gettext '
		Use this option to bring a resource group online or
		offline on one or more cluster nodes.  For failover
		resource groups which are already online, use this
		option to switch the primary owner of a group.  For
		scalable groups which are already online, use it to
		change the set of current primaries.
	')"
	typeset sctxt_p2="$(gettext '
		This option is also used to control the managed and
		unmanaged state of a resource group.
	')"
	typeset sctxt_p3="$(gettext '
		Once a resource group is brought online, all enabled
		resources in that group become available to clients.
	')"
	typeset sctxt_p4="$(gettext '
		Once a resource group is taken offline from all cluster
		nodes, the resources in that group are no longer
		available to clients of those resources.
	')"
	typeset sctxt_managed_p1="$(gettext '
		Once a resource group is brought from an unmanaged
		state to the managed state, it can then be brought
		online.
	')"
	typeset sctxt_offline_warning_p1="$(gettext '
		Remember that once a resource group is taken offline,
		the resources in that group are no longer available to
		clients of those resources.  Clients who depend on
		those resources will experience a loss of service.
	')"
	typeset sctxt_unmanage_p1="$(gettext '
		Before putting a resource group into an unmanaged state,
		it is first taken offline from all cluster nodes.
	')"
	typeset sctxt_unmanage_p2="$(gettext '
		A resource group can also be put into an unmanaged state.
		Once a resource group is unmanaged, it must be changed
		back to the managed state before it can be brought online.
	')"
	typeset sctxt_unmanage_p3="$(gettext '
		A resource group cannot be unmanaged until all of the
		resources within that group are first disabled.
	')"
	typeset sctxt_unmanage_p4="$(gettext '
		Once a resource group is unmanaged, it must be changed
		back to the managed state before it can be brought online.
	')"
	typeset sctxt_switch_p1="$(gettext '
		Switching primary ownership of a failover resource group
		typically results in a brief outage of service for all
		resources in the group.
	')"

	typeset tmpfile=${SCSETUP_TMP_RGLIST}
	typeset cachefile=${SCSETUP_RGM_CACHEFILE}
	typeset rgstatefile=${SCSETUP_TMP_RGSTATE}

	typeset prompt
	typeset header1
	typeset header2
	typeset answer
	typeset rglist
	typeset -l lrgstatelist		# lower case
	typeset rgstatelist
	typeset rgname
	typeset rgtype
	typeset rgstate
	typeset -l lrgstate		# lower case
	typeset -l lmainstate		# lower case
	typeset -l newstate		# lower case
	typeset -l laststate		# lower case
	typeset resource
	typeset rslist
	typeset deps
	typeset deps2
	typeset dep
	typeset -l lnodestate		# lower case
	typeset node
	typeset nodelist
	typeset online_nodelist
	typeset foo
	typeset foo2

	integer found
	integer index
	integer commands
	integer maxprimaries
	integer count

	# Unless nohelp is specified, print help and get confirmation
	if [[ -z "${nohelp}" ]]; then

		# Clear screen, print title and help
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"
		sc_print_para "${sctxt_p3}"
		sc_print_para "${sctxt_p4}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Get the list of resource groups
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] ||
		    [[ -r "${cachefile}" ]];  then
			rglist="$(scsetup_get_rglist "" "" "" ${cachefile})"
		else
			rglist="rg1 rg2 rg3 rg4 rg5 rg6 rg7 rg8 rg9 rg10 rg11 rg12 rg13 rg14"
		fi

		# Create the rgstate file
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			scsetup_create_rgstatefile ${rgstatefile}
		fi

		# Create the temp file
		rm -f ${tmpfile}
		let found=0
		for rgname in ${rglist}
		do
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]];  then
				lrgstate=
				lmainstate=
				lrgstatelist=" $(scsetup_get_rgstate ${rgname} "${rgstatefile}" "allnodes")"
				# Unmanaged?
				expr "${lrgstatelist}" : '.*\(unmanaged\)' >/dev/null && lmainstate="unmanaged"

				# Stop_Failed anywhere?
				if [[ -z "${lmainstate}" ]]; then
					expr "${lrgstatelist}" : '.*\(error--stop_failed\)' >/dev/null && lmainstate="error--stop_failed"
				fi

				# Online anywhere?
				if [[ -z "${lmainstate}" ]]; then
					expr "${lrgstatelist}" : '.*\([^_]online\)' >/dev/null && lmainstate="online"
				fi

				# Must be offline
				if [[ -z "${lmainstate}" ]]; then
					lmainstate=offline
				fi
				lrgstate=${lmainstate}
				rgstate=$(scsetup_rgstate_string ${lrgstate})

				# If mainstate is online, don't add more offline
				if [[ "${lmainstate}" == "online" ]]; then
					foo2=
				else
					foo2=offline
				fi

				# Add any additional state information
				for foo in online pending_online ${foo2} pending_offline unmanaged error--stop_failed
				do
					if [[ "${foo}" == "${lmainstate}" ]]; then
						continue
					fi
					lrgstate=
					if [[ "${foo}" == "online" ]] ||
					    [[ "${foo}" == "offline" ]]; then
						expr "${lrgstatelist}" : '.*\([^_]'${foo}'\)' >/dev/null && lrgstate=${foo}
					else
						expr "${lrgstatelist}" : '.*\('${foo}'\)' >/dev/null && lrgstate=${foo}
					fi
					if [[ -n "${lrgstate}" ]]; then
						rgstate="${rgstate}, $(scsetup_rgstate_string ${lrgstate})"
					fi
				done

				rgtype="$(scsetup_get_rgtype ${rgname})"
			else
				case ${rgname} in
				rg1)		rgstate="Unmanaged" ;;
				rg2)		rgstate="Online" ;;
				rg3)		rgstate="Pending_Online" ;;
				rg4)		rgstate="Offline" ;;
				rg5)		rgstate="Pending_Offline" ;;
				rg6)		rgstate="Stop_Failed" ;;
				*)		rgstate="Online" ;;
				esac

				rgtype="failover"
			fi
			((found += 1))
			printf "%-20s %-10.10s %s\n" "${rgname}" "${rgtype}" "${rgstate}"
		done > ${tmpfile}

		# Done with rgstate file
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			scsetup_rm_rgstatefile ${rgstatefile}
		fi

		# Are there any resource groups?
		if [[ ${found} -lt 1 ]]; then
			echo
			printf "$(gettext 'There are no resource groups configured.')\n"
			printf "$(gettext 'So, there is nothing to online/offline.')\n\n\a"
			sc_prompt_pause
			rm -f ${tmpfile}
			return 1
		fi

		# Initialize headers
		prompt="$(gettext 'Select the resource group you want to change:')"
		header1="$(printf "%-20s %-10.10s %s" "$(gettext 'Group Name')" "$(gettext 'Type')" "$(gettext 'State(s)')")"
		header2="$(printf "%-20s %-10.10s %s" "==========" "====" "========")"

		# Get the name of the resource group to change
		answer="$(
		    sc_get_scrolling_menuoptions	\
			"${prompt}"			\
			"${header1}"			\
			"${header2}"			\
			0 1 3				\
			:${tmpfile}			\
		)"
		rm -f ${tmpfile}

		# Done?
		if [[ -z "${answer}" ]]; then
			return 0
		fi

		# Break out rgname and rgstate
		rgname=$(IFS=: ; set -- ${answer}; echo ${1})
		rgstate=$(IFS=:, ; set -- ${answer}; echo ${3})
		lmainstate=$(scsetup_string_rgstate ${rgstate})

		# Get Maximum_primaries
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			maxprimaries="$(${SCHA_RG_GET} -G ${rgname} -O maximum_primaries)"
		else
			maxprimaries=1
		fi

		#
		# Get Online/offline action for rg
		#
		# Returned menu options are:
		#
		# 1)	Bring the group online
		# 2)	Bring the group offline from all cluster nodes
		# 3)	Put the group into an unmanaged state
		# 4)	Switch ownership of the group
		# 5)	Change the set of current primaries
		# 6)	Put the group into a managed state
		#
		newstate=
		laststate=
		case $(scsetup_get_rg_online_offline_menuoption "${rgname}" "${lmainstate}" "${maxprimaries}") in
		1)	newstate="online" ;;
		2)	newstate="offline" ;;
		3)	newstate="unmanaged" ;;
		4)	newstate="switch" ;;
		5)	newstate="change" ;;
		6)	newstate="managed" ;;
		*)	continue ;;
		esac

		# Online/offline/manage/unmanage/switch the rg
		while [[ -n "${newstate}" ]]
		do
			case ${newstate} in
			online)
				# Reset the "newstate"
				newstate=

				# Okay to continue?
				if [[ "${laststate}" == "managed" ]]; then
					prompt="$(printf "$(gettext 'Would you also like to bring \"%s\" online?')" "${rgname}")"
				else
					prompt="$(printf "$(gettext 'Are you sure you want to bring \"%s\" online?')" "${rgname}")"
				fi
				laststate=
				answer=$(sc_prompt_yesno "${prompt}" "${YES}") || break
				if [[ "${answer}" != "yes" ]]; then
					break
				fi

				# Check RG_dependencies
				deps=
				let found=0
				if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
					deps="$(scsetup_get_rg_dependencies ${rgname} "offline")"
				fi
				for dep in ${deps}
				do
					deps2="$(scsetup_get_rg_dependencies ${dep} "offline")"
					if [[ -n "${deps2}" ]]; then
						printf "$(gettext 'Resource group \"%s\" depends upon \"%s\".')\n" "${rgname}" "${dep}"
						printf "$(gettext 'And \"%s\", in turn, has other dependencies.')\n" "${dep}"
						((found += 1))
					fi
				done
				if [[ ${found} -ne 0 ]]; then
					printf "$(gettext 'Cannot bring \"%s\" online.')\n\n\a" "${rgname}"
					sc_prompt_pause
					break
				fi

				# Initialize command set
				set -A SCSETUP_DO_CMDSET
				let index=0

				# Set up commands
				for dep in ${deps}
				do
					foo="$(printf "$(gettext 'Resource group \"%s\" depends upon \"%s\".')" "${rgname}" "${dep}")"
					sc_print_para "${foo}"
					prompt="$(printf "$(gettext 'Do you also want to bring \"%s\" online?')" "${dep}")"
					answer=$(sc_prompt_yesno "${prompt}" "${YES}") || break 2
					if [[ "${answer}" == "yes" ]]; then
						SCSETUP_DO_CMDSET[index]="${SC_SCSWITCH} -Z -g ${dep}"
						((index += 1))
					else
						printf "$(gettext 'Cannot bring \"%s\" online.')\n\n\a" "${rgname}"
						sc_prompt_pause
						break 2
					fi
				done

				# Online command
				SCSETUP_DO_CMDSET[index]="${SC_SCSWITCH} -Z -g ${rgname}"

				# Doit
				scsetup_do_cmdset 1
				;;

			managed)
				# Reset the "newstate"
				newstate=

				# Print help
				sc_print_para "${sctxt_managed_p1}"

				# Okay to continue?
				prompt="$(printf "$(gettext 'Are you sure you want the %s to manage \"%s\"?')" "RGM" "${rgname}")"
				answer=$(sc_prompt_yesno "${prompt}" "${YES}") || break
				if [[ "${answer}" != "yes" ]]; then
					break
				fi

				# Check RG_dependencies
				deps=
				let found=0
				if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
					deps="$(scsetup_get_rg_dependencies ${rgname} "unmanaged")"
				fi
				for dep in ${deps}
				do
					deps2="$(scsetup_get_rg_dependencies ${dep} "unmanaged")"
					if [[ -n "${deps2}" ]]; then
						printf "$(gettext 'Resource group \"%s\" depends upon \"%s\".')\n" "${rgname}" "${dep}"
						printf "$(gettext 'And \"%s\", in turn, has other dependencies.')\n" "${dep}"
						((found += 1))
					fi
				done
				if [[ ${found} -ne 0 ]]; then
					printf "$(gettext 'Cannot unmanage \"%s\".')\n\n\a" "${rgname}"
					sc_prompt_pause
					break
				fi

				# Initialize command set
				set -A SCSETUP_DO_CMDSET
				let index=0

				# Set up commands
				for dep in ${deps}
				do
					foo="$(printf "$(gettext 'Resource group \"%s\" depends upon \"%s\".')" "${rgname}" "${dep}")"
					sc_print_para "${foo}"
					prompt="$(printf "$(gettext 'Do you also want to manage \"%s\"?')" "${dep}")"
					answer=$(sc_prompt_yesno "${prompt}" "${YES}") || break 2
					if [[ "${answer}" == "yes" ]]; then
						SCSETUP_DO_CMDSET[index]="${SC_SCSWITCH} -o -g ${dep}"
						((index += 1))
					else
						printf "$(gettext 'Cannot manage \"%s\".')\n\n\a" "${rgname}"
						sc_prompt_pause
						break 2
					fi
				done

				# Manage command
				SCSETUP_DO_CMDSET[index]="${SC_SCSWITCH} -o -g ${rgname}"

				# Doit
				scsetup_do_cmdset 1 || break

				# See if the want to bring it online
				laststate="managed"
				newstate="online"
				continue
				;;

			offline)
				# Reset the "newstate"
				newstate=

				# Print offline warning
				sc_print_para "${sctxt_offline_warning_p1}"

				# Okay to continue?
				prompt="$(printf "$(gettext 'Are you sure you want to take \"%s\" offline?')" "${rgname}")"
				answer=$(sc_prompt_yesno "${prompt}" "${YES}") || break
				if [[ "${answer}" != "yes" ]]; then
					break
				fi

				# Look for other RG_dependencies
				deps=
				let found=0
				if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
					deps="$(scsetup_get_rg_depended_ons ${rgname} "online")"
				fi
				for dep in ${deps}
				do
					deps2="$(scsetup_get_rg_depended_ons ${dep} "online")"
					if [[ -n "${deps2}" ]]; then
						printf "$(gettext 'Resource group \"%s\" is depended upon by \"%s\".')\n" "${rgname}" "${dep}"
						printf "$(gettext 'And \"%s\", in turn, has other dependencies.')\n" "${dep}"
						((found += 1))
					fi
				done
				if [[ ${found} -ne 0 ]]; then
					printf "$(gettext 'Cannot take \"%s\" offline.')\n\n\a" "${rgname}"
					sc_prompt_pause
					break
				fi

				# Initialize command set
				set -A SCSETUP_DO_CMDSET
				let index=0

				# Set up commands
				for dep in ${deps}
				do
					foo="$(printf "$(gettext 'Resource group \"%s\" is depended upon by \"%s\".')" "${rgname}" "${dep}")"
					sc_print_para "${foo}"
					prompt="$(printf "$(gettext 'Do you also want to take \"%s\" offline?')" "${dep}")"
					answer=$(sc_prompt_yesno "${prompt}" "${YES}") || break 2
					if [[ "${answer}" == "yes" ]]; then
						SCSETUP_DO_CMDSET[index]="${SC_SCSWITCH} -F -g ${dep}"
						((index += 1))
					else
						printf "$(gettext 'Cannot take \"%s\" offline.')\n\n\a" "${rgname}"
						sc_prompt_pause
						break 2
					fi
				done

				# Offline command
				SCSETUP_DO_CMDSET[index]="${SC_SCSWITCH} -F -g ${rgname}"
				# Doit
				scsetup_do_cmdset 1 || break

				# Initialize command set
				set -A SCSETUP_DO_CMDSET
				let index=0

				# Unmanage?
				if [[ "${laststate}" != "unmanaged" ]]; then
					sc_print_para "${sctxt_unmanage_p2}"
	
					prompt="$(printf "$(gettext 'Do you want to unmanage \"%s\"?')" "${rgname}")"
					foo="${NO}"
				else
					laststate=
					prompt="$(printf "$(gettext 'Do you still want to unmanage \"%s\"?')" "${rgname}")"
					foo="${YES}"
				fi
				answer=$(sc_prompt_yesno "${prompt}" "${foo}") || break
				if [[ "${answer}" == "yes" ]]; then
					newstate="unmanaged2"
					continue
				fi
				;;

			unmanaged)
				# Reset "newstate" to the next state
				laststate=${newstate}
				if [[ "${lmainstate}" == "online" ]]; then
					sc_print_para "${sctxt_unmanage_p1}"
					newstate="offline"
					continue
				else
					newstate="unmanaged2"
					continue
				fi
				;;

			unmanaged2)
				# Reset the "newstate"
				newstate=

				# Unmanage?
				if [[ "${laststate}" == "unmanaged" ]]; then
					# Clear laststate
					laststate=

					# Print message
					sc_print_para "${sctxt_unmanage_p4}"

					# Okay to continue?
					prompt="$(printf "$(gettext 'Are you sure you want to unmanage \"%s\"?')" "${rgname}")"
					answer=$(sc_prompt_yesno "${prompt}" "${YES}") || break
					if [[ "${answer}" != "yes" ]]; then
						break
					fi
				fi

				# If anything enabled, disable them?
				rslist=
				if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
					rslist="$(${SCHA_RG_GET} -G ${rgname} -O resource_list)"
					rslist="$(scsetup_get_enabled_resources ${rslist})"
				fi

				# Disable enabled resources
				let commands=0
				if [[ -n "${rslist}" ]]; then

					# Print the list
					foo="$(gettext 'The following resource(s) are still enabled:')"
					(
						sc_print_para "${sctxt_unmanage_p3}"
						sc_print_para "${foo}"
						for resource in ${rslist}
						do
							printf "\t${resource}\n"
						done
						echo
					) | more

					# Okay to disable?
					prompt="$(printf "$(gettext 'Is it okay to disable these resource(s) first?')" "${rgname}")"
					answer=$(sc_prompt_yesno "${prompt}" "${YES}") || break
					if [[ "${answer}" != "yes" ]]; then
						printf "$(gettext 'These resource(s) must all be disabled before \"%s\" can be unmanaged.')\n\n\a" "${rgname}"
						break
					fi

					# Disable all resources in the group
					scsetup_disable_resources ${rgname}
					if [[ $? -ne 0 ]]; then
						printf "$(gettext 'All resources must be disabled before \"%s\" can be unmanaged.')\n\n\a" "${rgname}"
						break
					fi
					echo
					((commands += 1))
				fi

				# Look for unmanaged dependencies
				deps=
				let found=0
				if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
					deps="$(scsetup_get_rg_depended_ons ${rgname})"
				fi
				for dep in ${deps}
				do
					deps2="$(scsetup_get_rg_depended_ons ${dep})"
					if [[ -n "${deps2}" ]]; then
						printf "$(gettext 'Resource group \"%s\" depends upon \"%s\" being unmanaged.')\n" "${dep}" "${rgname}"
						printf "$(gettext 'And \"%s\", in turn, has other unmanaged dependencies.')\n" "${dep}"
						((found += 1))
					fi
				done
				if [[ ${found} -ne 0 ]]; then
					printf "$(gettext 'Cannot unmanage \"%s\".')\n\n\a" "${rgname}"
					sc_prompt_pause
					break
				fi

				# Initialize command set
				set -A SCSETUP_DO_CMDSET
				let index=0

				# Set up commands
				for dep in ${deps}
				do
					foo="$(printf "$(gettext 'Resource group \"%s\" depends upon \"%s\" being unmanaged.')" "${rgname}" "${dep}")"
					sc_print_para "${foo}"
					prompt="$(printf "$(gettext 'Do you also want to unmanage \"%s\"?')" "${dep}")"
					answer=$(sc_prompt_yesno "${prompt}" "${YES}") || break 2
					if [[ "${answer}" == "yes" ]]; then
						SCSETUP_DO_CMDSET[index]="${SC_SCSWITCH} -u -g ${dep}"
						((index += 1))
						((commands += 1))
					else
						printf "$(gettext 'Cannot unmanage \"%s\".')\n\n\a" "${rgname}"
						sc_prompt_pause
						break 2
					fi
				done

				# Unmanage command
				SCSETUP_DO_CMDSET[index]="${SC_SCSWITCH} -u -g ${rgname}"

				# Doit
				if [[ ${commands} -gt 0 ]]; then
					scsetup_do_cmdset 1 "" ${commands}
				else
					scsetup_do_cmdset 1
				fi
				;;

			switch)
				# Reset the "newstate"
				newstate=

				if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
					foo=
					online_nodelist="$(scsetup_get_rgstate ${rgname} "" "online")"
					nodelist="$(${SCHA_RG_GET} -G ${rgname} -O nodelist)"
					for node in ${nodelist}
					do
						for foo2 in ${online_nodelist}
						do
							if [[ "${foo2}" == "${node}" ]]; then
								continue 2
							fi
						done
						lnodestate="$(${SCHA_CLUSTER_GET} -O nodestate_node ${node})"
						if [[ "${lnodestate}" == "up" ]]; then
							foo="${foo} ${node}"
						fi
					done
					nodelist=$(echo ${foo})
				else
					nodelist="node2"
				fi

				# Anybody ready to take ownership?
				if [[ -z "${nodelist}" ]]; then
					echo
					printf "$(gettext 'There are no available nodes to take ownership of \"%s\".')\n\n\a" "${rgname}"
					sc_prompt_pause
					break
				fi

				# Menu of available nodes
				prompt="$(printf "$(gettext 'Select the node to take ownership of \"%s\":')" "${rgname}")"
				node="$(
					sc_get_scrolling_menuoptions	\
					"${prompt}"			\
					"" ""				\
					0 1 1				\
					${nodelist}			\
				)"
				if [[ -z "${node}" ]]; then
					break
				fi
		
				# Print warning message
				sc_print_para "${sctxt_switch_p1}"

				# Okay to continue?
				prompt="$(printf "$(gettext 'Are you sure you want to switch \"%s\"?')" "${rgname}")"
				answer=$(sc_prompt_yesno "${prompt}" "${YES}") || break
				if [[ "${answer}" != "yes" ]]; then
					break
				fi

				# Initialize command set
				set -A SCSETUP_DO_CMDSET
				let index=0

				# Manage command
				SCSETUP_DO_CMDSET[index]="${SC_SCSWITCH} -z -g ${rgname} -h ${node}"

				# Doit
				scsetup_do_cmdset 1
				;;

			change)
				# Reset the "newstate"
				newstate=

				# Create the temp file
				rm -f ${tmpfile}
				if [[ ${SCSETUP_ISMEMBER} -eq 1 ]];  then
					rgstatelist="$(scsetup_get_rgstate ${rgname})"
				else
					rgstatelist="node2:offline node3:offline node4:online"
				fi
				for foo in ${rgstatelist}
				do
					node=$(expr "${foo}" : '\(.*\):')
					lrgstate=$(expr "${foo}" : '.*:\(.*\)')
					rgstate=$(scsetup_rgstate_string ${lrgstate})
					printf "%-25s %s\n" "${node}" "${rgstate}"
				done > ${tmpfile}

				# Initialize headers
				prompt="$(gettext 'Select the node on which you want to change the group state:')"
				header1="$(printf "%-25s %s" "$(gettext 'Node Name')" "$(gettext 'Resource Group State')")"
				header2="$(printf "%-25s %s" "=========" "====================")"

				# Get the name of the node to change
				node="$(
				    sc_get_scrolling_menuoptions	\
					"${prompt}"			\
					"${header1}"			\
					"${header2}"			\
					0 1 1				\
					:${tmpfile}			\
				)"
				rm -f ${tmpfile}

				# Done?
				if [[ -z "${node}" ]]; then
					break
				fi

				# Get the state of the node
				if [[ ${SCSETUP_ISMEMBER} -eq 1 ]];  then
					lrgstate="$(scsetup_get_rgstate ${rgname} "" "" "${node}")"
				else
					case ${node} in
					node2)	lrgstate=offline ;;
					node3)	lrgstate=offline ;;
					node4)	lrgstate=online  ;;
					*)	lrgstate=offline ;;
					esac
				fi

				# What do we want to do?
				case ${lrgstate} in
				online|pending_online|error--stop_failed)
					#
					# Take the node offline
					#

					# See if it is the last node
					if [[ ${SCSETUP_ISMEMBER} -eq 1 ]];  then
						online_nodelist="$(scsetup_get_rgstate ${rgname} "" "online")"
					else
						online_nodelist="node4"
					fi
					if [[ -n "${online_nodelist}" ]] &&
					    [[ "${node}" == "${online_nodelist}" ]];  then
						newstate="offline"
						continue
					fi

					# Okay to continue?
					prompt="$(printf "$(gettext 'Okay to offline \"%s\" from \"%s\"?')" "${rgname}" "${node}")"
					answer=$(sc_prompt_yesno "${prompt}" "${YES}") || (newstate="change"; continue)
					if [[ "${answer}" != "yes" ]]; then
						newstate="change"
						continue
					fi

					# Construct the new online nodelist
					nodelist=
					for foo in ${online_nodelist}
					do
						if [[ "${foo}" == "${node}" ]]; then
							continue
						fi
						if [[ -z "${nodelist}" ]]; then
							nodelist=${foo}
						else
							nodelist="${nodelist},${foo}"
						fi
					done

					# Initialize command set
					set -A SCSETUP_DO_CMDSET
					let index=0

					# Switch
					SCSETUP_DO_CMDSET[index]="${SC_SCSWITCH} -z -g ${rgname} -h ${nodelist}"

					# Doit
					scsetup_do_cmdset 1 

					# More changes?
					newstate="change"
					;;

				offline|pending_offline)
					#
					# Bring the node online
					#

					# Make sure the node is in the cluster
					if [[ ${SCSETUP_ISMEMBER} -eq 1 ]];  then
						lnodestate="$(${SCHA_CLUSTER_GET} -O nodestate_node ${node})"
					else
						lnodestate=up
					fi
					if [[ "${lnodestate}" != "up" ]]; then
						echo
						printf "$(gettext '\"%s\" is not currently a member of the cluster.')\n\n\a" "${rgname}"
						sc_prompt_pause
						newstate="change"
						continue
					fi

					# Check maxprimaries
					if [[ ${SCSETUP_ISMEMBER} -eq 1 ]];  then
						online_nodelist="$(scsetup_get_rgstate ${rgname} "" "online")"
					else
						online_nodelist="node4"
					fi
					count=$(set -- ${online_nodelist}; echo $#)
					if [[ ${count} -ge ${maxprimaries} ]]; then
						echo
						printf "$(gettext 'The max number of primaries are already online for \"%s\".')\n\n\a" "${rgname}"
						sc_prompt_pause
						newstate="change"
						continue
					fi
						
					# Okay to continue?
					prompt="$(printf "$(gettext 'Okay to bring \"%s\" online on \"%s\"?')" "${rgname}" "${node}")"
					answer=$(sc_prompt_yesno "${prompt}" "${YES}") || (newstate="change"; continue)
					if [[ "${answer}" != "yes" ]]; then
						newstate="change"
						continue
					fi

					# Construct the new online nodelist
					nodelist=${node}
					if [[ ${SCSETUP_ISMEMBER} -eq 1 ]];  then
						online_nodelist="$(scsetup_get_rgstate ${rgname} "" "online")"
					else
						online_nodelist=node4
					fi
					for foo in ${online_nodelist}
					do
						nodelist="${nodelist},${foo}"
					done

					# Initialize command set
					set -A SCSETUP_DO_CMDSET
					let index=0

					# Switch
					SCSETUP_DO_CMDSET[index]="${SC_SCSWITCH} -z -g ${rgname} -h ${nodelist}"

					# Doit
					scsetup_do_cmdset 1 

					# More changes?
					newstate="change"
					;;

				unmanaged)
					newstate="unmanaged"
					continue
					;;

				*)
					prompt="$(gettext 'Unable to online or offline a group in an \"Unkown\" state.')"
					sc_print_para "${prompt}"
					sc_prompt_pause
					;;
				esac
			esac

			# Clear laststate
			laststate=
		done
	done

	return 0
}

#####################################################
#
# scsetup_menu_rgm_rs_change_props() rsflavor
#
#	rsflavor	- must be "standard" or "extension".
#
#	Change "standard" or "extension" properties of a resource.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_rgm_rs_change_props()
{
	typeset -l lrsflavor=${1}

	typeset sctxt_rsstate_enabled_ext_p1="$(gettext '
		Since this resource is enabled, only those extension
		properties which can be changed while the resource is
		in this state will be shown in the properties menu.  You
		may need to disable the resource in order to change
		certain properties.  Check the man page for your
		resource type for more information.
	')"
	typeset sctxt_rsstate_enabled_std_p1="$(gettext '
		Since this resource is enabled, only those standard
		properties which can be changed while the resource is
		in this state will be shown in the properties menu.
		You may need to disable the resource in order to change
		certain properties.  Check the r_properties(5) man page
		for more information regarding the setting of standard
		resource properties.
	')"
	typeset sctxt_rsstate_disabled_ext_p1="$(gettext '
		This resource is currently disabled.  However, not all
		resource properties can be changed even when the
		resource is in this state.  Only those extension
		properties which can be changed when the resource is in
		a disabled state will be shown in the properties
		menu.   Check the man page for your resource type for
		more information.
	')"
	typeset sctxt_rsstate_disabled_std_p1="$(gettext '
		This resource is currently disabled.  However, not all
		resource properties can be changed even when the
		resource is in this state.  Only those standard
		properties which can be changed when the resource is in
		a disabled state will be shown in the properties
		menu.   Check the r_properties(5) man page for more
		information regarding the setting of standard resource
		properties.
	')"

	typeset sctxt_props_prompt1="    $(gettext 'Property name:       ')"
	typeset sctxt_props_prompt2="    $(gettext 'Property description:')"
	typeset sctxt_props_prompt3="    $(gettext 'Property type:       ')"
	typeset sctxt_props_prompt4="    $(gettext 'Current value:       ')"
	typeset sctxt_props_prompt5="    $(gettext 'New value:           ')"

	typeset tmpfile1=${SCSETUP_TMP_RSLIST}
	typeset tmpfile2=${SCSETUP_TMP_PROPLIST}
	typeset cachefile=${SCSETUP_RGM_CACHEFILE}

	typeset SCSETUP_RS_PROP_NAMES		# Property names
	typeset SCSETUP_RS_PROP_DESCS		# Property descriptions
	typeset SCSETUP_RS_PROP_TYPES		# Property types
	typeset SCSETUP_RS_PROP_VALUES		# Property values

	typeset answer
	typeset rslist
	typeset rsname
	typeset rsstate
	typeset rstype
	typeset prompt
	typeset header1
	typeset header2
	typeset property
	typeset value
	typeset propvalue
	typeset -l lpropvalue			# lower case
	typeset -l proptype			# lower case
	typeset foo

	integer found
	integer count
	integer boolean_is_set

	# Loop until done or Ctrl-D is typed
	while true
	do
		# If not in debug mode, use scha_ commands to get rslist
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			scsetup_rm_scrgadmfile ${cachefile}
		fi

		# Get the list of resources
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] ||
		    [[ -r "${cachefile}" ]];  then
			rslist="$(scsetup_get_rslist "" "" ${cachefile})"
		else
			rslist="res1 res2 res3 res4 res5 res6 res7 res8 res9 res10"
		fi

		# Create the temp file
		rm -f ${tmpfile1}
		let found=0
		for rsname in ${rslist}
		do
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]];  then
				scsetup_is_resource_enabled ${rsname}
				case $? in
				1)	rsstate="Enabled" ;;
				0)	rsstate="Disabled" ;;
				*)	rsstate=
					((found -= 1))
					continue
					;;
				esac
				rstype="$(${SCHA_RS_GET} -R ${rsname} -O type)"
			else
				rsstate="<DEBUG>"
				rstype="<DEBUG>"
			fi
			((found += 1))
			printf "%-25s %-16.16s %-22.22s\n" "${rsname}" "${rsstate}" "${rstype}"
		done > ${tmpfile1}

		# Are there any resources?
		if [[ ${found} -lt 1 ]]; then
			echo
			printf "$(gettext 'There are no resources configured.')\n\n\a"
			sc_prompt_pause
			rm -f ${tmpfile1}
			return 1
		fi

		# Initialize menu headings
		prompt="$(gettext 'Select the resource whose properties you want to change:')"
		header1="$(printf "%-25s %-16.16s %-22.22s" "$(gettext 'Resource Name')" "$(gettext 'Resource State')" "$(gettext 'Resource Type')")"
		header2="$(printf "%-25s %-16.16s %-22.22s" "=============" "==============" "=============")"

		# Get the name of the resource to change
		rsname="$(
		    sc_get_scrolling_menuoptions	\
			"${prompt}"			\
			"${header1}"			\
			"${header2}"			\
			0 1 1				\
			:${tmpfile1}			\
		)"
		rm -f ${tmpfile1}

		# Done?
		if [[ -z "${rsname}" ]]; then
			return 0
		fi

		# Enabled or disabled?
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]];  then
			scsetup_is_resource_enabled ${rsname}
			if [[ $? -eq 0 ]]; then
				rsstate="disabled"
			else
				rsstate="enabled"
			fi
		else
			rsstate="disabled"
		fi

		# Print help text
		if [[ "${rsstate}" == "enabled" ]]; then
			if [[ "${lrsflavor}" == "standard" ]]; then
				sc_print_para "${sctxt_rsstate_enabled_std_p1}"
			else
				sc_print_para "${sctxt_rsstate_enabled_ext_p1}"
			fi
		else
			if [[ "${lrsflavor}" == "standard" ]]; then
				sc_print_para "${sctxt_rsstate_disabled_std_p1}"
			else
				sc_print_para "${sctxt_rsstate_disabled_ext_p1}"
			fi
		fi
		sc_prompt_pause

		# Initialize menu headings
		prompt="$(printf "$(gettext 'Select the %s property you want to change:')" "${lrsflavor}")"
		header1="$(printf "%-30s %-30.30s" "$(gettext 'Property Name')" "$(gettext 'Current Setting')")"
		header2="$(printf "%-30s %-30.30s" "=============" "===============")"

		# Loop until done or Ctrl-D is typed
		while true
		do
			# Clear the resource attributes arrays
			set -A SCSETUP_RS_PROP_NAMES
			set -A SCSETUP_RS_PROP_DESCS
			set -A SCSETUP_RS_PROP_TYPES
			set -A SCSETUP_RS_PROP_VALUES

			# Cache scrgadm output
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
				scsetup_create_scrgadmfile ${cachefile}
			fi

			# Set the resource attributes arrays
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] ||
			    [[ -r "${cachefile}" ]]; then
				scsetup_get_rs_props ${rsname} ${lrsflavor} ${rsstate} ${cachefile}
			# If debug, fabricate some debug data
			else
				set -A SCSETUP_RS_PROP_NAMES Prop_int Prop_string Prop_array Prop_other

				SCSETUP_RS_PROP_DESCS[0]="Integer property"
				SCSETUP_RS_PROP_DESCS[1]="String property"
				SCSETUP_RS_PROP_DESCS[2]="String array property"
				SCSETUP_RS_PROP_DESCS[3]="Other property"

				SCSETUP_RS_PROP_TYPES[0]=Int
				SCSETUP_RS_PROP_TYPES[1]=String
				SCSETUP_RS_PROP_TYPES[2]=Stringarray
				SCSETUP_RS_PROP_TYPES[3]=

				SCSETUP_RS_PROP_VALUES[0]=20
				SCSETUP_RS_PROP_VALUES[1]="hello"
				SCSETUP_RS_PROP_VALUES[2]=
				SCSETUP_RS_PROP_VALUES[3]=
			fi

			# Remove scrgadm output
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
				scsetup_rm_scrgadmfile ${cachefile}
			fi

			# Are there any properties to set?
			if [[ -z "${SCSETUP_RS_PROP_NAMES[0]}" ]]; then
				echo
				if [[ "${rsstate}" == "disabled" ]]; then
					printf "$(gettext 'There are no tunable %s properties for \"%s\".')\n\n\a" "${lrsflavor}" "${rsname}"
				else
					printf "$(gettext 'There are no tunable %s properties for \"%s\" at this time.')\n" "${lrsflavor}" "${rsname}"
					printf "$(gettext 'Additional properties may be tunable in the %s state.')\n\n\a" "disabled"
				fi
				sc_prompt_pause
				continue 2
			fi

			# Create the temp file
			rm -f ${tmpfile2}
			for property in ${SCSETUP_RS_PROP_NAMES[*]}
			do
				value="$(scsetup_get_rs_prop_value ${property})"
				printf "%-30s %-30.30s\n" "${property}" "${value}"
			done >${tmpfile2}

			# Get the property
			property="$(
			    sc_get_scrolling_menuoptions	\
				"${prompt}"			\
				"${header1}"			\
				"${header2}"			\
				0 1 1				\
				:${tmpfile2}			\
			)"
			rm -f ${tmpfile2}

			# Done with this resource?
			if [[ -z "${property}" ]]; then
				continue 2
			fi

			# Print the name
			sc_print_prompt "${sctxt_props_prompt1}" "space"
			echo "${property}"

			# Print the description
			sc_print_prompt "${sctxt_props_prompt2}" "space"
			propvalue="$(scsetup_get_rs_prop_description ${property})"
			echo "${propvalue}"

			# Print the type
			sc_print_prompt "${sctxt_props_prompt3}" "space"
			proptype="$(scsetup_get_rs_prop_type ${property})"
			echo "${proptype}"

			# Print the current value
			sc_print_prompt "${sctxt_props_prompt4}" "space"
			propvalue="$(scsetup_get_rs_prop_value ${property})"
			echo "${propvalue}"

			# If proptype is boolean, switch the setting
			let boolean_is_set=0
			if [[ "${proptype}" == "boolean" ]];  then
				lpropvalue=${propvalue}
				case ${lpropvalue} in
				true)	value=FALSE
					let boolean_is_set=1
					;;

				false)	value=TRUE
					let boolean_is_set=1
					;;
				esac

				if [[ ${boolean_is_set} -eq 1 ]]; then
					sc_print_prompt "${sctxt_props_prompt5}" "space"
					echo "${value}"
					echo
				fi
			fi

			# Get the new value
			while [[ ${boolean_is_set} -eq 0 ]]
			do
				# Get user input
				value=
				sc_print_prompt "${sctxt_props_prompt5}" "space"
				read value

				# Ctrl-D?
				if [[ $? -ne 0 ]]; then
					echo
					continue 2
				fi

				# Compress ", " in stringarrays
				if [[ "${proptype}" == "stringarray" ]]; then
					value="$(echo ${value} | sed 's/, /,/g')"
				fi

				# Too many options?
				if [[ "${proptype}" != "string" ]];  then
					count=$(set -- ${value};  echo $#)
					if [[ ${count} -gt 1 ]]; then
						echo "\a\c"
						continue
					fi
				fi

				# Newline
				echo        

				# Nothing entered
				if [[ -z "${value}" ]];  then
					if [[ -z "${propvalue}" ]]; then
						continue 2
					fi
					if [[ "${proptype}" == "int" ]];  then
						echo "\a\c"
						continue
					fi
					answer=$(sc_prompt_yesno "$(gettext 'Do you want to try to clear the property?')" "${NO}")
					if [[ "${answer}" != "yes" ]]; then
						continue 2
					fi
				fi

				#
				# Attempt to make sure the value is in some
				# kind of legal range.  Note that we currently
				# do not check for all value types.
				#
				case ${proptype} in
				int)
					if [[ $(expr "${value}" : '[0-9]*') -ne ${#value} ]]; then
						printf "$(gettext '\"%s\" is not numeric.')\n\n\a" "${value}"
						continue
					fi
					;;

				boolean)
					lpropvalue=${value}
					case ${lpropvalue} in
					true)	value=TRUE ;;
					false)	value=FALSE ;;
					*)
						printf "$(gettext '%s must be set to either \"%s\" or \"%s\".')\n\n\a" "Boolean" "TRUE" "FALSE"
						continue
						;;
					esac
					;;

				string|stringarray)
					;;

				*)
					if [[ "${value}" == *,* ]]; then
						printf "$(gettext 'Stringarray is not expected.')\n\n\a"
						continue
					fi
					;;
				esac

				# Done
				break
			done

			# Initialize
			set -A SCSETUP_DO_CMDSET

			# Set up the command to change the property
			if [[ "${lrsflavor}" == "extension" ]]; then
				foo="-x"
			else
				foo="-y"
			fi
			SCSETUP_DO_CMDSET[0]="${SC_SCRGADM} -c -j ${rsname} ${foo} ${property}=\"${value}\""

			# Run it
			scsetup_do_cmdset
		done
	done

	return 0
}

#####################################################
#
# scsetup_re_version_resource() index rgstatefile [summaryfile]
#
#	index		- index into an already initialized
#			    set of SCSETUP_RS_*_UPGRD arrays:
#
#				SCSETUP_RS_NAMES_UPGD
#				SCSETUP_RS_CVERS_UPGD
#				SCSETUP_RS_TYPE_UPGD
#				SCSETUP_RS_PVERS_UPGD
#				SCSETUP_RS_WHEN_UPGD
#
#	rgstatefile	- resource group statefile (see
#			    scsetup_create_rgstatefile())
#
#	summaryfile	- summarize errors in this file
#
#	This function re-versions SCSETUP_RS_NAMES_UPGD[index] to
#	SCSETUP_RS_PVERS_UPGD[index], if allowed by
#	SCSETUP_RS_WHEN_UPGD[index].
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_re_version_resource()
{
	integer index=${1} 
	typeset rgstatefile=${2}
	typeset summaryfile=${3}

	typeset prompt1
	typeset prompt2
	typeset answer
	typeset errmsg
	typeset nodelist
	typeset rgname
	typeset -l lmonitored		# lower case

	integer status

	# Initialize prompts
	prompt1="$(printf "$(gettext 'The \"%s\" resource is currently running version \"%s\" of resource type \"%s\".')" "${SCSETUP_RS_NAMES_UPGD[index]}" "${SCSETUP_RS_CVERS_UPGD[index]}" "${SCSETUP_RS_TYPE_UPGD[index]}")"
	prompt2="$(printf "$(gettext 'Is it okay to upgrade to version \"%s\"?')" "${SCSETUP_RS_PVERS_UPGD[index]}")"

	# Okay to continue?
	sc_print_para "${prompt1}"
	answer=$(sc_prompt_yesno "${prompt2}" "${YES}") || return 1
	if [[ "${answer}" != "yes" ]]; then
		return 1
	fi

	# Check "when"
	case "${SCSETUP_RS_WHEN_UPGD[index]}" in
	"Anytime")
		;;

	"At creation")
		sc_print_para "$(printf "$(gettext 'Resources can only be upgrade to \"%s\" at creation time.')" "${SCSETUP_RS_TYPE_UPGD[index]}:${SCSETUP_RS_PVERS_UPGD[index]}")"
		errmsg="$(printf "$(gettext '\"%s\" must be removed and re-created to use the new version.')" "${SCSETUP_RS_NAMES_UPGD[index]}")"
		printf "%s\n\n\a" "${errmsg}"
		if [[ -n "${summaryfile}" ]]; then
			echo "${errmsg}" >> ${summaryfile}
		fi
		sc_prompt_pause
		return 1
		;;
		
	"When disabled")
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			# Enabled?
			scsetup_is_resource_enabled ${SCSETUP_RS_NAMES_UPGD[index]}

			# Enabled or enabled/online?
			if [[ $? -ne 0 ]]; then
				sc_print_para "$(printf "$(gettext 'Resources can only be upgrade to \"%s\" when they are disabled.')" "${SCSETUP_RS_TYPE_UPGD[index]}:${SCSETUP_RS_PVERS_UPGD[index]}")"
				errmsg="$(printf "$(gettext '\"%s\" must be disabled before it can be upgraded.')" "${SCSETUP_RS_NAMES_UPGD[index]}")"
				printf "%s\n\n\a" "${errmsg}"
				if [[ -n "${summaryfile}" ]]; then
					echo "${errmsg}" >> ${summaryfile}
				fi
				sc_prompt_pause
				return 1
			fi
		fi
		;;
			
	"When offline")
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			rgname=$(${SCHA_RS_GET} -R ${SCSETUP_RS_NAMES_UPGD[index]} -O group)
			if [[ -n "${rgname}" ]]; then
				nodelist=$(scsetup_get_rgstate ${rgname} ${rgstatefile} "not_offline")
			fi
			if [[ -z "${rgname}" ]] || [[ -n "${nodelist}" ]]; then
				sc_print_para "$(printf "$(gettext 'Resources can only be upgrade to \"%s\" when the groups to which they belong are offline.')" "${SCSETUP_RS_TYPE_UPGD[index]}:${SCSETUP_RS_PVERS_UPGD[index]}")"
				errmsg="$(printf "$(gettext '\"%s\" must be offline before \"%s\" can be upgraded.')" "${rgname}" "${SCSETUP_RS_NAMES_UPGD[index]}")"
				printf "%s\n\n\a" "${errmsg}"
				if [[ -n "${summaryfile}" ]]; then
					echo "${errmsg}" >> ${summaryfile}
				fi
				sc_prompt_pause
				return 1
			fi
		fi
		;;

	"When unmanaged")
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			rgname=$(${SCHA_RS_GET} -R ${SCSETUP_RS_NAMES_UPGD[index]} -O group)
			if [[ -n "${rgname}" ]]; then
				nodelist=$(scsetup_get_rgstate ${rgname} ${rgstatefile} "unmanaged")
			fi
			if [[ -z "${rgname}" ]] || [[ -z "${nodelist}" ]]; then
				sc_print_para "$(printf "$(gettext 'Resources can only be upgrade to \"%s\" when the groups to which they belong are unmanaged.')" "${SCSETUP_RS_TYPE_UPGD[index]}:${SCSETUP_RS_PVERS_UPGD[index]}")"
				errmsg="$(printf "$(gettext '\"%s\" must be unmanaged before \"%s\" can be upgraded.')" "${rgname}" "${SCSETUP_RS_NAMES_UPGD[index]}")"
				printf "%s\n\n\a" "${errmsg}"
				if [[ -n "${summaryfile}" ]]; then
					echo "${errmsg}" >> ${summaryfile}
				fi
				sc_prompt_pause
				return 1
			fi
		fi
		;;

	"When unmonitored")
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			lmonitored=$(${SCHA_RS_GET} -R ${SCSETUP_RS_NAMES_UPGD[index]} -O monitored_switch)
			if [[ "${lmonitored}" == "enabled" ]]; then
				let status=1
			else
				let status=0
			fi

			# If monitored, but not enabled, should be okay
			if [[ ${status} -ne 0 ]]; then
				# Enabled?
				scsetup_is_resource_enabled ${SCSETUP_RS_NAMES_UPGD[index]}
				let status=$?
			fi

			# If monitored or monitored/enabled,
			# but group is offline, should be okay
			if [[ ${status} -ne 0 ]]; then
				rgname=$(${SCHA_RS_GET} -R ${SCSETUP_RS_NAMES_UPGD[index]} -O group)
				if [[ -n "${rgname}" ]]; then
					nodelist=$(scsetup_get_rgstate ${rgname} ${rgstatefile} "not_offline")
				fi
				if [[ -n "${rgname}" ]] && [[ -z "${nodelist}" ]]; then
					let status=0
				fi
			fi

			# Monitored or monitored/enabled or
			# monitored/enabled/online?
			if [[ ${status} -ne 0 ]]; then

				sc_print_para "$(printf "$(gettext 'Resources can only be upgrade to \"%s\" if they are unmonitored.')" "${SCSETUP_RS_TYPE_UPGD[index]}:${SCSETUP_RS_PVERS_UPGD[index]}")"
				errmsg="$(printf "$(gettext '\"%s\" must have monitoring disabled before it can be upgraded.')" "${SCSETUP_RS_NAMES_UPGD[index]}")"
				printf "%s\n\n\a" "${errmsg}"
				if [[ -n "${summaryfile}" ]]; then
					echo "${errmsg}" >> ${summaryfile}
				fi
				sc_prompt_pause
				return 1
			fi
		fi
		;;
	esac

	# Go ahead and try to re-version
	set -A SCSETUP_DO_CMDSET

	SCSETUP_DO_CMDSET[0]="${SC_SCRGADM} -c -j ${SCSETUP_RS_NAMES_UPGD[index]} -y Type_version=${SCSETUP_RS_PVERS_UPGD[index]}"

	# Run it without re-confirming
	scsetup_do_cmdset 1 || return 1

	return 0
}

#####################################################
#
# scsetup_menu_rgm_rs_manage_versions() [nohelp]
#
#	nohelp		- if this flag is given, do not
#			    clear screen, print title, print help,
#			    or ask for confirmation to continue
#
#	Manage resource versioning.
#
#	This function always returns zero.
#
#####################################################
scsetup_menu_rgm_rs_manage_versions()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Resource Versioning <<<
	')"
	typeset sctxt_p1="$(gettext '
		Use this option to manage the versioning of resources.
	')"
	typeset sctxt_p2="$(gettext '
		The \"Type_version\" property is a special standard
		property of a resource which specifies the version of a
		resource type used by that resource.  Once a new version
		of a resource type is installed and registered, the
		\"Type_version\" property of resources of that resource
		type can be changed to upgrade those resources to the
		new version.
	')"

	typeset sctxt_prompt_operation="$(gettext 'Please select from one of the following options:')"
	typeset sctxt_option_operation_001="$(gettext 'Show versioning status')"
	typeset sctxt_option_operation_002="$(gettext 'Re-version selected resources')"
	typeset sctxt_option_operation_003="$(gettext 'Re-version all eligible resources of a given resource type')"
	typeset sctxt_option_operation_004="$(gettext 'Re-version all eligible resources')"
	typeset sctxt_option_return="$(gettext 'Return to the resource properties menu')"

	typeset tmpfile1=${SCSETUP_TMP_RSLIST}
	typeset tmpfile1_sorted=${SCSETUP_TMP_RSLIST_SORTED}
	typeset tmpsummary=${SCSETUP_TMP_SUMMARY}
	typeset cachefile=${SCSETUP_RGM_CACHEFILE}
	typeset rgstatefile=${SCSETUP_TMP_RGSTATE}

	# Variables for call to scsetup_get_upgradeable_resources()
	typeset SCSETUP_RS_NAMES_UPGD		# Resource names
	typeset SCSETUP_RS_CVERS_UPGD		# Resource current versions
	typeset SCSETUP_RS_TYPE_UPGD		# Resource type
	typeset SCSETUP_RS_PVERS_UPGD		# Possible upgrade versions
	typeset SCSETUP_RS_WHEN_UPGD		# Upgrade when

	typeset prompt
	typeset header1
	typeset header2
	typeset answer
	typeset option
	typeset task
	typeset to_when
	typeset rsname
	typeset rstype
	typeset newvers
	typeset curvers
	typeset rstypes_done
	typeset foo

	integer i
	integer linecount
	integer found

	# Unless nohelp is specified, print help and get confirmation
	if [[ -z "${nohelp}" ]]; then

		# Clear screen, print title and help
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"

		# Okay to continue?
		scsetup_continue || return 0
	fi

	# Loop until done or Ctrl-D is typed
	task=
	while true
	do
		# If we are already on the "select" or "allrt" menu, stay there
		if [[ "${task}" != "select" ]] &&
		    [[ "${task}" != "allrt" ]]; then

			# Get the menu option
			option=$(sc_get_menuoption \
			    "T2+++${sctxt_prompt_operation}" \
			    "S+0+1+${sctxt_option_operation_001}" \
			    "S+0+2+${sctxt_option_operation_002}" \
			    "S+0+3+${sctxt_option_operation_003}" \
			    "S+0+4+${sctxt_option_operation_004}" \
			    "R+++" \
			    "S+0+q+${sctxt_option_return}" \
			)

			# Set the task
			case ${option} in
			1)	task="show"	;;
			2)	task="select"	;;
			3)	task="allrt"	;;
			4)	task="all"	;;
			*)	break		;;
			esac
		fi

		# Remove the rgstatefile
		scsetup_rm_rgstatefile ${rgstatefile}

		# If not a cluster member and no cachefile, set for debug
		if [[ ${SCSETUP_ISMEMBER} -ne 1 ]] &&
		    [[ ! -r "${cachefile}" ]]; then

			set -A SCSETUP_RS_NAMES_UPGD
			set -A SCSETUP_RS_CVERS_UPGD
			set -A SCSETUP_RS_TYPE_UPGD
			set -A SCSETUP_RS_PVERS_UPGD
			set -A SCSETUP_RS_WHEN_UPGD

			SCSETUP_RS_NAMES_UPGD[0]=res1
			SCSETUP_RS_NAMES_UPGD[1]=res2

			SCSETUP_RS_CVERS_UPGD[0]=1.0
			SCSETUP_RS_CVERS_UPGD[1]=2.0

			SCSETUP_RS_TYPE_UPGD[0]=typeX
			SCSETUP_RS_TYPE_UPGD[1]=typeY

			SCSETUP_RS_PVERS_UPGD[0]=3.0
			SCSETUP_RS_PVERS_UPGD[1]=3.0

			SCSETUP_RS_WHEN_UPGD[0]=Anytime
			SCSETUP_RS_WHEN_UPGD[1]="When unmonitored"

		# Otherwise, get the upgradeable resources and rgstatefile
		else
			scsetup_get_upgradeable_resources ${cachefile}

			# Create the rgstatefile
			case ${task} in
			select|allrt|all)
				scsetup_create_rgstatefile ${rgstatefile}
				;;
			esac
		fi

		# Make sure that there is at least one resource
		if [[ -z "${SCSETUP_RS_NAMES_UPGD[0]}" ]]; then
			echo
			printf "$(gettext 'There are no resources configured.')\n\n\a"
			sc_prompt_pause
			break
		fi

		# Switch on task
		case ${task} in
		show)		# Show re-versioning status
			(
				echo
				printf "%10.10s %-17s %-27s %s\n" "" "$(gettext 'Resource Name')" "$(gettext 'Current Version')" "$(gettext 'Upgradeable To')"
				printf "%10.10s %-17s %-27s %s\n" "" "$(gettext '=============')" "$(gettext '===============')" "$(gettext '==============')"
				echo

				let i=0
				while [[ -n "${SCSETUP_RS_NAMES_UPGD[i]}" ]]
				do
					# Set "to_when"
					if [[ -n "${SCSETUP_RS_PVERS_UPGD[i]}" ]]; then
						to_when=${SCSETUP_RS_PVERS_UPGD[i]}
						if [[ -n "${SCSETUP_RS_WHEN_UPGD[i]}" ]]; then
							to_when="${to_when} - ${SCSETUP_RS_WHEN_UPGD[i]}"
						fi
					else
						to_when=
					fi

					# Print line
					printf "%10.10s %-17s %-27s %s\n" "" "${SCSETUP_RS_NAMES_UPGD[i]}" "${SCSETUP_RS_TYPE_UPGD[i]}:${SCSETUP_RS_CVERS_UPGD[i]}" "${to_when}"

					# Next
					((i += 1))
				done
			) | more

			# Done
			sc_prompt_pause
			continue
			;;

		select)		# Select individual resources for re-versioning

			# Initialize headers
			prompt="$(gettext 'Select the resource you want to upgrade:')"
			header1="$(printf "%-27s %-17s %s" "$(gettext 'New Version')" "$(gettext 'Resource Name')" "$(gettext 'Current Version')")"
			header2="$(printf "%-27s %-17s %s" "$(gettext '===========')" "$(gettext '=============')" "$(gettext '===============')")"

			# Create the temp file
			rm -f ${tmpfile1}
			let found=0
			let i=0
			while [[ -n "${SCSETUP_RS_NAMES_UPGD[i]}" ]]
			do
				# Anything to upgrade to?
				if [[ -z "${SCSETUP_RS_PVERS_UPGD[i]}" ]]; then
					((i += 1))
					continue
				fi
				let found=1

				# Print line
				printf "%-27s %-17s %s\n" "${SCSETUP_RS_TYPE_UPGD[i]}:${SCSETUP_RS_PVERS_UPGD[i]}" "${SCSETUP_RS_NAMES_UPGD[i]}" "${SCSETUP_RS_CVERS_UPGD[i]}"

				# Next
				((i += 1))
			done > ${tmpfile1}

			# If the list is empty, we are done
			if [[ ${found} -eq 0 ]]; then
				echo
				printf "$(gettext 'There are no resources ready to be re-versioned.')\n"
				sc_prompt_pause
				rm -f ${tmpfile1}
				task=
				continue
			fi

			# Sort it
			rm -f ${tmpfile1_sorted}
			sort ${tmpfile1} >${tmpfile1_sorted}
			rm -f ${tmpfile1}

			# Get the name of the resource to upgrade
			answer="$(
			    sc_get_scrolling_menuoptions	\
				"${prompt}"			\
				"${header1}"			\
				"${header2}"			\
				0 1 3				\
				:${tmpfile1_sorted}		\
			)"
			rm -f ${tmpfile1_sorted}

			# Done?
			if [[ -z "${answer}" ]]; then
				task=
				continue
			fi

			# Get resource type, resource name, and versions
			(IFS=: ; set -- ${answer};  echo ${*}) | read rstype newvers rsname curvers

			# Find it in our set of arrays
			let found=0
			let i=0
			while [[ -n "${SCSETUP_RS_NAMES_UPGD[i]}" ]]
			do
				if [[ "${rsname}" == "${SCSETUP_RS_NAMES_UPGD[i]}" ]] &&
				    [[ "${curvers}" == "${SCSETUP_RS_CVERS_UPGD[i]}" ]] &&
				    [[ "${newvers}" == "${SCSETUP_RS_PVERS_UPGD[i]}" ]]; then
					# Reversion the resource at index "i"
					scsetup_re_version_resource ${i} ${rgstatefile}

					# Done
					let found=1
					break
				fi

				# Next
				((i += 1))
			done

			# Should never happen
			if [[ ${found} -eq 0 ]]; then
				echo
				printf "$(gettext 'Unable to re-version \"%s\".')\n" "${rsname}"
				sc_prompt_pause
				continue
			fi
	
			# Done
			continue
			;;

		allrt)		# Re-version all resources of a given rt

			# Initialize headers
			prompt="$(gettext 'Select the resource type and version for upgrade:')"
			header1="$(printf "%s" "$(gettext 'New Version')")"
			header2="$(printf "%s" "$(gettext '===========')")"

			# Create the temp file
			rm -f ${tmpfile1}
			let found=0
			let i=0
			while [[ -n "${SCSETUP_RS_NAMES_UPGD[i]}" ]]
			do
				# Anything to upgrade to?
				if [[ -z "${SCSETUP_RS_PVERS_UPGD[i]}" ]]; then
					((i += 1))
					continue
				fi
				let found=1

				# Print line
				printf "%s\n" "${SCSETUP_RS_TYPE_UPGD[i]}:${SCSETUP_RS_PVERS_UPGD[i]}"

				# Next
				((i += 1))
			done > ${tmpfile1}

			# If the list is empty, we are done
			if [[ ${found} -eq 0 ]]; then
				echo
				printf "$(gettext 'There are no resources ready to be re-versioned.')\n"
				sc_prompt_pause
				rm -f ${tmpfile1}
				task=
				continue
			fi

			# Sort it, and weed out duplicates
			rm -f ${tmpfile1_sorted}
			sort ${tmpfile1} | uniq >${tmpfile1_sorted}
			rm -f ${tmpfile1}

			# Get the name of the resource types to upgrade
			answer="$(
			    sc_get_scrolling_menuoptions	\
				"${prompt}"			\
				"${header1}"			\
				"${header2}"			\
				0 1 1				\
				:${tmpfile1_sorted}		\
			)"
			rm -f ${tmpfile1_sorted}

			# Done?
			if [[ -z "${answer}" ]]; then
				task=
				continue
			fi

			# Get resource type and version
			(IFS=: ; set -- ${answer};  echo ${*}) | read rstype newvers

			# Re-version each resource which qualifies
			rm -f ${tmpsummary}
			rstypes_done=
			let found=0
			let i=0
			while [[ -n "${SCSETUP_RS_NAMES_UPGD[i]}" ]]
			do
				if [[ "${rstype}" == "${SCSETUP_RS_TYPE_UPGD[i]}" ]] &&
				    [[ "${newvers}" == "${SCSETUP_RS_PVERS_UPGD[i]}" ]]; then
					# Only do it once
					for foo in ${rstypes_done} 
					do
						if [[ "${foo}" == "${SCSETUP_RS_NAMES_UPGD[i]}" ]]; then
							((i += 1))
							continue 2
						fi
					done

					# Reversion the resource at index "i"
					scsetup_re_version_resource ${i} ${rgstatefile} ${tmpsummary}
					if [[ $? -eq 0 ]]; then
						rstypes_done="${rstypes_done} ${SCSETUP_RS_NAMES_UPGD[i]}"
					fi

					let found=1
				fi

				# Next
				((i += 1))
			done

			# Should never happen
			if [[ ${found} -eq 0 ]]; then
				echo
				printf "$(gettext 'Unable to re-version \"%s\" resources.')\n" "${rstype}"
				sc_prompt_pause
				rm -f ${tmpsummary}
				continue
			fi

			# Re-try messages
			let linecount=0
			if [[ -s "${tmpsummary}" ]]; then
				wc -l ${tmpsummary} | read linecount foo
			fi
			if [[ ${linecount} -gt 1 ]]; then
			    (
				sc_print_para "$(gettext 'Here is a summary of messages:')"
				while read line
				do
					printf "\t${line}\n"
				done < ${tmpsummary}
				echo
			    ) | more

				sc_prompt_pause
			fi
	
			# Done
			rm -f ${tmpsummary}
			continue
			;;

		all)		# Re-version all resources

			# Re-version each resource which can be upgraded
			rstypes_done=
			let found=0
			let i=0
			while [[ -n "${SCSETUP_RS_NAMES_UPGD[i]}" ]]
			do
				if [[ -n "${SCSETUP_RS_PVERS_UPGD[i]}" ]]; then

					# Only do it once
					for foo in ${rstypes_done} 
					do
						if [[ "${foo}" == "${SCSETUP_RS_NAMES_UPGD[i]}" ]]; then
							((i += 1))
							continue 2
						fi
					done

					# Reversion the resource at index "i"
					scsetup_re_version_resource ${i} ${rgstatefile} ${tmpsummary}
					if [[ $? -eq 0 ]]; then
						rstypes_done="${rstypes_done} ${SCSETUP_RS_NAMES_UPGD[i]}"
					fi

					let found=1
				fi

				# Next
				((i += 1))
			done

			# Anything to re-version?
			if [[ ${found} -eq 0 ]]; then
				echo
				printf "$(gettext 'There is nothing to re-version.')\n"
				rm -f ${tmpsummary}
				sc_prompt_pause
				continue
			fi
	
			# Re-try messages
			let linecount=0
			if [[ -s "${tmpsummary}" ]]; then
				wc -l ${tmpsummary} | read linecount foo
			fi
			if [[ ${linecount} -gt 1 ]]; then
			    (
				sc_print_para "$(gettext 'Here is a summary of messages:')"
				while read line
				do
					printf "\t${line}\n"
				done < ${tmpsummary}
				echo
			    ) | more

				sc_prompt_pause
			fi

			# Done
			rm -f ${tmpsummary}
			continue
			;;

		*)		# Done
			break
			;;

		esac
	done

	# Remove the rgstatefile
	scsetup_rm_rgstatefile ${rgstatefile}

	return 0
}

#####################################################
#
# scsetup_get_rs_changeproperties_menuoption()
#
#	Print the resource change-properties menu, and return
#	the selected option.
#
#	This function always returns zero.
#	
#####################################################
scsetup_get_rs_changeproperties_menuoption()
{
	typeset sctxt_title_2="$(gettext 'Please select from one of the following options:')"
	typeset sctxt_option_001="$(gettext 'Change standard resource properties')"
	typeset sctxt_option_002="$(gettext 'Change extension resource properties')"
	typeset sctxt_option_003="$(gettext 'Manage resource versioning')"
	typeset sctxt_option_return="$(gettext 'Return to the resource group menu')"

	typeset option

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

	echo "${option}"

	return 0
}

#####################################################
#
# scsetup_menu_rgm_rs_changeproperties() [nohelp]
#
#	nohelp		- if this flag is given, do not
#			    clear screen, print title, print help,
#			    or ask for confirmation to continue
#
#	Change properties of a resource.
#
#	This function always returns zero.
#
#####################################################
scsetup_menu_rgm_rs_changeproperties()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Change Properties of a Resource <<
	')"
	typeset sctxt_p1="$(gettext '
		Use this option to change properties of a resource.
	')"
	typeset sctxt_p2="$(gettext '
		Resources have two types of properties, standard properties
		and extension properties.   Standard resource properties are
		described on the r_properties(5) man page.  Extended
		properties are described on the individual man pages
		for each resource type.
	')"
	typeset sctxt_p3="$(gettext '
		The \"Type_version\" property is a special standard
		property of a resource which specifies the version of a
		resource type used by that resource. The \"Type_version\"
		property of resources can sometimes be changed to
		upgrade resources to a new version.  This menu option
		includes support for the management of resource
		re-versioning.
	')"
	typeset sctxt_p4="$(gettext '
		Not all resource properties can be changed at any
		time.  For example, some properties can only be set at
		the time that the resource is created, some can only be
		changed when the resource is disabled, and some can
		never be changed.
	')"

	# Unless nohelp is specified, print help and get confirmation
	if [[ -z "${nohelp}" ]]; then

		# Clear screen, print title and help
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"
		sc_print_para "${sctxt_p3}"
		sc_print_para "${sctxt_p4}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Get the menu option
                case $(scsetup_get_rs_changeproperties_menuoption) in
                '1')    scsetup_menu_rgm_rs_change_props "standard" ;;
                '2')    scsetup_menu_rgm_rs_change_props "extension" ;;
                '3')    scsetup_menu_rgm_rs_manage_versions ;;
                'q')    break ;;
                esac              
	done

	return 0
}

#####################################################
#
# scsetup_menu_rgm_rs_delete() [delete] [nohelp]
#
#	delete		- the resource to delete
#
#	nohelp		- if this flag is given, do not
#			    clear screen, print title, print help,
#			    or ask for confirmation to continue
#
#	Remove a resource from a resource group.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_rgm_rs_delete()
{
	typeset delete=${1}
	typeset nohelp=${2}

	typeset sctxt_title="$(gettext '
		>>> Remove a Resource from a Resource Group <<<
	')"
	typeset sctxt_p1="$(gettext '
		Use this option to to remove a resource from a resource
		group.
	')"
	typeset sctxt_p2="$(gettext '
		Before a resource can be removed, it must be in the
		disabled state.   Before a resource can be disabled,
		all resources that depend on it must first be
		disabled.
	')"
	typeset sctxt_p3="$(gettext '
		If the resource you select for removal is not already
		disabled, you can disable it using this menu option.
	')"
	typeset sctxt_p4="$(gettext '
		Once a resource has been disabled or removed, the
		resource is no longer available to clients of that
		resource.
	')"
	typeset sctxt_remove_warning_p1="$(gettext '
		Remember that once a resource is removed, the resource
		is no longer available to clients of that resource.
		Clients which depend upon that resource will experience
		a loss of service.
	')"
	typeset sctxt_netdeps_p1="$(gettext '
		It is not possible to remove a resource for which
		explicit network dependencies exist.   And it is not
		possible to modify the \"Network_resources_used\" property
		of a resource after that resource has been created.
		The only way to remove these dependencies is to remove
		the resources themselves which make use of them.
	')"

	typeset tmpfile=${SCSETUP_TMP_RSLIST}
	typeset cachefile=${SCSETUP_RGM_CACHEFILE}

	typeset nopause
	typeset answer
	typeset prompt
	typeset prompt2
	typeset header1
	typeset header2
	typeset rglist
	typeset rgname
	typeset rslist
	typeset resource
	typeset netdep
	typeset netdeps
	typeset dep
	typeset deps
	typeset list
	typeset newlist
	typeset item

	integer commands=0
	integer found
	integer index
	integer disabled

	if [[ -n "${delete}" ]]; then
		nohelp=1
		nopause=1
		resource=${delete}
	fi

	# Unless nohelp is specified, print help and get confirmation
	if [[ -z "${nohelp}" ]]; then

		# Clear screen, print title and help
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"
		sc_print_para "${sctxt_p3}"
		sc_print_para "${sctxt_p4}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Initialize
	prompt="$(gettext 'Select the resource you want to remove:')"
	header1="$(printf "%-25s %s" "$(gettext 'Resource Name')" "$(gettext 'Resource Group')")"
	header2="$(printf "%-25s %s" "=============" "==============")"

	# Loop until done or Ctrl-D is typed
	while [[ -z "${delete}" ]]
	do
		# Get the rglist
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] ||
		    [[ -r "${cachefile}" ]]; then
			rglist="$(scsetup_get_rglist "" "" "" ${cachefile})"
		else
			rglist="rg1 rg2 rg3 rg4 rg5 rg6 rg7 rg8 rg9 rg10 rg11 rg12 rg13 rg14"
		fi

		# Create the temp file
		rm -f ${tmpfile}
		let found=0
		for rgname in ${rglist}
		do
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]];  then
				rslist="$(${SCHA_RG_GET} -G ${rgname} -O resource_list)"
			else
				rslist="${rgname}res1 ${rgname}res2 ${rgname}res3 ${rgname}res4"
			fi
			for resource in ${rslist}
			do
				((found += 1))
				printf "%-25s %s\n" "${resource}" "${rgname}"
			done
		done > ${tmpfile}

		# If the list is empty, we are done
		if [[ ${found} -eq 0 ]]; then
			echo
			printf "$(gettext 'There are no resources configured.')\n"
			printf "$(gettext 'So, there is nothing to remove.')\n\n\a"
			sc_prompt_pause
			rm -f ${tmpfile}
			return 1
		fi

		# Get the name of the resource to delete
		resource="$(
		    sc_get_scrolling_menuoptions	\
			"${prompt}"			\
			"${header1}"			\
			"${header2}"			\
			0 1 1				\
			:${tmpfile}			\
		)"
		rm -f ${tmpfile}

		# Done?
		if [[ -z "${resource}" ]]; then
			return 0
		fi

		# Confirm
		sc_print_para "${sctxt_remove_warning_p1}"
		prompt2="$(printf "$(gettext 'Are you sure you want to remove \"%s\"?')" "${resource}")"
		answer=$(sc_prompt_yesno "${prompt2}" "${YES}") || return 1
		if [[ "${answer}" == "yes" ]]; then
			delete=${resource}
		else
			prompt2="$(gettext 'Do you want to select a different resource to remove?')"
			answer=$(sc_prompt_yesno "${prompt2}" "${NO}") || return 1
			if [[ "${answer}" != "yes" ]]; then
				return 1
			fi
		fi
	done

	# First, see if anyone explicitly depends on us as a network resource
	netdeps=
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
		netdeps="$(scsetup_get_resource_depended_ons ${resource} "" "true")"
	fi
	if [[ -n "${netdeps}" ]]; then
		prompt2="$(printf "$(gettext 'The following resource(s) all have explicit network dependencies on \"%s\":')" "${delete}")"

		# Print the list
		(
			sc_print_para "${prompt2}"
			for netdep in ${netdeps}
			do
				printf "\t${netdep}\n"
			done
			echo
			sc_print_para "${sctxt_netdeps_p1}"
		) | more

		# Confirm
		sc_prompt_pause
		return 1
	fi

	# If the resource is enabled, it must first be disabled.
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
		scsetup_is_resource_enabled ${delete}
		if [[ $? -eq 1 ]]; then
			let disabled=0
			prompt2="$(printf "$(gettext '\"%s\" is still enabled.  You cannot remove a resource as long it remains enabled.')" "${delete}")"
			sc_print_para "${prompt2}"
			prompt2="$(printf "$(gettext 'Is it okay to disable \"%s\"?')" "${delete}")"
			answer=$(sc_prompt_yesno "${prompt2}" "${YES}") || continue
			if [[ "${answer}" == "yes" ]]; then
				scsetup_disable_resource ${delete}
				if [[ $? -eq 0 ]]; then
					let disabled=1
				fi
			fi
			if [[ ${disabled} -ne 1 ]]; then
				printf "$(gettext '\"%s\" must be disabled before it can be removed.')\n\n\a" "${delete}"
				sc_prompt_pause
				return 1
			fi
		fi
	fi

	# Cleanup explicit dependencies
	set -A SCSETUP_DO_CMDSET
	let index=0
	deps=
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
		deps="$(scsetup_get_resource_depended_ons ${resource} "true")"
	fi
	for dep in ${deps}
	do
		# Resource_dependencies
		newlist=
		list="$(${SCHA_RS_GET} -R ${dep} -O resource_dependencies)"
		let found=0
		for item in ${list}
		do
			if [[ "${item}" == "${delete}" ]]; then
				let found=1
				continue
			fi
			if [[ -n "${newlist}" ]]; then
				newlist="${newlist},"
			fi
			newlist="${newlist}${item}"
		done
		if [[ ${found} -eq 1 ]]; then
			SCSETUP_DO_CMDSET[index]="${SC_SCRGADM} -c -j ${dep} -y Resource_dependencies=${newlist}"
			((index += 1))
			((commands += 1))
		fi

		# Resource_dependencies_weak
		newlist=
		list="$(${SCHA_RS_GET} -R ${dep} -O resource_dependencies_weak)"
		let found=0
		for item in ${list}
		do
			if [[ "${item}" == "${delete}" ]]; then
				let found=1
				continue
			fi
			if [[ -n "${newlist}" ]]; then
				newlist="${newlist},"
			fi
			newlist="${newlist}${item}"
		done
		if [[ ${found} -eq 1 ]]; then
			SCSETUP_DO_CMDSET[index]="${SC_SCRGADM} -c -j ${dep} -y Resource_dependencies_weak=${newlist}"
			((index += 1))
			((commands += 1))
		fi

		# Resource_dependencies_restart
		newlist=
		list="$(${SCHA_RS_GET} -R ${dep} -O resource_dependencies_restart)"
		let found=0
		for item in ${list}
		do
			if [[ "${item}" == "${delete}" ]]; then
				let found=1
				continue
			fi
			if [[ -n "${newlist}" ]]; then
				newlist="${newlist},"
			fi
			newlist="${newlist}${item}"
		done
		if [[ ${found} -eq 1 ]]; then
			SCSETUP_DO_CMDSET[index]="${SC_SCRGADM} -c -j ${dep} -y Resource_dependencies_restart=${newlist}"
			((index += 1))
			((commands += 1))
		fi
	done

	# Add the command to remove the resource
	SCSETUP_DO_CMDSET[index]="${SC_SCRGADM} -r -j ${delete}"

	# Do it!
	if [[ ${commands} -gt 0 ]]; then
		scsetup_do_cmdset 1 "${nopause}" "${commands}" || return 1
	else
		scsetup_do_cmdset 1 "${nopause}" || return 1
	fi

	return 0
}

#####################################################
#
# scsetup_enable_resource() resource
#
#	Enable a resource.
#
#	If there are first-level disabled dependencies in the dependency
#	graph which do not, in turn, have other dependencies, we
#	will offer to enable those resources.   However, if there are,
#	in turn, second-level disabled dependencies, we send the user
#	back to the menu to enable those.   This approach is taken
#	primarily to simplify the user interface and to avoid confusion
#	around which resources are actually being enabled.  If we were
#	to support an arbitrary level of enabling of the dependency graph,
#	there is risk that unwanted enabling could easily occur due to user
#	error.	Secondarily, we do not believe that enabling or disabling of a
#	resource is a common occurance, and we do not want to needlessly
#	complicate the code.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_enable_resource()
{
	typeset resource=${1}

	typeset prompt
	typeset dep
	typeset dep2
	typeset deps
	typeset deps2
	typeset disabled_deps
	typeset final_deps_list
	typeset answser
	typeset foo

	integer i

	# Get dependencies
	deps=
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
		deps="$(scsetup_get_resource_dependencies ${resource})"
	fi

	# Get disabled dependencies
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]];  then
		disabled_deps=
		for dep in ${deps}
		do
			scsetup_is_resource_enabled ${dep}
			if [[ $? -eq 0 ]]; then
				disabled_deps="${disabled_deps} ${dep}"
			fi
		done
	fi

	# Are there dependencies on disabled resources?
	if [[ -n "${disabled_deps}" ]]; then
		# Print the list
		prompt="$(printf "$(gettext '\"%s\" has dependencies on the following disabled resource(s):')" "${resource}")"
		(
			sc_print_para "${prompt}"
			for dep in ${disabled_deps}
			do
				printf "\t${dep}\n"
			done
			echo
		) | more

		# See if there is another level of dependencies
		# We only offer to go one level deep, in the dependency
		# graph, in order to simplify the user interface.
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]];  then
			deps2=
			for dep in ${disabled_deps}
			do
				deps2="${deps2} $(scsetup_get_resource_dependencies ${dep})"
			done
			for dep2 in ${deps2}
			do
				scsetup_is_resource_enabled ${dep2}
				if [[ $? -eq 0 ]]; then
					printf "\t${dep2}\n"
					printf "$(gettext 'These resource(s) must be enabled before \"%s\".')\n\n\a" "${resource}"
					return 1
				fi
			done
		fi

		# If we are here, there are no second-level dependencies
		# Is it okay to enable these other first-level dependencies?
		# There is no default provided, as we want the user to take
		# some extra caution.
		answer=$(sc_prompt_yesno "$(gettext 'Is it okay to enable these other resource(s) first?')" "${YES}")
		if [[ "${answer}" == "yes" ]]; then
			set -A SCSETUP_DO_CMDSET

			# To support inter-RG dependencies the whole list of resources
			# to be enabled must be passed to a single scswitch invocation.
			# Assumption is RGM will take care of enabling them in the right order.
			final_deps_list=${resource}
			for dep in ${disabled_deps}
			do
				final_deps_list="${final_deps_list},${dep}"
			done
			SCSETUP_DO_CMDSET[0]="${SC_SCSWITCH} -e -j ${final_deps_list}"
			# Run the commands
			scsetup_do_cmdset 1 1
			if [[ $? -ne 0 ]]; then
				echo
				printf "$(gettext 'All resource dependencies were not enabled.')\n"
				printf "$(gettext 'An error occured in attempting to enable resources \"%s\".')\n" "${resource}"
				printf "$(gettext '\"%s\" has not been enabled.')\n\n\a" "${resource}"
				return 1
			fi
			return 0
		else
			printf "$(gettext 'All resources upon which \"%s\" depends must be enabled first.')\n\n\a" "${resource}"
			return 1
		fi
	fi

	# If we reached it means there are no dependencies on the resource
	# Enable the resource
	set -A SCSETUP_DO_CMDSET
	SCSETUP_DO_CMDSET[0]="${SC_SCSWITCH} -e -j ${resource}"
	scsetup_do_cmdset 1 1 || return 1

	return 0
}

#####################################################
#
# scsetup_disable_resource() resource
#
#	Disable a resource.
#
#	If there are first-level enabled depended-upon dependencies in the
#	dependency graph which do not, in turn, have other depended-upon
#	dependencies, we will offer to disable those resources.   However,
#	if there are, in turn, second-level enabled depended-upon
#	dependencies, we send the user back to the menu to disable those.
#	This is approach is taken primarily to simplify the user interface
#	and to avoid confusion around which resources are actually being
#	disabled.  If we were to support an arbitrary level of disabling
#	of the dependency graph, there is risk that unwanted disabling
#	could easily occur due to user error.  Secondarily, we do not
#	believe that enabling or disabling of a	resource is a common
#	occurance, and we do not want to needlessly complicate the code.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_disable_resource()
{
	typeset resource=${1}

	typeset prompt
	typeset dep
	typeset dep2
	typeset deps
	typeset deps2
	typeset enabled_deps
	typeset final_deps_list
	typeset answser
	typeset foo

	integer i

	# Get depended-upon dependencies
	deps=
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
		deps="$(scsetup_get_resource_depended_ons ${resource})"
	fi

	# Get enabled depended-upon dependencies
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]];  then
		enabled_deps=
		for dep in ${deps}
		do
			scsetup_is_resource_enabled ${dep}
			if [[ $? -eq 1 ]]; then
				enabled_deps="${enabled_deps} ${dep}"
			fi
		done
	fi

	# Are there depended-upon enabled dependencies?
	if [[ -n "${enabled_deps}" ]]; then
		# Print list
		prompt="$(printf "$(gettext '\"%s\" is depended upon by the following enabled resource(s):')" "${resource}")"
		(
			sc_print_para "${prompt}"
			for dep in ${enabled_deps}
			do
				printf "\t${dep}\n"
			done
		) | more

		# See if there is another level of dependencies
		# We only offer to go one level deep, in in the dependency
		# graph, in order to simplify the user interface.
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]];  then
			deps2=
			for dep in ${enabled_deps}
			do
				deps2="${deps2} $(scsetup_get_resource_depended_ons ${dep})"
			done
			for dep2 in ${deps2}
			do
				scsetup_is_resource_enabled ${dep2}
				if [[ $? -eq 1 ]]; then
					printf "\t${dep2}\n"
					printf "$(gettext 'These resource(s) must be disabled before \"%s\".')\n\n\a" "${resource}"
					return 1
				fi
			done
		fi

		# If we are here, there are no second-level depended-upon
		# dependencies.  Is it okay to disable these other first-level
		# dependencies?  There is no default provided, as we want the
		# user to take some extra caution.
		answer=$(sc_prompt_yesno "$(gettext 'Is it okay to disable these other resource(s) first?')" "${YES}")
		if [[ "${answer}" == "yes" ]]; then
			set -A SCSETUP_DO_CMDSET

			# To support inter-RG dependencies the whole list of resources
			# to be disabled must be passed to a single scswitch invocation.
			# Assumption is RGM will take care of disabling them in the right order.

			final_deps_list=${resource}
			for dep in ${enabled_deps}
			do
				final_deps_list="${final_deps_list},${dep}"
			done
			SCSETUP_DO_CMDSET[0]="${SC_SCSWITCH} -n -j ${final_deps_list}"

			# Run the commands, no confirmation
			scsetup_do_cmdset 1 1
			if [[ $? -ne 0 ]]; then
				echo
				printf "$(gettext 'All resource dependencies were not disabled.')\n"
				printf "$(gettext 'These resource(s) must be disabled before \"%s\".')\n" "${resource}"
				printf "$(gettext '\"%s\" has not been disabled.')\n\n\a" "${resource}"
				return 1
			fi
			return 0
		else
			printf "$(gettext 'All resources which depend upon \"%s\" must be disabled first.')\n\n\a" "${resource}"
			return 1
		fi
	fi

	# If we reached it means there are no dependencies on the resource
	# Disable the resource
	set -A SCSETUP_DO_CMDSET
	SCSETUP_DO_CMDSET[0]="${SC_SCSWITCH} -n -j ${resource}"
	scsetup_do_cmdset 1 1 || return 1

	return 0
}

#####################################################
#
# scsetup_disable_resources() rgname
#
#	Attempt to disable all resources in a resource group.
#
#	Return:
#		zero		Completed
#		non-zero	Not successful
#
#####################################################
scsetup_disable_resources()
{
	typeset rgname=${1}

	typeset enabled_list
	typeset enabled_net_list
	typeset resource
	typeset rslist
	typeset rstype
	typeset deps

	integer count

	# Must be a cluster member
	if [[ ${SCSETUP_ISMEMBER} -ne 1 ]];  then
		return 0
	fi

	# Get the resource list for this group
	rslist="$(${SCHA_RG_GET} -G ${rgname} -O resource_list)"

	#
	# Get the list of enabled resources in this group.
	#
	# We want to disable resources in some sort of order.  Network
	# resources should be disabled last.  Without constructing the
	# complete dependency graph, we make a simple assumption that the
	# resources with the least number of dependencies on them should
	# be disabled first.   This assumption will not always work, but
	# it is a good best effort.
	#
	enabled_list=
	enabled_net_list=
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
		for resource in ${rslist}
		do
			# If it is not enabled, skip it
			scsetup_is_resource_enabled ${resource}
			if [[ $? -ne 1 ]]; then
				continue
			fi

			# See if it is a network resource
			rstype="$(${SCHA_RS_GET} -R ${resource} -O type)"
			scsetup_is_network_rstype ${rstype}
			if [[ $? -eq 1 ]]; then
				enabled_net_list="${enabled_net_list} ${resource}"
				continue
			fi

			#
			# Add a weighting prefix to it, indicating
			# the number of resources depending upon us
			#
			count=0
			deps="$(scsetup_get_resource_depended_ons ${resource})"
			if [[ -n "${deps}" ]]; then
				count=$(set -- ${deps}; echo $#)
			fi
			enabled_list="${enabled_list} ${count}:${resource}"
		done
	fi

	# Sort the enabled list by weighting prefix, then strip the prefix
	enabled_list="$(
		for resource in ${enabled_list}
		do
			echo ${resource}
		done | sort -n | awk -F: '{ print $2 }'
	)"

	# Add the net list
	enabled_list="${enabled_list} ${enabled_net_list}"
	enabled_list="$(echo ${enabled_list})"

	# Disable each resource
	let count=0
	for resource in ${enabled_list}
	do
		# Make sure it is still disabled, since
		# scsetup_disable_resource() can give the user the
		# oportunity to disable more resources.
		scsetup_is_resource_enabled ${resource}
		if [[ $? -ne 1 ]]; then
			continue
		fi

		# Disable the resource
		scsetup_disable_resource ${resource}
		if [[ $? -ne 0 ]]; then
			printf "$(gettext 'Failed to disable \"%s\".')\n" "${resource}"
			((count += 1))
		fi
	done

	if [[ ${count} -gt 0 ]]; then
		echo "\a"
	fi

	return ${count}
}

#####################################################
#
# scsetup_menu_rgm_rs_enable_disable() [nohelp]
#
#	nohelp		- if this flag is given, do not
#			    clear screen, print title, print help,
#			    or ask for confirmation to continue
#
#	Enable/disable a resource.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_rgm_rs_enable_disable()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Enable or Disable a Resource <<<
	')"
	typeset sctxt_p1="$(gettext '
		Use this option to either enable or disable a resource.
	')"
	typeset sctxt_p2="$(gettext '
		Once a resource is enabled in an online resource group,
		the resource becomes available to clients.  Before a
		resource can be enabled, all resources upon which it
		depends must also first be enabled.
	')"
	typeset sctxt_p3="$(gettext '
		Once a resource is disabled, the resource is no longer
		available to clients of that resource.   Before a
		resource can be disabled, all resources which depend
		upon it must also first be disabled.
	')"
	typeset sctxt_disable_warning_p1="$(gettext '
		Remember that once a resource is disabled, the resource
		is no longer available to clients of that resource.
		Clients which depend upon that resource will experience
		a loss of service.
	')"

	typeset tmpfile=${SCSETUP_TMP_RSLIST}

	typeset prompt
	typeset header1
	typeset header2

	typeset prompt2
	typeset answer
	typeset resource
	typeset state

	integer found

	# Unless nohelp is specified, print help and get confirmation
	if [[ -z "${nohelp}" ]]; then

		# Clear screen, print title and help
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"
		sc_print_para "${sctxt_p3}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Initialize
	prompt="$(gettext 'Select the resource for which you want to make a state change:')"
	header1="$(printf "%-25s %-16.16s" "$(gettext 'Resource Name')" "$(gettext 'Resource State')")"
	header2="$(printf "%-25s %-16.16s" "=============" "==============")"

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Get the list of resources
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] ||
		    [[ -r "${cachefile}" ]];  then
			rslist="$(scsetup_get_rslist "" "" ${cachefile})"
		else
			rslist="res1 res2 res3 res4 res5 res6 res7 res8 res9 res10"
		fi

		# Create the temp file
		rm -f ${tmpfile}
		let found=0
		for resource in ${rslist}
		do
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]];  then
				scsetup_is_resource_enabled ${resource}
				case $? in
				1)	state="Enabled" ;;
				0)	state="Disabled" ;;
				*)	state=
					((found -= 1))
					continue
					;;
				esac
			else
				state="<DEBUG>"
			fi
			((found += 1))
			printf "%-25s %-16.16s\n" "${resource}" "${state}"
		done > ${tmpfile}

		# Are there any resources?
		if [[ ${found} -lt 1 ]]; then
			echo
			printf "$(gettext 'There are no resources configured.')\n"
			printf "$(gettext 'So, there is nothing to Enable/Disable.')\n\n\a"
			sc_prompt_pause
			rm -f ${tmpfile}
			return 1
		fi

		# Get the name of the resource to change
		resource="$(
		    sc_get_scrolling_menuoptions	\
			"${prompt}"			\
			"${header1}"			\
			"${header2}"			\
			0 1 1				\
			:${tmpfile}			\
		)"
		rm -f ${tmpfile}

		# Done?
		if [[ -z "${resource}" ]]; then
			return 0
		fi

		# Enable or disable?
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			scsetup_is_resource_enabled ${resource}
			case $? in
			1)	state="Enabled" ;;
			0)	state="Disabled" ;;
			*)	state= ;;
			esac
		else
			state="Debug"
		fi
		if [[ "${state}" == "Enabled" ]] ||
		    [[ "${state}" == "Debug" ]]; then
			sc_print_para "${sctxt_disable_warning_p1}"
			prompt2="$(printf "$(gettext 'Are you sure you want to disable \"%s\"?')" "${resource}")"
			answer=$(sc_prompt_yesno "${prompt2}" "${YES}") || continue
			if [[ "${answer}" == "yes" ]]; then
				scsetup_disable_resource ${resource}
				sc_prompt_pause
				continue
			fi
		fi
		if [[ "${state}" == "Disabled" ]] ||
		    [[ "${state}" == "Debug" ]]; then
			prompt2="$(printf "$(gettext 'Do you want to enable \"%s\"?')" "${resource}")"
			answer=$(sc_prompt_yesno "${prompt2}" "${YES}") || continue
			if [[ "${answer}" == "yes" ]]; then
				scsetup_enable_resource ${resource}
				sc_prompt_pause
				continue
			fi
		fi
		prompt2="$(gettext 'Do you want to select a different resource?')"
		answer=$(sc_prompt_yesno "${prompt2}" "${NO}") || return 1
		if [[ "${answer}" != "yes" ]]; then
			return 1
		fi
	done

	return 0
}

#####################################################
#
# scsetup_menu_rgm_rs_clear() [nohelp]
#
#	nohelp		- if this flag is given, do not
#			    clear screen, print title, print help,
#			    or ask for confirmation to continue
#
#	Clear resource STOP_FAILED error flags.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_rgm_rs_clear()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Clear the STOP_FAILED Error Flag from a Resource <<<
	')"
	typeset sctxt_p1="$(gettext '
		Use this option to clear the STOP_FAILED error flag
		from a resource.  Clearing the STOP_FAILED error flag
		places the resource into the offline state on the
		specified nodes.
	')"

	typeset tmpfile=${SCSETUP_TMP_RSLIST}
	typeset cachefile=${SCSETUP_RGM_CACHEFILE}

	typeset prompt
	typeset header1
	typeset header2
	typeset answer
	typeset rslist
	typeset resource
	typeset nodelist
	typeset nodename

	integer found

	# Unless nohelp is specified, print help and get confirmation
	if [[ -z "${nohelp}" ]]; then

		# Clear screen, print title and help
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Initialize
	prompt="$(gettext 'Select the resource whose STOP_FAILED flag you want to clear:')"
	header1="$(printf "%-25s %-14s %-20s" "$(gettext 'Resource Name')" "$(gettext 'Error Flag')" "$(gettext 'Node')")"
	header2="$(printf "%-25s %-14s %-20s" "=============" "==========" "====")"

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Get the list of resources
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] ||
		    [[ -r "${cachefile}" ]];  then
			rslist="$(scsetup_get_rslist "" "" ${cachefile})"
		else
			rslist="res1 res2 res3 res4"
		fi

		# Create the temp file
		rm -f ${tmpfile}
		let found=0
		for resource in ${rslist}
		do
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]];  then
				nodelist="$(scsetup_is_resource_stop_failed ${resource})"
			else
				nodelist="node1 node2"
			fi
			for nodename in ${nodelist}
			do
				((found += 1))
				printf "%-25s %-14s %-20s\n" "${resource}" "STOP_FAILED" "${nodename}"
			done
		done > ${tmpfile}

		# Are there any resources?
		if [[ ${found} -lt 1 ]]; then
			echo
			printf "$(gettext 'There are no resources with the STOP_FAILED error flag set.')\n"
			printf "$(gettext 'So, there is nothing to clear.')\n\n\a"
			sc_prompt_pause
			rm -f ${tmpfile}
			return 1
		fi

		# Get the name of the resource to clear
		answer="$(
		    sc_get_scrolling_menuoptions	\
			"${prompt}"			\
			"${header1}"			\
			"${header2}"			\
			0 1 3				\
			:${tmpfile}			\
		)"
		rm -f ${tmpfile}

		# Done?
		if [[ -z "${answer}" ]]; then
			return 0
		fi
		resource=$(IFS=: ; set -- ${answer}; echo ${1})
		nodename=$(IFS=: ; set -- ${answer}; echo ${3})

		# Clear STOP_FAILED
		set -A SCSETUP_DO_CMDSET
		SCSETUP_DO_CMDSET[0]="${SC_SCSWITCH} -c -h ${nodename} -j ${resource} -f STOP_FAILED"
		scsetup_do_cmdset || return 1
		break
	done

	return 0
}

#####################################################
#
# scsetup_menu_rgm_status()
#
#	Print status
#
#	This function always returns zero.
#
#####################################################
scsetup_menu_rgm_status()
{
	typeset tmpfile=${SCSETUP_TMP_SCSTAT}

	echo
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
		rm -f ${tmpfile}
		${SC_SCSTAT} -g >${tmpfile}
		if [[ -s "${tmpfile}" ]]; then
			more ${tmpfile}
		else
			printf "$(gettext 'There are no configured resource groups.')\n\n\a"
		fi
		rm -f ${tmpfile}
	else
		echo "DEBUG:  Not a cluster member - no status."
	fi
	sc_prompt_pause

	return 0
}

#####################################################
#
# scsetup_help_rgm_menu()
#
#	Print help information from the rgm menu.
#	This is the same help information as is printed
#	from the MAIN RGM help menu.  But, we ask for confirmation
#	before returning to the previous menu.
#
#	This function always returns zero.
#
#####################################################
scsetup_help_rgm_menu()
{
	clear
	scsetup_help_main_rgm
	sc_prompt_pause

	return 0
}

#####################################################
#
# scsetup_get_rgm_menuoption()
#
#	Print the RGM menu, and return the selected option.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_rgm_menuoption()
{
	typeset sctxt_title_1="$(gettext '*** Resource Group Menu ***')"
	typeset sctxt_title_2="$(gettext 'Please select from one of the following options:')"
	typeset sctxt_option_001="$(gettext 'Create a resource group')"
	typeset sctxt_option_002="$(gettext 'Add a network resource to a resource group')"
	typeset sctxt_option_003="$(gettext 'Add a data service resource to a resource group')"
	typeset sctxt_option_004="$(gettext 'Resource type registration')"
	typeset sctxt_option_005="$(gettext 'Online/Offline or Switchover a resource group')"
	typeset sctxt_option_006="$(gettext 'Enable/Disable a resource')"
	typeset sctxt_option_007="$(gettext 'Change properties of a resource group')"
	typeset sctxt_option_008="$(gettext 'Change properties of a resource')"
	typeset sctxt_option_009="$(gettext 'Remove a resource from a resource group')"
	typeset sctxt_option_010="$(gettext 'Remove a resource group')"
	typeset sctxt_option_011="$(gettext 'Clear the stop_failed error flag from a resource')"
	typeset sctxt_option_help="$(gettext 'Help')"
	typeset sctxt_option_status="$(gettext 'Show current status')"
	typeset sctxt_option_return="$(gettext 'Return to the main menu')"

	typeset option

	# Return
	option=$(sc_get_menuoption \
		"T1+++${sctxt_title_1}" \
		"T2+++${sctxt_title_2}" \
		"S+0+1+${sctxt_option_001}" \
		"S+0+2+${sctxt_option_002}" \
		"S+0+3+${sctxt_option_003}" \
		"S+0+4+${sctxt_option_004}" \
		"S+0+5+${sctxt_option_005}" \
		"S+0+6+${sctxt_option_006}" \
		"S+0+7+${sctxt_option_007}" \
		"S+0+8+${sctxt_option_008}" \
		"S+0+9+${sctxt_option_009}" \
		"S+0+10+${sctxt_option_010}" \
		"S+0+11+${sctxt_option_011}" \
		"R+++" \
		"S+0+?+${sctxt_option_help}" \
		"S+0+s+${sctxt_option_status}" \
		"S+0+q+${sctxt_option_return}" \
	)

	echo "${option}"

	return 0
}

#####################################################
#
# scsetup_menu_rgm()
#
#	RGM menu.
#
#	This function always returns zero.
#
#####################################################
scsetup_menu_rgm()
{
	typeset cachefile=${SCSETUP_RGM_CACHEFILE}

	# Loop around the RGM RG menu
	while true
	do
		# Just to be safe, clean up any possible cachefile
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			scsetup_rm_scrgadmfile ${cachefile}
		fi

		# Do it
		case $(scsetup_get_rgm_menuoption) in
		'1')	scsetup_menu_rgm_rg_create ;;
		'2')	scsetup_menu_rgm_rs_addnet ;;
		'3')	scsetup_menu_rgm_rs_addds ;;
		'4')	scsetup_menu_rgm_rt_registration ;;
		'5')	scsetup_menu_rgm_rg_online_offline ;;
		'6')	scsetup_menu_rgm_rs_enable_disable ;;
		'7')	scsetup_menu_rgm_rg_changeproperties ;;
		'8')	scsetup_menu_rgm_rs_changeproperties ;;
		'9')	scsetup_menu_rgm_rs_delete ;;
		'10')	scsetup_menu_rgm_rg_delete ;;
		'11')	scsetup_menu_rgm_rs_clear ;;
		'?')	scsetup_help_rgm_menu ;;
		's')	scsetup_menu_rgm_status ;;
		'q')	break ;;
                esac 
	done

	return 0
}

#####################################################
#####################################################
##
## Cluster transport
##
#####################################################
#####################################################

#####################################################
#
# scsetup_prompt_transport_adapter() "[prompt]"
#
#	Prompt for the transport adapter name, then
#	perform simple verification.  If "prompt" is not given,
#	a default prompt is used.
#
#	The prompt is printed on file descriptor 4, and the answer
#	is printed to stdout.  File descriptor 4 should be
#	dupped to the original stdout before this function is called.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_prompt_transport_adapter()
{
	typeset prompt="${1}"

	typeset dflt_prompt="$(gettext 'Name of adapter?')"
	typeset answer

	# If no prompt is given, use the default
	if [[ -z "${prompt}" ]]; then
		prompt="${dflt_prompt}"
	fi

	#
	# The caller of this function should have already opened
	# descriptor 4 as a dup of the original stdout.
	#
	# Dup this function's stdout to descriptor 5.
	# Then, re-direct stdout to descriptor 4.
	#
	# So, the default stdout from this function will go to
	# the original stdout (probably the tty).  Descriptor 5
	# has the answer printed to it.
	#
	exec 5>&1
	exec 1>&4

	# Loop until we get the value or Ctrl-D is typed
	while true
	do
		# Get the adapter name
		answer=$(sc_prompt "${prompt}") || return 1

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

		# okay
		echo ${answer} >&5
		break
	done

	return 0
}

#####################################################
#
# scsetup_prompt_transport_junction() "[prompt]"
#
#	Prompt for the transport junction name, then
#	perform simple verification.  If "prompt" is not given,
#	a default prompt is used.
#
#	The prompt is printed on file descriptor 4, and the answer
#	is printed to stdout.  File descriptor 4 should be
#	dupped to the original stdout before this function is called.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_prompt_transport_junction()
{
	typeset prompt="${1}"

	typeset dflt_prompt="$(gettext 'Name of cluster transport junction?')"
	typeset answer

	# If no prompt is given, use the default
	if [[ -z "${prompt}" ]]; then
		prompt="${dflt_prompt}"
	fi

	#
	# The caller of this function should have already opened
	# descriptor 4 as a dup of the original stdout.
	#
	# Dup this function's stdout to descriptor 5.
	# Then, re-direct stdout to descriptor 4.
	#
	# So, the default stdout from this function will go to
	# the original stdout (probably the tty).  Descriptor 5
	# has the answer printed to it.
	#
	exec 5>&1
	exec 1>&4

	# Loop until we get the value or Ctrl-D is typed
	while true
	do
		# Get the junction name
		answer=$(sc_prompt "${prompt}") || return 1

		# 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
		echo ${answer} >&5
		break
	done

	return 0
}

#####################################################
#
# scsetup_prompt_transport_endpoint()
#
#	Get the adapter endpoint of an existing transport cable.
#
#	The prompt is printed on file descriptor 4, and the answer
#	is printed to stdout.  File descriptor 4 should be
#	dupped to the original stdout before this function is called.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_prompt_transport_endpoint()
{
	typeset answer

	typeset sctxt_p1="$(gettext '
		Each existing cluster transport cable can be
		identified by naming one of the cable endpoints.
		Since one of the two endpoints is always attached to a
		node, you will be asked to supply the node and adapter
		names of one of the endpoints of the cable you are
		trying to identify.
	')"

	integer found
	typeset nodelist
	typeset nodename
	typeset adapterlist
	typeset adaptername
	typeset adapter
	typeset endpointlist
	typeset endpoint
	typeset prompt
	typeset answer

	#
	# The caller of this function should have already opened
	# descriptor 4 as a dup of the original stdout.
	#
	# Dup this function's stdout to descriptor 5.
	# Then, re-direct stdout to descriptor 4.
	#
	# So, the default stdout from this function will go to
	# the original stdout (probably the tty).  Descriptor 5
	# has the answer printed to it.
	#
	exec 5>&1
	exec 1>&4

	# Print help
	sc_print_para "${sctxt_p1}"

	# Loop until we get the value or Ctrl-D is typed
	while true
	do
		# Get nodelist
		nodelist=
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then

			# Get nodelist
			nodelist="$(scsetup_get_nodelist)"

			# Make sure we have a nodelist
			if [[ -z "${nodelist}" ]]; then
				printf "$(gettext 'Unable to establish the list of cluster nodes.')\n\n\a"
				sc_prompt_pause
				return 1
			fi
		fi

		# Get the node name for the endpoint
		answer=$(scsetup_prompt_nodename "${nodelist}" "$(gettext 'To which node is the cable attached?')") || return 1
		nodename=${answer}

		# Get the adaptername
		prompt="$(printf "$(gettext 'Name of the adapter on \"%s\"?')" "${nodename}")"
		while true
		do
			# Prompt for adapter name
			answer=$(scsetup_prompt_transport_adapter "${prompt}") || continue 2

			# Get the list of configured adapters for this node
			adapterlist=
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
				adapterlist="$(scsetup_get_adapterlist ${nodename})"
			fi

			# See if this adapter is configured
			let found=0
			for adapter in ${adapterlist}
			do
				if [[ "${answer}" = "${adapter}" ]]; then
					let found=1
					break
				fi
			done

			#
			# If there is a adapterlist, but the adapter
			# is not found, print error.
			#
			if [[ -n "${adapterlist}" ]] && [[ ${found} -eq 0 ]]; then
				printf "$(gettext 'Unknown adapter.')\n\n\a"
				continue
			fi

			# Okay
			adaptername=${answer}
			break
		done

		# Get the list of configured endpoints
		endpointlist=
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			endpointlist="$(scsetup_get_endpoints)"
		fi

		# See if this endpoint is configured
		let found=0
		answer="${nodename}:${adaptername}@0"
		for endpoint in ${endpointlist}
		do
			if [[ "${answer}" = "${endpoint}" ]]; then
				let found=1
				break
			fi
		done
		answer="${nodename}:${adaptername}"

		#
		# If there is an endpointlist, but the endpoint
		# is not found, print error.
		#
		if [[ -n "${endpointlist}" ]] && [[ ${found} -eq 0 ]]; then
			printf "$(gettext 'Unknown cable.')\n\n\a"
			continue
		fi

		# okay
		echo ${answer} >&5
		break
	done

	return 0
}

#####################################################
#
# scsetup_menu_transport_addcable() [nohelp]
#
#	nohelp		- if this flag is given, do not
#			    clear screen, print title, print help,
#			    or ask for confirmation to continue
#
#	Add a cluster transport cable to the cluster, along with
#	any necessary adapters and junctions used to create the cable.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_transport_addcable()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Add a Cluster Transport Cable <<<
	')"
        typeset sctxt_p1="$(gettext '
		Each cluster transport cable either directly connects
		two cluster nodes or connects a cluster node to a port
		on a transport junction.  Only two-node clusters may
		use directly-connected cables;  all cables on clusters
		with more than two nodes must be cabled to junctions.
	')"
	typeset sctxt_p2="$(gettext '
		This option is used to add a new cluster transport
		cable to the cluster configuration.  If either of the
		two endpoints of the cable do not already exist,
		they will also be added to the configuration.
	')"
	typeset sctxt_p1_directconnect="$(gettext '
		Since this is a two-node cluster, direct-connect cabling
		of the transport cables may be supported.  Refer to the
		documentation for your cluster transport adapters for
		more information on whether or not your hardware supports
		direct-connect cabling.  Some adapter types may require
		the use of junctions even on two-node clusters.
	')"
	typeset sctxt_p2_directconnect="$(gettext '
		Note that direct-connect cabling can complicate the
		later addition of a third node to the cluster.
	')"
	typeset sctxt_p1_selected_direct="$(gettext '
		Since the cable you are adding is a direct-connect
		cable, each cable endpoint must be attached directly to
		an adapter on each of the two nodes in the cluster.
		You will be asked to supply the names of each of these
		two adapters.
	')"
	typeset sctxt_p1_not_directconnect="$(gettext '
		Since there are more than two nodes in this cluster,
		all transport cables must have one end connected to
		a transport adapter on a node and the other end connected
		to a port on a cluster transport junction.  Direct-connect
		cabling is not supported on clusters with greater than
		two nodes.
	')"
	typeset sctxt_p1_selected_not_direct="$(gettext '
		Since the cable you are adding is not a direct-connect cable,
		one end must be attached to a node and the other attached
		to a cluster transport junction.  You will be asked to
		supply the name of the node and adapter for the first
		endpoint, as well as the name of the junction and port
		for the second endpoint.
	')"
	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 certain junction types, you may allow scsetup
		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 '
		Please remember that some types of cluster transport
		junctions are not compatible with the default port
		naming assignments.  For more information regarding
		port naming requirements, refer to the
		scconf_transp_jct family of man pages (for example,
		scconf_transp_jct_dolphinswitch(1M)).
	')"
	typeset sctxt_prompt_dfltport="$(gettext '
		Okay to use the default for this cable connection?
	')"

	integer twonodes
	integer directconnect
	integer index1
	integer index2
	integer found
	typeset trtype
	typeset list
	typeset nodelist
	typeset adapterlist
	typeset junctionlist
	typeset node
	typeset adapter
	typeset junction
	typeset endpoint_nodelist
	typeset endpoint_adapterlist
	typeset endpoint_junction
	typeset endpoint_junctionport
	typeset answer
	typeset prompt
	typeset thisadapterdriver
	typeset thisadapter

	#
	# Print title
	#
	if [[ -z "${nohelp}" ]]; then
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Initialize
		let twonodes=0
		let directconnect=0
		trtype=
		nodelist=
		adapterlist=
		endpoint_nodelist=
		endpoint_adapterlist=

		# Get nodelist, twonodes, and trtype
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then

			# Get nodelist
			nodelist="$(scsetup_get_nodelist)"

			# Make sure we have a nodelist
			if [[ -z "${nodelist}" ]]; then
				printf "$(gettext 'Unable to establish the list of cluster nodes.')\n\n\a"
				sc_prompt_pause
				return 1
			fi

			# Set "twonodes" based on number of nodes in node list
			if [[ $(set -- ${nodelist}; echo $#) -eq 2 ]]; then
				let twonodes=1
			fi

			# Get trtype
			trtype="$(scsetup_get_trtypes)"

			# Make sure we have only one transport type
			if [[ -z "${trtype}" ]]; then
				printf "$(gettext 'Unable to determine transport type.')\n\n\a"
				sc_prompt_pause
				return 1
			fi
			if [[ $(set -- ${trtype}; echo $#) -gt 1 ]]; then
				printf "$(gettext 'Scsetup does not support clusters with mixed transport types.')\n\n\a"
				sc_prompt_pause
				return 1
			fi
		else
			# We must be running in DEBUG mode
			answer=$(sc_prompt_yesno "$(gettext 'DEBUG:  Is this a two-node cluster?')" "${YES}") || return 1
			if [[ "${answer}" = "yes" ]]; then
				let twonodes=1

				#
				# Since this is just DEBUG mode, we do
				# not error-check node name responses.
				#
				answer=$(sc_prompt "$(gettext 'DEBUG:  What is the name of the first node?')" "node1") || return 1
				nodelist="${answer}"

				answer=$(sc_prompt "$(gettext 'DEBUG:  What is the name of the second node?')" "node2") || return 1
				nodelist="${nodelist} ${answer}"
			fi

			# Since this is just DEBUG mode, do not check trtype
			answer=$(sc_prompt "$(gettext 'DEBUG:  What transport type are you using?')" "dlpi") || return 1
			trtype=${answer}
		fi

		# Two node clusters may be directly connected.
		if [[ ${twonodes} -eq 1 ]]; then
			sc_print_para "${sctxt_p1_directconnect}"
			sc_print_para "${sctxt_p2_directconnect}"
			answer=$(sc_prompt_yesno "$(gettext 'Are you adding a directly-connected cable?')" "${NO}") || return 1
			if [[ "${answer}" = "yes" ]]; then
				let directconnect=1
			fi
		else
			sc_print_para "${sctxt_p1_not_directconnect}"
		fi

		# Direct connect
		if [[ ${directconnect} -eq 1 ]]; then

			# Print help
			sc_print_para "${sctxt_p1_selected_direct}"

			# Get the two adapters for the two nodes
			endpoint_nodelist="${nodelist}"
			endpoint_adapterlist=
			for node in ${endpoint_nodelist}
			do
				# Get the adapter name
				while true
				do
					prompt="$(printf "$(gettext 'Name of the adapter to use on \"%s\"?')" "${node}")"
					answer=$(scsetup_prompt_transport_adapter "${prompt}") || return 1
					thisadapterdriver=$(expr ${answer} : '\([a-z]*\)')
					if [[ "${thisadapterdriver}" = "${SCSETUP_WILDCAT_ADAPTER}" ]]; then
						printf "$(gettext 'WCI transport adapters cannot be configured without junctions.')\n\n\a"
						continue;
					fi
					break
				done

				# add it to the list
				endpoint_adapterlist="${endpoint_adapterlist} ${answer}"
			done

		# NOT direct connect
		else
			# Print help
			sc_print_para "${sctxt_p1_selected_not_direct}"

			# Get the node name for first endpoint
			answer=$(scsetup_prompt_nodename "${nodelist}" "$(gettext 'To which node do you want to add the cable?')") || return 1
			endpoint_nodelist=${answer}

			# Get the adapter name for first endpoint
			prompt="$(printf "$(gettext 'Name of the adapter to use on \"%s\"?')" "${endpoint_nodelist}")"
			answer=$(scsetup_prompt_transport_adapter "${prompt}") || return 1
			endpoint_adapterlist="${endpoint_adapterlist} ${answer}"

			# if Wildcat, we know the Junction name
			thisadapter=${answer}
			thisadapterdriver=$(expr ${answer} : '\([a-z]*\)')

			if [[ "${thisadapterdriver}" = "${SCSETUP_WILDCAT_ADAPTER}" ]]; then
				thisadapterinst=$(expr ${answer} : '[a-z]*\([0-9]*\)')
				answer=${SCSETUP_WILDCAT_JUNCTION}${thisadapterinst}
				text="$(printf "$(gettext 'Adapter \"%s\" is connected to virtual switch \"%s\".')" "${thisadapter}" "${answer}")"
				sc_print_para "${text}"
			# Otherwise, the user specifies the Junction name
			else
				# Get the name of the junction for the second endpoint
				answer=$(scsetup_prompt_transport_junction "$(gettext 'Name of the junction at the other end of the cable?')") || return 1
			fi

			endpoint_junction=${answer}
			# Use default junction ports?
			sc_print_para "${sctxt_p1_dfltport}"
			sc_print_para "${sctxt_p2_dfltport}"
			answer=$(sc_prompt_yesno "${sctxt_prompt_dfltport}" "${YES}") || return 1

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

			# otherwise, prompt for the name
			else
				answer=$(sc_prompt "$(gettext 'What is the name of the port you want to use?')") || return 1
			fi
			endpoint_junctionport=${answer}
		fi

		#
		# Set up the command set
		#

		# Initialize
		set -A SCSETUP_DO_CMDSET
		let index1=0

		# Create any needed adapters
		set -A list ${endpoint_adapterlist}
		let index2=0
		for node in ${endpoint_nodelist}
		do
			# Get the list of configured adapters for this node
			adapterlist=
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
				adapterlist="$(scsetup_get_adapterlist ${node})"
			fi

			# See if our adapter is already configured
			let found=0
			for adapter in ${adapterlist}
			do
				if [[ "${list[index2]}" = "${adapter}" ]]; then
					let found=1
					break
				fi
			done

			# If not, add command to create adapter
			if [[ ${found} -eq 0 ]]; then
				SCSETUP_DO_CMDSET[index1]="${SC_SCCONF} -a -A trtype=${trtype},name=${list[index2]},node=${node}"
				((index1 += 1))
			fi

			# Next
			((index2 += 1))
		done

		# Create any needed junctions
		if [[ -n ${endpoint_junction} ]]; then

			# Get the list of configured junctions
			junctionlist=
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
				junctionlist="$(scsetup_get_junctionlist)"
			fi

			# See if our junction is already configured
			let found=0
			for junction in ${junctionlist}
			do
				if [[ "${endpoint_junction}" = "${junction}" ]]; then
					let found=1
					break
				fi
			done

			# If not, add command to create junction
			if [[ ${found} -eq 0 ]]; then
				SCSETUP_DO_CMDSET[index1]="${SC_SCCONF} -a -B type=switch,name=${endpoint_junction}"
				((index1 += 1))
			fi
		fi

		# Add command to create cable
		SCSETUP_DO_CMDSET[index1]="${SC_SCCONF} -a -m "
		set -A list ${endpoint_adapterlist}
		let index2=0

		# Add all node endpoints
		for node in ${endpoint_nodelist}
		do
			# Add adapter endpoint to command
			if [[ ${index2} -gt 0 ]]; then
				SCSETUP_DO_CMDSET[index1]="${SCSETUP_DO_CMDSET[index1]},"
			fi
			SCSETUP_DO_CMDSET[index1]="${SCSETUP_DO_CMDSET[index1]}endpoint=${node}:${list[index2]}"

			# Next
			((index2 += 1))
		done

		# Add the junction endpoint
		if [[ -n "${endpoint_junction}" ]]; then
			SCSETUP_DO_CMDSET[index1]="${SCSETUP_DO_CMDSET[index1]},endpoint=${endpoint_junction}"

			# And, the junction endpoint port
			if [[ -n "${endpoint_junctionport}" ]] &&
			    [[ "${endpoint_junctionport}" != "@" ]]; then
				SCSETUP_DO_CMDSET[index1]="${SCSETUP_DO_CMDSET[index1]}@${endpoint_junctionport}"
			fi
		fi

		# Attempt to issue the command(s)
		scsetup_do_cmdset || return 1

		# Done
		break
	done

	return 0
}

#####################################################
#
# scsetup_menu_transport_addjunction() [nohelp]
#
#	nohelp		- if this flag is given, do not
#				clear screen, print title, print help,
#				or ask for confirmation to continue.
#
#	Add a cluster transport junction to the cluster.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_transport_addjunction()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Add a Cluster Transport Junction <<<
	')"
	typeset sctxt_p1="$(gettext '
		This option is used to add a new cluster transport
		junction to the cluster configuration.
	')"

	typeset junctionlist
	typeset junctionname
	typeset junction
	typeset answer
	typeset prompt

	#
	# Print title
	#
	if [[ -z "${nohelp}" ]]; then
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Get the junctionname
		while true
		do
			# Prompt for junction name
			answer=$(scsetup_prompt_transport_junction "$(gettext 'Name of the junction to add?')") || return 1

			# Get the list of configured junctions
			junctionlist=
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
				junctionlist="$(scsetup_get_junctionlist)"
			fi

			# See if our junction is already configured
			for junction in ${junctionlist}
			do
				if [[ "${answer}" = "${junction}" ]]; then
					printf "$(gettext 'Junction \"%s\" is already configured on \"%s\".')\n\n\a" "${answer}" "${nodename}"
					continue 2
				fi
			done

			# Okay
			junctionname=${answer}
			break
		done

		#
		# Set up the command set
		#

		# Initialize
		set -A SCSETUP_DO_CMDSET

		# Add the command
		SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -a -B type=switch,name=${junctionname}"

		# Attempt to issue the command
		scsetup_do_cmdset || return 1

		# Done
		break
	done

	return 0
}

#####################################################
#
# scsetup_menu_transport_addadapter() [nohelp]
#
#	nohelp		- if this flag is given, do not
#				clear screen, print title, print help,
#				or ask for confirmation to continue.
#
#	Add a cluster transport adapter to the cluster.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_transport_addadapter()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Add a Cluster Transport Adapter to a Node <<<
	')"
	typeset sctxt_p1="$(gettext '
		This option is used to add a new cluster transport
		adapter to the cluster configuration.
	')"
	typeset sctxt_p1_adapterdata="$(gettext '
		You will be asked to supply both the name of the adapter
		and the name of the node on which the adapter is found.
	')"

	typeset nodelist
	typeset nodename
	typeset adapterlist
	typeset adaptername
	typeset adapter
	typeset trtype
	typeset answer
	typeset prompt
	typeset default_trtypes

	nodelist=
	let nodecount=0

	#
	# Print title
	#
	if [[ -z "${nohelp}" ]]; then
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Get nodelist and trtype
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then

			# Get nodelist
			nodelist="$(scsetup_get_nodelist)"

			# Make sure we have a nodelist
			if [[ -z "${nodelist}" ]]; then
				printf "$(gettext 'Unable to establish the list of cluster nodes.')\n\n\a"
				sc_prompt_pause
				return 1
			fi

			# Set node count
			let nodecount=$(set -- ${nodelist}; echo $#)

			# Get trtype
			trtype="$(scsetup_get_trtypes)"

			# Make sure we have only one transport type
			if [[ -z "${trtype}" ]]; then
				# Single node cluster
				if [[ ${nodecount} -eq 1 ]]; then
					# Default trtypes
					if [[ -f "${SC_SCADMINDIR}/defaults" ]]; then
						default_trtypes=$(grep '^SC_DFLT_KNOWN_TRTYPES=' \
						     ${SC_SCADMINDIR}/defaults | \
						     nawk -F'=' '{print $2}' 2>/dev/null)
					fi

					while true
					do
						trtype=$(sc_prompt "$(gettext 'What transport type are you using?')" "dlpi") || return 1
						if [[ -n "${default_trtypes}" ]] &&
						   [[ "${default_trtypes}" != *${trtype}* ]]; then
							printf "$(gettext 'Unknown transport type.')\n\n\a"
						else
							break
						fi
					done

				else
					printf "$(gettext 'Unable to determine transport type.')\n\n\a"
					sc_prompt_pause
					return 1
				fi
			fi
			if [[ $(set -- ${trtype}; echo $#) -gt 1 ]]; then
				printf "$(gettext 'Scsetup does not support clusters with mixed transport types.')\n\n\a"
				sc_prompt_pause
				return 1
			fi
		else
			# Since this is just DEBUG mode, do not check trtype
			answer=$(sc_prompt "$(gettext 'DEBUG:  What transport type are you using?')" "dlpi") || return 1
			trtype=${answer}
		fi

		# Print help
		sc_print_para "${sctxt_p1_adapterdata}"

		# Get the nodename
		answer=$(scsetup_prompt_nodename "${nodelist}" "$(gettext 'To which node do you want to add the adapter?')") || return 1
		nodename=${answer}

		# Get the adaptername
		prompt="$(printf "$(gettext 'Name of the adapter to add to \"%s\"?')" "${nodename}")"
		while true
		do
			# Prompt for adapter name
			answer=$(scsetup_prompt_transport_adapter "${prompt}") || continue 2

			# Get the list of configured adapters for this node
			adapterlist=
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
				adapterlist="$(scsetup_get_adapterlist ${nodename})"
			fi

			# See if our adapter is already configured
			for adapter in ${adapterlist}
			do
				if [[ "${answer}" = "${adapter}" ]]; then
					printf "$(gettext 'Adapter \"%s\" is already configured on \"%s\".')\n\n\a" "${answer}" "${nodename}"
					continue 2
				fi
			done

			# Okay
			adaptername=${answer}
			break
		done

		#
		# Set up the command set
		#

		# Initialize
		set -A SCSETUP_DO_CMDSET

		# Add the command
		SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -a -A trtype=${trtype},name=${adaptername},node=${nodename}"

		# Attempt to issue the command
		scsetup_do_cmdset || return 1

		# Done
		break
	done

	return 0
}

#####################################################
#
# scsetup_menu_transport_rmcable() [nohelp]
#
#	nohelp		- if this flag is given, do not
#				clear screen, print title, print help,
#				or ask for confirmation to continue.
#
#	Remove a cluster transport cable.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_transport_rmcable()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Remove a Cluster Transport Cable <<<
	')"
	typeset sctxt_p1="$(gettext '
		This option is used to remove an existing
		cluster transport cable from the cluster configuration.
		However, the two endpoints of the cable will remain
		configured.
	')"
	typeset sctxt_p2="$(gettext '
		It is very important that you not disable or remove
		the last remaining healthy connection to an active cluster
		node.  Please check the status of other cables before
		you proceed.
	')"

	typeset endpoint

	#
	# Print title
	#
	if [[ -z "${nohelp}" ]]; then
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Get the endpoint
		endpoint=$(scsetup_prompt_transport_endpoint) || return 1

		#
		# Set up the command set
		#

		# Initialize
		set -A SCSETUP_DO_CMDSET

		# Add the command
		SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -r -m endpoint=${endpoint}"

		# Attempt to issue the command
		scsetup_do_cmdset || return 1

		# Done
		break
	done

	return 0
}

#####################################################
#
# scsetup_menu_transport_rmadapter() [nohelp]
#
#	nohelp		- if this flag is given, do not
#				clear screen, print title, print help,
#				or ask for confirmation to continue.
#
#	Remove a cluster transport adapter from the cluster.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_transport_rmadapter()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Remove a Cluster Transport Adapter <<<
	')"
	typeset sctxt_p1="$(gettext '
		This option is used to remove an existing cluster transport
		adapter from the cluster configuration.  An adapter cannot
		be removed if it is still in use as an endpoint in a
		transport cable.
	')"
	typeset sctxt_p1_adapterdata="$(gettext '
		You will be asked to supply both the name of the adapter
		and the name of the node on which the adapter is found.
	')"

	integer found
	typeset nodelist
	typeset nodename
	typeset adapterlist
	typeset adaptername
	typeset adapter
	typeset answer
	typeset prompt

	#
	# Print title
	#
	if [[ -z "${nohelp}" ]]; then
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Get nodelist
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then

			# Get nodelist
			nodelist="$(scsetup_get_nodelist)"

			# Make sure we have a nodelist
			if [[ -z "${nodelist}" ]]; then
				printf "$(gettext 'Unable to establish the list of cluster nodes.')\n\n\a"
				sc_prompt_pause
				return 1
			fi
		fi

		# Print help
		sc_print_para "${sctxt_p1_adapterdata}"

		# Get the nodename
		answer=$(scsetup_prompt_nodename "${nodelist}" "$(gettext 'On which node is the adapter found?')") || return 1
		nodename=${answer}

		# Get the adaptername
		prompt="$(printf "$(gettext 'Name of the adapter to remove from \"%s\"?')" "${nodename}")"
		while true
		do
			# Prompt for adapter name
			answer=$(scsetup_prompt_transport_adapter "${prompt}") || continue 2

			# Get the list of configured adapters for this node
			adapterlist=
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
				adapterlist="$(scsetup_get_adapterlist ${nodename})"
			fi

			# See if our adapter is configured
			let found=0
			for adapter in ${adapterlist}
			do
				if [[ "${answer}" = "${adapter}" ]]; then
					let found=1
					break
				fi
			done

			#
			# If there is an adapterlist, but the adapter
			# is not found, print error.
			#
			if [[ -n "${adapterlist}" ]] && [[ ${found} -eq 0 ]]; then
				printf "$(gettext 'Unknown adapter.')\n\n\a"
				continue
			fi

			# Okay
			adaptername=${answer}
			break
		done

		#
		# Set up the command set
		#

		# Initialize
		set -A SCSETUP_DO_CMDSET

		# Add the command
		SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -r -A name=${adaptername},node=${nodename}"

		# Attempt to issue the command
		scsetup_do_cmdset || return 1

		# Done
		break
	done

	return 0
}

#####################################################
#
# scsetup_menu_transport_rmjunction() [nohelp]
#
#	nohelp		- if this flag is given, do not
#				clear screen, print title, print help,
#				or ask for confirmation to continue.
#
#	Remove a cluster transport junction from the cluster.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_transport_rmjunction()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Remove a Cluster Transport Junction <<<
	')"
	typeset sctxt_p1="$(gettext '
		This option is used to remove an existing cluster transport
		junction from the cluster configuration.  A junction cannot
		be removed if any of the ports are still in use as a endpoints
		in any transport cables.
	')"

	integer found
	typeset junctionlist
	typeset junctionname
	typeset junction
	typeset answer

	#
	# Print title
	#
	if [[ -z "${nohelp}" ]]; then
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Get the junctionname
		while true
		do
			# Prompt for junction name
			answer=$(scsetup_prompt_transport_junction "$(gettext 'Name of the junction to remove?')") || return 1

			# Get the list of configured junctions
			junctionlist=
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
				junctionlist="$(scsetup_get_junctionlist)"
			fi

			# See if our junction is configured
			let found=0
			for junction in ${junctionlist}
			do
				if [[ "${answer}" = "${junction}" ]]; then
					let found=1
					break
				fi
			done

			#
			# If there is a junctionlist, but the junction
			# is not found, print error.
			#
			if [[ -n "${junctionlist}" ]] && [[ ${found} -eq 0 ]]; then
				printf "$(gettext 'Unknown junction.')\n\n\a"
				continue
			fi

			# Okay
			junctionname=${answer}
			break
		done

		#
		# Set up the command set
		#

		# Initialize
		set -A SCSETUP_DO_CMDSET

		# Add the command
		SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -r -B name=${junctionname}"

		# Attempt to issue the command
		scsetup_do_cmdset || return 1

		# Done
		break
	done

	return 0
}

#####################################################
#
# scsetup_menu_transport_cableon() [nohelp]
#
#	nohelp		- if this flag is given, do not
#				clear screen, print title, print help,
#				or ask for confirmation to continue.
#
#	Enable a cluster transport cable.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_transport_cableon()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Enable a Cluster Transport Cable <<<
	')"
	typeset sctxt_p1="$(gettext '
		This option is used to enable an already existing
		cluster transport cable.
	')"

	typeset endpoint

	#
	# Print title
	#
	if [[ -z "${nohelp}" ]]; then
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Get the endpoint
		endpoint=$(scsetup_prompt_transport_endpoint) || return 1

		#
		# Set up the command set
		#

		# Initialize
		set -A SCSETUP_DO_CMDSET

		# Add the command
		SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -c -m endpoint=${endpoint},state=enabled"

		# Attempt to issue the command
		scsetup_do_cmdset || return 1

		# Done
		break
	done

	return 0
}

#####################################################
#
# scsetup_menu_transport_cableoff() [nohelp]
#
#	nohelp		- if this flag is given, do not
#				clear screen, print title, print help,
#				or ask for confirmation to continue.
#
#	Disable a cluster transport cable.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_transport_cableoff()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Disable a Cluster Transport Cable <<<
	')"
	typeset sctxt_p1="$(gettext '
		This option is used to disable an existing
		cluster transport cable.
	')"
	typeset sctxt_p2="$(gettext '
		It is very important that you not disable or remove
		the last remaining healthy connection to an active cluster
		node.  Please check the status of other cables before
		you proceed.
	')"

	typeset endpoint

	#
	# Print title
	#
	if [[ -z "${nohelp}" ]]; then
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Get the endpoint
		endpoint=$(scsetup_prompt_transport_endpoint) || return 1

		#
		# Set up the command set
		#

		# Initialize
		set -A SCSETUP_DO_CMDSET

		# Add the command
		SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -c -m endpoint=${endpoint},state=disabled"

		# Attempt to issue the command
		scsetup_do_cmdset || return 1

		# Done
		break
	done

	return 0
}

#####################################################
#
# scsetup_help_transport_menu()
#
#	Print help information from the transport menu.
#	This is the same help information as is printed
#	from the MAIN help menu.  But, we ask for confirmation
#	before returning to the previous menu.
#
#	This function always returns zero.
#
#####################################################
scsetup_help_transport_menu()
{
	clear
	scsetup_help_main_transport
	sc_prompt_pause

	return 0
}

#####################################################
#
# scsetup_get_transport_menuoption()
#
#	Print the cluster transport menu, and return
#	the selected option.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_transport_menuoption()
{
	typeset sctxt_title_1="$(gettext '*** Cluster Interconnect Menu ***')"
	typeset sctxt_title_2="$(gettext 'Please select from one of the following options:')"
	typeset sctxt_option_001="$(gettext 'Add a transport cable')"
	typeset sctxt_option_002="$(gettext 'Add a transport adapter to a node')"
	typeset sctxt_option_003="$(gettext 'Add a transport junction')"
	typeset sctxt_option_004="$(gettext 'Remove a transport cable')"
	typeset sctxt_option_005="$(gettext 'Remove a transport adapter from a node')"
	typeset sctxt_option_006="$(gettext 'Remove a transport junction')"
	typeset sctxt_option_007="$(gettext 'Enable a transport cable')"
	typeset sctxt_option_008="$(gettext 'Disable a transport cable')"
	typeset sctxt_option_help="$(gettext 'Help')"
	typeset sctxt_option_return="$(gettext 'Return to the Main Menu')"

	typeset option

	option=$(sc_get_menuoption \
		"T1+++${sctxt_title_1}" \
		"T2+++${sctxt_title_2}" \
		"S+0+1+${sctxt_option_001}" \
		"S+0+2+${sctxt_option_002}" \
		"S+0+3+${sctxt_option_003}" \
		"S+0+4+${sctxt_option_004}" \
		"S+0+5+${sctxt_option_005}" \
		"S+0+6+${sctxt_option_006}" \
		"S+0+7+${sctxt_option_007}" \
		"S+0+8+${sctxt_option_008}" \
		"R+++" \
		"S+0+?+${sctxt_option_help}" \
		"S+0+q+${sctxt_option_return}" \
	)

	echo "${option}"

	return 0
}

#####################################################
#
# scsetup_menu_transport()
#
#	Cluster transport menu
#
#	This function always returns zero.
#
#####################################################
scsetup_menu_transport()
{
	# Loop around the cluster transport menu
	while true
	do
		case $(scsetup_get_transport_menuoption) in
		'1')    scsetup_menu_transport_addcable ;;
		'2')    scsetup_menu_transport_addadapter ;;
		'3')    scsetup_menu_transport_addjunction ;;
		'4')    scsetup_menu_transport_rmcable ;;
		'5')    scsetup_menu_transport_rmadapter ;;
		'6')    scsetup_menu_transport_rmjunction ;;
		'7')    scsetup_menu_transport_cableon ;;
		'8')    scsetup_menu_transport_cableoff ;;
		'?')    scsetup_help_transport_menu ;;
		'q')    break ;;
                esac 
	done

	return 0
}

#####################################################
#####################################################
##
## Private hostnames
##
#####################################################
#####################################################

#####################################################
#
# scsetup_menu_privatehosts_namechange() [nohelp]
#
#	nohelp		- if this flag is given, do not
#				clear screen, print title, print help,
#				or ask for confirmation to continue.
#
#	Change the private hostname for a given node in the cluster.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_privatehosts_namechange()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Change a Private Hostname <<<
	')"
	typeset sctxt_p1="$(gettext '
		Nodes may contact other nodes in the cluster 
		over the cluster interconnect by accessing them using
		their private hostnames.   Default private hostnames
		are assigned during cluster installation.
	')"
	typeset sctxt_p2="$(gettext '
		Note that private hostnames should never be stored
		in the hosts(4) or other naming services databases.
		A special nsswitch facility (see nsswitch.conf(4))
		performs all hostname lookups for private hostnames.
	')"
	typeset sctxt_p3="$(gettext '
		This option is used to change the private hostname
		for a given cluster node.   Any application or service
		which might cache private hostnames should be stopped
		before this change is made, then re-started after the
		change.  Please refer to the Sun Cluster documentation
		for additional information regarding changes to private
		hostnames before attempting to make any changes.
	')"

	typeset nodelist
	typeset nodename
	typeset privatename
	typeset answer
	typeset prompt

	#
	# Print title
	#
	if [[ -z "${nohelp}" ]]; then
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"
		sc_print_para "${sctxt_p3}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Get nodelist
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then

			# Get nodelist
			nodelist="$(scsetup_get_nodelist)"

			# Make sure we have a nodelist
			if [[ -z "${nodelist}" ]]; then
				printf "$(gettext 'Unable to establish the list of cluster nodes.')\n\n\a"
				sc_prompt_pause
				return 1
			fi
		fi

		# Get the nodename
		answer=$(scsetup_prompt_nodename "${nodelist}" "$(gettext 'Which cluster node do you want to change?')") || return 1
		nodename=${answer}

		# Get the new private hostname
		prompt="$(printf "$(gettext 'What is the new private hostname for \"%s\"?')" "${nodename}")"
		answer=$(sc_prompt "${prompt}") || return 1
		privatename=${answer}

		#
		# Set up the command set
		#

		# Initialize
		set -A SCSETUP_DO_CMDSET

		# Add the command
		SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -c -P node=${nodename},privatehostname=${privatename}"

		# Attempt to issue the command
		scsetup_do_cmdset || return 1

		# Done
		break
	done

	return 0
}

#####################################################
#
# scsetup_help_privatehosts_menu()
#
#	Print help information from the private hostnames menu.
#	This is the same help information as is printed
#	from the MAIN help menu.  But, we ask for confirmation
#	before returning to the previous menu.
#
#	This function always returns zero.
#
#####################################################
scsetup_help_privatehosts_menu()
{
	clear
	scsetup_help_main_privatehosts
	sc_prompt_pause

	return 0
}

#####################################################
#
# scsetup_get_privatehosts_menuoption()
#
#	Print the private hostnames menu, and return the selected option.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_privatehosts_menuoption()
{
	typeset sctxt_title_1="$(gettext '*** Private Hostnames Menu ***')"
	typeset sctxt_title_2="$(gettext 'Please select from one of the following options:')"
	typeset sctxt_option_001="$(gettext 'Change a private hostname')"
	typeset sctxt_option_help="$(gettext 'Help')"
	typeset sctxt_option_return="$(gettext 'Return to the Main Menu')"

	typeset option

	option=$(sc_get_menuoption \
		"T1+++${sctxt_title_1}" \
		"T2+++${sctxt_title_2}" \
		"S+0+1+${sctxt_option_001}" \
		"R+++" \
		"S+0+?+${sctxt_option_help}" \
		"S+0+q+${sctxt_option_return}" \
	)

	echo "${option}"

	return 0
}

#####################################################
#
# scsetup_menu_privatehosts()
#
#	Private hostnames menu
#
#	This function always returns zero.
#
#####################################################
scsetup_menu_privatehosts()
{
	# Loop around the private hostnames menu
	while true
	do
		case $(scsetup_get_privatehosts_menuoption) in
		'1')    scsetup_menu_privatehosts_namechange ;;
		'?')    scsetup_help_privatehosts_menu ;;
		'q')    break ;;
                esac 
	done

	return 0
}

#####################################################
#####################################################
##
## Device Groups
##
#####################################################
#####################################################

#####################################################
#
# scsetup_menu_devicegroups_addvxvm() [nohelp]
#
#	nohelp		- if this flag is given, do not
#				clear screen, print title, print help,
#				or ask for confirmation to continue.
#
#	Register a VxVM disk group as a cluster device group.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_devicegroups_addvxvm()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Register a VxVM Disk Group as a Device Group <<<
	')"
	typeset sctxt_p1="$(gettext '
		VERITAS Volume Manager disk groups are always managed by
		the cluster as cluster device groups.  This option is
		used to register a VxVM disk group with the
		cluster as a cluster device group.
	')"
	typeset sctxt_p1_preferenced="$(gettext '
		Primary ownership of a device group is determined by
		either specifying or not specifying a preferred
		ordering of the nodes that can own the device group. If
		an order is specified, this will be the order in which
		nodes will attempt to establish ownership. If an order
		is not specified, the first node that attempts to
		access a disk in the device group becomes the owner.
	')"
	typeset sctxt_p1_list1="$(gettext '
		Please list the nodes which are directly attached to
		all of the disks in this disk group and are, therefore,
		eligible to take primary ownership of the group.
	')"
	typeset sctxt_p1_list2="$(gettext '
		Please list the nodes which are directly attached to
		all of the disks in this disk group and are, therefore,
		eligible to take primary ownership of the group.  The
		order in which you list these names is important,
		as it also specifies the order in which nodes will
		attempt to establish ownership of the group.
	')"
	typeset sctxt_p1_list3="$(gettext '
		Please list the order in which nodes should attempt
		to establish ownership of the group.
	')"
	typeset sctxt_p2_list1="$(gettext '
		List one node name per line.   At least two node nodes
		must be given.  When finished, type Control-D:
	')"
	typeset sctxt_p2_list2="${sctxt_p2_list1}"
	typeset sctxt_p2_list3="$(gettext '
		List one node name per line:
	')"
	typeset sctxt_node_prompt1="$(gettext 'Node name:')"
	typeset sctxt_node_prompt2="$(gettext 'Node name (Ctrl-D to finish):')"
	typeset sctxt_p1_numsecondaries="$(gettext '
		The desired number of secondaries value can be set to any 
		integer between 1 and the number of non-primary provider nodes 
		in the device group. The cluster framework will use this number
		as a guide while configuring the actual secondaries for the
		device group. The default number of secondaries for a device 
		group is 1. A smaller number of secondaries will typically 
		result in less performance penalty, but it can reduce 
		availability.
	')"

	typeset dgname
	typeset dgtype
	typeset dg_nodelist
	typeset preferenced
	typeset failback

	integer nodecount
	integer dg_nodecount
	integer getlist
	integer count
	integer found
	typeset nodelist
	typeset node
	typeset list
	typeset foo
	typeset answer
	typeset answers

	#
	# Print title
	#
	if [[ -z "${nohelp}" ]]; then
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Initialize
		let nodecount=0
		nodelist=
		dg_nodelist=
		preferenced=
		failback=

		# Get nodelist and nodecount
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then

			# Get nodelist
			nodelist="$(scsetup_get_nodelist)"

			# Make sure we have a nodelist
			if [[ -z "${nodelist}" ]]; then
				printf "$(gettext 'Unable to establish the list of cluster nodes.')\n\n\a"
				sc_prompt_pause
				return 1
			fi

			# Set node count
			let nodecount=$(set -- ${nodelist}; echo $#)
		else
			# We must be running in DEBUG mode
			answer=$(sc_prompt_yesno "$(gettext 'DEBUG:  Is this a two-node cluster?')" "${YES}") || return 1
			if [[ "${answer}" = "yes" ]]; then

				# Set nodecount
				let nodecount=2

				#
				# Since this is just DEBUG mode, we do
				# not error-check node name responses.
				#
				answer=$(sc_prompt "$(gettext 'DEBUG:  What is the name of the first node?')" "node1") || return 1
				nodelist="${answer}"

				answer=$(sc_prompt "$(gettext 'DEBUG:  What is the name of the second node?')" "node2") || return 1
				nodelist="${nodelist} ${answer}"
			else
				# If not two, then get the node count
				while true
				do
					answer=$(sc_prompt "$(gettext 'DEBUG:  How  many nodes are in the cluster?')") || return 1

					# In range?
					if [[ $(expr ${answer} : '[0-9]*') -ne $(expr ${answer} : '.*') ]] ||
					    [[ ${answer} -lt 2 ]] ||
					    [[ ${answer} -gt ${SC_MAXNODEID} ]]; then
						printf "\a"
					else
						break
					fi
				done

				# Set nodecount
				let nodecount=${answer}

				# Set nodelist (node1, node2, node3, ...)
				count=0
				while [[ ${count} -lt ${nodecount} ]]
				do
					((count += 1))
					nodelist="${nodelist} node${count}"
				done
				
			fi
		fi

		# Get the name of the device group
		answer=$(sc_prompt "$(gettext 'Name of the VxVM disk group you want to register?')") || return 1
		dgname=${answer}

		# Make sure it is not already registered
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			dgtype=$(scsetup_get_devicegroup_type ${dgname})
			if [[ -n "${dgtype}" ]]; then
				printf "$(gettext '\"%s\" is already registered as a device group')\n\n\a" "${dgname}"
				continue
			fi
		fi

		# Preferenced?
		sc_print_para "${sctxt_p1_preferenced}"
		answer=$(sc_prompt_yesno "$(gettext 'Do you want to configure a preferred ordering?')" "${YES}") || return 1
		if [[ "${answer}" = "yes" ]]; then
			preferenced="true"
		else
			preferenced="false"
		fi

		# Two node cluster
		if [[ ${nodecount} -eq 2 ]]; then
			answer=$(sc_prompt_yesno "$(gettext 'Are both nodes attached to all disks in this group?')" "${YES}") || return 1

			# They MUST be!
			if [[ "${answer}" != "yes" ]]; then
				printf "$(gettext 'In a two-node cluster, all disks in the group must be dual-ported.')\n\n\a"
				continue
			fi

			# If preferenced is true, find out who is first
			if [[ "${preferenced}" = "true" ]]; then
				answer=$(scsetup_prompt_nodename "${nodelist}" "$(gettext 'Which node is the preferred primary for this device group?')") || return 1
				set -A list ${nodelist}
				if [[ "${answer}" = "${list[0]}" ]]; then
					dg_nodelist="${list[0]} ${list[1]}"
				elif [[ "${answer}" = "${list[1]}" ]]; then
					dg_nodelist="${list[1]} ${list[0]}"
				else
					printf "$(gettext 'Internal error in scsetup_menu_devicegroups_addvxvm()')\n\n\a"
					sc_prompt_pause
					return 1
				fi
			fi

		# More than two nodes
		else
			answer=$(sc_prompt_yesno "$(gettext 'Are all nodes attached to all disks in this group?')" "${YES}") || return 1

			# Clear flag to get node list
			let getlist=0

			# Get list of disks, no preferenced order
			if [[ "${answer}" = "no" ]] &&
			    [[ "${preferenced}" = "false" ]]; then
				let getlist=1

			# Get list of disks, preferenced ordering
			elif [[ "${answer}" = "no" ]] &&
			    [[ "${preferenced}" = "true" ]]; then
				let getlist=2

			# Get the preference list
			elif [[ "${answer}" = "yes" ]] &&
			    [[ "${preferenced}" = "true" ]]; then
				let getlist=3
			fi

			# Get the nodelist
			while [[ ${getlist} -gt 0 ]]
			do
				# Initialize
				answers=

				# Prompt based on type
				case ${getlist} in
				1)	# list of disks, no order
					sc_print_para "${sctxt_p1_list1}"
					sc_print_para "${sctxt_p2_list1}"
					;;

				2)	# list of disks, ordered
					sc_print_para "${sctxt_p1_list2}"
					sc_print_para "${sctxt_p2_list2}"
					;;

				3)	# Preference order only
					sc_print_para "${sctxt_p1_list3}"
					sc_print_para "${sctxt_p2_list3}"
					;;
				esac

				# Get the dg nodelist
				let count=0
				while [[ ${count} -lt ${nodecount} ]]
				do
					#
					# Cannot use Ctrl-D if we have not yet
					# typed in at least two node names or
					# if we are just typing preference list.
					#
					if [[ ${count} -lt 2 ]] ||
					    [[ ${getlist} -eq 3 ]]; then
						answer=$(sc_prompt "${sctxt_node_prompt1}" "" "nonl") || continue
					else
						answer=$(sc_prompt "${sctxt_node_prompt2}" "" "nonl") || break
					fi

					# must be in our nodelist
					let found=0
					for node in ${nodelist}
					do
						if [[ "${answer}" = "${node}" ]]; then
							let found=1
							break
						fi
					done

					# Make sure we found it
					if [[ -n "${nodelist}" ]] &&
					    [[ ${found} -eq 0 ]]; then
						echo
						printf "$(gettext 'Unknown node name.')\n\n\a"
						continue
					fi

					# Make sure it is not a duplicate
					for node in ${answers}
					do
						if [[ "${answer}" = "${node}" ]]; then
							echo
							printf "$(gettext '\"%s\" already entered.')\n\n\a" "${answer}"
							continue 2
						fi
					done

					# Okay, add it to list of answers
					answers="${answers} ${answer}"

					# Next
					((count += 1))
				done

				# Verify that the list is correct
				echo
				case ${getlist} in
				1)	sc_print_para "$(gettext 'This is the list of nodes:')" ;;
				2|3)	
					sc_print_para "$(gettext 'This is the ordered list of nodes:')" ;;
				esac
				for node in ${answers}
				do
					printf "\t${node}\n"
				done
				echo
				answer=$(sc_prompt_yesno "$(gettext 'Is it correct?')" "${YES}") || return 1
				if [[ "${answer}" != "yes" ]]; then
					continue
				fi

				# Set dg_nodelist
				dg_nodelist="${answers}"

				# Done
				break
			done
		fi

		# If the dg_nodelist is not set, set to the default
		if [[ -z "${dg_nodelist}" ]]; then
			dg_nodelist="${nodelist}"
		fi

		# Reformat the dg_nodelist to give to scconf
		foo="${dg_nodelist}"
		dg_nodelist=
		dg_nodecount=0
		for node in ${foo}
		do
			if [[ -n "${dg_nodelist}" ]]; then
				dg_nodelist="${dg_nodelist}:"
			fi
			dg_nodelist="${dg_nodelist}${node}"
			(( dg_nodecount += 1 ))
		done

		# Failback
		failback=
		if [[ "${preferenced}" = "true" ]]; then
			answer=$(sc_prompt_yesno "$(gettext 'Enable \"failback\" for this disk device group?')" "${NO}") || return 1
			if [[ "${answer}" = "yes" ]]; then
				failback="enabled"
			fi
		fi

		# numsecondaries
		numsecondaries=${SC_DEFAULT_NUMSECONDARIES}
		if [[ ${dg_nodecount} -gt 2 ]]; then
			while true
			do
				sc_print_para "${sctxt_p1_numsecondaries}"
				answer=$(sc_prompt "$(gettext 'What is the desired number of secondaries ?')" "${numsecondaries}") || return 1

				if [[ $(expr "${answer}" : '[0-9][0-9]*') -ne ${#answer} ]]; then
					echo
					printf "$(gettext 'The desired number of secondaries must be a valid integer.')\n"
					continue
				fi

				if [[ ${answer} -lt 1 ]] || 
			   	   [[ ${answer} -ge ${dg_nodecount} ]]; then
					echo
					printf "$(gettext 'Input must be between 1 and the number of non-primary nodes in the device group.')\n\n\a"
					continue
				else
					numsecondaries=${answer}
					break
				fi	
			done
		fi
				
		#
		# Set up the command set
		#

		# Initialize
		set -A SCSETUP_DO_CMDSET

		# Add the command
		SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -a -D type=${SCSETUP_DG_VXVM_SET},name=${dgname}"

		# Nodelist?	(the default is all nodes)
		if [[ -n "${dg_nodelist}" ]]; then
			SCSETUP_DO_CMDSET[0]="${SCSETUP_DO_CMDSET[0]},nodelist=${dg_nodelist}"
		fi

		# Preferenced?	("false" is the default)
		if [[ "${preferenced}" = "true" ]]; then
			SCSETUP_DO_CMDSET[0]="${SCSETUP_DO_CMDSET[0]},preferenced=true"
		fi

		# Failback?	("disabled" is the default)
		if [[ "${failback}" = "enabled" ]]; then
			SCSETUP_DO_CMDSET[0]="${SCSETUP_DO_CMDSET[0]},failback=enabled"
		fi

		# numsecondaries?
		if [[ ${numsecondaries} -ne ${SC_DEFAULT_NUMSECONDARIES} ]]; then
			SCSETUP_DO_CMDSET[0]="${SCSETUP_DO_CMDSET[0]},numsecondaries=${numsecondaries}"
		fi

		# Attempt to issue the command
		scsetup_do_cmdset || return 1

		# Done
		break
	done

	return 0
}

#####################################################
#
# scsetup_menu_devicegroups_syncvxvm() [nohelp]
#
#	nohelp		- if this flag is given, do not
#				clear screen, print title, print help,
#				or ask for confirmation to continue.
#
#	Synchronize volume information for a VxVM device group.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_devicegroups_syncvxvm()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Synchronize Volume Information for a VxVM Device Group <<<
	')"
	typeset sctxt_p1="$(gettext '
		VERITAS Volume Manager disk groups are always managed
		by the cluster as cluster device groups.  This option
		is used to synchronize volume information for a VxVM
		device group between the VxVM software and the
		clustering software.  It should be selected anytime a
		volume is either added to or removed from a VxVM disk
		group.  Otherwise, the cluster will be unaware of the
		changes.
	')"
	typeset dgname
	typeset dgtype

	typeset answer

	#
	# Print title
	#
	if [[ -z "${nohelp}" ]]; then
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do

		# Get the name of the device group
		answer=$(sc_prompt "$(gettext 'Name of the VxVM device group you want to synchronize?')") || return 1
		dgname=${answer}

		# Make sure it is a VxVM device group
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			dgtype=$(scsetup_get_devicegroup_type ${dgname})
			if [[ -z "${dgtype}" ]] ||
			    [[ "${dgtype}" != "${SCSETUP_DG_VXVM_LOOKUP}" ]]; then
				printf "$(gettext '\"%s\" is not a %s device group.')\n\n\a" "${dgname}" "${SCSETUP_DG_VXVM_LOOKUP}"
				continue
			fi
		fi

		#
		# Set up the command set
		#

		# Initialize
		set -A SCSETUP_DO_CMDSET

		# Add the command
		SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -c -D name=${dgname},sync"

		# Attempt to issue the command
		scsetup_do_cmdset || return 1

		# Done
		break
	done

	return 0
}

#####################################################
#
# scsetup_menu_devicegroups_rmvxvm() [nohelp]
#
#	nohelp		- if this flag is given, do not
#				clear screen, print title, print help,
#				or ask for confirmation to continue.
#
#	Unregister a VxVM disk group as a cluster device group.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_devicegroups_rmvxvm()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Unregister a VxVM Disk Group as a Device Group <<<
	')"
	typeset sctxt_p1="$(gettext '
		VERITAS Volume Manager disk groups are always managed
		by the cluster as cluster device groups.  This option is used
		to unregister a VxVM cluster device group.
	')"
	typeset sctxt_p2="$(gettext '
		Before you attempt to unregister this group, please be sure
		that there are no mounts or other active references to
		any of the devices in the group.
	')"

	typeset dgname
	typeset dgtype
	typeset answer

	#
	# Print title
	#
	if [[ -z "${nohelp}" ]]; then
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do

		# Get the name of the device group
		answer=$(sc_prompt "$(gettext 'Name of the VxVM device group you want to unregister?')") || return 1
		dgname=${answer}

		# Make sure it is a VxVM device group
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			dgtype=$(scsetup_get_devicegroup_type ${dgname})
			if [[ -z "${dgtype}" ]] ||
			    [[ "${dgtype}" != "${SCSETUP_DG_VXVM_LOOKUP}" ]]; then
				printf "$(gettext '\"%s\" is not a %s device group.')\n\n\a" "${dgname}" "${SCSETUP_DG_VXVM_LOOKUP}"
				continue
			fi
		fi

		#
		# Set up the command set
		#

		# Initialize
		set -A SCSETUP_DO_CMDSET

		# Add the command
		SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -r -D name=${dgname}"

		# Attempt to issue the command
		scsetup_do_cmdset || return 1

		# Done
		break
	done

	return 0
}

#####################################################
#
# scsetup_menu_devicegroups_addnodevxvm() [nohelp]
#
#	nohelp		- if this flag is given, do not
#				clear screen, print title, print help,
#				or ask for confirmation to continue.
#
#	Add a node to a VxVM device group.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_devicegroups_addnodevxvm()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Add a Node to a VxVM Device Group <<<
	')"
	typeset sctxt_p1="$(gettext '
		VERITAS Volume Manager disk groups are always managed by
		the cluster as cluster device groups.  This option is
		used to add a node to an already existing VxVM cluster
		device group.
	')"

	typeset nodelist
	typeset nodename
	typeset node
	typeset list
	typeset dgname
	typeset dgtype
	typeset answer

	#
	# Print title
	#
	if [[ -z "${nohelp}" ]]; then
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		#Initialize
		nodelist=

		# Get the name of the device group
		answer=$(sc_prompt "$(gettext 'Name of the VxVM device group to which you want to add a node?')") || return 1
		dgname=${answer}

		# Make sure it is a VxVM device group
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			dgtype=$(scsetup_get_devicegroup_type ${dgname})
			if [[ -z "${dgtype}" ]] ||
			    [[ "${dgtype}" != "${SCSETUP_DG_VXVM_LOOKUP}" ]]; then
				printf "$(gettext '\"%s\" is not a %s device group.')\n\n\a" "${dgname}" "${SCSETUP_DG_VXVM_LOOKUP}"
				continue
			fi
		fi

		# Get the nodelist
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then

			nodelist="$(scsetup_get_nodelist)"

			# Make sure we have a nodelist
			if [[ -z "${nodelist}" ]]; then
				printf "$(gettext 'Unable to establish the list of cluster nodes.')\n\n\a"
				sc_prompt_pause
				return 1
			fi
		fi

		# Get the nodename
		while true
		do
			answer=$(scsetup_prompt_nodename "${nodelist}" "$(gettext 'Name of the node to add to this group?')") || return 1

			# Make sure it is not already there
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
				list="$(scsetup_get_devicegroup_nodes ${dgname})"
				for node in ${list}
				do
					if [[ "${answer}" = "${node}" ]]; then
						printf "$(gettext '\"%s\" is already part of this group.')\n\n\a" "${answer}"
						continue 2
					fi
				done
			fi

			# Done
			break
		done

		# Okay
		nodename=${answer}

		#
		# Set up the command set
		#

		# Initialize
		set -A SCSETUP_DO_CMDSET

		# Add the command
		SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -a -D type=${SCSETUP_DG_VXVM_SET},name=${dgname},nodelist=${nodename}"

		# Attempt to issue the command
		scsetup_do_cmdset || return 1

		# Done
		break
	done

	return 0
}

#####################################################
#
# scsetup_menu_devicegroups_rmnodevxvm() [nohelp]
#
#	nohelp		- if this flag is given, do not
#				clear screen, print title, print help,
#				or ask for confirmation to continue.
#
#	Remove a node from a VxVM device group.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_devicegroups_rmnodevxvm()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Remove a Node from a VxVM Device Group <<<
	')"
	typeset sctxt_p1="$(gettext '
		VERITAS Volume Manager disk groups are always managed by
		the cluster as cluster device groups.  This option is
		used to remove a node from an already existing
		VxVM cluster device group.
	')"

	integer found
	typeset nodelist
	typeset nodename
	typeset node
	typeset list
	typeset dgname
	typeset dgtype
	typeset answer

	#
	# Print title
	#
	if [[ -z "${nohelp}" ]]; then
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		#Initialize
		nodelist=

		# Get the name of the device group
		answer=$(sc_prompt "$(gettext 'Name of the VxVM device group from which you want to remove a node?')") || return 1
		dgname=${answer}

		# Make sure it is a VxVM device group
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			dgtype=$(scsetup_get_devicegroup_type ${dgname})
			if [[ -z "${dgtype}" ]] ||
			    [[ "${dgtype}" != "${SCSETUP_DG_VXVM_LOOKUP}" ]]; then
				printf "$(gettext '\"%s\" is not a %s device group.')\n\n\a" "${dgname}" "${SCSETUP_DG_VXVM_LOOKUP}"
				continue
			fi
		fi

		# Get the dg nodelist
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			nodelist="$(scsetup_get_devicegroup_nodes ${dgname})"
		fi

		# Get the nodename
		while true
		do
			answer=$(sc_prompt "$(gettext 'Name of the node to remove from this group?')") || return 1

			# Make sure the node is in the list
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
				list="$(scsetup_get_devicegroup_nodes ${dgname})"
				let found=0
				for node in ${list}
				do
					if [[ "${answer}" = "${node}" ]]; then
						let found=1
						break
					fi
				done
				if [[ ${found} -ne 1 ]]; then
					printf "$(gettext '\"%s\" is not a part of this group.')\n\n\a" "${answer}"
					continue
				fi
			fi

			# Done
			break
		done

		# Okay
		nodename=${answer}

		#
		# Set up the command set
		#

		# Initialize
		set -A SCSETUP_DO_CMDSET

		# Add the command
		SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -r -D name=${dgname},nodelist=${nodename}"

		# Attempt to issue the command
		scsetup_do_cmdset || return 1

		# Done
		break
	done

	return 0
}

#####################################################
#
# scsetup_get_changeprops_menuoption()
#
#	Print the device group change properties menu, and return the 
#	selected option.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_changeprops_menuoption()
{
	typeset sctxt_title_1="$(gettext '*** Device Group Change properties Menu ***')"
	typeset sctxt_title_2="$(gettext 'Please select from one of the following options:')"
	typeset sctxt_option_001="$(gettext 'Change the preferenced and/or failback properties')"
	typeset sctxt_option_002="$(gettext 'Change the numsecondaries property')"
	typeset sctxt_option_help="$(gettext 'Help')"
	typeset sctxt_option_return="$(gettext 'Return to the Device Groups Menu')"

	typeset option

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

	echo "${option}"

	return 0
}

#####################################################
#
# scsetup_menu_devicegroups_changeprops() [nohelp]
#
#	Device groups change properties menu.
#
#	Return:
#		Always zero
#
#####################################################
scsetup_menu_devicegroups_changeprops()
{
	# Loop around the devicegroup change properties menu
	while true
	do
		case $(scsetup_get_changeprops_menuoption) in
		'1')    scsetup_menu_changeprops_prio_failback ;;
		'2')	scsetup_menu_changeprops_numsecs ;;
		'?')    scsetup_help_devicegroups_menu ;;
		'q')    break ;;
                esac 
	done

	return 0
}

####################################################
#
# scsetup_menu_changeprops_numsecs() [nohelp]
#
#	nohelp		- if this flag is given, do not
#				clear screen, print title, print help,
#				or ask for confirmation to continue.
#
#	Change the Desired number of secondaries property of a device group.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_changeprops_numsecs()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Change numsecondaries property of a Device Group <<<
	')"
	typeset sctxt_p1="$(gettext '
		This option is used to change the \"numsecondaries\" property of a device group.
	')"
	typeset sctxt_p2="$(gettext '
		The desired number of secondaries value can be set to any 
		integer between 1 and the number of non-primary provider nodes 
		in the device group. The cluster framework will use this number
		as a guide while establishing the actual secondaries for the
		device group. The default number of secondaries for a device 
		group is 1. A smaller number of secondaries will typically
		result in less performance penalty, but it can reduce
		availability.
	')"

	typeset dgname
	typeset answer

	#
	# Print title
	#
	if [[ -z "${nohelp}" ]]; then
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Get the name of the device group
		answer=$(sc_prompt "$(gettext 'Name of the device group you want to change?')") || return 1
		dgname=${answer}

		# Make sure it is a known device group
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			dgtype=$(scsetup_get_devicegroup_type ${dgname})
			if [[ -z "${dgtype}" ]]; then
				printf "$(gettext '\"%s\" is not a known device group.')\n\n\a" "${dgname}"
				continue
			fi
		fi

		sc_print_para "$(printf "$(gettext 'If the \"numsecondaries\" property is reset, the system default value will always be used.')")"
		answer=$(sc_prompt_yesno "$(gettext 'Do you want to reset the \"numsecondaries\" property ?')") || return 1
		if [[ ${answer} = "yes" ]]; then
			#
			# Set up the command set
			#

			# Initialize
			set -A SCSETUP_DO_CMDSET

			# Add the command
			SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -c -D name=${dgname},numsecondaries="

			# Attempt to issue the command
			scsetup_do_cmdset || return 1

			# Done
			break
		fi

		numsecs=0
		while true
		do
			#Initialize
			numsecs=`${SC_SCCONF} -pv | grep "(${dgname})" | grep "Device group desired number of secondaries" | awk -F: '{print $2}'`

			# Change value
			answer=$(sc_prompt "$(gettext 'Please specify the desired number of secondaries.')" "current value:$numsecs") || return 1

			if [[ $(expr "${answer}" : '[0-9][0-9]*') -ne ${#answer} ]]; then
				printf "$(gettext 'The desired number of secondaries must be a valid positive integer.')\n"
				continue
			elif [[ ${answer} -eq 0 ]]; then
				printf "$(gettext 'The desired number of secondaries must be a valid positive integer.')\n"
				continue
			else 
				numsecs=$answer
				break
			fi
		done

		#
		# Set up the command set
		#

		# Initialize
		set -A SCSETUP_DO_CMDSET

		# Add the command
		SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -c -D name=${dgname},numsecondaries=$numsecs"

		# Attempt to issue the command
		scsetup_do_cmdset || return 1

		# Done
		break

	done

	return 0
}

#####################################################
#
# scsetup_menu_changeprops_prio_failback() [nohelp]
#
#	nohelp		- if this flag is given, do not
#				clear screen, print title, print help,
#				or ask for confirmation to continue.
#
#	Change the preference and/or failback properties of a device group.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_changeprops_prio_failback()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Change preferenced and/or failback properties of a Device Group <<<
	')"
	typeset sctxt_p1="$(gettext '
		This option is used to change the \"preferenced\" and/or
		\"failback\" properties of a device group.
	')"
	typeset sctxt_p2="$(gettext '
		The scheme for establishing the primary ownership of a
		device group is based on the setting of a special
		ownership preference attribute.  If the attribute is
		not set, the primary owner of an otherwise unowned
		device group is the first node which attempts to access
		a disk in that group. However, if this attribute is
		set, you must specify the preferred order in which
		nodes will attempt to establish ownership.
	')"
	typeset sctxt_p3="$(gettext '
		If you disable the \"preferenced\" attribute, then the
		\"failback\" attribute is also automatically disabled.
		However, if you attempt to enable or re-enable the
		\"preferenced\" attribute, you will have the choice
		of enabling or disabling the \"failback\" attribute.
	')"
	typeset sctxt_p4="$(gettext '
		Note that if the \"preferenced\" attribute is either
		enabled or re-enabled that you will be required to
		re-establish the order of nodes in the primary ownership
		preference list.
	')"
	sctxt_p1_list="$(gettext '
		Please list the order in which nodes should attempt
		to establish ownership of the group.
	')"
	sctxt_p2_list="$(gettext '
		List one node name per line:
	')"

	typeset dgname
	typeset dgtype
	typeset dg_nodelist
	typeset preferenced
	typeset failback

	integer found
	integer count
	integer listcount
	typeset nodename
	typeset node
	typeset list
	typeset foo
	typeset answer
	typeset answers

	#
	# Print title
	#
	if [[ -z "${nohelp}" ]]; then
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"
		sc_print_para "${sctxt_p3}"
		sc_print_para "${sctxt_p4}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		#Initialize
		dg_nodelist=
		preferenced=
		failback=

		# Get the name of the device group
		answer=$(sc_prompt "$(gettext 'Name of the device group you want to change?')") || return 1
		dgname=${answer}

		# Make sure it is a known device group
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			dgtype=$(scsetup_get_devicegroup_type ${dgname})
			if [[ -z "${dgtype}" ]]; then
				printf "$(gettext '\"%s\" is not a known device group.')\n\n\a" "${dgname}"
				continue
			fi
		fi

		# Disable "preferenced"?
		answer=$(sc_prompt_yesno "$(gettext 'Do you want to disable the \"preferenced\" attribute?')") || return 1
		if [[ "${answer}" = "yes" ]]; then
			preferenced="false"
			failback="disabled"
		fi

		# Disable "failback"?
		if [[ -z "${preferenced}" ]]; then
			answer=$(sc_prompt_yesno "$(gettext 'Do you just want to disable \"failback\"?')") || return 1
			if [[ "${answer}" = "yes" ]]; then
				failback="disabled"
			fi
		fi

		# Enable "preferenced"?
		if [[ -z "${preferenced}" ]] && [[ -z "${failback}" ]]; then
			answer=$(sc_prompt_yesno "$(gettext 'Do you want to enable the \"preferenced\" attribute?')") || return 1
			if [[ "${answer}" = "yes" ]]; then
				preferenced="true"
			else
				sc_print_prompt "\n$(gettext 'Type ENTER to return to the menu:')"
				read
				echo
				return 1
			fi
		fi

		# Establish list of nodes currently in device group
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			list="$(scsetup_get_devicegroup_nodes ${dgname})"
			if [[ -z "${list}" ]]; then
				printf "$(gettext 'Unable to establish the list of nodes for this device group.')\n\n\a"
				sc_prompt_pause
				return 1
			fi
		fi

		# If "preferenced" is true, get the nodelist and "failback"
		if [[ "${preferenced}" = "true" ]]; then

			# Change the preference order?
			sc_print_para "$(gettext 'Consider the following node preference order for this group:')"
			dg_nodelist="${list}"
			for node in ${list}
			do
				printf "\t${node}\n"
			done
			echo
			answer=$(sc_prompt_yesno "$(gettext 'Do you want to change it?')" "${NO}") || return 1

			# Yes, change the order
			if [[ "${answer}" = "yes" ]]; then
				dg_nodelist=
			fi
			let listcount=$(set -- ${list}; echo $#)
			while [[ -z "${dg_nodelist}" ]]
			do
				# Initialize
				let count=0
				answers=

				# Prompt
				sc_print_para "${sctxt_p1_list}"
				sc_print_para "${sctxt_p2_list}"

				# Get the new order
				while [[ ${count} -lt ${listcount} ]]
				do
					answer=$(sc_prompt "$(gettext 'Node name:')" "" "nonl") || return 1

					# Must be in our list
					let found=0
					for node in ${list}
					do
						if [[ "${answer}" = "${node}" ]]; then
							let found=1
							break
						fi
					done

					# Make sure we found it
					if [[ ${found} -eq 0 ]]; then
						echo
						printf "$(gettext 'Node is not part of this device group.')\n\n\a"
						continue
					fi

					# Make sure it is not a duplicate
					for node in ${answers}
					do
						if [[ "${answer}" = "${node}" ]]; then
							echo
							printf "$(gettext '\"%s\" already entered.')\n\n\a" "${answer}"
							continue 2
						fi
					done

					# Okay, add it to list of answers
					answers="${answers} ${answer}"

					# Next
					((count += 1))
				done

				# Verify that the list is correct
				echo
				sc_print_para "$(gettext 'This is the new preference order:')"
				for node in ${answers}
				do
					printf "\t${node}\n"
				done
				echo
				answer=$(sc_prompt_yesno "$(gettext 'Is it correct?')" "${YES}") || return 1
				if [[ "${answer}" != "yes" ]]; then
					continue
				fi

				# Set the dg nodelist
				dg_nodelist="${answers}"

				# Done
				break
			done

			# Failback?
			failback=
			answer=$(sc_prompt_yesno "$(gettext 'Enable \"failback\" for this disk device group?')" "${NO}") || return 1
			if [[ "${answer}" = "yes" ]]; then
				failback="enabled"
			else
				failback="disabled"
			fi
		fi

		# If the dg_nodelist is not set, set to the default
		if [[ -z "${dg_nodelist}" ]]; then
			dg_nodelist="${list}"
		fi

		# Reformat the dg_nodelist to give to scconf
		foo="${dg_nodelist}"
		dg_nodelist=
		for node in ${foo}
		do
			if [[ -n "${dg_nodelist}" ]]; then
				dg_nodelist="${dg_nodelist}:"
			fi
			dg_nodelist="${dg_nodelist}${node}"
		done

		#
		# Set up the command set
		#

		# Initialize
		set -A SCSETUP_DO_CMDSET

		# Add the command
		SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -c -D name=${dgname}"

		# Nodelist?
		if [[ -n "${dg_nodelist}" ]]; then
			SCSETUP_DO_CMDSET[0]="${SCSETUP_DO_CMDSET[0]},nodelist=${dg_nodelist}"
		fi

		# Preferenced?
		if [[ -n "${preferenced}" ]]; then
			SCSETUP_DO_CMDSET[0]="${SCSETUP_DO_CMDSET[0]},preferenced=${preferenced}"
		fi

		# Failback?
		if [[ -n "${failback}" ]]; then
			SCSETUP_DO_CMDSET[0]="${SCSETUP_DO_CMDSET[0]},failback=${failback}"
		fi

		# Attempt to issue the command
		scsetup_do_cmdset || return 1

		# Done
		break

	done

	return 0
}

#####################################################
#
# scsetup_help_devicegroups_menu()
#
#	Print help information from the device groups menu.
#	This is the same help information as is printed
#	from the MAIN help menu.  But, we ask for confirmation
#	before returning to the previous menu.
#
#	This function always returns zero.
#
#####################################################
scsetup_help_devicegroups_menu()
{
	clear
	scsetup_help_main_devicegroups
	sc_prompt_pause

	return 0
}

#####################################################
#
# scsetup_get_devicegroups_menuoption()
#
#	Print the device groups menu, and return the selected option.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_devicegroups_menuoption()
{
	typeset sctxt_title_1="$(gettext '*** Device Groups Menu ***')"
	typeset sctxt_title_2="$(gettext 'Please select from one of the following options:')"
	typeset sctxt_option_001="$(gettext 'Register a VxVM disk group as a device group')"
	typeset sctxt_option_002="$(gettext 'Synchronize volume information for a VxVM device group')"
	typeset sctxt_option_003="$(gettext 'Unregister a VxVM device group')"
	typeset sctxt_option_004="$(gettext 'Add a node to a VxVM device group')"
	typeset sctxt_option_005="$(gettext 'Remove a node from a VxVM device group')"
	typeset sctxt_option_006="$(gettext 'Change key properties of a device group')"
	typeset sctxt_option_help="$(gettext 'Help')"
	typeset sctxt_option_return="$(gettext 'Return to the Main Menu')"

	typeset option

	option=$(sc_get_menuoption \
		"T1+++${sctxt_title_1}" \
		"T2+++${sctxt_title_2}" \
		"S+0+1+${sctxt_option_001}" \
		"S+0+2+${sctxt_option_002}" \
		"S+0+3+${sctxt_option_003}" \
		"S+0+4+${sctxt_option_004}" \
		"S+0+5+${sctxt_option_005}" \
		"S+0+6+${sctxt_option_006}" \
		"R+++" \
		"S+0+?+${sctxt_option_help}" \
		"S+0+q+${sctxt_option_return}" \
	)

	echo "${option}"

	return 0
}

#####################################################
#
# scsetup_menu_devicegroups()
#
#	Device groups menu
#
#	This function always returns zero.
#
#####################################################
scsetup_menu_devicegroups()
{
	# Loop around the devicegroups menu
	while true
	do
		case $(scsetup_get_devicegroups_menuoption) in
		'1')    scsetup_menu_devicegroups_addvxvm ;;
		'2')	scsetup_menu_devicegroups_syncvxvm ;;
		'3')    scsetup_menu_devicegroups_rmvxvm ;;
		'4')    scsetup_menu_devicegroups_addnodevxvm ;;
		'5')    scsetup_menu_devicegroups_rmnodevxvm ;;
		'6')    scsetup_menu_devicegroups_changeprops ;;
		'?')    scsetup_help_devicegroups_menu ;;
		'q')    break ;;
                esac 
	done

	return 0
}

#####################################################
#####################################################
##
## Authentication of nodes able to install into the cluster
##
#####################################################
#####################################################

#####################################################
#
# scsetup_menu_auth_alloff() [nohelp]
#
#	nohelp		- if this flag is given, do not
#				clear screen or print title.
#
#	Prevent any new machines from installing into the cluster.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_auth_alloff()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Prevent Any New Machines from Installing into the Cluster <<<
	')"
	typeset sctxt_p1="$(gettext '
		This option is used to prevent any new machines from
		installing themselves into the cluster.  It does this
		by setting an attribute which tells the processes
		responsible for helping new machines to add themselves
		to the cluster to ignore all such add requests coming
		in over the public network.
	')"

	#
	# Clear screen and print title
	#
	if [[ -z "${nohelp}" ]]; then
		clear
		sc_print_title "${sctxt_title}"
	fi

	# Print help
	sc_print_para "${sctxt_p1}"

	#
	# Set up the command set
	#

	# Initialize
	set -A SCSETUP_DO_CMDSET

	# Add the command
	SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -a -T node=."

	# Attempt to issue the command
	scsetup_do_cmdset || return 1

	return 0
}

#####################################################
#
# scsetup_menu_auth_allon() [nohelp]
#
#	nohelp		- if this flag is given, do not
#				clear screen or print title.
#
#	Allow any machine to install into the cluster.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_auth_allon()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Permit Any Machine to Install itself into the Cluster <<<
	')"
	typeset sctxt_p1="$(gettext '
		This option is used to permit any machine to install
		itself into the cluster.  It does this by completely
		clearing the list of machines recognized as being
		permitted to install themselves into the cluster.  An
		empty list means that any node can add itself.  When
		the processes responsible for helping new machines to
		add themselves to the cluster confirm that the list is
		empty, they attempt to honor all such add requests
		coming in over the public network.
	')"
	typeset sctxt_p2="$(gettext '
		Of course, any machine attempting to install itself as
		a cluster node must first have all of the necessary
		software and hardware correctly installed and configured,
		including a good physical connection to the private cluster
		interconnect.  Refer to the Sun Cluster installation
		documentation and the scinstall(1M) man page for more
		information regarding installation and adding new machines
		to the cluster.
	')"

	#
	# Clear screen and print title
	#
	if [[ -z "${nohelp}" ]]; then
		clear
		sc_print_title "${sctxt_title}"
	fi

	# Print help
	sc_print_para "${sctxt_p1}"
	sc_print_para "${sctxt_p2}"

	#
	# Set up the command set
	#

	# Initialize
	set -A SCSETUP_DO_CMDSET

	# Add the command
	SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -r -T all"

	# Attempt to issue the command
	scsetup_do_cmdset || return 1

	return 0
}

#####################################################
#
# scsetup_menu_auth_addnode() [nohelp]
#
#	nohelp		- if this flag is given, do not
#				clear screen, print title, print help,
#				or ask for confirmation to continue.
#
#	Add a machine to the list of nodes permitted to install into
#	the cluster.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_auth_addnode()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Specify a Machine which may Install itself into the Cluster <<<
	')"
	typeset sctxt_p1="$(gettext '
		This option is used to permit a given machine to
		install itself into the cluster.  It does this by
		adding the node name that you give to the list of nodes
		recognized as being permitted to install themselves
		into the cluster.
	')"
	typeset sctxt_p2="$(gettext '
		Of course, any machine attempting to install itself as
		a cluster node must first have all of the necessary
		software and hardware correctly installed and configured,
		including a good physical connection to the private cluster
		interconnect.  Refer to the Sun Cluster installation
		documentation and the scinstall(1M) man page for more
		information regarding installation and adding new machines
		to the cluster.
	')"

	typeset addhost
	typeset answer

	#
	# Clear screen and print title
	#
	if [[ -z "${nohelp}" ]]; then
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"
		sc_print_para "${sctxt_p2}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Get the name of the machine
		answer=$(sc_prompt "$(gettext 'Name of the host to add to the list of recognized machines?')") || return 1
		addhost=${answer}

		#
		# Set up the command set
		#

		# Initialize
		set -A SCSETUP_DO_CMDSET

		# Add the command
		SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -a -T node=${addhost}"

		# Attempt to issue the command
		scsetup_do_cmdset || return 1

		# Done
		break
	done

	return 0
}

#####################################################
#
# scsetup_menu_auth_unix() [nohelp]
#
#	nohelp		- if this flag is given, do not
#				clear screen or print title.
#
#	Use standard UNIX authentication methods for install.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_auth_unix()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Use standard UNIX Authentication <<<
	')"
	typeset sctxt_p1="$(gettext '
		To be added as a cluster node, a machine must appear in
		the list of hosts that are permitted to install themselves
		into cluster configuration.  If this list is empty, any
		machine may add itself to the cluster configuration.
	')"
	typeset sctxt_p2="$(gettext '
		The identity of machines contacting the cluster over
		the public network for installation purposes may be
		confirmed using either standard UNIX or the more secure
		Diffie-Hellman, or DES, authentication.  However, DES
		authentication is not usually considered necessary for
		this purpose, since machines which are not physically
		connected to the cluster interconnect will never be
		able to actually join the cluster membership anyway.
	')"
	typeset sctxt_p3="$(gettext '
		Standard UNIX authentication is the default.  This option
		is used to restore this default.
	')"

	#
	# Clear screen and print title
	#
	if [[ -z "${nohelp}" ]]; then
		clear
		sc_print_title "${sctxt_title}"
	fi

	# Print help
	sc_print_para "${sctxt_p1}"
	sc_print_para "${sctxt_p2}"
	sc_print_para "${sctxt_p3}"

	#
	# Set up the command set
	#

	# Initialize
	set -A SCSETUP_DO_CMDSET

	# Add the command
	SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -c -T authtype=unix"

	# Attempt to issue the command
	scsetup_do_cmdset || return 1

	return 0
}


#####################################################
#
# scsetup_menu_auth_des() [nohelp]
#
#	nohelp		- if this flag is given, do not
#				clear screen or print title.
#
#	Use DES authentication methods for install.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_auth_des()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Use Diffie-Hellman Authentication <<<
	')"
	typeset sctxt_p1="$(gettext '
		To be added as a cluster node, a machine must appear in
		the list of hosts that are permitted to install themselves
		into cluster configuration.  If this list is empty, any
		machine may add itself to the cluster configuration.
	')"
	typeset sctxt_p2="$(gettext '
		The identity of machines contacting the cluster over
		the public network for installation purposes may be
		confirmed using either standard UNIX or the more secure
		Diffie-Hellman, or DES, authentication.  However, DES
		authentication is not usually considered necessary for
		this purpose, since machines which are not physically
		connected to the private cluster interconnect will
		never be able to actually join the cluster membership
		anyway.
	')"
	typeset sctxt_p3="$(gettext '
		This option is used to select DES authentication methods
		for use during node installation.  Remember that if
		DES authentication is selected, you must also configure
		all necessary encryption keys before a node can join
		(see keyserv(1M), publickey(4)).
	')"

	#
	# Clear screen and print title
	#
	if [[ -z "${nohelp}" ]]; then
		clear
		sc_print_title "${sctxt_title}"
	fi

	# Print help
	sc_print_para "${sctxt_p1}"
	sc_print_para "${sctxt_p2}"
	sc_print_para "${sctxt_p3}"

	#
	# Set up the command set
	#

	# Initialize
	set -A SCSETUP_DO_CMDSET

	# Add the command
	SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -c -T authtype=des"

	# Attempt to issue the command
	scsetup_do_cmdset || return 1

	return 0
}

#####################################################
#
# scsetup_help_auth_menu()
#
#	Print help information from the auth menu.
#	This is the same help information as is printed
#	from the MAIN help menu.  But, we ask for confirmation
#	before returning to the previous menu.
#
#	This function always returns zero.
#
#####################################################
scsetup_help_auth_menu()
{
	clear
	scsetup_help_main_auth
	sc_prompt_pause

	return 0
}

#####################################################
#
# scsetup_get_auth_menuoption()
#
#	Print the authentication menu, and return the selected option.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_auth_menuoption()
{
	typeset sctxt_title_1="$(gettext '*** New Nodes Menu ***')"
	typeset sctxt_title_2="$(gettext 'Please select from one of the following options:')"
	typeset sctxt_option_001="$(gettext 'Prevent any new machines from being added to the cluster')"
	typeset sctxt_option_002="$(gettext 'Permit any machine to add itself to the cluster')"
	typeset sctxt_option_003="$(gettext 'Specify the name of a machine which may add itself')"
	typeset sctxt_option_004="$(gettext 'Use standard UNIX authentication')"
	typeset sctxt_option_005="$(gettext 'Use Diffie-Hellman authentication')"
	typeset sctxt_option_help="$(gettext 'Help')"
	typeset sctxt_option_return="$(gettext 'Return to the Main Menu')"

	typeset option

	option=$(sc_get_menuoption \
		"T1+++${sctxt_title_1}" \
		"T2+++${sctxt_title_2}" \
		"S+0+1+${sctxt_option_001}" \
		"S+0+2+${sctxt_option_002}" \
		"S+0+3+${sctxt_option_003}" \
		"S+0+4+${sctxt_option_004}" \
		"S+0+5+${sctxt_option_005}" \
		"R+++" \
		"S+0+?+${sctxt_option_help}" \
		"S+0+q+${sctxt_option_return}" \
	)

	echo "${option}"

	return 0
}

#####################################################
#
# scsetup_menu_auth()
#
#	Authentication menu
#
#	This function always returns zero.
#
#####################################################
scsetup_menu_auth()
{
	# Loop around the auth menu
	while true
	do
		case $(scsetup_get_auth_menuoption) in
		'1')    scsetup_menu_auth_alloff ;;
		'2')    scsetup_menu_auth_allon ;;
		'3')    scsetup_menu_auth_addnode ;;
		'4')    scsetup_menu_auth_unix ;;
		'5')    scsetup_menu_auth_des ;;
		'?')    scsetup_help_auth_menu ;;
		'q')    break ;;
                esac 
	done

	return 0
}

#####################################################
#####################################################
##
## Other cluster-wide options
##
#####################################################
#####################################################

#####################################################
#
# scsetup_menu_other_clustername() [nohelp]
#
#	nohelp		- if this flag is given, do not
#				clear screen, print title, print help,
#				or ask for confirmation to continue.
#
#	Change the the name of the cluster.
#
#	Return:
#		zero		Completed
#		non-zero	Not completed
#
#####################################################
scsetup_menu_other_clustername()
{
	typeset nohelp=${1}

	typeset sctxt_title="$(gettext '
		>>> Changing the Name of the Cluster <<<
	')"
	typeset sctxt_p1="$(gettext '
		This option is used to change the name of the cluster.
	')"

	typeset answer
	typeset clustername

	#
	# Print help
	#
	if [[ -z "${nohelp}" ]]; then
		clear
		sc_print_title "${sctxt_title}"
		sc_print_para "${sctxt_p1}"

		# Okay to continue?
		scsetup_continue || return 1
	fi

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Get the new cluster name
		answer=$(sc_prompt "$(gettext 'What name do you want to assign to this cluster?')") || return 1
		clustername=${answer}

		#
		# Set up the command set
		#

		# Initialize
		set -A SCSETUP_DO_CMDSET

		# Add the command
		SCSETUP_DO_CMDSET[0]="${SC_SCCONF} -c -C cluster=${clustername}"

		# Attempt to issue the command
		scsetup_do_cmdset || return 1

		# Done
		break
	done

	return 0
}

#####################################################
#
# scsetup_help_other_menu()
#
#	Print help information from the other cluster props menu.
#	This is the same help information as is printed
#	from the MAIN help menu.  But, we ask for confirmation
#	before returning to the previous menu.
#
#	This function always returns zero.
#
#####################################################
scsetup_help_other_menu()
{
	clear
	scsetup_help_main_other
	sc_prompt_pause

	return 0
}

#####################################################
#
# scsetup_get_other_menuoption()
#
#	Print the other cluster options menu, and return the selected option.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_other_menuoption()
{
	typeset sctxt_title_1="$(gettext '*** Other Cluster Properties Menu ***')"
	typeset sctxt_title_2="$(gettext 'Please select from one of the following options:')"
	typeset sctxt_option_001="$(gettext 'Change the name of the cluster')"
	typeset sctxt_option_help="$(gettext 'Help')"
	typeset sctxt_option_return="$(gettext 'Return to the Main Menu')"

	typeset option

	option=$(sc_get_menuoption \
		"T1+++${sctxt_title_1}" \
		"T2+++${sctxt_title_2}" \
		"S+0+1+${sctxt_option_001}" \
		"R+++" \
		"S+0+?+${sctxt_option_help}" \
		"S+0+q+${sctxt_option_return}" \
	)

	echo "${option}"

	return 0
}

#####################################################
#
# scsetup_menu_other()
#
#	Other cluster properties menu
#
#	This function always returns zero.
#
#####################################################
scsetup_menu_other()
{
	# Loop around
	while true
	do
		case $(scsetup_get_other_menuoption) in
		'1')    scsetup_menu_other_clustername ;;
		'?')    scsetup_help_other_menu ;;
		'q')    break ;;
                esac 
	done

	return 0
}

#####################################################
#####################################################
##
## Main menu
##
#####################################################
#####################################################

#####################################################
#
# scsetup_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.
#
#####################################################
scsetup_get_main_menuoption()
{
	typeset help=${1}

	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 'Quorum')"
	typeset sctxt_option_002="$(gettext 'Resource groups')"
	typeset sctxt_option_003="$(gettext 'Data Services')"
	typeset sctxt_option_004="$(gettext 'Cluster interconnect')"
	typeset sctxt_option_005="$(gettext 'Device groups and volumes')"
	typeset sctxt_option_006="$(gettext 'Private hostnames')"
	typeset sctxt_option_007="$(gettext 'New nodes')"
	typeset sctxt_option_008="$(gettext 'Other cluster properties')"
	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 option

	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}" \
			"S+0+6+${sctxt_option_006}" \
			"S+0+7+${sctxt_option_007}" \
			"S+0+8+${sctxt_option_008}" \
			"R+++" \
			"S+0+q+${sctxt_option_return}" \
		)
	else
		option=$(sc_get_menuoption \
			"T1+++${sctxt_title_1_main}" \
			"T2+++${sctxt_title_2_main}" \
			"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}" \
			"S+0+6+${sctxt_option_006}" \
			"S+0+7+${sctxt_option_007}" \
			"S+0+8+${sctxt_option_008}" \
			"R+++" \
			"S+0+?+${sctxt_option_help}" \
			"S+0+q+${sctxt_option_exit}" \
		)
	fi

	echo "${option}"

	return 0
}

#####################################################
#
# scsetup_help_main_menu 
#
#	Print help information for the main menu.
#
#####################################################
scsetup_help_main_menu()
{
	while true
	do
		case $(scsetup_get_main_menuoption help) in
		'1')	scsetup_help_main_quorum ;;
		'2')	scsetup_help_main_rgm ;;
		'3')	scsetup_help_main_dataservices ;;
		'4')	scsetup_help_main_transport ;;
		'5')	scsetup_help_main_devicegroups ;;
		'6')	scsetup_help_main_privatehosts ;;
		'7')	scsetup_help_main_auth ;;
		'8')	scsetup_help_main_other ;;
		'q')	break ;;
		esac

		echo
		sc_print_prompt "$(gettext 'Type ENTER to return to the previous menu:')" || return 1
		read
		echo
	done

	return 0
}

#####################################################
#
# scsetup_menu()
#
#	Menu driven scsetup.
#
#	This function always returns zero.
#
#####################################################
scsetup_menu()
{
	# Loop around the main menu
	while true
	do
		case $(scsetup_get_main_menuoption) in
		'1')    scsetup_menu_quorum ;;
		'2')	scsetup_menu_rgm ;;
		'3')	scsetup_menu_dataservices ;;
		'4')    scsetup_menu_transport ;;
		'5')    scsetup_menu_devicegroups ;;
		'6')    scsetup_menu_privatehosts ;;
		'7')    scsetup_menu_auth ;;
		'8')    scsetup_menu_other ;;
		'?')    scsetup_help_main_menu ;;
		'q')    break ;;
                esac 
	done

	return 0
}

#####################################################
#####################################################
##
## Initialize cluster
##
#####################################################
#####################################################

#####################################################
#
# scsetup_initcluster()
#
#	The purpose of this function is to provide an interactive
#	dialog to the user at initial install time for setting up
#	quorum, resetting installmode, etc.
#
#	This function should only be called if installmode is enabled.
#
#	Return:
#		zero 		Success
#		non-zero	Failure
#
#####################################################
scsetup_initcluster()
{
	typeset sctxt_title="$(gettext '
		>>> Initial Cluster Setup <<<
	')"
	typeset sctxt_p1="$(gettext '
		This program has detected that the cluster \"installmode\"
		attribute is still enabled.  As such, certain initial
		cluster setup steps will be performed at this time.
		This includes adding any necessary quorum devices,
		then resetting both the quorum vote counts and the
		\"installmode\" property.
	')"
	typeset sctxt_p2="$(gettext '
		Please do not proceed if any additional nodes have yet
		to join the cluster.
	')"
	typeset sctxt_p1_qdev="$(gettext '
		Dual-ported SCSI-2 disks may be used as quorum devices
		in two-node clusters.  However, clusters with more than
		two nodes require that SCSI-3 PGR disks be used for all
		disks with more than two node-to-disk paths.  You can
		use a disk containing user data or one that is a member
		of a device group as a quorum device.
	')"
	typeset sctxt_p2_qdev="$(gettext '
		Each quorum disk must be connected to at least
		two nodes.  Please refer to the Sun Cluster documentation
		for more information on supported quorum device topologies.
	')"
	typeset sctxt_p1_reset="$(gettext '
		Once the \"installmode\" property has been reset,
		this program will skip \"Initial Cluster Setup\"
		each time it is run again in the future.  However,
		quorum devices can always be added to the cluster
		using the regular menu options.  Resetting this
		property fully activates quorum settings and is
		necessary for the normal and safe operation of
		the cluster.
	')"
	typeset sctxt_reset_cmd1="${SC_SCCONF} -c -q reset"
	typeset sctxt_reset_cmd2="${SC_SCCONF} -a -T node=."

	integer nodecount
	integer qdevcount
	integer status
	typeset nodelist
	typeset qdevlist
	typeset answer

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

	# Okay to continue?
	scsetup_continue || return 1

	# Loop until done or Ctrl-D is typed
	while true
	do
		# Initialize
		let nodecount=0
		let qdevcount=0
		nodelist=
		qdevlist=

		# Get nodelist and nodecount
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then

			# Get nodelist
			nodelist="$(scsetup_get_nodelist)"

			# Make sure we have a nodelist
			if [[ -z "${nodelist}" ]]; then
				printf "$(gettext 'Unable to establish the list of cluster nodes.')\n\n\a"
				sc_prompt_pause
				return 1
			fi

			# Set node count
			let nodecount=$(set -- ${nodelist}; echo $#)
		else
			# We must be running in DEBUG mode
			while true
			do
				answer=$(sc_prompt "$(gettext 'DEBUG:  How  many nodes are in the cluster?')") || return 1

				# In range?
				if [[ $(expr ${answer} : '[0-9]*') -ne $(expr ${answer} : '.*') ]] ||
				    [[ ${answer} -lt 1 ]] ||
				    [[ ${answer} -gt ${SC_MAXNODEID} ]]; then
					printf "\a"
				else
					break
				fi
			done

			# Set nodecount
			let nodecount=${answer}
		fi

		# Make sure that we have at least two nodes
		if [[ ${nodecount} -lt 2 ]]; then
			printf "$(gettext 'The cluster must have at least two nodes before running %s.')\n\n\a" "${PROG}"
			return 1
		fi

		# Add any needed quorum devices
		while true
		do
			# Do you want to add any quorum devices?
			answer=$(sc_prompt_yesno "$(gettext 'Do you want to add any quorum disks?')" "${YES}") || return 1

			# Okay, add device
			if [[ "${answer}" = "yes" ]]; then

				# Print help
				sc_print_para "${sctxt_p1_qdev}"
				sc_print_para "${sctxt_p2_qdev}"

				# Add it
				while true
				do
					# Try again?
					scsetup_menu_quorum_addev "nohelp"
					if [[ $? -ne 0 ]]; then
						answer=$(sc_prompt_yesno "$(gettext 'Do you want to try again?')") || return 1
					else
						answer=$(sc_prompt_yesno "$(gettext 'Do you want to add another quorum disk?')") || return 1
						# If DEBUG, add to qdevcount
						if [[ ${SCSETUP_ISMEMBER} -eq 0 ]]; then
							((qdevcount += 1))
						fi
					fi
					if [[ "${answer}" = "no" ]]; then
						break
					fi
				done
			fi

			#
			# Get qdevlist and qdevcount
			# Note that if we are not a cluster member,
			# we must be in DEBUG mode.  In DEBUG, the qdevcount
			# was alredy adjusted for us on successful return
			# from scsetup_menu_quorum_addev().
			#
			if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then

				# Get qdevlist
				qdevlist="$(scsetup_get_qdevlist)"

				# Set qdevcount count
				let qdevcount=$(set -- ${qdevlist}; echo $#)
			fi

			# All two node clusters must have at least one qdev
			if [[ ${nodecount} -eq 2 ]] &&
			    [[ ${qdevcount} -lt 1 ]]; then
				printf "$(gettext 'All two-node clusters must have at least one quorum disk.')\n\n\a"
				return 1
			fi

			# Done
			break
		done

		# Reset installmode
		sc_print_para "${sctxt_p1_reset}"
		answer=$(sc_prompt_yesno "$(gettext 'Is it okay to reset \"installmode\"?')" "${YES}") || return 1
		if [[ "${answer}" = "yes" ]] &&
		    [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then

			# Run the commands
			echo
			echo "${sctxt_reset_cmd1}"
			${sctxt_reset_cmd1} 2>&1
			status=$?
			if [[ ${status} -eq 0 ]]; then
				echo "${sctxt_reset_cmd2}"
				${sctxt_reset_cmd2} 2>&1
				status=$?
			fi

			# Failed
			if [[ ${status} -ne 0 ]]; then
				echo
				printf "$(gettext 'Command failed.')\n\n\a"
				return 1
			fi

			# Log it
			if [[ -n "${SCSETUP_CMD_LOG}" ]]; then
				echo "${sctxt_reset_cmd1}" >>${SCSETUP_CMD_LOG}
				echo "${sctxt_reset_cmd2}" >>${SCSETUP_CMD_LOG}
			fi

			# Success message
			echo
			sc_print_para "$(gettext 'Cluster initialization is complete.')"

			# Pause
			echo
			sc_print_prompt "$(gettext 'Type ENTER to proceed to the main menu:')" || return 1
			read
			echo

		# If no reset to installmode, return error
		elif [[ "${answer}" = "no" ]]; then
			return 1
		fi

		# Done
		break
	done

	return 0
}

#####################################################
#####################################################
##
## Main
##
#####################################################
#####################################################
main()
{
	typeset c
	integer isinstallmode=0
	integer result

	# load common functions
	loadlib ${SC_SCADMINLIBDIR}/${SC_LIB_SC} ${SC_LOADED_COMMON} || return 1
	let SC_LOADED_COMMON=1

	# Make sure that we are a member of the cluster
        if [[ -x /usr/sbin/clinfo ]]; then
                eval /usr/sbin/clinfo >/dev/null 2>&1
                if [[ $? -eq 0 ]]; then
			let SCSETUP_ISMEMBER=1
		elif [[ -z "${SC_DEBUG}" ]]; then
			printf "$(gettext '%s:  This node is not currently in the cluster')\n" "${PROG}" >&2
			return 1
		fi
	fi

	# If we are a cluster member, we must be root
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
		verify_isroot || return 1
	fi

	# If installmode is enabled, we do not want to do menu driven interface
	let isinstallmode=0
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
		let isinstallmode=$(scsetup_get_installmode)
	fi

	# Arrange for cleanup on SIGHUP or SIGINT
	trap 'cleanup 10' HUP INT

	# Create scsetup tmpdir, if it does not already exist
	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]] &&
	    [[ ! -d "${SCSETUP_TMPDIR}" ]] &&
	    [[ -d "$(dirname ${SCSETUP_TMPDIR})" ]]; then
		mkdir -m 0755 ${SCSETUP_TMPDIR}
		chgrp sys ${SCSETUP_TMPDIR}
	fi

	# If scsetup is just being used as a "library", we are done
	if [[ -n "${SCSETUP_LIBRARY}" ]]; then
		return 0
	fi

	# Get command line options, if there are any.
	while getopts f: c 2>/dev/null
	do
		case ${c} in
		f)	# Log file

			# Make sure the log file is not already set
			if [[ -n "${SCSETUP_CMD_LOG}" ]]; then
				print_usage
				return 1
			fi

			# Set the logfile
			SCSETUP_CMD_LOG=${OPTARG}

			# Add heading for this session to the log file
			if [[ -s "${SCSETUP_CMD_LOG}" ]]; then
				printf "\n" >>${SCSETUP_CMD_LOG} 2>/dev/null
			fi
			printf "#\n" >>${SCSETUP_CMD_LOG} 2>/dev/null
			if [[ $? -ne 0 ]]; then
				printf "$(gettext '%s:  Unable to write to the command log.')\n" "${PROG}" >&2
				return 1
			fi
			printf "# %s - %s\n" "${PROG}" "$(date)" >>${SCSETUP_CMD_LOG}
			printf "#\n" >>${SCSETUP_CMD_LOG}
			;;

		\?)	# bad option
			print_usage
			return 1
			;;

		*)	# we missed something!
			printf "$(gettext '%s:  Internal error checking usage')\n" "${PROG}" >&2
			return 1
			;;
		esac
	done
		
	# Generate start event
	generate_event "cmd_start" 0
	
	# If isinstallmode, initialize cluster before proceeding to menu
	if [[ ${isinstallmode} -eq 1 ]] || [[ "${SC_DEBUG}" = "2" ]]; then
		# Init cluster
		scsetup_initcluster || return 1

		# Make sure isinstallmode was cleared
		let isinstallmode=0
		if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
			let isinstallmode=$(scsetup_get_installmode)
		fi

		# If isinstallmode is not set, do not proceed to menu
		if [[ ${isinstallmode} -eq 1 ]]; then
			return 0
		fi
	fi

	# Go to the menu
	scsetup_menu

	# Cleanup files
	cleanup

	# Return
	return 0
}

#####################################################
#
# scsetup_help_main_dataservices()
#
#	Print the main help message for Data services.
#
#	This function always returns zero.
#
#####################################################
scsetup_help_main_dataservices()
{
	typeset sctxt_title="$(gettext '
		*** Help Screen - Data services ***
	')"
	typeset sctxt_p1="$(gettext '
		Data services on a Sun Cluster are applications, such as Oracle
		RAC, that have been configured to run on a cluster rather than
		on a single server. A data service includes the application
		software and the supporting Sun Cluster software that starts,
		stops and monitors the application.
	')"

	sc_print_title "${sctxt_title}"
	sc_print_para "${sctxt_p1}"

	return 0
}

#####################################################
#
# scsetup_menu_dataservices()
#
#	Data services menu
#
#	This function always returns zero.
#
#####################################################
scsetup_menu_dataservices()
{
	# Loop around the dataservices menu
	while true
	do
		case $(scsetup_get_dataservices_menuoption) in
		'1')    scsetup_menu_dataservices_oraclerac ;;
		'?')    scsetup_help_dataservices_menu ;;
		'q')    break ;;
                esac 
	done

	return 0
}

#####################################################
#
# scsetup_help_dataservices_menu()
#
#	Print help information from the Data services menu.
#	This is the same help information as is printed
#	from the MAIN help menu.  But, we ask for confirmation
#	before returning to the previous menu.
#
#	This function always returns zero.
#
#####################################################
scsetup_help_dataservices_menu()
{
	clear
	scsetup_help_main_dataservices
	sc_prompt_pause

	return 0
}

#####################################################
#
# scsetup_get_dataservices_menuoption()
#
#	Print the Data services menu, and return the selected option.
#
#	This function always returns zero.
#
#####################################################
scsetup_get_dataservices_menuoption()
{
	typeset sctxt_title_1="$(gettext '*** Data Services Menu ***')"
	typeset sctxt_title_2="$(gettext 'Please select from one of the following options:')"
	typeset sctxt_option_001="$(gettext 'Sun Cluster support for Oracle RAC')"

	typeset sctxt_option_help="$(gettext 'Help')"
	typeset sctxt_option_return="$(gettext 'Return to the Main Menu')"

	typeset option

	option=$(sc_get_menuoption \
		"T1+++${sctxt_title_1}" \
		"T2+++${sctxt_title_2}" \
		"S+0+1+${sctxt_option_001}" \
		"R+++" \
		"S+0+?+${sctxt_option_help}" \
		"S+0+q+${sctxt_option_return}" \
	)

	echo "${option}"

	return 0
}

#####################################################
#
# scsetup_menu_dataservices_oraclerac()
#
#	Print the Oracle RAC Configuration menu,
#	and return the selected option.
#
#	This function always returns zero.
#
#####################################################
scsetup_menu_dataservices_oraclerac()
{
	typeset sctxt_title="$(gettext '
		*** Sun Cluster Support for Oracle RAC ***
	')"
	typeset sctxt_p1="$(gettext '
		Sun Cluster provides a support layer for running Oracle Real
		Application Clusters \(RAC\) database instances. This option
		enables you to create and modify the RAC framework resource
		group for managing the Sun Cluster support for RAC.
	')"
	typeset sctxt_p2="$(gettext '
		After the RAC framework resource group has been created,
		you can use the Sun Cluster system administration tools to
		administer the RAC framework resource group.
	')"
	typeset sctxt_prompt="$(gettext 'Please select from one of the following options:')"
	typeset sctxt_option_001="$(gettext 'Create the RAC framework resource group')"
	typeset sctxt_option_002="$(gettext 'Remove the RAC framework resource group')"
	typeset sctxt_option_003="$(gettext 'Add nodes to the RAC framework resource group')"
	typeset sctxt_option_004="$(gettext 'Remove nodes from the RAC framework resource group')"
	typeset sctxt_option_status="$(gettext 'Show the status of RAC framework resource group')"
	typeset sctxt_option_return="$(gettext 'Return to the Data Services Menu')"
	typeset option

	sc_print_title "${sctxt_title}"
	sc_print_para "${sctxt_p1}"
	sc_print_para "${sctxt_p2}"

	if [[ ! -x ${RAC_SETUP} ]];then
		printf "$(gettext 'Sun Cluster support for Oracle RAC is not installed on this system.')\n" "${PROG}" >&2
		sc_prompt_pause
		return 1
	fi

	scsetup_continue || return 1

		
	# Loop around the dataservices menu
	while true
	do
		option=$(sc_get_menuoption \
			"T2+++${sctxt_prompt}" \
			"S+0+1+${sctxt_option_001}" \
			"S+0+2+${sctxt_option_002}" \
			"S+0+3+${sctxt_option_003}" \
			"S+0+4+${sctxt_option_004}" \
			"R+++" \
			"S+0+s+${sctxt_option_status}" \
			"S+0+q+${sctxt_option_return}" \
		)

		case ${option} in
		'1')    scsetup_menu_dataservices_oraclerac_createrg ;;
		'2')    scsetup_menu_dataservices_oraclerac_removerg ;;
		'3')    scsetup_menu_dataservices_oraclerac_addnodes ;;
		'4')    scsetup_menu_dataservices_oraclerac_removenodes ;;
		's')    scsetup_menu_dataservices_oraclerac_status ;;
		'q')    break ;;
                esac 
	done

	return 0
}


#####################################################
#
# scsetup_menu_dataservices_oraclerac_createrg()
#
#	This fuction creates the Oracle RAC resource group.
#	The node list for the RAC resource group is evaluated.
#	This function calls the "rac_setup" script to create
#	the RAC resource group.
#
#	Return:
#		zero		Completed
#		non-zero	Not successful
#
#####################################################
scsetup_menu_dataservices_oraclerac_createrg()
{
	typeset prompt
	typeset rg_state
	typeset rg_name=$(${RAC_SETUP} -G)
	typeset node
	typeset nodelist
	typeset set_nodelist
	typeset log_option
	typeset sctxt_p1="$(gettext '
		This option is used to create the RAC framework resource
		group. You must now choose the cluster nodes that you want to
		be configured in the resource group.
	')"


	# Get resource group name and state
	rg_name=${rg_name:-"rac-framework-rg"}
	rg_state=$(${SCHA_RG_GET} -G ${rg_name} -O RG_STATE)

	if [[ $? -eq 0 ]];then
		sc_print_para "$(printf "$(gettext 'The RAC framework resource group \"%s\" already exists.')\n" "${rg_name}")"
		sc_prompt_pause
		return 1
	fi

	nodelist=$(scsetup_get_nodelist)

	sc_print_title "${sctxt_title}"

	sc_print_para "${sctxt_p1}"

	answer=$(sc_prompt_yesno "$(gettext 'Do you want to configure all nodes in the resource group?')" "${YES}") || return 1

	if [[ "${answer}" = "yes" ]]; then
		set_nodelist=${nodelist}
	else
		prompt="$(gettext 'Select cluster nodes that you want to add to this resource group:')"
		set_nodelist="$(
				sc_get_scrolling_menuoptions	\
					"${prompt}"		\
					"" ""			\
					1 0 0			\
					${nodelist}	\
			)"
	fi

	printf "    $(gettext 'You are about to create Oracle RAC framework resource group on these nodes.')\n\n"

	printf "%-25s %s\n\n" "$(gettext 'Resource Group')" "${rg_name}"

	for node in ${set_nodelist}
	do
		printf "%-25s %s\n" "$(gettext "Node")" "${node}"
	done

	print

	scsetup_continue || return 1

	if [[ -n ${SCSETUP_CMD_LOG} ]];then
		log_option="-f ${SCSETUP_CMD_LOG}"
	fi

	set_nodelist=$(echo ${set_nodelist}|sed -e "s/ /,/g")
	${RAC_SETUP} -a -g ${rg_name} -j ALL -v -N ${set_nodelist} ${log_option}

	if [[ $? -ne 0 ]];then
		printf "$(gettext 'Commands failed.')\n\n\a"
		sc_prompt_pause
		return 1
	fi

	sc_print_para "$(gettext 'Commands completed successfully.')"
	sc_prompt_pause
	return 0
}

#####################################################
#
# scsetup_menu_dataservices_oraclerac_removerg()
#
#
#	This fuction removes the Oracle RAC resource group.
#	This function calls the "rac_setup" script to remove
#	the RAC resource group.
#
#	Return:
#		zero		Completed
#		non-zero	Not successful
#
#####################################################
scsetup_menu_dataservices_oraclerac_removerg()
{
	typeset rg_state
	typeset -l lrg_state
	typeset rg_name=$(${RAC_SETUP} -G)
	typeset answer
	typeset log_option

	# Get resource group name and state
	rg_name=${rg_name:-"rac-framework-rg"}
	lrg_state=$(${SCHA_RG_GET} -G ${rg_name} -O RG_STATE)
	# lrg_state=${rg_state}

	if [[ $? -ne 0 ]];then
		printf "$(gettext 'The RAC framework resource group does not exist.')\n"
		sc_prompt_pause
		return 1
	fi

	printf "    $(gettext 'The "%s" resource group is %s.')\n\n" "${rg_name}" "${lrg_state}"

	prompt="$(printf "$(gettext 'Is it okay to remove \"%s\" resource group?')" "${rg_name}")"
	answer=$(sc_prompt_yesno "${prompt}" "${NO}")

	if [[ ${answer} == "no" ]];then
		return 1
        fi

	if [[ -n ${SCSETUP_CMD_LOG} ]];then
		log_option="-f ${SCSETUP_CMD_LOG}"
	fi

	${RAC_SETUP} -R -g $rg_name -v ${log_option}

	if [[ $? -ne 0 ]];then
		printf "$(gettext 'Commands failed.')\n\n\a"
		sc_prompt_pause
		return 1
	fi

	sc_print_para "$(gettext 'Commands completed successfully.')"
	sc_prompt_pause
	return 0

}

#####################################################
#
# scsetup_menu_dataservices_oraclerac_addnodes()
#
#	This fuction adds nodes to the Oracle RAC resource group.
#	This function calls the "rac_setup" script to modify
#	the Nodelist property of the RAC resource group. Additionally
#	the program also sets the maximum_primaries and desired_primaries
#	properties to the number of nodes selected.
#
#	Return:
#		zero		Completed
#		non-zero	Not successful
#
#####################################################
scsetup_menu_dataservices_oraclerac_addnodes()
{
	typeset addnodes=
	typeset nonracnodes=
	typeset racnodes
	typeset racnode
	typeset node
	typeset nodelist
	typeset set_nodelist
	typeset rg_state
	typeset log_option
	typeset rg_name=$(${RAC_SETUP} -G)

	# Get resource group name and state
	rg_name=${rg_name:-"rac-framework-rg"}
	rg_state=$(${SCHA_RG_GET} -G ${rg_name} -O RG_STATE)

	if [[ $? -ne 0 ]];then
		printf "$(gettext 'The RAC framework resource group does not exist.')\n"
		sc_prompt_pause
		return 1
	fi

	nodelist=$(scsetup_get_nodelist)
	racnodes=$(${SCHA_RG_GET} -G ${rg_name} -O NODELIST)

	for node in ${nodelist}
	do
		for racnode in ${racnodes}
		do
			if [[ ${racnode} == ${node} ]];then
				continue 2
			fi
		done
		nonracnodes="${nonracnodes} ${node}"
	done

	if [[ -z "${nonracnodes}" ]];then
		sc_print_para "$(printf "$(gettext 'All cluster nodes are already in \"%s\" resource group.')" "${rg_name}")"
		sc_prompt_pause
		return 1
	fi

	prompt="$(gettext 'Select the nodes to add to the RAC framework resource group')"

	addnodes="$(
				sc_get_scrolling_menuoptions	\
					"${prompt}"		\
					"" ""			\
					0 0 0			\
					${nonracnodes}	\
			)"

	if [[ -z "${addnodes}" ]];then
		printf "    $(gettext 'The list of nodes for \"%s\" resource group is not modified.')\n\n" "${rg_name}"
		sc_prompt_pause
		return 1
	fi

	set_nodelist="${racnodes} ${addnodes}"

	sc_print_para "$(printf "$(gettext 'Here is the new list of nodes for \"%s\" resource group:')" "${rg_name}")"
	for node in ${set_nodelist}
	do
		printf "\t${node}\n"
	done
	printf "\n"

	prompt="$(gettext 'Are you ready to update the list of nodes now?')"
	answer=$(sc_prompt_yesno "${prompt}" "${YES}") || continue

	if [[ ${answer} == "no" ]];then
		return 1
	fi

	if [[ -n ${SCSETUP_CMD_LOG} ]];then
		log_option="-f ${SCSETUP_CMD_LOG}"
	fi

	set_nodelist=$(echo ${set_nodelist}|sed -e "s/ /,/g")
	${RAC_SETUP} -c -v -g ${rg_name} -N ${set_nodelist} ${log_option}

	if [[ $? -ne 0 ]];then
		printf "$(gettext 'Command failed.')\n\n\a"
		sc_prompt_pause
		return 1
	fi

	sc_print_para "$(gettext 'Command completed successfully.')"
	sc_prompt_pause
	return 0
}

#####################################################
#
# scsetup_menu_dataservices_oraclerac_removenodes()
#
#	This fuction removes nodes from the Oracle RAC resource group.
#	This function calls the "rac_setup" script to modify
#	the Nodelist property of the RAC resource group. Additionally
#	the program also sets the maximum_primaries and desired_primaries
#	properties to the number of nodes selected.
#
#	Return:
#		zero		Completed
#		non-zero	Not successful
#
#####################################################
scsetup_menu_dataservices_oraclerac_removenodes()
{
	typeset remnodes=
	typeset racnodes
	typeset racnode
	typeset set_nodelist
	typeset node
	typeset prompt
	integer maxremove
	typeset rg_state
	typeset log_option
	typeset rg_name=$(${RAC_SETUP} -G)
	typeset sctxt_p1="$(gettext '
		Before you attempt to remove a node from the RAC framework
		resource group, ensure that Sun Cluster support for Oracle
		RAC is not running on the node. Removing a node from the RAC
		framework resource group does not stop Sun Cluster support
		for Oracle RAC on the node.
		')"

	# Get resource group name and state
	rg_name=${rg_name:-"rac-framework-rg"}
	rg_state=$(${SCHA_RG_GET} -G ${rg_name} -O RG_STATE)

	if [[ $? -ne 0 ]];then
		printf "$(gettext 'The RAC framework resource group does not exist.')\n"
		sc_prompt_pause
		return 1
	fi

	racnodes=$(${SCHA_RG_GET} -G ${rg_name} -O NODELIST)

	maxremove=$(expr $(echo ${racnodes}|wc -w) - 1)

	if [[ ${maxremove} -eq 0 ]]; then
		sc_print_para "$(printf "$(gettext 'There is only one node in \"%s\" resource group.')" "${rg_name}")"
		sc_prompt_pause
		return 1
	fi

	sc_print_para "${sctxt_p1}"

	prompt="$(gettext 'Select the nodes to remove from the RAC framework resource group')"

	remnodes="$(
				sc_get_scrolling_menuoptions	\
					"${prompt}"		\
					"" ""			\
					0 ${maxremove} 0	\
					${racnodes}	\
			)"

	if [[ -z "${remnodes}" ]];then
		printf "    $(gettext 'The list of nodes for \"%s\" resource group is not modified.')\n\n" "${rg_name}"
		sc_prompt_pause
		return 1
	fi

	set_nodelist=
	for racnode in ${racnodes}
	do
		for node in ${remnodes}
		do
			if [[ ${racnode} == ${node} ]];then
				continue 2
			fi
		done
		if [[ -z "${set_nodelist}" ]];then
			set_nodelist="${racnode}"
		else
			set_nodelist="${set_nodelist} ${racnode}"
		fi
	done

	sc_print_para "$(printf "$(gettext 'Here is the new list of nodes for \"%s\" resource group:')" "${rg_name}")"
	for node in ${set_nodelist}
	do
		printf "\t${node}\n"
	done
	printf "\n"

	prompt="$(gettext 'Are you ready to update the list of nodes now?')"
	answer=$(sc_prompt_yesno "${prompt}" "${YES}") || continue

	if [[ ${answer} == "no" ]];then
		return 1
	fi

	if [[ -n ${SCSETUP_CMD_LOG} ]];then
		log_option="-f ${SCSETUP_CMD_LOG}"
	fi

	set_nodelist=$(echo ${set_nodelist}|sed -e "s/ /,/g")
	${RAC_SETUP} -c -v -g ${rg_name} -N ${set_nodelist} ${log_option}

	if [[ $? -ne 0 ]];then
		printf "$(gettext 'Command failed.')\n\n\a"
		sc_prompt_pause
		return 1
	fi

	sc_print_para "$(gettext 'Command completed successfully.')"
	sc_prompt_pause
	return 0
}
#####################################################
#
# scsetup_menu_dataservices_oraclerac_status()
#
#	This fuction prints the status of the Oracle RAC resource group.
#
#	Return:
#		zero		Completed
#		non-zero	Not successful
#
#####################################################
scsetup_menu_dataservices_oraclerac_status()
{
	typeset rg_state
	typeset rg_name=$(${RAC_SETUP} -G)
	typeset rs_name
	typeset rs_names
	typeset returnstatus
	typeset rg_text=$(gettext 'Resource Name|Group Name')

	# Get resource group name and state
	rg_name=${rg_name:-"rac-framework-rg"}
	rg_state=$(${SCHA_RG_GET} -G ${rg_name} -O RG_STATE)

	if [[ $? -ne 0 ]];then
		printf "$(gettext 'The RAC framework resource group does not exist.')\n"
		sc_prompt_pause
		return 1
	fi

	rs_names=
	for rs_name in $(/usr/cluster/bin/scha_resourcegroup_get -G ${rg_name} -O RESOURCE_LIST)
	do
		rs_names="${rs_names}| ${rs_name} "
	done

	if [[ ${SCSETUP_ISMEMBER} -eq 1 ]]; then
		${SC_SCSTAT}  -g|egrep " ${rg_name} ${rs_names}|------|${rg_text}"|more
		returnstatus=$?
	else
		echo "DEBUG:  Not a cluster member - no status."
		sc_prompt_pause
	fi

	sc_prompt_pause
	return ${returnstatus}
}

	# Run it
	main $*
	exitstatus=$?

	# If scsetup is just being used as a "library", we are done
	if [[ -n "${SCSETUP_LIBRARY}" ]]; then
		return 0
	fi

	# Done. Generate end event.
	generate_event "cmd_end" ${exitstatus}
	exit ${exitstatus}

