#!/bin/sh

unalias -a
unset GREP_OPTIONS

# If called from old release's script restarted in ksh, redirect to use old detect 
if [ "x$KSH" != x -a "x$CVPROGRAM_RESTARTED" = xyes ]; then
	if [ "x$CV_OLD_DETECT" = x ]; then
		. /usr/bin/detect
	else
		. $CV_OLD_DETECT
	fi
	return 0
fi

# if this script is running as another script: /path/to/proxy -as [/path/to/]program ...
if [ x$1 = x-as ]; then
	PROGRAM=`basename $2`
	# if the program does not specify a directory assume same as the proxy
	[ x$PROGRAM = x$2 ] && PROGDIR=`dirname $0` || PROGDIR=`dirname $2`
	[ ! -d "$PROGDIR" ] && echo "*** Wrong non-existing program directory specified: $PROGDIR" && exit 1
else
	PROGRAM=`basename $0`
	PROGDIR=`dirname $0`
fi
PROGDIR=`cd $PROGDIR 2>/dev/null && pwd`

SILConfigFileName="SILConfig.xml"
freeSpaceNeededForTempInKB=50000

case $PROGRAM in
detect|detect2|cvpkg*|rom|foi|silent_install|InstallUpdates|RemoveUpdates|cvupd*) ;;
*) return 0 ;;
esac

# Restart in bash
if [ -f /bin/bash -a "x$BASH_VERSION" = x ]; then
	check_real_bash="`/bin/bash -c 'echo $BASH_VERSION' 2>/dev/null`"
	if [ x"$check_real_bash" != x ]; then
		/bin/bash $0 "$@"
		exit $?
	fi
fi

AWK=awk; [ `uname` = "SunOS" -a -f /usr/bin/nawk ] && AWK=/usr/bin/nawk
# Remember initial env vars which will be used to start galaxy service later inside the python installer
if [ x"$CV_INIT_ENV" = x ]
then
	# Use awk command to consider environment variables having newlines, example mc command on SUSE
	CV_INIT_ENV=`$AWK 'END { for (name in ENVIRON) {
            print name"="ENVIRON[name]"@@CV_ENVIRONMENT_VARIABLE_SEPRATOR@@";
           }
         }' < /dev/null`
	CV_SH_CLI="$0 $@"
	export CV_INIT_ENV CV_SH_CLI
fi

# backward compatibility
case $PROGRAM in
InstallUpdates|RemoveUpdates)
	if [ x"$CV_UPDATE_DIR" != x ]; then
		. /usr/bin/detect
		return 0
	fi
	;;
cvupd*)
	. /usr/bin/detect
	return 0
	;;
cvpkgrm|cvpkgchg|cvpkgcheck)
	if [ -f $PROGDIR/detect -a -f $PROGDIR/acsls_utils ]; then
		rm -f $PROGDIR/detect.org
		mv $PROGDIR/detect $PROGDIR/detect.org
		grep -v \/usr\/bin\/detect $PROGDIR/detect.org > $PROGDIR/detect
		CV_OLD_DETECT=$PROGDIR/detect; export CV_OLD_DETECT
		. $CV_OLD_DETECT
		return 0
	fi
	;;
esac

# get free space under directory $1
getFreeSpace()
{
	LANG_BAK=$LANG; LANG=C
	case `uname -s` in
		HP*) set `df -k $1 | grep free` ;;
		Darwin)
			case "`sw_vers -productVersion | $AWK -F\. '{print $2}'`" in
				"7") set `df -k $1`; shift 10 ;;
				*) set `df -k $1`; shift 13 ;;
			esac
			;;
		*) set `df -k $1`; shift 10 ;;
	esac
	echo "$1"
	LANG=$LANG_BAK
}

