#!/bin/bash
#  $Id: patch_add.sh 145921 2017-10-04 08:28:28Z steven.durrans@oracle.com $
#  Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
#  This software code contains proprietary information 
#  and should be treated as confidential

# Need to be root in order to add patches
u="`LANG=C LC_ALL=C id | sed 's/.*uid=\([0-9][0-9]*\).*/\1/'`"
if [ "$u" = "0" ]
then
  : # all is okay
else
  echo "You must be root to run this program"
  exit 15
fi

if [ -f ${TTAMSG}/common -a -f ${TTAMSG}/patch_add ]; then
  . ${TTAMSG}/common
  . ${TTAMSG}/patch_add
else
  echo "Unable to open message file: ${TTAMSG}/patch_add"
  exit 1
fi

# Check SGD has been configured
CONFIGURED=`cat ${TTAINSTDIR}/var/configure 2>/dev/null`
if [ "${CONFIGURED}" != "" ] ; then
   echo "${err_sgd_not_configured}"
   exit 1;
fi

GetPrivUsrGrp()
{
    cat ${TTAINSTDIR}/var/serverconfig/global/array.properties 2>/dev/null | awk -F= \
	'BEGIN { u="ttasys"; wu="ttaserv"; g="ttaserv" }
	$1 == "tarantella.config.array.privilegeduser" { u = $2 }
	$1 == "tarantella.config.array.webserveruser" { wu = $2 }
	$1 == "tarantella.config.array.privilegedgroup" { g = $2 }
	END { print u " " wu " " g }'
}
_privusrgrp=`GetPrivUsrGrp`
privusr=`expr "$_privusrgrp" : '\([^ ]*\) .*'`
webservusr=`expr "$_privusrgrp" : '.* \([^ ]*\) .*'`
privgrp=`expr "$_privusrgrp" : '.* \([^ ]*\)$'`

PATCH_CFG=${TTAINSTDIR}/var/info/patch.cfg
PATCH_VERSION="PATCHED_VERSION"

GetSGDVersion() {
    TTAVERSION="${TTAINSTDIR}/etc/pkg/ttaversion"
    
    if [ ! -s "${TTAVERSION}" ]; then
	return
    fi
    
    SGD_VERSION=`tail -1 ${TTAVERSION}`
    echo "${SGD_VERSION}"
}


PATCH_LIST=${TTAINSTDIR}/var/info/patch.list
PATCH_LOG=${TTAINSTDIR}/var/log/patch.log
BACKUP_BIN_DIR=${TTAINSTDIR}/bin/bin/backups
BACKUP_JSERVER_DIR=${TTAINSTDIR}/bin/java/backups
BACKUP_WEBSERVER_DIR=${TTAINSTDIR}/webserver/backups
BACKUP_FILE_DIR=${TTAINSTDIR}/var/patchbackups
DELIM="|"
ACTIVE="active"
INACTIVE="inactive"

AddedPatch() {
   echo "$1 - Added patch : $2 $3" >> ${PATCH_LOG}
}

RemovedPatch() {
   echo "$1 - Removed patch : $2 $3" >> ${PATCH_LOG}
}

Check_sgd_running() {
    # ps output only gives limited characters in the command so truncate
    # the install directory if it's too long
    match=`echo $2 | cut -c1-25`

  # Count the number of lines in the file
  entries=`wc -l "$1" 2> /dev/null | awk '{print $1}'`
  if [ ! -s "$1" ]; then
      # Delete an empty file
      rm -f "$1" 2> /dev/null
      return 2;
  elif [ $entries -eq 1 ]; then
      ThePid=`tail -1 "$1" 2>/dev/null | sed 's/ //g'`
      if [ ! -n "${ThePid}" ]; then
          # No pid in the file
	  rm -f "$1" 2> /dev/null
	  return 1
      elif [ -n "`ps -fp${ThePid} 2>/dev/null | egrep \"$match\" | egrep -v egrep`" ] ; then
          # Single pid and the process is still running
	  return 0
      fi

      # The file exists but the process isn't one we expect
      rm -f "$1" 2> /dev/null
      return 1
  else
      # Multiple entries in the file - write all the pids for our processes
      # into a "running" file
      while read Pid ; do
         [ -n "`ps -fp${Pid} 2>/dev/null | egrep \"$match\" | egrep -v egrep`" ] && echo ${Pid} >> running
      done < $1

      if [ -s running ]; then
          # Move the "running" file back to the correct location
          mv -f running $1
          running_entries=`wc -l "$1" 2> /dev/null | awk '{print $1}'`
          ThePid=`tail -1 "$1" 2>/dev/null | sed 's/ //g'`
          if [ $running_entries -eq 1 ]; then
              # Single running process
	      return 0
          else
              # Multiple running processes
              return 3
          fi
      else
          rm -f "$1" 2> /dev/null
          return 1
      fi
  fi
}

ExitIfRunning() {
    DIR=$4

    Check_sgd_running $1 $2
    result=$?
    if [ ${result} -eq 0 -o ${result} -eq 3 ]; then
	echo "$3"
	cd ${TTAINSTDIR}/bin
	rm -rf ${DIR} 2> /dev/null
	exit 1
    fi
}

# Delete all the patches of the given type from the patch list
DeleteRedundantPatches () {
    [ -f "${PATCH_LIST}" ] || {
        return
    }

    TYPE=$1

    # Find and delete the redundant patches from the old version
    [ -x "/usr/bin/nawk" ] && AWK="nawk" || AWK="awk"
    LIST=`grep "${DELIM}${TYPE}${DELIM}" ${PATCH_LIST} |
    ${AWK} -F "${DELIM}" -v version=${FILE_VERSION} '{
        if ($6 == version)
          print $1
    }' | tr ' ' '|'`

    if [ -n "${LIST}" ]; then
	egrep -v "${LIST}" ${PATCH_LIST} > ${TTAINSTDIR}/var/info/patch.list.tmp
	mv -f ${TTAINSTDIR}/var/info/patch.list.tmp ${PATCH_LIST}
    fi
}


# If the SGD server has been upgraded, delete any patches which have
# been superseded by the new version.
TidyUpAfterUpgrade() {
    # If patch config file doesn't exist there is nothing to do here.
    [ -f "${PATCH_CFG}" ] || {
        return;
    }
    
    FILE_VERSION=`grep "${PATCH_VERSION}" ${PATCH_CFG} 2> /dev/null | awk '{print $3}'`
    CURRENT_VERSION=`GetSGDVersion`

    case "${CURRENT_VERSION}" in
	${FILE_VERSION})
            return
	    ;;
	*)
	    DeleteRedundantPatches "binary" 
	    DeleteRedundantPatches "jserver"
	    DeleteRedundantPatches "webserver"
	    DeleteRedundantPatches "webcomp"
	    DeleteRedundantPatches "file"
	    ;;
    esac
}

# Modifies a entry in the patch list
# By default, it changes the status from active -> inactive.
# If a second parameter is supplied, it swaps entry for the new 
# entry without any other changes
UpdateEntry() {
    FROM_ENTRY=$1
    TO_ENTRY=$2

    if [ -z "${TO_ENTRY}" ]; then
	TO_ENTRY=`echo ${FROM_ENTRY} | sed -e 's/'${DELIM}${ACTIVE}${DELIM}'/'${DELIM}${INACTIVE}${DELIM}'/g'`
    fi

    grep -v "${FROM_ENTRY}" ${PATCH_LIST} > patch.list.tmp
    echo ${TO_ENTRY} >> patch.list.tmp
    mv -f patch.list.tmp ${PATCH_LIST}	
}

# Update the patch name for a patch command
UpdateRef() {
    COMMAND=$1
    NAME=$2
    PATCH_CFG=$3

    grep -v "^${COMMAND} :" ${PATCH_CFG} > patch.cfg.tmp
    mv -f patch.cfg.tmp ${PATCH_CFG}
    echo "${COMMAND} : ${NAME}" >> ${PATCH_CFG}
}

machinearch ()
{
#!/bin/sh
#  $Id: ixiarch.sh 23561 2012-05-15 08:22:43Z ww161634 $
#  Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
#  This software code contains proprietary information
#  and should be treated as confidential.
#
#  Print canonical syscode for platform

# There are three valid types of command line:
#
# 1.     visionarch
# 2.     visionarch <available codes>...
# 3.	 visionarch [-c|-o]
#
# 1. The architecture is echoed
# 2. The best architecture from the list is returned
# 3. The -c and -o options return just the system Code or the OS type.

# 0) INITIALIZE VARIABLES

# Some of these are historical, but dont cause any harm
PATH=/bin:/usr/bin:/sbin:/usr/sbin:$XDTHOME/bin:$PMWMHOME/bin:$IXIHOME/bin:$PATH


# 1) Arguments
numcodes=0
for i
do
  case $i in
    -c )
      codeonly=1
    ;;
  
    -o )
      osonly=1
    ;;

    -n )
      if [ -z "$codeonly" -a -z "$osonly" ]
      then
	  displayname=1	
      fi
    ;;
 
    * )
      checkcodes="$checkcodes $i"
      numcodes=`expr $numcodes + 1`
    ;;

   esac
done

# fast exit
if [ $numcodes = 1 ]
then
  echo $checkcodes
  exit 0
fi


# 2) MESSAGES
myname=`basename $0`

#  First define some messages.
#  They get overwritten by sourcing from a file, scripts.ll_TT,
#  so there's no need to translate them here.  

#  Messages for the visionarch script.
#  These follow text like "visionarch: !4! ", and may extend to several lines.
msg_xdtarch_no_uname=\
'No uname command found.'
msg_xdtarch_os_cpu=\
'Cannot recognize the Operating System or processor type.'
msg_xdtarch_ver_rel=\
'Cannot calculate version or release.'
msg_xdtarch_no_match=\
'Cannot find matching installed system.'

#  End of messages
# Try to find a language script
posslangfiles=""
for lang in C $IXILANG $PANLANG $LANG
do
  for pathname in $XDTHOME/bin/scripts. $PMWMHOME/bin/scripts. $IXIHOME/bin/scripts. ./scripts.
  do
    posslangfiles="$posslangfiles $pathname.$lang"
  done
done

# see if we can find one of those language files
for f in $posslangfiles
do
  if [ -f $f ]
  then
    . $scriptslangfile			# source it
    break
  fi						
done
  
# 3) TRY UNAME AND SET UP VARIABLES

unamev=`uname -v 2>/dev/null`
if [ $? -ne 0 ]
then
  # This isn't really a UNIX system is it?
  echo >&2  "$myname: !2! $msg_xdtarch_no_uname"
  exit 2
fi

U_SYSTEM=`uname -s 2>/dev/null`  || U_SYSTEM=UNKNOWN
U_RELEASE=`uname -r 2>/dev/null` || U_RELEASE=UNKNOWN
U_VERSION=`uname -v 2>/dev/null` || U_VERSION=UNKNOWN

# Some machines use -m arg to return 'model' rather
# than architecture.  For example, NCR SVR4 returns
# 3433,3434.  On such machines need to use -p which
# returns processor.

