#! /bin/sh
. /usr/local/news/lib/innshellvars

##  $Revision: 1.6 $
##  Summarize INN log files.
##  Optional arguments:
##	norotate	Do not rotate logfiles

##  If you get an error from this line:
##	sh -c 'egrep "`ls /etc`" /dev/null'
##  then get a better egrep, like the FSF one.

##  Directory where old log files are kept.
OLD=${MOST_LOGS}/OLD
##  If you want to archive the active file, enable this line.
ACTIVEFILE=${ACTIVE}
##  Number of lines of error in each category to report.
TOP=${TOP-20}
##  NN log file.
NN=${PATHETC}/nn/Log
##  Where nntpsend, if used, writes its log information.
NNTPSEND=${MOST_LOGS}/nntpsend.log
##  Where news.daily places expire output, unless noexplog was used.
EXPLOG=${MOST_LOGS}/expire.log

##  If you divide your news syslog into separate files, list them here.
SYSLOG_CRIT=${MOST_LOGS}/news.crit
SYSLOG_ERR=${MOST_LOGS}/news.err
SYSLOG_NOTICE=${MOST_LOGS}/news.notice
SYSLOGS="${SYSLOG_CRIT} ${SYSLOG_ERR} ${SYSLOG_NOTICE}"

##  Where tally control and unwanted processors are found.
TALLY_CONTROL=${PATHBIN}/tally.control
TALLY_UNWANTED=${PATHBIN}/tally.unwanted
UNWANTED_LOG=${MOST_LOGS}/unwanted.log
CONTROL_LOG=${MOST_LOGS}/control.log
CONTROL_DATA=
test -f ${MOST_LOGS}/newgroup.log && CONTROL_DATA=${MOST_LOGS}/newgroup.log
test -f ${MOST_LOGS}/rmgroup.log \
	&& CONTROL_DATA="${CONTROL_DATA} ${MOST_LOGS}/rmgroup.log"

##  Build up the list of log files to process.
LOGS="${ERRLOG} ${EXPLOG} ${LOG} ${ACTIVEFILE} ${SYSLOGS} ${UNWANTED_LOG}"

test -n "${NNTPSEND}" -a -f "${NNTPSEND}" && LOGS="${LOGS} ${NNTPSEND}"
test -n "${CONTROL_DATA}" && LOGS="${LOGS} ${CONTROL_LOG}"
for F in checkgroups default ihave newgroup rmgroup sendme sendsys \
	senduuname version miscctl badcontrol failedpgp badpgp; do
    test -f ${MOST_LOGS}/${F}.log && LOGS="${LOGS} ${MOST_LOGS}/${F}.log"
done

PROGNAME=scanlogs
LOCK=${LOCKS}/LOCK.${PROGNAME}

##  Set defaults.
ROTATE=true

##  Parse JCL.
for I
do
    case "X${I}" in
    Xnonn)
	# Ignore this.
	;;
    Xnorotate)
	ROTATE=false
	;;
    *)
	echo "Unknown flag ${I}" 1>&2
	exit 1
	;;
    esac
done

##  Make sure every log exists.
for F in ${LOGS} ; do
    test ! -f ${F} && touch ${F}
done

##  Temporary files.
T=${TMPDIR}/scan$$
PROBS=${TMPDIR}/scanlog$$
trap "rm -f ${T} ${PROBS}; exit 0" 0 1 2 3 15

