#!/bin/ksh -p
#
# ident "@(#)utfwadm.sh	1.66 03/04/04 SMI"
#
# Copyright 1998-2002 Sun Microsystems, Inc.  All rights reserved.
#

#
# TBD:
# * make sure incremental add and remove works for different interfaces as
#   well as different units.
# * make all exits clean up properly
# * replace "SUNW.NewT.SUNW" with "SUNW.${PROD_KEYWORD_UC}.SUNW"
#

CORONA_NAME=SunRay
CORONA_TITLE="Sun Ray"

export PATH=/usr/bin:/usr/ccs/bin:/usr/sbin
export LC_ALL=C

ME=$0
TMPDIR="/var/opt/SUNWut/tmp"

#
# Function Definitions
#

function Usage {
print "usage: $ME {-A|-D|-P|-R} {-a|-e enetAddr} [-f firmware] {-n intf | -N subnet} ..."
print "\t-A            # add the specified unit(s) to the upgrade list"
print "\t-D            # delete the specified unit(s) from the upgrade list"
print "\t-P            # print version information" 
print "\t-R            # remove firmware modules from boot directory"
print "\t-a            # apply to all units"
print "\t-e enetAddr   # apply to the unit given by the six hex bytes"
print "\t              #  of its ethernet address"
print "\t-n intf       # name of a decidated network interface to enable upgrades on"
print "\t              #  (e.g., hme0, vge1, etc. \"all\" = all interfaces)"
print "\t-N subnetwork # shared subnetwork address to enable upgrades on"
print "\t-f firmware   # use the firmware described by the path \"firmware\""
print "\t              #  for upgrades on the given network interface(s)"
exit 1;
}


#
# Get the UTC offset in minutes
#  usage: GetTimeOffset
# calculates the offset in minutes from UTC and puts it into UTC_OFFSET
#
function GetTimeOffset {
	LOCAL=$(date '+%H');
	GMT=$(date -u '+%H');
	if [ ${LOCAL} -gt ${GMT} ]
	then
		let TIME=24+${GMT}-${LOCAL};
	else
		let TIME=${GMT}-${LOCAL};
	fi
	print $(( ${TIME} * 3600 ));
}


function SetLocale {
	UTC_OFFSET=$(GetTimeOffset)
	dhtadm -M -m ${CORONA_NAME} -e 'UTCoffst=${UTC_OFFSET}'
}


function UnSetLocale {
	dhtadm -M -m ${CORONA_NAME} -e 'UTCoffst='
}

