#!/data/data/com.qflistudio.azure/files/usr/bin/sh
# shellcheck shell=sh
# shellcheck disable=SC2039,SC2059,SC3043

termux_exec__system_linker_exec__init() {

TERMUX_EXEC__SYSTEM_LINKER_EXEC__LOG_LEVEL___N="TERMUX_EXEC__SYSTEM_LINKER_EXEC__LOG_LEVEL"
termux_exec__system_linker_exec__copy_variable TERMUX_EXEC__SYSTEM_LINKER_EXEC__LOG_LEVEL "$TERMUX_EXEC__SYSTEM_LINKER_EXEC__LOG_LEVEL___N" || return $?
case "${TERMUX_EXEC__SYSTEM_LINKER_EXEC__LOG_LEVEL:-}" in
    0|1|2) :;; *) TERMUX_EXEC__SYSTEM_LINKER_EXEC__LOG_LEVEL=1;; # Default: `1` (OFF=0, NORMAL=1, DEBUG=2)
esac

}



termux_exec__system_linker_exec__log() { local log_level="${1}"; shift; if [ "$TERMUX_EXEC__SYSTEM_LINKER_EXEC__LOG_LEVEL" -ge "$log_level" ]; then echo "termux-exec:" "$@"; fi }
termux_exec__system_linker_exec__log_error() { echo "termux-exec:" "$@" 1>&2; }



##
# `termux_exec__system_linker_exec__main` [`<argument...>`]
##
termux_exec__system_linker_exec__main() {

    termux_exec__system_linker_exec__init || return $?


    if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then
        termux_exec__system_linker_exec__show_help || return $?
        return 0
    elif [ "${1:-}" = "--version" ]; then
        echo "termux-exec-system-linker-exec version=1:2.4.0 org=termux project=termux-exec-package"; return $?
        return 0
    fi


    local command_type="${1:-}"
    [ $# -gt 0 ] && shift 1

    if [ "$command_type" = "is-enabled" ]; then
        if [ "${1:-}" = "-q" ] || [ "${1:-}" = "--quiet" ]; then
            TERMUX_EXEC__SYSTEM_LINKER_EXEC__LOG_LEVEL=0
            shift 1
        elif [ "${1:-}" = "-v" ]; then
            TERMUX_EXEC__SYSTEM_LINKER_EXEC__LOG_LEVEL=2
            shift 1
        fi
    else
        echo "The command '$command_type' passed to 'termux-exec-system-linker-exec' is not valid." 1>&2
        return 64 # EX__USAGE
    fi


    local output=""

    # TODO: Add `should-enable-for-file` command.
    if [ "$command_type" = "is-enabled" ]; then
        termux_exec__system_linker_exec__enabled__run_command output || return $?
    fi

    if [ -n "$output" ]; then
        echo "$output" || return $?
    fi

    return 0

}



##
# **IMPORTANT** The logic must be kept consistent with the
# `isSystemLinkerExecEnabled()` function in `TermuxExecLDPreload.c`.
#
#
# `termux_exec__system_linker_exec__enabled__run_command` `<output_variable_name>`
##
termux_exec__system_linker_exec__enabled__run_command() {

    local output_variable_name="${1:-}"

    termux_exec__system_linker_exec__set_variable "$output_variable_name" "" || return $?

    local android_build_version_sdk="${ANDROID__BUILD_VERSION_SDK:-}"
    case "$android_build_version_sdk" in
        ''|*[!0-9]*)
            android_build_version_sdk="$(getprop "ro.build.version.sdk")" || true
            case "$android_build_version_sdk" in
                ''|*[!0-9]*)
                    termux_exec__system_linker_exec__log_error "Failed to get android_build_version_sdk value from 'getprop': '$android_build_version_sdk'"
                    return 1
                    ;;
            esac
            ;;
    esac
    termux_exec__system_linker_exec__log 2 "android_build_version_sdk: '$android_build_version_sdk'"


    local system_linker_exec_mode="${TERMUX_EXEC__SYSTEM_LINKER_EXEC__MODE:-}"
    case "${system_linker_exec_mode:-}" in
        disable|enable|force) :;;
        *) system_linker_exec_mode="enable";;
    esac
    termux_exec__system_linker_exec__log 2 "system_linker_exec_mode: '$system_linker_exec_mode'"


    local __system_linker_exec_enabled="false"
    if [ "$system_linker_exec_mode" = "disable" ]; then
        __system_linker_exec_enabled="false"

    elif [ "$system_linker_exec_mode" = "force" ]; then
        local system_linker_exec_available="false"
        # If running on Android `>= 10`.
        if [ "$android_build_version_sdk" -ge 29 ]; then
            system_linker_exec_available="true"
        fi
        termux_exec__system_linker_exec__log 2 "system_linker_exec_available: '$system_linker_exec_available'"

        if [ "$system_linker_exec_available" = "true" ]; then
            __system_linker_exec_enabled="true"
        fi

    else
        # If running on Android `>= 10`.
        if [ "$android_build_version_sdk" -ge 29 ]; then
            local app_data_file_exec_exempted="false"
            # If '/proc/self/attr/current' is not readable,
            # then SeLinux may not be supported on the device.
            # Reading the file with `cat` may fail with `Illegal argument`
            # error on such devices, even though `test -f` and `test -r`
            # commands for the `access()` call succeed.
            # `cat: /proc/self/attr/current: Illegal argument`
            # - https://github.com/termux/termux-exec-package/issues/30
            local se_process_context
            se_process_context="$(cat "/proc/self/attr/current")" || true
            if [ -z "$se_process_context" ]; then
                termux_exec__system_linker_exec__log_error "Failed to read se_process_context value from '/proc/self/attr/current': '$se_process_context'"
                termux_exec__system_linker_exec__log 2 "se_process_context_available: 'false'"
                app_data_file_exec_exempted="true"
            else
                termux_exec__system_linker_exec__log 2 "se_process_context_from_file: '$se_process_context'"
                case "$se_process_context" in
                    "u:r:untrusted_app_25:"*|"u:r:untrusted_app_27:"*)
                        app_data_file_exec_exempted="true"
                        ;;
                esac
            fi

            termux_exec__system_linker_exec__log 2 "app_data_file_exec_exempted: '$app_data_file_exec_exempted'"

            if [ "$app_data_file_exec_exempted" = "false" ]; then
                __system_linker_exec_enabled="true"
            fi
        fi
    fi
    termux_exec__system_linker_exec__log 2 "system_linker_exec_enabled: '$__system_linker_exec_enabled'"

    termux_exec__system_linker_exec__set_variable "$output_variable_name" "$__system_linker_exec_enabled"

}



