#!/bin/sh
# Copyright 11/21/01 Sun Microsystems, Inc. All Rights Reserved.
#pragma ident  "@(#)sunmc-postinstall.sh	1.5 01/11/21 Sun Microsystems"

#
#Takes Patch number and Patch version as argument and return 0 if the patch
#is obsoleted else returns 1.
#

checkInObsoletedPatch() {
    
    obsolete_patch=""
    obsolete_patch=`${LOCAL_PATCH_COMMAND} -p $RELOC_PARAM | /usr/bin/cut -d : -f 3`
    for each_obsolete_patch in $obsolete_patch
    do
         if [ $each_obsolete_patch = "Requires" ] ; then
              continue
         fi
         #echo $each_obsolete_patch
         obsolete_patch_number=`echo $each_obsolete_patch | /usr/bin/cut -d- -f1`
         obsolete_patch_version=`echo $each_obsolete_patch | /usr/bin/cut -d- -f2`
         obsolete_patch_version=`echo $obsolete_patch_version | /usr/bin/cut -c1,2 `

         if [ $obsolete_patch_number -eq $1 ] ; then
                 if [ $obsolete_patch_version -ge $2 ] ; then
                      return 0
                 fi
         fi

    done
    return 1
}

#
#Takes patch number and patch version in argument. Returns 0 if patch is available
#else return 1.
#

checkInAvailPatch() {


        required_patch_number=$1
        required_patch_version=$2

        patches_available=""
        patches_available=`${LOCAL_PATCH_COMMAND} -p $RELOC_PARAM | /usr/bin/nawk ' { print $2 }'`
        
        patch_number_found=`echo "$patches_available" | /usr/bin/grep -c $required_patch_number`
        if [ $patch_number_found -eq 0 ] ; then
                return 1
        fi
        for avail_patch  in $patches_available ;
        do
                avail_patch_number=`echo $avail_patch | /usr/bin/cut -d- -f1`
                avail_patch_version=`echo $avail_patch | /usr/bin/cut -d- -f2`

                if [ $required_patch_number -eq $avail_patch_number ] ; then
                        if [ $required_patch_version -le $avail_patch_version ]; then
                                return 0
                        fi
                fi
        done
        return 1
}

#
#Checks if the patch is currently installed on the machine ot obsoleted by 
#some other patch. If the patch is either installed or obsoleted
#it returns 0 else returns 1.
#

check_postinstall_patch_dependency () {
    required_patch="$1"

    reqrd_patch_not_avail=""
    reqrd_patch_not_avail_flag=0

    required_patch_number=""
    required_patch_version=""

    # check if the patch is present

    required_patch_number=`echo $required_patch | /usr/bin/cut -d- -f1`
    required_patch_version=`echo $required_patch | /usr/bin/cut -d- -f2`

    checkInAvailPatch  $required_patch_number  $required_patch_version
    if [ $? -eq 1 ] ; then
        checkInObsoletedPatch $required_patch_number $required_patch_version
        if [ $? -eq 1 ] ; then
            return 1
        fi
    fi
    return 0
}

#
#It checks the version of package installed on the machine and version
#of one of the package in patch. If they match, it returns 0 else it 
#returns 1. It returns 2 if non of the packages in the patch is installed,
#means patch is not required.
#

is_patch_version_correct ()
{
    patch_to_be_checked="$1"
    patch_directory="$2"
    packages_in_patch=`/usr/bin/ls -1 "$2/$1" | /usr/bin/grep SUNW`
    for each_pkg in $packages_in_patch
    do
        /usr/bin/pkginfo -qi $each_pkg > /dev/null 2>&1
        if [ $? -eq 0 ] ; then
            installed_version_string=`/usr/bin/pkgparam $each_pkg SUNW_PRODVERS`
            patch_version_string=`/usr/bin/pkgparam -f $2/$1/$each_pkg/pkginfo SUNW_PRODVERS`
            if [ "$installed_version_string" = "$patch_version_string" ] ; then
                return 0
            else
                return 1
            fi
        else
            continue
        fi
    done
    return 2
}

