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

#########################################################################
#									#
# Script ID: attbckshare						#
# Author: Copyright (C) 2012-2019, 2021  Mark Grant			#
#									#
# Released under the GPLv3 only.					#
# SPDX-License-Identifier: GPL-3.0-only					#
#									#
# Purpose:								#
# To mount a CIFS or NFS backup share. E.g.				#
# 	\\Ambrosia\charybdisbck or hermes:/srv/backups/charybdis	#
# 	on								#
# 	/mnt/charybdisbck						#
#									#
# Syntax:	attbckshare [ -a --adhoc || -h --help || -v --verbose	#
#				|| -V --version || -w --weekly ]	#
#									#
# 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 mounts a CIFS or NFS share as a target for the backup	#
# scripts.								#
#									#
# In order to make the package portable all the necessary parameters	#
# are stored in a $PREFIX/etc/lixbackups/backups.conf file.		#
# For further information please consult the backups.conf man page.	#
#									#
#########################################################################

#########################################################################
#									#
# Changelog								#
#									#
# Date		Author	Version	Description				#
#									#
# 09/04/2010	MG	1.0.1	Created for Linux.			#
# 26/08/2010	MG	1.0.2	Major revision completed supporting	#
#				FreeBSD as well as Linux. Also put all	#
#				relevant parameters in variables at	#
#				beginning of script to enhance		#
#				portability. (e.g. System, backup user	#
#				etc.).					#
# 18/11/2010	MG	1.0.3	Changed to emit help and version on	#
#				input of correct flag as argument. Also	#
#				stored version in string in Init section#
# 28/11/2010	MG	1.0.4	Changed script to read parameters from	#
#				etclocation/backups.conf and, when	#
#				necessary (FreeBSD), the ~/.nsmbrc file.#
# 10/01/2012	MG	1.0.5	Removed the .sh extension from the	#
#				command name.				#
# 05/11/2012	MG	1.0.6	Reverted to the .sh file extension.	#
# 26/02/2013	MG	1.0.7	Changed command line option processing	#
#				to use getopts.				#
# 01/04/2013	MG	1.0.8	Moved config files to new backups	#
#				directory under sysconfdir. Added	#
#				exclude files for system, weekly, daily	#
#				and data.				#
# 22/08/2013	MG	1.0.9	Debian best practice documentation	#
#				requires that programs placed in the	#
#				PATH should not have extensions as the	#
#				programs may be rewritten in a		#
#				different language. This would then	#
#				require a name change, or, if left	#
#				as-is would cause confusion. So name	#
#				changed to remove .sh extension.	#
# 06/01/2014	MG	1.1.1	Changed stdout & stderr message output	#
#				to use a function directing to one or	#
#				other based on a status. Changed	#
#				version option to -V. Added verbose	#
#				option -v.				#
# 16/11/2014	MG	1.1.2	Switched from getopts to GNU getopt to	#
#				allow long options.			#
# 17/11/2014	MG	1.1.3	Change FreeBSD specifics to *BSD and	#
#				change Linux to be the default.		#
# 22/11/2014	MG	1.1.4	Add overall package version to -V.	#
# 02/02/2015	MG	1.1.5	Remove BSD support.			#
# 02/02/2015	MG	1.2.1	Add support for NFS shares. Add support	#
#				for different weekly and ad hoc targets.#
# 24/02/2015	MG	1.2.2	Change configuration files directory to	#
#				lixbackups to limit risk of conflict	#
#				with other backup packages.		#
# 26/02/2015	MG	1.2.3	Use logger to write key messages to	#
#				syslog.					#
# 19/06/2017	MG	1.2.4	Ensure script respects the 80 column	#
#				rule.					#
# 07/09/2017	MG	1.2.5	As of kernel version 4.13.0 the default	#
#				CIFS protocol version has been changed	#
#				from 1.0 to 3.0. However, some old NAS	#
#				devices may well still only know 1.0.	#
#				So introduce a config file param for	#
#				cifs version. If left blank the the	#
#				system default will be used.		#
# 30/11/2017	MG	1.2.6	Add SPDX license tags to source files.	#
# 03/12/2017	MG	1.2.7	Adopt normal exit code policy; 0 on	#
#				success, 1 on failure.			#
# 09/01/2019	MG	1.2.8	Use absolute bash path in shebang	#
#				instead of env. Using env is OK for a 	#
#				non-AutoTools script.			#
# 13/02/2019	MG	1.3.1	Do not hard code outputprefix contents.	#
#				Make true booleans.			#
#				Standardise parameters of output().	#
#				Remove script_exit_code variable.	#
#				Improve if statements with [[ ... ]].	#
#				Change verbosity to verbose boolean.	#
#				Refactor into functions.		#
#				Make appropriate variables read-only.	#
#				Use more meaningful exit codes.		#
#				Replace echo with more standard printf.	#
#				Add test for config file existence.	#
#				Ensure numerics use (( )) not [[ ]]	#
#				(( var )) does not need $.		#
#				Specify type for numeric variables.	#
# 19/04/2019	MG	1.3.2	Replace obsolete backticks with $(cmd).	#
# 09/08/2019	MG	1.3.3	Correct getopt CL for proper quoting.	#
# 11/10/2019	MG	1.3.4	Move script_exit() before it is used.	#
# 05/03/2021	MG	1.3.5	Prepend invocations of programs in this	#
#				package with sbindir to allow for	#
#				parallel AutoTool and distro package	#
#				installations.				#
# 24/11/2021	MG	1.3.6	Tighten SPDX tag.			#
#									#
#########################################################################