# if there is space in parameter, temporarily transfer to "@_@" - will transfer back later
args=""
while [ $# -gt 0 ]; do
    args="$args `echo "$1" | sed 's; ;@_@;g'`"
    shift
done
set -- $args

# echo value for first attribute $1 from xml $2
getXmlAttr() { set -- $1 `cat $2`; echo $@ | $AWK -F"$1=\"" '{print $2}' | $AWK -F\" '{print $1}'; }
# return true if attribute $1 has value $2 in xml $3
attrHasValInXml() { set -- $1 $2 `cat $3`; case "$@" in *$1=\"$2\"*) return 0;; *) return 1;; esac; }

# SIL related functions
isInstallerRunningFromSILShare() { [ "`basename $1`" = "installer" ]; }
getSILConfigDirPathFromInstallerLocation()
{	
	isInstallerRunningFromSILShare "$1" || return 0
	installerPath=`cd $1 2>/dev/null && pwd -P`
	silConfigDirPath=""
	[ -f "$installerPath/../../../SILConfig.xml" ] && silConfigDirPath="$installerPath/../../../"
	[ "x" = "x$silConfigDirPath" -a -f "$installerPath/../../SILConfig.xml" ] && silConfigDirPath="$installerPath/../../"
	if [ "x" != "x$silConfigDirPath" -a -d "$silConfigDirPath" ]; then
		silConfigDirPath="`cd $silConfigDirPath 2>/dev/null && pwd -P`"
		echo "$silConfigDirPath"
	fi
}
restartFromLatestSILServerShare()
{	
	answerFilePath=`echo $@ | $AWK -F"-p " '{print $2}' | $AWK '{print $1}'`
	[ "x$answerFilePath" != "x" -a -f "$answerFilePath" ] && silType=`getXmlAttr silType $answerFilePath`	
	if [ "x$silType" = "x2" ]; then
		useLatestSilServerShareFlag="-uselatestsilservershare"
	else		
		useLatestSilServerShareFlag=`echo $@ | grep '\-uselatestsilservershare'`
	fi
	if [ "x$useLatestSilServerShareFlag" != "x" ]; then
		isInstallerRunningFromSILShare "$PROGDIR" || return 0
		silConfigDirPath="`getSILConfigDirPathFromInstallerLocation $PROGDIR`"
		[ "x" = "x$silConfigDirPath" ] && return 0
		[ ! -d "$silConfigDirPath" ] && return 0
		silConfigFilePath="$silConfigDirPath/$SILConfigFileName"
		[ -f $silConfigFilePath ] || return 0

		SILServerShare=`grep 'currentShare' $silConfigFilePath | $AWK -F"path=" '{ print $2 }' | cut -d'"' -f2 `
		if [ "x" != "x$SILServerShare" ]; then
			progDirRealPath=`cd $PROGDIR 2>/dev/null && pwd -P`
			isCurrentSILServerShare=`echo $progDirRealPath | grep $SILServerShare`
			if [ "x" = "x$isCurrentSILServerShare" ]; then
				args=`echo $@ | $AWK -F"-uselatestsilservershare" ' { print $1 $2 }'`
				cmdToExec="$silConfigDirPath/$SILServerShare/installer/$PROGRAM $args"
				exec $cmdToExec
				exit $?
			fi
		fi
	fi
}
restartFromLatestSILServerShare $@

# Already processed argument -uselatestsilservershare remove if exist
args=`echo $@ | $AWK -F"-uselatestsilservershare" ' { print $1 $2 }'`
set -- $args

# debug logging
isRootUser() { [ `id | sed "s/[^=]*=\([^)]*\)(.*/\1/"` = "0" ]; }
isRootUser && CV_LOGDIR=/var/log/.gxsetup/sh/$PROGRAM || CV_LOGDIR=$HOME/var/log/.gxsetup/sh/$PROGRAM
logenv() { [ -f $CV_LOGFILE ] || return 0; echo "$1" >> $CV_LOGFILE; env >> $CV_LOGFILE; }
rotateLog()
{
	CV_LOGGING_STARTED=yes; export CV_LOGGING_STARTED
	mkdir -p $CV_LOGDIR >/dev/null 2>&1
	[ ! -f $CV_LOGDIR/cvlog.ini ] && echo "MAX_LOG_NUM=8" >$CV_LOGDIR/cvlog.ini
	. $CV_LOGDIR/cvlog.ini
	[ x$MAX_LOG_NUM = x0 ] && CV_LOGFILE="" && return 1
	CV_LOGFILE=$CV_LOGDIR/sh.log
	[ x$MAX_LOG_NUM = x1 ] && echo "_cv_sh_log_ `date`" > $CV_LOGFILE && return 0
	echo "_cv_sh_log_ `date`" >> $CV_LOGFILE
	while [ `grep -c "^_cv_sh_log_" $CV_LOGFILE` -gt $MAX_LOG_NUM ]; do
		sed '1d' $CV_LOGFILE > $CV_LOGFILE.org; sed '/^_cv_sh_log_/,$!d' $CV_LOGFILE.org > $CV_LOGFILE
		rm -f $CV_LOGFILE.org >/dev/null 2>&1
	done
	return 0
}
if [ x$CV_LOGGING_STARTED = x ] && rotateLog; then
	exec 2>>$CV_LOGFILE
	CVDBG=x; export CVDBG
	logenv "enviroment at starting $PROGDIR/$PROGRAM:"
	set -$CVDBG
fi

setReg() { isRootUser && CV_REG=/etc/CommVaultRegistry/Galaxy || CV_REG=$HOME/CommVaultRegistry/Galaxy; }
getReg() { [ -f "$CV_REG/$1/$2/.properties" ] && <"$CV_REG/$1/$2/.properties" $AWK '$1 == "'"$3"'" { print $2 }'; }
delReg()
{
	[ -f "$CV_REG/$1/$2/.properties" ] || return 0
	cp $CV_REG/$1/$2/.properties $CV_REG/$1/$2/.properties.org
	sed '/^'"$3 "'/d' $CV_REG/$1/$2/.properties.org > $CV_REG/$1/$2/.properties
	rm -f $CV_REG/$1/$2/.properties.org
}
setRegValue()
{
    if [ $# -ne 3 ]
    then
        echo "*** setRegValue(): Invalid number of arguments"
        return 1
    fi

    KEY="$CVREG/Galaxy/$GALAXY_INST/$1"

    [ ! -d  $KEY ] && mkdir -p "$KEY" 
    [ ! -f $KEY/.properties ] && touch "$KEY/.properties"


    PROP="$KEY/.properties"
    TMP_PROP="${PROP}.tmp"

    rm -f $TMP_PROP
    < $PROP awk '$1 != "'"$2"'" { print $0 }' > $TMP_PROP
    echo "$2 $3" >> $TMP_PROP
    rm -f $PROP
    mv $TMP_PROP $PROP
    return 0
}
setReg

# User specified installer
getUserSpecifiedInstaller()
{
	CV_USER_NEWINSTALL=""
	[ -n "$FORCE_INSTALLER" -a -f "$FORCE_INSTALLER" ] && CV_USER_NEWINSTALL="$FORCE_INSTALLER"
	[ -f /tmp/newinstall.gz ] && CV_USER_NEWINSTALL="/tmp/newinstall.gz"
	[ -f /tmp/newinstall ] && CV_USER_NEWINSTALL="/tmp/newinstall"
	[ -n "$CV_USER_NEWINSTALL" ] || return 0
	newinstall=`basename $CV_USER_NEWINSTALL`
	[ x$newinstall != xnewinstall ] && [ x$newinstall != xnewinstall.gz ] && \
	echo "*** Installer name should be either newinstall or newinstall.gz" && return 1
	[ x$newinstall = xnewinstall.gz ] && CV_NEWINSTALLGZ=$CV_USER_NEWINSTALL
	[ x$newinstall = xnewinstall ] || gunzip $CV_USER_NEWINSTALL >/dev/null 2>&1 || gzip -d $CV_USER_NEWINSTALL >/dev/null 2>&1
	[ $? -ne 0 ] && echo "*** Unable to gunzip and use user specified installer $CV_USER_NEWINSTALL" && return 1
	installerType="user specified"
	CV_NEWINSTALL=`dirname $CV_USER_NEWINSTALL`/newinstall
	chmod +x $CV_NEWINSTALL >/dev/null 2>&1 && return 0
	echo "*** Unable to chmod and use user specified installer $CV_NEWINSTALL" && return 1
}

# Restart myself using detect script from newinstall
restartMe() { eval "`sed -n 's;^#DTCT;;p' $CV_NEWINSTALL 2>/dev/null`"; }

# If user specified the installer, get latest script from it and restart
[ x$restartedViaNewDetect = xyes ] || getUserSpecifiedInstaller || exit 1
if [ -n "$CV_NEWINSTALL" ] && [ -f "$CV_NEWINSTALL" ] && [ x$restartedViaNewDetect != xyes ]; then
	restartedViaNewDetect=yes; export CV_NEWINSTALL restartedViaNewDetect
	restartMe $@
	exit $?
fi

# cleanup temp dir on exit
cleanup()
{
	if [ x"$CVTMPDIR" != x ] && [ ! -f "$CVTMPDIR/install" ]; then
		[ -d "$CVTMPDIR" ] && rm -rf "$CVTMPDIR"
		CVTMPDIR=`dirname $CVTMPDIR`
		[ "`basename $CVTMPDIR`" = ".gxsetup" ] && [ x"`ls $CVTMPDIR`" = x ] && rm -rf "$CVTMPDIR"
	fi
}
trap cleanup EXIT

isRequiredSpaceAvailabe()
{
	dirToCheck=$1
	freeSpaceNeededInKB=$2
	# Do not fail space check for non existing directories
	[ ! -d $dirToCheck ] && mkdir -p $dirToCheck
	freeSpaceAvailableInKB=`getFreeSpace $dirToCheck`
	[ "$freeSpaceAvailableInKB" -ge "$freeSpaceNeededInKB" ]
}
validateAndSetTempDir()
{
	tempDirPath=$1
	noSpaceCheckFlag=$2
	retCode=0
	[ x$tempDirPath = x ] && return 1
	[ x$noSpaceCheckFlag != x -a "$noSpaceCheckFlag" = "1" ] && CVTMPDIR="$tempDirPath" && return 0
	isRequiredSpaceAvailabe $tempDirPath $freeSpaceNeededForTempInKB || retCode=1
	[ $retCode -eq 0 ] && CVTMPDIR="$tempDirPath"
	return $retCode
}
# Set unix temp directory
setTempRootDir()
{
	# *** List of temp directory candidate with their prioroty ( first in the list has highest priority)
	# CLI option -tmpdir has top priority
	# if temp dir is specified in answer xml, use it
	# if env var GX_TMP_DIR is specified, use it
	# for fresh install if insdir is specified in CLI, use it
	# SIL client do not have write access to install directory, use appDataDir
	# for fresh install if insdir is specified in answer xml, use it
	# adding package/update/upgrade to use existing instance's insdir except for SIL clients
	# otherwise use ~ if HOME is / use /tmp
	noSpaceCheckFlag=$1
	[ "x$REG_nSILCLIENT" != "x1" ] && [ x$REG_dGALAXYHOME != x ] && cvInstanceHomeDir="`dirname $REG_dGALAXYHOME`"
	userHomeDir=$HOME; [ "x$userHomeDir" = "x/" -o "x$userHomeDir" = "x" ] && userHomeDir=/tmp
	for candidateTempDir in $CVTMPDIR $XML_unixTempDirectory $GX_TMP_DIR $CLI_insdir $REG_sAPPDATADIR $XML_installDirectory $cvInstanceHomeDir $userHomeDir
	do
		validateAndSetTempDir $candidateTempDir $noSpaceCheckFlag && return 0
	done
	echo "Unable to set temp directory. Make sure that temp directory has write access and has atleast 50 MB free space"
	return 1
}
setTempDir()
{
	setTempRootDir $1 || return $?
	[ "`basename $CVTMPDIR`" != ".gxsetup" ] && CVTMPDIR=$CVTMPDIR/.gxsetup
	CVTMPDIR=$CVTMPDIR/$PROGRAM
	mkdir -p $CVTMPDIR >/dev/null 2>&1
}
CVTMPDIR=`echo $@ | $AWK -F"-tmpdir " '{print $2}' | $AWK '{print $1}'`
CVJOBID=`echo $@ | $AWK -F"-jobid " '{print $2}' | $AWK '{print $1}'`
inputXml=`echo $@ | $AWK -F"-p " '{print $2}' | $AWK '{print $1}'`
# if started by roles manager, use the instance's parameters
if [ "$PROGRAM" = rom -a -f "$PROGDIR/../galaxy_vm" ]; then
	. "$PROGDIR/../galaxy_vm"
	XML_cvInstance="$GALAXY_INST"
	CLI_FOCUS="$GALAXY_INST"
	REG_dGALAXYHOME=`getReg "$XML_cvInstance" "Base" "dGALAXYHOME"`
	[ x$REG_dGALAXYHOME != x ] && cvInstanceHomeDir="`dirname $REG_dGALAXYHOME`"
	CV_ROM=yes && export CV_ROM
fi
# if input xml is present, get temp candidates and use it if available
if [ "x$inputXml" != "x" -a -f "$inputXml" ]
then
	XML_unixTempDirectory=`getXmlAttr unixTempDirectory $inputXml`
	XML_installDirectory=`getXmlAttr installDirectory $inputXml`
	XML_cvInstance=`getXmlAttr Focus $inputXml`
	if [ "x$XML_cvInstance" != "x" -a "x$XML_cvInstance" != "xNew" ]
	then		
		cvInstanceHomeDir=`getReg "$XML_cvInstance" "Base" "dGALAXYHOME"`
		[ x$cvInstanceHomeDir != x ] && cvInstanceHomeDir="`dirname $cvInstanceHomeDir`"
	fi
fi
[ x$CVJOBID = x ] || GX_TMP_DIR=""
setTempDir "1" || exit $?

# list matrix of supported platforms
getPFMatrix()
{
	cat <<EOD
linux-glibc2.3;linux-glibc2.3;Linux glibc-2.3;so;32;linux-glibc;X86;Linux;glibc2.3;17;;linux-x86
linux-glibc2.4;linux-glibc2.3;Linux glibc-2.4;so;32;linux-glibc;X86;Linux;glibc2.4;17;;linux-x86
linux-glibc2.5;linux-glibc2.3;Linux glibc-2.5;so;32;linux-glibc;X86;Linux;glibc2.5;17;;linux-x86
linux-glibc2.6;linux-glibc2.3;Linux glibc-2.6;so;32;linux-glibc;X86;Linux;glibc2.6;17;;linux-x86
linux-glibc2.7;linux-glibc2.3;Linux glibc-2.7;so;32;linux-glibc;X86;Linux;glibc2.6;17;;linux-x86
linux-glibc2.9;linux-glibc2.3;Linux glibc-2.9;so;32;linux-glibc;X86;Linux;glibc2.6;17;;linux-x86
linux-glibc2.11;linux-glibc2.3;Linux glibc-2.11;so;32;linux-glibc;X86;Linux;glibc2.6;17;;linux-x86
linux-glibc2.12;linux-glibc2.3;Linux glibc-2.12;so;32;linux-glibc;X86;Linux;glibc2.6;17;;linux-x86
linux-glibc2.3-x86_64;linux-glibc2.3-x86_64;Linux glibc-2.3 for x86_64;so;32;linux-glibc-x86_64;X64;Linux;glibc2.3;18;;linux-x8664
linux-glibc2.4-x86_64;linux-glibc2.3-x86_64;Linux glibc-2.4 for x86_64;so;32;linux-glibc-x86_64;X64;Linux;glibc2.4;18;;linux-x8664
linux-glibc2.5-x86_64;linux-glibc2.3-x86_64;Linux glibc-2.5 for x86_64;so;32;linux-glibc-x86_64;X64;Linux;glibc2.5;18;;linux-x8664
linux-glibc2.6-x86_64;linux-glibc2.3-x86_64;Linux glibc-2.6 for x86_64;so;32;linux-glibc-x86_64;X64;Linux;glibc2.6;18;;linux-x8664
linux-glibc2.7-x86_64;linux-glibc2.3-x86_64;Linux glibc-2.7 for x86_64;so;32;linux-glibc-x86_64;X64;Linux;glibc2.6;18;;linux-x8664
linux-glibc2.9-x86_64;linux-glibc2.3-x86_64;Linux glibc-2.9 for x86_64;so;32;linux-glibc-x86_64;X64;Linux;glibc2.6;18;;linux-x8664
linux-glibc2.11-x86_64;linux-glibc2.3-x86_64;Linux glibc-2.11 for x86_64;so;32;linux-glibc-x86_64;X64;Linux;glibc2.6;18;;linux-x8664
linux-glibc2.12-x86_64;linux-glibc2.3-x86_64;Linux glibc-2.12 for x86_64;so;32;linux-glibc-x86_64;X64;Linux;glibc2.6;18;;linux-x8664
linux-glibc2.3-ppc64;linux-glibc2.3-ppc64;Linux glibc-2.3 for ppc64;so;32;linux-glibc-ppc64;PPC64;Linux;glibc2.3;26;;linux-ppc64
linux-glibc2.4-ppc64;linux-glibc2.3-ppc64;Linux glibc-2.4 for ppc64;so;32;linux-glibc-ppc64;PPC64;Linux;glibc2.4;26;;linux-ppc64
linux-glibc2.5-ppc64;linux-glibc2.3-ppc64;Linux glibc-2.5 for ppc64;so;32;linux-glibc-ppc64;PPC64;Linux;glibc2.5;26;;linux-ppc64
linux-glibc2.6-ppc64;linux-glibc2.3-ppc64;Linux glibc-2.6 for ppc64;so;32;linux-glibc-ppc64;PPC64;Linux;glibc2.6;26;;linux-ppc64
linux-glibc2.17-ppc64le;linux-glibc2.17-ppc64le;Linux glibc-2.17 for ppc64le;so;32;linux-glibc-ppc64le;PPC64LE;Linux;glibc2.6;41;;linux-ppc64-le
linux-glibc2.17-arm64;linux-glibc2.17-arm64;Linux glibc-2.17 for ARM64;so;32;linux-glibc-arm64;AARCH64;Linux;glibc2.6;42;;linux-arm64
solaris2.10;solaris2.10;Solaris 10;so;64;solaris;SPARC;Solaris;5.10;10;;sol-sparc
solaris2.10-sparc-x86;solaris2.10-sparc-x86;Solaris 10 on Sparc x86;so;32;solaris;SPARC;Solaris;5.10;36;;sol-sparc-x86
solaris2.11;solaris2.10;Solaris 11;so;64;solaris;SPARC;Solaris;5.10;10;;sol-sparc
solaris2.10-x86_64;solaris2.10-x86_64;Solaris 10 on x86_64;so;32;solaris-x86_64;X64;Solaris;5.10;11;;sol-x8664
solaris2.10-x86;solaris2.10-x86;Solaris 10 on x86;so;32;solaris-x86;X86;Solaris;5.10;35;;sol-x86
solaris2.11-x86_64;solaris2.10-x86_64;Solaris 11 on x86_64;so;32;solaris-x86_64;X64;Solaris;5.10;11;;sol-x8664
aix5.2-32;aix5.2-32;AIX 5.2;so;32;aix-32;PPC;AIX;5.2;6;;aix52-32
aix5.3-32;aix5.2-32;AIX 5.3;so;32;aix-32;PPC;AIX;5.3;6;;aix52-32
aix6.1;aix6.1;AIX 6.1;so;64;aix;PPC;AIX;6.1;39;;aix-ppc
hp11.23-ia64;hp11.23-ia64;HP-UX 11.23 IA64;so;32;hp-ia64;IA64;HP;B.11.23;14;;hp-ia64
hp11.31-ia64;hp11.23-ia64;HP-UX 11.31 IA64;so;32;hp-ia64;IA64;HP;B.11.31;14;;hp-ia64
darwin8-i386;darwin9-i386;MAC OS X 10.4 on Intel;dylib;32;darwin-i386;X86;Darwin;6;21;;dwn-x86
darwin9-i386;darwin9-i386;MAC OS X 10.5 on Intel;dylib;32;darwin-i386;X86;Darwin;6;21;;dwn-x86
darwin10-i386;darwin9-i386;MAC OS X 10.6 on Intel;dylib;32;darwin-i386;X86;Darwin;6;21;;dwn-x86
darwin11-i386;darwin9-i386;MAC OS X 10.7 on Intel;dylib;32;darwin-i386;X86;Darwin;6;21;;dwn-x86
darwin12-i386;darwin9-i386;MAC OS X 10.8 on Intel;dylib;32;darwin-i386;X86;Darwin;6;21;;dwn-x86
darwin13-i386;darwin9-i386;MAC OS X 10.9 on Intel;dylib;32;darwin-i386;X86;Darwin;6;21;;dwn-x86
darwin14-i386;darwin9-i386;MAC OS X 10.10 on Intel;dylib;32;darwin-i386;X86;Darwin;6;21;;dwn-x86
darwin8-x86_64;darwin9-x86_64;MAC OS X 10.4 on Intel;dylib;32;darwin-x86_64;X86_64;Darwin;6;40;;dwn-x8664
darwin9-x86_64;darwin9-x86_64;MAC OS X 10.5 on Intel;dylib;32;darwin-x86_64;X86_64;Darwin;6;40;;dwn-x8664
darwin10-x86_64;darwin9-x86_64;MAC OS X 10.6 on Intel;dylib;32;darwin-x86_64;X86_64;Darwin;6;40;;dwn-x8664
darwin11-x86_64;darwin9-x86_64;MAC OS X 10.7 on Intel;dylib;32;darwin-x86_64;X86_64;Darwin;6;40;;dwn-x8664
darwin12-x86_64;darwin9-x86_64;MAC OS X 10.8 on Intel;dylib;32;darwin-x86_64;X86_64;Darwin;6;40;;dwn-x8664
darwin13-x86_64;darwin9-x86_64;MAC OS X 10.9 on Intel;dylib;32;darwin-x86_64;X86_64;Darwin;6;40;;dwn-x8664
darwin14-x86_64;darwin9-x86_64;MAC OS X 10.10 on Intel;dylib;32;darwin-x86_64;X86_64;Darwin;6;40;;dwn-x8664
freebsd7;freebsd7;FreeBSD 7;so;32;freebsd;X86;FreeBSD;7.1;28;;fbsd-x86
freebsd7-x86_64;freebsd7-x86_64;FreeBSD 7 on x86_64;so;32;freebsd-x86_64;X64;FreeBSD;7.1;30;;fbsd-x8664
linux-glibc2.3-s390;linux-glibc2.3-s390;Linux glibc-2.3 for s390;so;64;linux-glibc-s390;s390;Linux;glibc2.3;29;;linux-s390
linux-glibc2.4-s390;linux-glibc2.3-s390;Linux glibc-2.4 for s390;so;64;linux-glibc-s390;s390;Linux;glibc2.4;29;;linux-s390
linux-glibc2.5-s390;linux-glibc2.3-s390;Linux glibc-2.5 for s390;so;64;linux-glibc-s390;s390;Linux;glibc2.5;29;;linux-s390
linux-glibc2.6-s390;linux-glibc2.3-s390;Linux glibc-2.6 for s390;so;64;linux-glibc-s390;s390;Linux;glibc2.6;29;;linux-s390
EOD
}

# echos supported release lists for prefix $1 and suffix $2
getSupportReleaseLists() 
{
	[ -z "$2" ] && getPFMatrix | $AWK -F\; '$6 == "'"$1"'" {print $1}' | sed 's/'"$1"'//' || \
	getPFMatrix | $AWK -F\; '$6 == "'"$1"''"$2"'" {print $1}' | sed -e 's/'"$1"'//' -e 's/'"$2"'//'
}

# returns 0 if $1 >= $2; $1 and $2 are in the form of x[.y]
ge()
{
	x1="`echo $1 | $AWK -F'.' '{ print $1 }'`"
	y1="`echo $1 | $AWK -F'.' '{ print $2 }'`"
	x2="`echo $2 | $AWK -F'.' '{ print $1 }'`"
	y2="`echo $2 | $AWK -F'.' '{ print $2 }'`"
	[ "$x1" -gt "$x2" ] && return 0
	[ "$x1" -lt "$x2" ] && return 1
	[ "${y1:-0}" -ge "${y2:-0}" ] && return 0
	return 1
}

# getRevisedSystemID <prefix> <releasemajor> <releaseminor> <suffix> <osname>
getMappedSystemID()
{
	x="$2$3"
	xx=`echo $x | $AWK -F'.' '{ print $1 }'`
	xy=`echo $x | $AWK -F'.' '{ print $2 }'`
	[ "$5" = SunOS ] && x="`expr $xx - 3`.$xy"
	[ "$5" = FreeBSD -o "$5" = Darwin ] && x="$xx"
	for i in `getSupportReleaseLists $1 $4`; do
		ge $i $x && break
	done
	PLATFORM_ID="$1$i$4"
	REALPLAT_ID="$1$x$4"
	return 0
}

# Linux flavor check for deprecated versions
isLinuxFlavorObsolete()
{
	# Allow EulerOS
	[ -f /etc/euleros-release ] && return 1

	# Oracle Linux needs 4 and above
	# Oracle VM needs 3 and above
	if [ -f /etc/oracle-release ]; then
		if [ "`cat /etc/oracle-release | $AWK '{print $2}'`" = "VM" ]; then
			ge "`cat /etc/oracle-release | $AWK '{print $5}'`" "3" && return 1 || return 0
		else
			ge "`cat /etc/oracle-release | $AWK '{print $5}'`" "4" && return 1 || return 0
		fi
	fi
	# Red Hat need 5 and above
	if [ -f /etc/redhat-release -a -f /usr/bin/lsb_release ]; then
		ge "`/usr/bin/lsb_release -r 2>/dev/null | $AWK '{print $2}'`" "5" && return 1 || return 0
	fi
	# Ubuntu need 7.11 and above
	if [ -f /etc/lsb-release ]; then
		if (grep Ubuntu /etc/lsb-release >/dev/null 2>&1); then
			ge "`/usr/bin/lsb_release -r 2>/dev/null | $AWK '{print $2}'`" "7.11" && return 1 || return 0
		fi
	fi
	# Debian need 4.1 and above
	if [ -f /etc/debian_version ]; then
		ge "`cat /etc/debian_version`" "4.1" && return 1 || return 0
	fi
	# SuSE need 10 and above
	if [ -f /etc/SuSE-release ]; then
		ge "`grep '^VERSION' /etc/SuSE-release | $AWK -F= '{print $2}' | sed  "s/ //g" | $AWK -F\. '{print $1}'`" "10" && return 1 || return 0
	fi

	if [ -f /etc/fedora-release ]; then
		netdruidID=`cat /etc/fedora-release | $AWK '{print $1}'`
		if [ x"$netdruidID" = "xNetrduid" ]; then
			#Netdruid is a fedora fork. Support from version 1 
			ge "`cat /etc/fedora-release | $AWK '{print $3}'`" "1" && return 1 || return 0
		else
			# Fedora needs 8 and above
			ge "`cat /etc/fedora-release | $AWK '{print $3}'`" "8" && return 1 || return 0
		fi
	fi
	# Gentoo needs 10 and above - but as it is version-less and no way to find release number so just let it go
	if [ -f /etc/gentoo-release ]; then
		return 1
	fi
	return 1
}

# Echoes the type of the system, on which we're running
# Returns 0, if the system's been recognized, 1 otherwise
getPlatformID()
{
	SYS_NAME=`uname -s`
	[ x$SYS_NAME = xAIX ] && SYS_REL=`uname -v`.`uname -r` || SYS_REL=`uname -r`
	SYS_REL=`echo $SYS_REL | sed -e "s/^[^0-9]//" -e "s/^\.//"`
	SYS_REL_MAJOR=`echo $SYS_REL | sed "s/\..*//"`
	SYS_REL_OTHER=`echo $SYS_REL | sed -e "s/^$SYS_REL_MAJOR//" -e "s/-RELEASE//"`
	PREFIX=""
	SUFFIX=""
	case $SYS_NAME in
	SunOS)
		PREFIX="solaris"
		if [ `uname -m` = "i86pc" ]; then
			[ `isainfo -b` != "64" ] && PLATFORM_ID="NA" && return 0
			SUFFIX="-x86_64"
		fi
		[ "`uname -r`" = "5.8" -o "`uname -r`" = "5.9" ] && PLATFORM_ID="NA" && return 0
		if [ "`uname -r`" = "5.10" ]; then
			PATCH_LEVEL=`uname -v | $AWK -F_ '{ print $2 }' | sed 's/-/./g'`
			# solaris 10 VM to check update level >=6
			if [ $PATCH_LEVEL = "Virtual" ]; then
				ge 5 `head -n 1 /etc/release | $AWK -F_ '{ print $2 }' | sed -e 's/u//' -e 's/wos//'` && PLATFORM_ID="NA" && return 0
			else
				# solaris 10 to check kernel patch level: min 119689.06 for sparc and 118345.04 for x86
				if [ `uname -p` = "sparc" ]; then
					ge 119689.05 $PATCH_LEVEL && PLATFORM_ID="NA" && return 0
				else
					ge 118345.03 $PATCH_LEVEL && PLATFORM_ID="NA" && return 0
				fi
			fi
		fi
		;;
	HP-UX)
		PREFIX="hp"
		[ `uname -m` != "ia64" -o "$SYS_REL" = "11.11" ] && PLATFORM_ID="NA" && return 0
		SUFFIX="-ia64"
		;;
	AIX)
		PREFIX="aix"
		[ "$SYS_REL" = "5.2" -o "$SYS_REL" = "5.3" ] && PLATFORM_ID="NA" && return 0
		;;
	Linux*)
		PREFIX="linux-glibc"
		SUFFIX="-`uname -m`"
		SHOW_REAL=no
		[ x$PROGRAM = xdetect -a x`basename $PROGDIR` = xtemp ] && SHOW_REAL=yes
		[ x$SUFFIX = x-ia64 ] && [ x$SHOW_REAL = xno ] && PLATFORM_ID="NA" && return 0
		isLinuxFlavorObsolete && [ x$SHOW_REAL = xno ] && PLATFORM_ID="NA" && return 0
		case "$SUFFIX" in
			-x86_64|-ppc64|-ppc64le|-s390) ;;
			-s390x) SUFFIX="-s390" ;;
			-aarch64) SUFFIX="-arm64";;
			*) SUFFIX="";
		esac
		[ x$SUFFIX = x-x86_64 ] && [ "$RESET32BITLINUX" = "yes" -o -f /tmp/cvpkgadd_unlock_32 ] && SUFFIX=""
		unset SYS_REL_MAJOR SYS_REL_OTHER
	    
		# Try get lbc version from ldd -verson output first
		LIBC_VER="`ldd --version | head -n 1 | sed 's;.*) \([2-9]*\)\.\([0-9]*\).*;\1.\2;'`"
		if [ x"$LIBC_VER" = x ]; then
			# Try to get away w/o using gcc first
			LIBC_SO=`ldd /bin/ls 2>/dev/null | grep libc.so | $AWK '{ print $3 }'`
			case "$LIBC_SO" in
			*libc.so*)
				rm -f $CVTMPDIR/get_glibc_ver_$$ >/dev/null 2>&1
				cp -f $LIBC_SO $CVTMPDIR/get_glibc_ver_$$ >/dev/null 2>&1
				chmod +x $CVTMPDIR/get_glibc_ver_$$ >/dev/null 2>&1
				h1="`$CVTMPDIR/get_glibc_ver_$$ | head -1`"
				rm -f $CVTMPDIR/get_glibc_ver_$$ >/dev/null 2>&1
				LIBC_VER=`echo $h1 | sed 's/.*version \([2-9]*\)\.\([0-9]*\).*/\1.\2/'`
				if [ x"$LIBC_VER" = x ]; then
					LIBC_RPM=`rpm -q -f $LIBC_SO 2>/dev/null`
					case "$LIBC_RPM" in
						*libc-[2-9].[0-9]*) LIBC_VER=`echo $LIBC_RPM | sed 's/.*libc-\([2-9]*\)\.\([0-9]*\).*/\1.\2/'` ;;
					esac
				else
					LIBC_VER3=`echo $h1 | sed 's/.*version \([2-9]*\)\.\([0-9]*\)\.\([0-9]*\)[^(0-9)]*/\3/'`
					[ x"$LIBC_VER3" = x -o x"$LIBC_VER3" = x"$h1" ] && LIBC_VER3=0
					ge "$LIBC_VER" "2.4" && LIBC_VER3=9
					ge "2.2" "$LIBC_VER" && LIBC_VER3=0
					[ "$LIBC_VER3" -lt 3 ] && PLATFORM_ID="NA" && return 0
				fi
				;;
			esac
		fi
		if [ x"$LIBC_VER" != x ]; then
			SYS_REL_MAJOR="$LIBC_VER"
		else
			if [ -f /usr/include/gnu/libc-version.h ]; then
				(echo "#include <gnu/libc-version.h>"
				 echo "#include <stdio.h>"
				 echo "int main(void) {"
				 echo "printf(\"%s\", gnu_get_libc_version()); }") > $CVTMPDIR/$$.c
				gcc $CVTMPDIR/$$.c -o $CVTMPDIR/$$ 2>/dev/null || exit 1
				SYS_REL_MAJOR=`$CVTMPDIR/$$ | $AWK -F. '{ print $1 "." $2 }'`
				rm -f $CVTMPDIR/$$.c $CVTMPDIR/$$
			else
				(echo "#include <features.h>"
				 echo "int main(void) {"
				 echo "printf(\"%d.%d\", __GLIBC__, __GLIBC_MINOR__); }") > $CVTMPDIR/$$.c
				gcc $CVTMPDIR/$$.c -o $CVTMPDIR/$$ 2>/dev/null || exit 1
				SYS_REL_MAJOR=`$CVTMPDIR/$$`
				rm -f $CVTMPDIR/$$.c $CVTMPDIR/$$
			fi
		fi
		# Linux x86/x8664 glibc lower than 2.5 is no longer supported from Release 11 SP10
		[ x$SUFFIX = x -o x$SUFFIX = x-x86_64 ] && ge "2.4" "$SYS_REL_MAJOR" && [ x$SHOW_REAL = xno ] && PLATFORM_ID="NA" && return 0
		;;
	Darwin)
		PREFIX="darwin"
		[ "`uname -m`" = "Power Macintosh" -o "`uname -m`" = "i386" -o `uname -r | $AWK -F'.' '{print $1 }'` -lt 13 ] && PLATFORM_ID="NA" && return 0
		SUFFIX="-x86_64"
		;;
	FreeBSD)
		PREFIX="freebsd"
		[ "`uname -m`" = "amd64" ] && SUFFIX="-x86_64"
		# FreeBSD 7 and 8 no longer supported from Release 11 SP10
		ge "8" "$SYS_REL_MAJOR" && PLATFORM_ID="NA" && return 0
		;;
	*)
		PLATFORM_ID="NA"
		return 0
		;;
	esac
	getMappedSystemID "$PREFIX" "$SYS_REL_MAJOR" "$SYS_REL_OTHER" "$SUFFIX" "$SYS_NAME"
	# On platforms aix52-32, dwn-x86, aix-ppc-32, sol-sparc-x86, sol-sparc-x86, sol-x86, linux-s390-31 (BSID's 6, 21, 37, 36, 35, 38) PLATFORM_ID
	# should always be NA, but adding additional check to be sure.
	[ x$SHOW_REAL = xyes ] && return 0
	BSID=`getOsInfoN 10`
	if [ "x$BSID" = "x" -o "$BSID" = "6" -o "$BSID" = "21" -o "$BSID" = "37" -o "$BSID" = "36" -o "$BSID" = "35" -o "$BSID" = "38" ]; then
		PLATFORM_ID="NA"
		REALPLAT_ID="NA"
		return 0
	fi
	return 0
}

