#!/bin/ksh93

# Usage: see $0 -h

typeset -r DEFAULT_HOSTLIST=/var/arpwatch/hosts
typeset -r VERSION='1.0' FPROG=${.sh.file} PROG=${FPROG##*/} SDIR=${FPROG%/*}

function showUsage {
	[[ -n $1 ]] && X='-?' ||  X='--man'
	getopts -a ${PROG} "${ print ${USAGE} ; }" OPT $X
}

function cleanup {
	[[ -n ${TMP} ]] && rm -f ${TMP}
}

function doMain {
	typeset -A HOSTS
	typeset H C T TMP RES=
	[[ -z ${HOSTLIST} ]] && HOSTLIST="${DEFAULT_HOSTLIST}"
	if [[ ! -r ${HOSTLIST} ]]; then
		print -u2 "${HOSTLIST} not found -> nothing to do - exiting."
		return 0
	fi
	T=${ whence arpfetch ; }
	[[ -z $T ]] && print -u2 'arpfetch not found - exiting.' && return 1
	T=${ whence arpsnmp ; }
	[[ -z $T ]] && print -u2 'arpsnmp not found - exiting.' && return 1

	while read H C T; do
		[[ -z $H || $H == '#' ]] && continue
		HOSTS["$H"]="${C:-public}"
	done < ${HOSTLIST}
	(( ${#HOSTS[@]} )) || \
		{ print -u2 'No hosts to query - exiting.' ; return 0; }

	TMP=${ mktemp /tmp/arpwatch.XXXXXX ; }
	[[ -z ${TMP} ]] && \
		print -u2 "Unable to create a tmp file - exiting." && return 1

	for H in ${!HOSTS[@]} ; do
		RES+=${ arpfetch ${H} ${HOSTS["${H}"]} 2> ${TMP} ; }
		[[ -s ${TMP} ]] || continue
		print -u2 "arpfetch erross for ${H}:"
		sed -e 's/^/	/' ${TMP}
		if [[ -n ${ERR_DIR} ]]; then
			if [[ ! -d ${ERR_DIR} ]]; then
				mkdir -p ${ERR_DIR} || { ERR_DIR= ; continue; }
			fi
			cp ${TMP} ${ERR_DIR}/${H}.err && \
				print -u2 "Errors saved to ${ERR_DIR}/${H}.err"
		fi
	done
	print -n "${RES}" >${TMP}

	# yes, we don't check DATAFILE - leave it to arpsnmp and as a "feature" to
	# pass add. args to arpsnmp (for experienced users ;-)).
	T=${ arpsnmp -d ${DATAFILE} ${TMP} 2>&1 | \
		sed -e '/suppressed DECnet flip flop/d' ; }

	if [[ -n $T ]]; then
		if [[ -n ${EMAIL} ]]; then
			print "$T" | mailx -s "${ hostname; } arpwatch report" ${EMAIL}
		else
			print "$T"
		fi
	fi
}

USAGE="[-?${VERSION}"' ]
[-copyright?Copyright (c) 2016 Jens Elkner. All rights reserved.]
[-license?CDDL 1.0]
[+NAME?'"${PROG}"' - fetch arp tables from cisco machines]
[+DESCRIPTION?This is a script suitable as a cron job, to fetch the arp tables from a cisco machine using \barpfetch\b(1m) and \barpsnmp\b(1m).]
[h:help?Print this help and exit.]
[F:functions?Print a list of all functions available.]
[T:trace]:[functionList?A comma separated list of functions of this script to trace (convinience for troubleshooting).]
[+?]
[E:errors]:[dir?The directory where all errors produced by aarpfetch(1M) gets stored. For each host a file with the name of the corresponding host and the suffix \b.err\b gets created in the given \adir\a if an error occurs. Existing files are silently overwritten. Default: "", i.e. no error messages get saved.]
[c:config]:[file?The file, which contains line-by-line the hostname or IP address of the cisco machine to query optionally followed by the read/only snmp community string to use when arpfetch-ing arp data from it. Both values are separated by one or more whitespaces. Empty lines or lines starting with a \b#\b are ignored. Default: '"${DEFAULT_HOSTLIST}"']
[e:email]:[address?Where to send the results aka arp tables. Default: "", i.e. results get copied to stdout.]
[f:datafile]:[file?Set the ethernet/ip address database filename to be used by \barpsnmp\b(1M). If unset, arpsnmp choose, what to use.]
[+SEE ALSO?\barpfetch -h\b, \barpsnmp\b(1M).]
'
TMP=
ERR_DIR=
HOSTLIST=
EMAIL=
DATAFILE=
X="${ print ${USAGE} ; }"
while getopts "${X}" OPT ; do
	case ${OPT} in
		h) showUsage ; exit 0 ;;
		T)	if [[ ${OPTARG} == 'ALL' ]]; then
				typeset -ft ${ typeset +f ; }
			else
				typeset -ft ${OPTARG//,/ }
			fi
			;;
		F) typeset +f && exit 0 ;;
		E) ERR_DIR="${OPTARG}" ;;
		c) HOSTLIST="${OPTARG}" ;;
		e) EMAIL="${OPTARG}" ;;
		f) DATAFILE="-f ${OPTARG}" ;;
		*) showUsage 1 ; exit 1 ;;
	esac
done

X=$((OPTIND-1))
shift $X && OPTIND=1
unset X

trap cleanup EXIT
doMain "$@"
