Files
terminal_worse/env/termenv
T

223 lines
6.9 KiB
Bash
Executable File

#!/bin/sh
# termenv - independent native plugin environment for Terminal
# This is a POSIX sh environment, not a Linux userland. Packages are
# Terminal-compatible .deb files (scripts or iOS/Darwin arm64 binaries).
ROOT="${TERM_ROOT:-$HOME/Documents/.terminal}"
APPDIR="${APPDIR:-/Applications/Terminal.app}"
PROFILE="$ROOT/etc/profile"
SOURCES="$ROOT/etc/apt/sources.list"
usage() {
printf '%s\n' "Usage: termenv <command>"
printf '%s\n' ""
printf '%s\n' " init Create the independent prefix and the local apt repository"
printf '%s\n' " status Show prefix, PATH, apt/dpkg and installed packages"
printf '%s\n' " enter Print the command that activates the environment"
printf '%s\n' " run <cmd...> Run a command inside the environment"
printf '%s\n' " on Add activation to ~/Documents/.profile"
printf '%s\n' " off Remove activation from ~/Documents/.profile"
printf '%s\n' " selftest init + apt update + install the sample \"hello\" package"
printf '%s\n' " clean Remove apt caches and temporary files"
printf '%s\n' ""
printf '%s\n' "Environment:"
printf '%s\n' " TERM_ROOT=~/Documents/.terminal"
printf '%s\n' " PREFIX=$TERM_ROOT"
}
ensure_dirs() {
mkdir -p "$ROOT/bin" "$ROOT/sbin" "$ROOT/lib" "$ROOT/include" \
"$ROOT/share/man" "$ROOT/etc/apt" \
"$ROOT/var/lib/dpkg/info" "$ROOT/var/lib/apt/lists" \
"$ROOT/var/cache/apt/archives" "$ROOT/var/log" \
"$ROOT/tmp" "$ROOT/repo/pool" "$ROOT/home"
[ -f "$ROOT/var/lib/dpkg/status" ] || : > "$ROOT/var/lib/dpkg/status"
}
write_profile() {
if [ ! -f "$PROFILE" ]; then
cat > "$PROFILE" <<EOF
# Terminal plugin environment (generated by termenv init)
TERM_ROOT="\$HOME/Documents/.terminal"
export TERM_ROOT
PREFIX="\$TERM_ROOT"
export PREFIX
TERM_PLUGIN_ENV=1
export TERM_PLUGIN_ENV
PATH="\$TERM_ROOT/bin:\$TERM_ROOT/sbin:\$TERM_ROOT/usr/bin:\$PATH"
export PATH
LD_LIBRARY_PATH="\$TERM_ROOT/lib:\$TERM_ROOT/usr/lib:\$LD_LIBRARY_PATH"
export LD_LIBRARY_PATH
CPATH="\$TERM_ROOT/include:\$CPATH"
export CPATH
LIBRARY_PATH="\$TERM_ROOT/lib:\$TERM_ROOT/usr/lib:\$LIBRARY_PATH"
export LIBRARY_PATH
PKG_CONFIG_PATH="\$TERM_ROOT/lib/pkgconfig:\$PKG_CONFIG_PATH"
export PKG_CONFIG_PATH
MANPATH="\$TERM_ROOT/share/man:\$MANPATH"
export MANPATH
EOF
fi
}
write_sources() {
LOCAL_LINE="deb [trusted=yes] file://$ROOT/repo ./"
PROCURUS_LINE="deb [trusted=yes] https://repo.procurs.us/ ./"
HAVOC_LINE="deb [trusted=yes] https://repo.havoc.app/ ./"
if [ ! -f "$SOURCES" ]; then
{
printf '%s\n' "$LOCAL_LINE"
printf '%s\n' "$PROCURUS_LINE"
printf '%s\n' "$HAVOC_LINE"
} > "$SOURCES"
return
fi
TMP="$ROOT/tmp/sources.$$"
awk -v desired="$LOCAL_LINE" '
/^deb .*file:\/\/.*\/\.terminal\/repo/ { print desired; found=1; next }
{ print }
END { if (!found) print desired }
' "$SOURCES" > "$TMP"
mv "$TMP" "$SOURCES"
if ! grep -qF "https://repo.procurs.us/" "$SOURCES"; then
printf '%s\n' "$PROCURUS_LINE" >> "$SOURCES"
fi
if ! grep -qF "https://repo.havoc.app/" "$SOURCES"; then
printf '%s\n' "$HAVOC_LINE" >> "$SOURCES"
fi
}
make_sample() {
if grep -q '^Package: hello$' "$ROOT/repo/Packages" 2>/dev/null; then
return 0
fi
SAMPLE="$ROOT/share/termenv/samples/hello"
mkdir -p "$SAMPLE/bin"
cat > "$SAMPLE/bin/hello" << 'EOF'
#!/bin/sh
echo "Hello from the Terminal plugin environment."
echo "PREFIX=$PREFIX"
echo "TERM_ROOT=$TERM_ROOT"
if [ -d "$HOME/Documents/_sandbox" ]; then
echo "Sandbox escape: available (see $HOME/Documents/_sandbox)"
fi
EOF
chmod +x "$SAMPLE/bin/hello"
if [ -f "$APPDIR/bin/mkdeb" ]; then
sh "$APPDIR/bin/mkdeb" hello 1.0.0 "$SAMPLE" iphoneos-arm64
echo "termenv: mkdeb exit=$?"
fi
}
do_init() {
echo "termenv: creating directories..."
ensure_dirs
echo "termenv: writing profile/sources..."
write_profile
write_sources
[ -f "$ROOT/repo/Packages" ] || : > "$ROOT/repo/Packages"
echo "termenv: creating sample package..."
make_sample
echo "termenv: sample ready"
echo "Prefix: $ROOT"
echo "Profile: $PROFILE"
echo "Run: source \"$PROFILE\" (or: termenv on)"
}
do_status() {
ensure_dirs
echo "Terminal native plugin environment"
echo " prefix: $ROOT"
echo " profile: $PROFILE"
echo " apt: $APPDIR/bin/apt"
echo " dpkg: $APPDIR/bin/dpkg"
echo " sources: $SOURCES"
if [ -f "$SOURCES" ]; then
sed 's/^/ /' "$SOURCES"
fi
echo " packages:"
if [ -s "$ROOT/var/lib/dpkg/status" ]; then
awk '/^Package: /{printf " %s", substr($0,10)} /^Version: /{printf " %s", substr($0,10)} /^Status: /{status=substr($0,9)} /^$/{if(status ~ /installed/) print ""}' "$ROOT/var/lib/dpkg/status"
else
echo " (none)"
fi
echo " sandbox: $HOME/Documents/_sandbox"
}
do_run() {
if [ $# -eq 0 ]; then
echo "usage: termenv run <command...>" >&2
exit 2
fi
if [ -f "$PROFILE" ]; then
. "$PROFILE"
fi
"$@"
}
do_on() {
do_init
PROFILE_FILE="$HOME/Documents/.profile"
MARK_BEGIN="# >>> Terminal plugin environment >>>"
MARK_END="# <<< Terminal plugin environment <<<"
if grep -qF "$MARK_BEGIN" "$PROFILE_FILE" 2>/dev/null; then
echo "Activation already present in $PROFILE_FILE"
return 0
fi
{
echo "$MARK_BEGIN"
echo "source \"\$HOME/Documents/.terminal/etc/profile\""
echo "$MARK_END"
} >> "$PROFILE_FILE"
echo "Activation added to $PROFILE_FILE"
}
do_off() {
PROFILE_FILE="$HOME/Documents/.profile"
if [ ! -f "$PROFILE_FILE" ]; then
echo "No $PROFILE_FILE"
return 0
fi
TMP="$ROOT/tmp/profile.$$"
awk '
/# >>> Terminal plugin environment >>>/ {skip=1; next}
/# <<< Terminal plugin environment <<</ {skip=0; next}
!skip {print}
' "$PROFILE_FILE" > "$TMP"
mv "$TMP" "$PROFILE_FILE"
echo "Activation removed from $PROFILE_FILE"
}
do_clean() {
rm -rf "$ROOT/tmp"/*
rm -f "$ROOT/var/cache/apt/archives/"*.deb
echo "Cleaned caches"
}
do_selftest() {
do_init
. "$PROFILE"
echo "=== apt update ==="
APT_SKIP_REMOTE=1 sh "$APPDIR/bin/apt" update
echo "=== apt install hello ==="
sh "$APPDIR/bin/apt" install hello
echo "=== hello ==="
hello
echo "=== installed packages ==="
sh "$APPDIR/bin/apt" list --installed
echo "=== dpkg -l ==="
sh "$APPDIR/bin/dpkg" -l
}
case "${1:-}" in
init) do_init ;;
status) do_status ;;
enter) echo "source \"$PROFILE\"" ;;
run) shift; do_run "$@" ;;
on) do_on ;;
off) do_off ;;
clean) do_clean ;;
selftest) do_selftest ;;
""|-h|--help|help) usage ;;
*) usage; exit 2 ;;
esac