#
# Verify a dotted IP address
#  usage:  CheckIPA <ipaddr>
# returns a 0 if a good ipa is given, and a 1 otherwise
#
function CheckIPA {
  IP_ADDR=`expr ${1} : '^\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)$'`
  if [ ! "${IP_ADDR}" ]; then
    return 1
  fi
  NNO1=${1%%.*}
  tmp=${1#*.}
  NNO2=${tmp%%.*}
  tmp=${tmp#*.}
  NNO3=${tmp%%.*}
  tmp=${tmp#*.}
  NNO4=${tmp%%.*}
  if [ ${NNO1} -gt 255 -o ${NNO2} -gt 255 -o ${NNO3} -gt 255 -o ${NNO4} -gt 255 ]; then
    return 1
  fi
  return 0
}

#
# get information about a given network interface
#  usage: GetInterfaceInfo <intf name>
# If <intf name> not specified, use the primary interface
#
# get the following info into the following variables:
#  INTF_IPA:	the IPA of the interface
#  INTF_NAME:	the symbolic name for this interface
#  INTF_MASK:	the subnet mask for this interface
#  INTF_NET:	the address of this network
#  INTF_MTU:	the MTU for this interface
#  INTF_BC:	the broadcast address for this network
#  INTF_ROUTER:	the address of the router for this network
#
#  this is only to be called after the interface has been setup (i.e., after
# the "ifconfig plumb" has been done), and the /etc/hosts table has been setup.
#  returns a 0 if all values are set properly and a 1 otherwise
#

function GetInterfaceInfo {

	typeset intf
	if [[ $# -eq 0 ]]; then
            # Interface not specified.  Use the info from the primary interface for the MTU.
            intf=`grep -l "^${HOSTNAME}\$" /etc/hostname.* | \
                sed -e "s/^..*\.\([^\.][^\.]*\)$/\1/"`
            if [[ -z "$intf" ]]; then
		print -u2 "Error: unable to get information on primary interface"
		exit 1
            fi
	else
	    intf=$1
	fi

	# get the intf's mtu, network address, and IP address
	netstat -n -I $intf | grep "^${intf}" |
	    read -u0 Xcard INTF_MTU INTF_NET INTF_IPA Xstats

	# get the intf's symbolic name
	INTF_NAME=$(sed -n \
	    -e "s/^[ 	]*${INTF_IPA}[ 	]*\([^ 	]*\).*$/\1/p" "${HOSTS}")

	if [ -z "$INTF_NAME" -o -z "$INTF_MTU" -o -z "$INTF_NET" -o \
	    -z "$INTF_IPA" ]
	then
		return 1
	fi

	# get the intf's netmask and broadcast address
	INTF_INFO=$(ifconfig ${intf});
	if [ ${?} -ne 0 ] || [ -z "${INTF_INFO}" ]
	then
		return 1;
	fi
	typeset -i10 n1 n2 n3 n4
	print $INTF_INFO |
	    sed -n '/netmask/ {
			s/^.*netmask \([^ 	]*\).*/\1/
			s/\(..\)/16#\1 /g
			s/ $//p
		}' |
	    read -u0 n1 n2 n3 n4
	INTF_MASK=$(print $n1.$n2.$n3.$n4)

	INTF_BC=$(print $INTF_INFO | sed -n -e 's/.*broadcast \([^ ]*\).*/\1/p')

	# get the intf's router address
	netstat -n -r | grep "^${INTF_NET}" | read -u0 Xdest INTF_ROUTER Xother
	if [ -z "${INTF_ROUTER}" ]
	then
		return 1;
	fi

	return 0;
}

# get a list of existing interfaces with DHCP entries
function GetCurrentCfg {
    typeset DHTADM_P="${TMPDIR}/dhtadm-P.$$"
    rm -f $DHTADM_P 2> /dev/null
    dhtadm -P 2>/dev/null | sed -e "1,2d" > $DHTADM_P

    # get interfaces that currently configure to support SunRay
    sed -n "s/^${CORONA_NAME}-\([^0-9 	][^ 	]*\)[ 	].*$/\1/p" ${NETWORKS} \
	>${TMPDIR}/newtifs.$$

    # get subnetworks that are currently configured for SunRay
    # this does not include the networks for interfaces.
    sed -n -e \
	"s/^${CORONA_NAME}-\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)[ 	].*$/\1/p" \
	$DHTADM_P | sort -u >${TMPDIR}/allnets.$$
    rm -f $DHTADM_P
}

# get the DHCP daemon's pid
function GetDHCPpid {
  dhcppid=`pgrep in.dhcpd`
}


#
# HupDHCP - send a HUP signal to the dhcp daemon
#
HupDHCP () {

    pkill -HUP in.dhcpd
    case $? in
    0)	# signal sent succesfully
	print "### reinitialized DHCP daemon"
	;;
    1)	# dhcp is not currently running
	print "#### DHCP daemon not reinitialized because it is not currently running.\
	    \nYou may want to start one manually using \"/etc/init.d/dhcp start\"."
	;;
    *)	# failed with some other error
	print -u2 "Warning: failed to initialize the DHCP daemon.\
	\nYou may want to restart it manually."
	;;
    esac
}

function GetVersion  {
    FW_FILE_INPUT=${1}
    # extract the version string and make file names
    FW_TYPE=$(od -t x4 $FW_FILE_INPUT | head -1 | cut -d " " -f 2) 2> /dev/null
    case $FW_TYPE in
	4badbeef | 8badbeef)	
	    VERSION="$(what $FW_FILE_INPUT | sed -n '/^	version=/s///p')"
			;;
	abadbeef)	# compressed, execute in RAM
	    dd if=$FW_FILE_INPUT bs=8 skip=1 2> /dev/null | $LZD > $UC_FW_FILE  2> /dev/null
	    VERSION="$(what $UC_FW_FILE | sed -n '/^	version=/s///p')"
	    rm -f $UC_FW_FILE
			;;
	*)	print -u2 "Error: Unknown firmware module type (magic number=\"$FW_TYPE\")."
	    exit 1;
		;;
    esac

}
#
# Global Variables
#

