#! /bin/bash
#########################################################################
#									#
#	dosab is automatically generated,				#
#		please do not modify!					#
#									#
#########################################################################

#########################################################################
#									#
# Script ID: dosab							#
# Author: Copyright (C) 2018-2019, 2021, 2023  Mark Grant		#
#									#
# Released under the GPLv3 only.					#
# SPDX-License-Identifier: GPL-3.0-only					#
#									#
# Purpose:								#
# To determine if a server is contactable and conditional on that,	#
# execute stored commands.						#
#									#
# Syntax:	dosab [ -h --help || -V --version ]			#
#									#
# Exit codes used:-							#
# Bash standard Exit Codes:	0 - success				#
#				1 - general failure			#
# User-defined exit code range is 64 - 113				#
#	C/C++ Semi-standard exit codes from sysexits.h range is 64 - 78	#
#		EX_USAGE	64	command line usage error	#
#		EX_DATAERR	65	data format error		#
#		EX_NOINPUT	66	cannot open input		#
#		EX_NOUSER	67	addressee unknown		#
#		EX_NOHOST	68	host name unknown		#
#		EX_UNAVAILABLE	69	service unavailable		#
#		EX_SOFTWARE	70	internal software error		#
#		EX_OSERR	71	system error (e.g., can't fork)	#
#		EX_OSFILE	72	critical OS file missing	#
#		EX_CANTCREAT	73	can't create (user) output file	#
#		EX_IOERR	74	input/output error		#
#		EX_TEMPFAIL	75	temp failure; user is invited	#
#					to retry			#
#		EX_PROTOCOL	76	remote error in protocol	#
#		EX_NOPERM	77	permission denied		#
#		EX_CONFIG	78	configuration error		#
#	User-defined (here) exit codes range 79 - 113:			#
#		None							#
#									#
# Further Info:								#
# This script reads the file server.list and sequentially determines if	#
# the named server exists. If server 'srv' is contactable commands	#
# within the file srv.available are read and executed, if it is not	#
# contactable then the file srv.unavailable is processed in the same	#
# manner.								#
#									#
#########################################################################

#########################################################################
#									#
# Changelog								#
#									#
# Date		Author	Version	Description				#
#									#
# 28/09/2018	MG	1.0.1	First release.				#
# 26/04/2019	MG	1.1.1	Standardise output function.		#
#				Remove script_exit_code variable.	#
#				Improve trap handling.			#
#				Refactor into functions.		#
#				Tidy up local and readonly variables.	#
#				Use more meaningful exit codes.		#
#				Replace #! env bash to absolute path	#
#				from configure.				#
# 05/05/2019	MG	1.1.2	Correct getopt CL for proper quoting.	#
#				Use eval to process variables which may	#
#				contain quotes.				#
# 11/10/2019	MG	1.1.3	Move std_cmd_err_handler() before it is	#
#				used.					#
#				Move script_exit() before it is used.	#
# 26/11/2021	MG	1.1.4	Tighten SPDX tag.			#
# 16/10/2023	MG	1.2.0	Drop .sh extension from scripts in	#
#				$PATH.					#
#									#
#########################################################################


##################
# Init variables #
##################

readonly outputprefix="$(basename $0):"
readonly version=1.2.0				# Script version
readonly etclocation=/etc/dosab		# Path to etc directory
readonly packageversion=1.2.2		# Package version


#############
# Functions #
#############

# -h --help output.
# No parameters
# No return value
usage()
{
cat << EOF
Usage is $0 [options]
	-h or --help displays usage information
	OR
	-V or --version displays version information
EOF
}

# Standard function to tidy up and return exit code.
# Parameters - 	$1 is the exit code.
# No return value.
script_exit()
{
	exit $1
}

# Standard function to test command error and exit if non-zero.
# Parameters - $1 is $?
# No return value.
std_cmd_err_handler()
{
	if (( $1 )); then
		script_exit $1
	fi
}

# Standard function to emit messages depending on various parameters.
# Parameters -	$1 What:-	The message to emit.
#		$2 Where:-	stdout == 0
#				stderr != 0
#		$3 Syslog:-	$3 == 0, No.
#				$3 != 0, Yes.
# No return value.
output()
{
	if (( !$2 )); then
		printf "%s %s\n" $outputprefix "$1"
	else
		printf "%s %s\n" $outputprefix "$1" 1>&2
	fi
	if (( $3 )); then
		logger "$outputprefix $1"
		std_cmd_err_handler $?
	fi
}

# Standard trap exit function.
# No parameters.
# No return value.
trap_exit()
{
	local -i exit_code=$?
	local msg

	msg="Script terminating with exit code $exit_code due to trap received."
	output "$msg" 1 0
	script_exit $exit_code
}

# Setup trap.
trap trap_exit SIGHUP SIGINT SIGQUIT SIGTERM

# Process command line arguments with GNU getopt.
# Parameters -	$1 is the command line.
# No return value.
proc_CL()
{
	local GETOPTTEMP
	local tmpGETOPTTEMP

	tmpGETOPTTEMP="getopt -o hV --long help,version"
	GETOPTTEMP=$($tmpGETOPTTEMP -n "$0" -- "$@")
	std_cmd_err_handler $?

	eval set -- "$GETOPTTEMP"
	std_cmd_err_handler $?

	while true; do
		case "$1" in
		-h|--help)
			usage
			shift
			script_exit 0
			;;
		-V|--version)
			printf "%s Script version %s\n" $0 $version
			printf "%s Package version %s\n" $0 $packageversion
			shift
			script_exit 0
			;;
		--)	shift
			break
			;;
		*)	output "Internal error." 1 0
			script_exit 64
			;;
		esac
	done

	# Script does not accept other arguments.
	if (( $# > 0 )); then
		output "Invalid argument." 1 0
		script_exit 64
	fi
}

# Run the command file.
# Parameters - $1 is the command file name.
# No return value.
run_cmd_file()
{
	local command

	if [[ ! -f $1 ]]; then
		output "$1 is not available." 0 0
		return
	fi

	exec 4<"$1"
	std_cmd_err_handler $?

	output "Processing $1" 0 0

	while read -u4 -r command; do
		if [[ $command = "#"* || $command = "" ]]; then
			continue
		fi
		eval "$command"
	done
	exec 4<&-
}

# Process the server of interest.
# Parameters - $1 is the server name.
# No return value.
proc_server()
{
	# Is server contactable
	eval "ping -c 3 $1 > /dev/null 2>&1"
	if (( ! $? )); then
		output "$1 is available." 0 0
		eval "run_cmd_file $etclocation/$1.available"
	else
		output "$1 is not available." 0 0
		eval "run_cmd_file $etclocation/$1.unavailable"
	fi

}

# Read and process servers of interest from server.list
# No parameters.
# No return value.
proc_server_list()
{
	local srv

	if [ ! -f "$etclocation/server.list" ]; then
		output "$etclocation/server.list does not exist." 1 1
		script_exit 66
	fi

	exec 3<$etclocation/server.list
	std_cmd_err_handler $?

	while read -u3 -r srv; do
		# Ignore comment lines and blank lines.
		if [[ $srv = "#"* || $srv = "" ]]; then
			continue
		fi
		proc_server "$srv"
	done
	exec 3<&-
}


########
# Main #
########

proc_CL "$@"

proc_server_list

output "script completed." 0 1
script_exit 0

