#!/bin/sh

# ClonePanel - Manages duplicate accounts on two or more webservers,
# including snapshot backups, monitoring and failover dns.
# Copyright (C)2006 Chris Cheers, Internet Lynx.
# Contact chris[at]clonepanel[dot]com.
# Internet Lynx, PO Box 7117, Mannering Park, NSW 2259, Australia

# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

Version=0.33
# setup_cron -h for built-in documentation

set -u
# Be strict about variable declaration

unset PATH
#avoid use of $PATH - limit script to system commands we choose

PROGRAM_DIR=$(/bin/echo $0 |/bin/sed -e "s/\/[a-zA-Z0-9_]*$//")
# Extract the working directory from command line
# NB - if your system doesn't have echo and sed in these locations
# then this line will need to be changed in all shell scripts

# Standard include files:
. $PROGRAM_DIR/includes

# Built-in documentation:
function showdocs {
	$CAT <<-EODOC
		Handle cron jobs to sync data for all accounts in clonepanel system.

		Inputs may be given as command line parameters or interactively.
		
		Usage:
		./setcron
		Command line options: 
		-h		Print these instructions and exit
		-l		List jobs in existing crontab and exit
		-m minutes	Minutes field increment (default 13)
		-H hours		Hours field increment (default 1)
		-n all|error|none	When to notify by e-mail (default in config)
		-d 			Dummy run (do not write to cron)


EODOC
	exit $DOC_REQUEST
}

function addtime {
# Function to add a time interval: eg. addtime 13:25 1:55 adds 1h55 to
# 13:25 giving 15:20
	h=$($ECHO "$1" |$CUT -d: -f1)
	m=$($ECHO "$1" |$CUT -d: -f2)
	hinc=$($ECHO "$2" |$CUT -d: -f1)
	minc=$($ECHO "$2" |$CUT -d: -f2)
	m=$($EXPR $m + $minc)
	while [ $m -ge 60 ]
	do
		m=$($EXPR $m - 60)
		h=$($EXPR $h + 1)
	done
	h=$($EXPR $h + $hinc)
	while [ $h -ge 24 ]
	do
		h=$($EXPR $h - 24)
	done;
	$ECHO "$h:$m";
	exit 0
}

# Initialise default variables:
minute=0
hour=0
dummy='n'
list='n'
minutes=13
hours=1
notify=$CRONTAB_DEFAULT_NOTIFY

# Start real script

# Check for help request and input variables in the command line options:
while getopts ":hlm:H:n:d" opt
do
	case $opt in
		h)	showdocs
			;;
		m)	minutes=$OPTARG
			;;
		H)	hours=$OPTARG
			;;
		n)	notify=$OPTARG
			;;
		d)	dummy='y'
			;;
		l)	list='y'
			;;
		*)	$ECHO "Unknown option. Use -h for instructions"; exit $E_UNKNOWN_OPT
			;;
	esac
done
shift $(($OPTIND - 1))
OPTIND=1
# reset getopts for next time


if [ $list == "y" ]; then
	$CRONTAB -l |$GREP "$PROGRAM_DIR/"
	exit $LIST_REQUEST
fi

if [ $notify == "none" ]; then
	append=" >/dev/null 2>%1"
elif [ $notify == "error" ]; then
	append=" >/dev/null"
else 
	append=''
fi

if [ -f "$CRONTAB_TMP" ]; then
	$RM $CRONTAB_TMP
	checkerror $? $E_REMOVE_CRONTEMP_FAILED
fi
$TOUCH $CRONTAB_TMP
checkerror $? $E_TOUCH_CRONTEMP_FAILED

# Creating cron jobs, starting with user jobs (sync and rotate)
for user in `$FIND $ACCOUNTS_DIR -maxdepth 1 -mindepth 1 -type d -printf "%f "`
do
	config -u $user
	# User-specific Include files (only after defining $user)

	for job in `$FIND $CRONJOB_DIR -maxdepth 1 -type f -printf "%f "`
	do
		command=''
		freq=''
		. $CRONJOB_DIR/$job
		
		if [ "$command" -a "$freq" ]; then
			interval=$($EXPR 24 / $freq)
# Interval (hours) between runs
			newtime=$(addtime "$hour:$minute" "$hours:$minutes")
			hour=$($ECHO "$newtime" |$CUT -d: -f1)
			minute=$($ECHO "$newtime" |$CUT -d: -f2)
# Start time for this job
			hourlist="$hour"
			nexthour="$hour"
			for (( i=1; i < $freq; i++ ))
			do
				newtime=$(addtime "$nexthour:$minute" "$interval:0")
				nexthour=$($ECHO "$newtime" |$CUT -d: -f1)
				hourlist="$hourlist,$nexthour"
			done ;
			$ECHO "$minute $hourlist * * * $PROGRAM_DIR/$command -u $user $append" >>$CRONTAB_TMP
		fi
	done

done

# Next add host cron jobs (monitor)
allhosts=(`$FIND $HOSTS_DIR -maxdepth 1 -mindepth 1 -type d -printf "%f "`)

if [ ! "$append" ]; then
# Use no less than error-level reporting on monitor jobs
	append=" >/dev/null"
fi

calls=()
minute=0
for host in ${allhosts[*]}
do
	config -H $host
	# Host-specific Include files

	if [ "$MONITOR_IP" == "NONE" ]; then
		continue
# Skip this host if monitoring not requested
	fi
	if [ ${#calls[@]} -le $minute ]; then
		call=''
	else
		call=${calls[$minute]}
	fi
# call is blank initially, subsequently takes already defined value for this minute
	calls[$minute]="$call -H $host"
# append host name to call
	minute=`$EXPR $minute + 1`
	if [ $minute -ge $MONITOR_FREQUENCY ]; then
		minute=0
# increment minute only as far as monitoring frequency - then go back to zero
	fi
done
# After above loop we have defined an array of calls to hostnames

# Next loop writes the cron jobs
for (( minute = 0 ; minute < ${#calls[@]} ; minute++ ))
do
	minutelist=$minute
	for (( i = $minute+$MONITOR_FREQUENCY ; i < 60 ; i+=$MONITOR_FREQUENCY ))
	do
		minutelist="$minutelist,$i"
	done
	$ECHO "$minutelist * * * * $PROGRAM_DIR/monitor ${calls[$minute]} $append" >>$CRONTAB_TMP
done

# Finally add error_manager (handles status checking and failover)
$ECHO "*/$ERROR_MANAGER_UPDATE_FREQ * * * * $PROGRAM_DIR/$ERROR_MANAGER_SCRIPT" >>$CRONTAB_TMP

if [ $dummy == "y" ]; then
	cecho -c $warning "Dummy run requested. If not the following jobs would be written to crontab:"
	$CAT $CRONTAB_TMP
	exit $LIST_REQUEST
fi

$CRONTAB -l |$GREP -v "$PROGRAM_DIR/" >>$CRONTAB_TMP
# Fetch any cron jobs NOT controlled by this system and add these to new crontab

$CRONTAB $CRONTAB_TMP
checkerror $? $E_WRITE_CRONTAB_FAILED

cecho -c $ok "setup_cron complete - new cron jobs written."
