Skip to content

Sandcastle_Arg_checker

S0AndS0 edited this page Jan 29, 2016 · 4 revisions

The Arg_checker function originated from a StackOverFlow post and has expanded considerably to handle many more options than the author described.

This has been modified from the above example such that the function maybe called multiple times during scripted runtime; allowing for customized error reporting and verbose scripted actions.

## Print help and log errors example 1
<command_to_test> || Arg_checker --help='<function_name>' --exit='# [<command_to_test>] # Failed' -ep='<function_name>'
## Print help and log errors example 2
_function_args="${@:---help='<function_name>' --exit='# [<function_name>] # Failed to receive any arguments'}"
## Print function name after assigning variables based on command line options in ${_function_args}
Arg_checker ${_function_args} -ep='<function_name>'

What follows is an abridged version of the Arg_checker function with custom features exposed.

Arg_checker(){
	_script_args="${@:---help='Arg_checker' --exit='# [Arg_checker] # Failed to receive any arguments'}"
	if [ "${#_script_args}" -gt "0" ]; then
		echo "## Notice [Arg_checker] parsing general arguments and setting their variables..."
		for _KEY in ${_script_args}; do
			case "${_prefix}${_KEY}" in
				-ep=*|--external-parse=*)	_key="-ep" ;	_value="${_KEY#*=}" ;;
				-ex=*|--exit=*)				_key="-ex" ;	_value="${_KEY#*=}" ;;
				-h=*|--help=*)				_key="-H" ;		_value="${_KEY#*=}" ;;
				-h|--help)					_key="-h" ;		_value="${_KEY#*=}" ;;
				-vf=*|--var-file=*)			_key="-vf" ;	_value="${_KEY#*=}" ;;
			esac
			case $_key in
				-ep)
					_prefix="" ; _key=""
					_external_parse="${_value}"
				;;
				-ex)
					_prefix="" ; _key=""
					_exit="${_value}"
				;;
				-H)
					_prefix="" ; _key=""
					_help_args="${_value}"
				;;
				-h)
					_prefix="" ; _key=""
					_help_args="${_script_name},Arg_checker_tor"
				;;
				-vf)
					_prefix="" ; _key=""
					_var_files="${_value}"
				;;
				-W)
					_prefix="" ; _key=""
					_tor_web_dir="${_value}"
					Output_variables_file "_tor_web_dir" "${_tor_web_dir}"
				;;
			esac
		done
		echo "#	Notice [Arg_checker] parsing specific arguments for any [-h=...] values"
		if [ "${#_help_args}" != "0" ]; then
			Parse_help "${_help_args}" "${_exit:-0}"
		fi
## Check for presence of [-vf] value and load before further processing any variables
#	assigned within, note this maybe used to overwrite existing values
		if [ "${_external_parse}" = "${_script_name}" ]; then
			echo "#	Notice [Arg_checker] parsing specific arguments for any [-vf=...] values"
		fi
		if [ "${#_var_files}" != "0" ]; then
			if [ "${_external_parse}" = "${_script_name}" ]; then
				echo "#	Notice : [-vf] option detected, parsing arguments from [${_var_files//,/] and [}] file(s)."
			fi
			Parse_varfile_load "${_var_files}"
		fi
		if [ "${#_external_ipv4}" = "0" ]; then
			echo '## Warning [Arg_checker] function detected no [-ip] argument passed, nor was this value set via [-vf] argument
			echo "#	if using [${_script_name}] for client only installation you may feed false vales, ei [-ip=1.1.1.1]"
			echo "#	however, if using [${_script_name}] for any other previous you may press [Enter] when prompted"
			echo '#	to have this value automatically assigned for you via a request to [opendns.com] during runtime'
			echo ''
			echo '# Press [Ctrl^c] to quit now, or [Enter] to auto-assign, or [your-ip] if known to assign now...'
			echo '#	Your choice...? ~: '
			read _read_external_ipv4
			if [ "${#_read_external_ipv4}" != "0" ]; then
				echo "#	Setting [${_read_external_ipv4}] to [\${_external_ipv4}] variable and continuing..."
				_external_ipv4="${_read_external_ipv4}"
			fi
		fi
		if [ "${_external_parse}" = "${_script_name}" ]; then
			echo "#	Beginning tor installation process for [${_script_name}], this may take more"
			echo "#	than a minuet, please [${USER}] be present and pashent..."
		elif [ "${_external_parse}" != "${_script_name}" ]; then
			_arg_check_count="$((${_arg_check_count:0}+1))"
			echo "## Notice #${_arg_check_count} [${_external_parse}] : finished reading arguments"
			echo "#	with function [Arg_checker] continuing processing [${_script_name}] for [${USER}]..."
		fi
	elif [ "${#_script_args}" = "0" ]; then
		echo '## Error [Arg_checker] function reading arguments!'
		echo "#	Was [${_script_name}] script given any arguments?"
		echo "#	Try [ ${_script_name} --help ] to start learning about [${_script_name}]"
		echo "#	or [ ${_script_name} --h=\"function_name\" ] to learn about spicific functions"
		exit 1
	fi
}

