#!/bin/sh

# Counts number _nd of top-level subdirs in two MON_DIRs and performs
# actions (if not empty) in case of:
# a) _nd reached level CRIT_NO, previous level was not CRIT_NO;
# b) _nd reached level WARN_NO, previous level was normal;
# c) _nd returned to normal level, previous level was not normal.


die() {
	echo $@
	exit 1
}

# These variables should be altered in config file.
# Absolute path to directories to monitor
MON1_DIR="/tmp/mon1"
MON2_DIR="/tmp/mon2"
# Number of TD subdirs: warning level.
WARN_NO=3
# Number of TD subdirs: critical level.
CRIT_NO=4
# Action to execute in case a). Any shell command (s), pipes allowed, but no local vars.
CRIT_ACTION="ls -l | tee hoho | wc -l"

# "Semi-local" variables (for use in config also).
_me="$(basename $0)"
_date="$(date '+%Y-%m-%d')"

# These variables may be altered in config file.
# Absolute paths to trigger files
TRIGGER1_FILE="/tmp/ndmon.trigger1"
TRIGGER2_FILE="/tmp/ndmon.trigger2"
# Messages.
# Note: ${_me} and ${_date} are valid at the moment and can be used in config.
# Note: if WARN_NO, CRIT_NO and CRIT_ACTION are to be set in config, they should set be above messages.
TO_CRIT_FROM_OTHER_MSG="${_me}-${_date}: critical number ${CRIT_NO} of TL subdirs, executing \"${CRIT_ACTION}\"."
TO_WARN_FROM_NORM_MSG="${_me}-${_date}: warning: number of TL subdirs reached ${WARN_NO}."
TO_NORM_MSG="${_me}-${_date}: number of TL subdirs returned to normal (less then ${WARN_NO})"

# Source config file
_config_file="$(dirname $0)/../etc/${_me}.conf"
[ -r "${_config_file}" ] || _config_file="/opt/etc/${_me}.conf"
[ -r "${_config_file}" ] || _config_file="/usr/local/etc/${_me}.conf"
[ -r "${_config_file}" ] || _config_file="$(dirname $0)/${_me}.conf"
[ -r "${_config_file}" ] && . "${_config_file}" \
#	|| echo "${_me}-${_date}: warning: unable to find configuration file ${_config_file}."
# If you need a lot of warnings, just uncomment the line above.

# These variables are for internal use only
_norm_id="NORM"
_warn_id="WARN"
_crit_id="CRIT"

# If there is no saved state, assume it was NORM.
[ -f "${TRIGGER1_FILE}" ] || echo ${_norm_id} > "${TRIGGER1_FILE}"
[ -f "${TRIGGER2_FILE}" ] || echo ${_norm_id} > "${TRIGGER2_FILE}"
[ -r "${TRIGGER1_FILE}" -a -r "${TRIGGER2_FILE}" ] || \
	die "${_me}-${_date}: unable to create trigger file(s) \"${TRIGGER1_FILE}\" and/or \"${TRIGGER2_FILE}\"."

# This function should only be called from check_dir_for_trigger()
#	arg no. 1: MON_DIR, we assume it exists.
determine_state() {
	_mon_dir="$1"
    _nd=$(find "${_mon_dir}" -mindepth 1 -maxdepth 1 -type d | wc -l)
    [ ${_nd} -lt ${WARN_NO} ] && echo ${_norm_id} && exit
    [ ${_nd} -lt ${CRIT_NO} ] && echo ${_warn_id} && exit
    echo ${_crit_id}
}

# Actual work.
#	arg no. 1: MON_DIR, will be checked for existance.
#	arg no. 2: TRIGGER_FILE, will be checked for rw access.
check_dir_for_trigger()
{
	_mon_dir="$1"
	_trigger_file="$2"
	_caller="check_dir_for_trigger()"
	[ -d "${_mon_dir}" ] || \
		die "${_me}-${_date}: ${_caller}: directory \"${_mon_dir}\" does not exist, check config \"${_config_file}\"."
	[ -r "${_trigger_file}" ] || \
		die "${_me}-${_date}: ${_caller}: trigger \"${_trigger_file}\" is unreadable, check config \"${_config_file}\"."
	[ -w "${_trigger_file}" ] || \
		die "${_me}-${_date}: ${_caller}: trigger \"${_trigger_file}\" is unwritable, check config \"${_config_file}\"."
	_old_state="$(cat ${_trigger_file})"
	_new_state="$(determine_state ${_mon_dir})"
	if [ ${_new_state} = ${_crit_id} -a ${_old_state} != ${_crit_id} ]; then
		# Case a)
		[ -n "${TO_CRIT_FROM_OTHER_MSG}" ] && echo "${TO_CRIT_FROM_OTHER_MSG}"
		if [ -n "${CRIT_ACTION}" ]; then
			eval ${CRIT_ACTION}
		fi
		echo ${_new_state} > "${_trigger_file}"
		return 1
	fi
	if [ ${_new_state} = ${_warn_id} -a ${_old_state} = ${_norm_id} ]; then
		# Case b)
		[ -n "${TO_WARN_FROM_NORM_MSG}" ] && echo ${TO_WARN_FROM_NORM_MSG}
	elif [ ${_new_state} = ${_norm_id} -a ${_old_state} != ${_norm_id} ]; then
		# Case c)
		[ -n "${TO_NORM_MSG}" ] && echo ${TO_NORM_MSG}
	fi
	echo ${_new_state} > "${_trigger_file}"
	return 0
}

# main()
check_dir_for_trigger "${MON1_DIR}" "${TRIGGER1_FILE}"
_retval1=$?
check_dir_for_trigger "${MON2_DIR}" "${TRIGGER2_FILE}"
_retval2=$?
[ ${_retval1} -eq 0 -a ${_retval2} -eq 0 ] && exit 0 || exit 1