CONF=/etc/inet/inetd.conf
HOSTS=/etc/inet/hosts
NETWORKS=/etc/inet/networks
UC_FW_FILE=${TMPDIR}/tmpfile.$$
HOSTNAME_R=/etc/hostname

WHICH=""	# One or all selection; "all" or "one"
MODE=""		# Major program option; "add" or "delete"
ETHER=""	# Ethernet address of a particular terminal
INTFS=""	# List of network interfaces
SUBNETS=""	# List of subnetworks
PROD_NAME="Corona"	# The name of the product
BOOTDIR=$(grep 'in\.tftpd.*/' /etc/inetd.conf | nawk '{print $NF}' -)
if [ -z "$BOOTDIR" -o ! -d "$BOOTDIR" ]
then
	BOOTDIR="/tftpboot"
fi
FW_PATH=""	# path to the firmware file(s)
FW_DIR=""	# directory of where the firmware file(s) live
FW_NAMES=""	# list of the name(s) of the firmware file(s) to use


#
# MAIN
#

# check if we're root
if [ $(IFS='=(';set $(id) ; print $2) -ne 0 ]
then
	print -u2 "Error: must have super user (root) privileges\n"
	Usage
fi

BASEDIR=$(pkginfo -r SUNWuto)
if [ ${?} -ne 0 ]
then
  print -u2 "Error: SUNWuto package must be installed"
  exit 1;
fi
FWLIBDIR=$BASEDIR/SUNWut/lib/firmware
BINDIR=$BASEDIR/SUNWut/bin
LZD=$BASEDIR/SUNWut/sbin/lzd
DODHCP="Y"

GetCurrentCfg;

