#!/bin/sh
# $Id$

ETCDIR=${ETCDIR-"/etc/avenger"}
export ETCDIR
DEFSUFFIX=${DEFSUFFIX-"default"}
export DEFSUFFIX

unset opt_cmd
unset opt_file
unset FILEX
unset local_ok

_usage () {
    echo usage: `basename $0`: '{-s file | ext}' >&2
    exit 0
}

_init_return () {
    if test "$#" -gt 0; then
	reject "$@"
    fi
    exit 0
}

_findfile () {
    if test -z "${1+set}"; then
	opt_file=./$opt_cmd
	test -f "$opt_file" && return
	_init_return
    elif test -n "$SEPARATOR"; then
	_rest="$1"
	unset _chopped
	FILEX="${SEPARATOR}$_rest"
	opt_file="./$opt_cmd${FILEX}"
	while :; do
	    test -f "./local${FILEX}" && local_ok=yes
	    if test -f "$opt_file"; then
		PREFIX="$_rest"
		SUFFIX="$_chopped"
		_i=1
		while :; do
		    _rest="${_chopped#*$SEPARATOR}"
		    test x"$_rest" = x"$_chopped" && break
		    _chopped="$_rest"
		    eval SUFFIX${_i}='"$_chopped"'
		    eval export SUFFIX${_i}
		    _i=$(($_i+1))
		done
		return
	    fi
	    test -z "$_rest" && break
	    _next="${_rest%$SEPARATOR*}"
	    if test x"$_next" = x"$_rest"; then
		#echo "rest is $_rest"
		#echo "chopped is $_chopped"
		#echo "chopped+ is ${_chopped:+${SEPARATOR}}"
		_chopped="${_rest}${_chopped:+${SEPARATOR}}${_chopped}"
		_rest=''
	    else
		_chopped="${_rest##*$SEPARATOR}${_chopped:+${SEPARATOR}}$_chopped"
		_rest="$_next"
	    fi
	    FILEX="${_rest:+$SEPARATOR}$_rest${SEPARATOR}${DEFSUFFIX}"
	    opt_file="./$opt_cmd$FILEX"
	done
    fi
    _init_return user unknown
}

