#!/data/data/com.termux/files/usr/bin/bash

#title:         sudo
#description:   a wrapper script to drop to the supported shells or
#               execute shell script files or their text passed as
#               an argument with superuser (root) context in termux
#author:        agnostic-apollo
#usage:         run "sudo --help" for detailed list of usages
#date:          14-Dec-2020
#bash version:  4.1 or higher
#credits:       https://gitlab.com/st42/termux-sudo
#               https://github.com/cswl/tsu
version=0.2.0



### Install Instructions For Termux In Android:

#The `sudo` file should be placed in termux `bin` directory `/data/data/com.termux/files/usr/bin`.  
#It should have `termux` `uid:gid` ownership and have executable `700` permission before it can be run directly without `bash`.  
#
#1. Download the `sudo` file.  
#
#    - Download to termux bin directory directly from github using `curl` using a non-root termux shell.  
#        Run `pkg install curl` to install `curl` first.  
#        - Latest release:  
#
#          `curl -L 'https://github.com/agnostic-apollo/sudo/releases/latest/download/sudo' -o "/data/data/com.termux/files/usr/bin/sudo"`  
#
#        - Specific release:  
#
#          `curl -L 'https://github.com/agnostic-apollo/sudo/releases/download/v0.1.0/sudo' -o "/data/data/com.termux/files/usr/bin/sudo"`  
#
#        - Master Branch *may be unstable*:  
#
#          `curl -L 'https://github.com/agnostic-apollo/sudo/raw/master/sudo' -o "/data/data/com.termux/files/usr/bin/sudo"`  
#
#    - Download `sudo` file manually from github to the android download directory and then copy it to termux bin directory.  
#
#      You can download the `sudo` file from a github release from the `Assets` dropdown menu.  
#
#      You can also download it from a specific github branch/tag by opening the `sudo` file from the `Code` section.  
#      Right-click or hold the `Raw` button at the top and select `Download/Save link`.  
#
#      Then copy the file to termux bin directory using `cat` command below or use a root file browser to manually place it.  
#
#       `cat "/storage/emulated/0/Download/sudo" > "/data/data/com.termux/files/usr/bin/sudo"`  
#
#2. Set `termux` ownership and executable permissions.  
#
#    - If you used a `curl` or `cat` to copy the file, then use a non-root termux shell to set ownership and permissions with `chown` and `chmod` commands respectively:  
#
#      `export termux_bin_path="/data/data/com.termux/files/usr/bin"; export owner="$(stat -c "%u" "$termux_bin_path")"; chown "$owner:$owner" "$termux_bin_path/sudo" && chmod 700 "$termux_bin_path/sudo";`  
#
#    - If you used a root file browser to copy the file, then use `su` to start a root shell to set ownership and permissions with `chown` and `chmod` commands respectively:  
#
#      `export termux_bin_path="/data/data/com.termux/files/usr/bin"; export owner="$(stat -c "%u" "$termux_bin_path")"; su -c "chown \"$owner:$owner\" \"$termux_bin_path/sudo\" && chmod 700 \"$termux_bin_path/sudo\"";`  
#
#    - Or manually set them with your root file browser. You can find `termux` `uid` and `gid` by running the command `id -u` in a non-root termux shell or by checking the properties of the termux `bin` directory from your root file browser.  
#

sudo_set_default_variables() {

#set termux and android default variables
TERMUX_FILES="/data/data/com.termux/files"
TERMUX_HOME_BASENAME="home"
TERMUX_HOME="$TERMUX_FILES/$TERMUX_HOME_BASENAME"
TERMUX_PREFIX_BASENAME="usr"
TERMUX_PREFIX="$TERMUX_FILES/$TERMUX_PREFIX_BASENAME"
TERMUX_BIN="$TERMUX_PREFIX/bin"
TERMUX_BIN_APPLETS="$TERMUX_PREFIX/bin/applets"
TERMUX_PATH="$TERMUX_BIN:$TERMUX_BIN_APPLETS"
TERMUX_LD_LIBRARY_PATH="$TERMUX_PREFIX/lib"
TMPDIR="$TERMUX_PREFIX/tmp"
SYS_XBIN="/system/xbin"
SYS_BIN="/system/bin"
ANDROID_PATH="$SYS_XBIN:$SYS_BIN"
ANDROID_OTHER_BIN_PATHS="/sbin:/vendor/bin:/system/sbin"
BASH_SHELL_PATH="$TERMUX_BIN/bash"
TERM="xterm-256color"

#termux is currently an english-only environment
LANG="en_US.UTF-8"


### Set User Modifiable Variables Start
### It is highly advisable to use the sudo.config file instead to modify the default values

#set SUDO_SHELL_HOME which will be used as sudo shell home directory
[ ! -z "$SUDO_SHELL_HOME" ] && custom_sudo_shell_home_set=1
SUDO_SHELL_HOME="${SUDO_SHELL_HOME:=$TERMUX_HOME/.suroot}" #default to '$TERMUX_HOME/.suroot'
#SUDO_SHELL_HOME="${SUDO_SHELL_HOME:=$TERMUX_HOME}" #use '$TERMUX_HOME' as sudo shell home

#set SUDO_POST_SHELL_HOME which will be used as sudo post shell home directory
[ ! -z "$SUDO_POST_SHELL_HOME" ] && custom_sudo_post_shell_home_set=1
SUDO_POST_SHELL_HOME="${SUDO_POST_SHELL_HOME:=$TERMUX_HOME/.suroot}" #default to '$TERMUX_HOME/.suroot'
#SUDO_POST_SHELL_HOME="${SUDO_POST_SHELL_HOME:=$TERMUX_HOME}" #use '$TERMUX_HOME' as sudo post shell home

#set the prompt string 1 for the sudo shell
SUDO_SHELL_PS1="${SUDO_SHELL_PS1:=# }" #default to "# "

#set the prompt string 1 for the sudo post shell
SUDO_POST_SHELL_PS1="${SUDO_POST_SHELL_PS1:=# }" #default to "# "

#set any additional paths you want to export other than termux bin, android bin and su bin paths,
#separated with colons `:`
#the string must not start or end with or contain two consecutive colons ':'
#the `--export-paths` option will override this value
ADDITIONAL_PATHS_TO_EXPORT="${ADDITIONAL_PATHS_TO_EXPORT:=}" #default to none

#set to "1" or pass "-L" as argument if you want to automatically export all the paths that already exist
#in the PATH variable at the moment the sudo command is run
#the default paths mentioned above and any path in ADDITIONAL_PATHS_TO_EXPORT are always exported
export_all_existing_paths_in_path_variable="${export_all_existing_paths_in_path_variable:=0}" #default to 0

#set any additional ld library paths you want to export other than termux lib and android lib paths,
#separated with colons `:`
#the string must not start or end with or contain two consecutive colons ':'
#the `--export-ld-lib-paths` option will override this value
ADDITIONAL_LD_LIBRARY_PATHS_TO_EXPORT="${ADDITIONAL_LD_LIBRARY_PATHS_TO_EXPORT:=}" #default to none

#set to "1" or pass "-P" as argument if you want to automatically export all the paths that already exist
#in the LD_LIBRARY_PATH variable at the moment the sudo command is run
#the default paths mentioned above and any path in ADDITIONAL_LD_LIBRARY_PATHS_TO_EXPORT are always exported
export_all_existing_paths_in_ld_library_path_variable="${export_all_existing_paths_in_ld_library_path_variable:=0}" #default to 0

#set to 1 if you want to automatically create rc files for interactive shells, otherwise 0
sudo_shells_automatically_create_rc_files="${sudo_shells_automatically_create_rc_files:=1}" #default to 1

#set to 1 if you want to automatically create history files for interactive shells, otherwise 0
sudo_shells_automatically_create_history_files="${sudo_shells_automatically_create_history_files:=1}" #default to 1

#set to 1 if you want to store command history for interactive shells, otherwise 0
sudo_shells_history_enabled="${sudo_shells_history_enabled:=1}" #default to 1


#for f in SUDO_SHELL_HOME SUDO_POST_SHELL_HOME SUDO_SHELL_PS1 SUDO_POST_SHELL_PS1 ADDITIONAL_PATHS_TO_EXPORT export_all_existing_paths_in_path_variable ADDITIONAL_LD_LIBRARY_PATHS_TO_EXPORT export_all_existing_paths_in_ld_library_path_variable sudo_shells_automatically_create_rc_files sudo_shells_automatically_create_history_files sudo_shells_history_enabled; do echo "$f=\`${!f}\`"; done; echo $'\n'

### Set User Modifiable Variables End


### Set Default Variables Start
#The following variables must not be modified unless you know what you are doing

sudo_verbose_level=0 #default to log level 0
sudo_args_verbose_level=0 #set this to 1 manually, if you want to debug arguments received
rootfs_previous_state_ro=0 #default to yes
system_previous_state_ro=0 #default to yes

command_type="path" #default to path
command_type_path_forced=0 #default to 0
same_sudo_post_shell_as_sudo_shell=0 #default to 0
same_sudo_post_shell_home_as_sudo_shell_home=0 #default to 0
parse_commands_as_per_run_command_intent_rules=0 #default to 0
exec_sudo_shell=0 #default to 0
disable_preserve_environment_for_su=0 #default to 0
disable_stdin_for_core_script=0 #default to 0
run_core_script_in_background=0 #default to 0
exit_early_if_core_script_fails=0 #default to 0
go_back_to_last_activity_after_running_core_script=0 #default to 0
go_to_launcher_activity_after_running_core_script=0 #default to 0
clear_shell_after_running_core_script=0 #default to 0
run_interactive_post_sudo_shell_after_running_core_script=0 #default to 0
force_use_temp_script_file_for_core_script=0 #default to 0
core_script_is_path_to_script_file=0 #default to 0
decode_core_script_content=0 #default to 0
do_not_delete_sudo_temp_directory_on_exit=0 #default to 0
remove_previous_sudo_temp_files=0 #default to 0
use_root_for_path_search_and_validation=0 #default to 0
do_not_remount_partitions_back_to_ro_after_sudo=0 #default to 0
force_remount_partitions_back_to_ro_after_sudo=0 #default to 0
hold_after_sudo=0 #default to 0
hold_only_on_failure=0 #default to 0
sleep_after_sudo=0 #default to 0
sleep_only_on_failure=0 #default to 0
dry_run_sudo=0 #default to 0
disable_arguments_logging=0 #default to 0
set_sudo_shell_terminal_title=0 #default to 0
force_set_priority_to_android_paths=0 #default to 0

SUDO_SHELL="" #default to none
SUDO_SHELL_BASENAME="" #default to none
SUDO_SHELL_PARENT_DIR="" #default to none
SUDO_POST_SHELL="" #default to none
SUDO_POST_SHELL_BASENAME="" #default to none
SUDO_POST_SHELL_PARENT_DIR="" #default to none
SUDO_SHELL_RCFILE="" #default to none
SUDO_POST_SHELL_RCFILE="" #default to none
SUDO_SHELL_HISTFILE="" #default to none
SUDO_POST_SHELL_HISTFILE="" #default to none
SUDO_TEMP_DIRECTORY="" #default to none
SUDO_TEMP_DIRECTORY_PREFIX=".sudo.temp"
SUDO_CORE_SCRIPT_TEMP_FILENAME="" #default to none
SUDO_CORE_SCRIPT_REDIRECT_MODE="" #default to none
SUDO_SHELL_WORKING_DIR="" #default to none
SUDO_SHELL_TERMINAL_TITLE="" #default to none
ADDITIONAL_SUDO_SHELL_PRE_COMMANDS_TO_RUN="" #default to none
ADDITIONAL_SUDO_SHELL_POST_COMMANDS_TO_RUN="" #default to none
ADDITIONAL_SUDO_POST_SHELL_PRE_COMMANDS_TO_RUN="" #default to none
ADDITIONAL_SUDO_POST_SHELL_POST_COMMANDS_TO_RUN="" #default to none
SUDO_SHELL_STDIN_STRING="" #default to none
SUDO_POST_SHELL_STDIN_STRING="" #default to none
SUDO_SUPPORTED_SHELLS="" #default to none
SUDO_SUPPORTED_POST_SHELLS="" #default to none
SLEEP_TIME_AFTER_SUDO="" #default to none
HOLD_STRING_AFTER_SUDO="" #default to none
COMMA_ALTERNATIVE="‚" #U+201A, &sbquo;, &#8218;, single low-9 quotation mark
SUDO_ARG_MAX_SAFE_LIMIT=122880 #value should be in bytes, default to 120KB

SUDO_SUPPORTED_INTERACTIVE_SHELLS="bash zsh dash sh fish python ruby pry node perl lua5.2 lua5.3 lua5.4 php python2 ksh"
SUDO_SUPPORTED_SCRIPT_SHELLS="bash zsh dash sh fish python ruby node perl lua5.2 lua5.3 lua5.4 php python2 ksh"
SUDO_SCRIPT_SHELLS_WITHOUT_PROCESS_SUBSTITUTION_SUPPORT="dash sh node php"

declare -ga SUDO_COMMAND=()
declare -ga SHELL_COMMAND=()
declare -ga SHELL_INTERACTIVE_COMMAND=()
declare -ga SUDO_SHELL_COMMAND=()
declare -ga SUDO_SHELL_INTERACTIVE_COMMAND=()
declare -ga SUDO_POST_SHELL_INTERACTIVE_COMMAND=()

declare -ga SHELL_ADDITIONAL_COMMAND_OPTIONS=()
declare -ga SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS=()
declare -ga SUDO_SHELL_ADDITIONAL_COMMAND_OPTIONS=()
declare -ga SUDO_SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS=()
declare -ga SUDO_POST_SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS=()
declare -ga SUDO_RLWRAP_ADDITIONAL_COMMAND_OPTIONS=()
declare -ga SUDO_SU_ENV_ADDITIONAL_COMMAND_OPTIONS=()
declare -ga SUDO_SU_RUN_ADDITIONAL_COMMAND_OPTIONS=()

#set regexes for validation
valid_number_regex='^[0-9]+$'
valid_absolute_path_regex='^(/[^/]+)+$'
valid_path_in_rootfs_partition_regex='^/[^/]*/?$'
valid_path_in_system_partition_regex='^/system/.*'
valid_su_mount_master_option_prefixed_string='^[ \t]*(--mount-master|-mm)[ \t]*'

### Set Default Variables End

}

[[ x"${BASH_SOURCE[0]}" == x"$0" ]] && sudo_exit_command="exit" || sudo_exit_command="return"

function sudo_log() { local log_level="${1}"; shift; if [[ $sudo_verbose_level -ge $log_level ]]; then echo "$@"; fi }
function sudo_log_literal() { local log_level="${1}"; shift; if [[ $sudo_verbose_level -ge $log_level ]]; then echo -e "$@"; fi }
function sudo_log_errors() { echo "$@" 1>&2; }
function sudo_log_args() { if [[ $sudo_args_verbose_level -ge "1" ]]; then echo "$@"; fi }
function sudo_log_arg_errors() { echo "$@" 1>&2; }

#enable the following line if you want to log function runtimes with the '-vv' option
#sudo_start_time=$(date +%s%3N); function sudo_log_literal() { local log_level="${1}"; shift; if [[ $sudo_verbose_level -ge $log_level ]]; then if [[ "$*" == *"Running"* ]]; then sudo_end_time=$(date +%s%3N); run_time=$((sudo_end_time-sudo_start_time)); echo -e "Runtime $run_time\n"; sudo_start_time=$(date +%s%3N); fi; echo -e "$@"; fi }


sudo_main() {

	local return_value

	#if sudo_config_file exists, source it
	sudo_config_file="/data/data/com.termux/files/home/.config/sudo/sudo.config"
	sudo_config_file_sourced=0
	if [ -f "$sudo_config_file" ] && [ -r "$sudo_config_file" ]; then
		source "$sudo_config_file"
		sudo_config_file_sourced=1
	fi

	#set default variables
	#there are set by a function so that they do not automatically override already set variables
	#if the script is sourced
	#user modifiable variables will only be set if the sudo_config_file didn't set them or
	#if they were not already exported
	sudo_set_default_variables

	#process the command or options passed to sudo
	process_sudo_parameters "$@"

	#validate command_type
	if [ -z "$command_type" ]; then
		show_sudo_help
		return_value=0
	elif [[ "$command_type" != *,* ]] && [[ ",su,asu,path,script," == *",$command_type,"* ]]; then
		sudo_run
		return_value=$?
	else
		sudo_log_errors "Unknown command type $command_type"
		exit_sudo_on_error
	fi

	sudo_run_pre_exit_commands $return_value

	$sudo_exit_command $return_value

}

