#! /bin/sh
#
# ident data/SCCS/s.install_cluster_patchadd 1.4 02/14/06:16:27:49 SMI
#
# Script to install a patch cluster supplement for Solaris 2.6 - 9
#
########################################################################

set -e

#
# Force the path to first look in certain directories
#
PATH=/sbin:/usr/sbin:/bin:$PATH
export PATH


#
# Supplement tag information
# (Tag needs to be convertible to a valid filename too...)
SUPPLEMENT_NAME="Solaris 7 Recommended Patch Cluster"

# Broadcast what we are doing
#
echo
echo "Patch cluster install script for ${SUPPLEMENT_NAME}"
echo

logname=`echo ${SUPPLEMENT_NAME} | sed 's/ /_/g'`_log
LOGFILE=/var/sadm/install_data/${logname}

#
# Command line and environment option processing
#
# (Default is *not* to save base objects)
#
Usage()
{
	echo "usage: `basename $0` [-q] [-nosave] [target] [patchdir]"
	echo " [-q]       - quiet option, suppresses interactive warning"
	echo " [-nosave]  - do not save original objects"
        echo " [target]   - destination system to apply or query patches, can be one of:" 
        echo "              [-R client_root_path]  - apply/query patch on bootable client root"
	echo " [patchdir] - optional pathname to directory of patches"

}

cleanup()
{
	#
	# A little cleanup.
	#
	if [ "$finished" = "NO" ]; then
		failed_list="${failed_list} ${patch}"
	fi

	#
	# List the patches that failed installation (if any)
	#
	if [ " ${failed_list}" != " " ]
	then
		echo
		echo "The following patches were not able to be installed:"
		echo ${failed_list} | tr ' ' '\012' | sed 's/^/	/g'
	fi

	echo
        echo "For more installation messages refer to the installation logfile:"
	echo "  ${LOGFILE}"
	echo 
	echo "Use '/usr/bin/showrev -p' to verify installed patch-ids."
	echo "Refer to individual patch README files for more patch detail."
        echo "Rebooting the system is usually necessary after installation."
}

uid=`id | sed 's/uid=\([0-9]*\)(.*/\1/'`
if [ "$uid" != "0" ] ; then
	echo "You must be root to execute this script."
	exit 1
fi

###################################################################
# New functionality: user prompt driven by install_cluster_question
###################################################################

# Check to see if the install_cluster_question file is present.
# If it is, cat it to stdout - it includes the user prompt for
# a passcode stored in the CLUSTER_README file. If it is present
# but empty or unreadable (shouldn't happen, but it's possible),
# err on the side of caution and provide a default prompt.

answer_required="no"

if [ -f install_cluster_question ]
then
   answer_required="yes"
   if [ -r install_cluster_question -a -s install_cluster_question ]
   then
      cat install_cluster_question
   else
      echo "[empty/unreadable install_cluster_question file: default used]"
      echo "  "
      echo "Special handling may be required for some of the patches in"
      echo "this cluster.  Please refer to the CAUTION section in the"
      echo "cluster README for further instructions on how to proceed."
      echo "  "
      echo "This section also contains a passcode that will need to be"
      echo "provided below to allow the install_cluster script to continue"
      echo "running."
      echo "  "
      echo "Please enter passcode:"
   fi
fi

# If the question file is present, look up the passcode in the
# CLUSTER_README file. Try to anticipate various ways in which
# PASSCODE: may appear in the README file.
# Look for PASSCODE:, remove any tab characters, look for PASSCODE:
# optionally preceded by blanks, only use the first matching line,
# strip away PASSCODE: and any blanks before or after it.

if [ "$answer_required" = "yes" ]
then
   answer_string=`grep PASSCODE: CLUSTER_README | 
      tr -d '\011' |
      egrep -e "^ *PASSCODE:" |
      head -1 |
      sed -e "s/^ *PASSCODE: *//"`

   # If the answer string cannot be found, improvise. Provide a
   # diagnostic message, set the answer to a known value, and
   # provide it to the user so that cluster installation may
   # proceed.

   if [ -z "$answer_string" ]
   then
      echo "  "
      echo "[ERROR: 'PASSCODE:' missing/malformed in CLUSTER_README]"
      echo "  "
      echo "The passcode value expected in the CLUSTER_README file"
      echo "cannot be determined. Please type 'proceed' (no quotes)"
      echo "to proceed with cluster installation:"
      answer_string="proceed"
   fi

   # Prompt user for the answer string. If it's wrong, exit.

   read user_response

   if [ ! "$user_response" = "$answer_string" ]
   then
      echo "Passcode is incorrect; exiting."
      exit 1
   fi

fi  # end of passcode retrieval/response/check block

###################################################################
# end of install_cluster_question / passcode processing
###################################################################