for MACHARG in m p
do
    U_MACHINE=`uname -"$MACHARG" 2>/dev/null` || U_MACHINE=UNKNOWN

    # 4)  FIND THE MACHINE
    # Note that we only look for cpu/os combinations our products currently
    # support - if you want better matching, most GNU software comes with
    # a script called 'config.guess' which does a more thorough job (and
    # has totally different output!)

    CPU= 			# Characters 1-2 of syscode
    OS= 			# Characters 3-4 of syscode
    VER=			# Digits 5-6 of syscode
    REL= 			# Digits 7-8 of syscode


    case ${U_MACHINE}::${U_SYSTEM}::${U_RELEASE}::${U_VERSION} in
      # Intel FreeBSD
      i*::FreeBSD::*:* )
        CPU=i3
        OS=fb
        NAME="FreeBSD (Intel)"
        VER=`expr $U_RELEASE : '[^0-9]*\([0-9][0-9]*\)[^0-9]'`
        REL=`expr $U_RELEASE : '[^0-9]*[0-9][0-9]*[^0-9]\([0-9][0-9]*\)'`
       ;;
      # MacOS X
      powerpc::Darwin::*::*)
        CPU=pp
        OS=dw
        NAME="Darwin (PowerPC)"
        VER=`expr $U_RELEASE : '[^0-9]*\([0-9][0-9]*\)[^0-9]'`
        REL=`expr $U_RELEASE : '[^0-9]*[0-9][0-9]*[^0-9]\([0-9][0-9]*\)'`
       ;;
      # MacOS X (Intel)
      i386::Darwin::*::*)
        CPU=i3
        OS=dw
        NAME="Darwin (Intel)"
        VER=`expr $U_RELEASE : '[^0-9]*\([0-9][0-9]*\)[^0-9]'`
        REL=`expr $U_RELEASE : '[^0-9]*[0-9][0-9]*[^0-9]\([0-9][0-9]*\)'`
       ;;
      # PowerPC Linux
      ppc*::Linux::*::*)
        CPU=pp
        OS=li
        NAME="Linux (PowerPC)"
        VER=`expr $U_RELEASE : '[^0-9]*\([0-9][0-9]*\)[^0-9]'`
        REL=`expr $U_RELEASE : '[^0-9]*[0-9][0-9]*[^0-9]\([0-9][0-9]*\)'`
       ;;
      # Intel Linux
      i*::Linux::*::* )
	CPU=i3
	OS=li
	NAME="Linux (Intel)"
	VER=`expr $U_RELEASE : '[^0-9]*\([0-9][0-9]*\)[^0-9]'`
	REL=`expr $U_RELEASE : '[^0-9]*[0-9][0-9]*[^0-9]\([0-9][0-9]*\)'`
      ;;
      # Athlon 64 Linux
      x86_64::Linux::*::* )
	CPU=i3
	OS=li
	NAME="Linux (AMD 64)"
	VER=`expr $U_RELEASE : '[^0-9]*\([0-9][0-9]*\)[^0-9]'`
	REL=`expr $U_RELEASE : '[^0-9]*[0-9][0-9]*[^0-9]\([0-9][0-9]*\)'`
      ;;
      # PowerPC Linux
      ppc*::Linux::*::* )
        CPU=pp
        OS=li
        NAME="Linux (PowerPC)"
        VER=`expr $U_RELEASE : '[^0-9]*\([0-9][0-9]*\)[^0-9]'`
        REL=`expr $U_RELEASE : '[^0-9]*[0-9][0-9]*[^0-9]\([0-9][0-9]*\)'`
       ;;
      # Sequent (Intel)
      i*::DYNIX*::*::* )
	CPU=i3
	OS=dy
	NAME="Sequent DYNIX/ptx (Intel)"
	VER=`expr $U_VERSION : 'V\([0-9]\).*'`
	REL=`expr $U_VERSION : 'V[0-9].\([0-9].[0-9]\)' | sed 's/\.//g'`
      ;;

      # The Sun family
      *::SunOS::4.*::* )
	CPU=sp
	OS=su
	VER=4
	NAME="Sun SunOS (Sparc)"
	REL=`expr $U_RELEASE : '4.\([^_]*\)' | sed 's/[^0-9]//g'`
      ;;
      sun*::SunOS::5.*::* )
	CPU=sp
	OS=so
	VER=5
	NAME="Sun Solaris (Sparc)"
	REL=`expr $U_RELEASE : '5.\([0-9][0-9]*\).*' | sed 's/[^0-9]//g'`
      ;;
      *86*::SunOS::5.*::* )
	CPU=i3
	OS=so
	VER=5
	NAME="Sun Solaris (Intel)"
	REL=`expr $U_RELEASE : '5.\(.*\)' | sed 's/[^0-9]//g'`
      ;;
      *::SunOS::5.*::* )
	CPU=sp
	OS=so
	VER=5
	NAME="Sun Solaris (Sparc)"
	REL=`expr $U_RELEASE : '5.\([0-9][0-9]*\).*' | sed 's/[^0-9]//g'`
      ;;

      # HP
      *::HP-UX::*::* )
	CPU=pa
	OS=hp
	NAME="Hewlett-Packard HP-UX (PA-RISC)"
	VER=`expr $U_RELEASE : '[^.]*.\([0-9]*\).*'`
	REL=`expr $U_RELEASE : '[^.]*.[^.]*.\([0-9]*\)'`
      ;;

      # Data General
      *::dgux::5.4*::* )
	CPU=m8
	OS=dg
	VER=54
	NAME="Data General DG/UX (Motorola)"
	REL=`expr $U_RELEASE : '5.4\(.*\)' | sed 's/[^0-9]//g' | sed 's/\(.\).*\(.\)$/\1\2/'`
      ;;

      # Data General on Intel
      *::dgux::R4*::* )
	case `uname -p`  in
	  m* )
	    CPU=m8 ;;
	  * )
	    CPU=i3 ;;
	esac
	OS=dg
	VER=04
	NAME="Data General DG/UX (Intel)"
	REL=`expr $U_RELEASE : 'R4.\(.*\)' | sed 's/[^0-9]//g'`
        REL=`echo $REL | sed 's/\(..\).*/\1/'`
      ;;

      # OSF/1
      alpha::OSF1::*::* )
	CPU=ax
	OS=o1
	NAME="DEC OSF/1 (Alpha)"
	VER=`echo $U_RELEASE | sed 's/\([^.]*\).*/\1/' | sed 's/[^0-9]//g'`
	REL=`echo $U_RELEASE | sed 's/[^.]*.\(.*\)/\1/' | sed 's/[^0-9]//g'`
      ;;

      # ULTRIX
      *::ULTRIX::*::* )
	CPU=mp
	OS=ul
	NAME="DEC Ultrix (MIPS)"
	VER=`echo $U_RELEASE | sed 's/\([^.]*\).*/\1/' | sed 's/[^0-9]//g'`
	REL=`echo $U_RELEASE | sed 's/[^.]*.\(.*\)/\1/' | sed 's/[^0-9]//g'`
      ;;

      # IRIX
      *::IRIX::4.*::* )
	CPU=mp
	OS=ir
	VER=`echo $U_RELEASE | sed 's/\([^.]*\).*/\1/' | sed 's/[^0-9]//g'`
	REL=`echo $U_RELEASE | sed 's/[^.]*.\(.*\)/\1/' | sed 's/[^0-9]//g'`
      ;;
      
      *::IRIX::5.1::* )
	CPU=mp
	OS=ir
	VER=`echo $U_RELEASE | sed 's/\([^.]*.[^.]*\).*/\1/' | sed 's/[^0-9]//g'`
	REL=`echo $U_RELEASE | sed 's/[^.]*.[^.]*.\(.*\)/\1/' | sed 's/[^0-9]//g'`
      ;;

      # Note
      # If we ever get minor release numbers of 5.2 we'll have to do
      # something different
      *::IRIX::5.2::* )
	CPU=mp
	OS=ir
	VER=`echo $U_RELEASE | sed 's/\([^.]*\).*/\1/' | sed 's/[^0-9]//g'`
	REL=20
      ;;
      # Note
      # This system does not exist yet
      *::IRIX::5.2.*::* )
	CPU=mp
	OS=ir
	VER=`echo $U_RELEASE | sed 's/\([^.]*\).*/\1/' | sed 's/[^0-9]//g'`
	REL=`echo $U_RELEASE | sed 's/[^.]*.\(.*\)/\1/' | sed 's/[^0-9]//g'`
      ;;

      # catchall for other irix versions
      # 6.4 and later change from IRIX to IRIX64
      *::IRIX*::*::* )
	CPU=mp
	OS=ir
	VER=`echo $U_RELEASE | sed 's/\([^.]*\).*/\1/' | sed 's/[^0-9]//g'`
	REL=`echo $U_RELEASE | sed 's/[^.]*.\(.*\)/\1/' | sed 's/[^0-9]//g'`
      ;;

      # AIX
      # note that we can't figure out the patch level of a 3.2.x (x<4)
      # system (even IBM can't tell you immediately!)
      *::AIX::*::* )
	CPU=rs
	OS=ai
	NAME="IBM AIX (Risc)"
	VER=$U_VERSION
	REL=$U_RELEASE
      ;;

      # RISC OS (the mips variety, not acorn)
      # version 5 like output
      mips::*::*::RISCos )
	CPU=mp
	OS=ro
	VER=`echo $U_RELEASE | sed 's/\([^.]*\).*/\1/' | sed 's/[^0-9]//g'`
	REL=`echo $U_RELEASE | sed 's/[^.]*.\(.*\)/\1/' | sed 's/[^0-9]//g'`
      ;;
      # version 4 like output
      mips::*::*::UMIPS )
	CPU=mp
	OS=ro
	VER=`echo $U_RELEASE | sed 's/\([0-9]*\).*/\1/'`
	REL=`echo $U_RELEASE | sed 's/[0-9]*\(.*\)/\1/' | sed 's/[^0-9]//g'`
      ;;

      # Siemens Nixdorf mips R4000 (at least)
      R4000::*::*::* )
	CPU=mp
	OS=sx
	NAME="Siemens Nixdorf SINIX (MIPS)"
	VER=`echo $U_RELEASE | sed 's/\([0-9]*\).*/\1/'`
	REL=`echo $U_RELEASE | sed 's/[0-9]*\(.*\)/\1/' | sed 's/[^0-9]//g'`
      ;;

      # Motorola SVR4
      *88*::*::4*::* )
	CPU=m8
	OS=mo
	VER=`expr $U_VERSION : '[^V]*.\([^.]*\).*' | sed 's/[^0-9]//g'`
	REL=`expr $U_VERSION : '[^V]*.[^.]*.\(.*\)' | sed 's/[^0-9]//g'`
      ;;

      # windows nt with nutcracker
      *::Windows_NT::*::* )
	CPU=i3
	OS=wi
	VER="$U_RELEASE"
	REL="$U_VERSION"
      ;;

      DRS*::*::*::* )
	  PROC=`uname -p 2>/dev/null` || PROC=UNKNOWN
	  case "$PROC" in
	    sparc | SPARC )
	      CPU=sp
	      OS=nx
	      NAME="ICL DRS/NX (Sparc)"
	      ;;
	    i386 )
	      CPU=i386
	      OS=nx
	      NAME="ICL DRS/NX (Intel)"
	      ;;
	  esac

	  VER=`expr $U_VERSION : '\([0-9]\).*'`
	  REL=`expr $U_VERSION : '[0-9]..*\([0-9].[0-9]\)' | sed 's/\.//g'`
      ;;

      
      *::UnixWare::*::* )
	CPU=i3
	OS=un
	NAME="SCO UnixWare (Intel)"
	VER=`expr $U_VERSION : '\([0-9]\)'`
	REL=`expr $U_VERSION : '[0-9].\(.*\)' | sed -e 's/\.//'`
	if [ -z "$REL" ]; then
		REL=00
        elif [ "x`expr $REL : '[0-9]\([0-9]\)'`" = "x" ] ; then
		REL="$REL"0
	fi
	;;

      *::OpenUNIX::*::* )
        CPU=i3
        OS=un
        NAME="SCO UnixWare (Intel)"
        VER=`expr $U_VERSION : '\([0-9]\)'`
        REL=`expr $U_VERSION : '[0-9].\(.*\)' | sed -e 's/\.//'`
        if [ -z "$REL" ]; then
                REL=00
        elif [ "x`expr $REL : '[0-9]\([0-9]\)'`" = "x" ] ; then
                REL="$REL"0
        fi
        ;;

      # Various Intel based Unixen.  These seem particularly reluctant
      # to divulge their OS name, so we have to grep through
      # various system files to find the OS string

      *86*::*::*::* )
	if grep -s -i UnixWare /stand/boot 2>/dev/null 1>&2 || strings /stand/1/unix_mp 2>/dev/null | grep -s -i Unixware 2>/dev/null 1>&2
	then
          # It's some version of Unixware obviously
	  CPU=i3
	  OS=un
	  NAME="SCO UnixWare (Intel)"
          if expr $U_VERSION : 'D\([0-9]*.*\)' 2>/dev/null 1>&2
	  then
            # It's a date stamped version ; we dont yet know how to figure out
            # which so just pretend that it is unixware 212
            VER=02
            REL=12
          else
	    VER=`expr $U_VERSION : '\([0-9]\)'`
	    REL=`expr $U_VERSION : '[0-9].\(.*\)' | sed -e 's/\.//'`
	    if [ "x`expr $REL : '[0-9]\([0-9]\)'`" = "x" ] 
	    then
		REL="$REL"0
	    fi
          fi
	else
	  if [ "$U_SYSTEM" = "SCO_SV" ]
	  then
	    CPU=i3
	    OS=sc
	    VER=`expr $U_RELEASE : '^\([0-9]*\)'`
	    NAME="SCO OpenServer (Intel)"
	    # just the release string ie: 3.2v5.0.0
	    relstr=`uname -X | grep Release | awk '{ print $3 }'`
	    # just the major SCO version after the SVR? (3.2v) bit
	    U_VERSION=`expr ${relstr} : '[0-9.]*v\([0-9]\)[0-9.]*'`
	    REL=`expr ${U_RELEASE}::${U_VERSION} : '[0-9]*\(.*\)' | sed 's/[^0-9]//g'`
	  else
	    if grep -s 'The Santa Cruz Operation' /etc/gettydefs 2>/dev/null 1>&2
	    then
	      CPU=i3
	      OS=sc
	      NAME="SCO Unix (Intel)"
	      VER=`expr $U_RELEASE : '^\([0-9]*\)'`
	      REL=`expr ${U_RELEASE}::${U_VERSION} : '[0-9]*\(.*\)' | sed 's/[^0-9]//g'`
	    else
	      # DYNIX/ptx V2 doesn't return 'DYNIX' or 'ptx' in uname.
	      # This kludge may work, may not, it's either this
	      # or flip a coin!   
	      if grep -s 'ptx' /etc/versionlog 2>/dev/null 1>&2
	      then
		CPU=i3
		OS=dy
		NAME="Sequent DYNIX/ptx (Intel)"
		VER=`expr $U_VERSION : 'V\([0-9]\).*'`
		REL=`expr $U_VERSION : 'V[0-9].\([0-9].[0-9]\)' | sed 's/\.//g'`
	      else
	        # Assume OS must be System V Release 4.
	        CPU=i3
	        OS=sv
		NAME="System V Release 4 (Intel)"
	        VER=`expr $U_RELEASE : '^\([0-9]*\)'`
	        REL=`expr ${U_RELEASE}::${U_VERSION} : '[0-9]*\(.*\)' | sed 's/[^0-9]//g'`
	      fi
	    fi
	  fi
	fi
	;;	
    esac

    if [ -n "$CPU" -a -n "$OS" -a -n "$VER" -a -n "$REL" ]
    then
	break
    fi