##  Rotate the logs?
if ${ROTATE} ; then
    ##  Lock out others.
    shlock -p $$ -f ${LOCK} || {
	echo "$0: Locked by `cat ${LOCK}`"
	exit 1
    }
    trap "rm -f ${T} ${PROBS} ${LOCK}; exit 0" 1 2 3 15

    HERE=`pwd`
    cd ${MOST_LOGS}
    test ! -d ${OLD} && mkdir ${OLD}

    ctlinnd -s logmode
    PAUSED=false
    ctlinnd -s pause "Flushing log and syslog files" 2>&1 && PAUSED=true
    OUTPUT=`ctlinnd flushlogs 2>&1`
    if [ "$OUTPUT" != "Ok" -a "$OUTPUT" != "In debug mode" ]; then
	echo "$OUTPUT"
	echo 'Cannot flush logs.'
	rm -f ${LOCK}
	exit 1
    fi

    ##  Make sure these .old files exist, in case innd is down.
    for F in ${LOG} ${ERRLOG} ${EXPLOG} ; do
	if [ ! -f ${F}.old ]; then
	    rm -f ${F}.old
	    cp ${F} ${F}.old
	    cat /dev/null >${F}
	fi
    done

    ##  Copy syslog files, truncating old inode since syslog has it open.
    for F in ${SYSLOGS}; do
	rm -f ${F}.old
	cp ${F} ${F}.old
	cat /dev/null >${F}
    done
    ctlinnd -s logmode

    ##  Make a copy of the active file.
    if [ -n ${ACTIVEFILE} ] ; then
	BASE=`basename ${ACTIVEFILE}`
	rm -f ${OLD}/${BASE}.old
	cp ${ACTIVEFILE} ${OLD}/${BASE}.old
    fi

    ##  These are live files, so use link rather than copy.
    for F in ${NNTPSEND} ; do
	if [ -f ${F} ]; then
	    rm -f ${F}.old ${F}.new
	    ln ${F} ${F}.old
	    touch ${F}.new
	    chmod 0660 ${F}.new
	    mv ${F}.new ${F}
	fi
    done

    ##  Tally control messages if we logged them.
    test -n "${CONTROL_DATA}" && cat ${CONTROL_DATA} | ${TALLY_CONTROL}

    ${PAUSED} && ctlinnd -s go "Flushing log and syslog files" 2>&1

    cd ${OLD}
    for F in ${LOGS}; do
	##  Process the current (just-flushed) log
	BASE=`basename ${F}`
	rm -f ${OLD}/${BASE}
	case ${F} in
	${SYSLOG_CRIT}|${ERRLOG}|${EXPLOG}|${LOG}|${SYSLOG_NOTICE})
	    ##  Make a link that can be deleted (since if not rotating
	    ##  we delete the copy that is made in ${TMPDIR}).
	    mv ${F}.old ${OLD}/${BASE}
	    rm -f ${OLD}/${BASE}.0
	    ln ${OLD}/${BASE} ${OLD}/${BASE}.0
	    ;;
	${ACTIVEFILE})
	    mv ${BASE}.old ${OLD}/${BASE}
	    ;;
	${SYSLOG_ERR})
	    mv ${F}.old ${OLD}/${BASE}
	    ;;
	${UNWANTED_LOG})
	    ##  Rotate and compress the file.
	    BASE=`basename ${F}`
	    if [ ! -f ${BASE} -a -f ../${BASE} ]; then
		cp ../${BASE} ${BASE}
		chmod 0440 ${BASE}
	    fi
	    if [ -f ${BASE} ]; then
		${LOG_COMPRESS} <${BASE} >${BASE}.0${Z} && rm -f ${BASE}
		chmod 0440 ${BASE}.0${Z}

		##  Do rotation.
		if [ X${LOGCYCLES} = X ]; then       
		    LOGCYCLES=3
		fi
		EXT=${LOGCYCLES}
		rm -f ${BASE}.${LOGCYCLES}${Z}
		while [ ${EXT} -gt 0 ] ; do
		    NEXT=${EXT}
		    EXT=`expr ${EXT} - 1`
		    test -f ${BASE}.${EXT}${Z} \
			&& rm -f ${BASE}.${NEXT}${Z} \
			&& mv ${BASE}.${EXT}${Z} ${BASE}.${NEXT}${Z}
		done
	    fi
	    ##  Innreport assumes where unwanted.log exists, so leave it
	    ##  and process later.
	    ;;
	*)
	    if [ -f ${F}.old ]; then
		mv ${F}.old ${OLD}/${BASE}
	    else
		rm -f ${OLD}/${BASE} ${F}.new
		touch ${F}.new
		chmod 0660 ${F}.new
		ln ${F} ${F}.old
		mv ${F}.new ${F}
		mv ${F}.old ${OLD}/${BASE}
	    fi
	    ;;
	esac
    done
    cd ${HERE}

    ##  Truncate logs from send-nntp and/or send-uucp.
    if [ -s ${MOST_LOGS}/send-nntp.log ] ; then
	${LOG_COMPRESS} <${MOST_LOGS}/send-nntp.log >${OLD}/send-nntp.1${Z}
	cat /dev/null >${MOST_LOGS}/send-nntp.log
    fi
    if [ -s ${MOST_LOGS}/send-uucp.log ] ; then
	${LOG_COMPRESS} <${MOST_LOGS}/send-uucp.log >${OLD}/send-uucp.1${Z}
	cat /dev/null >${MOST_LOGS}/send-uucp.log
    fi