# Test to make sure there are arguments for the script
while getopts ADPRae:f:n:N:hz NAME 2>/dev/null
do
	case $NAME in
	A) # add the specified unit(s) to the upgrade list
		if [ -n "$MODE" ]
		then
			print -u2 "Error: can only specify -A, -D, -R or -P"
			Usage;
		fi
		MODE=add
		;;
	D) # delete the specified unit(s) from the upgrade list
		if [ -n "$MODE" ]
		then
			print -u2 "Error: can only specify -A, -D, -R or -P"
			Usage;
		fi
		MODE=delete
		;;
	P) # print information about NewTVer values
		if [ -n "$MODE" ]
		then
			print -u2 "Error: can only specify -A, -D, -R or -P"
			Usage;
		fi
		MODE=prt
		;;
	R) # remove firmware files from $BOOTDIR
		if [ -n "$MODE" ]
		then
			print -u2 "Error: can only specifiy -A, -D, -R or -P"
			Usage;
		fi
		MODE=clean
		;;
	a) # apply to all units
		if [ -n "$WHICH" ]
		then
			Usage;
		fi
		WHICH=all
		;;
	e) # apply to the unit given by the six hex bytes of its EA
		if [ -n "$WHICH" ]
		then
			Usage;
		fi
		WHICH=one
		ETHER="$OPTARG"
		;;
	f) # use \"firmware\" as pathname for the module to use
	   	FW_PATH="$OPTARG"
		;;
	n) # a network interface name to enable upgrades on (allow multiple)
		if [ $OPTARG = "all" ]; then
			if [ ! -s ${TMPDIR}/newtifs.$$ ]; then
			        # WARNING - do not change this error message,
				# without also modifying 2.0 patch postpatch
				# script which parses it
				print -u2 "Warning: no private interconnect interfaces configured - no action taken"
				exit 0
			fi
			INTFS=`cat ${TMPDIR}/newtifs.$$`
			rm ${TMPDIR}/newtifs.$$
		else
			gotit=false
			for Intf in `cat ${TMPDIR}/newtifs.$$`
			do
				if [[ "$OPTARG" == "$Intf" ]]; then
					INTFS="$INTFS $OPTARG"
					gotit=true
					break
				fi
			done
			if ! $gotit; then
				print -u2 \
				"\nError: Interface \"${OPTARG}\" is not currently configured as a dedicated\n" \
				"interconnect.  You must configure the interface as a dedicated interconnect\n" \
				"before using this command to configure the firmware.  If you are trying to\n" \
				"configure the firmware for a shared network, please use the -N option.\n"

				Usage
				exit 1
			fi
		fi	
		;;
	N) # a subnetwork address to enable upgrades on (allow multiple)
		if [ $OPTARG = "all" ]; then
			if [ ! -s ${TMPDIR}/allnets.$$ ]; then
			        # WARNING - do not change this error message,
				# without also modifying 2.0 patch postpatch
				# script which parses it
				print -u2 "Warning: no subnetworks configured - no action taken"
				exit 0
			fi
			SUBNETS=`cat ${TMPDIR}/allnets.$$`
			rm ${TMPDIR}/allnets.$$
		else
			SUBNETS="$SUBNETS $OPTARG"
		fi	
		;;
	h)
		Usage
		;;
	z)
		DODHCP="N"
		;;
	?)
		Usage
		;;
	esac
done

# validate the input
if [ -z "$MODE" ]
then
	print -u2 "Error: Must specify either -A, -D, -R or -P"
	Usage
fi

if [ "$MODE" = "prt" ]
then
        ISSETUP=`dhtadm -P 2>/dev/null | grep -w "${CORONA_NAME}"`
	GetVersion /opt/SUNWut/lib/firmware/CoronaP1
	FW_VERSION="${VERSION#*-}"
	print "System Version         " $FW_VERSION
	print
	if [ -z "${ISSETUP}" ]; then
	  print "${CORONA_TITLE} interconnect framework is not configured";
	  exit 1;
	fi
	print "Domain          Intf    Upgrade to"
	dhtadm -P | nawk '/NewTVer=/ {
				domain = $1
				ver = $3
				sub(":.*NewTVer=\"*", "", ver)
				sub("\"*:.*$", "", ver)
				intf = $3
				sub(":.*Intf=\"*", "", intf)
				sub("\"*:.*$", "", intf)
				type = "???"
				if (domain ~ "\\\.")
					type = intf
				else if (substr(domain, 1, 2) == "01") {
					sub("^01", "", domain)
					type = "Ether"
				}
				printf "%-16s%-8s%s\n", domain, type, ver
			}'
	exit 0
fi

if [ "$MODE" = "clean" ]
then
	rm -f $BOOTDIR/$PROD_NAME*
	rm -f $BOOTDIR/$CORONA_NAME*
	rm -f $BOOTDIR/rewrite.*
	rm -f $BOOTDIR/view
	rm -f $BOOTDIR/view.*
	rm -f $BOOTDIR/nukeview
	exit 0
fi

if [ -z "$WHICH" ]
then
	print -u2 "Error: Must specify the unit(s) to be affected"
	Usage
fi

if [ -n "$INTFS" ]
then
	for INTF in $INTFS
	do 
		INTF_INFO=$(ifconfig $INTF);
		if [ ${?} -ne 0 ] || [ -z "${INTF_INFO}" ]
		then
			print -u2 "Error: Interface \"$INTF\" not found"
			exit 1
		fi
	done
elif [ -n "$SUBNETS" ]
then
	for NET in $SUBNETS
	do
		CheckIPA ${NET}
		if [ ${?} -ne 0 ]; then
			print -u2 "Error:invalid subnetwork address: \"${NET}\""
			exit 1
		fi
	done
