#! /usr/bin/ksh
#
# ident "@(#)ssp_config.ksh	1.56    00/01/28     SMI"
#
# Copyright (c) 1996, 1998-2000 by Sun Microsystems, Inc.
# All rights reserved.
#
#

#
# Some globals we use
#
SSPOPT=${SSPOPT:-/opt/SUNWssp}		export SSPOPT
SSPETC=${SSPETC:-/etc/opt/SUNWssp}	export SSPETC
SSPVAR=${SSPVAR:-/var/opt/SUNWssp}	export SSPVAR
SSPLOGGER=${SSPLOGGER:-${SSPVAR}/adm}	export SSPLOGGER
TEXTDOMAIN=${TEXTDOMAIN:-SUNW_SSP}	export TEXTDOMAIN

PLATFORM_TYPE=Ultra-Enterprise-10000
CBCONFIGFILE=${SSPVAR}/.ssp_private/cb_config
ETHERSFILE=/etc/ethers
HOSTSFILE=/etc/hosts
INITTAB=/etc/inittab
RESERVED_PLAT="starfire common"
ENV=${SSPETC}/ssp_env.sh
MYPID=$$
EDD_ERC=edd.erc
EDD_EMC=edd.emc

#
# The current shipping version is required.
# This number must be changed if a newer PROM version is required by a
# particular SSP release.
PROM_REQUIRED=3.46

# The following line should be commented out when a version newer than 3.46
# is released - but it won't hurt if left alone but remember to uncomment
# the line in check_proms where PROM_CUURENT is set.
PROM_CURRENT=3.46

# Location of the flash PROM file
FLASH_BOOT_FILE=${SSPOPT}/cbobjs/flash_boot.ima

#############################################################################
#
# Display usage message
#
#############################################################################
usage()
{
    gettext "Usage: ssp_config [spare|cb]\n       ssp_terminate\n       ssp_upgrade <package-dir>\n       ssp_install <package-dir>\n       ssp_backup <target-dir>\n       ssp_restore <backup-file>\n       ssp_post_os_upgrade\n"
}

#############################################################################
#
# Generic routine for fatal errors.  Displays error message ($*) and exits.
#
#############################################################################
fatal()
{
    typeset format=$(gettext "ERROR!")
    print -u2 "$format  $*"
    print -u2 $(gettext "ABORTING!")
    exit 2
}

#############################################################################
#
# rotate_file
#
# Rotate a file, useful for keeping backup copies (e.g. for logs).
#
# $1 - file name (without suffix, e.g. "/var/adm/messages")
# $2 - highest numbered suffix to keep (e.g. "6" for "/var/adm/messages.6".
#
#############################################################################
rotate_file()
{
    typeset file=$1
    typeset -i num=$2
    typeset -i min

    while (( $num > 0 ))
    do
	min=$((num - 1))
	[[ -f ${file}.${min} ]] && mv -f ${file}.${min} ${file}.${num}
	num=${min}
    done
    if [[ -f ${file} ]]
    then
	mv -f ${file} ${file}.0
    fi
}

#############################################################################
#
# getuid
#
# Returns the uid (integer) for the process on stdout.
#
#############################################################################
getuid()
{
    typeset uid=$(id)
    eval ${uid%%\(*}
    print "$uid"
}

#############################################################################
#
# getpid
#
# Returns the process id(s) (integer) for a specific process.  May return
# more than one.
#
# $1 - name of process to look for (must be short name as in ps)
# $2 - owner of process (defaults to root)
#
#############################################################################
getpid()
{
    ps -u ${2:-root} | awk '{ if ($4 == "'"$1"'") { print $1 } }'
}

#############################################################################
#
# yes_or_no
#
# Query the user for yes or no input.
#
# $1 - prompt, should not include final newline or "(y/n)"
# Returns true (0) for yes, false (1) for no.
#
#############################################################################
yes_or_no()
{
    typeset -l ans=""
    # TRANSLATION_NOTE - these are the shell globs for an affirmative or a
    # negative answer, respectively.  The comparision is done after the
    # input is converted to lower case (using any locale specific case
    # conversion).  The defaults are any words starting with "y" or "n".
    typeset ansYes="$(gettext "y*")"
    typeset ansNo="$(gettext "n*")"
    typeset prompt="${1}"
    # TRANSLATION_NOTE - this is the format for yes or no prompts - %s is
    # the actual question.
    typeset format="$(gettext "%s (y/n)")"

    while true
    do
	printf "$format" "$prompt"
	read ans
	case "$ans" in
	$ansYes)
	    return 0;;
	$ansNo)
	    return 1;;
	esac 
    done
}

###########################################################################
#
# save_n_copy
# 
# save dst file before copying from src file
# $1 - dst
# $2 - src
# $3 - mode
# $4 - owner
#
###########################################################################
save_n_copy()
{
    typeset dst=${1}
    typeset src=${2}
    typeset mode=${3}
    typeset owner=${4}

    if [[ ! -f "${src}" ]]
    then
	# source file doesn't exist, don't do anything
	return
    fi

    if [[ -f "${dst}" ]]
    then
	if cmp -s ${dst} ${src}
	then
	    # no copy necessary
	    return
	fi
	rotate_file ${dst} 8
    fi

    if cp ${src} ${dst}
    then
	chmod "${mode}" ${dst}
	chown "${owner}" ${dst}
    else
	# TRANSLATION_NOTE - %s is destination file
	fatal "$(printf "$(gettext 'Could not create %s!')" "${dst}!")"
    fi
}

#############################################################################
#
# lookup_ip_addr()
#
# Given a hostname as an argument, set the variable in $2,
# and the return status of the match (0=OK)
#
# Bugids 4023717, 4086719, 4056209:
# Use /etc/nsswitch.conf file (to decide between NIS+, NIS, DNS, files).
#
# $1 - name of host to lookup
# $2 - variable to store result in, defaults to HOST_ADDR
#
#############################################################################
lookup_ip_addr()
{
    typeset _addr
    typeset _name
    typeset _junk
    typeset _line
    typeset _names
    typeset _file=${HOSTSFILE:-/etc/hosts}
    typeset _var=${2:-HOST_ADDR}
    getent hosts ${1} | read _addr _name _junk
    if [[ -n "$_addr" ]]
    then
	eval "${_var}=\"${_addr}\""
	return 0
    fi

    if [[ ! -f "${_file}" ]]
    then
	# nowhere else to look (why is there no hosts file???)
	return 1
    fi

    while read _addr _name
    do
	if [[ -z "$_addr" || "$_addr" == "#"* || \
	      -z "$_name" || "$_name" == "#"* ]]
	then
	    # empty or comment line
	    continue
	fi

	# strip off any trailing comment part
	_name=${_name%%#*}

	# there is an embedded tab in the pattern below
	if [[ "$_name" == ?(*[	\t])${1}?(.*) ]]
	then
	    # short or long name matches, only at beginning of word
	    eval "${_var}=\"${_addr}\""
	    return 0
	fi
    done < "${_file}"

    # we did not find a match
    return 1
}


#############################################################################
#
# lookup_etheraddr()
#
# Given a hostname as an argument, set the ETHER_ADDR variable,
# and the return status of the match (0=OK)
#
# Bugids 4023717, 4086719, 4056209:
# Use /etc/nsswitch.conf file (to decide between NIS+, NIS, DNS, files).
#
# $1 - name of host to look for
# $2 - variable to save address in, defaults to ETHER_ADDR
#
#############################################################################
lookup_etheraddr()
{
    typeset _name
    typeset _addr
    typeset _junk
    typeset _var=${2:-ETHER_ADDR}
    typeset _file=${ETHERSFILE:-/etc/ethers}
    getent ethers ${1} | read _name _addr _junk
    if [[ -n "$_addr" ]]
    then
	eval "${_var}=\"${_addr}\""
	return 0
    fi

    if [[ ! -f "${_file}" ]]
    then
	# no where else to look!
	return 1
    fi

    while read _name _addr _junk
    do
	if [[ -z "$_name" || "$_name" == "#"* || \
	      -z "$_addr" || "$_addr" == "#"* ]]
	then
	    # skip comments and whitespace
	    continue
	fi

	if [[ "$_name" == ${1}?(.*) ]]
	then
	    eval "${_var}=\"${_addr}\""
	    return 0
	fi
    done < "${_file}"

    return 1
}

#############################################################################
#
# get_ip_addr - prompts the user for an IP address for the host
# given as an argument and checks to make sure that the answer is at least
# of the form of an IP address.
#
# $1 - name of host to query for
# $2 - name of variable to store result in, defaults to HOST_ADDR
#
#############################################################################
get_ip_addr()
{
    typeset _ip_glob="+([0-9]).+([0-9]).+([0-9]).+([0-9])"
    typeset _ipset=false
    typeset _addr=""
    typeset _var=${2}
    typeset _fmt=""

    _var=${_var:-HOST_ADDR}
    _fmt=$(gettext "I could not automatically determine the IP address of %s.")
    printf "\n${_fmt}\n" "${1}"
    _fmt=$(gettext "Please enter the IP address of %s: ")
    while true
    do
	printf "${_fmt}" "${1}"
	read _addr
	if [[ -n "$_addr" ]]
	then
	    if [[ "${_addr}" == +([0-9]).+([0-9]).+([0-9]).+([0-9]) ]]
	    then
		eval "$_var=\"$_addr\""
		break
	    else
		printf "\n$(gettext "ERROR! \"%s\" is not an IP address!")\n" \
		    "$_addr"
	    fi
	fi
    done

    print
    gettext "You should make sure that this host/IP address is set up properly in the /etc/inet/hosts file or in your local name service system." | fmt
}

#############################################################################
#
# get_procspeed - prompts the user for the processor/interconnect frequencies
#
#############################################################################
get_procspeed()
{
    typeset options
    typeset procspeed
    typeset procmultiple
    typeset interconnect
    typeset -i cpuspeed

    while true
    do
        print
        gettext "You must specify what type of processor modules you have installed in your Enterprise-10000 platform.  Please select one of the options below." | fmt
	set -A options \
		"$(gettext '250 MHz processors')" \
	 	"$(gettext '336 MHz processors')" \
	 	"$(gettext '400 MHz processors')" \
	 	"$(gettext 'Unlisted (manually enter clock values)')"
# rfe#4221108, move this line to above the "Unlisted" line above
#	 	"$(gettext '500 MHz processors')" \
	print

	PS3=$(gettext "\nWhat speed of processors do you have installed? ")
# rfe#4221108, replace the "select" line below with this one
#	select procspeed in "${options[0]}" "${options[1]}" "${options[2]}" "${options[3]}" "${options[4]}"
	select procspeed in "${options[0]}" "${options[1]}" "${options[2]}" "${options[3]}"
	do

	  case "$procspeed" in

	  "${options[0]}")
	      # 250 MHz procs
	      interconnect=83333333
	      procmultiple=three-to-two
	      cpuspeed=250
	      ;;

	  "${options[1]}")
	      # 336 MHz procs
	      interconnect=83333333
	      procmultiple=two-to-one
	      cpuspeed=336
	      ;;

	  "${options[2]}")
	      # 400 MHz procs
	      interconnect=100000000
	      procmultiple=two-to-one
	      cpuspeed=400
	      ;;

