179 lines
5.4 KiB
Bash
179 lines
5.4 KiB
Bash
--: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
|