#! /bin/sh
# smart patch applier
# Copyright (C) 1999  Henry Spencer.
# 
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
# 
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# patcher [-v] patchfile targetdir target key
# From targetdir, patch target from patchfile unless it already contains
# key and it appears to have been patched with the same patch.  Backup
# original as target.preipsec, and patched copy as target.wipsec, with
# patch md5sum stored as target.ipsecmd5.
#
# RCSID $Id: patcher,v 1.5 1999/04/10 22:51:28 henry Exp $

verbose=

for dummy
do
	case "$1" in
	-v)	verbose=yes		;;
	--)	shift ; break		;;
	-*)	echo "$0: unknown option \`$1'" >&2 ; exit 2	;;
	*)	break			;;
	esac
	shift
done
if test $# -ne 4
then
	echo "Usage: $0 [-v] patchfile targetdir target key" >&2
	exit 2
fi

patchfile="$1"
dir="$2"
target="$3"
key="$4"

need() {
	if test ! -f $1
	then
		echo "$0: cannot find file \`$1'" >&2
		exit 1
	fi
}

need $patchfile
need $dir/$target
psum="`md5sum $patchfile | awk '{print $1}'`"

if test ! -f $dir/$target.ipsecmd5
then
	# no records of patching...
	if egrep -q "$key" $dir/$target
	then
		# patched but no record of how
		echo "$0: $dir/$target has old patch which cannot be verified or undone" >&2
		exit 1
	fi
	# looks like it's never been patched, proceed to patching
elif test " `cat $dir/$target.ipsecmd5`" = " $psum"
then
	# patch has not changed
	if test "$verbose"
	then
		echo "* $patchfile apparently already installed"
	fi
	exit 0
elif test ! -f $dir/$target.preipsec -o ! -f $dir/$target.wipsec
then
	echo "$0: $dir/$target has out-of-date patch which cannot be undone" >&2
	echo "$0:	($target.preipsec or $target.wipsec is missing)" >&2
	exit 1
elif ! cmp -s $dir/$target $dir/$target.wipsec
then
	echo "$0: cannot unpatch $dir/$target, it has changed since patching" >&2
	exit 1
else
	# must undo old patch
	rm $dir/$target
	mv $dir/$target.preipsec $dir/$target
	rm $dir/$target.wipsec $dir/$target.ipsecmd5
fi

# now, try to figure out patch options
if patch --help >/dev/null 2>/dev/null
then
	# looks like a modern version
	popts='-p0 -b -z .preipsec'
else
	# looks like an old one
	popts='-p0 -b .preipsec'
fi

if ( cd $dir ; patch $popts ) <$patchfile
then
	if test ! -f $dir/$target.preipsec
	then
		echo "$0: backup file $dir/$target.preipsec not created properly" >&2
		exit 1
	fi
	cp -p $dir/$target $dir/$target.wipsec
	echo "$psum" >$dir/$target.ipsecmd5
else
	exit 1
fi
