#!/bin/ksh
#<! IBM_PROLOG_BEGIN_TAG 
#<! This is an automatically generated prolog. 
#<!  
#<! bos72Q src/bos/usr/sbin/bootpkg/bootpkg.sh 1.15.8.2 
#<!  
#<! Licensed Materials - Property of IBM 
#<!  
#<! Restricted Materials of IBM 
#<!  
#<! COPYRIGHT International Business Machines Corp. 2004,2019 
#<! All Rights Reserved 
#<!  
#<! US Government Users Restricted Rights - Use, duplication or 
#<! disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#<!  
#<! IBM_PROLOG_END_TAG 


#commands
BIN=/usr/bin
SBIN=/usr/sbin
SAVEVG=$BIN/savevg
RM=$BIN/rm
GREP=$BIN/grep
MKDIR=$BIN/mkdir
DSPMSG=$BIN/dspmsg
CAT=$BIN/cat
RESTORE="$SBIN/restore -xqf"
OSLEVEL_R="$BIN/oslevel -r"
CUT=$BIN/cut
AWK=$BIN/awk
TAR=$BIN/tar
SED=$BIN/sed
XARGS=$BIN/xargs
LN=$BIN/ln
EGREP=$BIN/egrep
UNMOUNT=$SBIN/umount
BOSBOOT=$SBIN/bosboot
MOUNT=$SBIN/mount
CHROOT=$SBIN/chroot
MV=$BIN/mv
SLEEP=$BIN/sleep
CP=$BIN/cp
FILE=$BIN/file
LS=$BIN/ls
FIND=$BIN/find
DF=$BIN/df
TAIL=$BIN/tail

#constants
BOOTPKG_LIBROOT=/usr/lib/bootpkg
mspot_list=$BOOTPKG_LIBROOT/bootpkg_list
INST_ROOT="./lpp/bos/inst_root"
NIM_CHROOT_LIBS_LINKS_BASE=/usr/lib/._spot_libs_links_@_$RANDOM
NIM_CHROOT_LIBS_LINKS1=${NIM_CHROOT_LIBS_LINKS_BASE}/usr/ccs/lib
NIM_CHROOT_LIBS_LINKS2=${NIM_CHROOT_LIBS_LINKS_BASE}/usr/lib
NIM_CHROOT_LIBS_BASE=/usr/lib/._spot_libs_@_71438
NIM_CHROOT_LIBS1=${NIM_CHROOT_LIBS_BASE}/usr/ccs/lib
NIM_CHROOT_LIBS2=${NIM_CHROOT_LIBS_BASE}/usr/lib
SET_CHROOT_LIBPATH="export LIBPATH=${NIM_CHROOT_LIBS_LINKS1}:${NIM_CHROOT_LIBS_LINKS2}:${NIM_CHROOT_LIBS1}:${NIM_CHROOT_LIBS2}:/usr/ccs/lib:/usr/lib"
DISK_DEV=/dev/hdisk0
TAPE_DEV=/dev/rmt0
CD_DEV=/dev/cd
ENT_DEV=/dev/ent0
FILE_LIST="/usr/ccs/lib/libnim.a.min /usr/lib/boot/network/rc.dd_boot /usr/lib/boot/network/link_meth /usr/lib/boot/network/rc.bos_inst /usr/lib/boot/network/rc.diag /usr/lib/boot/network/link_methods"


#message file
#CATFILE=cmdinstl_e.cat
CATFILE=cmdnim.cat
SET=22
DEFAULT_MSG='processing error encountered\n'

#globals
MAX_MNT=20
access_pnt=
DATA=
this_list=
tar_file=
location=
device=
mounts=
index=
bi_name=
rc=0
new_location=
TMPDIR=
ERR=
mksysb_ver=

#----------------------------    bootpkg_init    --------------------------------
#
# NAME: bootpkg_init
#
# FUNCTION:
#		initialize variables, create temporary files and directories
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#		
#

# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#		parameters:
#			none
#		global:
#			ERR		=	temp file that will contain error output of commands
#			TMPDIR	=	temp directory for bootpkg
#
# RETURNS: (int)
#		0							= success
#		
#
# OUTPUT:
#-------------------------------------------------------------------------------

function bootpkg_init
{

	TMPDIR=$(/usr/lib/instl/libinst_mkworkdir) || err_from_cmd libinst_workdir
	ERR=$TMPDIR/bootpkg.err

	#touch error log
	>$ERR
}

#----------------------------    cleanup    --------------------------------
#
# NAME: cleanup
#
# FUNCTION:
#		delete temporary files, unmount file systems
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#	handler for signal 'zero' - called when we exit
#		
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#		parameters:
#			none
#		global:
#			mounts		=	list of mounted file systems
#			TMPDIR		=	temporary directory for bootpkg
#			DATA		=	temporary directory that contains contents of the tar archive
#			location_mnt=	directory that will contain the boot package
#
# RETURNS: (int)
#		0							= success
#		
#
# OUTPUT:
#-------------------------------------------------------------------------------
function cleanup
{
	if [[ $unmounted != "yes" ]]
	then
		unmount_chroot_libs
	
		let unmount_retries=10
		while [[ -n ${mounts} ]] && (( unmount_retries > 0 ))
		do
			unmount_dir all 2>/dev/null
			if [[ -n ${mounts} ]] 
			then
				let unmount_retries=unmount_retries-1
				${SLEEP} 1
			fi
		done
		[[ -n ${mounts} ]] && unmount_dir all force

		#only unmount once
		unmounted="yes"
	fi

	cd /tmp
	[[ -d $DATA ]] && [[ $1 != "mounts" ]] && $RM -rf $DATA >/dev/null 2>&1

	[[ $1 = "mounts" ]] && return 0

	#cd into a safe directory
	cd /tmp
	$RM -rf $TMPDIR >/dev/null 2>&1

	[[ $rc != "0" && $new_location = "yes" ]] && $RM -rf $location_mnt >/dev/null 2>&1
	[[ $took_mksysb = "yes" && $nim_resources = "yes" ]] && $RM -f $FILE_LIST >/dev/null 2>&1
}

#----------------------------    err_signal    --------------------------------
#
# NAME: err_signal
#
# FUNCTION:
#		exits if a signal is received- which calls cleanup
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#		
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#		parameters:
#			
#		global:
#			
#	
#
# OUTPUT:
#-------------------------------------------------------------------------------
function err_signal
{
	rc=99
	exit $rc
}

#----------------------------    error    --------------------------------
#
# NAME: error
#
# FUNCTION:
#		set rc, exit- which calls cleanup
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#		calls error on failure
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#		parameters:
#			
#		global:
#
# OUTPUT:
#-------------------------------------------------------------------------------
function error
{
	rc=$1
	case "$rc" in
	13 ) echo "\nBackup device or file name must be an absolute path." >&2 ;;
	esac
	exit $rc
}

