#!/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
# cronjob -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
		Add / remove cron jobs from list to include in crontab for an account in clonepanel system.
		Inputs may be given as command line parameters or interactively.
		Usage:
		1. List cron jobs already defined:
		./cronjob -u myaccount
		2. Add / delete a job (enter data at prompts):
		./cronjob add|del
		3. Add / delete a job (data on command line):
		./cronjob -c mycommand -t timesperday -u myaccount [-f] add|del
		Command line options: 
		-h		Print these instructions and exit
		-c mycommand	Script to run, eg. sync, get_dns -s, rollover
		-t timesperday	Number of times per day to run this script
		-u myaccount	CPanel username of the account
		-f		Force overwrite add or multiple delete
		
EODOC
	exit $DOC_REQUEST
}


# Get job filename(s) based on user input command
function get_cronjob_file {
	n_matches=0
	matches=`$FIND $CRONJOB_DIR -maxdepth 1 -type f`
	if [ ! "$matches" ]; then
		return
	fi
# Start with all job records for this username
	if [ ! "$commandline" ]; then
		n_matches=`$ECHO $matches |$WC -w`
		return
	fi
# Without a given job name, just return full list
	jobs=$matches
	matches=''
	n_matches=0
# If a command is given then match this also - reset match list
	for job in $jobs
	do
		matched=`$GREP -l "command='$commandline'" $job`
		if [ "$matched" ]; then
			matches="$matched $matches"
			n_matches=$($EXPR $n_matches + 1 )
		fi
	done
# Anything now matches command given
}

function create_job_file {
	cecho -c $info "Creating $CRONJOB_DIR/$jobfile"
	$CAT >$CRONJOB_DIR/$jobfile << ENDDATA
command='$commandline'
frequency=$timesperday
ENDDATA
}

# Initialise own input variables:
command=list
user=''
commandline=''
timesperday=0
force='n'

# Start real script

# Check for help request and input variables in the command line options:
while getopts ":hu:c:t:f:" opt
do
	case $opt in
		h)	showdocs
			;;
		u)	user=$OPTARG
			;;
		c)	commandline=$OPTARG
			;;
		t)	timesperday=$OPTARG
			;;
		f)	force='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 [ $# -gt 0 ]; then
        command=$1
fi

if [ ! $user ]; then
	cecho -n -c $prompt "Enter CPanel account username: "
	read user
	if [ ! $user ]; then
		cecho -c $error "Account username must be specified"
		exit $E_BLANK_INPUTS
	fi
fi

config -u $user
# User-specific config options

if [ ! -d $USER_DIR ]; then
	cecho -c $error "Error: No account with that username."
	exit $E_NO_ACCOUNT
fi

if [ ! -d "$CRONJOB_DIR" ] ; then
	cecho -c $info "Creating directory $CRONJOB_DIR"
	create_dir $CRONJOB_DIR
fi

case $command in
	list)
		cecho -c $ok "Cron jobs listed for $user:"

		get_cronjob_file
		if [ $n_matches -gt 0 ]; then
			for jobfilename in $matches
			do
				cecho -c $info "Cron job $jobfilename:"
				$CAT $jobfilename
			done
			cecho -c $ok "$n_matches job(s) listed"
		else
			cecho -c $warning "No matching jobs"
		fi
		;;
	add)
		if [ ! "$commandline" ]; then
			cecho -n -c $prompt "Enter cron script name, including options if any: "
			read commandline
			if [ ! "$commandline" ]; then
				cecho -c $error "Script name must be specified"
				exit $E_BLANK_INPUTS
			fi
		fi
		if [ $timesperday -eq 0 ]; then
			cecho -n -c $prompt "Enter times per day to run [1]: "
			read timesperday
			if [ ! $timesperday ]; then
				timesperday=1
			fi
		fi

		get_cronjob_file
		case $n_matches in
			1)
				if [ $force != 'y' ]; then
					cecho -n -c $prompt "One matching cron job exists - replace it (y/n)?: "
					read force
				fi
				;;
			0)
				;;
			*)
				if [ $force != 'y' ]; then
					cecho -n -c $prompt "$n_matches matching cron jobs exist - delete all (y/n)?: "
					read force
				fi
				;;
		esac
		if [ $n_matches -gt 0 ]; then
			if [ $force == 'y' ]; then
				for match in $matches
				do
					$RM $match
					checkerror $? $E_FAILED_DELETE_JOB
				done
			else 
				cecho -c $error "Aborted"
				exit $USER_ABORT
			fi
		fi
		
		highest=`$FIND $CRONJOB_DIR -maxdepth 1 -type f -printf "%f\n" | $SORT -n | $TAIL -n 1`
# highest numeric existing entry
		if [ ! "$highest" ]; then
			highest=0
		fi

		jobfile=$($EXPR $highest + 1 )
#			We could just use the command line but this allows
#			for multiple entries (eg different options, same script)
		create_job_file
		cecho -c $ok "Add cron job done!"
		;;
	del)
		if [ ! "$commandline" ]; then
			cecho -n -c $prompt "Enter cron script name, including options if any: "
			read commandline
			if [ ! "$commandline" ]; then
				cecho -c $error "Script name must be specified"
				exit $E_BLANK_INPUTS
			fi
		fi

		get_cronjob_file
		case $n_matches in
			0)
				cecho -c $error "No matching cron jobs - nothing to delete"
				exit $E_JOB_NOT_FOUND
				;;												
			1)
				$RM $matches
				checkerror $? $E_FAILED_DELETE_JOB
				cecho -c $ok "1 matching job deleted"
				;;
			*)
				if [ $force != 'y' ]; then
					cecho -n -c $prompt "$n_matches cron jobs match your input - delete all (y/n)?: "
					read force
				fi
				if [ $force == 'y' ]; then
					for match in $matches
					do
						$RM $match
						checkerror $? $E_FAILED_DELETE_JOB
					done
					cecho -c $ok "$n_matches job(s) deleted"
				else 
					cecho -c $error "Aborted"
					exit $USER_ABORT
				fi
				;;
		esac
		cecho -c $ok "Delete cron job done!"
		;;	
	*)	cecho -c $error "Unknown option. Use -h for instructions";
		 exit $E_UNKNOWN_OPT
		;;
esac



