Drop the tool offering during this initial install
This commit is contained in:
1 parent
08b7460900
commit
c77a7b555b
1 file changed
-319
@@ -1,262 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
# The configurator normally runs under this small PTY proxy so Ctrl-T can work
|
||||
# as a global tools shortcut even while gum owns the terminal in raw mode. The
|
||||
# child configurator keeps stdout on the existing stream (so generated config and
|
||||
# logs behave normally), while stderr and /dev/tty traffic are relayed through the
|
||||
# PTY. Pressing Ctrl-T kills the current configurator screen, opens Tools, then
|
||||
# starts the configurator over at keyboard selection.
|
||||
if [[ -z "${OMARCHY_CONFIGURATOR_INNER:-}" && -z "${OMARCHY_CONFIGURATOR_NO_KEY_PROXY:-}" ]] && { [[ -t 0 ]] || [[ -t 2 ]]; }; then
|
||||
OMARCHY_CONFIGURATOR_PYTHON=$(command -v python3 2>/dev/null || command -v python 2>/dev/null || true)
|
||||
if [[ -n "$OMARCHY_CONFIGURATOR_PYTHON" ]]; then
|
||||
export OMARCHY_CONFIGURATOR_SCRIPT
|
||||
OMARCHY_CONFIGURATOR_SCRIPT=$(readlink -f "${BASH_SOURCE[0]}" 2>/dev/null || printf '%s' "${BASH_SOURCE[0]}")
|
||||
exec "$OMARCHY_CONFIGURATOR_PYTHON" - "$@" <<'PY'
|
||||
import errno
|
||||
import fcntl
|
||||
import os
|
||||
import pty
|
||||
import select
|
||||
import signal
|
||||
import sys
|
||||
import termios
|
||||
import time
|
||||
|
||||
CTRL_T = b"\x14"
|
||||
SCRIPT = os.environ["OMARCHY_CONFIGURATOR_SCRIPT"]
|
||||
ARGS = sys.argv[1:]
|
||||
|
||||
try:
|
||||
tty_fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
|
||||
except OSError:
|
||||
env = os.environ.copy()
|
||||
env["OMARCHY_CONFIGURATOR_INNER"] = "1"
|
||||
os.execvpe("bash", ["bash", SCRIPT] + ARGS, env)
|
||||
|
||||
stdout_fd = os.dup(1)
|
||||
original_tty = termios.tcgetattr(tty_fd)
|
||||
current_master = None
|
||||
current_pgid = None
|
||||
|
||||
|
||||
def restore_tty():
|
||||
try:
|
||||
termios.tcsetattr(tty_fd, termios.TCSADRAIN, original_tty)
|
||||
except termios.error:
|
||||
pass
|
||||
|
||||
|
||||
def write_tty(data):
|
||||
if data:
|
||||
os.write(tty_fd, data)
|
||||
|
||||
|
||||
def copy_window_size(master):
|
||||
try:
|
||||
size = fcntl.ioctl(tty_fd, termios.TIOCGWINSZ, b"\0" * 8)
|
||||
fcntl.ioctl(master, termios.TIOCSWINSZ, size)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
def on_winch(signum, frame):
|
||||
if current_master is not None:
|
||||
copy_window_size(current_master)
|
||||
if current_pgid is not None:
|
||||
try:
|
||||
os.killpg(current_pgid, signal.SIGWINCH)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
def on_termination(signum, frame):
|
||||
if current_pgid is not None:
|
||||
try:
|
||||
os.killpg(current_pgid, signum)
|
||||
except OSError:
|
||||
pass
|
||||
restore_tty()
|
||||
raise SystemExit(128 + signum)
|
||||
|
||||
|
||||
def exit_code(status):
|
||||
if os.WIFEXITED(status):
|
||||
return os.WEXITSTATUS(status)
|
||||
if os.WIFSIGNALED(status):
|
||||
return 128 + os.WTERMSIG(status)
|
||||
return 1
|
||||
|
||||
|
||||
def spawn_child(tools_only=False):
|
||||
global current_master, current_pgid
|
||||
|
||||
pid, master = pty.fork()
|
||||
if pid == 0:
|
||||
os.dup2(stdout_fd, 1)
|
||||
try:
|
||||
os.close(stdout_fd)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
env = os.environ.copy()
|
||||
env["OMARCHY_CONFIGURATOR_INNER"] = "1"
|
||||
env["OMARCHY_CONFIGURATOR_CTRL_T"] = "1"
|
||||
if tools_only:
|
||||
env["OMARCHY_CONFIGURATOR_TOOLS_ONLY"] = "1"
|
||||
else:
|
||||
env.pop("OMARCHY_CONFIGURATOR_TOOLS_ONLY", None)
|
||||
|
||||
os.execvpe("bash", ["bash", SCRIPT] + ARGS, env)
|
||||
|
||||
os.set_blocking(master, False)
|
||||
current_master = master
|
||||
current_pgid = pid
|
||||
copy_window_size(master)
|
||||
return pid, master
|
||||
|
||||
|
||||
def wait_for_child(pid, timeout):
|
||||
deadline = time.time() + timeout
|
||||
while time.time() < deadline:
|
||||
try:
|
||||
done, status = os.waitpid(pid, os.WNOHANG)
|
||||
except ChildProcessError:
|
||||
return 0
|
||||
if done == pid:
|
||||
return exit_code(status)
|
||||
time.sleep(0.05)
|
||||
return None
|
||||
|
||||
|
||||
def terminate_child(pid):
|
||||
for sig, timeout in ((signal.SIGTERM, 0.5), (signal.SIGKILL, 0.2)):
|
||||
try:
|
||||
os.killpg(pid, sig)
|
||||
except ProcessLookupError:
|
||||
return 0
|
||||
except OSError:
|
||||
try:
|
||||
os.kill(pid, sig)
|
||||
except OSError:
|
||||
return 0
|
||||
|
||||
code = wait_for_child(pid, timeout)
|
||||
if code is not None:
|
||||
return code
|
||||
return 130
|
||||
|
||||
|
||||
def drain_master(master):
|
||||
while True:
|
||||
try:
|
||||
data = os.read(master, 4096)
|
||||
except BlockingIOError:
|
||||
return
|
||||
except OSError:
|
||||
return
|
||||
if not data:
|
||||
return
|
||||
write_tty(data)
|
||||
|
||||
|
||||
def relay_child(tools_only=False):
|
||||
global current_master, current_pgid
|
||||
|
||||
pid, master = spawn_child(tools_only)
|
||||
try:
|
||||
while True:
|
||||
try:
|
||||
done, status = os.waitpid(pid, os.WNOHANG)
|
||||
except ChildProcessError:
|
||||
drain_master(master)
|
||||
return 0
|
||||
if done == pid:
|
||||
drain_master(master)
|
||||
return exit_code(status)
|
||||
|
||||
try:
|
||||
readable, _, _ = select.select([tty_fd, master], [], [], 0.1)
|
||||
except InterruptedError:
|
||||
continue
|
||||
|
||||
if tty_fd in readable:
|
||||
try:
|
||||
data = os.read(tty_fd, 1024)
|
||||
except OSError:
|
||||
data = b""
|
||||
if not data:
|
||||
continue
|
||||
|
||||
if not tools_only and CTRL_T in data:
|
||||
before = data.split(CTRL_T, 1)[0]
|
||||
if before:
|
||||
try:
|
||||
os.write(master, before)
|
||||
except OSError:
|
||||
pass
|
||||
terminate_child(pid)
|
||||
drain_master(master)
|
||||
return "tools"
|
||||
|
||||
try:
|
||||
os.write(master, data)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
if master in readable:
|
||||
try:
|
||||
data = os.read(master, 4096)
|
||||
except BlockingIOError:
|
||||
continue
|
||||
except OSError as exc:
|
||||
if exc.errno != errno.EIO:
|
||||
raise
|
||||
data = b""
|
||||
if data:
|
||||
write_tty(data)
|
||||
finally:
|
||||
current_master = None
|
||||
current_pgid = None
|
||||
try:
|
||||
os.close(master)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
signal.signal(signal.SIGWINCH, on_winch)
|
||||
signal.signal(signal.SIGHUP, on_termination)
|
||||
signal.signal(signal.SIGTERM, on_termination)
|
||||
|
||||
# Use raw-ish input so Ctrl-T/Ctrl-C can be intercepted and relayed, but keep
|
||||
# the real terminal's output processing intact. Full raw mode disables ONLCR,
|
||||
# causing gum/logo newlines to stair-step across the screen.
|
||||
tty_attrs = termios.tcgetattr(tty_fd)
|
||||
tty_attrs[0] &= ~(termios.BRKINT | termios.ICRNL | termios.INPCK | termios.ISTRIP | termios.IXON)
|
||||
tty_attrs[2] |= termios.CS8
|
||||
tty_attrs[3] &= ~(termios.ECHO | termios.ICANON | termios.IEXTEN | termios.ISIG)
|
||||
tty_attrs[6][termios.VMIN] = 1
|
||||
tty_attrs[6][termios.VTIME] = 0
|
||||
termios.tcsetattr(tty_fd, termios.TCSADRAIN, tty_attrs)
|
||||
|
||||
try:
|
||||
while True:
|
||||
result = relay_child(tools_only=False)
|
||||
if result == "tools":
|
||||
relay_child(tools_only=True)
|
||||
continue
|
||||
raise SystemExit(result)
|
||||
finally:
|
||||
restore_tty()
|
||||
try:
|
||||
os.close(stdout_fd)
|
||||
os.close(tty_fd)
|
||||
except OSError:
|
||||
pass
|
||||
PY
|
||||
fi
|
||||
fi
|
||||
unset OMARCHY_CONFIGURATOR_PYTHON
|
||||
|
||||
# Minimal live-ISO presentation helpers. Keep these local to the ISO: the
|
||||
# installed Omarchy package owns target setup helpers, while the ISO owns the
|
||||
# installer UI that runs before any target packages exist.
|
||||
@@ -323,20 +66,10 @@ abort() {
|
||||
exit 1
|
||||
}
|
||||
|
||||
tools_hint() {
|
||||
[[ -n "${OMARCHY_CONFIGURATOR_CTRL_T:-}" && -z "${OMARCHY_CONFIGURATOR_TOOLS_ONLY:-}" ]] || return 0
|
||||
|
||||
# Draw the shortcut as a fixed footer instead of in the form body. Keep the
|
||||
# cursor where the active gum widget expects it; do not print a newline from
|
||||
# the bottom row or the VT will scroll.
|
||||
printf "\0337\033[%s;1H\033[2K%s\033[38;5;8mCtrl-T Tools\033[0m\0338" "$TERM_HEIGHT" "$PADDING_LEFT_SPACES"
|
||||
}
|
||||
|
||||
step() {
|
||||
clear_logo
|
||||
echo
|
||||
gum style --padding "0 0 0 $PADDING_LEFT" "$1"
|
||||
tools_hint
|
||||
echo
|
||||
}
|
||||
|
||||
@@ -352,58 +85,6 @@ notice() {
|
||||
echo
|
||||
}
|
||||
|
||||
# Tools menu — recovery-style actions kept off the main install path.
|
||||
# Inlines its own disk picker so Ctrl-T can open it before disk_form is defined
|
||||
# further down in the script.
|
||||
tools_menu() {
|
||||
while true; do
|
||||
step "Tools"
|
||||
local choice
|
||||
choice=$(gum choose --header "Pick a tool" \
|
||||
"Open partition tool" \
|
||||
"Drop to shell" \
|
||||
"Reboot" \
|
||||
"Power off" \
|
||||
"Back to installer") || return 0
|
||||
|
||||
case "$choice" in
|
||||
"Open partition tool")
|
||||
local d disks
|
||||
disks=$(lsblk -dpno NAME,TYPE 2>/dev/null | awk '$2=="disk"{print $1}' | grep -E '/dev/(sd|hd|vd|nvme|mmcblk|xv)' || true)
|
||||
if [[ -z "$disks" ]]; then
|
||||
notice "No suitable disks found" 2
|
||||
continue
|
||||
fi
|
||||
d=$(echo "$disks" | gum choose --header "Select disk") || continue
|
||||
clear
|
||||
cfdisk "$d" || true
|
||||
partprobe "$d" 2>/dev/null || true
|
||||
sync
|
||||
sleep 1
|
||||
;;
|
||||
"Drop to shell")
|
||||
clear
|
||||
echo "Type 'exit' to return to the tools menu."
|
||||
bash --norc || true
|
||||
;;
|
||||
"Reboot")
|
||||
reboot
|
||||
;;
|
||||
"Power off")
|
||||
poweroff
|
||||
;;
|
||||
"Back to installer")
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
if [[ -n "${OMARCHY_CONFIGURATOR_TOOLS_ONLY:-}" ]]; then
|
||||
tools_menu
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# STEP 1: KEYBOARD LAYOUT
|
||||
|
||||
keyboard_form() {
|
||||
|
||||
Reference in new issue
Block a user