else
	print -u2 "Error: Must specify either the network interface(s) or"
	print -u2 "the subnetwork address(es) upon which upgrades will be done"
	Usage
fi

# get the firmware file(s) to use
if [ -n "$FW_PATH" -a ! -d "$FW_PATH" ]
then
	# user specified firmware path, so check it out
	FW_DIR="$(dirname "$FW_PATH")"
	if [ "$FW_DIR" == "." ]
	then
		print -u2 "Error: Must provide full pathname for alternative firmware"
		Usage
	fi
	if [ ! -d "$FW_DIR" ]
	then
		print -u2 "Error: Firmware directory \"$FW_DIR\" not found"
		Usage
	fi

	FW_NAMES="$(basename "$FW_PATH")"
	if [ ! -f "$FW_DIR/$FW_NAMES" ]
	then
		print -u2 "Error: Firmware file \"$FW_DIR/$FW_NAMES\" not found"
		Usage
	fi
else
	# use the system firmware location and get the firmware files
	if [ -d "$FW_PATH" ]
	then
		FW_DIR="$FW_PATH"
	else
		FW_DIR="$FWLIBDIR"
	fi
	if [ ! -d "$FW_DIR" ]
	then
		print -u2 "Error: Firmware directory \"$FW_DIR\" not found"
		Usage
	fi
	FW_NAMES=""
	for FW_NAME in $(ls $FW_DIR/$PROD_NAME*)
	do
		FW_NAMES="$FW_NAMES $(basename "$FW_NAME")"
	done
fi

# Normalize Ethernet address for use with DHCP
if [ $WHICH = one ]
then
	# Some people will insist on entering the colons
	typeset -u ETHER	# force to upper case
	case "$ETHER" in
	*[0-9A-F]:[0-9A-F]*)
		# Get rid of colons
		SAVEIFS=$IFS
		IFS=:			# colon is separator
		for BYTE in $ETHER
		do
			case $BYTE in
			?)
				# single digit gets leading zero
				NETHER=${NETHER}0$BYTE
				;;
			*)
				NETHER=${NETHER}$BYTE
				;;
			esac
		done
		IFS=$SAVEIFS
		ETHER=$NETHER
		;;
	esac
	case $ETHER in
	[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]) # ok, exactly 12 hex characters
		;;
	*)
		print -u2 "Error: Invalid ethernet address: \"$ETHER\""
		Usage;
		;;
	esac
fi