done

# 5) Do sanity checking and cleanup
VER=`echo $VER | sed 's/[^0-9]//g'`
REL=`echo $REL | sed 's/[^0-9]//g'`

if [ -z "$CPU" -o -z "$OS" ]
then
  echo "$myname: !10! $msg_xdtarch_os_cpu"
  exit 10
fi

if [ -z "$VER" -o -z "$REL" ]
then
  echo "$myname: !11! $msg_xdtarch_ver_rel"
  exit 11
fi

# Add leading zeroes
REL=`echo 0$REL | sed 's/.*\(..\)/\1/'`
VER=`echo 0$VER | sed 's/.*\(..\)/\1/'`

# 6) So we now know it all

syscode=$CPU$OS$VER$REL

if  test -n "$codeonly"
then
    echo $CPU$OS
    exit 0
fi

if  test -n "$osonly"
then
    echo $VER$REL
    exit 0
fi

# 7) Check for codes given on the command line

if [ ! -z "$checkcodes" ]
then
    for i in $checkcodes
    do
	# Filter the input $checkcodes by matching CPU and OS, and strip
	# them off leaving just the VER and REL.  The tr command replaces
	# spaces by line-feeds, so that the following sort can do its stuff.
	posscodes=`echo $checkcodes | tr ' ' '\012' \
				| sed -ne "s/$CPU$OS//p" | sort -n`
	if [ -z "$posscodes" ]
	then				# None supplied for correct CPU+OS
	    echo >&2 "$myname: !5! $msg_xdtarch_no_match"
	    exit 5
	fi 

	# Some of them are the right platform.
	# The following algorithm returns the greatest possible code which
	# is older than this syscode, or, failing that, the least possible
	# code which is more recent than this one.

	for ver_rel in $posscodes
	do
	    if [ $VER$REL -eq $ver_rel ]
	    then 			# bingo we have this exact release
		echo $syscode
		exit 0
	    elif [ $VER$REL -gt $ver_rel ]
	    then 			# store this previous version
		priorcode=$CPU$OS$ver_rel
	    else 			# $VER$REL is < $ver_rel
		if [ -n "$priorcode" ]
		then
		    echo $priorcode
		    exit 0
		else
		    # Oh dear, we have no previous version so we should use
		    # the oldest newer version which is this current one ...
		    echo $CPU$OS$ver_rel
		    exit 0
		fi
	    fi
	done
    done
    if [ -n "$priorcode" ]
    then
        echo $priorcode
        exit 0
    fi
else
    if [ -n "$displayname" ]
    then
	echo "$NAME"
    else
	echo $syscode
    fi
fi

}
MACHINEARCH=`machinearch`


PATCH_TXT=patch.txt
KEYSTORE_PASS_FILE=keystore.pass
TMP_PATCH=tmp_patch
TOPLEVEL_PATCH_DIR=${TTAINSTDIR}/bin/${TMP_PATCH}

Usage_add() {
   echo "$info_long_usage"
   exit 1
}

Unpack() {
    PATCHFILE=$1
    PATCH_DIR=$2

    # Unpack the patch file
    echo "${info_unpacking} ${PATCHFILE}"
    mkdir ${PATCH_DIR} 2>>${PATCH_LOG}
    cd ${PATCH_DIR}
    
    case "${PATCHFILE}" in
	*.tar.gz)
	    gunzip -c ${PATCHFILE} > unzipped.tar
      if [ $? -ne 0 ] ; then 
        echo ${err_unzip}
	      cd ${TTAINSTDIR}/bin
	      rm -rf ${PATCH_DIR}
	      exit 1
      fi
	    PATCHFILE=unzipped.tar
	    ;;
	*.tar)
	    # Will be unpacked below
	    ;;
	*)
	    echo "${err_file_format}"
	    cd ${TTAINSTDIR}/bin
	    rm -rf ${PATCH_DIR}
	    exit 1
	    ;;
    esac

    tar -xf ${PATCHFILE}
    if [ $? -ne 0 ]; then
	echo ${err_untar}
	cd ${TTAINSTDIR}/bin
	rm -rf ${PATCH_DIR}
	exit 1
    fi
}

# Get the value of the parameter from patch.txt
Get_Value () {
    VALUE=`grep $1 ${PATCH_TXT} | tr '=' ' ' | awk '{for (i=2; i<=NF; i++) print $i}'`
    echo "${VALUE}"
}

# Check for any conflicts with the installed patches
CheckConflicts() {
    PATCH_DIR=$1

    # Extract conflicts data and check existing patches
    echo "${info_checking_conflicts}"
    CONFLICTS=`Get_Value CONFLICTS`
    if [ -z "${CONFLICTS}" ]; then
	# No conflicts defined
	return 0
    fi

    echo "${CONFLICTS}" | tr ' ' '\012' | 
    while read data; do
	CheckExists "${data}"
	if [ "$?" -eq 1 ]; then
	    cd ..
	    rm -rf ${PATCH_DIR}
	    echo "${err_patch_conflict}" ${data}
	    echo "${err_patch_failed_requirements}"
	    exit 1 # exits the sub-shell
	fi
    done

    # If conflicts exist, the patch directory no longer exists
    if [ -d ${PATCH_DIR} ]; then
	return 0
    else
	return 1
    fi
}

# Check that dependencies are resolved
CheckDependencies() {
    PATCH_DIR=$1

    # Extract dependencies data and check existing patches
    echo "${info_checking_dependencies}"
    DEPENDS=`Get_Value DEPENDENCIES`
    if [ -z "${DEPENDS}" ]; then
	# No dependencies defined
	return 0
    fi

    echo "${DEPENDS}" | tr ' ' '\012' |
    while read data; do
	# Check installed patches
	CheckExists "${data}"
	if [ "$?" -eq 0 ]; then
	    cd ..
	    rm -rf ${PATCH_DIR}
	    echo "${err_patch_depends} ${data}"
	    echo "${err_patch_failed_requirements}"
	    exit 1 # exits the sub-shell
	fi
    done
   
    # If dependencies exist, the patch directory no longer exists
    if [ -d ${PATCH_DIR} ]; then
	echo "${DEPENDS}"
	return 0
    else
	return 1
    fi  
}

AddPatchEntry() {
    NAME=$1
    TYPE=$2
    DATE=$3
    CPATH=$4
    OPATH=$5
    SGDVERSION=$6
    
    echo "${NAME}${DELIM}${TYPE}${DELIM}${DATE}${DELIM}${CPATH}${DELIM}${OPATH}${DELIM}${SGD_VERSION}${DELIM}${ACTIVE}${DELIM}" >> ${PATCH_LIST}
}

# Check whether a patch with the same name is already installed
CheckExists() {
    NAME=$1

    if [ ! -s "${PATCH_LIST}" ]; then
	return 0
    fi

    # Check whether the patch is already installed
    INSTALLED=`grep "^${NAME}${DELIM}" ${PATCH_LIST}`
    if [ -n "${INSTALLED}" ]; then
	return 1
    else
	return 0
    fi    
}

AddSuperseded() {
    TO_INSTALL=$1
    SUPERSEDES=$2

    LINE=`grep "^${SUPERSEDES}:" ${PATCH_CFG} 2> /dev/null`
    if [ -z "${LINE}" ]; then
	echo "${SUPERSEDES}:${TO_INSTALL}" >> ${PATCH_CFG}
    else
	FOUND=`echo ${LINE} | egrep ".*:.*,${TO_INSTALL},.*|.*:${TO_INSTALL},|.*:.*,${TO_INSTALL}\$"`
	if [ -z "${FOUND}" ]; then
	    NEW_LINE="${LINE},${TO_INSTALL}"
	    sed -e 's/'${LINE}'/'${NEW_LINE}'/' ${PATCH_CFG} > cfg.tmp
	    mv -f cfg.tmp ${PATCH_CFG}
	fi
    fi
}

PostPatchScript() {
  POST_SCRIPT=`Get_Value POST_PATCH_SCRIPT`

  if [ -n "${POST_SCRIPT}" ] ; then
    echo ${info_post_install}
    export TTAINSTDIR
    ./${POST_SCRIPT} 2>&1 | tee -a ${PATCH_LOG}

  fi
}