# OS information
getOsInfoN()       { getPFMatrix | $AWK -F\; '$1 == "'"$PLATFORM_ID"'" { print $'"$1"' }'; }
getPlatformType()  { tmp=`getOsInfoN 7`; [ x"$tmp" = x ] && echo "Any" || echo "$tmp"; }
getSubType()       { tmp=`getOsInfoN 8`; [ x"$tmp" = x ] && echo "Any" || echo "$tmp"; }
getVersion()       { [ x"`uname -s`" = xLinux ] && echo $REALPLAT_ID | awk -F\- '{print $2}' && return; tmp=`getOsInfoN 9`; [ x"$tmp" = x ] && echo "Any" || echo "$tmp"; }
getLinuxDistributionName()
{
	# Check if os-release is present then try distribution specific release file
	# If available, use LSB to identify distribution
	if [ -f /etc/os-release ]; then
		DISTRO=`cat /etc/os-release | grep ^NAME= | cut -d"=" -f2`            
	elif [ -f /etc/oracle-release ]; then
		DISTRO=`cat /etc/oracle-release | sed s/.release*.*//g`
	elif [ -f /etc/centos-release ]; then
		DISTRO=`cat /etc/centos-release | sed -n '/release*.*(*)/ s/.release*.*//p' | head -n 1`            
	elif [ -f /etc/fedora-release ]; then
		netdruidID=`cat /etc/fedora-release | $AWK '{print $1}'`
		[ x"$netdruidID" = "xNetrduid" ] && DISTRO="Netdruid" || DISTRO=`grep 'Fedora release' /etc/fedora-release | $AWK '{print $1 " " $2}'`
	elif [ -f /etc/redhat-release ]; then
		DISTRO=`cat /etc/redhat-release | sed -n '/release*.*(*)/ s/.release*.*//p' | head -n 1`
	elif [ -f /etc/SuSE-release ]; then
		DISTRO=`cat /etc/SuSE-release | tr "\n" ' '| sed s/VERSION.*//`                                                                             
	elif [ -f /etc/lsb-release -o -d /etc/lsb-release.d ]; then
		# use lsb_release command if exists or directly read info form /etc/lsb_release file
		lsb_release -i >/dev/null 2>&1 && lsb_release -r >/dev/null 2>&1                
		[ $? -eq 0 ] && DISTRO=`lsb_release -i | cut -f2 | sed s/'^\t'//` || DISTRO=`< /etc/lsb-release grep DISTRIB_ID= | sed "s/.*=//"`
	elif [ -f /etc/debian_version ]; then
		DISTRO="Debian"            
	elif [ -f /etc/system-release ]; then
		DISTRO=`cat /etc/system-release | sed s/.release*.*//g`
	else
		# if all of these fails, check if a file exists with name release or version, if exists use its name as distribution
		DISTRO=`ls -d /etc/[A-Za-z]*[_-][rv]e[lr]* | grep -v "lsb" | grep -v "system" | grep -v "os-" | head -1 | cut -d'/' -f3 | cut -d'-' -f1 | cut -d'_' -f1`
	fi
	# strip all double quotes        
	DISTRO=`echo $DISTRO | sed -e "s/^\"//" -e "s/\"$//"`        
	echo $DISTRO
}
getLinuxDistributionRelease()
{
	RELEASE=`uname -r`        
	# If Linux, try to determine specific distribution
	# Check if os-release is present then try distribution specific release file
	# If available, use LSB to identify distribution
	if [ -f /etc/os-release ]; then
		RELEASE=`cat /etc/os-release | grep ^VERSION_ID= | cut -d"=" -f2`
	elif [ -f /etc/oracle-release ]; then
		RELEASE=`cat /etc/oracle-release | sed s/.*release\ // | sed s/\ .*//`            
	elif [ -f /etc/centos-release ]; then
		RELEASE=`cat /etc/centos-release | sed -n '/release*.*(*)/ s/.*release\ //p' | sed s/\ .*// | head -n 1`
	elif [ -f /etc/fedora-release ]; then
		netdruidID=`cat /etc/fedora-release | $AWK '{print $1}'`
		[ x"$netdruidID" = "xNetrduid" ] && RELEASE=`cat /etc/fedora-release | $AWK '{print $3}'` || \
		RELEASE=`grep 'Fedora release' /etc/fedora-release | $AWK '{print $3 " " $4}'`            
	elif [ -f /etc/SuSE-release ]; then
		RELEASE=`grep VERSION /etc/SuSE-release | cut -f3 -d" "`.`grep PATCHLEVEL /etc/SuSE-release | cut -f3 -d" "`
	elif [ -f /etc/lsb-release -o -d /etc/lsb-release.d ]; then
		# use lsb_release command if exists or directly read info form /etc/lsb_release file
		lsb_release -i >/dev/null 2>&1 && lsb_release -r >/dev/null 2>&1                
		[ $? -eq 0 ] && RELEASE=`lsb_release -r | cut -f2 | sed s/'^\t'//` || RELEASE=`< /etc/lsb-release grep DISTRIB_RELEASE= | sed "s/.*=//"`
	elif [ -f /etc/debian_version ]; then
		RELEASE=`cat /etc/debian_version`
	elif [ -f /etc/system-release ]; then
		RELEASE=`cat /etc/system-release | sed s/.*release\ // | sed s/\ .*//`
	fi
	# strip all double quotes                
	RELEASE=`echo $RELEASE | sed -e "s/^\"//" -e "s/\"$//"`
	echo $RELEASE
}
getOSBuild()
{ 
	[ x"`uname -s`" = xDarwin ] && sw_vers -productVersion && return; 
	[ x"`uname -s`" = xAIX ] && echo "`uname -v`.`uname -r`" && return;
	[ x"`uname -s`" = xLinux ] && getLinuxDistributionRelease && return;
	uname -r
}