# install or remove the firmware file(s)
for FW_NAME in $FW_NAMES
do
	# check the firmware file's validity
	FW_FILE="$FW_DIR/$FW_NAME"
	if [ ! -r "$FW_FILE" ]
	then
		print -u2 "Error: Firmware file \"$FW_FILE\" not accessible"
		Usage
	fi
	TYPE=$(file $FW_FILE | cut -f2)
	if [ "$TYPE" != "data" ]
	then
		print -u2 "Error: Improper firmware file \"$FW_FILE\"."
		Usage
	fi

	# extract the version string and make file names
	GetVersion $FW_FILE
	if [ -z "$VERSION" ]
	then
		print -u2 "Error: Unable to get firmware version from file \"$FW_FILE\"."
		exit 1
	fi
	FW_BASENAME="${VERSION%%-*}"
	SRAY_BASENAME=$CORONA_NAME$(echo $FW_BASENAME | sed -n 's/^Corona//p')
	FW_VERSION="${VERSION#*-}"

	# determine if this is a unit-specific operation
	if [ $WHICH == "all" ]
	then
		# check if new file and link is to be added
		if [ $MODE == "add" ]
		then
			# add for all, so copy the fw to bootdir with ugly name
			(umask 0022 ; mkdir -p $BOOTDIR)
			cp -p "$FW_FILE" "$BOOTDIR/$VERSION"
			if [ ${?} -ne 0 ]
			then
				print -u2 "Error: unable to copy \"$FW_FILE\" to \"$BOOTDIR/$VERSION\""
				exit 1
			fi

			# link the general name to the ugly name
			# N.B.:  target of symlink in tftpboot directory must
			# not have a leading '/'
			rm -f "$BOOTDIR/$FW_BASENAME"
			rm -f "$BOOTDIR/$SRAY_BASENAME"
			ln -s "$VERSION" "$BOOTDIR/$FW_BASENAME"
			if [ ${?} -ne 0 ]
			then
				print -u2 "Error: unable to link \"$BOOTDIR/$FW_BASENAME\" to \"$BOOTDIR/$VERSION\""
				exit 1
			fi
			ln -s "$VERSION" "$BOOTDIR/$SRAY_BASENAME"
			if [ ${?} -ne 0 ]
			then
				print -u2 "Error: unable to link \"$BOOTDIR/$SRAY_BASENAME\" to \"$BOOTDIR/$VERSION\""
				exit 1
			fi
		fi
	else
		if [ $MODE == "add" ]
		then
			# add specific, so copy fw to bootdir with ugly name
			(umask 0022 ; mkdir -p $BOOTDIR)
			cp -p "$FW_FILE" "$BOOTDIR/$VERSION.$ETHER"
			if [ ${?} -ne 0 ]
			then
				print -u2 "Error: unable to copy \"$FW_FILE\" to \"$BOOTDIR/$VERSION.$ETHER\""
				exit 1
			fi

			# link the specific name to the real ugly name
			# N.B.:  target of symlink in tftpboot directory must
			# not have a leading '/'
			rm -f "$BOOTDIR/$FW_BASENAME.$ETHER"
			rm -f "$BOOTDIR/$SRAY_BASENAME.$ETHER"
			ln -s "$VERSION.$ETHER" "$BOOTDIR/$FW_BASENAME.$ETHER"
			if [ ${?} -ne 0 ]
			then
				print -u2 "Error: unable to link \"$BOOTDIR/$FW_BASENAME.$ETHER"\" to \"$BOOTDIR/$VERSION.$ETHER"\""
				exit 1
			fi
			ln -s "$VERSION.$ETHER" "$BOOTDIR/$SRAY_BASENAME.$ETHER"
			if [ ${?} -ne 0 ]
			then
				print -u2 "Error: unable to link \"$BOOTDIR/$SRAY_BASENAME.$ETHER"\" to \"$BOOTDIR/$VERSION.$ETHER"\""
				exit 1
			fi
		fi
	fi
done


# check if we need to uncomment the tftp line in inetd.conf
RESULT=$(egrep "^#tftp" $CONF)
if [ -n "$RESULT" ]
then
	TEMP=$CONF.$$
	rm -f $TEMP
	trap "rm -f $TEMP" 0 1 2
	cp -p $CONF $TEMP
	chmod u+w $TEMP
	ed $TEMP <<-2HERE2 >/dev/null
	g/#tftp/s/#tftp/tftp/p
	w
	q
	2HERE2
	chmod u-w $TEMP
	mv $TEMP $CONF

	# restart the inetd
	ps -eo pid,comm | grep inetd | read INETD_PID INETD_COMM

	kill -HUP $INETD_PID
fi