#----------------------------   err_from_cmd     --------------------------------
#
# NAME: err_from_cmd
#
# FUNCTION:
#		displays error output of a failed command, exits
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#		parameters:
#			
#		global:
#			ERR	=	contains the error output of failed commands
#
# RETURNS: (int)
#		0							= success
#		
#
# OUTPUT:
#-------------------------------------------------------------------------------
function err_from_cmd
{
	typeset err_fs=$($DF -P $ERR | $TAIL -1 | $AWK '{print $6}')
	typeset -i err_fs_free_space=$($DF $err_fs | $TAIL -1 | $AWK '{print $3}')
	if [[ ! -s $ERR && $err_fs_free_space -eq 0 ]]; then
		if [[ -n $1 ]]; then
			echo "An error occurred with the $1 command. The $err_fs filesystem is filled up. Unable to display the stderr of the $1 command." >&2
		else
			# Should never get here, since all calls within this file send the name of the failing command as a parameter.
			# Just in case...
			echo "An error occurred. The $err_fs filesystem is filled up. Unable to display the stderr of the failing command." >&2
		fi
	fi

	$CAT $ERR >&2
	error 20
}

#----------------------------   warning_from_cmd    --------------------------------
#
# NAME: warning_from_cmd
#
# FUNCTION:
#		displays error output of a failed command without exiting
#
# DATA STRUCTURES:
#		parameters:
#			
#		global:
#			ERR	=	contains the error output of failed commands
#
# OUTPUT:
#-------------------------------------------------------------------------------
function warning_from_cmd
{
	$CAT $ERR >&2
}

