--:Minify:-- syscall.open("/dev/tty/TTY1","r") --stdin (fd 0) syscall.open("/dev/tty/TTY1","w") --stdout (fd 1) syscall.open("/dev/null","w") --stderr (fd 2) local fs = require("sys.fs") local MAX_ATTEMPTS = 3 local function readLine(mask) local input = "" while true do local ch = syscall.read(0) if not ch or ch == "" then -- buffer empty, spin elseif ch == "\n" then syscall.write(1, "\n") return input elseif ch == "\b" then if #input > 0 then input = input:sub(1, -2) syscall.write(1, "\b \b") end else input = input .. ch syscall.write(1, mask or ch) end end end local function firstBoot() local shadow = fs.readAllText("/etc/shadow") or "" if shadow:match("%S") then return end syscall.devctl(1, "clear") syscall.devctl(1, "spos", 1, 1) syscall.devctl(1, "sfgc", 3) syscall.write(1, "HyperionOS First Boot Setup\n") syscall.devctl(1, "sfgc", 1) syscall.write(1, "No root password is set. Please create one now.\n\n") while true do syscall.write(1, "New root password: ") local pw1 = readLine("*") syscall.write(1, "Confirm password: ") local pw2 = readLine("*") if pw1 ~= pw2 then syscall.devctl(1, "sfgc", 2) syscall.write(1, "Passwords do not match. Try again.\n\n") syscall.devctl(1, "sfgc", 1) elseif #pw1 < 6 then syscall.devctl(1, "sfgc", 2) syscall.write(1, "Password too short (minimum 6 characters).\n\n") syscall.devctl(1, "sfgc", 1) else local ok, err = syscall.auth_setpassword(0, pw1) if ok then syscall.devctl(1, "sfgc", 3) syscall.write(1, "Root password set.\n\n") syscall.devctl(1, "sfgc", 1) sleep(0.5) break else syscall.devctl(1, "sfgc", 2) syscall.write(1, "Error: " .. tostring(err) .. "\n") syscall.devctl(1, "sfgc", 1) end end end end local function spawnShell(username, uid, shell, homedir) local shellText = fs.readAllText(shell) if not shellText then syscall.write(1, "login: shell not found: " .. shell .. "\n") sleep(2) return false end -- Spawn a wrapper that loads and runs the shell, reporting any error back -- via exit code channel so we can display it local errFifo = {} local proc = syscall.spawn(function() syscall.setuid(uid) syscall.chdir(homedir) syscall.setEnviron("HOME", homedir) syscall.setEnviron("USER", username) syscall.setEnviron("SHELL", shell) syscall.setEnviron("PATH", "/bin/") local shellFn, loadErr = load(shellText, "@" .. shell) if not shellFn then -- Report load error via log and a recognizable exit code syscall.log("login: shell load error: " .. tostring(loadErr), "ERROR") syscall.exit(-1) return end local ok, runErr = xpcall(shellFn, debug.traceback) if not ok then syscall.log("login: shell runtime error: " .. tostring(runErr), "ERROR") end end, username .. ":shell") while true do local exited, code = syscall.collect(proc) if exited then if code then syscall.devctl(1, "sfgc", 2) syscall.write(1, "\nShell exited with code: " .. tostring(code) .. "\n") syscall.write(1, "(Check /var/log/syslog.log for details)\n") syscall.devctl(1, "sfgc", 1) sleep(2) end return true end sleep(0.1) end end local function doLogin() syscall.devctl(1, "clear") syscall.devctl(1, "sfgc", 1) syscall.devctl(1, "sbgc", 16) syscall.devctl(1, "spos", 1, 1) local hostname = syscall.getHostname() or "hyperion" syscall.write(1, "HyperionOS\n") syscall.write(1, hostname .. " login\n\n") local attempts = 0 while attempts < MAX_ATTEMPTS do syscall.devctl(1, "sfgc", 1) syscall.write(1, "Username: ") local username = readLine(nil) if username == "" then goto continue end syscall.write(1, "Password: ") local password = readLine("*") local ok, err = syscall.auth_login(username, password) if ok then local uid = syscall.auth_getuid(username) local pwent = uid and syscall.auth_getpasswd(uid) local shell = (pwent and pwent.shell) or "/bin/hysh" local homedir = (pwent and pwent.homedir) or "/" syscall.devctl(1, "sfgc", 3) syscall.write(1, "\nWelcome, " .. username .. "!\n") syscall.devctl(1, "sfgc", 1) sleep(0.3) spawnShell(username, uid, shell, homedir) return -- back to login prompt else attempts = attempts + 1 sleep(1) syscall.devctl(1, "sfgc", 2) syscall.write(1, "Login incorrect.\n\n") syscall.devctl(1, "sfgc", 1) end ::continue:: end syscall.devctl(1, "sfgc", 2) syscall.write(1, "Maximum login attempts exceeded.\n") syscall.devctl(1, "sfgc", 1) sleep(5) end firstBoot() while true do doLogin() end