# for each given network interface do either add or remove of the defined units
for INTF in $INTFS $SUBNETS
do
	CheckIPA $INTF
	# if failed this means the INTF is an interface, otherwise a subnetwork
	if [ $? -eq 0 ]; then
		if [ ${?} -ne 0 ]
		then
			print -u2 "Error: unable to get information on the primary interface"
			exit 1;
		fi
		INTF_NET=${INTF}
	else 
		# get info on the interface
		GetInterfaceInfo "$INTF";
		if [ ${?} -ne 0 ]
		then
			print -u2 "Error: unable to get information on interface \"$INTF\"";
			exit 1;
		fi
	fi

	if [ $MODE == "add" ]
	then
		# set the version option for the selected unit(s)
		if [ $WHICH == "all" ]
		then
			# upgrade all units by putting the version option
			# in the network macro
			dhtadm -M -m "$INTF_NET" -e "NewTVer=$FW_VERSION" 2> ${TMPDIR}/Err.$$
			if [ ${?} -ne 0 ]
			then
				print -u2 "Error: cannot add firmware version to network macro \"$INTF_NET\":"
				print -u2 $(cat ${TMPDIR}/Err.$$)
				rm -f ${TMPDIR}/Err.$$;
				exit 1;
			fi
			rm -f ${TMPDIR}/Err.$$;

			# print successfully done message
			print "\tAll the units served by \"$(uname -n)\" on the $INTF_NET"
			print "\tnetwork interface, running firmware other than version"
			print "\t\"$FW_VERSION\" will be upgraded at their next power-on.\n"
		else
			# upgrade a specific unit, check if unit macro exists
			if [ -z "$(dhtadm -P | grep "^01$ETHER")" ]
			then
				# doesn't exist, so create it
				dhtadm -A -m "01$ETHER" -d ":NewTVer=_NULL_VALUE_:" 2> ${TMPDIR}/Err.$$;
				if [ ${?} -ne 0 ]
				then
					print -u2 "Error: cannot create macro \"01$ETHER\":"
					print -u2 $(cat ${TMPDIR}/Err.$$)
					rm -f ${TMPDIR}/Err.$$;
					exit 1;
				fi
				rm -f ${TMPDIR}/Err.$$;
			fi

			# add/modify individual unit's macro
			dhtadm -M -m "01$ETHER" -e "NewTVer=$FW_VERSION" 2> ${TMPDIR}/Err.$$;
			if [ ${?} -ne 0 ]
			then
				print -u2 "Error: cannot add version option to \"01$ETHER\" macro:"
				print -u2 $(cat ${TMPDIR}/Err.$$)
				rm -f ${TMPDIR}/Err.$$;
				exit 1;
			fi
			rm -f ${TMPDIR}/Err.$$;

			# print successfully done message
			print "\tUnit \"$ETHER\" will be upgraded at its next power-on"
			print "\tif it is served by host \"$(uname -n)\" and is connected to"
			print "\tthe $INTF_NET network and is not already running firmware"
			print "\tversion \"$FW_VERSION\".\n"
		fi
	else
		# disable upgrade(s) for specified unit(s)
		if [ $WHICH == "all" ]
		then
			# remove fw version
			RESULT=$(dhtadm -P | grep "^$INTF_NET.*:NewTVer=.*:");
			if [ -n "$RESULT" ]
			then
				# exists, so remove the fw server macro
				dhtadm -M -m "$INTF_NET" -e "NewTVer=" 2> ${TMPDIR}/Err.$$;
				if [ ${?} -ne 0 ]
				then
					print -u2 "Error: cannot remove version option from \"$INTF_NET\" macro:"
					print -u2 $(cat ${TMPDIR}/Err.$$)
					rm -f ${TMPDIR}/Err.$$;
					exit 1;
				fi
				rm -f ${TMPDIR}/Err.$$;
			fi
		fi
	fi
done

