--: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