#!/bin/bash
# $Header: /cvs/WebShield/wsrc/files/mgmt/add_extra_rule,v 1.5 2004/08/03 14:25:09 bwhittak Exp $
#
# Copyright (C) 2004 Networks Associates Technology Inc. All rights reserved.
#
# Called by the UI to add an extra.rule file obtained from user.
#
if [ -f $NETAWSS/.profile.vars ]; then
    . $NETAWSS/.profile.vars
else
    . /var/NAIENV/.profile.vars
fi
[[ "$PATH" == "$wsPATH":* || -z "$wsPATH" ]] || PATH=$wsPATH:$PATH

shopt -s extglob
shopt -s nullglob
. spam-functions

# what do I call myself?
declare -r me=${0##*/}
declare -r cmdline="$me $*"

# constants
declare -r inst="$me.$(date -u '+%Y%m%d%H%M%S').$$"
declare -r tmp=/tmp/$inst	# temporary directory

# event codes
declare -r PROGevent=UPDATE_PROGRESS
declare -r CHNGevent=SPAM_UPDATE_CHANGE
declare -r NOCHevent=SPAM_UPDATE_NOCHANGE
declare -r FAILevent=SPAM_UPDATE_FAIL
declare -r INTRevent=SPAM_UPDATE_INTR

# functions

SendLog()	# send stuff to syslog and echo to stdout
{
    local saverr=$?	# save previous error
    [[ $# -gt 0 ]] || return $saverr	# nothing to send
    printf '%s\n' "$@" >&2
    printf '%s\n' "$@" | logger -t "$me[$$]"
    return $saverr	# return saved error
}

envl=( \
	${WS_SESSION:+-i UI_SESSION_ID -v "$WS_SESSION"} \
	${WS_USER_ID:+-i USER_NAME -v "$WS_USER_ID"} \
	${WS_SOURCE_IP:+-i SOURCE_IP -v "$WS_SOURCE_IP"} \
)	# list of event properties derived from UI environment
Event()		# report an event
{
    evrep -n $me -i AUDIT_ID -v $inst "$@" "${extralist[@]}" "${envl[@]}"
}

declare -a bad_reason	# reason array for last bad event
GoodEvent()	# a good update progress event
{
    local saverr=$?	# save previous error
    bad_reason=()
    Event -e $PROGevent::"$@"
    return $saverr	# return saved error
}
BadEvent()	# a bad update progress event
{
    local saverr=$?	# save previous error
    bad_reason=( "$@" )	# save the reason for possible exit
    Event -e $PROGevent::"$@"
    return $saverr	# return saved error
}

declare -a exit_event	#event array set by Exit caller for exit event
Exit()		# the standard way out
{
    error=${1:-$?}		# set exit code
    shift
    SendLog "$me: Exit $error: $*"
    # send events
    [[ -n $exit_event ]] || exit_event=$FAILevent
    Event -e "${exit_event[@]}"
    exit $error
}

BadExit()	# failed for some reason
{
    if [[ $1 == "-e" ]]; then
	exit_event=( $2 )
	shift 2
    elif [[ -n $bad_reason ]]; then
	exit_event=( "$FAILevent::${bad_reason[@]}" )
    else
	exit_event=( "$FAILevent" )
    fi
    Exit 1 "$@"
}

trap 'BadExit -e $INTRevent on signal' hup int term

GoodExit()	# all happy
{
    if [[ $1 == "-e" ]]; then
	exit_event=( $2 )
	shift 2
    fi
    Exit 0 "$@"
}

GiveUp()
{
    # build event reason array
    local -a r=( $1 )
    while shift && [[ $1 == -* ]]; do r=( "${r[@]}" "$1" "$2" ); shift; done
    # rest is system output
    local IFS=$'\n'
    [[ $# -gt 0 ]] && r=( "${r[@]}" -i SYSTEM_ERROR_TEXT -v "$*" )
    BadEvent "${r[@]}"
    BadExit "$r:" "$@"
}

# now we start
GoodEvent UpdateLocal -i COMMANDLINE -v "$cmdline"

[[ $# -gt 0 ]] || GiveUp NoFile

trap 'rm -rf "$tmp"' EXIT
out=$(exec 2>&1; rm -rf "$tmp" && mkdir -p "$tmp") ||
    GiveUp SystemCommandError "$out"

for f do
    # basic check for well formed RPM
    out=$(file "$f" 2>&1) && [[ $out == "$f: RPM "* ]] &&
    rpm_name=$(rpm -qp \
	--queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}.rpm' "$f") &&
    out=$(rpm -K --nosignature "$f" 2>&1) || GiveUp RPMmalformed "${out#"$f: "}"
    # check it has only legal files
    list=$(rpm -qlp --nosignature "$f" 2>&1)
    out=$(echo "$list" | grep -v '/etc/mail/spamassassin/[^/]*\.cf' 2>&1)
    [[ -z "$out" ]] || GiveUp RPMbadFiles "$out"
    # make sure none of them are installed already
    out=$( (rpm -qlp $SPAMRPMEXTRA/*.rpm 2>/dev/null
		ls -d /etc/mail/spamassassin/*.cf) | fgrep -x "$list" )
    [[ -z "$out" ]] || GiveUp RPMconflictFiles "$out"
    # check it's got no scripts
    out=$(rpm -q --triggers --scripts --nosignature -p "$f" 2>&1)
    [[ -z "$out" ]] || GiveUp RPMbadScripts "$out"
    out=$(cp "$f" "$tmp/$rpm_name" 2>&1) || GiveUp SystemCommandError "$out"
    rpms=( "${rpms[@]}" "$tmp/$rpm_name" )
    rpm_list=( "${rpm_list[@]}" $rpm_name )
    unset rpm_name
done
extralist=( ${rpm_list[@]/#/-i RPM_NAME -v } )

# check for RPM conflicts and dependency problems
out=$(exec 2>&1; inrpms=$(GetLatest) &&
	rpm --test -i --nodeps \
	    $inrpms/*.rpm $SPAMRPMEXTRA/*.rpm "${rpms[@]}") ||
	GiveUp RPMconflict "$out"

# check rules file validity
out=$(exec 2>&1; inrpms=$(GetLatest) &&
	TestSpamRPMs $inrpms/*.rpm $SPAMRPMEXTRA/*.rpm "${rpms[@]}") ||
	GiveUp UpdateTestFail

# have a go at installing
out=$(wsmount 2>&1 <<-END
	mkdir -p "$SPAMRPMEXTRA"
	cp "${rpms[@]}" "$SPAMRPMEXTRA"
	END) || GiveUp SystemCommandError "$out"

# restart spamd
out=$(/etc/init.d/spamassassin_jail restart) ||
    GiveUp SystemCommandError "$out"

# I can find no fault with this file
GoodExit -e $CHNGevent::AddExtraRule
