#!/bin/sh
# @(#) backoutpatch 3.1 92/12/16 SMI
echo "@(#) backoutpatch 3.1 92/12/16"

spoolonly="no"

USAGE="usage: backoutpatch [-s]  <patch number>"

for i in $*
do
	case $i in
	-s)	spoolonly="yes"; shift;;
	-*)	echo $USAGE; exit 2;;
	esac
done

# change directory to location of patch
if [ ! -d /var/sadm/patch/$1 ]; then
	echo "Patch $1 has not been applied to this system."
	exit 1
fi
cd /var/sadm/patch/$1

thisdir=`pwd`
patchnum=`basename $thisdir`

Product=`sed -n 's/^OS=\(.*\)/\1/p' /var/sadm/softinfo/INST_RELEASE`
Instver=`sed -n 's/^VERSION=\(.*\)/\1/p' /var/sadm/softinfo/INST_RELEASE`
prodver=$Product"_"$Instver

if [ "$spoolonly" = "yes" ]; then
	if [ -f softinfo_sed ]; then
	    sed -f softinfo_sed /var/sadm/softinfo/$prodver > /tmp/soft.$$
	    mv /var/sadm/softinfo/$prodver /var/sadm/softinfo/sav.$prodver
	    cp /tmp/soft.$$ /var/sadm/softinfo/$prodver
	fi
#
# this code deleted /export/root/templates when called from installpatch
# (bug in installpatch handling  VERSION=11.4.2,PATCH=1)
#	if [ -f spooled_dirs ]; then
#		cat spooled_dirs | xargs rm -fr
#	fi
	exit 0
fi

if [ ! -f /var/sadm/patch/$patchnum/.oldfilessaved ]; then
	echo "Patch $1 was installed without backing up the original"
	echo "files.  It cannot be backed out."
	exit 1
fi

#
# generate list of packages to be removed
#

pkglist=
for i in */pkgmap; do
	pkg=`expr $i : '\(.*\)/pkgmap'`
	pkglist="$pkglist $pkg"
done

#
# find the package instances for this patch
#
pkginstlist=
for j in /var/sadm/pkg/*; do
	if grep -s "SUNW_PATCHID *= *$patchnum" $j/pkginfo > \
			/dev/null 2>&1;  then
		pkginst=`basename $j`
		pkginstlist="$pkginstlist $pkginst"
	fi
done

#
# Build admin file for later use by pkgrm
#

cat > /tmp/admin.$$ << EOF
mail=
instance=unique
partial=nocheck
runlevel=nocheck
idepend=quit
rdepend=quit
space=quit
setuid=nocheck
conflict=nocheck
action=nocheck
basedir=default
EOF

for i in $pkginstlist; do
	echo "Doing pkgrm of $i package:"
	/usr/sbin/pkgrm -a /tmp/admin.$$ -n $i >> /var/sadm/patch/$patchnum/log 2>&1
	if [ $? != 0 ]; then
		echo "/npkgrm of $i package failed.  See"
		echo "/var/sadm/patch/$patchnum/log for reason for failure."
		rm -fr /tmp/*.$$
		exit 1
	fi
done

#
# restore old versions of files
#
echo "Restoring previous version of files"
cd save
find . -print | cpio -pdumv / 
if [ $? != 0 ]; then
	echo "Restore of old files failed."
	echo "See README file for instructions."
	rm -f /tmp/*.$$
	exit 1
fi
cd ..

echo "Making the package database consistent with restored files:"
for i in $pkglist; do
	sed -e '/^:/d' -e '/^[^ ][^ ]* i/d' $i/pkgmap | \
	sed 's/^[^ ]* . [^ ]* \([^ ]*\).*$/\/\1/' > /tmp/pkgfiles.$$
	#
	# find package instance of originally-installed package
	#
        Pkgabbrev=`sed -n 's/^[ 	]*PKG[ 	]*=[ 	]*\([^ 	]*\).*$/\1/p' $i/pkginfo`
        Pkgarch=`sed -n 's/^[ 	]*ARCH[ 	]*=[ 	]*\([^ 	]*\).*$/\1/p' $i/pkginfo`
        Pkgver=`sed -n \
           -e 's/^[ 	]*VERSION[ 	]*=[ 	]*\([^ 	]*\)\.[0-9][0-9]*[	 ]*$/\1/p' \
           -e 's/^[ 	]*VERSION[ 	]*=[ 	]*\([^ 	]*\),PATCH=.*$/\1/p' $i/pkginfo `
        minver=`expr $Pkgver : '\(.*\)\.0$'`
        while [ "$minver" != "" ] ; do
                Pkgver=$minver
                minver=`expr $Pkgver : '\(.*\)\.0$'`
        done
	pkginst=
        for j in /var/sadm/pkg/$Pkgabbrev*; do
                OrigPkgver=`sed -n 's/^VERSION=\(.*\)$/\1/p' $j/pkginfo`
                minver=`expr $OrigPkgver : '\(.*\)\.0$'`
                while [ "$minver" != "" ] ; do
                        OrigPkgver=$minver
                        minver=`expr $OrigPkgver : '\(.*\)\.0$'`
                done
                if grep -s "^PKG=$Pkgabbrev$" $j/pkginfo > /dev/null 2>&1 \
                   && grep -s "^ARCH=$Pkgarch$" $j/pkginfo > /dev/null 2>&1 \
                   && [ "$OrigPkgver" = "$Pkgver" ] ;
		then
			pkginst=`basename $j`
			basedir=`grep '^BASEDIR' /var/sadm/pkg/$pkginst/pkginfo | sed -e 's@.*=\ *@@' -e 's@/$@@' -e 's@/a/@/@' -e 's@/a$@/@'`
			break;
		fi
	done

        if [ "$pkginst" = "" ] ; then
                echo "Inconsistent pkginfo values between patch and original pkg."
                echo "Compare pkginfo values for PKG, ARCH, or VERSION."
                echo "Installpatch has been terminated."
                exit 1
        fi

	# Generate list of files restored
	#

	rm -f /tmp/existfiles.$$
	cat /tmp/pkgfiles.$$ |
	(while read k
	do
		k=$basedir$k
		if ls -d $k >/dev/null 2>&1
		then
			echo $k >> /tmp/existfiles.$$
		fi
	done)
	cat /tmp/existfiles.$$ | installf $pkginst -
	installf -f $pkginst
done

if [ -f softinfo_sed ]; then
    sed -f softinfo_sed /var/sadm/softinfo/$prodver > /tmp/soft.$$
    mv /var/sadm/softinfo/$prodver /var/sadm/softinfo/sav.$prodver
    cp /tmp/soft.$$ /var/sadm/softinfo/$prodver
fi
if [ -f spooled_dirs ]; then
	cat spooled_dirs | xargs rm -fr
fi

cd /
rm -fr /var/sadm/patch/$patchnum

rm -f /tmp/*.$$

echo "backoutpatch finished."
exit 0