getOSName_macOS_generic()
{
	# OSXSoftwareLicense.rtf lists like below
	# SOFTWARE LICENSE AGREEMENT FOR macOS High Sierra\ (note the backslash in the end, and also that the OS name is 2 words)
	# SOFTWARE LICENSE AGREEMENT FOR APPLE CONFIDENTIAL macOS PRE-RELEASE SEED SOFTWARE (this was Catalina Beta)
	# SOFTWARE LICENSE AGREEMENT FOR macOS Mojave (here it's single word and no backslash in the end)
        $AWK '/SOFTWARE LICENSE AGREEMENT FOR /' '/System/Library/CoreServices/Setup Assistant.app/Contents/Resources/en.lproj/OSXSoftwareLicense.rtf' | $AWK -F 'macOS' '{print $NF}' | sed 's/\\//g' | sed 's/^[ \t]*//g'
}

getOSName_macOS()
{
	# Ref: https://support.apple.com/en-ca/HT201260
	MAC_MAJOR=`sw_vers -productVersion | $AWK -F\. '{print $1}'`
	MAC_MINOR=`sw_vers -productVersion | $AWK -F\. '{print $2}'`
	if [ "$MAC_MAJOR" = "11" ]; then
		case "$MAC_MINOR" in
		"0") echo "macOS Big Sur";;
		*)   echo "macOS" ;;
		esac
	else
		case "$MAC_MINOR" in
		"14") echo "macOS Mojave";;
		"13") echo "macOS High Sierra";;
		"12") echo "macOS Sierra";;
		"11") echo "OS X El Capitan";;
		"10") echo "OS X Yosemite";;
		"9") echo "OS X Mavericks";;
		"8") echo "OS X Mountain Lion";;
		"7") echo "OS X Lion";;
		"6") echo "OS X Snow Leopard";;
		"5") echo "OS X Leopard";;
		"4") echo "OS X Tiger";;
		"3") echo "OS X Panther";;
		"2") echo "OS X Jaguar";;
		"1") echo "OS X Puma";;
		"0") echo "OS X Cheetah";;
		*) 
			FRIENDLY_NAME=`getOSName_macOS_generic`
			if [ x"$FRIENDLY_NAME" = x ]; then
				echo "macOS"
			else
				echo "macOS $FRIENDLY_NAME"
			fi
			;;
		esac
	fi
	return 0
}
getOSName()
{ 
	[ x"`uname -s`" = xDarwin ] && getOSName_macOS && return
	[ x"`uname -s`" = xLinux ] && getLinuxDistributionName && return
	uname
}
getProcessorType()
{
	if [ x"`uname -s`" = xDarwin ]; then
		[ -f /tmp/cvpkgadd_unlock_32 ] && echo "i386" || echo "x86_64"
		return
	fi
	tmp=`uname -p 2>/dev/null`; [ x"$tmp" = x -o x"$tmp" = xunknown ] && uname -m 2>/dev/null || echo "$tmp";
}

# Global Variables - platform info
setPFID()
{
	getPlatformID
	[ "$PLATFORM_ID" = "NA" ] && return 0
	PACKPLAT_ID=`getOsInfoN 2`
	UPDATEOS_ID=`getOsInfoN 12`
	BINARYSET_ID=`getOsInfoN 10`
	PLATFORM_BIT=`getOsInfoN 5`
	CV_OSINFO="`getPlatformType`;`getSubType`;Unix;`getVersion`;`getOSBuild`;`getOSName`;`getProcessorType`"
	export PLATFORM_ID REALPLAT_ID PACKPLAT_ID UPDATEOS_ID BINARYSET_ID PLATFORM_BIT CV_OSINFO
}

# returns true if sp $1 is newer than $2
newerSP()
{
	a=`echo $1 | sed s/[a-z]//g | sed s/[A-Z]//g`
	b=`echo $2 | sed s/[a-z]//g | sed s/[A-Z]//g`
	[ $a -lt $b ] && return 1
	[ $a -gt $b ] && return 0
	expr $1 '>' $2 >/dev/null
}

