McAfee autoupdate & wrapper

Tony Finch fanf2 at CAM.AC.UK
Thu May 6 16:11:59 IST 2004


Following the discussion in March, I've found time to have a look at the
autoupdate script. I've added proxy and retry support, and it now uses
McAfee's own idea of the current dat file version rather than believing
the filesystem layout.

--
Tony Finch  <fanf2 at cam.ac.uk>  http://www.cus.cam.ac.uk/~fanf2/
    Mail Support, University of Cambridge Computing Service
     New Museums Site, Pembroke Street, Cambridge, CB2 3QH

-------------------------- MailScanner list ----------------------
To leave, send    leave mailscanner    to jiscmail at jiscmail.ac.uk
Before posting, please see the Most Asked Questions at
http://www.mailscanner.biz/maq/     and the archives at
http://www.jiscmail.ac.uk/lists/mailscanner.html
-------------- next part --------------
#!/bin/sh -e
#
# Update the McAfee data files.
#
# $Cambridge: hermes/conf/build/bin/uvscan-update,v 1.45 2004/05/06 15:07:47 fanf2 Exp $

# $PREFIX is the directory where the uvscan binary is (NOT a symlink to
# the binary), which is where it looks for its dat files. You may run
# uvscan via a symlink to this place (e.g. from /usr/local/bin/uvscan)
# and it will still look for the dat files here. If uvscan's library
# dependencies can be found in a standard place (e.g. /usr/local/lib)
# then you don't need a wrapper script to set LD_LIBRARY_PATH before
# running it.
#
# The dat files are installed in a subdirectory of $DATDIR named
# according to their version number, with symlinks from $PREFIX into
# the subdirectory via a current link. The current link is updated
# without locking on the assumption that this is sufficiently unlikely
# to cause a problem.

# defaults
OPTS=""
PREFIX=/opt/uvscan
FTPDIR=http://download.nai.com/products/datfiles/4.x/nai
RETRIES=1
INTERVAL=300

# handle the command line
usage () {
	echo "usage: $0 [-dfrtv] [-Rnnn] [-Innn] [proxy] [prefix]"
	echo "	-d	delete old files"
	echo "	-e	get extra.dat"
	echo "	-f	force update"
	echo "	-r	show README"
	echo "	-t	timestamp output"
	echo "	-v	verbose"
	echo "	-R	number of retries"
	echo "	-I	retry interval"
	echo "	proxy	URL of FTP/HTTP proxy server"
	echo "	prefix	uvscan installation directory"
	exit 1
}
case $# in
[012345])
	: ok
	;;
*)	usage
	;;
