#! /bin/ksh
#
# ident "@(#)scinstall_jumpstart.ksh	1.13	03/04/16 SMI"
#
# Copyright 1999-2003 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#

#####################################################
#
# copycdimage() src dst
#
#	src	- source of copy
#	dst	- destination of copy
#
#	Copy src to dst of an entire directory
#	hierarchy.   The destination directory
#	must not already exist.
#
#	Return:
#		zero		Success
#		non-zero	Failure
#
#####################################################
copycdimage()
{
	typeset -r src=$1
	typeset -r dst=$2

	# Check args
	if [[ $# -ne 2 ]]; then
		printf "$(gettext '%s:  Internal error - bad call to copycdimage()')\n" ${PROG} >&2
		return 1
	fi

	# Make sure that the src directory exists
	if [[ ! -d "${src}" ]]; then
		printf "$(gettext '%s:  Cannot find \"%s\"')\n" "${PROG}" "${src}" | logerr       
		return 1
	fi

	# Make sure that the dst directory does NOT exist
	if [[ -f "${dst}" ]] || [[ -d "${dst}" ]]; then
		printf "$(gettext '%s:  \"%s\" already exists')\n" "${PROG}" "${dst}" | logerr       
		return 1
	fi

	# Perform the copy
 	printf "$(gettext 'Copying \"%s\"')\n" "${src}" | logmsg
	mkdir -m 755 -p ${dst}
	if [[ $? -ne 0 ]]; then
		printf "$(gettext '%s:  Failed to create %s')\n" "${PROG}" "${dst}" | logerr
		return 1
	fi
	rm -f ${tmperr}
	(
		cd ${src} 2>>${tmperr} || return 1
		find . -depth -print | cpio -pdmu ${dst} 2>${tmperr} >/dev/null || return 1
		return 0
	)
	if [[ $? -ne 0 ]]; then
		[[ -s ${tmperr} ]] && cat ${tmperr} | logerr
		rm -r ${tmperr}
		printf "$(gettext '%s:  Failed to copy \"%s\"')\n" "${PROG}" "${src}" | logerr
		return 1
	fi  
 	printf "$(gettext 'Completed copy of \"%s\"')\n" "${src}" | logmsg

	return 0
}

#####################################################
#
# autoclient_jumpdir() jumpstart_dir autoscreleasedir
#
#	jumpstart_dir			location of JumpStart directory
#	autoscreleasedir		release directory
#
#	Check for errors, and setup our JumpStart
#	infrastructure, as needed.
#
#	Return:
#		zero		Success
#		non-zero	Failure
#
#####################################################
autoclient_jumpdir()
{
	typeset -r jumpstart_dir=$1
	typeset -r autoscreleasedir=$2

	typeset finish

	if [[ $# -ne 2 ]]; then
		printf "$(gettext '%s:  Internal error - bad call to autoclient_jumpdir()')\n" ${PROG} >&2
		return 1
	fi

	# Jumpstart directory must begin with /
	if [[ "${jumpstart_dir}" != /* ]]; then
		printf "$(gettext '%s:  The JumpStart directory name must begin with slash (/)')\n" "${PROG}" | logerr
		return 1
	fi

	# Make sure it is a directory
	if [[ ! -d "${jumpstart_dir}" ]]; then
		printf "$(gettext '%s:  Cannot find JumpStart directory \"%s\"')\n" "${PROG}" "${jumpstart_dir}" | logerr
		return 1
	fi

	# set lockfile
	lockfile=${jumpstart_dir}/.${PROG}.lock
	setlock ${lockfile} || return 1


	# Make sure there is a check program
	if [[ ! -x ${jumpstart_dir}/${SC_CHECK} ]]; then
		printf "$(gettext '%s:  \"%s\" is not a JumpStart directory')\n" "${PROG}" "${jumpstart_dir}" | logerr
		printf "$(gettext '%s:  There is no executable \"%s\" utility')\n" "${PROG}" "${SC_CHECK}" | logerr
		return 1
	fi

	# Create a rules file, if it does not exist
	if [[ ! -f ${jumpstart_dir}/${SC_RULES} ]]; then
		echo >${jumpstart_dir}/${SC_RULES} || return 1
		chmod 0644 ${jumpstart_dir}/${SC_RULES} || return 1
		printf "$(gettext 'Created an empty \"%s\" file')\n" "${SC_RULES}" | logmsg
	fi

	#
	# Make sure that our release directory exists for
	# release specific autohainstall.class and autohainstall.finish.
	#
	if [[ ! -d "${jumpstart_dir}/${autoscreleasedir}" ]]; then
		mkdir -m 755 -p ${jumpstart_dir}/${autoscreleasedir}
		if [[ $? -ne 0 ]]; then
			printf "$(gettext '%s:  Failed to create %s')\n" "${PROG}" "${jumpstart_dir}/${autoscreleasedir}" | logerr
			return 1
		fi
		printf "$(gettext 'Created \"%s\"')\n" "${autoscreleasedir}" | logmsg
	fi

	#
	# Copy in the class file, if it is not already there.
	# Issue warning on mis-match.
	#
	if [[ ! -f ${SC_SCLIBDIR}/${SC_AUTOSCCLASS} ]]; then
		printf "$(gettext '%s:  \"%s\" file not found in \"%s\"')\n" "${PROG}" "${SC_AUTOSCCLASS}" "${SC_SCLIBDIR}" | logerr
		return 1
	fi
	if [[ -f ${jumpstart_dir}/${autoscreleasedir}/${SC_AUTOSCCLASS} ]]; then
		diff ${SC_SCLIBDIR}/${SC_AUTOSCCLASS} ${jumpstart_dir}/${autoscreleasedir}/${SC_AUTOSCCLASS} >/dev/null 2>&1
		if [[ $? -ne 0 ]]; then
			printf "$(gettext 'NOTE:  The class file in \"%s\" no longer matches the original')\n" "${autoscreleasedir}" | logmsg
		fi
	else
		cp -p ${SC_SCLIBDIR}/${SC_AUTOSCCLASS} ${jumpstart_dir}/${autoscreleasedir}
		if [[ $? -ne 0 ]]; then
			printf "$(gettext '%s:  Failed to copy the autoinstall class file')\n" "${PROG}" | logerr
			return 1
		fi
		printf "$(gettext 'Copied  \"%s\" to %s')\n" "${SC_AUTOSCCLASS}" "${autoscreleasedir}" | logmsg
	fi

	#
	# Copy in the finish files, if it they not already there.
	#
	for finish in ${SC_AUTOSCFINISH} ${SC_AUTOSCFINISH_KSH}
	do
		if [[ ! -f ${SC_SCLIBDIR}/${finish} ]]; then
			printf "$(gettext '%s:  \"%s\" file not found in \"%s\"')\n" "${PROG}" "${finish}" "${SC_SCLIBDIR}" | logerr
			return 1
		fi
		if [[ -f ${jumpstart_dir}/${autoscreleasedir}/${finish} ]]; then
			diff ${SC_SCLIBDIR}/${finish} ${jumpstart_dir}/${autoscreleasedir}/${finish} >/dev/null 2>&1
			if [[ $? -ne 0 ]]; then
				printf "$(gettext 'NOTE:  The finish script in \"%s\" no longer matches the original')\n" "${autoscreleasedir}" | logmsg
			fi
		else
			cp -p ${SC_SCLIBDIR}/${finish} ${jumpstart_dir}/${autoscreleasedir}
			if [[ $? -ne 0 ]]; then
				printf "$(gettext '%s:  Failed to copy the autoinstall finish script')\n" "${PROG}" | logerr
				return 1
			fi
			printf "$(gettext 'Copied  \"%s\" to %s')\n" "${finish}" "${autoscreleasedir}" | logmsg
		fi
	done

	return 0
}

#####################################################
#
# autoclient_create_installdata() jumpstart_dir installnode [clustername]
#
#	jumpstart_dir			location of JumpStart directory
#	installnode			name of node being installed
#	clustername			name of the cluster
#
#	Create the following, if it does not already exist:
#
#	${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}
#	${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/${installnode}
#	${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/${installnode}/${SC_AUTOSCDATA}
#	${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/../clusters
#
#	If possible, also create the following:
#
#	${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/../clusters/${clustername}
#	${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/../clusters/${clustername}
#	  and, a symlink to the nodename for the cluster node
#
#	Return:
#		zero		Success
#		non-zero	Failure
#
#####################################################
autoclient_create_installdata()
{
	typeset -r jumpstart_dir=$1
	typeset -r installnode=$2
	typeset -r clustername=$3

	typeset ip_script=${SC_SCLIBDIR}/${SC_IP_PERL}
	typeset dir
	typeset dirs
	typeset foo

	# Check args
	if [[ $# -ne 2 ]] && [[ $# -ne 3 ]]; then
		printf "$(gettext '%s:  Internal error - bad call to autoclient_create_installdata()')\n" ${PROG} >&2
		return 1
	fi

	# Create the nodes directory, installnode directory, and clusters dir
	dirs="\
		${jumpstart_dir}/${SC_AUTOSCCONFIGDIR} \
		${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/${installnode} \
		${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/../clusters \
	"
	if [[ -n "${clustername}" ]]; then
		dirs="${dirs} ${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/../clusters/${clustername}"
	fi
	for dir in ${dirs}
	do
		if [[ ! -d ${dir} ]]; then
			mkdir -m 755 -p ${dir}
			if [[ $? -ne 0 ]]; then
				printf "$(gettext '%s:  Failed to create %s')\n" "${PROG}" "${dir}" | logerr
				return 1
			fi
			printf "$(gettext 'Created \"%s\"')\n" "${dir}" | logmsg
		fi
	done

	# Remove any old nodenames in the clusters directory
	rm -f ${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/../clusters/*/${installnode}

	# If clustername is given, attempt to create the link
	if [[ -n "${clustername}" ]]; then
		ln -s ../../nodes/${installnode} ${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/../clusters/${clustername}/${installnode} 2>/dev/null
		printf "$(gettext 'Created \"%s\"')\n" "${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/../clusters/${clustername}/${installnode}" | logmsg
	fi

	# Remove the old data file
	rm -f ${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/${installnode}/${SC_AUTOSCDATA}

	# Split SC_ARGVAR_PATCHDIR into SC_AUTOINSTALL_PATCHHOST and
	# SC_AUTOINSTALL_PATCHDIR

	if [[ -n "${SC_ARGVAR_PATCHDIR}" ]]; then
		cd ${SC_ARGVAR_PATCHDIR} 2>/dev/null
		if [[ $? -ne 0 ]]; then
			printf "$(gettext '%s: Failed to access %s')\n" "${PROG}" "${SC_ARGVAR_PATCHDIR}" | logerr
			return 1
		fi
		
		# Set the SC_AUTOINSTALL_PATCHHOST and SC_AUTOINSTALL_PATCHDIR
		set -A foo $(autoclient_fs ${SC_ARGVAR_PATCHDIR} ${mynodename})
		if [[ -z "${foo[0]}" ]] || [[ -z "${foo[1]}" ]]; then
			printf "$(gettext '%s: Failed to parse %s')\n" "${PROG}" "${SC_ARGVAR_PATCHDIR}" | logerr
			return 1
		fi

		mkdir -m 0755 ${tmp_mntpnt}
		if [[ $? -ne 0 ]]; then
			printf "$(gettext 'Internal error, cannot create directory \"%s\"')\n" ${tmp_mntpnt} | logerr
			return 1
		fi

		mount -F nfs -o ro ${foo[0]}:${foo[1]} ${tmp_mntpnt} >/dev/null 2>&1
		if [[ $? -ne 0 ]]; then
			printf "$(gettext 'Cannot NFS mount \"%s:%s\", please provide a directory that can be NFS mounted.')\n" ${foo[0]} ${foo[1]} | logerr
			rm -rf ${tmp_mntpnt}
			return 1
		fi
		umount ${tmp_mntpnt}
		rm -rf ${tmp_mntpnt}
			
		if [[ -x /usr/bin/perl ]]; then
			SC_AUTOINSTALL_PATCHHOST=$(${ip_script} convert_to_ip ${foo[0]})
		else
			SC_AUTOINSTALL_PATCHHOST=${foo[0]}
		fi
		SC_AUTOINSTALL_PATCHDIR=${foo[1]}
		SC_ARGVAR_PATCHDIR=
		set -A foo
	fi

	# Create the new data file
	argvar_append_all_tofile "${SC_IDX}" ${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/${installnode}/${SC_AUTOSCDATA} || return 1
	printf "$(gettext 'Created \"%s\"')\n" "${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/${installnode}/${SC_AUTOSCDATA}" | logmsg

	# Add the mount and other SC_AUTOINSTALL_ variables to it
	echo "SC_AUTOINSTALL_HOST=\"$(echo ${SC_AUTOINSTALL_HOST})\"" >>${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/${installnode}/${SC_AUTOSCDATA} || return 1
	echo "SC_AUTOINSTALL_DIR=\"$(echo ${SC_AUTOINSTALL_DIR})\"" >>${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/${installnode}/${SC_AUTOSCDATA} || return 1
	echo "SC_AUTOINSTALL_TOOLSDIR=\"$(echo ${SC_AUTOINSTALL_TOOLSDIR})\"" >>${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/${installnode}/${SC_AUTOSCDATA} || return 1
	echo "SC_AUTOINSTALL_PATCHHOST=\"$(echo ${SC_AUTOINSTALL_PATCHHOST})\"" >>${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/${installnode}/${SC_AUTOSCDATA} || return 1
	echo "SC_AUTOINSTALL_PATCHDIR=\"$(echo ${SC_AUTOINSTALL_PATCHDIR})\"" >>${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/${installnode}/${SC_AUTOSCDATA} || return 1
	echo "SC_AUTOINSTALL_PATCHES=\"patches\"" >>${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/${installnode}/${SC_AUTOSCDATA} || return 1
	echo "SC_AUTOINSTALL_ARCHIVE=\"archive\"" >>${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/${installnode}/${SC_AUTOSCDATA} || return 1
	echo "SC_AUTOINSTALL_FINISH=\"finish\"" >>${jumpstart_dir}/${SC_AUTOSCCONFIGDIR}/${installnode}/${SC_AUTOSCDATA} || return 1

	return 0
}

#####################################################
#
# autoclient_update_rules() jumpstart_dir autoscreleasedir installnode
#
#	jumpstart_dir			location of JumpStart directory
#	autoscreleasedir		release direcotry
#	installnode			name of node being installed
#
#	Update the rules file in the given "jumpstart_dir"
#	for the given "installnode".
#
#	Return:
#		zero		Success
#		non-zero	Failure
#
#####################################################
autoclient_update_rules()
{
	typeset -r jumpstart_dir=$1
	typeset -r autoscreleasedir=$2
	typeset -r installnode=$3

	# Check args
	if [[ $# -ne 3 ]]; then
		printf "$(gettext '%s:  Internal error - bad call to autoclient_update_rules()')\n" ${PROG} >&2
		return 1
	fi

	# Remove any old entries from the rules file
	grep '^hostname[ 	][ 	]*'${installnode}'[ 	]' ${jumpstart_dir}/${SC_RULES} >/dev/null 2>&1
	if [[ $? -eq 0 ]]; then
		printf "$(gettext 'Removing host \"%s\" from \"%s\" file') ...\n" "${installnode}" "${SC_RULES}"
		ex ${jumpstart_dir}/${SC_RULES} >/dev/null 2>&1 <<END
1,\$g/^hostname[ 	][ 	]*${installnode}[ 	].*/d
wq
END
	fi

	# Add the new entry to the rules file
	printf "$(gettext 'Updating \"%s\" file for host \"%s\"') ...\n" "${SC_RULES}" "${installnode}"

	# our ex script will not work if file is all comments, so ...
	grep -v '^#' ${jumpstart_dir}/${SC_RULES} >/dev/null 2>&1
	if [[ $? -ne 0 ]]; then
		echo >>${jumpstart_dir}/${SC_RULES}
	fi

	# insert before first non-blank or non-comment line
	ex ${jumpstart_dir}/${SC_RULES} >/dev/null 2>&1 <<END
set wrapscan
set magic
$
/^[^#]*\$/
i
hostname ${installnode}  -  ${autoscreleasedir}/${SC_AUTOSCCLASS}  ${autoscreleasedir}/${SC_AUTOSCFINISH}
.
wq
END
	if [[ $? -ne 0 ]]; then
		printf "$(gettext '%s:  Failed to update the \"%s\" file correctly')\n" "${PROG}" "${SC_RULES}" | logerr
		return 1
	fi

	# Run the "check" program to create "rules.ok"
	printf "\n"
	printf "$(gettext 'Running the \"%s\" utility')...\n" "${SC_CHECK}" | logmsg

	# Subshell
	(
		typeset retval

		cd ${jumpstart_dir}
		echo "--------------------------------"
		./check
		retval=$?
		echo "--------------------------------"
		return ${retval}
	)

	if [[ $? -ne 0 ]]; then
		printf "\n"
		printf "$(gettext '%s:  \"%s\" failed')\n" "${PROG}" "${SC_CHECK}" | logerr
		printf "$(gettext '%s:  Correct the problem and re-run \"%s\"')\n" "${PROG}" "${SC_CHECK}" | logerr
		return 1
	fi

	# Done
	printf "\n"

	return 0
}

#####################################################
#
# autoclient_argvars()
#
#	The following variables are all inherited from the
#	caller:
#
#	cdimagebasedir			base direcotory for cdimage
#	jumpstart_dir			location of JumpStart directory
#	installnode			node to install (given w/ -h)
#	services			space seperated list of services
#	sponsornode			sponsor node (given w/ -N)
#	global				global devices directory
#	clustername			cluster name
#	auth_options			"-T <authentication_options>"
#	adapter_options			"-A <adapter_options> ..."
#	bb_options			"-B <blackbox_options> ..."
#	cable_options			"-m <cable_options> ..."
#	netaddr_options			"-w <network_options" 
#	patch_options			"-M <patch_options>" 
#	oflg				true or false (-o)
#
#	Set the SC_ARGVAR_ variables based on the variables listed
#	above as inherited from the caller.
#
#	Return:
#		zero		Success
#		non-zero	Failure
#
#####################################################
autoclient_argvars()
{
	typeset foo
	typeset adapter
	typeset endpoints
	typeset cables
	typeset e1ports
	typeset e2ports

	integer i
	integer j
	integer me
	integer him
	integer found

	# Clear the new argvars
	argvar_clear_all_argvars

	# Set SC_ARGVAR_NODENAME
	SC_ARGVAR_NODENAME[SC_IDX]=${installnode}

	# Set SC_ARGVAR_JUMPSTARTDIR
	SC_ARGVAR_JUMPSTARTDIR=${jumpstart_dir}

	# Set SC_ARGVAR_CLUSTERNAME
	SC_ARGVAR_CLUSTERNAME=${clustername}

	# Set SC_ARGVAR_ONENODE
	SC_ARGVAR_ONENODE=${oflg}

	# Set SC_ARGVAR_AUTHLIST and SC_ARGVAR_AUTHTYPE
	if [[ "${sponsornode}" = "${installnode}" ]]; then
		SC_ARGVAR_AUTHLIST="$(print_subopt_values "${auth_options}" "node")"
		SC_ARGVAR_AUTHTYPE="$(print_subopt_values "${auth_options}" "authtype")"
	fi

	# Set SC_ARGVAR_NETADDR and SC_ARGVAR_NETMASK
	if [[ "${sponsornode}" = "${installnode}" ]]; then
		SC_ARGVAR_NETADDR="$(print_subopt_values "${netaddr_options}" "netaddr")"
		SC_ARGVAR_NETMASK="$(print_subopt_values "${netaddr_options}" "netmask")"
	fi

	# Set SC_ARGVAR_SPONSORNODE
	SC_ARGVAR_SPONSORNODE[SC_IDX]=${sponsornode}

	# Set SC_ARGVAR_JUNCTIONS and SC_ARGVAR_JUNCTYPES
	SC_ARGVAR_JUNCTIONS[SC_IDX]="$(print_subopt_values "${bb_options}" "name")"
	SC_ARGVAR_JUNCTYPES[SC_IDX]="$(print_subopt_values "${bb_options}" "type")"

	# Set SC_ARGVAR_DIRECT
	if [[ -n "${SC_ARGVAR_JUNCTIONS}" ]]; then
		SC_ARGVAR_DIRECT=0
	elif [[ "${sponsornode}" = "${installnode}" ]]; then
		SC_ARGVAR_DIRECT=1
	else
		SC_ARGVAR_DIRECT=
	fi

	# Set SC_ARGVAR_ADAPTERS and SC_ARGVAR_TRTYPES
	SC_ARGVAR_ADAPTERS[SC_IDX]="$(print_subopt_values "${adapter_options}" "name")"
	SC_ARGVAR_TRTYPES[SC_IDX]="$(print_subopt_values "${adapter_options}" "trtype")"

	# Set SC_ARGVAR_E2CABLES, SC_ARGVAR_E1PORTS, and SC_ARGVAR_E2PORTS
	let i=0
	set -A cables
	set -A e1ports
	set -A e2ports
	set -A endpoints $(print_subopt_values "${cable_options}" "endpoint")
	while true
	do
		# Are we done?
		if [[ -z "${endpoints[i]}" ]]; then
			break
		fi

		# Make sure we have an even number
		if [[ -z "${endpoints[i+1]}" ]]; then
			printf "$(gettext '%s:  There must be two endpoints per cable')\n" ${PROG} >&2
			printf "$(gettext '%s:  Internal error - bad cable_options passed to autoclient()')\n" ${PROG} >&2
			return 1
		fi

		# Decide which of the two endpoints in this set connects to me
		let j=0
		let me=-1
		while [[ ${j} -lt 2 ]]; do
			set -A foo
			if [[ ${endpoints[i+j]} = :* ]]; then
				foo=${installnode}
			elif [[ ${endpoints[i+j]} = *:* ]]; then
				set -A foo $(IFS=: ; echo ${endpoints[i+j]})
			fi
			if [[ "${foo}" = "${installnode}" ]]; then
				if [[ ${me} -ne -1 ]]; then
					printf "$(gettext '%s:  Only one end of a cable can attach to this node')\n" ${PROG} >&2
					printf "$(gettext '%s:  Internal error - bad cable_options passed to autoclient()')\n" ${PROG} >&2
					return 1
				fi
				let me=${j}
			fi
			((j += 1))
		done
		if [[ ${me} -eq -1 ]]; then
			printf "$(gettext '%s:  At least one end of each cable must attach to this node')\n" ${PROG} >&2
			printf "$(gettext '%s:  Internal error - bad cable_options passed to autoclient()')\n" ${PROG} >&2
			return 1
		fi

		# Set him, the compliment to me
		let him=$((me ^ 1))

		# Which adapter am I?
		foo=$(expr "${endpoints[i+me]}" : '.*:\([^@]*\).*')
		let j=0
		let found=0
		for adapter in ${SC_ARGVAR_ADAPTERS[SC_IDX]}
		do
			if [[ "${foo}" = "${adapter}" ]]; then
				let found=1
				break
			fi
			((j += 1))
		done
		if [[ ${found} -eq 0 ]]; then
			printf "$(gettext '%s:  Cable endpoint must match one of the adapters')\n" ${PROG} >&2
			printf "$(gettext '%s:  Internal error - bad cable_options passed to autoclient()')\n" ${PROG} >&2
			return 1
		fi

		# Set cables and ports
		set -A foo $(IFS=@ ; echo ${endpoints[i+me]})
		e1ports[j]=${foo[1]}
		set -A foo $(IFS=@ ; echo ${endpoints[i+him]})
		cables[j]=${foo[0]}
		e2ports[j]=${foo[1]}

		# Next set of two
		((i += 2))
	done

	# cables and ports line up with adapters
	let i=0
	for adapter in ${SC_ARGVAR_ADAPTERS[SC_IDX]}
	do
		if [[ -z "${cables[i]}" ]]; then
			cables[i]="@"
		fi
		if [[ -z "${e1ports[i]}" ]]; then
			e1ports[i]="@"
		fi
		if [[ -z "${e2ports[i]}" ]]; then
			e2ports[i]="@"
		fi
		((i += 1))
	done
	SC_ARGVAR_E2CABLES="${cables[*]}"
	SC_ARGVAR_E1PORTS="${e1ports[*]}"
	SC_ARGVAR_E2PORTS="${e2ports[*]}"

	# Set SC_ARGVAR_GDIR
	SC_ARGVAR_GDIR[SC_IDX]=${global}

	# Set SC_ARGVAR_PATCHDIR and SC_ARGVAR_RESPONSE_PATCHDIR
	SC_ARGVAR_PATCHDIR="$(print_subopt_values "${patch_options}" "patchdir")"
	SC_ARGVAR_RESPONSE_PATCHDIR="${SC_ARGVAR_PATCHDIR}"

	# Set SC_ARGVAR_PATCHFILE
	SC_ARGVAR_PATCHFILE="$(print_subopt_values "${patch_options}" "patchlistfile")"

	# Set SC_ARGVAR_SERVICES
	SC_ARGVAR_SERVICES[SC_IDX]="${services}"

	return 0
}

#####################################################
#
# autoclient()
#
#	The following variables are all inherited from the
#	caller:
#
#	mynodename			the name of this machine
#	cdimagebasedir			base direcotory for cdimage
#	jumpstart_dir			location of JumpStart directory
#	installnode			node to install (given w/ -h)
#	services			space seperated list of services
#	sponsornode			sponsor node (given w/ -N)
#	global				global devices directory
#	clustername			cluster name
#	auth_options			"-T <authentication_options>"
#	adapter_options			"-A <adapter_options> ..."
#	bb_options			"-B <blackbox_options> ..."
#	cable_options			"-m <cable_options> ..."
#	netaddr_options			"-w <network_options" 
#	oflg				true of false (-o)
#
#	Add jumpstart client "installnode" to the "jumstart_dir".
#
#	Return:
#		zero		Success
#		non-zero	Failure
#
#####################################################
autoclient()
{
	#
	# This SC_ARGVAR_ list must be identical to the list used
	# by interactive install.   We must re-declare the
	# list here in order to limit the scope.
	#
	typeset SC_ARGVAR_NODENAME
	typeset SC_ARGVAR_JUMPSTARTDIR
	typeset SC_ARGVAR_CLUSTERNAME
	typeset SC_ARGVAR_ONENODE
	typeset SC_ARGVAR_AUTHLIST
	typeset SC_ARGVAR_AUTHTYPE
	typeset SC_ARGVAR_NETADDR
	typeset SC_ARGVAR_NETMASK
	typeset SC_ARGVAR_TWONODES
	typeset SC_ARGVAR_DIRECT
	typeset SC_ARGVAR_SPONSORNODE
	typeset SC_ARGVAR_JUNCTIONS
	typeset SC_ARGVAR_JUNCTYPES
	typeset SC_ARGVAR_ADAPTERS
	typeset SC_ARGVAR_TRTYPES
	typeset SC_ARGVAR_E2CABLES
	typeset SC_ARGVAR_E1PORTS
	typeset SC_ARGVAR_E2PORTS
	typeset SC_ARGVAR_GDIR
	typeset SC_ARGVAR_PATCHDIR
	typeset SC_ARGVAR_RESPONSE_PATCHDIR
	typeset SC_ARGVAR_PATCHFILE
	typeset SC_ARGVAR_SERVICES

	typeset SC_IDX=0
	typeset SC_INDICES=${SC_IDX}
	typeset SC_OTHERNODE=

	typeset SC_AUTOINSTALL_HOST=
	typeset SC_AUTOINSTALL_DIR=

	typeset autoscreleasedir=
	typeset detailed_release=

	typeset foo
	typeset realcdimage
	typeset productdir
	typeset toolsdir

	# Check args and variables inherited from caller
	if [[ $# -ne 0 ]] ||
	    [[ -z "${cdimagebasedir}" ]] ||
	    [[ -z "${jumpstart_dir}" ]] ||
	    [[ -z "${installnode}" ]]; then
		printf "$(gettext '%s:  Internal error - bad call to autoclient()')\n" ${PROG} >&2
		return 1
	fi

	# Set the SC_ARGVAR_ variables from the options variables
	autoclient_argvars || return 1

	# Set the SC_AUTOINSTALL_HOST and SC_AUTOINSTALL_DIR
	set -A foo $(autoclient_fs ${cdimagebasedir} ${mynodename})
	if [[ -z "${foo[0]}" ]] || [[ -z "${foo[1]}" ]]; then
		return 1
	fi
	SC_AUTOINSTALL_HOST=${foo[0]}
	SC_AUTOINSTALL_DIR=${foo[1]}
	set -A foo

	#
	# Temporarily set SC_OE_VERSION to persuade getproduct() to
	# use the OE version from the scinstall path, even if it is
	# not actually the correct OE version for the cluster itself.
	# The autoinstall script actually ensures that the correct
	# version is used (by calling scinstall w/ the -d option).
	#
	SC_OE_VERSION=${SC_OE_SCINSTALLDIR}

	# Set the name of the release directory
	realcdimage=$(find_cdimagebasedir "${cdimagebasedir}" "${SC_PRODUCT}" "${SC_CLUSTER}") || return 1

	# Get the Product directory
	productdir=$(getproduct ${realcdimage}/${SC_CDTOC} "${SC_PRODUCT}" ${SC_CLUSTER} "dir") || return 1

	# Reset SC_OE_VERSION
	SC_OE_VERSION=

	# The Tools directory is at the same level as Product
	toolsdir=$(dirname ${productdir})/Tools
	if [[ ! -d "${toolsdir}" ]]; then
		printf "$(gettext '%s:  Cannot find \"%s\"')\n" "${PROG}" "${toolsdir}"
		return 1
	fi

	# Set the name of the autosc release dir, use detailed release 
	# information
	detailed_release=$(print_release "" "${toolsdir}/dot.release" 2>/dev/null)
	autoscreleasedir=${SC_AUTOSCINSTALL_D}/${detailed_release}
 
	# Make Tools directory relative to cdimagebasedir
	SC_AUTOINSTALL_TOOLSDIR=$(echo ${toolsdir} | sed -n 's#'${cdimagebasedir}/'\(.*\)#\1#p')

	# Set up our JumpStart directory, as needed
	autoclient_jumpdir ${jumpstart_dir} ${autoscreleasedir} || return 1

	# Create the data file from our SC_ARGVAR_ and SC_AUTOINSTALL_ vars
	autoclient_create_installdata ${jumpstart_dir} ${installnode} ${clustername} || return 1

	# Update the rules file
	autoclient_update_rules ${jumpstart_dir} ${autoscreleasedir} ${installnode} || return 1

	return 0
}