# Execute any pre-install script
# The exit code of the script should be 0 (success) or none zero (failure)
# On failure we tidy up and exit.
PrePatchScript() {
    patch_dir="$1"
    pre_script="`Get_Value PRE_PATCH_SCRIPT`"

    if [ -n "${pre_script}" ]
    then
        export TTAINSTDIR
        # Need admin to see output of script so no re-direction to log file
        # And check return code so no 'tee'
        ./"${pre_script}"
        if [ "$?" -ne 0 ]
        then
            cd "${patch_dir}"/..
            rm -rf "${patch_dir}" 2>&1 | tee -a "${PATCH_LOG}"
            exit 1
        fi
    fi
    return 0
}

# Binary details are in the form "name[:<user>:<group>:<permissions>]"
CopyBinary() {
    BINARY_DETAILS=$1
    BINARY_NAME=$2

    # Move the binary to the correct location
    \cp ${BINARY_NAME} "${TTAINSTDIR}/bin/bin/"
    echo "${info_binary} ${BINARY_NAME}"

    # Split the details to get the user/group and permissions
    USER=`echo "${BINARY_DETAILS}" | ${AWK} -F ":" '{print $2}'`
    case "${USER}" in
	"")
    	    # No details supplied
	    return
	    ;;
	"PRIVUSR")
	    USER=${privusr}
	    ;;
    esac

    GROUP=`echo "${BINARY_DETAILS}" | ${AWK} -F ":" '{print $3}'`
    case "${GROUP}" in
	"PRIVGRP")
	    GROUP=${privgrp}
           ;;
    esac
    
    PERMISSIONS=`echo "${BINARY_DETAILS}" | ${AWK} -F ":" '{print $4}'`
    
    chown ${USER}:${GROUP} ${TTAINSTDIR}/bin/bin/${BINARY_NAME}
    chmod ${PERMISSIONS} ${TTAINSTDIR}/bin/bin/${BINARY_NAME}
}

Add_Apache()
{
    NEW_APACHE_VERSION=$1
    PREVIOUS_apache=`cat "${TTAINSTDIR}/var/info/apacheversion"`
    PATCH_NAME=`Get_Value APACHE_PATCH`
    # Check new version is not same
    if [ "${NEW_APACHE_VERSION}" = "${PREVIOUS_apache}" ]; then
	    echo "${err_already_installed1}${PATCH_NAME}${err_already_installed2}"
      return 1
    fi

    WEBSERVER_DIR=${TTAINSTDIR}/webserver
    APACHE_DIR=${WEBSERVER_DIR}/apache
    OLD_APACHE_DIR="${APACHE_DIR}/${PREVIOUS_apache}"
    NEW_APACHE_DIR=${APACHE_DIR}/${NEW_APACHE_VERSION}
    SGD_VERSION=`GetSGDVersion`

    # The directory might already be present if upgrading a previously patched
    # server.
    # The upgrade will have reverted to it's default apache version, but will have
    # left the directories of the newer version intact.
    # We still need to apply the patch.
    # Rename the existing directory and carry on. Bugs 20840050 20820949
    if [ -d "${NEW_APACHE_DIR}" ] ; then
      mv -f ${NEW_APACHE_DIR} ${NEW_APACHE_DIR}.pre_${SGD_VERSION}
    fi

    echo ${info_webserver_apache}
    
    # Move the new  apache into the correct location
    mv -f ${NEW_APACHE_VERSION} ${APACHE_DIR}
    \cp -rpP  ${OLD_APACHE_DIR}/conf ${NEW_APACHE_DIR}
    cd ${NEW_APACHE_DIR}/conf
    find . -type f -exec grep -l "${OLD_APACHE_DIR}" {} \; -print 2>/dev/null | while read file
    do
      sed "s|${OLD_APACHE_DIR}|${NEW_APACHE_DIR}|g" $file > $file.tmp
      cp $file.tmp $file
      rm $file.tmp
    done

    cd ${APACHE_DIR}
    # Set the correct file ownership
    chown -R ${privusr}:${privgrp} ${NEW_APACHE_VERSION}

    # Update var/info/apacheversion 
    echo "${NEW_APACHE_VERSION}" > ${TTAINSTDIR}/var/info/tmp-apacheversion
    mv -f ${TTAINSTDIR}/var/info/apacheversion ${TTAINSTDIR}/var/info/apacheversion.${PREVIOUS_apache}
    mv -f ${TTAINSTDIR}/var/info/tmp-apacheversion ${TTAINSTDIR}/var/info/apacheversion
    chown ${privusr}:${privgrp} ${TTAINSTDIR}/var/info/apacheversion
    chmod 640 ${TTAINSTDIR}/var/info/apacheversion

    # Update any previous patches to be inactive
    # Update the patch log
    if [ -s "${PATCH_LIST}" ]; then
	    # Look for an old version which is superceded by this update
	    ENTRY=`grep "${DELIM}${TYPE}${DELIM}" ${PATCH_LIST} | grep "${PREVIOUS_apache}"`
	
	    if [ -n "${ENTRY}" ]; then
	      # Update the entry to show that version as now inactive
	      UpdateEntry "${ENTRY}"
	    fi
    fi

    # Add new patch entry 
    DATE=`date`
    AddPatchEntry "${PATCH_NAME}" "${TYPE}" "${DATE}" "${NEW_APACHE_DIR}" "${OLD_APACHE_DIR}" "${SGD_VERSION}"

    return 0
}

Add_Tomcat()
{
    NEW_TOMCAT_VERSION=$1
    PREVIOUS_tomcat=`cat "${TTAINSTDIR}/var/info/tomcatversion"`
    PATCH_NAME=`Get_Value TOMCAT_PATCH`

    # Check new version is not same
    if [ ${NEW_TOMCAT_VERSION} = ${PREVIOUS_tomcat} ]; then
	    echo "${err_already_installed1}${PATCH_NAME}${err_already_installed2}"
      return 1
    fi

    WEBSERVER_DIR=${TTAINSTDIR}/webserver
    TOMCAT_DIR=${WEBSERVER_DIR}/tomcat
    OLD_TOMCAT_DIR="${TOMCAT_DIR}/${PREVIOUS_tomcat}"
    NEW_TOMCAT_DIR=${TOMCAT_DIR}/${NEW_TOMCAT_VERSION}
    SGD_VERSION=`GetSGDVersion`

    # The directory might already be present if upgrading a previously patched
    # server.
    # The upgrade will have reverted to it's default tomcat version, so we
    # still need to apply the patch.
    # Rename the existing directory and carry on. Bugs 20840050 20820949
    if [ -d "${NEW_TOMCAT_DIR}" ] ; then
      mv -f ${NEW_TOMCAT_DIR} ${NEW_TOMCAT_DIR}.pre_${SGD_VERSION}
    fi

    echo ${info_webserver_tomcat}
    
    # Move the new tomcat into the correct location
    mv -f ${NEW_TOMCAT_VERSION} ${TOMCAT_DIR}
    \cp -rpP  ${OLD_TOMCAT_DIR}/conf ${NEW_TOMCAT_DIR}
    cd ${NEW_TOMCAT_DIR}/conf
    find . -type f -exec grep -l "${OLD_TOMCAT_DIR}" {} \; -print 2>/dev/null | while read file
    do
      sed "s|${OLD_TOMCAT_DIR}|${NEW_TOMCAT_DIR}|g" $file > $file.tmp
      cp $file.tmp $file
      rm $file.tmp
    done
    cd ${TOMCAT_DIR}

    # Update var/info/tomcatversion 
    echo "${NEW_TOMCAT_VERSION}" > ${TTAINSTDIR}/var/info/tmp-tomcatversion
    mv -f ${TTAINSTDIR}/var/info/tomcatversion ${TTAINSTDIR}/var/info/tomcatversion.${PREVIOUS_tomcat}
    mv -f ${TTAINSTDIR}/var/info/tmp-tomcatversion ${TTAINSTDIR}/var/info/tomcatversion
    chown ${privusr}:${privgrp} ${TTAINSTDIR}/var/info/tomcatversion
    chmod 640 ${TTAINSTDIR}/var/info/tomcatversion

    # Copy over webapps - stuff not covered by config-install
    # which is looking for files in $INSTALL_DIR/bin/java
    \cp -p ${PREVIOUS_tomcat}/webapps/sgdadmin.war ${NEW_TOMCAT_VERSION}/webapps 2>>${PATCH_LOG}
    \cp -rpP ${PREVIOUS_tomcat}/webapps/sgd ${NEW_TOMCAT_VERSION}/webapps 2>>${PATCH_LOG}
    \cp -rpP ${PREVIOUS_tomcat}/webapps/sgdadmin ${NEW_TOMCAT_VERSION}/webapps 2>>${PATCH_LOG}
    # Set the correct file ownership
    chown -R ${webservusr}:${privgrp} ${NEW_TOMCAT_VERSION} 2>/dev/null

    # Update any previous patches to be inactive
    # Update the patch log
    if [ -s "${PATCH_LIST}" ]; then
      # Look for an old version which is superceded by this update
      ENTRY=`grep "${DELIM}${TYPE}${DELIM}" ${PATCH_LIST} | grep "${PREVIOUS_tomcat}"`

      if [ -n "${ENTRY}" ]; then
        # Update the entry to show that version as now inactive
        UpdateEntry "${ENTRY}"
      fi
    fi

    # Add new patch entry 
    DATE=`date`
    AddPatchEntry "${PATCH_NAME}" "${TYPE}" "${DATE}" "${NEW_TOMCAT_DIR}" "${OLD_TOMCAT_DIR}" "${SGD_VERSION}"
    
    return 0
}

Add_Webserver() {

    PATCH_DIR=$1
    APACHE_RET=1
    TOMCAT_RET=1
    WS_CONFIG=webserver_config

    CheckDependencies "${PATCH_DIR}"
    if [ "$?" -eq 1 ]; then
      return
    fi

    # Copy in webserver config script
    if [ -f "${PATCH_DIR}/${WS_CONFIG}" ] ; then
      # if file exist change permissions so writable
      if [ -f "${TTAINSTDIR}/bin/scripts/${WS_CONFIG}" ] ; then
        chmod 750 "${TTAINSTDIR}/bin/scripts/${WS_CONFIG}"
      fi
      \cp ${WS_CONFIG} "${TTAINSTDIR}/bin/scripts"
      chmod 550 "${TTAINSTDIR}/bin/scripts/${WS_CONFIG}"
      chown ${privusr}:${privgrp} "${TTAINSTDIR}/bin/scripts/${WS_CONFIG}"
    fi

    if [ ! -f "${TTAINSTDIR}/bin/scripts/webserver_config" ] ; then
      echo ${err_webserver_config_missing}
      exit
    fi

    # Read patch data
    APACHE_VERSION=`Get_Value APACHE_VERSION`
    if [ -n "${APACHE_VERSION}" ]; then
		  Add_Apache "${APACHE_VERSION}"
      APACHE_RET=$?
    fi

    cd ${PATCH_DIR}
    TOMCAT_VERSION=`Get_Value TOMCAT_VERSION`
    if [ -n "${TOMCAT_VERSION}" ]; then
      Add_Tomcat "${TOMCAT_VERSION}"
      TOMCAT_RET=$?
    fi

    # If successfully installed apache or tomcat patch then
    # Run webserver config 
    if [ "${APACHE_RET}" = "0" -o "${TOMCAT_RET}" = "0" ]; then
      INSTDIR=${TTAINSTDIR}
      PATCH=1
      UPGRADE=${SGD_VERSION}
      LOGFILE=${PATCH_LOG}
      PRODUCT_VERSION_FULL=${SGD_VERSION}
      export PREVIOUS_apache PREVIOUS_tomcat INSTDIR PATCH UPGRADE LOGFILE PRODUCT_VERSION_FULL
      echo ${info_webserver_config}
      ${TTAINSTDIR}/bin/scripts/webserver_config >> ${LOGFILE}
      ${TTAINSTDIR}/bin/tarantella stop >> ${LOGFILE} 
    
      # Execute any post patch script
      cd ${PATCH_DIR}
      PostPatchScript
    fi

    # Remove the temporary patch directory
    cd ${PATCH_DIR}/..
    rm -rf ${PATCH_DIR} 2>>${PATCH_LOG}
}