#
#Returns 1 if patch needed to be installed else returns 0.
#
is_patch_needed ()
{
    #
    #Here we may want to see if we have some package installed 
    #for which the patch is not installed. System will say patch
    #is installed even if it was installed for only 2 packages
    # out of more then 2.
    #

    patch_name=$1
    patch_directory=$2
    check_postinstall_patch_dependency "$patch_name"
    if [ $? -eq 1 ] ; then
        #
        #Patch is neither installed not obsoleted.
        #
        return 1
    fi

    #
    #Now check if all the installed packages from this patch are patched or not.
    #
    packages_patched=`${LOCAL_PATCH_COMMAND} -p $RELOC_PARAM | /usr/bin/grep $patch_name | /usr/bin/cut -d : -f 6`
    #
    # This is required because on some machines, packages are separated by commas.
    #
    packages_patched=`echo $packages_patched | /usr/bin/sed -e 's/,//g'`

    packages_in_patch=""
    packages_in_patch=`/usr/bin/ls -1 "$patch_directory/$patch_name" | /usr/bin/grep SUNW`

    for each_package in $packages_in_patch
    do
        #
        #See if the package is installed on the system, if yes then
        #if it is present in the patched packages. If no then install
        #the patch.
        #
        /usr/bin/pkginfo -qi  $RELOC_PARAM $each_package
        if [ $? -eq 0 ] ; then
            #
            #package is installed on the system, so now check for the 
            #version of installed package and package in the patch. If
            #they are not same then dont install patch.
            #

            installed_package_version=""
            patch_package_version=""
            installed_package_version=`/usr/bin/pkgparam $RELOC_PARAM $each_package SUNW_PRODVERS`
            patch_package_version=`/usr/bin/pkgparam -f ${patch_directory}/${patch_name}/${each_package}/pkginfo SUNW_PRODVERS`
            if [ "$installed_package_version" = "$patch_package_version" ] ; then
		echo "$packages_patched" | /usr/bin/grep $each_package >/dev/null 2>&1
		if [ $? -ne 0 ] ; then
		    #
		    #package is not patched yet, so lets patch it.
		    #
		    return 1
		fi
            fi
        fi
    done

    return 0
}

add_postinstall_patches () 
{
    patch_directory="$2"
    failed_patch=""
    for each_patch in $1
    do
	LOCAL_PATCH_COMMAND="/usr/sbin/patchadd"
	if [ "$OSVERS" = "2.5.1" ] ; then
	    LOCAL_PATCH_COMMAND="${patch_directory}/${each_patch}/installpatch"
	fi

	${LOCAL_PATCH_COMMAND} $RELOC_PARAM $patch_directory/$each_patch
	if [ $? -ne 0 ] ; then
            failed_patch="$failed_patch $each_patch"
	fi
    done
    if [ -z "$failed_patch" ] ; then
        return 0
    fi
    FAILED_PATCHES="$FAILED_PATCHES $failed_patch"
    return 1
}

#
#$1=CD number
#Uses SRC_DIRECTORY and sets it to new value
#
get_current_cd_source_directory ()
{
    while [ 1 -eq 1 ]
    do
        if [ -d "${SRC_DIRECTORY}/../../disk$1/image" ]; then 
            answer="${SRC_DIRECTORY}/../../disk$1/image"
        else
            cd /
            eject cd 2> /dev/null
            tmp_auto=""
            if [ "$AUTOCONFIG_RUNFILE" != "" ] ; then # Run autoconfig
                tmp_auto=`getAutoConfig "CORE_DISK$1"`
            fi
            if [ -z "$tmp_auto" ] ; then
                tmp_auto="/cdrom/cdrom0/image"
            fi
            get_input_from_user 'Please insert CD $3 or enter the source directory from disk $3 \\\[$2\\\]' "$tmp_auto" "$1"
        fi
        if [ -z "$answer" ] ; then
            answer="$tmp_auto"
        fi

        echologverbose 'New source directory: $2' "$answer"
        cd_count=0
        while [ 1 ]
        do
            sleep 1
            if [ -d "$answer" ] ; then
                break
            fi
            cd_count=`/usr/bin/expr $cd_count + 1`
            if [ $cd_count -ge 10 ] ; then
                echolog 'Invalid directory $2' "$answer"
                break
            fi
        done
        if [ ! -d "$answer" ]; then
            $CMD_ECHO "  \c"
            echolog 'Invalid directory.'
            echolog ''
            continue
        fi
        SRC_DIRECTORY="$answer"
        if [ "$AUTOCONFIG_SAVEFILE" ] ; then
            saveAutoConfig "CORE_DISK$1" "$answer"
        fi
        break
    done
}

sunmc_postinstall () 
{
    
    SRC_DIRECTORY=$1
    patch_registration_file="$SRC_DIRECTORY/PatchRegistry"
    if [ ! -f "$patch_registration_file" ] ; then
        return 0
    fi
    FAILED_PATCHES=""
    for cdnumber in 1 2 3 4 5
    do 
        install_sunmc_patch "$SRC_DIRECTORY" $cdnumber
    done
    if [ -z "$FAILED_PATCHES" ] ; then
        return 0
    fi
    echolog 'Patches could not get installed = $2' "$FAILED_PATCHES"
    echolog "Please install these patches mannualy."
    return 1
}

