#!/bin/sh
# @(#) backoutpatch 3.2 93/02/18 SMI
# (internal revision info): $Revision: 1.9 $ $Date: 1993/02/11 05:15:22 $
echo "@(#) backoutpatch 3.2 93/02/18"

# change log (starting from 2/8/93): 
# 
# 2/8/93 - Installpatch and backoutpatch should permit a patch 
#          to be installed which contains only postinstall scripts 
#          and no actual files delivered.
# 2/9/93 - Backoutpatch should resolve macros in the pkgmap.
# 2/9/93 - pkgrm should be executed in such a way that messages
#          are echoed to the screen in addition to the log.

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 -a \
     ! -f /var/sadm/patch/$patchnum/.nofilestosave ]; 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 > /tmp/pkgrmlog.$$ 2>&1
	pkgrmerr=$?
        cat /tmp/pkgrmlog.$$ >> /var/sadm/patch/$patchnum/log
        cat /tmp/pkgrmlog.$$ 
        rm /tmp/pkgrmlog.$$
        if [ $pkgrmerr != 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
#
if [ ! -f /var/sadm/patch/$patchnum/.nofilestosave ]; then
	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
		#
		# 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
		#

		sed -e '/^:/d' -e '/^[^ ][^ ]* i/d' $i/pkgmap | \
		sed 's/^[^ ]* . [^ ]* \([^ ]*\).*$/\/\1/' > /tmp/pkgfiles.$$
		if [ -s /tmp/pkgfiles.$$ ]; then
			#
			# resolve any macros in the list of files
			#
			(rm -f /tmp/pkgmacros.$$ /tmp/resolvedfiles.$$
			cat /var/sadm/pkg/$pkginst/pkginfo |
			while read i
			do
				echo `echo $i| sed -e 's/^\(.*\)=.*/\1/'`=\"`echo $i|sed -e 's/^\(.*\=\)//'`\" | grep -v '^PATH' >> /tmp/pkgmacros.$$
			done
			. /tmp/pkgmacros.$$
		        cat /tmp/pkgfiles.$$ | 
		        while read i 
		        do
				eval echo $i >> /tmp/resolvedfiles.$$
			done
			)
			rm -f /tmp/existfiles.$$
			cat /tmp/resolvedfiles.$$ |
			(while read k
			do
				k=$basedir$k
				if ls -d $k >/dev/null 2>&1
				then
					echo $k >> /tmp/existfiles.$$
				fi
			done)
			if [ -s /tmp/existfiles.$$ ]; then
				cat /tmp/existfiles.$$ | installf $pkginst -
				installf -f $pkginst
			fi
		fi
	done
fi

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


