[termux-setup] break termux-setupv2 into modules
This commit is contained in:
parent
120785d2b7
commit
645fbc276a
|
|
@ -1,13 +1,19 @@
|
|||
#!/data/data/com.termux/files/usr/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# 0_termux-setupv2.sh
|
||||
# - Termux bootstrap (packages, wakelock)
|
||||
# - proot-distro + Debian bootstrap
|
||||
# - ADB wireless pair/connect via Termux:API notifications (no Shizuku)
|
||||
# - Optional PPK / phantom-process tweaks (best-effort)
|
||||
# -----------------------------------------------------------------------------
|
||||
# GENERATED FILE: do not edit directly.
|
||||
# Source modules: termux-setup/*.sh + manifest.sh
|
||||
# Rebuild: (cd termux-setup && bash build_bundle.sh)
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
# ---- BEGIN 00_lib_common.sh ----
|
||||
# shellcheck shell=bash
|
||||
# Module file (no shebang). Bundled by build_bundle.sh
|
||||
|
||||
RED="\033[31m"; YEL="\033[33m"; GRN="\033[32m"; BLU="\033[34m"; RST="\033[0m"; BOLD="\033[1m"
|
||||
|
||||
log() { printf "${BLU}[iiab]${RST} %s\n" "$*"; }
|
||||
ok() { printf "${GRN}[iiab]${RST} %s\n" "$*"; }
|
||||
warn() { printf "${YEL}[iiab] WARNING:${RST} %s\n" "$*" >&2; }
|
||||
|
|
@ -17,6 +23,13 @@ have() { command -v "$1" >/dev/null 2>&1; }
|
|||
need() { have "$1" || return 1; }
|
||||
die() { echo "[!] $*" >&2; exit 1; }
|
||||
|
||||
# ---- END 00_lib_common.sh ----
|
||||
|
||||
|
||||
# ---- BEGIN 10_mod_logging.sh ----
|
||||
# shellcheck shell=bash
|
||||
# Module file (no shebang). Bundled by build_bundle.sh
|
||||
|
||||
# -------------------------
|
||||
# Logging
|
||||
# -------------------------
|
||||
|
|
@ -57,9 +70,11 @@ setup_logging() {
|
|||
fi
|
||||
|
||||
# Header (best-effort)
|
||||
local started
|
||||
started="$(date -Is 2>/dev/null || date 2>/dev/null || echo "?")"
|
||||
{
|
||||
echo "=== iiab termux setup v2 log ==="
|
||||
echo "Started: $(date -Is)"
|
||||
echo "Started: $started"
|
||||
echo "Script: $0"
|
||||
echo "Args: ${*:-}"
|
||||
echo "Android SDK=${ANDROID_SDK:-?} Release=${ANDROID_REL:-?}"
|
||||
|
|
@ -89,80 +104,17 @@ setup_logging() {
|
|||
fi
|
||||
}
|
||||
|
||||
# -------------------------
|
||||
# Defaults
|
||||
# -------------------------
|
||||
STATE_DIR="${HOME}/.iiab-android"
|
||||
ADB_STATE_DIR="${STATE_DIR}/adbw_pair"
|
||||
LOG_DIR="${STATE_DIR}/logs"
|
||||
mkdir -p "$STATE_DIR" "$ADB_STATE_DIR"
|
||||
# ---- END 10_mod_logging.sh ----
|
||||
|
||||
HOST="127.0.0.1"
|
||||
CONNECT_PORT=""
|
||||
TIMEOUT_SECS=180
|
||||
NOTIF_BASE_ID=9400
|
||||
NOTIF_SEQ=0
|
||||
LAST_NOTIF_ID=""
|
||||
CLEANUP_OFFLINE=1
|
||||
DEBUG=0
|
||||
|
||||
RESET_DEBIAN=0
|
||||
ONLY_CONNECT=0
|
||||
|
||||
CHECK_NO_ADB=0
|
||||
CHECK_SDK=""
|
||||
CHECK_MON=""
|
||||
CHECK_PPK=""
|
||||
|
||||
# Modes are mutually exclusive (baseline is default)
|
||||
MODE="baseline" # baseline|with-adb|adb-only|connect-only|ppk-only|check|all
|
||||
MODE_SET=0
|
||||
# ---- BEGIN 20_mod_termux_base.sh ----
|
||||
# shellcheck shell=bash
|
||||
# Module file (no shebang). Bundled by build_bundle.sh
|
||||
|
||||
# Termux apt options (avoid conffile prompts)
|
||||
TERMUX_APT_OPTS=( "-y" "-o" "Dpkg::Options::=--force-confdef" "-o" "Dpkg::Options::=--force-confold" )
|
||||
termux_apt() { apt-get "${TERMUX_APT_OPTS[@]}" "$@"; }
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
./0_termux-setupv2.sh
|
||||
-> Termux baseline + Debian bootstrap (idempotent). No ADB prompts.
|
||||
|
||||
./0_termux-setupv2.sh --with-adb
|
||||
-> Termux baseline + Debian bootstrap + ADB pair/connect if needed (skips if already connected).
|
||||
|
||||
./0_termux-setupv2.sh --adb-only
|
||||
-> Only ADB pair/connect if needed (no Debian; skips if already connected).
|
||||
|
||||
./0_termux-setupv2.sh --connect-only [CONNECT_PORT]
|
||||
-> Connect-only (no pairing). Use this after the device was already paired before.
|
||||
|
||||
./0_termux-setupv2.sh --ppk-only
|
||||
-> Set PPK only: max_phantom_processes=256 (requires ADB already connected).
|
||||
Android 14-16 usually achieve this via "Disable child process restrictions" in Developer Options.
|
||||
|
||||
./0_termux-setupv2.sh --check
|
||||
-> Check readiness: developer options flag (if readable),
|
||||
(Android 14+) "Disable child process restrictions" proxy flag, and (Android 12-13) PPK effective value.
|
||||
|
||||
./0_termux-setupv2.sh --all
|
||||
-> baseline + Debian + ADB pair/connect if needed + (Android 12-13 only) apply --ppk + run --check.
|
||||
|
||||
Optional:
|
||||
--connect-port 41313 (5 digits) Skip CONNECT PORT prompt
|
||||
--timeout 180 Seconds to wait per prompt
|
||||
--reset-debian Reset (reinstall) Debian in proot-distro
|
||||
--no-log Disable logging
|
||||
--log-file /path/file Write logs to a specific file
|
||||
--debug Extra logs
|
||||
|
||||
Notes:
|
||||
- ADB prompts require: `pkg install termux-api` + Termux:API app installed + notification permission.
|
||||
- Wireless debugging must be enabled.
|
||||
- This script never uses adb root.
|
||||
EOF
|
||||
}
|
||||
|
||||
# -------------------------
|
||||
# Android info
|
||||
# -------------------------
|
||||
|
|
@ -193,7 +145,6 @@ release_wakelock() {
|
|||
ok "Wakelock released (termux-wake-unlock)."
|
||||
fi
|
||||
}
|
||||
trap 'cleanup_notif >/dev/null 2>&1 || true; release_wakelock >/dev/null 2>&1 || true' EXIT INT TERM
|
||||
|
||||
# -------------------------
|
||||
# One-time repo selector
|
||||
|
|
@ -209,7 +160,8 @@ step_termux_repo_select_once() {
|
|||
if [[ -r /dev/tty ]]; then
|
||||
printf "\n${YEL}[iiab] One-time setup:${RST} Select a nearby Termux repository mirror for faster downloads.\n" >&2
|
||||
local ans="Y"
|
||||
if ! read -r -p "[iiab] Launch termux-change-repo now? [Y/n]: " ans < /dev/tty; then
|
||||
printf "[iiab] Launch termux-change-repo now? [Y/n]: " > /dev/tty
|
||||
if ! read -r ans < /dev/tty; then
|
||||
warn "No interactive TTY available; skipping mirror selection (run script directly to be prompted)."
|
||||
return 0
|
||||
fi
|
||||
|
|
@ -262,7 +214,9 @@ step_termux_base() {
|
|||
termux-api \
|
||||
|| true
|
||||
|
||||
if have proot-distro && have adb && have termux-notification; then
|
||||
if have proot-distro && \
|
||||
have adb && have termux-notification && \
|
||||
have termux-dialog; then
|
||||
ok "Termux baseline ready."
|
||||
date > "$stamp"
|
||||
else
|
||||
|
|
@ -270,6 +224,13 @@ step_termux_base() {
|
|||
fi
|
||||
}
|
||||
|
||||
# ---- END 20_mod_termux_base.sh ----
|
||||
|
||||
|
||||
# ---- BEGIN 30_mod_debian.sh ----
|
||||
# shellcheck shell=bash
|
||||
# Module file (no shebang). Bundled by build_bundle.sh
|
||||
|
||||
# -------------------------
|
||||
# Debian bootstrap
|
||||
# -------------------------
|
||||
|
|
@ -324,22 +285,47 @@ step_debian_bootstrap_default() {
|
|||
fi
|
||||
|
||||
log "Installing minimal tools inside Debian (noninteractive)..."
|
||||
if ! debian_exists; then
|
||||
warn_red "Debian is not available in proot-distro (install may have failed). Rerun later."
|
||||
return 0
|
||||
fi
|
||||
local rc=0
|
||||
set +e
|
||||
proot-distro login debian -- bash -lc '
|
||||
set -e
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update
|
||||
apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confold \
|
||||
install ca-certificates curl coreutils
|
||||
' || true
|
||||
|
||||
'
|
||||
rc=$?
|
||||
set -e
|
||||
if [[ $rc -eq 0 ]]; then
|
||||
ok "Debian bootstrap complete."
|
||||
else
|
||||
warn_red "Debian bootstrap incomplete (inner apt-get failed, rc=$rc)."
|
||||
warn "You can retry later with: proot-distro login debian"
|
||||
fi
|
||||
}
|
||||
|
||||
# ---- END 30_mod_debian.sh ----
|
||||
|
||||
|
||||
# ---- BEGIN 40_mod_termux_api.sh ----
|
||||
# shellcheck shell=bash
|
||||
# Module file (no shebang). Bundled by build_bundle.sh
|
||||
|
||||
# -------------------------
|
||||
# Termux:API notifications + prompts
|
||||
# -------------------------
|
||||
NOTIF_BASE_ID=9400
|
||||
NOTIF_SEQ=0
|
||||
LAST_NOTIF_ID=""
|
||||
|
||||
# Termux:API sanity check (notifications)
|
||||
# -------------------------
|
||||
termux_api_ready() {
|
||||
have termux-notification || return 1
|
||||
have termux-dialog || return 1
|
||||
|
||||
# Quick probe: some Samsung setups fail until Termux:API app is installed/allowed.
|
||||
# We try a harmless notification and remove it.
|
||||
|
|
@ -377,6 +363,7 @@ notify_ask_one() {
|
|||
local key="$1" title="$2" content="$3"
|
||||
local out="$ADB_STATE_DIR/$key.txt"
|
||||
rm -f "$out"
|
||||
local action
|
||||
|
||||
# Fresh notification each time + sound (use a new ID so Android plays sound each time)
|
||||
local nid
|
||||
|
|
@ -387,6 +374,15 @@ notify_ask_one() {
|
|||
if have termux-notification-remove; then
|
||||
termux-notification-remove "$nid" >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
# termux-notification does not provide a reply input; use termux-dialog to capture text.
|
||||
if ! have termux-dialog; then
|
||||
warn "termux-dialog not available. Install: pkg install termux-api + Termux:API app."
|
||||
return 1
|
||||
fi
|
||||
|
||||
action="sh -lc 'termux-dialog -i -t \"${title}\" -h \"${content}\" | tr -d \"\\n\" | sed -n \"s/.*\\\"text\\\"[[:space:]]*:[[:space:]]*\\\"\\([^\\\"]*\\)\\\".*/\\1/p\" > \"${out}\"'"
|
||||
|
||||
termux-notification \
|
||||
--id "$nid" \
|
||||
--ongoing \
|
||||
|
|
@ -395,14 +391,13 @@ notify_ask_one() {
|
|||
--content "$content" \
|
||||
--sound \
|
||||
--button1 "Answer" \
|
||||
--button1-action "sh -lc 'printf \"%s\" \"\$REPLY\" > \"$out\"'" \
|
||||
--button1-action "$action" \
|
||||
|| return 1
|
||||
|
||||
local start now
|
||||
start="$(date +%s)"
|
||||
while true; do
|
||||
if [[ -s "$out" ]]; then
|
||||
# Remove the prompt notification as soon as we got the answer
|
||||
if [[ -f "$out" ]]; then
|
||||
if have termux-notification-remove; then
|
||||
termux-notification-remove "$nid" >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
|
@ -411,7 +406,6 @@ notify_ask_one() {
|
|||
fi
|
||||
now="$(date +%s)"
|
||||
if (( now - start >= TIMEOUT_SECS )); then
|
||||
# Remove the prompt notification on timeout too
|
||||
if have termux-notification-remove; then
|
||||
termux-notification-remove "$nid" >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
|
@ -450,6 +444,16 @@ ask_code_6digits() {
|
|||
done
|
||||
}
|
||||
|
||||
# ---- END 40_mod_termux_api.sh ----
|
||||
|
||||
|
||||
# ---- BEGIN 50_mod_adb.sh ----
|
||||
# shellcheck shell=bash
|
||||
# Module file (no shebang). Bundled by build_bundle.sh
|
||||
|
||||
# -------------------------
|
||||
# ADB wireless pair/connect wizard
|
||||
# -------------------------
|
||||
cleanup_offline_loopback() {
|
||||
local keep_serial="$1" # e.g. 127.0.0.1:41313
|
||||
local serial state rest
|
||||
|
|
@ -462,9 +466,6 @@ cleanup_offline_loopback() {
|
|||
done < <(adb devices 2>/dev/null | tail -n +2 | sed '/^[[:space:]]*$/d')
|
||||
}
|
||||
|
||||
# -------------------------
|
||||
# ADB wireless pair/connect wizard
|
||||
# -------------------------
|
||||
adb_pair_connect() {
|
||||
need adb || die "Missing adb. Install: pkg install android-tools"
|
||||
|
||||
|
|
@ -552,7 +553,10 @@ adb_device_state() {
|
|||
|
||||
# Return first loopback serial in "device" state (e.g. 127.0.0.1:41313)
|
||||
adb_any_loopback_device() {
|
||||
adb devices 2>/dev/null | awk -v h="$HOST" 'NR>1 && $2=="device" && index($1, h":")==1 {print $1; exit}'
|
||||
adb devices 2>/dev/null | awk -v h="$HOST" '
|
||||
NR>1 && $2=="device" && index($1, h":")==1 {print $1; found=1; exit}
|
||||
END { exit (found ? 0 : 1) }
|
||||
'
|
||||
}
|
||||
|
||||
# Pick the loopback serial we will operate on:
|
||||
|
|
@ -628,6 +632,16 @@ adb_loopback_serial_or_die() {
|
|||
echo "$s"
|
||||
}
|
||||
|
||||
# ---- END 50_mod_adb.sh ----
|
||||
|
||||
|
||||
# ---- BEGIN 60_mod_ppk_checks.sh ----
|
||||
# shellcheck shell=bash
|
||||
# Module file (no shebang). Bundled by build_bundle.sh
|
||||
|
||||
# PPK / phantom-process checks and tuning via ADB (best-effort)
|
||||
# Moved out of 99_main.sh to keep it as an orchestrator.
|
||||
|
||||
# -------------------------
|
||||
# PPK / phantom-process tuning (best-effort)
|
||||
# -------------------------
|
||||
|
|
@ -763,6 +777,90 @@ check_readiness() {
|
|||
return 0
|
||||
}
|
||||
|
||||
# ---- END 60_mod_ppk_checks.sh ----
|
||||
|
||||
|
||||
# ---- BEGIN 99_main.sh ----
|
||||
# shellcheck shell=bash
|
||||
# Module file (no shebang). Bundled by build_bundle.sh
|
||||
|
||||
# 0_termux-setupv2.sh
|
||||
# - Termux bootstrap (packages, wakelock)
|
||||
# - proot-distro + Debian bootstrap
|
||||
# - ADB wireless pair/connect via Termux:API notifications (no Shizuku)
|
||||
# - Optional PPK / phantom-process tweaks (best-effort)
|
||||
|
||||
# -------------------------
|
||||
# Defaults
|
||||
# -------------------------
|
||||
STATE_DIR="${HOME}/.iiab-android"
|
||||
ADB_STATE_DIR="${STATE_DIR}/adbw_pair"
|
||||
LOG_DIR="${STATE_DIR}/logs"
|
||||
mkdir -p "$STATE_DIR" "$ADB_STATE_DIR"
|
||||
|
||||
HOST="127.0.0.1"
|
||||
CONNECT_PORT=""
|
||||
TIMEOUT_SECS=180
|
||||
CLEANUP_OFFLINE=1
|
||||
DEBUG=0
|
||||
|
||||
RESET_DEBIAN=0
|
||||
ONLY_CONNECT=0
|
||||
|
||||
CHECK_NO_ADB=0
|
||||
CHECK_SDK=""
|
||||
CHECK_MON=""
|
||||
CHECK_PPK=""
|
||||
|
||||
# Modes are mutually exclusive (baseline is default)
|
||||
MODE="baseline" # baseline|with-adb|adb-only|connect-only|ppk-only|check|all
|
||||
MODE_SET=0
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
./0_termux-setupv2.sh
|
||||
-> Termux baseline + Debian bootstrap (idempotent). No ADB prompts.
|
||||
|
||||
./0_termux-setupv2.sh --with-adb
|
||||
-> Termux baseline + Debian bootstrap + ADB pair/connect if needed (skips if already connected).
|
||||
|
||||
./0_termux-setupv2.sh --adb-only
|
||||
-> Only ADB pair/connect if needed (no Debian; skips if already connected).
|
||||
|
||||
./0_termux-setupv2.sh --connect-only [CONNECT_PORT]
|
||||
-> Connect-only (no pairing). Use this after the device was already paired before.
|
||||
|
||||
./0_termux-setupv2.sh --ppk-only
|
||||
-> Set PPK only: max_phantom_processes=256 (requires ADB already connected).
|
||||
Android 14-16 usually achieve this via "Disable child process restrictions" in Developer Options.
|
||||
|
||||
./0_termux-setupv2.sh --check
|
||||
-> Check readiness: developer options flag (if readable),
|
||||
(Android 14+) "Disable child process restrictions" proxy flag, and (Android 12-13) PPK effective value.
|
||||
|
||||
./0_termux-setupv2.sh --all
|
||||
-> baseline + Debian + ADB pair/connect if needed + (Android 12-13 only) apply --ppk + run --check.
|
||||
|
||||
Optional:
|
||||
--connect-port 41313 (5 digits) Skip CONNECT PORT prompt
|
||||
--timeout 180 Seconds to wait per prompt
|
||||
--reset-debian Reset (reinstall) Debian in proot-distro
|
||||
--no-log Disable logging
|
||||
--log-file /path/file Write logs to a specific file
|
||||
--debug Extra logs
|
||||
|
||||
Notes:
|
||||
- ADB prompts require: `pkg install termux-api` + Termux:API app installed + notification permission.
|
||||
- Wireless debugging must be enabled.
|
||||
- This script never uses adb root.
|
||||
EOF
|
||||
}
|
||||
|
||||
trap 'cleanup_notif >/dev/null 2>&1 || true; release_wakelock >/dev/null 2>&1 || true' EXIT INT TERM
|
||||
|
||||
# NOTE: Termux:API prompts live in 40_mod_termux_api.sh
|
||||
|
||||
# -------------------------
|
||||
# Self-check
|
||||
# -------------------------
|
||||
|
|
@ -1015,3 +1113,7 @@ main() {
|
|||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
# ---- END 99_main.sh ----
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
# shellcheck shell=bash
|
||||
# Module file (no shebang). Bundled by build_bundle.sh
|
||||
|
||||
RED="\033[31m"; YEL="\033[33m"; GRN="\033[32m"; BLU="\033[34m"; RST="\033[0m"; BOLD="\033[1m"
|
||||
|
||||
log() { printf "${BLU}[iiab]${RST} %s\n" "$*"; }
|
||||
ok() { printf "${GRN}[iiab]${RST} %s\n" "$*"; }
|
||||
warn() { printf "${YEL}[iiab] WARNING:${RST} %s\n" "$*" >&2; }
|
||||
warn_red() { printf "${RED}${BOLD}[iiab] WARNING:${RST} %s\n" "$*" >&2; }
|
||||
|
||||
have() { command -v "$1" >/dev/null 2>&1; }
|
||||
need() { have "$1" || return 1; }
|
||||
die() { echo "[!] $*" >&2; exit 1; }
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
# shellcheck shell=bash
|
||||
# Module file (no shebang). Bundled by build_bundle.sh
|
||||
|
||||
# -------------------------
|
||||
# Logging
|
||||
# -------------------------
|
||||
LOG_ENABLED=1
|
||||
LOG_FILE="" # if empty, auto-generate under $LOG_DIR
|
||||
LOG_KEEP=20 # keep last N logs
|
||||
|
||||
rotate_logs() {
|
||||
[[ -d "${LOG_DIR:-}" ]] || return 0
|
||||
local n=$((LOG_KEEP + 1))
|
||||
while IFS= read -r f; do
|
||||
[[ -n "${f:-}" ]] || continue
|
||||
[[ -n "${LOG_FILE:-}" && "$f" == "$LOG_FILE" ]] && continue
|
||||
rm -f -- "$f" 2>/dev/null || true
|
||||
done < <(ls -1t "$LOG_DIR"/*.log 2>/dev/null | tail -n +"$n" || true)
|
||||
}
|
||||
|
||||
setup_logging() {
|
||||
# Save original console fds so interactive tools still work after we redirect stdout/stderr.
|
||||
exec 3>&1 4>&2
|
||||
|
||||
# If logging is disabled, still allow --debug to trace to console.
|
||||
if [[ "${LOG_ENABLED:-1}" -ne 1 ]]; then
|
||||
if [[ "${DEBUG:-0}" -eq 1 ]]; then
|
||||
set -x
|
||||
ok "Debug trace enabled (bash -x) -> console (logging disabled)"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
mkdir -p "$LOG_DIR" 2>/dev/null || true
|
||||
|
||||
if [[ -z "${LOG_FILE:-}" ]]; then
|
||||
LOG_FILE="${LOG_DIR}/0_termux-setupv2.$(date +%Y%m%d-%H%M%S).log"
|
||||
else
|
||||
# Best-effort: ensure parent dir exists
|
||||
mkdir -p "$(dirname -- "$LOG_FILE")" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Header (best-effort)
|
||||
local started
|
||||
started="$(date -Is 2>/dev/null || date 2>/dev/null || echo "?")"
|
||||
{
|
||||
echo "=== iiab termux setup v2 log ==="
|
||||
echo "Started: $started"
|
||||
echo "Script: $0"
|
||||
echo "Args: ${*:-}"
|
||||
echo "Android SDK=${ANDROID_SDK:-?} Release=${ANDROID_REL:-?}"
|
||||
echo "PWD: $(pwd 2>/dev/null || true)"
|
||||
echo "================================"
|
||||
} >>"$LOG_FILE" 2>/dev/null || true
|
||||
|
||||
# Best-effort: restrict log readability (may include debug/xtrace)
|
||||
chmod 600 "$LOG_FILE" 2>/dev/null || true
|
||||
|
||||
rotate_logs
|
||||
|
||||
# Duplicate stdout/stderr to console + log (strip ANSI in log)
|
||||
exec \
|
||||
> >(tee >(sed -E 's/\x1B\[[0-9;]*[ -/]*[@-~]//g' >>"$LOG_FILE")) \
|
||||
2> >(tee >(sed -E 's/\x1B\[[0-9;]*[ -/]*[@-~]//g' >>"$LOG_FILE") >&2)
|
||||
|
||||
ok "Logging to: $LOG_FILE"
|
||||
|
||||
# If --debug, send xtrace only to log
|
||||
if [[ "${DEBUG:-0}" -eq 1 ]]; then
|
||||
exec 9>>"$LOG_FILE"
|
||||
export BASH_XTRACEFD=9
|
||||
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
|
||||
set -x
|
||||
ok "Debug trace enabled (bash -x) -> log only"
|
||||
fi
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
# shellcheck shell=bash
|
||||
# Module file (no shebang). Bundled by build_bundle.sh
|
||||
|
||||
# Termux apt options (avoid conffile prompts)
|
||||
TERMUX_APT_OPTS=( "-y" "-o" "Dpkg::Options::=--force-confdef" "-o" "Dpkg::Options::=--force-confold" )
|
||||
termux_apt() { apt-get "${TERMUX_APT_OPTS[@]}" "$@"; }
|
||||
|
||||
# -------------------------
|
||||
# Android info
|
||||
# -------------------------
|
||||
get_android_sdk() { getprop ro.build.version.sdk 2>/dev/null || true; }
|
||||
get_android_release() { getprop ro.build.version.release 2>/dev/null || true; }
|
||||
ANDROID_SDK="$(get_android_sdk)"
|
||||
ANDROID_REL="$(get_android_release)"
|
||||
|
||||
# -------------------------
|
||||
# Wakelock (Termux:API)
|
||||
# -------------------------
|
||||
WAKELOCK_HELD=0
|
||||
acquire_wakelock() {
|
||||
if have termux-wake-lock; then
|
||||
if termux-wake-lock; then
|
||||
WAKELOCK_HELD=1
|
||||
ok "Wakelock acquired (termux-wake-lock)."
|
||||
else
|
||||
warn "Failed to acquire wakelock (termux-wake-lock)."
|
||||
fi
|
||||
else
|
||||
warn "termux-wake-lock not available. Install: pkg install termux-api + Termux:API app."
|
||||
fi
|
||||
}
|
||||
release_wakelock() {
|
||||
if [[ "$WAKELOCK_HELD" -eq 1 ]] && have termux-wake-unlock; then
|
||||
termux-wake-unlock || true
|
||||
ok "Wakelock released (termux-wake-unlock)."
|
||||
fi
|
||||
}
|
||||
|
||||
# -------------------------
|
||||
# One-time repo selector
|
||||
# -------------------------
|
||||
step_termux_repo_select_once() {
|
||||
local stamp="$STATE_DIR/stamp.termux_repo_selected"
|
||||
[[ -f "$stamp" ]] && return 0
|
||||
if ! have termux-change-repo; then
|
||||
warn "termux-change-repo not found; skipping mirror selection."
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -r /dev/tty ]]; then
|
||||
printf "\n${YEL}[iiab] One-time setup:${RST} Select a nearby Termux repository mirror for faster downloads.\n" >&2
|
||||
local ans="Y"
|
||||
printf "[iiab] Launch termux-change-repo now? [Y/n]: " > /dev/tty
|
||||
if ! read -r ans < /dev/tty; then
|
||||
warn "No interactive TTY available; skipping mirror selection (run script directly to be prompted)."
|
||||
return 0
|
||||
fi
|
||||
ans="${ans:-Y}"
|
||||
if [[ "$ans" =~ ^[Yy]$ ]]; then
|
||||
# Logging redirects stdout/stderr to pipes, which can break the UI.
|
||||
# Run it using /dev/tty and the original console fds (3/4).
|
||||
if [[ -r /dev/tty ]]; then
|
||||
termux-change-repo </dev/tty >&3 2>&4 || true
|
||||
else
|
||||
termux-change-repo || true
|
||||
fi
|
||||
ok "Mirror selection completed (or skipped inside the UI)."
|
||||
else
|
||||
warn "Mirror selection skipped by user."
|
||||
fi
|
||||
date > "$stamp"
|
||||
return 0
|
||||
fi
|
||||
|
||||
warn "No /dev/tty available; skipping mirror selection."
|
||||
return 0
|
||||
}
|
||||
|
||||
# -------------------------
|
||||
# Baseline packages
|
||||
# -------------------------
|
||||
step_termux_base() {
|
||||
local stamp="$STATE_DIR/stamp.termux_base"
|
||||
if [[ -f "$stamp" ]]; then
|
||||
ok "Termux baseline already prepared (stamp found)."
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "Updating Termux packages (noninteractive) and installing baseline dependencies..."
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
termux_apt update || true
|
||||
termux_apt upgrade || true
|
||||
|
||||
termux_apt install \
|
||||
ca-certificates \
|
||||
curl \
|
||||
coreutils \
|
||||
grep \
|
||||
sed \
|
||||
gawk \
|
||||
openssh \
|
||||
proot proot-distro \
|
||||
android-tools \
|
||||
termux-api \
|
||||
|| true
|
||||
|
||||
if have proot-distro && \
|
||||
have adb && have termux-notification && \
|
||||
have termux-dialog; then
|
||||
ok "Termux baseline ready."
|
||||
date > "$stamp"
|
||||
else
|
||||
warn_red "Baseline incomplete (missing proot-distro/adb/termux-notification). Not stamping; rerun later."
|
||||
fi
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
# shellcheck shell=bash
|
||||
# Module file (no shebang). Bundled by build_bundle.sh
|
||||
|
||||
# -------------------------
|
||||
# Debian bootstrap
|
||||
# -------------------------
|
||||
debian_exists() {
|
||||
have proot-distro || return 1
|
||||
proot-distro login debian -- true >/dev/null 2>&1
|
||||
}
|
||||
|
||||
ensure_proot_distro() {
|
||||
if have proot-distro; then return 0; fi
|
||||
warn "proot-distro not found; attempting to install..."
|
||||
termux_apt install proot-distro || true
|
||||
have proot-distro
|
||||
}
|
||||
|
||||
proot_install_debian_safe() {
|
||||
local out rc
|
||||
set +e
|
||||
out="$(proot-distro install debian 2>&1)"
|
||||
rc=$?
|
||||
set -e
|
||||
if [[ $rc -eq 0 ]]; then return 0; fi
|
||||
if echo "$out" | grep -qi "already installed"; then
|
||||
warn "Debian is already installed; continuing."
|
||||
return 0
|
||||
fi
|
||||
printf "%s\n" "$out" >&2
|
||||
return $rc
|
||||
}
|
||||
|
||||
step_debian_bootstrap_default() {
|
||||
if ! ensure_proot_distro; then
|
||||
warn "Unable to ensure proot-distro; skipping Debian bootstrap."
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "$RESET_DEBIAN" -eq 1 ]]; then
|
||||
warn "Reset requested: reinstalling Debian (clean environment)..."
|
||||
if proot-distro help 2>/dev/null | grep -qE '\breset\b'; then
|
||||
proot-distro reset debian || true
|
||||
else
|
||||
if debian_exists; then proot-distro remove debian || true; fi
|
||||
proot_install_debian_safe || true
|
||||
fi
|
||||
else
|
||||
if debian_exists; then
|
||||
ok "Debian already present in proot-distro. Not reinstalling."
|
||||
else
|
||||
log "Installing Debian (proot-distro install debian)..."
|
||||
proot_install_debian_safe || true
|
||||
fi
|
||||
fi
|
||||
|
||||
log "Installing minimal tools inside Debian (noninteractive)..."
|
||||
if ! debian_exists; then
|
||||
warn_red "Debian is not available in proot-distro (install may have failed). Rerun later."
|
||||
return 0
|
||||
fi
|
||||
local rc=0
|
||||
set +e
|
||||
proot-distro login debian -- bash -lc '
|
||||
set -e
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update
|
||||
apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confold \
|
||||
install ca-certificates curl coreutils
|
||||
'
|
||||
rc=$?
|
||||
set -e
|
||||
if [[ $rc -eq 0 ]]; then
|
||||
ok "Debian bootstrap complete."
|
||||
else
|
||||
warn_red "Debian bootstrap incomplete (inner apt-get failed, rc=$rc)."
|
||||
warn "You can retry later with: proot-distro login debian"
|
||||
fi
|
||||
}
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
# shellcheck shell=bash
|
||||
# Module file (no shebang). Bundled by build_bundle.sh
|
||||
|
||||
# -------------------------
|
||||
# Termux:API notifications + prompts
|
||||
# -------------------------
|
||||
NOTIF_BASE_ID=9400
|
||||
NOTIF_SEQ=0
|
||||
LAST_NOTIF_ID=""
|
||||
|
||||
# Termux:API sanity check (notifications)
|
||||
termux_api_ready() {
|
||||
have termux-notification || return 1
|
||||
have termux-dialog || return 1
|
||||
|
||||
# Quick probe: some Samsung setups fail until Termux:API app is installed/allowed.
|
||||
# We try a harmless notification and remove it.
|
||||
local msg="iiab test notification"
|
||||
if ! termux-notification --id "$NOTIF_BASE_ID" --title "iiab" --content "$msg" --priority max --sound >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
if have termux-notification-remove; then
|
||||
termux-notification-remove "$NOTIF_BASE_ID" >/dev/null 2>&1 || true
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
sanitize_timeout() {
|
||||
# Ensure TIMEOUT_SECS is a positive integer
|
||||
if ! [[ "${TIMEOUT_SECS:-}" =~ ^[0-9]+$ ]]; then
|
||||
warn "Invalid --timeout='${TIMEOUT_SECS:-}'. Falling back to 180."
|
||||
TIMEOUT_SECS=180
|
||||
elif (( TIMEOUT_SECS < 5 )); then
|
||||
warn "Very low --timeout=${TIMEOUT_SECS}. Forcing minimum 5 seconds."
|
||||
TIMEOUT_SECS=5
|
||||
fi
|
||||
}
|
||||
|
||||
cleanup_notif() {
|
||||
have termux-notification-remove || return 0
|
||||
termux-notification-remove "$NOTIF_BASE_ID" >/dev/null 2>&1 || true
|
||||
if [[ -n "${LAST_NOTIF_ID:-}" ]]; then
|
||||
termux-notification-remove "$LAST_NOTIF_ID" >/dev/null 2>&1 || true
|
||||
fi
|
||||
}
|
||||
|
||||
notify_ask_one() {
|
||||
# args: key title content
|
||||
local key="$1" title="$2" content="$3"
|
||||
local out="$ADB_STATE_DIR/$key.txt"
|
||||
rm -f "$out"
|
||||
local action
|
||||
|
||||
# Fresh notification each time + sound (use a new ID so Android plays sound each time)
|
||||
local nid
|
||||
nid=$((NOTIF_BASE_ID + 1 + NOTIF_SEQ))
|
||||
NOTIF_SEQ=$((NOTIF_SEQ + 1))
|
||||
LAST_NOTIF_ID="$nid"
|
||||
|
||||
if have termux-notification-remove; then
|
||||
termux-notification-remove "$nid" >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
# termux-notification does not provide a reply input; use termux-dialog to capture text.
|
||||
if ! have termux-dialog; then
|
||||
warn "termux-dialog not available. Install: pkg install termux-api + Termux:API app."
|
||||
return 1
|
||||
fi
|
||||
|
||||
action="sh -lc 'termux-dialog -i -t \"${title}\" -h \"${content}\" | tr -d \"\\n\" | sed -n \"s/.*\\\"text\\\"[[:space:]]*:[[:space:]]*\\\"\\([^\\\"]*\\)\\\".*/\\1/p\" > \"${out}\"'"
|
||||
|
||||
termux-notification \
|
||||
--id "$nid" \
|
||||
--ongoing \
|
||||
--priority max \
|
||||
--title "$title" \
|
||||
--content "$content" \
|
||||
--sound \
|
||||
--button1 "Answer" \
|
||||
--button1-action "$action" \
|
||||
|| return 1
|
||||
|
||||
local start now
|
||||
start="$(date +%s)"
|
||||
while true; do
|
||||
if [[ -f "$out" ]]; then
|
||||
if have termux-notification-remove; then
|
||||
termux-notification-remove "$nid" >/dev/null 2>&1 || true
|
||||
fi
|
||||
tr -d '\r\n' < "$out"
|
||||
return 0
|
||||
fi
|
||||
now="$(date +%s)"
|
||||
if (( now - start >= TIMEOUT_SECS )); then
|
||||
if have termux-notification-remove; then
|
||||
termux-notification-remove "$nid" >/dev/null 2>&1 || true
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
ask_port_5digits() {
|
||||
# args: key title
|
||||
local key="$1" title="$2" v=""
|
||||
while true; do
|
||||
v="$(notify_ask_one "$key" "$title" "(5 digits)")" || return 1
|
||||
v="${v//[[:space:]]/}"
|
||||
[[ "$v" =~ ^[0-9]{5}$ ]] || continue
|
||||
echo "$v"
|
||||
return 0
|
||||
done
|
||||
}
|
||||
|
||||
ask_code_6digits() {
|
||||
local v=""
|
||||
while true; do
|
||||
v="$(notify_ask_one code "PAIR CODE" "(6 digits)")" || return 1
|
||||
v="${v//[[:space:]]/}"
|
||||
[[ -n "$v" ]] || continue
|
||||
[[ "$v" =~ ^[0-9]+$ ]] || continue
|
||||
# Normalize to 6 digits (allow missing leading zeros)
|
||||
if ((${#v} < 6)); then
|
||||
v="$(printf "%06d" "$v")"
|
||||
fi
|
||||
[[ "$v" =~ ^[0-9]{6}$ ]] || continue
|
||||
echo "$v"
|
||||
return 0
|
||||
done
|
||||
}
|
||||
|
|
@ -0,0 +1,183 @@
|
|||
# shellcheck shell=bash
|
||||
# Module file (no shebang). Bundled by build_bundle.sh
|
||||
|
||||
# -------------------------
|
||||
# ADB wireless pair/connect wizard
|
||||
# -------------------------
|
||||
cleanup_offline_loopback() {
|
||||
local keep_serial="$1" # e.g. 127.0.0.1:41313
|
||||
local serial state rest
|
||||
while read -r serial state rest; do
|
||||
[[ -n "${serial:-}" ]] || continue
|
||||
[[ "$serial" == ${HOST}:* ]] || continue
|
||||
[[ "$state" == "offline" ]] || continue
|
||||
[[ "$serial" == "$keep_serial" ]] && continue
|
||||
adb disconnect "$serial" >/dev/null 2>&1 || true
|
||||
done < <(adb devices 2>/dev/null | tail -n +2 | sed '/^[[:space:]]*$/d')
|
||||
}
|
||||
|
||||
adb_pair_connect() {
|
||||
need adb || die "Missing adb. Install: pkg install android-tools"
|
||||
|
||||
# Only require Termux:API when we will prompt the user
|
||||
if [[ "$ONLY_CONNECT" != "1" || -z "${CONNECT_PORT:-}" ]]; then
|
||||
termux_api_ready || die "Termux:API not ready."
|
||||
fi
|
||||
|
||||
echo "[*] adb: $(adb version | head -n 1)"
|
||||
adb start-server >/dev/null 2>&1 || true
|
||||
|
||||
if [[ "$ONLY_CONNECT" == "1" ]]; then
|
||||
if [[ -n "$CONNECT_PORT" ]]; then
|
||||
CONNECT_PORT="${CONNECT_PORT//[[:space:]]/}"
|
||||
[[ "$CONNECT_PORT" =~ ^[0-9]{5}$ ]] || die "Invalid CONNECT PORT (must be 5 digits): '$CONNECT_PORT'"
|
||||
else
|
||||
echo "[*] Asking CONNECT PORT..."
|
||||
CONNECT_PORT="$(ask_port_5digits connect "CONNECT PORT")" || die "Timeout waiting CONNECT PORT."
|
||||
fi
|
||||
|
||||
local serial="${HOST}:${CONNECT_PORT}"
|
||||
adb disconnect "$serial" >/dev/null 2>&1 || true
|
||||
echo "[*] adb connect $serial"
|
||||
adb connect "$serial" >/dev/null || die "adb connect failed to $serial. Verify Wireless debugging is enabled and CONNECT PORT is correct."
|
||||
|
||||
if [[ "$CLEANUP_OFFLINE" == "1" ]]; then
|
||||
cleanup_offline_loopback "$serial"
|
||||
fi
|
||||
|
||||
echo "[*] Devices:"
|
||||
adb devices -l
|
||||
|
||||
echo "[*] ADB check (shell):"
|
||||
adb -s "$serial" shell sh -lc 'echo "it worked: adb shell is working"; id' || true
|
||||
|
||||
cleanup_notif
|
||||
ok "ADB connected (connect-only): $serial"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -n "$CONNECT_PORT" ]]; then
|
||||
CONNECT_PORT="${CONNECT_PORT//[[:space:]]/}"
|
||||
[[ "$CONNECT_PORT" =~ ^[0-9]{5}$ ]] || die "Invalid --connect-port (must be 5 digits): '$CONNECT_PORT'"
|
||||
else
|
||||
echo "[*] Asking CONNECT PORT..."
|
||||
CONNECT_PORT="$(ask_port_5digits connect "CONNECT PORT")" || die "Timeout waiting CONNECT PORT."
|
||||
fi
|
||||
|
||||
echo "[*] Asking PAIR PORT..."
|
||||
local pair_port
|
||||
pair_port="$(ask_port_5digits pair "PAIR PORT")" || die "Timeout waiting PAIR PORT."
|
||||
|
||||
echo "[*] Asking PAIR CODE..."
|
||||
local code
|
||||
code="$(ask_code_6digits)" || die "Timeout waiting PAIR CODE."
|
||||
|
||||
local serial="${HOST}:${CONNECT_PORT}"
|
||||
adb disconnect "$serial" >/dev/null 2>&1 || true
|
||||
|
||||
echo "[*] adb pair ${HOST}:${pair_port}"
|
||||
printf '%s\n' "$code" | adb pair "${HOST}:${pair_port}" || die "adb pair failed. Verify PAIR PORT and PAIR CODE (and that the pairing dialog is showing)."
|
||||
|
||||
echo "[*] adb connect $serial"
|
||||
adb connect "$serial" >/dev/null || die "adb connect failed after pairing. Re-check CONNECT PORT and Wireless debugging."
|
||||
|
||||
if [[ "$CLEANUP_OFFLINE" == "1" ]]; then
|
||||
cleanup_offline_loopback "$serial"
|
||||
fi
|
||||
|
||||
echo "[*] Devices:"
|
||||
adb devices -l
|
||||
|
||||
echo "[*] ADB check (shell):"
|
||||
adb -s "$serial" shell sh -lc 'echo "it worked: adb shell is working"; getprop ro.product.model; getprop ro.build.version.release' || true
|
||||
|
||||
cleanup_notif
|
||||
ok "ADB connected: $serial"
|
||||
}
|
||||
|
||||
# Return state for an exact serial (e.g. "device", "offline", empty)
|
||||
adb_device_state() {
|
||||
local s="$1"
|
||||
adb devices 2>/dev/null | awk -v s="$s" 'NR>1 && $1==s {print $2; exit}'
|
||||
}
|
||||
|
||||
# Return first loopback serial in "device" state (e.g. 127.0.0.1:41313)
|
||||
adb_any_loopback_device() {
|
||||
adb devices 2>/dev/null | awk -v h="$HOST" '
|
||||
NR>1 && $2=="device" && index($1, h":")==1 {print $1; found=1; exit}
|
||||
END { exit (found ? 0 : 1) }
|
||||
'
|
||||
}
|
||||
|
||||
# Pick the loopback serial we will operate on:
|
||||
# - If CONNECT_PORT is set, require that exact HOST:PORT to be in "device" state.
|
||||
# - Otherwise, return the first loopback device.
|
||||
adb_pick_loopback_serial() {
|
||||
if [[ -n "${CONNECT_PORT:-}" ]]; then
|
||||
local p="${CONNECT_PORT//[[:space:]]/}"
|
||||
[[ "$p" =~ ^[0-9]{5}$ ]] || return 1
|
||||
local target="${HOST}:${p}"
|
||||
[[ "$(adb_device_state "$target")" == "device" ]] && { echo "$target"; return 0; }
|
||||
return 1
|
||||
fi
|
||||
adb_any_loopback_device
|
||||
}
|
||||
|
||||
# If already connected, avoid re-pairing/re-connecting prompts (useful for --all),
|
||||
# BUT only consider loopback/target connections as "already connected".
|
||||
adb_pair_connect_if_needed() {
|
||||
need adb || die "Missing adb. Install: pkg install android-tools"
|
||||
adb start-server >/dev/null 2>&1 || true
|
||||
|
||||
local serial=""
|
||||
|
||||
# If user provided a connect-port, insist on that exact target serial.
|
||||
if [[ -n "${CONNECT_PORT:-}" ]]; then
|
||||
CONNECT_PORT="${CONNECT_PORT//[[:space:]]/}"
|
||||
[[ "$CONNECT_PORT" =~ ^[0-9]{5}$ ]] || die "Invalid --connect-port (must be 5 digits): '$CONNECT_PORT'"
|
||||
|
||||
local target="${HOST}:${CONNECT_PORT}"
|
||||
|
||||
if [[ "$(adb_device_state "$target")" == "device" ]]; then
|
||||
ok "ADB already connected to target: $target (skipping pair/connect)."
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Try connect-only first (in case it was already paired before)
|
||||
adb connect "$target" >/dev/null 2>&1 || true
|
||||
if [[ "$(adb_device_state "$target")" == "device" ]]; then
|
||||
ok "ADB connected to target: $target (connect-only succeeded; skipping pair)."
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Not connected: run full wizard (pair+connect)
|
||||
adb_pair_connect
|
||||
return $?
|
||||
fi
|
||||
|
||||
# No explicit port: only skip if we already have a loopback device connected.
|
||||
if serial="$(adb_any_loopback_device 2>/dev/null)"; then
|
||||
ok "ADB already connected (loopback): $serial (skipping pair/connect)."
|
||||
return 0
|
||||
fi
|
||||
|
||||
adb_pair_connect
|
||||
}
|
||||
|
||||
require_adb_connected() {
|
||||
need adb || { warn_red "Missing adb. Install: pkg install android-tools"; return 1; }
|
||||
adb start-server >/dev/null 2>&1 || true
|
||||
if ! adb_pick_loopback_serial >/dev/null 2>&1; then
|
||||
warn_red "No ADB device connected."
|
||||
warn "If already paired before: run --connect-only [PORT]."
|
||||
warn "Otherwise: run --adb-only to pair+connect."
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
adb_loopback_serial_or_die() {
|
||||
local s
|
||||
s="$(adb_pick_loopback_serial 2>/dev/null)" || return 1
|
||||
echo "$s"
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
# shellcheck shell=bash
|
||||
# Module file (no shebang). Bundled by build_bundle.sh
|
||||
|
||||
# PPK / phantom-process checks and tuning via ADB (best-effort)
|
||||
# Moved out of 99_main.sh to keep it as an orchestrator.
|
||||
|
||||
# -------------------------
|
||||
# PPK / phantom-process tuning (best-effort)
|
||||
# -------------------------
|
||||
ppk_fix_via_adb() {
|
||||
need adb || die "Missing adb. Install: pkg install android-tools"
|
||||
|
||||
local serial
|
||||
if ! serial="$(adb_pick_loopback_serial)"; then
|
||||
CHECK_NO_ADB=1
|
||||
warn "No ADB loopback device connected (expected ${HOST}:${CONNECT_PORT:-*})."
|
||||
return 1
|
||||
fi
|
||||
ok "Using ADB device: $serial"
|
||||
|
||||
log "Setting PPK: max_phantom_processes=256"
|
||||
# Some Android versions may ignore/rename this; we don't hard-fail.
|
||||
adb -s "$serial" shell sh -lc '
|
||||
set -e
|
||||
# Persist device_config changes if supported
|
||||
if command -v device_config >/dev/null 2>&1; then
|
||||
device_config set_sync_disabled_for_tests persistent >/dev/null 2>&1 || true
|
||||
device_config put activity_manager max_phantom_processes 256 || true
|
||||
echo "dumpsys effective max_phantom_processes:"
|
||||
dumpsys activity settings 2>/dev/null | grep -i "max_phantom_processes=" | head -n 1 || true
|
||||
else
|
||||
echo "device_config not found; skipping."
|
||||
fi
|
||||
' || true
|
||||
|
||||
ok "PPK set done (best effort)."
|
||||
return 0
|
||||
}
|
||||
|
||||
# Prefer Android 14+ feature-flag override if present:
|
||||
# OFF -> true, ON -> false
|
||||
adb_get_child_restrictions_flag() {
|
||||
local serial="$1"
|
||||
adb -s "$serial" shell getprop persist.sys.fflag.override.settings_enable_monitor_phantom_procs \
|
||||
2>/dev/null | tr -d '\r' || true
|
||||
}
|
||||
|
||||
# -------------------------
|
||||
# Check readiness (best-effort)
|
||||
# -------------------------
|
||||
check_readiness() {
|
||||
# Reset exported check signals so final_advice() never sees stale values
|
||||
CHECK_NO_ADB=0
|
||||
CHECK_SDK=""
|
||||
CHECK_MON=""
|
||||
CHECK_PPK=""
|
||||
|
||||
need adb || die "Missing adb. Install: pkg install android-tools"
|
||||
adb start-server >/dev/null 2>&1 || true
|
||||
|
||||
local serial
|
||||
if ! serial="$(adb_pick_loopback_serial)"; then
|
||||
CHECK_NO_ADB=1
|
||||
# Best-effort: keep local SDK so final_advice can still warn on A12-13.
|
||||
CHECK_SDK="${ANDROID_SDK:-}"
|
||||
warn_red "No ADB device connected. Cannot run checks."
|
||||
warn "If already paired before: run --connect-only [PORT]."
|
||||
warn "Otherwise: run --adb-only to pair+connect."
|
||||
return 1
|
||||
fi
|
||||
|
||||
ok "Check using ADB device: $serial"
|
||||
|
||||
local dev_enabled sdk rel mon mon_fflag ds ppk_eff
|
||||
sdk="$(adb -s "$serial" shell getprop ro.build.version.sdk 2>/dev/null | tr -d '\r' || true)"
|
||||
rel="$(adb -s "$serial" shell getprop ro.build.version.release 2>/dev/null | tr -d '\r' || true)"
|
||||
dev_enabled="$(adb -s "$serial" shell settings get global development_settings_enabled 2>/dev/null | tr -d '\r' || true)"
|
||||
mon_fflag="$(adb_get_child_restrictions_flag "$serial")"
|
||||
if [[ "$mon_fflag" == "true" || "$mon_fflag" == "false" ]]; then
|
||||
mon="$mon_fflag"
|
||||
else
|
||||
mon="$(adb -s "$serial" shell settings get global settings_enable_monitor_phantom_procs 2>/dev/null | tr -d '\r' || true)"
|
||||
fi
|
||||
|
||||
# Get effective value from dumpsys (device_config get may return 'null' even when an effective value exists)
|
||||
ds="$(adb -s "$serial" shell dumpsys activity settings 2>/dev/null | tr -d '\r' || true)"
|
||||
ppk_eff="$(printf '%s\n' "$ds" | awk -F= '/max_phantom_processes=/{print $2; exit}' | tr -d '[:space:]' || true)"
|
||||
|
||||
# Export check signals for the final advice logic
|
||||
CHECK_SDK="${sdk:-}"
|
||||
CHECK_MON="${mon:-}"
|
||||
CHECK_PPK="${ppk_eff:-}"
|
||||
|
||||
log " Android release=${rel:-?} sdk=${sdk:-?}"
|
||||
|
||||
if [[ "${dev_enabled:-}" == "1" ]]; then
|
||||
ok " Developer options: enabled (development_settings_enabled=1)"
|
||||
elif [[ -n "${dev_enabled:-}" ]]; then
|
||||
warn " Developer options: unknown/disabled (development_settings_enabled=${dev_enabled})"
|
||||
else
|
||||
warn " Developer options: unreadable (permission/ROM differences)."
|
||||
fi
|
||||
|
||||
# Android 14+ only: "Disable child process restrictions" proxy flag
|
||||
if [[ "${sdk:-}" =~ ^[0-9]+$ ]] && (( sdk >= 34 )); then
|
||||
if [[ "${mon:-}" == "false" ]]; then
|
||||
ok " Child restrictions: OK (monitor=false)"
|
||||
elif [[ "${mon:-}" == "true" ]]; then
|
||||
warn " Child restrictions: NOT OK (monitor=true)"
|
||||
elif [[ -n "${mon:-}" && "${mon:-}" != "null" ]]; then
|
||||
warn " Child restrictions: unknown (${mon})"
|
||||
else
|
||||
warn " Child restrictions: unreadable/absent"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Android 12-13 only: PPK matters (use effective value from dumpsys)
|
||||
if [[ "${sdk:-}" =~ ^[0-9]+$ ]] && (( sdk >= 31 && sdk <= 33 )); then
|
||||
if [[ "${ppk_eff:-}" =~ ^[0-9]+$ ]]; then
|
||||
if (( ppk_eff >= 256 )); then
|
||||
ok " PPK: OK (max_phantom_processes=${ppk_eff})"
|
||||
else
|
||||
warn " PPK: low (max_phantom_processes=${ppk_eff}) -> suggest: run --ppk-only"
|
||||
fi
|
||||
else
|
||||
warn " PPK: unreadable (dumpsys max_phantom_processes='${ppk_eff:-}')."
|
||||
fi
|
||||
fi
|
||||
|
||||
log " dumpsys (phantom-related):"
|
||||
printf '%s\n' "$ds" | grep -i phantom || true
|
||||
|
||||
if [[ "${sdk:-}" =~ ^[0-9]+$ ]] && (( sdk >= 34 )); then
|
||||
log " Note: On A14+, max_phantom_processes is informational; rely on Child restrictions."
|
||||
fi
|
||||
if [[ "${sdk:-}" =~ ^[0-9]+$ ]] && (( sdk >= 34 )) && [[ "${mon:-}" == "false" ]]; then
|
||||
log " Child restrictions OK."
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
|
@ -0,0 +1,332 @@
|
|||
# shellcheck shell=bash
|
||||
# Module file (no shebang). Bundled by build_bundle.sh
|
||||
|
||||
# 0_termux-setupv2.sh
|
||||
# - Termux bootstrap (packages, wakelock)
|
||||
# - proot-distro + Debian bootstrap
|
||||
# - ADB wireless pair/connect via Termux:API notifications (no Shizuku)
|
||||
# - Optional PPK / phantom-process tweaks (best-effort)
|
||||
|
||||
# -------------------------
|
||||
# Defaults
|
||||
# -------------------------
|
||||
STATE_DIR="${HOME}/.iiab-android"
|
||||
ADB_STATE_DIR="${STATE_DIR}/adbw_pair"
|
||||
LOG_DIR="${STATE_DIR}/logs"
|
||||
mkdir -p "$STATE_DIR" "$ADB_STATE_DIR"
|
||||
|
||||
HOST="127.0.0.1"
|
||||
CONNECT_PORT=""
|
||||
TIMEOUT_SECS=180
|
||||
CLEANUP_OFFLINE=1
|
||||
DEBUG=0
|
||||
|
||||
RESET_DEBIAN=0
|
||||
ONLY_CONNECT=0
|
||||
|
||||
CHECK_NO_ADB=0
|
||||
CHECK_SDK=""
|
||||
CHECK_MON=""
|
||||
CHECK_PPK=""
|
||||
|
||||
# Modes are mutually exclusive (baseline is default)
|
||||
MODE="baseline" # baseline|with-adb|adb-only|connect-only|ppk-only|check|all
|
||||
MODE_SET=0
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
./0_termux-setupv2.sh
|
||||
-> Termux baseline + Debian bootstrap (idempotent). No ADB prompts.
|
||||
|
||||
./0_termux-setupv2.sh --with-adb
|
||||
-> Termux baseline + Debian bootstrap + ADB pair/connect if needed (skips if already connected).
|
||||
|
||||
./0_termux-setupv2.sh --adb-only
|
||||
-> Only ADB pair/connect if needed (no Debian; skips if already connected).
|
||||
|
||||
./0_termux-setupv2.sh --connect-only [CONNECT_PORT]
|
||||
-> Connect-only (no pairing). Use this after the device was already paired before.
|
||||
|
||||
./0_termux-setupv2.sh --ppk-only
|
||||
-> Set PPK only: max_phantom_processes=256 (requires ADB already connected).
|
||||
Android 14-16 usually achieve this via "Disable child process restrictions" in Developer Options.
|
||||
|
||||
./0_termux-setupv2.sh --check
|
||||
-> Check readiness: developer options flag (if readable),
|
||||
(Android 14+) "Disable child process restrictions" proxy flag, and (Android 12-13) PPK effective value.
|
||||
|
||||
./0_termux-setupv2.sh --all
|
||||
-> baseline + Debian + ADB pair/connect if needed + (Android 12-13 only) apply --ppk + run --check.
|
||||
|
||||
Optional:
|
||||
--connect-port 41313 (5 digits) Skip CONNECT PORT prompt
|
||||
--timeout 180 Seconds to wait per prompt
|
||||
--reset-debian Reset (reinstall) Debian in proot-distro
|
||||
--no-log Disable logging
|
||||
--log-file /path/file Write logs to a specific file
|
||||
--debug Extra logs
|
||||
|
||||
Notes:
|
||||
- ADB prompts require: `pkg install termux-api` + Termux:API app installed + notification permission.
|
||||
- Wireless debugging must be enabled.
|
||||
- This script never uses adb root.
|
||||
EOF
|
||||
}
|
||||
|
||||
trap 'cleanup_notif >/dev/null 2>&1 || true; release_wakelock >/dev/null 2>&1 || true' EXIT INT TERM
|
||||
|
||||
# NOTE: Termux:API prompts live in 40_mod_termux_api.sh
|
||||
|
||||
# -------------------------
|
||||
# Self-check
|
||||
# -------------------------
|
||||
self_check() {
|
||||
log "Self-check summary:"
|
||||
log " Android release=${ANDROID_REL:-?} sdk=${ANDROID_SDK:-?}"
|
||||
|
||||
if have proot-distro; then
|
||||
log " proot-distro: present"
|
||||
log " proot-distro list:"
|
||||
proot-distro list 2>/dev/null | sed 's/^/ /' || true
|
||||
if debian_exists; then ok " Debian: present"; else warn " Debian: not present"; fi
|
||||
else
|
||||
warn " proot-distro: not present"
|
||||
fi
|
||||
|
||||
if have adb; then
|
||||
log " adb: present"
|
||||
adb devices -l 2>/dev/null | sed 's/^/ /' || true
|
||||
local serial
|
||||
if serial="$(adb_pick_loopback_serial 2>/dev/null)"; then
|
||||
log " adb shell id (first device):"
|
||||
adb -s "$serial" shell id 2>/dev/null | sed 's/^/ /' || true
|
||||
fi
|
||||
else
|
||||
warn " adb: not present"
|
||||
fi
|
||||
|
||||
if have termux-wake-lock; then ok " Termux:API wakelock: available"; else warn " Termux:API wakelock: not available"; fi
|
||||
if have termux-notification; then ok " Termux:API notifications: command present"; else warn " Termux:API notifications: missing"; fi
|
||||
}
|
||||
|
||||
final_advice() {
|
||||
# 1) Android-related warnings (only meaningful if we attempted checks)
|
||||
local sdk="${CHECK_SDK:-${ANDROID_SDK:-}}"
|
||||
local adb_connected=0
|
||||
local serial="" mon="" mon_fflag=""
|
||||
|
||||
# Best-effort: detect whether an ADB loopback device is already connected.
|
||||
# (We do NOT prompt/pair here; we only check current state.)
|
||||
if have adb; then
|
||||
adb start-server >/dev/null 2>&1 || true
|
||||
if adb_pick_loopback_serial >/dev/null 2>&1; then
|
||||
adb_connected=1
|
||||
serial="$(adb_pick_loopback_serial 2>/dev/null || true)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Baseline safety gate:
|
||||
# On Android 12-13 (SDK 31-33), IIAB/proot installs can fail if PPK is low (often 32).
|
||||
# Baseline mode does NOT force ADB pairing nor run check_readiness(), so PPK may be unknown.
|
||||
# If PPK is not determined, suggest running --all BEFORE telling user to proceed to proot-distro.
|
||||
if [[ "$MODE" == "baseline" ]]; then
|
||||
if [[ "$sdk" =~ ^[0-9]+$ ]] && (( sdk >= 31 && sdk <= 33 )); then
|
||||
# If we didn't run checks, CHECK_PPK will be empty. Even with adb_connected=1, baseline
|
||||
# still doesn't populate CHECK_PPK unless user ran --check/--all.
|
||||
if [[ "${CHECK_PPK:-}" != "" && "${CHECK_PPK:-}" =~ ^[0-9]+$ ]]; then
|
||||
: # PPK determined -> ok to continue with normal advice below
|
||||
else
|
||||
warn "Android 12-13: PPK value hasn't been verified (max_phantom_processes may be low, e.g. 32)."
|
||||
warn "Before starting the IIAB install, run the complete setup so it can apply/check PPK=256; otherwise the installation may fail:"
|
||||
ok " ./0_termux-setupv2.sh --all"
|
||||
return 0
|
||||
fi
|
||||
elif [[ "$sdk" =~ ^[0-9]+$ ]] && (( sdk >= 34 )); then
|
||||
# On Android 14+, rely on "Disable child process restrictions"
|
||||
# Proxy signals: settings_enable_monitor_phantom_procs (or the fflag override).
|
||||
# Baseline does not run check_readiness(), so CHECK_MON is usually empty.
|
||||
if [[ "${CHECK_MON:-}" == "false" ]]; then
|
||||
: # Verified OK (rare in baseline) -> continue
|
||||
else
|
||||
# If ADB is already connected, try to read the flag best-effort (no prompts).
|
||||
if [[ "$adb_connected" -eq 1 && -n "${serial:-}" ]]; then
|
||||
mon_fflag="$(adb_get_child_restrictions_flag "$serial")"
|
||||
if [[ "$mon_fflag" == "true" || "$mon_fflag" == "false" ]]; then
|
||||
mon="$mon_fflag"
|
||||
else
|
||||
mon="$(adb -s "$serial" shell settings get global settings_enable_monitor_phantom_procs 2>/dev/null | tr -d '\r' || true)"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "${mon:-}" == "false" ]]; then
|
||||
: # Restrictions already disabled -> ok to continue
|
||||
else
|
||||
if [[ "${mon:-}" == "true" ]]; then
|
||||
warn "Android 14+: child process restrictions appear ENABLED (monitor=true)."
|
||||
else
|
||||
warn "Android 14+: child process restrictions haven't been verified (monitor flag unreadable/unknown)."
|
||||
fi
|
||||
warn "Before starting the IIAB install, run the complete setup (--all) so it can guide you to verify such setting; otherwise the installation may fail:"
|
||||
ok " ./0_termux-setupv2.sh --all"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "${CHECK_NO_ADB:-0}" -eq 1 ]]; then
|
||||
# If we could not check, still warn on A12-13 because PPK is critical there
|
||||
if [[ "$sdk" =~ ^[0-9]+$ ]] && (( sdk >= 31 && sdk <= 33 )); then
|
||||
warn "A12-13: verify PPK=256 before installing IIAB."
|
||||
fi
|
||||
else
|
||||
# A14+ child restrictions proxy (only if readable)
|
||||
if [[ "$sdk" =~ ^[0-9]+$ ]] && (( sdk >= 34 )) && [[ "${CHECK_MON:-}" == "true" ]]; then
|
||||
warn "A14+: disable child process restrictions before installing IIAB."
|
||||
fi
|
||||
|
||||
# Only warn about PPK on A12-13 (A14+ uses child restrictions)
|
||||
if [[ "$sdk" =~ ^[0-9]+$ ]] && (( sdk >= 31 && sdk <= 33 )); then
|
||||
if [[ "${CHECK_PPK:-}" =~ ^[0-9]+$ ]] && (( CHECK_PPK < 256 )); then
|
||||
warn "PPK is low (${CHECK_PPK}); consider --ppk-only."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# 2) Debian “next step” should only be shown for modes that actually bootstrap Debian
|
||||
case "$MODE" in
|
||||
baseline|with-adb|all)
|
||||
if debian_exists; then
|
||||
ok "Next: proot-distro login debian"
|
||||
else
|
||||
warn "Debian not present. Run: proot-distro install debian"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
# adb-only/connect-only/ppk-only/check: do not suggest Debian login as a generic ending
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# -------------------------
|
||||
# Args
|
||||
# -------------------------
|
||||
set_mode() {
|
||||
local new="$1"
|
||||
if [[ "$MODE_SET" -eq 1 ]]; then
|
||||
die "Modes are mutually exclusive. Already set: --${MODE}. Tried: --${new}"
|
||||
fi
|
||||
MODE="$new"
|
||||
MODE_SET=1
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--with-adb) set_mode "with-adb"; shift ;;
|
||||
--adb-only) set_mode "adb-only"; shift ;;
|
||||
--connect-only)
|
||||
set_mode "connect-only"
|
||||
ONLY_CONNECT=1
|
||||
# Optional positional port (5 digits)
|
||||
if [[ "${2:-}" =~ ^[0-9]{5}$ ]]; then
|
||||
CONNECT_PORT="$2"
|
||||
shift 2
|
||||
else
|
||||
shift
|
||||
fi
|
||||
;;
|
||||
--ppk-only) set_mode "ppk-only"; shift ;;
|
||||
--check) set_mode "check"; shift ;;
|
||||
--all) set_mode "all"; shift ;;
|
||||
--connect-port) CONNECT_PORT="${2:-}"; shift 2 ;;
|
||||
--timeout) TIMEOUT_SECS="${2:-180}"; shift 2 ;;
|
||||
--host) HOST="${2:-127.0.0.1}"; shift 2 ;;
|
||||
--reset-debian|--clean-debian) RESET_DEBIAN=1; shift ;;
|
||||
--no-log) LOG_ENABLED=0; shift ;;
|
||||
--log-file) LOG_FILE="${2:-}"; shift 2 ;;
|
||||
--debug) DEBUG=1; shift ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
*) shift ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# -------------------------
|
||||
# Main flows
|
||||
# -------------------------
|
||||
main() {
|
||||
setup_logging "$@"
|
||||
sanitize_timeout
|
||||
acquire_wakelock
|
||||
|
||||
case "$MODE" in
|
||||
baseline)
|
||||
step_termux_repo_select_once
|
||||
step_termux_base
|
||||
step_debian_bootstrap_default
|
||||
;;
|
||||
|
||||
with-adb)
|
||||
step_termux_repo_select_once
|
||||
step_termux_base
|
||||
step_debian_bootstrap_default
|
||||
adb_pair_connect_if_needed
|
||||
;;
|
||||
|
||||
adb-only)
|
||||
step_termux_base
|
||||
adb_pair_connect_if_needed
|
||||
;;
|
||||
|
||||
connect-only)
|
||||
step_termux_base
|
||||
adb_pair_connect
|
||||
;;
|
||||
|
||||
ppk-only)
|
||||
# No baseline, no Debian. Requires adb already available + connected.
|
||||
require_adb_connected || exit 1
|
||||
ppk_fix_via_adb || true
|
||||
;;
|
||||
|
||||
check)
|
||||
step_termux_base
|
||||
check_readiness || true
|
||||
;;
|
||||
|
||||
all)
|
||||
step_termux_repo_select_once
|
||||
step_termux_base
|
||||
step_debian_bootstrap_default
|
||||
adb_pair_connect_if_needed
|
||||
|
||||
# Android 12-13 only (SDK 31-33): apply PPK tuning automatically
|
||||
if [[ "${ANDROID_SDK:-}" =~ ^[0-9]+$ ]] && (( ANDROID_SDK >= 31 && ANDROID_SDK <= 33 )); then
|
||||
log "Android SDK=${ANDROID_SDK} detected -> applying --ppk automatically (12-13 rule)."
|
||||
ppk_fix_via_adb || true
|
||||
else
|
||||
log "Android SDK=${ANDROID_SDK:-?} -> skipping auto-PPK (only for Android 12-13)."
|
||||
fi
|
||||
check_readiness || true
|
||||
;;
|
||||
|
||||
*)
|
||||
die "Unknown MODE='$MODE'"
|
||||
;;
|
||||
esac
|
||||
|
||||
self_check
|
||||
ok "0_termux-setupv2.sh completed (mode=$MODE)."
|
||||
log "---- Mode list ----"
|
||||
log "Connect-only: --connect-only [PORT]"
|
||||
log "Pair+connect: --adb-only"
|
||||
log "Check: --check"
|
||||
log "Apply PPK: --ppk-only"
|
||||
log "Base+Debian+Pair+connect: --with-adb"
|
||||
log "Full run: --all"
|
||||
log "Reset Debian: --reset-debian"
|
||||
log "-------------------"
|
||||
final_advice
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
# termux-setup modules
|
||||
|
||||
This project is maintained as multiple Bash "modules" that are bundled into a single script:
|
||||
`0_termux-setup_v2.sh` (the file served for: `curl ... | bash`).
|
||||
|
||||
## Rules
|
||||
|
||||
- Modules MUST NOT include a shebang (`#!...`).
|
||||
- Modules SHOULD NOT run top-level code (prefer functions), except `99_main.sh`.
|
||||
- Do not add `set -euo pipefail` in modules (the bundle already sets it once).
|
||||
- Keep module names stable and ordered via `manifest.sh`.
|
||||
|
||||
Recommended header for every module:
|
||||
|
||||
```
|
||||
# termux-setup module.
|
||||
# DO NOT add a shebang or "set -euo pipefail" here.
|
||||
# Keep only function/variable definitions (no top-level execution).
|
||||
# See: termux-setup/README.md
|
||||
```
|
||||
|
||||
## Rebuild:
|
||||
|
||||
```
|
||||
cd termux-setup
|
||||
bash build_bundle.sh
|
||||
```
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# build_bundle.sh
|
||||
# Bundles modules listed in manifest.sh into ../0_termux-setup_v2.sh
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$SCRIPT_DIR"
|
||||
|
||||
MANIFEST="${ROOT_DIR}/manifest.sh"
|
||||
[[ -f "$MANIFEST" ]] || { echo "[!] Missing manifest.sh at: $MANIFEST" >&2; exit 1; }
|
||||
|
||||
# Modules live next to build_bundle.sh (same dir)
|
||||
MOD_DIR="$ROOT_DIR"
|
||||
|
||||
PARENT_DIR="$(cd -- "${ROOT_DIR}/.." && pwd)"
|
||||
OUT_DIR="${ROOT_DIR}/dist"
|
||||
OUT_FILE="${PARENT_DIR}/0_termux-setup_v2.sh"
|
||||
TMP_FILE="${OUT_DIR}/.0_termux-setup_v2.tmp.$RANDOM$RANDOM"
|
||||
|
||||
mkdir -p "$OUT_DIR"
|
||||
|
||||
# Load MODULES array
|
||||
# shellcheck source=/dev/null
|
||||
source "$MANIFEST"
|
||||
|
||||
# With "set -u", don't reference an unset array directly.
|
||||
if ! declare -p MODULES >/dev/null 2>&1; then
|
||||
echo "[!] manifest.sh did not define MODULES array." >&2
|
||||
exit 1
|
||||
fi
|
||||
if (( ${#MODULES[@]} < 1 )); then
|
||||
echo "[!] MODULES array is empty in manifest.sh." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cleanup_tmp() { rm -f -- "$TMP_FILE" 2>/dev/null || true; }
|
||||
trap cleanup_tmp EXIT
|
||||
|
||||
# Bundle header
|
||||
{
|
||||
echo '#!/data/data/com.termux/files/usr/bin/bash'
|
||||
echo 'set -euo pipefail'
|
||||
echo
|
||||
echo '# -----------------------------------------------------------------------------'
|
||||
echo '# GENERATED FILE: do not edit directly.'
|
||||
echo '# Source modules: termux-setup/*.sh + manifest.sh'
|
||||
echo '# Rebuild: (cd termux-setup && bash build_bundle.sh)'
|
||||
echo '# -----------------------------------------------------------------------------'
|
||||
echo
|
||||
} >"$TMP_FILE"
|
||||
|
||||
# Append each module
|
||||
for mod in "${MODULES[@]}"; do
|
||||
src="${MOD_DIR}/${mod}"
|
||||
|
||||
if [[ ! -f "$src" ]]; then
|
||||
echo "[!] Missing module: $src" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Disallow standalone scripts: modules must not have a shebang
|
||||
if head -n 1 "$src" | grep -q '^#!'; then
|
||||
echo "[!] Module must NOT include a shebang: $src" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
{
|
||||
echo
|
||||
echo "# ---- BEGIN ${mod} ----"
|
||||
cat "$src"
|
||||
echo
|
||||
echo "# ---- END ${mod} ----"
|
||||
echo
|
||||
} >>"$TMP_FILE"
|
||||
done
|
||||
|
||||
# Ensure final newline
|
||||
printf '\n' >>"$TMP_FILE"
|
||||
|
||||
# Install bundle atomically
|
||||
chmod 700 "$TMP_FILE" 2>/dev/null || true
|
||||
mv -f -- "$TMP_FILE" "$OUT_FILE"
|
||||
chmod 700 "$OUT_FILE" 2>/dev/null || true
|
||||
|
||||
echo "[ok] Wrote: $OUT_FILE"
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# termux-setup manifest
|
||||
# Order matters: later modules can rely on functions/vars defined earlier.
|
||||
|
||||
MODULES=(
|
||||
"00_lib_common.sh"
|
||||
"10_mod_logging.sh"
|
||||
"20_mod_termux_base.sh"
|
||||
"30_mod_debian.sh"
|
||||
"40_mod_termux_api.sh"
|
||||
"50_mod_adb.sh"
|
||||
"60_mod_ppk_checks.sh"
|
||||
"99_main.sh"
|
||||
)
|
||||
Loading…
Reference in New Issue