# returns true if sp $1,transid $2 is newer than sp $3,transid $4
newerTransID()
{
	[ "$*" = "SP0 0 SP0 0" ] && return 0
	newerSP "$1" "$3" && return 0
	[ x$1 = x$3 ] || return 1
	[ $2 -gt $4 ]
}

# find, compose and echo "SP# TransID" from update.ini file $1
getTransactionIDfromFile()
{
	PATCHINTTRANSID=`grep "\[TransactionID\]" $1 | cut -f2 -d"=" | tr -d '\n'`
	PATCHSP=`grep "ActiveSP\]" $1 | cut -f2 -d"=" | tr -d '\n'`
	[ "x$PATCHSP" = "x" ] && isHotFix=`grep "IsHotFix\]" $1 | cut -f2 -d"=" | tr -d '\n'`
	[ "x$PATCHSP" = "x" -a "x$isHotFix" = "xYes" ] && PATCHSP=`grep "ServicePackHotFix\]" $1 | cut -f2 -d"=" | tr -d '\n'`
	[ "x$PATCHSP" = "x" ] && PATCHSP="SP0"
	[ "x$PATCHINTTRANSID" = "x" ] && PATCHINTTRANSID="0"
	echo "$PATCHSP $PATCHINTTRANSID"
}

# find, compose and echo "SP# TransID" from CVUpdatePack_Cumulative.ini and CumulativeUpdatePackInstallMap.xml
getTransactionIDfromCUConfigFile()
{		
	CUPackSP=""
	CUPackPatchTransID=""
	if [ "x$1" != x -a "x$2" != x -a -f "$1" -a -f "$2" ]
	then				
		CUPackSP=`grep "ActiveSP\]" $1 | cut -f2 -d"=" | tr -d '\n'`
		CUPackPatchTransID=`grep 'newinstall.gz' $2 | $AWK -F'TransactionID=' '{print $2}' | cut -d'"' -f2 | sort | tail -1`
	fi
	[ "x$CUPackSP" = "x" ] && CUPackSP="SP0"
	[ "x$CUPackPatchTransID" = "x" ] && CUPackPatchTransID="0"
	echo "$CUPackSP $CUPackPatchTransID"
}

# From installation media's update folder find the latest newinstall.gz
getUpdInstaller()
{
	installerType="update"
	[ x$PROGRAM = xInstallUpdates -o x$PROGRAM = xRemoveUpdates ] && updatesDir="$PROGDIR" || updatesDir="$PROGDIR/$UPDATEOS_ID"
	# single loose update
	[ -d "$updatesDir/Config" ] && CV_NEWINSTALL=`find "$updatesDir" -name 'newinstall.gz' | sort | tail -1` && return 0
	[ -d "$updatesDir/Updates" -o -d "$updatesDir/LooseUpdates" ] || return 1
	[ -d "$updatesDir/Updates" ] && updatesDir="$updatesDir/Updates" || updatesDir="$updatesDir/LooseUpdates"
	installList=`find "$updatesDir" -name "newinstall.gz" 2>/dev/null`
	[ "x" = "x$installList" ] && return 1
	maxTransactionID="SP0 0"
	for curUpdate in $installList; do            
		updateini=`dirname $curUpdate`/../../Config/update.ini
		if [ -f $updateini ]
		then
			newTransID="`getTransactionIDfromFile $updateini`"
		else
			CUInstallMapXml=`dirname $curUpdate`/../../Config/CumulativeUpdatePackInstallMap.xml
			CVUpdateINI=`dirname $curUpdate`/../../Config/CVUpdatePack_Cumulative.ini
			newTransID="`getTransactionIDfromCUConfigFile $CVUpdateINI $CUInstallMapXml`"
		fi
		newerTransID $newTransID $maxTransactionID || continue
		maxTransactionID="$newTransID"
		CV_NEWINSTALL="$curUpdate"
	done
	return 0
}

# set cvzip 
setCvzip()
{
	CVZIP=""
	[ -f $PROGDIR/$UPDATEOS_ID/$PACKPLAT_ID/BinaryPayLoad/cvzip ] && CVZIP="$PROGDIR/$UPDATEOS_ID/$PACKPLAT_ID/BinaryPayLoad/cvzip" && return 0
	[ -f $REG_dGALAXYHOME/Base/cvzip ] && CVZIP="$REG_dGALAXYHOME/Base/cvzip" && return 0
	return 1
}

getLatestDetectFromUpdates()
{
	[ x$PROGRAM = xcvpkgrm -o x$PROGRAM = xcvpkgchg -o x$PROGRAM = xcvpkgcheck ] && return 1
	[ x$restartedViaNewDetect = xyes ] && restartedViaNewDetect="" && unset restartedViaNewDetect && return 1
	setPFID
	getUpdInstaller || return 1
	[ x$CV_NEWINSTALL = x ] && return 1
	[ -f $CVTMPDIR/newinstall ] && rm -f $CVTMPDIR/newinstall >/dev/null 2>&1
	if setCvzip; then
		$CVZIP -d $CV_NEWINSTALL $CVTMPDIR/newinstall >/dev/null 2>&1 || return 1
	else
		cp -f $CV_NEWINSTALL $CVTMPDIR
		gunzip $CVTMPDIR/newinstall.gz >/dev/null 2>&1 || gzip -d $CVTMPDIR/newinstall.gz >/dev/null 2>&1 || return 1
	fi
	CV_NEWINSTALLGZ=$CV_NEWINSTALL
	CV_NEWINSTALL=$CVTMPDIR/newinstall
	restartedViaNewDetect=yes
	export CV_NEWINSTALL CV_NEWINSTALLGZ
	export restartedViaNewDetect
	return 0
}

getPkgInstaller()
{
	installerType="package"
	CV_NEWINSTALL="$PROGDIR/$UPDATEOS_ID/$PACKPLAT_ID/BinaryPayLoad/newinstall"
	[ -f "$CV_NEWINSTALL" ]
}

getInstanceInstaller()
{
	installerType="instance"
	CV_NEWINSTALL=$REG_dGALAXYHOME/installer/newinstall
	[ -f "$CV_NEWINSTALL" ]
}

# check if this platform is valid for installing CVGxFusion
# return 0 if valid; otherwise echo invalid reason
# Ref: https://doc.lucidworks.com/fusion/3.0/Installation_and_Configuration/System-Requirements.html
isInstallValid4CVGxFusion()
{
	[ -f /tmp/cvpkgadd_unlock_CVGxFusion ] && return 0
	# it must be linux x86_64
	[ x"$PACKPLAT_ID" != xlinux-glibc2.3-x86_64 ] && echo "*** This platform is not Linux 64-bit" && return 1
	# Linux kernel need to be 2.6 or later
	ge 2.5 `uname -r` && echo "*** Linux kernel must be 2.6 or later" && return 1
	# Red Hat need 6.6 and above
	if [ -f /etc/redhat-release -a -f /usr/bin/lsb_release ]; then
		ge 6.5 "`/usr/bin/lsb_release -r 2>/dev/null | awk '{print $2}'`" && \
		echo "*** RedHat based Linux, including CentOS, must be 6.6.x or later" && return 1
	fi
	# JVM need JDK 1.8 or later
	if [ -f /usr/bin/javac ]; then
		ge 1.7 "`/usr/bin/javac -version 2>&1 | awk '{print $2}'`" && \
		echo "*** Java must be installed with JDK 1.8 or later" && return 1
	else
		echo "*** Java must be installed with JDK 1.8 or later" && return 1
	fi
	return 0
}

isValid4SQLServer()
{
	[ -f /tmp/cvpkgadd_unlock_CVGxSQLServer ] && return 0
	[ x"$PACKPLAT_ID" != xlinux-glibc2.3-x86_64 ] && echo "*** This platform is not Linux 64-bit" && return 1
	#Need to be either/later versions of RHEL7.3/Ubuntu 16.04/SUSE V12 SP2
	if [ -f /etc/redhat-release ]; then
		ge 7.2 "`cat /etc/redhat-release | sed s/.*release\ // | sed s/\ .*//`" && \
		echo "*** RHEL release version must be 7.3 or later" && return 1
	elif [ -f /etc/lsb-release ]; then
		if (grep Ubuntu /etc/lsb-release >/dev/null 2>&1); then
			ge 16.03 "`/usr/bin/lsb_release -r 2>/dev/null | $AWK '{print $2}'`" && \
			echo "*** Ubuntu version must be 16.04 or later" && return 1
		fi
	elif [ -f /etc/SuSE-release ]; then
		ge 12.1 "`grep '^VERSION_ID' /etc/os-release | $AWK -F= '{print $2}' | sed  "s/ //g" | sed 's/\"//g'`" && \
		echo "*** SUSE version must be 12 SP2 or later" && return 1
	fi
	return 0
}

isValid4CVGxIndexingServer()
{
	[ -f /tmp/cvpkgadd_unlock_CVGxIndexingServer ] && return 0
	[ x"$PACKPLAT_ID" != xlinux-glibc2.3-x86_64 ] && echo "*** This platform is not Linux 64-bit" && return 1
	# Need to be RedHat based distribution 7.2 and above
	if [ -f /etc/redhat-release ]; then
		if [ -f /etc/centos-release ]; then
			ge 7.1 "`cat /etc/redhat-release | sed s/.*release\ // | sed s/\ .*//`" && \
			echo "*** CentOS release version must be 7.2 or later" && return 1
		else
			ge 7.1 "`cat /etc/redhat-release | sed s/.*release\ // | sed s/\ .*//`" && \
			echo "*** RedHat release version must be 7.2 or later" && return 1
		fi
	else
		echo "*** Must be RHEL 7.2/CentOS 7.2 or later versions of Linux distribution " && return 1
	fi
	return 0
}
# Argument parsing for "detect"
parseArg_detect()
{
	while [ $# -gt 0 ]; do
		case $1 in
		-tmpdir)
			CVTMPDIR="$2"
			shift 2
			;;
		-osinfo)
			getPlatformType
			getSubType
			echo "Unix"
			getVersion
			getOSBuild
			getOSName
			getProcessorType
			shift
			;;
		-pfinfo)
			echo "PLATFORM_ID=$PLATFORM_ID"
			echo "REALPLAT_ID=$REALPLAT_ID"
			if [ x$PROGRAM = xdetect -a x`basename $PROGDIR` = xtemp ]; then
				echo "PACKPLAT_ID=$REALPLAT_ID"
			else
				echo "PACKPLAT_ID=$PACKPLAT_ID"
			fi
			shift
			;;
		-get-platform-id)
			echo "|$PACKPLAT_ID|" | tr -d '\n'
			shift
			;;
		-check-space)
			CLI_insdir="$2"; PKG_SIZE="$3"
			shift 3
			[ -z "$CLI_insdir" ] && CLI_insdir="/opt"
			PKG_SIZE=`expr $PKG_SIZE / 1024 + 25`
			free=`getFreeSpace $CLI_insdir`
			echo "Avalable space on $CLI_insdir is $free KB"
			echo "Required space on $CLI_insdir is $PKG_SIZE KB"
			[ "$free" -lt "$PKG_SIZE" ] && echo "*** Insufficient space for seeding."
			return 0
			;;
		-isvalid)
			packagesToCheck=`echo $@ | $AWK -F"-isvalid" '{print $2}'`
			isPackagesNotAllowed=0
			outPutToSend=""
			for curPkg in $packagesToCheck; do
				curStatus=""
				curExitCode=0
				curOutPut="Success"
				case "$curPkg" in
					CVGxStoragePool|1139)
						GlusterPreReqCheckFilePath="$PROGDIR/GlusterPreReqCheck.sh"
						[ ! -f $GlusterPreReqCheckFilePath ] && GlusterPreReqCheckFilePath=`find $PROGDIR -name 'GlusterPreReqCheck.sh' | head -1`
						curOutPut=`eval $GlusterPreReqCheckFilePath 2>/dev/null`
						curExitCode=$?
						;;
					CVGxFusion|1155)
						curOutPut=`eval isInstallValid4CVGxFusion 2>/dev/null`
						curExitCode=$?
						;;
					CVGxIndexingServer|1156)
						curOutPut=`eval isValid4CVGxIndexingServer 2>/dev/null`
						curExitCode=$?
						;;
					CVGxSQLServer|1212)
						curOutPut=`eval isValid4SQLServer 2>/dev/null`
						curExitCode=$?
						;;
					CVGxOES|1121)
						curOutPut="New installation of OES File system package is stopped from V11 SP23"
						curExitCode=1
						;;
					*)
						curExitCode=0
						;;
				esac
				[ $curExitCode -ne 0 ] && isPackagesNotAllowed=1
				curOutPut=`echo "$curOutPut" | tr '\n' ' ' | tr '\r' ' '`
				echo "$curPkg|$curExitCode|$curOutPut"
			done
			return $isPackagesNotAllowed
			;;
		-*)
			echo
			echo "*** Wrong option specified: $1."
			echo
			return 1
			;;
		*)
			echo
			echo "*** Wrong parameter specified: $1."
			echo
			return 1
			;;
		esac
	done
	return 0
}