# rfe#4221108, add these 6 lines
#	  "${options[3]}")
#	      # 500 MHz procs
#	      interconnect=100000000
#	      procmultiple=five-to-two
#	      cpuspeed=500
#	      ;;

# rfe#4221108, replace the optins[3] line below with this options[4] line:
#	  "${options[4]}")
	  "${options[3]}")
	      # manually entered values
	      print
	      gettext 'You have selected options which should only be used by Sun authorized personnel.  Incorrect data entry can result in damage to your processors! ' | fmt
	          # return to processor speed menu
	      if ! yes_or_no "$(gettext '\nAre you sure you want to proceed?')"
	      then
	          # return to processor speed menu
	          continue
	      fi

	      # collect the interconnect frequency
	      interconnect=
	      while [[ -z "$interconnect" ]]
	      do
		  print
	          gettext 'Enter the interconnect frequency in Hertz.  For example, 83.333 MHz is\ngiven as 83333333.  Be careful, incorrect values can cause damage.' | fmt
		  gettext '\nWhat is the interconnect frequency (in Hertz)? '
		  read interconnect
		  if [[ "$interconnect" != +([0-9]) ]]
		  then
		       interconnect=
		       gettext '\nInterconnect frequency must be a number.\n'
		  elif expr "$interconnect" \< 40000000 >/dev/null 2>&1 
		  then
		      interconnect=
		      gettext '\nInterconnect frequency must be at least 40000000 (40MHz)\n'
		  elif expr "$interconnect" \> 120000000 >/dev/null 2>&1
		  then
		      interconnect=
		      gettext '\nInterconnect frequency must be less than 120000000 (120MHz)\n'
		  fi
	      done

	      # collect the processor multiplier
	      print
	      gettext 'You must specify the processor clock multipler.  Please select one of the options below.' | fmt
	      print
	      PS3="$(gettext "\nWhat is the processor clock multiplier? ")"
# rfe#4221108, replace the "select" line below with this line
#	      select procmultiple in "two-to-one" "three-to-one" "three-to-two" "five-to-two"
	      select procmultiple in "two-to-one" "three-to-one" "three-to-two"
	      do
		  case $procmultiple in
		  two-to-one)
		      cpuspeed=$(( 2 * 2 * $interconnect / 1000000 ))
		      break
		      ;;
		  three-to-one)
		      cpuspeed=$(( 2 * 3 * $interconnect / 1000000 ))
		      break
		      ;;
		  three-to-two)
		      cpuspeed=$(( 3 * $interconnect / 1000000 ))
		      break
		      ;;
# rfe#4221108, add these 6 lines
#		  five-to-two)
#		      cpuspeed=$(( 5 * $interconnect / 1000000 ))
#		      break
#		      ;;
		  *)
		      print
		      ;;
		  esac
	      done
	     
	      ;;

	    *)
	      # invalid entry - go back to the processor speed menu
	      REPLY=
	      print
	      continue
	      ;;

	  esac

	  break

	done	# select procspeed ...

	print
	printf "$(gettext 'Your selections are apparently for a %d MHz processor.')" $cpuspeed | fmt
	print
	if yes_or_no "$(gettext 'Is this correct?')"
	then
	  break
	fi

    done  # while true
    if [[ -n "$1" ]]
    then
        eval "${1}=$interconnect"
    fi
    if [[ -n "$2" ]]
    then
        eval "${2}=$procmultiple"
    fi
}

#############################################################################
#
# save_procspeed - save the processor speeds we've already determined
#
# $1 - interconnect
# $2 - procmultiple
#############################################################################
save_procspeed()
{
    typeset ssp_interconnect
    typeset ssp_procmultiple
    typeset SSPRESOURCE=/var/opt/SUNWssp/.ssp_private/ssp_resource
    ssp_interconnect=Ultra-Enterprise-10000.platformTargetInterconnectClockFreq
    ssp_procmultiple=Ultra-Enterprise-10000.platformTargetProcClockMultiple

    sed -e "s/${ssp_interconnect}:.*\$/${ssp_interconnect}:${1}/" \
        -e "s/${ssp_procmultiple}:.*\$/${ssp_procmultiple}:${2}/" $SSPRESOURCE > $SSPRESOURCE.$$ && chown ssp $SSPRESOURCE.$$ && chmod 644 $SSPRESOURCE.$$ && mv $SSPRESOURCE.$$ $SSPRESOURCE
}

#############################################################################
#
# get_platform_name - prompts the user for the platform name
#
# $CHANGE - set to 1 if the platform name is changed
# $1 - name of variable to set (also contains default value), defaults
#      to PLATFORM_NAME
#############################################################################
get_platform_name()
{
    typeset _ans
    typeset _default
    typeset _fmt
    typeset _var=${1}

    eval "_default=\$${_var}"
    while true
    do
        print
	gettext 'The platform name identfies the entire host machine to the SSP software.  The platform name occupies a different name space than domain names (hostnames of bootable systems).' | fmt
	print

	if [[ -n "$_default" ]]
	then
	    # TRANSLATION_NOTE - %s is the default platform name
	    _fmt=$(gettext 'What is the name of the platform this SSP will service [%s]? ')
	else
	    _fmt=$(gettext 'What is the name of the platform this SSP will service? ')
	fi

	printf "$_fmt" "$_default"

	read _ans
	if [[ -n "$_ans" ]]
	then
	    if [[ "$_default" != "$_ans" ]]
	    then
		CHANGE=TRUE
		_default="$_ans"
	    fi
	else
	    _ans="$_default"
	fi

	if [[ "$RESERVED_PLAT" == *(* )"$_ans"*( *) ]]
	then
	    _fmt=$(gettext 'ERROR!  %s is a reserved name!')
	    _default=""
	    printf "\n${_fmt}\n" "${_ans}"
	    continue
	fi

	if [[ -n "$_ans" ]]
	then
	    eval "${_var}=\"${_ans}\""
	    return 0
	fi
    done
}

#############################################################################
#
# hexip - function to convert a standard IP address into a hexidecimal
# IP address suitable for tftpboot.  This does no error checking so you'd
# better send it a valid IP address.  The result is echo'd so you will
# probably want to use this with back-quotes as in: HIP=`hexip 1.2.3.4`
#
#############################################################################
hexip()
{
    typeset ip=$1
    printf "%02X%02X%02X%02X\n" $(print $ip | tr . ' ')
}


#############################################################################
#
# get_cb_name()
#
# function to get a control board name.
#
# $PLATFORM_NAME	- name of platform (used to build default name)
# $CB0_NAME, $CB1_NAME	- current name of conbrds 0 and 1, set on exit
# $CHANGE		- set to "true" if name was changed
# $1 - control board number, either 0 or 1
# $2 - variable to store result in, defautls to $CB{$1}_NAME, default value
#      is also taken from here.
#
#############################################################################
get_cb_name()
{
    typeset -i _num="$1"
    typeset _prompt
    typeset _fmt
    typeset _name
    typeset _newname
    typeset _oldname
    typeset _var="$2"

    if [[ -z "$_var" ]]
    then
	_var="CB${_num}_NAME"
    fi


    # if no control board, then clear the name
    _prompt=$(printf "$(gettext "Do you have a control board %d?")" "$_num")

    print
    if ! yes_or_no "$_prompt"
    then
	eval $_var=""
	return
    fi

    eval "_newname=\"\$$_var\""
    _oldname="${_newname}"
    if [[ -z "${_newname}" ]]
    then
	_newname=${PLATFORM_NAME}cb${_num}
    fi

    # TRANSLATION_NOTE - %d is either 0 or 1, %s is default conbrd name
    _fmt=$(gettext "Please enter the host name of the control board %d [%s]: ")
    print
    printf "${_fmt}" "${_num}" "${_newname}"
    read _name

    if [[ -n "$_name" ]]
    then
	_newname="$_name"
    fi

    if [[ "${_oldname}" != "${_newname}" ]]
    then
	CHANGE=true
    fi

    eval "$_var=\"$_newname\""
}

#############################################################################
#
# get_cb
#
# Get control board information.
#
# $1 - control board number (0 or 1)
# $2 - variable to store name in - defaults to CB{$1}_NAME
# $3 - variable to store IP addr in - defaults to CB{$1}_ADDR
#
#############################################################################
get_cb()
{
    typeset _cb=$1
    typeset _var1=$2
    typeset _var2=$3
    typeset _cb_name

    if [[ -z "$_var1" ]]
    then
	_var1="CB${_cb}_NAME"
    fi

    if [[ -z "$_var2" ]]
    then
	_var2="CB${_cb}_ADDR"
    fi
    get_cb_name ${_cb} _cb_name
    if [[ -n "${_cb_name}" ]]
    then
	eval "$_var1=\"${_cb_name}\""
	if ! lookup_ip_addr "${_cb_name}" "$_var2"
	then
	    get_ip_addr ${_cb_name} ${_var2}
	fi
    else
	eval "$_var1="
	eval "$_var2="
    fi
}

#############################################################################
#
# get_primary_cb
#
# Identify the primary control board in a two board system.
#
# $P0, $P1 - P{$primary_cb} is set to "P", the other one is cleared
# $1 - cb0's name
# $2 - cb1's name
#
#############################################################################
get_primary_cb()
{
    typeset cb0="$1"
    typeset cb1="$2"
    typeset -i _cb
    typeset _fmt
    typeset _name=
    typeset _prompt

    P0=
    P1=

    if [[ -n "$cb0" && "$cb0" == "$cb1" ]]
    then
	gettext "\nControl Board 0 and Control Board 1 are identical.\n"
	return 1
    elif [[ -z "$cb0" && -z "$cb1" ]]
    then
	gettext "\nNo control board has been identified.\n"
	return 1
    elif [[ -z "$cb1" ]]
    then
	P0=P
	return 0
    elif [[ -z "$cb0" ]]
    then
	P1=P
	return 0
    fi

    prompt=$(gettext "Is Control Board %d [%s] the primary?")
    while true
    do
	gettext "\nPlease identify the primary control board.\n"
	for _cb in 0 1
	do
	    _name=$(eval print \$cb${_cb})
	    _prompt=$(printf "$prompt" "${_cb}" "${_name}")

	    if yes_or_no "$_prompt"
	    then
		eval P${_cb}=P
		return 
	    fi
	done

    done
}

