# This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file.
# Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT.


core_init_isFattening()
{
	core_variable_isSet _program_fattening
}

core_compatibility_basename()
{
	printf '%s' "${1##*/}"
}

core_compatibility_which()
{
	command -v "$1"
}

core_compatibility_whichNoOutput()
{
	core_compatibility_which "$1" 1>/dev/null 2>/dev/null
}

core_variable_isSet()
{
	# These expressions work in all shells bar pdksh 5.2.14, which treats expanded emptiness as unset...
	# Other techniques here: http://mywiki.wooledge.org/BashFAQ/083
	# eval "[ \"\${$1+set}\" = 'set' ]"
	# eval "$(printf '[ "${%s+set}" = '%s' ]' "$1" "set")"
	
	local x
	eval x="\"\${$1+set}\""
	[ "$x" = 'set' ]
}

core_variable_isUnset()
{
	# eval "[ \"\${$1+unset}\" != 'unset' ]"
	! core_variable_isSet "$1"
}

core_variable_indirectValue()
{
	eval "core_variable_indirectValue_result=\"\$${1}\""
}

core_init_verbosity()
{
	if core_variable_isSet ${_program_namespace}_verbose; then
		local core_variable_indirectValue_result
		core_variable_indirectValue ${_program_namespace}_verbose
		printf '%s' $core_variable_indirectValue_result
	else
		printf '%s' 0
	fi
}

core_init_language()
{
	if core_variable_isSet ${_program_namespace}_language; then
		local core_variable_indirectValue_result
		core_variable_indirectValue ${_program_namespace}_language
		printf '%s' $core_variable_indirectValue_result
	else
		printf '%s' 'en_US.UTF-8'
	fi
}

# We're supposed to use tput, but:-
# - It isn't present in BusyBox and Toybox (and other minimal systems without ncurses)
# - It doesn't work on a FreeBSD 10 default install (terminfo db probably missing)
# - terminfo databases are notorious for being broken and incomplete
# So we use ANSI sequences if we recognise the 'TERM' variable
# That stick to a small VT102 / ECMA-48 subset
# And fallback to tput if available
# http://wiki.bash-hackers.org/scripting/terminalcodes
# http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
# http://www.termsys.demon.co.uk/vtansi.htm
# https://www.gnu.org/software/termutils/manual/termutils-2.0/html_chapter/tput_1.html
# https://en.wikipedia.org/wiki/ANSI_escape_code
# http://mywiki.wooledge.org/BashFAQ/037?highlight=%28ps1%29
# “\e[x,y,zm” with x=brightness, y=foreground, z=background. For example:
# “\e[0;33;40m” shows dark (=0) yellow (=33) characters on black (=40) background
core_terminal_ansiSupported()
{
	if core_variable_isUnset TERM; then
		return 1
	fi
	
	case "$TERM" in
		
		# xterm-color, xterm-256color, linux-16color, etc
		# dtterm on AIX? kterm? others?
		xterm*|rxvt*|urxvt*|linux*|vt*)
			return 0
		;;
		
	esac
	
	return 1
}

core_terminal_ansiSequence()
{
	IFS='' printf "\033[${1}m"
}

core_terminal_tput()
{
	# Defensive syntax (|| true) for systems such as FreeBSD 10 where tput doesn't seem to support 'setaf' et al
	# Defensive setting of terminal so unset or empty TERM uses 'dumb', which disables option generation
	tput -T"${TERM:-dumb}" "$@" 2>/dev/null || true
}

core_terminal_colour()
{
	if [ ! -t $1 ]; then
		return 0
	fi
	
	local terminfoCommand
	local ansiGroundCodeBit
	case "$2" in
		
		foreground)
			terminfoCommand=setaf
			ansiGroundCodeBit=3
		;;
		
		background)
			terminfoCommand=setbf
			ansiGroundCodeBit=4
		;;
		
	esac
	
	local ansiColorCodeBit
	case "$3" in
		black)
			ansiColorCodeBit=0
		;;
		
		red)
			ansiColorCodeBit=1
		;;
			
		green)
			ansiColorCodeBit=2
		;;
		
		yellow)
			ansiColorCodeBit=3
		;;
		
		blue)
			ansiColorCodeBit=4
		;;
		
		magenta)
			ansiColorCodeBit=5
		;;
		
		cyan)
			ansiColorCodeBit=6
		;;
		
		white)
			ansiColorCodeBit=7
		;;
		
		default)
			ansiColorCodeBit=9
		;;
	esac

	if core_terminal_ansiSupported; then
		core_terminal_ansiSequence ${ansiGroundCodeBit}${ansiColorCodeBit}
	elif core_compatibility_whichNoOutput tput; then
		core_terminal_tput $terminfoCommand $ansiColorCodeBit
	fi
}