# do post cleanup to delete things
if [ $MODE == "delete" ]
then
	if [ $WHICH == "all" ]
	then
		# remove fw version options from all individual unit macros
		NAMES=$(dhtadm -P |
		    sed -n 's/^\(0108[^ 	]*\)[ 	]*.*:NewTVer=.*:.*$/\1/p');
		if [ -n "$NAMES" ]
		then
			for NAME in $NAMES
			do
				# remove the fw version option from the given individual unit's macro
				MACRO=$(dhtadm -P |
				    sed -n -e "s/^${NAME}.*Macro[ 	]*\(.*\):NewTVer=[^:]*:\(.*\)/\1:\2/p");
				if [ "$MACRO" == ":" ]
				then
					# delete the macro
					dhtadm -D -m "$NAME" 2> ${TMPDIR}/Err.$$;
					if [ ${?} -ne 0 ]
					then
						print -u2 "Error: cannot remove \"$NAME\" macro:"
						print -u2 $(cat ${TMPDIR}/Err.$$)
						rm -f ${TMPDIR}/Err.$$;
						exit 1;
					fi
					rm -f ${TMPDIR}/Err.$$;
				elif [ -n "$MACRO" ]
				then
					# delete the macro and add another one without the fw srvr ipa
					dhtadm -D -m "$NAME" 2> ${TMPDIR}/Err.$$;
					if [ ${?} -ne 0 ]
					then
						print -u2 "Error: cannot remove \"$NAME\" macro:"
						print -u2 $(cat ${TMPDIR}/Err.$$)
						rm -f ${TMPDIR}/Err.$$;
						exit 1;
					fi
					rm -f ${TMPDIR}/Err.$$;

					dhtadm -A -m "$NAME" -d "$MACRO" 2> ${TMPDIR}/Err.$$;
					if [ ${?} -ne 0 ]
					then
						print -u2 "Error: cannot create the \"$NAME\" macro as $MACRO:"
						print -u2 $(cat ${TMPDIR}/Err.$$)
						rm -f ${TMPDIR}/Err.$$;
						exit 1;
					fi
					rm -f ${TMPDIR}/Err.$$;
				fi
			done
		fi
	else
		# remove the fw version from the given individual unit's macro
		MACRO=$(dhtadm -P |
		sed -n -e "s/^01${ETHER}.*Macro[ 	]*\(.*\):NewTVer=[^:]*\(:.*\)/\1\2/p");
		if [ "$MACRO" == ":" ]
		then
			# delete the current macro and add another one without
			#  the firmware server's IPA
			dhtadm -D -m "01$ETHER" 2> ${TMPDIR}/Err.$$;
			if [ ${?} -ne 0 ]
			then
				print -u2 "Error: cannot remove \"01$ETHER\" macro:"
				print -u2 $(cat ${TMPDIR}/Err.$$)
				rm -f ${TMPDIR}/Err.$$;
				exit 1;
			fi
			rm -f ${TMPDIR}/Err.$$;
		elif [ -n "$MACRO" ]
		then
			# delete the current macro and add another one without
			# the firmware server's IPA
			dhtadm -D -m "01$ETHER" 2> ${TMPDIR}/Err.$$;
			if [ ${?} -ne 0 ]
			then
				print -u2 "Error: cannot remove \"01$ETHER\" macro:"
				print -u2 $(cat ${TMPDIR}/Err.$$)
				rm -f ${TMPDIR}/Err.$$;
				exit 1;
			fi
			rm -f ${TMPDIR}/Err.$$;

			dhtadm -A -m "01$ETHER" -d "$MACRO" 2> ${TMPDIR}/Err.$$;
			if [ ${?} -ne 0 ]
			then
				print -u2 "Error: cannot create the \"01$ETHER\" macro as $MACRO:"
				print -u2 $(cat ${TMPDIR}/Err.$$)
				rm -f ${TMPDIR}/Err.$$;
				exit 1;
			fi
			rm -f ${TMPDIR}/Err.$$;
		fi

		# print successfully done message
		print "\tAutomatic firmware upgrades are disabled for \"${ETHER}\"".
	fi
fi

#### temp hack for backward compatibility
if [ "$MODE" == "add" ]
then
	REWR1="$FWLIBDIR/rewrite.sim"
	REWR2="$FWLIBDIR/rewrite.csi"
	if [ -f "$REWR1" -o -f "$REWR2" ]
	then
		rm -f "$BOOTDIR/view"
		rm -f "$BOOTDIR/view.*"
		rm -f "$BOOTDIR/nukeview"
		cp "$REWR1" "$BOOTDIR"
		cp "$REWR2" "$BOOTDIR"
		ln -s "rewrite.sim" "$BOOTDIR/nukeview"
	fi
fi
####

if [ $DODHCP = "Y" ]; then
	HupDHCP
fi

exit 0;
