aboutsummaryrefslogtreecommitdiff
path: root/apkg-bin
diff options
context:
space:
mode:
Diffstat (limited to 'apkg-bin')
-rwxr-xr-xapkg-bin591
1 files changed, 591 insertions, 0 deletions
diff --git a/apkg-bin b/apkg-bin
new file mode 100755
index 0000000..5d8de7f
--- /dev/null
+++ b/apkg-bin
@@ -0,0 +1,591 @@
+#!/bin/sh
+#
+# APKG-BIN - Alice Binary Package Manager (C) 2023-2026 Emmett1
+#
+# Fetches pre-built .spm packages from a binary repo, resolves dependencies,
+# and installs via spm. Alternative to source-based 'apkg'.
+
+msg() {
+ printf "%s\n" "[apkg-bin] $*" >&2
+}
+
+die() {
+ [ "$1" ] && printf "%s\n" "error: $1" >&2
+ exit 1
+}
+
+needroot() {
+ [ "$(id -u)" = 0 ] || die "This operation requires root access"
+}
+
+prompt_user() {
+ [ "$APKG_NOPROMPT" ] && return
+ msg "Press ENTER to continue. Press Ctrl+C to abort."
+ read -r _null
+}
+
+needbinsrc() {
+ [ "$APKGBIN_REPO" ] || die "APKGBIN_REPO is not set"
+}
+
+needcachedb() {
+ [ -f "$APKGBIN_CACHE_DIR/APKGBINDB" ] || die "No cached APKGBINDB found. Run 'apkg-bin -S' first."
+ [ -r "$APKGBIN_CACHE_DIR/APKGBINDB" ] || die "No read permission on $APKGBIN_CACHE_DIR/APKGBINDB"
+}
+
+pkg_is_installed() {
+ [ -s "$SPM_PKGDB/$1" ]
+}
+
+pkg_installed_ver() {
+ head -n1 "$SPM_PKGDB/$1" 2>/dev/null
+}
+
+# get field from a APKGBINDB line: bin_fetch_field <line> <fieldnum>
+# 1=namever, 2=size, 3=sha3sum, 4=deps, 5=preinstall, 6=postinstall, 7=desc
+bin_fetch_field() {
+ _line=$1
+ _field=$2
+ _rest=$_line
+ _i=1
+ while [ "$_i" -lt "$_field" ]; do
+ _rest=${_rest#*|}
+ _i=$((_i + 1))
+ done
+ case $_field in
+ 7) printf "%s\n" "${_rest#*|}" ;;
+ *) printf "%s\n" "${_rest%%|*}" ;;
+ esac
+}
+
+# find a package name in APKGBINDB, output the full line
+bin_find_pkg() {
+ _pkg=$1
+ _line=$(grep "^$_pkg#" "$APKGBIN_CACHE_DIR/APKGBINDB" 2>/dev/null | head -n1)
+ [ "$_line" ] && printf "%s\n" "$_line"
+}
+
+# get full name#version-release for a package name
+bin_get_pkgid() {
+ _line=$(bin_find_pkg "$1") || return 1
+ bin_fetch_field "$_line" 1
+}
+
+# get deps for a package (space-separated names) from APKGBINDB only
+bin_get_deps() {
+ _line=$(bin_find_pkg "$1" 2>/dev/null)
+ if [ "$_line" ]; then
+ _deps=$(bin_fetch_field "$_line" 4)
+ if [ "$_deps" ]; then
+ printf "%s\n" "$_deps" | tr ',' ' '
+ fi
+ fi
+}
+
+# get description for a package
+bin_get_desc() {
+ _line=$(bin_find_pkg "$1") || return 0
+ bin_fetch_field "$_line" 7
+}
+
+# get preinstall script (base64) for a package
+bin_get_preinstall() {
+ _line=$(bin_find_pkg "$1" 2>/dev/null) || return 0
+ bin_fetch_field "$_line" 5
+}
+
+# get postinstall script (base64) for a package
+bin_get_postinstall() {
+ _line=$(bin_find_pkg "$1" 2>/dev/null) || return 0
+ bin_fetch_field "$_line" 6
+}
+
+# run a pre/post install script from base64
+bin_run_script() {
+ _name=$1
+ _b64=$2
+ _tag=$3 # "pre" or "post"
+ [ "$_b64" ] || return 0
+ msg "Running ${_tag}install script for $_name ..."
+ printf "%s\n" "$_b64" | base64 -d | sh -e || {
+ msg "Warning: ${_tag}install script for $_name failed"
+ }
+}
+
+solve_alias() {
+ [ "$APKG_ALIAS" ] || {
+ printf "%s\n" "$@"
+ return
+ }
+ for _a in "$@"; do
+ _d=$(printf "%s\n" $APKG_ALIAS | tr ' ' '\n' | grep "^$_a:" | head -n1 | awk -F : '{print $2}')
+ printf "%s\n" "${_d:-$_a}"
+ done
+}
+
+bin_checkdep() {
+ # skip packages not in APKGBINDB
+ if ! bin_find_pkg "$1" >/dev/null 2>&1; then
+ [ "$_process" ] && msg "Warning: '$1' not found in APKGBINDB, skipping"
+ return
+ fi
+ _process="$_process $1"
+ for _d in $(solve_alias $(bin_get_deps "$1")); do
+ [ "$_d" = "$1" ] && continue
+ if [ "$_skip_installed" ]; then
+ pkg_is_installed "$_d" && continue
+ fi
+ # cycle detection
+ printf "%s\n" $_process | tr ' ' '\n' | grep -Fxq "$_d" && continue
+ # already resolved
+ printf "%s\n" $DEPS | tr ' ' '\n' | grep -Fxq "$_d" && continue
+ bin_checkdep "$_d"
+ done
+ printf "%s\n" $DEPS | tr ' ' '\n' | grep -Fxq "$1" || DEPS="$DEPS $1"
+}
+
+bin_deplist() {
+ DEPS=""
+ _process=""
+ _skip_installed=""
+ for _p in "$@"; do
+ printf "%s\n" $DEPS | tr ' ' '\n' | grep -Fxq "$_p" || bin_checkdep "$_p"
+ done
+ printf "%s\n" $DEPS | tr ' ' '\n' | grep -v ^$
+}
+
+bin_sync() {
+ needbinsrc
+ mkdir -p "$APKGBIN_CACHE_DIR" 2>/dev/null
+ [ -w "$APKGBIN_CACHE_DIR" ] || die "No write permission on $APKGBIN_CACHE_DIR"
+ case $APKGBIN_REPO in
+ http://*|https://*|ftp://*)
+ msg "Syncing $APKGBIN_REPO ..."
+ curl -fL -o "$APKGBIN_CACHE_DIR/APKGBINDB.tmp" "$APKGBIN_REPO/APKGBINDB" || {
+ rm -f "$APKGBIN_CACHE_DIR/APKGBINDB.tmp"
+ die "Failed to fetch APKGBINDB from $APKGBIN_REPO"
+ }
+ mv "$APKGBIN_CACHE_DIR/APKGBINDB.tmp" "$APKGBIN_CACHE_DIR/APKGBINDB"
+ ;;
+ *)
+ [ -f "$APKGBIN_REPO/APKGBINDB" ] || die "No APKGBINDB found at $APKGBIN_REPO"
+ msg "Syncing $APKGBIN_REPO (local) ..."
+ cp "$APKGBIN_REPO/APKGBINDB" "$APKGBIN_CACHE_DIR/APKGBINDB"
+ ;;
+ esac
+ msg "Sync complete."
+}
+
+bin_generate() {
+ [ "$APKG_REPO" ] || die "APKG_REPO is not set (needed to read abuild metadata)"
+ [ -d "$APKG_PACKAGE_DIR" ] || die "APKG_PACKAGE_DIR ($APKG_PACKAGE_DIR) not found"
+ [ -r "$APKG_PACKAGE_DIR" ] || die "No read permission on $APKG_PACKAGE_DIR"
+ [ -w "$APKG_PACKAGE_DIR" ] || die "No write permission on $APKG_PACKAGE_DIR"
+ mkdir -p "$APKGBIN_CACHE_DIR" 2>/dev/null
+ [ -w "$APKGBIN_CACHE_DIR" ] || die "No write permission on $APKGBIN_CACHE_DIR"
+
+ _output="${APKG_PACKAGE_DIR}/APKGBINDB"
+ > "$_output"
+
+ _count=0
+ for _spm in "$APKG_PACKAGE_DIR"/*.spm; do
+ [ -f "$_spm" ] || continue
+ _filename=${_spm##*/}
+ _namever=${_filename%.spm}
+ _name=${_namever%%#*}
+ _size=$(stat -c%s "$_spm" 2>/dev/null || wc -c < "$_spm")
+ _sha3=$(sha3sum "$_spm" 2>/dev/null | awk '{print $1}')
+
+ _deps=""
+ for _r in $APKG_REPO; do
+ if [ -f "$_r/$_name/depends" ]; then
+ for _d in $(grep -Ev '^(#|$)' "$_r/$_name/depends" | awk '{print $1}'); do
+ for _rr in $APKG_REPO; do
+ [ -d "$_rr/$_d" ] && { _deps="$_deps$_d,"; break; }
+ done
+ done
+ _deps=${_deps%,}
+ break
+ fi
+ done
+
+ _desc=""
+ _pre=""
+ _post=""
+ for _r in $APKG_REPO; do
+ [ -f "$_r/$_name/info" ] && [ ! "$_desc" ] && \
+ _desc=$(grep '^description:' "$_r/$_name/info" | sed 's/^description:[[:space:]]*//')
+ [ -f "$_r/$_name/preinstall" ] && [ ! "$_pre" ] && \
+ _pre=$(base64 "$_r/$_name/preinstall" 2>/dev/null | tr -d '\n')
+ [ -f "$_r/$_name/postinstall" ] && [ ! "$_post" ] && \
+ _post=$(base64 "$_r/$_name/postinstall" 2>/dev/null | tr -d '\n')
+ done
+
+ printf "%s|%s|%s|%s|%s|%s|%s\n" "$_namever" "$_size" "$_sha3" "$_deps" "$_pre" "$_post" "$_desc" >> "$_output"
+ _count=$((_count + 1))
+ done
+
+ # also cache locally so -l/-s/-i work immediately
+ mkdir -p "$APKGBIN_CACHE_DIR"
+ [ "$_output" = "$APKGBIN_CACHE_DIR/APKGBINDB" ] || cp "$_output" "$APKGBIN_CACHE_DIR/APKGBINDB"
+ msg "Wrote APKGBINDB with $_count entries to $_output"
+}
+
+bin_download_pkg() {
+ _pkgid=$1
+ _name=${_pkgid%%#*}
+ _pkgfile="$_pkgid.spm"
+
+ mkdir -p "$APKGBIN_CACHE_DIR" 2>/dev/null
+ [ -w "$APKGBIN_CACHE_DIR" ] || die "No write permission on $APKGBIN_CACHE_DIR"
+
+ case $APKGBIN_REPO in
+ http://*|https://*|ftp://*)
+ _urlfile=$(printf "%s\n" "$_pkgfile" | sed 's/#/%23/g')
+ _target="$APKGBIN_CACHE_DIR/$_pkgfile"
+ if [ "$force" ] || [ ! -f "$_target" ]; then
+ msg "Downloading $APKGBIN_REPO/$_pkgfile"
+ curl -fL -o "$_target.tmp" "$APKGBIN_REPO/$_urlfile" || {
+ rm -f "$_target.tmp"
+ die "Failed to download $_pkgfile from $APKGBIN_REPO"
+ }
+ mv "$_target.tmp" "$_target"
+ fi
+ ;;
+ *)
+ _target="$APKGBIN_REPO/$_pkgfile"
+ [ -f "$_target" ] || die "Package file not found: $_target"
+ ;;
+ esac
+
+ # verify sha3sum if available in APKGBINDB
+ _line=$(bin_find_pkg "$_name")
+ _expected=$(bin_fetch_field "$_line" 3)
+ if [ "$_expected" ]; then
+ _actual=$(sha3sum "$_target" | awk '{print $1}')
+ [ "$_actual" = "$_expected" ] || die "sha3sum mismatch for $_pkgfile"
+ fi
+
+ printf "%s\n" "$_target"
+}
+
+bin_install() {
+ _resolve=${1:-1}; shift # 1=resolve deps, 0=no deps
+ needroot
+ needcachedb
+ [ "$1" ] || die "No packages specified"
+
+ _todo=""
+ for _p in "$@"; do
+ if pkg_is_installed "$_p"; then
+ msg "Package '$_p' is already installed. Skipping."
+ else
+ _todo="$_todo $_p"
+ fi
+ done
+ [ "$_todo" ] || { msg "Nothing to install."; exit 0; }
+
+ if [ "$_resolve" = 1 ]; then
+ msg "Solving dependencies..."
+ _deps=$(_skip_installed=1 bin_deplist $_todo)
+ else
+ _deps=$_todo
+ fi
+ [ "$_deps" ] || { msg "Nothing to install."; exit 0; }
+
+ _total=$(printf "%s\n" "$_deps" | wc -l)
+ msg "Installing $_total package(s): $(printf "%s\n" "$_deps" | tr '\n' ' ')"
+
+ for _d in $_deps; do
+ _pkgid=$(bin_get_pkgid "$_d") || continue
+ msg " $_pkgid"
+ done
+
+ prompt_user
+
+ for _d in $_deps; do
+ _pkgid=$(bin_get_pkgid "$_d") || continue
+ _pkgpath=$(bin_download_pkg "$_pkgid") || continue
+ bin_run_script "$_d" "$(bin_get_preinstall "$_d")" pre
+ msg "Installing $_pkgid ..."
+ SPM_ROOT=${APKG_ROOT%/} spm -i "$_pkgpath" || die "Failed to install $_pkgid"
+ bin_run_script "$_d" "$(bin_get_postinstall "$_d")" post
+ done
+}
+
+bin_upgrade() {
+ needroot
+ needcachedb
+ [ "$1" ] || die "No packages specified"
+
+ for _p in "$@"; do
+ if ! pkg_is_installed "$_p"; then
+ msg "Package '$_p' not installed. Skipping."
+ continue
+ fi
+ _pkgid=$(bin_get_pkgid "$_p") || {
+ msg "Package '$_p' not found in APKGBINDB. Skipping."
+ continue
+ }
+ _pkgpath=$(bin_download_pkg "$_pkgid") || continue
+ _installed=$(pkg_installed_ver "$_p")
+ _available=${_pkgid#*#}
+ [ "$_installed" = "$_available" ] && msg "Package '$_p' is up to date, reinstalling."
+ bin_run_script "$_p" "$(bin_get_preinstall "$_p")" pre
+ msg "Upgrading $_pkgid ..."
+ SPM_ROOT=${APKG_ROOT%/} spm -u "$_pkgpath" || die "Failed to upgrade $_pkgid"
+ bin_run_script "$_p" "$(bin_get_postinstall "$_p")" post
+ done
+}
+
+bin_sysupgrade() {
+ needroot
+ needcachedb
+
+ msg "Checking for outdated packages..."
+ _outdated=$(_apply_mask=1 bin_list_outdated | awk '{print $1}')
+ [ "$_outdated" ] || { msg "No outdated packages."; exit 0; }
+
+ msg "Resolving dependencies..."
+ _skip_installed=""
+ DEPS=""
+ for _name in $_outdated; do
+ printf "%s\n" $DEPS | tr ' ' '\n' | grep -Fxq "$_name" || {
+ _process=""
+ bin_checkdep "$_name"
+ }
+ done
+ _all=$(printf "%s\n" $DEPS | tr ' ' '\n' | grep -v ^$ | sort -u)
+
+ _newpkgs=""
+ _upgradepkgs=""
+ _seen_new=""
+ _seen_up=""
+ for _name in $_all; do
+ if pkg_is_installed "$_name"; then
+ printf "%s\n" $_seen_up | tr ' ' '\n' | grep -Fxq "$_name" && continue
+ _seen_up="$_seen_up $_name"
+ _pkgid=$(bin_get_pkgid "$_name") || continue
+ _installed=$(pkg_installed_ver "$_name")
+ _available=${_pkgid#*#}
+ [ "$_installed" = "$_available" ] && continue
+ _upgradepkgs="$_upgradepkgs $_name"
+ else
+ printf "%s\n" $_seen_new | tr ' ' '\n' | grep -Fxq "$_name" && continue
+ _seen_new="$_seen_new $_name"
+ _newpkgs="$_newpkgs $_name"
+ fi
+ done
+
+ [ "$_newpkgs" ] && msg "Installing new package(s): $_newpkgs"
+ [ "$_upgradepkgs" ] || { msg "All packages up to date."; exit 0; }
+ _ncount=$(printf "%s\n" $_upgradepkgs | wc -l)
+ msg "Upgrading $_ncount package(s): $(printf "%s\n" $_upgradepkgs | tr '\n' ' ')"
+ prompt_user
+
+ if [ "$_newpkgs" ]; then
+ for _name in $_newpkgs; do
+ _pkgid=$(bin_get_pkgid "$_name") || continue
+ _pkgpath=$(bin_download_pkg "$_pkgid") || continue
+ bin_run_script "$_name" "$(bin_get_preinstall "$_name")" pre
+ msg "Installing $_pkgid ..."
+ SPM_ROOT=${APKG_ROOT%/} spm -i "$_pkgpath" || die "Failed to install $_pkgid"
+ bin_run_script "$_name" "$(bin_get_postinstall "$_name")" post
+ done
+ fi
+ for _name in $_upgradepkgs; do
+ _pkgid=$(bin_get_pkgid "$_name") || continue
+ _pkgpath=$(bin_download_pkg "$_pkgid") || continue
+ bin_run_script "$_name" "$(bin_get_preinstall "$_name")" pre
+ msg "Upgrading $_pkgid ..."
+ SPM_ROOT=${APKG_ROOT%/} spm -u "$_pkgpath" || die "Failed to upgrade $_pkgid"
+ bin_run_script "$_name" "$(bin_get_postinstall "$_name")" post
+ done
+
+ msg "System upgrade complete."
+}
+
+bin_list_outdated() {
+ needcachedb
+ [ -d "$SPM_PKGDB" ] || return 0
+ for _db in "$SPM_PKGDB"/*; do
+ [ -f "$_db" ] || continue
+ _name=${_db##*/}
+ if [ "$APKG_MASK" ] && [ "$_apply_mask" ]; then
+ printf "%s\n" "$APKG_MASK" | tr ' ' '\n' | grep -Fxq "$_name" && continue
+ fi
+ _installed=$(head -n1 "$_db")
+ _line=$(bin_find_pkg "$_name") || continue
+ _namever=$(bin_fetch_field "$_line" 1)
+ _available=${_namever#*#}
+ [ "$_installed" = "$_available" ] || printf "%s\n" "$_name $_installed -> $_available"
+ done
+}
+
+bin_search() {
+ needcachedb
+ _pattern=$1
+ while IFS= read -r _line; do
+ [ "$_line" ] || continue
+ _namever=$(bin_fetch_field "$_line" 1)
+ _name=${_namever%%#*}
+ _display=$(printf "%s\n" "$_namever" | tr '#' ' ')
+ if [ "$_pattern" ]; then
+ printf "%s\n" "$_name" | grep -q "$_pattern" || continue
+ fi
+ if [ "$verbose" ]; then
+ _desc=$(bin_fetch_field "$_line" 7)
+ printf "%s %s\n" "$_display" "$_desc"
+ else
+ printf "%s\n" "$_name"
+ fi
+ done < "$APKGBIN_CACHE_DIR/APKGBINDB"
+}
+
+bin_list_installed() {
+ [ -d "$SPM_PKGDB" ] || return 0
+ for _db in "$SPM_PKGDB"/*; do
+ [ -f "$_db" ] || continue
+ _name=${_db##*/}
+ if [ "$verbose" ]; then
+ _ver=$(head -n1 "$_db")
+ printf "%s %s\n" "$_name" "$_ver"
+ else
+ printf "%s\n" "$_name"
+ fi
+ done
+}
+
+bin_clean() {
+ needcachedb
+ _dldir="$APKGBIN_CACHE_DIR"
+ [ -d "$_dldir" ] || { msg "No downloaded packages to clean."; exit 0; }
+ _count=0
+ for _spm in "$_dldir"/*.spm; do
+ [ -f "$_spm" ] || continue
+ _filename=${_spm##*/}
+ _name=${_filename%%#*}
+ _line=$(bin_find_pkg "$_name" 2>/dev/null)
+ [ "$_line" ] || continue
+ _expected=$(bin_fetch_field "$_line" 3)
+ [ "$_expected" ] || continue
+ _actual=$(sha3sum "$_spm" | awk '{print $1}')
+ if [ "$_actual" != "$_expected" ]; then
+ msg "Removing $_filename (sha3sum mismatch)"
+ rm -f "$_spm"
+ _count=$((_count + 1))
+ fi
+ done
+ msg "Removed $_count package(s) with sha3sum mismatch."
+}
+
+bin_show_deps() {
+ needcachedb
+ [ "$1" ] || die "No package specified"
+ _deps=$(bin_get_deps "$1")
+ [ "$_deps" ] && printf "%s\n" $_deps
+}
+
+bin_show_deptree() {
+ needcachedb
+ [ "$1" ] || die "No package specified"
+ [ "$(bin_find_pkg "$1")" ] || exit 0
+ _deps=$(bin_deplist "$1")
+ printf "%s\n" "$_deps" | grep -Fxq "$1" || _deps="$_deps
+$1"
+ printf "%s\n" "$_deps" | grep -v ^$
+}
+
+bin_help() {
+ cat << 'EOF'
+usage: apkg-bin <option> [arg(s)]
+
+options:
+ -g generate APKGBINDB from APKG_PACKAGE_DIR and APKG_REPO
+ -S sync APKGBINDB from APKGBIN_REPO
+ -s [pattern] search available binary packages (optional filter)
+ -i <pkg(s)> install package(s) without dependency resolution
+ -I <pkg(s)> install package(s) with dependency resolution
+ -u <pkg(s)> upgrade package(s)
+ -U full system upgrade (all outdated packages)
+ -o <pkg(s)> download package(s) only (no install)
+ -c clean downloaded packages with sha3sum mismatch
+ -d <pkg> show direct dependencies for a package
+ -D <pkg(s)> show full dependency tree for package(s)
+ -l list outdated packages
+ -a list all installed packages
+ -f force re-download of cached packages
+ -v verbose output
+ -h print this help message
+
+environment variables:
+ APKGBIN_REPO binary repo URL or path
+ APKGBIN_CACHE_DIR cache directory (required)
+ APKG_REPO source repo directories (needed for -g)
+ APKG_PACKAGE_DIR package directory (default: $PWD)
+ APKG_ROOT alternative install root
+ APKG_MASK packages to skip during -U (system upgrade)
+ APKG_ALIAS dependency substitution (real:alias pairs)
+ APKG_NOPROMPT skip confirmation prompts
+EOF
+}
+
+_filter_flags() {
+ _args=""
+ for _a in "$@"; do
+ case $_a in
+ -f) force=1 ;;
+ -v) verbose=1 ;;
+ *) _args="$_args $_a" ;;
+ esac
+ done
+}
+
+parseopts() {
+ while [ "$1" ]; do
+ case $1 in
+ -g) bin_generate; exit 0;;
+ -S) bin_sync; exit 0;;
+ -s) _do_search=1; if [ "$2" ] && [ "${2#-}" = "$2" ]; then search_pattern="$2"; shift; fi;;
+ -i) shift; _filter_flags "$@"; bin_install 0 $_args; exit 0;;
+ -I) shift; _filter_flags "$@"; bin_install 1 $_args; exit 0;;
+ -u) shift; _filter_flags "$@"; bin_upgrade $_args; exit 0;;
+ -U) bin_sysupgrade; exit 0;;
+ -o) shift; _filter_flags "$@"; needcachedb; for _p in $_args; do _pkgid=$(bin_get_pkgid "$_p") || die "Package '$_p' not found in APKGBINDB"; bin_download_pkg "$_pkgid"; done; exit 0;;
+ -c) bin_clean; exit 0;;
+ -d) bin_show_deps "$2"; exit 0;;
+ -D) shift; _filter_flags "$@"; needcachedb; _valid=""; for _p in $_args; do [ "$(bin_find_pkg "$_p")" ] && _valid="$_valid $_p"; done; [ "$_valid" ] || exit 0; _out=$(bin_deplist $_valid); for _p in $_valid; do printf "%s\n" "$_out" | grep -Fxq "$_p" || _out="$_out
+$_p"; done; printf "%s\n" "$_out" | grep -v ^$; exit 0;;
+ -l) bin_list_outdated; exit 0;;
+ -a) bin_list_installed; exit 0;;
+ -f) force=1;;
+ -v) verbose=1;;
+ -h) bin_help; exit 0;;
+ -*) die "invalid option '$1'";;
+ *) pkg="$pkg $1";;
+ esac
+ shift
+ done
+}
+
+main() {
+ parseopts "$@"
+
+ if [ "$_do_search" ]; then
+ bin_search "$search_pattern"
+ exit 0
+ fi
+
+ bin_help
+ exit 0
+}
+
+umask 022
+
+SPM_PKGDB="${APKG_ROOT%/}/var/lib/spm/db"
+APKG_PACKAGE_DIR="${APKG_PACKAGE_DIR:-$PWD}"
+[ "$APKGBIN_CACHE_DIR" ] || die "APKGBIN_CACHE_DIR is not set"
+
+main "$@"
+
+exit 0