_init () {
    exec 3>&0 0</dev/null 1>&2
    unset _opt_s
    opt_cmd=rcpt
    while getopts mrs: _name; do
	case $_name in
	    s)
		_opt_s="$OPTARG"
		;;
	    r)
		opt_cmd=rcpt
		;;
	    m)
		opt_cmd=mail
		;;
	    ?)
		_usage
		;;
	esac
    done
    shift $(($OPTIND - 1))
    if test -n "${_opt_s+set}"; then
	test "$#" -gt 0 && _usage
	case "$_opt_s" in
	    /*)
		opt_file="$_opt_s"
		;;
	    *)
		opt_file="$ETCDIR/$_opt_s"
		;;
	esac
	test -f "$opt_file" || _init_return
    else
	test "$#" -gt 1 && _usage
	_findfile "$@"
	export FILEX
	export PREFIX
	export SUFFIX
	exec >> log${FILEX} 2>&1
    fi
}

setvars () {
    echo . >&3
    while read _line <&3 ; do
	case $_line in
	    .*)
		return
		;;
	    _*=*)
		eval ${_line%%=*}='"${_line#*=}"'
		;;
	    *=*)
		eval ${_line%%=*}='"${_line#*=}"'
		eval export ${_line%%=*}
		;;
	esac
    done
    echo premature EOF from asmtpd >&2
    exit 111
}

errcheck () {
    test -z "$MAIL_ERROR" && return
    if test -z "$*"; then
	printf "return %s\n" "$MAIL_ERROR" >&3
    else
	printf "return %s\n" "$*" >&3
    fi
    exit 0
}

accept () {
    if test -z "$*"; then
	echo return 250 ok >&3
    else
	#echo return 250 "$*" >&3
	printf "return 250 %s\n" "$*" >&3
    fi
    exit 0
}

reject () {
    if test -z "$*"; then
	echo return 550 command rejected for policy reasons >&3
    else
	#echo return 550 "$*" >&3
	printf "return 550 %s\n" "$*" >&3
    fi
    exit 0
}

defer () {
    if test -z "$*"; then
	echo return 451 temporary error in processing >&3
    else
	#echo return 451 "$*" >&3
	printf "return 451 %s\n" "$*" >&3
    fi
    exit 0
}

bodytest () {
    if test -z "$*"; then
	echo "usage: bodytest command [arg...]" >&2
	exit 1
    fi
    echo "bodytest $* 2>>$PWD/log${FILEX}" >&3
    exit 0
}

redirect () {
    if test -z "$*"; then
	echo "usage: redirect user" >&2
	exit 1
    fi
    echo "redirect $*" >&3
    exit 0
}

greylist () {
    _key="$*"
    test -z "$_key" && _key="$CLIENT_IP $RECIPIENT $SENDER"
    dbutil --expire=+$greylist_ttl2 -q greylist_ok.db "$_key"
    test "$?" != 1 && return
    _time=`dbutil -t +$greylist_delay` || return
    dbutil --expire=+$greylist_ttl1 -nu greylist.db "$_key" "$_time"
    _time=`dbutil -q greylist.db "$_key"`
    test -z "$_time" && return
    _now=`dbutil -t` || return
    if test "$_now" -gt "$_time"; then
	dbutil -u greylist_ok.db "$_key" 1
	dbutil -x greylist.db "$_key"
	return
    fi
    defer Try again in $((($_time-$_now+59)/60)) minutes
}

spf () {
    if test "$#" -lt 1; then
	echo 'usage: spf VARIABLE-NAME [spf mechanisms...]' >& 2
    else
	echo "spf $*" >&3
    fi
}

spf1 () {
    if test "$#" -lt 1; then
	echo 'usage: spf1 VARIABLE-NAME [spf mechanisms...]' >& 2
    else
	echo "spf1 $*" >&3
    fi
}

dns () {
    if test "$#" -ne 3; then
	echo 'usage: dns VARIABLE-NAME TYPE DOMAIN-NAME' >&2
    fi
    case "$2" in
	a|mx|ptr|txt)
	    echo dns-"$2" "$1" "$3" >&3
	    ;;
	*)
	    echo "bad DNS request type $2" >&2
	    ;;
    esac
}

rbl () {
    unset _opt_i
    unset _opt_p
    unset _opt_f
    OPTIND=1
    while getopts ipfs: _name; do
	case $_name in
	    i)
		_opt_i=1
		;;
	    p)
		_opt_p=1
		;;
	    f)
		_opt_f=1
		;;
	    *)
		echo 'usage: rbl [-i][-p][-f] VARIABLE-NAME DOMAIN' >&2
		return
		;;
	esac
    done
    shift $(($OPTIND - 1))
    if test "$#" -ne 2; then
	echo 'usage: rbl [-i][-p][-f] VARIABLE-NAME DOMAIN' >&2
	return
    fi
    test -z "$_opt_i" -a -z "$_opt_p" -a -z "$_opt_f" && _opt_i=1
    test "$_opt_i" && echo "dns-a $1 $CLIENT_REVIP.$2" >&3
    test "$_opt_p" -a "${CLIENT_NAME+set}" \
	&& echo "dns-a $1 $CLIENT_NAME.$2" >&3
    test "$_opt_f" -a "${SENDER_HOST+set}" \
	&& echo "dns-a $1 $SENDER_HOST.$2" >&3
}

greylist_delay=30m		# Seconds to wait before allowing message
greylist_ttl1=5h		# How long to remember first-time senders
greylist_ttl2=36D		# How long to remember ok senders

_init "$@"
. "$opt_file"
exit 0