finished="NO"
saveold=''
quiet="NO"
target=""
while [ "$1" != "" ];
do
	case $1 in
	-nosave)	saveold='-d';;
	--nosave)	saveold='-d';;
	-n)	        saveold='-d';;
	-q)		quiet='YES';;
	-R)		shift
                        if [ $# -gt 0 ] && [ ! -d $1 ]; then
                            echo "$1 client root path not found?"
                            exit 1
                        else
                            target="-R $1" 
                        fi;;
	-*)		Usage; exit 2;;
	*)
		if [ "$finished" = "YES" ]; then
			Usage; exit 2
		fi
		#
		# Where do we find the list of patches to install
		# (we need an absolute pathname...)
		#
		# This is done to maintain the cwd to PATCHDIR to
		# suppress auto unmounts...
		if [ ! -d $1 ]; then
                  echo "$1 optional patch directory not found?"
                  exit 1
                else
		  cd $1
		  finished="YES"
                fi
		;;
	esac
	shift
done
PATCHDIR=`pwd`

if [ "$quiet" != "YES" ]; then
	cat << EOF

*WARNING* SYSTEMS WITH LIMITED DISK SPACE SHOULD *NOT* INSTALL PATCHES:
With or without using the save option, the patch installation process
will still require some amount of disk space for installation and
administrative tasks in the /, /usr, /var, or /opt partitions where
patches are typically installed.  The exact amount of space will
depend on the machine's architecture, software packages already 
installed, and the difference in the patched objects size.  To be
safe, it is not recommended that a patch cluster be installed on a
system with less than 4 MBytes of available space in each of these
partitions.  Running out of disk space during installation may result
in only partially loaded patches.  Check and be sure adequate disk space
is available before continuing.

EOF
	while .
	do
	  echo "Are you ready to continue with install? [y/n]: \c"
	  read reply
	  case $reply
	  in
	    y)	break;;
	    n)	exit;;
	    *)	echo invalid response, enter only 'y' for yes or 'n' for no;;	
	  esac
	done
fi

#
# The patch reference directory must exist
#
if [ ! -d /var/sadm/patch ]; then
        mkdir /var/sadm/patch
        chown bin /var/sadm/patch
        chgrp bin /var/sadm/patch
        chmod 555 /var/sadm/patch
fi

#
# If using save feature:
# Approximate and set cluster save size value.  The maximum save space
# needed should be about no more than half of the actual patch cluster size
# since the patch installation procedure will use compression to save files, and
# patches with multiple architecture packages will only have appropriate
# packages installed on the system.
#
if [ "${saveold}" != -d ]; then
	echo "Determining if sufficient save space exists..."
	BASESIZE=`du -sk $PATCHDIR | cut -f1`
	SUPPLEMENT_SIZE=`expr $BASESIZE / 2`
	bytes_avail=`df -b /var/sadm/patch | tail -1`
	bytes_avail=`echo $bytes_avail | sed 's/.*\ //'`
	if [ ${SUPPLEMENT_SIZE} -gt ${bytes_avail} ]; then
		echo "Insufficient space in /var/sadm/patch to save old files."
		echo "Space required in kilobytes:  ${SUPPLEMENT_SIZE}"
		echo "Space available in kilobytes:  ${bytes_avail}"
		exit 1
	else
		echo "Sufficient save space exists, continuing..."
	fi
else
	echo "The nosave option was used.  Objects will not be saved."
fi


#
# Install all the patches in PATCHDIR
#
# Simply go down the list of existing patches and apply them one at a time
#
echo "Installing patches located in ${PATCHDIR}"
echo "" >> ${LOGFILE}
echo "" >> ${LOGFILE}
echo "*** Install ${SUPPLEMENT_NAME} begins `date` ***" >> ${LOGFILE}
echo "*** PATCHDIR = ${PATCHDIR} ***" >> ${LOGFILE}
echo "" >> ${LOGFILE}

set +e

finished="YES"
failed_list=
trap 'echo; echo Interrupted ... Please wait; cleanup; exit 1' 1 2 3 15

#
# First check for the patch_order file.  If it exists use it for patch
# installation sequence.  If no patch_order file exists then assume
# all directories that begin with 1 in the current directory are the
# patches we want to install and assume the shell coallating sequence
# is the desired install order...
#

if [ -f patch_order ]; then
	patchlist=`cat patch_order`
	echo "Using patch_order file for patch installation sequence"
else
	patchlist=[1..9][0..9][0..9][0..9][0..9][0..9]*
fi

for patch in ${patchlist} ; do
	if [ -d $patch ]; then
		echo "Installing ${patch}..." | tee -a ${LOGFILE}
		finished="NO"
		( /usr/sbin/patchadd ${saveold} ${target} ${patch} ) >> ${LOGFILE} 2>&1
		result=$?
		if [ ${result} -ne 0 ]; then
			echo "  Installation of ${patch} failed. Return code ${result}."
			failed_list="${failed_list} ${patch}"
		fi
		finished="YES"
	fi
done
cleanup

if [ " ${failed_list}" != " " ]; then
        exit 1
else
        exit 0
fi 