# check if this user is not sudo user
isNotSudoUser() { sudo -v 2>/dev/null && return 1 || return 0; }

# Check if this platform is supported or not
isPlatformSuppoted()
{
	[ "$PLATFORM_ID" = "NA" ] && cat << EOF && return 1

*** This platform is no longer supported. 
*** You may install one of the two previous software releases and
*** associate the client with a CommServe from the latest release.

EOF
	[ x"$PLATFORM_ID" = x ] && cat << EOF && return 1

*** Unable to detect the platform info.
*** Please collect sh.log under /var/log/.gxsetup/sh/silent_install and/or
*** /var/log/.gxsetup/sh/cvpkgadd and/or /var/log/.gxsetup/sh/detect for
*** troubleshooting.

EOF
	[ x`uname` = xDarwin ] && [ `id | sed "s/[^=]*=\([^)]*\)(.*/\1/"` != "0" ] && cat << EOF && return 1

*** This user is not supported to install on this platform.
*** Please use sudo or relogin as an Admin user and retry. 

EOF
	return 0
}

# Retrive soem basic info from answer xml $1
parseAnsXML()
{
	XML_Focus=`getXmlAttr Focus $1`
	XML_install32Base=`getXmlAttr install32Base $1`
	XML_unixTempDirectory=`getXmlAttr unixTempDirectory $1`
	XML_installDirectory=`getXmlAttr installDirectory $1`
	XML_cleanupExistingInstance=`getXmlAttr cleanupExistingInstance $1`
	XML_launchRolesManager=`getXmlAttr launchRolesManager $1`
	if [ x$CV_START_SERVICE != xno ]; then
		XML_startService=`getXmlAttr startService $1`
		if [ x$XML_startService = x0 ]; then
			CV_START_SERVICE="no"
			export CV_START_SERVICE
		fi
	fi
	if [ x$CV_STOP_SERVICE != xno ]; then
		XML_stopService=`getXmlAttr stopService $1`
		if [ x$XML_stopService = x0 ]; then
			CV_STOP_SERVICE="no"
			export CV_STOP_SERVICE
		fi
	fi
}

# for push upgrade need adjust args to put xml last
adjustUpgradeArgs()
{
	while [ -n "$1" ]; do
		[ "$1" = "-p" ] && answer_xml=$2 && shift 2 && continue
		NEWINSTALL_ARGS="$NEWINSTALL_ARGS $1"
		shift
	done
	[ x$answer_xml = x ] || NEWINSTALL_ARGS="$NEWINSTALL_ARGS $answer_xml"
}

# Argument parsing for "cvpkgadd/rom/silent_install"
parseArg_install()
{
	NEWINSTALL_ARGS=""
	CVTMPDIR=""
	NEWINSTALL_TYPE=install
	IS_PUSH="no"
	NOX11=""
	IS_SVC="false"
	while [ $# -gt 0 ]; do
		case "$1" in
		-reinstall)
			NEWINSTALL_TYPE=upgrade
			[ x$PROGRAM = xcvpkgadd ] && shift && continue
			CLI_FOCUS="$2"
			NEWINSTALL_ARGS="$NEWINSTALL_ARGS $2"
			shift 2
			;;
		-upgrade)
			[ x$PROGRAM = xcvpkgadd ] && echo "*** This option $1 is only available for silent_install" && exit 1
			NEWINSTALL_TYPE=upgrade
			CLI_FOCUS="$2"
			NEWINSTALL_ARGS="$NEWINSTALL_ARGS $2"
			shift 2
			;;
		-custompackage)
			[ x$PROGRAM = xcvpkgadd ] && echo "*** This option $1 is only available for silent_install" && exit 1
			NEWINSTALL_TYPE=custompackage
			CLI_FOCUS="$2"
			NEWINSTALL_ARGS="$NEWINSTALL_ARGS $2"
			shift 2
			;;
		-rom-seed)
			[ x$PROGRAM = xcvpkgadd ] && echo "*** This option $1 is only available for silent_install" && exit 1
			[ x$2 = x ] && echo "*** You must specify a destination directory for the seed package after option $1" && exit 1
			case $2 in
				/*) ;;
				*) echo "*** The destination directory for the seed package must be a full path" && exit 1 ;;
			esac
			NEWINSTALL_TYPE=custompackage
			CLI_FOCUS="$2"
			NEWINSTALL_ARGS="$NEWINSTALL_ARGS -type 1 -pkgs 1002 -stagingdirectory $2 -mediadir $PROGDIR -rom"
			shift 2
			;;
		-ans-xml)
			[ x"$2" = x ] && echo "*** -ans-xml must be followed by an xml answer file" && exit 1
			ANS_XML="$2"
			case $2 in
				/*) ;;
				*) echo "*** The provided answer xml $2 must be with a full path" && exit 1 ;;
			esac
			[ ! -f "$ANS_XML" ] && echo "*** Provided xml answer file $ANS_XML does not exist" && exit 1
			NEWINSTALL_ARGS="$NEWINSTALL_ARGS $1 $2"
			shift 2
			;;
		-recover)
			echo "*** Recover option is no longer available"
			return 1
			;;
		-tmpdir)
			CVTMPDIR="$2"
			shift 2
			;;
		-cleanup)
			CLI_CLEANUP="yes"
			shift
			;;
		-add|add|+)
			echo "*** The $1 functionality has been added to product using argument -selectedRoles. Please refer documentation ***"
			shift
			;;
		-console-dbg)
			CV_CONSOLE_LOG="DEBUG"
			export CV_CONSOLE_LOG
			shift
			;;
		-no-rollback)
			CV_NO_ROLLBACK="yes"
			export CV_NO_ROLLBACK
			shift
			;;
		-version)
			CLI_VERSION="yes"
			shift
			;;
		-check)
			CLI_CHECK="yes"
			shift
			;;
		-list)
			CLI_LIST="yes"
			shift
			;;
		-jobid)
			IS_PUSH="yes"
			NOX11='--nox11'
			GX_TMP_DIR=""
			NEWINSTALL_ARGS="$NEWINSTALL_ARGS $1"
			shift
			;;
		-silent|--silent)
			NOX11='--nox11'
			NEWINSTALL_ARGS="$NEWINSTALL_ARGS $1"
			shift
			;;
		-svc)
			IS_SVC="true"
			NEWINSTALL_ARGS="$NEWINSTALL_ARGS $1"
			shift
			;;
		-p)
			[ x"$2" = x ] && echo "*** -p must be followed by an xml answer file" && exit 1
			ANS_XML="$2"
			[ x$2 = xdefault ] && ANS_XML="$PROGDIR/default.xml"
			[ ! -f "$ANS_XML" ] && echo "*** Provided xml answer file $ANS_XML does not exist" && exit 1
			# check special pkg validity
			for pkg in 1139 1155 1156 1212; do
				if attrHasValInXml ComponentId $pkg "$ANS_XML"; then
					parseArg_detect -isvalid $pkg && continue
					echo "*** Package $pkg is not valid for this platform" && exit 1
				fi
			done
			parseAnsXML "$ANS_XML"
			NEWINSTALL_ARGS="$NEWINSTALL_ARGS $1 $ANS_XML"
			shift 2
			;;
		*)
			NEWINSTALL_ARGS="$NEWINSTALL_ARGS $1"
			shift
			;;
		esac
	done
	[ "$IS_PUSH" = "yes" -a "$NEWINSTALL_TYPE" = 'upgrade' ] && adjustUpgradeArgs
	return 0
}

# Argument parsing for "InstallUpdates/RemoveUpdates"
parseArg_update()
{
	NEWINSTALL_ARGS=""
	CVTMPDIR=""
	[ x$PROGRAM = xRemoveUpdates ] && NEWINSTALL_TYPE="removeupdates" || NEWINSTALL_TYPE="installupdates"
	IS_PUSH="no"
	NOX11=""
	while [ $# -gt 0 ]; do
		case "$1" in
		-tmpdir)
			CVTMPDIR="$2"
			shift 2
			;;
		-jobid)
			IS_PUSH="yes"
			NOX11='--nox11'
			GX_TMP_DIR=""
			NEWINSTALL_ARGS="$NEWINSTALL_ARGS $1"
			shift
			;;
		-instance|-i|-vm)
			[ x"$2" = x ] && echo "*** -vm/-i/-instance must be followed by an instance id" && exit 1
			CLI_FOCUS="$2"
			shift 2
			;;
		-restart)
			NEWINSTALL_TYPE="restartservices"
			NEWINSTALL_ARGS="$NEWINSTALL_ARGS $1"
			shift
			;;
		-gui)
			[ x"$2" = x ] && echo "*** -p must be followed by an xml answer file" && exit 1
			[ ! -f "$2" ] && echo "*** Provided xml answer file $2 does not exist" && exit 1
			XML_Focus=`grep INSTANCE $2 | $AWK -F: '{print $2}'`
			IS_PUSH="yes"
			NOX11='--nox11'
			GX_TMP_DIR=""
			NEWINSTALL_ARGS="$NEWINSTALL_ARGS $1 $2"
			shift 2
			;;
		*)
			NEWINSTALL_ARGS="$NEWINSTALL_ARGS $1"
			shift
			;;
		esac
	done
	return 0
}

# Argument parsing for "cvpkgcheck"
parseArg_check()
{
	NEWINSTALL_ARGS=""
	CVTMPDIR=""
	NEWINSTALL_TYPE=checkcrc
	IS_PUSH="no"
	NOX11=""
	while [ $# -gt 0 ]; do
		case "$1" in
		-tmpdir)
			CVTMPDIR="$2"
			shift 2
			;;
		-i)
			[ x"$2" = x ] && echo "*** -i must be followed by an instance id" && exit 1
			CLI_FOCUS="$2"
			shift 2
			;;
		-p)
			[ x"$2" = x ] && echo "*** -p must be followed by a list of packages" && exit 1
			CLI_PKG_LIST="$2"
			NEWINSTALL_ARGS="$NEWINSTALL_ARGS $1 $2"
			shift 2
			;;
		*)
			NEWINSTALL_ARGS="$NEWINSTALL_ARGS $1"
			shift
			;;
		esac
	done
	[ x$CLI_FOCUS = x ] && CLI_FOCUS=all
	return 0
}

# Argument parsing for "cvpkgrm/cvpkgchg"
parseArg_process()
{
	if [ x$PROGRAM = xcvpkgcheck ]; then
		parseArg_check $@
		return $?
	fi
	NEWINSTALL_ARGS=""
	CVTMPDIR=""
	NEWINSTALL_TYPE=uninstall
	IS_PUSH="no"
	NOX11=""
	while [ $# -gt 0 ]; do
		case "$1" in
		-tmpdir)
			CVTMPDIR="$2"
			shift 2
			;;
		-jobid)
			IS_PUSH="yes"
			NOX11='--nox11'
			GX_TMP_DIR=""
			NEWINSTALL_ARGS="$NEWINSTALL_ARGS $1"
			shift
			;;
		-instance|-i)
			[ x"$2" = x ] && echo "*** -i/-instance must be followed by an instance id" && exit 1
			[ x"$PROGRAM" = xcvpkgchg -a x"$2" = xall ] && echo "*** cvpkgchg cannot change all instances" && exit 1
			CLI_FOCUS="$2"
			NEWINSTALL_ARGS="$NEWINSTALL_ARGS $1 $2"
			shift 2
			;;
		-npkgid)
			[ x"$2" = x ] && echo "*** -npkgid must be followed by a native package id" && exit 1
			CLI_NPKGID="$2"
			NEWINSTALL_ARGS="$NEWINSTALL_ARGS $1 $2"
			shift 2
			;;
		-p)
			if [ x$PROGRAM = xcvpkgchg ]; then
				[ x"$2" = x ] && echo "*** -p must be followed by permission, such as 770" && exit 1
			else
				[ x"$2" = x ] && echo "*** -p must be followed by an xml answer file" && exit 1
				[ ! -f "$2" ] && echo "*** Provided xml answer file $2 does not exist" && exit 1
				parseAnsXML "$2"
			fi
			NEWINSTALL_ARGS="$NEWINSTALL_ARGS $1 $2"
			shift 2
			;;
		*)
			NEWINSTALL_ARGS="$NEWINSTALL_ARGS $1"
			shift
			;;
		esac
	done
	return 0
}

# get a list of installed instances for release $1
getInstalledInstances()
{
	FOCUS_RELEASE="$1"
	set -- `ls $CV_REG | grep "^Instance[0-9][0-9][0-9]$"`
	if [ x$FOCUS_RELEASE != x ]; then
		FOCUS_INSTANCES=""
		for FOCUS in $@; do
			[ x"`getReg $FOCUS "Base" "sVERSION" | $AWK -F\. '{print $1}'`" != x$FOCUS_RELEASE ] && continue
			FOCUS_INSTANCES="$FOCUS_INSTANCES $FOCUS"
		done
		isRootUser && extra="" || extra="Please retry with sudo."
		[ x"$FOCUS_INSTANCES" = x ] && echo "*** Instances of release $FOCUS_RELEASE not found. $extra"
		set -- $FOCUS_INSTANCES
	fi
	INSTALLED_INSTANCES="$@"
	TOTAL_INSTANCES=$#
	[ $TOTAL_INSTANCES -gt 0 ]
}

# decide on target instance
setFocus()
{
	if [ x$CLI_FOCUS != x ]; then
		case $CLI_FOCUS in
			Instance*) ;;
			*) CLI_FOCUS="Instance"`echo $CLI_FOCUS | $AWK '{printf "%03d\n", $0;}'` ;;
		esac
		FOCUS="$CLI_FOCUS"
	elif [ x$XML_Focus != x ]; then
		FOCUS="$XML_Focus"
	elif [ x$CLI_NPKGID != x ]; then
		FOCUS=`getReg "" "" "$CLI_NPKGID"`
		[ x$FOCUS = x ] && echo "*** Could not find instance id from native package id $CLI_NPKGID" && return 1
	elif [ x$1 = x-allow-user-input ]; then
		if getInstalledInstances $2; then
			[ $TOTAL_INSTANCES -eq 1 ] && FOCUS=$INSTALLED_INSTANCES && return 0
			echo
			echo "Please choose one of the following instances:"
			echo 
			i=1
			for FOCUS in $INSTALLED_INSTANCES; do
				sVERSION=`getReg $FOCUS "Base" "sVERSION"`
				sCSHOSTNAME=`getReg $FOCUS CommServe sCSHOSTNAME`
				[ x$sCSHOSTNAME = x ] && sCSHOSTNAME=None
				sPhysicalNodeName=`getReg $FOCUS "" sPhysicalNodeName` 
				echo "    [$i]  $FOCUS ($sPhysicalNodeName linked to $sCSHOSTNAME)[$sVERSION]"
				i=`expr $i + 1`
			done
			echo "    [$i]  Quit"
			while :; do
				printf "Enter your choice [1] > " && read ANS
				[ x$ANS = x ] && ANS=1 && break
				[ x$ANS = x$i ] && return 1
				[ $ANS -gt 0 2>/dev/null ] && [ $ANS -lt $i 2>/dev/null ] && break
				echo "*** Wrong choice, please enter a number between 1 and $i"
			done
			FOCUS=`echo $INSTALLED_INSTANCES | $AWK '{print $'"$ANS"'}'`
			echo "User Choice:$ANS($FOCUS)"
		else
			FOCUS=""
			return 1
		fi
	else
		FOCUS=""
		return 1
	fi
	return 0
}

# get attributes for instance $1
getInstanceAttr()
{
	FOCUS="$1"
	[ x$FOCUS != x ] || setFocus || return 1
	REG_dGALAXYHOME=`getReg "$FOCUS" "Base" "dGALAXYHOME"`
	REG_sAPPDATADIR=`getReg "$FOCUS" "Base" "sConfigDir"`
	REG_nSILCLIENT=`getReg "$FOCUS" "Installer" "nSILCLIENT"`
	REG_sUpdateOSID=`getReg "$FOCUS" "" "sUpdateOSID"`
	REG_sVERSION=`getReg "$FOCUS" "Base" "sVERSION" | cut -f1 -d"("`
	return 0
}

# set 32 on 64 flag for Linux 
set32on64Linux()
{
	[ "$PACKPLAT_ID" = linux-glibc2.3-x86_64 ] || return 0
	[ "$XML_install32Base" = "1" -o "$REG_sUpdateOSID" = "linux-x86" ] && RESET32BITLINUX=yes && touch /tmp/cvpkgadd_unlock_32 && setPFID
}

# set shared installer info from XML $1
setSharedInstaller()
{
	SHARED_INSTALLER="false"	
	isInstallerRunningFromSILShare $1 || return 0
	silConfgFilePath="`getSILConfigDirPathFromInstallerLocation $1`"
	silConfgFilePath="$silConfgFilePath/$SILConfigFileName"
	[ -f "$silConfgFilePath" ] || return 0
	SHARED_INSTALLER="true"
	NEWINSTALL_ARGS="-sharedinstaller $NEWINSTALL_ARGS"
	XML_binarySetName=`getXmlAttr binarySetName $silConfgFilePath`
	[ x$XML_binarySetName = x$UPDATEOS_ID ] && return 0
	echo "*** This share can only be used on $XML_binarySetName machines. The current OS type is $UPDATEOS_ID"
	return 1
}

# set IPS upgrade arg
setIPSUpgrade()
{
	[ "x$IS_SVC" = "xtrue" ] || return 0
	currentVersion=`getReg "$XML_Focus" "Base" "sVERSION"|sed "s/\([0-9][0-9]*\).*/\1/"`
	newVersion=`grep "VERSION" "$PROGDIR/version" | $AWK -F'=' '{print $2}'|sed "s/\([0-9][0-9]*\).*/\1/"`
	[ "x$newVersion" != "x" -a "x$currentVersion" != "x" ] && [ $newVersion -gt $currentVersion ] && NEWINSTALL_TYPE="upgrade $XML_Focus"
}