core_terminal_effect()
{
	if [ ! -t $1 ]; then
		return 0
	fi
	shift 1
	
	local effect
	local terminfoCommand
	local ansiCode
	for effect in "$@"
	do
		case "$effect" in
			
			bold)
				terminfoCommand=bold
				ansiCode=1
			;;
			
			dim)
				terminfoCommand=dim
				ansiCode=2
			;;
			
			# underscore not supported
			# $(tput smul)test$(tput rmul)
			# vs
			# ansiCode=4
			
			# standout mode (often bold or reversed)
			# smso / rmso
			
			blink)
				terminfoCommand=blink
				ansiCode=5
			;;
			
			reversed)
				terminfoCommand=rev
				ansiCode=7
			;;
			
			invisible)
				terminfoCommand=invis
				ansiCode=8
			;;
			
		esac

		if core_terminal_ansiSupported; then
			core_terminal_ansiSequence $ansiCode
		elif core_compatibility_whichNoOutput tput; then
			core_terminal_tput $terminfoCommand
		fi
	done
}

core_terminal_reset()
{
	if [ -t $1 ]; then
		if core_terminal_ansiSupported; then
			core_terminal_ansiSequence 0
		elif core_compatibility_whichNoOutput tput; then
			core_terminal_tput sgr0
		fi
	fi
}

core_message()
{
	local messageKind="$1"
	local message="$2"
	
	local shouldEcho=0
	local prefix=''
	case "$messageKind" in
		
		FAIL)
			prefix="$(core_terminal_effect 2 bold)$(core_terminal_colour 2 foreground red)"
			shouldEcho=1
		;;
		
		WARN)
			prefix="$(core_terminal_effect 2 bold)$(core_terminal_colour 2 foreground yellow)"
			shouldEcho=1
		;;
	
		NOTICE)
			if [ $(core_init_verbosity) -gt 0 ]; then
				prefix="$(core_terminal_colour 2 foreground cyan)"
				shouldEcho=1
			fi
		;;
	
		INFO)
			if [ $(core_init_verbosity) -gt 1 ]; then
				prefix="$(core_terminal_colour 2 foreground white)"
				shouldEcho=1
			fi
		;;
		
		TODO)
			if [ $(core_init_verbosity) -gt 1 ]; then
				prefix="$(core_terminal_effect 2 dim)"
				shouldEcho=1
			fi
		;;
	
		DEBUG)
			if [ $(core_init_verbosity) -gt 2 ]; then
				prefix="$(core_terminal_effect 2 dim)$(core_terminal_colour 2 foreground magenta)"
				shouldEcho=1
			fi
		;;
	
		*)
			shouldEcho=1
		;;

	esac
	
	if [ $shouldEcho -eq 1 ]; then
		printf '%s%s%s\n' "$prefix" "$_program_name: $messageKind: $message" "$(core_terminal_reset 2)" 1>&2
	fi
}

core_exitError()
{
	core_message FAIL "$2"
	exit $1
}

core_TODO()
{
	core_message TODO "$*"
}

if core_init_isFattening; then
	core_dependency_declares()
	{
		_program_fattening_declares "$@"
	}
	core_dependency_declaresAsArray()
	{
		local variableName
		for variableName in "$@"
		do
			_program_fattening_declares "$variableName"
			_program_fattening_declares "${variableName}_initialised"
		done
	}
else
	core_dependency_declares()
	{
		:
	}
	core_dependency_declaresAsArray()
	{
		:
	}
fi

core_libraryName=shellfire
core_dependency_declares core_libraryName

