#!/bin/ksh
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# bos72Q src/bos/usr/lib/nim/methods/c_mk_lpp_source.sh 1.23.5.6 
#  
# Licensed Materials - Property of IBM 
#  
# COPYRIGHT International Business Machines Corp. 1993,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 
# @(#)68        1.23.5.6  src/bos/usr/lib/nim/methods/c_mk_lpp_source.sh, cmdnim, bos72Q, q2019_17A6 4/16/19 09:24:13
#
#   COMPONENT_NAME: CMDNIM
#
#   FUNCTIONS: ./usr/lib/nim/methods/c_mk_lpp_source.sh
#
#   ORIGINS: 27
#
#
#   (C) COPYRIGHT International Business Machines Corp. 1993
#   All Rights Reserved
#   Licensed Materials - Property of IBM
#   US Government Users Restricted Rights - Use, duplication or
#   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
#

# include common NIM shell defines/functions
NIMPATH=${0%/*}
NIMPATH=${NIMPATH%/*}
[[ ${NIMPATH} = ${0} ]] && NIMPATH=/usr/lpp/bos.sysmgt/nim
NIM_METHODS="${NIMPATH}/methods"
. ${NIM_METHODS}/c_sh_lib

#---------------------------- local defines     --------------------------------

#---------------------------- module globals    --------------------------------
REQUIRED_ATTRS="location"
OPTIONAL_ATTRS="source packages arch mount_opts recover force use_source_simages"
location=""
source=""
packages=""
arch=""
recover=""
typeset -i max_options=0
missing=""
src_access=""
M_flag=""
gencopy_cmd=""
geninstall_cmd=""

print_info=""   #tells whether to print diagnostic info
                   #while creating an lpp_source resource
ATTR_OUT_FILE="/tmp/c_mk_lpp_source-attr_out"
TEMP_SCRIPT="/tmp/nimver.sh"
mklpp_53=""
force=""

#---------------------------- prep_source       --------------------------------
#
# NAME: prep_source
#
# FUNCTION:
#		prepares the source of the LPP images for use
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#		calls error on failure
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#		parameters:
#			source				= source of LPP images
#		global:
#			access_pnt			= local access point
#
# RETURNS: (int)
#		0							= success
#
# OUTPUT:
#-------------------------------------------------------------------------------
function prep_source {

	typeset source=${1}

	# what kind of source?
	case ${source} in

		 /dev/usbms+([0-9])) 
			nim_mount ${source} 
			[[ ! -d "${access_pnt}${OFFSET_FOR_CDROM}" ]] && \
				src_access=${access_pnt}${OFFSET_FOR_CDROM_OLD} || \
				src_access=${access_pnt}

			lvl_type="rte"
			[[ ! -e "${access_pnt}/${BOS_PATH_ON_CDROM}" ]] && \
				BOS_PATH_ON_CDROM=${BOS_PATH_ON_CDROM_OLD}
			lvl_source="${access_pnt}/${BOS_PATH_ON_CDROM}"
			lvl_arch=${arch}

		;; 

		/dev/cd+([0-9]))
			# source is CDROM; mount it
			nim_mount ${source}
			[[ ! -d "${access_pnt}${OFFSET_FOR_CDROM}" ]] && \
				src_access=${access_pnt}${OFFSET_FOR_CDROM_OLD} || \
				src_access=${access_pnt}

			lvl_type="rte"
			[[ ! -e "${access_pnt}/${BOS_PATH_ON_CDROM}" ]] && \
				BOS_PATH_ON_CDROM=${BOS_PATH_ON_CDROM_OLD}
			lvl_source="${access_pnt}/${BOS_PATH_ON_CDROM}"
			lvl_arch=${arch}
		;;

		/dev/rmt+([0-9]))
			# source is tape; nothing to do because installp will handle block size
			src_access=${source}

			lvl_type="device"
			lvl_source=${source}
			lvl_arch=${arch}
		;;

		*)
			# assume source is a directory or iso image pathname
			# make sure we've got local access
			nim_mount ${source}
			src_access=${access_pnt}

			lvl_type="rte"
			if [[ -e "${access_pnt}/installp/ppc/bos" ]] || \
			   [ -e "${access_pnt}/installp/ppc/bos.usr."* ] ; then
				lvl_source="${access_pnt}/installp/ppc/bos"
			else
				lvl_source="${access_pnt}/bos"
			fi
			lvl_arch=${arch}
		;;

	esac

} # end of prep_source

#---------------------------- check_for_bos     --------------------------------
#
# NAME: check_for_bos
#
# FUNCTION:
#		checks for a BOS runtime image and renames the file if necessary
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#		calls error on failure
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#		parameters:
#			location				= location of lpp_source
#		global:
#
# RETURNS: (int)
#		0							= success
#		1							= failure
#
# OUTPUT:
#-------------------------------------------------------------------------------
function check_for_bos {

	typeset location=${1}
	typeset i=""
	typeset change_name=""
	typeset bos_arch=""
	typeset mac_arch=""
	typeset fs_info=""

	#look for new "bos" offset - 5.1 release
	[[ -d "${location}/installp/ppc" ]] && \
			ppc_location="${location}/installp/ppc"

	# is "location" a local directory?
	if ${C_STAT} -a location=${location} -a vfstype="0 3" -a no_error_msg="yes" 2>/dev/null
	then

		# does "arch" have a value for BFFCREATE? If not, then
		# we should check the server arch
		if [[ -n ${arch} ]]
		then
		
			[[ ${arch} = ia64 ]] &&
				bos_arch=".I*"
		else

			mac_arch=`get_mac_arch`
			[[ -z ${mac_arch} ]] && error ${ERR_SOURCE} mac_arch

			[[ ${mac_arch} = ia64 ]] &&
				bos_arch=".I*"
		fi

		# is there a BOS runtime which was created by BFFCREATE? (it
		#		gives the file a weird name)
		for i in $( ${LS} ${ppc_location:-${location}}/bos.usr*${bos_arch} 2>/dev/null )
		do

			# make sure we rename the correct file
			if [[ -n ${bos_arch} ]]
			then
				# rename the file
				${MV} ${i} ${ppc_location:-${location}}/bos 2>${ERR} || err_from_cmd ${MV}
				change_name="true"

				break
			else
				if [[ ${i} = *bos.usr!(*.I*) ]]
				then
					# rename the file
					${MV} ${i} ${ppc_location:-${location}}/bos 2>${ERR} || err_from_cmd ${MV}
					change_name="true"

					break
				fi
			fi
		done

		# remove any other of BOS runtime files left around (we only want
		#		one "bos" file in an lpp_source)
		for i in $( ${LS} ${ppc_location:-${location}}/bos.usr* 2>/dev/null )
		do

			${RM} ${i} 2>${ERR} || warning_from_cmd ${RM}
			change_name="true"

		done

		# now, update the TOC so the new name is used from now on
		[[ -n ${change_name} ]] && ${RM} ${ppc_location:-${location}}/.toc 2>/dev/null 1>&2
		if [[ ! -f ${ppc_location:-${location}}/.toc ]] 
		then
			# test for inutoc space requirement
			fs_info=`LANG=C ${DF} -m ${ppc_location:-${location}} | ${AWK} '(NR==2){print $3":"$7}'`

			if (( ${fs_info%:*} < 5 )); then
				${CHFS} -a size=+5M ${fs_info#*:} || err_from_cmd ${CHFS}
			fi

			${INUTOC} ${ppc_location:-${location}} 2>${ERR} || err_from_cmd ${INUTOC}
		fi

	fi

	# is "location" a local directory, remote directory, or CDROM?
	# Note: Include NFS v3,v4 and automount in the check
	if ${C_STAT} -a location=${ppc_location:-${location}} -a vfstype="0 2 3 5 18 19 34 35" -a no_error_msg="yes" 2>/dev/null
	then

      # is there a BOS runtime image present?
      if [[ -f ${ppc_location:-${location}}/bos ]]
      then

         # add it to the options list
         # include the I so that when check_options checks for REQUIRED_SIMAGES,
         # it determines the bos image to be an install image, not an update
         print "bos bos.rte I" >>${TMPDIR}/options.list

      fi

	fi
} # end of check_for_bos

#---------------------------- list_options      --------------------------------
#
# NAME: list_options
#
# FUNCTION:
#		generates a list of LPPs which reside on the specified device
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#		calls error on failure
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#		parameters:
#			1						= source of LPP images
#			2						= non-NULL if list is just going to be displayed
#		global:
#
# RETURNS: (int)
#		0							= list of LPPs generated
#		1							= do options exist on <device> or unable to gen list
#
# OUTPUT:
#-------------------------------------------------------------------------------
function list_options {

	typeset source=${1}
	typeset list_only=${2}
	typeset -i retries=10
	typeset rc=

	# generate a list of product names
	# NOTE that INUSERVERS is an environment variable which effects the behavior
	#		of installp.  When set, it causes installp to bypass looking in the
	#		/etc/niminfo file for the NIM_USR_SPOT variable, which is used to
	#		prevent users from executing installp from the command line on machines
	#		whose /usr filesystem has been converted into a SPOT
	export INUSERVERS=yes

	# if geninstall returns 99, then it was unable to obtain the lock. 
	# Instead of erroring out, retry a few times.
	while [[ $retries -ne 0 ]]
	do
		${geninstall_cmd:-$INSTALLP} ${arch:+-I "$M_flag"} -d ${source} \
			 -L </dev/null >${TMPDIR}/installp.L 2>${ERR}
		rc=$?
		if [[ $rc = 99 ]]; then
			retries=$(( retries - 1 ))
		else
			break
		fi
	done
	[[ $rc != 0 ]] && err_from_cmd ${INSTALLP} || >${ERR}

	# return if the list is empty
	[[ ! -s ${TMPDIR}/installp.L ]] && return 1

	# filter out extraneous info
	# include the fifth field, the image type, so that when check_options 
	# checks for REQUIRED_SIMAGES, it only looks at install images, not updates
 	${AWK} 'BEGIN { FS=":" } /:/ {print $1 " " $2 " " $5}' ${TMPDIR}/installp.L \
			>${TMPDIR}/options.list 2>${ERR} || err_from_cmd ${AWK}

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

	# check for the BOS runtime image
	check_for_bos ${source}

	# display the list of available options
	${AWK} 'END{ for (i=1; i<=p; i++) \
						{	print packs[i,0]; \
							for (j=2; j<=packs[i,1]; j++) \
								print "\t" packs[i,j]; \
						}} \
				{ for( i=1; i<=p; i++) \
						if ($1 == packs[i,0]) break; \
					if (i > p){ packs[i,0] = $1; packs[i,1] = 1; p=i;} \
					packs[i,1] = packs[i,1] + 1; \
					packs[i, packs[i,1] ] = $2;}' ${TMPDIR}/options.list

	exit 0

} # end of list_options

#---------------------------- check_options     ------------------------------
#
# NAME: check_options 
#
# FUNCTION:
#		checks to see if there are any requested options which are not present
#			on the specified source device
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#		calls error on failure
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#		parameters:
#			1						= source of option images
#			2						= list of options to check
#		global:
#			max_options			= max number of options
#			option_names		= array of option names
#			ere					= array of extended regular expressions for options
#			missing				= list of missing option names
#
# RETURNS: (int)
#		0							= success - all requested options are present
#		1							= failure - one or more options missing
#
# OUTPUT:
#-------------------------------------------------------------------------------
function check_options {

	typeset source=${1}
	typeset options="${2}"
	typeset i=
	typeset name=
	typeset -i j=1
	typeset put_bos_back_in=""
	typeset MKSPOT_PRE_I="_SPOT._.pre_i.usr.1.0.0.0"
	typeset MKSPOT_POST_I="_SPOT._.post_i.usr.1.0.0.0"
	typeset ck_req_simages=

	# reset the list of "missing" options
	missing=""

	# if we are checking for required simages, set a variable so that
	# later on we ensure the images are install images, not update images
	[[ ${options} = ${REQUIRED_SIMAGES} ]] && ck_req_simages=yes

	if [[ ${source} != /dev/* ]]
	then

		# check for the BOS runtime image
		check_for_bos ${source}

	elif	[[ ${options} = **([ 	])bos+([ 	])* ]]
	then

		# take "bos" out of the list
		options=$(print ${options} | ${AWK} '{gsub(/[ 	]*bos[ 	]/," ");print}')
		put_bos_back_in=TRUE

	elif [[ ${options} = **([ 	])bos ]]
	then

		# take "bos" out of the list
		options=${options%bos}
		put_bos_back_in=TRUE

	fi

	# first, we transform the option list into extended regular expressions
	let max_options=0
	for i in ${options}
	do
		let max_options=max_options+1

		option_names[max_options]=${i}

		# does package name have any keywords in it?
		if [[ ${i} = ?*.any ]]
		then

			# protect any periods
			name=$(  echo ${i} | ${AWK} '{gsub(/\./,"\\.");print}' )

			# "<name>.any" means match everything up to ".any", but no deeper (ie,
			#		don't match on "<name>.something.somethingelse"
			ere[max_options]=$(  echo ${name} | \
										${AWK} '{gsub(/\\\.any$/,"\\.[^. ]+ ");print}' )

		elif [[ ${i} = ?*.all.?* ]]
		then

			# protect any periods
			name=$(  echo ${i} | ${AWK} '{gsub(/\./,"\\.");print}' )

			# ".all." indicates that the wildcard exists in the middle of a name
			ere[max_options]=$(  echo ${name} | \
										${AWK} '{gsub(/\\\.all\\\./,"\\.[^. ]+\\.");\
													print}' )

		else

			if [[ ${i} = ?*.all!(.*) ]]
			then

				# remove the word "all"
				option_names[max_options]=${i%.all}

				# replace ".all" with the appropriate ere
				name=${i}
				name=$(  echo ${name} | ${AWK} '{gsub(/\.all$/,"\\..+");print}' )

				# protect any periods
				tmp=$(   echo ${option_names[max_options]} | \
							${AWK} '{gsub(/\./,"\\.");print}' )

				# "<name>.all" means match on:
				#		1) just <name>
				#		2) <name>.anything
				ere[max_options]="(^${tmp} )|(^${tmp}\.[^. ]+ )|( ${name}$)"

			else
				
				# no keywords used: match on the name explicitly
				ere[max_options]="(^${option_names[max_options]} )"


				# protect any periods
				ere[max_options]=$(  echo ${ere[max_options]} | \
											${AWK} '{gsub(/\./,"\\.");print}' )
                # for libc++.rte
				# protect any plus signs
				ere[max_options]=$(  echo ${ere[max_options]} | \
											${AWK} '{gsub(/\+/,"\\+");print}' )
			fi
		fi
	done

	# now, look for missing options & generate a list of package names
	>${TMPDIR}/packages
	while (( j<=max_options ))
	do

		if [[ -n ${ck_req_simages} ]]; then 
		  # if checking REQUIRED_SIMAGES, ensure the packages are install images
		  package=$(${EGREP} "${ere[j]}" ${TMPDIR}/options.list 2>/dev/null | \
		            ${AWK} 'END{for (i in names) print names[i]}; \
		            {if (!($1 in names) && $3 == "I") names[$1]=$1}' 2>/dev/null)
		else 
		  package=$(${EGREP} "${ere[j]}" ${TMPDIR}/options.list 2>/dev/null | \
		            ${AWK} 'END{for (i in names) print names[i]}; \
		            {if (!($1 in names)) names[$1]=$1}' 2>/dev/null)
		fi

		if [[ -n "${package}" ]] && [[ ${package} != "all" ]]
		then

			for i in ${package}
			do

				# add package name to the list
				${EGREP} "^${i}$" ${TMPDIR}/packages >/dev/null 2>&1 || \
					print ${i} >> ${TMPDIR}/packages

			done

		else

	
			# Do not report missing SPOT creation hooks
			[[ "${option_names[j]}" != ${MKSPOT_PRE_I} ]] &&
			[[ "${option_names[j]}" != ${MKSPOT_POST_I} ]] &&
				missing="${missing}\t\t${option_names[j]}\n"

		fi

		let j=j+1
	done

	#if this is a multi-volume lpp_source, then remove required simages from the missing list
	#and add them to the packages list
	if [[ $do_multi_vol = "yes" ]] 
	then
		# add the simages to the packages file
		echo $missing | $AWK -vreq="$REQUIRED_SIMAGES" '{if (index(req, $1) > 0) printf("%s\n", $1)}' >>${TMPDIR}/packages

		# if any simages are missing, remove them from the missing list to avoid the warning
		for i in $REQUIRED_SIMAGES
		do
			missing=$(echo $missing | $AWK -vthis="$i" '$1 != this {if (split($0, a) > 0) printf("\\t\\t%s\\n", $1)}')
		done
	else
		# DVD media is optional, since graphics may not be present for CD-ROM
		# we remove any missing graphics from the list
		for i in $SIMAGES_OPTIONS_GRAPHICS
		do
			# strip the wildcard (.all) from package name
			[[ ${i} = ?*.all!(.*) ]] && i=${i%.all}
			missing=$(echo $missing | $AWK -vthis="$i" '$1 != this {if (split($0, a) > 0) printf("\\t\\t%s\\n", $1)}')
		done
	fi


	[[ -n "${put_bos_back_in}" ]] && print "bos" >>${TMPDIR}/packages

	[[ -n "${missing}" ]] && return 1

	return 0

} # end of check_options

#---------------------------- undo              --------------------------------
#
# NAME: undo
#
# FUNCTION:
#		backs out changes made by mk_lpp_source
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#		parameters:
#			1						= source of LPP options
#			2						= non-NULL if $1 is to be removed
#			3->					= error message stuff
#		global:
#
# RETURNS: (int)
#
# OUTPUT:
#-------------------------------------------------------------------------------
function undo {

	typeset dir=${1}
	typeset rmdir=${2}
	shift 2

	[[ -n "${rmdir}" ]] && [[ "${dir}" != /usr ]] && ${RM} -r ${dir} 2>/dev/null

	nim_unmount # umount anything which has been mounted by nim_mount

	[[ $# = 1 ]] && err_from_cmd $1 || error $@

} # end of undo

#---------------------------- mk_lpp_source     --------------------------------
#
# NAME: mk_lpp_source
#
# FUNCTION:
#		creates an lpp_source type resource using the bffcreate command
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#		calls error on failure
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#		parameters:
#			1						= location to put images in
#			2						= options to put in <location>
#		global:
#			missing				= list of missing option names
#			undo_on_interrupt
#			src_access			= local access point for source of LPP images
#
# RETURNS: (int)
#		0							= success
#		1							= failure
#
# OUTPUT:
#-------------------------------------------------------------------------------
function mk_lpp_source {
	typeset location=${1}
	typeset options="${2:-${SIMAGES_OPTIONS}}"
	typeset err_msg=${3}
	typeset rmdir=
	typeset bff_verbose=
	typeset gen_source=

	#Setting the -v flag for bffcreate tells it to output the name of each file
    #it copies.  Do this if detailed output is enabled for this operation.
    [[ ${print_info} = "yes" ]] && bff_verbose="-v"

	#if the multi_volume flag is set, the master is also the server, and the source is 
	#product media, then allow processing of multiple volumes
	[[ $multi_volume = "yes" && -z $INU_SINGLE_CD ]] && do_multi_vol="yes"

	if [[ ${options} != "all" ]]
	then
		# check for options which do not reside on the source device
		check_options ${src_access} "${options}" || \
			warning ${err_msg} ${source} "$( echo ${missing} )"
	else
		${ECHO} ${options} >${TMPDIR}/packages
	fi

	# create <location> if it doesn't already exist
	if [[ ! -d ${location} ]]
	then
		if [[ ${mklpp_53} = "yes" ]]
        then
			${C_MKDIR} -a location=${location} >> ${ATTR_OUT_FILE} 2>${ERR} || err_from_cmd ${C_MKDIR}
	 	else
			${C_MKDIR} -a location=${location} 2>${ERR} || err_from_cmd ${C_MKDIR}
		fi

		rmdir=TRUE
		undo_on_interrupt="undo ${location} TRUE"
	fi

	# make prepend to filesets passed -- for gencopy call
	if [[ -n ${gencopy_cmd} ]] && [[ -z ${packages} ]]
	then
		# prefix installp files
		gencopy_list=""
		for i in `${CAT} ${TMPDIR}/packages`
		do
			gencopy_list="${gencopy_list} I:${i} "
		done
		${ECHO} ${gencopy_list} >${TMPDIR}/packages

		# prefix RPM files ?
		if [[ ${LPP_SOURCE_LEVEL} > 50 ]]
		then
			gencopy_list=""
			for i in `${ECHO} ${SIMAGES_OPTIONS_RPMS}`
			do
				gencopy_list="${gencopy_list} R:${i} "
			done	
			${ECHO} ${gencopy_list} >>${TMPDIR}/packages
		fi
	fi

	if [[ -n ${arch} ]]
	then
		# arch value passed, so we call bffcreate w/ two -M flags
		# flags given are N & (R/I)
		${GENCOPY} -b "-MN -q" -X -t ${location} -d ${src_access} \
			$(${CAT} ${TMPDIR}/packages) 2>${ERR} 1>&2
	fi

	# use the gencopy (bffcreate) command to retrieve the images from the source device
	# NOTE that bffcreate only takes package names, not option names, and that
	# 		these names get generated by the check_options function

    # $bff_verbose flag was added here, see the beginning
    # of this function above

	# if the source is a CD, then unmount and pass the path to the device instead
	# of the mount point- reason is that if the CD is mounted, then gencopy will
	# never check the multi-volume .toc file on the product CD
	if [[ $source = /dev/cd* ]] 
	then
		nim_unmount $src_access
		gen_source=$source
	else
		gen_source=$src_access
	fi

	if ${gencopy_cmd:-$BFFCREATE -q ${bff_verbose}} \
			${gencopy_cmd:+-b "${arch:+$M_flag} -q ${bff_verbose}"} \
			-X -t ${location} -d ${gen_source} \
			$(${CAT} ${TMPDIR}/packages) 2>&1 | sed '/^[ 	]*$/d' 2>${ERR}
	then

		:

	else

		undo ${location} "${rmdir}" ${BFFCREATE}

	fi

	undo_on_interrupt=""

	# generate a list of the options which just got retrieved so that we
	#		can check for missing options when we return to main
	# make sure that all our options got created by bffcreate
	list_options ${location}

	do_multi_vol=
} # end of mk_lpp_source
	
#---------------------------- c_mk_lpp_source       ----------------------------
#
# NAME: c_mk_lpp_source
#
# FUNCTION:
#		creates an lpp_source type NIM resource
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#		calls error on failure
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#		parameters:
#		global:
#
# RETURNS: (int)
#		0	= success
#		1	= failure
#
# OUTPUT:
#-------------------------------------------------------------------------------

# signal processing
trap cleanup 0
trap err_signal 1 2 11 15

# NIM initialization
nim_init

# initialize local variables
typeset c=""
typeset check_only=""
typeset list_only=""
typeset suppress_simages_warn=""

# set parameters from command line
while getopts :a:clqsvpmdn c
do
	case ${c} in

		a)		# validate the attr ass
				parse_attr_ass "${OPTARG}"

				# include the assignment for use in this environment
				eval ${variable}=\"${value}\"
				;;

		c)		# check for missing options
				check_only=yes
				;;

		l)		# list option info only
				list_only=yes
				;;

		q)		# show attr info
				cmd_what
				exit 0
				;;

		s)		# suppress the simages warning from being printed
				suppress_simages_warn=yes
				;;

		v)		# verbose mode (for debugging)
				set -x
				for i in $(typeset +f)
				do
					typeset -ft $i
				done
				;;

		p)		#print diagnostic info to terminal
				print_info="yes"
                ;;

        m)		#determines whether to redirect attr_ass output to a temp file
                mklpp_53="yes"
                ;;

		d)		#dump the contents of ATTR_OUT_FILE
				if [[ -f ${ATTR_OUT_FILE} ]] 
				then
					${CAT} ${ATTR_OUT_FILE}
					${RM} ${ATTR_OUT_FILE}
				fi

				[[ -f ${TEMP_SCRIPT} ]] && ${RM} ${TEMP_SCRIPT}

				exit 0
				;;

		n)		#allow multi-volume source
				multi_volume="yes"
				;;

		\?)	# unknown option
				error ${ERR_BAD_OPT} ${OPTARG}
				;;
	esac
done

# check for missing attrs
ck_attrs

[[ -f ${ATTR_OUT_FILE} ]] && ${RM} ${ATTR_OUT_FILE}

# look for new "bos" offset - 5.1 release
[[ -d "${location}/installp/ppc" ]] && ppc_location="${location}/installp/ppc"

# set flag value for cross-platform
[[ "${arch}" != "ia64" ]] && 
	M_flag="-MR"	||
	M_flag="-MI"

# set geninstall_cmd & gencopy_cmd (if needed)
set_geninst ""

# check for errors
if [[ -n "${list_only}" ]] && [[ -n "${check_only}" ]]
then

	error ${ERR_SYNTAX} "c_mk_lpp_source: -a location=<> [-a attr=val] [-c]|[-l]"

fi
if [[ -z "${source}" ]]
then

	ATTR_TEMP=$NIM_ATTR_FORCE	# copy the env value of NIM_ATTR_FORCE
	export NIM_ATTR_FORCE=no	# Do not "force" cuz we need the err_num
	# not going to create an lpp_source, so location must already exist and be
	#		a local directory
	# first, check to see if it is a CDROM filesystem
	if ${C_STAT} -a location=${location} -a vfstype="5 34" -a no_error_msg="yes" >/dev/null 2>&1
	then

		# CDROM filesystem - return this information
		# we need to know when an lpp_source is a CDROM so that we can prevent
		#		it from being used in define operations for non-/usr SPOTs (which
		#		would require mounting the CDROM inside of the SPOT's inst_root)
		if [[ -z "${list_only}" ]]
		then
			[[ ${mklpp_53} = "yes" ]] && echo "cdrom=yes" >> ${ATTR_OUT_FILE} || echo "cdrom=yes"
		fi

	else
		export NIM_ATTR_FORCE=$ATTR_TEMP	# reexport NIM_ATTR_FORCE value

		if ${C_STAT} -a location=${location} 2>${ERR}
		then
			# remove the current TOC (if present)
			[[ -d "${location}/installp/ppc" ]] && \
				toc_location="${location}/installp/ppc" || \
				toc_location="${location}"
			if [[ -f ${toc_location}/.toc ]] && [[ ${RETAIN_LPP_TOC} != 1 ]]
			then 
				${RM} ${toc_location}/.toc 2>${ERR} || err_from_cmd ${RM} 
			fi 
		fi
	fi

	export NIM_ATTR_FORCE=$ATTR_TEMP	# reexport NIM_ATTR_FORCE value
	# set the lvl_type and lvl_source variables for the set_option_lists
	# call that will come later.  Those variables would normally be set in
	# the prep_source routine.
	lvl_type="rte"
	if [[ -e "${location}/installp/ppc/bos" ]] || \
	   [ -e "${location}/installp/ppc/bos.usr."* ] ; then
		lvl_source="${location}/installp/ppc/bos"
	else
		lvl_source="${location}/bos"
	fi
	lvl_arch="${arch}"

elif [[ -n "${check_only}" ]]
then

	error ${ERR_CONTEXT} "-c"

else

	# prepare the source device for use
	prep_source ${source}

	# if use_source_simages is set to 'yes' then extract c_sh_lib from the
	# source's bos.sysmgt package, copy the c_sh_lib's SIMAGES_* variables
	# into a file and source it.
	if [[ "${use_source_simages}" = "yes" ]]; then
		${CP} ${src_access}/installp/ppc/bos.sysmgt* "${TMPDIR}" 2>${ERR} 1>&2 || err_from_cmd "${CP}"
		cd "${TMPDIR}" 2>${ERR} 1>&2 || err_from_cmd "cd"
		${RESTORE} -xvqf bos.sysmgt* ./usr/lpp/bos.sysmgt/nim/methods/c_sh_lib 2>${ERR} 1>&2 || err_from_cmd "${RESTORE}"
		cd - 2>${ERR} 1>&2 || err_from_cmd "cd"
		${EGREP} -p '^SIMAGES_[A-Za-z0-9_]+[ 	]*=[ 	]*"' "${TMPDIR}/usr/lpp/bos.sysmgt/nim/methods/c_sh_lib" > "${TMPDIR}/c_sh_lib-source" 2>${ERR} || err_from_cmd "${EGREP}"
		. "${TMPDIR}/c_sh_lib-source"
	fi
fi

# Need to call check_for_bos to be sure that the bos image is
# appropriately named before calling set_option_lists.
check_for_bos ${source:-${location}}

# call set_option_lists to set the "SIMAGES_OPTIONS" and "REQUIRED_SIMAGES"
# lists that should be used for creating and checking the lpp_source.
set_option_lists ${lvl_type} ${lvl_source} ${lvl_arch}

${CDCHECK} -aq ${src_access} 2>/dev/null 1>&2
cdcheckrc=$?
if [[ $cdcheckrc -eq 0 ]]; then
    export INU_SINGLE_CD="true"
fi

[[ -z $multi_volume ]] && export INU_SINGLE_CD="true"

# determine the missing simages if this is a recover
if [[ -n ${recover} ]]; then

	list_options ${location}

	if check_options ${location} "${REQUIRED_SIMAGES}" 
	then
		# not missing any simages; if > AIX 5.2, ensure vendor profile exists
		if  [[ ${LPP_SOURCE_LEVEL} -ge 52 ]] && \
			[[ ! -s ${ppc_location:-${location}}/bos.vendor.profile ]]
		then
			# copy the vendor profile from the source into the lpp_source
			if [[ -s ${src_access}/installp/ppc/bos.vendor.profile ]]
			then
				${CP} ${src_access}/installp/ppc/bos.vendor.profile \
						   ${ppc_location:-${location}}/bos.vendor.profile || \
						   err_from_cmd "/usr/bin/cp"

			elif [[ -s ${src_access}/bos.vendor.profile ]]
			then
				${CP} ${src_access}/bos.vendor.profile \
						   ${ppc_location:-${location}}/bos.vendor.profile || \
						   err_from_cmd "/usr/bin/cp"

			else
				error ${ERR_SRC_MISSING_VPROF} ${source}
			fi		
		fi
		
		# if we get here then the lpp_source has all the simages packages and 
		# the bos.vendor.profile; nothing more to do so exit
		[[ ${mklpp_53} = "yes" ]] && echo "simages=yes" >> ${ATTR_OUT_FILE} || echo "simages=yes"
		exit 0

	else
		# format the list of missing packages for gencopy; if the lpp_source
		# is missing a vendor profile, then gencopy will copy it automatically
		packages="$( echo "${missing}" | \
				${AWK} 'BEGIN { ORS=" " } gsub("\t\t","")'  )"
		missing=""
	fi
fi

# generate list of options which are present on the source
# also, display the list & exit if list_only was specified
list_options ${src_access:-${location}} "${list_only}"

# if we get here, then the ${TMPDIR}/options.list file (generated in the
#		previous step) must have something in it
[[ ! -s ${TMPDIR}/options.list ]] && \
	error ${ERR_SUPPLY_ARCH_OR_BAD_SOURCE} "${source:-${location}}"


# create the lpp_source?
if [[ -n "${source}" ]]
then

 	if [[ -n "${packages}" ]]
	then	
		mk_lpp_source ${location} "${packages}" \
						${ERR_MISSING_REQ_PKGS_SRC}
	else
		# No packages specified on command line...
		mk_lpp_source ${location} "${SIMAGES_OPTIONS} ${SIMAGES_OPTIONS_GRAPHICS}" \
			${ERR_MISSING_DFLT_PKGS_SRC}
	fi
fi

# stat the lpp_source directory: it must be a local directory
${C_STAT} -a location=${location} -a vfstype="0 3 5 34" 2>${ERR} || \
	err_from_cmd ${C_STAT}

# look for new "bos" offset again - since the directory may have been created
[[ -d "${location}/installp/ppc" ]] && ppc_location="${location}/installp/ppc"

# check the options which reside in the lpp_source

# if this is a recovery, then zero out the packages so that the error messages
# make sense
[[ -n ${recover} ]] && packages=""

# Check to see if the lpp_source provides SIMAGES (ie, the
#		"s"upport "images" which NIM needs in order to support install operations
# if so, display an attribute assignment so that it gets added to the
#		object definition for this lpp_source

#display a message saying that the script will now check for missing SIMAGES
[[ $print_info = "yes" ]] && ${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_START_SIMAGES} \
	'Now checking for missing install images...\n'

if check_options ${location} "${REQUIRED_SIMAGES}"
then
	# ensure that a 5.2 lpp_source with SIMAGES has a bos.vendor.profile
	# if not, print a warning 
	if  [[ ${LPP_SOURCE_LEVEL} -ge 52 ]] && \
		[[ ! -s ${ppc_location:-${location}}/bos.vendor.profile ]]
	then
		[[ -z ${suppress_simages_warn} ]] && warning ${ERR_MISSING_VPROF}
	else
		[[ $mklpp_53 = "yes" ]] && echo "simages=yes" >> ${ATTR_OUT_FILE} || echo "simages=yes"
	fi
fi

req_missing="${missing}"

# if packages were specified, then ensure that all specified packages were 
# copied correctly; do not check if packages == "all"
if [[ -n ${packages} && ${packages} != "all" ]]
then
	missing=""
	# check for missing requested packages
	check_options ${location} "${packages}"
	[[ -n "${missing}" ]] && \
		warning ${ERR_MISSING_REQ_PKGS_LPPSRC} "$(echo ${missing})"
fi

# if no packages were specified, then we assume the lpp_source will be
# used for rte BOS installs.  If simages are missing, then print a warning
# unless suppress_simages_warn is set to yes.
if [[ -z ${packages} && -n ${req_missing} && -z ${suppress_simages_warn} ]]
then
	warning ${ERR_NO_SIMAGES} "$(echo ${req_missing})"
elif [[ $print_info = "yes" ]]
then
    #print an informational message indicating that this lpp_source
    #meets "simages" requirements
    ${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_SIMAGES_SET} \
        'All required install images have been found. This lpp_source is now ready.\n'

fi

if [[ $cdcheckrc -eq 0 || -z $multi_volume ]]; then
    unset INU_SINGLE_CD
fi

exit 0