# get newinstall(.gz) in order of (1)user-specified (2)update (3)rundir/newinstall if svc/shared (4)package (5)instance
# update installer, if exist, is already set by function getLatestDetectFromUpdates thus skipped here
getInstallFile()
{
	[ x$CV_NEWINSTALL != x ] && return 0
	[ "x$IS_SVC" = "xtrue" ] && installerType="instance" && CV_NEWINSTALL="$PROGDIR/newinstall" && return 0
	[ "x$SHARED_INSTALLER" = "xtrue" ] && installerType="shared" && CV_NEWINSTALL="$PROGDIR/newinstall" && return 0
	getPkgInstaller || getInstanceInstaller
	[ ! -f "$CV_NEWINSTALL" ] && echo "*** Could not find any installer to use" && return 1
	return 0
}

# Get version from installer file $1
getNewinstallVersion() { eval v=`sed -n 's;^CV_NEWINSTALL_VER=;;p' $1`; echo $v; }

# start python installer
runNewinstall()
{
	if [ x"$CV_NEWINSTALL" != "x" -a x"$CV_NEWINSTALL" != x"$REG_dGALAXYHOME/installer/newinstall" -a -f $CV_NEWINSTALL ]
	then
		newInstallFileDirName=`dirname $CV_NEWINSTALL`
		if [ $newInstallFileDirName != $CVTMPDIR ]
		then
			cp -f $CV_NEWINSTALL $CVTMPDIR
			if [ $? -eq 0 ]
			then
				CV_NEWINSTALL_SRC=$CV_NEWINSTALL
				CV_NEWINSTALL=$CVTMPDIR/newinstall
			else
				echo "Warning...Unable to copy installer file from ${newInstallFileDirName} to ${CVTMPDIR}"
			fi
		fi
	fi
	# if started by roles manager, rename newinstall to rominstall
	if [ "$PROGRAM" = rom -a -f "$PROGDIR/../galaxy_vm" ]; then
		[ -f "$CV_NEWINSTALL" ] || CV_NEWINSTALL=$CV_NEWINSTALL_SRC
		# Try using instance installer
		[ -f "$CV_NEWINSTALL" ] || CV_NEWINSTALL="$REG_dGALAXYHOME/installer/newinstall"
		[ -f /tmp/newinstall ] && CV_NEWINSTALL="/tmp/newinstall"
		[ ! -f "$CV_NEWINSTALL" ] && echo "*** Could not find any installer for Roles Manager to use" && exit 1
		cp -f "$CV_NEWINSTALL" "$CVTMPDIR/rominstall"
		CV_NEWINSTALL_SRC=$CV_NEWINSTALL
		CV_NEWINSTALL="$CVTMPDIR/rominstall"
	fi
	# if fail over install, rename newinstall to foiinstall
	if [ "$PROGRAM" = foi ]; then
		[ -f "$CV_NEWINSTALL" ] || CV_NEWINSTALL=$CV_NEWINSTALL_SRC
		[ -f "$CV_NEWINSTALL" ] || CV_NEWINSTALL="/tmp/newinstall"
		[ ! -f "$CV_NEWINSTALL" ] && echo "*** Could not find any installer for fail over package install to use" && exit 1
		mkdir -p $CVTMPDIR
		CV_NEWINSTALL_SRC=$CV_NEWINSTALL
	fi
	chmod +x $CV_NEWINSTALL >/dev/null 2>&1
	if [ x"$CV_NEWINSTALL_SRC" = x ]; then
		echo "Using $installerType installer $CV_NEWINSTALL:`getNewinstallVersion $CV_NEWINSTALL`"
	else
		echo "Using $installerType installer $CV_NEWINSTALL_SRC:`getNewinstallVersion $CV_NEWINSTALL`"
	fi
	#[ x$CV_NEWINSTALLGZ != x ] && echo " - unzipped from $CV_NEWINSTALLGZ"
	[ "$CLI_CHECK" = "yes" ] && $CV_NEWINSTALL --check
	[ "$CLI_LIST" = "yes" ] && $CV_NEWINSTALL --list
	[ "$CLI_VERSION" = "yes" -o "$CLI_CHECK" = "yes" -o "$CLI_LIST" = "yes" ] && \
	[ x"$NEWINSTALL_ARGS" = x ] && exit 0
	CV_MEDIA_DIR=$PROGDIR; export CV_MEDIA_DIR
	CV_INSTALL_PROG_NAME=$PROGRAM; export CV_INSTALL_PROG_NAME
	logenv "enviroment before running $CV_NEWINSTALL:"
	eval "$CV_NEWINSTALL" $NOX11 --target "$CVTMPDIR" $NEWINSTALL_TYPE $NEWINSTALL_ARGS
}

# check if to skip deconfiguration of obsolete rpm 
checkObsoleteRpmPkg()
{
	obsoleteRPMPackageNames=`getReg "$FOCUS" "" "sObsoleteRPMPackageNames"`
	[ x"$obsoleteRPMPackageNames" = "x" ] && return 0
	for obsoletePackageName in $obsoleteRPMPackageNames; do
		installedRPMPackage=`rpm -q $obsoletePackageName` || continue
		delReg $FOCUS "" "sObsoleteRPMPackageNames"
		echo "Upgrading obsolete RPM package '$obsoletePackageName', skipping de-configuration for '$FOCUS'"
		return 1
	done
	return 0
}

# remove/change/check instance $1
processInstance()
{
	getInstanceAttr $1 || return 1
	[ x$REG_dGALAXYHOME = x ] && echo "*** Could not find install directory from registry for $1" && return 1
	[ ! -d "$REG_dGALAXYHOME" ] && echo "*** $1 home directory $REG_dGALAXYHOME does not exist" && return 1
	[ x$REG_sVERSION = x ] && echo "*** Could not find version info from registry for $1" && return 1
	shift 1
	echo; echo "~~~ $FOCUS $REG_sVERSION @$REG_dGALAXYHOME ~~~"; echo
	if [ x$REG_sVERSION = x11.0.0 ]; then
		[ x$PROGRAM != xcvpkgrm ] || checkObsoleteRpmPkg || return 0
		PROGDIR=$REG_dGALAXYHOME/installer
		setTempDir || exit $?
		[ x$restartedViaNewDetect = xyes ] || CV_NEWINSTALL=$PROGDIR/newinstall
		[ x$PROGRAM = xcvpkgchg ] && NEWINSTALL_TYPE="cvpkgchg -i $FOCUS"
		[ x$PROGRAM = xcvpkgcheck ] && NEWINSTALL_TYPE="checkcrc -i $FOCUS"
		runNewinstall
	elif [ x$REG_sVERSION = x10.0.0 ]; then
		[ x$PROGRAM = xcvpkgcheck -a x$CLI_FOCUS = xall ] && set -- -i $FOCUS $NEWINSTALL_ARGS
		[ x$PROGRAM = xcvpkgrm -a x$CLI_FOCUS = xall ] && set -- -i $FOCUS
		$REG_dGALAXYHOME/installer/$PROGRAM $@
	else
		[ x$PROGRAM = xcvpkgcheck -a x$CLI_FOCUS = xall ] && set -- -i $FOCUS $NEWINSTALL_ARGS
		[ x$PROGRAM = xcvpkgrm -a x$CLI_FOCUS = xall ] && set -- -i $FOCUS
		$REG_dGALAXYHOME/$PROGRAM $@
	fi
	return 0
}