install_sunmc_patch ()
{
    if [ ! -f "$1/PatchRegistry" ] ; then
        echologverbose "Patch registry file not present."
        return 0
    fi 
    COMMON_PATCH_LIST=`get_value_from_cfgfile "$1/PatchRegistry" "Common:$2" "="`
    OSSPECIFIC_PATCH_LIST=`get_value_from_cfgfile "$1/PatchRegistry" "Solaris_${OSVERS}:$2" "="`
    echologverbose "COMMON_PATCH_LIST=$COMMON_PATCH_LIST OSSPECIFIC_PATCH_LIST=$OSSPECIFIC_PATCH_LIST"
    if [ -z "$COMMON_PATCH_LIST" -a -z "$OSSPECIFIC_PATCH_LIST" ] ; then
        echologverbose 'No patch to install from CD $2' "$2"
        return 0
    fi
    CURRENT_CD=`get_value_from_cfgfile "$1/PatchRegistry" "CD" "="`
    if [ $? -eq 1 ] ; then
        echologverbose "Could not get the current CD from registration file."
        return 0
    fi
    echologverbose "CURRENT_CD=$CURRENT_CD"
    PATCH_LIST="$COMMON_PATCH_LIST $OSSPECIFIC_PATCH_LIST"
    PATCH_LIST=`echo $PATCH_LIST`
    if [ -z "$PATCH_LIST" ] ; then
        echologverbose 'No patch to install from CD $2' "$2"
        return 0
    fi
    if [ $CURRENT_CD -ne $2 ] ; then
        #
        #Ask user for the CD
        #
        echologverbose "CURRENT_CD=$CURRENT_CD, Asking CD = $2"
        while [ 1 -eq 1 ] 
        do
            get_current_cd_source_directory $2 
            CURRENT_CD=`get_value_from_cfgfile "$SRC_DIRECTORY/PatchRegistry" "CD" "="`
            if [ $? -ne 0 ] ; then
                echologverbose "Could not get the current CD from registration file."
                return 0
            fi
            if [ $CURRENT_CD -eq $2 ] ; then
                break
            fi
        done
    fi
    PATCH_DIR="$SRC_DIRECTORY/Patches"
    
    OS_PATCH_DIRECTORY="${PATCH_DIR}/Solaris_${OSVERS}"
    COMMON_PATCH_DIRECTORY="${PATCH_DIR}/Common"


    patches_tobe_installed=""
    for each_patch in $PATCH_LIST
    do
        echologverbose "Handling patch $each_patch"
        PATCH_NAME="$each_patch"
        PATCH_DIRECTORY=""
	if [ ! -d "${OS_PATCH_DIRECTORY}/${PATCH_NAME}" ] ; then
            if [ ! -d "${COMMON_PATCH_DIRECTORY}/${PATCH_NAME}" ] ; then
                echologverbose "Patch is present in the registry but not present on the CD"
		continue
            else
                PATCH_DIRECTORY="${COMMON_PATCH_DIRECTORY}"
            fi
        else
	    PATCH_DIRECTORY="${OS_PATCH_DIRECTORY}"
	fi

	LOCAL_PATCH_COMMAND="/usr/sbin/patchadd"
	if [ "$OSVERS" = "2.5.1" ] ; then
	    LOCAL_PATCH_COMMAND="${PATCH_DIRECTORY}/${PATCH_NAME}/installpatch"
	fi
        echologverbose "PATCH_DIRECTORY=$PATCH_DIRECTORY LOCAL_PATCH_COMMAND=$LOCAL_PATCH_COMMAND"
        is_patch_version_correct "${PATCH_NAME}"  "${PATCH_DIRECTORY}"
        if [ $? -ne 0 ] ; then
            echologverbose 'Version mismatch for patch $2 or non of the packages in this patch is installed.' "${PATCH_NAME}"
            continue
        fi
	is_patch_needed $PATCH_NAME "${PATCH_DIRECTORY}"
	if [ $? -eq 1 ] ; then
	    patches_tobe_installed="$patches_tobe_installed $PATCH_NAME"
	fi
    done
    echologverbose "Patches needed = $patches_tobe_installed"
    if [ ! -z "$patches_tobe_installed" ] ; then
	add_postinstall_patches "$patches_tobe_installed" "${PATCH_DIRECTORY}"
	return $?
    fi

    return 0
}