Add_Jserver() {
    NAME=$1
    PATCH_DIR=$2

    CheckConflicts "${PATCH_DIR}"
    if [ "$?" -eq 1 ]; then
	return
    fi

    CheckDependencies "${PATCH_DIR}"
    if [ "$?" -eq 1 ]; then
	return
    fi

    # Patch meets the requirements so go ahead with the installation
    echo "${info_jserver_install} ${NAME}"
    if [ ! -d "${BACKUP_JSERVER_DIR}" ]; then
	mkdir "${BACKUP_JSERVER_DIR}"
    fi

    [ -x "/usr/bin/nawk" ] && AWK="nawk" || AWK="awk"

    DATE=`date`
    SGD_VERSION=`GetSGDVersion`

    # Get the jar file
    JAR=`Get_Value JAR`

    JAR_EXE=`jar`

    # Extract the content of the jar
    ${JAR_EXE} -xf ${JAR}

    # Extract superseded data
    SUPERSEDED=`Get_Value SUPERSEDED`
    echo "${SUPERSEDED}" | tr ' ' '\012' |
    while read data; do
	if [ -z "${data}" ]; then
	    continue
	fi
	
	AddSuperseded ${NAME} ${data}
	# Handle each superseded patch
	grep "^${data}${DELIM}" ${PATCH_LIST} | grep "${DELIM}jserver${DELIM}" |
	while read ENTRY; do
	    CLASS_PATH=`echo "${ENTRY}" | ${AWK} -F "${DELIM}" '{print $4}'`
	    CLASS=`echo "${ENTRY}" | ${AWK} -F "${DELIM}" '{print $5}' | sed -e 's:'${TTAINSTDIR}/bin/java/':'':'`
	    UpdateEntry "${ENTRY}"
   	    # Add a new entry for the patch class
	    AddPatchEntry "${NAME}" "jserver" "${DATE}" "${CLASS}:${TTAINSTDIR}/bin/java/${NAME}.jar" "${CLASS_PATH}" "${SGD_VERSION}"
	done
    done

    mv -f ${JAR} ${TTAINSTDIR}/bin/java/${NAME}.jar
    # Change the classpath to include it
    JAR_LOCATION="\${JAVADIR}/${NAME}.jar"
    sed -e 's%'CLASSPATH='%'CLASSPATH=${JAR_LOCATION}:'%' ${TTAINSTDIR}/bin/scripts/jserverstart > tmp.start
    \cp tmp.start ${TTAINSTDIR}/bin/scripts/jserverstart
    
    # For each file not already covered by a superseding patch
    find . -name "*.class" | sed -e 's:'./'::' | while read CLASS; do
	AddPatchEntry "${NAME}" "jserver" "${DATE}" "${CLASS}:${TTAINSTDIR}/bin/java/${NAME}.jar" "${TTAINSTDIR}/bin/java/${CLASS}" "${SGD_VERSION}"
    done

    # Output message
    echo "${info_jserver_complete}"

    # Execute any post patch script
    cd  ${PATCH_DIR}
    PostPatchScript

    # Tidy up
    cd ..
    rm -rf ${PATCH_DIR} 2> /dev/null

    # Update log
    AddedPatch "${DATE}" "jserver" "${NAME}"    
}

Add_Binary() {
    NAME=$1
    PATCH_DIR=$2

    CheckConflicts "${PATCH_DIR}"
    if [ "$?" -eq 1 ]; then
	return
    fi

    CheckDependencies "${PATCH_DIR}"
    if [ "$?" -eq 1 ]; then
	return
    fi

    # Patch meets the requirements so go ahead with the installation
    echo "${info_binary_install} ${NAME}"
    if [ ! -d "${BACKUP_BIN_DIR}" ]; then
	mkdir "${BACKUP_BIN_DIR}"
    fi

    [ -x "/usr/bin/nawk" ] && AWK="nawk" || AWK="awk"
    DATE=`date`
    SGD_VERSION=`GetSGDVersion`
    # Extract superseded data
    SUPERSEDED=`Get_Value SUPERSEDED`
    if [ -n "${SUPERSEDED}" ]; then
	echo "${SUPERSEDED}" | tr ' ' '\012' |
	while read data; do
	    AddSuperseded ${NAME} ${data}
	    # For each superseded patch, check whether it is currently installed
	    grep "^${data}${DELIM}" ${PATCH_LIST} | grep "${DELIM}binary${DELIM}" | 
	    while read ENTRY; do
		# If the patch is already inactive, skip it
		IS_INACTIVE=`echo "${ENTRY}" | ${AWK} -F "${DELIM}" '{print $7}' | grep ${INACTIVE}`
		if [ -n "${IS_INACTIVE}" ]; then
		    continue
		fi

	        # Handle each binary in the patch
		PATCH_PATH=`echo "${ENTRY}" | ${AWK} -F "${DELIM}" '{print $4}'`
		BINARY_NAME=`echo "${PATCH_PATH}" | sed -e 's:'${TTAINSTDIR}/bin/bin/':'':'`
		NEW_PATCH_PATH="${BACKUP_BIN_DIR}/${BINARY_NAME}.${data}"
   	        # Back up the superseded binary
		\cp -p "${PATCH_PATH}" "${NEW_PATCH_PATH}"

	        # Add in the new binary from the patch
		BINARY_DETAILS=`Get_Value BINARY | grep "${BINARY_NAME}:"`
		CopyBinary "${BINARY_DETAILS}" "${BINARY_NAME}"
		# Remove binary from patch dir so not handled again by none superseded code below
		rm -f "${BINARY_NAME}"

	        # Modify the patch list for the superseded binary
		NEW_ENTRY=`echo "${ENTRY}" | sed -e 's/'${DELIM}${ACTIVE}${DELIM}'/'${DELIM}${INACTIVE}${DELIM}'/g' | sed -e 's:'${DELIM}${PATCH_PATH}${DELIM}':'${DELIM}${NEW_PATCH_PATH}${DELIM}':'`
		UpdateEntry "${ENTRY}" "${NEW_ENTRY}"
	        # Create a new entry for the patch binary
		AddPatchEntry "${NAME}" "binary" "${DATE}" "${TTAINSTDIR}/bin/bin/${BINARY_NAME}" "${NEW_PATCH_PATH}" "${SGD_VERSION}"
	    done
	done
    fi
    
    # Extract list of binaries included in the patch
    BINARIES=`Get_Value BINARY`
    # Move any that were not handled by the superseded logic to the correct location
    echo "${BINARIES}" | sort -u | while read binary; do
	BNAME=`echo ${binary} | ${AWK} -F ":" '{print $1}'`
	if [ -s "${BNAME}" ]; then
            EXISTING_ENTRY=`grep "${DELIM}${TTAINSTDIR}/bin/bin/${BNAME}${DELIM}" ${PATCH_LIST} | grep "${DELIM}${ACTIVE}${DELIM}" | grep -v "^${NAME}${DELIM}"`
            if [ -n "${EXISTING_ENTRY}" ]; then
               EXISTING_NAME=`echo "${EXISTING_ENTRY}" | ${AWK} -F "${DELIM}" '{print $1}'`
               BACKUP_PATH="${BACKUP_BIN_DIR}/${BNAME}.${EXISTING_NAME}"
            else
    	       BACKUP_PATH="${BACKUP_BIN_DIR}/${BNAME}.${SGD_VERSION}"
            fi

    	    # Back up the original binary
	    \cp -p "${TTAINSTDIR}/bin/bin/${BNAME}" "${BACKUP_PATH}"
   	    # Add in the new binary
	    CopyBinary "${binary}" "${BNAME}"

            # Update the old entry if required
            if [ -n "${EXISTING_ENTRY}" ]; then
               NEW_ENTRY=`echo "${EXISTING_ENTRY}" | sed -e 's/'${DELIM}${ACTIVE}${DELIM}'/'${DELIM}${INACTIVE}${DELIM}'/g' | sed -e 's:'${DELIM}${TTAINSTDIR}/bin/bin/${BNAME}${DELIM}':'${DELIM}${BACKUP_PATH}${DELIM}':'`
               UpdateEntry "${EXISTING_ENTRY}" "${NEW_ENTRY}"
            fi

	    # Add a new entry to the patch list
	    AddPatchEntry "${NAME}" "binary" "${DATE}" "${TTAINSTDIR}/bin/bin/${BNAME}" "${BACKUP_PATH}" "${SGD_VERSION}"
	fi
    done

    echo "${info_binary_complete}"

    # Execute any post patch script
    cd ${PATCH_DIR}
    PostPatchScript

    # Tidy up
    cd ..
    rm -rf ${PATCH_DIR} 2> /dev/null

    # Log the status
    AddedPatch "${DATE}" "binary" "${NAME}"
}

Update_Patch_Commands() {
    FILELIST=$1
    LOG_MSG=$2
    PATCH_NAME=$3
    
    # Pass the other files off to patch_update
    exec ${TTAINSTDIR}/bin/scripts/patch_update ${PATCH_DIR} "${FILELIST}" "${LOG_MSG}" "${PATCH_LOG}" "${PATCH_NAME}" "${PATCH_CFG}" ${PATCH_ADD_CALLBACK}
}

Add_Commands() {
    NAME=$1
    PATCH_DIR=$2

    # Handle the patch_update first, as it can't update itself
    IS_UPDATE=`ls patch_update 2> /dev/null`
    if [ -n "${IS_UPDATE}" ]; then
	\cp patch_update ${TTAINSTDIR}/bin/scripts
	chown ${privusr}:${privgrp} ${TTAINSTDIR}/bin/scripts/patch_update
	UpdateRef "patch_update" "${NAME}" "${PATCH_CFG}"
    fi

    # Update any other available patch commands
    TO_UPDATE=`ls patch_* en-us/patch_* 2> /dev/null | grep -v update`
    if [ -z "${TO_UPDATE}" ]; then
	# Only patch_update included
	cd ..
	rm -rf ${PATCH_DIR} 2> /dev/null
    else
	echo ${info_update_commands}
	DATE=`date`
	LOG_MSG="${DATE} - ${info_updated_commands} : ${NAME}"
	Update_Patch_Commands "${TO_UPDATE}" "${LOG_MSG}" "${NAME}"
    fi
}