#############################################################################
#
# parse_cb_config
#
# Parse the cb_config file
#
# how many entries in file? assuming only a single line...
# this needs to be expanded to handle multiple entries.
#
# $PLATFORM_NAME	- name of the platform
# $CB0_NAME		- name of CB #0
# $CB1_NAME		- name of CB #1
# $CB0_ADDR		- ip address of CB #0
# $CB1_ADDR		- ip address of CB #1
# $P0, $P1		- set to P if either CB0 or CB1 is primary
# $VALID_CONFIG		- "true" if a valid configuration exists
# $PLATFORM_LOCKED	- "true" if the platform is set
#
#############################################################################
parse_cb_config()
{
    VALID_CONFIG=
    PLATFORM_LOCKED=
    if [[ -s "${CBCONFIGFILE}" ]]
    then
	# try and parse current info
	PLATFORM_NAME=$(cut -d: -f1 ${CBCONFIGFILE})
	# we only support Ultra-Enterprise-10000, do not allow this to be
	# set in the file
	PLATFORM_TYPE=$(cut -d: -f2 ${CBCONFIGFILE})
	CB0_NAME=$(cut -d: -f3 ${CBCONFIGFILE})
	P0=$(cut -d: -f4 ${CBCONFIGFILE})
	CB1_NAME=$(cut -d: -f5 ${CBCONFIGFILE})
	P1=$(cut -d: -f6 ${CBCONFIGFILE})
	if [[ -n "$CB0_NAME" ]]
	then
	    lookup_ip_addr "$CB0_NAME" CB0_ADDR
	fi
	if [[ -n "$CB1_NAME" ]]
	then
	    lookup_ip_addr "$CB1_NAME" CB1_ADDR
	fi

	VALID_CONFIG=true

	PLATFORM_LOCKED=true
	# platform name is set?
	if [[ -z "$PLATFORM_NAME" ]]
	then
	    PLATFORM_LOCKED=
	    VALID_CONFIG=
	fi

	# platform type is correct?
	if [[ -z "$PLATFORM_TYPE" ]]
	then
	    PLATFORM_TYPE="Ultra-Enterprise-10000"
	    VALID_CONFIG=
	fi
	    
	if [[ -z "$CB0_NAME" && -z "$CB1_NAME" ]]
	then
	    VALID_CONFIG=
	fi

	# sanity check P0/P1
	if [[ -n "$P1" && -n "$P0" ]]
	then
	    P0=
	    P1=
	    VALID_CONFIG=
	elif [[ -n "$P1" && -z "$CB1_NAME" ]]
	then
	    P1=
	    VALID_CONFIG=
	elif [[ -n "$P0" && -z "$CB0_NAME" ]]
	then
	    P0=
	    VALID_CONFIG=
	fi

    else
	# file not present
	PLATFORM_NAME=
	CB0_NAME=
	CB1_NAME=
	CB0_ADDR=
	CB1_ADDR=
	P0=
	P1=
    fi
}

#############################################################################
#
# remove_ssp_startup_from_inittab()
# Remove a call to ssp_startup, which starts SSP daemons, from /etc/inittab
# Re-read /etc/inittab
#
# Code based on SUNWsspr/postremove
#
#############################################################################
remove_ssp_startup_from_inittab()
{
    typeset file=${INITTAB:-/etc/inittab}
    typeset initline
    if [[ -f ${file} ]]
    then
	initline=$(grep "^sp:234:respawn:.*ssp_startup.sh" ${file} 2>/dev/null)
	# Remove the ssp_startup from the /etc/inittab file.
	if [[ -n "$initline" ]] ; then
	    (echo '/^sp:234:respawn:.*ssp_startup.sh/d';
	    echo 'w';
	    echo 'q' ) | ed -s ${file} > /dev/null
	fi
   fi

   # Have init re-read /etc/inittab:
   init q

   # Pull out rc scripts as well
   if [ -f /etc/init.d/ssp ]
   then
       rm -f /etc/rc?.d/[SK][0-9][0-9]ssp
   fi
}


#############################################################################
#
# add_ssp_startup_to_inittab()
# Add a call to ssp_startup, which starts SSP daemons, to the startup
# scripts (instead of inittab, which was used historically)
#
# Code based on SUNWsspr/postinstall
#
#############################################################################
add_ssp_startup_to_inittab()
{
    # First remove old versions of the ssp_startup line in the file, if any:
    remove_ssp_startup_from_inittab

    # configure startup scripts
    ln -sf /etc/init.d/ssp /etc/rc2.d/S99ssp
    ln -sf /etc/init.d/ssp /etc/rc1.d/K20ssp
    ln -sf /etc/init.d/ssp /etc/rc0.d/K20ssp
}

#############################################################################
#
# tftpboot_setup()
# Set up the tftpboot stuff
#
# Move files from /tftpboot.spare to /tftpboot in case this
# system used to be the SSP spare (bugid 4036803).
#
# This routine should be called only for the main SSP, not spare SSP
# (bugids 4112732, 4036803).
#
#############################################################################
tftpboot_setup()
{
    typeset file
    if [[ -d /tftpboot.spare && ! -d /tftpboot ]]
    then
	mv /tftpboot.spare /tftpboot
    elif [[ -d /tftpboot.spare && -d /tftpboot ]]
    then
	# directory already there--move contents conditionally
	for file in /tftpboot.spare/* /tftpboot.spare/.*
	do
	    if [[ -f "${file}" && ! -e /tftpboot/${file##*/} ]]
	    then
		mv -f "${file}" /tftpboot
	    fi
	done
	rm -rf /tftpboot.spare

    elif [[ ! -d /tftpboot ]]
    then
	mkdir -m 755 /tftpboot
    fi

    CBOBJS=${SSPOPT}/cbobjs
    /usr/sbin/install -f /tftpboot -s -m 444 ${CBOBJS}/cbe.ima
    /usr/sbin/install -f /tftpboot -s -m 444 ${SSPVAR}/.ssp_private/cb_port

    if [[ -n "${CB0_ADDR}" ]]
    then
	CB0HEXIP=$(hexip ${CB0_ADDR})
	rm -f /tftpboot/${CB0HEXIP}
	ln -f /tftpboot/cbe.ima /tftpboot/${CB0HEXIP}
	chmod 444 /tftpboot/${CB0HEXIP}
	rm -f /tftpboot/${CB0HEXIP}.cb_port
	ln -f /tftpboot/cb_port /tftpboot/${CB0HEXIP}.cb_port
	chmod 444 /tftpboot/${CB0HEXIP}.cb_port
    fi

    if [[ -n "${CB1_ADDR}" ]]
    then
	CB1HEXIP=$(hexip ${CB1_ADDR})
	rm -f /tftpboot/${CB1HEXIP}
	ln /tftpboot/cbe.ima /tftpboot/${CB1HEXIP}
	chmod 444 /tftpboot/${CB1HEXIP}
	rm -f /tftpboot/${CB1HEXIP}.cb_port
	ln /tftpboot/cb_port /tftpboot/${CB1HEXIP}.cb_port
	chmod 444 /tftpboot/${CB1HEXIP}.cb_port
    fi

    #
    # Uncomment tftp from or add tftp to the inetd.conf file if necessary.
    #
    if grep '^#tftp' /etc/inetd.conf > /dev/null ; then # Uncomment
		ed /etc/inetd.conf << EOF >/dev/null
/^#tftp
s/^#//
.
w
q
EOF
    elif ! grep '^tftp' /etc/inetd.conf > /dev/null ; then # Add
	# Uh-oh!  Where's the tftp line?! Let's add it near the end.
	ed /etc/inetd.conf << EOF >/dev/null
$
i
tftp	dgram	udp	wait	root	/usr/sbin/in.tftpd	in.tftpd -s /tftpboot
.
w
q
EOF
	fi	

	#
	# Have inetd re-read /etc/inetd.conf to update with any changes above
	# (Note: we have to use ps to get the PID, since it's not saved in a
	# .pid file) (Bugid 4069016)
	#
	inetd_pid=$(getpid inetd root)

	if [[ -n "$inetd_pid" ]]
	then
	    kill -HUP $inetd_pid
	fi

	#
	# The /tftpboot directory should already exist, start the
	# RARPD daemon
	#
	#/usr/sbin/in.rarpd -a
	#/usr/sbin/rpc.bootparamd
	# Better to do it right--start and stop nfs.server (bug 4294678):
	/etc/init.d/nfs.server stop
	/etc/init.d/nfs.server start
}


