#! /bin/sh

#
#	Once-a whatever do some command
#
#		Designed to be run from cron, periodically, and @boot
#		to arrange that the command is executed once, but not
#		more often than that, each period.  Making sure it is
#		executed at least once is a job for correctly setting
#		up crontab, preventing more than once is what this script
#		handles.
#
#		Succeed or fail, the command is run just once per period.
#
#	Caution: system crashes just when this script is running could
#		allow the command to run twice (once just before, and again
#		immediately after) the crash (if the record file is not
#		correctly updated) or never for the period (if the record
#		file does get updated, but the command does not get started.)
#
#		This kind of thing should be very rare...
#

DB=/var/db/once-a
EXCODE=99

usage()
{
	echo >&2 "Usage: $0 period cmd [args]"
	echo >&2 "     preiod: day | week | fortnight | month | year"
	echo >&2 "              or 'test' just to verify setup"
	exit ${EXCODE}
}

case "$#" in
[01])	usage;;
esac

case "${LOGNAME}" in
'')	LOGNAME=${USER:-$( id -un $)};;
esac

DB="${DB}/${LOGNAME}"

test -d "${DB}" || {
	echo >&2 "Once-a database directory does not exist: ${DB}"
	exit ${EXCODE}
}

echo "Testing" > "${DB}/Test" || {
	echo >&2 "Once-a database directory ($DB) not writeable"
	exit ${EXCODE}
}
rm -f "${DB}/Test"

period=$1; shift
cmd=$1; shift

case "${period}" in
[Tt]est)	exit 0;;
[Dd]ay)		fmt="%Y %m %d";;
[Ww]eek)	fmt="%Y %U";;
[Ff]ortnight)	fmt="%Y %U";;	# Don't change this one!
[Mm]onth)	fmt="%Y %m";;
[Yy]ear)	fmt="%Y";;
*)		usage;;
esac

BASE=$(basename "${cmd}")

test -s "${DB}/${BASE}" && {
	LAST=$(cat "${DB}/${BASE}")
	NOW=$(date +"${fmt}")

	case "${period}" in
	[Ff]ortnight)
		set -$- ${NOW} "$@";
		Y=$1; W=$2; shift 2
		set -$- ${LAST} "$@";
		LY=$1; LW=$2; shift 2

		test ${LY} -lt ${Y} && W=$(( $W + 52 ))
		W=$(( $W / 2 ))
		LW=$(( $LW / 2))

		test $W -eq $LW && exit 0
		;;

	*)	test "${LAST}" = "${NOW}" && exit 0;;
	esac
}

date +"${fmt}" > "${DB}/${BASE}"
exec "${cmd}" "$@"