else
    ##  Don't use the real OLD directory, instead use TMPDIR
    OLD=${TMPDIR}

    ##  Make a snapshot of what we need for below.
    ctlinnd -s pause "Snapshot log and syslog files" 2>&1
    for F in ${SYSLOG_CRIT} ${ERRLOG} ${EXPLOG} ${LOG} ${SYSLOG_NOTICE} ; do
	BASE=`basename ${F}`
	rm -f ${OLD}/${BASE}.0
	cp ${F} ${OLD}/${BASE}.0
    done
    ctlinnd -s go "Snapshot log and syslog files" 2>&1
fi

##
##  We now (finally!) have copies of the log files where we need them.
##

##  Display syslog critical messages.
BASE=`basename ${SYSLOG_CRIT}`
OLD_SYSLOG=${OLD}/${BASE}.0
if [ -s ${OLD_SYSLOG} ] ; then
    echo Syslog critical messages:
    cat ${OLD_SYSLOG}
    echo ---------
    echo ''
fi
rm -f ${OLD_SYSLOG}

##  Display error log.
BASE=`basename ${ERRLOG}`
OLD_ERRLOG=${OLD}/${BASE}.0
if [ -s ${OLD_ERRLOG} ] ; then
    echo Error log:
    cat ${OLD_ERRLOG}
    echo ---------
    echo ''
fi
rm -f ${OLD_ERRLOG}

##  Scan for various problems in articles we were offered or sent...
BASE=`basename ${LOG}`
OLD_LOG=${OLD}/${BASE}.0

##  and summarize syslog information.
BASE=`basename ${SYSLOG_NOTICE}`
OLD_SYSLOG=${OLD}/${BASE}.0
if [ -s ${OLD_SYSLOG} -o -s ${OLD_LOG} ] ; then
    ${PATHBIN}/innreport -f ${PATHETC}/innreport.conf ${OLD_SYSLOG} ${OLD_LOG}
    echo ---------
    echo ''
fi
rm -f ${OLD_LOG} ${OLD_SYSLOG}
if ${ROTATE} ; then
    BASE=`basename ${UNWANTED_LOG}`
    if [ -f ${UNWANTED_LOG}.old ]; then
	mv ${UNWANTED_LOG}.old ${OLD}/${BASE}
    else
	rm -f ${OLD}/${BASE}
	cp ${UNWANTED_LOG} ${OLD}/${BASE}
	chmod 0660 ${OLD}/${BASE}
    fi
fi

OLD_SYSLOG=${OLD}/${EXPLOG}.0
rm -f ${EXPLOG}

##  Compress and rotate the logs.
if ${ROTATE} ; then
    cd ${OLD}
    if [ X${LOGCYCLES} = X ]; then       
        LOGCYCLES=3
    fi
    for F in ${LOGS} ; do
	##  Skip if it's unwanted.log, since it's already rotated
	if [ ${F} = ${UNWANTED_LOG} ]; then
	    continue
	fi
	##  Skip if file doesn't exist.
	BASE=`basename ${F}`
	test -f ${BASE} || continue

	##  Compress the file.
	${LOG_COMPRESS} <${BASE} >${BASE}.0${Z} && rm -f ${BASE}
	chmod 0440 ${BASE}.0${Z}

	##  Do rotation.
	EXT=${LOGCYCLES}
	rm -f ${BASE}.${LOGCYCLES}${Z}
	while [ ${EXT} -gt 0 ] ; do
	    NEXT=${EXT}
	    EXT=`expr ${EXT} - 1`
	    test -f ${BASE}.${EXT}${Z} \
		&& rm -f ${BASE}.${NEXT}${Z} \
		&& mv ${BASE}.${EXT}${Z} ${BASE}.${NEXT}${Z}
	done
    done

    ##  Remove lock.
    rm -f ${LOCK}
fi

##  All done.
exit 0
