Рефакторинг кода: дедупликация ucode, исправления shellcheck и глобальное улучшение install.sh
This commit is contained in:
@@ -4,6 +4,7 @@ fe-app-tachyon/node_modules
|
|||||||
fe-app-tachyon/.yarn/
|
fe-app-tachyon/.yarn/
|
||||||
fe-app-tachyon/.env
|
fe-app-tachyon/.env
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
shellcheck-v0.10.0/
|
||||||
AGENTS.md
|
AGENTS.md
|
||||||
|
|
||||||
sandbox/
|
sandbox/
|
||||||
|
|||||||
@@ -747,6 +747,7 @@ build_apk_package() {
|
|||||||
sudo chown "$(id -u):$(id -g)" "$output_file"
|
sudo chown "$(id -u):$(id -g)" "$output_file"
|
||||||
sudo rm -rf "$temp_root" "$temp_scripts"
|
sudo rm -rf "$temp_root" "$temp_scripts"
|
||||||
elif have_unshare_root; then
|
elif have_unshare_root; then
|
||||||
|
# shellcheck disable=SC2048,SC2086
|
||||||
unshare -r sh -c "
|
unshare -r sh -c "
|
||||||
chown -R 0:0 '$temp_root' '$temp_scripts'
|
chown -R 0:0 '$temp_root' '$temp_scripts'
|
||||||
'$apk_bin' mkpkg \
|
'$apk_bin' mkpkg \
|
||||||
@@ -761,7 +762,7 @@ build_apk_package() {
|
|||||||
-I 'maintainer:${maintainer}' \
|
-I 'maintainer:${maintainer}' \
|
||||||
-I 'url:${PROJECT_URL}' \
|
-I 'url:${PROJECT_URL}' \
|
||||||
-I 'depends:${depends}' \
|
-I 'depends:${depends}' \
|
||||||
'${extra_args[@]}' \
|
${extra_args[*]} \
|
||||||
-s pre-install:'$temp_scripts/${script_prefix}-pre-install.sh' \
|
-s pre-install:'$temp_scripts/${script_prefix}-pre-install.sh' \
|
||||||
-s post-install:'$temp_scripts/${script_prefix}-post-install.sh' \
|
-s post-install:'$temp_scripts/${script_prefix}-post-install.sh' \
|
||||||
-s pre-deinstall:'$temp_scripts/${script_prefix}-pre-deinstall.sh' \
|
-s pre-deinstall:'$temp_scripts/${script_prefix}-pre-deinstall.sh' \
|
||||||
@@ -770,6 +771,7 @@ build_apk_package() {
|
|||||||
"
|
"
|
||||||
else
|
else
|
||||||
stderr_file="$(mktemp)"
|
stderr_file="$(mktemp)"
|
||||||
|
# shellcheck disable=SC2048,SC2086
|
||||||
if ! fakeroot sh -c "
|
if ! fakeroot sh -c "
|
||||||
chown -R 0:0 '$temp_root' '$temp_scripts'
|
chown -R 0:0 '$temp_root' '$temp_scripts'
|
||||||
'$apk_bin' mkpkg \
|
'$apk_bin' mkpkg \
|
||||||
@@ -784,7 +786,7 @@ build_apk_package() {
|
|||||||
-I 'maintainer:${maintainer}' \
|
-I 'maintainer:${maintainer}' \
|
||||||
-I 'url:${PROJECT_URL}' \
|
-I 'url:${PROJECT_URL}' \
|
||||||
-I 'depends:${depends}' \
|
-I 'depends:${depends}' \
|
||||||
'${extra_args[@]}' \
|
${extra_args[*]} \
|
||||||
-s pre-install:'$temp_scripts/${script_prefix}-pre-install.sh' \
|
-s pre-install:'$temp_scripts/${script_prefix}-pre-install.sh' \
|
||||||
-s post-install:'$temp_scripts/${script_prefix}-post-install.sh' \
|
-s post-install:'$temp_scripts/${script_prefix}-post-install.sh' \
|
||||||
-s pre-deinstall:'$temp_scripts/${script_prefix}-pre-deinstall.sh' \
|
-s pre-deinstall:'$temp_scripts/${script_prefix}-pre-deinstall.sh' \
|
||||||
|
|||||||
+177
-16
@@ -1,6 +1,8 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# shellcheck shell=dash
|
# shellcheck shell=dash
|
||||||
|
|
||||||
|
INSTALLER_VERSION="2.0.0"
|
||||||
|
|
||||||
REPO_OWNER="Dushnilin"
|
REPO_OWNER="Dushnilin"
|
||||||
REPO_NAME="tachyon"
|
REPO_NAME="tachyon"
|
||||||
|
|
||||||
@@ -12,6 +14,9 @@ DOWNLOAD_TIMEOUT_SECONDS=600
|
|||||||
PKG_IS_APK=0
|
PKG_IS_APK=0
|
||||||
FETCHER=""
|
FETCHER=""
|
||||||
TMP_DIR=""
|
TMP_DIR=""
|
||||||
|
LOCK_FILE="/tmp/tachyon.install.lock"
|
||||||
|
LOG_FILE="/tmp/tachyon-install.log"
|
||||||
|
START_TIME=""
|
||||||
TACHYON_WAS_ENABLED=0
|
TACHYON_WAS_ENABLED=0
|
||||||
TACHYON_WAS_RUNNING=0
|
TACHYON_WAS_RUNNING=0
|
||||||
TACHYON_LEGACY_DETECTED=0
|
TACHYON_LEGACY_DETECTED=0
|
||||||
@@ -20,6 +25,12 @@ TACHYON_I18N_REQUESTED=0
|
|||||||
INSTALLER_LANG="en"
|
INSTALLER_LANG="en"
|
||||||
SING_BOX_INSTALL_VARIANT=""
|
SING_BOX_INSTALL_VARIANT=""
|
||||||
|
|
||||||
|
# Runtime flags (see parse_args)
|
||||||
|
ASSUME_YES=0
|
||||||
|
DRY_RUN=0
|
||||||
|
VERBOSE=0
|
||||||
|
QUIET=0
|
||||||
|
|
||||||
TACHYON_RELEASE_JSON=""
|
TACHYON_RELEASE_JSON=""
|
||||||
TACHYON_RELEASE_TAG=""
|
TACHYON_RELEASE_TAG=""
|
||||||
TACHYON_BACKEND_URL=""
|
TACHYON_BACKEND_URL=""
|
||||||
@@ -39,22 +50,51 @@ LEGACY_CONFIG_BACKUP=""
|
|||||||
|
|
||||||
command -v apk >/dev/null 2>&1 && PKG_IS_APK=1
|
command -v apk >/dev/null 2>&1 && PKG_IS_APK=1
|
||||||
|
|
||||||
|
log_line() {
|
||||||
|
# Append a timestamped line to the log file, best-effort (never fatal).
|
||||||
|
[ -n "$LOG_FILE" ] || return 0
|
||||||
|
printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S' 2>/dev/null || echo '----------------')" "$1" >>"$LOG_FILE" 2>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
msg() {
|
msg() {
|
||||||
|
log_line "INFO $1"
|
||||||
|
[ "$QUIET" -eq 1 ] && return 0
|
||||||
printf '\033[32;1m%s\033[0m\n' "$1"
|
printf '\033[32;1m%s\033[0m\n' "$1"
|
||||||
}
|
}
|
||||||
|
|
||||||
warn() {
|
warn() {
|
||||||
printf '\033[33;1m%s\033[0m\n' "$1"
|
log_line "WARN $1"
|
||||||
|
printf '\033[33;1m%s\033[0m\n' "$1" >&2
|
||||||
}
|
}
|
||||||
|
|
||||||
fail() {
|
fail() {
|
||||||
|
log_line "FAIL $1"
|
||||||
printf '\033[31;1m%s\033[0m\n' "$1" >&2
|
printf '\033[31;1m%s\033[0m\n' "$1" >&2
|
||||||
|
printf '\033[31;1m%s\033[0m\n' "See $LOG_FILE for details." >&2
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug() {
|
||||||
|
log_line "DEBUG $1"
|
||||||
|
[ "$VERBOSE" -eq 1 ] || return 0
|
||||||
|
printf '\033[36m[debug] %s\033[0m\n' "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
step() {
|
||||||
|
# Announce a top-level installation stage, numbered for clarity.
|
||||||
|
step_no="$1"
|
||||||
|
step_total="$2"
|
||||||
|
step_text="$3"
|
||||||
|
log_line "STEP [$step_no/$step_total] $step_text"
|
||||||
|
[ "$QUIET" -eq 1 ] && return 0
|
||||||
|
printf '\033[34;1m[%s/%s]\033[0m \033[1m%s\033[0m\n' "$step_no" "$step_total" "$step_text"
|
||||||
|
}
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
Usage: $0
|
Tachyon installer v${INSTALLER_VERSION}
|
||||||
|
|
||||||
|
Usage: $0 [options]
|
||||||
|
|
||||||
Installs or updates Tachyon packages:
|
Installs or updates Tachyon packages:
|
||||||
- tachyon
|
- tachyon
|
||||||
@@ -64,6 +104,17 @@ Installs or updates Tachyon packages:
|
|||||||
Can also install or switch sing-box variant:
|
Can also install or switch sing-box variant:
|
||||||
- stable sing-box from OpenWrt feeds
|
- stable sing-box from OpenWrt feeds
|
||||||
- sing-box-extended from GitHub OpenWrt packages (for xHTTP support)
|
- sing-box-extended from GitHub OpenWrt packages (for xHTTP support)
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-y, --yes Assume "yes"/default answer for every interactive prompt
|
||||||
|
-n, --dry-run Resolve versions and show planned actions, but don't
|
||||||
|
download, install, remove, or modify anything on disk
|
||||||
|
-v, --verbose Print extra diagnostic detail while installing
|
||||||
|
-q, --quiet Suppress informational output (errors/warnings still show)
|
||||||
|
--version Print the installer version and exit
|
||||||
|
-h, --help Show this help text and exit
|
||||||
|
|
||||||
|
Log file: $LOG_FILE
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,16 +125,57 @@ parse_args() {
|
|||||||
usage
|
usage
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
|
--version)
|
||||||
|
printf 'tachyon-installer %s\n' "$INSTALLER_VERSION"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
-y|--yes)
|
||||||
|
ASSUME_YES=1
|
||||||
|
;;
|
||||||
|
-n|--dry-run)
|
||||||
|
DRY_RUN=1
|
||||||
|
;;
|
||||||
|
-v|--verbose)
|
||||||
|
VERBOSE=1
|
||||||
|
;;
|
||||||
|
-q|--quiet)
|
||||||
|
QUIET=1
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
fail "Unknown installer option: $1"
|
fail "Unknown installer option: $1 (see --help)"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
shift
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
|
if [ "$VERBOSE" -eq 1 ] && [ "$QUIET" -eq 1 ]; then
|
||||||
|
fail "--verbose and --quiet cannot be used together"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
acquire_lock() {
|
||||||
|
# Guard against two copies of the installer running at once, which could
|
||||||
|
# corrupt package state or UCI config. Stale locks (dead PID) are reclaimed.
|
||||||
|
if [ -f "$LOCK_FILE" ]; then
|
||||||
|
existing_pid="$(cat "$LOCK_FILE" 2>/dev/null || true)"
|
||||||
|
if [ -n "$existing_pid" ] && kill -0 "$existing_pid" 2>/dev/null; then
|
||||||
|
fail "Another instance of the installer appears to be running (pid $existing_pid). Remove $LOCK_FILE if this is incorrect."
|
||||||
|
fi
|
||||||
|
debug "Removing stale lock file from pid $existing_pid"
|
||||||
|
rm -f "$LOCK_FILE"
|
||||||
|
fi
|
||||||
|
printf '%s' "$$" >"$LOCK_FILE" 2>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
|
release_lock() {
|
||||||
|
[ -f "$LOCK_FILE" ] || return 0
|
||||||
|
lock_pid="$(cat "$LOCK_FILE" 2>/dev/null || true)"
|
||||||
|
[ "$lock_pid" = "$$" ] && rm -f "$LOCK_FILE"
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
[ -n "$TMP_DIR" ] && rm -rf "$TMP_DIR"
|
[ -n "$TMP_DIR" ] && rm -rf "$TMP_DIR"
|
||||||
|
release_lock
|
||||||
}
|
}
|
||||||
|
|
||||||
read_openwrt_release_value() {
|
read_openwrt_release_value() {
|
||||||
@@ -617,7 +709,7 @@ function installer_confirm_remove_https_dns_proxy() {
|
|||||||
|
|
||||||
warn("Detected conflicting package: https-dns-proxy\n");
|
warn("Detected conflicting package: https-dns-proxy\n");
|
||||||
|
|
||||||
if (run("[ ! -t 0 ]")) {
|
if (truthy(env("TACHYON_INSTALLER_ASSUME_YES", "0")) || run("[ ! -t 0 ]")) {
|
||||||
warn("Remove the conflicting https-dns-proxy package and continue?: 1 (yes, non-interactive)\n");
|
warn("Remove the conflicting https-dns-proxy package and continue?: 1 (yes, non-interactive)\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1111,6 +1203,7 @@ install_json_ucode() {
|
|||||||
TACHYON_INSTALLER_LEGACY_BRAND="$LEGACY_BRAND" \
|
TACHYON_INSTALLER_LEGACY_BRAND="$LEGACY_BRAND" \
|
||||||
TACHYON_INSTALLER_LEGACY_BACKEND="$LEGACY_BACKEND_PACKAGE" \
|
TACHYON_INSTALLER_LEGACY_BACKEND="$LEGACY_BACKEND_PACKAGE" \
|
||||||
TACHYON_INSTALLER_LEGACY_CONFIG_ALT="$LEGACY_CONFIG_PACKAGE_ALT" \
|
TACHYON_INSTALLER_LEGACY_CONFIG_ALT="$LEGACY_CONFIG_PACKAGE_ALT" \
|
||||||
|
TACHYON_INSTALLER_ASSUME_YES="$ASSUME_YES" \
|
||||||
ucode "$(install_json_helper_path)" "$@"
|
ucode "$(install_json_helper_path)" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1170,6 +1263,11 @@ pkg_is_installed() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pkg_list_update() {
|
pkg_list_update() {
|
||||||
|
if [ "$DRY_RUN" -eq 1 ]; then
|
||||||
|
msg "[dry-run] would update package lists ($([ "$PKG_IS_APK" -eq 1 ] && echo apk || echo opkg))"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$PKG_IS_APK" -eq 1 ]; then
|
if [ "$PKG_IS_APK" -eq 1 ]; then
|
||||||
apk update </dev/null
|
apk update </dev/null
|
||||||
else
|
else
|
||||||
@@ -1180,6 +1278,11 @@ pkg_list_update() {
|
|||||||
pkg_install_name() {
|
pkg_install_name() {
|
||||||
pkg_name="$1"
|
pkg_name="$1"
|
||||||
|
|
||||||
|
if [ "$DRY_RUN" -eq 1 ]; then
|
||||||
|
msg "[dry-run] would install package: $pkg_name"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$PKG_IS_APK" -eq 1 ]; then
|
if [ "$PKG_IS_APK" -eq 1 ]; then
|
||||||
apk add "$pkg_name" </dev/null
|
apk add "$pkg_name" </dev/null
|
||||||
else
|
else
|
||||||
@@ -1188,6 +1291,11 @@ pkg_install_name() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pkg_install_files() {
|
pkg_install_files() {
|
||||||
|
if [ "$DRY_RUN" -eq 1 ]; then
|
||||||
|
msg "[dry-run] would install downloaded package file(s): $*"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$PKG_IS_APK" -eq 1 ]; then
|
if [ "$PKG_IS_APK" -eq 1 ]; then
|
||||||
apk add --allow-untrusted "$@" </dev/null
|
apk add --allow-untrusted "$@" </dev/null
|
||||||
else
|
else
|
||||||
@@ -1361,7 +1469,7 @@ numbered_yes_no_prompt() {
|
|||||||
prompt_text="$1"
|
prompt_text="$1"
|
||||||
answer=""
|
answer=""
|
||||||
|
|
||||||
if [ ! -t 0 ]; then
|
if [ "$ASSUME_YES" -eq 1 ] || [ ! -t 0 ]; then
|
||||||
msg "$prompt_text: 1 ($(installer_text yes), non-interactive)"
|
msg "$prompt_text: 1 ($(installer_text yes), non-interactive)"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
@@ -1502,7 +1610,7 @@ select_sing_box_installation() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -t 0 ]; then
|
if [ "$ASSUME_YES" -eq 1 ] || [ ! -t 0 ]; then
|
||||||
SING_BOX_INSTALL_VARIANT="stable"
|
SING_BOX_INSTALL_VARIANT="stable"
|
||||||
msg "$(installer_text sing_box_prompt): $default_choice ($(installer_text sing_box_stable), non-interactive)"
|
msg "$(installer_text sing_box_prompt): $default_choice ($(installer_text sing_box_stable), non-interactive)"
|
||||||
return 0
|
return 0
|
||||||
@@ -1552,6 +1660,11 @@ install_selected_sing_box() {
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
if [ "$DRY_RUN" -eq 1 ]; then
|
||||||
|
msg "[dry-run] would install sing-box variant: $SING_BOX_INSTALL_VARIANT"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
[ -x /usr/bin/tachyon ] || fail "tachyon backend must be installed before sing-box component action"
|
[ -x /usr/bin/tachyon ] || fail "tachyon backend must be installed before sing-box component action"
|
||||||
msg "Installing selected sing-box variant through Tachyon ucode backend"
|
msg "Installing selected sing-box variant through Tachyon ucode backend"
|
||||||
if ! /usr/bin/tachyon component_action sing_box "$action" >"$output_file" 2>&1; then
|
if ! /usr/bin/tachyon component_action sing_box "$action" >"$output_file" 2>&1; then
|
||||||
@@ -1561,6 +1674,11 @@ install_selected_sing_box() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cleanup_legacy_installation() {
|
cleanup_legacy_installation() {
|
||||||
|
if [ "$DRY_RUN" -eq 1 ]; then
|
||||||
|
msg "[dry-run] would stop/disable and remove legacy or conflicting packages"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
state_file="$TMP_DIR/install-state.env"
|
state_file="$TMP_DIR/install-state.env"
|
||||||
|
|
||||||
install_json_ucode installer-cleanup-legacy >"$state_file" ||
|
install_json_ucode installer-cleanup-legacy >"$state_file" ||
|
||||||
@@ -1655,6 +1773,11 @@ download_tachyon_packages() {
|
|||||||
TACHYON_I18N_FILE=""
|
TACHYON_I18N_FILE=""
|
||||||
TACHYON_SHA256_FILE="$TMP_DIR/sha256sums.txt"
|
TACHYON_SHA256_FILE="$TMP_DIR/sha256sums.txt"
|
||||||
|
|
||||||
|
if [ "$DRY_RUN" -eq 1 ]; then
|
||||||
|
msg "[dry-run] would download and verify: $TACHYON_BACKEND_NAME, $TACHYON_APP_NAME${TACHYON_I18N_REQUESTED:+$([ "$TACHYON_I18N_REQUESTED" -eq 1 ] && printf ', luci-i18n-tachyon-ru package')}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
download_with_retry "$TACHYON_SHA256_URL" "$TACHYON_SHA256_FILE" "sha256sums.txt" || fail "Failed to download sha256sums.txt"
|
download_with_retry "$TACHYON_SHA256_URL" "$TACHYON_SHA256_FILE" "sha256sums.txt" || fail "Failed to download sha256sums.txt"
|
||||||
|
|
||||||
download_with_retry "$TACHYON_BACKEND_URL" "$TACHYON_BACKEND_FILE" "$TACHYON_BACKEND_NAME" || fail "Failed to download $TACHYON_BACKEND_NAME"
|
download_with_retry "$TACHYON_BACKEND_URL" "$TACHYON_BACKEND_FILE" "$TACHYON_BACKEND_NAME" || fail "Failed to download $TACHYON_BACKEND_NAME"
|
||||||
@@ -1692,6 +1815,11 @@ install_backend_package() {
|
|||||||
migrate_legacy_configuration() {
|
migrate_legacy_configuration() {
|
||||||
[ "$TACHYON_LEGACY_DETECTED" -eq 1 ] || return 0
|
[ "$TACHYON_LEGACY_DETECTED" -eq 1 ] || return 0
|
||||||
|
|
||||||
|
if [ "$DRY_RUN" -eq 1 ]; then
|
||||||
|
msg "[dry-run] would migrate the legacy configuration to Tachyon"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -n "$LEGACY_CONFIG_BACKUP" ]; then
|
if [ -n "$LEGACY_CONFIG_BACKUP" ]; then
|
||||||
cp "$LEGACY_CONFIG_BACKUP" /etc/config/tachyon ||
|
cp "$LEGACY_CONFIG_BACKUP" /etc/config/tachyon ||
|
||||||
fail "Failed to restore the legacy configuration for migration"
|
fail "Failed to restore the legacy configuration for migration"
|
||||||
@@ -1727,21 +1855,37 @@ install_ui_packages() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
post_install() {
|
post_install() {
|
||||||
|
if [ "$DRY_RUN" -eq 1 ]; then
|
||||||
|
msg "[dry-run] would run post-install cleanup and (re)start the Tachyon service"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
TACHYON_WAS_ENABLED="$TACHYON_WAS_ENABLED" TACHYON_WAS_RUNNING="$TACHYON_WAS_RUNNING" \
|
TACHYON_WAS_ENABLED="$TACHYON_WAS_ENABLED" TACHYON_WAS_RUNNING="$TACHYON_WAS_RUNNING" \
|
||||||
install_json_ucode installer-post-install ||
|
install_json_ucode installer-post-install ||
|
||||||
fail "Failed to complete Tachyon post-install actions"
|
fail "Failed to complete Tachyon post-install actions"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TOTAL_STEPS=10
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
trap cleanup EXIT HUP INT TERM
|
trap cleanup EXIT HUP INT TERM
|
||||||
|
|
||||||
parse_args "$@"
|
parse_args "$@"
|
||||||
|
START_TIME="$(date +%s 2>/dev/null || echo 0)"
|
||||||
|
: >"$LOG_FILE" 2>/dev/null || true
|
||||||
|
log_line "Tachyon installer v${INSTALLER_VERSION} starting (args: $*)"
|
||||||
|
|
||||||
|
acquire_lock
|
||||||
check_root
|
check_root
|
||||||
init_tmp_dir
|
init_tmp_dir
|
||||||
detect_fetcher
|
detect_fetcher
|
||||||
check_system
|
check_system
|
||||||
|
|
||||||
msg "Updating package lists..."
|
if [ "$DRY_RUN" -eq 1 ]; then
|
||||||
|
warn "Dry-run mode: no packages, files, or configuration will be changed."
|
||||||
|
fi
|
||||||
|
|
||||||
|
step 1 "$TOTAL_STEPS" "Updating package lists"
|
||||||
pkg_list_update || fail "Failed to update package lists"
|
pkg_list_update || fail "Failed to update package lists"
|
||||||
ensure_bootstrap_ucode_runtime
|
ensure_bootstrap_ucode_runtime
|
||||||
|
|
||||||
@@ -1753,32 +1897,49 @@ main() {
|
|||||||
|
|
||||||
msg "$(installer_text install_start)"
|
msg "$(installer_text install_start)"
|
||||||
|
|
||||||
msg "$(installer_text resolving_release)"
|
step 2 "$TOTAL_STEPS" "$(installer_text resolving_release)"
|
||||||
resolve_tachyon_release
|
resolve_tachyon_release
|
||||||
|
debug "Resolved release tag: $TACHYON_RELEASE_TAG"
|
||||||
|
|
||||||
msg "$(installer_text downloading_packages)"
|
step 3 "$TOTAL_STEPS" "$(installer_text downloading_packages)"
|
||||||
download_tachyon_packages
|
download_tachyon_packages
|
||||||
|
|
||||||
msg "$(installer_text cleaning_legacy)"
|
step 4 "$TOTAL_STEPS" "$(installer_text cleaning_legacy)"
|
||||||
cleanup_legacy_installation
|
cleanup_legacy_installation
|
||||||
|
|
||||||
msg "$(installer_text installing_backend)"
|
step 5 "$TOTAL_STEPS" "$(installer_text installing_backend)"
|
||||||
install_backend_package
|
install_backend_package
|
||||||
|
|
||||||
msg "$(installer_text migrating_config)"
|
step 6 "$TOTAL_STEPS" "$(installer_text migrating_config)"
|
||||||
migrate_legacy_configuration
|
migrate_legacy_configuration
|
||||||
|
|
||||||
msg "$(installer_text installing_ui)"
|
step 7 "$TOTAL_STEPS" "$(installer_text installing_ui)"
|
||||||
install_ui_packages
|
install_ui_packages
|
||||||
|
|
||||||
msg "$(installer_text installing_singbox)"
|
step 8 "$TOTAL_STEPS" "$(installer_text installing_singbox)"
|
||||||
install_selected_sing_box
|
install_selected_sing_box
|
||||||
|
|
||||||
msg "$(installer_text running_postinstall)"
|
step 9 "$TOTAL_STEPS" "$(installer_text running_postinstall)"
|
||||||
post_install
|
post_install
|
||||||
|
|
||||||
msg "Tachyon $TACHYON_PACKAGE_VERSION has been installed successfully"
|
step 10 "$TOTAL_STEPS" "Done"
|
||||||
|
print_summary
|
||||||
|
}
|
||||||
|
|
||||||
|
print_summary() {
|
||||||
|
end_time="$(date +%s 2>/dev/null || echo 0)"
|
||||||
|
elapsed=$((end_time - START_TIME))
|
||||||
|
[ "$elapsed" -ge 0 ] 2>/dev/null || elapsed=0
|
||||||
|
|
||||||
|
printf '\n'
|
||||||
|
if [ "$DRY_RUN" -eq 1 ]; then
|
||||||
|
msg "Dry run complete in ${elapsed}s — no changes were made."
|
||||||
|
else
|
||||||
|
msg "Tachyon $TACHYON_PACKAGE_VERSION has been installed successfully (${elapsed}s)"
|
||||||
|
fi
|
||||||
msg "Source release: ${REPO_OWNER}/${REPO_NAME}@${TACHYON_RELEASE_TAG}"
|
msg "Source release: ${REPO_OWNER}/${REPO_NAME}@${TACHYON_RELEASE_TAG}"
|
||||||
|
[ "$TACHYON_LEGACY_DETECTED" -eq 1 ] && msg "Legacy installation migrated and removed."
|
||||||
|
msg "Full log: $LOG_FILE"
|
||||||
warn "Open LuCI and review your rules before enabling Tachyon"
|
warn "Open LuCI and review your rules before enabling Tachyon"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,17 +27,20 @@ let common = require("core.common");
|
|||||||
let as_string = common.as_string;
|
let as_string = common.as_string;
|
||||||
let shell_quote = common.shell_quote;
|
let shell_quote = common.shell_quote;
|
||||||
|
|
||||||
|
let command_status = common.command_status;
|
||||||
|
let command_success_from_args = common.command_success_from_args;
|
||||||
|
let command_output_from_args = common.command_output_from_args;
|
||||||
|
let command_exists = common.command_exists;
|
||||||
|
let command_from_args = common.command_from_args;
|
||||||
|
let write_json = common.write_json;
|
||||||
|
let command_output = common.command_output;
|
||||||
|
|
||||||
|
|
||||||
function arg_bool(value) {
|
function arg_bool(value) {
|
||||||
value = lc(as_string(value));
|
value = lc(as_string(value));
|
||||||
return value == "1" || value == "true" || value == "yes" || value == "on";
|
return value == "1" || value == "true" || value == "yes" || value == "on";
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_from_args(args) {
|
|
||||||
let parts = [];
|
|
||||||
for (let arg in args)
|
|
||||||
push(parts, shell_quote(arg));
|
|
||||||
return join(" ", parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_env(assignments) {
|
function command_env(assignments) {
|
||||||
let parts = [];
|
let parts = [];
|
||||||
@@ -46,42 +49,15 @@ function command_env(assignments) {
|
|||||||
return join(" ", parts);
|
return join(" ", parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_status(command) {
|
|
||||||
let status = int(system(command));
|
|
||||||
return status > 255 ? int(status / 256) : status;
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_success(command) {
|
function command_success(command) {
|
||||||
return command_status("(" + command + ") >/dev/null 2>&1") == 0;
|
return command_status("(" + command + ") >/dev/null 2>&1") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_success_from_args(args) {
|
|
||||||
return command_success(command_from_args(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_output(command) {
|
|
||||||
let pipe = fs.popen(command, "r");
|
|
||||||
if (!pipe)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let data = pipe.read("all");
|
|
||||||
let status = pipe.close();
|
|
||||||
if (status != 0 || data == null)
|
|
||||||
return "";
|
|
||||||
return as_string(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_output_from_args(args) {
|
|
||||||
return command_output(command_from_args(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_exists(name) {
|
|
||||||
return command_success_from_args([ "command", "-v", name ]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function write_json(value) {
|
|
||||||
print(sprintf("%J", value), "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
function write_file(path, value) {
|
function write_file(path, value) {
|
||||||
return fs.writefile(as_string(path), as_string(value)) != null;
|
return fs.writefile(as_string(path), as_string(value)) != null;
|
||||||
|
|||||||
@@ -2,45 +2,20 @@
|
|||||||
|
|
||||||
let fs = require("fs");
|
let fs = require("fs");
|
||||||
|
|
||||||
function as_string(value) {
|
let common = require("core.common");
|
||||||
return value == null ? "" : "" + value;
|
let as_string = common.as_string;
|
||||||
}
|
let write_json = common.write_json;
|
||||||
|
let read_json_file = common.read_json_file;
|
||||||
|
let object_or_empty = common.object_or_empty;
|
||||||
|
let read_stdin = common.read_stdin;
|
||||||
|
let array_or_empty = common.array_or_empty;
|
||||||
|
let read_stdin_json = common.read_stdin_json;
|
||||||
|
|
||||||
|
|
||||||
function read_json_file(path) {
|
|
||||||
let data = fs.readfile(path);
|
|
||||||
if (data == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
return json(data);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function read_stdin() {
|
|
||||||
let input = fs.open("/dev/stdin", "r");
|
|
||||||
if (!input)
|
|
||||||
return "";
|
|
||||||
let data = input.read("all");
|
|
||||||
input.close();
|
|
||||||
return data == null ? "" : data;
|
|
||||||
}
|
|
||||||
|
|
||||||
function read_stdin_json() {
|
|
||||||
let data = read_stdin();
|
|
||||||
try {
|
|
||||||
return json(data);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function write_json(value) {
|
|
||||||
print(sprintf("%J", value), "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
function stdin_contains_ci(needle) {
|
function stdin_contains_ci(needle) {
|
||||||
needle = lc(as_string(needle));
|
needle = lc(as_string(needle));
|
||||||
@@ -84,13 +59,7 @@ function object_get_default(key, fallback) {
|
|||||||
print(as_string(fallback), "\n");
|
print(as_string(fallback), "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
function object_or_empty(value) {
|
|
||||||
return type(value) == "object" ? value : {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function array_or_empty(value) {
|
|
||||||
return type(value) == "array" ? value : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function str_contains(haystack, needle) {
|
function str_contains(haystack, needle) {
|
||||||
return index(as_string(haystack), as_string(needle)) >= 0;
|
return index(as_string(haystack), as_string(needle)) >= 0;
|
||||||
|
|||||||
@@ -55,6 +55,18 @@ const SB_SERVICE_MIXED_INBOUND_PORT = getenv("SB_SERVICE_MIXED_INBOUND_PORT") ||
|
|||||||
const SB_VARIANT_STATE_FILE = getenv("SB_VARIANT_STATE_FILE") || "/etc/tachyon/sing-box-variant";
|
const SB_VARIANT_STATE_FILE = getenv("SB_VARIANT_STATE_FILE") || "/etc/tachyon/sing-box-variant";
|
||||||
const GITHUB_RAW_URL = getenv("GITHUB_RAW_URL") || "https://raw.githubusercontent.com/itdoginfo/allow-domains/main";
|
const GITHUB_RAW_URL = getenv("GITHUB_RAW_URL") || "https://raw.githubusercontent.com/itdoginfo/allow-domains/main";
|
||||||
const BUILTIN_SUBNET_URLS = {
|
const BUILTIN_SUBNET_URLS = {
|
||||||
|
|
||||||
|
let option = common.option;
|
||||||
|
let command_status = common.command_status;
|
||||||
|
let command_success_from_args = common.command_success_from_args;
|
||||||
|
let bool_option = common.bool_option;
|
||||||
|
let command_output_from_args = common.command_output_from_args;
|
||||||
|
let command_from_args = common.command_from_args;
|
||||||
|
let object_or_empty = common.object_or_empty;
|
||||||
|
let write_json = common.write_json;
|
||||||
|
let array_or_empty = common.array_or_empty;
|
||||||
|
let command_output = common.command_output;
|
||||||
|
|
||||||
twitter: getenv("SUBNETS_TWITTER") || GITHUB_RAW_URL + "/Subnets/IPv4/twitter.lst",
|
twitter: getenv("SUBNETS_TWITTER") || GITHUB_RAW_URL + "/Subnets/IPv4/twitter.lst",
|
||||||
meta: getenv("SUBNETS_META") || GITHUB_RAW_URL + "/Subnets/IPv4/meta.lst",
|
meta: getenv("SUBNETS_META") || GITHUB_RAW_URL + "/Subnets/IPv4/meta.lst",
|
||||||
discord: getenv("SUBNETS_DISCORD") || GITHUB_RAW_URL + "/Subnets/IPv4/discord.lst",
|
discord: getenv("SUBNETS_DISCORD") || GITHUB_RAW_URL + "/Subnets/IPv4/discord.lst",
|
||||||
@@ -88,14 +100,6 @@ let shell_quote = common.shell_quote;
|
|||||||
let read_json_file = common.read_json_file;
|
let read_json_file = common.read_json_file;
|
||||||
let read_stdin = common.read_stdin;
|
let read_stdin = common.read_stdin;
|
||||||
|
|
||||||
function command_from_args(args) {
|
|
||||||
let parts = [];
|
|
||||||
|
|
||||||
for (let arg in args)
|
|
||||||
push(parts, shell_quote(arg));
|
|
||||||
|
|
||||||
return join(" ", parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_env(assignments) {
|
function command_env(assignments) {
|
||||||
let parts = [];
|
let parts = [];
|
||||||
@@ -106,18 +110,6 @@ function command_env(assignments) {
|
|||||||
return join(" ", parts);
|
return join(" ", parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_output(command) {
|
|
||||||
let pipe = fs.popen(command, "r");
|
|
||||||
if (!pipe)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let data = pipe.read("all");
|
|
||||||
let status = pipe.close();
|
|
||||||
if (status != 0 || data == null)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
return as_string(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
function file_md5(path) {
|
function file_md5(path) {
|
||||||
path = as_string(path);
|
path = as_string(path);
|
||||||
@@ -128,22 +120,12 @@ function file_md5(path) {
|
|||||||
return length(fields) > 0 ? as_string(fields[0]) : "";
|
return length(fields) > 0 ? as_string(fields[0]) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_output_from_args(args) {
|
|
||||||
return command_output(command_from_args(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_status(command) {
|
|
||||||
let status = int(system(command));
|
|
||||||
return status > 255 ? int(status / 256) : status;
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_success(command) {
|
function command_success(command) {
|
||||||
return command_status(command + " >/dev/null 2>&1") == 0;
|
return command_status(command + " >/dev/null 2>&1") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_success_from_args(args) {
|
|
||||||
return system(command_from_args(args) + " >/dev/null 2>&1") == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function now_seconds() {
|
function now_seconds() {
|
||||||
return int(clock()[0]);
|
return int(clock()[0]);
|
||||||
@@ -160,9 +142,6 @@ function log_message(message, level) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
function write_json(value) {
|
|
||||||
print(sprintf("%J", value), "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
function json_text(value) {
|
function json_text(value) {
|
||||||
return sprintf("%J", value) + "\n";
|
return sprintf("%J", value) + "\n";
|
||||||
@@ -226,9 +205,6 @@ function arg_number(value) {
|
|||||||
return int(value);
|
return int(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function object_or_empty(value) {
|
|
||||||
return type(value) == "object" ? value : {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function text_first_chars(value, max_chars) {
|
function text_first_chars(value, max_chars) {
|
||||||
value = as_string(value);
|
value = as_string(value);
|
||||||
@@ -252,26 +228,8 @@ function file_last_nonblank_line_value(path, fallback, max_chars) {
|
|||||||
return text_first_chars(result, max_chars);
|
return text_first_chars(result, max_chars);
|
||||||
}
|
}
|
||||||
|
|
||||||
function array_or_empty(value) {
|
|
||||||
return type(value) == "array" ? value : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function option(section, key, fallback) {
|
|
||||||
if (fallback == null)
|
|
||||||
fallback = "";
|
|
||||||
|
|
||||||
let value = object_or_empty(section)[key];
|
|
||||||
if (value == null)
|
|
||||||
return fallback;
|
|
||||||
if (type(value) == "array")
|
|
||||||
return join(" ", value);
|
|
||||||
return as_string(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function bool_option(section, key, fallback) {
|
|
||||||
let value = object_or_empty(section)[key];
|
|
||||||
return value == null ? !!fallback : arg_bool(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function section_name(section) {
|
function section_name(section) {
|
||||||
return as_string(object_or_empty(section)[".name"]);
|
return as_string(object_or_empty(section)[".name"]);
|
||||||
|
|||||||
@@ -9,9 +9,10 @@ const PUNYCODE_INITIAL_BIAS = 72;
|
|||||||
const PUNYCODE_INITIAL_N = 128;
|
const PUNYCODE_INITIAL_N = 128;
|
||||||
const PUNYCODE_DELIMITER = "-";
|
const PUNYCODE_DELIMITER = "-";
|
||||||
|
|
||||||
function as_string(value) {
|
let common = require("core.common");
|
||||||
return value == null ? "" : "" + value;
|
let as_string = common.as_string;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function ascii_lower(value) {
|
function ascii_lower(value) {
|
||||||
let upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
let upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ const APPLIED_MIGRATIONS_OPTION = "applied_migrations";
|
|||||||
const SERVER_COUNTRY_METHOD_FLAG_EMOJI = "flag_emoji";
|
const SERVER_COUNTRY_METHOD_FLAG_EMOJI = "flag_emoji";
|
||||||
const SERVER_COUNTRY_METHOD_COUNTRY_IS = "country_is";
|
const SERVER_COUNTRY_METHOD_COUNTRY_IS = "country_is";
|
||||||
const CHILD_ITEM_TYPES = [
|
const CHILD_ITEM_TYPES = [
|
||||||
|
|
||||||
|
let command_output = common.command_output;
|
||||||
|
|
||||||
"subscription_url",
|
"subscription_url",
|
||||||
"section_interface",
|
"section_interface",
|
||||||
"urltest"
|
"urltest"
|
||||||
@@ -43,18 +46,6 @@ const CHILD_ITEM_TYPES = [
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
function command_output(command) {
|
|
||||||
let pipe = fs.popen(command, "r");
|
|
||||||
if (!pipe)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let data = pipe.read("all");
|
|
||||||
let status = pipe.close();
|
|
||||||
if (status != 0 || data == null)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
return replace(as_string(data), /[\r\n]+$/g, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
function run(command) {
|
function run(command) {
|
||||||
return system(command) == 0;
|
return system(command) == 0;
|
||||||
|
|||||||
@@ -3,9 +3,10 @@
|
|||||||
let ip = require("core.ip");
|
let ip = require("core.ip");
|
||||||
let domain_config = require("config.domain");
|
let domain_config = require("config.domain");
|
||||||
|
|
||||||
function as_string(value) {
|
let common = require("core.common");
|
||||||
return value == null ? "" : "" + value;
|
let as_string = common.as_string;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function strip_list_comment(line) {
|
function strip_list_comment(line) {
|
||||||
line = replace(as_string(line), /[[:space:]]*\/\/.*$/, "");
|
line = replace(as_string(line), /[[:space:]]*\/\/.*$/, "");
|
||||||
|
|||||||
@@ -34,6 +34,10 @@ let command_output_from_args = common.command_output_from_args;
|
|||||||
let command_trimmed_output_from_args = common.command_trimmed_output_from_args;
|
let command_trimmed_output_from_args = common.command_trimmed_output_from_args;
|
||||||
let command_exists = common.command_exists;
|
let command_exists = common.command_exists;
|
||||||
|
|
||||||
|
let object_or_empty = common.object_or_empty;
|
||||||
|
let array_or_empty = common.array_or_empty;
|
||||||
|
|
||||||
|
|
||||||
function string_starts_with(value, prefix) {
|
function string_starts_with(value, prefix) {
|
||||||
value = as_string(value);
|
value = as_string(value);
|
||||||
prefix = as_string(prefix);
|
prefix = as_string(prefix);
|
||||||
@@ -73,13 +77,7 @@ function list_has_value(values, needle) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function object_or_empty(value) {
|
|
||||||
return type(value) == "object" ? value : {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function array_or_empty(value) {
|
|
||||||
return type(value) == "array" ? value : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function contains(values, needle) {
|
function contains(values, needle) {
|
||||||
for (let value in array_or_empty(values))
|
for (let value in array_or_empty(values))
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
#!/usr/bin/env ucode
|
#!/usr/bin/env ucode
|
||||||
|
|
||||||
function as_string(value) {
|
let common = require("core.common");
|
||||||
return value == null ? "" : "" + value;
|
let as_string = common.as_string;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function str_last_index(value, needle) {
|
function str_last_index(value, needle) {
|
||||||
value = as_string(value);
|
value = as_string(value);
|
||||||
|
|||||||
@@ -6,32 +6,17 @@ let common = require("core.common");
|
|||||||
let as_string = common.as_string;
|
let as_string = common.as_string;
|
||||||
let shell_quote = common.shell_quote;
|
let shell_quote = common.shell_quote;
|
||||||
|
|
||||||
function command_from_args(args) {
|
let command_exists = common.command_exists;
|
||||||
let parts = [];
|
let command_from_args = common.command_from_args;
|
||||||
for (let arg in args)
|
let command_output = common.command_output;
|
||||||
push(parts, shell_quote(arg));
|
|
||||||
return join(" ", parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_success(args) {
|
function command_success(args) {
|
||||||
return system(command_from_args(args) + " >/dev/null 2>&1") == 0;
|
return system(command_from_args(args) + " >/dev/null 2>&1") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_output(args) {
|
|
||||||
let pipe = fs.popen(command_from_args(args), "r");
|
|
||||||
if (!pipe)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let data = pipe.read("all");
|
|
||||||
let status = pipe.close();
|
|
||||||
if (status != 0 || data == null)
|
|
||||||
return "";
|
|
||||||
return as_string(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_exists(name) {
|
|
||||||
return command_success([ "command", "-v", name ]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function apk_installed(package_name) {
|
function apk_installed(package_name) {
|
||||||
return command_exists("apk") && command_success([ "apk", "info", "-e", as_string(package_name) ]);
|
return command_exists("apk") && command_success([ "apk", "info", "-e", as_string(package_name) ]);
|
||||||
|
|||||||
@@ -64,6 +64,21 @@ let as_string = common.as_string;
|
|||||||
let shell_quote = common.shell_quote;
|
let shell_quote = common.shell_quote;
|
||||||
let read_json_file = common.read_json_file;
|
let read_json_file = common.read_json_file;
|
||||||
|
|
||||||
|
let option = common.option;
|
||||||
|
let list_option = common.list_option;
|
||||||
|
let command_status = common.command_status;
|
||||||
|
let command_success_from_args = common.command_success_from_args;
|
||||||
|
let bool_option = common.bool_option;
|
||||||
|
let read_stdin = common.read_stdin;
|
||||||
|
let command_output_from_args = common.command_output_from_args;
|
||||||
|
let command_exists = common.command_exists;
|
||||||
|
let command_from_args = common.command_from_args;
|
||||||
|
let object_or_empty = common.object_or_empty;
|
||||||
|
let write_json = common.write_json;
|
||||||
|
let array_or_empty = common.array_or_empty;
|
||||||
|
let command_output = common.command_output;
|
||||||
|
|
||||||
|
|
||||||
function arg_number(value) {
|
function arg_number(value) {
|
||||||
value = as_string(value);
|
value = as_string(value);
|
||||||
return value == "" || match(value, /[^0-9-]/) != null ? 0 : int(value, 10);
|
return value == "" || match(value, /[^0-9-]/) != null ? 0 : int(value, 10);
|
||||||
@@ -74,21 +89,12 @@ function arg_bool(value) {
|
|||||||
return value == "1" || value == "true" || value == "yes" || value == "on";
|
return value == "1" || value == "true" || value == "yes" || value == "on";
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_from_args(args) {
|
|
||||||
let parts = [];
|
|
||||||
for (let arg in args)
|
|
||||||
push(parts, shell_quote(arg));
|
|
||||||
return join(" ", parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalize_status(status) {
|
function normalize_status(status) {
|
||||||
status = int(status);
|
status = int(status);
|
||||||
return status > 255 ? int(status / 256) : status;
|
return status > 255 ? int(status / 256) : status;
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_status(command) {
|
|
||||||
return normalize_status(system(command));
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_capture(command) {
|
function command_capture(command) {
|
||||||
let pipe = fs.popen(command, "r");
|
let pipe = fs.popen(command, "r");
|
||||||
@@ -100,26 +106,13 @@ function command_capture(command) {
|
|||||||
return { status, output: data == null ? "" : as_string(data) };
|
return { status, output: data == null ? "" : as_string(data) };
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_output(command) {
|
|
||||||
let result = command_capture(command);
|
|
||||||
return result.status == 0 ? result.output : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_success(command) {
|
function command_success(command) {
|
||||||
return command_status(command + " >/dev/null 2>&1") == 0;
|
return command_status(command + " >/dev/null 2>&1") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_output_from_args(args) {
|
|
||||||
return command_output(command_from_args(args) + " 2>/dev/null");
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_success_from_args(args) {
|
|
||||||
return command_success(command_from_args(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_exists(name) {
|
|
||||||
return command_success_from_args([ "command", "-v", as_string(name) ]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function module_args(module_path, args) {
|
function module_args(module_path, args) {
|
||||||
let result = [ "ucode", "-L", LIB_DIR, module_path ];
|
let result = [ "ucode", "-L", LIB_DIR, module_path ];
|
||||||
@@ -187,18 +180,7 @@ function status_success(args, input) {
|
|||||||
return status_capture(args, input).status == 0;
|
return status_capture(args, input).status == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function write_json(value) {
|
|
||||||
print(sprintf("%J", value), "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
function read_stdin() {
|
|
||||||
let input = fs.open("/dev/stdin", "r");
|
|
||||||
if (!input)
|
|
||||||
return "";
|
|
||||||
let data = input.read("all");
|
|
||||||
input.close();
|
|
||||||
return data == null ? "" : as_string(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -211,37 +193,10 @@ function parse_json_or_null(value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function object_or_empty(value) {
|
|
||||||
return type(value) == "object" ? value : {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function array_or_empty(value) {
|
|
||||||
return type(value) == "array" ? value : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function option(section, key, fallback) {
|
|
||||||
if (fallback == null)
|
|
||||||
fallback = "";
|
|
||||||
let value = object_or_empty(section)[key];
|
|
||||||
if (value == null)
|
|
||||||
return as_string(fallback);
|
|
||||||
if (type(value) == "array")
|
|
||||||
return join(" ", value);
|
|
||||||
return as_string(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function list_option(section, key) {
|
|
||||||
let value = object_or_empty(section)[key];
|
|
||||||
if (type(value) == "array")
|
|
||||||
return value;
|
|
||||||
if (as_string(value) != "")
|
|
||||||
return [ as_string(value) ];
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function bool_option(section, key, fallback) {
|
|
||||||
return arg_bool(option(section, key, fallback ? "1" : "0"));
|
|
||||||
}
|
|
||||||
|
|
||||||
function settings() {
|
function settings() {
|
||||||
return object_or_empty(uci_core.get_all(CONFIG_NAME, "settings"));
|
return object_or_empty(uci_core.get_all(CONFIG_NAME, "settings"));
|
||||||
|
|||||||
@@ -3,9 +3,17 @@
|
|||||||
let fs = require("fs");
|
let fs = require("fs");
|
||||||
let core_ip = require("core.ip");
|
let core_ip = require("core.ip");
|
||||||
|
|
||||||
function as_string(value) {
|
let common = require("core.common");
|
||||||
return value == null ? "" : "" + value;
|
let as_string = common.as_string;
|
||||||
}
|
let write_json = common.write_json;
|
||||||
|
let read_json_file = common.read_json_file;
|
||||||
|
let write_json_file = common.write_json_file;
|
||||||
|
let object_or_empty = common.object_or_empty;
|
||||||
|
let read_stdin = common.read_stdin;
|
||||||
|
let array_or_empty = common.array_or_empty;
|
||||||
|
let read_stdin_json = common.read_stdin_json;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function url_encode(value) {
|
function url_encode(value) {
|
||||||
value = as_string(value);
|
value = as_string(value);
|
||||||
@@ -23,45 +31,14 @@ function url_encode(value) {
|
|||||||
print("\n");
|
print("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
function read_stdin() {
|
|
||||||
let input = fs.open("/dev/stdin", "r");
|
|
||||||
if (!input)
|
|
||||||
return "";
|
|
||||||
let data = input.read("all");
|
|
||||||
input.close();
|
|
||||||
return data == null ? "" : data;
|
|
||||||
}
|
|
||||||
|
|
||||||
function read_stdin_json() {
|
|
||||||
try {
|
|
||||||
return json(read_stdin());
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function proxy_response_is_retryable_error() {
|
function proxy_response_is_retryable_error() {
|
||||||
let response = read_stdin();
|
let response = read_stdin();
|
||||||
return index(response, "<html") == 0 || index(response, "403 Forbidden") >= 0;
|
return index(response, "<html") == 0 || index(response, "403 Forbidden") >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function read_json_file(path) {
|
|
||||||
let data = fs.readfile(path);
|
|
||||||
if (data == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
return json(data);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function write_json_file(path, value) {
|
|
||||||
return fs.writefile(path, sprintf("%J", value) + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
function parse_json_object(value) {
|
function parse_json_object(value) {
|
||||||
try {
|
try {
|
||||||
@@ -605,13 +582,7 @@ function object_value(object, key) {
|
|||||||
return type(object) == "object" && object[key] != null ? as_string(object[key]) : "";
|
return type(object) == "object" && object[key] != null ? as_string(object[key]) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
function object_or_empty(value) {
|
|
||||||
return type(value) == "object" ? value : {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function array_or_empty(value) {
|
|
||||||
return type(value) == "array" ? value : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function str_startswith(value, prefix) {
|
function str_startswith(value, prefix) {
|
||||||
value = as_string(value);
|
value = as_string(value);
|
||||||
@@ -942,9 +913,6 @@ function print_line(value) {
|
|||||||
print(value, "\n");
|
print(value, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
function write_json(value) {
|
|
||||||
print(sprintf("%J", value), "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
function stdin_json() {
|
function stdin_json() {
|
||||||
let value = read_stdin_json();
|
let value = read_stdin_json();
|
||||||
|
|||||||
@@ -15,26 +15,23 @@ let list_option = common.list_option;
|
|||||||
let bool_option = common.bool_option;
|
let bool_option = common.bool_option;
|
||||||
let as_string = common.as_string;
|
let as_string = common.as_string;
|
||||||
|
|
||||||
|
let write_compact_string_array = common.write_compact_string_array;
|
||||||
|
let run_args = common.run_args;
|
||||||
|
let read_stdin = common.read_stdin;
|
||||||
|
let command_output_from_args = common.command_output_from_args;
|
||||||
|
let csv_to_json_array = common.csv_to_json_array;
|
||||||
|
let command_from_args = common.command_from_args;
|
||||||
|
let object_or_empty = common.object_or_empty;
|
||||||
|
let write_json = common.write_json;
|
||||||
|
let option = common.option;
|
||||||
|
|
||||||
|
|
||||||
function arg_bool(value) {
|
function arg_bool(value) {
|
||||||
value = lc(as_string(value));
|
value = lc(as_string(value));
|
||||||
return value == "1" || value == "true" || value == "yes";
|
return value == "1" || value == "true" || value == "yes";
|
||||||
}
|
}
|
||||||
|
|
||||||
function object_or_empty(value) {
|
|
||||||
return type(value) == "object" ? value : {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function option(section, key, fallback) {
|
|
||||||
if (fallback == null)
|
|
||||||
fallback = "";
|
|
||||||
|
|
||||||
let value = object_or_empty(section)[key];
|
|
||||||
if (value == null)
|
|
||||||
return fallback;
|
|
||||||
if (type(value) == "array")
|
|
||||||
return join(" ", value);
|
|
||||||
return as_string(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function uci_section(section_name) {
|
function uci_section(section_name) {
|
||||||
return object_or_empty(uci_core.get_all(CONFIG_NAME, section_name));
|
return object_or_empty(uci_core.get_all(CONFIG_NAME, section_name));
|
||||||
@@ -48,28 +45,8 @@ function uci_settings() {
|
|||||||
return uci_section("settings");
|
return uci_section("settings");
|
||||||
}
|
}
|
||||||
|
|
||||||
function write_json(value) {
|
|
||||||
print(sprintf("%J", value), "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
function write_compact_string_array(values) {
|
|
||||||
print("[");
|
|
||||||
for (let i = 0; i < length(values); i++) {
|
|
||||||
if (i > 0)
|
|
||||||
print(",");
|
|
||||||
print(sprintf("%J", as_string(values[i])));
|
|
||||||
}
|
|
||||||
print("]\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
function read_stdin() {
|
|
||||||
let input = fs.open("/dev/stdin", "r");
|
|
||||||
if (!input)
|
|
||||||
return "";
|
|
||||||
let data = input.read("all");
|
|
||||||
input.close();
|
|
||||||
return data == null ? "" : data;
|
|
||||||
}
|
|
||||||
|
|
||||||
function write_text_file(path, text) {
|
function write_text_file(path, text) {
|
||||||
let result = fs.writefile(path, as_string(text));
|
let result = fs.writefile(path, as_string(text));
|
||||||
@@ -98,35 +75,12 @@ function unlink_file(path) {
|
|||||||
|
|
||||||
let shell_quote = common.shell_quote;
|
let shell_quote = common.shell_quote;
|
||||||
|
|
||||||
function command_from_args(args) {
|
|
||||||
let parts = [];
|
|
||||||
|
|
||||||
for (let arg in args)
|
|
||||||
push(parts, shell_quote(arg));
|
|
||||||
|
|
||||||
return join(" ", parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
function run_args(args) {
|
|
||||||
return system(command_from_args(args)) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function run_args_quiet(args) {
|
function run_args_quiet(args) {
|
||||||
return system(command_from_args(args) + " >/dev/null 2>&1") == 0;
|
return system(command_from_args(args) + " >/dev/null 2>&1") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_output_from_args(args) {
|
|
||||||
let pipe = fs.popen(command_from_args(args), "r");
|
|
||||||
if (!pipe)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let data = pipe.read("all");
|
|
||||||
let status = pipe.close();
|
|
||||||
if (status != 0 || data == null)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
return as_string(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
function log_debug(message) {
|
function log_debug(message) {
|
||||||
run_args([ "logger", "-t", "tachyon", "[debug] " + as_string(message) ]);
|
run_args([ "logger", "-t", "tachyon", "[debug] " + as_string(message) ]);
|
||||||
@@ -175,15 +129,6 @@ function text_list_to_csv(value, separator_mode) {
|
|||||||
print_csv(text_list_values(value, separator_mode));
|
print_csv(text_list_values(value, separator_mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
function csv_to_json_array(value) {
|
|
||||||
value = as_string(value);
|
|
||||||
if (value == "") {
|
|
||||||
print("[]\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
write_compact_string_array(split(value, ","));
|
|
||||||
}
|
|
||||||
|
|
||||||
function csv_list_contains(value, needle) {
|
function csv_list_contains(value, needle) {
|
||||||
needle = as_string(needle);
|
needle = as_string(needle);
|
||||||
|
|||||||
@@ -25,84 +25,43 @@ let as_string = common.as_string;
|
|||||||
let shell_quote = common.shell_quote;
|
let shell_quote = common.shell_quote;
|
||||||
let read_json_file = common.read_json_file;
|
let read_json_file = common.read_json_file;
|
||||||
|
|
||||||
|
let option = common.option;
|
||||||
|
let command_status = common.command_status;
|
||||||
|
let command_success_from_args = common.command_success_from_args;
|
||||||
|
let bool_option = common.bool_option;
|
||||||
|
let command_output_from_args = common.command_output_from_args;
|
||||||
|
let command_exists = common.command_exists;
|
||||||
|
let command_from_args = common.command_from_args;
|
||||||
|
let object_or_empty = common.object_or_empty;
|
||||||
|
let write_json = common.write_json;
|
||||||
|
let array_or_empty = common.array_or_empty;
|
||||||
|
let command_output = common.command_output;
|
||||||
|
|
||||||
|
|
||||||
function bool_value(value) {
|
function bool_value(value) {
|
||||||
value = lc(as_string(value));
|
value = lc(as_string(value));
|
||||||
return value == "1" || value == "true" || value == "yes" || value == "on";
|
return value == "1" || value == "true" || value == "yes" || value == "on";
|
||||||
}
|
}
|
||||||
|
|
||||||
function write_json(value) {
|
|
||||||
print(sprintf("%J", value), "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_from_args(args) {
|
|
||||||
let parts = [];
|
|
||||||
for (let arg in args)
|
|
||||||
push(parts, shell_quote(arg));
|
|
||||||
return join(" ", parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_output(command) {
|
|
||||||
let pipe = fs.popen(command, "r");
|
|
||||||
if (!pipe)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let data = pipe.read("all");
|
|
||||||
let status = pipe.close();
|
|
||||||
if (status != 0 || data == null)
|
|
||||||
return "";
|
|
||||||
return as_string(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_output_from_args(args) {
|
|
||||||
return command_output(command_from_args(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_status(command) {
|
|
||||||
let status = int(system(command));
|
|
||||||
return status > 255 ? int(status / 256) : status;
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_success(command) {
|
function command_success(command) {
|
||||||
return command_status(command + " >/dev/null 2>&1") == 0;
|
return command_status(command + " >/dev/null 2>&1") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_success_from_args(args) {
|
|
||||||
return system(command_from_args(args) + " >/dev/null 2>&1") == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_exists(name) {
|
|
||||||
return command_success_from_args([ "command", "-v", name ]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function log_message(message, level) {
|
function log_message(message, level) {
|
||||||
level = as_string(level || "info");
|
level = as_string(level || "info");
|
||||||
command_success_from_args([ "logger", "-t", "tachyon", "[" + level + "] " + as_string(message) ]);
|
command_success_from_args([ "logger", "-t", "tachyon", "[" + level + "] " + as_string(message) ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function object_or_empty(value) {
|
|
||||||
return type(value) == "object" ? value : {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function array_or_empty(value) {
|
|
||||||
return type(value) == "array" ? value : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function option(section, key, fallback) {
|
|
||||||
if (fallback == null)
|
|
||||||
fallback = "";
|
|
||||||
|
|
||||||
let value = object_or_empty(section)[key];
|
|
||||||
if (value == null)
|
|
||||||
return fallback;
|
|
||||||
if (type(value) == "array")
|
|
||||||
return join(" ", value);
|
|
||||||
return as_string(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function bool_option(section, key, fallback) {
|
|
||||||
let value = object_or_empty(section)[key];
|
|
||||||
return value == null ? !!fallback : bool_value(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function section_name(section) {
|
function section_name(section) {
|
||||||
return as_string(object_or_empty(section)[".name"]);
|
return as_string(object_or_empty(section)[".name"]);
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
#!/usr/bin/env ucode
|
#!/usr/bin/env ucode
|
||||||
|
|
||||||
function as_string(value) {
|
let common = require("core.common");
|
||||||
return value == null ? "" : "" + value;
|
let as_string = common.as_string;
|
||||||
}
|
let write_json = common.write_json;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function bool_arg(value) {
|
function bool_arg(value) {
|
||||||
value = as_string(value);
|
value = as_string(value);
|
||||||
return value == "1" || value == "true";
|
return value == "1" || value == "true";
|
||||||
}
|
}
|
||||||
|
|
||||||
function write_json(value) {
|
|
||||||
print(sprintf("%J", value), "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalize_strategy_whitespace(value) {
|
function normalize_strategy_whitespace(value) {
|
||||||
value = replace(as_string(value), /[\t\r\n]/g, " ");
|
value = replace(as_string(value), /[\t\r\n]/g, " ");
|
||||||
|
|||||||
@@ -2,14 +2,12 @@
|
|||||||
|
|
||||||
let fs = require("fs");
|
let fs = require("fs");
|
||||||
|
|
||||||
function as_string(value) {
|
let common = require("core.common");
|
||||||
return value == null ? "" : "" + value;
|
let as_string = common.as_string;
|
||||||
}
|
let read_stdin = common.read_stdin;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function read_stdin() {
|
|
||||||
let data = fs.readfile("/dev/stdin");
|
|
||||||
return data == null ? "" : data;
|
|
||||||
}
|
|
||||||
|
|
||||||
function strip_trailing_cr(line) {
|
function strip_trailing_cr(line) {
|
||||||
line = as_string(line);
|
line = as_string(line);
|
||||||
|
|||||||
@@ -15,54 +15,34 @@ let as_string = common.as_string;
|
|||||||
let shell_quote = common.shell_quote;
|
let shell_quote = common.shell_quote;
|
||||||
let read_json_file = common.read_json_file;
|
let read_json_file = common.read_json_file;
|
||||||
|
|
||||||
|
let option = common.option;
|
||||||
|
let command_status = common.command_status;
|
||||||
|
let command_success_from_args = common.command_success_from_args;
|
||||||
|
let bool_option = common.bool_option;
|
||||||
|
let command_output_from_args = common.command_output_from_args;
|
||||||
|
let command_exists = common.command_exists;
|
||||||
|
let command_from_args = common.command_from_args;
|
||||||
|
let object_or_empty = common.object_or_empty;
|
||||||
|
let write_json = common.write_json;
|
||||||
|
let array_or_empty = common.array_or_empty;
|
||||||
|
let command_output = common.command_output;
|
||||||
|
|
||||||
|
|
||||||
function bool_value(value) {
|
function bool_value(value) {
|
||||||
value = lc(as_string(value));
|
value = lc(as_string(value));
|
||||||
return value == "1" || value == "true" || value == "yes" || value == "on";
|
return value == "1" || value == "true" || value == "yes" || value == "on";
|
||||||
}
|
}
|
||||||
|
|
||||||
function write_json(value) {
|
|
||||||
print(sprintf("%J", value), "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_from_args(args) {
|
|
||||||
let parts = [];
|
|
||||||
for (let arg in args)
|
|
||||||
push(parts, shell_quote(arg));
|
|
||||||
return join(" ", parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_output(command) {
|
|
||||||
let pipe = fs.popen(command, "r");
|
|
||||||
if (!pipe)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let data = pipe.read("all");
|
|
||||||
let status = pipe.close();
|
|
||||||
if (status != 0 || data == null)
|
|
||||||
return "";
|
|
||||||
return as_string(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_output_from_args(args) {
|
|
||||||
return command_output(command_from_args(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_status(command) {
|
|
||||||
let status = int(system(command));
|
|
||||||
return status > 255 ? int(status / 256) : status;
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_success(command) {
|
function command_success(command) {
|
||||||
return command_status(command + " >/dev/null 2>&1") == 0;
|
return command_status(command + " >/dev/null 2>&1") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_success_from_args(args) {
|
|
||||||
return system(command_from_args(args) + " >/dev/null 2>&1") == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_exists(name) {
|
|
||||||
return command_success_from_args([ "command", "-v", name ]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function module_command(args) {
|
function module_command(args) {
|
||||||
let command_args = [ "ucode", "-L", LIB_DIR ];
|
let command_args = [ "ucode", "-L", LIB_DIR ];
|
||||||
@@ -80,30 +60,9 @@ function log_message(message, level) {
|
|||||||
command_success_from_args([ "logger", "-t", "tachyon", "[" + level + "] " + as_string(message) ]);
|
command_success_from_args([ "logger", "-t", "tachyon", "[" + level + "] " + as_string(message) ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function object_or_empty(value) {
|
|
||||||
return type(value) == "object" ? value : {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function array_or_empty(value) {
|
|
||||||
return type(value) == "array" ? value : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function option(section, key, fallback) {
|
|
||||||
if (fallback == null)
|
|
||||||
fallback = "";
|
|
||||||
|
|
||||||
let value = object_or_empty(section)[key];
|
|
||||||
if (value == null)
|
|
||||||
return fallback;
|
|
||||||
if (type(value) == "array")
|
|
||||||
return join(" ", value);
|
|
||||||
return as_string(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function bool_option(section, key, fallback) {
|
|
||||||
let value = object_or_empty(section)[key];
|
|
||||||
return value == null ? !!fallback : bool_value(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function section_name(section) {
|
function section_name(section) {
|
||||||
return as_string(object_or_empty(section)[".name"]);
|
return as_string(object_or_empty(section)[".name"]);
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
#!/usr/bin/env ucode
|
#!/usr/bin/env ucode
|
||||||
|
|
||||||
function as_string(value) {
|
let common = require("core.common");
|
||||||
return value == null ? "" : "" + value;
|
let as_string = common.as_string;
|
||||||
}
|
let write_json = common.write_json;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function write_json(value) {
|
|
||||||
print(sprintf("%J", value), "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalize_strategy_whitespace(value) {
|
function normalize_strategy_whitespace(value) {
|
||||||
value = replace(as_string(value), /[\t\r\n]/g, " ");
|
value = replace(as_string(value), /[\t\r\n]/g, " ");
|
||||||
|
|||||||
@@ -5,18 +5,12 @@ let uci_core = require("core.uci");
|
|||||||
|
|
||||||
const CONFIG_NAME = getenv("TACHYON_CONFIG_NAME") || "tachyon";
|
const CONFIG_NAME = getenv("TACHYON_CONFIG_NAME") || "tachyon";
|
||||||
|
|
||||||
function as_string(value) {
|
let common = require("core.common");
|
||||||
return value == null ? "" : "" + value;
|
let as_string = common.as_string;
|
||||||
}
|
let read_stdin = common.read_stdin;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function read_stdin() {
|
|
||||||
let input = fs.open("/dev/stdin", "r");
|
|
||||||
if (!input)
|
|
||||||
return "";
|
|
||||||
let data = input.read("all");
|
|
||||||
input.close();
|
|
||||||
return data == null ? "" : data;
|
|
||||||
}
|
|
||||||
|
|
||||||
function hex_digit_value(value) {
|
function hex_digit_value(value) {
|
||||||
let pos = index("0123456789abcdef", lc(as_string(value)));
|
let pos = index("0123456789abcdef", lc(as_string(value)));
|
||||||
|
|||||||
@@ -2,9 +2,14 @@
|
|||||||
|
|
||||||
let fs = require("fs");
|
let fs = require("fs");
|
||||||
|
|
||||||
function as_string(value) {
|
let common = require("core.common");
|
||||||
return value == null ? "" : "" + value;
|
let as_string = common.as_string;
|
||||||
}
|
let write_json = common.write_json;
|
||||||
|
let read_json_file = common.read_json_file;
|
||||||
|
let read_stdin = common.read_stdin;
|
||||||
|
let array_or_empty = common.array_or_empty;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function int_arg(value) {
|
function int_arg(value) {
|
||||||
value = as_string(value);
|
value = as_string(value);
|
||||||
@@ -16,35 +21,9 @@ function bool_arg(value) {
|
|||||||
return value == "1" || value == "true";
|
return value == "1" || value == "true";
|
||||||
}
|
}
|
||||||
|
|
||||||
function read_stdin() {
|
|
||||||
let input = fs.open("/dev/stdin", "r");
|
|
||||||
if (!input)
|
|
||||||
return "";
|
|
||||||
let data = input.read("all");
|
|
||||||
input.close();
|
|
||||||
return data == null ? "" : data;
|
|
||||||
}
|
|
||||||
|
|
||||||
function read_json_file(path) {
|
|
||||||
let data = fs.readfile(path);
|
|
||||||
if (data == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
return json(data);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function array_or_empty(value) {
|
|
||||||
return type(value) == "array" ? value : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function write_json(value) {
|
|
||||||
print(sprintf("%J", value), "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
function first_field(line) {
|
function first_field(line) {
|
||||||
let fields = split(trim(as_string(line)), /[ \t\r\n]+/);
|
let fields = split(trim(as_string(line)), /[ \t\r\n]+/);
|
||||||
|
|||||||
@@ -4,9 +4,14 @@ let fs = require("fs");
|
|||||||
let ip = require("core.ip");
|
let ip = require("core.ip");
|
||||||
let domain_config = require("config.domain");
|
let domain_config = require("config.domain");
|
||||||
|
|
||||||
function as_string(value) {
|
let common = require("core.common");
|
||||||
return value == null ? "" : "" + value;
|
let as_string = common.as_string;
|
||||||
}
|
let read_json_file = common.read_json_file;
|
||||||
|
let write_json_file = common.write_json_file;
|
||||||
|
let object_or_empty = common.object_or_empty;
|
||||||
|
let array_or_empty = common.array_or_empty;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function json_decode_text(text) {
|
function json_decode_text(text) {
|
||||||
try {
|
try {
|
||||||
@@ -17,10 +22,6 @@ function json_decode_text(text) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function read_json_file(path) {
|
|
||||||
let data = fs.readfile(path);
|
|
||||||
return data == null ? null : json_decode_text(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
function write_text_file(path, text) {
|
function write_text_file(path, text) {
|
||||||
let result = fs.writefile(path, text);
|
let result = fs.writefile(path, text);
|
||||||
@@ -31,13 +32,7 @@ function write_text_file(path, text) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function write_json_file(path, value) {
|
|
||||||
return write_text_file(path, sprintf("%J", value) + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
function array_or_empty(value) {
|
|
||||||
return type(value) == "array" ? value : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function array_from_value(value) {
|
function array_from_value(value) {
|
||||||
if (value == null)
|
if (value == null)
|
||||||
@@ -47,9 +42,6 @@ function array_from_value(value) {
|
|||||||
return [ value ];
|
return [ value ];
|
||||||
}
|
}
|
||||||
|
|
||||||
function object_or_empty(value) {
|
|
||||||
return type(value) == "object" ? value : {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function trim_string(value) {
|
function trim_string(value) {
|
||||||
let text = as_string(value);
|
let text = as_string(value);
|
||||||
|
|||||||
@@ -12,6 +12,12 @@ let as_string = common.as_string;
|
|||||||
let shell_quote = common.shell_quote;
|
let shell_quote = common.shell_quote;
|
||||||
let read_json_file = common.read_json_file;
|
let read_json_file = common.read_json_file;
|
||||||
|
|
||||||
|
let read_stdin = common.read_stdin;
|
||||||
|
let write_json = common.write_json;
|
||||||
|
let array_or_empty = common.array_or_empty;
|
||||||
|
let read_stdin_json = common.read_stdin_json;
|
||||||
|
|
||||||
|
|
||||||
function ascii_lower(value) {
|
function ascii_lower(value) {
|
||||||
let upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
let upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
let lower = "abcdefghijklmnopqrstuvwxyz";
|
let lower = "abcdefghijklmnopqrstuvwxyz";
|
||||||
@@ -20,9 +26,6 @@ function ascii_lower(value) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function write_json(value) {
|
|
||||||
print(sprintf("%J", value), "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
function run(command) {
|
function run(command) {
|
||||||
return system(command) == 0;
|
return system(command) == 0;
|
||||||
@@ -105,23 +108,7 @@ function server_set_option(section, option, value) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
function read_stdin() {
|
|
||||||
let input = fs.open("/dev/stdin", "r");
|
|
||||||
if (!input)
|
|
||||||
return "";
|
|
||||||
let data = input.read("all");
|
|
||||||
input.close();
|
|
||||||
return data == null ? "" : data;
|
|
||||||
}
|
|
||||||
|
|
||||||
function read_stdin_json() {
|
|
||||||
try {
|
|
||||||
return json(read_stdin());
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function stdin_first_nonempty_line() {
|
function stdin_first_nonempty_line() {
|
||||||
for (let line in split(read_stdin(), "\n")) {
|
for (let line in split(read_stdin(), "\n")) {
|
||||||
@@ -143,9 +130,6 @@ function shell_single_quote(value) {
|
|||||||
print("'", replace(value, /'/g, "'\\''"), "'\n");
|
print("'", replace(value, /'/g, "'\\''"), "'\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
function array_or_empty(value) {
|
|
||||||
return type(value) == "array" ? value : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function array_append_string(value) {
|
function array_append_string(value) {
|
||||||
let result = array_or_empty(read_stdin_json());
|
let result = array_or_empty(read_stdin_json());
|
||||||
|
|||||||
@@ -8,6 +8,15 @@ let common = require("core.common");
|
|||||||
let as_string = common.as_string;
|
let as_string = common.as_string;
|
||||||
let shell_quote = common.shell_quote;
|
let shell_quote = common.shell_quote;
|
||||||
|
|
||||||
|
let option = common.option;
|
||||||
|
let command_status = common.command_status;
|
||||||
|
let command_success_from_args = common.command_success_from_args;
|
||||||
|
let command_output_from_args = common.command_output_from_args;
|
||||||
|
let command_from_args = common.command_from_args;
|
||||||
|
let object_or_empty = common.object_or_empty;
|
||||||
|
let command_output = common.command_output;
|
||||||
|
|
||||||
|
|
||||||
function constant_value(name, fallback) {
|
function constant_value(name, fallback) {
|
||||||
let value = constants[name];
|
let value = constants[name];
|
||||||
return value == null ? as_string(fallback) : as_string(value);
|
return value == null ? as_string(fallback) : as_string(value);
|
||||||
@@ -38,21 +47,12 @@ function shell_assignment(name, value) {
|
|||||||
print(as_string(name), "=", shell_quote(value), "\n");
|
print(as_string(name), "=", shell_quote(value), "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_from_args(args) {
|
|
||||||
let parts = [];
|
|
||||||
for (let arg in args)
|
|
||||||
push(parts, shell_quote(arg));
|
|
||||||
return join(" ", parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalize_status(status) {
|
function normalize_status(status) {
|
||||||
status = int(status);
|
status = int(status);
|
||||||
return status > 255 ? int(status / 256) : status;
|
return status > 255 ? int(status / 256) : status;
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_status(command) {
|
|
||||||
return normalize_status(system(command));
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_capture(command) {
|
function command_capture(command) {
|
||||||
let pipe = fs.popen(command, "r");
|
let pipe = fs.popen(command, "r");
|
||||||
@@ -64,18 +64,8 @@ function command_capture(command) {
|
|||||||
return { status, output: data == null ? "" : as_string(data) };
|
return { status, output: data == null ? "" : as_string(data) };
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_output(command) {
|
|
||||||
let result = command_capture(command);
|
|
||||||
return result.status == 0 ? result.output : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_output_from_args(args) {
|
|
||||||
return command_output(command_from_args(args) + " 2>/dev/null");
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_success_from_args(args) {
|
|
||||||
return command_status(command_from_args(args) + " >/dev/null 2>&1") == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_status_from_args(args) {
|
function command_status_from_args(args) {
|
||||||
return command_status(command_from_args(args));
|
return command_status(command_from_args(args));
|
||||||
@@ -118,20 +108,7 @@ function bool_text(value) {
|
|||||||
return value == "1" || value == "true" || value == "yes" || value == "on";
|
return value == "1" || value == "true" || value == "yes" || value == "on";
|
||||||
}
|
}
|
||||||
|
|
||||||
function object_or_empty(value) {
|
|
||||||
return type(value) == "object" ? value : {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function option(section, key, fallback) {
|
|
||||||
if (fallback == null)
|
|
||||||
fallback = "";
|
|
||||||
let value = object_or_empty(section)[key];
|
|
||||||
if (value == null)
|
|
||||||
return as_string(fallback);
|
|
||||||
if (type(value) == "array")
|
|
||||||
return join(" ", value);
|
|
||||||
return as_string(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function file_exists(path) {
|
function file_exists(path) {
|
||||||
return fs.stat(as_string(path)) != null;
|
return fs.stat(as_string(path)) != null;
|
||||||
|
|||||||
@@ -9,6 +9,16 @@ let as_string = common.as_string;
|
|||||||
let shell_quote = common.shell_quote;
|
let shell_quote = common.shell_quote;
|
||||||
let read_json_file = common.read_json_file;
|
let read_json_file = common.read_json_file;
|
||||||
|
|
||||||
|
let command_status = common.command_status;
|
||||||
|
let command_success_from_args = common.command_success_from_args;
|
||||||
|
let command_output_from_args = common.command_output_from_args;
|
||||||
|
let command_from_args = common.command_from_args;
|
||||||
|
let object_or_empty = common.object_or_empty;
|
||||||
|
let write_json = common.write_json;
|
||||||
|
let array_or_empty = common.array_or_empty;
|
||||||
|
let command_output = common.command_output;
|
||||||
|
|
||||||
|
|
||||||
function constant_value(name, fallback) {
|
function constant_value(name, fallback) {
|
||||||
let value = constants[name];
|
let value = constants[name];
|
||||||
return value == null ? as_string(fallback) : as_string(value);
|
return value == null ? as_string(fallback) : as_string(value);
|
||||||
@@ -124,21 +134,12 @@ let startup_config_fingerprint = "";
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
function command_from_args(args) {
|
|
||||||
let parts = [];
|
|
||||||
for (let arg in args)
|
|
||||||
push(parts, shell_quote(arg));
|
|
||||||
return join(" ", parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalize_status(status) {
|
function normalize_status(status) {
|
||||||
status = int(status);
|
status = int(status);
|
||||||
return status > 255 ? int(status / 256) : status;
|
return status > 255 ? int(status / 256) : status;
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_status(command) {
|
|
||||||
return normalize_status(system(command));
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_capture(command) {
|
function command_capture(command) {
|
||||||
let pipe = fs.popen(command, "r");
|
let pipe = fs.popen(command, "r");
|
||||||
@@ -150,16 +151,9 @@ function command_capture(command) {
|
|||||||
return { status, output: data == null ? "" : as_string(data) };
|
return { status, output: data == null ? "" : as_string(data) };
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_output(command) {
|
|
||||||
let result = command_capture(command);
|
|
||||||
return result.status == 0 ? result.output : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function write_json(value) {
|
|
||||||
print(sprintf("%J", value), "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_success(command) {
|
function command_success(command) {
|
||||||
return command_status(command + " >/dev/null 2>&1") == 0;
|
return command_status(command + " >/dev/null 2>&1") == 0;
|
||||||
@@ -169,13 +163,7 @@ function command_status_from_args(args) {
|
|||||||
return command_status(command_from_args(args));
|
return command_status(command_from_args(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_output_from_args(args) {
|
|
||||||
return command_output(command_from_args(args) + " 2>/dev/null");
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_success_from_args(args) {
|
|
||||||
return command_status(command_from_args(args) + " >/dev/null 2>&1") == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function external_config_fingerprint() {
|
function external_config_fingerprint() {
|
||||||
let data = fs.readfile(CONFIG_FILE);
|
let data = fs.readfile(CONFIG_FILE);
|
||||||
@@ -208,13 +196,7 @@ function bool_text(value) {
|
|||||||
return value == "1" || value == "true" || value == "yes" || value == "on";
|
return value == "1" || value == "true" || value == "yes" || value == "on";
|
||||||
}
|
}
|
||||||
|
|
||||||
function object_or_empty(value) {
|
|
||||||
return type(value) == "object" ? value : {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function array_or_empty(value) {
|
|
||||||
return type(value) == "array" ? value : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function string_array_contains(values, needle) {
|
function string_array_contains(values, needle) {
|
||||||
needle = as_string(needle);
|
needle = as_string(needle);
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ let common = require("core.common");
|
|||||||
let as_string = common.as_string;
|
let as_string = common.as_string;
|
||||||
let shell_quote = common.shell_quote;
|
let shell_quote = common.shell_quote;
|
||||||
|
|
||||||
|
let command_success_from_args = common.command_success_from_args;
|
||||||
|
let command_from_args = common.command_from_args;
|
||||||
|
|
||||||
|
|
||||||
function env(name, fallback) {
|
function env(name, fallback) {
|
||||||
let value = getenv(name);
|
let value = getenv(name);
|
||||||
return value == null ? as_string(fallback) : as_string(value);
|
return value == null ? as_string(fallback) : as_string(value);
|
||||||
@@ -23,21 +27,12 @@ const SING_BOX_CRONET = env("TACHYON_SING_BOX_CRONET", "/usr/lib/libcronet.so");
|
|||||||
const SING_BOX_MANAGED_MARKER = env("SB_MANAGED_SERVICE_MARKER", "Tachyon managed sing-box service for binary variants");
|
const SING_BOX_MANAGED_MARKER = env("SB_MANAGED_SERVICE_MARKER", "Tachyon managed sing-box service for binary variants");
|
||||||
const PACKAGE_TEST_MODE = env("TACHYON_PACKAGE_TEST_MODE", "") != "";
|
const PACKAGE_TEST_MODE = env("TACHYON_PACKAGE_TEST_MODE", "") != "";
|
||||||
|
|
||||||
function command_from_args(args) {
|
|
||||||
let parts = [];
|
|
||||||
for (let arg in args)
|
|
||||||
push(parts, shell_quote(arg));
|
|
||||||
return join(" ", parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalize_status(status) {
|
function normalize_status(status) {
|
||||||
status = int(status);
|
status = int(status);
|
||||||
return status > 255 ? int(status / 256) : status;
|
return status > 255 ? int(status / 256) : status;
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_success_from_args(args) {
|
|
||||||
return normalize_status(system(command_from_args(args) + " >/dev/null 2>&1")) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function path_exists(path) {
|
function path_exists(path) {
|
||||||
return fs.stat(as_string(path)) != null;
|
return fs.stat(as_string(path)) != null;
|
||||||
|
|||||||
@@ -2,9 +2,10 @@
|
|||||||
|
|
||||||
let fs = require("fs");
|
let fs = require("fs");
|
||||||
|
|
||||||
function as_string(value) {
|
let common = require("core.common");
|
||||||
return value == null ? "" : "" + value;
|
let as_string = common.as_string;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function arg_bool(value) {
|
function arg_bool(value) {
|
||||||
return value === true || value == "true" || value == "1" || value == 1;
|
return value === true || value == "true" || value == "1" || value == 1;
|
||||||
|
|||||||
@@ -20,24 +20,19 @@ let as_string = common.as_string;
|
|||||||
let shell_quote = common.shell_quote;
|
let shell_quote = common.shell_quote;
|
||||||
let read_json_file = common.read_json_file;
|
let read_json_file = common.read_json_file;
|
||||||
|
|
||||||
function read_stdin() {
|
let list_option = common.list_option;
|
||||||
let input = fs.open("/dev/stdin", "r");
|
let command_success_from_args = common.command_success_from_args;
|
||||||
if (!input)
|
let bool_option = common.bool_option;
|
||||||
return "";
|
let command_output_from_args = common.command_output_from_args;
|
||||||
let data = input.read("all");
|
let command_from_args = common.command_from_args;
|
||||||
input.close();
|
let command_trimmed_output_from_args = common.command_trimmed_output_from_args;
|
||||||
return data == null ? "" : data;
|
let object_or_empty = common.object_or_empty;
|
||||||
}
|
let read_stdin = common.read_stdin;
|
||||||
|
let read_stdin_json = common.read_stdin_json;
|
||||||
|
let option = common.option;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function read_stdin_json() {
|
|
||||||
let data = read_stdin();
|
|
||||||
try {
|
|
||||||
return json(data);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function write_text_file(path, text) {
|
function write_text_file(path, text) {
|
||||||
let result = fs.writefile(path, as_string(text));
|
let result = fs.writefile(path, as_string(text));
|
||||||
@@ -56,35 +51,9 @@ function unlink_file(path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_from_args(args) {
|
|
||||||
let parts = [];
|
|
||||||
|
|
||||||
for (let arg in args)
|
|
||||||
push(parts, shell_quote(arg));
|
|
||||||
|
|
||||||
return join(" ", parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_output_from_args(args) {
|
|
||||||
let pipe = fs.popen(command_from_args(args), "r");
|
|
||||||
if (!pipe)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let data = pipe.read("all");
|
|
||||||
let status = pipe.close();
|
|
||||||
if (status != 0 || data == null)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
return as_string(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_trimmed_output_from_args(args) {
|
|
||||||
return replace(command_output_from_args(args), /[\r\n]+$/g, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_success_from_args(args) {
|
|
||||||
return system(command_from_args(args) + " >/dev/null 2>&1") == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function uci_get(path) {
|
function uci_get(path) {
|
||||||
return uci_core.get(path);
|
return uci_core.get(path);
|
||||||
@@ -94,9 +63,6 @@ function uci_exists(path) {
|
|||||||
return uci_core.exists(path);
|
return uci_core.exists(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
function object_or_empty(value) {
|
|
||||||
return type(value) == "object" ? value : {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function file_first_line(path) {
|
function file_first_line(path) {
|
||||||
let data = fs.readfile(path);
|
let data = fs.readfile(path);
|
||||||
@@ -578,34 +544,8 @@ function arg_bool(value) {
|
|||||||
return value == "1" || value == "true" || value == "yes" || value == "on";
|
return value == "1" || value == "true" || value == "yes" || value == "on";
|
||||||
}
|
}
|
||||||
|
|
||||||
function option(section, key, fallback) {
|
|
||||||
if (fallback == null)
|
|
||||||
fallback = "";
|
|
||||||
|
|
||||||
let value = object_or_empty(section)[key];
|
|
||||||
if (value == null)
|
|
||||||
return fallback;
|
|
||||||
if (type(value) == "array")
|
|
||||||
return join(" ", value);
|
|
||||||
return as_string(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function list_option(section, key, fallback) {
|
|
||||||
let value = object_or_empty(section)[key];
|
|
||||||
if (type(value) == "array")
|
|
||||||
return value;
|
|
||||||
|
|
||||||
value = trim(as_string(value));
|
|
||||||
if (value != "")
|
|
||||||
return split(value, /[ \t\r\n]+/);
|
|
||||||
|
|
||||||
fallback = as_string(fallback);
|
|
||||||
return fallback == "" ? [] : [ fallback ];
|
|
||||||
}
|
|
||||||
|
|
||||||
function bool_option(section, key, fallback) {
|
|
||||||
return arg_bool(option(section, key, fallback ? "1" : "0"));
|
|
||||||
}
|
|
||||||
|
|
||||||
function bool_value(value) {
|
function bool_value(value) {
|
||||||
return arg_bool(value) ? "1" : "0";
|
return arg_bool(value) ? "1" : "0";
|
||||||
|
|||||||
@@ -12,21 +12,13 @@ const OFFSET_FILE = "/var/run/tachyon_telegram_offset";
|
|||||||
let as_string = common.as_string;
|
let as_string = common.as_string;
|
||||||
let shell_quote = common.shell_quote;
|
let shell_quote = common.shell_quote;
|
||||||
|
|
||||||
function command_from_args(args) {
|
let command_status = common.command_status;
|
||||||
let result = [];
|
let command_success_from_args = common.command_success_from_args;
|
||||||
for (let arg in args)
|
let command_from_args = common.command_from_args;
|
||||||
push(result, shell_quote(arg));
|
|
||||||
return join(" ", result);
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_status(command) {
|
|
||||||
let status = int(system(command));
|
|
||||||
return status > 255 ? int(status / 256) : status;
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_success_from_args(args) {
|
|
||||||
return command_status(command_from_args(args) + " >/dev/null 2>&1") == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_capture(command) {
|
function command_capture(command) {
|
||||||
let pipe = fs.popen(command, "r");
|
let pipe = fs.popen(command, "r");
|
||||||
|
|||||||
@@ -39,14 +39,16 @@ let as_string = common.as_string;
|
|||||||
let shell_quote = common.shell_quote;
|
let shell_quote = common.shell_quote;
|
||||||
let read_json_file = common.read_json_file;
|
let read_json_file = common.read_json_file;
|
||||||
|
|
||||||
function read_stdin() {
|
let write_json = common.write_json;
|
||||||
let input = fs.open("/dev/stdin", "r");
|
let command_status = common.command_status;
|
||||||
if (!input)
|
let command_success_from_args = common.command_success_from_args;
|
||||||
return "";
|
let command_output_from_args = common.command_output_from_args;
|
||||||
let data = input.read("all");
|
let command_from_args = common.command_from_args;
|
||||||
input.close();
|
let object_or_empty = common.object_or_empty;
|
||||||
return data == null ? "" : data;
|
let read_stdin = common.read_stdin;
|
||||||
}
|
let command_output = common.command_output;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function parse_json_or_null(value) {
|
function parse_json_or_null(value) {
|
||||||
try {
|
try {
|
||||||
@@ -57,22 +59,11 @@ function parse_json_or_null(value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function write_json(value) {
|
|
||||||
print(sprintf("%J", value), "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
function json_text(value) {
|
function json_text(value) {
|
||||||
return sprintf("%J", value) + "\n";
|
return sprintf("%J", value) + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_from_args(args) {
|
|
||||||
let parts = [];
|
|
||||||
|
|
||||||
for (let arg in args)
|
|
||||||
push(parts, shell_quote(arg));
|
|
||||||
|
|
||||||
return join(" ", parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_env(assignments) {
|
function command_env(assignments) {
|
||||||
let parts = [];
|
let parts = [];
|
||||||
@@ -83,35 +74,13 @@ function command_env(assignments) {
|
|||||||
return join(" ", parts);
|
return join(" ", parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_output(command) {
|
|
||||||
let pipe = fs.popen(command, "r");
|
|
||||||
if (!pipe)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let data = pipe.read("all");
|
|
||||||
let status = pipe.close();
|
|
||||||
if (status != 0 || data == null)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
return as_string(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_output_from_args(args) {
|
|
||||||
return command_output(command_from_args(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_status(command) {
|
|
||||||
let status = int(system(command));
|
|
||||||
return status > 255 ? int(status / 256) : status;
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_success(command) {
|
function command_success(command) {
|
||||||
return command_status(command + " >/dev/null 2>&1") == 0;
|
return command_status(command + " >/dev/null 2>&1") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_success_from_args(args) {
|
|
||||||
return command_success(command_from_args(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
function module_success(module_path, args) {
|
function module_success(module_path, args) {
|
||||||
let command_args = [ "ucode", "-L", LIB_DIR, module_path ];
|
let command_args = [ "ucode", "-L", LIB_DIR, module_path ];
|
||||||
@@ -201,9 +170,6 @@ function unsigned_number(value) {
|
|||||||
return int(value);
|
return int(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function object_or_empty(value) {
|
|
||||||
return type(value) == "object" ? value : {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function path_basename(path) {
|
function path_basename(path) {
|
||||||
let parts = split(as_string(path), "/");
|
let parts = split(as_string(path), "/");
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ const BYEDPI_LISTEN_ADDRESS = "127.0.0.1";
|
|||||||
const BYEDPI_PORT_BASE = 1080;
|
const BYEDPI_PORT_BASE = 1080;
|
||||||
|
|
||||||
const RESERVED_TAGS = {
|
const RESERVED_TAGS = {
|
||||||
|
|
||||||
|
let common = require("core.common");
|
||||||
|
let as_string = common.as_string;
|
||||||
|
|
||||||
[DNS_SERVER_TAG]: true,
|
[DNS_SERVER_TAG]: true,
|
||||||
[FAKEIP_DNS_SERVER_TAG]: true,
|
[FAKEIP_DNS_SERVER_TAG]: true,
|
||||||
[BOOTSTRAP_DNS_SERVER_TAG]: true,
|
[BOOTSTRAP_DNS_SERVER_TAG]: true,
|
||||||
@@ -51,9 +55,6 @@ const RESERVED_TAGS = {
|
|||||||
[BYPASS_OUTBOUND_TAG]: true
|
[BYPASS_OUTBOUND_TAG]: true
|
||||||
};
|
};
|
||||||
|
|
||||||
function as_string(value) {
|
|
||||||
return value == null ? "" : "" + value;
|
|
||||||
}
|
|
||||||
|
|
||||||
function tag(base, postfix) {
|
function tag(base, postfix) {
|
||||||
let candidate = as_string(base) + "-" + as_string(postfix);
|
let candidate = as_string(base) + "-" + as_string(postfix);
|
||||||
|
|||||||
@@ -12,24 +12,11 @@ const COUNTRY_IS_BATCH_SIZE = 100;
|
|||||||
|
|
||||||
let shell_quote = common.shell_quote;
|
let shell_quote = common.shell_quote;
|
||||||
|
|
||||||
function command_from_args(args) {
|
let command_output_from_args = common.command_output_from_args;
|
||||||
let parts = [];
|
let command_from_args = common.command_from_args;
|
||||||
for (let arg in args)
|
|
||||||
push(parts, shell_quote(arg));
|
|
||||||
return join(" ", parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_output_from_args(args) {
|
|
||||||
let pipe = fs.popen(command_from_args(args) + " 2>/dev/null", "r");
|
|
||||||
if (!pipe)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let data = pipe.read("all");
|
|
||||||
let status = pipe.close();
|
|
||||||
if (status != 0 || data == null)
|
|
||||||
return "";
|
|
||||||
return as_string(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
function remove_file(path) {
|
function remove_file(path) {
|
||||||
if (as_string(path) != "")
|
if (as_string(path) != "")
|
||||||
|
|||||||
@@ -18,30 +18,15 @@ const CHECK_DOMAIN = "example.com";
|
|||||||
let as_string = common.as_string;
|
let as_string = common.as_string;
|
||||||
let shell_quote = common.shell_quote;
|
let shell_quote = common.shell_quote;
|
||||||
|
|
||||||
function command_from_args(args) {
|
let command_status = common.command_status;
|
||||||
let result = [];
|
let command_success_from_args = common.command_success_from_args;
|
||||||
for (let arg in args)
|
let command_output_from_args = common.command_output_from_args;
|
||||||
push(result, shell_quote(arg));
|
let command_from_args = common.command_from_args;
|
||||||
return join(" ", result);
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_status(command) {
|
|
||||||
let status = int(system(command));
|
|
||||||
return status > 255 ? int(status / 256) : status;
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_success_from_args(args) {
|
|
||||||
return command_status(command_from_args(args) + " >/dev/null 2>&1") == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_output_from_args(args) {
|
|
||||||
let pipe = fs.popen(command_from_args(args), "r");
|
|
||||||
if (!pipe)
|
|
||||||
return "";
|
|
||||||
let data = pipe.read("all");
|
|
||||||
let status = pipe.close();
|
|
||||||
return status == 0 && data != null ? as_string(data) : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
function settings() {
|
function settings() {
|
||||||
return common.object_or_empty(uci_core.get_all(CONFIG_NAME, "settings"));
|
return common.object_or_empty(uci_core.get_all(CONFIG_NAME, "settings"));
|
||||||
|
|||||||
@@ -18,37 +18,17 @@ const DIAGNOSTICS_UC = getenv("TACHYON_DIAGNOSTICS_UC") || LIB_DIR + "/diagnosti
|
|||||||
|
|
||||||
let shell_quote = common.shell_quote;
|
let shell_quote = common.shell_quote;
|
||||||
|
|
||||||
function command_from_args(args) {
|
let command_status = common.command_status;
|
||||||
let parts = [];
|
let command_success_from_args = common.command_success_from_args;
|
||||||
for (let arg in args)
|
let command_output_from_args = common.command_output_from_args;
|
||||||
push(parts, shell_quote(arg));
|
let command_from_args = common.command_from_args;
|
||||||
return join(" ", parts);
|
let command_output = common.command_output;
|
||||||
}
|
|
||||||
|
|
||||||
function command_output(command) {
|
|
||||||
let pipe = fs.popen(command, "r");
|
|
||||||
if (!pipe)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let data = pipe.read("all");
|
|
||||||
let status = pipe.close();
|
|
||||||
if (status != 0 || data == null)
|
|
||||||
return "";
|
|
||||||
return as_string(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_output_from_args(args) {
|
|
||||||
return command_output(command_from_args(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_status(command) {
|
|
||||||
let status = int(system(command));
|
|
||||||
return status > 255 ? int(status / 256) : status;
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_success_from_args(args) {
|
|
||||||
return command_status(command_from_args(args) + " >/dev/null 2>&1") == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function ensure_dir(path) {
|
function ensure_dir(path) {
|
||||||
return command_success_from_args([ "mkdir", "-p", path ]);
|
return command_success_from_args([ "mkdir", "-p", path ]);
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ let runtime_constants = require("singbox.constants");
|
|||||||
let option = common.option;
|
let option = common.option;
|
||||||
let bool_option = common.bool_option;
|
let bool_option = common.bool_option;
|
||||||
|
|
||||||
function as_string(value) {
|
let as_string = common.as_string;
|
||||||
return value == null ? "" : "" + value;
|
|
||||||
}
|
|
||||||
|
|
||||||
function bool_value(value) {
|
function bool_value(value) {
|
||||||
return value === true || value == "1" || value == "true" || value == "yes" || value == "on";
|
return value === true || value == "1" || value == "true" || value == "yes" || value == "on";
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ const SRS_SUPERCELL_URL = "https://raw.githubusercontent.com/ushan0v/sing-box-su
|
|||||||
const SRS_GITHUB_URL = "https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geosite/github.srs";
|
const SRS_GITHUB_URL = "https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geosite/github.srs";
|
||||||
|
|
||||||
const COMMUNITY_SERVICES = {
|
const COMMUNITY_SERVICES = {
|
||||||
|
|
||||||
|
let common = require("core.common");
|
||||||
|
let as_string = common.as_string;
|
||||||
|
|
||||||
russia_inside: true,
|
russia_inside: true,
|
||||||
russia_outside: true,
|
russia_outside: true,
|
||||||
ukraine_inside: true,
|
ukraine_inside: true,
|
||||||
@@ -35,9 +39,6 @@ const COMMUNITY_SERVICES = {
|
|||||||
github: true
|
github: true
|
||||||
};
|
};
|
||||||
|
|
||||||
function as_string(value) {
|
|
||||||
return value == null ? "" : "" + value;
|
|
||||||
}
|
|
||||||
|
|
||||||
function is_community(name) {
|
function is_community(name) {
|
||||||
return COMMUNITY_SERVICES[as_string(name)] === true;
|
return COMMUNITY_SERVICES[as_string(name)] === true;
|
||||||
|
|||||||
@@ -41,12 +41,18 @@ const SB_MANAGED_SERVICE_MARKER = getenv("SB_MANAGED_SERVICE_MARKER") || "Tachyo
|
|||||||
let as_string = common.as_string;
|
let as_string = common.as_string;
|
||||||
let shell_quote = common.shell_quote;
|
let shell_quote = common.shell_quote;
|
||||||
|
|
||||||
function command_from_args(args) {
|
let option = common.option;
|
||||||
let parts = [];
|
let command_status = common.command_status;
|
||||||
for (let arg in args)
|
let command_success_from_args = common.command_success_from_args;
|
||||||
push(parts, shell_quote(arg));
|
let bool_option = common.bool_option;
|
||||||
return join(" ", parts);
|
let command_output_from_args = common.command_output_from_args;
|
||||||
}
|
let command_exists = common.command_exists;
|
||||||
|
let command_from_args = common.command_from_args;
|
||||||
|
let object_or_empty = common.object_or_empty;
|
||||||
|
let array_or_empty = common.array_or_empty;
|
||||||
|
let command_output = common.command_output;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function command_env(assignments) {
|
function command_env(assignments) {
|
||||||
let parts = [];
|
let parts = [];
|
||||||
@@ -55,38 +61,14 @@ function command_env(assignments) {
|
|||||||
return join(" ", parts);
|
return join(" ", parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_output(command) {
|
|
||||||
let pipe = fs.popen(command, "r");
|
|
||||||
if (!pipe)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let data = pipe.read("all");
|
|
||||||
let status = pipe.close();
|
|
||||||
if (status != 0 || data == null)
|
|
||||||
return "";
|
|
||||||
return as_string(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_output_from_args(args) {
|
|
||||||
return command_output(command_from_args(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_status(command) {
|
|
||||||
let status = int(system(command));
|
|
||||||
return status > 255 ? int(status / 256) : status;
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_success(command) {
|
function command_success(command) {
|
||||||
return command_status(command + " >/dev/null 2>&1") == 0;
|
return command_status(command + " >/dev/null 2>&1") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_success_from_args(args) {
|
|
||||||
return system(command_from_args(args) + " >/dev/null 2>&1") == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_exists(name) {
|
|
||||||
return command_success_from_args([ "command", "-v", name ]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function write_file(path, value) {
|
function write_file(path, value) {
|
||||||
return fs.writefile(as_string(path), as_string(value)) != null;
|
return fs.writefile(as_string(path), as_string(value)) != null;
|
||||||
@@ -114,35 +96,14 @@ function file_first_line(path) {
|
|||||||
return trim(newline >= 0 ? substr(data, 0, newline) : data);
|
return trim(newline >= 0 ? substr(data, 0, newline) : data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function object_or_empty(value) {
|
|
||||||
return type(value) == "object" ? value : {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function array_or_empty(value) {
|
|
||||||
return type(value) == "array" ? value : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function option(section, key, fallback) {
|
|
||||||
if (fallback == null)
|
|
||||||
fallback = "";
|
|
||||||
|
|
||||||
let value = object_or_empty(section)[key];
|
|
||||||
if (value == null)
|
|
||||||
return fallback;
|
|
||||||
if (type(value) == "array")
|
|
||||||
return join(" ", value);
|
|
||||||
return as_string(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function arg_bool(value) {
|
function arg_bool(value) {
|
||||||
value = lc(as_string(value));
|
value = lc(as_string(value));
|
||||||
return value == "true" || value == "1" || value == "yes" || value == "on";
|
return value == "true" || value == "1" || value == "yes" || value == "on";
|
||||||
}
|
}
|
||||||
|
|
||||||
function bool_option(section, key, fallback) {
|
|
||||||
let value = object_or_empty(section)[key];
|
|
||||||
return value == null ? !!fallback : arg_bool(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function whitespace_items(value) {
|
function whitespace_items(value) {
|
||||||
let result = [];
|
let result = [];
|
||||||
|
|||||||
@@ -35,10 +35,20 @@ let common = require("core.common");
|
|||||||
let as_string = common.as_string;
|
let as_string = common.as_string;
|
||||||
let shell_quote = common.shell_quote;
|
let shell_quote = common.shell_quote;
|
||||||
|
|
||||||
function read_stdin() {
|
let command_output = common.command_output;
|
||||||
let data = fs.readfile("/dev/stdin");
|
let write_json = common.write_json;
|
||||||
return data == null ? "" : data;
|
let list_option = common.list_option;
|
||||||
}
|
let command_success_from_args = common.command_success_from_args;
|
||||||
|
let bool_option = common.bool_option;
|
||||||
|
let command_output_from_args = common.command_output_from_args;
|
||||||
|
let command_from_args = common.command_from_args;
|
||||||
|
let object_key_count = common.object_key_count;
|
||||||
|
let object_or_empty = common.object_or_empty;
|
||||||
|
let read_stdin = common.read_stdin;
|
||||||
|
let array_or_empty = common.array_or_empty;
|
||||||
|
let option = common.option;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function read_json(path) {
|
function read_json(path) {
|
||||||
if (path == null || path == "" || path == "-")
|
if (path == null || path == "" || path == "-")
|
||||||
@@ -60,9 +70,6 @@ function write_file(path, value) {
|
|||||||
return fs.writefile(path, value) != null;
|
return fs.writefile(path, value) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function write_json(path, value) {
|
|
||||||
return write_file(path, sprintf("%J", value) + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
function write_stdout_json(value) {
|
function write_stdout_json(value) {
|
||||||
print(sprintf("%J", value), "\n");
|
print(sprintf("%J", value), "\n");
|
||||||
@@ -131,21 +138,7 @@ function append_state_list_once(list, value) {
|
|||||||
print(list, list != "" ? " " : "", value, "\n");
|
print(list, list != "" ? " " : "", value, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
function object_or_empty(value) {
|
|
||||||
return type(value) == "object" ? value : {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function option(section, key, fallback) {
|
|
||||||
if (fallback == null)
|
|
||||||
fallback = "";
|
|
||||||
|
|
||||||
let value = object_or_empty(section)[key];
|
|
||||||
if (value == null)
|
|
||||||
return fallback;
|
|
||||||
if (type(value) == "array")
|
|
||||||
return join(" ", value);
|
|
||||||
return as_string(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function bool_value(value, fallback) {
|
function bool_value(value, fallback) {
|
||||||
if (value == null)
|
if (value == null)
|
||||||
@@ -155,9 +148,6 @@ function bool_value(value, fallback) {
|
|||||||
return value == "1" || value == "true" || value == "yes" || value == "on";
|
return value == "1" || value == "true" || value == "yes" || value == "on";
|
||||||
}
|
}
|
||||||
|
|
||||||
function bool_option(section, key, fallback) {
|
|
||||||
return bool_value(object_or_empty(section)[key], fallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
function unsigned_number(value) {
|
function unsigned_number(value) {
|
||||||
value = as_string(value);
|
value = as_string(value);
|
||||||
@@ -533,14 +523,6 @@ function files_equal(left, right) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
function command_from_args(args) {
|
|
||||||
let parts = [];
|
|
||||||
|
|
||||||
for (let arg in args)
|
|
||||||
push(parts, shell_quote(arg));
|
|
||||||
|
|
||||||
return join(" ", parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_env(assignments) {
|
function command_env(assignments) {
|
||||||
let parts = [];
|
let parts = [];
|
||||||
@@ -562,26 +544,8 @@ function command_args_with(base, extra) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function command_output(command) {
|
|
||||||
let pipe = fs.popen(command, "r");
|
|
||||||
if (!pipe)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let data = pipe.read("all");
|
|
||||||
let status = pipe.close();
|
|
||||||
if (status != 0 || data == null)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
return as_string(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_output_from_args(args) {
|
|
||||||
return command_output(command_from_args(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_success_from_args(args) {
|
|
||||||
return system(command_from_args(args) + " >/dev/null 2>&1") == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function command_status_from_args(args) {
|
function command_status_from_args(args) {
|
||||||
let status = int(system(command_from_args(args)));
|
let status = int(system(command_from_args(args)));
|
||||||
@@ -821,14 +785,6 @@ function uci_named_section(section_name_value) {
|
|||||||
return object_or_empty(uci_core.get_all(CONFIG_NAME, section_name_value));
|
return object_or_empty(uci_core.get_all(CONFIG_NAME, section_name_value));
|
||||||
}
|
}
|
||||||
|
|
||||||
function list_option(section, key) {
|
|
||||||
let value = object_or_empty(section)[key];
|
|
||||||
if (type(value) == "array")
|
|
||||||
return value;
|
|
||||||
if (as_string(value) != "")
|
|
||||||
return [ as_string(value) ];
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function find_section(sections, name) {
|
function find_section(sections, name) {
|
||||||
name = as_string(name);
|
name = as_string(name);
|
||||||
@@ -1020,9 +976,6 @@ function is_array(value) {
|
|||||||
return type(value) == "array";
|
return type(value) == "array";
|
||||||
}
|
}
|
||||||
|
|
||||||
function array_or_empty(value) {
|
|
||||||
return type(value) == "array" ? value : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function int_or_zero(value) {
|
function int_or_zero(value) {
|
||||||
value = as_string(value);
|
value = as_string(value);
|
||||||
@@ -1067,9 +1020,6 @@ function log_subscription_source_summary(section_name_value, source_index, norma
|
|||||||
log_message(subscription_source_summary(section_name_value, source_index, normalized_path, result), "info");
|
log_message(subscription_source_summary(section_name_value, source_index, normalized_path, result), "info");
|
||||||
}
|
}
|
||||||
|
|
||||||
function object_key_count(value) {
|
|
||||||
return type(value) == "object" ? length(keys(value)) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function valid_metadata_object(value) {
|
function valid_metadata_object(value) {
|
||||||
return type(value) == "object" && object_key_count(value) > 1;
|
return type(value) == "object" && object_key_count(value) > 1;
|
||||||
|
|||||||
@@ -6,6 +6,13 @@ let common = require("core.common");
|
|||||||
let as_string = common.as_string;
|
let as_string = common.as_string;
|
||||||
let shell_quote = common.shell_quote;
|
let shell_quote = common.shell_quote;
|
||||||
|
|
||||||
|
let read_json_file = common.read_json_file;
|
||||||
|
let write_json_file = common.write_json_file;
|
||||||
|
let object_or_empty = common.object_or_empty;
|
||||||
|
let write_json = common.write_json;
|
||||||
|
let array_or_empty = common.array_or_empty;
|
||||||
|
|
||||||
|
|
||||||
function trim(value) {
|
function trim(value) {
|
||||||
value = as_string(value);
|
value = as_string(value);
|
||||||
let start = 0;
|
let start = 0;
|
||||||
@@ -287,23 +294,13 @@ function read_file(path) {
|
|||||||
return fs.readfile(path);
|
return fs.readfile(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
function read_json_file(path) {
|
|
||||||
let data = read_file(path);
|
|
||||||
return data == null ? null : json_decode_text(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
function validate_subscription(path) {
|
function validate_subscription(path) {
|
||||||
let value = read_json_file(path);
|
let value = read_json_file(path);
|
||||||
return type(value) == "object" && type(value.outbounds) == "array" && length(value.outbounds) > 0;
|
return type(value) == "object" && type(value.outbounds) == "array" && length(value.outbounds) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function write_json_file(path, value) {
|
|
||||||
return fs.writefile(path, sprintf("%J", value) + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
function write_json(value) {
|
|
||||||
print(sprintf("%J", value), "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
function canonical_runtime_value(value) {
|
function canonical_runtime_value(value) {
|
||||||
if (type(value) == "array") {
|
if (type(value) == "array") {
|
||||||
@@ -350,13 +347,7 @@ function runtime_outbounds_equal(left_path, right_path) {
|
|||||||
return sprintf("%J", left) == sprintf("%J", right);
|
return sprintf("%J", left) == sprintf("%J", right);
|
||||||
}
|
}
|
||||||
|
|
||||||
function array_or_empty(value) {
|
|
||||||
return type(value) == "array" ? value : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function object_or_empty(value) {
|
|
||||||
return type(value) == "object" ? value : {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function base64_decode(value) {
|
function base64_decode(value) {
|
||||||
value = as_string(value);
|
value = as_string(value);
|
||||||
|
|||||||
Reference in New Issue
Block a user