#! /bin/ksh -p
#
# ident "@(#)scpatchadm.ksh 1.5     03/03/05 SMI"
#
# Copyright 1999-2003 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#

# PATH
PATH=/bin:/usr/bin:/sbin:/usr/sbin; export PATH

# Our name
typeset -r PROG=${0##*/}

# Global constants which may be set from the environment
typeset    SC_PATCH_INSTALL_LOG=${SC_PATCH_INSTALL_LOG:-/var/cluster/logs/install/${PROG}.log.$$}

# Constants
typeset -r ARGS="$*"
typeset -r TMP_PATCHDIR=/tmp/patchsrcdir.$$
typeset -r TMP_PATCHLIST=sorted_patchlist.$$
typeset -r TMP_PATCHLIST_NUMSORT=num_sorted_patchlist.$$
typeset -r TMP_PATCHLIST_INSTALLED=installed_patchlist.$$
typeset -r TMP_PATCHLIST_FAILED=failed_patchlist.$$
typeset -r BACKOUT_FILE=/tmp/patchsrcdir.$$/backout.$$
typeset -r REQUIRED_FILE=/tmp/patchsrcdir.$$/required.$$
typeset -r SCAN_FILE=/tmp/patchsrcdir.$$/scan.$$
typeset -r APPLIED_PATCHLIST=/tmp/patchsrcdir.$$/appliedpatches.$$
typeset -r PATCH_TMP_LOG=${TMP_PATCHDIR}/${PROG}.$$

typeset VERBOSE='n'

typeset BASE
typeset BASE_OPT

# Return Values:
#	Note that only errors 1,2,3 are fatal.
#
#	0		success
#	1		Usage error
#	2		Bad parameters specified
#	3		Setup error
#	4		Individual patch access error
#	5		Other error, possible patchadd failure
#	6		Internal error

integer -r USAGE_ERROR=1
integer -r PARAM_ERROR=2
integer -r SETUP_ERROR=3
integer -r ACCESS_ERROR=4
integer -r PATCHADD_ERROR=5
integer -r INTERNAL_ERROR=6

#####################################################
#
# print_usage
#
#       Print the command syntax
#
#	Return values: None.
#
#####################################################
print_usage()
{
	printf "$(gettext 'usage: %s [-V] [-M patchdir=<dir>[[,patchlistfile=<file>] || [,patchids=<patch1:patch2...>]]')\n" "${PROG}" >&2
}

#####################################################
#
# openlog
#
#       Create the log file.
#
#       Return values:
#
#               zero            success
#               non-zero        failure
#
#####################################################
openlog()
{
	echo "\n${PROG} ${ARGS}\n" >> ${SC_PATCH_INSTALL_LOG} || return ${SETUP_ERROR}

	return 0
}

#####################################################
#
# logmsg()
#
#	Print message to the install log file.
#	If the install log has not been created, just
#	print to stdout.
#
#	Return values: None.
#
#####################################################
logmsg()
{
        if [[ ! -f "${SC_PATCH_INSTALL_LOG}" ]]; then
                cat
        else
                cat >>${SC_PATCH_INSTALL_LOG}
        fi
}

#####################################################
#
# cleanup() exitstatus
#
#	existatus		status to exit with
#
# 	Clean up and exit.
#
#	Return values: None.
#
#####################################################
cleanup()
{
	integer exitstatus=$1

	if [[ ${exitstatus} -eq 10 ]]; then
		printf "$(gettext '%s: Interrupted, exiting...')\n" "${PROG}" | logmsg
	fi

	rm -rf ${TMP_PATCHDIR}

	exit ${exitstatus}
}

#####################################################
#
# check_specifiers good_specifiers suboptions
#
#	good_specifiers		- recognized suboptions
#	suboptions		- suboptions specified
#
#       Verify that the user specified legal suboptions.
#
#       Return values:
#
#               zero            success
#               non-zero        failure
#
#####################################################
check_specifiers()
{
	typeset -r good_specifiers="$(IFS=, ; echo $1)"
	typeset -r suboptions="$(IFS=, ; echo $2)"
	typeset option
	typeset user_specifier
	typeset good_specifier

	for option in ${suboptions}
	do
		if [[ "${option}" = *=* ]]; then
			user_specifier="$(expr "${option}" : '\(.*\)=.*')"
		fi
		if [[ -n "${user_specifier}" ]]; then
			for good_specifier in ${good_specifiers}
			do
				if [[ "${user_specifier}" = "${good_specifier}" ]]; then
					continue 2
				fi
			done
			return ${PARAM_ERROR}
		else
			return ${PARAM_ERROR}
		fi
	done
	return 0
}

#####################################################
#
# get_specifier suboptions specifier
#
#	suboption		- suboptions specified
#	specifier		- one valid specifier
#
#       From the user provided list of suboptions,
#	print the value of a particular specifier.
#
#       Return values: None.
#
#####################################################
get_specifier()
{
	typeset -r suboptions="$(IFS=, ; echo $1)"
	typeset -r specifier=$2

	typeset suboption
	typeset suboption_val


	for suboption in ${suboptions}
	do
		if [[ "${suboption}" = -* ]]; then
			continue
		fi

		if [[ "${suboption}" = *=* ]]; then
			suboption_val="$(expr "${suboption}" : ${specifier}'=\(.*\)')"
		fi

		if [[ -n "${suboption_val}" ]]; then
			echo ${suboption_val}
		fi
	done
}

#####################################################
#
# scan_dir pdir
#
#	pdir		- patch directory
#
#       Look for and print out the valid patches found
#	in the provided patch directory.
#
#       Return values: None.
#
#####################################################
scan_dir()
{
	typeset -r pdir=$1
	
	typeset simple_patches
	typeset patch

	simple_patches=
	for patch in `ls -1 ${pdir}`
	do
		if [[ -f ${pdir}/${patch}/.diPatch ]] || 
		    [[ -f ${pdir}/${patch}/installpatch ]]; then
			simple_patches="${simple_patches} ${patch}"
		fi
	done

	echo ${simple_patches}
}

#####################################################
#
# sanity_check patch_list
#
#	patch_list		- patch list derived 
#				  from user input
#
#       Look for any discrepancies in the patch list
#	that is ready for installation. The caller
#	might can decide what to do about the 
#	discrepancies. 
#	
#	Note: Sun Plex Manager needs this functionality,
#	this will be modified when Sun Plex Manager is 
#	ready to use this.
#
#       Return values:
#		0	- Proceed with installation
#		>0	- Do not proceed
#
#####################################################
sanity_check()
{
	typeset patch_list=$1

	if [[ ${VERBOSE} != 'y' ]]; then
		if [[ -z "${patch_list}" ]]; then
			printf "$(gettext '%s: No patches to install')\n" "${PROG}" | logmsg
			return ${PARAM_ERROR}
		fi
		return 0
	fi

	missing_dependencies=

	# Expand the patchlist
	expanded_patchlist=
	for new_patch in ${patch_list}
	do
		expanded_patchlist="${expanded_patchlist} ${new_patch}"
		patches_obsoletes="$(grep SUNW_OBSOLETES ${TMP_PATCHDIR}/${new_patch}/*/pkginfo | /usr/bin/nawk -F= '{print $2}' | head -1)"
		expanded_patchlist="${expanded_patchlist} ${patches_obsoletes}"
	done

	for new_patch in ${patch_list}
	do
		patches_required="$(grep SUNW_REQUIRES ${TMP_PATCHDIR}/${new_patch}/*/pkginfo | /usr/bin/nawk -F= '{print $2}' | head -1)"
		if [[ -z "${patches_required}" ]]; then
			continue
		fi
		for reqd_patch in ${patches_required}
		do
			pbase=${reqd_patch%-*}
			prev=${reqd_patch##*-}

			rev_found="$(grep ${pbase} ${APPLIED_PATCHLIST} | /usr/bin/nawk -F- '{print $2}')"
			if [[ -n ${rev_found} ]]; then
				if [[ ${rev_found} -ge ${prev} ]]; then
					continue
				fi
			fi
			for new_patch_ in ${expanded_patchlist}
			do
				pbase_new=${new_patch_%-*}
				if [[ "${pbase}" = "${pbase_new}" ]]; then
					prev_new=${new_patch_##*-}
					if [[ "${prev_new}" -ge "${prev}" ]]; then
						continue 2
					fi
				fi
			done
			missing_dependencies="${missing_dependencies} ${new_patch}:${reqd_patch}"
		done
	done
	
	printf "$(gettext '%s: The following patch dependencies are not satisfied:')\n" "${PROG}"
	for dep in ${missing_dependencies}
	do
		echo ${dep%:*} Requires ${dep##*:} or later
	done

	return 0
}

#####################################################
#
# sort_patches pdir provided_list
#
#	pdir 			- patch directory
#	provided_list		- patch list derived 
#				  from user input
#
#	Sort the provided patch list. The patches
#	should be present the patch directory. The
#	sorted output is kept in the same patch
#	directory (TMP_PATCHLIST). Patches which are
#	actually not present in the patch directory 
#	get skipped.
#
#       Return values: None.
#
#####################################################
sort_patches()
{
	typeset pdir=$1
	typeset provided_list=$2

	integer not_done
	
	typeset patches_required
	typeset patchinfo
	typeset patchbase
	typeset patchnum

	rm -f ${BACKOUT_FILE}
	rm -f ${REQUIRED_FILE}
	rm -f ${SCAN_FILE}

	touch ${TMP_PATCHDIR}/${TMP_PATCHLIST}

	if [[ -z "${provided_list}" ]]; then
		return
	fi

	# The algorithm generates a backout list first then reverses the 
	# order of the list to get an install list.

	for patch in ${provided_list}
	do
		if [[ ! -f ${TMP_PATCHDIR}/${patch}/.diPatch ]] &&
		    [[ ! -f ${pdir}/${patch}/installpatch ]]; then
			continue
		fi
		# Create entries in the "scan" file
		patches_required="$(grep SUNW_REQUIRES ${TMP_PATCHDIR}/${patch}/*/pkginfo | /usr/bin/nawk -F= '{print $2}' | head -1)"
		if [[ -z "${patches_required}" ]]; then
			echo ${patch} "( )" >> $SCAN_FILE
		else
			echo ${patch} "(" ${patches_required} ")" >> $SCAN_FILE
		fi
	done

	if [[ ! -s $SCAN_FILE ]]; then
		return
	fi

	not_done=0

	while [[ ${not_done} = 0 ]]; do
   		if [ -s ${SCAN_FILE} ]; then
      			cat ${SCAN_FILE} | while read patchinfo
      			do
         			patchnum=`echo ${patchinfo} | awk '{print $1}'`
         			patchbase=${patchnum%-*}
         			grep -v "^${patchbase}" ${SCAN_FILE} | grep "${patchbase}" > /dev/null
         			if [ $? = 0 ]; then
            				echo ${patchinfo} >> ${REQUIRED_FILE}
         			else
            				echo ${patchnum} >> ${BACKOUT_FILE}
         			fi
      			done
   		fi

   		if [ -s ${REQUIRED_FILE} ]; then
      			mv ${REQUIRED_FILE} ${SCAN_FILE}
   		else
      			not_done=1          # We are done!
   		fi
	done

	# Now we reverse the order of the lines in BACKOUT_FILE
	/usr/bin/cat -n ${BACKOUT_FILE} | sort -rn | /usr/bin/nawk '{print $2}' > ${TMP_PATCHDIR}/${TMP_PATCHLIST}
}

#####################################################
#
# print_summary_of_patches pfile
#
#	pfile 		- patch list file
#
#	Given the sorted list of patches, print the
#	summary line.
#
#       Return values: None.
#
#####################################################
print_summary_of_patches()
{
	typeset pfile=$1

	printf "$(gettext '\n%s: Would attempt to install the following patches...')\n" "${PROG}" | logmsg

	for patch in $(cat ${pfile})
	do
		echo ${patch} | logmsg
	done
}

#####################################################
#
# derive_summary_of_installed_patches pfile
#
#	pfile 		- patch list file
#
#	Given the sorted list of patches, list only
#	those installed on the system now
#
#       Return values:
#		0	- patchadd installed all patches
#		>0	- patchadd failed to install 
#			  one or more patches
#
#####################################################
derive_summary_of_installed_patches()
{
	typeset pfile=$1

	cat ${pfile} | sort > ${TMP_PATCHDIR}/${TMP_PATCHLIST_NUMSORT}

	printf "$(gettext '\n%s: The following patches are now installed on the system:')\n" "${PROG}" | logmsg

	/usr/sbin/patchadd ${BASE_OPT} -p | /usr/bin/nawk -F: '{
		split($2, pid, " ");
		print(pid[1]);
	}' | sort > ${TMP_PATCHDIR}/${TMP_PATCHLIST_INSTALLED}

	/usr/bin/comm -12 ${TMP_PATCHDIR}/${TMP_PATCHLIST_INSTALLED} ${TMP_PATCHDIR}/${TMP_PATCHLIST_NUMSORT} | logmsg

	/usr/bin/comm -23 ${TMP_PATCHDIR}/${TMP_PATCHLIST_NUMSORT} ${TMP_PATCHDIR}/${TMP_PATCHLIST_INSTALLED} > ${TMP_PATCHDIR}/${TMP_PATCHLIST_FAILED} 2>&1

	if [[ -s ${TMP_PATCHDIR}/${TMP_PATCHLIST_FAILED} ]]; then 
		printf "$(gettext '\n%s: Failed to install the following patches:')\n" "${PROG}" | logmsg
		cat ${TMP_PATCHDIR}/${TMP_PATCHLIST_FAILED} | logmsg
		return ${PATCHADD_ERROR}
	fi
}

#####################################################
#
# copy_and_extract_patches pdir
#
#	pdir 		- patch directory
#	pfile 		- patch list file
#	pids 		- list of patch ids
#
#	Link/untar/unzip patches into the temp directory.
#
#       Return values:
#		zero  		- if successful
#		non-zero	- in case errors were found
#
#####################################################
copy_and_extract_patches()
{
	typeset pdir=$1
	typeset pfile=$2
	typeset pids=$3

	typeset patch
	typeset tarred_patch
	typeset compressed_patch
	typeset jarred_patch
	typeset zipped_patch

	typeset provided_patchlist

	integer error_flag=0

	echo >${PATCH_TMP_LOG}

	for patch in `ls -1 ${pdir}`
	do
		if [[ -f ${pdir}/${patch}/.diPatch ]] || 
		    [[ -f ${pdir}/${patch}/installpatch ]]; then
			ln -s ${pdir}/${patch} ${TMP_PATCHDIR}/${patch} >> ${PATCH_TMP_LOG} 2>&1
			if [[ $? -ne 0 ]]; then
				error_flag=${ACCESS_ERROR}
			fi
		fi
	done

	# Spread out the compressed patches too
	for tarred_patch in `ls -1 ${pdir}/*.tar 2>/dev/null`
	do
		(
			cd ${TMP_PATCHDIR}
			/usr/bin/tar xf ${tarred_patch} >> ${PATCH_TMP_LOG} 2>&1
			if [[ $? -ne 0 ]]; then
				error_flag=${ACCESS_ERROR}
			fi
		)
	done

	# Now copy any zipped/jarred patches to the temporary directory
	for compressed_patch in `ls -1 ${pdir}/*.zip ${pdir}/*.jar 2>/dev/null`
	do
		ln -s ${compressed_patch} ${TMP_PATCHDIR}/"$(basename ${compressed_patch})" >> ${PATCH_TMP_LOG} 2>&1
		if [[ $? -ne 0 ]]; then
			error_flag=${ACCESS_ERROR}
		fi
	done

	# If there are any zipped patches in the temp directory, unzip them.
	# In fact, unzip jarred patches too as that is the prescribed method.
	for zipped_patch in `ls -1 ${TMP_PATCHDIR}/*.zip ${TMP_PATCHDIR}/*.jar 2>/dev/null`
	do
		# unzip produces too much output, just log the result
		/usr/bin/unzip -n -d ${TMP_PATCHDIR} ${zipped_patch} >/dev/null 2>&1
		if [[ $? -ne 0 ]]; then
			printf "$(gettext '%s: Warning or error detected during unzipping patch \"%s\"')\n" "${PROG}" "${zipped_patch##*/}" >> ${PATCH_TMP_LOG}
			error_flag=${ACCESS_ERROR}
		fi
	done

	# If any patch list was provided, are all the patches really there ?
	provided_patchlist=
	if [[ "${pfile}" != "default_file" ]]; then
		provided_patchlist="$(cat ${pdir}/${pfile})"
	elif [[ "${pids}" != "all_patches" ]]; then
		provided_patchlist="${pids}"
	fi

	for patch in ${provided_patchlist}
	do
		if [[ ! -f ${TMP_PATCHDIR}/${patch}/.diPatch ]] &&
		    [[ ! -f ${pdir}/${patch}/installpatch ]]; then
			printf "$(gettext '%s: Can not access, skipping patch \"%s\"')\n" "${PROG}" "${patch}" >> ${PATCH_TMP_LOG}
			error_flag=${ACCESS_ERROR}
			continue
		fi
	done
	
	cat ${PATCH_TMP_LOG} | logmsg
	/usr/bin/rm -f ${PATCH_TMP_LOG}

	return ${error_flag}
}

#####################################################
#
# install_patches pdir pfile pids
#
#	pdir 		- patch directory
#	pfile 		- patch list file
#	pids 		- list of patch ids
#
#	Installs patches from the pdir, uses either
#	pfile or pids as guide. This routine performs
#	very basic validity checks on the directory
#	and patch list file, performs setup, moves 
#	all the patches to a temporary directory in 
#	installable form, and derives a sorted list 
#	to be supplied to patchadd. Finally it calls
#	patchadd if in non-verbose mode.
#	
#       Return values:
#		zero  		- if successful
#		non-zero	- otherwise
#
#####################################################
install_patches()
{
	typeset pdir=$1
	typeset pfile=$2
	typeset pids=$3

	typeset cmd

	typeset bad_entries=

	integer sanity_check_error=0
	integer copy_and_extract_error=0
	integer cmd_ret

	if [[ "${pdir}" = "default_dir" ]]; then
		pdir="/var/cluster/patches/"
	fi

	if [[ ! -d ${pdir} ]]; then
		printf "$(gettext '%s: Problem accessing directory \"%s\"')\n" "${PROG}" "${pdir}" | logmsg
		return ${PARAM_ERROR}
	fi

	# If the provided patch list file doesn't exist or has invalid entries,
	# print a warning and exit
	if [[ "${pfile}" != "default_file" ]]; then
		if [[ ! -r ${pdir}/${pfile} ]]; then
			printf "$(gettext '%s: Could not access the patch list file \"%s\"')\n" "${PROG}" "${pfile}" | logmsg
			return ${PARAM_ERROR}
		fi

		bad_entries="$(cat ${pdir}/${pfile} | /usr/bin/nawk '{print $2}')"
		if [[ -n ${bad_entries} ]]; then
			printf "$(gettext '%s: More than one entry per line specified in \"%s\"')\n" "${PROG}" "${pfile}" | logmsg
			return ${PARAM_ERROR}
		fi
	fi
			
	# Create the temporary directory ...
	mkdir -m 755 -p ${TMP_PATCHDIR}
	if [[ $? -ne 0 ]]; then
		printf "$(gettext '%s: Problem creating temporary directory \"%s\"')\n" "${PROG}" "${TMP_PATCHDIR}" | logmsg
		return ${SETUP_ERROR}
	fi

	# ... and the list of patches already applied on the system
	/usr/sbin/patchadd ${BASE_OPT} -p | /usr/bin/nawk -F: '{
		split($2, pid, " ");
		print(pid[1]);
		
		obs_cnt = split($3, obs, ",");
		if (obs_cnt > 1) {
			for (i = 1; i < obs_cnt; i++) {
				print(obs[i]);
			}
			split(obs[obs_cnt], lst_elem, " ");
			print(lst_elem[1]);
		}
	}' > ${APPLIED_PATCHLIST}
	if [[ $? -ne 0 ]]; then
		printf "$(gettext '%s: Problem creating temporary file \"%s\"')\n" "${PROG}" "${APPLIED_PATCHLIST}" | logmsg
		return ${SETUP_ERROR}
	fi

	# get the patches in installable form in the temp directory
	copy_and_extract_patches ${pdir} ${pfile} "${pids}"
	copy_and_extract_error=$?

	if [[ "${pfile}" = "default_file" ]] && 
	    [[ "${pids}" = "all_patches" ]]; then
		
		# The user didn't provide a patch list file, scan the patch
		# directory and build a list.

		set -A derived_list "$(scan_dir ${TMP_PATCHDIR})"

		sort_patches "${TMP_PATCHDIR}" "${derived_list}"

	elif [[ "${pfile}" != "default_file" ]]; then
		sort_patches "${TMP_PATCHDIR}" "$(cat ${pdir}/${pfile})"
	else
		sort_patches "${TMP_PATCHDIR}" "${pids}"
	fi

	sanity_check "$(cat ${TMP_PATCHDIR}/${TMP_PATCHLIST})"
	sanity_check_error=$?
	if [[ ${sanity_check_error} -ne 0 ]]; then
		return ${sanity_check_error}
	fi

	print_summary_of_patches ${TMP_PATCHDIR}/${TMP_PATCHLIST}
	cmd_ret=0
	if [[ ${VERBOSE} = 'n' ]]; then
		cmd="/usr/sbin/patchadd ${BASE_OPT} -M ${TMP_PATCHDIR} ${TMP_PATCHLIST}"
		echo >${PATCH_TMP_LOG}
		echo ${cmd} >>${PATCH_TMP_LOG}
		eval ${cmd} >>${PATCH_TMP_LOG} 2>&1
		cat ${PATCH_TMP_LOG} | logmsg
		/usr/bin/rm -f ${PATCH_TMP_LOG}
		derive_summary_of_installed_patches ${TMP_PATCHDIR}/${TMP_PATCHLIST}
		cmd_ret=$?
	fi

	# Patchadd return value of zero does not always mean success. In case
	# one or more patch could not be extracted or copied properly, or 
	# patchadd failed silently, we need to return an error
	if [[ ${cmd_ret} -eq 0 ]]; then
		return ${copy_and_extract_error}
	else
		return ${cmd_ret}
	fi
}

#####################################################
#
# Main
#
#####################################################

main()
{

	integer Mflg=0
	typeset bad_subopt=
	typeset -r uid=$(expr "$(id)" : 'uid=\([0-9]*\)*')

	# root permission is required
	if [[ -z "${uid}" ]]; then
		printf "$(gettext '%s: Problem obtaining uid')\n" "${PROG}" >&2
		return ${SETUP_ERROR}
	fi	

	if [[ ${uid} -ne 0 ]]; then
		printf "$(gettext '%s: Must be root')\n" "${PROG}" >&2
		return ${SETUP_ERROR}
	fi

	# Now try opening the log file
	openlog
	if [[ $? -ne 0 ]]; then
		printf "$(gettext '%s: Problem opening logfile \"%s\"')\n" "${PROG}" "${SC_PATCH_INSTALL_LOG}" >&2
	else
		printf "$(gettext '%s: Logging reports to \"%s\"')\n" "${PROG}" "${SC_PATCH_INSTALL_LOG}"
	fi

	while getopts :VM: c
	do
		case ${c} in
		V)	#
			VERBOSE='y'

			;;

		M)	#
			Mflg=1

			patch_specifier="${OPTARG}"
			check_specifiers "patchdir,patchlistfile,patchids" "${patch_specifier}"
			if [[ $? -ne 0 ]]; then
				print_usage
				return ${USAGE_ERROR}
			fi

			pdir="$(get_specifier ${patch_specifier} "patchdir")"
			pfile="$(get_specifier ${patch_specifier} "patchlistfile")"
			pids="$(get_specifier ${patch_specifier} "patchids")"
			
			bad_subopt="$(echo ${pdir} | /usr/bin/nawk '{print $2}')"
			if [[ -z "${bad_subopt}" ]]; then
				bad_subopt="$(echo ${pfile} | /usr/bin/nawk '{print $2}')"
			fi

			if [[ -z "${bad_subopt}" ]]; then
				bad_subopt="$(echo ${pids} | /usr/bin/nawk '{print $2}')"
			fi

			if [[ -n "${bad_subopt}" ]]; then
				print_usage
				return ${USAGE_ERROR}
			fi

			if [[ -z "${pdir}" ]]; then
				print_usage
				return ${USAGE_ERROR}
			fi

			if [[ -n "${pfile}" ]] && [[ -n "${pids}" ]]; then
				print_usage
				return ${USAGE_ERROR}
			fi
	
			if [[ -z "${pfile}" ]]; then
				pfile="default_file"
			fi

			if [[ -z "${pids}" ]]; then
				pids="all_patches"
			fi

			install_patches ${pdir} ${pfile} "${pids}"
		
			return $?
			;;

		*)	#
			print_usage
			return ${USAGE_ERROR}
			;;
		esac
	done

	# without any option, do the defaults
	if [[ ${Mflg} -eq 0 ]]; then
		install_patches "default_dir" "default_file" "all_patches"
		return $?
	fi

	return 0
}

# Determine if it is a jumpstart environment
if [[ -n ${SI_CONFIG_DIR} ]]; then
	BASE="/a"
	BASE_OPT="-R /a"
else
	BASE="/"
	BASE_OPT=
fi

umask 022

trap 'cleanup 10' HUP INT

main $*
cleanup $?