sudo_run() {

	local return_value

	sudo_log_literal 2 "\nRunning sudo"

	#if sudo_config_file_sourced is enabled
	if [[ "$sudo_config_file_sourced" == "1" ]]; then
		sudo_log 2 "config was sourced from ~/.config/sudo/sudo.config"
	fi

	SUDO_SCRIPT_PATH="$(readlink -f -- "${BASH_SOURCE[0]}")"
	return_value=$?
	if [ $return_value -ne 0 ] || [[ ! "$SUDO_SCRIPT_PATH" =~ $valid_absolute_path_regex ]]; then
		sudo_log_errors "Failure while finding SUDO_SCRIPT_PATH"
		sudo_log_errors "SUDO_SCRIPT_PATH=\"$SUDO_SCRIPT_PATH\""
		if [ $return_value -eq 0 ]; then
			return_value=1
		fi
		return $return_value
	fi

	export SUDO_SCRIPT_PATH

	#if command_type equals "su" or "asu"
	if [[ "$command_type" == "su" ]] || [[ "$command_type" == "asu" ]]; then
		SUDO_SUPPORTED_SHELLS="$SUDO_SUPPORTED_INTERACTIVE_SHELLS"

		# The arguments passed to '--shell-options' are meant for interactive shell
		SUDO_SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS=("${SUDO_SHELL_ADDITIONAL_COMMAND_OPTIONS[@]}")
		SUDO_SHELL_ADDITIONAL_COMMAND_OPTIONS=()

		interactive_sudo_shell_required=1
	#if command_type equals "path"
	elif [[ "$command_type" == "path" ]]; then
		SUDO_SUPPORTED_SHELLS="bash"

		#unset SUDO_SHELL so that it defaults to bash in sudo_set_sudo_shell
		SUDO_SHELL=""

		#ignore any shell options that are passed
		SUDO_SHELL_ADDITIONAL_COMMAND_OPTIONS=()

		interactive_sudo_shell_required=0
	#if command_type equals "script"
	elif [[ "$command_type" == "script" ]]; then
		SUDO_SUPPORTED_SHELLS="$SUDO_SUPPORTED_SCRIPT_SHELLS"
		SUDO_SUPPORTED_POST_SHELLS="$SUDO_SUPPORTED_INTERACTIVE_SHELLS"

		interactive_sudo_shell_required=0
	else
		sudo_log_errors "command_type \"$command_type\" not handled while running sudo command in \"sudo_run\""
		return 1
	fi

	#if command_type equals "script"
	if [[ "$command_type" == "script" ]]; then
		#if disable_stdin_for_core_script is enabled or stdin is not available while running this script
		#force enable disable_stdin_for_core_script
		if [[ "$disable_stdin_for_core_script" == "1" ]] || [ ! -t 0 ]; then
			disable_stdin_for_core_script=1
		else
			disable_stdin_for_core_script=0
		fi
	fi


	#if run_interactive_post_sudo_shell_after_running_core_script is enabled and command_type equals "script"
	if [[ "$run_interactive_post_sudo_shell_after_running_core_script" == "1" ]] && [[ "$command_type" == "script" ]]; then
		#if same_sudo_post_shell_home_as_sudo_shell_home is enabled
		if [[ "$same_sudo_post_shell_home_as_sudo_shell_home" == "1" ]]; then
			#override SUDO_POST_SHELL_HOME
			SUDO_POST_SHELL_HOME="$SUDO_SHELL_HOME"
		fi
	else
		#unset SUDO_POST_SHELL_HOME so that SUDO_POST_SHELL variables are not set
		SUDO_POST_SHELL_HOME=""
	fi


	#test if bash shell executable file exists at BASH_SHELL_PATH
	#this is to ensure that bash shell is always the default shell if '--shell` and '--post-shell' options are not passed
	#and the shell is automatically validated so that it doesn't have to again in sudo_set_sudo_shell and sudo_set_sudo_post_shell
	#bash shell is also needed by the 'su --shell' command
	#sudo_run_file_type_tests_on_path label path log_file_tests_failure_errors show_stat_output_on_file_tests_failure check_if_absolute_path file_type_tests
	sudo_run_file_type_tests_on_path "BASH_SHELL_PATH" "$BASH_SHELL_PATH" 1 1 1 "frx" || return $?

	#set SU and SU_BIN_PATH
	sudo_set_su_variables || return $?

	#set required variables to be used by this script
	sudo_set_required_variables || return $?

	#set priority_dependent_variables with termux priority
	sudo_set_priority_dependent_variables "termux" || return $?

	#export variables and functions to be used by this script
	sudo_export_or_unexport_shared_variables_for_su export || return $?

	#set SU_ENV_COMMAND
	sudo_set_su_env_command || return $?



	#set SUDO_SHELL and SUDO_SHELL_BASENAME
	sudo_set_sudo_shell || return $?

	#if command_type does not equal "path"
	#command_type "path" does not use an interactive shell so no need to set these
	if [[ "$command_type" != "path" ]]; then
		#set SUDO_SHELL_RCFILE and SUDO_SHELL_RCFILE_VALUE to be sourced when SUDO_SHELL is run
		sudo_set_sudo_shell_rcfile || return $?

		#set SUDO_SHELL_HISTFILE
		sudo_set_sudo_shell_histfile || return $?
	fi

	#set SUDO_SHELL_COMMAND and SUDO_SHELL_INTERACTIVE_COMMAND command to be run
	sudo_set_sudo_shell_command || return $?



	#if SUDO_POST_SHELL_HOME is set
	if [ ! -z "$SUDO_POST_SHELL_HOME" ]; then
		#if same_sudo_post_shell_as_sudo_shell is enabled
		if [[ "$same_sudo_post_shell_as_sudo_shell" == "1" ]]; then
			#override SUDO_POST_SHELL
			SUDO_POST_SHELL="$SUDO_SHELL"
		fi

		#set SUDO_POST_SHELL and SUDO_POST_SHELL_BASENAME
		sudo_set_sudo_post_shell || return $?

		#set SUDO_POST_SHELL_RCFILE and SUDO_POST_SHELL_RCFILE_VALUE to be sourced when SUDO_POST_SHELL is run
		sudo_set_sudo_post_shell_rcfile || return $?

		#set SUDO_POST_SHELL_HISTFILE file
		sudo_set_sudo_post_shell_histfile || return $?

		#set SUDO_POST_SHELL_INTERACTIVE_COMMAND command to be run
		sudo_set_sudo_post_shell_command || return $?
	fi



	#if command_type equals "path"
	if [[ "$command_type" == "path" ]]; then
		#set SUDO_PATH_COMMAND
		sudo_set_sudo_command_path || return $?
	fi



	#set PRE_SUDO_SHELL_COMMANDS_TO_RUN
	sudo_set_pre_sudo_shell_commands_to_run || return $?

	#if SUDO_POST_SHELL_HOME is set
	if [ ! -z "$SUDO_POST_SHELL_HOME" ]; then
		#set PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN
		sudo_set_pre_sudo_post_shell_commands_to_run || return $?
	fi



	#set traps to run commands before exiting sudo
	set_sudo_traps || return $?



	#create SUDO_SHELL_HOME, SUDO_SHELL_RCFILE, SUDO_SHELL_HISTFILE and/or
	#SUDO_POST_SHELL_HOME, SUDO_POST_SHELL_RCFILE, SUDO_POST_SHELL_HISTFILE
	#and SUDO_SHELL_WORKING_DIR if missing
	#and SUDO_TEMP_DIRECTORY if required
	#android rootfs "/" partition and/or system "/system" partition may be remounted
	#as rw if they are to be used for SUDO_SHELL_HOME, SUDO_POST_SHELL_HOME or SUDO_SHELL_WORKING_DIR
	sudo_setup_sudo_shell_home_and_working_environment_wrapper
	return_value=$?
	if [ $return_value -ne 0 ]; then
		#if SUDO_TEMP_DIRECTORY_FD is set, then close it
		if [ ! -z "$SUDO_TEMP_DIRECTORY_FD" ]; then
			exec {SUDO_TEMP_DIRECTORY_FD}>&-
		fi
		return $return_value
	fi



	#set SU_RUN_COMMAND
	sudo_set_su_run_command || return $?

	#run sudo command depending on command type

	local SUDO_EXIT_CODE=0

	BASH_SHELL_COMMAND=("$BASH_SHELL_PATH" "--noprofile" "--norc")
	printf -v "BASH_SHELL_COMMAND_STRING" "%q " "${BASH_SHELL_COMMAND[@]}"

	#if command_type equals "su" or "asu"
	if [[ "$command_type" == "su" ]] || [[ "$command_type" == "asu" ]]; then

		#if SUDO_SHELL_INTERACTIVE_COMMAND is not set
		if [ ${#SUDO_SHELL_INTERACTIVE_COMMAND[@]} -eq 0 ]; then
			sudo_log_errors "SUDO_SHELL_INTERACTIVE_COMMAND is not set while running sudo $command_type command in \"sudo_run\""
			return 1
		fi

		#unexport variables not to be used by su anymore
		sudo_export_or_unexport_shared_variables_for_su unexport || return $?


		#set SUDO_COMMAND_TO_RUN to run su that will run PRE_SUDO_SHELL_COMMANDS_TO_RUN commands and then
		#start an interactive SUDO_SHELL
		SUDO_COMMAND_TO_RUN="$SU_RUN_COMMAND $PRE_SUDO_SHELL_COMMANDS_TO_RUN"
		printf -v "SUDO_SHELL_INTERACTIVE_COMMAND_STRING" "$SUDO_SHELL_INTERACTIVE_COMMAND_PRINT_FORMAT" "${SUDO_SHELL_INTERACTIVE_COMMAND[@]}"
		SUDO_COMMAND_TO_RUN+="$SUDO_SHELL_INTERACTIVE_COMMAND_STRING"

		#if SUDO_SHELL_STDIN_STRING is set
		if [ ! -z "$SUDO_SHELL_STDIN_STRING" ]; then
			#if SUDO_SHELL_BASENAME is in SUDO_SCRIPT_SHELLS_WITHOUT_PROCESS_SUBSTITUTION_SUPPORT
			if [[ " $SUDO_SCRIPT_SHELLS_WITHOUT_PROCESS_SUBSTITUTION_SUPPORT " == *" $SUDO_SHELL_BASENAME "* ]]; then
				#pass SUDO_SHELL_STDIN_STRING as stdin with a herestring to SUDO_SHELL
				SUDO_COMMAND_TO_RUN+=' <<<'"'${SUDO_SHELL_STDIN_STRING//\'/\'\\\'\'}'"
			else
				#pass SUDO_SHELL_STDIN_STRING as stdin with process substitution to SUDO_SHELL
				SUDO_COMMAND_TO_RUN+=' < <(printf "%s" '"'${SUDO_SHELL_STDIN_STRING//\'/\'\\\'\'}'"')'
			fi
		fi

		#if exec_sudo_shell is enabled, then prepend "exec"
		if [[ "$exec_sudo_shell" == "1" ]]; then
			SUDO_COMMAND_TO_RUN="exec $SUDO_COMMAND_TO_RUN"
		fi


		sudo_log_literal 2 "\n\n\nRunning sudo $command_type commmand"
		sudo_log 1 $'\n'"SUDO_COMMAND_TO_RUN=\`$SUDO_COMMAND_TO_RUN\`"

		#if dry_run_sudo is not enabled
		if [[ "$dry_run_sudo" != "1" ]]; then
			#run SUDO_COMMAND_TO_RUN
			sudo_unset_pre_su_variables
			$SUDO_COMMAND_TO_RUN
			SUDO_EXIT_CODE=$?
			sudo_set_post_su_variables
		fi


	#if command_type equals "path"
	elif [[ "$command_type" == "path" ]]; then

		#set script to run in SUDO_PATH_COMMAND_TO_RUN
		sudo_set_sudo_path_command || return $?

		#unexport variables not to be used by su anymore
		sudo_export_or_unexport_shared_variables_for_su unexport || return $?


		#set SUDO_COMMAND_TO_RUN to run su that will run PRE_SUDO_SHELL_COMMANDS_TO_RUN commands and then
		#run the SUDO_PATH_COMMAND_TO_RUN
		SUDO_COMMAND_TO_RUN="$SU_RUN_COMMAND $PRE_SUDO_SHELL_COMMANDS_TO_RUN"

		#if exec_sudo_shell is enabled, then prepend "exec"
		if [[ "$exec_sudo_shell" == "1" ]]; then
			SUDO_COMMAND_TO_RUN="exec $SUDO_COMMAND_TO_RUN"
		fi

		#pass the SUDO_PATH_FD_PATH to the BASH_SHELL as an argument
		SUDO_COMMAND_TO_RUN+="$BASH_SHELL_COMMAND_STRING \"$SUDO_PATH_FD_PATH\""


		sudo_log_literal 2 "\n\n\nRunning sudo $command_type commmand"
		sudo_log 1 $'\n'"SUDO_COMMAND_TO_RUN=\`$SUDO_COMMAND_TO_RUN\`"

		#if disable_arguments_logging is not enabled
		if [[ "$disable_arguments_logging" != "1" ]]; then
			sudo_log 1 $'\n'"SUDO_PATH_COMMAND_TO_RUN=\`$SUDO_PATH_COMMAND_TO_RUN\`"
		fi

		#if dry_run_sudo is not enabled
		if [[ "$dry_run_sudo" != "1" ]]; then
			#run SUDO_COMMAND_TO_RUN
			sudo_unset_pre_su_variables
			$SUDO_COMMAND_TO_RUN
			SUDO_EXIT_CODE=$?
			sudo_set_post_su_variables
		fi

		#if SUDO_PATH_FD_PATH is set, then close it
		if [ ! -z "$SUDO_PATH_FD_PATH" ]; then
			exec {SUDO_PATH_FD_PATH}>&-
			SUDO_PATH_FD_PATH=""
		fi


	#if command_type equals "script"
	elif [[ "$command_type" == "script" ]]; then

		#if SUDO_SHELL_COMMAND is not set
		if [ ${#SUDO_SHELL_COMMAND[@]} -eq 0 ]; then
			sudo_log_errors "SUDO_SHELL_COMMAND is not set while running sudo $command_type command in \"sudo_run\""
			return 1
		fi

		#if run_interactive_post_sudo_shell_after_running_core_script is enabled and SUDO_POST_SHELL_INTERACTIVE_COMMAND is not set
		if [[ "$run_interactive_post_sudo_shell_after_running_core_script" == "1" ]] && [ ${#SUDO_POST_SHELL_INTERACTIVE_COMMAND[@]} -eq 0 ]; then
			sudo_log_errors "SUDO_POST_SHELL_INTERACTIVE_COMMAND is not set while running sudo $command_type command in \"sudo_run\""
			return 1
		fi

		#set script to run in SUDO_SCRIPT_COMMAND_TO_RUN
		sudo_set_sudo_script_command || return $?

		#unexport variables not to be used by su anymore
		sudo_export_or_unexport_shared_variables_for_su unexport || return $?


		#set SUDO_COMMAND_TO_RUN to run su that will run the SUDO_SCRIPT_COMMAND_TO_RUN
		SUDO_COMMAND_TO_RUN="$SU_RUN_COMMAND "

		#if exec_sudo_shell is enabled, then prepend "exec"
		if [[ "$exec_sudo_shell" == "1" ]]; then
			SUDO_COMMAND_TO_RUN="exec $SUDO_COMMAND_TO_RUN"
		fi

		#pass the SUDO_SCRIPT_FD_PATH to the BASH_SHELL as an argument
		SUDO_COMMAND_TO_RUN+="$BASH_SHELL_COMMAND_STRING \"$SUDO_SCRIPT_FD_PATH\""


		sudo_log_literal 2 "\n\n\nRunning sudo $command_type commmand"
		sudo_log 1 $'\n'"SUDO_COMMAND_TO_RUN=\`$SUDO_COMMAND_TO_RUN\`"

		#if disable_arguments_logging is not enabled
		if [[ "$disable_arguments_logging" != "1" ]]; then
			sudo_log 1 $'\n'"SUDO_SCRIPT_COMMAND_TO_RUN=\`$SUDO_SCRIPT_COMMAND_TO_RUN\`"
		fi

		#if dry_run_sudo is not enabled
		if [[ "$dry_run_sudo" != "1" ]]; then
			#run SUDO_COMMAND_TO_RUN
			sudo_unset_pre_su_variables
			$SUDO_COMMAND_TO_RUN
			SUDO_EXIT_CODE=$?
			sudo_set_post_su_variables
		fi

		#if SUDO_SCRIPT_FD is set, then close it
		if [ ! -z "$SUDO_SCRIPT_FD" ]; then
			exec {SUDO_SCRIPT_FD}>&-
			SUDO_SCRIPT_FD=""
		fi


	else
		sudo_log_errors "command_type \"$command_type\" not handled while running sudo command in \"sudo_run\""
		return 1
	fi

	#if dry_run_sudo is not enabled
	if [[ "$dry_run_sudo" != "1" ]]; then
		sudo_log 2 $'\n'"SUDO_EXIT_CODE=\"$SUDO_EXIT_CODE\""
	fi

	#if sudo is being run in an interactive shell, then reset terminal
	if [[ $- == *i* ]]; then
		stty sane &>/dev/null
	fi

	return $SUDO_EXIT_CODE

}

#sudo_run_pre_exit_commands exit_code
sudo_run_pre_exit_commands() {

	local return_value

	local exit_code="$1"

	#if hold_after_sudo is enabled
	if [[ "$hold_after_sudo" == "1" ]]; then
		#if hold_only_on_failure is not enabled or (hold_only_on_failure is enabled and exit_code does not equal 0)
		if [[ "$hold_only_on_failure" != "1" ]] || ([[ "$hold_only_on_failure" == "1" ]] && [[ "$exit_code" != "0" ]]); then
			#if stdin and stdout are available
			if [ -t 0 ] && [ -t 1 ]; then
				#if HOLD_STRING_AFTER_SUDO is set
				if [ ! -z "$HOLD_STRING_AFTER_SUDO" ]; then
					local valid_alphanumeric_and_punct_string_regex='^[[:alnum:][:punct:]]+$'

					if [[ "$HOLD_STRING_AFTER_SUDO" =~ $valid_alphanumeric_and_punct_string_regex ]]; then
						#read from stdin until HOLD_STRING_AFTER_SUDO is correctly entered
						#read should never timeout because of TMOUT=0
						local exit_while=0
						while [[ $exit_while != "1" ]]; do
							TMOUT=0 read -p "Enter \"$HOLD_STRING_AFTER_SUDO\" to exit:"$'\n' input
							if [ $? -ne 0 ] || [[ "$input" == "$HOLD_STRING_AFTER_SUDO" ]]; then
								exit_while=1
							fi
						done
					else
						sudo_log_errors "HOLD_STRING_AFTER_SUDO \"$HOLD_STRING_AFTER_SUDO\" is invalid. It can only contain alphanumeric and punctuation characters"
						return 1
					fi

				#else if only '--hold' was passed
				else
					#read any character from stdin in silent mode
					#read should never timeout because of TMOUT=0
					TMOUT=0 read -s -n 1
				fi
			fi
		fi
	fi

	#if sleep_after_sudo is enabled
	if [[ "$sleep_after_sudo" == "1" ]]; then
		#if sleep_only_on_failure is not enabled or (sleep_only_on_failure is enabled and exit_code does not equal 0)
		if [[ "$sleep_only_on_failure" != "1" ]] || ([[ "$sleep_only_on_failure" == "1" ]] && [[ "$exit_code" != "0" ]]); then
			local valid_floating_point_number_regex='^[0-9]+(\.[0-9]+)?$'

			if [[ "$SLEEP_TIME_AFTER_SUDO" =~ $valid_floating_point_number_regex ]]; then
				#sleep for SLEEP_TIME_AFTER_SUDO seconds
				sleep "$SLEEP_TIME_AFTER_SUDO"
			else
				sudo_log_errors "SLEEP_TIME_AFTER_SUDO \"$SLEEP_TIME_AFTER_SUDO\" is not a valid floating point number"
				return 1
			fi
		fi
	fi

	return 0

}

sudo_set_su_variables() {

	local return_value

	sudo_log_literal 2 "\nRunning sudo_set_su_variables"

	SU=""
	SU_BIN_PATH=""

	local -a su_search_paths=("/su/bin/su")

	#if "/sbin" is accessible
	if [ -x "/sbin" ]; then
		su_search_paths+=("/sbin/su" "/sbin/bin/su")
	fi

	su_search_paths+=("/system/xbin/su" "/system/bin/su" "/su/xbin/su" "/magisk/.core/bin/su")

	local su
	local su_found=0
	local su_help=""

	for su in "${su_search_paths[@]}"; do
		if [ -x "$su" ]; then
			sudo_log 2 "A su binary found at \"$su\""
			su_found=1

			sudo_unset_pre_su_variables
			su_help="$($su --help < /dev/null)"
			sudo_set_post_su_variables

			#if '--shell' option is not supported, then continue searching
			if [[ "$su_help" != *"--shell"* ]]; then
				sudo_log 2 "The su binary found does not support '--shell' option, continuing search"
				continue
			#if '--preserve-environment' option is not supported, then continue searching
			elif [[ "$su_help" != *"--preserve-environment"* ]]; then
				sudo_log 2 "The su binary found does not support '--preserve-environment' option, continuing search"
				continue
			#if '--mount-master' option is not supported, then continue searching
			elif [[ "$su_help" != *"--mount-master"* ]]; then
				sudo_log 2 "The su binary found does not support '--mount-master' option, continuing search"
				continue
			#else use the su
			else
				SU="$su"
				SU_BIN_PATH="${su%/su}"
				break
			fi

			sudo_log 2 ""
		fi
	done

	#if SU is not set
	if [ -z "$SU" ]; then
		#if su_found is not set to "1"
		if [[ "$su_found" != "1" ]]; then
			sudo_log_errors "No 'su' binary found"
		else
			sudo_log_errors "No 'su' binary found that supports the '--shell', '--preserve-environment' and '--mount-master' options"
		fi

		sudo_log_errors "sudo requires a 'su' binary that supports the '--shell', '--preserve-environment' and '--mount-master' options"
		return 1
	fi

	sudo_log 2 "SU=\"$SU\""
	sudo_log 2 "SU_BIN_PATH=\"$SU_BIN_PATH\""

	return 0

}

#set the su command that will be used to set up the sudo environment
sudo_set_su_env_command() {

	local return_value

	sudo_log_literal 2 "\nRunning sudo_set_su_env_command"

	#set SU_ENV_COMMAND_VARIABLES_TO_EXPORT
	sudo_set_su_env_command_variables_to_export || return $?

	SU_ENV_COMMAND="$SU"

	#if rootfs_partition_dependent_paths or system_partition_dependent_paths is set
	if [ ! -z "$rootfs_partition_dependent_paths" ] || [ ! -z "$system_partition_dependent_paths" ]; then
		#if SUDO_SU_ENV_ADDITIONAL_COMMAND_OPTIONS does not start with the '--mount-master' or '-mm' command option, then
		#add the '--mount-master' option to SU_ENV_COMMAND at the start as required by su
		if [[ ! "${SUDO_SU_ENV_ADDITIONAL_COMMAND_OPTIONS[*]}" =~ $valid_su_mount_master_option_prefixed_string  ]]; then
			SU_ENV_COMMAND+=" --mount-master"
		fi
	fi

	#if SUDO_SU_ENV_ADDITIONAL_COMMAND_OPTIONS is set, then add the options to SU_ENV_COMMAND
	if [ ${#SUDO_SU_ENV_ADDITIONAL_COMMAND_OPTIONS[@]} -ne 0 ]; then
		printf -v "SUDO_SU_ENV_ADDITIONAL_COMMAND_OPTIONS_STRING" "%q " "${SUDO_SU_ENV_ADDITIONAL_COMMAND_OPTIONS[@]}"
		SU_ENV_COMMAND+=" $SUDO_SU_ENV_ADDITIONAL_COMMAND_OPTIONS_STRING"
		SU_ENV_COMMAND="${SU_ENV_COMMAND% }" #remove trailing space
	fi

	#We rely on termux to set up most of the environment since it will be dependent on android os and device
	#hence '--preserve-environment' is required
	#we also source the sudo script in some SU_ENV_COMMAND commands to define its functions
	#so that only the parent function is called within a new su shell instead of
	#calling a new su shell for every root command that needs to be run inside
	#the child functions
	#this has drastic performance improvements in some cases where multiple root
	#commands need to be run since creating a new su shell for each command has too
	#much overhead
	SU_ENV_COMMAND+=" --preserve-environment --shell $BASH_SHELL_PATH -c $SU_ENV_COMMAND_VARIABLES_TO_EXPORT "

	sudo_log 2 "SU_ENV_COMMAND=\`$SU_ENV_COMMAND\`"

	return 0

}

#set the su command that will be used to run the sudo command_type command
sudo_set_su_run_command() {

	local return_value

	sudo_log_literal 2 "\nRunning sudo_set_su_run_command"

	SU_RUN_COMMAND="$SU"

	#if rootfs_partition_dependent_paths or system_partition_dependent_paths is set
	if [ ! -z "$rootfs_partition_dependent_paths" ] || [ ! -z "$system_partition_dependent_paths" ]; then
		#if SUDO_SU_RUN_ADDITIONAL_COMMAND_OPTIONS does not start with the '--mount-master' or '-mm' command option, then
		#add the '--mount-master' option to SU_RUN_COMMAND at the start as required by su
		if [[ ! "${SUDO_SU_RUN_ADDITIONAL_COMMAND_OPTIONS[*]}" =~ $valid_su_mount_master_option_prefixed_string  ]]; then
			SU_RUN_COMMAND+=" --mount-master"
		fi
	fi

	#if SUDO_SU_RUN_ADDITIONAL_COMMAND_OPTIONS is set, then add the options to SU_RUN_COMMAND
	if [ ${#SUDO_SU_RUN_ADDITIONAL_COMMAND_OPTIONS[@]} -ne 0 ]; then
		printf -v "SUDO_SU_RUN_ADDITIONAL_COMMAND_OPTIONS_STRING" "%q " "${SUDO_SU_RUN_ADDITIONAL_COMMAND_OPTIONS[@]}"
		SU_RUN_COMMAND+=" $SUDO_SU_RUN_ADDITIONAL_COMMAND_OPTIONS_STRING"
		SU_RUN_COMMAND="${SU_RUN_COMMAND% }" #remove trailing space
	fi

	#if disable_preserve_environment_for_su is not enabled, then use the option
	if [[ "$disable_preserve_environment_for_su" != "1" ]]; then
		SU_RUN_COMMAND+=" --preserve-environment"
	fi

	SU_RUN_COMMAND+=" --shell $BASH_SHELL_PATH -c"

	sudo_log 2 "SU_RUN_COMMAND=\`$SU_RUN_COMMAND\`"

	return 0

}

sudo_set_required_variables() {

	local return_value

	#do not modify unless you known what you are doing

	sudo_log_literal 2 "\nRunning sudo_set_required_variables"

	#set LD_PRELOAD
	export LD_PRELOAD="$TERMUX_PREFIX/lib/libtermux-exec.so"

	SUDO_LD_PRELOAD="$LD_PRELOAD"

	local remove_duplicates_in_path_variable=0
	local remove_duplicates_in_ld_library_path_variable=0

	#store PATH and LD_LIBRARY_PATH
	OLD_PATH="$PATH"
	OLD_LD_LIBRARY_PATH="$LD_LIBRARY_PATH"


	#set PATH
	PATH="$TERMUX_PATH:$SYS_XBIN:$SYS_BIN"

	sudo_log 2 "PATH=\"$PATH\""

	#find machine arch
	ARCH="$(dpkg --print-architecture)"
	return_value=$?
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failed to find machine arch"
		return $return_value
	fi

	sudo_log 2 "ARCH=\"$ARCH\""

	#set LD_LIBRARY_PATH
	#if ARCH is 64 bit
	if [[ "$ARCH" == *64 ]]; then
		LD_LIBRARY_PATH="$TERMUX_LD_LIBRARY_PATH:/system/lib64:/system/lib"
	else
		LD_LIBRARY_PATH="$TERMUX_LD_LIBRARY_PATH:/system/lib"
	fi

	SUDO_LD_LIBRARY_PATH="$LD_LIBRARY_PATH"

	sudo_log 2 "LD_LIBRARY_PATH=\"$LD_LIBRARY_PATH\""

	#set ANDROID_PATH

	#if SU_BIN_PATH is not empty, then append it to ANDROID_PATH
	if [ ! -z "$SU_BIN_PATH" ]; then
		ANDROID_PATH+=":$SU_BIN_PATH"
	fi

	#if ANDROID_OTHER_BIN_PATHS is not empty, then append it to ANDROID_PATH
	if [ ! -z "$ANDROID_OTHER_BIN_PATHS" ]; then
		ANDROID_PATH+=":$ANDROID_OTHER_BIN_PATHS"
	fi

	#set TERMUX_PRIORITY_PATH with priority to termux binary and executable paths
	TERMUX_PRIORITY_PATH="$TERMUX_PATH:$ANDROID_PATH"

	#set ANDROID_PRIORITY_PATH with priority to android binary and executable paths
	ANDROID_PRIORITY_PATH="$ANDROID_PATH:$TERMUX_PATH"

	#if export_all_existing_paths_in_path_variable is enabled and OLD_PATH is not empty, then append it to PATH variables
	if [[ "$export_all_existing_paths_in_path_variable" == "1" ]] && [ ! -z "$OLD_PATH" ]; then
		TERMUX_PRIORITY_PATH+=":$OLD_PATH"
		ANDROID_PRIORITY_PATH+=":$OLD_PATH"
		remove_duplicates_in_path_variable=1
	fi

	#if ADDITIONAL_PATHS_TO_EXPORT is not empty, then append it to PATH variables
	if [ ! -z "$ADDITIONAL_PATHS_TO_EXPORT" ]; then
		TERMUX_PRIORITY_PATH+=":$ADDITIONAL_PATHS_TO_EXPORT"
		ANDROID_PRIORITY_PATH+=":$ADDITIONAL_PATHS_TO_EXPORT"
		remove_duplicates_in_path_variable=1
	fi

	#remove_duplicates_in_path_variable is only enabled if custom paths are added to the PATH variables
	#this will reduce execution time since an external call to awk with a subshell will not be made
	#default paths set must not have any duplicates

	#remove duplicates from TERMUX_PRIORITY_PATH and check if it is valid and can be used as the PATH variable
	sudo_parse_and_validate_path_variable "TERMUX_PRIORITY_PATH" "TERMUX_PRIORITY_PATH" "$TERMUX_PRIORITY_PATH" "$remove_duplicates_in_path_variable"
	return_value=$?
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failed to parse and validate \"TERMUX_PRIORITY_PATH\""
		return $return_value
	fi

	#remove duplicates from ANDROID_PRIORITY_PATH and check if it is valid and can be used as the PATH variable
	sudo_parse_and_validate_path_variable "ANDROID_PRIORITY_PATH" "ANDROID_PRIORITY_PATH" "$ANDROID_PRIORITY_PATH" "$remove_duplicates_in_path_variable"
	return_value=$?
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failed to parse and validate \"ANDROID_PRIORITY_PATH\""
		return $return_value
	fi


	#set LD_LIBRARY_PATH_TO_EXPORT
	#if ARCH is 64 bit
	if [[ "$ARCH" == *64 ]]; then
		ANDROID_LD_LIBRARY_PATH="/system/lib64:/system/lib"
	#if ARCH is 32 bit
	else
		ANDROID_LD_LIBRARY_PATH="/system/lib"
	fi

	#set TERMUX_PRIORITY_LD_LIBRARY_PATH with priority to termux library paths
	TERMUX_PRIORITY_LD_LIBRARY_PATH="$TERMUX_LD_LIBRARY_PATH:$ANDROID_LD_LIBRARY_PATH"

	#set ANDROID_PRIORITY_LD_LIBRARY_PATH with priority to android library paths
	ANDROID_PRIORITY_LD_LIBRARY_PATH="$ANDROID_LD_LIBRARY_PATH:$TERMUX_LD_LIBRARY_PATH"

	#if export_all_existing_paths_in_ld_library_path_variable is enabled and OLD_LD_LIBRARY_PATH is not empty, then append it to LD_LIBRARY_PATH variables
	if [[ "$export_all_existing_paths_in_ld_library_path_variable" == "1" ]] && [ ! -z "$OLD_LD_LIBRARY_PATH" ]; then
		TERMUX_PRIORITY_LD_LIBRARY_PATH+=":$OLD_LD_LIBRARY_PATH"
		ANDROID_PRIORITY_LD_LIBRARY_PATH+=":$OLD_LD_LIBRARY_PATH"
		remove_duplicates_in_ld_library_path_variable=1
	fi

	#if ADDITIONAL_LD_LIBRARY_PATHS_TO_EXPORT is not empty, then append it to LD_LIBRARY_PATH variables
	if [ ! -z "$ADDITIONAL_LD_LIBRARY_PATHS_TO_EXPORT" ]; then
		TERMUX_PRIORITY_LD_LIBRARY_PATH+=":$ADDITIONAL_LD_LIBRARY_PATHS_TO_EXPORT"
		ANDROID_PRIORITY_LD_LIBRARY_PATH+=":$ADDITIONAL_LD_LIBRARY_PATHS_TO_EXPORT"
		remove_duplicates_in_ld_library_path_variable=1
	fi

	#remove_duplicates_in_path_variable is only enabled if custom paths are added to the LD_LIBRARY_PATH variables
	#this will reduce execution time since an external call to awk with a subshell will not be made
	#default paths set must not have any duplicates

	#remove duplicates from TERMUX_PRIORITY_LD_LIBRARY_PATH and check if it is valid and can be used as the LD_LIBRARY_PATH variable
	sudo_parse_and_validate_path_variable "TERMUX_PRIORITY_LD_LIBRARY_PATH" "TERMUX_PRIORITY_LD_LIBRARY_PATH" "$TERMUX_PRIORITY_LD_LIBRARY_PATH" "$remove_duplicates_in_ld_library_path_variable"
	return_value=$?
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failed to parse and validate \"TERMUX_PRIORITY_LD_LIBRARY_PATH\""
		return $return_value
	fi

	#remove duplicates from ANDROID_PRIORITY_LD_LIBRARY_PATH and check if it is valid and can be used as the LD_LIBRARY_PATH variable
	sudo_parse_and_validate_path_variable "ANDROID_PRIORITY_LD_LIBRARY_PATH" "ANDROID_PRIORITY_LD_LIBRARY_PATH" "$ANDROID_PRIORITY_LD_LIBRARY_PATH" "$remove_duplicates_in_ld_library_path_variable"
	return_value=$?
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failed to parse and validate \"ANDROID_PRIORITY_LD_LIBRARY_PATH\""
		return $return_value
	fi


	#set TERMUX_PRIORITY_LD_PRELOAD_COMMAND to set LD_PRELOAD to libtermux-exec.so
	TERMUX_PRIORITY_LD_PRELOAD_COMMAND="export LD_PRELOAD='$TERMUX_PREFIX/lib/libtermux-exec.so';"

	#set ANDROID_PRIORITY_LD_PRELOAD_COMMAND to unset LD_PRELOAD
	ANDROID_PRIORITY_LD_PRELOAD_COMMAND="unset LD_PRELOAD;"



	#set SUDO_SHELL_HOME
	sudo_trim_trailing_newlines "SUDO_SHELL_HOME" "$SUDO_SHELL_HOME"

	#replace "$PREFIX/" or "~/" prefix with termux absolute paths in SUDO_SHELL_HOME
	#canonicalize_path is only enabled if a custom path was passed for SUDO_SHELL_HOME by the user
	#this will reduce execution time since an external call to readlink with a subshell will not be made
	sudo_expand_termux_path "SUDO_SHELL_HOME" "SUDO_SHELL_HOME" "$SUDO_SHELL_HOME" "$TERMUX_PREFIX" "$TERMUX_HOME" "$custom_sudo_shell_home_set"
	return_value=$?
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failed to expand SUDO_SHELL_HOME \"$SUDO_SHELL_HOME\""
		return $return_value
	fi

	#if SUDO_SHELL_HOME is not a valid absolute path
	if [[ ! "$SUDO_SHELL_HOME" =~ $valid_absolute_path_regex ]]; then
		sudo_log_errors "The SUDO_SHELL_HOME \"$SUDO_SHELL_HOME\" is not a valid absolute path"
		return 1
	fi

	sudo_log 2 "SUDO_SHELL_HOME=\"$SUDO_SHELL_HOME\""

	#find the parent directory of the SUDO_SHELL_HOME
	SUDO_SHELL_HOME_BASENAME="${SUDO_SHELL_HOME##*/}" #strip longest match of */ from start
	SUDO_SHELL_HOME_PARENT_DIR="${SUDO_SHELL_HOME:0:${#SUDO_SHELL_HOME} - ${#SUDO_SHELL_HOME_BASENAME}}" #substring from 0 to position of basename
	case $SUDO_SHELL_HOME_PARENT_DIR in *[!/]*/) SUDO_SHELL_HOME_PARENT_DIR=${SUDO_SHELL_HOME_PARENT_DIR%"${SUDO_SHELL_HOME_PARENT_DIR##*[!/]}"};; *[/]) SUDO_SHELL_HOME_PARENT_DIR="/";; esac #remove trailing slashes if not root

	sudo_log 2 "SUDO_SHELL_HOME_PARENT_DIR=\"$SUDO_SHELL_HOME_PARENT_DIR\""


	#use SUDO_SHELL_HOME as SUDO_TEMP_DIRECTORY_PARENT_DIRECTORY
	SUDO_TEMP_DIRECTORY_PARENT_DIRECTORY="$SUDO_SHELL_HOME"



	#if SUDO_POST_SHELL_HOME is set
	if [ ! -z "$SUDO_POST_SHELL_HOME" ]; then
		#set SUDO_POST_SHELL_HOME
		sudo_trim_trailing_newlines "SUDO_POST_SHELL_HOME" "$SUDO_POST_SHELL_HOME"

		#replace "$PREFIX/" or "~/" prefix with termux absolute paths in SUDO_POST_SHELL_HOME
		#canonicalize_path is only enabled if a custom path was passed for SUDO_POST_SHELL_HOME by the user
		#this will reduce execution time since an external call to readlink with a subshell will not be made
		sudo_expand_termux_path "SUDO_POST_SHELL_HOME" "SUDO_POST_SHELL_HOME" "$SUDO_POST_SHELL_HOME" "$TERMUX_PREFIX" "$TERMUX_HOME" "$custom_sudo_post_shell_home_set"
		return_value=$?
		if [ $return_value -ne 0 ]; then
			sudo_log_errors "Failed to expand \"SUDO_POST_SHELL_HOME\""
			return $return_value
		fi

		#if SUDO_POST_SHELL_HOME is not a valid absolute path
		if [[ ! "$SUDO_POST_SHELL_HOME" =~ $valid_absolute_path_regex ]]; then
			sudo_log_errors "The SUDO_POST_SHELL_HOME \"$SUDO_POST_SHELL_HOME\" is not a valid absolute path"
			return 1
		fi

		sudo_log 2 "SUDO_POST_SHELL_HOME=\"$SUDO_POST_SHELL_HOME\""

		#find the parent directory of the SUDO_POST_SHELL_HOME
		SUDO_POST_SHELL_HOME_BASENAME="${SUDO_POST_SHELL_HOME##*/}" #strip longest match of */ from start
		SUDO_POST_SHELL_HOME_PARENT_DIR="${SUDO_POST_SHELL_HOME:0:${#SUDO_POST_SHELL_HOME} - ${#SUDO_POST_SHELL_HOME_BASENAME}}" #substring from 0 to position of basename
		case $SUDO_POST_SHELL_HOME_PARENT_DIR in *[!/]*/) SUDO_POST_SHELL_HOME_PARENT_DIR=${SUDO_POST_SHELL_HOME_PARENT_DIR%"${SUDO_POST_SHELL_HOME_PARENT_DIR##*[!/]}"};; *[/]) SUDO_POST_SHELL_HOME_PARENT_DIR="/";; esac #remove trailing slashes if not root

		sudo_log 2 "SUDO_POST_SHELL_HOME_PARENT_DIR=\"$SUDO_POST_SHELL_HOME_PARENT_DIR\""
	fi



	#if SUDO_SHELL_WORKING_DIR is set
	if [ ! -z "$SUDO_SHELL_WORKING_DIR" ]; then
		#set SUDO_SHELL_WORKING_DIR
		sudo_set_sudo_shell_working_dir || return $?
	fi



	#create TMPDIR if missing
	sudo_setup_termux_tmp_dir || return $?



	#set rootfs_partition_dependent_paths and system_partition_dependent_paths
	#which are required by sudo_set_su_env_command and sudo_set_su_run_command functions to add '--mount-master option'
	#to SU_ENV_COMMAND and SU_RUN_COMMAND if required and then by the sudo_remount_partitions_for_sudo_shell_homes function
	#using parent directories for rootfs checks since some directories in root like /mnt may
	#require rootfs to be mounted as rw to be writeable

	rootfs_partition_dependent_paths=""
	system_partition_dependent_paths=""

	#if SUDO_SHELL_HOME is in system "/system" partition
	if [[ "$SUDO_SHELL_HOME" =~ $valid_path_in_system_partition_regex ]]; then
		system_partition_dependent_paths+=" SUDO_SHELL_HOME \"$SUDO_SHELL_HOME\""
	#if SUDO_SHELL_HOME_PARENT_DIR is in rootfs "/" partition
	elif [[ "$SUDO_SHELL_HOME_PARENT_DIR" =~ $valid_path_in_rootfs_partition_regex ]]; then
		rootfs_partition_dependent_paths+=" SUDO_SHELL_HOME \"$SUDO_SHELL_HOME\""
	fi

	#if SUDO_POST_SHELL_HOME is in system "/system" partition
	if [[ "$SUDO_POST_SHELL_HOME" =~ $valid_path_in_system_partition_regex ]]; then
		system_partition_dependent_paths+=" SUDO_POST_SHELL_HOME \"$SUDO_POST_SHELL_HOME\""
	#if SUDO_POST_SHELL_HOME_PARENT_DIR is in rootfs "/" partition
	elif [[ "$SUDO_POST_SHELL_HOME_PARENT_DIR" =~ $valid_path_in_rootfs_partition_regex ]]; then
		rootfs_partition_dependent_paths+=" SUDO_POST_SHELL_HOME \"$SUDO_POST_SHELL_HOME\""
	fi

	#if SUDO_SHELL_WORKING_DIR is in system "/system" partition
	if [[ "$SUDO_SHELL_WORKING_DIR" =~ $valid_path_in_system_partition_regex ]]; then
		system_partition_dependent_paths+=" SUDO_SHELL_WORKING_DIR \"$SUDO_SHELL_WORKING_DIR\""
	#if SUDO_SHELL_WORKING_DIR_PARENT_DIR is in rootfs "/" partition
	elif [[ "$SUDO_SHELL_WORKING_DIR_PARENT_DIR" =~ $valid_path_in_rootfs_partition_regex ]]; then
		rootfs_partition_dependent_paths+=" SUDO_SHELL_WORKING_DIR \"$SUDO_SHELL_WORKING_DIR\""
	fi

	#if rootfs_partition_dependent_paths or system_partition_dependent_paths is set
	if [ ! -z "$rootfs_partition_dependent_paths" ] || [ ! -z "$system_partition_dependent_paths" ]; then
		#find android sdk/os version
		ANDROID_SDK_VERSION="$(getprop "ro.build.version.sdk")"
		return_value=$?
		if [ $return_value -ne 0 ] || [[ ! "$ANDROID_SDK_VERSION" =~ $valid_number_regex ]]; then
			sudo_log_errors "Failure while finding \"ro.build.version.sdk\" property"
			sudo_log_errors "ANDROID_SDK_VERSION = \"$ANDROID_SDK_VERSION\""
			if [ $return_value -eq 0 ]; then
				return_value=1
			fi
			return $return_value
		fi

		sudo_log 2 "ANDROID_SDK_VERSION=\"$ANDROID_SDK_VERSION\""

		# If android >= 10
		if [ "$ANDROID_SDK_VERSION" -ge 29 ]; then
			[ ! -z "$rootfs_partition_dependent_paths" ] && sudo_log_errors "The rootfs \"/\" partition cannot be mounted as rw to be used for$rootfs_partition_dependent_paths since in android >= 10 the rootfs partition is likely a read-only system-as-root SAR partition"
			[ ! -z "$system_partition_dependent_paths" ] && sudo_log_errors "The system \"/system\" partition cannot be mounted as rw to be used for$system_partition_dependent_paths since in android >= 10 the system partition is an ext4 dedup filesystem"
			return 1
		fi
	fi

	return 0

}

#function that should be called before running su commands
#this will unset variable so that some su binaries like the ones provided by magisk run successfully
sudo_unset_pre_su_variables() {
	unset LD_PRELOAD
	unset LD_LIBRARY_PATH
}

#function that should be called after running su commands
#this will reset variable previously unset by sudo_unset_pre_su_variables so that sudo script commands run successfully
sudo_set_post_su_variables() {
	LD_PRELOAD="$SUDO_LD_PRELOAD"
	LD_LIBRARY_PATH="$SUDO_LD_LIBRARY_PATH"
}

#set variables to export with priority to termux or android bin and library paths
#sudo_set_priority_dependent_variables termux|android
sudo_set_priority_dependent_variables() {

	local return_value

	#if parameter count is not 1
	if [ $# -ne 1 ]; then
		sudo_log_errors "Invalid parameter count to \"sudo_set_priority_dependent_variables\""
		return 1
	fi

	local priority="$1"

	if [[ "$priority" != "termux" ]] && [[ "$priority" != "android" ]]; then
		sudo_log_errors "priority \"$priority\" passed to \"sudo_set_priority_dependent_variables\" does not equal \"termux\" or \"android\""
		return 1
	fi

	#if priority to the previous call to this function was the same, then just return
	if [[ "$priority" == "$previous_priority_dependent_variables_priortiy" ]]; then
		return 0
	fi

	sudo_log_literal 2 "\nRunning sudo_set_priority_dependent_variables with priority \"$priority\""

	#set PATH_TO_EXPORT
	#if priority equals "termux" then PATH_TO_EXPORT should be set to TERMUX_PRIORITY_PATH
	if [[ "$priority" == "termux" ]]; then
		PATH_TO_EXPORT="$TERMUX_PRIORITY_PATH"
	#if priority equals "android" then PATH_TO_EXPORT should be set to ANDROID_PRIORITY_PATH
	else
		PATH_TO_EXPORT="$ANDROID_PRIORITY_PATH"
	fi

	sudo_log 2 "PATH_TO_EXPORT=\"$PATH_TO_EXPORT\""


	#if priority equals "termux" then LD_LIBRARY_PATH_TO_EXPORT should be set to TERMUX_PRIORITY_LD_LIBRARY_PATH
	if [[ "$priority" == "termux" ]]; then
		LD_LIBRARY_PATH_TO_EXPORT="$TERMUX_PRIORITY_LD_LIBRARY_PATH"
	#if priority equals "android" then LD_LIBRARY_PATH_TO_EXPORT should be set to ANDROID_PRIORITY_LD_LIBRARY_PATH
	else
		LD_LIBRARY_PATH_TO_EXPORT="$ANDROID_PRIORITY_LD_LIBRARY_PATH"
	fi

	sudo_log 2 "LD_LIBRARY_PATH_TO_EXPORT=\"$LD_LIBRARY_PATH_TO_EXPORT\""


	#if priority equals "termux" then LD_PRELOAD_COMMAND should be set to TERMUX_PRIORITY_LD_PRELOAD_COMMAND
	if [[ "$priority" == "termux" ]]; then
		LD_PRELOAD_COMMAND="$TERMUX_PRIORITY_LD_PRELOAD_COMMAND"
	#if priority equals "android" then LD_PRELOAD_COMMAND should be set to ANDROID_PRIORITY_LD_PRELOAD_COMMAND
	else
		LD_PRELOAD_COMMAND="$ANDROID_PRIORITY_LD_PRELOAD_COMMAND"
	fi

	sudo_log 2 "LD_PRELOAD_COMMAND=\"$LD_PRELOAD_COMMAND\""


	previous_priority_dependent_variables_priortiy="$priority"

	return 0

}

#the function is used to export variables so that they can be used from within the SU_ENV_COMMAND su bash shell
#the variables must be unexported after the sudo environment has been setup up
#and only the command_type SU_RUN_COMMAND su needs to be run
#the command_type su shell should not have the variables of the sudo script in its environment
#sudo_export_or_unexport_shared_variables_for_su export|unexport
sudo_export_or_unexport_shared_variables_for_su() {

	local return_value

	#if parameter count is not 1
	if [ $# -ne 1 ]; then
		sudo_log_errors "Invalid parameter count to \"sudo_export_or_unexport_shared_variables_for_su\""
		return 1
	fi

	local command="$1"

	if [[ "$command" != "export" ]] && [[ "$command" != "unexport" ]]; then
		sudo_log_errors "command \"$command\" passed to \"sudo_export_or_unexport_shared_variables_for_su\" does not equal \"export\" or \"unexport\""
		return 1
	fi

	#if command equals "unexport"
	if [[ "$command" == "unexport" ]]; then
		command="export -n"
	fi

	$command sudo_verbose_level

	if [ ! -z "$sudo_start_time" ]; then
		$command sudo_start_time
	fi

	return 0

}

sudo_set_su_env_command_variables_to_export() {

	local return_value

	#set SU_ENV_COMMAND_VARIABLES_TO_EXPORT
	SU_ENV_COMMAND_VARIABLES_TO_EXPORT="export PATH='${PATH_TO_EXPORT//\'/\'\\\'\'}'; export LD_LIBRARY_PATH='${LD_LIBRARY_PATH_TO_EXPORT//\'/\'\\\'\'}'; export HOME='${SUDO_SHELL_HOME//\'/\'\\\'\'}'; export LANG='${LANG//\'/\'\\\'\'}'; $LD_PRELOAD_COMMAND"

	return 0

}

sudo_set_pre_sudo_shell_commands_to_run() {

	local return_value

	sudo_log_literal 2 "\nRunning sudo_set_pre_sudo_shell_commands_to_run"

	local priority

	#if command_type equals "asu"
	if [[ "$command_type" == "asu" ]]; then
		#set PRE_SUDO_SHELL_COMMANDS_TO_RUN with priority to android bin and library paths
		sudo_log 2 "Setting PRE_SUDO_SHELL_COMMANDS_TO_RUN with priority to android bin and library paths since command_type is \"asu\""
		priority="android"
	#if command_type equals "path" and (SUDO_PATH_COMMAND is in /system partition or force_set_priority_to_android_paths is enabled)
	elif [[ "$command_type" == "path" ]] && ([[ "$SUDO_PATH_COMMAND" =~ $valid_path_in_system_partition_regex ]] || [[ "$force_set_priority_to_android_paths" == "1" ]]); then
		#set PRE_SUDO_SHELL_COMMANDS_TO_RUN with priority to android bin and library paths
		sudo_log 2 "Setting PRE_SUDO_SHELL_COMMANDS_TO_RUN with priority to android bin and library paths since command_type is \"path\" and SUDO_PATH_COMMAND is in \"/system\" partition or force_set_priority_to_android_paths is enabled"
		priority="android"
	else
		#set PRE_SUDO_SHELL_COMMANDS_TO_RUN with priority to termux bin and library paths
		sudo_log 2 "Setting PRE_SUDO_SHELL_COMMANDS_TO_RUN with priority to termux bin and library paths"
		priority="termux"
	fi

	#set priority_dependent_variables with new priority if needed
	sudo_set_priority_dependent_variables "$priority" || return $?

	#set PRE_SUDO_SHELL_COMMANDS_TO_RUN
	#set variables that need to be exported when running the sudo shell
	PRE_SUDO_SHELL_COMMANDS_TO_RUN=""
	PRE_SUDO_SHELL_COMMANDS_TO_RUN+="export TERMUX_PRIORITY_PATH='${TERMUX_PRIORITY_PATH//\'/\'\\\'\'}';"$'\n'
	PRE_SUDO_SHELL_COMMANDS_TO_RUN+="export TERMUX_PRIORITY_LD_LIBRARY_PATH='${TERMUX_PRIORITY_LD_LIBRARY_PATH//\'/\'\\\'\'}';"$'\n'
	PRE_SUDO_SHELL_COMMANDS_TO_RUN+="export ANDROID_PRIORITY_PATH='${ANDROID_PRIORITY_PATH//\'/\'\\\'\'}';"$'\n'
	PRE_SUDO_SHELL_COMMANDS_TO_RUN+="export ANDROID_PRIORITY_LD_LIBRARY_PATH='${ANDROID_PRIORITY_LD_LIBRARY_PATH//\'/\'\\\'\'}';"$'\n'
	PRE_SUDO_SHELL_COMMANDS_TO_RUN+="export PATH='${PATH_TO_EXPORT//\'/\'\\\'\'}';"$'\n'
	PRE_SUDO_SHELL_COMMANDS_TO_RUN+="export LD_LIBRARY_PATH='${LD_LIBRARY_PATH_TO_EXPORT//\'/\'\\\'\'}';"$'\n'
	PRE_SUDO_SHELL_COMMANDS_TO_RUN+="export PREFIX='$TERMUX_PREFIX';"$'\n'
	PRE_SUDO_SHELL_COMMANDS_TO_RUN+="export TMPDIR='$TMPDIR';"$'\n'
	PRE_SUDO_SHELL_COMMANDS_TO_RUN+="export HOME='${SUDO_SHELL_HOME//\'/\'\\\'\'}';"$'\n'
	PRE_SUDO_SHELL_COMMANDS_TO_RUN+="export TERM='${TERM//\'/\'\\\'\'}';"$'\n'
	PRE_SUDO_SHELL_COMMANDS_TO_RUN+="export LANG='${LANG//\'/\'\\\'\'}';"$'\n'

	#if command_type equals "script" and disable_stdin_for_core_script is enabled
	if [[ "$command_type" == "script" ]] && [[ "$disable_stdin_for_core_script" == "1" ]]; then
		#unset PS1 so that scripts run by script shells can check that interactive shell is not available
		PRE_SUDO_SHELL_COMMANDS_TO_RUN+="unset PS1;"$'\n'
	else
		PRE_SUDO_SHELL_COMMANDS_TO_RUN+="export PS1='${SUDO_SHELL_PS1//\'/\'\\\'\'}';"$'\n'
	fi

	#if LD_PRELOAD_COMMAND is not empty, then append it to PRE_SUDO_SHELL_COMMANDS_TO_RUN
	if [ ! -z "$LD_PRELOAD_COMMAND" ]; then
		PRE_SUDO_SHELL_COMMANDS_TO_RUN+="$LD_PRELOAD_COMMAND"$'\n'
	fi

	#if SUDO_SHELL_RCFILE_COMMANDS is not empty, then append it to PRE_SUDO_SHELL_COMMANDS_TO_RUN
	if [ ! -z "$SUDO_SHELL_RCFILE_COMMANDS" ]; then
		PRE_SUDO_SHELL_COMMANDS_TO_RUN+="$SUDO_SHELL_RCFILE_COMMANDS"$'\n'
	fi

	#if SUDO_SHELL_HISTFILE_COMMANDS is not empty, then append it to PRE_SUDO_SHELL_COMMANDS_TO_RUN
	if [ ! -z "$SUDO_SHELL_HISTFILE_COMMANDS" ]; then
		PRE_SUDO_SHELL_COMMANDS_TO_RUN+="$SUDO_SHELL_HISTFILE_COMMANDS"$'\n'
	fi

	#if set_sudo_shell_terminal_title is enabled and stdout is available, then add command to set terminal title to PRE_SUDO_SHELL_COMMANDS_TO_RUN
	if [[ "$set_sudo_shell_terminal_title" == "1" ]] && [ -t 1 ]; then
		PRE_SUDO_SHELL_COMMANDS_TO_RUN+='echo -ne "\e]0;'"$SUDO_SHELL_TERMINAL_TITLE"'\a";'$'\n'
	fi

	#if SUDO_SHELL_WORKING_DIR is set, then append cd command to PRE_SUDO_SHELL_COMMANDS_TO_RUN
	if [ ! -z "$SUDO_SHELL_WORKING_DIR" ]; then
		PRE_SUDO_SHELL_COMMANDS_TO_RUN+="cd '${SUDO_SHELL_WORKING_DIR//\'/\'\\\'\'}';"$'\n'
	fi

	#if command_type equals "su", "asu" or "path"
	if [[ "$command_type" == "su" ]] || [[ "$command_type" == "asu" ]] || [[ "$command_type" == "path" ]]; then
		#if ADDITIONAL_SUDO_SHELL_PRE_COMMANDS_TO_RUN is not empty, then append it to PRE_SUDO_SHELL_COMMANDS_TO_RUN
		if [ ! -z "$ADDITIONAL_SUDO_SHELL_PRE_COMMANDS_TO_RUN" ]; then
			PRE_SUDO_SHELL_COMMANDS_TO_RUN+="$ADDITIONAL_SUDO_SHELL_PRE_COMMANDS_TO_RUN"$'\n\n'
		fi
	fi

	#sudo_log 2 $'\n'"PRE_SUDO_SHELL_COMMANDS_TO_RUN=\"$PRE_SUDO_SHELL_COMMANDS_TO_RUN\""

	return 0

}

sudo_set_pre_sudo_post_shell_commands_to_run() {

	local return_value

	sudo_log_literal 2 "\nRunning sudo_set_pre_sudo_post_shell_commands_to_run"

	#set PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN with priority to termux paths
	sudo_log_literal 2 "\nSetting PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN with priority to termux paths"
	local priority="termux"

	#set priority_dependent_variables with new priority if needed
	sudo_set_priority_dependent_variables "$priority" || return $?

	#set PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN
	#set variables that need to be exported when running the sudo post shell
	PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN=""
	PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN+="export TERMUX_PRIORITY_PATH='${TERMUX_PRIORITY_PATH//\'/\'\\\'\'}';"$'\n'
	PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN+="export TERMUX_PRIORITY_LD_LIBRARY_PATH='${TERMUX_PRIORITY_LD_LIBRARY_PATH//\'/\'\\\'\'}';"$'\n'
	PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN+="export ANDROID_PRIORITY_PATH='${ANDROID_PRIORITY_PATH//\'/\'\\\'\'}';"$'\n'
	PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN+="export ANDROID_PRIORITY_LD_LIBRARY_PATH='${ANDROID_PRIORITY_LD_LIBRARY_PATH//\'/\'\\\'\'}';"$'\n'
	PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN+="export PATH='${PATH_TO_EXPORT//\'/\'\\\'\'}';"$'\n'
	PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN+="export LD_LIBRARY_PATH='${LD_LIBRARY_PATH_TO_EXPORT//\'/\'\\\'\'}';"$'\n'
	PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN+="export PREFIX='$TERMUX_PREFIX';"$'\n'
	PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN+="export TMPDIR='$TMPDIR';"$'\n'
	PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN+="export HOME='${SUDO_POST_SHELL_HOME//\'/\'\\\'\'}';"$'\n'
	PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN+="export TERM='${TERM//\'/\'\\\'\'}';"$'\n'
	PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN+="export LANG='${LANG//\'/\'\\\'\'}';"$'\n'
	PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN+="export PS1='${SUDO_POST_SHELL_PS1//\'/\'\\\'\'}';"$'\n'

	#if LD_PRELOAD_COMMAND is not empty, then append it to PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN
	if [ ! -z "$LD_PRELOAD_COMMAND" ]; then
		PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN+="$LD_PRELOAD_COMMAND"$'\n'
	fi

	#if SUDO_POST_SHELL_RCFILE_COMMANDS is not empty, then append it to PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN
	if [ ! -z "$SUDO_POST_SHELL_RCFILE_COMMANDS" ]; then
		PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN+="$SUDO_POST_SHELL_RCFILE_COMMANDS"$'\n'
	fi

	#if SUDO_POST_SHELL_HISTFILE_COMMANDS is not empty, then append it to PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN
	if [ ! -z "$SUDO_POST_SHELL_HISTFILE_COMMANDS" ]; then
		PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN+="$SUDO_POST_SHELL_HISTFILE_COMMANDS"$'\n'
	fi

	#sudo_log 2 $'\n'"PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN=\"$PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN\""

	return 0

}

sudo_set_sudo_command_path() {

	local return_value

	sudo_log_literal 2 "\nRunning sudo_set_sudo_command_path"

	SUDO_PATH_COMMAND="${SUDO_COMMAND[0]}"

	sudo_log 1 "SUDO_PATH_COMMAND=\"$SUDO_PATH_COMMAND\""

	#if SUDO_PATH_COMMAND is empty
	if [ -z "$SUDO_PATH_COMMAND" ]; then
		sudo_log_errors "The sudo command path \"$SUDO_PATH_COMMAND\" is empty"
		return 1
	fi

	#if force_set_priority_to_android_paths is enabled
	if [[ "$force_set_priority_to_android_paths" == "1" ]]; then
		#set priority_dependent_variables to android for PATH_TO_EXPORT used by the sudo_find_absolute_path_for_executable_and_validate function
		#we do this now and later in the sudo_set_pre_sudo_shell_commands_to_run function as well once the final SUDO_PATH_COMMAND has been set
		sudo_set_priority_dependent_variables "android" || return $?
	fi

	#find the absolute path for SUDO_PATH_COMMAND that should be used and validate it
	#SUDO_PATH_COMMAND is either considered an absolute path, otherwise searched for in current working directory or in all the paths in $PATH_TO_EXPORT variable
	#if use_root_for_path_search_and_validation is enabled
	if [[ "$use_root_for_path_search_and_validation" == "1" ]]; then
		sudo_unset_pre_su_variables
		SUDO_COMMAND_ABSOLUTE_PATH="$($SU_ENV_COMMAND "source '${SUDO_SCRIPT_PATH//\'/\'\\\'\'}'; sudo_find_absolute_path_for_executable_and_validate \"SUDO_COMMAND_ABSOLUTE_PATH\" \"SUDO_PATH_COMMAND\" '${SUDO_PATH_COMMAND//\'/\'\\\'\'}' '${PATH_TO_EXPORT//\'/\'\\\'\'}' \"$TERMUX_PREFIX\" \"$TERMUX_HOME\" 1" < /dev/null)"
		return_value=$?
		sudo_set_post_su_variables
	else
		sudo_find_absolute_path_for_executable_and_validate "SUDO_COMMAND_ABSOLUTE_PATH" "SUDO_PATH_COMMAND" "$SUDO_PATH_COMMAND" "$PATH_TO_EXPORT" "$TERMUX_PREFIX" "$TERMUX_HOME" 0
		return_value=$?
	fi
	if [ $return_value -ne 0 ] && [ $return_value -ne 112 ]; then
		sudo_log_errors "Failure while running \"sudo_find_absolute_path_for_executable_and_validate\""
		return $return_value
	elif [ $return_value -eq 112 ]; then
		sudo_log_errors "Command \"$SUDO_PATH_COMMAND\" not found"
		sudo_log_errors "Check your spelling and try again"
		return 1
	fi

	SUDO_PATH_COMMAND="$SUDO_COMMAND_ABSOLUTE_PATH"

	sudo_log 1 "SUDO_PATH_COMMAND_UPDATED=\"$SUDO_PATH_COMMAND\""

	#if SUDO_PATH_COMMAND is not a valid absolute path
	if [[ ! "$SUDO_PATH_COMMAND" =~ $valid_absolute_path_regex ]]; then
		sudo_log_errors "The SUDO_PATH_COMMAND \"$SUDO_PATH_COMMAND\" is not a valid absolute path"
		return 1
	fi

	return 0

}

sudo_set_sudo_path_command() {

	local return_value

	sudo_log_literal 2 "\n\n\nRunning sudo_set_sudo_path_command"

	#if SUDO_COMMAND is not set
	if [ ${#SUDO_COMMAND[@]} -eq 0 ]; then
		sudo_log_errors "SUDO_COMMAND is not set while running \"sudo_set_sudo_path_command\""
		return 1
	fi

	sudo_log 2 "SUDO_COMMAND_ARRAY_COUNT=\"${#SUDO_COMMAND[@]}\""

	sudo_log 2 $'\n'"SUDO_PATH_COMMAND=\`$SUDO_PATH_COMMAND\`"

	SUDO_PATH_COMMAND_TO_RUN=""

	#if "su" binary is being run, then unset LD_PRELOAD and LD_LIBRARY_PATH
	#if only "su" was passed without the '-a' option and current directory
	#did not have the "su" binary, then the wrapper script by termux at
	#$PREFIX/bin/su would ideally have been chosen by
	#the sudo_set_sudo_command_path function as SUDO_PATH_COMMAND, in
	#which case the wrapper script would ideally also automatically
	#unset the variables
	if [[ "$SUDO_PATH_COMMAND" == *"/su" ]]; then
		SUDO_PATH_COMMAND_TO_RUN="unset LD_PRELOAD; unset LD_LIBRARY_PATH; "
	fi

	#if SUDO_COMMAND argument size is 1, then only a path was passed to be executed
	if [ ${#SUDO_COMMAND[@]} -eq 1 ]; then

		SUDO_PATH_COMMAND_TO_RUN+="'${SUDO_PATH_COMMAND//\'/\'\\\'\'}'"
	#else path was passed as $1, followed by arguments that should be passed to the path
	else
		SUDO_COMMAND=("${SUDO_COMMAND[@]:1}") #remove first element since its the unparsed SUDO_PATH_COMMAND

		#if parse_commands_as_per_run_command_intent_rules is enabled
		if [[ "$parse_commands_as_per_run_command_intent_rules" == "1" ]]; then
			sudo_log 2 "Processing SUDO_PATH_COMMAND_ARGS array as per RUN_COMMAND intent rules"
		fi

		for i in "${!SUDO_COMMAND[@]}"; do
			#if parse_commands_as_per_run_command_intent_rules is enabled
			if [[ "$parse_commands_as_per_run_command_intent_rules" == "1" ]]; then
				#replace any COMMA_ALTERNATIVE characters with normal commas `,` that exist in {SUDO_COMMAND[$i]}
				if [[ "${SUDO_COMMAND[$i]}" == *"$COMMA_ALTERNATIVE"* ]]; then
					sudo_log 2 "COMMA_ALTERNATIVE found in SUDO_PATH_COMMAND_ARG $((i+1))"
					sudo_replace_comma_alternative_chars_with_commas_in_string "SUDO_COMMAND[$i]" "${SUDO_COMMAND[$i]}"
				fi
			fi

			#if disable_arguments_logging is not enabled
			if [[ "$disable_arguments_logging" != "1" ]]; then
				sudo_log 2 "SUDO_PATH_COMMAND_ARG $((i+1))=\`${SUDO_COMMAND[$i]}\`"$'\n'
			fi
		done

		printf -v "SUDO_PATH_COMMAND_ARGS" "%q " "${SUDO_COMMAND[@]}"
		SUDO_PATH_COMMAND_ARGS="${SUDO_PATH_COMMAND_ARGS% }" #remove trailing space

		SUDO_PATH_COMMAND_ARGS_LENGTH="${#SUDO_PATH_COMMAND_ARGS}"
		sudo_log 2 "SUDO_PATH_COMMAND_ARGS_LENGTH=\"$SUDO_PATH_COMMAND_ARGS_LENGTH\""


		#The `path` would not contribute much to crossing ARG_MAX since its only a path to a file, unless the path is too long
		#The ARG_MAX would be a concern only when arguments to `path` are passed via process substitution to the sudo script
		#and not as a direct argument since in that case ARG_MAX would have crossed at the point instead
		#if SUDO_PATH_COMMAND_ARGS_LENGTH is greater than SUDO_ARG_MAX_SAFE_LIMIT
		if [[ "$SUDO_PATH_COMMAND_ARGS_LENGTH" -gt "$SUDO_ARG_MAX_SAFE_LIMIT" ]]; then
			sudo_log 1 "Warning! The SUDO_PATH_COMMAND_ARGS_LENGTH \"$SUDO_PATH_COMMAND_ARGS_LENGTH\" is greater than $((SUDO_ARG_MAX_SAFE_LIMIT / 1024))KB. This may cause an \"Argument list too long\" exception."
		fi

		#pass SUDO_PATH_COMMAND_ARGS to SUDO_PATH_COMMAND
		SUDO_PATH_COMMAND_TO_RUN+=" '${SUDO_PATH_COMMAND//\'/\'\\\'\'}' $SUDO_PATH_COMMAND_ARGS"
	fi

	#SUDO_PATH_COMMAND_TO_RUN and SUDO_SCRIPT_COMMAND_TO_RUN needs to be passed to the BASH_SHELL inside su
	#by the sudo_run function
	#we pass the SUDO_PATH_COMMAND_TO_RUN to bash instead of directly passing commands to 'su -c' because
	#LD_PRELOAD does not work in the later case and scripts that are using #!/usr/bin/* shebang instead of termux
	#shebang fail
	#check sudo_set_sudo_script_command function for more details on why fd is used
	sudo_get_unsed_file_descriptor "SUDO_SCRIPT_FD"
	return_value=$?
	if [ $return_value -ne 0 ] || [[ ! "$SUDO_SCRIPT_FD" =~ $valid_number_regex ]]; then
		sudo_log_errors "Failure while getting an unused file descriptor to write SUDO_PATH_COMMAND_TO_RUN"
		sudo_log_errors "SUDO_SCRIPT_FD = \"$SUDO_SCRIPT_FD\""
		if [ $return_value -eq 0 ]; then
			return_value=1
		fi
		return $return_value
	fi

	#android fd directory is /proc/self/fd
	#using $$ instead of self so that su can access it
	SUDO_PATH_FD_PATH="/proc/$$/fd/$SUDO_SCRIPT_FD"

	#use printf to write to SUDO_SCRIPT_FD
	sudo_log_literal 2 "Writing SUDO_PATH_COMMAND_TO_RUN to SUDO_PATH_FD_PATH \"$SUDO_PATH_FD_PATH\""
	eval "exec $SUDO_SCRIPT_FD<" <(printf "%s" "$SUDO_PATH_COMMAND_TO_RUN")
	return_value=$?
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failure while writing SUDO_PATH_COMMAND_TO_RUN to SUDO_SCRIPT_FD \"$SUDO_SCRIPT_FD\""
		return $return_value
	fi

	return 0

}

sudo_set_sudo_script_command() {

	local return_value

	sudo_log_literal 2 "\n\n\nRunning sudo_set_sudo_script_command"

	SUDO_SCRIPT_COMMAND_TO_RUN=$'\n'

	#append PRE_SUDO_SHELL_COMMANDS_TO_RUN to SUDO_SCRIPT_COMMAND_TO_RUN
	SUDO_SCRIPT_COMMAND_TO_RUN+="$PRE_SUDO_SHELL_COMMANDS_TO_RUN"$'\n\n'

	#if ADDITIONAL_SUDO_SHELL_PRE_COMMANDS_TO_RUN is not empty, then append it to SUDO_SCRIPT_COMMAND_TO_RUN
	if [ ! -z "$ADDITIONAL_SUDO_SHELL_PRE_COMMANDS_TO_RUN" ]; then
		SUDO_SCRIPT_COMMAND_TO_RUN+="$ADDITIONAL_SUDO_SHELL_PRE_COMMANDS_TO_RUN"$'\n\n'
	fi

	sudo_log 2 "SUDO_COMMAND_ARRAY_COUNT=\"${#SUDO_COMMAND[@]}\""

	#if a SUDO_CORE_SCRIPT or arguments passed and SUDO_CORE_SCRIPT is not empty
	#the SUDO_CORE_SCRIPT can optionally not be passed or passed as an empty string so that other "features"
	#of the "script" command_type can still be used
	if [ ${#SUDO_COMMAND[@]} -ne 0 ] && [ ! -z "${SUDO_COMMAND[0]}" ]; then

		sudo_log 2 ""

		#if parse_commands_as_per_run_command_intent_rules is enabled
		if [[ "$parse_commands_as_per_run_command_intent_rules" == "1" ]]; then
			sudo_log 2 "Processing SUDO_CORE_SCRIPT and SUDO_CORE_SCRIPT_COMMAND_ARGS array as per RUN_COMMAND intent rules"
		fi

		for i in "${!SUDO_COMMAND[@]}"; do
			#if its the SUDO_CORE_SCRIPT argument and decode_core_script_content or core_script_is_path_to_script_file is enabled
			if [ "$i" -eq 0 ] && ([[ "$decode_core_script_content" == "1" ]] ||  [[ "$core_script_is_path_to_script_file" == "1" ]]); then
				#The SUDO_COMMAND[1] contains encoded data or a path to a file so no need to process it
				continue
			fi

			#if parse_commands_as_per_run_command_intent_rules is enabled
			if [[ "$parse_commands_as_per_run_command_intent_rules" == "1" ]]; then
				#replace any COMMA_ALTERNATIVE characters with normal commas `,` that exist in {SUDO_COMMAND[$i]}
				if [[ "${SUDO_COMMAND[$i]}" == *"$COMMA_ALTERNATIVE"* ]]; then
					#if its the SUDO_CORE_SCRIPT argument
					if [ "$i" -eq 0 ]; then
						sudo_log 2 "COMMA_ALTERNATIVE found in SUDO_CORE_SCRIPT"
					else
						sudo_log 2 "COMMA_ALTERNATIVE found in SUDO_CORE_SCRIPT_COMMAND_ARG $((i+1))"
					fi
					sudo_replace_comma_alternative_chars_with_commas_in_string "SUDO_COMMAND[$i]" "${SUDO_COMMAND[$i]}"
				fi
			fi

			#if disable_arguments_logging is not enabled
			if [[ "$disable_arguments_logging" != "1" ]]; then
				#if its the SUDO_CORE_SCRIPT argument
				if [ "$i" -eq 0 ]; then
					sudo_log 2 "SUDO_CORE_SCRIPT=\`${SUDO_COMMAND[$i]}\`"$'\n'
				#else SUDO_CORE_SCRIPT was passed as $1, followed by arguments that should be passed to the script
				else
					sudo_log 2 "SUDO_CORE_SCRIPT_COMMAND_ARG $((i+1))=\`${SUDO_COMMAND[$i]}\`"$'\n'
				fi
			fi
		done

		#set the first argument as SUDO_CORE_SCRIPT
		SUDO_CORE_SCRIPT="${SUDO_COMMAND[0]}"

		#if SUDO_CORE_SCRIPT_TEMP_FILENAME is empty, then use default
		if [ -z "$SUDO_CORE_SCRIPT_TEMP_FILENAME" ]; then
			SUDO_CORE_SCRIPT_TEMP_FILENAME="sudo_core_script"
		else
			#else if user passed the filename with --script-name' option, then
			#strip longest match of */ from start, to remove any directory path passed and keep only the basename
			SUDO_CORE_SCRIPT_TEMP_FILENAME="${SUDO_CORE_SCRIPT_TEMP_FILENAME##*/}"
			#if empty, then use default
			SUDO_CORE_SCRIPT_TEMP_FILENAME="${SUDO_CORE_SCRIPT_TEMP_FILENAME:=sudo_core_script}"
		fi

		#start a new SUDO_SHELL script shell and pass SUDO_CORE_SCRIPT to it
		#the SCRIPT_ARGUMENT_FOR_SCRIPT_SHELL will contain the SUDO_CORE_SCRIPT argument that will be passed to the SUDO_SHELL
		#the way the SUDO_CORE_SCRIPT argument will be passed will depend on script shell capabilities and the options set
		#sudo_set_script_argument_for_script_shell shell_basename heredoc_word heredoc_word_quote script_is_path_to_script_file force_use_temp_script_file decode_script_content script_file_label script_file_name script_file_path/script_content
		sudo_set_script_argument_for_script_shell "$SUDO_SHELL_BASENAME" "SUDO_CORE_SCRIPT_EOF" "'" "$core_script_is_path_to_script_file" "$force_use_temp_script_file_for_core_script" "$decode_core_script_content" "SUDO_CORE_SCRIPT" "$SUDO_CORE_SCRIPT_TEMP_FILENAME" "$SUDO_CORE_SCRIPT"
		return_value=$?
		if [ $return_value -ne 0 ]; then
			sudo_log_errors "Failed to create SUDO_CORE_SCRIPT argument commands to pass them to SUDO_SHELL \"$SUDO_SHELL\""
			return $return_value
		fi

		#pass the SCRIPT_ARGUMENT_FOR_SCRIPT_SHELL set by sudo_set_script_argument_for_script_shell to SUDO_SHELL
		printf -v "SUDO_SHELL_COMMAND_STRING" "$SUDO_SHELL_COMMAND_PRINT_FORMAT" "${SUDO_SHELL_COMMAND[@]}"
		SUDO_CORE_SCRIPT_COMMAND_TO_RUN="$SUDO_SHELL_COMMAND_STRING$SCRIPT_ARGUMENT_FOR_SCRIPT_SHELL"

		#if arguments need to be passed to SUDO_CORE_SCRIPT
		if [ ${#SUDO_COMMAND[@]} -gt 1 ]; then
			SUDO_COMMAND=("${SUDO_COMMAND[@]:1}") #remove first element since its the script

			printf -v "SUDO_CORE_SCRIPT_COMMAND_ARGS" "%q " "${SUDO_COMMAND[@]}"
			SUDO_CORE_SCRIPT_COMMAND_ARGS="${SUDO_CORE_SCRIPT_COMMAND_ARGS% }" #remove trailing space

			SUDO_CORE_SCRIPT_COMMAND_ARGS_LENGTH="${#SUDO_CORE_SCRIPT_COMMAND_ARGS}"
			sudo_log 2 "SUDO_CORE_SCRIPT_COMMAND_ARGS_LENGTH=\"$SUDO_CORE_SCRIPT_COMMAND_ARGS_LENGTH\""

			#The `core_script` would not contribute much to crossing ARG_MAX since its either passed with process substitution or
			#as a path to a file storing it, unless the path is too long
			#The ARG_MAX would be a concern only when arguments to `core_script` are passed via process substitution to the sudo script
			#and not as a direct argument since in that case ARG_MAX would have crossed at the point instead
			#if SUDO_CORE_SCRIPT_COMMAND_ARGS_LENGTH is greater than SUDO_ARG_MAX_SAFE_LIMIT
			if [[ "$SUDO_CORE_SCRIPT_COMMAND_ARGS_LENGTH" -gt "$SUDO_ARG_MAX_SAFE_LIMIT" ]]; then
				sudo_log 1 "Warning! The SUDO_CORE_SCRIPT_COMMAND_ARGS_LENGTH \"$SUDO_CORE_SCRIPT_COMMAND_ARGS_LENGTH\" is greater than $((SUDO_ARG_MAX_SAFE_LIMIT / 1024))KB. This may cause an \"Argument list too long\" exception."
			fi

			#pass the arguments to the SUDO_SHELL after the SCRIPT_ARGUMENT_FOR_SCRIPT_SHELL
			SUDO_CORE_SCRIPT_COMMAND_TO_RUN+=" $SUDO_CORE_SCRIPT_COMMAND_ARGS"
		fi

		#if SUDO_CORE_SCRIPT_REDIRECT_MODE or SUDO_SHELL_STDIN_STRING is set or
		#disable_stdin_for_core_script or run_core_script_in_background is enabled
		if [ ! -z "$SUDO_CORE_SCRIPT_REDIRECT_MODE" ] || \
			[ ! -z "$SUDO_SHELL_STDIN_STRING" ] || \
				[[ "$disable_stdin_for_core_script" == "1" ]] || \
					[[ "$run_core_script_in_background" == "1" ]]; then
			#surround SUDO_CORE_SCRIPT_COMMAND_TO_RUN with command grouping
			SUDO_CORE_SCRIPT_COMMAND_TO_RUN="{"$'\n\n'"$SUDO_CORE_SCRIPT_COMMAND_TO_RUN"$'\n\n''}'

			#if SUDO_CORE_SCRIPT_REDIRECT_MODE is set
			if [ ! -z "$SUDO_CORE_SCRIPT_REDIRECT_MODE" ]; then

				#if SUDO_CORE_SCRIPT_REDIRECT_MODE equal "0", then redirect stderr to stdout
				if [[ "$SUDO_CORE_SCRIPT_REDIRECT_MODE" == "0" ]]; then
					SUDO_CORE_SCRIPT_COMMAND_TO_RUN+=' 2>&1'

				#elif SUDO_CORE_SCRIPT_REDIRECT_MODE equal "1", then redirect stdout to stderr
				elif [[ "$SUDO_CORE_SCRIPT_REDIRECT_MODE" == "1" ]]; then
					SUDO_CORE_SCRIPT_COMMAND_TO_RUN+=' 1>&2'

				#elif SUDO_CORE_SCRIPT_REDIRECT_MODE equal "2", then redirect stdout to /dev/null
				elif [[ "$SUDO_CORE_SCRIPT_REDIRECT_MODE" == "2" ]]; then
					SUDO_CORE_SCRIPT_COMMAND_TO_RUN+=' 1>/dev/null'

				#elif SUDO_CORE_SCRIPT_REDIRECT_MODE equal "3", then redirect stderr to /dev/null
				elif [[ "$SUDO_CORE_SCRIPT_REDIRECT_MODE" == "3" ]]; then
					SUDO_CORE_SCRIPT_COMMAND_TO_RUN+=' 2>/dev/null'

				#elif SUDO_CORE_SCRIPT_REDIRECT_MODE equal "4", then redirect both stdout and stderr to /dev/null
				elif [[ "$SUDO_CORE_SCRIPT_REDIRECT_MODE" == "4" ]]; then
					SUDO_CORE_SCRIPT_COMMAND_TO_RUN+=' &>/dev/null'

				#elif SUDO_CORE_SCRIPT_REDIRECT_MODE equal "5", then redirect stderr to stdout and redirect stdout to stderr
				elif [[ "$SUDO_CORE_SCRIPT_REDIRECT_MODE" == "5" ]]; then
					SUDO_CORE_SCRIPT_COMMAND_TO_RUN+=' 3>&2 2>&1 1>&3'

				#elif SUDO_CORE_SCRIPT_REDIRECT_MODE equal "6", then redirect stderr to stdout and redirect stdout to /dev/null
				elif [[ "$SUDO_CORE_SCRIPT_REDIRECT_MODE" == "6" ]]; then
					SUDO_CORE_SCRIPT_COMMAND_TO_RUN+=' 2>&1 1>/dev/null'

				#else append SUDO_CORE_SCRIPT_REDIRECT_MODE to SUDO_CORE_SCRIPT_COMMAND_TO_RUN
				else
					SUDO_CORE_SCRIPT_COMMAND_TO_RUN+=" $SUDO_CORE_SCRIPT_REDIRECT_MODE"

				fi
			fi

			#if SUDO_SHELL_STDIN_STRING is set
			if [ ! -z "$SUDO_SHELL_STDIN_STRING" ]; then
				#if SUDO_SHELL_BASENAME is in SUDO_SCRIPT_SHELLS_WITHOUT_PROCESS_SUBSTITUTION_SUPPORT
				if [[ " $SUDO_SCRIPT_SHELLS_WITHOUT_PROCESS_SUBSTITUTION_SUPPORT " == *" $SUDO_SHELL_BASENAME "* ]]; then
					#pass SUDO_SHELL_STDIN_STRING as stdin with a herestring to SUDO_SHELL
					SUDO_CORE_SCRIPT_COMMAND_TO_RUN+=' <<<'"'${SUDO_SHELL_STDIN_STRING//\'/\'\\\'\'}'"
				else
					#pass SUDO_SHELL_STDIN_STRING as stdin with process substitution to SUDO_SHELL
					SUDO_CORE_SCRIPT_COMMAND_TO_RUN+=' < <(printf "%s" '"'${SUDO_SHELL_STDIN_STRING//\'/\'\\\'\'}'"')'
				fi
			else
				#if disable_stdin_for_core_script is enabled, then redirect stdin to /dev/null
				if [[ "$disable_stdin_for_core_script" == "1" ]]; then
					SUDO_CORE_SCRIPT_COMMAND_TO_RUN+=' < /dev/null'
				fi
			fi

			#if run_core_script_in_background is enabled, then start SUDO_CORE_SCRIPT in background
			if [[ "$run_core_script_in_background" == "1" ]]; then
				SUDO_CORE_SCRIPT_COMMAND_TO_RUN+=' &'
				SUDO_CORE_SCRIPT_COMMAND_TO_RUN+=$'\n''export SUDO_SCRIPT_PID=$!;'
				SUDO_CORE_SCRIPT_COMMAND_TO_RUN+=$'\n''export SUDO_SCRIPT_EXIT_CODE=0;'
			fi

			SUDO_CORE_SCRIPT_COMMAND_TO_RUN+=$'\n\n'
		fi

		#if run_core_script_in_background is not enabled
		if [[ "$run_core_script_in_background" != "1" ]]; then
			SUDO_CORE_SCRIPT_COMMAND_TO_RUN+=$'\n''export SUDO_SCRIPT_EXIT_CODE=$?;'$'\n\n'

			#if exit_early_if_core_script_fails is enabled, then exit if SUDO_SCRIPT_EXIT_CODE does not equal 0
			if [[ "$exit_early_if_core_script_fails" == "1" ]]; then
				SUDO_CORE_SCRIPT_COMMAND_TO_RUN+='[ $SUDO_SCRIPT_EXIT_CODE -ne 0 ] && exit $SUDO_SCRIPT_EXIT_CODE'$'\n\n'
			fi
		fi

		#append SUDO_CORE_SCRIPT_COMMAND_TO_RUN to SUDO_SCRIPT_COMMAND_TO_RUN
		SUDO_SCRIPT_COMMAND_TO_RUN+="$SUDO_CORE_SCRIPT_COMMAND_TO_RUN"

	else
		#append dummy SUDO_SCRIPT_EXIT_CODE to SUDO_SCRIPT_COMMAND_TO_RUN
		SUDO_SCRIPT_COMMAND_TO_RUN+='export SUDO_SCRIPT_EXIT_CODE=0;'$'\n\n'
	fi

	#if ADDITIONAL_SUDO_SHELL_POST_COMMANDS_TO_RUN is not empty, then append it to SUDO_SCRIPT_COMMAND_TO_RUN
	if [ ! -z "$ADDITIONAL_SUDO_SHELL_POST_COMMANDS_TO_RUN" ]; then
		SUDO_SCRIPT_COMMAND_TO_RUN+="$ADDITIONAL_SUDO_SHELL_POST_COMMANDS_TO_RUN"$'\n\n'
	fi

	#if go_back_to_last_activity_after_running_core_script is enabled, then simulate double back button press to go to the last activity, first to close keyboard and second to close terminal session
	if [[ "$go_back_to_last_activity_after_running_core_script" == "1" ]]; then
		SUDO_SCRIPT_COMMAND_TO_RUN+='$(export PATH="$ANDROID_PRIORITY_PATH"; export LD_LIBRARY_PATH="$ANDROID_PRIORITY_LD_LIBRARY_PATH"; unset LD_PRELOAD; input keyevent KEYCODE_BACK; input keyevent KEYCODE_BACK;);'$'\n\n'
	#if go_to_launcher_activity_after_running_core_script is enabled, then simulate home button press to go to the launcher activity
	elif [[ "$go_to_launcher_activity_after_running_core_script" == "1" ]]; then
		SUDO_SCRIPT_COMMAND_TO_RUN+='$(export PATH="$ANDROID_PRIORITY_PATH"; export LD_LIBRARY_PATH="$ANDROID_PRIORITY_LD_LIBRARY_PATH"; unset LD_PRELOAD; am start --user 0 -a android.intent.action.MAIN -c android.intent.category.HOME &>/dev/null;);'$'\n\n'
	fi

	#if clear_shell_after_running_core_script is enabled, then add clear command
	if [[ "$clear_shell_after_running_core_script" == "1" ]]; then
		SUDO_SCRIPT_COMMAND_TO_RUN+="clear"$'\n'
	fi

	#if run_interactive_post_sudo_shell_after_running_core_script is enabled, start a new interactive post shell
	#we do not check if stdout and stdin are available since sudo could be piped or redirected and may not be connected to a tty
	#the -t 0 and -t 1 checks fail if sudo is run in a simple subshell in android 10 but not on 7
	if [[ "$run_interactive_post_sudo_shell_after_running_core_script" == "1" ]]; then
		#append PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN
		SUDO_SCRIPT_COMMAND_TO_RUN+="$PRE_SUDO_POST_SHELL_COMMANDS_TO_RUN"$'\n'

		#if ADDITIONAL_SUDO_POST_SHELL_PRE_COMMANDS_TO_RUN is not empty, then append it to SUDO_SCRIPT_COMMAND_TO_RUN
		if [ ! -z "$ADDITIONAL_SUDO_POST_SHELL_PRE_COMMANDS_TO_RUN" ]; then
			SUDO_SCRIPT_COMMAND_TO_RUN+="$ADDITIONAL_SUDO_POST_SHELL_PRE_COMMANDS_TO_RUN"$'\n'
		fi

		printf -v "SUDO_POST_SHELL_INTERACTIVE_COMMAND_STRING" "$SUDO_POST_SHELL_INTERACTIVE_COMMAND_PRINT_FORMAT" "${SUDO_POST_SHELL_INTERACTIVE_COMMAND[@]}"
		SUDO_POST_SHELL_INTERACTIVE_COMMAND_STRING="${SUDO_POST_SHELL_INTERACTIVE_COMMAND_STRING% }" #remove trailing space

		#if SUDO_POST_SHELL_STDIN_STRING is set
		if [ ! -z "$SUDO_POST_SHELL_STDIN_STRING" ]; then
			#surround SUDO_POST_SHELL_INTERACTIVE_COMMAND_STRING with command grouping
			SUDO_POST_SHELL_INTERACTIVE_COMMAND_STRING="{"$'\n\n'"$SUDO_POST_SHELL_INTERACTIVE_COMMAND_STRING"$'\n\n''}'

			#if SUDO_POST_SHELL_BASENAME is in SUDO_SCRIPT_SHELLS_WITHOUT_PROCESS_SUBSTITUTION_SUPPORT
			if [[ " $SUDO_SCRIPT_SHELLS_WITHOUT_PROCESS_SUBSTITUTION_SUPPORT " == *" $SUDO_POST_SHELL_BASENAME "* ]]; then
				#pass SUDO_POST_SHELL_STDIN_STRING as stdin with a herestring to SUDO_POST_SHELL
				SUDO_POST_SHELL_INTERACTIVE_COMMAND_STRING+=' <<<'"'${SUDO_POST_SHELL_STDIN_STRING//\'/\'\\\'\'}'"
			else
				#pass SUDO_POST_SHELL_STDIN_STRING as stdin with process substitution to SUDO_POST_SHELL
				SUDO_POST_SHELL_INTERACTIVE_COMMAND_STRING+=' < <(printf "%s" '"'${SUDO_POST_SHELL_STDIN_STRING//\'/\'\\\'\'}'"')'
			fi
		fi

		SUDO_SCRIPT_COMMAND_TO_RUN+="$SUDO_POST_SHELL_INTERACTIVE_COMMAND_STRING"$'\n'

		#if ADDITIONAL_SUDO_POST_SHELL_POST_COMMANDS_TO_RUN is not empty, then append it to SUDO_SCRIPT_COMMAND_TO_RUN
		if [ ! -z "$ADDITIONAL_SUDO_POST_SHELL_POST_COMMANDS_TO_RUN" ]; then
			SUDO_SCRIPT_COMMAND_TO_RUN+="$ADDITIONAL_SUDO_POST_SHELL_POST_COMMANDS_TO_RUN"$'\n'
		fi
	else
		#exit with exit code of SUDO_CORE_SCRIPT
		SUDO_SCRIPT_COMMAND_TO_RUN+='exit $SUDO_SCRIPT_EXIT_CODE'$'\n'
	fi



	#set SUDO_SCRIPT_COMMAND_TRAPS and SUDO_SCRIPT_COMMAND_TRAPS_REMOVE_TEMP_DIRECTORY_FUNCTION
	sudo_create_script_command_traps
	return_value=$?
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failed to create traps commands for SUDO_TEMP_DIRECTORY \"$SUDO_TEMP_DIRECTORY\""
		return $return_value
	fi

	#if SUDO_SCRIPT_COMMAND_TRAPS is set
	if [ ! -z "$SUDO_SCRIPT_COMMAND_TRAPS" ]; then
		#if a script shell that doesn't support process substitution is being used or '-f' is passed, then
		#sudo_set_script_argument_for_script_shell_for_sudo will store temp core_script file at SUDO_CORE_SCRIPT_TEMP_FILENAME in SUDO_TEMP_DIRECTORY
		#add traps at start of SUDO_SCRIPT_COMMAND_TO_RUN to remove the SUDO_TEMP_DIRECTORY when the script exits
		SUDO_SCRIPT_COMMAND_TO_RUN=$'\n'"$SUDO_SCRIPT_COMMAND_TRAPS"$'\n'"$SUDO_SCRIPT_COMMAND_TO_RUN"
	fi



	#SUDO_SCRIPT_COMMAND_TO_RUN cannot be passed to the bash shell inside su using process substitution
	#since the "self" in "proc/self/fd/#" passed by process substitution is for the sudo script process
	#and not for the bash process inside su
	#so when bash shell inside su tries to read from it, then there will be errors like
	#"/proc/self/fd/63: No such file or directory"
	#hence we manually create a file descriptor and pass its path to su or to be more specific to the bash shell
	#for the path and script commands
	#/system/xbin/su --shell="/data/data/com.termux/files/usr/bin/bash" --preserve-environment -c "bash --noprofile --norc" <(echo 'echo 1')

	#the method that is used for passing data to su using file descriptors in sudo_run function and elsewhere is the following
	#get an unsed file descriptor for the current sudo script process
	#manually set fd path in /proc/$$/fd since that is where the fd are created in android
	#$$ returns pid of current process
	#then run something like `exec 3< <(printf "%s" "string")`
	#this will create a pseudo pipe file descriptor and attach stdout of printf to the file descriptor 3
	#this file descriptor will exist at /proc/$$/fd/3
	#this basically creates the file descriptor and "saves" the output of printf before su is started
	#so /proc/self/fd issues do not occur
	#we pass this path to whatever requires it inside su, like bash or cat
	#the path will of course be for current sudo script process and not for bash because of $$
	#but since bash is being run with root it will be able to read from it
	#the file descriptor will be like a read only stream like in pipes. seeking forward/backward is not possibly
	#and once data has been read by another process, it is gone and cannot be read again from the start
	#credits and details: https://stackoverflow.com/a/20018118/14686958 by Jo So

	#there are other reasons as well why this method is being used other than the /proc/self/fd issues
	#1) This method is faster than heredocs and herestrings since data is processed only in memory
	#   and does not create temp files on the disk increasing execution time like the later. The data is of course
	#   buffered with a likely limit of 64KB but that's still large enough not to cause problems for average script text passing
	#2) The temp files created by heredocs and herestrings are in TMPDIR which in termux's case is $PREFIX/usr/tmp.
	#   The TMPDIR is relatively less secure since non-root processes can access it and ideally shouldn't be used due to
	#   potential risk of privilege escalation or private data leakage. Although any process in termux context could get
	#   su access if termux app has been granted root access but other apps granted SAF access can by default only access
	#   $TERMUX_HOME/ and not $PREFIX/.
	#   You can confirm usage of TMPDIR by running:
	#   ```
	#   #for herestrings
	#   sleep 3 <<<"here string" & lsof -w -p $! | grep 0r
	#
	#   #for heredocs
	#   sleep 3 <<EOF &
	#   here doc
	#	EOF
	#   lsof -w -p $! | grep 0r
	#	```
	#3) The script command_type may require stdin to be usable by the scripts
	#   If heredocs and herestrings are used, then they will be read by the bash shell through the stdin
	#   which will prevent the script shells to use it for user input and they may even read characters from
	#   the script itself as stdin in some cases
	#   Hence process substitution should be used which leaves stdin free, but of course that is not possible due
	#   to /proc/self/fd issues due to su usage.
	#   The other alternative is to create another temp file in SUDO_TEMP_DIRECTORY and store the SUDO_SCRIPT_COMMAND_TO_RUN
	#   in it and pass the path to bash. This will of course increase execution time significantly due to creation of
	#   the SUDO_TEMP_DIRECTORY directory on every run even if sudo_core_script temp file is not to be created
	#   and also due to another call to the su shell for the creation of the another temp file.
	#   Another hacky alternative that will work is to solve the /proc/self/fd issue itself
	#   That can be done by guessing the real path of fd inside the su shell and pass that to bash instead
	#   That can be done by running:
	#   ```
	#   fd_number="$(echo <(echo "") | sed -E 's|/proc/self/fd/([0-9]+)|\1|')"
	#	/system/xbin/su --shell="/data/data/com.termux/files/usr/bin/bash" --preserve-environment -c "bash_shell_pid=$$; "'su_shell_pid=$(pgrep -P $bash_shell_pid); bash /proc/$su_shell_pid/fd/'"$fd_number" <(echo 'echo 1')
	#	```
	#   Use the path to the 'su' installed on your device if its not at '/system/xbin/su'
	#   The first line will just get the fd number that is chosen by default by bash when it uses process substitution which
	#   which is likely going to be 63
	#   The second line is the shorter version of SU_RUN_COMMAND used by the sudo script
	#	The single and double quoting is extremely important to make sure some things are
	#   run in the local sudo script bash shell and others inside the su shell
	#   note that the local bash shell is of the sudo script and is different from the bash shell that is inside the su shell
	#   First we get store the pid of the local bash shell in bash_shell_pid. Note the double quotes so that $$ expands locally.
	#   Then we get pid of su shell by finding the process whose parent pid matches the bash_shell_pid.
	#   Since there are no background processes run by the sudo script, pgrep should return a single pid.
	#	Then we pass the /proc/su_shell_pid/fd/fd_number path to bash directly that the `<(echo 'echo 1')` process substitution will create
	#   The su_shell_pid is inside single quotes so it expands inside the su shell and fd_number is inside double quotes so it expands locally.
	#   Despite the /proc/self/fd/63 argument passed due to process substitution, bash will read from the path manually passed.
	#   Note that we cannot create the path using $PPID variable because multiple processes are created by the su shell and PPID will
	#   not match su_shell_pid.
	#   If the $PREFIX/bin/su is directly used by running `su --shell...` instead of full path, then another process is created
	#   because su in termux bin is actually a wrapper script and process substitution path will be created for it instead, it may even
	#   give errors while executing commands.
	#   This method is however not used because its a bit hacky but could work, but would require multiple device and multiple su implementation testing.
	#   Another reason this isn't used is because normally, the sudo binary of linux distros will close all open file descriptors other
	#   than standard input, standard output and standard error when its called for security reasons to prevent child processes
	#   from getting access to file descriptors of the parent processes that were not intended for it.
	#   Some su binaries behave in the same way. There are however not closed by SuperSU v2.82 as shown by the above test and neither by magisk v21.1
	#   but other android su implementations may close the file descriptors, breaking this method.
	#
	#   To monitor the file descriptors 63 opened by child processes, run the following
	#   ```
	#   #drop to a root shell so that root processes can also be monitored
	#   sudo su
	#   #run a background infinite loop that passes a comma separated list of pids returned by ps to ls using brace expansion that will list
	#   #all files in /proc/{pids}/fd paths and then grep only fds matching 63 and output their pid to stdout which is captured by $pid
	#   #if $pid is set, then ps is used to display pid,ppid,cmd of all pids stored in the $pid variable
	#   (while true; do pid="$(eval "ls --color=never -d -1 /proc/{$(ps --no-headers -o pid -g | sed -z -e 's/\n/,/g' -e 's/ //g' -e 's/,$//')}/fd/* 2>/dev/null" | grep "/fd/63" | sed -E 's|/proc/([0-9]+)/fd/.*|\1|g')"; [ ! -z "$pid" ] && ps -wwo pid,ppid,cmd $(echo "$pid" | sed -z -E 's/[ \n\t]+/ /'); done) &
	#   #store the pid of the background process so that it can be killed later
	#   while_pid=$!
	#   #then drop to another root shell
	#   sudo su
	#   #then run the su command with an added sleep command for background monitoring to work, you may want to increase the sleep time
	#   #ideally two commands would be shown by ps that created fd 63, one for the local bash interactive shell of the sudo su command
	#   #and the other for the newly created su shell since the fd will be copied during the fork
	#   fd_number="$(echo <(echo "") | sed -E 's|/proc/self/fd/([0-9]+)|\1|')"
	#   /system/xbin/su --shell="/data/data/com.termux/files/usr/bin/bash" --preserve-environment -c "bash_shell_pid=$$; "'su_shell_pid=$(pgrep -P $bash_shell_pid); sleep 0.3; bash /proc/$su_shell_pid/fd/'"$fd_number" <(echo 'echo 1')
	#	#exit the second root shell once done
	#   exit
	#   #kill background process, do not leave it running since it will consume lots of resources and may slow down the system
	#   kill $while_pid
	#   ```
	#  #there are probably other methods using lsof etc.

	sudo_get_unsed_file_descriptor "SUDO_SCRIPT_FD"
	return_value=$?
	if [ $return_value -ne 0 ] || [[ ! "$SUDO_SCRIPT_FD" =~ $valid_number_regex ]]; then
		sudo_log_errors "Failure while getting an unused file descriptor to write SUDO_SCRIPT_COMMAND_TO_RUN"
		sudo_log_errors "SUDO_SCRIPT_FD = \"$SUDO_SCRIPT_FD\""
		if [ $return_value -eq 0 ]; then
			return_value=1
		fi
		return $return_value
	fi

	#android fd directory is /proc/self/fd
	#using $$ instead of self so that su can access it
	SUDO_SCRIPT_FD_PATH="/proc/$$/fd/$SUDO_SCRIPT_FD"

	#use printf to write to SUDO_SCRIPT_FD
	sudo_log_literal 2 "\nWriting SUDO_SCRIPT_COMMAND_TO_RUN to SUDO_SCRIPT_FD_PATH \"$SUDO_SCRIPT_FD_PATH\""
	eval "exec $SUDO_SCRIPT_FD<" <(printf "%s" "$SUDO_SCRIPT_COMMAND_TO_RUN")
	return_value=$?
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failure while writing SUDO_SCRIPT_COMMAND_TO_RUN to SUDO_SCRIPT_FD \"$SUDO_SCRIPT_FD\""
		return $return_value
	fi

	return 0

}

sudo_check_if_setting_up_sudo_temp_directory_is_required() {

	local return_value

	sudo_log_literal 2 "\nRunning sudo_check_if_setting_up_sudo_temp_directory_is_required"

	#if SUDO_SHELL_BASENAME is in SUDO_SCRIPT_SHELLS_WITHOUT_PROCESS_SUBSTITUTION_SUPPORT
	#or force_use_temp_script_file is enabled
	#then the script file will need to be stored in a temp script file in SUDO_TEMP_DIRECTORY
	#this logic must be same as that in sudo_set_script_argument_for_script_shell function
	#so that SUDO_TEMP_DIRECTORY has already been created if needed
	#and the script_file path can be set correctly and be passed to the script shell
	#its not directly created in the other function to reduce a call to the su shell
	if [[ " $SUDO_SCRIPT_SHELLS_WITHOUT_PROCESS_SUBSTITUTION_SUPPORT " == *" $SUDO_SHELL_BASENAME "* ]] || [[ "$force_use_temp_script_file_for_core_script" == "1" ]]; then
		#enable SETUP_SUDO_TEMP_DIRECTORY
		sudo_log 2 "SETUP_SUDO_TEMP_DIRECTORY enabled"
		SETUP_SUDO_TEMP_DIRECTORY=1
	fi

	return 0

}

#sudo_set_script_argument_for_script_shell shell_basename heredoc_word heredoc_word_quote script_is_path_to_script_file force_use_temp_script_file decode_script_content script_file_label script_file_name script_file_path/script_content
sudo_set_script_argument_for_script_shell() {

	local return_value

	#if parameter count is not 9
	if [ $# -ne 9 ]; then
		sudo_log_errors "Invalid parameter count to \"sudo_set_script_argument_for_script_shell\""
		return 1
	fi

	local shell_basename="$1"
	local heredoc_word="$2"
	local heredoc_word_quote="$3"
	local script_is_path_to_script_file="$4"
	local force_use_temp_script_file="$5"
	local decode_script_content="$6"
	local script_file_label="$7"
	local script_file_name="$8"

	#if shell_basename is not in any of the SUDO_SUPPORTED_SCRIPT_SHELLS, then exit with error
	if [[ "$shell_basename" == *' '* ]] || [[ " $SUDO_SUPPORTED_SCRIPT_SHELLS " != *" $shell_basename "* ]]; then
		sudo_log_errors "The shell_basename \"$shell_basename\" while running \"sudo_set_script_argument_for_script_shell\" is not supported. It must be one of \"$SUDO_SUPPORTED_SCRIPT_SHELLS\""
		return 1
	fi

	SCRIPT_ARGUMENT_FOR_SCRIPT_SHELL=""

	#if script_is_path_to_script_file is enabled, then just pass script_file_path as the argument to the script shell
	if [[ "$script_is_path_to_script_file" == "1" ]]; then
		local script_file_path="$9"

		sudo_log 2 "$script_file_label will be passed to the script shell as a path to a file"

		#replace "$PREFIX/" or "~/" prefix with termux absolute paths in script_file_path
		sudo_expand_termux_path "script_file_path" "$script_file_label" "$script_file_path" "$TERMUX_PREFIX" "$TERMUX_HOME" 1
		return_value=$?
		if [ $return_value -ne 0 ]; then
			sudo_log_errors "Failed to expand $script_file_label \"$script_file_path\""
			return $return_value
		fi

		#if script_file_path is not a valid absolute path
		if [[ ! "$script_file_path" =~ $valid_absolute_path_regex ]]; then
			sudo_log_errors "The $script_file_label \"$script_file_path\" is not a valid absolute path"
			return 1
		fi

		sudo_log 2 "script_file_path=\"$script_file_path\""
		printf -v "script_file_path_string" "%q" "$script_file_path"
		SCRIPT_ARGUMENT_FOR_SCRIPT_SHELL="$script_file_path_string"

	else
		local script_content="$9"

		#if shell is in SUDO_SCRIPT_SHELLS_WITHOUT_PROCESS_SUBSTITUTION_SUPPORT (dash, sh, node, php)
		#or force_use_temp_script_file is enabled
		#store the script in a temp script file in SUDO_TEMP_DIRECTORY and pass that as argument to the script shell
		if [[ " $SUDO_SCRIPT_SHELLS_WITHOUT_PROCESS_SUBSTITUTION_SUPPORT " == *" $shell_basename "* ]] || [[ "$force_use_temp_script_file" == "1" ]]; then
			local log_content=1

			#if disable_arguments_logging is enabled
			if [[ "$disable_arguments_logging" == "1" ]]; then
				log_content=0
			fi

			sudo_log 2 "$script_file_label will be passed to the script shell after being store in a temp file"

			#if SUDO_TEMP_DIRECTORY is not a valid absolute path
			if [[ ! "$SUDO_TEMP_DIRECTORY" =~ $valid_absolute_path_regex ]]; then
				sudo_log_errors "The SUDO_TEMP_DIRECTORY \"$SUDO_TEMP_DIRECTORY\" is not a valid absolute path, required by \"sudo_set_script_argument_for_script_shell\""
				return 1
			fi

			script_file="$SUDO_TEMP_DIRECTORY/$script_file_name"

			sudo_log 2 "$script_file_label temp file=\"$script_file\""

			#sudo_create_sudo_temp_file label path log_content decode_content content
			sudo_create_sudo_temp_file "$script_file_label" "$script_file" "$log_content" "$decode_script_content" "$script_content"
			return_value=$?
			if [ $return_value -ne 0 ]; then
				sudo_log_errors "Failure while running \"sudo_create_sudo_temp_file\""
				return $return_value
			fi

			printf -v "script_file_string" "%q" "$script_file"
			SCRIPT_ARGUMENT_FOR_SCRIPT_SHELL="$script_file_string"

		#if shell is bash, zsh, fish, ksh, python python2, ruby, perl, lua5.2, lua5.3, lua5.4
		#use process substitution with printf to pass script_content to the script shell
		#heredoc is not used since that will create a temp file in TMPDIR which is slower and less secure
		#note that ARG_MAX will not cross because of passing the script_content as an argument to printf
		#since printf is a shell built-in and exec is not done. It will however cross if an external call were to
		#be made to printf with `$PREFIX/bin/print`. The ARG_MAX would be a concern only when `core_script`
		#is passed via process substitution to the sudo script and not as a direct argument since in that
		#case ARG_MAX would have crossed at the point instead
		elif [[ " bash zsh fish ksh python python2 ruby perl lua5.2 lua5.3 lua5.4 " == *" $shell_basename "* ]]; then

			sudo_log 2 "$script_file_label will be passed to the script shell using process substitution with printf command"

			SCRIPT_ARGUMENT_FOR_SCRIPT_SHELL='<(printf "%s" '"'${script_content//\'/\'\\\'\'}
'"')'

			#sudo_log 2 "$script_file_label will be passed to the script shell using process substitution with a cat heredoc"

#			SCRIPT_ARGUMENT_FOR_SCRIPT_SHELL='<(cat <<'"$heredoc_word_quote$heredoc_word$heredoc_word_quote"'
#'"$script_content"'
#
#'"$heredoc_word"'
#)'


		else
			sudo_log_errors "shell_basename \"$shell_basename\" not handled while running \"sudo_set_script_argument_for_script_shell\""
			return 1
		fi
	fi

	return 0

}

#sudo_create_sudo_temp_file label path log_content decode_content content
sudo_create_sudo_temp_file() {

	local return_value

	#if parameter count is not 5
	if [ $# -ne 5 ]; then
		sudo_log_errors "Invalid parameter count to \"sudo_create_sudo_temp_file\""
		return 1
	fi

	local label="$1"
	local path="$2"
	local log_content="$3"
	local decode_content="$4"
	local content="$5"

	#if path is not a valid absolute path
	if [[ ! "$path" =~ $valid_absolute_path_regex ]]; then
		sudo_log_errors "The \"$label\" file at path \"$path\" is not an absolute path"
		return 2
	fi

	local temp_file_fd
	local temp_file_fd_path

	sudo_get_unsed_file_descriptor "temp_file_fd"
	return_value=$?
	if [ $return_value -ne 0 ] || [[ ! "$temp_file_fd" =~ $valid_number_regex ]]; then
		sudo_log_errors "Failure while getting an unused file descriptor to write decoded $label"
		sudo_log_errors "temp_file_fd = \"$temp_file_fd\""
		if [ $return_value -eq 0 ]; then
			return_value=1
		fi
		return $return_value
	fi

	#android fd directory is /proc/self/fd
	#using $$ instead of self so that su can access it
	temp_file_fd_path="/proc/$$/fd/$temp_file_fd"

	#write the contents to temp_file_fd_path
	#decode first if required
	#decoding of binary data needs to be done on the fly since
	#binary data cannot be stored in a variable to be passed using herestring
	#and nor can a heredoc be used to pass binary data
	#process substitution is not possible for passing data to su due to /proc/self/fd issues
	#hence a fd is opened and used instead
	#a herestring or heredoc could have been used for passing text only data
	#but those will create a temp file in TMPDIR which is slower and less secure
	sudo_log 2 "Writing $label to temp_file_fd \"$temp_file_fd\""
	if [[ "$decode_content" == "1" ]]; then
		eval "exec $temp_file_fd<" <(printf '%s' "$content" | base64 -d)
	else
		eval "exec $temp_file_fd<" <(printf '%s' "$content")
	fi
	return_value=$?
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failure while writing $label to temp_file_fd \"$temp_file_fd\""
	else
		#use cat to read contents from fd at temp_file_fd_path
		#and redirect stdout to file at path to write to it
		sudo_log 2 "Creating $label file at \"$path\""
		sudo_unset_pre_su_variables
		$SU_ENV_COMMAND "cat \"$temp_file_fd_path\" > '${path//\'/\'\\\'\'}'"
		return_value=$?
		sudo_set_post_su_variables
	fi

	#if temp_file_fd is set, then close it
	if [ ! -z "$temp_file_fd" ]; then
		exec {temp_file_fd}>&-
	fi

	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failure while creating $label file at \"$path\""
		return $return_value
	fi

	#read file at path again and log its content but only if binary data is not stored in it
	if [[ $sudo_verbose_level -ge 1 ]] && [[ "$log_content" == "1" ]]  && [[ "$decode_content" != "1" ]]; then
		local file_contents=""
		sudo_unset_pre_su_variables
		file_contents="$($SU_ENV_COMMAND "cat '${path//\'/\'\\\'\'}'" < /dev/null)"
		sudo_set_post_su_variables
		sudo_log 1 $'\n'"${label}_CONTENTS=\`$file_contents\`"
	fi

	return 0

}

sudo_set_sudo_shell() {

	local return_value

	sudo_log_literal 2 "\nRunning sudo_set_sudo_shell"

	#if SUDO_SHELL is set
	if [ ! -z "$SUDO_SHELL" ]; then
		sudo_trim_trailing_newlines "SUDO_SHELL" "$SUDO_SHELL"

		#validate the SUDO_SHELL
		#if use_root_for_path_search_and_validation is enabled
		if [[ "$use_root_for_path_search_and_validation" == "1" ]]; then
			sudo_unset_pre_su_variables
			SUDO_SHELL="$($SU_ENV_COMMAND "source '${SUDO_SCRIPT_PATH//\'/\'\\\'\'}'; sudo_validate_shell \"SUDO_SHELL\" '${SUDO_SHELL//\'/\'\\\'\'}' '${SUDO_SUPPORTED_SHELLS//\'/\'\\\'\'}' \"$TERMUX_PREFIX\" \"$TERMUX_BIN\" \"$TERMUX_HOME\"" < /dev/null)"
			return_value=$?
			sudo_set_post_su_variables
		else
			SUDO_SHELL="$(sudo_validate_shell "SUDO_SHELL" "$SUDO_SHELL" "$SUDO_SUPPORTED_SHELLS" "$TERMUX_PREFIX" "$TERMUX_BIN" "$TERMUX_HOME")"
			return_value=$?
		fi
		if [ $return_value -ne 0 ]; then
			sudo_log_errors "Failed to validate \"SUDO_SHELL\""
			return $return_value
		fi
	else
		#default to bash as SUDO_SHELL
		SUDO_SHELL="$BASH_SHELL_PATH"
	fi

	#if SUDO_SHELL is not a valid absolute path
	if [[ ! "$SUDO_SHELL" =~ $valid_absolute_path_regex ]]; then
		sudo_log_errors "The SUDO_SHELL \"$SUDO_SHELL\" is not a valid absolute path"
		return 1
	fi

	sudo_log 1 "SUDO_SHELL=\"$SUDO_SHELL\""

	#find the basename and parent directory of the SUDO_SHELL
	SUDO_SHELL_BASENAME="${SUDO_SHELL##*/}" #strip longest match of */ from start
	SUDO_SHELL_PARENT_DIR="${SUDO_SHELL:0:${#SUDO_SHELL} - ${#SUDO_SHELL_BASENAME}}" #substring from 0 to position of basename
	case $SUDO_SHELL_PARENT_DIR in *[!/]*/) SUDO_SHELL_PARENT_DIR=${SUDO_SHELL_PARENT_DIR%"${SUDO_SHELL_PARENT_DIR##*[!/]}"};; *[/]) SUDO_SHELL_PARENT_DIR="/";; esac #remove trailing slashes if not root

	sudo_log 2 "SUDO_SHELL_BASENAME=\"$SUDO_SHELL_BASENAME\""
	sudo_log 2 "SUDO_SHELL_PARENT_DIR=\"$SUDO_SHELL_PARENT_DIR\""

	#if SUDO_SHELL is not in any of the SUDO_SUPPORTED_SHELLS, then exit with error
	#the basename of the shell file could be faked but the actual shell inside the file is not checked
	if [[ "$SUDO_SHELL_BASENAME" == *' '* ]] || [[ " $SUDO_SUPPORTED_SHELLS " != *" $SUDO_SHELL_BASENAME "* ]]; then
		sudo_log_errors "The SUDO_SHELL \"$SUDO_SHELL\" is not supported. It must be one of \"$SUDO_SUPPORTED_SHELLS\""
		return 1
	fi

	return 0

}

sudo_set_sudo_post_shell() {

	local return_value

	sudo_log_literal 2 "\nRunning sudo_set_sudo_post_shell"

	#if SUDO_POST_SHELL is set
	if [ ! -z "$SUDO_POST_SHELL" ]; then
		sudo_trim_trailing_newlines "SUDO_POST_SHELL" "$SUDO_POST_SHELL"

		#validate the SUDO_POST_SHELL
		#if use_root_for_path_search_and_validation is enabled
		if [[ "$use_root_for_path_search_and_validation" == "1" ]]; then
			sudo_unset_pre_su_variables
			SUDO_POST_SHELL="$($SU_ENV_COMMAND "source '${SUDO_SCRIPT_PATH//\'/\'\\\'\'}'; sudo_validate_shell \"SUDO_POST_SHELL\" '${SUDO_POST_SHELL//\'/\'\\\'\'}' '${SUDO_SUPPORTED_POST_SHELLS//\'/\'\\\'\'}' \"$TERMUX_PREFIX\" \"$TERMUX_BIN\" \"$TERMUX_HOME\"" < /dev/null)"
			return_value=$?
			sudo_set_post_su_variables
		else
			SUDO_POST_SHELL="$(sudo_validate_shell "SUDO_POST_SHELL" "$SUDO_POST_SHELL" "$SUDO_SUPPORTED_POST_SHELLS" "$TERMUX_PREFIX" "$TERMUX_BIN" "$TERMUX_HOME")"
			return_value=$?
		fi
		if [ $return_value -ne 0 ]; then
			sudo_log_errors "Failed to validate \"SUDO_POST_SHELL\""
			return $return_value
		fi
	else
		#default to bash as SUDO_POST_SHELL
		SUDO_POST_SHELL="$BASH_SHELL_PATH"
	fi

	#if SUDO_POST_SHELL is not a valid absolute path
	if [[ ! "$SUDO_POST_SHELL" =~ $valid_absolute_path_regex ]]; then
		sudo_log_errors "The SUDO_POST_SHELL \"$SUDO_POST_SHELL\" is not a valid absolute path"
		return 1
	fi

	sudo_log 1 "SUDO_POST_SHELL=\"$SUDO_POST_SHELL\""

	#find the basename and parent directory of the SUDO_POST_SHELL
	SUDO_POST_SHELL_BASENAME="${SUDO_POST_SHELL##*/}" #strip longest match of */ from start
	SUDO_POST_SHELL_PARENT_DIR="${SUDO_POST_SHELL:0:${#SUDO_POST_SHELL} - ${#SUDO_POST_SHELL_BASENAME}}" #substring from 0 to position of basename
	case $SUDO_POST_SHELL_PARENT_DIR in *[!/]*/) SUDO_POST_SHELL_PARENT_DIR=${SUDO_POST_SHELL_PARENT_DIR%"${SUDO_POST_SHELL_PARENT_DIR##*[!/]}"};; *[/]) SUDO_POST_SHELL_PARENT_DIR="/";; esac #remove trailing slashes if not root

	sudo_log 2 "SUDO_POST_SHELL_BASENAME=\"$SUDO_POST_SHELL_BASENAME\""
	sudo_log 2 "SUDO_POST_SHELL_PARENT_DIR=\"$SUDO_POST_SHELL_PARENT_DIR\""

	#if SUDO_POST_SHELL is not in any of the SUDO_SUPPORTED_SHELLS, then exit with error
	#the basename of the shell file could be faked but the actual shell inside the file is not checked
	if [[ "$SUDO_POST_SHELL_BASENAME" == *' '* ]] || [[ " $SUDO_SUPPORTED_POST_SHELLS " != *" $SUDO_POST_SHELL_BASENAME "* ]]; then
		sudo_log_errors "The SUDO_POST_SHELL \"$SUDO_POST_SHELL\" is not supported. It must be one of \"$SUDO_SUPPORTED_POST_SHELLS\""
		return 1
	fi

	return 0

}

#sudo_validate_shell shell_label user_shell supported_shells termux_prefix termux_bin termux_home
sudo_validate_shell() {

	local return_value

	#if parameter count is not 6
	if [ $# -ne 6 ]; then
		sudo_log_errors "Invalid parameter count to \"sudo_validate_shell\""
		return 1
	fi

	local shell_label="$1"
	local user_shell="$2"
	local supported_shells="$3"
	local termux_prefix="$4"
	local termux_bin="$5"
	local termux_home="$6"

	local shell

	#if user_shell is set to a shell in supported_shells, then set user_shell to "$termux_bin/$user_shell"
	if [[ "$user_shell" != *'/'* ]]; then
		if [[ "$user_shell" != *' '* ]] && [[ " $supported_shells " == *" $user_shell "* ]]; then
			shell="$termux_bin/$user_shell"
		else
			sudo_log_errors "The $shell_label \"$user_shell\" is not supported. It must be one of \"$supported_shells\""
			return 1
		fi
	else
		#replace "$PREFIX/" or "~/" prefix with termux absolute paths in user_shell
		sudo_expand_termux_path "user_shell" "$shell_label" "$user_shell" "$termux_prefix" "$termux_home" 1
		return_value=$?
		if [ $return_value -ne 0 ]; then
			sudo_log_errors "Failed to expand $shell_label \"$user_shell\""
			return $return_value
		fi

		shell="$user_shell"
	fi

	#sudo_run_file_type_tests_on_path label path log_file_tests_failure_errors show_stat_output_on_file_tests_failure check_if_absolute_path file_type_tests
	sudo_run_file_type_tests_on_path "$shell_label" "$shell" 1 1 1 "frx" || return $?

	#echo shell to stdout
	echo "$shell"

}

sudo_set_sudo_shell_rcfile() {

	local return_value

	sudo_log_literal 2 "\nRunning sudo_set_sudo_shell_rcfile"

	#set rcfile variables
	sudo_set_shell_rcfile "SUDO_SHELL" "$SUDO_SHELL_BASENAME" "$SUDO_SHELL_HOME"
	return_value=$?
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failure while running \"sudo_set_rcfile_functions\" for SUDO_SHELL \"$SUDO_SHELL\""
		return $return_value
	fi

	SUDO_SHELL_RCFILE="$SHELL_RCFILE"
	SUDO_SHELL_RCFILE_PARENT_DIR="$SHELL_RCFILE_PARENT_DIR"
	SUDO_SHELL_RCFILE_COMMANDS="$SHELL_RCFILE_COMMANDS"
	SUDO_SHELL_RCFILE_VALUE="$SHELL_RCFILE_VALUE"
	SUDO_SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS+=("${SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS[@]}")


	sudo_log 2 "SUDO_SHELL_RCFILE=\"$SUDO_SHELL_RCFILE\""
	sudo_log 2 "SUDO_SHELL_RCFILE_PARENT_DIR=\"$SUDO_SHELL_RCFILE_PARENT_DIR\""
	sudo_log 2 "SUDO_SHELL_RCFILE_COMMANDS=\"$SUDO_SHELL_RCFILE_COMMANDS\""
	sudo_log 2 "SUDO_SHELL_RCFILE_VALUE=\`$SUDO_SHELL_RCFILE_VALUE\`"

	return 0

}

sudo_set_sudo_post_shell_rcfile() {

	local return_value

	sudo_log_literal 2 "\nRunning sudo_set_sudo_post_shell_rcfile"

	#set rcfile variables
	sudo_set_shell_rcfile "SUDO_POST_SHELL" "$SUDO_POST_SHELL_BASENAME" "$SUDO_POST_SHELL_HOME"
	return_value=$?
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failure while running \"sudo_set_rcfile_functions\" for SUDO_POST_SHELL \"$SUDO_POST_SHELL\""
		return $return_value
	fi

	SUDO_POST_SHELL_RCFILE="$SHELL_RCFILE"
	SUDO_POST_SHELL_RCFILE_PARENT_DIR="$SHELL_RCFILE_PARENT_DIR"
	SUDO_POST_SHELL_RCFILE_COMMANDS="$SHELL_RCFILE_COMMANDS"
	SUDO_POST_SHELL_RCFILE_VALUE="$SHELL_RCFILE_VALUE"
	SUDO_POST_SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS+=("${SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS[@]}")


	sudo_log 2 "SUDO_POST_SHELL_RCFILE=\"$SUDO_POST_SHELL_RCFILE\""
	sudo_log 2 "SUDO_POST_SHELL_RCFILE_PARENT_DIR=\"$SUDO_POST_SHELL_RCFILE_PARENT_DIR\""
	sudo_log 2 "SUDO_POST_SHELL_RCFILE_COMMANDS=\"$SUDO_POST_SHELL_RCFILE_COMMANDS\""
	sudo_log 2 "SUDO_POST_SHELL_RCFILE_VALUE=\`$SUDO_POST_SHELL_RCFILE_VALUE\`"

	return 0

}

#sudo_set_shell_rcfile shell_basename shell_home
sudo_set_shell_rcfile() {

	local return_value

	#if parameter count is not 3
	if [ $# -ne 3 ]; then
		sudo_log_errors "Invalid parameter count to \"sudo_set_shell_rcfile\""
		return 1
	fi

	local shell_label="$1"
	local shell_basename="$2"
	local shell_home="$3"

	#RCFILE are usually unique for different shells
	#if shell_home==TERMUX_HOME and shell has no --rc param or
	#environmental variable, then termux shells and sudo shells will
	#have to share rc files

	#was going to add support for tcsh but decided not to after reading the following and having a chuckle
	#https://web.fe.up.pt/~jmcruz/etc/unix/sh-vs-csh.html

	SHELL_RCFILE=""
	SHELL_RCFILE_PARENT_DIR=""
	SHELL_RCFILE_COMMANDS=""
	SHELL_RCFILE_VALUE=""
	SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS=()

	#if shell is zsh
	if [[ "$shell_basename" == "zsh" ]]; then
		#if shell_home==TERMUX_HOME, then termux shell and sudo shell rc files are shared
		#since only the parent dir of ".zshrc" file can be defined in ZDOTDIR
		SHELL_RCFILE="$shell_home/.zshrc"
		SHELL_RCFILE_COMMANDS="export ZDOTDIR='${shell_home//\'/\'\\\'\'}';"

	#if shell is fish
	elif [[ "$shell_basename" == "fish" ]]; then
		#if shell_home==TERMUX_HOME, then termux shell and sudo shell rc files are shared since "config.fish" is always loaded
		#XDG_RUNTIME_DIR is exported and is inside shell_home because otherwise fish shell creates
		#the "$TMPDIR/fish.root" directory with root ownership
		SHELL_RCFILE="$shell_home/.config/fish/config.fish"
		SHELL_RCFILE_COMMANDS="export XDG_CONFIG_HOME='${shell_home//\'/\'\\\'\'}/.config';"
		SHELL_RCFILE_COMMANDS+=$'\n'"export XDG_CACHE_HOME='${shell_home//\'/\'\\\'\'}/.cache';"
		SHELL_RCFILE_COMMANDS+=$'\n'"export XDG_DATA_HOME='${shell_home//\'/\'\\\'\'}/.local/share';"
		SHELL_RCFILE_COMMANDS+=$'\n'"export XDG_RUNTIME_DIR='${shell_home//\'/\'\\\'\'}/.cache/tmp';"
		SHELL_RCFILE_COMMANDS+=$'\n'"[ ! -d \"\$XDG_CONFIG_HOME\" ] && mkdir -p \"\$XDG_CONFIG_HOME\";"
		SHELL_RCFILE_COMMANDS+=$'\n'"[ ! -d \"\$XDG_DATA_HOME\" ] && mkdir -p \"\$XDG_DATA_HOME\";"
		SHELL_RCFILE_COMMANDS+=$'\n'"[ ! -d \"\$XDG_RUNTIME_DIR\" ] && mkdir -p \"\$XDG_RUNTIME_DIR\";"

	#if shell is ruby
	elif [[ "$shell_basename" == "ruby" ]]; then
		#if shell_home==TERMUX_HOME, then termux shell and sudo shell rc files are shared since "~/.irbrc" is always loaded
		SHELL_RCFILE="$shell_home/.irbrc"

	#if shell is pry
	elif [[ "$shell_basename" == "pry" ]]; then
		#if shell_home==TERMUX_HOME, then termux shell and sudo shell rc files are shared since "~/.pryrc" is always loaded
		SHELL_RCFILE="$shell_home/.pryrc"

	#if shell is bash, dash, sh, ksh, php, python
	elif [[ " bash dash sh ksh python php python2 " == *" $shell_basename "* ]]; then
		#if shell_home==TERMUX_HOME, then set the RCFILE with "sudo_" appended to it
		#so that termux shell and sudo shell rc files are not shared since --rc params or
		#environmental variables can be used to define the path to the rc file
		local shell_rcfile_subname
		if [[ "$shell_home" == "$TERMUX_HOME" ]]; then
			shell_rcfile_subname="sudo_${shell_basename}"
		else
			shell_rcfile_subname="${shell_basename}"
		fi

		#if shell is bash
		if [[ "$shell_basename" == "bash" ]]; then
			#use the --rcfile param to pass the path to rcfile
			SHELL_RCFILE="$shell_home/.${shell_rcfile_subname}rc"
			SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS+=("--rcfile" "$SHELL_RCFILE")

		#if shell is python, python2
		elif [[ " python python2 " == *" $shell_basename "* ]]; then
			#use the PYTHONSTARTUP environmental variable to pass the path to rcfile
			SHELL_RCFILE="$shell_home/.${shell_rcfile_subname}rc"
			SHELL_RCFILE_COMMANDS="export PYTHONSTARTUP='${SHELL_RCFILE//\'/\'\\\'\'}';"

		#if shell is php
		elif [[ "$shell_basename" == "php" ]]; then
			#use the -c param to pass the path to ini file
			SHELL_RCFILE="$shell_home/${shell_rcfile_subname}.ini"
			SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS+=("-c" "$SHELL_RCFILE")

		#if shell is dash, sh, ksh
		else
			#use the PYTHONSTARTUP environmental variable to pass the path to rcfile
			SHELL_RCFILE="$shell_home/.${shell_rcfile_subname}rc"
			SHELL_RCFILE_COMMANDS="export ENV='${SHELL_RCFILE//\'/\'\\\'\'}';"
		fi

	#if shell is node, perl, lua5.2, lua5.3, lua5.4
	elif [[ " node perl lua5.2 lua5.3 lua5.4 " == *" $shell_basename "* ]]; then
		#the shell does not have a rc file or does not use it
		sudo_log 2 "The \"$shell_basename\" shell does not have a rc file or does not use it"
	else
		sudo_log_errors "shell_basename \"$shell_basename\" not handled while running \"sudo_set_shell_rcfile\""
		return 1
	fi


	#if SHELL_RCFILE is set
	if [ ! -z "$SHELL_RCFILE" ]; then

		#if SHELL_RCFILE is not a valid absolute path
		if [[ ! "$SHELL_RCFILE" =~ $valid_absolute_path_regex ]]; then
			sudo_log_errors "The ${shell_label}_RCFILE \"$SHELL_RCFILE\" is not a valid absolute path"
			return 1
		fi

		#if SHELL_RCFILE_COMMANDS is set
		if [ ! -z "$SHELL_RCFILE_COMMANDS" ]; then
			SHELL_RCFILE_COMMANDS+=$'\n'
		fi

		SHELL_RCFILE_COMMANDS+="export RCFILE='${SHELL_RCFILE//\'/\'\\\'\'}';"


		#find the parent directory of the SHELL_RCFILE
		SHELL_RCFILE_BASENAME="${SHELL_RCFILE##*/}" #strip longest match of */ from start
		SHELL_RCFILE_PARENT_DIR="${SHELL_RCFILE:0:${#SHELL_RCFILE} - ${#SHELL_RCFILE_BASENAME}}" #substring from 0 to position of basename
		case $SHELL_RCFILE_PARENT_DIR in *[!/]*/) SHELL_RCFILE_PARENT_DIR=${SHELL_RCFILE_PARENT_DIR%"${SHELL_RCFILE_PARENT_DIR##*[!/]}"};; *[/]) SHELL_RCFILE_PARENT_DIR="/";; esac #remove trailing slashes if not root

		#set SHELL_RCFILE_VALUE to be set in SHELL_RCFILE
		SHELL_RCFILE_VALUE=""

		#if shell is bash, zsh, dash, sh, fish or ksh
		if [[ " bash zsh dash sh fish ksh " == *" $shell_basename "* ]]; then
			#not defining any variables since they are dynamically defined by "sudo" command
			#overriding may create problems in the future as well if dynamically defined variable values change
			#PATH, LD_LIBRARY_PATH and PS1 must never be overridden in rcfile, otherwise "sudo" commands will not work properly,
			#specially the "sudo asu" and "sudo <command>" commands

			#define any required functions to add to SHELL_RCFILE_VALUE in RCFILE_FUNCTIONS
			sudo_set_rcfile_functions "$shell_basename" || return $?

			#if RCFILE_FUNCTIONS is not empty, then append it to SHELL_RCFILE_VALUE
			if [ ! -z "$RCFILE_FUNCTIONS" ]; then
				SHELL_RCFILE_VALUE+="$RCFILE_FUNCTIONS"$'\n'
			fi
		fi
	fi

	return 0

}

#sudo_set_rcfile_functions
sudo_set_rcfile_functions() {

	local return_value

	#if parameter count is not 1
	if [ $# -ne 1 ]; then
		sudo_log_errors "Invalid parameter count to \"sudo_set_rcfile_functions\""
		return 1
	fi

	local shell_basename="$1"

	RCFILE_FUNCTIONS=""

	#if shell is fish
	if [[ "$shell_basename" == "fish" ]]; then

		#define export helper function for fish shell that allows export command in bash to be used
		FISH_SHELL_EXPORT_FUNCTION='
function export
    if [ $argv ]
        set var (echo $argv | cut -f1 -d=)
        set val (echo $argv | cut -f2 -d=)
        set -g -x $var $val
    end
end

funcsave export
'

		#define unset helper function for fish shell that allows export command in bash to be used
		FISH_SHELL_UNSET_FUNCTION='
function unset
    set --erase $argv
end

funcsave unset
'

	#define tpath helper function for fish shell that sets priority to termux paths
	FISH_SHELL_TPATH_FUNCTION='
function tpath
    export PATH="$TERMUX_PRIORITY_PATH";
    export LD_LIBRARY_PATH="$TERMUX_PRIORITY_LD_LIBRARY_PATH";
    '"$TERMUX_PRIORITY_LD_PRELOAD_COMMAND"'
end
'

	#define apath helper function for fish shell that sets priority to android paths
	FISH_SHELL_APATH_FUNCTION='
function apath
    export PATH="$ANDROID_PRIORITY_PATH";
    export LD_LIBRARY_PATH="$ANDROID_PRIORITY_LD_LIBRARY_PATH";
    '"$ANDROID_PRIORITY_LD_PRELOAD_COMMAND"'
end
'

		RCFILE_FUNCTIONS="$FISH_SHELL_EXPORT_FUNCTION"
		RCFILE_FUNCTIONS+=$'\n'"$FISH_SHELL_UNSET_FUNCTION"
		RCFILE_FUNCTIONS+=$'\n'"$FISH_SHELL_TPATH_FUNCTION"
		RCFILE_FUNCTIONS+=$'\n'"$FISH_SHELL_APATH_FUNCTION"





	#if shell is bash, zsh, dash, sh or ksh
	elif [[ " bash zsh dash sh ksh " == *" $shell_basename "* ]]; then

		#define tpath helper function for bash, zsh, sh, etc shells that sets priority to termux paths
		GENERAL_SHELL_TPATH_FUNCTION='
tpath() {
    export PATH="$TERMUX_PRIORITY_PATH";
    export LD_LIBRARY_PATH="$TERMUX_PRIORITY_LD_LIBRARY_PATH";
    '"$TERMUX_PRIORITY_LD_PRELOAD_COMMAND"'
}
'


		#define apath helper function for bash, zsh, sh, etc shells that sets priority to android paths
		GENERAL_SHELL_APATH_FUNCTION='
apath() {
    export PATH="$ANDROID_PRIORITY_PATH";
    export LD_LIBRARY_PATH="$ANDROID_PRIORITY_LD_LIBRARY_PATH";
    '"$ANDROID_PRIORITY_LD_PRELOAD_COMMAND"'
}
'


		RCFILE_FUNCTIONS="$GENERAL_SHELL_TPATH_FUNCTION"
		RCFILE_FUNCTIONS+=$'\n'"$GENERAL_SHELL_APATH_FUNCTION"

	fi

	return 0

}

sudo_set_sudo_shell_histfile() {

	local return_value

	sudo_log_literal 2 "\nRunning sudo_set_sudo_shell_histfile"

	#set histfile variables
	sudo_set_shell_histfile "SUDO_SHELL" "$SUDO_SHELL_BASENAME" "$SUDO_SHELL_HOME" "$sudo_shells_history_enabled"
	return_value=$?
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failure while running \"sudo_set_shell_histfile\" for SUDO_SHELL \"$SUDO_SHELL\""
		return $return_value
	fi

	SUDO_SHELL_HISTFILE="$SHELL_HISTFILE"
	SUDO_SHELL_HISTFILE_PARENT_DIR="$SHELL_HISTFILE_PARENT_DIR"
	SUDO_SHELL_HISTFILE_COMMANDS="$SHELL_HISTFILE_COMMANDS"
	SUDO_SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS+=("${SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS[@]}")

	sudo_log 2 "SUDO_SHELL_HISTFILE=\"$SUDO_SHELL_HISTFILE\""
	sudo_log 2 "SUDO_SHELL_HISTFILE_PARENT_DIR=\"$SUDO_SHELL_HISTFILE_PARENT_DIR\""
	sudo_log 2 "SUDO_SHELL_HISTFILE_COMMANDS=\"$SUDO_SHELL_HISTFILE_COMMANDS\""

	return 0

}

sudo_set_sudo_post_shell_histfile() {

	local return_value

	sudo_log_literal 2 "\nRunning sudo_set_sudo_post_shell_histfile"

	#set histfile variables
	sudo_set_shell_histfile "SUDO_POST_SHELL" "$SUDO_POST_SHELL_BASENAME" "$SUDO_POST_SHELL_HOME" "$sudo_shells_history_enabled"
	return_value=$?
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failure while running \"sudo_set_shell_histfile\" for SUDO_POST_SHELL \"$SUDO_POST_SHELL\""
		return $return_value
	fi

	SUDO_POST_SHELL_HISTFILE="$SHELL_HISTFILE"
	SUDO_POST_SHELL_HISTFILE_PARENT_DIR="$SHELL_HISTFILE_PARENT_DIR"
	SUDO_POST_SHELL_HISTFILE_COMMANDS="$SHELL_HISTFILE_COMMANDS"
	SUDO_POST_SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS+=("${SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS[@]}")

	sudo_log 2 "SUDO_POST_SHELL_HISTFILE=\"$SUDO_POST_SHELL_HISTFILE\""
	sudo_log 2 "SUDO_POST_SHELL_HISTFILE_PARENT_DIR=\"$SUDO_POST_SHELL_HISTFILE_PARENT_DIR\""
	sudo_log 2 "SUDO_POST_SHELL_HISTFILE_COMMANDS=\"$SUDO_POST_SHELL_HISTFILE_COMMANDS\""

	return 0

}

#sudo_set_shell_histfile shell_label shell_basename shell_home shell_history_enabled
sudo_set_shell_histfile() {

	local return_value

	#if parameter count is not 4
	if [ $# -ne 4 ]; then
		sudo_log_errors "Invalid parameter count to \"sudo_set_shell_histfile\""
		return 1
	fi

	local shell_label="$1"
	local shell_basename="$2"
	local shell_home="$3"
	local shell_history_enabled="$4"

	SHELL_HISTFILE=""
	SHELL_HISTFILE_PARENT_DIR=""
	SHELL_HISTFILE_COMMANDS=""
	SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS=()

	#if shell_history_enabled is enabled
	if [[ "$shell_history_enabled" == "1" ]]; then

		#history files are usually unique for different shells
		#if shell_home==TERMUX_HOME, then termux shells and sudo
		#shells will have to share history files if the shell does
		#not support HISTFILE variable

		#if shell is fish
		if [[ "$shell_basename" == "fish" ]]; then
			local histfile_session_id

			#if shell_home and TERMUX_HOME are same, then set the HISTFILE with "sudo_"
			#appended to it to keep sudo shells command history separate from termux shells
			if [[ "$shell_home" == "$TERMUX_HOME" ]]; then
				histfile_session_id="sudo_fish"
			else
				histfile_session_id="fish"
			fi

			#fish uses the variable fish_history to store the session id for the history file
			#the history file ends up being "${fish_history}_history"
			SHELL_HISTFILE="$shell_home/.local/share/fish/${histfile_session_id}_history"
			SHELL_HISTFILE_COMMANDS="export fish_history='$histfile_session_id';"

		#if shell is python
		elif [[ "$shell_basename" == "python" ]]; then
			#python uses "~/.python_history" file to store history by default
			#history feature was introduced in 3.4
			SHELL_HISTFILE="$shell_home/.python_history"

		#if shell is ruby
		elif [[ "$shell_basename" == "ruby" ]]; then
			#irb uses "~/.irb_history" file to store history by default
			#if rvm is used, then its "~/.irb-history"
			#there are no params or environmental variables that can be used to set history settings
			#history settings can be changed by defining following config options in "~/.irbrc" file
			#IRB.conf[:HISTORY_FILE] = "~/.irb_history"
			#IRB.conf[:SAVE_HISTORY] = 1000
			SHELL_HISTFILE="$shell_home/.irb_history"

		#if shell is pry
		elif [[ "$shell_basename" == "pry" ]]; then
			#pry uses "~/.pry_history" file to store history by default
			#there are no params or environmental variables that can be used to set history settings
			#history settings can be changed by defining following config options in "~/.pryrc" file
			#Pry.config.history_file = "~/.pry_history"
			#Pry.config.history_load = true
			#Pry.config.history_save = true
			SHELL_HISTFILE="$shell_home/.pry_history"

		#if shell is php
		elif [[ "$shell_basename" == "php" ]]; then
			#php uses "~/.php_history" file to store history by default
			SHELL_HISTFILE="$shell_home/.php_history"

		#if shell is bash, zsh, dash, sh, ksh, node, perl
		elif [[ " bash zsh dash sh ksh node perl " == *" $shell_basename "* ]]; then
			#if shell_home and TERMUX_HOME are same, then set the HISTFILE with "sudo_"
			#appended to it to keep sudo shells command history separate from termux shells
			local shell_histfile_subname
			if [[ "$shell_home" == "$TERMUX_HOME" ]]; then
				shell_histfile_subname="sudo_${shell_basename}"
			else
				shell_histfile_subname="${shell_basename}"
			fi

			#if shell is bash
			if [[ "$shell_basename" == "bash" ]]; then
				#bash uses HISTFILE environment variable for history file
				SHELL_HISTFILE="$shell_home/.${shell_histfile_subname}_history"
				SHELL_HISTFILE_COMMANDS="export HISTSIZE=1000;"
				SHELL_HISTFILE_COMMANDS+=$'\n'"export HISTFILESIZE=1000;"
			#if shell is zsh
			elif [[ "$shell_basename" == "zsh" ]]; then
				#zsh uses HISTFILE environment variable for history file
				SHELL_HISTFILE="$shell_home/.${shell_histfile_subname}_history"
				SHELL_HISTFILE_COMMANDS="export HISTSIZE=1000;"
				SHELL_HISTFILE_COMMANDS+=$'\n'"export SAVEHIST=1000;"

			#if shell is node
			elif [[ "$shell_basename" == "node" ]]; then
				#node uses NODE_REPL_HISTORY to define path for history file
				#and NODE_REPL_HISTORY_SIZE for size of history file
				SHELL_HISTFILE="$shell_home/.${shell_histfile_subname}_history"
				SHELL_HISTFILE_COMMANDS="export NODE_REPL_HISTORY='${SHELL_HISTFILE//\'/\'\\\'\'}';"
				SHELL_HISTFILE_COMMANDS+=$'\n'"export NODE_REPL_HISTORY_SIZE=1000;"

			#if shell is perl
			elif [[ "$shell_basename" == "perl" ]]; then
				#use rlwrap "--history-filename" and "--histsize" params to set history settings
				SHELL_HISTFILE="$shell_home/.${shell_histfile_subname}_history"
				SUDO_RLWRAP_ADDITIONAL_COMMAND_OPTIONS+=("--history-filename" "$SHELL_HISTFILE" "--histsize" "1000")

			#if shell is dash sh ksh
			else
				#the shells use HISTFILE environment variable for history file
				SHELL_HISTFILE="$shell_home/.${shell_histfile_subname}_history"
			fi

		#if shell is python2, lua5.2, lua5.3, lua5.4
		elif [[ " python2 lua5.2 lua5.3 lua5.4 " == *" $shell_basename "* ]]; then
			#the shell does not have a history file or does not use it
			sudo_log 2 "The \"$shell_basename\" shell does not have a history file or does not use it"

		else
			sudo_log_errors "shell_basename \"$shell_basename\" not handled while running \"sudo_set_shell_histfile\""
			return 1
		fi


		#if SHELL_HISTFILE is set
		if [ ! -z "$SHELL_HISTFILE" ]; then
			#if SHELL_HISTFILE is not a valid absolute path
			if [[ ! "$SHELL_HISTFILE" =~ $valid_absolute_path_regex ]]; then
				sudo_log_errors "The ${shell_label}_HISTFILE \"$SHELL_HISTFILE\" is not a valid absolute path"
				return 1
			fi

			#if SHELL_HISTFILE_COMMANDS is set
			if [ ! -z "$SHELL_HISTFILE_COMMANDS" ]; then
				SHELL_HISTFILE_COMMANDS+=$'\n'
			fi

			SHELL_HISTFILE_COMMANDS+="export HISTFILE='${SHELL_HISTFILE//\'/\'\\\'\'}';"

			#find the parent directory of the SHELL_HISTFILE
			SHELL_HISTFILE_BASENAME="${SHELL_HISTFILE##*/}" #strip longest match of */ from start
			SHELL_HISTFILE_PARENT_DIR="${SHELL_HISTFILE:0:${#SHELL_HISTFILE} - ${#SHELL_HISTFILE_BASENAME}}" #substring from 0 to position of basename
			case $SHELL_HISTFILE_PARENT_DIR in *[!/]*/) SHELL_HISTFILE_PARENT_DIR=${SHELL_HISTFILE_PARENT_DIR%"${SHELL_HISTFILE_PARENT_DIR##*[!/]}"};; *[/]) SHELL_HISTFILE_PARENT_DIR="/";; esac #remove trailing slashes if not root
		fi

	else
		#if shell is fish
		if [[ "$shell_basename" == "fish" ]]; then
			#fish uses '--private' flag to disable history
			SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS+=("--private")

		#if shell is python
		elif [[ "$shell_basename" == "python" ]]; then
			#disable the "readline.write_history_file" function that writes history to file
			SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS+=("-c" 'import readline; readline.write_history_file = lambda *args: None')

		#if shell is pry
		elif [[ "$shell_basename" == "pry" ]]; then
			#use the "Pry.config.history_save" config to disable history saving
			#the "--no-history" flag to disable history loading is raising an exception in pry-0.13.1
			#using the "Pry.config.history_load" config option with "-e" to disable history loading
			#does not work, since its already loaded by the time its run
			SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS+=("-e" 'Pry.config.history_save = false;')

		#if shell is node
		elif [[ "$shell_basename" == "node" ]]; then
			#node uses NODE_REPL_HISTORY to define path for history file
			#unsetting it disables history
			SHELL_HISTFILE_COMMANDS="export NODE_REPL_HISTORY='';"

		#if shell is perl
		elif [[ "$shell_basename" == "perl" ]]; then
			#use rlwrap "--history-filename" to set history settings
			SUDO_RLWRAP_ADDITIONAL_COMMAND_OPTIONS+=("--history-filename" "/dev/null")

		#if shell is bash, zsh, dash, sh, ksh
		elif [[ " bash zsh dash sh ksh " == *" $shell_basename "* ]]; then
			#if shell is bash
			#if [[ "$shell_basename" == "bash" ]]; then
				#bash uses 'history' shopt_option to control history, so unset it with a command option
				#for some reason this does not work since bash shell automatically enables history by default for interactive shells
				#can be confirmed by running "shopt -o" in a new interactive shell
				#SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS+=("+o" "history")
			#fi

			#unsetting HISTFILE does not work for all shells like bash since it sets the default value if HISTFILE is not set
			#HISTFILE may still be overridden in a startup or a rc file
			SHELL_HISTFILE_COMMANDS="export HISTFILE='/dev/null';"

		#if shell is ruby, lua5.2, lua5.3, lua5.4, php, python2
		elif [[ " ruby lua5.2 lua5.3 lua5.4 php python2 " == *" $shell_basename "* ]]; then
			#the shell does not have a history file or does not use it or cannot be disabled using any params or environmental variables
			sudo_log 2 "The \"$shell_basename\" shell does not have a history file or does not use it or cannot be disabled using any params or environmental variables"

		else
			sudo_log_errors "shell_basename \"$shell_basename\" not handled while running \"sudo_set_shell_histfile\""
			return 1
		fi
	fi

	return 0

}

sudo_set_sudo_shell_command() {

	local return_value

	sudo_log_literal 2 "\nRunning sudo_set_sudo_shell_command"

	SHELL_ADDITIONAL_COMMAND_OPTIONS=("${SUDO_SHELL_ADDITIONAL_COMMAND_OPTIONS[@]}")
	SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS=("${SUDO_SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS[@]}")

	#set shell command variables
	sudo_set_shell_command "SUDO_SHELL" "$SUDO_SHELL" "$SUDO_SHELL_BASENAME" "$SUDO_SHELL_PARENT_DIR" "$interactive_sudo_shell_required"
	return_value=$?
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failure while running \"sudo_set_shell_command\" for SUDO_SHELL \"$SUDO_SHELL\""
		return $return_value
	fi

	SUDO_SHELL_COMMAND=("${SHELL_COMMAND[@]}")
	SUDO_SHELL_INTERACTIVE_COMMAND=("${SHELL_INTERACTIVE_COMMAND[@]}")
	SUDO_SHELL_COMMAND_PRINT_FORMAT="$SHELL_COMMAND_PRINT_FORMAT"
	SUDO_SHELL_INTERACTIVE_COMMAND_PRINT_FORMAT="$SHELL_INTERACTIVE_COMMAND_PRINT_FORMAT"


	sudo_log 2 "SUDO_SHELL_COMMAND=\"${SUDO_SHELL_COMMAND[*]}\""
	sudo_log 2 "SUDO_SHELL_INTERACTIVE_COMMAND=\"${SUDO_SHELL_INTERACTIVE_COMMAND[*]}\""

	return 0

}

sudo_set_sudo_post_shell_command() {

	local return_value

	sudo_log_literal 2 "\nRunning sudo_set_sudo_post_shell_command"

	SHELL_ADDITIONAL_COMMAND_OPTIONS=()
	SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS=("${SUDO_POST_SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS[@]}")

	#set shell command variables
	sudo_set_shell_command "SUDO_POST_SHELL" "$SUDO_POST_SHELL" "$SUDO_POST_SHELL_BASENAME" "$SUDO_POST_SHELL_PARENT_DIR" 1
	return_value=$?
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failure while running \"sudo_set_shell_command\" for SUDO_POST_SHELL \"$SUDO_POST_SHELL\""
		return $return_value
	fi

	SUDO_POST_SHELL_INTERACTIVE_COMMAND=("${SHELL_INTERACTIVE_COMMAND[@]}")
	SUDO_POST_SHELL_INTERACTIVE_COMMAND_PRINT_FORMAT="$SHELL_INTERACTIVE_COMMAND_PRINT_FORMAT"

	sudo_log 2 "SUDO_POST_SHELL_INTERACTIVE_COMMAND=\"${SUDO_POST_SHELL_INTERACTIVE_COMMAND[*]}\""

	return 0

}

#sudo_set_shell_command shell_label shell shell_basename shell_parent_dir interactive_shell_required
sudo_set_shell_command() {

	local return_value

	#if parameter count is not 5
	if [ $# -ne 5 ]; then
		sudo_log_errors "Invalid parameter count to \"sudo_set_shell_command\""
		return 1
	fi

	local shell_label="$1"
	local shell="$2"
	local shell_basename="$3"
	local shell_parent_dir="$4"
	local interactive_shell_required="$5"

	local shell_dependency_label=""
	local shell_dependency=""
	local shell_interactive_dependency_label=""
	local shell_interactive_dependency=""

	SHELL_COMMAND_PRINT_FORMAT="%q "
	SHELL_INTERACTIVE_COMMAND_PRINT_FORMAT="%q "

	#if shell is bash
	if [[ "$shell_basename" == "bash" ]]; then
		SHELL_COMMAND=("$shell" "--noprofile" "--norc" "${SHELL_ADDITIONAL_COMMAND_OPTIONS[@]}")
		SHELL_INTERACTIVE_COMMAND=("$shell" "${SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS[@]}" "-i")

	#if shell is zsh
	elif [[ "$shell_basename" == "zsh" ]]; then
		SHELL_COMMAND=("$shell" "--no-rcs" "${SHELL_ADDITIONAL_COMMAND_OPTIONS[@]}")
		SHELL_INTERACTIVE_COMMAND=("$shell" "${SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS[@]}" "-i")

	#if shell is python, python2
	elif [[ " python python2 " == *" $shell_basename "* ]]; then
		SHELL_COMMAND=("$shell" "${SHELL_ADDITIONAL_COMMAND_OPTIONS[@]}")
		SHELL_INTERACTIVE_COMMAND=("$shell" "-i" "${SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS[@]}")

	#if shell is ruby
	elif [[ "$shell_basename" == "ruby" ]]; then
		#the ruby interactive shell is named irb
		SHELL_COMMAND=("$shell" "${SHELL_ADDITIONAL_COMMAND_OPTIONS[@]}")
		SHELL_INTERACTIVE_COMMAND=("$shell_parent_dir/irb" "${SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS[@]}")

		shell_interactive_dependency_label="irb"
		shell_interactive_dependency="$TERMUX_BIN/irb"

	#if shell is pry
	elif [[ "$shell_basename" == "pry" ]]; then
		#pry does not support passing scripts, ruby must be used instead
		SHELL_COMMAND=()
		SHELL_INTERACTIVE_COMMAND=("$shell" "${SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS[@]}")

	#if shell is perl
	elif [[ "$shell_basename" == "perl" ]]; then
		SHELL_COMMAND=("$shell" "${SHELL_ADDITIONAL_COMMAND_OPTIONS[@]}")

		#the perl interactive shell is started with rlwrap
		#rlwrap -A -pgreen -S "perl> " perl -wnE 'say eval()//$@'
		local shell_interactive_command_string;
		printf -v "shell_interactive_command_string" "%q " \
			"$TERMUX_BIN/rlwrap" "-A" "-pgreen" "-S" "perl> " "${SUDO_RLWRAP_ADDITIONAL_COMMAND_OPTIONS[@]}" \
				"$shell_parent_dir/perl" "${SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS[@]}" "-wnE" 'say eval()//$@'
		SHELL_INTERACTIVE_COMMAND=("$shell_interactive_command_string")
		SHELL_INTERACTIVE_COMMAND_PRINT_FORMAT="%s"

		shell_interactive_dependency_label="rlwrap"
		shell_interactive_dependency="$TERMUX_BIN/rlwrap"

	#if shell is php
	elif [[ "$shell_basename" == "php" ]]; then
		SHELL_COMMAND=("$shell" "${SHELL_ADDITIONAL_COMMAND_OPTIONS[@]}")
		SHELL_INTERACTIVE_COMMAND=("$shell" "${SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS[@]}" "-a")

	#if shell is dash, sh, ksh, fish, node, lua5.2, lua5.3, lua5.4
		elif [[ " dash sh ksh fish node lua5.2 lua5.3 lua5.4 " == *" $shell_basename "* ]]; then
		SHELL_COMMAND=("$shell" "${SHELL_ADDITIONAL_COMMAND_OPTIONS[@]}")
		SHELL_INTERACTIVE_COMMAND=("$shell" "${SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS[@]}" "-i")
	else
		sudo_log_errors "shell_basename \"$shell_basename\" not handled while running \"sudo_set_shell_command\""
		return 1
	fi

	#if interactive_shell_required is not enabled
	if [[ "$interactive_shell_required" != "1" ]]; then
		#if shell_dependency is set
		if [ ! -z "$shell_dependency" ]; then
			#if use_root_for_path_search_and_validation is enabled
			if [[ "$use_root_for_path_search_and_validation" == "1" ]]; then
				sudo_unset_pre_su_variables
				SUDO_POST_SHELL="$($SU_ENV_COMMAND "source '${SUDO_SCRIPT_PATH//\'/\'\\\'\'}'; sudo_run_file_type_tests_on_path \"$shell_dependency_label\" '${shell_dependency//\'/\'\\\'\'}' 1 1 1 \"frx\"" < /dev/null)"
				return_value=$?
				sudo_set_post_su_variables
			else
				sudo_run_file_type_tests_on_path "$shell_dependency_label" "$shell_dependency" 1 1 1 "frx"
				return_value=$?
			fi
			if [ $return_value -ne 0 ]; then
				sudo_log_errors "\"$shell_dependency_label\" is required to run non-interactive \"$shell_basename\" shell"
				return $return_value
			fi
		fi
	else
		#if shell_interactive_dependency is set
		if [ ! -z "$shell_interactive_dependency" ]; then
			#if use_root_for_path_search_and_validation is enabled
			if [[ "$use_root_for_path_search_and_validation" == "1" ]]; then
				sudo_unset_pre_su_variables
				SUDO_POST_SHELL="$($SU_ENV_COMMAND "source '${SUDO_SCRIPT_PATH//\'/\'\\\'\'}'; sudo_run_file_type_tests_on_path \"$shell_interactive_dependency_label\" '${shell_interactive_dependency//\'/\'\\\'\'}' 1 1 1 \"frx\"" < /dev/null)"
				return_value=$?
				sudo_set_post_su_variables
			else
				sudo_run_file_type_tests_on_path "$shell_interactive_dependency_label" "$shell_interactive_dependency" 1 1 1 "frx"
				return_value=$?
			fi
			if [ $return_value -ne 0 ]; then
				sudo_log_errors "\"$shell_interactive_dependency_label\" is required to run interactive \"$shell_basename\" shell"
				return $return_value
			fi
		fi
	fi

	return 0

}

sudo_setup_sudo_shell_home_and_working_environment_wrapper() {

	local return_value

	sudo_log_literal 2 "\n\n\nRunning sudo_setup_sudo_shell_home_and_working_environment_wrapper stage 1"

	SETUP_SUDO_TEMP_DIRECTORY=0
	SUDO_TEMP_DIRECTORY_FD=""


	#if command_type equals "script" and
	if [[ "$command_type" == "script" ]]; then
		#enable SETUP_SUDO_TEMP_DIRECTORY if required
		sudo_check_if_setting_up_sudo_temp_directory_is_required || return $?

		#if SETUP_SUDO_TEMP_DIRECTORY is enabled
		if [[ "$SETUP_SUDO_TEMP_DIRECTORY" == "1" ]]; then

			#find an unused fd that is passed to su which the function sudo_setup_sudo_temp_directory will use to write the SUDO_TEMP_DIRECTORY value
			#which is later read after su returns
			#stdout cannot be used to return SUDO_TEMP_DIRECTORY from su using a subshell due to logging and possibly other output to stdout
			sudo_get_unsed_file_descriptor "SUDO_TEMP_DIRECTORY_FD"
			return_value=$?
			if [ $return_value -ne 0 ] || [[ ! "$SUDO_TEMP_DIRECTORY_FD" =~ $valid_number_regex ]]; then
				sudo_log_errors "Failure while getting an unused file descriptor to write SUDO_TEMP_DIRECTORY"
				sudo_log_errors "SUDO_TEMP_DIRECTORY_FD = \"$SUDO_TEMP_DIRECTORY_FD\""
				if [ $return_value -eq 0 ]; then
					return_value=1
				fi
				return $return_value
			fi

			#android fd directory is /proc/self/fd
			#using $$ instead of self so that su can access it
			SUDO_TEMP_DIRECTORY_FD_PATH="/proc/$$/fd/$SUDO_TEMP_DIRECTORY_FD"

			sudo_log 2 "SUDO_TEMP_DIRECTORY_FD_PATH=\"$SUDO_TEMP_DIRECTORY_FD_PATH\""

			#write empty string to fd just to create it
			eval "exec $SUDO_TEMP_DIRECTORY_FD<" <(echo -n "")
			return_value=$?
			if [ $return_value -ne 0 ]; then
				sudo_log_errors "Failure while opening SUDO_TEMP_DIRECTORY_FD \"$SUDO_TEMP_DIRECTORY_FD\" to write SUDO_TEMP_DIRECTORY"
				return $return_value
			fi
		fi
	fi

	#if SETUP_SUDO_TEMP_DIRECTORY is not enabled and dry_run_sudo is enabled,
	#then just return since no need to create homes, rc files, history files, work dir and temp dir
	if [[ "$SETUP_SUDO_TEMP_DIRECTORY" != "1" ]] && [[ "$dry_run_sudo" == "1" ]]; then
		return 0
	fi



	#remount android rootfs "/" partition and/or system "/system" partition as rw if
	#they need to be used for SUDO_SHELL_HOME, SUDO_POST_SHELL_HOME or SUDO_SHELL_WORKING_DIR
	sudo_remount_partitions_for_sudo_shell_homes "rw" || return $?



	local -a SU_ENV_COMMAND_ADDITIONAL_VARIABLES_TO_EXPORT_ARRAY=(
		SUDO_SHELL_HOME_PARENT_DIR
		SUDO_SHELL_HOME

		sudo_shells_automatically_create_rc_files
		SUDO_SHELL_RCFILE_PARENT_DIR
		SUDO_SHELL_RCFILE
		SUDO_SHELL_RCFILE_VALUE

		sudo_shells_automatically_create_history_files
		SUDO_SHELL_HISTFILE_PARENT_DIR
		SUDO_SHELL_HISTFILE

		SUDO_POST_SHELL_HOME_PARENT_DIR
		SUDO_POST_SHELL_HOME

		sudo_shells_automatically_create_rc_files
		SUDO_POST_SHELL_RCFILE_PARENT_DIR
		SUDO_POST_SHELL_RCFILE
		SUDO_POST_SHELL_RCFILE_VALUE

		sudo_shells_automatically_create_history_files
		SUDO_POST_SHELL_HISTFILE_PARENT_DIR
		SUDO_POST_SHELL_HISTFILE

		SUDO_SHELL_WORKING_DIR

		remove_previous_sudo_temp_files
		SETUP_SUDO_TEMP_DIRECTORY
		SUDO_TEMP_DIRECTORY_PARENT_DIRECTORY
		SUDO_TEMP_DIRECTORY_PREFIX
		SUDO_TEMP_DIRECTORY
		SUDO_TEMP_DIRECTORY_FD_PATH

		TERMUX_FILES
		TERMUX_PREFIX
		TERMUX_PREFIX_BASENAME
		TERMUX_HOME
		TERMUX_HOME_BASENAME

		dry_run_sudo
	)

	local var

	#export additional variables that are required by su that were not exported by sudo_export_or_unexport_shared_variables_for_su
	for var in "${SU_ENV_COMMAND_ADDITIONAL_VARIABLES_TO_EXPORT_ARRAY[@]}"; do
	    export "${var}"
	done



	sudo_log_literal 2 "\nRunning sudo_setup_sudo_shell_home_and_working_environment"

	#run sudo_setup_sudo_shell_home_and_working_environment that sets up the sudo environment
	sudo_unset_pre_su_variables
	$SU_ENV_COMMAND "source '${SUDO_SCRIPT_PATH//\'/\'\\\'\'}'; sudo_setup_sudo_shell_home_and_working_environment"
	return_value=$?
	sudo_set_post_su_variables
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failure while running \"sudo_setup_sudo_shell_home_and_working_environment\""
		return $return_value
	fi



	#remove export property from additional variables exported earlier
	for var in "${SU_ENV_COMMAND_ADDITIONAL_VARIABLES_TO_EXPORT_ARRAY[@]}"; do
	    export -n "${var}"
	done




	sudo_log_literal 2 "\nRunning sudo_setup_sudo_shell_home_and_working_environment_wrapper stage 2"

	#if SETUP_SUDO_TEMP_DIRECTORY is enabled
	if [[ "$SETUP_SUDO_TEMP_DIRECTORY" == "1" ]]; then
		#if SUDO_TEMP_DIRECTORY_FD_PATH does not exist
		if [ ! -e "$SUDO_TEMP_DIRECTORY_FD_PATH" ]; then
			sudo_log_errors "The SUDO_TEMP_DIRECTORY_FD_PATH \"$SUDO_TEMP_DIRECTORY_FD_PATH\" does not exist that needs to be used to read SUDO_TEMP_DIRECTORY"
			return 1
		fi

		#read the value of SUDO_TEMP_DIRECTORY from SUDO_TEMP_DIRECTORY_FD_PATH which the sudo_setup_sudo_temp_directory function would have written while running su
		SUDO_TEMP_DIRECTORY="$(cat "$SUDO_TEMP_DIRECTORY_FD_PATH")"
		return_value=$?
		if [ $return_value -ne 0 ]; then
			sudo_log_errors "Failure to read SUDO_TEMP_DIRECTORY from SUDO_TEMP_DIRECTORY_FD_PATH \"$SUDO_TEMP_DIRECTORY_FD_PATH\""
			return $return_value
		fi

		#if SUDO_TEMP_DIRECTORY is not a valid absolute path
		if [[ ! "$SUDO_TEMP_DIRECTORY" =~ $valid_absolute_path_regex ]]; then
			sudo_log_errors "The SUDO_TEMP_DIRECTORY \"$SUDO_TEMP_DIRECTORY\" is not a valid absolute path"
			return 1
		fi

		sudo_log 2 "SUDO_TEMP_DIRECTORY=\"$SUDO_TEMP_DIRECTORY\""

		#if SUDO_TEMP_DIRECTORY_FD is set, then close it
		if [ ! -z "$SUDO_TEMP_DIRECTORY_FD" ]; then
			exec {SUDO_TEMP_DIRECTORY_FD}>&-
			SUDO_TEMP_DIRECTORY_FD=""
		fi
	fi

	return 0

}

sudo_setup_sudo_shell_home_and_working_environment() {

	local return_value

	#sudo_setup_shell_home shell_label shell_home_parent_dir shell_home shell_automatically_create_rc_file shell_rcfile_parent_dir shell_rcfile shell_rcfile_value  shell_histfile_parent_dir shell_histfile
	sudo_setup_shell_home "SUDO_SHELL" "$SUDO_SHELL_HOME_PARENT_DIR" "$SUDO_SHELL_HOME" "$sudo_shells_automatically_create_rc_files" "$SUDO_SHELL_RCFILE_PARENT_DIR" "$SUDO_SHELL_RCFILE" "$SUDO_SHELL_RCFILE_VALUE" "$sudo_shells_automatically_create_history_files" "$SUDO_SHELL_HISTFILE_PARENT_DIR" "$SUDO_SHELL_HISTFILE"
	return_value=$?
	if [ $return_value -ne 0 ] && [ $return_value -ne 112 ]; then
		sudo_log_errors "Failed to setup SUDO_SHELL_HOME"
		return $return_value
	fi

	#if dry_run_sudo is not enabled, only then run it
	#if it is enabled, then we must be running this function because SETUP_SUDO_TEMP_DIRECTORY was enabled
	#in which case no need to create post shell home and work dir
	if [[ "$dry_run_sudo" != "1" ]]; then

		#if SUDO_POST_SHELL_HOME is set
		if [ ! -z "$SUDO_POST_SHELL_HOME" ]; then
			#if SUDO_SHELL and SUDO_POST_SHELL home, rcfile or histfiles are different
			if [[ "$SUDO_POST_SHELL_HOME" != "$SUDO_SHELL_HOME" ]] || \
					[[ "$SUDO_POST_SHELL_RCFILE" != "$SUDO_SHELL_RCFILE" ]] || \
				 		[[ "$SUDO_POST_SHELL_HISTFILE" != "$SUDO_SHELL_HISTFILE" ]]; then
				#sudo_setup_shell_home shell_label shell_home_parent_dir shell_home shell_automatically_create_rc_file shell_rcfile_parent_dir shell_rcfile shell_rcfile_value shell_histfile_parent_dir  shell_histfile
				sudo_setup_shell_home "SUDO_POST_SHELL"  "$SUDO_POST_SHELL_HOME_PARENT_DIR" "$SUDO_POST_SHELL_HOME" "$sudo_shells_automatically_create_rc_files" "$SUDO_POST_SHELL_RCFILE_PARENT_DIR" "$SUDO_POST_SHELL_RCFILE" "$SUDO_POST_SHELL_RCFILE_VALUE" "$sudo_shells_automatically_create_history_files" "$SUDO_POST_SHELL_HISTFILE_PARENT_DIR" "$SUDO_POST_SHELL_HISTFILE"
				return_value=$?
				if [ $return_value -ne 0 ] && [ $return_value -ne 112 ]; then
					sudo_log_errors "Failed to setup SUDO_POST_SHELL_HOME"
					return $return_value
				fi
			fi
		fi

		#if SUDO_SHELL_WORKING_DIR is set
		if [ ! -z "$SUDO_SHELL_WORKING_DIR" ]; then
			#create SUDO_SHELL_WORKING_DIR if missing
			sudo_setup_sudo_shell_working_dir || return $?
		fi
	fi

	#setup SUDO_TEMP_DIRECTORY
	sudo_setup_sudo_temp_directory
	return_value=$?
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failure while running \"sudo_setup_sudo_temp_directory\""
		return $return_value
	fi

	return 0

}

#sudo_setup_shell_home shell_label shell_home_parent_dir shell_home shell_automatically_create_rc_file shell_rcfile_parent_dir shell_rcfile shell_rcfile_value  shell_histfile_parent_dir shell_histfile
sudo_setup_shell_home() {

	local return_value

	#if parameter count is not 10
	if [ $# -ne 10 ]; then
		sudo_log_errors "Invalid parameter count to \"sudo_setup_shell_home\""
		return 1
	fi

	local shell_label="$1"
	local shell_home_parent_dir="$2"
	local shell_home="$3"
	local shell_automatically_create_rc_file="$4"
	local shell_rcfile_parent_dir="$5"
	local shell_rcfile="$6"
	local shell_rcfile_value="$7"
	local shell_automatically_create_history_file="$8"
	local shell_histfile_parent_dir="$9"
	local shell_histfile="${10}"

	local create_shell_home_if_it_does_not_exist
	local only_set_perms_and_ownership_on_creation_of_shell_home
	local shell_home_ownership
	local shell_home_permission
	local shell_home_file_type_tests

	local create_shell_rcfile_parent_dir_if_it_does_not_exist
	local only_set_perms_and_ownership_on_creation_of_shell_rcfile_parent_dir
	local shell_rcfile_parent_dir_ownership
	local shell_rcfile_parent_dir_permission
	local shell_rcfile_parent_dir_file_type_tests

	local create_shell_rcfile_if_it_does_not_exist
	local only_set_perms_and_ownership_on_creation_of_shell_rcfile
	local shell_rcfile_ownership
	local shell_rcfile_permission
	local shell_rcfile_file_type_tests

	local create_shell_histfile_parent_dir_if_it_does_not_exist
	local only_set_perms_and_ownership_on_creation_of_shell_histfile_parent_dir
	local shell_histfile_parent_dir_ownership
	local shell_histfile_parent_dir_permission
	local shell_histfile_parent_dir_file_type_tests

	local create_shell_histfile_if_it_does_not_exist
	local only_set_perms_and_ownership_on_creation_of_shell_histfile
	local shell_histfile_ownership
	local shell_histfile_permission
	local shell_histfile_file_type_tests

	local validation_result

	sudo_log_literal 2 "\nRunning sudo_setup_shell_home for $shell_label"



	create_shell_home_if_it_does_not_exist=1
	only_set_perms_and_ownership_on_creation_of_shell_home=1
	shell_home_permission="700"
	shell_home_file_type_tests="rwx"

	#validate if shell_home is a whitelisted path under TERMUX_FILES
	sudo_validate_path_is_a_whitelisted_path_under_termux_files "${shell_label}_HOME" "$shell_home"
	return_value=$?
	if [ $return_value -ne 0 ] && [ $return_value -ne 2 ] &&  [ $return_value -ne 3 ]; then
		return $return_value
	fi

	validation_result=$return_value

	#if shell_home is a whitelisted path under TERMUX_FILES
	if [ $validation_result -eq 0 ]; then
		#if shell_home and TERMUX_HOME are same, then root ownership
		#must not be set to it otherwise termux app non-root shell will not work
		if [[ "$shell_home" == "$TERMUX_HOME" ]]; then
			shell_home_ownership="--reference=\"$TERMUX_FILES\""
		else
			shell_home_ownership="root:root"
		fi
	#if shell_home is a blacklisted path under TERMUX_FILES
	elif [ $validation_result -eq 2 ]; then
		sudo_log_errors "The \"$shell_home\" cannot be used as ${shell_label}_HOME"
		return 1
	#if shell_home is not under TERMUX_FILES
	else
		shell_home_ownership="--reference='${shell_home_parent_dir//\'/\'\\\'\'}'"
	fi



	#if shell_automatically_create_rc_file is not enabled or dry_run_sudo is enabled, then unset shell_rcfile
	if [[ "$shell_automatically_create_rc_file" != "1" ]] || [[ "$dry_run_sudo" == "1" ]]; then
		shell_rcfile=""
	fi

	#if shell_rcfile is set
	if [ ! -z "$shell_rcfile" ]; then
		#if shell_rcfile_parent_dir is not the same as shell_home or one of subdirectories
		#otherwise remounting rootfs and system partition would become too complicated
		if [[ "$shell_rcfile_parent_dir" != "$shell_home" ]] && [[ "$shell_rcfile_parent_dir" != "$shell_home"/* ]]; then
			sudo_log_errors "The ${shell_label}_RCFILE_PARENT_DIR \"$shell_rcfile_parent_dir\" must be same as ${shell_label}_HOME \"$shell_home\" or be one of its subdirectories"
			return 1
		fi

		create_shell_rcfile_parent_dir_if_it_does_not_exist=1
		only_set_perms_and_ownership_on_creation_of_shell_rcfile_parent_dir=1
		shell_rcfile_parent_dir_permission="700"
		shell_rcfile_parent_dir_file_type_tests="rwx"

		create_shell_rcfile_if_it_does_not_exist=1
		only_set_perms_and_ownership_on_creation_of_shell_rcfile=1
		shell_rcfile_permission="600"
		shell_rcfile_file_type_tests="rw"

		#validate if shell_rcfile_parent_dir is a whitelisted path under TERMUX_FILES
		sudo_validate_path_is_a_whitelisted_path_under_termux_files "${shell_label}_RCFILE_PARENT_DIR" "$shell_rcfile_parent_dir"
			return_value=$?
		if [ $return_value -ne 0 ] && [ $return_value -ne 2 ] &&  [ $return_value -ne 3 ]; then
			return $return_value
		fi

		validation_result=$return_value

		#if shell_rcfile_parent_dir is a whitelisted path under TERMUX_FILES
		if [ $validation_result -eq 0 ]; then
			#if shell_rcfile_parent_dir and TERMUX_HOME are same, then root ownership
			#must not be set to it otherwise termux app non-root shell will not work
			if [[ "$shell_rcfile_parent_dir" == "$TERMUX_HOME" ]]; then
				shell_rcfile_parent_dir_ownership="--reference=\"$TERMUX_FILES\""
				shell_rcfile_ownership="--reference=\"$TERMUX_FILES\""
			else
				shell_rcfile_parent_dir_ownership="root:root"
				shell_rcfile_ownership="root:root"
			fi
		#if shell_rcfile_parent_dir is a blacklisted path under TERMUX_FILES
		elif [ $validation_result -eq 2 ]; then
			sudo_log_errors "The \"$shell_rcfile_parent_dir\" cannot be used as ${shell_label}_RCFILE_PARENT_DIR"
			return 1
		#if shell_rcfile_parent_dir is not under TERMUX_FILES
		else
			#if shell_rcfile_parent_dir and shell_home are same
			if [[ "$shell_rcfile_parent_dir" == "$shell_home" ]]; then
				shell_rcfile_parent_dir_ownership="--reference='${shell_home_parent_dir//\'/\'\\\'\'}'"
				shell_rcfile_ownership="--reference='${shell_home_parent_dir//\'/\'\\\'\'}'"
			else

				#find the parent directory of the shell_rcfile_parent_dir
				shell_rcfile_parent_dir_basename="${shell_rcfile_parent_dir##*/}" #strip longest match of */ from start
				shell_rcfile_parent_dir_parent_dir="${shell_rcfile_parent_dir:0:${#shell_rcfile_parent_dir} - ${#shell_rcfile_parent_dir_basename}}" #substring from 0 to position of basename
				case $shell_rcfile_parent_dir_parent_dir in *[!/]*/) shell_rcfile_parent_dir_parent_dir=${shell_rcfile_parent_dir_parent_dir%"${shell_rcfile_parent_dir_parent_dir##*[!/]}"};; *[/]) shell_rcfile_parent_dir_parent_dir="/";; esac #remove trailing slashes if not root

				shell_rcfile_parent_dir_ownership="--reference='${shell_rcfile_parent_dir_parent_dir//\'/\'\\\'\'}'"
				shell_rcfile_ownership="--reference='${shell_rcfile_parent_dir//\'/\'\\\'\'}'"
			fi
		fi
	fi



	#if shell_automatically_create_history_files is not enabled or dry_run_sudo is enabled, then unset shell_histfile
	if [[ "$shell_automatically_create_history_file" != "1" ]] || [[ "$dry_run_sudo" == "1" ]]; then
		shell_histfile=""
	fi

	#if shell_histfile is set
	if [ ! -z "$shell_histfile" ]; then

		#if shell_histfile_parent_dir is not the same as shell_home or one of subdirectories
		#otherwise remounting rootfs and system partition would become too complicated
		if [[ "$shell_histfile_parent_dir" != "$shell_home" ]] && [[ "$shell_histfile_parent_dir" != "$shell_home"/* ]]; then
			sudo_log_errors "The ${shell_label}_HISTFILE_PARENT_DIR \"$shell_histfile_parent_dir\" must be same as ${shell_label}_HOME \"$shell_home\" or be one of its subdirectories"
			return 1
		fi

		create_shell_histfile_parent_dir_if_it_does_not_exist=1
		only_set_perms_and_ownership_on_creation_of_shell_histfile_parent_dir=1
		shell_histfile_parent_dir_permission="700"
		shell_histfile_parent_dir_file_type_tests="rwx"

		create_shell_histfile_if_it_does_not_exist=1
		only_set_perms_and_ownership_on_creation_of_shell_histfile=1
		shell_histfile_permission="600"
		shell_histfile_file_type_tests="rw"

		#validate if shell_histfile_parent_dir is a whitelisted path under TERMUX_FILES
		sudo_validate_path_is_a_whitelisted_path_under_termux_files "${shell_label}_HISTFILE_PARENT_DIR" "$shell_histfile_parent_dir"
		return_value=$?
		if [ $return_value -ne 0 ] && [ $return_value -ne 2 ] &&  [ $return_value -ne 3 ]; then
			return $return_value
		fi

		validation_result=$return_value

		#if shell_histfile_parent_dir is a whitelisted path under TERMUX_FILES
		if [ $validation_result -eq 0 ]; then
			#if shell_histfile_parent_dir and TERMUX_HOME are same, then root ownership
			#must not be set to it otherwise termux app non-root shell will not work
			if [[ "$shell_histfile_parent_dir" == "$TERMUX_HOME" ]]; then
				shell_histfile_parent_dir_ownership="--reference=\"$TERMUX_FILES\""
				shell_histfile_ownership="--reference=\"$TERMUX_FILES\""
			else
				shell_histfile_parent_dir_ownership="root:root"
				shell_histfile_ownership="root:root"
			fi
		#if shell_histfile_parent_dir is a blacklisted path under TERMUX_FILES
		elif [ $validation_result -eq 2 ]; then
			sudo_log_errors "The \"$shell_histfile_parent_dir\" cannot be used as ${shell_label}_HISTFILE_PARENT_DIR"
			return 1
		#if shell_histfile_parent_dir is not under TERMUX_FILES
		else
			#if shell_histfile_parent_dir and shell_home are same
			if [[ "$shell_histfile_parent_dir" == "$shell_home" ]]; then
				shell_histfile_parent_dir_ownership="--reference='${shell_home_parent_dir//\'/\'\\\'\'}'"
				shell_histfile_ownership="--reference='${shell_home_parent_dir//\'/\'\\\'\'}'"
			else
				#find the parent directory of the shell_histfile_parent_dir
				shell_histfile_parent_dir_basename="${shell_histfile_parent_dir##*/}" #strip longest match of */ from start
				shell_histfile_parent_dir_parent_dir="${shell_histfile_parent_dir:0:${#shell_histfile_parent_dir} - ${#shell_histfile_parent_dir_basename}}" #substring from 0 to position of basename
				case $shell_histfile_parent_dir_parent_dir in *[!/]*/) shell_histfile_parent_dir_parent_dir=${shell_histfile_parent_dir_parent_dir%"${shell_histfile_parent_dir_parent_dir##*[!/]}"};; *[/]) shell_histfile_parent_dir_parent_dir="/";; esac #remove trailing slashes if not root

				shell_histfile_parent_dir_ownership="--reference='${shell_histfile_parent_dir_parent_dir//\'/\'\\\'\'}'"
				shell_histfile_ownership="--reference='${shell_histfile_parent_dir//\'/\'\\\'\'}'"
			fi
		fi
	fi



	sudo_create_shell_home "$shell_label" \
        "$shell_home" "$create_shell_home_if_it_does_not_exist" "$only_set_perms_and_ownership_on_creation_of_shell_home" "$shell_home_ownership" "$shell_home_permission" "$shell_home_file_type_tests" \
        "$shell_rcfile_parent_dir" "$create_shell_rcfile_parent_dir_if_it_does_not_exist" "$only_set_perms_and_ownership_on_creation_of_shell_rcfile_parent_dir" "$shell_rcfile_parent_dir_ownership" "$shell_rcfile_parent_dir_permission" "$shell_rcfile_parent_dir_file_type_tests" \
        "$shell_rcfile" "$create_shell_rcfile_if_it_does_not_exist" "$shell_rcfile_value" "$only_set_perms_and_ownership_on_creation_of_shell_rcfile" "$shell_rcfile_ownership" "$shell_rcfile_permission" "$shell_rcfile_file_type_tests" \
        "$shell_histfile_parent_dir" "$create_shell_histfile_parent_dir_if_it_does_not_exist" "$only_set_perms_and_ownership_on_creation_of_shell_histfile_parent_dir" "$shell_histfile_parent_dir_ownership" "$shell_histfile_parent_dir_permission" "$shell_histfile_parent_dir_file_type_tests" \
        "$shell_histfile" "$create_shell_histfile_if_it_does_not_exist" "$only_set_perms_and_ownership_on_creation_of_shell_histfile" "$shell_histfile_ownership" "$shell_histfile_permission" "$shell_histfile_file_type_tests"
	return_value=$?
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failure while running \"sudo_create_shell_home\""
		return $return_value
	fi

	return 0

}

#sudo_create_shell_home shell_label
#shell_home create_shell_home_if_it_does_not_exist only_set_perms_and_ownership_on_creation_of_shell_home shell_home_ownership shell_home_permission shell_home_file_type_tests
#shell_rcfile_parent_dir create_shell_rcfile_parent_dir_if_it_does_not_exist only_set_perms_and_ownership_on_creation_of_shell_rcfile_parent_dir shell_rcfile_parent_dir_ownership shell_rcfile_parent_dir_permission shell_rcfile_parent_dir_file_type_tests
#shell_rcfile create_shell_rcfile_if_it_does_not_exist shell_rcfile_value only_set_perms_and_ownership_on_creation_of_shell_rcfile shell_rcfile_ownership shell_rcfile_permission shell_rcfile_file_type_tests
#shell_histfile_parent_dir create_shell_histfile_parent_dir_if_it_does_not_exist only_set_perms_and_ownership_on_creation_of_shell_histfile_parent_dir shell_histfile_parent_dir_ownership shell_histfile_parent_dir_permission shell_histfile_parent_dir_file_type_tests
#shell_histfile create_shell_histfile_if_it_does_not_exist only_set_perms_and_ownership_on_creation_of_shell_histfile shell_histfile_ownership shell_histfile_permission shell_histfile_file_type_tests
sudo_create_shell_home() {

	local return_value

	#if parameter count is not 32
	if [ $# -ne 32 ]; then
		sudo_log_errors "Invalid parameter count to \"sudo_create_shell_home\""
		return 1
	fi

	local shell_label="$1"

	local shell_home="$2"
	local create_shell_home_if_it_does_not_exist="$3"
	local only_set_perms_and_ownership_on_creation_of_shell_home="$4"
	local shell_home_ownership="$5"
	local shell_home_permission="$6"
	local shell_home_file_type_tests="$7"


	local shell_rcfile_parent_dir="$8"
	local create_shell_rcfile_parent_dir_if_it_does_not_exist="$9"
	local only_set_perms_and_ownership_on_creation_of_shell_rcfile_parent_dir="${10}"
	local shell_rcfile_parent_dir_ownership="${11}"
	local shell_rcfile_parent_dir_permission="${12}"
	local shell_rcfile_parent_dir_file_type_tests="${13}"


	local shell_rcfile="${14}"
	local create_shell_rcfile_if_it_does_not_exist="${15}"
	local shell_rcfile_value="${16}"
	local only_set_perms_and_ownership_on_creation_of_shell_rcfile="${17}"
	local shell_rcfile_ownership="${18}"
	local shell_rcfile_permission="${19}"
	local shell_rcfile_file_type_tests="${20}"


	local shell_histfile_parent_dir="${21}"
	local create_shell_histfile_parent_dir_if_it_does_not_exist="${22}"
	local only_set_perms_and_ownership_on_creation_of_shell_histfile_parent_dir="${23}"
	local shell_histfile_parent_dir_ownership="${24}"
	local shell_histfile_parent_dir_permission="${25}"
	local shell_histfile_parent_dir_file_type_tests="${26}"

	local shell_histfile="${27}"
	local create_shell_histfile_if_it_does_not_exist="${28}"
	local only_set_perms_and_ownership_on_creation_of_shell_histfile="${29}"
	local shell_histfile_ownership="${30}"
	local shell_histfile_permission="${31}"
	local shell_histfile_file_type_tests="${32}"



	#create shell_home if missing and set ownership and permissions
	#sudo_create_modify_validate_directory directory_path_label directory_path check_if_absolute_path create_directory_if_it_does_not_exist only_set_perms_and_ownership_on_creation directory_chown_command_options directory_chmod_command_options sub_directories_chown_command_options sub_directories_chmod_command_options sub_files_chown_command_options sub_files_chmod_command_options file_type_tests
	sudo_create_modify_validate_directory "${shell_label}_HOME" "$shell_home" 1 "$create_shell_home_if_it_does_not_exist" "$only_set_perms_and_ownership_on_creation_of_shell_home" "$shell_home_ownership" "$shell_home_permission" - - - - "$shell_home_file_type_tests" || return $?



	#if shell_rcfile is set
	if [ ! -z "$shell_rcfile" ]; then
		#if shell_home and shell_rcfile_parent_dir are not same
		if [[ "$shell_home" != "$shell_rcfile_parent_dir" ]]; then
			#create shell_rcfile_parent_dir if missing and set ownership and permissions
			#sudo_create_modify_validate_directory directory_path_label directory_path check_if_absolute_path create_directory_if_it_does_not_exist directory_chown_command_options directory_chmod_command_options sub_directories_chown_command_options sub_directories_chmod_command_options sub_files_chown_command_options sub_files_chmod_command_options file_type_tests
			sudo_create_modify_validate_directory "${shell_label}_RCFILE_PARENT_DIR" "$shell_rcfile_parent_dir" 1 "$create_shell_rcfile_parent_dir_if_it_does_not_exist" "$only_set_perms_and_ownership_on_creation_of_shell_rcfile_parent_dir" "$shell_rcfile_parent_dir_ownership" "$shell_rcfile_parent_dir_permission" - - - - "$shell_rcfile_parent_dir_file_type_tests" || return $?
		fi

		#create shell_rcfile if missing and set ownership and permissions
		#sudo_create_modify_validate_file file_path_label file_path check_if_absolute_path create_file_if_it_does_not_exist file_creation_command_options file_content only_set_perms_and_ownership_on_creation file_chown_command_options file_chmod_command_options file_type_tests
		sudo_create_modify_validate_file "${shell_label}_RCFILE" "$shell_rcfile" 1 "$create_shell_rcfile_if_it_does_not_exist" "%s" "$shell_rcfile_value" "$only_set_perms_and_ownership_on_creation_of_shell_rcfile" "$shell_rcfile_ownership" "$shell_rcfile_permission" "$shell_rcfile_file_type_tests" || return $?
	fi



	#if shell_histfile is set
	if [ ! -z "$shell_histfile" ]; then
		#if shell_home and shell_histfile_parent_dir are not same
		#and shell_rcfile_parent_dir shell_histfile_parent_dir are not same
		if [[ "$shell_home" != "$shell_histfile_parent_dir" ]] && [[ "$shell_rcfile_parent_dir" != "$shell_histfile_parent_dir" ]]; then
			#create shell_histfile_parent_dir if missing and set ownership and permissions
			#sudo_create_modify_validate_directory directory_path_label directory_path check_if_absolute_path create_directory_if_it_does_not_exist directory_chown_command_options directory_chmod_command_options sub_directories_chown_command_options sub_directories_chmod_command_options sub_files_chown_command_options sub_files_chmod_command_options file_type_tests
			sudo_create_modify_validate_directory "${shell_label}_HISTFILE_PARENT_DIR" "$shell_histfile_parent_dir" 1 "$create_shell_histfile_parent_dir_if_it_does_not_exist" "$only_set_perms_and_ownership_on_creation_of_shell_histfile_parent_dir" "$shell_histfile_parent_dir_ownership" "$shell_histfile_parent_dir_permission" - - - - "$shell_histfile_parent_dir_file_type_tests" || return $?
		fi

		#create shell_histfile if missing and set ownership and permissions
		#sudo_create_modify_validate_file file_path_label file_path check_if_absolute_path create_file_if_it_does_not_exist file_creation_command_options file_content only_set_perms_and_ownership_on_creation file_chown_command_options file_chmod_command_options file_type_tests
		sudo_create_modify_validate_file "${shell_label}_HISTFILE" "$shell_histfile" 1 "$create_shell_histfile_if_it_does_not_exist" "%s" "" "$only_set_perms_and_ownership_on_creation_of_shell_histfile" "$shell_histfile_ownership" "$shell_histfile_permission" "$shell_histfile_file_type_tests" || return $?
	fi

	return 0

}

sudo_setup_termux_tmp_dir() {

	local return_value

	sudo_log_literal 2 "\nRunning sudo_setup_termux_tmp_dir"

	local create_termux_tmp_dir_if_it_does_not_exist
	local only_set_perms_and_ownership_on_creation_of_termux_tmp_dir
	local termux_tmp_dir_permission
	local termux_tmp_dir_ownership
	local termux_tmp_dir_file_type_tests

	create_termux_tmp_dir_if_it_does_not_exist=1
	only_set_perms_and_ownership_on_creation_of_termux_tmp_dir=1
	termux_tmp_dir_permission="700"
	termux_tmp_dir_ownership="--reference='$TERMUX_PREFIX'"
	termux_tmp_dir_file_type_tests="drwx"


	#create TMPDIR if missing
	#sudo_create_modify_validate_directory directory_path_label directory_path check_if_absolute_path create_directory_if_it_does_not_exist only_set_perms_and_ownership_on_creation directory_chown_command_options directory_chmod_command_options sub_directories_chown_command_options sub_directories_chmod_command_options sub_files_chown_command_options sub_files_chmod_command_options file_type_tests
	sudo_create_modify_validate_directory "TMPDIR" "$TMPDIR" 1 "$create_termux_tmp_dir_if_it_does_not_exist" "$only_set_perms_and_ownership_on_creation_of_termux_tmp_dir" "$termux_tmp_dir_ownership" "$termux_tmp_dir_permission" - - - - "$termux_tmp_dir_file_type_tests" || return $?

	return 0

}

sudo_set_sudo_shell_working_dir() {

	local return_value

	sudo_log_literal 2 "\nRunning sudo_set_sudo_shell_working_dir"

	#replace "$PREFIX/" or "~/" prefix with termux absolute paths in SUDO_SHELL_WORKING_DIR
	sudo_expand_termux_path "SUDO_SHELL_WORKING_DIR" "SUDO_SHELL_WORKING_DIR" "$SUDO_SHELL_WORKING_DIR" "$TERMUX_PREFIX" "$TERMUX_HOME" 1
	return_value=$?
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failed to expand SUDO_SHELL_WORKING_DIR \"$SUDO_SHELL_WORKING_DIR\""
		return $return_value
	fi

	#if SUDO_SHELL_WORKING_DIR is not a valid absolute path
	if [[ ! "$SUDO_SHELL_WORKING_DIR" =~ $valid_absolute_path_regex ]]; then
		sudo_log_errors "The SUDO_SHELL_WORKING_DIR \"$SUDO_SHELL_WORKING_DIR\" is not a valid absolute path"
		return 1
	fi

	sudo_log 1 "SUDO_SHELL_WORKING_DIR=\"$SUDO_SHELL_WORKING_DIR\""

	#find the parent directory of the SUDO_SHELL_WORKING_DIR
	SUDO_SHELL_WORKING_DIR_BASENAME="${SUDO_SHELL_WORKING_DIR##*/}" #strip longest match of */ from start
	SUDO_SHELL_WORKING_DIR_PARENT_DIR="${SUDO_SHELL_WORKING_DIR:0:${#SUDO_SHELL_WORKING_DIR} - ${#SUDO_SHELL_WORKING_DIR_BASENAME}}" #substring from 0 to position of basename
	case $SUDO_SHELL_WORKING_DIR_PARENT_DIR in *[!/]*/) SUDO_SHELL_WORKING_DIR_PARENT_DIR=${SUDO_SHELL_WORKING_DIR_PARENT_DIR%"${SUDO_SHELL_WORKING_DIR_PARENT_DIR##*[!/]}"};; *[/]) SUDO_SHELL_WORKING_DIR_PARENT_DIR="/";; esac #remove trailing slashes if not root

	sudo_log 2 "SUDO_SHELL_WORKING_DIR_PARENT_DIR=\"$SUDO_SHELL_WORKING_DIR_PARENT_DIR\""

	return 0

}

sudo_setup_sudo_shell_working_dir() {

	local return_value

	sudo_log_literal 2 "\nRunning sudo_setup_sudo_shell_working_dir"

	local create_shell_working_dir_if_it_does_not_exist
	local only_set_perms_and_ownership_on_creation_of_shell_working_dir
	local shell_working_dir_permission
	local shell_working_dir_ownership
	local shell_working_dir_file_type_tests

	create_shell_working_dir_if_it_does_not_exist=1
	only_set_perms_and_ownership_on_creation_of_shell_working_dir=1
	shell_working_dir_permission="700"

	#find the parent directory of the SUDO_SHELL_WORKING_DIR
	SUDO_SHELL_WORKING_DIR_BASENAME="${SUDO_SHELL_WORKING_DIR##*/}" #strip longest match of */ from start
	SUDO_SHELL_WORKING_DIR_PARENT_DIR="${SUDO_SHELL_WORKING_DIR:0:${#SUDO_SHELL_WORKING_DIR} - ${#SUDO_SHELL_WORKING_DIR_BASENAME}}" #substring from 0 to position of basename
	case $SUDO_SHELL_WORKING_DIR_PARENT_DIR in *[!/]*/) SUDO_SHELL_WORKING_DIR_PARENT_DIR=${SUDO_SHELL_WORKING_DIR_PARENT_DIR%"${SUDO_SHELL_WORKING_DIR_PARENT_DIR##*[!/]}"};; *[/]) SUDO_SHELL_WORKING_DIR_PARENT_DIR="/";; esac #remove trailing slashes if not root

	shell_working_dir_ownership="--reference='${SUDO_SHELL_WORKING_DIR_PARENT_DIR//\'/\'\\\'\'}'"


	#if SUDO_SHELL_WORKING_DIR is the same as TERMUX_FILES or is under it
	if [[ "$SUDO_SHELL_WORKING_DIR" == "$TERMUX_FILES" ]] || [[ "$SUDO_SHELL_WORKING_DIR" == "$TERMUX_FILES"/* ]]; then
		shell_working_dir_file_type_tests="drwx"
	#it might not be possible for the directory to be writable or executable in other paths like in storage
	else
		shell_working_dir_file_type_tests="dr"
	fi


	#create SUDO_SHELL_WORKING_DIR if missing
	#sudo_create_modify_validate_directory directory_path_label directory_path check_if_absolute_path create_directory_if_it_does_not_exist only_set_perms_and_ownership_on_creation directory_chown_command_options directory_chmod_command_options sub_directories_chown_command_options sub_directories_chmod_command_options sub_files_chown_command_options sub_files_chmod_command_options file_type_tests
	sudo_create_modify_validate_directory "SUDO_SHELL_WORKING_DIR" "$SUDO_SHELL_WORKING_DIR" 1 "$create_shell_working_dir_if_it_does_not_exist" "$only_set_perms_and_ownership_on_creation_of_shell_working_dir" "$shell_working_dir_ownership" "$shell_working_dir_permission" - - - - "$shell_working_dir_file_type_tests" || return $?

	return 0

}

sudo_setup_sudo_temp_directory() {

	local return_value

	local valid_absolute_path_regex='^(/[^/]+)+$'

	#if remove_previous_sudo_temp_files is enabled
	if [[ "$remove_previous_sudo_temp_files" == "1" ]]; then
		#if SUDO_TEMP_DIRECTORY_PARENT_DIRECTORY is set to an absolute path and SUDO_TEMP_DIRECTORY_PREFIX is not empty
		if [[ "$SUDO_TEMP_DIRECTORY_PARENT_DIRECTORY" =~ $valid_absolute_path_regex ]] && [ ! -z "$SUDO_TEMP_DIRECTORY_PREFIX" ]; then
			#remove all directories with the prefix SUDO_TEMP_DIRECTORY_PREFIX
			sudo_log_literal 2 "\nRemove all directories with the prefix \"$SUDO_TEMP_DIRECTORY_PREFIX\" in SUDO_TEMP_DIRECTORY_PARENT_DIRECTORY \"$SUDO_TEMP_DIRECTORY_PARENT_DIRECTORY\""
			find "$SUDO_TEMP_DIRECTORY_PARENT_DIRECTORY" -maxdepth 1 -type d -name "$SUDO_TEMP_DIRECTORY_PREFIX*" -exec rm -rf "{}" \;
			return_value=$?
			if [ $return_value -ne 0 ]; then
				sudo_log_errors "Failure while removing all directories with the prefix \"$SUDO_TEMP_DIRECTORY_PREFIX\" in SUDO_TEMP_DIRECTORY_PARENT_DIRECTORY \"$SUDO_TEMP_DIRECTORY_PARENT_DIRECTORY\""
				return $return_value
			fi
		fi
	fi

	#if SETUP_SUDO_TEMP_DIRECTORY is not enabled, then just return
	if [[ "$SETUP_SUDO_TEMP_DIRECTORY" != "1" ]]; then
		return 0
	fi

	sudo_log_literal 2 "\nRunning sudo_setup_sudo_temp_directory"

	#if SUDO_TEMP_DIRECTORY_PARENT_DIRECTORY is not a valid absolute path
	if [[ ! "$SUDO_TEMP_DIRECTORY_PARENT_DIRECTORY" =~ $valid_absolute_path_regex ]]; then
		sudo_log_errors "The SUDO_TEMP_DIRECTORY_PARENT_DIRECTORY \"$SUDO_TEMP_DIRECTORY_PARENT_DIRECTORY\" is not a valid absolute path"
		return 1
	fi

	#if SUDO_TEMP_DIRECTORY_FD_PATH is not a valid absolute path
	if [[ ! "$SUDO_TEMP_DIRECTORY_FD_PATH" =~ $valid_absolute_path_regex ]]; then
		sudo_log_errors "The SUDO_TEMP_DIRECTORY_FD_PATH \"$SUDO_TEMP_DIRECTORY_FD_PATH\" is not a valid absolute path"
		return 1
	fi

	#create a temp directory in SUDO_TEMP_DIRECTORY_PARENT_DIRECTORY to store temp scripts used by the sudo script
	#SUDO_TEMP_DIRECTORY_PARENT_DIRECTORY by default would be same as SUDO_SHELL_HOME
	#TMPDIR is not used since termux will not be able to remove PREFIX or TMPDIR if the
	#directory is not removed automatically at the end of sudo execution and left there
	#the parent directory of the scripts must also have root ownership for security reasons
	#hence a directory is created to store script files since SUDO_SHELL_HOME itself may not have root ownership
	#specially if its the same as TERMUX_HOME
	#moreover if '--script-name' is passed, then there may be conflicts between executions since
	#temp files will likely share the same parent directory and have the same name
	#this will allow each execution of the script to have a separate directory for itself with a random suffix
	#scripts will also have an empty directory to use that will be unique for them, which will be removed after execution
	SUDO_TEMP_DIRECTORY="$(mktemp -d --tmpdir="$SUDO_TEMP_DIRECTORY_PARENT_DIRECTORY" "$SUDO_TEMP_DIRECTORY_PREFIX.XXXXXX")"
	return_value=$?
	if [ $return_value -ne 0 ] || [[ ! "$SUDO_TEMP_DIRECTORY" =~ $valid_absolute_path_regex ]]; then
		sudo_log_errors "Failure while running mktemp to create SUDO_TEMP_DIRECTORY"
		sudo_log_errors "SUDO_TEMP_DIRECTORY=\"$SUDO_TEMP_DIRECTORY\""
		if [ $return_value -eq 0 ]; then
			return_value=1
		fi
		return $return_value
	fi

	#write the value of SUDO_TEMP_DIRECTORY to SUDO_TEMP_DIRECTORY_FD
	printf "%s" "$SUDO_TEMP_DIRECTORY" > "$SUDO_TEMP_DIRECTORY_FD_PATH"
	return_value=$?
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failure while writing SUDO_TEMP_DIRECTORY to SUDO_TEMP_DIRECTORY_FD \"$SUDO_TEMP_DIRECTORY_FD\""
		return $return_value
	fi

	return 0

}

set_sudo_traps() {

	#set traps for the sudo itself
	trap 'sudo_trap' EXIT
	trap 'sudo_trap TERM' TERM
	trap 'sudo_trap INT' INT
	trap 'sudo_trap HUP' HUP
	trap 'sudo_trap QUIT' QUIT

	return 0

}

sudo_trap() {

	#the sudo_trap will do the following:
	#store the original trap signal in $sudo_exit_code
	#remove the EXIT trap so its not called again
	#remove temp_directory if set if sudo command failed
	#remount rootfs and system partitions back to ro if needed
	#if a signal argument was passed, then remove its trap and
	#then exit with the original trap signal exit code
	#so that parent processes can be notified if necessary

	local sudo_exit_code=$?
	trap - EXIT

	[ $sudo_exit_code -ne 0 ] && sudo_remove_sudo_temp_directory
	sudo_remount_partitions_for_sudo_shell_homes "ro"

	[ -n "$1" ] && trap - $1; exit $sudo_exit_code

}

sudo_remove_sudo_temp_directory() {

	#if SUDO_TEMP_DIRECTORY is a valid absolute path and SU_ENV_COMMAND is set and
	#do_not_delete_sudo_temp_directory_on_exit is not enabled and
	#sudo command failed
	if [[ "$SUDO_TEMP_DIRECTORY" =~ $valid_absolute_path_regex ]] && \
		[ ! -z "$SU_ENV_COMMAND" ] && \
			[[ "$do_not_delete_sudo_temp_directory_on_exit" != "1" ]]; then
		#remove SUDO_TEMP_DIRECTORY in case it wasn't already removed
		sudo_log_literal 2 "\nRemoving SUDO_TEMP_DIRECTORY in case it wasn't already removed"
		sudo_unset_pre_su_variables
		$SU_ENV_COMMAND "rm -rf '${SUDO_TEMP_DIRECTORY//\'/\'\\\'\'}'"
		sudo_set_post_su_variables
		SUDO_TEMP_DIRECTORY=""
	fi

}

sudo_create_script_command_traps() {

	local return_value

	sudo_log_literal 2 "\nRunning sudo_create_script_command_traps"

	#the sudo_script_trap will do the following:
	#store the original trap signal in $sudo_script_exit_code
	#call the sudo_script_custom_trap function
	#if it exits with 0, then continue normally
	#if it exits with 125 'ECANCELED', then do not continue and just return
	#if it exits with any other exit code, store it so that we exit
	#with that instead of the original trap signal
	#remove the EXIT trap so its not called again
	#remove temp_directory if set
	#if a signal argument was passed, then remove its trap
	#send the original trap signal to all the children of the pid
	#and exit with the original trap signal exit code or that of the
	#sudo_script_custom_trap function so that parent processes can be
	#notified if necessary

	SUDO_SCRIPT_COMMAND_TRAPS=""

	#if SUDO_TEMP_DIRECTORY is a valid absolute path and do_not_delete_sudo_temp_directory_on_exit is not enabled
	if [[ "$SUDO_TEMP_DIRECTORY" =~ $valid_absolute_path_regex ]] && [[ "$do_not_delete_sudo_temp_directory_on_exit" != "1" ]]; then
		#append the function to SUDO_SCRIPT_COMMAND_TRAPS to remove SUDO_TEMP_DIRECTORY
		#this may specially be necessary if '-E' is passed
		SUDO_SCRIPT_COMMAND_TRAPS_REMOVE_TEMP_DIRECTORY_FUNCTION="sudo_remove_temp_directory"

		SUDO_SCRIPT_COMMAND_TRAPS+='
export SUDO_SCRIPT_DIR='"'${SUDO_TEMP_DIRECTORY//\'/\'\\\'\'}'"'

'"$SUDO_SCRIPT_COMMAND_TRAPS_REMOVE_TEMP_DIRECTORY_FUNCTION"'() {
    rm -rf '"'${SUDO_TEMP_DIRECTORY//\'/\'\\\'\'}'"'
}
'
	else
		SUDO_SCRIPT_COMMAND_TRAPS_REMOVE_TEMP_DIRECTORY_FUNCTION=""
	fi

	SUDO_SCRIPT_COMMAND_TRAPS+='
sudo_script_custom_trap() { :; }

sudo_script_killtree() {
    local signal="$1"; local pid="$2"; local cpid
    for cpid in $(pgrep -P "$pid"); do sudo_script_killtree "$signal" "$cpid"; done
    [[ "$pid" != "$$" ]] && signal="${signal:=15}"; kill "-$signal" "$pid" 2>/dev/null
}

sudo_script_trap() {
    local sudo_script_exit_code=$?
    local return_value; sudo_script_custom_trap "$@"; return_value=$?
    [ $return_value -eq 125 ] && return 0
    [ $return_value -ne 0 ] && sudo_script_exit_code=$return_value
    trap - EXIT '"${SUDO_SCRIPT_COMMAND_TRAPS_REMOVE_TEMP_DIRECTORY_FUNCTION:+$'\n'    $SUDO_SCRIPT_COMMAND_TRAPS_REMOVE_TEMP_DIRECTORY_FUNCTION}"'
    [ -n "$1" ] && trap - $1
    sudo_script_killtree "$1" $$; exit $sudo_script_exit_code
}
'"
trap 'sudo_script_trap' EXIT
trap 'sudo_script_trap TERM' TERM
trap 'sudo_script_trap INT' INT
trap 'sudo_script_trap HUP' HUP
trap 'sudo_script_trap QUIT' QUIT
"
	return 0

}

#sudo_run_file_type_tests_on_path label path log_file_tests_failure_errors show_stat_output_on_file_tests_failure check_if_absolute_path file_type_tests
sudo_run_file_type_tests_on_path() {

	local return_value

	#if parameter count is not 6
	if [ $# -ne 6 ]; then
		sudo_log_errors "Invalid parameter count to \"sudo_run_file_type_tests_on_path\""
		return 1
	fi

	local label="$1"
	local path="$2"
	local log_file_tests_failure_errors="$3"
	local show_stat_output_on_file_tests_failure="$4"
	local check_if_absolute_path="$5"
	local file_type_tests="$6"

	#if file_type_tests is invalid
	if [[ ! "$file_type_tests" =~ ^[bcdefgGkhLOprSsuwx]+$ ]]; then
		sudo_log_errors "file_type_tests \"$file_type_tests\" passed to \"sudo_run_file_type_tests_on_path\" is not valid"
		return 1
	fi

	#if check_if_absolute_path is enabled and path is not a valid absolute path
	local valid_absolute_path_regex='^(/[^/]+)+$'
	if [[ "$check_if_absolute_path" == "1" ]] && [[ ! "$path" =~ $valid_absolute_path_regex ]]; then
		sudo_log_errors "The \"$label\" file \"$path\" is not an absolute path"
		return 2
	fi

	local command=""

	for (( i=0; i<${#file_type_tests}; i++ )); do
		file_type_test="${file_type_tests:$i:1}"

		[[ ! -z "$command" ]] && command+=" && "
		command+="test -$file_type_test '${path//\'/\'\\\'\'}'" #replace any single quotes `'` with `'\''` to maintain quoting and prevent arbitrary command execution with eval
	done

	#if command is empty
	if [[ -z "$command" ]]; then
		return 0
	fi

	#run all tests
	#0 means success, 1 means failure, other exit codes mean some other error
	eval "$command"
	return_value=$?
	if [ $return_value -eq 0 ]; then
		return 0
	fi

	if [ $return_value -ne 1 ] || \
		([ $return_value -eq 1 ] && [[ "$log_file_tests_failure_errors" == "1" ]]); then
		local file_type_tests_label=""

		declare -A file_type_tests_labels=(
			["b"]="[block special device]"
			["c"]="[character special device]"
			["d"]="[directory]"
			["e"]="[exists]"
			["f"]="[regular file]"
			["g"]="[set-group-id bit set]"
			["G"]="[owned by the current effective group id]"
			["k"]="[sticky bit set]"
			["h"]="[symbolic link]"
			["L"]="[symbolic link]"
			["O"]="[owned by the current effective user id]"
			["p"]="[pipe]"
			["r"]="[readable]"
			["S"]="[socket]"
			["s"]="[size greater than zero]"
			["u"]="[set-user-id bit set]"
			["w"]="[writable]"
			["x"]="[executable]"
		)

		for (( i=0; i<${#file_type_tests}; i++ )); do
			file_type_test="${file_type_tests:$i:1}"

			[[ ! -z "$file_type_tests_label" ]] && file_type_tests_label+=", "
			file_type_tests_label+="${file_type_tests_labels[$file_type_test]}"
		done
	fi

	if [ $return_value -ne 1 ]; then
		sudo_log_errors "Failed to run the following test types on the file \"$label\" at path \"$path\": $file_type_tests_label"
	else
		if [[ "$log_file_tests_failure_errors" == "1" ]]; then
			sudo_log_errors "The \"$label\" file at path \"$path\" failed one or more of the following test types: $file_type_tests_label"
			if [[ "$show_stat_output_on_file_tests_failure" == "1" ]]; then
				current_user_id="$(id -u 2>/dev/null)"
				current_user_name="$(id -un 2>/dev/null)"
				stat_output="$(stat --format="file type: %F"$'\n'"access: %A (%a)"$'\n'"owner: %U (%u)"$'\n'"group: %G (%g)"$'\n'"selinux context: %C"$'\n'"size: %s" "$path" 2>/dev/null)"
				#if stat_output is not empty
				if [[ ! -z "$stat_output" ]]; then
					sudo_log_errors "current user: $current_user_name ($current_user_id)"$'\n'"$stat_output"
				fi
			fi
		fi
	fi

	return $return_value

}

#sudo_create_modify_validate_directory directory_path_label directory_path check_if_absolute_path create_directory_if_it_does_not_exist only_set_perms_and_ownership_on_creation directory_chown_command_options directory_chmod_command_options sub_directories_chown_command_options sub_directories_chmod_command_options sub_files_chown_command_options sub_files_chmod_command_options file_type_tests
sudo_create_modify_validate_directory() {

	local return_value

	#if parameter count is not 12
	if [ $# -ne 12 ]; then
		sudo_log_errors "Invalid parameter count to \"sudo_create_modify_validate_directory\""
		return 1
	fi

	#sudo_log_literal 2 "\nRunning sudo_create_modify_validate_directory"

	local directory_path_label="$1"
	local directory_path="$2"
	local check_if_absolute_path="$3"
	local create_directory_if_it_does_not_exist="$4"
	local only_set_perms_and_ownership_on_creation="$5"
	local directory_chown_command_options="$6"
	local directory_chmod_command_options="$7"
	local sub_directories_chown_command_options="$8"
	local sub_directories_chmod_command_options="$9"
	local sub_files_chown_command_options="${10}"
	local sub_files_chmod_command_options="${11}"
	local file_type_tests="${12}"

	local directory_created=0

	#if create_directory_if_it_does_not_exist is not set to 0 or 1
	if [[ "$create_directory_if_it_does_not_exist" != "0" ]] && [[ "$create_directory_if_it_does_not_exist" != "1" ]]; then
		sudo_log_errors "create_directory_if_it_does_not_exist \"$create_directory_if_it_does_not_exist\" passed to \"sudo_create_modify_validate_directory\" is not equal to \"0\" or \"1\""
		return 1
	fi

	#if only_set_perms_and_ownership_on_creation is not set to 0 or 1
	if [[ "$only_set_perms_and_ownership_on_creation" != "0" ]] && [[ "$only_set_perms_and_ownership_on_creation" != "1" ]]; then
		sudo_log_errors "only_set_perms_and_ownership_on_creation \"$only_set_perms_and_ownership_on_creation\" passed to \"sudo_create_modify_validate_directory\" is not equal to \"0\" or \"1\""
		return 1
	fi

	#if check_if_absolute_path is enabled and directory_path is not a valid absolute path
	local valid_absolute_path_regex='^(/[^/]+)+$'
	if [[ "$check_if_absolute_path" == "1" ]] && [[ ! "$directory_path" =~ $valid_absolute_path_regex ]]; then
		sudo_log_errors "The \"$directory_path_label\" directory \"$directory_path\" is not an absolute path"
		return 2
	fi

	#check if a non-directory file exists at directory path
	if [ -e "$directory_path" ] && [ ! -d "$directory_path" ]; then
		sudo_log_errors "A non-directory file exists at $directory_path_label \"$directory_path\""
		return 1
	fi

	#if directory does not exist
	if [ ! -d "$directory_path" ]; then
		#if create_directory_if_it_does_not_exist is enabled, then create directory
		if [[ "$create_directory_if_it_does_not_exist" == "1" ]]; then
			sudo_log 2 "Creating $directory_path_label directory at \"$directory_path\""
			mkdir -p "$directory_path"
			return_value=$?
			if [ $return_value -ne 0 ]; then
				sudo_log_errors "Failed to create $directory_path_label directory at \"$directory_path\""
				return $return_value
			fi

			directory_created=1
		fi
	else
		sudo_log 2 "The $directory_path_label directory already exists at \"$directory_path\""
	fi

	#check if directory did not already exist or was not created successfully
	if [ ! -d "$directory_path" ]; then
		sudo_log_errors "Failed to find $directory_path_label directory at \"$directory_path\""
		return 1
	fi

	#if only_set_perms_and_ownership_on_creation is enabled and directory was not created
	if  [[ "$only_set_perms_and_ownership_on_creation" == "1" ]] && [[ "$directory_created" == "0" ]]; then
		sudo_log 2 "Skipping setting ownership and permission for $directory_path_label directory since it was not created"
	else

		#set directory ownership
		if [[ "$directory_chown_command_options" != "-" ]]; then
			IFS=$'\n'
			local -a directory_chown_command_options_array=( $(xargs -r -n1 -- printf -- "%s\n" <<< "$directory_chown_command_options") )
			IFS=$' \t\n'
			sudo_log 2 "Setting \"${directory_chown_command_options_array[*]}\" ownership to $directory_path_label directory at \"$directory_path\" directory"
			chown "${directory_chown_command_options_array[@]}" "$directory_path"
			return_value=$?
			if [ $return_value -ne 0 ]; then
				sudo_log_errors "Failed to set ownership of $directory_path_label directory at \"$directory_path\""
				return $return_value
			fi
		fi

		#set directory permissions
		if [[ "$directory_chmod_command_options" != "-" ]]; then
			IFS=$'\n'
			local -a directory_chmod_command_options_array=( $(xargs -r -n1 -- printf -- "%s\n" <<< "$directory_chmod_command_options") )
			IFS=$' \t\n'
			sudo_log 2 "Setting \"${directory_chmod_command_options_array[*]}\" permissions to $directory_path_label directory at \"$directory_path\" directory"
			chmod "${directory_chmod_command_options_array[@]}" "$directory_path"
			return_value=$?
			if [ $return_value -ne 0 ]; then
				sudo_log_errors "Failed to set permissions of $directory_path_label directory at \"$directory_path\""
				return $return_value
			fi
		fi

		#set subdirectories ownership
		if [[ "$sub_directories_chown_command_options" != "-" ]]; then
			IFS=$'\n'
			local -a sub_directories_chown_command_options_array=( $(xargs -r -n1 -- printf -- "%s\n" <<< "$sub_directories_chown_command_options") )
			IFS=$' \t\n'
			sudo_log 2 "Setting \"${sub_directories_chown_command_options_array[*]}\" ownership to $directory_path_label directory at \"$directory_path\" subdirectories"
			find "$directory_path" -type d -print0 | xargs -0 -r -- chown "${sub_directories_chown_command_options_array[@]}" --
			return_value=$?
			if [ $return_value -ne 0 ]; then
				sudo_log_errors "Failed to set ownership of subdirectories in $directory_path_label directory at \"$directory_path\""
				return $return_value
			fi
		fi

		#set subdirectories permissions
		if [[ "$sub_directories_chmod_command_options" != "-" ]]; then
			IFS=$'\n'
			local -a sub_directories_chmod_command_options_array=( $(xargs -r -n1 -- printf -- "%s\n" <<< "$sub_directories_chmod_command_options") )
			IFS=$' \t\n'
			sudo_log 2 "Setting \"${sub_directories_chmod_command_options_array[*]}\" permissions to $directory_path_label directory at \"$directory_path\" subdirectories"
			find "$directory_path" -type d -print0 | xargs -0 -r -- chmod "${sub_directories_chmod_command_options_array[@]}" --
			return_value=$?
			if [ $return_value -ne 0 ]; then
				sudo_log_errors "Failed to set permissions of subdirectories in $directory_path_label directory at \"$directory_path\""
				return $return_value
			fi
		fi

		#set subfiles ownership
		if [[ "$sub_files_chown_command_options" != "-" ]]; then
			IFS=$'\n'
			local -a sub_files_chown_command_options_array=( $(xargs -r -n1 -- printf -- "%s\n" <<< "$sub_files_chown_command_options") )
			IFS=$' \t\n'
			sudo_log 2 "Setting \"${sub_files_chown_command_options_array[*]}\" ownership to $directory_path_label directory at \"$directory_path\" subfiles"
			find "$directory_path" -type f -print0 | xargs -0 -r -- chown "${sub_files_chown_command_options_array[@]}" --
			return_value=$?
			if [ $return_value -ne 0 ]; then
				sudo_log_errors "Failed to set ownership of subfiles in $directory_path_label directory at \"$directory_path\""
				return $return_value
			fi
		fi

		#set subfiles permissions
		if [[ "$sub_files_chmod_command_options" != "-" ]]; then
			IFS=$'\n'
			local -a sub_files_chmod_command_options_array=( $(xargs -r -n1 -- printf -- "%s\n" <<< "$sub_files_chmod_command_options") )
			IFS=$' \t\n'
			sudo_log 2 "Setting \"${sub_files_chmod_command_options_array[*]}\" permissions to $directory_path_label directory at \"$directory_path\" subfiles"
			find "$directory_path" -type f -print0 | xargs -0 -r -- chmod "${sub_files_chmod_command_options_array[@]}" --
			return_value=$?
			if [ $return_value -ne 0 ]; then
				sudo_log_errors "Failed to set permissions of subfiles in $directory_path_label directory at \"$directory_path\""
				return $return_value
			fi
		fi
	fi


	#run file type tests with test command
	if [[ "$file_type_tests" != "-" ]]; then
		#sudo_run_file_type_tests_on_path label path log_file_tests_failure_errors show_stat_output_on_file_tests_failure check_if_absolute_path file_type_tests
		sudo_run_file_type_tests_on_path "$directory_path_label" "$directory_path" 1 1 0 "$file_type_tests" || return $?
	fi


	return 0

}

#sudo_create_modify_validate_file file_path_label file_path check_if_absolute_path create_file_if_it_does_not_exist file_creation_command_options file_content only_set_perms_and_ownership_on_creation file_chown_command_options file_chmod_command_options file_type_tests
sudo_create_modify_validate_file() {

	local return_value

	#if parameter count is not 10
	if [ $# -ne 10 ]; then
		sudo_log_errors "Invalid parameter count to \"sudo_create_modify_validate_file\""
		return 1
	fi

	#sudo_log_literal 2 "\nRunning sudo_create_modify_validate_file"

	local file_path_label="$1"
	local file_path="$2"
	local check_if_absolute_path="$3"
	local create_file_if_it_does_not_exist="$4"
	local file_creation_command_options="$5"
	local file_content="$6"
	local only_set_perms_and_ownership_on_creation="$7"
	local file_chown_command_options="$8"
	local file_chmod_command_options="$9"
	local file_type_tests="${10}"

	local file_created=0

	#if create_file_if_it_does_not_exist is not set to 0 or 1
	if [[ "$create_file_if_it_does_not_exist" != "0" ]] && [[ "$create_file_if_it_does_not_exist" != "1" ]]; then
		sudo_log_errors "create_file_if_it_does_not_exist \"$create_file_if_it_does_not_exist\" passed to \"sudo_create_modify_validate_file\" is not equal to \"0\" or \"1\""
		return 1
	fi

	#if only_set_perms_and_ownership_on_creation is not set to 0 or 1
	if [[ "$only_set_perms_and_ownership_on_creation" != "0" ]] && [[ "$only_set_perms_and_ownership_on_creation" != "1" ]]; then
		sudo_log_errors "only_set_perms_and_ownership_on_creation \"$only_set_perms_and_ownership_on_creation\" passed to \"sudo_create_modify_validate_file\" is not equal to \"0\" or \"1\""
		return 1
	fi

	#if check_if_absolute_path is enabled and file_path is not a valid absolute path
	local valid_absolute_path_regex='^(/[^/]+)+$'
	if [[ "$check_if_absolute_path" == "1" ]] && [[ ! "$file_path" =~ $valid_absolute_path_regex ]]; then
		sudo_log_errors "The \"$file_path_label\" file \"$file_path\" is not an absolute path"
		return 2
	fi

	#check if a non-file file exists at file path
	if [ -e "$file_path" ] && [ ! -f "$file_path" ]; then
		sudo_log_errors "A non-regular file exists at $file_path_label \"$file_path\""
		return 1
	fi

	#if it does not exist
	if [ ! -f "$file_path" ]; then
		#if create_file_if_it_does_not_exist is enabled, then create file
		if [[ "$create_file_if_it_does_not_exist" == "1" ]]; then

			sudo_log 2 "Creating $file_path_label \"$file_path\" file"
			local -a file_creation_command_options_array
			if [[ "$file_creation_command_options" != "-" ]]; then
				IFS=$'\n'
				file_creation_command_options_array=( $(xargs -r -n1 -- printf -- "%s\n" <<< "$file_creation_command_options") )
				IFS=$' \t\n'
			fi

			#if file_creation_options is set, then pass it to printf
			if [ ${#file_creation_command_options_array[@]} -ne 0 ]; then
				printf "${file_creation_command_options_array[@]}" "$file_content" > "$file_path"
			else
				printf "$file_content" > "$file_path"
			fi
			return_value=$?
			if [ $return_value -ne 0 ]; then
				sudo_log_errors "Failed to create $file_path_label file at \"$file_path\""
				return $return_value
			fi

			file_created=1
		fi
	else
		sudo_log 2 "The $file_path_label file already exists at \"$file_path\""
	fi

	#check if file did not already exist or was not created successfully
	if [ ! -f "$file_path" ]; then
		sudo_log_errors "Failed to find $file_path_label file at \"$file_path\""
		return 1
	fi

	#if only_set_perms_and_ownership_on_creation is enabled and file was not created
	if  [[ "$only_set_perms_and_ownership_on_creation" == "1" ]] && [[ "$file_created" == "0" ]]; then
		sudo_log 2 "Skipping setting ownership and permission for $file_path_label file since it was not created"
	else
		#set file ownership
		if [[ "$file_chown_command_options" != "-" ]]; then
			IFS=$'\n'
			local -a file_chown_command_options_array=( $(xargs -r -n1 -- printf -- "%s\n" <<< "$file_chown_command_options") )
			IFS=$' \t\n'
			sudo_log 2 "Setting \"${file_chown_command_options_array[*]}\" ownership to $file_path_label \"$file_path\" file"
			chown "${file_chown_command_options_array[@]}" "$file_path"
			return_value=$?
			if [ $return_value -ne 0 ]; then
				sudo_log_errors "Failed to set ownership of $file_path_label file at \"$file_path\""
				return $return_value
			fi
		fi

		#set file permissions
		if [[ "$file_chmod_command_options" != "-" ]]; then
			IFS=$'\n'
			local -a file_chmod_command_options_array=( $(xargs -r -n1 -- printf -- "%s\n" <<< "$file_chmod_command_options") )
			IFS=$' \t\n'
			sudo_log 2 "Setting \"${file_chmod_command_options_array[*]}\" permissions to $file_path_label \"$file_path\" file"
			chmod "${file_chmod_command_options_array[@]}" "$file_path"
			return_value=$?
			if [ $return_value -ne 0 ]; then
				sudo_log_errors "Failed to set permissions of $file_path_label file at \"$file_path\""
				return $return_value
			fi
		fi
	fi


	#run file type tests with test command
	if [[ "$file_type_tests" != "-" ]]; then
		#sudo_run_file_type_tests_on_path label path log_file_tests_failure_errors show_stat_output_on_file_tests_failure check_if_absolute_path file_type_tests
		sudo_run_file_type_tests_on_path "$file_path_label" "$file_path" 1 1 0 "$file_type_tests" || return $?
	fi


	return 0

}

#sudo_expand_termux_path variable_name label path termux_prefix termux_home canonicalize_path
sudo_expand_termux_path() {

	local return_value

	#if parameter count is not 6
	if [ $# -ne 6 ]; then
		sudo_log_errors "Invalid parameter count to \"sudo_expand_termux_path\""
		return 1
	fi

	local variable_name="$1"
	local label="$2"
	local path_to_expand="$3"
	local termux_prefix="$4"
	local termux_home="$5"
	local canonicalize_path="$6"

	[[ "$path_to_expand" == "\$PREFIX/" ]] && path_to_expand="$termux_prefix" #replace '$PREFIX/' with "$termux_prefix"
	[[ "$path_to_expand" == "~/" ]] && path_to_expand="$termux_home" #replace '~/' with "$termux_home"

	path_to_expand=${path_to_expand/#\$PREFIX\//$termux_prefix\/} #replace '$PREFIX/*' with "$termux_prefix/*"
	path_to_expand=${path_to_expand/#~\//$termux_home\/} #replace '~/*' with "$termux_home/*"

	#if canonicalize_path equals "1" or (canonicalize_path equals "2" and path_to_expand is not a symlink
	if [[ "$canonicalize_path" == "1" ]] || ([[ "$canonicalize_path" == "2" ]] && [ ! -L "$path_to_expand" ]); then
		path_to_expand="$(readlink -m -- "$path_to_expand")"
	fi

	local valid_bash_variable_name_regex='^[a-zA-Z][a-zA-Z0-9_]*(\[[0-9]+\])?$'

	#if variable_name does not equal "path_to_expand" and is valid bash variable_name
	if [[ "$variable_name" != "path_to_expand" ]] && [[ "$variable_name" =~ $valid_bash_variable_name_regex ]]; then
		#set variable_name to path_to_expand
		printf -v "$variable_name" "%s" "$path_to_expand"
	else
		sudo_log_errors "variable_name \"$1\" passed to \"sudo_expand_termux_path\" equals \"path_to_expand\" or is not a valid bash variable name"
		return 1
	fi

}

#the path will be first expanded
#if the path is an absolute path and an executable then that is returned, otherwise function fails with 112
#if the path is not an absolute path, then it is searched in current working directory by "readlink -m" and also in all the paths in paths_to_check_for_executable list (ideally $PATH variable)
#if an executable is found, then that is returned, otherwise function fails with 112
#sudo_find_absolute_path_for_executable_and_validate variable_name label path paths_to_check_for_executable termux_prefix termux_home output_path_to_stdout
sudo_find_absolute_path_for_executable_and_validate() {

	local return_value

	#if parameter count is not 7
	if [ $# -ne 7 ]; then
		sudo_log_errors "Invalid parameter count to \"sudo_find_absolute_path_for_executable_and_validate\""
		return 1
	fi

	local variable_name="$1"
	local label="$2"
	local path="$3"
	local paths_to_check_for_executable="$4"
	local termux_prefix="$5"
	local termux_home="$6"
	local output_path_to_stdout="$7"

	local executable_found=0
	local absolute_path

	#replace "$PREFIX/" or "~/" prefix with termux absolute paths in path
	sudo_expand_termux_path "absolute_path" "${label}_PATH" "$path" "$termux_prefix" "$termux_home" 1
	return_value=$?
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failed to expand ${label}_PATH \"$path\""
		return $return_value
	fi

	[[ "$output_path_to_stdout" == "1" ]] || sudo_log 2 "${label}_ABSOLUTE_PATH=\"$absolute_path\""

	test -f "$absolute_path" && test -r "$absolute_path" && test -x "$absolute_path"
	return_value=$?
	if [ $return_value -ne 0 ] && [ $return_value -ne 1 ]; then
		sudo_log_errors "Failed to run the following test types on the file \"${label}_PATH\" at path \"$absolute_path\": [regular file], [readable], [executable]"
		return $return_value
	elif [ $return_value -eq 0 ]; then
		[[ "$output_path_to_stdout" == "1" ]] || sudo_log 2 "Executable found at \"$absolute_path\""
		executable_found=1
	fi

	#if executable still not found and original path was not an absolute path, then check if path exists in PATH_TO_EXPORT
	local valid_absolute_path_regex='^(/[^/]+)+$'
	if [[ "$executable_found" == "0" ]] && [[ ! "$path" =~ $valid_absolute_path_regex ]]; then
		#check if paths_to_check_for_executable is valid
		local invalid_value_for_path_variable_regex='^:|:$|.*::.*|.*'$'\n''.*'
		if [[ "$paths_to_check_for_executable" =~ $invalid_value_for_path_variable_regex ]]; then
			sudo_log_errors "PATHS_TO_CHECK_FOR_EXECUTABLE \"$paths_to_check_for_executable\" is invalid, it cannot start or end with a colon, contain two consecutive colons \":\" or contain newline characters"
			return 1
		fi

		[[ "$output_path_to_stdout" == "1" ]] || sudo_log 2 "Checking for \"$path\" executable at following paths: \"$paths_to_check_for_executable\""

		#check if path is a binary or any executable in paths_to_check_for_executable
		for path_to_check_for_executable in ${paths_to_check_for_executable//:/ }; do
			absolute_path="$path_to_check_for_executable/$path"
			[[ "$output_path_to_stdout" == "1" ]] || sudo_log 2 "\"$absolute_path\""

			test -f "$absolute_path" && test -r "$absolute_path" && test -x "$absolute_path"
			return_value=$?
			if [ $return_value -ne 0 ] && [ $return_value -ne 1 ]; then
				sudo_log_errors "Failed to run the following test types on the file \"${label}_PATH\" at path \"$absolute_path\": [regular file], [readable], [executable]"
				return $return_value
			elif [ $return_value -eq 0 ]; then
				[[ "$output_path_to_stdout" == "1" ]] || sudo_log 2 "Executable found at \"$absolute_path\""
				executable_found=1
				break
			fi
		done
	fi

	#if executable is not found, then exit with error
	#since this is the final path
	if [[ "$executable_found" != "1" ]]; then
		return 112
	fi

	#if output_path_to_stdout is enabled, then create file
	if [[ "$output_path_to_stdout" == "1" ]]; then
		#echo absolute_path to stdout
		echo "$absolute_path"
	else
		local valid_bash_variable_name_regex='^[a-zA-Z][a-zA-Z0-9_]*(\[[0-9]+\])?$'

		#if variable_name does not equal "absolute_path" and is valid bash variable_name
		if [[ "$variable_name" != "absolute_path" ]] && [[ "$variable_name" =~ $valid_bash_variable_name_regex ]]; then
			#set variable_name to absolute_path
			printf -v "$variable_name" "%s" "$absolute_path"
		else
			sudo_log_errors "variable_name \"$1\" passed to \"sudo_find_absolute_path_for_executable_and_validate\" equals \"absolute_path\" or is not a valid bash variable name"
			return 1
		fi
	fi

}

#validate if path is under TERMUX_FILES and is not backlisted
#sudo_validate_path_is_a_whitelisted_path_under_termux_files label path
sudo_validate_path_is_a_whitelisted_path_under_termux_files() {

	local return_value

	#if parameter count is not 2
	if [ $# -ne 2 ]; then
		sudo_log_errors "Invalid parameter count to \"sudo_validate_path_is_a_whitelisted_path_under_termux_files\""
		return 1
	fi

	local label="$1"
	local path="$2"

	local valid_path_under_termux_files_regex='^'"$TERMUX_FILES"'/.+'
	local blacklisted_path_in_termux_files_regex='^'"$TERMUX_FILES"'[\/]+(('"$TERMUX_HOME_BASENAME"'[\/]+\.(cache|config|local|termux))|('"$TERMUX_PREFIX_BASENAME"')|('"$TERMUX_PREFIX_BASENAME"'[\/]+.*))([\/]+)?$'

	#if path same as TERMUX_FILES
	if [[ "$path" == "$TERMUX_FILES" ]]; then
		sudo_log 2 "$label \"$path\" is the same as TERMUX_FILES"
		return 2
	#if path is set to an absolute path under TERMUX_FILES
	elif [[ "$path" =~ $valid_path_under_termux_files_regex ]]; then
		#if path is set to a blacklist path under TERMUX_FILES
		if [[ "$path" =~ $blacklisted_path_in_termux_files_regex ]]; then
			sudo_log 2 "$label \"$path\" matches one of following blacklisted paths:"
			sudo_log 2 "\"$TERMUX_HOME/.{cache,config,local,termux}\", \"$TERMUX_PREFIX/*\""
			return 2
		else
			return 0
		fi
	else
		return 3
	fi

}

#sudo_parse_and_validate_path_variable variable_name label path remove_duplicates
sudo_parse_and_validate_path_variable() {

	local return_value

	#if parameter count is not 4
	if [ $# -ne 4 ]; then
		sudo_log_errors "Invalid parameter count to \"sudo_parse_and_validate_path_variable\""
		return 1
	fi

	local variable_name="$1"
	local label="$2"
	local path_to_parse="$3"
	local remove_duplicates="$4"

	#if remove_duplicates is enabled
	if [[ "$remove_duplicates" == "1" ]]; then
		#remove duplicates from path_to_parse
		path_to_parse="$(printf "%s" "$path_to_parse" | awk -v RS=: -v ORS= '!a[$0]++ {if (NR>1) printf(":"); printf("%s", $0) }' )"
		return_value=$?
		if [ $return_value -ne 0 ]; then
			sudo_log_errors "Failed to remove duplicates from $label \"$path_to_parse\""
			return $return_value
		fi
	fi

	#check if path_to_parse is valid
	local invalid_value_for_path_variable_regex='^:|:$|.*::.*|.*'$'\n''.*'
	if [[ "$path_to_parse" =~ $invalid_value_for_path_variable_regex ]]; then
		sudo_log_errors "$label \"$path_to_parse\" is invalid, it cannot start or end with a colon, contain two consecutive colons \":\" or contain newline characters"
		return 1
	fi

	local valid_bash_variable_name_regex='^[a-zA-Z][a-zA-Z0-9_]*(\[[0-9]+\])?$'

	#if variable_name does not equal "path_to_parse" and is valid bash variable_name
	if [[ "$variable_name" != "path_to_parse" ]] && [[ "$variable_name" =~ $valid_bash_variable_name_regex ]]; then
		#set variable_name to path
		printf -v "$variable_name" "%s" "$path_to_parse"
	else
		sudo_log_errors "variable_name \"$1\" passed to \"sudo_parse_and_validate_path_variable\" equals \"path_to_parse\" or is not a valid bash variable name"
		return 1
	fi

}

#sudo_remount_partitions_for_sudo_shell_homes remount_mode
#remount_mode must be "ro" or "rw"
sudo_remount_partitions_for_sudo_shell_homes() {

	local return_value

	#if dry_run_sudo is enabled, then just return
	if [[ "$dry_run_sudo" == "1" ]]; then
		return 0
	fi

	#if remount_mode equals "ro" and do_not_remount_partitions_back_to_ro_after_sudo is enabled, then just return
	if [[ "$remount_mode" == "ro" ]] && [[ "$do_not_remount_partitions_back_to_ro_after_sudo" == "1" ]]; then
		return 0
	fi

	sudo_log_literal 2 "\nRunning sudo_remount_partitions_for_sudo_shell_homes"

	#if parameter count is not 1
	if [ $# -ne 1 ]; then
		sudo_log_errors "Invalid parameter count to \"sudo_remount_partitions_for_sudo_shell_homes\""
		return 1
	fi

	local remount_mode="$1"
	if [[ "$remount_mode" != "ro" ]] && [[ "$remount_mode" != "rw" ]]; then
		sudo_log_errors "remount_mode \"$remount_mode\" passed to \"sudo_remount_partitions_for_sudo_shell_homes\" does not equal \"ro\" or \"rw\""
		return 1
	fi

	#if rootfs_partition_dependent_paths is set
	if [ ! -z "$rootfs_partition_dependent_paths" ]; then
		#if remount_mode equals "rw"
		if [[ "$remount_mode" == "rw" ]]; then
			#remount android rootfs partition as rw
			sudo_log 2 "Remounting rootfs \"/\" partition as rw to be used for$rootfs_partition_dependent_paths"
			sudo_remount_partition "rootfs" "rw" 0
			return_value=$?
			if [ $return_value -ne 0 ] && [ $return_value -ne 112 ]; then
				sudo_log_errors "Failed to mount rootfs \"/\" partition as rw to be used for$rootfs_partition_dependent_paths"
				return $return_value
			fi

			rootfs_partition_remounted=1
		#if remount_mode equals "ro"
		elif [[ "$remount_mode" == "ro" ]]; then
			#if rootfs_partition_remounted is enabled
			if [[ "$rootfs_partition_remounted" == "1" ]]; then
				#mount rootfs partition back as as ro
				#if rootfs partition was not mounted as ro before running sudo command it will not be remounted to ro
				#unless force_remount_partitions_back_to_ro_after_sudo is enabled
				sudo_remount_partition "rootfs" "ro" "$force_remount_partitions_back_to_ro_after_sudo"
				rootfs_partition_remounted=0
			fi
		fi
	fi


	#if system_partition_dependent_paths is set
	if [ ! -z "$system_partition_dependent_paths" ]; then
		#if remount_mode equals "rw"
		if [[ "$remount_mode" == "rw" ]]; then
			#remount android system partition as rw
			sudo_log 2 "Remounting system \"/system\" partition as rw to be used for$system_partition_dependent_paths"
			sudo_remount_partition "system" "rw" 0
			return_value=$?
			if [ $return_value -ne 0 ] && [ $return_value -ne 112 ]; then
				sudo_log_errors "Failed to mount system \"/system\" partition as rw to be used for$system_partition_dependent_paths"
				return $return_value
			fi

			system_partition_remounted=1
		#if remount_mode equals "ro"
		elif [[ "$remount_mode" == "ro" ]]; then
			#if system_partition_remounted is enabled
			if [[ "$system_partition_remounted" == "1" ]]; then
				#mount system partition back as as ro
				#if system partition was not mounted as ro before running sudo command it will not be remounted to ro
				#unless force_remount_partitions_back_to_ro_after_sudo is enabled
				sudo_remount_partition "system" "ro" "$force_remount_partitions_back_to_ro_after_sudo"
				system_partition_remounted=0
			fi
		fi
	fi

	return 0

}

#sudo_get_unsed_file_descriptor variable_name
sudo_get_unsed_file_descriptor() {

	local return_value

	local variable_name="$1"

	local fd=2

	#ulimit -n returns per-process max file descriptors that can be opened
	#but not using it to reduce external call
	#instead using the default 256 set by most systems for compatibility
	#real limit is likely to be higher like 1024, depending on android kernel version
	#local max=$(ulimit -n || echo 256)
	local max=256

	#iterate over all fds and find one for which dupe fails and use that
	while ((++fd < max)); do
	   ! true <&$fd && break
	done 2>/dev/null
	return_value=$?
	if [ $return_value -ne 0 ]; then
		sudo_log_errors "Failed to find an unused descriptor between 2-$max. last fd: '$fd'"
		return $return_value
	fi

	local valid_bash_variable_name_regex='^[a-zA-Z][a-zA-Z0-9_]*(\[[0-9]+\])?$'

	#if variable_name does not equal "fd" and is valid bash variable_name
	if [[ "$variable_name" != "fd" ]] && [[ "$variable_name" =~ $valid_bash_variable_name_regex ]]; then
		#set variable_name to fd
		printf -v "$variable_name" "%s" "$fd"
	else
		sudo_log_errors "variable_name \"$1\" passed to \"sudo_get_unsed_file_descriptor\" equals \"fd\" or is not a valid bash variable name"
		return 1
	fi

}

#remount_partition must be "rootfs" or "system"
#remount_mode must be "ro" or "rw"
#force_remount must be "0" or "1"
#sudo_remount_partition remount_partition remount_mode force_r`emount
sudo_remount_partition() {

	local return_value

	#if parameter count is not 3
	if [ $# -ne 3 ]; then
		sudo_log_errors "Invalid parameter count to \"remount_android_rootfs_for_cldia\""
		return 1
	fi

	local remount_partition="$1"
	if [[ "$remount_partition" != "rootfs" ]] && [[ "$remount_partition" != "system" ]]; then
		sudo_log_errors "remount_partition \"$remount_partition\" passed to \"sudo_remount_partition\" does not equal \"rootfs\" or \"system\""
		return 1
	fi

	local remount_mode="$2"
	if [[ "$remount_mode" != "ro" ]] && [[ "$remount_mode" != "rw" ]]; then
		sudo_log_errors "remount_mode \"$remount_mode\" passed to \"sudo_remount_partition\" does not equal \"ro\" or \"rw\""
		return 1
	fi

	local force_remount="$3"
	if [[ "$force_remount" != "0" ]] && [[ "$force_remount" != "1" ]]; then
		sudo_log_errors "remount_mode \"$remount_mode\" passed to \"sudo_remount_partition\" does not equal \"0\" or \"1\""
		return 1
	fi

	local remount_partition_mount_point
	local current_mount_mode_command_output
	local current_mount_mode
	local remount_partition_previous_state_ro
	local remount_partition_previous_state_ro_variable_name
	local mountBinaryPath
	local remount_command_output

	#search for mount executable
	for f in "$SYS_XBIN" "$SYS_BIN"; do
		test -x "$f/mount"
		return_value=$?
		if [ $return_value -ne 0 ] && [ $return_value -ne 1 ]; then
			sudo_log_errors "test command for \"$f/mount\" failed"
			return $return_value
		fi

		#if mount executable exists at "$f/mount"
		if [ $return_value -eq 0 ]; then
			mountBinaryPath="$f/mount"
			break
		fi
	done

	#if mount executable not found
	if [ -z "$mountBinaryPath" ]; then
		sudo_log_errors "\nCannot find mount executable"
		return 1
	fi

	#if remount_partition equals "rootfs"
	if [[ "$remount_partition" == "rootfs" ]]; then
		remount_partition_mount_point="/"
	#if remount_partition equals "system"
	elif [[ "$remount_partition" == "system" ]]; then
		remount_partition_mount_point="/system"
	else
		sudo_log_errors "remount_partition \"$remount_partition\" not handled"
		return 1
	fi

	#find entry of the mount point in /proc/mounts
	#there is an additional "^[^ ]+ " before the path so that only mount points are matched and not the mount sources
	#there is an additional " " after the path so that grep does not match mounts on subdirectories of the mount point
	#or any enteries in the same directory as the mount point with the same basename but with one or more characters at the end
	remount_partition_mount_entry="$(grep -m 1 -E "^[^ ]+ $remount_partition_mount_point " /proc/mounts)"
	return_value=$?
	if [ $return_value -ne 0 ] && [ $return_value -ne 1 ]; then
		sudo_log_errors "$remount_partition_mount_entry"
		sudo_log_errors "Failed to run grep to get remount_partition_mount_entry from /proc/mounts"
		return $return_value
	fi
	sudo_log 2 "remount_partition_mount_entry = \"$remount_partition_mount_entry\""

	#if remount_partition_mount_entry is empty, then mount_point is not mounted
	if [[ -z "$remount_partition_mount_entry" ]]; then
		sudo_log 2 "No mount entries found for \"$remount_partition_mount_point\" in /proc/mounts"
		sudo_log 2 "\"$remount_partition_mount_point\" is not mounted"
		return 112
	fi

	#check if remount_partition_mount_point is currently mounted as the same mount_mode as remount_mode or not
	current_mount_mode_command_output="$(echo "$remount_partition_mount_entry" | grep -E "^[^ ]+ $remount_partition_mount_point [^ ]+ ro,")"
	return_value=$?
	if [ $return_value -ne 0 ] && [ $return_value -ne 1 ]; then
		sudo_log_errors "$current_mount_mode_command_output"
		sudo_log_errors "Failed to find if $remount_partition_mount_point is mounted as $remount_mode"
		return $return_value
	#if current_mount_mode equals "ro"
	elif [ $return_value -eq 0 ]; then
		current_mount_mode="ro"
	#if current_mount_mode equals "rw"
	else
		current_mount_mode="rw"
	fi

	remount_partition_previous_state_ro_variable_name="${remount_partition}_previous_state_ro"

	#if remount_mode equals "rw"
	if [[ "$remount_mode" == "rw" ]]; then
		#set previous remount state of remount_partition to be used later
		#note that $remount_partition will be evaluated to the value in the variable like "rootfs" or "system"
		sudo_log 2 "Setting $remount_partition_previous_state_ro_variable_name to $return_value"
		eval $remount_partition_previous_state_ro_variable_name=$return_value
	fi

	#if remount_mode is equal to current_mount_mode
	if [[ "$remount_mode" == "$current_mount_mode" ]]; then
		sudo_log 2 "\"$remount_partition_mount_point\" is already mounted as $remount_mode"

		#if force_remount is not enabled, then exit
		if [[ $force_remount != "1" ]]; then
			return 0
		else
			sudo_log 2 "Force remounting \"$remount_partition_mount_point\" as $remount_mode"
		fi
	else
		sudo_log 2 "\"$remount_partition_mount_point\" is mounted as $current_mount_mode"
	fi

	#if remount_mode equals "ro"
	if [[ "$remount_mode" == "ro" ]]; then
		#find previous remount state of remount_partition
		#note that $remount_partition will be evaluated to the value in the variable like "rootfs" or "system"
		eval remount_partition_previous_state_ro="\$$remount_partition_previous_state_ro_variable_name"

		#if rootfs was previously mounted as rw and force_remount is not set to 1
		#remount_partition_previous_state_ro will be 0 if it was ro, 1 if it was rw
		if [[ "$remount_partition_previous_state_ro" == "1" ]] && [[ $force_remount -ne 1 ]]; then
			sudo_log 2 "Skipping remount \"$remount_partition_mount_point\" as ro since it was previously mounted as rw"
			return 0
		fi
	fi

	#if SU or SU_ENV_COMMAND is not set
	#this function is sourced and called by the sudo_tests script in which case sudo_main is not called to set SU and SU_ENV_COMMAND
	if [ -z "$SU" ] || [ -z "$SU_ENV_COMMAND" ]; then
		#set SU and SU_BIN_PATH
		sudo_set_su_variables || return $?

		#set SU_ENV_COMMAND
		sudo_set_su_env_command || return $?
	fi

	#remount remount_partition_mount_point as remount_mode in global namespace
	sudo_log 2 $'\n'"Remounting $remount_partition_mount_point as $remount_mode"

	sudo_unset_pre_su_variables
	remount_command_output="$($SU_ENV_COMMAND "\"$mountBinaryPath\" -o \"$remount_mode,remount\" \"$remount_partition_mount_point\"" 2>&1 < /dev/null)"
	return_value=$?
	sudo_set_post_su_variables
	#if mount_point is busy error received, then just ignore
	if [ $return_value -eq 32 ] && [[ "$remount_mode" == "ro" ]] && [[ "$remount_command_output" == *"$remount_partition_mount_point is busy"* ]]; then
		sudo_log 2 "Failed to remount $remount_partition_mount_point as $remount_mode, since its busy"
		sudo_log 2 "Ignoring error and force setting result_code to \"0\""
		return 0
	#else if non zero exit code received or output is set, then exit with error
	#in some cases exit code is 0, even though mount actually fails like if partition is read only
	elif [ $return_value -ne 0 ] || [ ! -z "$remount_command_output" ]; then
		sudo_log_errors "$remount_command_output"
		sudo_log_errors "Failed to remount $remount_partition_mount_point as $remount_mode"
		if [ $return_value -eq 0 ]; then
			return_value=1
		fi
	else
		sudo_log 2 "Remount $remount_partition_mount_point as $remount_mode successful"
	fi

	return $return_value

}

#sudo_replace_comma_alternative_chars_with_commas_in_string string
sudo_replace_comma_alternative_chars_with_commas_in_string() {

	local valid_bash_variable_name_regex='^[a-zA-Z][a-zA-Z0-9_]*(\[[0-9]+\])?$'

	#if $1 is valid bash variable_name
	if [[ "$1" =~ $valid_bash_variable_name_regex ]]; then
		#set variable_name stored in $1 to variable_value in $2 after replacing all COMMA_ALTERNATIVE characters with a comma ',' in $2
		printf -v "$1" "%s" "${2//$COMMA_ALTERNATIVE/,}"
	else
		sudo_log_errors "variable_name \"$1\" passed to \"sudo_replace_comma_alternative_chars_with_commas_in_string\" is not a valid bash variable name"
	fi

}

#sudo_trim_trailing_newlines variable_name variable_value
sudo_trim_trailing_newlines() {

	local extglob_was_unset=1
	shopt extglob >/dev/null && extglob_was_unset=0 #check if 'extglob' is currently set
	(( extglob_was_unset )) && shopt -s extglob #set 'extglob', if currently unset

	local valid_bash_variable_name_regex='^[a-zA-Z][a-zA-Z0-9_]*(\[[0-9]+\])?$'

	#if $1 is valid bash variable_name
	if [[ "$1" =~ $valid_bash_variable_name_regex ]]; then
		#set variable_name stored in $1 to variable_value in $2 without trailing newline and carriage return characters
		printf -v "$1" "%s" "${2%%*([$'\r\n'])}"
	else
		sudo_log_errors "variable_name \"$1\" passed to \"sudo_trim_trailing_newlines\" is not a valid bash variable name"
	fi

	(( extglob_was_unset )) && shopt -u extglob #unset 'extglob', if previously unset

}

process_sudo_parameters() {

	#parse options to sudo command
	while getopts ":hvabBcdDeEfFHilLnNoOpPrRsS-:" opt; do
		case ${opt} in
			-)
				long_optargs="${OPTARG#*=}"
				case "${OPTARG}" in
					help-extra)
						sudo_log_args "Parsing option: '--${OPTARG%=*}'"
						show_sudo_help_extra
						$sudo_exit_command 0
						;;
					help-extra*)
						sudo_log_arg_errors "Invalid option or parameters not allowed for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					help)
						sudo_log_args "Parsing option: '--${OPTARG%=*}'"
						show_sudo_help
						$sudo_exit_command 0
						;;
					help*)
						sudo_log_arg_errors "Invalid option or parameters not allowed for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					version)
						sudo_log_args "Parsing option: '--${OPTARG%=*}'"
						echo "$version"
						$sudo_exit_command 0
						;;
					version*)
						sudo_log_arg_errors "Invalid option or parameters not allowed for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					comma-alternative=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						COMMA_ALTERNATIVE="$val"
						;;
					comma-alternative | comma-alternative=)
						sudo_log_arg_errors "No parameters set for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					dry-run)
						sudo_log_args "Parsing option: '--${OPTARG%=*}'"
						dry_run_sudo=1
						;;
					dry-run*)
						sudo_log_arg_errors "Invalid option or parameters not allowed for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					export-paths=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						sudo_trim_trailing_newlines "ADDITIONAL_PATHS_TO_EXPORT" "$val"
						;;
					export-paths | export-paths=)
						sudo_log_arg_errors "No parameters set for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					export-ld-lib-paths=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						sudo_trim_trailing_newlines "ADDITIONAL_LD_LIBRARY_PATHS_TO_EXPORT" "$val"
						;;
					export-ld-lib-paths | export-ld-lib-paths=)
						sudo_log_arg_errors "No parameters set for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					force-remount-ro)
						sudo_log_args "Parsing option: '--${OPTARG%=*}'"
						force_remount_partitions_back_to_ro_after_sudo=1
						;;
					force-remount-ro*)
						sudo_log_arg_errors "Invalid option or parameters not allowed for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					hold)
						sudo_log_args "Parsing option: '--${OPTARG%=*}'"
						HOLD_STRING_AFTER_SUDO=""
						hold_after_sudo=1
						;;
					hold=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						#if parse_commands_as_per_run_command_intent_rules is enabled
						if  [[ "$parse_commands_as_per_run_command_intent_rules" == "1" ]]; then
							sudo_replace_comma_alternative_chars_with_commas_in_string "val" "$val"
						fi
						sudo_trim_trailing_newlines "HOLD_STRING_AFTER_SUDO" "$val"
						hold_after_sudo=1
						;;
					hold=)
						sudo_log_arg_errors "No parameters set for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					hold-if-fail)
						sudo_log_args "Parsing option: '--${OPTARG%=*}'"
						hold_only_on_failure=1
						;;
					hold-if-fail*)
						sudo_log_arg_errors "Invalid option or parameters not allowed for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					list-interactive-shells)
						sudo_log_args "Parsing option: '--${OPTARG%=*}'"
						echo "$SUDO_SUPPORTED_INTERACTIVE_SHELLS"
						$sudo_exit_command 0
						;;
					list-interactive-shells*)
						sudo_log_arg_errors "Invalid option or parameters not allowed for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					list-script-shells)
						sudo_log_args "Parsing option: '--${OPTARG%=*}'"
						echo "$SUDO_SUPPORTED_SCRIPT_SHELLS"
						$sudo_exit_command 0
						;;
					list-script-shells*)
						sudo_log_arg_errors "Invalid option or parameters not allowed for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					no-create-hist)
						sudo_log_args "Parsing option: '--${OPTARG%=*}'"
						sudo_shells_automatically_create_history_files=0
						;;
					no-create-hist*)
						sudo_log_arg_errors "Invalid option or parameters not allowed for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					no-create-rc)
						sudo_log_args "Parsing option: '--${OPTARG%=*}'"
						sudo_shells_automatically_create_rc_files=0
						;;
					no-create-rc*)
						sudo_log_arg_errors "Invalid option or parameters not allowed for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					no-hist)
						sudo_log_args "Parsing option: '--${OPTARG%=*}'"
						sudo_shells_history_enabled=0
						;;
					no-hist*)
						sudo_log_arg_errors "Invalid option or parameters not allowed for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					no-log-args)
						sudo_log_args "Parsing option: '--${OPTARG%=*}'"
						disable_arguments_logging=1
						;;
					no-log-args*)
						sudo_log_arg_errors "Invalid option or parameters not allowed for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					no-remount-ro)
						sudo_log_args "Parsing option: '--${OPTARG%=*}'"
						do_not_remount_partitions_back_to_ro_after_sudo=1
						;;
					no-remount-ro*)
						sudo_log_arg_errors "Invalid option or parameters not allowed for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					keep-temp)
						sudo_log_args "Parsing option: '--${OPTARG%=*}'"
						do_not_delete_sudo_temp_directory_on_exit=1
						;;
					keep-temp*)
						sudo_log_arg_errors "Invalid option or parameters not allowed for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					post-shell=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						sudo_trim_trailing_newlines "SUDO_POST_SHELL" "$val"
						;;
					post-shell | post-shell=)
						sudo_log_arg_errors "No parameters set for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					post-shell-home=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						#if parse_commands_as_per_run_command_intent_rules is enabled
						if  [[ "$parse_commands_as_per_run_command_intent_rules" == "1" ]]; then
							sudo_replace_comma_alternative_chars_with_commas_in_string "val" "$val"
						fi
						sudo_trim_trailing_newlines "SUDO_POST_SHELL_HOME" "$val"
						custom_sudo_post_shell_home_set=1
						;;
					post-shell-home | post-shell-home=)
						sudo_log_arg_errors "No parameters set for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					post-shell-options=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						#if parse_commands_as_per_run_command_intent_rules is enabled
						if  [[ "$parse_commands_as_per_run_command_intent_rules" == "1" ]]; then
							sudo_replace_comma_alternative_chars_with_commas_in_string "val" "$val"
						fi
						IFS=$'\n' val_arr=( $(xargs -r -n1 -- printf -- "%s\n" <<<"$val") )
						IFS=$' \t\n'
						SUDO_POST_SHELL_INTERACTIVE_ADDITIONAL_COMMAND_OPTIONS=( "${val_arr[@]}" )
						;;
					post-shell-options | post-shell-options=)
						sudo_log_arg_errors "No parameters set for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					post-shell-post-commands=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						#if parse_commands_as_per_run_command_intent_rules is enabled
						if  [[ "$parse_commands_as_per_run_command_intent_rules" == "1" ]]; then
							sudo_replace_comma_alternative_chars_with_commas_in_string "val" "$val"
						fi
						ADDITIONAL_SUDO_POST_SHELL_POST_COMMANDS_TO_RUN="$val"
						;;
					post-shell-post-commands | post-shell-post-commands=)
						sudo_log_arg_errors "No parameters set for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					post-shell-pre-commands=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						#if parse_commands_as_per_run_command_intent_rules is enabled
						if  [[ "$parse_commands_as_per_run_command_intent_rules" == "1" ]]; then
							sudo_replace_comma_alternative_chars_with_commas_in_string "val" "$val"
						fi
						ADDITIONAL_SUDO_POST_SHELL_PRE_COMMANDS_TO_RUN="$val"
						;;
					post-shell-pre-commands | post-shell-pre-commands=)
						sudo_log_arg_errors "No parameters set for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					post-shell-stdin-string=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						#if parse_commands_as_per_run_command_intent_rules is enabled
						if  [[ "$parse_commands_as_per_run_command_intent_rules" == "1" ]]; then
							sudo_replace_comma_alternative_chars_with_commas_in_string "val" "$val"
						fi
						SUDO_POST_SHELL_STDIN_STRING="$val"
						;;
					post-shell-stdin-string | post-shell-stdin-string=)
						sudo_log_arg_errors "No parameters set for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					remove-prev-temp)
						sudo_log_args "Parsing option: '--${OPTARG%=*}'"
						remove_previous_sudo_temp_files=1
						;;
					remove-prev-temp*)
						sudo_log_arg_errors "Invalid option or parameters not allowed for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					script-decode)
						sudo_log_args "Parsing option: '--${OPTARG%=*}'"
						force_use_temp_script_file_for_core_script=1
						decode_core_script_content=1
						;;
					script-decode*)
						sudo_log_arg_errors "Invalid option or parameters not allowed for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					script-name=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						#if parse_commands_as_per_run_command_intent_rules is enabled
						if  [[ "$parse_commands_as_per_run_command_intent_rules" == "1" ]]; then
							sudo_replace_comma_alternative_chars_with_commas_in_string "val" "$val"
						fi
						sudo_trim_trailing_newlines "SUDO_CORE_SCRIPT_TEMP_FILENAME" "$val"
						;;
					script-name | script-name=)
						sudo_log_arg_errors "No parameters set for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					script-redirect=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						#if parse_commands_as_per_run_command_intent_rules is enabled
						if  [[ "$parse_commands_as_per_run_command_intent_rules" == "1" ]]; then
							sudo_replace_comma_alternative_chars_with_commas_in_string "val" "$val"
						fi
						sudo_trim_trailing_newlines "SUDO_CORE_SCRIPT_REDIRECT_MODE" "$val"
						;;
					script-redirect | script-redirect=)
						sudo_log_arg_errors "No parameters set for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					shell=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						sudo_trim_trailing_newlines "SUDO_SHELL" "$val"
						;;
					shell | shell=)
						sudo_log_arg_errors "No parameters set for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					shell-home=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						#if parse_commands_as_per_run_command_intent_rules is enabled
						if  [[ "$parse_commands_as_per_run_command_intent_rules" == "1" ]]; then
							sudo_replace_comma_alternative_chars_with_commas_in_string "val" "$val"
						fi
						sudo_trim_trailing_newlines "SUDO_SHELL_HOME" "$val"
						custom_sudo_shell_home_set=1
						;;
					shell-home | shell-home=)
						sudo_log_arg_errors "No parameters set for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					shell-options=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						#if parse_commands_as_per_run_command_intent_rules is enabled
						if  [[ "$parse_commands_as_per_run_command_intent_rules" == "1" ]]; then
							sudo_replace_comma_alternative_chars_with_commas_in_string "val" "$val"
						fi
						IFS=$'\n' val_arr=( $(xargs -r -n1 -- printf -- "%s\n" <<<"$val") )
						IFS=$' \t\n'
						SUDO_SHELL_ADDITIONAL_COMMAND_OPTIONS=( "${val_arr[@]}" )
						;;
					shell-options | shell-options=)
						sudo_log_arg_errors "No parameters set for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					shell-post-commands=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						#if parse_commands_as_per_run_command_intent_rules is enabled
						if  [[ "$parse_commands_as_per_run_command_intent_rules" == "1" ]]; then
							sudo_replace_comma_alternative_chars_with_commas_in_string "val" "$val"
						fi
						ADDITIONAL_SUDO_SHELL_POST_COMMANDS_TO_RUN="$val"
						;;
					shell-post-commands | shell-post-commands=)
						sudo_log_arg_errors "No parameters set for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					shell-pre-commands=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						#if parse_commands_as_per_run_command_intent_rules is enabled
						if  [[ "$parse_commands_as_per_run_command_intent_rules" == "1" ]]; then
							sudo_replace_comma_alternative_chars_with_commas_in_string "val" "$val"
						fi
						ADDITIONAL_SUDO_SHELL_PRE_COMMANDS_TO_RUN="$val"
						;;
					shell-pre-commands | shell-pre-commands=)
						sudo_log_arg_errors "No parameters set for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					shell-stdin-string=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						#if parse_commands_as_per_run_command_intent_rules is enabled
						if  [[ "$parse_commands_as_per_run_command_intent_rules" == "1" ]]; then
							sudo_replace_comma_alternative_chars_with_commas_in_string "val" "$val"
						fi
						SUDO_SHELL_STDIN_STRING="$val"
						;;
					shell-stdin-string | shell-stdin-string=)
						sudo_log_arg_errors "No parameters set for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					sleep=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						sudo_trim_trailing_newlines "SLEEP_TIME_AFTER_SUDO" "$val"
						sleep_after_sudo=1
						;;
					sleep | sleep=)
						sudo_log_arg_errors "No parameters set for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					sleep-if-fail)
						sudo_log_args "Parsing option: '--${OPTARG%=*}'"
						sleep_only_on_failure=1
						;;
					sleep-if-fail*)
						sudo_log_arg_errors "Invalid option or parameters not allowed for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					su-env-options=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						#if parse_commands_as_per_run_command_intent_rules is enabled
						if  [[ "$parse_commands_as_per_run_command_intent_rules" == "1" ]]; then
							sudo_replace_comma_alternative_chars_with_commas_in_string "val" "$val"
						fi
						IFS=$'\n' val_arr=( $(xargs -r -n1 -- printf -- "%s\n" <<<"$val") )
						IFS=$' \t\n'
						SUDO_SU_ENV_ADDITIONAL_COMMAND_OPTIONS=( "${val_arr[@]}" )
						;;
					su-env-options | su-env-options=)
						sudo_log_arg_errors "No parameters set for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					su-run-options=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						#if parse_commands_as_per_run_command_intent_rules is enabled
						if  [[ "$parse_commands_as_per_run_command_intent_rules" == "1" ]]; then
							sudo_replace_comma_alternative_chars_with_commas_in_string "val" "$val"
						fi
						IFS=$'\n' val_arr=( $(xargs -r -n1 -- printf -- "%s\n" <<<"$val") )
						IFS=$' \t\n'
						SUDO_SU_RUN_ADDITIONAL_COMMAND_OPTIONS=( "${val_arr[@]}" )
						;;
					su-run-options | su-run-options=)
						sudo_log_arg_errors "No parameters set for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					title=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						#if parse_commands_as_per_run_command_intent_rules is enabled
						if  [[ "$parse_commands_as_per_run_command_intent_rules" == "1" ]]; then
							sudo_replace_comma_alternative_chars_with_commas_in_string "val" "$val"
						fi
						sudo_trim_trailing_newlines "SUDO_SHELL_TERMINAL_TITLE" "$val"
						set_sudo_shell_terminal_title=1
						;;
					title | title=)
						SUDO_SHELL_TERMINAL_TITLE=""
						set_sudo_shell_terminal_title=1
						;;
					work-dir=?*)
						val="$long_optargs"
						sudo_log_args "Parsing option: '--${OPTARG%=*}', value: '${val}'"
						#if parse_commands_as_per_run_command_intent_rules is enabled
						if  [[ "$parse_commands_as_per_run_command_intent_rules" == "1" ]]; then
							sudo_replace_comma_alternative_chars_with_commas_in_string "val" "$val"
						fi
						sudo_trim_trailing_newlines "SUDO_SHELL_WORKING_DIR" "$val"
						;;
					work-dir | work-dir=)
						sudo_log_arg_errors "No parameters set for option: '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
					'' ) #"--" terminates argument processing to support non-options that start with dashes
						sudo_log_args "Parsing option: '--'"
						break
						;;
					*)
						sudo_log_arg_errors "Unknown option '--${OPTARG%=*}'"
						exit_sudo_on_error
						;;
				esac
				;;
			h)
				sudo_log_args "Parsing option: '-${opt}'"
				show_sudo_help
				$sudo_exit_command 0
				;;
			v)
				sudo_log_args "Parsing option: '-${opt}'"
				if [ "$sudo_verbose_level" -lt "2" ]; then
					sudo_verbose_level=$((sudo_verbose_level+1));
				else
					sudo_log_arg_errors "Invalid Option, max verbose level is 2"
					exit_sudo_on_error
				fi
				;;
			a)
				sudo_log_args "Parsing option: '-${opt}'"
				force_set_priority_to_android_paths=1
				;;
			b)
				sudo_log_args "Parsing option: '-${opt}'"
				go_back_to_last_activity_after_running_core_script=1
				;;
			B)
				sudo_log_args "Parsing option: '-${opt}'"
				run_core_script_in_background=1
				;;
			c)
				sudo_log_args "Parsing option: '-${opt}'"
				clear_shell_after_running_core_script=1
				;;
			d)
				sudo_log_args "Parsing option: '-${opt}'"
				disable_stdin_for_core_script=1
				;;
			D)
				sudo_log_args "Parsing option: '-${opt}'"
				disable_preserve_environment_for_su=1
				;;
			e)
				sudo_log_args "Parsing option: '-${opt}'"
				exit_early_if_core_script_fails=1
				;;
			E)
				sudo_log_args "Parsing option: '-${opt}'"
				exec_sudo_shell=1
				;;
			f)
				sudo_log_args "Parsing option: '-${opt}'"
				force_use_temp_script_file_for_core_script=1
				;;
			F)
				sudo_log_args "Parsing option: '-${opt}'"
				core_script_is_path_to_script_file=1
				;;
			H)
				sudo_log_args "Parsing option: '-${opt}'"
				same_sudo_post_shell_home_as_sudo_shell_home=1
				;;
			i)
				sudo_log_args "Parsing option: '-${opt}'"
				run_interactive_post_sudo_shell_after_running_core_script=1
				;;
			l)
				sudo_log_args "Parsing option: '-${opt}'"
				go_to_launcher_activity_after_running_core_script=1
				;;
			L)
				sudo_log_args "Parsing option: '-${opt}'"
				export_all_existing_paths_in_ld_library_path_variable=1
				;;
			n)
				sudo_log_args "Parsing option: '-${opt}'"
				SUDO_CORE_SCRIPT_REDIRECT_MODE=3
				;;
			N)
				sudo_log_args "Parsing option: '-${opt}'"
				SUDO_CORE_SCRIPT_REDIRECT_MODE=4
				;;
			o)
				sudo_log_args "Parsing option: '-${opt}'"
				SUDO_CORE_SCRIPT_REDIRECT_MODE=0
				;;
			O)
				sudo_log_args "Parsing option: '-${opt}'"
				SUDO_CORE_SCRIPT_REDIRECT_MODE=1
				;;
			p)
				sudo_log_args "Parsing option: '-${opt}'"
				command_type="path"
				command_type_path_forced=1
				;;
			P)
				sudo_log_args "Parsing option: '-${opt}'"
				export_all_existing_paths_in_path_variable=1
				;;
			r)
				sudo_log_args "Parsing option: '-${opt}'"
				parse_commands_as_per_run_command_intent_rules=1
				;;
			R)
				sudo_log_args "Parsing option: '-${opt}'"
				use_root_for_path_search_and_validation=1
				;;
			s)
				sudo_log_args "Parsing option: '-${opt}'"
				command_type="script"
				;;
			S)
				sudo_log_args "Parsing option: '-${opt}'"
				same_sudo_post_shell_as_sudo_shell=1
				;;
			\?)
				sudo_log_arg_errors "Unknown option: '-${OPTARG}'"
				exit_sudo_on_error
				;;
		esac
	done
	shift $((OPTIND -1)) #remove already processed arguments from argument list

	#if arguments received
	if [ $# -ne 0 ]; then
		#if (command_type_path_forced is not enabled and $1 equals "su" or "asu"
		if [[ "$command_type_path_forced" != "1" ]] && ([[ "$1" == "su" ]] || [[ "$1" == "asu" ]]); then
			command_type="$1"
			shift #remove $1 from the argument list

			#if more arguments are given
			if [ $# -ne 0 ]; then
				sudo_log_arg_errors "Unknown arguments to \"$command_type\": '$*'"
				exit_sudo_on_error
			fi
		#if command_type equals "path" or "script"
		elif [[ "$command_type" == "path" ]] || [[ "$command_type" == "script" ]]; then
			#set rest of the arguments to the sudo script as SUDO_COMMAND
			SUDO_COMMAND=()
			local return_value
			local read_argument_from_fd
			local fd_number
			local i=1
			for arg in "$@"; do
				read_argument_from_fd=0

				#if process substitution was used to pass path to an fd file as argument that contains the actual argument value
				#and the fd is not of stdin, stdout or stderr
				if [[ "$arg" =~ ^/proc/self/fd/[0-9]+$ ]] && [[ ! "$arg" =~ ^/proc/self/fd/(0|1|2)$ ]]; then
					fd_number="${arg##*/}"
					#if fd is readable, then
					if read -t 0 -u "$fd_number" 2>/dev/null; then
						#enable read_argument_from_fd
						read_argument_from_fd=1

						#if command_type equals "script" and its the first argument
						if [[ "$command_type" == "script" ]] && [ $i -eq 1 ]; then
							#disable read_argument_from_fd since we are reading it here with cat
							#fd can't be read again, seeking backwards is not possible
							read_argument_from_fd=0

							#read core_script from fd in encoded form since it may contain non UTF-8 or binary data
							encoded_arg="$(cat "$arg" | base64)"
							return_value=$?
							if [ $return_value -ne 0 ] && [ $return_value -ne 1 ]; then
								sudo_log_arg_errors "Failure while encoding core_script received as argument"
								$sudo_exit_command $return_value
							fi

							#check if core_script contains non UTF-8 or binary data
							#decode data first before passing to grep
							printf '%s' "$encoded_arg" | base64 -d | grep -axvq '.*'
							return_value=$?
							if [ $return_value -ne 0 ] && [ $return_value -ne 1 ]; then
								sudo_log_arg_errors "Failure while checking if core_script contains non UTF-8 or binary data"
								$sudo_exit_command $return_value
							#if found
							elif [ $return_value -eq 0 ]; then
								#enable use of temp script file for core_script and enable decoding
								force_use_temp_script_file_for_core_script=1
								decode_core_script_content=1

								#set encoded data to arg
								arg="$encoded_arg"
							#if not found
							else
								#set decoded data to arg
								arg="$(printf '%s' "$encoded_arg" | base64 -d)"
							fi
						fi
					fi
				fi

				#if read_argument_from_fd is enabled
				if [[ "$read_argument_from_fd" == "1" ]]; then
					#use the fd file content as argument value
					SUDO_COMMAND+=( "$(<"$arg")" )
				else
					#directly use the argument value
					SUDO_COMMAND+=("$arg")
				fi

				i=$((i + 1))
			done
			shift $# #remove all remaining arguments from argument list
		fi
	#else show help
	else
		if [[ "$command_type" == "script" ]]; then
			SUDO_COMMAND=()
		else
			show_sudo_help
			$sudo_exit_command 0
		fi
	fi

}

show_sudo_help() {

	cat <<'SUDO_HELP_EOF'

sudo is a wrapper script to drop to the supported shells or execute
shell script files or their text passed as an argument with super
user (root) context in termux.


Usage:
  sudo [command_options] su
  sudo [command_options] asu
  sudo [command_options] [-p] <command> [command_args]
  sudo [command_options] -s <core_script> [core_script_args]


Available command_options:
  [ -h | --help ]    display this help screen
  [ --help-extra ]   display more help about how sudo command works
  [ --version ]      display version
  [ -v | -vv ]       set verbose level to 1 or 2
  [ -a ]             force set priority to android paths for path
                     command type
  [ -b ]             go back to last activity after running core_script
  [ -B ]             run core_script in background
  [ -c ]             clear shell after running core_script
  [ -d ]             disable stdin for core_script
  [ -D ]             disable preserve environment for su
  [ -e ]             exit early if core_script fails
  [ -E ]             exec interactive shell or the path command
  [ -f ]             force use temp script file for core_script
  [ -F ]             consider core_script to be a path to script file
                     instead of script text
  [ -H ]             same sudo post shell home as sudo shell home
  [ -i ]             run interactive sudo post shell after running
                     core_script
  [ -l ]             go to launcher activtiy after running core_script
  [ -L ]             export all existing paths in '$LD_LIBRARY_PATH'
                     variable
  [ -n ]             redirect stderr to /dev/null for core_script
  [ -N ]             redirect stdout and stderr to /dev/null for
                     core_script
  [ -o ]             redirect stderr to stdout for core_script
  [ -O ]             redirect stdout to stderr for core_script
  [ -p ]             set 'path' as command type [default]
  [ -P ]             export all existing paths in '$PATH' variable
  [ -r ]             parse commands as per RUN_COMMAND intent rules
  [ -R ]             use root for searching and validating paths
  [ -s ]             set 'script' as command type
  [ -S ]             same sudo post shell as sudo shell
  [ --comma-alternative=<alternative> ]
                     comma alternative character to be used for
                     the `-r` option instead of the default
  [ --dry-run ]
                     do not execute sudo commands
  [ --export-paths=<paths> ]
                     additional paths to export in PATH variable,
                     separated with colons ':'
  [ --export-ld-lib-paths=<paths> ]
                     additional paths to export in LD_LIBRARY_PATH
                     variable, separated with colons ':'
  [ --force-remount-ro ]
                     force remount rootfs and system partitions back
                     to ro after sudo commands
  [ --hold[=<string>] ]
                     hold sudo from exiting until string is entered,
                     defaults to any character if string is not passed
  [ --hold-if-fail ]
                     if '--hold' option is passed, then only hold if
                     exit code of sudo does not equal '0'
  [ --list-interactive-shells ]
                     display list of supported interactive shells
  [ --list-script-shells ]
                     display list of supported script shells
  [ --no-create-rc ]
                     do not create rc files automatically
  [ --no-create-hist ]
                     do not create history files automatically
  [ --no-hist ]
                     do not save history for sudo shell and sudo post
                     shell
  [ --no-log-args ]
                     do not log arguments and core_script content
                     when verbose mode is enabled
  [ --no-remount-ro ]
                     do not remount rootfs and system partitions back
                     to ro after sudo commands
  [ --keep-temp ]
                     do not delete sudo temp directory on exit
  [ --post-shell=<shell> ]
                     name or absolute path for sudo post shell
  [ --post-shell-home=<path> ]
                     absolute path for sudo post shell home
  [ --post-shell-options=<options> ]
                     additional options to pass to sudo post shell
  [ --post-shell-post-commands=<commands> ]
                     bash commands to run after sudo post shell
  [ --post-shell-pre-commands=<commands> ]
                     bash commands to run before sudo post shell
  [ --post-shell-stdin-string=<string> ]
                     string to pass as stdin to sudo post shell
  [ --remove-prev-temp ]
                     remove temp files and directories created on
                     previous runs of sudo command
  [ --script-decode ]
                     consider the core_script as base64
                     encoded that should be decoded before execution
  [ --script-name=<name> ]
                     filename to use for the core_script temp file
                     created in '.sudo.temp.XXXXXX' directory instead
                     of 'sudo_core_script'
  [ --script-redirect=<mode/string> ]
                     core_script redirect mode for stdout and stderr
  [ --shell=<shell> ]
                     name or absolute path for sudo shell
  [ --shell-home=<path> ]
                     absolute path for sudo shell home
  [ --shell-options=<options> ]
                     additional options to pass to sudo shell
  [ --shell-post-commands=<commands> ]
                     bash commands to run after sudo shell for script
                     command type
  [ --shell-pre-commands=<commands> ]
                     bash commands to run before sudo shell
  [ --shell-stdin-string=<string> ]
                     string to pass as stdin to sudo shell for script
                     command type
  [ --sleep=<seconds> ]
                     sleep for x seconds before exiting sudo
  [ --sleep-if-fail ]
                     if '--sleep' option is passed, then only sleep if
                     exit code of sudo does not equal '0'
  [ --su-env-options=<options> ]
                     additional options to pass to su that sets up the
                     sudo environment
  [ --su-run-options=<options> ]
                     additional options to pass to su that runs the
                     final sudo command_type command
  [ --title=<title> ]
                     title for sudo shell terminal
  [ --work-dir=<path> ]
                     absolute path for working directory


Set verbose level to 1 or 2 to get more info when running sudo command.

Pass '--dry-run' option with verbose mode enabled to see the commands
that will be run without actually executing them.

Visit https://github.com/agnostic-apollo/sudo for more help on how
sudo command works.
SUDO_HELP_EOF

echo $'\n'"Supported interactive shells: \`$SUDO_SUPPORTED_INTERACTIVE_SHELLS\`"
echo $'\n'"Supported script shells: \`$SUDO_SUPPORTED_SCRIPT_SHELLS\`"

}

show_sudo_help_extra() {

	show_sudo_help

	cat <<'SUDO_HELP_EOF'


The 'su' command type drops to an interactive shell in superuser (root)
context for any of the supported interactive shells. To drop to a root
'bash' shell, just run 'sudo su'. The priority will be set to termux
bin and library paths in '$PATH' and '$LD_LIBRARY_PATH' variables.
Use the '--shell' option to set the interactive shell to use.


The 'asu' command type is the same as 'su' command type but
instead the priority will be set to android bin and library paths in
'$PATH' and '$LD_LIBRARY_PATH' variables.
Use the '--shell' option to set the interactive shell to use.


The 'path' command type runs a single command in superuser (root)
context. You can use it just by running 'sudo <command> [command_args]'
where 'command' is the executable you want to run and 'command_args'
are any optional arguments to it. The 'command' will be run within a
'bash' shell. Priority is given to termux bin and library paths unless
'command' exists in '/system' partition.
To call the 'su' binary, run the 'sudo -p su [user]' command.


The 'script' command type takes any script text or path to a script
file for any of the supported script shells referred as 'sudo shell',
and executes the script with any optional arguments with the desired
script shell. This can be done by running the
'sudo -s <core_script> [core_script_args]' command.
The 'core_script' will be considered a 'bash' script by default.
The 'core_script' will be passed to the desired shell using
process substitution or after storing the 'core_script' in a temp file
in a temp directory in 'sudo shell' home
'$HOME/.sudo.temp.XXXXXX/sudo_core_script' and passing the path to
the desired shell, where 'XXXXXX' is a randomly generated string.
The method is automatically chosen based on the script shell
capabilities. The '-f' option can be used to force the usage of a
script file. The '-F' option can passed so that the 'core_script'
is considered as a path to script file that should be passed to
'sudo shell' directly instead of considering it as a script text.
Use the '--shell' option to set the script shell to use.
Use the '--post-shell' option to set the interactive shell to use if
'-i' option is passed.


Run "exit" command of your shell to exit interactive shells and return
to the termux shell.
SUDO_HELP_EOF

}

exit_sudo_on_error() {

	show_sudo_help
	sudo_run_pre_exit_commands 1
	$sudo_exit_command 1

}

#call sudo_main function
[[ x"${BASH_SOURCE[0]}" == x"$0" ]] && sudo_main "$@"; $sudo_exit_command 0;