##
# `termux_exec__system_linker_exec__is_valid_shell_name` `<name>`
##
termux_exec__system_linker_exec__is_valid_shell_name() {

    if [ -z "${1:-}" ]; then
        return 1
    fi

    local name_rest="${1#?}" # 1:end
    local name_first_char="${1%"$name_rest"}" # 0:1
    case "$name_first_char" in
        [a-zA-Z_])
            case "$name_rest" in
                *[!a-zA-Z0-9_]*) return 1;;
                *) return 0;;
            esac;;
        *) return 1;;
    esac

}

##
# `termux_exec__system_linker_exec__set_variable` `<variable_name>` `<variable_value>`
##
termux_exec__system_linker_exec__set_variable() {

    local variable_name="${1:-}"
    local variable_value="${2:-}"

    if ! termux_exec__system_linker_exec__is_valid_shell_name "$variable_name"; then
        termux_exec__system_linker_exec__log_error "The variable_name '$variable_name' is not a valid shell variable name."
        return 64 # EX__USAGE
    fi

    eval "$variable_name"=\"\$variable_value\"

}

termux_exec__system_linker_exec__copy_variable() {

    local output_variable_name="${1:-}"
    local input_variable_name="${2:-}"

    if ! termux_exec__system_linker_exec__is_valid_shell_name "$output_variable_name"; then
        termux_exec__system_linker_exec__log_error "The output_variable_name '$output_variable_name' is not a valid shell variable name."
        return 1
    fi

    if ! termux_exec__system_linker_exec__is_valid_shell_name "$input_variable_name"; then
        termux_exec__system_linker_exec__log_error "The input_variable_name '$input_variable_name' is not a valid shell variable name."
        return 1
    fi

    eval "$output_variable_name"=\"\$\{"$input_variable_name":-\}\"

}



##
# `termux_exec__system_linker_exec__show_help`
##
termux_exec__system_linker_exec__show_help() {

    cat <<'HELP_EOF'
termux-exec-system-linker-exec can be used to get states of
'system_linker_exec' in Termux.


Usage:
    termux-exec-system-linker-exec [command_options] <command>

Available commands:
    is-enabled                Get whether 'system_linker_exec'
                              is enabled in Termux.

Available command_options:
    [ -h | --help ]           Display this help screen.
    [ --version ]             Display version.
    [ -q | --quiet ]          Set log level to 'OFF'.
    [ -v ]
                              Set log level to 'DEBUG'.
HELP_EOF

}



termux_exec__system_linker_exec__main "$@"