Add_Bundle() {
    # NAME gets changed a lot, use BUNDLE_NAME
    BUNDLE_NAME=$1
    TTA_PATCH_DIR=$2

    # Check top level bundle dependency
    CheckDependencies "${TTA_PATCH_DIR}"
    # If the check fails don't go any further
    # tmp_patch already tidied up by CheckDependencies
    if [ "$?" -eq 1 ]; then
      exit 1
    fi

    # Get the list of components
    COMPONENTS=`Get_Value COMPONENT`
    echo ${info_read_bundle}

    # Special case. If the bundle contains a new set of patch commands.
    # Handle the commands patch first.
    # Patch update will then callback patch_add to install the rest of the bundle
    COMMANDS=`echo "${COMPONENTS}" | grep "^commands_"`
    # If contains new patch commands
    if [ -n "${COMMANDS}" ] ; then
        Unpack "${TTA_PATCH_DIR}/${COMMANDS}" "${TTA_PATCH_DIR}/${TMP_PATCH}"
        rm -f "${TTA_PATCH_DIR}/${COMMANDS}" unzipped.tar 2>/dev/null
        PATCH_ADD_CALLBACK="true"
        NAME=`Get_Value NAME`
        # Remove from bundle's patch.txt as already handled
        grep -v "^COMPONENT=${COMMANDS}" ../patch.txt > ../patch.txt.tmp
        mv ../patch.txt.tmp ../patch.txt
        Add_Commands ${NAME} "${TTA_PATCH_DIR}/${TMP_PATCH}"
    fi

    # Run any pre installation script at bundle level
    PrePatchScript "${TTA_PATCH_DIR}"

    echo "${COMPONENTS}" | while read file; do
        # Unpack the tar file
	Unpack "${TTA_PATCH_DIR}/${file}" "${TTA_PATCH_DIR}/${TMP_PATCH}"
  rm -f "${TTA_PATCH_DIR}/${file}" unzipped.tar 2>/dev/null
	
        # Run any pre installation script at component level
        PrePatchScript "${TTA_PATCH_DIR}${TMP_PATCH}"

        # Get the type
        TYPE=`Get_Value TYPE`
        case "${TYPE}" in
            jserver)
                Add_Jserver "${BUNDLE_NAME}" "${TTA_PATCH_DIR}/${TMP_PATCH}"
                ;;
            binary)
                Add_Binary "${BUNDLE_NAME}" "${TTA_PATCH_DIR}/${TMP_PATCH}"
                ;;
            JVM)
                Add_JVM "${TTA_PATCH_DIR}/${TMP_PATCH}"
                ;;
            webserver)
                Add_Webserver "${TTA_PATCH_DIR}/${TMP_PATCH}"
                ;;
            delete)
                Add_Delete ${BUNDLE_NAME} "${TTA_PATCH_DIR}/${TMP_PATCH}"
                ;;
            webcomp)
                Add_SGDWebComponents ${BUNDLE_NAME} "${TTA_PATCH_DIR}/${TMP_PATCH}" 
                ;;
            file)
                Add_File ${BUNDLE_NAME} "${TTA_PATCH_DIR}/${TMP_PATCH}"
                ;;
	esac
    done

  # Execute any post patch script
  cd ${TTA_PATCH_DIR}
  PostPatchScript
  
    # Tidy up
    if [ "${TTA_PATCH_DIR}" ]; then
	cd ${TTAINSTDIR}/bin
	rm -rf ${TTA_PATCH_DIR}
    fi
}

Delete_File() {
  DEST="$1"


  \rm -rf ${DEST}
}

Copy_File() {
  DETAILS=$1
  PATCH_DIR=$2
  DEST=$3

  # If destination a link delete it - Solaris
  if [ -h "${DEST}" ] ; then
    rm -f ${DEST}
  fi

  FILENAME=`echo "${DETAILS}" | ${AWK} -F ":" '{print $1}'`
  \cp -rP ${PATCH_DIR}/${FILENAME} ${DEST}

  Set_Permissions ${DEST} ${DETAILS}
}

Set_Permissions() {
  DEST=$1
  DETAILS=$2

  # Split the details to get the user/group and permissions
  USER=`echo "${DETAILS}" | ${AWK} -F ":" '{print $3}'`
  if [ -n "${USER}" ] ; then
    case "${USER}" in
      "PRIVUSR")
        USER=${privusr}
      ;;
      "WEBUSR")
        USER=${webservusr}
      ;;
    esac
    chown -h ${USER} ${DEST}
  fi

  GROUP=`echo "${DETAILS}" | ${AWK} -F ":" '{print $4}'`
  if [ -n "${GROUP}" ] ; then
    case "${GROUP}" in
      "PRIVGRP")
        GROUP=${privgrp}
      ;;
    esac
    chgrp -h ${GROUP} ${DEST}
  fi

  PERMISSIONS=`echo "${DETAILS}" | ${AWK} -F ":" '{print $5}'`
  if [ -n "${PERMISSIONS}" ] ; then
    chmod ${PERMISSIONS} ${DEST}
  fi

}

Add_Delete() {

  NAME="$1"
  PATCH_DIR="$2"

  CheckDependencies "${PATCH_DIR}"
  if [ "$?" -eq 1 ]; then
    return
  fi

  echo "${info_file_install} ${NAME}"
  [ -x "/usr/bin/nawk" ] && AWK="nawk" || AWK="awk"

  DATE=`date`
  SGD_VERSION=`GetSGDVersion`

  # Handle patch
  FILES=`Get_Value FILE`

  # handle files and directories
  echo "${FILES}" | sort -u | while read file; do
    cd ${PATCH_DIR}
    FILENAME="`echo "${file}" | ${AWK} -F ":" '{print $1}'`"

    # Backup any existing file
    FULLFILE="${TTAINSTDIR}/${FILENAME}"
    EXISTING_ENTRY="`grep "${DELIM}${FULLFILE}${DELIM}" ${PATCH_LIST} | grep "${DELIM}${ACTIVE}${DELIM}" | grep -v "^${NAME}${DELIM}"`"
    if [ -n "${EXISTING_ENTRY}" ];
    then
       EXISTING_NAME="`echo ${EXISTING_ENTRY} | ${AWK} -F "${DELIM}" '{print $1}'`"
       BACKUP_FILE="${BACKUP_FILE_DIR}/${FILENAME}.${EXISTING_NAME}"
    else
       BACKUP_FILE="${BACKUP_FILE_DIR}/${FILENAME}.${SGD_VERSION}"
    fi

    if [ -f "${FULLFILE}" -o -d "${FULLFILE}" ];
    then
      mkdir -p `dirname ${BACKUP_FILE}`
      # Only backup if not already backup up.
      # Useful to check incase a file is duplicated in same patch
      if [ ! -f "${BACKUP_FILE}" ] ; then
        \cp -rpP "${FULLFILE}" "${BACKUP_FILE}"
      fi
    fi
    echo "${info_binary} ${FULLFILE}"
    Delete_File "${FULLFILE}"

    if [ -n "${EXISTING_ENTRY}" ];
    then
       NEW_ENTRY=`echo "${EXISTING_ENTRY}" | sed -e 's/'${DELIM}${ACTIVE}${DELIM}'/'${DELIM}${INACTIVE}${DELIM}'/g' | sed -e 's:'${DELIM}${FULLFILE}${DELIM}':'${DELIM}${BACKUP_FILE}${DELIM}':'`
       UpdateEntry "${EXISTING_ENTRY}" "${NEW_ENTRY}"
    fi

    AddPatchEntry "${NAME}" "${TYPE}" "${DATE}" "${FULLFILE}" "${BACKUP_FILE}" "${SGD_VERSION}"

  done

  # Execute any post patch script
  cd ${PATCH_DIR}
  PostPatchScript
  # Reuse message
  echo "${info_webcomp_complete}"
  # Tidy up
  cd ..
  rm -rf ${PATCH_DIR} 2> /dev/null

  # Update log
  AddedPatch "${DATE}" "delete" "${NAME}"
}

Add_File() {
  NAME=$1
  PATCH_DIR=$2

  CheckDependencies "${PATCH_DIR}"
  if [ "$?" -eq 1 ];
  then
    return
  fi

  echo "${info_file_install} ${NAME}"
  [ -x "/usr/bin/nawk" ] && AWK="nawk" || AWK="awk"

  DATE=`date`
  SGD_VERSION=`GetSGDVersion`
  # Superceded patches
  SUPERSEDED=`Get_Value SUPERSEDED`
  if [ -n "${SUPERSEDED}" ]; then
    echo "${SUPERSEDED}" | tr ' ' '\012' |
    while read data; do
      if [ -z "${data}" ]; then
        continue
      fi

      AddSuperseded ${NAME} ${data}
      # For each superseded patch, check whether it is currently installed
      grep "^${data}${DELIM}" ${PATCH_LIST} | grep "${DELIM}file${DELIM}" |
      {
        while read ENTRY; do
          # If the patch is already inactive, skip it
          IS_INACTIVE=`echo "${ENTRY}" | ${AWK} -F "${DELIM}" '{print $7}' | grep ${INACTIVE}`
          if [ -n "${IS_INACTIVE}" ]; then
            continue
          fi

          # Handle each file in the superseded patch
          PATCH_PATH=`echo "${ENTRY}" | ${AWK} -F "${DELIM}" '{print $4}'`
          FILE_NAME=`basename "${PATCH_PATH}"`
          BACKUP_PATCH_FILE=`echo "${PATCH_PATH}" | sed 's:'${TTAINSTDIR}':'${BACKUP_FILE_DIR}':'`.${data}

          # Back up the superseded file
          # Only backup if not already backup up.
          # Useful to check incase a file is duplicated in same patch
          mkdir -p `dirname ${BACKUP_PATCH_FILE}`
          if [ ! -f "${BACKUP_PATCH_FILE}" ] ; then
            \cp -rpP "${PATCH_PATH}" "${BACKUP_PATCH_FILE}"
          fi

          RELATIVE_PATH=`echo "${PATCH_PATH}" | sed 's:'${TTAINSTDIR}/'::'`
          # Copy new file
          FILE_DETAILS=`Get_Value FILE | sort -u | grep "^${RELATIVE_PATH}:"`
          if [ -z "${FILE_DETAILS}" ] ; then
            FILE_DETAILS=`Get_Value FILE | sort -u | grep "^${FILE_NAME}:"`
          fi
          if [ -z "${FILE_DETAILS}" ] ; then
            FILE_DETAILS=`Get_Value FILE | sort -u | grep "^${FILE_NAME}$"`
          fi
          echo "${info_binary} ${PATCH_PATH}"
          Copy_File ${FILE_DETAILS} ${PATCH_DIR} "${PATCH_PATH}" 

          # Add file to list of files handled by superseding to be removed
          # before normal patch handling
          FILE_TO_REMOVE=`echo "${FILE_DETAILS}" | ${AWK} -F ":" '{print $1}'`
          HANDLED="${HANDLED} ${FILE_TO_REMOVE}"

          # Modify the patch list for the superseded file
          NEW_ENTRY=`echo "${ENTRY}" | sed -e 's/'${DELIM}${ACTIVE}${DELIM}'/'${DELIM}${INACTIVE}${DELIM}'/g' | sed -e 's:'${DELIM}${PATCH_PATH}${DELIM}':'${DELIM}${BACKUP_PATCH_FILE}${DELIM}':'`
          UpdateEntry "${ENTRY}" "${NEW_ENTRY}"
          # Create a new entry for the patch file
          AddPatchEntry "${NAME}" "file" "${DATE}" "${PATCH_PATH}" "${BACKUP_PATCH_FILE}" "${SGD_VERSION}"
        done
        # Remove form tmp_patch so not handled by code below.
        rm -f ${HANDLED} 2>/dev/null
      }
    done
  fi

  # Handle patch
  FILES=`Get_Value FILE`

  # Create any dirs first
  echo "${FILES}" | sort -u | while read file; do
    cd ${PATCH_DIR}
    FILENAME=`echo "${file}" | ${AWK} -F ":" '{print $1}'`
    # If a directory just mkdir and set ownership and permissions
    if [ -d "${FILENAME}" -a ! -d ${TTAINSTDIR}/${FILENAME} ]; then
        mkdir -p ${TTAINSTDIR}/${FILENAME} 2>/dev/null
        Set_Permissions ${TTAINSTDIR}/${FILENAME} ${file}
        AddPatchEntry "${NAME}" "file" "${DATE}" "${TTAINSTDIR}/${FILENAME}" "" "${SGD_VERSION}"
        echo "${info_binary} ${TTAINSTDIR}/${FILENAME}"
    fi
  done

  # handle files
  echo "${FILES}" | sort -u | while read file; do
    cd ${PATCH_DIR}
    FILENAME=`echo "${file}" | ${AWK} -F ":" '{print $1}'`
    # File valid and not handled in superseded above
    if [ -f "${FILENAME}" ]; then
      LOCATION=`echo "${file}" | ${AWK} -F ":" '{print $2}'`
      #EXTRA_INFO=`echo ${DETAILS} | grep ':'`
      if [ -z "${LOCATION}" ] ; then
        # No location specified find all occurrences of file omit tmp_patch directory
        cd ${TTAINSTDIR}
        find . \( -name ens -exec test {} = ./var/ens \; \) -prune -o -name ${file} -print 2>/dev/null | grep -v "${TMP_PATCH}" | sed -e 's:'./'::' | while read location; do
          # Is this file already patched ?
          EXISTING_ENTRY=`grep "${DELIM}${TTAINSTDIR}/${location}${DELIM}" ${PATCH_LIST} | grep "${DELIM}${ACTIVE}${DELIM}" | grep -v "^${NAME}${DELIM}"`
          if [ -n "${EXISTING_ENTRY}" ]; then
             EXISTING_NAME=`echo ${EXISTING_ENTRY} | ${AWK} -F "${DELIM}" '{print $1}'`
             BACKUP_FILE="${BACKUP_FILE_DIR}/${location}.${EXISTING_NAME}"
          else
             # Make backup of file
             BACKUP_FILE="${BACKUP_FILE_DIR}/${location}.${SGD_VERSION}"
          fi

          mkdir -p `dirname ${BACKUP_FILE}`
          # Only backup if not already backup up.
          # Useful to check incase a file is duplicated in same patch
          if [ ! -f "${BACKUP_FILE}" ] ; then
            \cp -rpP ${TTAINSTDIR}/${location} ${BACKUP_FILE} 
          fi
          # Copy in new file
          echo "${info_binary} ${TTAINSTDIR}/${location}"
          Copy_File ${file} ${PATCH_DIR} ${TTAINSTDIR}/${location}

          if [ -n "${EXISTING_ENTRY}" ]; then
             NEW_ENTRY=`echo "${EXISTING_ENTRY}" | sed -e 's/'${DELIM}${ACTIVE}${DELIM}'/'${DELIM}${INACTIVE}${DELIM}'/g' | sed -e 's:'${DELIM}${TTAINSTDIR}/${location}${DELIM}':'${DELIM}${BACKUP_FILE}${DELIM}':'` 
             UpdateEntry "${EXISTING_ENTRY}" "${NEW_ENTRY}"
          fi

          # Add patch entry
          AddPatchEntry "${NAME}" "file" "${DATE}" "${TTAINSTDIR}/${location}" "${BACKUP_FILE}" "${SGD_VERSION}"
        done
      else
        # Location specified
        # Backup any existing file
        FULLFILE=${TTAINSTDIR}/${FILENAME}
        EXISTING_ENTRY=`grep "${DELIM}${FULLFILE}${DELIM}" ${PATCH_LIST} | grep "${DELIM}${ACTIVE}${DELIM}" | grep -v "^${NAME}${DELIM}"`
        if [ -n "${EXISTING_ENTRY}" ]; then
           EXISTING_NAME=`echo ${EXISTING_ENTRY} | ${AWK} -F "${DELIM}" '{print $1}'`
           BACKUP_FILE=${BACKUP_FILE_DIR}/${FILENAME}.${EXISTING_NAME}
        else
           BACKUP_FILE=${BACKUP_FILE_DIR}/${FILENAME}.${SGD_VERSION}
        fi

        if [ -f "${FULLFILE}" ] ; then
          mkdir -p `dirname ${BACKUP_FILE}`
          # Only backup if not already backup up.
          # Useful to check incase a file is duplicated in same patch
          if [ ! -f "${BACKUP_FILE}" ] ; then
            \cp -rpP "${FULLFILE}" "${BACKUP_FILE}"
          fi
        else
           # If no file, create any missing directories 
           mkdir -p `dirname ${FULLFILE}` 2> /dev/null
        fi
        echo "${info_binary} ${FULLFILE}"
        Copy_File ${file} ${PATCH_DIR} ${FULLFILE}

        if [ -n "${EXISTING_ENTRY}" ]; then
           NEW_ENTRY=`echo "${EXISTING_ENTRY}" | sed -e 's/'${DELIM}${ACTIVE}${DELIM}'/'${DELIM}${INACTIVE}${DELIM}'/g' | sed -e 's:'${DELIM}${FULLFILE}${DELIM}':'${DELIM}${BACKUP_FILE}${DELIM}':'`
           UpdateEntry "${EXISTING_ENTRY}" "${NEW_ENTRY}"
        fi

        AddPatchEntry "${NAME}" "file" "${DATE}" "${FULLFILE}" "${BACKUP_FILE}" "${SGD_VERSION}"
      fi
    fi
  done

  # Execute any post patch script
  cd ${PATCH_DIR}
  PostPatchScript
  # Reuse message
  echo "${info_webcomp_complete}"
  # Tidy up
  cd ..
  rm -rf ${PATCH_DIR} 2> /dev/null

  # Update log
  AddedPatch "${DATE}" "file" "${NAME}"
}