#############################################################################
#
# tftpboot_disable()
# Disable the tftpboot stuff
#
# Move files from /tftpboot to /tftpboot.spare
# This must be done so /etc/init.d/nfs.server won't enable rarpd
# and cause cbs to query the spare SSP for tftp service instead of
# the main SSP (bugid 4036803).  We don't care if tftp is disabled,
# *but* /tftpboot mustn't be there so rarpd isn't enabled at bootup
# by /etc/init.d/nfs.server.
#
# This routine should be called only for the spare SSP, not main SSP
# (bugids 4112732, 4036803).
#
#############################################################################
tftpboot_disable()
{
    if [[ -d /tftpboot ]]
    then
	if [[ ! -d /tftpboot.spare ]]
	then
	    mv /tftpboot /tftpboot.spare
	else # target directory already there--move contents
	    mv /tftpboot/* /tftpboot/.[^.]* /tftpboot.spare 2>/dev/null
	    rm -rf /tftpboot
	fi
    fi

    # Disable the spare SSPs tftp boot server (bugid 4036803)
    if grep '^tftp' /etc/inetd.conf > /dev/null
    then
ed /etc/inetd.conf << EOF > /dev/null
/^tftp
s/^tftp/#tftp/
.
w
q
EOF
    fi

    #
    # Have inetd re-read /etc/inetd.conf to update with any changes above
    # Note: we have to use ps to get the PID, since it is not saved
    # in a .pid file. (Bugid 4069016)
    #
    inetd_pid=$(getpid inetd root)
    if [[ -n "$inetd_pid" ]]
    then
	kill -HUP $inetd_pid
    fi

    #
    # Kill the RARPD daemon, don't want it active on the spare
    #
    rarpd_pid=$(getpid in.rarpd root)
    if [[ -n "$rarpd_pid" ]]
    then
	kill $rarpd_pid
    fi
}

#############################################################################
#
# show_config
#
# Display the current control board configuration
#
#############################################################################
show_config()
{
    print
    # TRANSLATION_NOTE - make sure the equal signs (=) line up properly
    printf "$(gettext "Platform name     = %s")\n" "${PLATFORM_NAME}"
    if [[ -n "$CB0_NAME" && -n "$CB0_ADDR" ]]
    then
	printf "$(gettext "Control board %d = %s => %s")\n" 0 "${CB0_NAME}" "${CB0_ADDR}"
    else
	printf "$(gettext "Control board %d = [empty]")\n" 0
    fi
    if [[ -n "$CB1_NAME" && -n "$CB1_ADDR" ]]
    then
	printf "$(gettext "Control board %d = %s => %s")\n" 1 "${CB1_NAME}" "${CB1_ADDR}"
    else
	printf "$(gettext "Control board %d = [empty]")\n" 1
    fi
    if [ "$P0" == "P" ] 
    then 
	printf "$(gettext "Primary Control Board = 0")\n"
    else 
	printf "$(gettext "Primary Control Board = 1")\n"
    fi
}

#############################################################################
#
# save_cb_config
#
# Save out changes to the ${CBCONFIGFILE}.
#
#############################################################################
save_cb_config()
{
    # write out the cbconfig file
    print "${PLATFORM_NAME}:${PLATFORM_TYPE}:${CB0_NAME}:${P0}:${CB1_NAME}:${P1}" > /tmp/tmpcb$$
    save_n_copy "${CBCONFIGFILE}" /tmp/tmpcb$$ 644 ssp
    rm -f /tmp/tmpcb$$
}

#############################################################################
#
# get_n_save_cb_config
#
# Get the control board configuration.  This prompts the user for
# data using preloaded defaults from parse_cb_config.  The final results
# are actually saved to the ${CBCONFIGFILE}.
#
#############################################################################
get_n_save_cb_config()
{
    while true
    do
	if [[ "$VALID_CONFIG" == true ]]
	then
	    show_config
	    print

	    # upgrades should be noninteractive if possible
	    if [[ -n "$SSP_UPGRADE" ]]
	    then
		break
	    fi

	    if yes_or_no "$(gettext "Is this correct?")"
	    then
		break
	    fi
	fi

	if [[ -f /.SSP_DEFAULTS ]]
	then
	    # we force the user to enter a new ssp passwd by expiring
	    # the old one.
	    passwd -r files -d -f ssp
	    # unconfigured, so we don't know what kind of procs are out there
	    get_procspeed INTERCONNECT PROCMULTIPLE
	    # write out the ssp resource processor speeds
	    save_procspeed $INTERCONNECT $PROCMULTIPLE
	fi

	if [[ "$PLATFORM_LOCKED" != true ]]
	then
	    get_platform_name PLATFORM_NAME
	fi
	get_cb 0 CB0_NAME CB0_ADDR
	get_cb 1 CB1_NAME CB1_ADDR

	if ! get_primary_cb "$CB0_NAME" "$CB1_NAME"
	then
	    VALID_CONFIG=
	    continue
	fi
	VALID_CONFIG=true
    done

    # write out the cbconfig file
    if [[ ! -s "${CBCONFIGFILE}" || "${CHANGE}" == true ]]
    then
	save_cb_config
    fi

}

#############################################################################
#
# create_platform_link
#
# create the platform specific link in the data directory
#
#############################################################################
create_platform_link()
{
    # create the platform-specific data link
    typeset DATA=${SSPVAR}/data/${PLATFORM_TYPE}
    if [[ ! -d ${DATA} ]]
    then
	fmt=$(gettext "Couldn't find %s!")
	fatal "$(printf "$fmt\n" "${DATA}")"
    fi

    rm -f ${DATA}/${PLATFORM_NAME}
    if ! ln -s ./starfire ${DATA}/${PLATFORM_NAME}
    then
	fmt=$(gettext "Couldn't create %s!")
	fatal "$(printf "$fmt\n" "${DATA}/${PLATFORM_NAME}")"
    fi
}

#############################################################################
#
# copy_data_files
#
# Install the various data files and directories needed at runtime.
#
#############################################################################
copy_data_files()
{
    typeset p_etc=${SSPVAR}/etc/${PLATFORM_NAME}
    typeset cbobjs_dir=${p_etc}/cbobjs
    typeset tmpl=${SSPVAR}/.ssp_private/templates/${PLATFORM_TYPE}
    typeset platform_erc=${tmpl}/edd.platform.erc
    typeset domain_erc=${tmpl}/edd.domain.erc
    typeset domaindir=

    if [[ ! -d ${p_etc} ]]
    then
	mkdir -m 755 -p ${p_etc}
	chown ssp ${p_etc}
    fi

    if [[ ! -d ${cbobjs_dir} ]]
    then
	mkdir -m 755 -p ${cbobjs_dir}
	chown ssp ${cbobjs_dir}
    fi

    # if a copy of the platform erc file exists, save it off 
    save_n_copy ${p_etc}/${EDD_ERC} ${platform_erc} 640 ssp

    # if a copy of the platform emc file exists, save it off 
    save_n_copy ${p_etc}/${EDD_EMC} ${tmpl}/${EDD_EMC} 640 ssp

    # take care of domain files, too
    for domaindir in ${p_etc}/*
    do
	if [[ -f "${domaindir}/${EDD_ERC}" ]]
	then
	    save_n_copy ${domaindir}/${EDD_ERC} ${domain_erc} 640 ssp
	fi
    done

    # remove globalconst.tcl file, to be rebuilt by edd
    rm -f ${cbobjs_dir}/globalconst.tcl

    #
    # Make sure bids.tcl and thermcaldata.tcl are there
    # (bugs 4054660 4067723)
    touch ${cbobjs_dir}/bids.tcl
    chmod 644 ${cbobjs_dir}/bids.tcl
    chown ssp ${cbobjs_dir}/bids.tcl

    touch ${cbobjs_dir}/thermcaldata.tcl
    chmod 644 ${cbobjs_dir}/thermcaldata.tcl
    chown ssp ${cbobjs_dir}/thermcaldata.tcl

    #
    # Remove /etc/opt/SUNWssp/snmp/*.idy and let it be rebuilt by scotty
    #
    rm -f ${SSPETC}/snmp/*.idy
}

#############################################################################
#
# make_platform_config
#
# Install platform config file, we only do this on a first run.
#
#############################################################################
make_platform_config()
{    
    typeset platform_name=${1}
    typeset configdir=${SSPVAR}/data/${PLATFORM_TYPE}/config
    typeset platform_config=${configdir}/${platform_name}.config
    typeset starfire_config=${configdir}/starfire.config
    if [[ ! -s "${platform_config}" || "${CHANGE}" == true ]]
    then
	if cp ${starfire_config} ${platform_config}
	then
	    chown ssp ${platform_config}
	    chmod 644 ${platform_config}
	else
	    fatal "$(printf "$(gettext "Could not create %s!")" "${platform_config}!")"
	fi
    fi
}

#############################################################################
#
# ssp_terminate
#
# Terminate all SSP processes.
#
#############################################################################
ssp_terminate()
{
    for pid in $(ps -ef | egrep "ssp_startup.sh|hostview" | \
	    egrep -v egrep | awk '{print $2}')
    do
	kill -KILL $pid > /dev/null 2>&1
    done
    #
    # give time for ssp_startup to die so that it does not restart
    # the daemons.  (Actually, SIGKILL doesn't really need any time,
    # but it needs to be done first, at least.)
    #

    #
    # killing client apps
    for pid in $(ps -ef | \
	    egrep "bringup|hpost|scotty|netcon|netcon_server|obp_helper" | \
	    egrep -v "egrep|ps \-ef|rlogin|xterm" | awk '{print $2}')
    do
	kill -KILL $pid > /dev/null 2>&1
    done
    #
    # killing the daemons
    #
    # Kill daemons separately because egrep "snmpd" will cause snmpdx
    # to be killed (Bug ID 4235746)
    # for pid in $(ps -ef | egrep "edd|snmpd|straps|cbs|fad" | \
    #	    egrep -v "egrep|ps \-ef|rlogin|xterm" | awk '{print $2}')
    #do
    #	kill -KILL $pid > /dev/null 2>&1
    #done
    pid=$(getpid codd ssp) # bugid 4258031 (codd)
    if [[ -n "$pid" ]]
    then
      kill -KILL $pid > /dev/null 2>&1
    fi
    pid=$(getpid edd ssp)
    if [[ -n "$pid" ]]
    then
	kill -KILL $pid > /dev/null 2>&1
    fi
    pid=$(getpid snmpd root)
    if [[ -n "$pid" ]]
    then
	kill -KILL $pid > /dev/null 2>&1
    fi
    pid=$(getpid straps root)
    if [[ -n "$pid" ]]
    then
	kill -KILL $pid > /dev/null 2>&1
    fi
    pid=$(getpid cbs ssp)
    if [[ -n "$pid" ]]
    then
	kill -KILL $pid > /dev/null 2>&1
    fi
    pid=$(getpid fad ssp)
    if [[ -n "$pid" ]]
    then
	kill -KILL $pid > /dev/null 2>&1
    fi

    #
    # killing ap daemons
    #
    for pid in $(ps -ef | egrep "ap_ssp_daemon|ap_startup" | \
		egrep -v "egrep|ps \-ef|rlogin|xterm" | awk '{print $2}')
    do
	kill -KILL $pid > /dev/null 2>&1
    done
    #
    # killing machine_server
    #
    for pid in $(ps -ef | egrep machine_server | \
		egrep -v "egrep|ps \-ef|rlogin|xterm" | awk '{print $2}')
    do
	kill -KILL $pid > /dev/null 2>&1
    done

    # do *not* call exit here, it breaks other things

}

###########################################################################
#
# ssp_pkgrm
# 
# Check for package existence before invoking pkgrm.
# argument contains a list of packages to remove
#
###########################################################################
ssp_pkgrm()
{
    while [ $# -gt 0 ]
    do
	pkginfo $1 > /dev/null 2>&1
	if [[ $? -eq 0 ]]
	then
	    print -n "pkgrm $1..." 
	    pkgrm -n -a ${adminfile} $1 >> ${log} 2>&1
	    if [[ $? -ne 0 ]]
	    then
		pkg_err=1
		gettext "failed\n"
	    else
		gettext "done\n"
	    fi
	fi
	shift
    done
}

###########################################################################
#
# ssp_pkgadd
# 
# Individually perform pkgadd. The advantage of doing it one at a time
# is that we could install even if a package on the list is missing.
# argument contains a list of packages to add.
#
###########################################################################
ssp_pkgadd()
{
    typeset response

    while [[ $# -gt 0 ]]
    do
	if [[ -f "/tmp/${1}.response.${MYPID}" ]]
	then
	    response="-r /tmp/${1}.response.${MYPID}"
	else
	    response=-n
	fi

	print -n "pkgadd $1..." 
	pkgadd -d ${package_dir} ${response} -a ${adminfile} $1 >> ${log} 2>&1
	if [[ $? -ne 0 ]]
	then
	    pkg_err=1
	    gettext "failed\n"
	else
	    gettext "done\n"
	fi
	shift
    done
}

###########################################################################
#
# ssp_pkgadd_fp
#
# Install the Flash PROM (SUNWsspfp) if the user need/wants to
#
###########################################################################
ssp_pkgadd_fp()
{
    typeset prompt

    # Get here only if the PROM is not installed and the installed PROM
    # version is out of date; ask the user for direction
    print
    prompt=$(gettext "Do you want to install the SUNWsspfp package?")
    if yes_or_no "$prompt"
    then
	pkgadd -d ${package_dir} SUNWsspfp
	if [[ $? -ne 0 ]]
	then
	    pkg_err=1
	    print "pkgadd SUNWsspfp failed" >> ${log} 2>&1
	    gettext "SUNWsspfp package installation failed.\n"
	    print
	else
	    # pkgadd success
	    return
	fi
    fi

    # Either pkgadd failed or user answered 'n', need to upgrade later
    printf "$(gettext 'You must install the SUNWsspfp package and update the firmware on control board %s. See the Installation Guide for details.')" "$name" | fmt
    print
}

###########################################################################
#
# ssp_pkgadd_ab
#
# Install the SSP 3.1 AnswerBook (SUNWuessp). It needs to be interactive.
#
###########################################################################
ssp_pkgadd_ab()
{
    typeset prompt
    typeset SSP_AB=SUNWuessp

    # First check if the SSP AB package is available
    pkginfo -d ${package_dir} -q ${SSP_AB}
    if [[ $? -eq 0 ]]
    then
	# SSP AB on installation directory, ask if want to install
	prompt=$(gettext "Do you want to install the SSP 3.1.1 AnswerBook (SUNWuessp)?")
	if yes_or_no "$prompt"
	then
	    # Remove old package if installed
	    pkginfo -q ${SSP_AB}
	    if [[ $? -eq 0 ]]
	    then
		print -n "pkgrm ${SSP_AB}..."
		pkgrm -n -a ${adminfile} ${SSP_AB} >> ${log}
		if [[ $? -ne 0 ]]
		then
		    pkg_err=1
		    print "pkgrm $SSP_AB failed" >> ${log}
		    gettext "SUNWuessp package removal failed\n"
		    return
		fi
	    fi

	    # Add the SSP AB package
	    pkgadd -d ${package_dir} ${SSP_AB}
	    if [[ $? -ne 0 ]]
	    then
		pkg_err=1
		print "pkgadd $SSP_AB failed" >> ${log}
		gettext "SUNWuessp package installation failed\n"
	    fi
	fi  # Install SUNWuessp
    fi  # AB Available
}

###########################################################################
#
# save_a_copy
# 
# Make a backup copy of a file for upgrade purpose.
#
###########################################################################
save_a_copy()
{
    typeset format=$(gettext "Backing up %s as %s")
    while [[ $# -gt 0 ]]
    do
	if [[ -f "$1" ]]
	then
	    printf "$format\n" $1 $1.__upgrade
	    cp $1 $1.__upgrade
	fi
	shift
    done
}

#############################################################################
#
# main_or_spare
#
# Determine whether this is the main or spare SSP.
#
#############################################################################
main_or_spare()
{
	INITTAB=${INITTAB:-/etc/inittab}

	# Determine if we are the main or spare SSP
	# we use this to edit inittab appropriately
	if grep "^sp:234:respawn:.*ssp_startup.sh" $INITTAB > /dev/null 2>&1
	then
		SSP_STATION=main
	elif [[ -f /etc/rc2.d/S99ssp ]]
  	then
		SSP_STATION=main
	else
		SSP_STATION=spare
	fi
}

#############################################################################
#
# preupgrade
#
# Perform some basic preupgrade processing.  This determines whether the
# SSP was already a main or spare, and backs up key data files.
#
#############################################################################
preupgrade()
{
	typeset SSPRESOURCE=/var/opt/SUNWssp/.ssp_private/ssp_resource
	typeset -i PROCSPEED

	if [[ "${SSP_STATION}" == main ]]
	then
	    gettext "Upgrading main SSP.\n"
	else
	    gettext "Upgrading spare SSP.\n"
	fi
	
	# If the .ssp_resource file is present, save its value in a
	# pkgask file to stop SUNWsspdf from being interactive
	if [[ -f "$SSPRESOURCE" ]]
	then
	    INTERCONNECT=$(awk -F: '/^Ultra-Enterprise-10000.platformTargetInterconnectClockFreq:/ {print $2}' $SSPRESOURCE)
	    PROCMULTIPLE=$(awk -F: '/^Ultra-Enterprise-10000.platformTargetProcClockMultiple:/ {print $2}' $SSPRESOURCE)
	    case "$PROCMULTIPLE" in
	    three-*)
		# external clock tripler
		PROCSPEED=$((3 * $INTERCONNECT / 1000000 ))
		;;
	    two-*)
		# external clock doubler
		PROCSPEED=$((2 * $INTERCONNECT / 1000000 ))
		;;
# rfe#4221108, add these 5 lines
#	    five-*)
#		# external clock doubler
#		PROCSPEED=$((5 * $INTERCONNECT / 1000000 ))
#		;;
	    esac

	    if [[ "$PROCMULTIPLE" == *-one ]]
	    then
		# assume an internal clock doubler
		PROCSPEED=$(( 2 * $PROCSPEED ))
	    fi
	    printf "$(gettext 'Current SSP is configured for %d MHz processors.')" $PROCSPEED | fmt
	else
	    # can't pick up default values, so ask for them
	    get_procspeed INTERCONNECT PROCMULTIPLE
	fi

	# Backup volatile files
	save_a_copy \
	    /export/home/ssp/.Xdefaults \
	    /export/home/ssp/.openwin-menu \
	    /export/home/ssp/.xinitrc \
	    /export/home/ssp/.drtclrc \
	    /export/home/ssp/.openwin-init \
	    /export/home/ssp/.openwin-menu-ssp \
	    /export/home/ssp/.redxrc \
	    /export/home/ssp/.cshrc \
	    /export/home/ssp/.login \
	    /export/home/ssp/.postrc \
	    /var/opt/SUNWssp/.ssp_private/bringup.lock \
	    /var/opt/SUNWssp/.ssp_private/bringup_dr.lock \
	    /var/opt/SUNWssp/.ssp_private/ssp_resource \
	    /var/opt/SUNWssp/adm/.logger
}

#############################################################################
#
# convert_domain_config
#
# Convert domain_config file to new (3.1) (IDN enhanced) format.
#
# old (3.0) format:  domain : platform : physical : release : boardlist
# new (3.1) format:  domain : platform : physical : release : IDN : boardlist
#
# Also, in SSP3.2, OS releases 2.x are now 5.x.
#
#############################################################################
convert_domain_config()
{
    typeset oldfile=${1}
    typeset newfile=${1}.upgrade$$
    typeset mode=${2}
    typeset owner=${3}
    typeset domain
    typeset platform
    typeset physical
    typeset release
    typeset idn
    typeset boardlist
    typeset ver=

    if [[ ! -f "${oldfile}" ]]
    then
	format=$(gettext "Old domain config file '%s' not found.")
	printf "$format\n" "$oldfile"
	return
    fi

    > ${newfile}

    while IFS=: read domain platform physical release idn boardlist
    do
	if [[ -z "$boardlist" ]]
	then
	    boardlist="$idn"
	    idn="-1.0"
	fi

	# Switch from Solaris to SunOS numbering
	if [[ "${release}" == 2.* ]]
	then
	    release=5.${release#2.}
	fi

	print "${domain}:${platform}:${physical}:${release}:${idn}:${boardlist}" >> ${newfile}
    done < "${oldfile}"

    if cmp -s "${oldfile}" "${newfile}"
    then
	# files are the same, do not do anything
	rm -f ${newfile}
	return
    fi

    chmod ${mode} ${newfile}
    chown ${owner} ${newfile}
    mv ${newfile} ${oldfile}
}

#############################################################################
#
# update_prom
#
# Updates the Control Board PROM to the required version distributed in
# the SUNWsspfp package.
#
#############################################################################
update_prom()
{
    typeset name=$1

    printf "$(gettext 'Upgrading firmware on control board %s to version %s. This may take five or more minutes, please wait...')" "$name" "$PROM_CURRENT" | fmt
    rc=$(cb_prom -p ${FLASH_BOOT_FILE} -h ${name} | cut -d' ' -f3)
    print
    if [[ "${rc}" == "complete." ]]
    then
	# No need to reset the CB to make the new version active
	# This will be done when the SSP daemons are started
	printf "$(gettext 'The firmware version on %s has been successfully upgraded to %s.')" "$name" "$PROM_CURRENT" | fmt
    else
	printf "$(gettext 'The firmware upgrade procedure on %s failed. See the SSP Installatin Guide or cb_prom(1M) for details on the procedure to manually upgrade the firmware.')" "$name" | fmt
    fi
}

#############################################################################
#
# check_proms
#
# Check the Control Board PROMs to see if they need to be upgraded.  This
# can only be done from the main SSP, as the spare SSP can't ensure that
# a proper CBE that can do these checks is loaded.
#
#############################################################################
check_proms()
{
    typeset revision
    typeset name
    typeset delta

    if [[ -z "$SSP_STATION" ]]
    then
	main_or_spare
    fi

    # First we need to determine the "current" prom revision shipped with
    # this version of the SSP.
    #
    # The check below doesn't work because version 3.46 has 3.44 in the comments
    # area in the image file - must assume current version is 3.46 for SSP3.1.1
    # When we release a new version (say 3.47) in the future, the following
    # line should be uncommented out.
    #PROM_CURRENT=$(strings ${SSPOPT}/cbobjs/flash_boot.ima | grep Version | cut -d' ' -f2)

    printf "$(gettext "The required version of the control board firmware is %s. You must upgrade the firmware on your control boards if your firmware version is not %s. The control board firmware is distributed in the SUNWsspfp package.")" "$PROM_CURRENT" "$PROM_REQUIRED" | fmt

    if [[ "${SSP_STATION}" == spare ]]
    then
	print
	gettext 'Because this SSP is the spare SSP, the current version of the firmware on the control boards cannot be checked.  However, you should check this manually from the main SSP once it is running the current release of the SSP software, if you have not already done so.  This can be done by executing the commands given below. ' | fmt
	print 
	for name in $CB0_NAME $CB1_NAME
	do
	    # DO NOT TRANSLATE -- it is a command line
	    print "    % cb_prom -r -h $name"
	done
	print
	return
    fi

    # At this point, we're the main and it is safe to reboot the control
    # control boards and probe them.
    print
    gettext 'Resetting the control boards before checking firmware version...' | fmt
    print

    cb_reset $CB0_NAME $CB1_NAME

    print
    gettext 'Checking the firmware version on the control boards...' | fmt
    print

    for name in $CB0_NAME $CB1_NAME
    do
	revision=$(cb_prom -r -h ${name} | cut -d' ' -f4)

	if [[ "${revision}" == "failed;" ]]
	then
	    printf "$(gettext 'The firmware version on %s could not be determined.  Please check this manually.  See cb_prom(1M) for more information.')" "$name" | fmt
	else
	    delta=$(print "${revision} - ${PROM_REQUIRED}" | bc)

	    if [[ "$delta" == -* ]]
	    then
		# Older than required - automatic upgrade if possible
		printf "$(gettext 'The firmware version on %s (%s) is out of date and must be upgraded.')" "$name" "$revision" | fmt
		print

		# Check if the SUNWsspfp package is installed
		pkginfo -q SUNWsspfp
    		if [[ $? -ne 0 ]]
		then
		    # SUNWsspfp not installed
    		    printf "$(gettext 'The SUNWsspfp package is not installed. The ssp_upgrade tool cannot perform an upgrade of the firmware on control board %s. You must install this package so that the firmware on the control board can be updated.')" "$name" | fmt
    		    # Prompt the user if SUNWsspfp should be installed.
    		    ssp_pkgadd_fp
		fi

		# Update the prom if the user had installed SUNWsspfp
		pkginfo -q SUNWsspfp
    		if [[ $? -eq 0 ]]
		then
		    update_prom $name
		fi
	    else
		# current or newer than current - no need to upgrade
		printf "$(gettext 'The firmware version on %s (%s) is current.')" "$name" "$revision" | fmt
	    fi
	fi
    done
    print
}

#############################################################################
#
# update_emc_erc_files
#
# In SSP 3.1.1, obp_reset, cb_power_on, and cb_power_off were added to
# the edd.emc/edd.erc files. When upgrading or restoring from a backup,
# these need to be checked and added if necessary. The files that require
# checking/updating are:
# /var/opt/SUNWssp/.ssp_private/templates/Ultra-Enterprise-10000/edd.emc
#	obp_reset, cb_power_on/off
# /var/opt/SUNWssp/.ssp_private/templates/Ultra-Enterprise-10000/edd.platform.erc
#	cb_power_on/off
# /var/opt/SUNWssp/.ssp_private/templates/Ultra-Enterprise-10000/edd.domain.erc
#	obp_reset
# /var/opt/SUNWssp/etc/<platform>/edd.emc
#	obp_reset, cb_power_on/off
# /var/opt/SUNWssp/etc/<platform>/edd.erc
#	Cb_power_on/off
# /var/opt/SUNWssp/etc/<platform>/<domain>/edd.erc
#	obp_reset
#
#############################################################################
update_emc_erc_files()
{
    typeset tmpl=${SSPVAR}/.ssp_private/templates/${PLATFORM_TYPE}
    typeset edd_emc_file=${tmpl}/${EDD_EMC}
    typeset edd_platform_erc_file=${tmpl}/edd.platform.erc
    typeset domain_erc=${tmpl}/edd.domain.erc
    typeset domaindir=
    typeset p_etc=
    typeset edd_erc_file=
    typeset -i post_31_release=$1

    # Call parse_cb_config to set the PLATFORM_NAME
    parse_cb_config
    p_etc=${SSPVAR}/etc/${PLATFORM_NAME}

    if [[ ${post_31_release} -eq 1 ]]
    then
	# Check the installed edd.emc file
	if (( $(grep obp_reset ${edd_emc_file} | wc -l) < 1 ))
	then
	    ed -s ${edd_emc_file} << EOF > /dev/null
/^obpbooting
i
obp_reset : enabled		#cpu sig states indicate obp reset condition
.
/^bulk_power_norm
i
cb_power_on : enabled		#a control board has been powered on
cb_power_off : enabled		#a control board has been powered off
.
w
q
EOF
	fi

	# Check the installed edd.platform.erc file
	if (( $(grep cb_power_ ${edd_platform_erc_file} | wc -l) < 1 ))
	then
	    ed -s ${edd_platform_erc_file} << EOF > /dev/null
/^bulk_power_norm
i
cb_power_on : enabled : 0 : 1 : PowerOnact  -t %t -b %b
cb_power_off : enabled : 0 : 1 : PowerOffact  -t %t -b %b
.
w
q
EOF
	fi

	# Check the installed edd.domain.erc file
	if (( $(grep obp_reset ${domain_erc} | wc -l) < 1 ))
	then
	    ed -s ${domain_erc} << EOF > /dev/null
/^obpbooting
i
obp_reset : enabled : 300 : 3 : ObpResetact -d %d
.
w
q
EOF
	fi

	# Check the <platform>/edd.emc file
	edd_emc_file=${p_etc}/${EDD_EMC}
	if [[ -f "${edd_emc_file}" ]]
	then
	    if (( $(grep obp_reset ${edd_emc_file} | wc -l) < 1 ))
	    then
	        ed -s ${edd_emc_file} << EOF > /dev/null
/^obpbooting
i
obp_reset : enabled		#cpu sig states indicate obp reset condition
.
/^bulk_power_norm
i
cb_power_on : enabled		#a control board has been powered on
cb_power_off : enabled		#a control board has been powered off
.
w
q
EOF
	    fi
	fi

	# Check the <platform>/edd.erc file
	edd_erc_file=${p_etc}/${EDD_ERC}
	if [[ -f "${edd_erc_file}" ]]
	then
	    if (( $(grep cb_power_ ${edd_erc_file} | wc -l) < 1 ))
	    then
	        ed -s ${edd_erc_file} << EOF > /dev/null
/^bulk_power_norm
i
cb_power_on : enabled : 0 : 1 : PowerOnact  -t %t -b %b
cb_power_off : enabled : 0 : 1 : PowerOffact  -t %t -b %b
.
w
q
EOF
	    fi
        fi

	# Check each <platform>/<domain>/edd.erc file
	for domaindir in ${p_etc}/*
	do
	    domain_erc=${domaindir}/${EDD_ERC}
	    if [[ -f ${domain_erc} ]]
	    then
	        if (( $(grep obp_reset ${domain_erc} | wc -l) < 1 ))
	        then
		    ed -s ${domain_erc} << EOF > /dev/null
/^obpbooting
i
obp_reset : enabled : 300 : 3 : ObpResetact -d %d
.
w
q
EOF
	        fi
	    fi
        done
    else
	# Pre-SSP 3.1.1 - could be in restore or failover process
	# Remove 3.1.1 specific lines from the edd.emc and edd.erc files
	if (( $(grep obp_reset ${edd_emc_file} | wc -l) > 0 ))
	then
	    ed -s ${edd_emc_file} << EOF > /dev/null
/^obp_reset/d
w
q
EOF
	fi
	if (( $(grep cb_power_ ${edd_emc_file} | wc -l) > 0 ))
	then
	    ed -s ${edd_emc_file} << EOF > /dev/null
/^cb_power_on/d
/^cb_power_off/d
w
q
EOF
	fi

	# Check the installed edd.platform.erc file
	if (( $(grep cb_power_ ${edd_platform_erc_file} | wc -l) > 0 ))
	then
	    ed -s ${edd_platform_erc_file} << EOF > /dev/null
/^cb_power_on/d
/^cb_power_off/d
w
q
EOF
	fi

	# Check the edd.domain.erc file
	if (( $(grep obp_reset ${domain_erc} | wc -l) > 0 ))
	then
	    ed -s ${domain_erc} << EOF > /dev/null
/^obp_reset/d
w
q
EOF
	fi

	# Check the <platform>/edd.emc file
	edd_emc_file=${p_etc}/${EDD_EMC}
	if [[ -f "${edd_emc_file}" ]]
	then
	    if (( $(grep obp_reset ${edd_emc_file} | wc -l) > 0 ))
	    then
	        ed -s ${edd_emc_file} << EOF > /dev/null
/^obp_reset/d
/^cb_power_on/d
/^cb_power_off/d
w
q
EOF
	    fi
        fi

	# Check the <platform>/edd.erc file
	edd_erc_file=${p_etc}/${EDD_ERC}
	if [[ -f "${edd_erc_file}" ]]
	then
	    if (( $(grep cb_power_ ${edd_erc_file} | wc -l) > 0 ))
	    then
	        ed -s ${edd_erc_file} << EOF > /dev/null
/^cb_power_on/d
/^cb_power_off/d
w
q
EOF
	    fi
        fi

	# Check each <platform>/<domain>/edd.erc file
	for domaindir in ${p_etc}/*
	do
	    domain_erc=${domaindir}/${EDD_ERC}
	    if [[ -f ${domain_erc} ]]
	    then
	        if (( $(grep obp_reset ${domain_erc} | wc -l) > 0 ))
	        then
		    ed -s ${domain_erc} << EOF > /dev/null
/^obp_reset/d
w
q
EOF
	        fi
	    fi
	done
    fi
}

#############################################################################
#
# upgrade
#
# Upgrade the SSP software
#
#############################################################################
ssp_upgrade()
{
    SSP_UPGRADE=true
    CHANGE=true
    typeset package_dir=${1}
    typeset priv="${SSPVAR}/.ssp_private"
    typeset domain_config="${priv}/domain_config"
    typeset BAD_CF=
    typeset format
    typeset tmp_file=/var/tmp/ssp_tmp$$
    typeset saved_shadow=/var/tmp/shadow$$
    typeset major
    typeset minor
    typeset patch
    typeset -i post_31_release

    if [[ -z "$package_dir" ]]
    then
	usage
	exit 4
    fi
    parse_cb_config

    # cb_config file must exist
    if [[ ! -s "${CBCONFIGFILE}" ]]
    then
	printf "$(gettext "Missing %s.")\n" "${CBCONFIGFILE}"
	BAD_CF=1

    elif [[ -z "${PLATFORM_NAME}" ]]
    then
	format=$(gettext "Corrupted %s: Missing platform name.")
	printf "$format\n" "${CBCONFIGFILE}"
	BAD_CF=1

    elif [[ -z "${PLATFORM_TYPE}" ]]
    then
	format=$(gettext "Corrupted %s: Missing platform type.")
	printf "$format\n" "${CBCONFIGFILE}"
	BAD_CF=1
    fi

    # if we don't have a reasonable config, bail out now
    if [[ -n "$BAD_CF" ]]
    then
	gettext "Can not continue. Re-run ssp_config.\n"
	exit 1
    fi

    gettext "Beginning SSP upgrade..."
    print

    main_or_spare

    # disable daemons from restarting automatically (in case it's 3.0/3.1)
    remove_ssp_startup_from_inittab
    # shut down SSP software
    ssp_terminate

    # select a log file
    if [[ -d /var/sadm/system/logs ]]
    then
	log=/var/sadm/system/logs/ssp_upgrade_log
    else
	log=/var/tmp/ssp_upgrade_log
    fi
    # clear log file
    pkg_err=0
    > ${log}
    print "SSP software upgrade" >> ${log}
    date >> ${log}
    print >> ${log}

    # Set up pkgadd/pkgrm admin file
    adminfile=/tmp/ssp_upgrade_adminfile.$$
    cat > ${adminfile} << EOF
mail=
instance=overwrite
partial=nocheck
runlevel=nocheck
idepend=nocheck
rdepend=nocheck
space=quit
setuid=nocheck
conflict=nocheck
action=nocheck
basedir=default
EOF

    # Perform preupgrade if SSP 3.0 packages are installed.
    preupgrade

    # Remove SSP patches, if any
    if [[ -d /var/sadm/patch ]]
    then
	for patchdir in $(showrev -p | egrep 'SUNWssp' | \
		awk '{print $2}')
	do
		rm -fr /var/sadm/patch/$patchdir
	done
    fi

    # Check what version of SSP we are upgrading from
    # Example version format is:
    #         VERSION:  3.1.1,REV=99.04.13.19.17
    pkginfo -l SUNWsspue | grep VERSION | cut -d: -f2 | cut -d, -f1 > ${tmp_file}
    major=`cut -d. -f1 ${tmp_file}`
    minor=`cut -d. -f2 ${tmp_file}`
    patch=`cut -d. -f3 ${tmp_file}`

    # temp file no longer needed
    rm -f ${tmp_file}

    if [[ ${patch} -eq 1 || ${minor} -gt 1 ]]
    then
	post_31_release=1
    else
	post_31_release=0
    fi

    # Remove the rest of the packages
    # SUNWsspid and SUNWsspdo are new to SSP 3.1/3.1.1
    ssp_pkgrm \
	    SUNWsspdr SUNWsspid SUNWssppo SUNWsspob \
	    SUNWsspdo SUNWsspr SUNWsspst SUNWsspdf \
	    SUNWsspmn SUNWsspop

    # If upgrading from 3.0/3.1, need to save the shadow file in order to
    # preserve the ssp passwd because the 3.1 postremove (SUNWsspue)
    # removes the ssp entry in the /etc/shdow file
    if [[ ${post_31_release} -eq 0 ]]
    then
	cp /etc/shadow ${saved_shadow}
    fi

    ssp_pkgrm SUNWsspue SUNWuessp

    if [[ ${post_31_release} -eq 0 ]]
    then
	cp ${saved_shadow} /etc/shadow
	rm -f ${saved_shadow}
    fi

    # Now add the new packages
    ssp_pkgadd \
	    SUNWsspue SUNWsspop SUNWsspmn SUNWsspdf \
	    SUNWsspst SUNWsspr SUNWsspdo SUNWsspob \
	    SUNWssppo SUNWsspid SUNWsspdr

    # Install AnswerBook. It needs to be interactive.
    ssp_pkgadd_ab

    if [[ $pkg_err -eq 1 ]]
    then
	format=$(gettext "Error detected. See %s for detail.")
	printf "$format\n" "${log}"
	prompt=$(gettext "Do you want to continue?")
	if ! yes_or_no "$prompt"
	then
	    gettext "ABORTING!\n" >&2
	    exit 2
	fi
    fi

    # Update domain_config file
    save_n_copy ${domain_config} "" 640 ssp
    convert_domain_config ${domain_config} 644 ssp

    # Update control board objects 
    get_n_save_cb_config

    # create the platform-specific data link
    create_platform_link

    # create the platform configuration file
    make_platform_config

    # save the processor speed information
    save_procspeed $INTERCONNECT $PROCMULTIPLE

    if [[ "$SSP_STATION" == spare ]]
    then
	#
	# SPARE SSP
	#
	tftpboot_disable
	remove_ssp_startup_from_inittab

	# shut everything down
	ssp_terminate

	# give instruction about proms
	check_proms

	# fix for bug 4238446 - if we don't do this, old emc file from
	# a 3.0 installtion could take effect. The emc file format
	# has changed between 3.0 and 3.1/3.1.1.
	p_etc=${SSPVAR}/etc/${PLATFORM_NAME}
	tmpl=${SSPVAR}/.ssp_private/templates/${PLATFORM_TYPE}
	platform_erc=${tmpl}/edd.platform.erc
	if [[ ! -d ${p_etc} ]]
	then
	    mkdir -m 755 -p ${p_etc}
	    chown ssp ${p_etc}
	fi
	save_n_copy ${p_etc}/${EDD_ERC} ${platform_erc} 640 ssp
	save_n_copy ${p_etc}/${EDD_EMC} ${tmpl}/${EDD_EMC} 640 ssp
	# take care of domain files, too
	for domaindir in ${p_etc}/*
	do
	    if [[ -f "${domaindir}/${EDD_ERC}" ]]
	    then
		save_n_copy ${domaindir}/${EDD_ERC} ${domain_erc} 640 ssp
	    fi
	done

	# Check and update the edd.emc and edd.erc files if necessary
	# Argument 1 means we are on post-SSP 3.1
	update_emc_erc_files 1

	# cleanup and exit
	rm -f /.SSP_DEFAULTS
 
	# Remove /etc/opt/SUNWssp/snmp/*.idy and let it be rebuilt by scotty
	# when this ssp is made the main later
	rm -f ${SSPETC}/snmp/*.idy

	gettext "\nUpgrade of SPARE SSP completed.\n"
	print
	exit 0
    fi

    tftpboot_setup
    add_ssp_startup_to_inittab
    copy_data_files

    # Check and update the edd.emc and edd.erc files if necessary
    update_emc_erc_files 1

    # offer to validate the PROM versions
    check_proms
    # cleanup and exit
    rm -f /.SSP_DEFAULTS
    gettext "Upgrade of MAIN SSP completed.\n"
    print
#   gettext "Run '/etc/init.d/ssp start' to restart SSP software.\n"
#   print
}

#############################################################################
#
# configure_control_boards
#
# Only change the cb_config file
#
#############################################################################
configure_control_boards()
{
    typeset BAD_CF=
    parse_cb_config

    # cb_config file must exist
    if [[ ! -s "${CBCONFIGFILE}" ]]
    then
	printf "$(gettext "Missing %s.")\n" "${CBCONFIGFILE}"
	BAD_CF=1

    elif [[ -z "${PLATFORM_NAME}" ]]
    then
	format=$(gettext "Corrupted %s: Missing platform name.")
	printf "$format\n" "${CBCONFIGFILE}"
	BAD_CF=1

    elif [[ -z "${PLATFORM_TYPE}" ]]
    then
	format=$(gettext "Corrupted %s: Missing platform type.")
	printf "$format\n" "${CBCONFIGFILE}"
	BAD_CF=1
    fi

    # if we don't have a reasonable config, bail out now
    if [[ -n "$BAD_CF" ]]
    then
	gettext "Can not continue. Re-run ssp_config.\n"
	exit 1
    fi

    # bug#4223346: save original primary control board # 
    if [ "$P0" = "P" ]
    then
        primary=0
    else
        primary=1
    fi

    get_n_save_cb_config

    # bug#4223346: if control boards were changed, display restart reminder 
    if [[ ( (primary -eq 0) && ("$P0" != "P") ) || ( (primary -eq 1) && ("$P1" != "P") ) ]]
    then
         print
         printf "$(gettext "The primary control board has been changed.  The SSP processes")\n"
         printf "$(gettext "must be stopped and restarted.")\n"
         print
         gettext "Use the following command to stop and restart the SSP daemons:\n"
         print
         # DO NOT TRANSLATE -- it is a command line
         print "    # /etc/init.d/ssp [ stop | start ]"
         print
    fi

    exit 0
}

#############################################################################
#
# configure_spare
#
# Configure the spare SSP to act as the Main
#
#############################################################################
configure_spare()
{
    parse_cb_config
    
    print
    gettext "Beginning set up of the SPARE SSP workstation to control the host." | fmt
    print

    # get the control board config and save it
    get_n_save_cb_config

    # create the platform-specific data link
    create_platform_link

    # setup tftp
    tftpboot_setup

    # setup inittab
    add_ssp_startup_to_inittab

    #
    # Clean up and exit
    #
    rm -f /.SSP_DEFAULTS
    gettext "\nThis SPARE SSP is NOW configured to control the host.\n"
    gettext "\nThis machine is the MAIN SSP now.\n"
    print
}

#############################################################################
#
# configure_main
#
# Configure the SSP as either the main or spare SSP.  The default behavior
# of this script.  It also performs some standard initialization that
# should be run on any SSP.
#
#############################################################################
configure_main()
{
    if [[ -s "${CBCONFIGFILE}" ]]
    then
	parse_cb_config
    fi
    print
    gettext "Beginning setup of this workstation to act as a MAIN or SPARE SSP." | fmt
    print

    # we only ask for configuration if we don't have one.  if you want to
    # change the configuration anyway, use the "cb" argument.
    if [[ "$VALID_CONFIG" != true ]]
    then
	# no valid configuration, gotta ask for one
	get_n_save_cb_config

	# create the platform-specific data link
	create_platform_link

	# install platform config file, we only do this on a first run
	make_platform_config "${PLATFORM_NAME}"
    fi

    fmt=$(gettext "Are you currently configuring the MAIN SSP?")
    if ! yes_or_no "$fmt"
    then
	#
	# SPARE SSP
	#
	tftpboot_disable
	remove_ssp_startup_from_inittab
	# shut everything down
	ssp_terminate
	# cleanup and exit
	rm -f /.SSP_DEFAULTS
	gettext "\nSPARE SSP configuration completed.\n"
	print
	exit 0
    fi

    tftpboot_setup
    copy_data_files
    add_ssp_startup_to_inittab

    # cleanup and exit
    rm -f /.SSP_DEFAULTS
    gettext "\nMAIN SSP configuration completed.\n"
    print
}

#############################################################################
#
# require_args
#
# Require a specific number of arguments.
#
#############################################################################
require_args()
{
    typeset reqd=$1
    typeset actual=$2
    if [[ "$reqd" -ne "$actual" ]]
    then
	usage
	print
	fatal "$(gettext "Incorrect number arguments.")"
	exit 4
    fi
}

#############################################################################
#
# require_root
#
# Require root privileges.
#
#############################################################################
require_root()
{
    if [[ "$(getuid)" -ne 0 ]]
    then
	fatal "$(printf "$(gettext "You must be root to run %s.")" $0)"
    fi
}

#############################################################################
#
# validate_backup_args
#
# Validate that the argument to ssp_backup is a valid directory
#
#############################################################################
validate_backup_args()
{
    typeset filename_cpio=ssp_backup.cpio

    ssp_backup_filename=${1}

    if [[ -d $1 ]]
    then
	# form backup filename: <specified directory>/ssp_backup.cpio
	ssp_backup_filename=$1/${filename_cpio}
    else
	# Not directory, check if tape
	mt -f $1 status > /dev/null 2>&1
	if [[ $? -ne 0 ]]
	then
	    printf "$(gettext 'Invalid backup target specified.\nBackup file will be: /var/tmp/%s.\n')" "${filename_cpio}"
	    print
	    ssp_backup_filename=/var/tmp/${filename_cpio}
	fi
    fi
}

#############################################################################
#
# validate_restore_args
#
# Validate that the argument to ssp_restore is a valid filename
#
#############################################################################
validate_restore_args()
{
    ssp_restore_filename=${1}

    if [[ ! -f $1 ]]
    then
	# Not file, check if tape
	mt -f $1 status > /dev/null 2>&1
	if [[ $? -ne 0 ]]
	then
	    fatal "$(gettext "Invalid restore source specified\n.")"
	    print
	fi
    fi
}

#############################################################################
#
# perform_backup
#
# Generate a file list to send to cpio, which archives the files into
# the specified directory as filename ssp_backup.cpio or to the magnetic
# tape device.
#
#############################################################################
perform_backup()
{
    typeset SSPHOME=/export/home/ssp

    #
    # Set up the log file
    #
    log=${SSPVAR}/ssp_backup.out

    print "SSP files backup" > ${log}
    date >> ${log}
    print >> ${log}

   find ${SSPHOME}/.ssp_env \
	${SSPHOME}/.Xdefaults \
	${SSPHOME}/.cshrc \
	${SSPHOME}/.dtprofile \
	${SSPHOME}/.login \
	${SSPHOME}/.openwin-init \
	${SSPHOME}/.openwin-menu \
	${SSPHOME}/.openwin-menu-ssp \
	${SSPHOME}/.postrc \
	${SSPHOME}/.redxrc \
	${SSPHOME}/.xinitrc \
	${SSPHOME}/.dt/dtwmrc \
	${SSPHOME}/.dt/user.dtwmrc \
	${SSPVAR}/.ssp_private \
	${SSPVAR}/adm \
	${SSPVAR}/data \
	${SSPVAR}/etc \
	${SSPVAR}/ict \
	-print 2>> ${log} | cpio -ocv > ${ssp_backup_filename} 2>> ${log}
}

###########################################################################
#
# ssp_install
#
# Individually perform pkgadd. The advantage of doing it one at a time
# is that we could install even if a package on the list is missing.
# argument contains a list of packages to add.
#
###########################################################################
ssp_install()
{
    typeset package_dir=${1}

    if [[ -z "$package_dir" ]]
    then
	usage
	exit 4
    fi

    # select a log file
    if [[ -d /var/sadm/system/logs ]]
    then
	log=/var/sadm/system/logs/ssp_install_log
    else
	log=/var/tmp/ssp_install_log
    fi
    # clear log file
    pkg_err=0
    > ${log}
    print "SSP software install" >> ${log}
    date >> ${log}
    print >> ${log}

    # Set up pkgadd admin file
    adminfile=/tmp/ssp_install_adminfile.$$
    cat > ${adminfile} << EOF
mail=
instance=overwrite
partial=nocheck
runlevel=nocheck
idepend=nocheck
rdepend=nocheck
space=quit
setuid=nocheck
conflict=nocheck
action=nocheck
basedir=default
EOF

    # Now add the new packages
    ssp_pkgadd \
	SUNWsspue SUNWsspop SUNWsspmn SUNWsspdf \
	SUNWsspst SUNWsspr SUNWsspdo SUNWsspob \
	SUNWssppo SUNWsspid SUNWsspdr

    # Install AnswerBook. It needs to be interactive.
    ssp_pkgadd_ab

    # Install Flash PROM package. It needs to be interactive.
    ssp_pkgadd_fp

    if [[ $pkg_err -eq 1 ]]
    then
	format=$(gettext "Error detected. See %s for detail.")
	printf "$format\n" "${log}"
	exit 2
    fi
}

#############################################################################
#
# convert_domain_os_field
#
# Converts the OS version in the domain_config and domain_history files to
# reflect the format used in the SSP release.
#
# SSP 3.1 os versions are 2.5.1, 2.6, 2.7 etc while
# SSP 3.1.1 and later are 5.5.1, 5.6, 5.7 etc
#
# Parameters:
# $1 = restored_domain_file (config or history)
# $2 = post_31_release (1 if ssp3.1.1 or 3.2, 0 otherwise)
# $3 = major (x in x.y.z)
# $4 = minor (y in x.y.z)
# $5 = patch (z in x.y.z)
#
#############################################################################
convert_domain_os_field()
{
    typeset restored_domain_file=${1}
    typeset converted_file=${restored_domain_file}.converted$$
    typeset domain
    typeset platform
    typeset physical
    typeset release
    typeset idn
    typeset boardlist
    typeset -i post_31_release=${2}
    typeset major=${3}
    typeset minor=${4}
    typeset patch=${5}

    if [[ ! -f "${restored_domain_file}" ]]
    then
	# no domain config/history file, do nothing
	return
    fi

    # Empty the file to hold the converted lines
    > ${converted_file}

    while IFS=: read domain platform physical release idn boardlist
    do
	if [[ ${post_31_release} -eq 1 ]]
	then
	    # Switch from Solaris to SunOS numbering
	    if [[ "${release}" == 2.* ]]
	    then
	        release=5.${release#2.}
	    fi
	else
	    # Switch from SunOS to Solaris numbering
	    if [[ "${release}" == 5.* ]]
	    then
	        release=2.${release#5.}
	    fi
	fi
	if (( ($major > 3) || ( ($major == 3) && ($minor > 0) ) ))
	then
	    print "${domain}:${platform}:${physical}:${release}:${idn}:${boardlist}">> ${converted_file}
	else
	    print "${domain}:${platform}:${physical}:${release}:${boardlist}" >> ${converted_file}
	fi
    done < "${restored_domain_file}"

    if cmp -s "${restored_domain_file}" "${converted_file}"
    then
	# Files are the same, no release number changes
	rm -f ${converted_file}
	return
    fi

    cp ${converted_file} ${restored_domain_file}
    rm -f ${converted_file}
}

#############################################################################
#
# perform_restore
#
# Restore a backup done using ssp_backup.
#
#############################################################################
perform_restore()
{
    typeset this_ssp_name=`uname -n`
    typeset ssp_to_domain_hosts=${SSPVAR}/.ssp_private/ssp_to_domain_hosts
    typeset restored_domain_config=${SSPVAR}/.ssp_private/domain_config
    typeset restored_domain_history=${SSPVAR}/.ssp_private/domain_history
    typeset tmp_file=/var/tmp/ssp_tmp$$
    typeset old_ssp_name
    typeset major
    typeset minor
    typeset patch
    typeset -i post_31_release

    #
    # Set up the log file
    #
    log=${SSPVAR}/ssp_restore.out

    print "SSP files restore" > ${log}
    date >> ${log}
    print >> ${log}

    # Backup volatile files
    save_a_copy \
	/export/home/ssp/.Xdefaults \
	/export/home/ssp/.cshrc \
	/export/home/ssp/.dtprofile \
	/export/home/ssp/.login \
	/export/home/ssp/.openwin-init \
	/export/home/ssp/.openwin-menu \
	/export/home/ssp/.openwin-menu-ssp \
	/export/home/ssp/.postrc \
	/export/home/ssp/.redxrc \
	/export/home/ssp/.ssp_env \
	/export/home/ssp/.xinitrc \
	/export/home/ssp/.dt/dtwmrc \
	/export/home/ssp/.dt/user.dtwmrc

    cpio -icvdum < ${ssp_restore_filename} >>${log}

    # Change the SSP name in the $SSPVAR/.ssp_private/ssp_to_domain_hosts
    old_ssp_name=`cut -d' ' -f2 ${ssp_to_domain_hosts} | head -1`

    sed -e "s/ ${old_ssp_name}/ ${this_ssp_name}/g" ${ssp_to_domain_hosts} > ${tmp_file} 2>>${log}
    cp ${tmp_file} ${ssp_to_domain_hosts}
    rm -f ${tmp_file}

    # Remove /etc/opt/SUNWssp/snmp/*.idy and let it be rebuilt by scotty
    rm -f ${SSPETC}/snmp/*.idy

    # Check what version of SSP we are restoring into
    # Example version format is:
    #         VERSION:  3.1.1,REV=99.04.13.19.17
    pkginfo -l SUNWsspue | grep VERSION | cut -d: -f2 | cut -d, -f1 > ${tmp_file}
    major=`cut -d. -f1 ${tmp_file}`
    minor=`cut -d. -f2 ${tmp_file}`
    patch=`cut -d. -f3 ${tmp_file}`

    # temp file no longer needed
    rm -f ${tmp_file}

    if [[ ${patch} -eq 1 || ${minor} -gt 1 ]]
    then
	post_31_release=1

    else
	post_31_release=0
    fi

    # Check and update the edd.emc and edd.erc files if necessary
    update_emc_erc_files ${post_31_release}

    convert_domain_os_field ${restored_domain_config} ${post_31_release} ${major} ${minor} ${patch}
    convert_domain_os_field ${restored_domain_history} ${post_31_release} ${major} ${minor} ${patch}
}

#############################################################################
#
# perform_post_os_upgrade
#
# Sets up necessary files and links to work with SEA
#
#############################################################################
perform_post_os_upgrade()
{
    #
    # Set up the log file
    #
    log=${SSPVAR}/ssp_post_os_upgrade.out

    print "SSP software post_os_upgrade" > ${log}
    date >> ${log}
    print >> ${log}

    # No need to add the ssp SEA entries to /etc/inet/services
    # --alredy done when the SUNWsspr package is installed.
    #
    # Create symbolic links for Starfire's Solstice (SEA) configuration files
    #
    pkginfo -q SUNWsacom
    if [ $? -eq 0 ]
    then
	if [[ ! -h ${BASEDIR}/etc/snmp/conf/ssp_snmp.reg ]]
	then
            ln -s ${BASEDIR}/etc/opt/SUNWssp/snmp/sea/ssp_snmp.reg ${BASEDIR}/etc/snmp/conf/ssp_snmp.reg
	fi

	if [[ ! -h ${BASEDIR}/etc/snmp/conf/ssp_snmp.rsrc ]]
	then
            ln -s ${BASEDIR}/etc/opt/SUNWssp/snmp/sea/ssp_snmp.rsrc ${BASEDIR}/etc/snmp/conf/ssp_snmp.rsrc
	fi

	if [[ ! -h ${BASEDIR}/var/snmp/mib/ssp_snmp.mib ]]
	then
            ln -s ${BASEDIR}/etc/opt/SUNWssp/snmp/Ultra-Enterprise-10000.mib ${BASEDIR}/var/snmp/mib/ssp_snmp.mib
	fi
    fi
}


##
## MAIN CODE STARTS HERE
##
umask 033

if [[ -f ${ENV} ]]
then
    . ${ENV}
fi


#
# Set up the log file
#
log=${SSPVAR}/ssp_config.out

#
# Rotate the log files, we keep up to ${log}.6 around (actually 7 backups)
#
rotate_file ${log} 6

#
# Guess a subcommand based upon $0
#
subcommand=main

case "$(basename $0)" in
ssp_terminate*)
    subcommand=terminate
    ;;

ssp_configmain*)
    subcommand=main
    ;;

ssp_configspare*)
    subcommand=spare
    ;;

ssp_config?(.*))
    subcommand=main
    if (( $# >= 1 ))
    then
	subcommand=$1
	shift
    fi
    ;;

ssp_upgrade*)
    subcommand=upgrade
    ;;

ssp_install*)
    subcommand=install
    ;;

ssp_backup*)
    subcommand=backup
    ;;

ssp_restore*)
    subcommand=restore
    ;;

ssp_post_os_upgrade*)
    subcommand=post_os_upgrade
    ;;
esac


#
# Check the options
#
case "$subcommand" in

spare)
    require_args 0 $#
    require_root
    gettext "Configuring the spare SSP to control the Host\n"
    configure_spare "$@" 2>&1 | tee ${log}

    # we also should probably start the stuff up
    if (( $(ps -ef | egrep ssp_startup | grep -v grep | wc -l) < 1 ))
    then
        /etc/init.d/ssp start
    fi
    ;;

cb)
    require_args 0 $#
    require_root
    gettext "Configuring control boards\n"
    configure_control_boards "$@" 2>&1 | tee ${log}
    ;;

cpu)
    require_args 0 $#
    require_root
    gettext "Configuring processors\n"
    configure_processors "$@" 2>&1 | tee ${log}
    ;;

terminate)
    require_args 0 $#
    ssp_terminate "$@"
    ;;

sysidssp)
    require_args 0 $#
    require_root
    configure_main "$@" 2>&1 | tee ${log}
    ;;

main)
    require_args 0 $#
    require_root
    configure_main "$@" 2>&1 | tee ${log}

    # we also should probably start the stuff up
    main_or_spare
    if [[ "${SSP_STATION}" == main ]]
    then
	if (( $(ps -ef | egrep ssp_startup | grep -v grep | wc -l) < 1 ))
	then
	    /etc/init.d/ssp start
	fi
    fi
    ;;

upgrade)
    require_args 1 $#
    require_root
    ssp_upgrade "$@"
    ;;

prom)
    require_args 0 $#
    require_root
    parse_cb_config
    check_proms
    ;;

install*)
    require_args 1 $#
    require_root
    ssp_install "$@"
    ;;

backup*)
    require_args 1 $#
    require_root
    validate_backup_args "$@"
    perform_backup
    ;;

restore*)
    require_args 1 $#
    require_root
    validate_restore_args "$@"
    perform_restore
    ;;

post_os_upgrade*)
    require_args 0 $#
    require_root
    perform_post_os_upgrade
    ;;

*)
    usage
    exit 4
    ;;
esac
