#! /usr/bin/sh
#
# ident	"@(#)ap.sh	1.24	00/12/05 SMI"
#
# Copyright (c) 1996 by Sun Microsystems, Inc.
# All rights reserved.
#


#
#	Miscellaneous shell functions...
#


#
#	dbcorruptmessage AP_device
#
# Simple auxilary routine to the shell function getmdevs_fromvfstab.  Prints
# out instructions for a manual AP database repair scenario before
# getmdevs_fromvfstab invokes a subshell...
#
dbcorruptmessage() {
	 echo ""
	 echo "WARNING - AP database corruption detected for"
	 echo "AP metadevice $1. Repair the database by utilizing"
	 echo "the /sbin/ap* commands, then exit the sub_shell"
	 echo "via <ctrl>D to initiate an automatic reboot."
	 echo ""
}

#
#	isitan_apdev fsckdev_from_vfstab
#
# Simple auxiliary routine to the shell function getmdevs_fromvfstab.
# Determines whether or not the submitted fsckdev is an AP device.  An AP
# device is defined as one that begins with the path prefix "/dev/ap".
# IFS is set to "/" before invoking this routine.
#
isitan_apdev() {
	if [ "${1}" = "dev" ]
	then
		if [ "${2}" = "ap" ]
		then
			return 1
		fi
	fi
	return 0
}

#
#	getmdevs_fromvfstab
#
# Scan entire vfstab in order to locate any AP metadevices.  All located
# metadevices will concatenated into the space separated string
# stringof_mdevs.

# This function assumes that stdin is already set to /etc/vfstab (or other
# appropriate input stream).
#
getmdevs_fromvfstab() {
	(
	while read special fsckdev mountp fstype fsckpass automnt mntopts
	do
		case ${special} in
		'#'* | '')	# Ignore comments, empty lines
				continue ;;
		'-')		# Ignore no-action lines
				continue
		esac
 
		(
		IFS="/"
		isitan_apdev $fsckdev
		)
		if [ "${?}" = "1" ]
		then
 			${APDB_CHK} ${fsckdev}
 			if [ "${?}" != "0" ]
			then
 				dbcorruptmessage "${fsckdev}"
 				/sbin/sh < /dev/console
 				echo "*** SYSTEM WILL REBOOT AUTOMATICALLY ***"
 				/sbin/uadmin 2 1
 			fi
		fi
	done
	)
}

#
# 	ap_ifnetup net_device file_or_nis
#
# First, just try plumbing the interface up.  HW could have been moved
# or removed.  Then, if YP/NIS is running, attempt to rarp out on the
# interface to determine whether the interface is useable.  This is not
# guaranteed to work - if rarp has not been set up correctly on another
# machine on the sub-net, we will not get a response & incorrectly assume
# the interface down.
#
# returns
#	0 = success
#	!0 = failure
#
ap_ifnetup() {
	/sbin/ifconfig $1 plumb			>/dev/null 2>&1
 	if [ $? -ne 0 ] ; then
		return 1			# probably missing HW
	fi

	# determine whether nis is running from file or net
	if [ $2 = files ] ; then
		t=0				# no NIS, can't check
	else
		/sbin/ifconfig $1 debug auto-revarp	>/dev/null 2>&1
		t=$?				# use ifconfig rtn status
	fi
	/sbin/ifconfig $1 unplumb		>/dev/null 2>&1

	return $t
}

#
#	ap_ifnet_find
#
# we can only dependably rarp the base network of a machine.  This is
# because the ethernet address for a given machine is in the prom image,
# and all ethernet interfaces share the same address. Therefore if
# we have a le0 & le1, and rarp out the le1, the reply will come
# back on le0.
#
ap_ifnet_find() {
	#
	# determine the name of the primary interface to the machine
	#
	hostname="`shcat /etc/nodename			2>/dev/null`"
	if [ -z "$hostname" ] ; then
		return 1
	fi

	#
	# are there any ap'd network interfaces?
	#
	interface_names="`echo /etc/hostname.m*[0-9]	2>/dev/null`"
	if [ "$interface_names" = "/etc/hostname.m*[0-9]" ] ; then
		return 2
	fi

	#
	# There are ap interfaces, find the first one that
	# corresponds to the nodename
	#
	(
	ap_prim_if=""
	set /etc/hostname\.m*[0-9]
	while [ $# -ge 1 ] ; do
		ifname="`shcat $1			2>/dev/null`"
		if [ "$ifname" = "$hostname" ] ; then
			if [ -z "$ap_prim_if" ] ; then
				ap_prim_if="$1"
				break
			fi
		fi
		shift
	done

	#
	# if none of ap interfaces correspond with the primary interface
	# then we are done
	#
	if [ -z "$ap_prim_if" ] ; then
		return 3
	fi

	echo "auto-configuring AP network interface: $ap_prim_if"

	#
	# determine whether YP/NIS is running
	#
	forn=XX
	set `shcat /etc/nsswitch.conf`
	while [ $# -ge 1 -a $forn = XX ] ; do
		if [ $1 = ethers: ] ; then
			forn=$2
		else
			shift
		fi
	done

	#
	# break up the primary interface name to components to
	# allow us to start playing with it
	#
	IFS="$IFS."
	set $ap_prim_if

	shift			#skip "/etc/hostname"
	case "$1" in
	#
	# no point in testing hippi, it does not support arp, we
	# will have to hope it works
	#
	mhi*)	return ;;
	*)
		#
		# See if the ap active path is working
		# If the current path fails, then try all alternate
		# paths until we a. find working or b. run out.
		#
		ap_ifnetup $1 $forn
		if [ $? -ne 0 ] ; then
			#
			# interface was not responding.  Either rarp was
			# not set up or the hw is down.  Walk thru the
			# alternate paths, until a working interface is
			# found, or till we run out of alternate paths.
			#
			${APNET} -t $1 >/dev/null 2>&1
			while [ $? -eq 0 ] ; do
				#
				# try an alternate path
				#
				ap_ifnetup $1 $forn
				if [ $? -eq 0 ] ; then
					#
					# it worked, make the temp active path
					# the actual alternate path
					#
					${APNET} -w $1
					break
				fi
				${APNET} -t $1 >/dev/null 2>&1
			done
		fi
		;;
	esac

	)
}


################################################################################
#
#	Actual executable statements begin here...
#
################################################################################
(
#
# Default definitions:
#
PATH=/sbin

APDB_CHK=/sbin/apcheck
APNET=/sbin/apnet
APCONFIG=/sbin/apconfig
VFSTAB=/etc/vfstab
exec < ${VFSTAB}; getmdevs_fromvfstab
#
PATH=/sbin:/bin
LD_LIBRARY_PATH=/etc/lib; export LD_LIBRARY_PATH
${APCONFIG} -F
ap_ifnet_find
)
