#!/bin/ksh -u
# Maintain a history of the user's crontab file - since they won't bother.
# The point is: if it gets trashed, what was the last version.
# This works by examining the current crontab (started from cron) and recording
# a new version if it is different to the last one.
#
# This should NOT be run more than once a day, files are given names YYYY/MMDD
# and so it won't cope.
#
# SCCS: @(#)CrontabHistory	1.11 12/23/09 12:45:33
#
# Copyright (c) Alain Williams <addw@phcomp.co.uk>, 2006, 2007.
# This software is released under the GPLv3, see:
#	http://www.gnu.org/licenses/gpl-3.0.html


PROGNAME=${0##*/}

# Where are files, etc.
# Well, don't do it -- everything in the $HOME

Dir=CronHistory
Quiet=n

# Print a usage message & exit the program.
# If an argument is given print that as an error and exit 1
function Usage {
	(( $# > 0 )) && echo "$PROGNAME: $*" >&2
	cat <<-!
	Maintain a history of a user's crontab file.
	Usage: $0 [-opts]
	-d dir	Directory in which to save cron files, default: $Dir
	-q	Quiet, print nothing unless there is an error
	-x	eXplain
	--help	help message
	 Version: 1.11 12/23/09, latest at: http://www.phcomp.co.uk/Packages/CrontabHistory.html
	!
	exit $#
}

# Complain & die
Winge(){
	echo "$@" >&2
	exit 2
}

# Print a note unless quiet mode
Note(){
	[[ $Quiet = y ]] && return
	echo "$@"
}

# Parse options, recognise --help
while	[[ $# -ge $OPTIND ]] && eval A1=\$$OPTIND || A1=
	if [[ $A1 = --help ]]
	then	opt=x	# --help is -x
	else	getopts :d:qx opt
	fi
do	case "$opt" in
	d)	Dir="$OPTARG"	;;
	q)	Quiet=y		;;
	x)	Usage ;;
	:)	Usage "Missing argument to option '$OPTARG'" ;;
	\?)	Usage "Unknown option '$OPTARG'" ;;
	*)	Usage "Internal program error, unrecognised argument '$opt'" ;;
	esac
done
shift $((OPTIND - 1))

# Somewhere to keep it all
[[ -d $Dir ]] || mkdir --mode=775 $Dir || Winge "Cannot create directory $PWD/$Dir"

cd $Dir || Winge "Cannot cd to '$PWD/$Dir'"

eval $( date '+Year=%Y Day=%m%d' )

# Tidy up:
trap "rm -f .Latest .CronErr" EXIT

# What do we have now ?
crontab -l > .Latest 2>.CronErr || Winge "Error reading crontab: $(<.CronErr)"

# The file Latest will be a symlink to the lastest crontab, if it doesn't exist, create it
# and we are done:
if [[ ! -L Latest ]]
then	[[ -d $Year ]] || mkdir --mode=775 $Year || Winge "Cannot create directory $PWD/$Year"
	mv .Latest $Year/$Day || Winge "Aborting"
	ln -s $Year/$Day Latest || Winge "Aborting"
	echo "I don't appear to have been run before, initialising"
else	# Is it the same as what we just obtained ?
	if cmp -s Latest .Latest
	then	Note "Crontab appears unchanged since: $( ls -l Latest | sed -e 's/^[^>]*> //' )"
	else	# Need to keep todays
		Note "Crontab changed, last changed: $( ls -l Latest | sed -e 's/^[^>]*> //' )"
		[[ -d $Year ]] || mkdir --mode=775 $Year || Winge "Cannot create directory $PWD/$Year"
		mv .Latest $Year/$Day || Winge "Aborting"
		ln -sf $Year/$Day Latest || Winge "Aborting"
	fi
fi

# end