_core_dependency_requires=''
core_dependency_declares _core_dependency_requires
core_dependency_requires()
{
	# Or '*' for all
	_local_packageManager="$1"
	if [ -z "$_local_packageManager" ]; then
		# core_commandLine_exitCode_SOFTWARE
		core_exitError 70 "packageManager can not be empty"
	fi
	shift 1
	
	for _local_programName in "$@"
	do
		if [ -z "$_local_programName" ]; then
			# core_commandLine_exitCode_SOFTWARE
			core_exitError 70 "programName can not be empty"
		fi
		_core_dependency_requires="${_core_dependency_requires}${_local_packageManager} ${_local_programName}
"
		core_message DEBUG "Requires in packageManager '$_local_packageManager' program '$_local_programName'"
	done
	
	unset _local_packageManager
	unset _local_programName
}

# More for documentation than anything else for now
core_dependency_oneOf()
{
	# Or '*' for all
	_local_packageManager="$1"
	if [ -z "$_local_packageManager" ]; then
		# core_commandLine_exitCode_SOFTWARE
		core_exitError 70 "packageManager can not be empty"
	fi
	shift 1
	
	for _local_programName in "$@"
	do
		:
	done
	
	unset _local_packageManager
	unset _local_programName
}

# More for documentation than anything else for now
core_dependency_fallback()
{
	# eg !bash
	_local_condition="$1"
	
	for _local_programNameOnPath in "$@"
	do
		:
	done
	
	unset _local_condition
	unset _local_programNameOnPath
}

core_dependency_declares _core_uses_alreadySourced
# Duplicates logic in core/variable/array, but that is a hefty piece to pull in and breaks code (as the bash overrides handle arrays differently)
# Has a defect such that function paths containing $delimiter can be loaded more than once [highly unlikely except as a potential security defect]
# By specifying $1 as not, say, /usr/lib, and $2 as something other than core_libraryName, this code can be used for plugins
core_uses()
{
	local libPath="$1"
	local libraryName="$2"
	shift 2
	
	local namespacedModule
	local moduleName
	local sourced
	local relativeFunctionsFilePath
	local functionsFilePath
	
	# TODO: Does NOT WORK when using /bin/sh on Mac - implying older bash run as sh is broken
	local delimiter="$core_variable_array_delimiter"
	
	local module
	for module in "$@"
	do
		namespacedModule="$libraryName"/"$module"
		
		# Skip if already sourced
		local originalIFS="$IFS"
		local IFS="$delimiter"
		if core_variable_isUnset _core_uses_alreadySourced; then
			_core_uses_alreadySourced="${namespacedModule}"
		else
			for alreadySourcedNamespacedFunction in $_core_uses_alreadySourced
			do
				if [ "$namespacedModule" = "$alreadySourcedNamespacedFunction" ]; then
					continue 2
				fi
			done
			_core_uses_alreadySourced="${_core_uses_alreadySourced}${delimiter}${namespacedModule}"
		fi
		local IFS="$originalIFS"
		
		# Source
		moduleName="$(core_compatibility_basename "$namespacedModule")"
		sourced=0
		for relativeFunctionsFilePath in "$namespacedModule" "$namespacedModule"/"$moduleName"
		do
			functionsFilePath="$libPath"/"$relativeFunctionsFilePath".functions
			if [ -f "$functionsFilePath" ]; then
				# core_commandLine_exitCode_OSFILE
				. "$functionsFilePath" || core_exitError 72 "Can not load functions '$functionsFilePath'"
				sourced=1
			fi
		done
		if [ $sourced -eq 0 ]; then
			# core_commandLine_exitCode_OSFILE
			core_exitError 72 "Can not load functions for module '$namespacedModule'"
		fi
	done
}