##################
# Init variables #
##################
readonly outputprefix="$(basename $0):"
readonly version=1.3.6				# Set version variable
readonly etclocation=/etc/lixbackups	# Path to etc directory
readonly packageversion=1.3.8		# Version of the package

adhoc=false
bckuptype=""
cifsversion=""
mntdir=""
verbose=false
weekly=false


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

# -h --help output.
# No parameters
# No return value
usage()
{
cat << EOF
Usage is $0 [options]
	-a or --adhoc mount the ad hoc backup target share
	OR
	-h or --help displays usage information
	OR
	-v or --verbose verbose output
	OR
	-V or --version displays version information
	OR
	-w or --weekly mount the weekly target backup share
EOF
}

# 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
		if $verbose ; then
			printf "%s %s\n" $outputprefix "$1"
		fi
	else
		printf "%s %s\n" $outputprefix "$1" 1>&2
	fi
	if (( $3 )); then
		logger "$outputprefix $1"
		std_cmd_err_handler $?
	fi
}

# 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 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
}

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

	tmpGETOPTTEMP="getopt -o ahvVw --long adhoc,help,verbose,version,"
	tmpGETOPTTEMP+="weekly"
	GETOPTTEMP=$($tmpGETOPTTEMP -n "$0" -- "$@")
	std_cmd_err_handler $?

	eval set -- "$GETOPTTEMP"
	std_cmd_err_handler $?

	while true; do
		case "$1" in
		-a|--adhoc)
			if $weekly ; then
				msg="Options a and w are mutually exclusive."
				output "$msg" 1 0
				script_exit 64
			fi
			adhoc=true
			bckuptype="adhoc"
			shift
			;;
		-h|--help)
			usage
			shift
			script_exit 0
			;;
		-v|--verbose)
			verbose=true
			shift
			;;
		-V|--version)
			printf "%s Script version %s\n" $0 $version
			printf "%s Package version %s\n" $0 $packageversion
			shift
			script_exit 0
			;;
		-w|--weekly)
			if $adhoc ; then
				msg="Options a and w are mutually exclusive."
				output "$msg" 1 0
				script_exit 64
			fi
			weekly=true
			bckuptype="weekly"
			shift
			;;
		--)	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

	# One option has to be selected.
	if ! $adhoc && ! $weekly ; then
		output "Either a or w must be set." 1 0
		script_exit 64
	fi
}

# Process the config file.
# Parameters - None
# No return value.
proc_config_file()
{
	local oldIFS=$IFS
	local input=()
	local msg
	local adhoccredfile adhocnotifyuser adhoctarget adhoctype
	local weeklycredfile weeklynotifyuser weeklytarget weeklytype

	if [[ ! -f $etclocation/backups.conf \
		|| ! -r $etclocation/backups.conf ]]; then
		msg="Config file $etclocation/backups.conf does not exist, is "
		msg+="not a regular file or is not readable."
		output "$msg" 1 1
		script_exit 66
	fi

	IFS="="

	exec 3<$etclocation/backups.conf
	while read -u3 -ra input; do
		case ${input[0]} in
		weeklytype)
			weeklytype=${input[1]}
			;;
		weeklytarget)
			weeklytarget=${input[1]}
			;;
		weeklycredfile)
			weeklycredfile=${input[1]}
			;;
		weeklynotifyuser)
			weeklynotifyuser=${input[1]}
			;;
		adhoctype)
			adhoctype=${input[1]}
			;;
		adhoctarget)
			adhoctarget=${input[1]}
			;;
		adhoccredfile)
			adhoccredfile=${input[1]}
			;;
		adhocnotifyuser)
			adhocnotifyuser=${input[1]}
			;;
		cifsversion)
			cifsversion=${input[1]}
			;;
		mntdir)
			mntdir=${input[1]}
			;;
		esac
	done
	exec 3<&-

	case $bckuptype in
	adhoc)
		type=$adhoctype
		target=$adhoctarget
		credfile=$adhoccredfile
		notifyuser=$adhocnotifyuser
		;;
	weekly)
		type=$weeklytype
		target=$weeklytarget
		credfile=$weeklycredfile
		notifyuser=$weeklynotifyuser
		;;
	esac

	IFS=$oldIFS
}

# Build the mount command.
# Parameters - none
# No return value.
build_mnt_cmd()
{
	mountCL="mount -t "
	case $type in
	NFS)
		mountCL=$mountCL"nfs $target $mntdir"
		;;
	CIFS)
		mountCL=$mountCL"cifs -o credentials=$credfile $target $mntdir"
		if [[ $cifsversion ]]; then
			mountCL+=" -o vers=$cifsversion"
		fi
		;;
	*)	output "Invalid share type." 1 1
		script_exit 78
		;;
	esac
}


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

# Setup trap.
trap trap_exit SIGHUP SIGINT SIGQUIT SIGTERM

proc_CL "$@"

# Read parameters from $etclocation/backups.conf
proc_config_file

# Build Mount command.
build_mnt_cmd

# Exit if share already mounted.
if [[ $(/usr/sbin/chkbckshare -bt) == TRUE ]]; then
	msg="Backup share already mounted."
	output "$msg" 1 1
	script_exit 1
fi

# Finally mount.
eval "$mountCL"
status=$?

if (( status )); then
	msg="Failed to mount backup share. Mount error: $status"
	msg+=" Script exit code: $status"
	output "$msg" 1 1
	script_exit $status
fi

output "Share $target mounted on $mntdir" 0 1
script_exit 0

