#! /bin/sh
:
#ident	"@(#)smail/util:RELEASE-3_2_0_114:checkerr.sh,v 1.19 2001/08/03 13:32:13 woods Exp"
#
#    Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll
#    Copyright (C) 1992  Ronald S. Karr
# See the file COPYING, distributed with smail, for restriction
# and warranty information.

# Check for errors which have been deposited in the smail error
# directory.  If any new messages are found in this directory, save
# information related to those errors in the file .checkerror which is
# then mailed to the postmaster.  If the mail cannot be sent to the
# postmaster now, such as due to a configuration error, then try to
# send it in a future invocation of this script.

umask 022

PATH="/usr/local/libexec/smail:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"; export PATH
SMAIL_PROGRAM="/usr/local/sbin/sendmail"
SPOOL_DIRS="`$SMAIL_PROGRAM -bP spool_dirs`"
TMPDIR="/var/spool/smail/tmp"
if [ ! -d $TMPDIR ] ; then
	if mkdir $TMPDIR ; then
		chmod 700 $TMPDIR
	else
		echo "$0: $TMPDIR exists as a file!" 2>&1
		exit 1
	fi
fi
HOSTNAME="`$SMAIL_PROGRAM -bP primary_name`"
LOGFILE="`$SMAIL_PROGRAM -bP logfile`"
# Old fashioned smaillog form
OLD_LOGFILE="`echo $LOGFILE | sed -e 's,^\(.*\)/\([^/][^/]*\)$,\1/OLD/\2,'`"
PANICLOG="`$SMAIL_PROGRAM -bP paniclog`"
# Old fashioned smaillog form
OLD_PANICLOG="`echo $PANICLOG | sed -e 's,^\(.*\)/\([^/][^/]*\)$,\1/OLD/\2,'`"
DOT_Z=".gz"
ZCAT="gunzip -c"
PROG=$0

rm -f $TMPDIR/.chkerr.msg
cat > $TMPDIR/.chkerr.msg <<END_OF_FILE
From: MAILER-DAEMON
Subject: Mail errors on the host $HOSTNAME

Smail has detected new errors requiring your attention on the host
$HOSTNAME.

Messages which failed can be found in the directory:

	_SPOOLDIR_/error

and should be moved back to the directory:

	_SPOOLDIR_/input

when the situation which caused the error has been taken care of.
Messages which can neither be delivered nor bounced because of invalid
addresses should be examined to see if valid addresses can be
determined, and if not such messages can be disposed of as appropriate.

A sumary of these errors follows:
END_OF_FILE

