#!/bin/sh
# @(#) $Id: actsyncd.sh,v 1.8 1996/05/27 11:46:07 news Exp $
# @(#) Under RCS control in /usr/local/news/src/inn/local/RCS/actsyncd.sh,v
#
# actsyncd - actsync daemon
#
# usage:
#	actsyncd [-x] config_file
#
#	-r		reload instead of xexec
#	config_file	name of file used to determine how to run actsync

# By: Landon Curt Noll  	chongo@toad.com		(chongo was here /\../\)
#
# Copyright (c) Landon Curt Noll, 1993.
# All rights reserved.
#
# Permission to use and modify is hereby granted so long as this 
# notice remains.  Use at your own risk.  No warranty is implied.

# preset vars
#
# =()<. @<_PATH_SHELLVARS>@>()=
. /usr/local/news/lib/innshellvars
# Our lock file
LOCK=${LOCKS}/LOCK.actsyncd
# where actsync is located
ACTSYNC=${NEWSHOME}/lbin/actsync
# where secs is located
SECS=${NEWSHOME}/lbin/secs
# exit value of actsync if unable to get an active file
NOSYNC=127
# where ctlinnd lives
CTLINND="${NEWSBIN}/ctlinnd"
# by default we xexec instead of reloading
XEXEC=true
export XEXEC