core_usesIn()
{
	if [ $# -eq 1 ]; then
		local parentNamespace=''
	else
		local parentNamespace="${1}/"
		shift 1
	fi
	
	local module
	for module in "$@"
	do
		core_uses "$_program_libPath" "$core_libraryName" "${parentNamespace}${module}"
	done
}

core_init_defines()
{
	:
}

core_init_init()
{
	set -e
	set -u
	
	if [ "${_program_namespace+set}" != 'set' ]; then
		_program_namespace="${_program_name}"
	fi
}

core_init_shellDetection()
{
	if [ "${KSH_VERSION+set}" = 'set' ]; then
		_local_core_init_shellDetection_kshVersion="$KSH_VERSION"
	elif [ "${SH_VERSION+set}" = 'set' ]; then
		# seems to be set for pdksh when run as sh on OpenBSD (OpenBSD pdksh is modified)
		_local_core_init_shellDetection_kshVersion="$SH_VERSION"
	else
		_local_core_init_shellDetection_kshVersion=''
	fi
	
	if [ -n "$_local_core_init_shellDetection_kshVersion" ]; then
		# ksh93:  Version JM 93u 2011-02-08
		# ksh93:  Version AJM 93u+ 2012-08-01
		# pdksh:  @(#)PD KSH v5.2.14 99/07/13.2
		IFS=' ' read -r _local_core_init_shellDetection_version _local_core_init_shellDetection_garbage <<-EOF
			${_local_core_init_shellDetection_kshVersion}
		EOF
		
		case "$_local_core_init_shellDetection_version" in
		
			# ksh93
			'Version'|'.sh.version')
				core_init_shellDetected=ksh93
			;;
			
			'@(#)PD')
				core_init_shellDetected=pdksh
			;;
			
			'@(#)MIRBSD')
				core_init_shellDetected=mksh
			;;
			
			*)
				core_init_shellDetected=unknown-ksh
			;;
			
		esac
		
		unset _local_core_init_shellDetection_version
		unset _local_core_init_shellDetection_garbage
	elif [ "${BASH_VERSION+set}" = 'set' ]; then
		core_init_shellDetected=bash
	elif [ "${ZSH_VERSION+set}" = 'set' ]; then
		core_init_shellDetected=zsh
	elif [ "${YASH_VERSION+set}" = 'set' ]; then
		core_init_shellDetected=yash
	else
		core_init_shellDetected=sh
	fi
	
	unset _local_core_init_shellDetection_kshVersion
}

core_init_enableShellTweaks()
{
	# pdksh 5.2.14 barfs if the variable to unset is not set, even if set +u!
	# Worse, it refuses to let us override unset with a function. Hence this workaround everyone else has to use
	core_variable_unset()
	{
		unset "$@"
	}
	
	case "$core_init_shellDetected" in
		
		ksh93)
			# Set aliases for ksh93
			# https://stackoverflow.com/questions/12000949/scope-of-variables-in-ksh
			alias local='typeset'
		;;
		
		pdksh)
			# pdksh 5.2.14 barfs if the variable to unset is not set, even if set +u!
			core_variable_unset()
			{
				set +e
				unset "$1"
				set -e
			}
			
			# pdksh does not understand that in POSIX '$@' can be unset or empty but is still valid to reference
			# As a workaround, we disable unbound checks
			set +u
			
			# AIX pdksh also doesn't understand var=value exec command syntax... (it doesn't export var)!
		;;
			
		mksh)
			# See pdksh entry
			set +u
		;;
		
		yash)
			alias local='typeset'
		;;
		
	esac
}

core_init_setSaneEnvironmentDefaults()
{
	set +o allexport
	set -o errexit
	set +o ignoreeof
	set +o monitor
	set +o noclobber
	set +o noexec
	# aka set -f; disable globbing by default. Note that this is the opposite of usual behaviour
	set -o noglob
	# Does not work on FreeBSD sh; fine on dash, bash, etc
	# set +o nolog
	set +o notify
	set +o verbose
	set +o vi
	
	# unset will fail if, and only if, we've been source'd and they have been made readonly. Unlikely.
	
	# MUST be unset before making use of cd
	core_variable_unset CDPATH
	core_variable_unset HISTSIZE
	core_variable_unset MAILCHECK
	core_variable_unset MAILPATH
	core_variable_unset ENV
	core_variable_unset POSIXLY_CORRECT # affects bash, file, GNU grep, etc
	
	# bash specific
	core_variable_unset BASH_ENV
	core_variable_unset BASH_XTRACEFD
	core_variable_unset FCEDIT
	core_variable_unset FIGNORE
	core_variable_unset FUNCNEST
	core_variable_unset GLOBIGNORE
	core_variable_unset HISTCONTROL
	core_variable_unset HISTFILE
	core_variable_unset HISTFILESIZE
	core_variable_unset HISTIGNORE
	core_variable_unset HISTTIMEFORMAT
	core_variable_unset HOSTFILE
	core_variable_unset IGNOREEOF
	core_variable_unset INPUTRC
	core_variable_unset MAIL
	core_variable_unset TMOUT
}