#----------------------------   check_input     --------------------------------
#
# NAME: check_input
#
# FUNCTION:
#		validate input to bootpkg
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#		calls error on failure
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#		parameters:
#			
#		global:
#			nim_resources		=	produce a tarball of NIM installation resources?
#			bi_only				=	only produce boot image?
#			location			=	where to put the image/tarball
#			device				=	device for which boot image will be created
#			bosinst_data		=	NIM installation resource
#			resolv_conf			=	NIM installation resource
#			cust_script			=	NIM installation resource
#
# RETURNS: (int)
#		0							= success
#		
#
# OUTPUT:
#-------------------------------------------------------------------------------
function check_input
{
	#N and O are mutually exclusive, b, r, and c only make sense with N
	[[ $nim_resources = "yes" && $bi_only = "yes" ]] && error 1 #ERROR
	[[ $bosinst_data = "yes" || $resolv_conf  = "yes" || $cust_script = "yes" ]] && [[ $nim_resources != "yes" ]] && error 2 #ERROR

	#location and device are required, device  must be "ent", "disk", "tape", or "cd"
	[[ -z $location ]] && error 3 #ERROR
	[[ -z $device ]] && error 4 #ERROR
	[[ $device = "ent" || $device = "disk" || $device = "tape" || $device = "cd" ]] || error 5 #ERROR

	[[ $nim_resources = "yes" && $device != "ent" ]] && error 11

	[[ $nim_resources != "yes" && $no_tar = "yes" ]] && error 12

	[[ $location != ?*:?* ]] && [[ $location != /* ]] && no_abs="yes"
	[[ -n $mksysb ]] && [[ $mksysb != ?*:?* ]] && [[ $mksysb != /?* ]] && no_abs="yes"
	[[ -n $bosinst_data ]] && [[ $bosinst_data != ?*:?* ]] && [[ $bosinst_data != /?* ]] && no_abs="yes"
	[[ -n $resolv_conf ]] && [[ $resolv_conf != ?*:?* ]] && [[ $resolv_conf != /?* ]] && no_abs="yes"
	[[ -n $cust_script ]] && [[ $cust_script != ?*:?* ]] && [[ $cust_script != /?* ]] && no_abs="yes"

	[[ $no_abs = "yes" ]] && error 13

	#set the device to pass to bootpkg
	case $device in
		ent) device_param=$ENT_DEV ;;
		tape) device_param=$TAPE_DEV ;;
		disk) device_param=$DISK_DEV ;;
		cd) device_param=$CD_DEV ;;
	esac
}

#---------------------------- mount_dir         --------------------------------
#
# NAME: mount_dir 
#
# FUNCTION:
#		mounts the specified "object" over the specified local mount point; when
#			no local mount points are specified, this function will create one
#		"object"s may be on of the following:
#			1) local directory
#			2) remote directory (in the form of "host:dir")
#			3) local CDROM
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#		calls error on failure
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#		parameters:
#			1				= object to mount
#			2				= local mount point (optional)
#		global:
#			access_pnt			= set to local access point
#			mounts				= list of mounts performed by mount_dir
#			disable_cdumount		= if cdrom is already mounted by cdromd, don't cdumount
#
# RETURNS: (int)
#		0					= success; local mount pnt returned via access_pnt
#
# OUTPUT:
#-------------------------------------------------------------------------------
function mount_dir {

	typeset object=${1}
	typeset -i i=0
	typeset mnt_params=""
	typeset access_pnt_inode=""
	typeset automount_flag=""

	# NOTE that access_pnt is a global, not a local variable
	access_pnt=${2:-""}

	[[ -z "${object}" ]] && return 0

	# check for unnecessary mounts
	if [[ ${object} != ?*:?* ]] && \
		[[ ${object} != /dev/cd[0-9]* ]] && \
		[[ -z "${access_pnt}" ]]
	then
		# object is local directory and no specific mount point requested
		# therefore, no reason to mount it - return current path
		access_pnt=${object}
		return 0
	fi

	# need a local mount point?
	if [[ -z "${access_pnt}" ]]
	then
		# going to create a tmp directory in TMPDIR with a prefix of "mnt"
		# look for lowest, unused seqno
		while (( ${i} < ${MAX_MNT} ))
		do
			access_pnt=${TMPDIR}/mnt${i}
			[[ ! -d ${access_pnt} ]] && break
			let i=i+1
		done
		(( ${i} >= ${MAX_MNT} )) && error 6
	fi

	# need to create the local mount point?
	if [[ ! -r ${access_pnt} ]]
	then

		# yes - doesn't already exist
		${MKDIR} ${access_pnt} 2>${ERR} || err_from_cmd ${MKDIR}

		# get the inode of this directory.  This way when we attempt
		# to remove it later we know we are removing the same directory.
		access_pnt_inode=`${LS} -i -d ${access_pnt} 2>/dev/null | ${AWK} '{print ":"$1}'`
	fi

	# mount the "object" (either local CDROM, remote dir, or local dir)
	case ${object} in

		/dev/cd[0-9]*)	# CDROM
                        # check if the device is manage by the cdromd
                        ${CDCHECK} -aq ${object} 2>/dev/null 1>&2

			# If cdromd is running and we chroot to do a spot copy, cdromd will
			# not be detected in the chroot environment.  We use AUTOMOUNT_DISABLE_FLAG to 
			# disable all cd automount calls.
			# AUTOMOUNT_DISABLE_FLAG is set by c_instspot.c
            if [[ $? -eq 0 ]] && [[ $AUTOMOUNT_DISABLE_FLAG != "true" ]]
			then                                          			 # cdrom is managed by cdromd
                                automount_flag="true"
                                ${CDCHECK} -mq ${object} 2>/dev/null 1>&2                #check if cdrom is mounted
                                if [[ $? -eq 0 ]]; then
                                        disable_cdumount="true"
                                        access_pnt=`${CDCHECK} -mq ${object} 2>/dev/null`
                                else
                                        if ${CDMOUNT} -q ${object} 2>${ERR}              #mount the cdrom
                                        then
                                                access_pnt=`${CDCHECK} -mq ${object} 2>/dev/null` # get its mount point
                                        else
                                                warning_from_cmd ${CDMOUNT}
                                                err_from_cmd ${CDMOUNT}
                                        fi
                                fi

                        else
                                mnt_params="-r -vcdrfs"
                        fi
                        ;;

		?*:?*)			# remote dir
			mnt_params="-ohard,intr -vnfs"
			;;

		*)	;;			# local dir
	esac

        # if cdromd is not running, run the mount command
	if [[ $automount_flag != "true" ]]; then

		# if mount_opts is set, lets try them
		# if the mount fails, try removing the mount_opts
		if ${MOUNT} ${mnt_params} ${mount_opts} ${object} ${access_pnt} 2>${ERR}
		then
			:
		else
			warning_from_cmd ${MOUNT}
			${MOUNT} ${mnt_params} ${object} ${access_pnt} 2>${ERR} || \
				err_from_cmd ${MOUNT}
		fi
	fi

	# remember that we've got something mounted
	# NOTE that we're pushing this onto a stack - it is important that we do
	#		the unmounts in reverse order
	mounts="${object}:${access_pnt} ${mounts}"

} # end of mount_dir

#---------------------------- unmount_dir       --------------------------------
#
# NAME: unmount_dir
#
# FUNCTION:
#		unmounts anything which has been mounted by mount_dir
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#		calls error on failure
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#		parameters:
#			1						= either the keyword "all" or local mount pnt
#		global:
#			mounts				= list of mounts performed by mount_dir
#
# RETURNS: (int)
#		0							= success
#		1							= failure
#
# OUTPUT:
#-------------------------------------------------------------------------------
function unmount_dir {

	typeset dir=${1:-all}
	typeset force=${2}
	typeset i=""
	typeset mnt_pnt=""
	typeset tmp=""

	# cd to neutral dir
	if cd /tmp 2>${ERR}
	then
		:
	else
		warning_from_cmd cd
		return 1
	fi

	# look for the specified <dir>
	for i in ${mounts}
	do
		# separate stanza
		mnt_pnt=${i##*:}

		# this the one we're looking for?
		if [[ ${dir} = ${mnt_pnt} ]] || [[ ${dir} = all ]]
		then

			# unmount it, but first perform a sync and an slibclean to make
			# sure that nothing in the mount is still thought to be busy.
			${SYNC}
			${SLIBCLEAN}
			# If unmounting libraries that we set up for a chroot
			# environment, reset the libpath to make sure that
			# the mount will succeed.
			if [[ ${mnt_pnt} = *${NIM_CHROOT_LIBS1} ]] || 
			   [[ ${mnt_pnt} = *${NIM_CHROOT_LIBS2} ]]
			then
				${UNSET_CHROOT_LIBPATH}
			fi


                        # check if the device is manage by the cdromd
                        object=${i%%:*}
                        ${CDCHECK} -aq ${object} 2>/dev/null 1>&2
                        if [[ $? -eq 0 ]] && [[ $AUTOMOUNT_DISABLE_FLAG != "true" ]]
                        then                                                               # cdrom is managed by cdromd
                                ${CDCHECK} -mq ${object} 2>/dev/null 1>&2                  # check if cdrom is mounted
                                if [[ $? -eq 0 ]] && [[ $disable_cdumount != "true" ]];
                                then
                                        if ! ${CDUMOUNT} ${object} 1> /dev/null 2>${ERR}
                                        then
                                                warning_from_cmd ${CDUMOUNT}
                                                tmp="${i} ${tmp}"
                                        fi

                                fi
                        else
                                if [[ -n ${force} ]]
                                then

                                        # We were told to force unmount this directory.
                                        # Try to unmount without the force first.
                                        ${UNMOUNT} ${mnt_pnt} > /dev/null 2>&1
                                        if [[ $? -ne 0 ]]
                                        then
                                                if ! ${UNMOUNT} -f ${mnt_pnt} 1> /dev/null 2>${ERR}
                                                then
                                                        warning_from_cmd ${UNMOUNT}
                                                        tmp="${i} ${tmp}"
                                                fi
                                        fi
                                else
                                        if ! ${UNMOUNT} ${mnt_pnt} 2>${ERR}
                                        then
                                                warning_from_cmd ${UNMOUNT}
                                                tmp="${i} ${tmp}"
                                        fi
                                fi
                        fi
                else

			# not unmounting this dir - add it back to the list
			tmp="${i} ${tmp}"

		fi
	done

	# new list reflects the mounts that are still active
	mounts=${tmp}

} # end of unmount_dir

#----------------------------    mount_paths    --------------------------------
#
# NAME: 
#
# FUNCTION:
#		
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#		calls error on failure
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#		parameters:
#			
#		global:
#			location			=	where to put the image/tarball
#			device				=	device for which boot image will be created
#			bosinst_data		=	NIM installation resource
#			resolv_conf			=	NIM installation resource
#			cust_script			=	NIM installation resource
#			*_mnt				=	mount point of the above listed paths
#			took_mksysb			=	was mksysb of this system taken?
#
# RETURNS: (int)
#		0							= success
#		
#
# OUTPUT:
#-------------------------------------------------------------------------------
function mount_paths
{
	#first check if location is supposed to be created- if not, mount it
	if [[ ! -d $location && $location != ?*:?* ]]
	then
		$MKDIR -p $location >$ERR 2>&1 || err_from_cmd mkdir
		location_mnt=$location
		new_location="yes"
	else
		mount_dir $location
		location_mnt=$access_pnt
	fi

	#check each path provided, if nfs-mountable- mount it
	#mksysb
	if [[ $took_mksysb != "yes" ]]
	then
		mount_dir $mksysb
		mksysb_mnt=$access_pnt
	fi

	#bosinst_data
	if [[ -n $bosinst_data ]]
	then
		mount_dir $bosinst_data
		bosinst_data_mnt=$access_pnt
	elif [[ $nim_resources = "yes" ]]
	then
		[[ -f "/var/adm/ras/bosinst.data" ]] && bosinst_data="/var/adm/ras/bosinst.data"
	fi

	#cust- this one has no default value
	if [[ -n $cust_script ]]
	then
		mount_dir $cust_script
		cust_script_mnt=$access_pnt
	fi

	#resolv_conf
	if [[ -n $resolv_conf ]]
	then
		mount_dir $resolv_conf
		resolv_conf_mnt=$access_pnt
	elif [[ $nim_resources = "yes" ]]
	then
		[[ -f "/etc/resolv.conf" ]] && resolv_conf="/etc/resolv.conf"
	fi

	#create data directory inside of location
	DATA=$location_mnt/data_$$
	$MKDIR $DATA >$ERR 2>&1 || err_from_cmd mkdir
}

#----------------------------   get_newest_ver      --------------------------------
#
# NAME: get_newest_ver
#
# FUNCTION:
#		Given a version number in VRMF, and a list of versions in VRMF,
#		output the latest version in the list that is <= the given version
#		number
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#		calls error on failure
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#		parameters: file with list of VRMFs
#			    a version in VRMF
#		global:
#
# RETURNS: (int)
#		0							= success
#
# OUTPUT: a VRMF version number
#-------------------------------------------------------------------------------
function get_newest_ver
{
	typeset VERSION_FILE=$1
	typeset MYVER=$2
	typeset -i10 sver=0 srel=0 smod=0 sfix=0
	typeset -i10 this_ver=0 this_rel=0 this_mod=0 this_fix=0
	typeset final LINE

	[[ -f $VERSION_FILE ]] || error $ERR_FILE_MODE "open" $VERSION_FILE

	sver=`echo $MYVER | $CUT -d '.' -f 1` || err_from_cmd cut
	srel=`echo $MYVER | $CUT -d '.' -f 2` || err_from_cmd cut
	smod=`echo $MYVER | $CUT -d '.' -f 3` || err_from_cmd cut
	sfix=`echo $MYVER | $CUT -d '.' -f 4` || err_from_cmd cut

	while read LINE
	do
		if [[ $MYVER = $LINE ]]
		then
			final=$MYVER
			break
		fi

		this_ver=`echo $LINE | $CUT -d '.' -f 1` || err_from_cmd cut
		this_rel=`echo $LINE | $CUT -d '.' -f 2` || err_from_cmd cut
		this_mod=`echo $LINE | $CUT -d '.' -f 3` || err_from_cmd cut
		this_fix=`echo $LINE | $CUT -d '.' -f 4` || err_from_cmd cut
	
		if [[ $sver -gt $this_ver ]]
		then
			final=$LINE
		elif [[ $sver -eq $this_ver && $srel -gt $this_rel ]]
		then
			final=$LINE
		elif [[ $sver -eq $this_ver && $srel -eq $this_rel && $smod -gt $this_mod ]]
		then
			final=$LINE
		elif [[ $sver -eq $this_ver && $srel -eq $this_rel && $smod -eq $this_mod && $sfix -gt $this_fix ]]
		then
			final=$LINE
		fi		

	done <$VERSION_FILE

	echo $final
}

#----------------------------    prep_mksysb      --------------------------------
#
# NAME: prep_mksysb
#
# FUNCTION:
#		when the source is a mksysb, mounts resources and prepares variables
#		to later execute mksysb_SPOT
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#		calls error on failure
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#		parameters:
#		global:
#
# RETURNS: (int)
#		0							= success
#
# OUTPUT:
#-------------------------------------------------------------------------------
function prep_list
{
	typeset ver_list tar_list ls_list tf

	# get the version/release/mod levels from the mksysb and locate the appropriate SPOT list
	cd $DATA
	$RESTORE $mksysb_mnt ./image.data >$ERR 2>&1 || err_from_cmd restore
	mksysb_ver=$($GREP "OSLEVEL=" ./image.data 2>/dev/null | $CUT -d ' ' -f 2)
	$RM -f ./image.data >$ERR 2>&1 || err_from_cmd rm

	this_list=$TMPDIR/list
	ver_list=$TMPDIR/ver_list
	tar_list=$TMPDIR/tar_list
	ls_list=$TMPDIR/ls_list
	tf=$TMPDIR/tmp_file
	
	# get the right list from the SPOT list file
	$EGREP '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:' $mspot_list >$tf || err_from_cmd egrep
	$SED 's/://g' $tf >$ver_list || err_from_cmd sed
	final=$(get_newest_ver $ver_list $mksysb_ver) || err_from_cmd get_newest_var

	${AWK} -vver=$final 'BEGIN{this=0} /.*:$/ {this=0;if ($1 == ver ":") {this=1;next}} {if (this == 1 && NF > 0) print;}' $mspot_list > $this_list 2> $ERR || err_from_cmd awk

	# now find the right tar file (for the libnim.a.min)
	$LS /usr/lib/bootpkg/*-spotpkg.tar >$ls_list || err_from_cmd ls
	$AWK '{gsub("/usr/lib/bootpkg/", "", $0);gsub("-spotpkg.tar", "", $0); print}' $ls_list >$tar_list || err_from_cmd awk
	final=$(get_newest_ver $tar_list $mksysb_ver) || err_from_cmd get_newest_var
	tar_file=${BOOTPKG_LIBROOT}/${final}-spotpkg.tar

	#if the list is empty, error out
	[[ ! -s $this_list ]] && error 7 #${ERR_NO_LIST}

	#create the SPOT directory
	$MKDIR -p $DATA/SPOT >$ERR 2>&1 || err_from_cmd mkdir
}

#----------------------------     restore_symlinks     --------------------------------
#
# NAME: restore_symlinks
#
# FUNCTION:
#		Given a symlink and a backup file, this function will restore the file
#		linked to by the symbolic link and will continually follow successive
#		symlinks restored until a regular file is restored.
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#		makes recursive calls
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#		parameters: relative path of symlink
#			    path to backup file
#			    boolean recursive value
#		global:
#
# RETURNS: (int)
#		0							= success
#
# OUTPUT:
#-------------------------------------------------------------------------------
function restore_symlinks
{
        SYMLINK=$1
        BACKUP_NAME=$2
        ONE_MORE=$3

	#restore the actual file
        $RESTORE $BACKUP_NAME $SYMLINK > /dev/null 2> ${ERR} || err_from_cmd restore

	#base case is that the current file is not a symlink
        if [[ $ONE_MORE = "0" ]]
        then
		#progress is made by following whatever is linked to next
                NEW_LINK=$($LS -l $SYMLINK | $AWK '{print $11}') 

		#stop the recursion if the current file is not a symlink
                [[ -h $SYMLINK ]] || ONE_MORE=1 
                [[ $ONE_MORE = "0" ]] && restore_symlinks ".$NEW_LINK" $BACKUP_NAME $ONE_MORE
        fi
} #end restore_symlinks

#----------------------------     mksysb_SPOT     --------------------------------
#
# NAME: mksysb_SPOT
#
# FUNCTION:
#		Extracts necessary files from the source mksysb based on the SPOT lists and 
#		the .proto files contained on the mksysb
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#	
#
# RECOVERY OPERATION:
#		calls error function
#
# DATA STRUCTURES:
#		parameters: mksysb path, spot path, list file path, lpp_source mount point
#		global:
#
# RETURNS: (int)
#		0							= success
#
# OUTPUT:
#-------------------------------------------------------------------------------
function mksysb_SPOT
{
        MKSYSB=$1
        SPOTDIR=$2
        LISTFILE=$3
        PKG=$4
        TEMP1=$TMPDIR/$$.ong
        TEMP2=$TMPDIR/$$.tuk
        TEMP11=$TMPDIR/$$.ong.sym
        TEMP22=$TMPDIR/$$.tuk.sym
        TEMP111=$TMPDIR/$$.ong.sorted
        TEMP222=$TMPDIR/$$.tuk.sorted
        NEW_ROOT=$SPOTDIR/usr/lpp/bos/inst_root
        RESTORE_CMD="$SBIN/restore -xqf"


        no_proto=
        no_file=

        #determine which protofile to use from the device variable
        if [[ $device = "ent" ]]
        then
                PROTO_LIST=./usr/lib/boot/network/chrp.${device}.proto
        else
                PROTO_LIST=./usr/lib/boot/chrp.${device}.proto
        fi

        #we'll need the disk proto file for atm boot images
        PROTO_LIST="$PROTO_LIST ./usr/lib/boot/chrp.disk.proto"

        $GREP /usr/lpp/bos/inst_root $LISTFILE | $SED 's/\/usr\/lpp\/bos\/inst_root//' > $TEMP2
        $GREP -v /usr/lpp/bos/inst_root $LISTFILE > $TEMP1

        cd $SPOTDIR
        /usr/sbin/restore -xqdf $MKSYSB ./usr/bin/tee ./usr/lib/methods ./usr/lib/drivers ./usr/lib/microcode ./usr/lpp/bosinst/iscsi ./usr/lib/boot/network/*.proto ./usr/lib/boot/*.proto ./usr/lib/boot/protoext/* ./usr/lib/boot/unix ./usr/lib/boot/unix* ./usr/lpp/bosinst/BosMenus ./usr/lpp/bosinst/tape/tapefiles1 >> /tmp/restore.list 2> ${ERR} || err_from_cmd restore

        # Ensure relevant directories are created prior to extracting files.
        # This is a safety measure to prevent umask 077 issues occurring with
        # tar extractions "losing root ruid/euid". Root cause/resolution of
        # that issue does not negate this safety measure.
        for temp_dir in `$TAR -tvf $tar_file | $AWK '{print $NF}' | $AWK 'BEGIN {FS=OFS="/"} {$NF=""; NF--; print}' | /usr/bin/uniq`
        do
                $MKDIR -p $temp_dir
        done

        #untar the contents of the bos.sysmgt.nim.spot for this version
        $TAR -xf $tar_file 2>$ERR >> /tmp/restore.list || err_from_cmd tar

        if [[ $device = "tape" ]]
        then
                #move tapefiles1 to same location (directory) that
                #tape boot image is placed.
                $MV ./usr/lpp/bosinst/tape/tapefiles1 $location >$ERR 2>&1 || err_from_cmd mv
        fi

        #call parse_proto on each .proto file extracted
        for i in $PROTO_LIST
	do
		if [[ -f $SPOTDIR/$i ]]
                then
                        #get the name of the boot device this proto file is for
                        dev=$(echo ${i##*/} | $AWK -F. '{print $2}')

                        #grab all the files needed in the /usr part of the SPOT
                        # (they are the 6th field in the proto file, if we're looking at a regular file)
                        $AWK '{if (length($6) > 0 && $2 == "----" && substr($6, 1, 4) == "/usr"){print "."$6}}' $SPOTDIR/$i >>$TEMP1 2>${ERR} || err_from_cmd awk
                        $AWK '{if (length($6) > 0 && $2 == "----" && substr($6, 1, 4) == "/usr"){print "."$6}}' $SPOTDIR/$i >>$TEMP11 2>${ERR} || err_from_cmd awk

                        #grab all the files needed in the root part of the SPOT (same rules as above)
                        $AWK '{if (length($6) > 0 && $2 == "----" && substr($6, 1, 4) != "/usr"){print "."$6}}' $SPOTDIR/$i >>$TEMP2 2>${ERR} || err_from_cmd awk
                        $AWK '{if (length($6) > 0 && $2 == "----" && substr($6, 1, 4) != "/usr"){print "."$6}}' $SPOTDIR/$i >>$TEMP22 2>${ERR} || err_from_cmd awk

                        #add all files listed in this device's protoext files (there's only /usr files in there)
                        $AWK '{if (length($6) > 0){print "."$6}}' $SPOTDIR/usr/lib/boot/protoext/${dev}.proto.ext.* >>$TEMP1 2>${ERR} || err_from_cmd awk
                        $AWK '{if (length($6) > 0){print "."$6}}' $SPOTDIR/usr/lib/boot/protoext/${dev}.proto.ext.* >>$TEMP11 2>${ERR} || err_from_cmd awk

                        #Some protoext files may refer to symbolic links even though it is not noted in the file
                        #we still have to track down these links and restore them. This will be done through the
                        #calls to restore_symlinks below.

                else
                        no_proto=1
                fi
        done

        #first restore all proto files and all protoext files, then restore the /usr file system of the SPOT

        #restore /usr part and then / part
        sort $TEMP1 > $TEMP111
        [[ -s $TEMP1 ]] && ${XARGS} ${RESTORE} $MKSYSB < $TEMP111 >> /tmp/restore.list 2> ${ERR} || err_from_cmd restore
        #in /usr part, if a proto file is a symlink, restore the file(s) it links to
        # also, warn if proto files are missing
        for i in $($CAT $TEMP11)
            do
            [[ ! -e $i ]] && no_file=1 #check for missing files
            [[ -h $i ]] && restore_symlinks $i $MKSYSB 0
            done

        #do the same for root part
        #restore the inst_root part of the SPOT
        $MKDIR -p $NEW_ROOT >/dev/null 2>${ERR} || err_from_cmd mkdir
        $MKDIR -p $NEW_ROOT/var/adm/nim > /dev/null 2>&1
        $LN -fs $SPOTDIR/usr/bin $NEW_ROOT/bin >/dev/null 2>${ERR} || err_from_cmd ln
        $LN -fs $SPOTDIR/usr/lib $NEW_ROOT/lib >/dev/null 2>${ERR} || err_from_cmd ln
        cd $NEW_ROOT >/dev/null 2>${ERR} || err_from_cmd cd

        cat << END_HELP >> $TEMP2
./etc/objrepos/Cu*
./etc/objrepos/Pd*
./sbin/helpers/*
./sbin/helpers/*/*
END_HELP
        sort $TEMP2 > $TEMP222
        [[ -s $TEMP2 ]] && ${XARGS} ${RESTORE_CMD} $MKSYSB < $TEMP222 >> /tmp/restore.list 2> ${ERR} || err_from_cmd restore

        for i in $($CAT $TEMP22)
            do
            [[ ! -e $i ]] && no_file=1 #check for missing files
            [[ -h $i ]] && restore_symlinks $i $MKSYSB 0
            done

        $RM $TEMP1 $TEMP2 $TEMP11 $TEMP22 $TEMP111 $TEMP222 2>&1 > /dev/null

        #restore the symlinks in inst_root
        $LN -fs /usr/bin $NEW_ROOT/bin >/dev/null 2>${ERR} || err_from_cmd ln
        $LN -fs /usr/lib $NEW_ROOT/lib >/dev/null 2>${ERR} || err_from_cmd ln

}