# go into each spooling directory
(
    # silly trick to split SPOOL_DIRS on ':' without setting IFS in
    # the main script body
    IFS=:
    for i in $SPOOL_DIRS; do
	echo $i
    done
) | while read SPOOLDIR; do
    if [ ! -d $SPOOLDIR ] ; then
	# spool directory does not exist -- ignore it...
	continue
    fi
    cd $SPOOLDIR
    if [ $? != 0 ]; then
	# spool directory problems
	echo "" >> $TMPDIR/.chkerr.msg
	echo "WARNING: problem with changing to spool directory:  $SPOOLDIR" >> $TMPDIR/.chkerr.msg
	echo "" >> $TMPDIR/.chkerr.msg
	continue
    fi

    # cleanup old msg.* files in the input directory
    if [ -d input ]; then
	find input -name 'msg.*' -mtime +2 -print | while read fn
	do
	    rm -f "$fn"
	done
    fi

    # cleanup msglog files with no corresponding input or error file:
    if [ -d msglog ]; then
    	cd msglog		# XXX we should use find
	x="`echo [0-9]*`"	# XXX and a loop so as to not overflow cmd-line here!
	cd ..
	sleep 1			# avoids an almost impossible race condition
	if [ "$x" != '[0-9]*' ]; then
	    for i in $x; do
		if [ ! -f input/$i -a ! -f error/$i ]; then
		    rm -f msglog/$i
		fi
	    done
	fi
    fi

    # cleanup retry files older than any maximum retry time:
    if [ -d retry ]; then
	x=`$SMAIL_PROGRAM -bP retry_duration`
	# turn it back into #-of-days for find...
	def_retry_dur=`$SMAIL_PROGRAM -xD $x`
	max_retry_dur=$def_retry_dur
	RETRY_FILE=`$SMAIL_PROGRAM -bP retry_file`
	if [ -f "$RETRY_FILE" ]; then
		# 
		# sometimes using sh is like sucking dead bears
		# through hollow logs...  we have to do this nonsense
		# because while loops that read from pipes are
		# implemented in subshells so we force the issue so
		# that we can use an extra echo command in the
		# subshell to get the new value of max_retry_dur back
		# out again without using temporary data files...
		# 
		max_retry_dur=`awk '$1 ~ /^#/ { next; }
		     $1 ~ /^$/ { next; }
		     $2 ~ /\/./ {
			sub(/^.*\//, "", $2);
			printf("%s\n", $2);
		     }
		' $RETRY_FILE | (
		    while read x ; do
			y=\`$SMAIL_PROGRAM -xD $x\`
			if [ $y -gt $max_retry_dur ] ; then
			    max_retry_dur=$y
			fi
		    done
		    echo $max_retry_dur
		)`
	fi
	if [ $max_retry_dur -le 0 ] ; then
	    max_retry_dur=1
	fi
	find retry -type f -mtime +$max_retry_dur -print | xargs rm -f ""
    fi

    # if the last run found some errors, but couldn't deliver, try again now
    if [ -s .checkerror ]; then
	# don't send to the Postmaster if configuration errors still exist
	x="`$SMAIL_PROGRAM -bv Postmaster 2>/dev/null`"
	if [ "$x" ]; then
	    (
		sed -e "s;_SPOOLDIR_;$SPOOLDIR;g" $TMPDIR/.chkerr.msg
		echo ""
		cat .checkerror
	    ) | $SMAIL_PROGRAM -f"<+>" -eq -m Postmaster
	    if [ $? -ne 0 ]; then
		continue
	    fi
	    rm -f .checkerror
	else
	    # if we cannot reach the postmaster, don't go to the next step
	    continue
	fi
    fi

    if [ ! -d error ]; then
	# no error directory, so there could not be new errors
	continue
    fi

    # find any new errors
    if [ -f .lasttimedone ]; then
	mv -f .lasttimedone .thistime
	: > .lasttimedone
	find error -newer ../.thistime -name '[0-9]*' -print
    else
	: > .lasttimedone
	find error -name '[0-9]*' -print
    fi 2> /dev/null | while read f; do
	f=`expr "$f" : 'error/\(.*\)'`
	echo ""
	echo "------------------ Message $f ------------------"
	if [ -s msglog/$f ]; then
	    echo "The per-message log file contains:"
	    sed 's/^/ /' < msglog/$f
	else
	    echo "No per-message log file was created"
	fi
	echo ""
	echo "Logfile entries related to this message are:"
	(
	    if [ -f $LOGFILE ]; then
		cat $LOGFILE;
	    fi
	    if [ -f $LOGFILE.0 ]; then
		cat $LOGFILE.0;			# aka newsyslog
	    elif [ -f $LOGFILE.0$DOT_Z ]; then
		$ZCAT $LOGFILE.0$DOT_Z;		# aka newsyslog
	    fi
	    if [ -f $OLD_LOGFILE.0 ]; then
		cat $OLD_LOGFILE.0;		# aka smaillog
	    elif [ -f $OLD_LOGFILE.0$DOT_Z ]; then
		$ZCAT $OLD_LOGFILE.0$DOT_Z;	# aka smaillog
	    fi
	    if [ -f $LOGFILE.1 ]; then
		cat $LOGFILE.1;
	    elif [ -f $LOGFILE.1$DOT_Z ]; then
		$ZCAT $LOGFILE.1$DOT_Z;
	    fi
	    if [ -f $OLD_LOGFILE.1 ]; then
		cat $OLD_LOGFILE.1;
	    elif [ -f $OLD_LOGFILE.1$DOT_Z ]; then
		$ZCAT $OLD_LOGFILE.1$DOT_Z;
	    fi
	) | sed ":l1
		    /^[^|].*\[m$f\]/{
			:l2
			s/^/  /
			n
			/^|/!b l1
			s/^|	/|       /
			b l2
		    }
		    d"
	echo ""
	echo "Paniclog entries related to this messsage are:"
	(
	    if [ -f $PANICLOG ]; then
		cat $PANICLOG;
	    fi
	    if [ -f $PANICLOG.0 ]; then
		cat $PANICLOG.0;		# aka newsyslog
	    elif [ -f $PANICLOG.0$DOT_Z ]; then
		$ZCAT $PANICLOG.0$DOT_Z;	# aka newsyslog
	    fi
	    if [ -f $OLD_PANICLOG.0 ]; then
		cat $OLD_PANICLOG.0;		# aka smaillog
	    elif [ -f $OLD_PANICLOG.0$DOT_Z ]; then
		$ZCAT $OLD_PANICLOG.0$DOT_Z;	# aka smaillog
	    fi
	    if [ -f $PANICLOG.1 ]; then
		cat $PANICLOG.1;
	    elif [ -f $PANICLOG.1$DOT_Z ]; then
		$ZCAT $PANICLOG.1$DOT_Z;
	    fi
	    if [ -f $OLD_PANICLOG.1 ]; then
		cat $OLD_PANICLOG.1;
	    elif [ -f $OLD_PANICLOG.1$DOT_Z ]; then
		$ZCAT $OLD_PANICLOG.1$DOT_Z;
	    fi
	) | grep "\[m$f\]" | sed 's/^/  /'
    done > .newerrors

    mv .newerrors .checkerror

    if [ -s .checkerror ]; then
	# don't send to the Postmaster if configuration errors still exist
	x="`$SMAIL_PROGRAM -bv Postmaster 2>/dev/null`"
	if [ "$x" ]; then
	    (
		sed -e "s;_SPOOLDIR_;$SPOOLDIR;g" $TMPDIR/.chkerr.msg
		echo ""
		cat .checkerror
	    ) | $SMAIL_PROGRAM -f"<+>" -eq -m Postmaster
	    if [ $? -eq 0 ]; then
		rm -f .checkerror
	    fi
	fi
    fi
done

exit 0
