New build system + hysh functionality

This commit is contained in:
2026-02-21 12:49:57 -06:00
parent 0655f2a39e
commit 3cc1459769
23 changed files with 269 additions and 934 deletions

View File

@@ -1,295 +0,0 @@
--:Minify:--
syscall.open("/dev/tty/TTY1","r") --stdin (Device 0)
syscall.open("/dev/tty/TTY1","w") --stdout (Device 1)
syscall.open("/dev/null","w") --stderr (device 2)
local success, errorMsg = xpcall(function()
local fs = require("sys.fs")
syscall.devctl(1,"clear")
syscall.devctl(1,"sfgc",1)
syscall.devctl(1,"spos",1,1)
print("HyperionOS Bash Shell")
local userhost = (syscall.getUsername() or "Unknown").."@"..(syscall.getHostname() or "Unknown")
local commandHistory = {}
local terminate = false
syscall.setEnviron("SHELL","rtbash")
syscall.setEnviron("PATH","/bin/")
syscall.chdir("/")
local oldWD = ""
for i = 1, 16 do
syscall.devctl(1,"sbgc",i)
printInline(" ");
end
print("\n")
syscall.sigcatch(function(sig)
if sig == 1 then
terminate = true
end
end)
local builtinCmds = {}
builtinCmds.cd = function(path)
local cwd = syscall.getcwd()
local dirIn = (path or "")
if dirIn == "-" then
if oldWD == "" then
print("bash-cd: No previous working directory set.")
else
print(oldWD)
syscall.chdir(oldWD)
oldWD = cwd
end
return
end
local dirInMod = dirIn
if dirIn:sub(1, 1) ~= "/" then dirInMod = cwd .. "/" .. dirIn end
local parts = {}
for part in dirInMod:gmatch("[^/]+") do
if part == ".." then
if #parts > 0 then table.remove(parts) end
elseif part ~= "." and part ~= "" then
table.insert(parts, part)
end
end
local normDir = "/" .. table.concat(parts, "/")
if normDir:sub(#normDir, #normDir) ~= "/" then normDir = normDir .. "/" end
if not fs.isDir(normDir) then
print("bash-cd: "..dirIn..": No such directory.")
return
end
oldWD = cwd
syscall.chdir(normDir)
end
local function getUserInput()
syscall.devctl(1,"sfgc",3)
printInline(userhost)
syscall.devctl(1,"sfgc",1)
printInline(":")
syscall.devctl(1,"sfgc",10)
printInline(syscall.getcwd())
syscall.devctl(1,"sfgc",1)
printInline("$ ")
local curOffsetStr = syscall.devctl(1, "gpos")
local curOffsetX = tonumber(curOffsetStr:sub(1, curOffsetStr:find(";")-1))
local curOffsetY = tonumber(curOffsetStr:sub(curOffsetStr:find(";")+1))
local input = ""
local blinkState = false
local cursorPos = 1
local history = 0
while true do
local key=syscall.read(0)
if key then
if key == "\19" then --TODO: REPLACE WITH LEFT ARROW
if cursorPos > 1 then
cursorPos = cursorPos - 1
end
elseif key == "\20" then --TODO: REPLACE WITH RIGHT ARROW
if cursorPos <= #input then
cursorPos = cursorPos + 1
end
elseif key == "\17" then --TODO: REPLACE WITH UP ARROW
if history < #commandHistory then
syscall.devctl(1,"spos",curOffsetX,curOffsetY)
printInline((" "):rep(#input + 1))
history = history + 1
input = commandHistory[#commandHistory - history + 1]
cursorPos = #input + 1
end
elseif key == "\18" then --TODO: REPLACE WITH DOWN ARROW
if history > 1 then
syscall.devctl(1,"spos",curOffsetX,curOffsetY)
printInline((" "):rep(#input + 1))
history = history - 1
input = commandHistory[#commandHistory - history + 1]
cursorPos = #input + 1
elseif history == 1 then
syscall.devctl(1,"spos",curOffsetX,curOffsetY)
printInline((" "):rep(#input + 1))
history = 0
input = ""
cursorPos = 1
end
elseif key == "\b" then
if cursorPos > 1 then
syscall.devctl(1,"spos",curOffsetX,curOffsetY)
printInline((" "):rep(#input + 1))
input = string.sub(input, 1, cursorPos-2)..string.sub(input, cursorPos)
cursorPos = cursorPos - 1
end
elseif key == "\n" then
syscall.devctl(1,"spos",curOffsetX,curOffsetY)
print(input.." ")
return input
else
input = string.sub(input, 1, cursorPos-1)..key..string.sub(input, cursorPos)
cursorPos = cursorPos + 1
end
local screenSizeStr = syscall.devctl(1, "size")
local sizeX = tonumber(screenSizeStr:sub(1, screenSizeStr:find(";")-1))
local sizeY = tonumber(screenSizeStr:sub(screenSizeStr:find(";")+1))
local totalChars = sizeX * sizeY
local eocCharNum = ((curOffsetY - 1) * sizeX) + curOffsetX + #input
if eocCharNum >= totalChars then
syscall.devctl(1,"spos",sizeX,sizeY)
printInline(" ")
curOffsetY = curOffsetY - 1
end
end
syscall.devctl(1,"spos",curOffsetX,curOffsetY)
printInline(string.sub(input, 1, cursorPos-1))
if blinkState then
syscall.devctl(1,"sfgc",16)
syscall.devctl(1,"sbgc",1)
end
if cursorPos > #input then
printInline(" ")
else
printInline(string.sub(input, cursorPos, cursorPos))
end
syscall.devctl(1,"sfgc",1)
syscall.devctl(1,"sbgc",16)
printInline(string.sub(input, cursorPos+1))
if cursorPos <= #input then
printInline(" ")
end
local curBlink = ((math.floor(syscall.getUptime() / 500) % 2) == 0)
if curBlink ~= blinkState then
blinkState = curBlink
end
end
end
local function runCommand(command)
do
local func = load("return " .. command, "@equation", "t", {})
if func then
local success, result = pcall(func)
if success and type(result) == "number" then
print(result)
return
end
end
end
terminate = false
local args = string.split(command, " ")
if builtinCmds[args[1]] then
local success, msg = pcall(builtinCmds[args[1]], table.unpack(args, 2))
if not success then
local errSL = string.sub(msg, string.find(msg, "]") + 2)
syscall.devctl(1,"sfgc",2)
printInline(args[1]..": Program runtime error on line ")
print(string.sub(errSL, 1, string.find(errSL, ":") - 1))
syscall.devctl(1,"sfgc",1)
print(string.sub(errSL, string.find(errSL, ":") + 1))
end
return
end
local cmdPath = ""
if string.find(args[1], "/") then
if fs.exists(args[1]) then
cmdPath = args[1]
end
else
local paths = string.split(syscall.getEnviron("PATH"), ":")
for _, path in pairs(paths) do
if fs.exists(path..args[1]) then
cmdPath = path..args[1]
break
end
end
end
if cmdPath == "" then
print(args[1]..": Command not found")
return
end
local progName = string.sub(cmdPath, #cmdPath - string.find(string.reverse(cmdPath), "/") + 2)
local text = fs.readAllText(cmdPath)
local program, err = load(text, progName)
if not program then
local errSL = string.sub(err, string.find(err, ":") + 1)
syscall.devctl(1,"sfgc",2)
printInline(progName..": Program load error on line ")
print(string.sub(errSL, 1, string.find(errSL, ":") - 1))
syscall.devctl(1,"sfgc",1)
print(string.sub(errSL, string.find(errSL, ":") + 1))
return
end
local proc = syscall.spawn(function(...)
syscall.open("/dev/tty/TTY1","r")
syscall.open("/dev/tty/TTY1","w")
syscall.open("/dev/null","w")
local success, msg = pcall(program, ...)
if not success then
local errSL = string.sub(msg, string.find(msg, ":") + 1)
syscall.devctl(1,"sfgc",2)
printInline(progName..": Program runtime error on line ")
print(string.sub(errSL, 1, string.find(errSL, ":") - 1))
syscall.devctl(1,"sfgc",1)
print(string.sub(errSL, string.find(errSL, ":") + 1))
end
end, progName, nil, {table.unpack(args, 2)})
while true do
local exited, code = syscall.collect(proc)
if exited then
if code then
print("\nTask exited with code:\n"..tostring(code))
end
return
end
if terminate then
local success, err = syscall.kill(proc)
if success then
syscall.devctl(1,"sbgc",16)
syscall.devctl(1,"sfgc",2)
print("\nProgram Terminated.")
syscall.devctl(1,"sfgc",1)
end
terminate = false
break
end
sleep(0.05)
end
end
while true do
local command = getUserInput()
if command ~= "" then
if command ~= commandHistory[#commandHistory] then
table.insert(commandHistory, command)
end
runCommand(command)
end
end
--ERROR HANDLING
end, debug.traceback)
if not success then
syscall.log("Error running shell: "..errorMsg, "ERROR")
syscall.devctl(1,"sfgc",2)
syscall.devctl(1,"sbgc",16)
print()
print("Error running shell: ")
print(errorMsg)
end

View File

@@ -1,94 +0,0 @@
--:Minify:--
syscall.open("/dev/tty/TTY1","r")
syscall.open("/dev/tty/TTY1","w")
syscall.open("/dev/null","r")
syscall.devctl(1,"clear")
syscall.devctl(1,"sfgc",1)
syscall.devctl(1,"spos",1,1)
print("HyperionOS Bash Shell")
local str=""
local stopInput=false
local proc=0
local fs=require("sys.fs")
local timeout=false
syscall.setEnviron("SHELL","simpleshell")
printInline("> ")
syscall.sigcatch(function(sig)
if sig==1 then
syscall.kill(proc)
print("Terminated")
printInline("> ")
stopInput=false
end
end)
while true do
if not stopInput then
local input=syscall.read(0)
if input then
if input=="\b" then
if #str>0 then
str=str:sub(1,#str-1)
printInline("\b")
end
elseif input=="\n" then
print("")
stopInput=true
if str == "" then
printInline("> ")
stopInput=false
else
local path=nil
local split=string.split(str, " ")
if fs.exists("/bin/"..split[1]) then
path="/bin/"..split[1]
elseif fs.exists("/bin/"..split[1]..".lua") then
path="/bin/"..split[1]..".lua"
end
if not path then
print("Program not found")
printInline("> ")
stopInput=false
else
local text = fs.readAllText(path)
local program, err = load(text, path)
if not program then
print(err)
printInline("> ")
end
proc = syscall.spawn(function(...)
syscall.open("/dev/tty/TTY1","r")
syscall.open("/dev/tty/TTY1","w")
syscall.open("/dev/null","w")
program(...)
end, path, nil, {table.unpack(split, 2)})
end
str=""
end
else
str=str..input
printInline(input)
end
timeout=false
else
timeout=true
end
else
local exited, code = syscall.collect(proc)
if exited then
if code then
print("\nTask exited with code:\n"..tostring(code))
end
printInline("> ")
stopInput=false
end
timeout=true
end
if timeout then
if stopInput then
sleep(.5)
else
sleep(.05)
end
end
end

View File

@@ -1,7 +1,7 @@
--: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)
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")
@@ -78,21 +78,18 @@ local function spawnShell(username, uid, shell, homedir)
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("HOME", homedir)
syscall.setEnviron("USER", username)
syscall.setEnviron("SHELL", shell)
syscall.setEnviron("PATH", "/bin/")
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
@@ -103,21 +100,7 @@ local function spawnShell(username, uid, shell, homedir)
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
syscall.exit(0)
end
local function doLogin()
@@ -145,7 +128,7 @@ local function doLogin()
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 shell = (pwent and pwent.shell) or "/bin/hysh"
local homedir = (pwent and pwent.homedir) or "/"
syscall.devctl(1, "sfgc", 3)

View File

@@ -1,4 +0,0 @@
local fs = require("sys.fs")
local bashStr = fs.readAllText("/bin/bash")
local bashFun = load(bashStr)
syscall.spawn(bashFun, "bash")

View File

@@ -1,7 +1,7 @@
--:Minify:--
local fs = require("sys.fs")
local targetUser = ({...})[1] or "root"
local targetUser = ({ ... })[1] or "root"
local currentUid = syscall.getuid()
local currentUser = syscall.getUsername(currentUid) or tostring(currentUid)
@@ -26,7 +26,9 @@ else
syscall.write(1, "\n")
break
elseif ch == "\b" then
if #pw > 0 then pw = pw:sub(1, -2); syscall.write(1, "\b \b") end
if #pw > 0 then
pw = pw:sub(1, -2); syscall.write(1, "\b \b")
end
else
pw = pw .. ch
syscall.write(1, "*")
@@ -46,13 +48,13 @@ if currentUid == 0 then
syscall.setuid(targetUid)
end
local pwent = syscall.auth_getpasswd(targetUid)
local shell = (pwent and pwent.shell) or "/bin/hysh"
local pwent = syscall.auth_getpasswd(targetUid)
local shell = (pwent and pwent.shell) or "/bin/hysh"
local homedir = (pwent and pwent.homedir) or "/"
syscall.chdir(homedir)
syscall.setEnviron("HOME", homedir)
syscall.setEnviron("USER", targetUser)
syscall.setEnviron("HOME", homedir)
syscall.setEnviron("USER", targetUser)
syscall.setEnviron("SHELL", shell)
local shellText = fs.readAllText(shell)
@@ -63,10 +65,13 @@ if not shellText then
end
local shellFn, loadErr = load(shellText, "@" .. shell)
if not shellFn then
print("su: cannot load shell: " .. tostring(loadErr))
syscall.exit(1)
return
end
shellFn()
syscall.kill(syscall.getppid())
syscall.spawn(shellFn, targetUser .. ":" .. shell, syscall.getEnviron())
syscall.exit(0)