# http://mywiki.wooledge.org/BashFAQ/028 on $0
# http://mywiki.wooledge.org/Bashism?action=show&redirect=bashism
core_init_findOurNameAndPath()
{
	core_init_ourSymlinkName="$(core_compatibility_basename "$0")"
		
	# can be empty if 'bash file' used or 'bash </path/to/file' or ksh with PATH containing '.'
	_local_ourSymlinkPathRaw="${0%/*}"
	if [ -z "$_local_ourSymlinkPathRaw" ]; then
		# core_commandLine_exitCode_USAGE
		core_exitError 64 "Do not invoke this program either by specifying a shell interpreter on a file in the current working directory (eg bash '$0') or redirecting from a pipe into a shell interpreter (eg bash [-c] <'$0') or by using ksh with a PATH containing '.'"
	elif [ "$_local_ourSymlinkPathRaw" = "$0" ]; then
		# core_commandLine_exitCode_USAGE
		core_exitError 64 "Do not invoke this program either by specifying a shell interpreter on a file in the current working directory (eg bash '$0') or redirecting from a pipe into a shell interpreter (eg bash [-c] <'$0') or by using ksh with a PATH containing '.'"
	fi
	
	# At this point, we resolve $0 vs the current working directory
	# If we were exec'd, we have either a relative or an absolute path
	# cd does not take switches in AIX!
	cd "$_local_ourSymlinkPathRaw" 1>/dev/null
		core_init_ourSymlinkPath="$(pwd)"
		core_init_ourPath="$(pwd -P)"
	cd - 1>/dev/null
	
	core_init_ourSymlinkExecutablePath="$core_init_ourSymlinkPath"/"$core_init_ourSymlinkName"
	
	unset _local_ourSymlinkPathRaw
}

core_init_doNotRunAsSetUidOrSetGid()
{
	# Not a great defence; real purpose is to defeat a sysadmin making this script setuid/setgid:-
	# * Happens too late, really - the shell interpreter is running
	# * bash allows functions to be exported that can replace builtins (even the builtin builtin)
	
	if [ -u "$core_init_ourSymlinkExecutablePath" ]; then
		# core_commandLine_exitCode_NOPERM
		core_exitError 77 "We can not be run with the setuid bit set"
	fi
	
	if [ -g "$core_init_ourSymlinkExecutablePath" ]; then
		# core_commandLine_exitCode_NOPERM
		core_exitError 77 "We can not be run with setgid bit set"
	fi
}

core_init_shellPreferred='sh'
core_init_determinePreferredShell()
{
	IFS=' ' read -r _local_commented_shebang_path _local_shebang_shell _local_remainder <"$core_init_ourSymlinkExecutablePath"
	if [ -n "$_local_remainder" ]; then
		# core_commandLine_exitCode_SOFTWARE
		core_exitError 70 "Passing options to a shell ('#!$_local_shebang_path $_local_shebang_shell $_local_remainder') is not supported"
	fi
	IFS='!' read -r _local_comment _local_shebang_path <<-EOF
		$_local_commented_shebang_path
	EOF
	
	if [ -z "$_local_shebang_shell" ]; then
		core_init_shellPreferred="$(core_compatibility_basename "$_local_shebang_path")"
	else
		if [ "$_local_shebang_path" != '/usr/bin/env' ]; then
			# core_commandLine_exitCode_SOFTWARE
			core_exitError 70 "All shell scripts should use '/usr/bin/env' with a shell, not #!$_local_shebang_path $shebang_shell"
		fi
		core_init_shellPreferred="$_local_shebang_shell"
	fi
	
	unset _local_commented_shebang_path
	unset _local_shebang_shell
	unset _local_remainder
	unset _local_comment
	unset _local_shebang_path
}