# parse args
#
if [ $# -gt 1 ]; then
    if [ X"-r" = X"$1" ]; then
	XEXEC=
	shift
    fi
fi
if [ $# -ne 1 ]; then
    echo "usage: $0 config_file" 1>&2
    exit 1
fi
cfg="$1"
if [ ! -s "$cfg" ]; then
    echo "$0: config_file not found or empty: $ign" 1>&2
    exit 2
fi

# parse config_file
#
host="`sed -n -e 's/#.*//' -e 's/^host=[ 	]*//p' $cfg | tail -1`"
if [ -z "$host" ]; then
    echo "$0: no host specified in $cfg" 1>&2
    exit 3
fi
flags="`sed -n -e 's/#.*//' -e 's/^flags=[ 	]*//p' $cfg | tail -1`"
if [ -z "$flags" ]; then
    echo "$0: no flags specified in $cfg" 1>&2
    exit 4
fi
ign="`sed -n -e 's/#.*//' -e 's/^ignore_file=[ 	]*//p' $cfg | tail -1`"
if [ -z "$ign" ]; then
    echo "$0: no ignore file specified in $cfg" 1>&2
    exit 5
fi
if [ ! -s "$ign" ]; then
    echo "$0: ignore_file not found or empty: $ign" 1>&2
    exit 6
fi

# force -o a1 mode (overrides any -o argument in the command line)
#
flags="$flags -o a1"

# Lock out others
#
trap 'rm -f ${LOCK}; exit 1' 0 1 2 3 15
shlock -p $$ -f ${LOCK} || {
    echo "$0: Locked by `cat ${LOCK}`" 1>&2
    exit 7
}

# setup
#
activenew="${NEWSLIB}/active.new.$$"
out="${TMPDIR}/.sync.$$"
trap "rm -f $activenew $out ${LOCK}; exit" 0 1 2 3 15
rm -f "$out"
touch "$out"
chmod 0600 "$out"

# try to sync 
# 
# Try to sync off of the host.  If unable to connect/sync then retry
# up to 9 more times waiting 6 minutes between each try.
#
echo "=-= `date` for $host"
for loop in 1 2 3 4 5 6 7 8 9 10; do

    # pause the server
    #
    echo "=-= `date` for $host pause innd" >>$out 2>&1
    ${CTLINND} pause "actsyncd" >>$out
    if [ $? -ne 0 ]; then
	echo "FATAL: `date` for $host cannot pause innd" >>$out
	sed -e 's/^/    /' < "$out"
	exit 8
    fi

    # form the new active file
    #
    echo "rm -f $activenew" >>$out
    rm -f "$activenew" >>$out 2>&1
    echo "touch $activenew" >>$out
    touch "$activenew" >>$out 2>&1
    echo "chmod 0600 $activenew" >>$out
    chmod 0600 "$activenew" >>$out 2>&1
    echo "$ACTSYNC -i $ign $flags $host" >>$out
    eval "$ACTSYNC -i $ign $flags $host >$activenew 2>>$out"
    status=$?
    if [ "$status" -ne "$NOSYNC" ]; then

	# detect bad status
	#
	if [ "$status" -ne 0 ]; then
	    echo "FATAL: `date` for $host exit $status" >>$out
	    ${CTLINND} go "actsyncd" >>$out
	    sed -e 's/^/    /' < "$out"
	    exit "$status"
	fi

	# detect empty output
	#
	if [ ! -s "$activenew" ]; then
	    echo "FATAL: `date` for $host empty or missing $activenew" >>$out
	    ${CTLINND} go "actsyncd" >>$out
	    sed -e 's/^/    /' < "$out"
	    exit 9
	fi

	# form active.times lines for new newsgroups
	#
	NOW=`${SECS}`
	if [ -z "${NOW}" ]; then
	    echo "FATAL: `date` for $host secs output is empty" >>$out
	    ${CTLINND} go "actsyncd" >>$out
	    sed -e 's/^/    /' < "$out"
	    exit 10
	fi
	echo "=-= `date` for $host, forming active.times" >>$out
	eval "$ACTSYNC -i $ign $flags -o c -v 0 -q 12 ${ACTIVE} $activenew 2>>$out" | \
	    grep '^ctlinnd newgroup ' | \
	    awk '{print $3, NOW, "actsyncd";}' NOW=$NOW - >> ${ACTIVETIMES}

	# move the active file into place
	#
	wc "${ACTIVE}.old" "${ACTIVE}" "$activenew" | sed -e 's/^  *//' >>$out
	echo "rm -f ${ACTIVE}.old" >>$out
	rm -f "${ACTIVE}.old" >>$out 2>&1
	echo "ln ${ACTIVE} ${ACTIVE}.old" >>$out
	ln "${ACTIVE}" "${ACTIVE}.old" >>$out 2>&1
	echo "mv -f $activenew ${ACTIVE}" >>$out
	mv -f "$activenew" "${ACTIVE}" >>$out 2>&1

	# reload the new active or reexec the server if needed
	#
	if [ -z "$XEXEC" ]; then
	    # reload the modified active file
	    #
	    echo "=-= `date` for $host, reload active" >>$out
	    ${CTLINND} reload active actsyncd >>$out 2>&1
	    if [ $? -ne 0 ]; then
		echo "FATAL: `date` for $host cannot reload active" >>$out
		sed -e 's/^/    /' < "$out"
		exit 11
	    fi

	    # active file has been updated successfully, resume server
	    #
	    echo "=-= `date` for $host, go innd" >>$out
	    ${CTLINND} go "actsyncd" >>$out
	    if [ $? -ne 0 ]; then
		echo "FATAL: `date` for $host cannot go innd" >>$out
		sed -e 's/^/    /' < "$out"
		exit 12
	    fi
	else
	    # just re-exec the server and let the new server read new active
	    #
	    echo "=-= `date` for $host, xexec" >>$out
	    ${CTLINND} xexec '' >>$out 2>&1
	    if [ $? -ne 0 ]; then
		echo "FATAL: `date` for $host cannot xexec, server dead" >>$out
		sed -e 's/^/    /' < "$out"
		exit 13
	    fi
	    # see if the server has reloaded
	    #
	    sleep 30
	    ${CTLINND} mode >/dev/null 2>&1
	    if [ $? -ne 0 ]; then
		echo "FATAL: `date` for $host did not resume after xexec" >>$out
		sed -e 's/^/    /' < "$out"
		exit 14
	    fi
	fi

	# normal exit - all done
	#
	sed -e 's/^/    /' < "$out"
	exit "$status"
    fi

    # failed to form the active file, resume server
    #
    echo "=-= `date` for $host failed to connect/sync, retrying" >>$out
    ${CTLINND} go "actsyncd" >>$out
    if [ $? -ne 0 ]; then
	echo "FATAL: `date` for $host cannot go innd" >>$out
	sed -e 's/^/    /' < "$out"
	exit 15
    fi

    # wait 6 minutes
    #
    sleep 360
done

# give up
#
echo "FATAL: `date` for $host failed to connect/sync 10 times" >>$out
sed -e 's/^/    /' < "$tmp"
exit "$status"
