added users (spsf untangled by astronand)
This commit is contained in:
178
Src/Hyperion-bash/bin/login
Normal file
178
Src/Hyperion-bash/bin/login
Normal file
@@ -0,0 +1,178 @@
|
||||
--: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
|
||||
Reference in New Issue
Block a user