#---------------------------- get_nfs_exp --------------------------------------
#
# NAME: get_nfs_exp
#
# FUNCTION:
#        Checks whether the file system is remote or local if the file system is
#        remote file system then spot location is to be substitued with node
#        name and it's path.
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#        calls error on failure
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#        parameters: spotlocation
#        global:
#
# RETURNS: (char)
#      spotlocation              = success
#
# OUTPUT:
#-------------------------------------------------------------------------------
function get_nfs_exp
{
    typeset ERROR='eval echo error in get_nfs_exp >&2 ; $RM -f $TF1 $TF2; return 1'
    typeset DIR=$1
    typeset TF1=/tmp/tf1.$$
    typeset TF2=/tmp/tf2.$$
    typeset HOST  MNT_PT FS_NAME JUNK
    typeset HIT=""
    typeset DIR_NFS

    $RM -f $TF1 $TF2

    IS_NFS=$($FIND $DIR -prune -fstype nfs) || $ERROR

    if [[ -n $IS_NFS ]]; then
        $MOUNT > $TF1 || $ERROR
        $AWK '$4~/(^nfs*)/{print}' $TF1 > $TF2 || $ERROR

        while read HOST MNT_PT FS_NAME JUNK ; do
            if [[ ${DIR#${FS_NAME}} != ${DIR} ]]; then
                if [[ ${#HIT} -lt ${#FS_NAME} ]]; then
                    HIT=${FS_NAME}
                    DIR_NFS="$HOST:$MNT_PT"${DIR#$HIT}
                fi
            fi

        done < $TF2

        [[ -z $HIT ]] && $ERROR

        echo $DIR_NFS
    else
        echo $DIR
    fi

    $RM -f $TF1 $TF2
}


#---------------------------- setup_chroot_env  --------------------------------
#
# NAME: setup_chroot_env
#
# FUNCTION:
#		mounts the appropriate dirs in order to setup a chroot environment
#			within a SPOT
#		this kind of environment is required because we use installp to install
#			software into a SPOT, but it doesn't understand any pathnames other
#			than "/" and "/usr"
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#		calls error on failure
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#		parameters:
#			1						= optional; when present, it is the pathname of the
#											inst_root directory to use
#		global:
#			location				= SPOT pathname
#			new_root				= pathname of new root (where we'll chroot to)
#			chroot				= command to execute in order to chroot
#
# RETURNS: (int)
#		0							= success
#
# OUTPUT:
#-------------------------------------------------------------------------------
function setup_chroot_env {

        typeset ERROR='eval echo error in setup_chroot_env >&2'
	typeset root_sync=""
	typeset inr=""
	typeset inr_path=""
	typeset inr_ln=""
	typeset spot_fs=""
	typeset spot_fs_path=""
	typeset first_dir=""
	typeset dir_created=""
	typeset first_dir_inode=""
	typeset spot_location="$DATA/SPOT/usr"

	# initialize pathnames for the inst_root directory
	# this directory will become the root ("/") directory after we chroot
	if [[ -n "${1}" ]]
	then

		root_sync=TRUE
		inr=${1}
		inr_path=${inr}${inr%/*}
		inr_ln=${inr}${inr}

	else

		inr="${spot_location}/${INST_ROOT}"
		inr_path=${inr}/lpp/bos
		inr_ln=${inr_path}/inst_root

	fi

	# initialize pathnames for the SPOT's filesystem which will be created in
	#		the inst_root
	spot_fs=${spot_location}
	[[ -n "${spot_fs%/*}" ]] && \
		spot_fs_path=${inr}${spot_fs%/*} || \
		spot_fs_path=""

	# make sure SPOT exists
	[[ ! -d ${spot_location} ]] && error 8 #${ERR_DIR_DNE} spot ${spot_location}
	[[ ! -d ${spot_location}/${INST_ROOT} ]] && \
		error 9 #${ERR_DIR_DNE} inst_root "${spot_location}/${INST_ROOT}"

	# is this a non-/usr SPOT or are we going to root-sync a client?
	if [[ ${spot_location} != /usr ]] || [[ -n "${root_sync}" ]]
	then
	
		# not a /usr SPOT (or a root-sync), so we've got some things to do
		# we've got to construct an environment which we can chroot into in before
		#		calling installp because installp only knows how to install into
		#		the /usr filesystem
		new_root=${inr}

		# make sure no previous mounts have been left dangling
		${UNMOUNT} ${new_root}/usr >/dev/null 2>&1
		${UNMOUNT} ${new_root}/tmp >/dev/null 2>&1
		${UNMOUNT} ${new_root}/tftpboot >/dev/null 2>&1
		${UNMOUNT} ${new_root}/images >/dev/null 2>&1
		${UNMOUNT} ${new_root}/opt >/dev/null 2>&1
		${UNMOUNT} ${new_root}/dev >/dev/null 2>&1
		${UNMOUNT} ${new_root}${NIM_CHROOT_LIBS1} >/dev/null 2>&1
		${UNMOUNT} ${new_root}${NIM_CHROOT_LIBS2} >/dev/null 2>&1

		# create subdir in the root which corresponds to the filesystem
		#		where the root resides
		if [[ ! -d ${inr_path} ]]
		then
			$MKDIR -p $inr_path >$ERR 2>&1 || err_from_cmd mkdir
		fi
		if [[ ${inr_ln} != / ]]
		then

			# make sure no previous links have been left around
			${RM} -rf ${inr_ln} >/dev/null 2>&1

			# create sym link (to fake out the filesystem)
			${LN} -s / ${inr_ln} 2>${ERR} || err_from_cmd ${LN}
			tmp_files="${inr_ln} ${tmp_files}"
		fi


		# create subdir in the inst_root which corresponds to the filesystem
		#		where the SPOT resides
		if [[ -n "${spot_fs_path}" ]] && [[ ! -d ${spot_fs_path} ]]
		then
			$MKDIR -p ${spot_fs_path} >$ERR 2>&1 || err_from_cmd mkdir
		fi
		if [[ ${spot_fs} != /usr ]]
		then

			# make sure no previous links have been left around
			${RM} -rf ${inr}${spot_fs} >/dev/null 2>&1

			# create sym links (to fake out the filesystem)
			${LN} -s / ${inr}${spot_fs} 2>${ERR} || err_from_cmd ${LN}
			tmp_files="${inr}${spot_fs} ${tmp_files}"

		fi

                # mount the SPOT over the new_root /usr directory
                spot_location_nfs=$(get_nfs_exp $spot_location) || $ERROR
                mount_dir $spot_location_nfs $new_root/usr || $ERROR
 
		# mount the server's /tmp over the new_root /tmp directory
		mount_dir /tmp ${new_root}/tmp

		# mount the server's /dev over the new_root /dev directory
		mount_dir /dev ${new_root}/dev

		# initialize the chroot syntax
		chroot="${CHROOT} ${new_root}"

		# For a non-/usr SPOT, always make sure the server's libraries 
		# are available to the chroot'd environment since we'll be 
		# running the server's kernel when processing the SPOT.
		# Create the mount point for SPOTs that were defined prior
		# to 4.2.0
		if [[ ${location} != /usr ]]
		then
			[[ ! -d ${new_root}${NIM_CHROOT_LIBS1} ]] && \
				${MKDIR} -p ${new_root}${NIM_CHROOT_LIBS1}
			mount_dir /usr/ccs/lib ${new_root}${NIM_CHROOT_LIBS1}

			[[ ! -d ${new_root}${NIM_CHROOT_LIBS2} ]] && \
				${MKDIR} -p ${new_root}${NIM_CHROOT_LIBS2}
			mount_dir /usr/lib ${new_root}${NIM_CHROOT_LIBS2}

			# We now have our system's /usr/ccs/lib and /usr/lib mounted within
			# our spot which we'll use in our LIBPATH instead of the spot's
			# /usr/ccs/lib and /usr/lib in the chroot environment. However,
			# these mounted directories still contain symbolic links to
			# /usr/ccs/lib and /usr/lib which resolve to the spot's
			# /usr/ccs/lib and /usr/lib in the chroot environment. Therefore we
			# need to create two new directories which contain these same links
			# except have them point to our mounted directories and also have
			# them take precedence in our LIBPATH.

			# iterate through the two library directories we've overmounted
			for lib in /usr/ccs/lib /usr/lib
			do
				# create directory hierarchy to hold symbolic links
				for dir in `$FIND $lib -type d`
				do
					[[ ! -d ${new_root}${NIM_CHROOT_LIBS_LINKS_BASE}${dir} ]] && \
						$MKDIR -p ${new_root}${NIM_CHROOT_LIBS_LINKS_BASE}${dir}
				done

				# create symbolic links
				#  'linkFrom' is the pathname to an existing symbolic link
				#  'linkTo' is the pathname 'linkFrom' points to
				for linkFrom in `$FIND $lib -type l`
				do
					linkTo=`$LS -l $linkFrom | $AWK '{print $11}'`
					echo $linkTo | $EGREP '^(/usr/ccs/lib|/usr/lib)' > /dev/null 2>&1 && \
					[[ ! -e ${new_root}${NIM_CHROOT_LIBS_LINKS_BASE}${linkFrom} ]] && \
					$LN -s ${NIM_CHROOT_LIBS_BASE}${linkTo} ${new_root}${NIM_CHROOT_LIBS_LINKS_BASE}${linkFrom}
				done
			done

		fi

	else
	
		# /usr SPOT
		new_root=""
		chroot=""

	fi

} # end of setup_chroot_env

function unmount_chroot_libs {
	
	mnt_pnt=""
	found_mnt=""
	lib=""
	
	# Nothing to do if working with a /usr SPOT since we didn't mount
	# the libraries in the first place.
	[[ ${location} = /usr ]] && return 0

	# Look for the mounted libraries in the mount table.  Then look through
	# the mount list if it appears we need to unmount the libraries.
	${MOUNT} | ${EGREP} -q "(${NIM_CHROOT_LIBS1}|${NIM_CHROOT_LIBS2})"

	if [[ $? -eq 0 ]]
	then
		for i in ${mounts}
		do
			# separate stanza
			mnt_pnt=${i##*:}

			# is this one of the 2 we're looking for?
			if [[ ${mnt_pnt} = *${NIM_CHROOT_LIBS1} ]]
			then

				unmount_dir ${mnt_pnt} force
				found_mnt=${mnt_pnt}
				lib=${NIM_CHROOT_LIBS1}

			elif [[ ${mnt_pnt} = *${NIM_CHROOT_LIBS2} ]]
			then
				unmount_dir ${mnt_pnt} force
				found_mnt=${mnt_pnt}
				lib=${NIM_CHROOT_LIBS2}
			fi
		done
	fi

	# If we found a mount point above, unmount the SPOT from the chroot
	# environment.   This may also need force unmounting because we force 
	# unmounted the libraries which were mounted in the SPOT's subdirs.
	if [[ -n ${found_mnt} ]]
	then
		# Get the SPOT mount point by stripping off the end of the
		# library's mount point (matching the library location in the
		# chroot environment), then adding /usr back on.

		mnt_pnt=${found_mnt%%${lib}}/usr
		unmount_dir ${mnt_pnt} force
	fi

	# remove temporary LIBPATH links directores for chroot environment
	# (see setup_chroot_env function)
	[[ -d ${location}${NIM_CHROOT_LIBS_LINKS_BASE#/usr} ]] && \
		$RM -rf ${location}${NIM_CHROOT_LIBS_LINKS_BASE#/usr}

	return 0
}

#----------------------------    build_nim_resources    --------------------------------
#
# NAME: build_nim_resources
#
# FUNCTION:
#		create the tarball of NIM resources
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#		calls error on failure
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#		parameters:
#			none
#		global:
#			location_mnt		=	mount point where to put the image/tarball
#			bosinst_data		=	NIM installation resource
#			resolv_conf			=	NIM installation resource
#			cust_script			=	NIM installation resource
#			index				=	file that tells the filenames of NIM resources in the tarball
#			bi_name				=	name of boot image
#			took_mksysb			=	was mksysb of this system taken?
#
# RETURNS: (int)
#		0							= success
#		
#
# OUTPUT:
#-------------------------------------------------------------------------------
function build_nim_resources
{
	index=$DATA/index

	#touch the index file
	>$index

	#add the SPOT to the index
	echo "spot:./SPOT" >>$index

	#add the boot image to the index
	echo "boot:./$bi_name" >>$index

	#try to hard-link the mksysb file (time-saver), else just copy it over (and get yourself a cup of coffee)
	if [[ $took_mksysb != "yes" ]] 
	then
		$LN $mksysb_mnt $DATA/${mksysb_mnt##*/} >/dev/null 2>&1 || $CP $mksysb_mnt $DATA/
	fi
	echo "mksysb:./${mksysb_mnt##*/}" >>$index

	>$ERR

	if [[ -n $gen_bosinst_data ]]
	then
		$CAT >$DATA/bosinst.data <<__END__
    CONSOLE = Default
    INSTALL_METHOD = overwrite
    PROMPT = no
    EXISTING_SYSTEM_OVERWRITE = yes
    INSTALL_X_IF_ADAPTER = yes
    RUN_STARTUP = no
    RM_INST_ROOTS = no
    ERROR_EXIT =
    CUSTOMIZATION_FILE =
    TCB = no
    INSTALL_TYPE =
    BUNDLES =
    RECOVER_DEVICES = Default
    BOSINST_DEBUG = no
    ACCEPT_LICENSES = yes
    DESKTOP = CDE
    INSTALL_DEVICES_AND_UPDATES = yes
    IMPORT_USER_VGS =
    ENABLE_64BIT_KERNEL = Default
    CREATE_JFS2_FS = Default
    ALL_DEVICES_KERNELS = yes
    GRAPHICS_BUNDLE = yes
    MOZILLA_BUNDLE = no
    KERBEROS_5_BUNDLE = no
    SERVER_BUNDLE = no
    REMOVE_JAVA_118 = no
    HARDWARE_DUMP = yes
    ADD_CDE = no
    ADD_GNOME = no
    ADD_KDE = no
    ERASE_ITERATIONS = 0
    ERASE_PATTERNS =

target_disk_data:
    LOCATION =
    SIZE_MB =
    HDISKNAME =

locale:
    BOSINST_LANG =
    CULTURAL_CONVENTION =
    MESSAGES =
    KEYBOARD =
__END__
	elif [[ -n $bosinst_data_mnt ]] 
	then
		$CP $bosinst_data_mnt $DATA/ >$ERR 2>&1 && echo "bosinst_data:./${bosinst_data_mnt##*/}" >>$index
	fi

	[[ -n $resolv_conf_mnt ]] && $CP $resolv_conf_mnt $DATA/ >$ERR 2>&1 && echo "resolv_conf:./${resolv_conf_mnt##*/}" >>$index
	[[ -n $cust_script_mnt ]] && $CP $cust_script_mnt $DATA/ >$ERR 2>&1 && echo "cust_script:./${cust_script_mnt##*/}" >>$index

	[[ -s $ERR ]] && err_from_cmd cp

	#unmount stuff from the SPOT so that we don't try to tar up /dev/* and stuff
	cleanup "mounts"

	#remount location (since it was unmounted above)
	mount_dir $location
	location_mnt=$access_pnt

	#reset DATA with the new mount point
	DATA=${location_mnt}/data_$$

	if [[ $no_tar = "yes" ]]
	then
		$MV $DATA/* $location_mnt/
	else
		(
			cd $DATA
			$TAR -cf $location_mnt/nim_resources.tar ./* 2>$ERR >/dev/null
		) || err_from_cmd tar
	fi

	cd /tmp
	$RM -rf $DATA >/dev/null 2>&1
	unmount_dir $location_mnt force
}


# main

#signals
trap cleanup 0
trap err_signal 1 2 11 15

#initialization
bootpkg_init

while getopts :l:d:m:ONb:r:c:f:TB c
do
	case $c in
		l) location=$OPTARG ;;
		
		d) device=$OPTARG ;;

		m) mksysb=$OPTARG ;;

		f) mksysb_flags=$OPTARG ;;

		N) nim_resources="yes" ;;

		O) bi_only="yes" ;;

		b) bosinst_data=$OPTARG ;;

		r) resolv_conf=$OPTARG ;;

		c) cust_script=$OPTARG ;;

		T) no_tar="yes" ;;

		B) gen_bosinst_data="yes" ;;

		*) error 14 ;;

	esac
done

check_input

mount_paths

if [[ -n $mksysb ]]
then
	#check if the file is a mksysb, error out if not
	LANG=C $FILE $mksysb_mnt 2>/dev/null | $GREP "backup\/restore" >/dev/null 2>&1 || error 10
else
	#call mksysb and take a mksysb of this system
	mksysb_mnt=$DATA/`$OSLEVEL_R`"_mksysb"
	${SAVEVG} -X -e -i -f $mksysb_mnt ${mksysb_flags} rootvg >$ERR 2>&1 || err_from_cmd savevg
	took_mksysb="yes"
fi

#step 1 : set up the spot lists depending on the mksysb's version
prep_list

#step 2 : call mksysb_SPOT to extract the SPOT
if [[ $took_mksysb = "yes" && $nim_resources = "yes" ]] || [[ $took_mksysb != "yes" ]]
then
	mksysb_SPOT $mksysb_mnt $DATA/SPOT $this_list
fi

bi_name=${device}.bi

	if [[ ${mksysb_ver%%\.*} -ge 6 ]]
	then
		KERNEL="-k /usr/lib/boot/unix_64"
	elif [[ -f $DATA/SPOT/usr/lib/boot/unix_mp ]]
	then
		KERNEL="-k /usr/lib/boot/unix_mp"
	else
		KERNEL="-k /usr/lib/boot/unix_up"
	fi

if [[ $took_mksysb != "yes" ]]
then
	#step 3 : set up the chroot environment
	setup_chroot_env

	# Now use the libraries in the chroot environment
	${SET_CHROOT_LIBPATH}

	#step 4 : chroot into the SPOT and call bosboot
	cmd="$BOSBOOT -ad $device_param $KERNEL -b /tmp/$bi_name"
	$chroot $cmd >$ERR 2>&1 || err_from_cmd bosboot

	#put the boot image in location
	$MV /tmp/$bi_name $DATA/ >$ERR 2>&1 || err_from_cmd mv

	#if called for boot images only, copy it into location, then nothing more to do
	if [[ $bi_only = "yes" ]]
	then
		$CP $DATA/$bi_name $location_mnt/ >$ERR 2>&1 || err_from_cmd cp
		exit 0
	fi
else
	if [[ $device = "ent" ]]
	then
		(
			cd /
			$TAR -xf $tar_file >$ERR 2>&1
		) || err_from_cmd tar
	fi

	#just call bosboot- no need to chroot
	$BOSBOOT -ad $device_param $KERNEL -b $DATA/$bi_name >$ERR 2>&1 || err_from_cmd bosboot
fi

#now that we have the boot images, check for nim resources provided, and other stuff
#create the .tar package based on the input received from the command line.
[[ $nim_resources = "yes" ]] && build_nim_resources

#get around the savevg problem- make sure it works with savevg