This is the Parse_help function called by above Arg_checker function for printing help documentation for each function passed via -h=<function_name1>,<function_name1>,... option.

Parse_help(){
	_help_args="${1:-$_help_args}"
	_exit_line="${2:-$_exit}"
	if [ "${#_help_args}" != "0" ]; then
		_search_files_tor=$(grep -E 'source' ${_script_dir}/functions/tor/source_tor_functions.sh | grep -vE '#' | awk '{gsub("\"",""); print $2}' | awk '{gsub("\${_dir}","${_script_dir}"); print $1}')
		_search_files_shared=$(grep -E 'source' ${_script_dir}/functions/shared/source_shared_functions.sh | grep -vE '#' | awk '{gsub("\"",""); print $2}' | awk '{gsub("\${_dir}","${_script_dir}"); print $1}')
		_search_files_privoxy=$(grep -E 'source' ${_script_dir}/functions/privoxy/source_privoxy_functions.sh | grep -vE '#' | awk '{gsub("\"",""); print $2}' | awk '{gsub("\${_dir}","${_script_dir}"); print $1}')
		_search_files_nginx=$(grep -E 'source' ${_script_dir}/functions/nginx/source_nginx_functions.sh | grep -vE '#' | awk '{gsub("\"",""); print $2}' | awk '{gsub("\${_dir}","${_script_dir}"); print $1}')
		_search_files_polipo=$(grep -E 'source' ${_script_dir}/functions/polipo/source_polipo_functions.sh | grep -vE '#' | awk '{gsub("\"",""); print $2}' | awk '{gsub("\${_dir}","${_script_dir}"); print $1}')
		_search_files_squid=$(grep -E 'source' ${_script_dir}/functions/squid/source_squid_functions.sh | grep -vE '#' | awk '{gsub("\"",""); print $2}' | awk '{gsub("\${_dir}","${_script_dir}"); print $1}')
		_search_files_bind=$(grep -E 'source' ${_script_dir}/functions/bind/source_bind_functions.sh | grep -vE '#' | awk '{gsub("\"",""); print $2}' | awk '{gsub("\${_dir}","${_script_dir}"); print $1}')
		_search_files_firejail=$(grep -E 'source' ${_script_dir}/functions/firejail/source_firejail_functions.sh | grep -vE '#' | awk '{gsub("\"",""); print $2}' | awk '{gsub("\${_dir}","${_script_dir}"); print $1}')
		_search_files_firetools=$(grep -E 'source' ${_script_dir}/functions/firetools/source_firetools_functions.sh | grep -vE '#' | awk '{gsub("\"",""); print $2}' | awk '{gsub("\${_dir}","${_script_dir}"); print $1}')
		_search_files="${_search_files_tor},${_search_files_shared},${_search_files_polipo},${_search_files_privoxy},${_search_files_nginx},${_serach_files_squid},${_search_files_bind},${_search_files_firejail},${_search_files_firetools}"
		_line_range='400'
		echo "## Notice [Arg_checker] detected --help=[${_help_args}] searching for"
		echo "#	documentation now within [${_dirs//,/] [}] directories"
		for _files in ${_search_files//,/ }; do
			for _function in ${_help_args//,/ }; do
				_search_term=$(head -n1 <<<$(grep -ioE "${_function}.*" <<<$(ls ${_files})))
				_dir="${_search_term%/*}"
				if [ "${#_search_term}" != "0" ]; then
					if [ -f "${_dir}/${_search_term}" ]; then
						echo "# Help documentation for search term [${_search_term}]"
						echo "#	found under [${_dir}/${_search_term}]"
						grep -A${_line_range:-400} -iE "${_function}_help.*|${_search_term}.*" ${_dir}/${_search_term} | grep -B${_line_range:-400} -E '####' | less
					else
						echo "## Notice [Help_usage_tor] function reports..."
						echo "#	No file found to search for further help under [${_dir}/${_search_term}"
						echo "#	while searching for [${_search_term}]"
					fi
				fi
				_last_function="${_function}"
			done
		done
		echo "#	Finished processing help documentation for [${_help_args//,/ }]"
		if [ "${#_exit_line}" = "0" ]; then
			echo "#	Have a nice day ${USER} [${_script_name}] exiting now..."
			exit 1
		elif [ "${_exit_line}" = "0" ]; then
			echo "# allowing further processing..."
		elif [ "${#_exit_line}" -gt "0" ]; then
			echo "## Warning ${USER} [${_script_name}] exiting do to errors encountered."
			Error_generator "${_temp_dir}/${_script_name}_errors/${_last_function:$_script_name}.log" "#${_now}# Error [${_exit_line:-$_script_name}] did Not finish, please see related help documentation with [${_script_name} --help=${_last_function:-$_script_name}]" '1'
			exit 1
		fi
	fi
}

This is the Error_generator function called by above Arg_checker function for generating error logs if -ex="<string_or_command_to_log>"

Error_generator(){
	_message="$1"
	_log_destination="${2:-/tmp/errors/error_generator.log}"
	_log_directory="${_log_destination%*/}"
	_log_directory="${_log_directory:-/tmp/errors}"
	_log_file="${_log_destination##*/}"
	_log_file="${_log_file:-generall_messages.log}"
	_log_dest="${_log_directory}/${_log_file}"
	_exit="${3:-0}"
	_now="$(date)"
	if ! [ -d ${_log_directory} ]; then
		mkdir -p ${_log_directory}
	fi
	if [ "${#_log_dest}" != "0" ]; then
		if ! [ -f ${_log_dest} ]; then
			echo "#${_now}# Logs for [${_log_file}] started." | tee -a ${_log_dest}
		fi
		if [ "${#_message}" != "0"]; then
			echo "#${_now}#${_message}" | tee -a ${_log_dest}
		fi
		if [ "${_exit}" = "0" ]; then
			echo "#${_now}#	exit status not triggered in [Error_generator] function, silently allowing further processing..." >> ${_log_dest}
		elif [ "${#_exit}" -gt "0" ]; then
			echo "# Additionally : ${_exit}" | tee -a ${_log_dest}
			exit 1
		elif [ "${_exit}" != "0" ]; then
			echo "#${_now}# Exit status [${_exit}] did not equal [0] quitting [Error_generator] function" | tee -a ${_log_dest}
			exit 1
		fi
	fi
}

This is the Output_variables_file function called by above Arg_checker function for generating customized configuration files.

Output_variables_file(){
	_var_name="${1:?}"
	_var_value="${2:?}"
	if [ "${_external_parse}" != "${_script_name}" ] && [ "${_external_parse}" = -o "END" "end" ]; then
		_vars_out_file="${_script_dir}/variables/${USER}_vars.sh"
		Overwrite_config_checker "${_vars_out_file}"
		echo "${_var_name}=${_var_value}" | tee -a ${_vars_out_file}
		## Uncomment to clear value after writing
		#${_var_name}=${_var_value}
	elif [ "${_external_parse}" != "${_script_name}" ] && [ "${_external_parse}" = -o "WRITE" "write" ]; then
		_vars_out_file="${_script_dir}/variables/${USER}_vars.sh"
		echo "${_var_name}=${_var_value}" | tee -a ${_vars_out_file}
	fi
}

Okay... so what does the above do?

This scripted logic allows for these functions to be called by other functions within this script pack to have their respective variables assigned from arguments passed to Sandcastl.sh script. To start from Arg_checker we read command line options into thier respective variables

  • if _script_args contains a value then attempt to read them through for & case loop to assign variables

-- if at any point -ep=Sandcastle.sh is read, then print start up messages

-- if _help_args contains a value, string or number, pass control over to Parse_help function

--- if _help_args contains a recognized function name then print documentation found for the related function before checking exit status.

--- when Parse_help function is called if _exit contains a value other than 0, then quit script run time after printing help documentation.

--- if _exit contains a string then pass control over to Error_generator function after printing documentation.

---- When Error_generator function is called log string to error log before exiting.

-- if _var_files contains a value attempt to load with Parse_varfile_load function which essentally runs the source command if the file is found.

-- if _external_parse does not equal Sandcastle.sh (set by -ep="") then add 1 to _arg_check_count's internall variable and print the stirng contained within _external_parse after assigning variables. Essentally this prints where you are in scripted run time allong with the current function that is having variables set.

  • if _script_args does not equal any value then exit with error message.