# Ensures we run under a shell interpreter that we were designed for - no matter what is specified in the shebang
# This works around packaging tools that want '#!/bin/bash', but point to an old version. Needs to be coupled into loading new shell versions.
core_init_rexecUnderCorrectShell()
{
	if core_variable_isSet core_init_shell_rexecing; then
		if [ "$core_init_shell_rexecing" = "$$" ]; then
			# we've been successfully re-exec'd
			unset core_init_shell_rexecing
			return 0
		fi
	fi
	
	# Doesn't defend against bash as sh bugs
	if [ "$core_init_shellDetected" = "$core_init_shellPreferred" ]; then
		return 0
	fi

	if ! core_compatibility_whichNoOutput "$core_init_shellPreferred"; then
		#core_commandLine_exitCode_OSFILE
		core_exitError 72 "Preferred shell '$core_init_shellPreferred' does not exist on the PATH"
	fi
	_local_shellPath="$(core_compatibility_which "$core_init_shellPreferred")"

	# exec -a doesn't work in dash
	if [ "$core_init_shellDetected" = 'bash' ]; then
		# ksh on AIX does not export  core_init_shell_rexecing  when run as  core_init_shell_rexecing=$$ exec $program ...
		
		# Forces a privileged shell. Not a great defence to Shellshock, but has some value.
		# Also possible for ksh and pdksh (?mksh) but ksh doesn't export functions
		export core_init_shell_rexecing=$$
		exec "$_local_shellPath" -p "$core_init_ourSymlinkExecutablePath" "$@"
	else
		export core_init_shell_rexecing=$$
		core_init_shell_rexecing=$$ exec "$_local_shellPath" "$core_init_ourSymlinkExecutablePath" "$@"
	fi
	
	unset _local_shellPath
}

core_init_initialiseArrayDelimiter()
{
	# Choosing a delimiter is unreasonably hard.
	# - It needs to work when set in IFS.
	# - It has a lifetime longer than the instance run if used for fattening.
	# - Various common bash versions have different IFS handling bugs.
	# Ideally, we want to use '\000', as it never occurs in file names. However, this is only allowed by zsh
	# Near Ideally, '\001' is so rare in file names as to be a good choice.
	# - However, bash 3.2 when invoked as sh on Mac OS X or AIX 6 & 7 can't use this.
	# - bash 4.1 on CentOS 6.11 seems to have similar issues.
	# Fairly rare is `\r'
	# - However bash 3.1.X in MinGW MSYS, Gow, etc (various bash-on-windows flavours) can't support this.
	# ',' works but is fairly common
	
	
	# We want to use '\001' in IFS as it's rare enough to delimit array elements safely.
	# However, some 'popular' versions of bash have IFS bugs which often manifest when bash is run as 'sh'
	if core_variable_isSet core_variable_array_delimiter; then
		return 0
	fi
	
	if core_variable_isSet _program_arrayDelimiter; then
		core_variable_array_delimiter="$_program_arrayDelimiter"
	else
		core_variable_array_delimiter="$(printf '\r')"
	fi
	core_dependency_declares core_variable_array_delimiter
}

_core_init_makePathAbsolute()
{
	local variableName="$1"
	
	if core_variable_isUnset "$variableName"; then
		return 0
	fi
	
	local core_variable_indirectValue_result
	core_variable_indirectValue "$variableName"
	
	set +e
		
		cd "$core_variable_indirectValue_result" 1>/dev/null 2>/dev/null
			if [ $? -ne 0 ]; then
				set -e
				return 0
			fi
			
			local absolutePath="$(pwd -P)"
			eval "$variableName"'=$absolutePath'
			
		cd - 1>/dev/null
		
	set -e
}

core_init_makePathsAbsolute()
{
	_core_init_makePathAbsolute _program_libPath
	_core_init_makePathAbsolute _program_etcPath
	_core_init_makePathAbsolute _program_varPath
}

core_init_workAroundBugInHomeFolderTildeHandlingAndEnsureHOMEIsAlwaysSet()
{
	# Weirdly, it seems ~ expansion doesn't work in some contexts in some shells
	set +f
	cd ~ 1>/dev/null
		export HOME="$(pwd -P)"
	cd - 1>/dev/null
	set -f
}

core_init_main()
{
	core_init_init
	core_init_shellDetection
	core_init_enableShellTweaks
	core_init_setSaneEnvironmentDefaults
	core_init_findOurNameAndPath
	core_init_determinePreferredShell
	core_init_rexecUnderCorrectShell "$@"
	core_init_initialiseArrayDelimiter
	core_init_makePathsAbsolute
	core_init_workAroundBugInHomeFolderTildeHandlingAndEnsureHOMEIsAlwaysSet
	
	core_usesIn core
	if core_functions_exists _program; then
		_program
	else
		:
	fi

	if core_init_isFattening; then
		return 0
	fi
	core_functions_execute _core_functions "$@"
	${_program_entrypoint}
}

core_init_main "$@"