Add_SGDWebComponents() {
  NAME=$1
  PATCH_DIR=$2

  CheckDependencies "${PATCH_DIR}"
  if [ "$?" -eq 1 ]; then
    return
  fi

  echo "${info_webcomp_install} ${NAME}"
  # Make backup dir if doesn't exist
  if [ ! -d "${BACKUP_WEBSERVER_DIR}" ]; then
    mkdir "{BACKUP_WEBSERVER_DIR}"
  fi

  [ -x "/usr/bin/nawk" ] && AWK="nawk" || AWK="awk"
  DATE=`date`
  SGD_VERSION=`GetSGDVersion`
  # Superceded patches
  SUPERSEDED=`Get_Value SUPERSEDED`
  if [ -n "${SUPERSEDED}" ]; then
    echo "${SUPERSEDED}" | tr ' ' '\012' |
    while read data; do
      if [ -z "${data}" ]; then
        continue  
      fi

      AddSuperseded ${NAME} ${data}
      # For each superseded patch, check whether it is currently installed
      grep "^${data}${DELIM}" ${PATCH_LIST} | grep "${DELIM}webcomp${DELIM}" |
      {
        while read ENTRY; do
          # If the patch is already inactive, skip it
          IS_INACTIVE=`echo "${ENTRY}" | ${AWK} -F "${DELIM}" '{print $7}' | grep ${INACTIVE}`
          if [ -n "${IS_INACTIVE}" ]; then
            continue
          fi

          # Handle each file in the superseded patch
          PATCH_PATH=`echo "${ENTRY}" | ${AWK} -F "${DELIM}" '{print $4}'`
          FILE_NAME=`basename "${PATCH_PATH}"`
          BACKUP_PATCH_FILE=`echo "${PATCH_PATH}" | sed 's:'${TTAINSTDIR}':'${BACKUP_WEBSERVER_DIR}':'`.${data}

          # Back up the superseded file
          # Only backup if not already backup up.
          # Useful to check incase a file is duplicated in same patch
          if [ ! -f "${BACKUP_PATCH_FILE}" ] ; then
            \cp -p "${PATCH_PATH}" "${BACKUP_PATCH_FILE}"
          fi
          # Copy new file
          FILE_DETAILS=`Get_Value FILE | sort -u | grep "${FILE_NAME}"`
          echo "${info_binary} ${PATCH_PATH}"
          \cp -f ${PATCH_DIR}/${FILE_DETAILS} "${PATCH_PATH}"
          # Add file to list of files handled by superseding to be removed
          # before normal patch handling
          ADD_FILE=`echo "${HANDLED}" | grep "${FILE_DETAILS}"`
          if [ -z "${ADD_FILE}" ]; then
            HANDLED="${HANDLED} ${FILE_DETAILS}"
          fi

          # Modify the patch list for the superseded component 
          NEW_ENTRY=`echo "${ENTRY}" | sed -e 's/'${DELIM}${ACTIVE}${DELIM}'/'${DELIM}${INACTIVE}${DELIM}'/g' | sed -e 's:'${DELIM}${PATCH_PATH}${DELIM}':'${DELIM}${BACKUP_PATCH_FILE}${DELIM}':'`
          UpdateEntry "${ENTRY}" "${NEW_ENTRY}"
          # Create a new entry for the patch component
          AddPatchEntry "${NAME}" "webcomp" "${DATE}" "${PATCH_PATH}" "${BACKUP_PATCH_FILE}" "${SGD_VERSION}"
        done
        # Remove form tmp_patch so not handled by code below.
        rm -f ${HANDLED}
      }
    done
  fi

  # Handle patch
  FILES=`Get_Value FILE`
  echo "${FILES}" | sort -u | while read entry; do
    cd ${PATCH_DIR}
    file=`echo ${entry} | ${AWK} -F ":" '{print $1}'`
    # File valid and not handled in superseded above
    if [ -s ${file} ]; then
      # Was a location provided
      GIVEN_LOCATION=`echo "${entry}" | ${AWK} -F ":" '{print $2}'`
      if [ -z "${GIVEN_LOCATION}" ]; then
        # Find all occurrences of file omit tmp_patch directory
        cd ${TTAINSTDIR}
        find . \( -name ens -exec test {} = ./var/ens \; \) -prune -o -name ${file} -print 2>/dev/null | grep -v "${TMP_PATCH}" | sed -e 's:'./'::' | while read location; do
          # Is this file already patched ?
          EXISTING_ENTRY=`grep "${DELIM}${TTAINSTDIR}/${location}${DELIM}" ${PATCH_LIST} | grep "${DELIM}${ACTIVE}${DELIM}" | grep -v "^${NAME}${DELIM}"`
          if [ -n "${EXISTING_ENTRY}" ]; then
               EXISTING_NAME=`echo ${EXISTING_ENTRY} | ${AWK} -F "${DELIM}" '{print $1}'`
               BACKUP_FILE="${BACKUP_WEBSERVER_DIR}/${location}.${EXISTING_NAME}"
          else
               # Make backup of file
               BACKUP_FILE="${BACKUP_WEBSERVER_DIR}/${location}.${SGD_VERSION}"
          fi

          mkdir -p `dirname ${BACKUP_FILE}`
          # Only backup if not already backup up.
          # Useful to check incase a file is duplicated in same patch
          if [ ! -f "${BACKUP_FILE}" ] ; then
            \cp -p ${TTAINSTDIR}/${location} ${BACKUP_FILE}
          fi
          # Copy in new file
          echo "${info_binary} ${TTAINSTDIR}/${location}"
          \cp -f ${PATCH_DIR}/${file} ${TTAINSTDIR}/${location}

          if [ -n "${EXISTING_ENTRY}" ]; then
              NEW_ENTRY=`echo "${EXISTING_ENTRY}" | sed -e 's/'${DELIM}${ACTIVE}${DELIM}'/'${DELIM}${INACTIVE}${DELIM}'/g' | sed -e 's:'${DELIM}${TTAINSTDIR}/${location}${DELIM}':'${DELIM}${BACKUP_FILE}${DELIM}':'`
              UpdateEntry "${EXISTING_ENTRY}" "${NEW_ENTRY}"
          fi

          # Add patch entry
          AddPatchEntry "${NAME}" "webcomp" "${DATE}" "${TTAINSTDIR}/${location}" "${BACKUP_FILE}" "${SGD_VERSION}"
        done
      else
        # Location provided
        TOMCAT_VERSION=`cat "${TTAINSTDIR}/var/info/tomcatversion"`
        WEBCOMP_DEST="${TTAINSTDIR}/webserver/tomcat/${TOMCAT_VERSION}/${GIVEN_LOCATION}"

        # If there is an existing file back it up
        if [ -f "${WEBCOMP_DEST}" ] ; then
            # Is this file already patched ?
            EXISTING_ENTRY=`grep "${DELIM}${WEBCOMP_DEST}${DELIM}" ${PATCH_LIST} | grep "${DELIM}${ACTIVE}${DELIM}" | grep -v "^${NAME}${DELIM}"`
            if [ -n "${EXISTING_ENTRY}" ]; then
                EXISTING_NAME=`echo ${EXISTING_ENTRY} | ${AWK} -F "${DELIM}" '{print $1}'`
                BACKUP_FILE="${BACKUP_WEBSERVER_DIR}/webserver/tomcat/${TOMCAT_VERSION}/${GIVEN_LOCATION}.${EXISTING_NAME}"
            else
                # Make backup of file
                BACKUP_FILE="${BACKUP_WEBSERVER_DIR}/webserver/tomcat/${TOMCAT_VERSION}/${GIVEN_LOCATION}.${SGD_VERSION}"
            fi

            mkdir -p `dirname ${BACKUP_FILE}`
            # Only backup if not already backed up.
            # Useful to check incase a file is duplicated in same patch
            if [ ! -f "${BACKUP_FILE}" ] ; then
                \cp -p ${WEBCOMP_DEST} ${BACKUP_FILE}
            fi
        fi

        # Create any missing directories
        mkdir -p `dirname ${WEBCOMP_DEST}` 2> /dev/null
        # Copy the file
        \cp -f ${PATCH_DIR}/${file} ${WEBCOMP_DEST}
        echo "${info_binary} ${WEBCOMP_DEST}"
        Set_Permissions "${WEBCOMP_DEST}" "${entry}"

        if [ -n "${EXISTING_ENTRY}" ]; then
            NEW_ENTRY=`echo "${EXISTING_ENTRY}" | sed -e 's/'${DELIM}${ACTIVE}${DELIM}'/'${DELIM}${INACTIVE}${DELIM}'/g' | sed -e 's:'${DELIM}${WEBCOMP_DEST}${DELIM}':'${DELIM}${BACKUP_FILE}${DELIM}':'`
            UpdateEntry "${EXISTING_ENTRY}" "${NEW_ENTRY}"
        fi
        # Add patch entry
        AddPatchEntry "${NAME}" "webcomp" "${DATE}" "${WEBCOMP_DEST}" "${BACKUP_FILE}" "${SGD_VERSION}"
      fi
    fi
  done

  IS_ADMIN=`echo "${FILES}" | grep sgdadmin.war`
  if [ -n "${IS_ADMIN}" ] ; then
    TOMCAT_VERS=`cat "${TTAINSTDIR}/var/info/tomcatversion"`
    # Extract the new sgdadmin.war file over existing directory.
    # This should help preserve any customer additions.
    cd ${TTAINSTDIR}/webserver/tomcat/${TOMCAT_VERS}/webapps/sgdadmin
    jar xf ../sgdadmin.war 2>&1 | tee -a "${PATCH_LOG}"
    find . -type d -exec chown root:${privgrp} {} \; -exec chmod 750 {} \; 2>&1 | tee -a "${PATCH_LOG}"
    find . -type f -exec chown root:${privgrp} {} \; -exec chmod 640 {} \; 2>&1 | tee -a "${PATCH_LOG}"
  fi

  # Execute any post patch script
  cd ${PATCH_DIR}
  PostPatchScript
  echo "${info_webcomp_complete}"
  # Tidy up
  cd ..
  rm -rf ${PATCH_DIR} 2> /dev/null

  # Update log
  AddedPatch "${DATE}" "webcomp" "${NAME}"
}