esac
for arg in "$@"
do
	case $arg in
	-I*)	INTERVAL=${arg#-I}
		;;
	-R*)	RETRIES=${arg#-R}
		;;
	-*)	OPTS=$arg
		;;
	/*)	PREFIX=$arg
		;;
	http:)	ftp_proxy=$arg
		http_proxy=$arg
		export ftp_proxy
		export http_proxy
		;;
	*)	usage
		;;
	esac
done
case $OPTS in
*[!-dfrtv]*)
	usage
esac
option () {
	case $OPTS in
	-*$1*)	eval $2=yes
		;;
	*)	eval $2=no
		;;
	esac
}
option d DELETE
option e EXTRA
option f FORCE
option r README
option t TIME
option v VERBOSE
case $FORCE in
yes)	VERBOSE=yes
esac

# look for binaries and libraris in plausible places
PATH=$PREFIX:/usr/local/bin:/usr/bin:/bin
# this is only necessary for broken setups
LD_LIBRARY_PATH=$PREFIX
export PATH LD_LIBRARY_PATH

# where this script finds things
DATDIR=$PREFIX/datfiles
LINKREL=datfiles/current
LINKABS=$PREFIX/$LINKREL

# wrapper functions for echo etc.
timestamp () {
	case $TIME in
	yes)	date "+%Y-%m-%d %H:%M:%S "
	esac
}
say () {
	case $VERBOSE in
	yes)	echo "`timestamp`$*"
	esac
}
run () {
	say "> $*"
	"$@"
}
testeval () {
	# ugly workaround
	say "> $*"
	set +e
	eval "$*"
	ret=$?
	set -e
	return $ret
}
is () {
	test "$@" 2>/dev/null
}
say Starting $0
say DELETE=$DELETE
say FORCE=$FORCE
say README=$README
say TIME=$TIME
say VERBOSE=$VERBOSE
say RETRIES=$RETRIES
say INTERVAL=$INTERVAL
say PROXY=$ftp_proxy
say PREFIX=$PREFIX

if ! is -d $DATDIR || ! is -h $LINKABS
then
	INIT=yes
	VERBOSE=yes
	say Initial setup of $0
	run mkdir -p $DATDIR
fi
run cd $DATDIR

getver () {
	match="[0-9][0-9][0-9][0-9]"
	err="version.err"
	cmd="$1" out="$2" txt="$3"
	if testeval "$cmd 2>$err 1>&2"
	then
		VER=`cat $out | sed "/^$txt\($match\).*$/!d;s//\1/;q"`
		case $VER in
		$match)	run rm -f $out $err
			return
		esac
	fi
	cat $err
	VER=UNKNOWN
	run rm -f $out $err
}

# work out latest dat version
try=$RETRIES
while :
do	getver "wget --tries=$try --waitretry=$INTERVAL --passive-ftp $FTPDIR/update.ini" update.ini "DATVersion="
	VERSION=$VER
	case $VERSION in
	UNKNOWN)
		if ! try=`expr $try - 1`
		then break
		fi
		say Problem with McAfee datfile update from $FTPDIR
		say Sleeping for $INTERVAL seconds before retrying
		sleep $INTERVAL
		;;
	*)	break
		;;
	esac
done

# work out installed dat version
getver "uvscan --version" version.err "Virus data file v"
PREVIOUS=$VER

case $FORCE in
yes)	say Forced update from $PREVIOUS
	PREVIOUS=0000
	;;
*)	if is $VERSION -eq $PREVIOUS
	then	say Already have $VERSION
		run exit 0
	fi
esac

VERBOSE=yes

say Installed dat file is $PREVIOUS
say Latest dat file is $VERSION

if is $VERSION = UNKNOWN
then 	say Problem with McAfee datfile update from $FTPDIR
	run exit 1
elif is $VERSION -lt $PREVIOUS
then	say Remote version $VERSION older than installed version $PREVIOUS
	run exit 1
elif is -d $VERSION
then	say Cleaning away $VERSION directory
	run rm -rf $VERSION
fi

retry () {
	echo "$OUT"
	say Fetch or test failed -- removing bad McAfee data files
	run cd $DATDIR
	run rm -rf $VERSION
	if ! try=`expr $try - 1`
	then	say Giving up
		run exit 1
	fi
	say Sleeping for $INTERVAL seconds before retrying
	sleep $INTERVAL
	continue
}

try=$RETRIES
while :
do
	# fetch and extract dat files
	TARFILE=dat-$VERSION.tar
	run mkdir $VERSION
	run cd $VERSION
	if ! run wget --tries=$try --waitretry=$INTERVAL --passive-ftp --progress=dot:mega $FTPDIR/$TARFILE
	then retry
	fi
	run tar xvf $TARFILE

	# verify the contents
	CMD="uvscan --version --dat ."
	say "> $CMD"
	OUT=`$CMD 2>&1`
	case "$OUT" in
	*"Missing or invalid DAT"* | \
	*"Data file not found"* | \
	*"Removal datafile clean.dat not found"* | \
	*"Unable to remove viruses"* )
		retry
		;;
	*)	break
		;;
	esac
done

echo "$OUT"
say Update OK

# show information on this update?
case $README in
yes)	run sed	's/[[:cntrl:]]//g
		1,/^====================/d
		/^====================/,/^NEW VIRUSES DETECTED/d
		/^UNDERSTANDING VIRUS NAMES/,$d
		s/^/# /;/@MM/s/$/ <--/' readme.txt
esac
# remove some crap
run rm -f *.diz *.exe *.ini *.lst *.tar *.txt

# do remaining part of initial setup
case $INIT in
yes)	for file in *.dat extra.dat
	do
		run rm -f $PREFIX/$file
		run ln -s $LINKREL/$file $PREFIX/$file
	done
esac

# update the current version link
run rm -f $LINKABS
run ln -s $VERSION $LINKABS

# maybe delete old dat files
case $DELETE in
yes)	run cd $DATDIR
	run rm -rf $PREVIOUS
esac

say Completed OK
run exit 0

# done


More information about the MailScanner mailing list