# special cleanup for Mac laptop
cleanupMacLaptop()
{
    # In case registry corruption cleanup binary location
    /usr/local/bin/commvault stop
    [ -d "/opt/commvault" ] && rm -rf /opt/commvault
    [ -d "/opt/simpana" ] && rm -rf /opt/simpana
    # Mac laptop related cleanup
    rm -rf /var/log/.gxsetup/darwin_install.message
    rm -rf /Applications/"Process Manager.app"
    rm -f /usr/bin/laptop2startup.command /usr/bin/laptop2startup.Instance001.command
    rm -f /usr/local/bin/laptop2startup.command /usr/local/bin/laptop2startup.Instance001.command
    for user in `ls /Users`
    do
    	edgemonitor_db_path="/Users/$user/Library/Application Support/EdgeMonitor"
    	[ -d "$edgemonitor_db_path" ] && rm -rf "$edgemonitor_db_path"
    done
    /bin/launchctl unload -w /Library/LaunchAgents/com.commvault.EdgeMonitor.plist
    /bin/launchctl unload -w /Library/LaunchAgents/com.commvault.iGxUninstall.plist
    rm -rf /Library/LaunchAgents/com.commvault.EdgeMonitor.plist
    rm -rf /Library/LaunchAgents/com.commvault.iGxUninstall.plist
    rm -rf "/Applications/Edge Monitor.app"
    rm -f /Library/LaunchDaemons/com.commvault.galaxy.Instance001.plist
}

# Stop all Mac laptop apps
stopMacLaptopApp()
{
    osascript -e 'tell application "/opt/commvault/Base/EdgeMonitor.app" to quit'
    osascript -e 'tell application "/Applications/Process Manager.app/Contents/Resources/BackupUninstall.app" to quit'
    # it does not hurt to kill them even if the above "tell app to quit" succeeds
    pkill -f "/opt/commvault/Base/EdgeMonitor.app"
    pkill -f "/Applications/Process Manager.app/Contents/Resources/BackupUninstall.app"
}

checkIfJobResultsDirNotEmpty()
{
	FOCUS=$1	
	homeDir=$2
	logDir=$3
	REG_DONT_TOUCH_JOBRESULTS_DIR=`getReg "$FOCUS" "Installer" "dontTouchJobResultsDir"`	
	emptyCheckForJobResultsDir="no"
	[ x$REG_DONT_TOUCH_JOBRESULTS_DIR != x -a "$REG_DONT_TOUCH_JOBRESULTS_DIR" = "1" ] && emptyCheckForJobResultsDir="yes"
	if [ "x$emptyCheckForJobResultsDir" = "xyes" ]; then
		for KEY in `ls $CV_REG/$FOCUS/Machines`
		do
			jobResultsDir=`getReg "$FOCUS" "Machines/$KEY" "dJOBRESULTSDIR"`
		    if [ "x$jobResultsDir" != "x" -a -d $jobResultsDir ]; then
		    	case $jobResultsDir in
		    		$homeDir*|$logDir*)
						dirList=`ls $jobResultsDir`
						if [ "x$dirList" != "x" ]; then
							return 1
						fi
						;;
				esac		    		
		    fi
		done
	fi
	return 0
}

# call CvProductionDataUtil to cleanup ProductionData dir
# instance=$1; galaxyhome dir=$2
# if failed or not completely cleaned up, return false
cleanupProductionDataDir()
{
    # run the cleanup utility
    [ -f "$2/Base/CvProductionDataUtil" ] || return 0
    $2/Base/CvProductionDataUtil -vm $1 -op clean || return 1
    # get production data dir
    REG_sPRODUCTIONDATADIR=`getReg "$1" "iDataAgent" "sPRODUCTIONDATADIR"`
    [ "x$REG_sPRODUCTIONDATADIR" = x ] && return 0
    [ -d "$REG_sPRODUCTIONDATADIR" ] || return 0
    # check if there are still contents under it
    [ "x`ls $REG_sPRODUCTIONDATADIR`" = x ] || return 1
}

# locally uninstall all existing instances
# cleanupExistingInstance() function moved to inside python installer
cleanupExistingInstance()
{
    if [ x$XML_cleanupExistingInstance = x1 -o x$CLI_CLEANUP = xyes ]; then
        CV_CLEANUP_EXISTING_INSTANCE="yes"; export CV_CLEANUP_EXISTING_INSTANCE
    fi
    [ x$CV_CLEANUP_EXISTING_INSTANCE = xyes ] && [ x"`uname -s`" = xDarwin ] && stopMacLaptopApp
    return 0
}

# If there are newinstall updates, restart from the new detect script
if getLatestDetectFromUpdates; then
	restartMe $@
	exit $?
fi
[ x$1 = x-as ] && shift 2

setPFID

# set env var to not start service if user specified
if [ x"`echo $@ | grep '\-nostartSvc'`" != x ]; then
	# specified by CLI option
	args=`echo $@ | $AWK -F"-nostartSvc" ' { print $1 $2 }'`
	set -- $args
	CV_START_SERVICE="no"
	export CV_START_SERVICE
elif [ -f "$PROGDIR/.nostartSvc" ]; then
	# specified by custom package
	CV_START_SERVICE="no"
	export CV_START_SERVICE
fi

# set env var to not stop service if user specified
if [ x"`echo $@ | grep '\-nostopSvc'`" != x ]; then
	# specified by CLI option
	args=`echo $@ | $AWK -F"-nostopSvc" ' { print $1 $2 }'`
	set -- $args
	CV_STOP_SERVICE="no"
	export CV_STOP_SERVICE
elif [ -f "$PROGDIR/.nostopSvc" ]; then
	# specified by custom package
	CV_STOP_SERVICE="no"
	export CV_STOP_SERVICE
fi

# Run Solaris IPS configure iff started from "pkg (un)install":
#   silent_install -p xml -svc custom-solaris
#   cvpkgrm -i Instance001 -svc custom-solaris
if [ `uname` = "SunOS" -a x"$3" = x-svc -a x"$4" != x ]; then
	case $PROGRAM in
	silent_install)
		ps augxww | egrep "pkg.*install.*$4" | grep -v egrep || exit 0
		;;
	cvpkgrm)
		ps augxww | egrep "pkg.*uninstall.*$4" | grep -v egrep || exit 0
		;;
	esac
	args="`echo $@ | $AWK -F"-svc" ' { print $1 }'` -svc"
	set -- $args
fi

# Main process according to calling program
case $PROGRAM in
detect|detect2)
	parseArg_detect $@ || exit $?
	exit 0
	;;
cvpkgadd|silent_install|rom|foi)
	isPlatformSuppoted || exit 1
	parseArg_install $@ || exit 1
	cleanupExistingInstance || exit 1
	getInstanceAttr
	set32on64Linux
	setSharedInstaller "$PROGDIR" || exit 1
	setTempDir || exit $?
	setIPSUpgrade
	getInstallFile || exit 1
	runNewinstall
	exit_code=$?
	if [ -f /tmp/.rom ]; then
		echo
		echo "Base package install ended. Exit Code = $exit_code"
		echo
		. /tmp/.rom
		export ROM_SELECTED_ROLES
		rm -f /tmp/.rom
		REG_dGALAXYHOME=`getReg "$FOCUS" "Base" "dGALAXYHOME"`
		CV_ROM=yes && export CV_ROM
		PROGRAM=rom
		PROGDIR=$REG_dGALAXYHOME/installer
		# make sure the instance is installed
		if [ ! -d "$PROGDIR" ]; then
			echo
			echo "*** Cannot add additional roles as the instance is not complete."
			echo
			exit 1
		fi
		. $PROGDIR/branding
		# make sure the instance is registered to a CS
		CS=`getReg "$FOCUS" "CommServe" "sCSHOSTNAME"`
		if [ x$CS = x ]; then
			echo
			echo "*** Roles Manager cannot be launched as client is not registered to Commserve. Register the client and try adding roles using \"$SSCRIPT +\" command."
			echo
			exit 1
		fi
		AUTOREG=`getReg "$FOCUS" "Session" "nAutoRegister"`
		if [ x$AUTOREG != x -a x$AUTOREG != x0 -a x$AUTOREG != x6 ]; then
			# Registration in progress
			echo
			echo "Registration did not complete in expected time."
			echo "Communications service will try to register it automatically."
			echo "Once the client is registered Roles manager can be used for adding roles using command \"$SSCRIPT +\"."
			echo
			exit 0
		elif [ x$AUTOREG = x ]; then
			echo
			echo "The instance is not registered to the CommServe $CS yet."
			echo "To add roles from CommServe, you must first register the instance."
			echo
			exit 0
		fi

		echo
		echo "Starting Roles Manager to add roles from CommServe..."
		echo
		CVTMPDIR="$REG_dGALAXYHOME/.gxsetup/$PROGRAM"
		mkdir -p "$CVTMPDIR"
		# create a simple answer xml for semi silent install
		cat > $PROGDIR/pull.xml << EOD
<CVInstallManager_ClientSetup Focus="$FOCUS"/>
EOD
		NEWINSTALL_ARGS="-p $PROGDIR/pull.xml"
		runNewinstall
		exit_code=$?
	fi
	if [ -f /tmp/.foi ]; then
		. /tmp/.foi
		rm -f /tmp/.foi
		PROGRAM=foi
		PROGDIR=$CV_MEDIA_DIR
		if [ x$PATCH_STANDBY_CS = x"yes" ]; then
			export CV_STANDBY_INST_FOCUS
			export CV_START_SERVICE="no"
			NOX11='--nox11'
			NEWINSTALL_ARGS="$CV_PATCH_STANDBY_ARGS"
		else
			NEWINSTALL_ARGS="-p $CV_FOI_INPUT_XML"
			if [ x"$CV_FOI_TYPE" = x"1" ]; then
				NEWINSTALL_ARGS="$NEWINSTALL_ARGS -standbynode"
				CV_START_SERVICE="no"
				CV_STANDBY_INST_FOCUS=$CV_STANDBY_INST_FOCUS
				export CV_START_SERVICE CV_STANDBY_INST_FOCUS
			else
				NEWINSTALL_ARGS="$NEWINSTALL_ARGS -activenodefailoverinstance"
			fi
		fi
		runNewinstall
		exit_code=$?
		[ -f "$CV_FOI_INPUT_XML" ] && rm -f $CV_FOI_INPUT_XML
		unset CV_START_SERVICE
	fi
	exit $exit_code
	;;
InstallUpdates|RemoveUpdates)
	parseArg_update $@ || exit 1
	setFocus -allow-user-input 11 || exit 1
	getInstanceAttr $FOCUS
	setTempDir || exit $?
	getInstallFile || exit 1
	NEWINSTALL_TYPE="$NEWINSTALL_TYPE --instance $FOCUS"
	UPDATE_INSTANCE="$FOCUS"; export UPDATE_INSTANCE
	runNewinstall
	exit $?
	;;
cvpkgrm|cvpkgchg|cvpkgcheck)
	parseArg_process $@ || exit 1
	if [ x$CLI_FOCUS = xall ]; then
		# process all instances
		if getInstalledInstances; then
			for FOCUS in $INSTALLED_INSTANCES; do
				processInstance $FOCUS $@ || exit 1
			done
		else
			echo "*** There is no installed instance to process"
			exit 1
		fi
	else
		# process single instance
		setFocus -allow-user-input || exit 1
		processInstance $FOCUS $@ || exit 1
	fi
	;;
*)
	echo "*** $PROGRAM is not yet supported by detect script"
	exit 1
	;;
esac