##############################################################################

if [ "$#" -eq 0 ]; then
    Usage_add
fi

TidyUpAfterUpgrade

# Parse the arguments
FILE=""
UNPACK="true"
while [ ! -z "$1" ]; do
    case $1 in
	--help)
	    Usage_add
	    ;;
	--file)
	    case "$2" in
		"" | --*) 
		    echo ${err_invalid_arg} 
		    Usage_add
		    ;;
		/*)
		    # correct format
		    ;;
		*)
		    echo ${err_file_not_absolute}
		    exit 1
		    ;;
	    esac
	    FILE="$2"
	    ;;
     --cont)
        # Just updated patch commands continue with rest of bundle - don't unpack
        UNPACK="";
        ;;
	*) 
	    echo ${err_unknown_arg} "$1"
	    Usage_add
	    ;;
    esac
    shift; shift
done

# Check file was supplied
if [ -z "${FILE}" -a "${UNPACK}" ]; then
    echo ${err_missingfile}
    Usage_add
fi

# Check the file exists
if [ ! -f "${FILE}" -a "${UNPACK}" ]; then
    echo ${err_file_does_not_exist} ${FILE}
    exit 1
fi

# Check required/available disk space
[ -x "/usr/bin/nawk" ] && AWK="nawk" || AWK="awk"
[ "${UNPACK}" ] && FILE_SIZE=`ls -la "${FILE}" | $AWK '{ print $5 }'`
if [ -n "${FILE_SIZE}" ] ; then
  REQUIRED_DISK_SPACE=`expr ${FILE_SIZE} \* 6`
  # Convert to kilobytes
  KILOBYTES=`expr ${REQUIRED_DISK_SPACE} / 1000 + 1`
  MEGABYTES=`expr ${KILOBYTES} / 1000 + 1`
  AVAIL=`df -k "${TTAINSTDIR}" | $AWK '/[0-9]%/{print $(NF-2)}'`
  # Bail out if not enough
  if [ "${AVAIL}" -lt "${KILOBYTES}" ] ; then
    echo "${err_disk_space}${MEGABYTES} ${err_disk_space_unit}"
    exit 1
  fi
fi

# Unpack the patch file
if [ "${UNPACK}" ] ; then
    Unpack ${FILE} ${TOPLEVEL_PATCH_DIR}
else
    # Continue with unfinished bundle (but only if the patch directory exists)
    if [ -d "${TOPLEVEL_PATCH_DIR}" ] ; then
        cd ${TOPLEVEL_PATCH_DIR}
    else
        exit 1
    fi
fi

# Check patch is for this product
PRODUCT="`Get_Value PRODUCT`"
if [ -n "${PRODUCT}" ] ; then
  if [ "${PRODUCT}" != "Server" ] ; then
    cd ..
    rm -rf ${TOPLEVEL_PATCH_DIR}
    echo "${err_wrong_product} ${PRODUCT}"
    echo "${err_this_product}"
    exit 1
  fi
fi

# Check architecture
ARCH=`Get_Value ARCH`
if [ -n "${ARCH}" ] ; then
  SHORTARCH=`machinearch -c`
  if [ "${SHORTARCH}" != "${ARCH}" ] ; then 
    cd ..
	  rm -rf ${TOPLEVEL_PATCH_DIR}
    echo ${err_wrong_arch} ${ARCH}
    echo ${err_local_arch} ${SHORTARCH}
    exit 1
  fi
fi

# Check patch is for this version of SGD
PATCH_SGD_VERSION=`Get_Value SGD_VERSION`
if [ -n "${PATCH_SGD_VERSION}" ] ; then
  SGD_VERSION=`GetSGDVersion`
  SGD_SHORT_VERSION=`expr "${SGD_VERSION}" : '\(....\).*'`
  if [ "${SGD_SHORT_VERSION}" != "${PATCH_SGD_VERSION}" ] ; then
    cd ..
    rm -rf ${TOPLEVEL_PATCH_DIR}
    echo ${err_wrong_sgd} ${PATCH_SGD_VERSION}
    echo ${err_local_sgd} ${SGD_SHORT_VERSION}
    exit 1
  fi
fi 

# If the name exists, check it is not already installed
NAME=`Get_Value NAME`
if [ -n "${NAME}" ]; then
    CheckExists "${NAME}"
    if [ "$?" -eq 1 ]; then
	cd ..
	rm -rf ${TOPLEVEL_PATCH_DIR}
	echo "${err_already_installed1}${NAME}${err_already_installed2}"
	exit 1
    fi    
fi

# Check the patch is not superseded by another which is already installed
IS_SUPERSEDED=`grep "^${NAME}:" ${PATCH_CFG} | tr ':' ' ' | awk '{print $2}' | tr ',' ' '`
if [ -n "${IS_SUPERSEDED}" ]; then
    
    cd ..
    rm -rf ${TOPLEVEL_PATCH_DIR}
    echo "${err_superseded} ${IS_SUPERSEDED}"
    exit 1
fi

# Check for compatibility with the current patch mechanism
CURRENT_PATCH_MECH=`grep "^patch_add" ${PATCH_CFG} | awk '{print $3}'`
if [ -z "${CURRENT_PATCH_MECH}" ]; then
    # Mechanism has not been patched
    CURRENT_PATCH_MECH="2.0"
fi

REQUIRED_PATCH_MECH=`Get_Value PATCH_MECH`
if [ -n "${REQUIRED_PATCH_MECH}" ]; then
    VALID=`echo "${CURRENT_PATCH_MECH} ${REQUIRED_PATCH_MECH}" | tr '.' ' ' |
           awk '{if ($1>$3 || ($1==$3 && ($2>$4 || $2==$4))) print "valid"}'`
    if [ -z "${VALID}" ]; then
	echo "${err_mech_invalid_1} ${REQUIRED_PATCH_MECH} ${err_mech_invalid_2}"
	cd ..
	rm -rf ${TOPLEVEL_PATCH_DIR}
	exit 1
    fi
fi

# Check for restart action
ACTION=`Get_Value ACTION`
case "${ACTION}" in
    stop)
	ExitIfRunning ${TTAINSTDIR}/var/info/auxserver.pid ${TTAINSTDIR} "${err_sgd_running}" ${TOPLEVEL_PATCH_DIR}
	ExitIfRunning ${TTAINSTDIR}/var/info/jserver.pid "java -XX:-UseVMInterruptibleIO" "${err_sgd_running}" ${TOPLEVEL_PATCH_DIR}
	;;
    restart)
	RESTART=true
	;;
    array)
	ARRAY=true
	# Query whether the installation should proceed
	echo "${info_array}"
	while [ 1 -eq 1 ]; do
	    echo "${query_array}"
	    read continue
	    case "${continue}" in 
		y|Y|yes)
		    break;
		    ;;
		n|N|no)
		    echo "${info_abort}"
		    cd ..
		    rm -rf ${TOPLEVEL_PATCH_DIR}
		    exit 1
		    ;;
	    esac
	done
	;;
esac

# Get the type from the patch
TYPE=`Get_Value TYPE`

# Run any pre-install script
# Note bundle is a special case - we update the patch commands before running any
# pre-install script
if [ "${TYPE}" != "bundle" ]
then
    PrePatchScript "${TOPLEVEL_PATCH_DIR}"
fi

# Add the patch based on the type
case "${TYPE}" in
    webserver)
        Add_Webserver ${TOPLEVEL_PATCH_DIR}
        ;;
    jserver)
        Add_Jserver ${NAME} ${TOPLEVEL_PATCH_DIR}
        ;;
    binary)
        Add_Binary ${NAME} ${TOPLEVEL_PATCH_DIR}
        ;;
    bundle)
        Add_Bundle ${NAME} ${TOPLEVEL_PATCH_DIR}
        ;;
    commands)
        Add_Commands ${NAME} ${TOPLEVEL_PATCH_DIR}
        ;;
    delete)
        Add_Delete ${NAME} ${TOPLEVEL_PATCH_DIR}
        ;;
    webcomp)
        Add_SGDWebComponents ${NAME} ${TOPLEVEL_PATCH_DIR} 
        ;;
    file)
        Add_File ${NAME} ${TOPLEVEL_PATCH_DIR}
        ;;
    *)
        echo ${err_invalid_type} "${TYPE}"
        rm -rf ${TOPLEVEL_PATCH_DIR}
        exit 1
        ;;
esac

# Prompt for a restart, if required
if [ -n "${RESTART}" ]; then
    echo "${info_restart}"
fi  

# Warn other array nodes must be patched
if [ -n "${ARRAY}" ]; then
    echo "${info_array}"
fi

# Set correct ownership of patch.cfg and patch.list
chown ${privusr}:${privgrp} ${PATCH_LIST} ${PATCH_CFG} 2>/dev/null
chmod 640 ${PATCH_LIST} ${PATCH_CFG} 2>/dev/null

