forked from Hyperion/HyperionOS
balls
This commit is contained in:
46
.vscode/tasks.json
vendored
Executable file
46
.vscode/tasks.json
vendored
Executable file
@@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "Build",
|
||||||
|
"type": "shell",
|
||||||
|
|
||||||
|
"windows": {
|
||||||
|
"command": "powershell",
|
||||||
|
"args": [
|
||||||
|
"-NoProfile",
|
||||||
|
"-ExecutionPolicy",
|
||||||
|
"Bypass",
|
||||||
|
"-Command",
|
||||||
|
"if (Test-Path '${workspaceFolder}\\Build') { Remove-Item -LiteralPath '${workspaceFolder}\\Build' -Recurse -Force -ErrorAction SilentlyContinue }; New-Item -ItemType Directory -Path '${workspaceFolder}\\Build' | Out-Null; Get-ChildItem -Path '${workspaceFolder}\\Test' -Directory | ForEach-Object { $base = $_.FullName; Get-ChildItem -Path $base -File -Recurse | ForEach-Object { $rel = $_.FullName.Substring($base.Length).TrimStart(\"\\\"); $destPath = Join-Path '${workspaceFolder}\\Build' $rel; $destDir = Split-Path $destPath; if (-not (Test-Path $destDir)) { New-Item -ItemType Directory -Path $destDir | Out-Null }; Copy-Item -LiteralPath $_.FullName -Destination $destPath -Force } }"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
"linux": {
|
||||||
|
"command": "bash",
|
||||||
|
"args": [
|
||||||
|
"-c",
|
||||||
|
"[ -d \"${workspaceFolder}/Build\" ] && rm -rf \"${workspaceFolder}/Build\"; mkdir -p \"${workspaceFolder}/Build\"; for d in \"${workspaceFolder}/Test\"/*; do if [ -d \"$d\" ]; then find \"$d\" -type f | while read f; do rel=\"${f#$d/}\"; mkdir -p \"${workspaceFolder}/Build/$(dirname \"$rel\")\"; cp \"$f\" \"${workspaceFolder}/Build/$rel\"; done; fi; done"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
"osx": {
|
||||||
|
"command": "bash",
|
||||||
|
"args": [
|
||||||
|
"-c",
|
||||||
|
"[ -d \"${workspaceFolder}/Build\" ] && rm -rf \"${workspaceFolder}/Build\"; mkdir -p \"${workspaceFolder}/Build\"; for d in \"${workspaceFolder}/Test\"/*; do if [ -d \"$d\" ]; then find \"$d\" -type f | while read f; do rel=\"${f#$d/}\"; mkdir -p \"${workspaceFolder}/Build/$(dirname \"$rel\")\"; cp \"$f\" \"${workspaceFolder}/Build/$rel\"; done; fi; done"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "shared"
|
||||||
|
},
|
||||||
|
"problemMatcher": [],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
local computer = component.getFirst("computer")
|
|
||||||
local screen=component.getFirst("screen")
|
|
||||||
if not screen then
|
|
||||||
local function e(...)end
|
|
||||||
screen = {
|
|
||||||
print=e,
|
|
||||||
printInline=e,
|
|
||||||
clear=e
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
local ok,err = xpcall(function()
|
|
||||||
-- Init components
|
|
||||||
_G._DEVELOPMENT=true
|
|
||||||
_G.component=component
|
|
||||||
|
|
||||||
local printed=""
|
|
||||||
local print=function(text)
|
|
||||||
printed=printed..text.."\n"
|
|
||||||
screen.print(text)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Get CFG
|
|
||||||
local biosCfg = {}
|
|
||||||
local i=1
|
|
||||||
while i<=256 do
|
|
||||||
biosCfg[i]=computer.getData(i) or ""
|
|
||||||
i=i+1
|
|
||||||
end
|
|
||||||
computer.beep(800,0.2)
|
|
||||||
|
|
||||||
local function deepcopy(orig, copies)
|
|
||||||
copies = copies or {}
|
|
||||||
|
|
||||||
if type(orig) ~= 'table' then
|
|
||||||
return orig
|
|
||||||
elseif copies[orig] then
|
|
||||||
return copies[orig]
|
|
||||||
end
|
|
||||||
|
|
||||||
local copy = {}
|
|
||||||
copies[orig] = copy
|
|
||||||
|
|
||||||
for k, v in next, orig, nil do
|
|
||||||
local copied_key = deepcopy(k, copies)
|
|
||||||
local copied_val = deepcopy(v, copies)
|
|
||||||
copy[copied_key] = copied_val
|
|
||||||
end
|
|
||||||
|
|
||||||
return copy
|
|
||||||
end
|
|
||||||
|
|
||||||
local function save(table)
|
|
||||||
while i<=256 do
|
|
||||||
computer.setData(i, table[i] or nil)
|
|
||||||
i=i+1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function hasKey(tabl, query)
|
|
||||||
for i,v in pairs(tabl) do
|
|
||||||
if i==query then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Start boot seq
|
|
||||||
local disks={}
|
|
||||||
for i,v in component.list() do
|
|
||||||
if i=="disk" then
|
|
||||||
disks[v.id]=v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local idx = 1
|
|
||||||
local bootOption=1
|
|
||||||
while true do
|
|
||||||
if biosCfg[idx]=="$EOF" then break end
|
|
||||||
print("Atempting boot option "..tostring(bootOption).." labled \""..biosCfg[idx].."\".")
|
|
||||||
bootOption=bootOption+1
|
|
||||||
local drive={}
|
|
||||||
idx=idx+1
|
|
||||||
if not hasKey(disks,biosCfg[idx]) then
|
|
||||||
print("└─ Drive not found.")
|
|
||||||
print(" ")
|
|
||||||
idx=idx+3
|
|
||||||
goto invalid_boot
|
|
||||||
else
|
|
||||||
drive=disks[biosCfg[idx]]
|
|
||||||
print("├─ Drive found with id of \""..drive.id.."\"")
|
|
||||||
end
|
|
||||||
idx=idx+1
|
|
||||||
local path
|
|
||||||
local code
|
|
||||||
if drive.type=="udd" then
|
|
||||||
print("├─ Drive is Unmanaged, looking for MBR...")
|
|
||||||
sleep(0.02)
|
|
||||||
print("├─ Reading MBR...")
|
|
||||||
local tmp = drive.readBytes(0,512)
|
|
||||||
print("├─ MBR found, compiling bootloader...")
|
|
||||||
code = table.concat(tmp)
|
|
||||||
else
|
|
||||||
if not drive:fileExists(biosCfg[idx]) then
|
|
||||||
print("└─ Path not found.")
|
|
||||||
print(" ")
|
|
||||||
idx=idx+2
|
|
||||||
goto invalid_boot
|
|
||||||
else
|
|
||||||
print("├─ Kernel exists at path \""..biosCfg[idx].."\"")
|
|
||||||
path=biosCfg[idx]
|
|
||||||
end
|
|
||||||
code = drive:open(path).read()
|
|
||||||
end
|
|
||||||
idx=idx+1
|
|
||||||
_VG=deepcopy(_G)
|
|
||||||
print("├─ Created virtual ENV.")
|
|
||||||
local _,func = pcall(load,code,drive.id.." | "..path,nil,_G)
|
|
||||||
if not func then
|
|
||||||
print("└─ Compilation failure.")
|
|
||||||
print(" ")
|
|
||||||
idx=idx+1
|
|
||||||
goto invalid_boot
|
|
||||||
else
|
|
||||||
print("├─ Executing.")
|
|
||||||
end
|
|
||||||
local cmd=biosCfg[idx] or ""
|
|
||||||
idx=idx+1
|
|
||||||
local biosData = {}
|
|
||||||
biosData.bootDrive=drive
|
|
||||||
biosData.term=screen
|
|
||||||
screen.clear()
|
|
||||||
local ok, err = xpcall(func, debug.traceback, biosData, cmd)
|
|
||||||
screen.clear()
|
|
||||||
screen.print(printed)
|
|
||||||
if not ok then
|
|
||||||
print("└─ OS exited with error: "..err)
|
|
||||||
print(" ")
|
|
||||||
else
|
|
||||||
print("└─ OS exited.")
|
|
||||||
print(" ")
|
|
||||||
end
|
|
||||||
screen.print("Press enter to continue...")
|
|
||||||
while true do
|
|
||||||
local event = {computer.getMachineEvent()}
|
|
||||||
if event[1] == "keyTyped" then
|
|
||||||
if event[3] == "\n" then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
sleep(0.02)
|
|
||||||
end
|
|
||||||
::invalid_boot::
|
|
||||||
end
|
|
||||||
computer.beep(400,0.4)
|
|
||||||
print("No boot options available")
|
|
||||||
screen.print("Press enter to continue...")
|
|
||||||
while true do
|
|
||||||
local event = {computer.getMachineEvent()}
|
|
||||||
if event[1] == "keyTyped" then
|
|
||||||
if event[3] == "\n" then
|
|
||||||
computer.shutdown()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
sleep(0.02)
|
|
||||||
end
|
|
||||||
end, debug.traceback)
|
|
||||||
if not ok then
|
|
||||||
screen.clear()
|
|
||||||
screen.print("BIOS PANIC: "..err)
|
|
||||||
computer.beep(800,0.2)
|
|
||||||
sleep(0.02)
|
|
||||||
computer.beep(800,0.2)
|
|
||||||
sleep(0.02)
|
|
||||||
computer.beep(800,0.2)
|
|
||||||
sleep(0.02)
|
|
||||||
screen.print("Press enter to continue...")
|
|
||||||
while true do
|
|
||||||
local event = {computer.getMachineEvent()}
|
|
||||||
if event[1] == "keyTyped" then
|
|
||||||
if event[3] == "\n" then
|
|
||||||
computer.shutdown()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
sleep(0.02)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"disks":[1,2,3,56]
|
|
||||||
}
|
|
||||||
@@ -1,254 +0,0 @@
|
|||||||
HyperionOS
|
|
||||||
disk_1
|
|
||||||
/boot/ac/boot.ac
|
|
||||||
|
|
||||||
HyperionOS Dev
|
|
||||||
disk_2
|
|
||||||
/boot/Hyprkrnl.sys
|
|
||||||
|
|
||||||
$EOF
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
local computer = component.getFirst("computer")
|
|
||||||
local screen=component.getFirst("screen")
|
|
||||||
if not screen then
|
|
||||||
computer.beep(400,0.2)
|
|
||||||
sleep(0.2)
|
|
||||||
computer.beep(400,0.2)
|
|
||||||
while true do
|
|
||||||
computer.shutdown()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local idx = 1
|
|
||||||
local ok, err = xpcall(function()
|
|
||||||
for t, a in component.list() do
|
|
||||||
if t == "disk" then
|
|
||||||
if a:fileExists("boot.lua") then
|
|
||||||
screen.print("Bootable file found on "..a.id.." - reading...")
|
|
||||||
local code = a:open("boot.lua").read()
|
|
||||||
screen.print("Compiling boot.lua...")
|
|
||||||
local f = load(code)
|
|
||||||
if not f then error("bios boot compilation failed") end
|
|
||||||
screen.print("Booting...")
|
|
||||||
---@diagnostic disable-next-line: need-check-nil
|
|
||||||
local ok, err = xpcall(f, debug.traceback)
|
|
||||||
if not ok then screen.print(err); sleep(3) end
|
|
||||||
break
|
|
||||||
else
|
|
||||||
idx = idx+1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end, debug.traceback)
|
|
||||||
if not ok then
|
|
||||||
screen.print("BIOS error: "..err)
|
|
||||||
computer.beep(800,0.2)
|
|
||||||
osleep(0.02)
|
|
||||||
screen.print("Press enter to continue...")
|
|
||||||
while true do
|
|
||||||
local event = {computer.getMachineEvent()}
|
|
||||||
if event[1] == "keyTyped" then
|
|
||||||
if event[3] == "\n" then
|
|
||||||
computer.shutdown()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
sleep(0.02)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
computer.beep(400,0.4)
|
|
||||||
screen.print("No bootable filesystem found!")
|
|
||||||
screen.print("Press enter to continue...")
|
|
||||||
while true do
|
|
||||||
local event = {computer.getMachineEvent()}
|
|
||||||
if event[1] == "keyTyped" then
|
|
||||||
if event[3] == "\n" then
|
|
||||||
computer.shutdown()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
sleep(0.02)
|
|
||||||
end
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"disks":[3,4,8]
|
|
||||||
}
|
|
||||||
@@ -1,249 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,189 +0,0 @@
|
|||||||
local computer = component.getFirst("computer")
|
|
||||||
local screen=component.getFirst("screen")
|
|
||||||
if not screen then
|
|
||||||
local function e(...)end
|
|
||||||
screen = {
|
|
||||||
print=e,
|
|
||||||
printInline=e,
|
|
||||||
clear=e
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
local ok,err = xpcall(function()
|
|
||||||
-- Init components
|
|
||||||
_G._DEVELOPMENT=true
|
|
||||||
_G.component=component
|
|
||||||
|
|
||||||
local printed=""
|
|
||||||
local print=function(text)
|
|
||||||
printed=printed..text.."\n"
|
|
||||||
screen.print(text)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Get CFG
|
|
||||||
local biosCfg = {}
|
|
||||||
local i=1
|
|
||||||
while i<=256 do
|
|
||||||
biosCfg[i]=computer.getData(i) or ""
|
|
||||||
i=i+1
|
|
||||||
end
|
|
||||||
computer.beep(800,0.2)
|
|
||||||
-- Difine functions
|
|
||||||
local function copy(tabl)
|
|
||||||
local out = {}
|
|
||||||
for i,v in pairs(tabl) do
|
|
||||||
local t=type(v)
|
|
||||||
if t=="table" then
|
|
||||||
if i == "_G" then
|
|
||||||
out._G=out
|
|
||||||
else
|
|
||||||
out[i]=copy(v)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
out[i]=v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return out
|
|
||||||
end
|
|
||||||
|
|
||||||
local function save(table)
|
|
||||||
while i<=256 do
|
|
||||||
computer.setData(i, table[i] or nil)
|
|
||||||
i=i+1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function hasKey(tabl, query)
|
|
||||||
for i,v in pairs(tabl) do
|
|
||||||
if i==query then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Start boot seq
|
|
||||||
local disks={}
|
|
||||||
for i,v in component.list() do
|
|
||||||
if i=="disk" then
|
|
||||||
disks[v.id]=v
|
|
||||||
if v.type=="udd" then
|
|
||||||
v:writeBytes(0, "HDS") -- "HDS"
|
|
||||||
local tmp = v:readBytes(0,512) -- Just to make sure it writes the data
|
|
||||||
print(tmp)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local idx = 1
|
|
||||||
local bootOption=1
|
|
||||||
while true do
|
|
||||||
if biosCfg[idx]=="$EOF" then break end
|
|
||||||
print("Atempting boot option "..tostring(bootOption).." labled \""..biosCfg[idx].."\".")
|
|
||||||
bootOption=bootOption+1
|
|
||||||
local drive={}
|
|
||||||
idx=idx+1
|
|
||||||
if not hasKey(disks,biosCfg[idx]) then
|
|
||||||
print("└─ Drive not found.")
|
|
||||||
print(" ")
|
|
||||||
idx=idx+3
|
|
||||||
goto invalid_boot
|
|
||||||
else
|
|
||||||
drive=disks[biosCfg[idx]]
|
|
||||||
print("├─ Drive found with id of \""..drive.id.."\"")
|
|
||||||
end
|
|
||||||
idx=idx+1
|
|
||||||
local path
|
|
||||||
local code
|
|
||||||
if drive.type=="udd" then
|
|
||||||
print("├─ Drive is Unmanaged, looking for MBR...")
|
|
||||||
sleep(0.02)
|
|
||||||
print("├─ Reading MBR...")
|
|
||||||
local tmp = drive.readBytes(0,512)
|
|
||||||
print("├─ MBR found, compiling bootloader...")
|
|
||||||
code = table.concat(tmp)
|
|
||||||
else
|
|
||||||
if not drive:fileExists(biosCfg[idx]) then
|
|
||||||
print("└─ Path not found.")
|
|
||||||
print(" ")
|
|
||||||
idx=idx+2
|
|
||||||
goto invalid_boot
|
|
||||||
else
|
|
||||||
print("├─ Kernel exists at path \""..biosCfg[idx].."\"")
|
|
||||||
path=biosCfg[idx]
|
|
||||||
end
|
|
||||||
code = drive:open(path).read()
|
|
||||||
end
|
|
||||||
idx=idx+1
|
|
||||||
local _VG=copy(_G)
|
|
||||||
print("├─ Created virtual ENV.")
|
|
||||||
local _,func = pcall(load,code,drive.id.." | "..path,nil,_VG)
|
|
||||||
if not func then
|
|
||||||
print("└─ Compilation failure.")
|
|
||||||
print(" ")
|
|
||||||
idx=idx+1
|
|
||||||
goto invalid_boot
|
|
||||||
else
|
|
||||||
print("├─ Executing.")
|
|
||||||
end
|
|
||||||
local cmd=biosCfg[idx] or ""
|
|
||||||
idx=idx+1
|
|
||||||
local biosData = {}
|
|
||||||
biosData.bootDrive=drive
|
|
||||||
biosData.term=screen
|
|
||||||
screen.clear()
|
|
||||||
local ok, err = xpcall(func, debug.traceback, biosData, cmd)
|
|
||||||
screen.clear()
|
|
||||||
screen.print(printed)
|
|
||||||
if not ok then
|
|
||||||
print("└─ OS exited with error: "..err)
|
|
||||||
print(" ")
|
|
||||||
else
|
|
||||||
print("└─ OS exited.")
|
|
||||||
print(" ")
|
|
||||||
end
|
|
||||||
screen.print("Press enter to continue...")
|
|
||||||
while true do
|
|
||||||
local event = {computer.getMachineEvent()}
|
|
||||||
if event[1] == "keyTyped" then
|
|
||||||
if event[3] == "\n" then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
sleep(0.02)
|
|
||||||
end
|
|
||||||
::invalid_boot::
|
|
||||||
end
|
|
||||||
computer.beep(400,0.4)
|
|
||||||
print("No boot options available")
|
|
||||||
screen.print("Press enter to continue...")
|
|
||||||
while true do
|
|
||||||
local event = {computer.getMachineEvent()}
|
|
||||||
if event[1] == "keyTyped" then
|
|
||||||
if event[3] == "\n" then
|
|
||||||
computer.shutdown()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
sleep(0.02)
|
|
||||||
end
|
|
||||||
end, debug.traceback)
|
|
||||||
if not ok then
|
|
||||||
screen.clear()
|
|
||||||
screen.print("BIOS PANIC: "..err)
|
|
||||||
computer.beep(800,0.2)
|
|
||||||
sleep(0.02)
|
|
||||||
computer.beep(800,0.2)
|
|
||||||
sleep(0.02)
|
|
||||||
computer.beep(800,0.2)
|
|
||||||
sleep(0.02)
|
|
||||||
screen.print("Press enter to continue...")
|
|
||||||
while true do
|
|
||||||
local event = {computer.getMachineEvent()}
|
|
||||||
if event[1] == "keyTyped" then
|
|
||||||
if event[3] == "\n" then
|
|
||||||
computer.shutdown()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
sleep(0.02)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"disks":[1,2,3,4,8]
|
|
||||||
}
|
|
||||||
@@ -1,249 +0,0 @@
|
|||||||
HyperionOS
|
|
||||||
disk_3
|
|
||||||
/boot/ac/boot.ac
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
local driverutil={}
|
|
||||||
function driverutil.getFirst(type)
|
|
||||||
if drivers[type] then
|
|
||||||
if drivers[type][1] then
|
|
||||||
return drivers[type][1]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function driverutil.list(type)
|
|
||||||
if not type then
|
|
||||||
local tmp={}
|
|
||||||
for i,v in ipairs(drivers.raw) do
|
|
||||||
tmp[#tmp+1] = {type=v.type, obj=v}
|
|
||||||
end
|
|
||||||
local i=0
|
|
||||||
return function()
|
|
||||||
i=i+1
|
|
||||||
if tmp[i]==nil then return end
|
|
||||||
return tmp[i].type, tmp[i].obj
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local tmp={}
|
|
||||||
for i,v in ipairs(drivers[type]) do
|
|
||||||
tmp[#tmp+1] = {type=v.type, obj=v}
|
|
||||||
end
|
|
||||||
local i=0
|
|
||||||
return function()
|
|
||||||
i=i+1
|
|
||||||
if tmp[i]==nil then return end
|
|
||||||
return tmp[i].type, tmp[i].obj
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function runAsKernel(path, ...)
|
|
||||||
local func, err = load("return {'e'}", path, "t", _G)
|
|
||||||
if not func then return false, "\t"..err end
|
|
||||||
local ret = {xpcall(func, debug.traceback, ...)}
|
|
||||||
if not ret[1] then
|
|
||||||
return false, ret[2]
|
|
||||||
end
|
|
||||||
return true, table.unpack(ret, 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
runAsKernel(e, driverutil)
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"disks":[1,2,3,4,8]
|
|
||||||
}
|
|
||||||
@@ -1,249 +0,0 @@
|
|||||||
HyperionOS
|
|
||||||
disk_3
|
|
||||||
/boot/ac/boot.ac
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
local args={...}
|
|
||||||
if #args>0 then
|
|
||||||
load(args[1])(table.unpack(args, 2))
|
|
||||||
else
|
|
||||||
local sys = require("system")
|
|
||||||
local evhook = sys.addEventHook("keyTyped", function()
|
|
||||||
|
|
||||||
end)
|
|
||||||
local term = sys.getParentTermObject()
|
|
||||||
end
|
|
||||||
@@ -1,783 +0,0 @@
|
|||||||
-- SPDX-FileCopyrightText: 2017 Daniel Ratcliffe
|
|
||||||
--
|
|
||||||
-- SPDX-License-Identifier: LicenseRef-CCPL
|
|
||||||
|
|
||||||
--[[- The shell API provides access to CraftOS's command line interface.
|
|
||||||
It allows you to @{run|start programs}, @{setCompletionFunction|add completion
|
|
||||||
for a program}, and much more.
|
|
||||||
@{shell} is not a "true" API. Instead, it is a standard program, which injects
|
|
||||||
its API into the programs that it launches. This allows for multiple shells to
|
|
||||||
run at the same time, but means that the API is not available in the global
|
|
||||||
environment, and so is unavailable to other @{os.loadAPI|APIs}.
|
|
||||||
## Programs and the program path
|
|
||||||
When you run a command with the shell, either from the prompt or
|
|
||||||
@{shell.run|from Lua code}, the shell API performs several steps to work out
|
|
||||||
which program to run:
|
|
||||||
1. Firstly, the shell attempts to resolve @{shell.aliases|aliases}. This allows
|
|
||||||
us to use multiple names for a single command. For example, the `list`
|
|
||||||
program has two aliases: `ls` and `dir`. When you write `ls /rom`, that's
|
|
||||||
expanded to `list /rom`.
|
|
||||||
2. Next, the shell attempts to find where the program actually is. For this, it
|
|
||||||
uses the @{shell.path|program path}. This is a colon separated list of
|
|
||||||
directories, each of which is checked to see if it contains the program.
|
|
||||||
`list` or `list.lua` doesn't exist in `.` (the current directory), so she
|
|
||||||
shell now looks in `/rom/programs`, where `list.lua` can be found!
|
|
||||||
3. Finally, the shell reads the file and checks if the file starts with a
|
|
||||||
`#!`. This is a [hashbang][], which says that this file shouldn't be treated
|
|
||||||
as Lua, but instead passed to _another_ program, the name of which should
|
|
||||||
follow the `#!`.
|
|
||||||
[hashbang]: https://en.wikipedia.org/wiki/Shebang_(Unix)
|
|
||||||
@module[module] shell
|
|
||||||
]]
|
|
||||||
local make_package = dofile("rom/modules/main/cc/require.lua").make
|
|
||||||
|
|
||||||
local multishell = multishell
|
|
||||||
local parentShell = shell
|
|
||||||
local parentTerm = term.current()
|
|
||||||
|
|
||||||
if multishell then
|
|
||||||
multishell.setTitle(multishell.getCurrent(), "shell")
|
|
||||||
end
|
|
||||||
|
|
||||||
local bExit = false
|
|
||||||
local sDir = parentShell and parentShell.dir() or ""
|
|
||||||
local sPath = parentShell and parentShell.path() or ".:/rom/programs"
|
|
||||||
local tAliases = parentShell and parentShell.aliases() or {}
|
|
||||||
local tCompletionInfo = parentShell and parentShell.getCompletionInfo() or {}
|
|
||||||
local tProgramStack = {}
|
|
||||||
|
|
||||||
local shell = {} --- @export
|
|
||||||
local function createShellEnv(dir)
|
|
||||||
local env = { shell = shell, multishell = multishell }
|
|
||||||
env.require, env.package = make_package(env, dir)
|
|
||||||
return env
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set up a dummy require based on the current shell, for loading some of our internal dependencies.
|
|
||||||
local require
|
|
||||||
do
|
|
||||||
local env = setmetatable(createShellEnv("/rom/programs"), { __index = _ENV })
|
|
||||||
require = env.require
|
|
||||||
end
|
|
||||||
local expect = require("cc.expect").expect
|
|
||||||
local exception = require "cc.internal.exception"
|
|
||||||
|
|
||||||
-- Colours
|
|
||||||
local promptColour, textColour, bgColour
|
|
||||||
if term.isColour() then
|
|
||||||
promptColour = colours.yellow
|
|
||||||
textColour = colours.white
|
|
||||||
bgColour = colours.black
|
|
||||||
else
|
|
||||||
promptColour = colours.white
|
|
||||||
textColour = colours.white
|
|
||||||
bgColour = colours.black
|
|
||||||
end
|
|
||||||
|
|
||||||
local function tokenise(...)
|
|
||||||
local sLine = table.concat({ ... }, " ")
|
|
||||||
local tWords = {}
|
|
||||||
local bQuoted = false
|
|
||||||
for match in string.gmatch(sLine .. "\"", "(.-)\"") do
|
|
||||||
if bQuoted then
|
|
||||||
table.insert(tWords, match)
|
|
||||||
else
|
|
||||||
for m in string.gmatch(match, "[^ \t]+") do
|
|
||||||
table.insert(tWords, m)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
bQuoted = not bQuoted
|
|
||||||
end
|
|
||||||
return tWords
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Execute a program using os.run, unless a shebang is present.
|
|
||||||
-- In that case, execute the program using the interpreter specified in the hashbang.
|
|
||||||
-- This may occur recursively, up to the maximum number of times specified by remainingRecursion
|
|
||||||
-- Returns the same type as os.run, which is a boolean indicating whether the program exited successfully.
|
|
||||||
local function executeProgram(remainingRecursion, path, args)
|
|
||||||
local file, err = fs.open(path, "r")
|
|
||||||
if not file then
|
|
||||||
printError(err)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- First check if the file begins with a #!
|
|
||||||
local contents = file.readLine() or ""
|
|
||||||
|
|
||||||
if contents:sub(1, 2) == "#!" then
|
|
||||||
file.close()
|
|
||||||
|
|
||||||
remainingRecursion = remainingRecursion - 1
|
|
||||||
if remainingRecursion == 0 then
|
|
||||||
printError("Hashbang recursion depth limit reached when loading file: " .. path)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Load the specified hashbang program instead
|
|
||||||
local hashbangArgs = tokenise(contents:sub(3))
|
|
||||||
local originalHashbangPath = table.remove(hashbangArgs, 1)
|
|
||||||
local resolvedHashbangProgram = shell.resolveProgram(originalHashbangPath)
|
|
||||||
if not resolvedHashbangProgram then
|
|
||||||
printError("Hashbang program not found: " .. originalHashbangPath)
|
|
||||||
return false
|
|
||||||
elseif resolvedHashbangProgram == "rom/programs/shell.lua" and #hashbangArgs == 0 then
|
|
||||||
-- If we try to launch the shell then our shebang expands to "shell <program>", which just does a
|
|
||||||
-- shell.run("<program>") again, resulting in an infinite loop. This may still happen (if the user
|
|
||||||
-- has a custom shell), but this reduces the risk.
|
|
||||||
-- It's a little ugly special-casing this, but it's probably worth warning about.
|
|
||||||
printError("Cannot use the shell as a hashbang program")
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Add the path and any arguments to the interpreter's arguments
|
|
||||||
table.insert(hashbangArgs, path)
|
|
||||||
for _, v in ipairs(args) do
|
|
||||||
table.insert(hashbangArgs, v)
|
|
||||||
end
|
|
||||||
|
|
||||||
hashbangArgs[0] = originalHashbangPath
|
|
||||||
return executeProgram(remainingRecursion, resolvedHashbangProgram, hashbangArgs)
|
|
||||||
end
|
|
||||||
|
|
||||||
contents = contents .. "\n" .. (file.readAll() or "")
|
|
||||||
file.close()
|
|
||||||
|
|
||||||
local dir = fs.getDir(path)
|
|
||||||
local env = setmetatable(createShellEnv(dir), { __index = _G })
|
|
||||||
env.arg = args
|
|
||||||
|
|
||||||
local func, err = load(contents, "@/" .. fs.combine(path), nil, env)
|
|
||||||
if not func then
|
|
||||||
-- We had a syntax error. Attempt to run it through our own parser if
|
|
||||||
-- the file is "small enough", otherwise report the original error.
|
|
||||||
if #contents < 1024 * 128 then
|
|
||||||
local parser = require "cc.internal.syntax"
|
|
||||||
if parser.parse_program(contents) then printError(err) end
|
|
||||||
else
|
|
||||||
printError(err)
|
|
||||||
end
|
|
||||||
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
if settings.get("bios.strict_globals", false) then
|
|
||||||
getmetatable(env).__newindex = function(_, name)
|
|
||||||
error("Attempt to create global " .. tostring(name), 2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local ok, err, co = exception.try(func, table.unpack(args, 1, args.n))
|
|
||||||
|
|
||||||
if ok then return true end
|
|
||||||
|
|
||||||
if err and err ~= "" then
|
|
||||||
printError(err)
|
|
||||||
exception.report(err, co)
|
|
||||||
end
|
|
||||||
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Run a program with the supplied arguments.
|
|
||||||
--
|
|
||||||
-- Unlike @{shell.run}, each argument is passed to the program verbatim. While
|
|
||||||
-- `shell.run("echo", "b c")` runs `echo` with `b` and `c`,
|
|
||||||
-- `shell.execute("echo", "b c")` runs `echo` with a single argument `b c`.
|
|
||||||
--
|
|
||||||
-- @tparam string command The program to execute.
|
|
||||||
-- @tparam string ... Arguments to this program.
|
|
||||||
-- @treturn boolean Whether the program exited successfully.
|
|
||||||
-- @since 1.88.0
|
|
||||||
-- @usage Run `paint my-image` from within your program:
|
|
||||||
--
|
|
||||||
-- shell.execute("paint", "my-image")
|
|
||||||
function shell.execute(command, ...)
|
|
||||||
expect(1, command, "string")
|
|
||||||
for i = 1, select('#', ...) do
|
|
||||||
expect(i + 1, select(i, ...), "string")
|
|
||||||
end
|
|
||||||
|
|
||||||
local sPath = shell.resolveProgram(command)
|
|
||||||
if sPath ~= nil then
|
|
||||||
tProgramStack[#tProgramStack + 1] = sPath
|
|
||||||
if multishell then
|
|
||||||
local sTitle = fs.getName(sPath)
|
|
||||||
if sTitle:sub(-4) == ".lua" then
|
|
||||||
sTitle = sTitle:sub(1, -5)
|
|
||||||
end
|
|
||||||
multishell.setTitle(multishell.getCurrent(), sTitle)
|
|
||||||
end
|
|
||||||
|
|
||||||
local result = executeProgram(100, sPath, { [0] = command, ... })
|
|
||||||
|
|
||||||
tProgramStack[#tProgramStack] = nil
|
|
||||||
if multishell then
|
|
||||||
if #tProgramStack > 0 then
|
|
||||||
local sTitle = fs.getName(tProgramStack[#tProgramStack])
|
|
||||||
if sTitle:sub(-4) == ".lua" then
|
|
||||||
sTitle = sTitle:sub(1, -5)
|
|
||||||
end
|
|
||||||
multishell.setTitle(multishell.getCurrent(), sTitle)
|
|
||||||
else
|
|
||||||
multishell.setTitle(multishell.getCurrent(), "shell")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return result
|
|
||||||
else
|
|
||||||
printError("No such program")
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Install shell API
|
|
||||||
|
|
||||||
--- Run a program with the supplied arguments.
|
|
||||||
--
|
|
||||||
-- All arguments are concatenated together and then parsed as a command line. As
|
|
||||||
-- a result, `shell.run("program a b")` is the same as `shell.run("program",
|
|
||||||
-- "a", "b")`.
|
|
||||||
--
|
|
||||||
-- @tparam string ... The program to run and its arguments.
|
|
||||||
-- @treturn boolean Whether the program exited successfully.
|
|
||||||
-- @usage Run `paint my-image` from within your program:
|
|
||||||
--
|
|
||||||
-- shell.run("paint", "my-image")
|
|
||||||
-- @see shell.execute Run a program directly without parsing the arguments.
|
|
||||||
-- @changed 1.80pr1 Programs now get their own environment instead of sharing the same one.
|
|
||||||
-- @changed 1.83.0 `arg` is now added to the environment.
|
|
||||||
function shell.run(...)
|
|
||||||
local tWords = tokenise(...)
|
|
||||||
local sCommand = tWords[1]
|
|
||||||
if sCommand then
|
|
||||||
return shell.execute(sCommand, table.unpack(tWords, 2))
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Exit the current shell.
|
|
||||||
--
|
|
||||||
-- This does _not_ terminate your program, it simply makes the shell terminate
|
|
||||||
-- after your program has finished. If this is the toplevel shell, then the
|
|
||||||
-- computer will be shutdown.
|
|
||||||
function shell.exit()
|
|
||||||
bExit = true
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Return the current working directory. This is what is displayed before the
|
|
||||||
-- `> ` of the shell prompt, and is used by @{shell.resolve} to handle relative
|
|
||||||
-- paths.
|
|
||||||
--
|
|
||||||
-- @treturn string The current working directory.
|
|
||||||
-- @see setDir To change the working directory.
|
|
||||||
function shell.dir()
|
|
||||||
return sDir
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set the current working directory.
|
|
||||||
--
|
|
||||||
-- @tparam string dir The new working directory.
|
|
||||||
-- @throws If the path does not exist or is not a directory.
|
|
||||||
-- @usage Set the working directory to "rom"
|
|
||||||
--
|
|
||||||
-- shell.setDir("rom")
|
|
||||||
function shell.setDir(dir)
|
|
||||||
expect(1, dir, "string")
|
|
||||||
if not fs.isDir(dir) then
|
|
||||||
error("Not a directory", 2)
|
|
||||||
end
|
|
||||||
sDir = fs.combine(dir, "")
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set the path where programs are located.
|
|
||||||
--
|
|
||||||
-- The path is composed of a list of directory names in a string, each separated
|
|
||||||
-- by a colon (`:`). On normal turtles will look in the current directory (`.`),
|
|
||||||
-- `/rom/programs` and `/rom/programs/turtle` folder, making the path
|
|
||||||
-- `.:/rom/programs:/rom/programs/turtle`.
|
|
||||||
--
|
|
||||||
-- @treturn string The current shell's path.
|
|
||||||
-- @see setPath To change the current path.
|
|
||||||
function shell.path()
|
|
||||||
return sPath
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set the @{path|current program path}.
|
|
||||||
--
|
|
||||||
-- Be careful to prefix directories with a `/`. Otherwise they will be searched
|
|
||||||
-- for from the @{shell.dir|current directory}, rather than the computer's root.
|
|
||||||
--
|
|
||||||
-- @tparam string path The new program path.
|
|
||||||
-- @since 1.2
|
|
||||||
function shell.setPath(path)
|
|
||||||
expect(1, path, "string")
|
|
||||||
sPath = path
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Resolve a relative path to an absolute path.
|
|
||||||
--
|
|
||||||
-- The @{fs} and @{io} APIs work using absolute paths, and so we must convert
|
|
||||||
-- any paths relative to the @{dir|current directory} to absolute ones. This
|
|
||||||
-- does nothing when the path starts with `/`.
|
|
||||||
--
|
|
||||||
-- @tparam string path The path to resolve.
|
|
||||||
-- @usage Resolve `startup.lua` when in the `rom` folder.
|
|
||||||
--
|
|
||||||
-- shell.setDir("rom")
|
|
||||||
-- print(shell.resolve("startup.lua"))
|
|
||||||
-- -- => rom/startup.lua
|
|
||||||
function shell.resolve(path)
|
|
||||||
expect(1, path, "string")
|
|
||||||
local sStartChar = string.sub(path, 1, 1)
|
|
||||||
if sStartChar == "/" or sStartChar == "\\" then
|
|
||||||
return fs.combine("", path)
|
|
||||||
else
|
|
||||||
return fs.combine(sDir, path)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function pathWithExtension(_sPath, _sExt)
|
|
||||||
local nLen = #sPath
|
|
||||||
local sEndChar = string.sub(_sPath, nLen, nLen)
|
|
||||||
-- Remove any trailing slashes so we can add an extension to the path safely
|
|
||||||
if sEndChar == "/" or sEndChar == "\\" then
|
|
||||||
_sPath = string.sub(_sPath, 1, nLen - 1)
|
|
||||||
end
|
|
||||||
return _sPath .. "." .. _sExt
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Resolve a program, using the @{path|program path} and list of @{aliases|aliases}.
|
|
||||||
--
|
|
||||||
-- @tparam string command The name of the program
|
|
||||||
-- @treturn string|nil The absolute path to the program, or @{nil} if it could
|
|
||||||
-- not be found.
|
|
||||||
-- @since 1.2
|
|
||||||
-- @usage Locate the `hello` program.
|
|
||||||
--
|
|
||||||
-- shell.resolveProgram("hello")
|
|
||||||
-- -- => rom/programs/fun/hello.lua
|
|
||||||
function shell.resolveProgram(command)
|
|
||||||
expect(1, command, "string")
|
|
||||||
-- Substitute aliases firsts
|
|
||||||
if tAliases[command] ~= nil then
|
|
||||||
command = tAliases[command]
|
|
||||||
end
|
|
||||||
|
|
||||||
-- If the path is a global path, use it directly
|
|
||||||
if command:find("/") or command:find("\\") then
|
|
||||||
local sPath = shell.resolve(command)
|
|
||||||
if fs.exists(sPath) and not fs.isDir(sPath) then
|
|
||||||
return sPath
|
|
||||||
else
|
|
||||||
local sPathLua = pathWithExtension(sPath, "lua")
|
|
||||||
if fs.exists(sPathLua) and not fs.isDir(sPathLua) then
|
|
||||||
return sPathLua
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Otherwise, look on the path variable
|
|
||||||
for sPath in string.gmatch(sPath, "[^:]+") do
|
|
||||||
sPath = fs.combine(shell.resolve(sPath), command)
|
|
||||||
if fs.exists(sPath) and not fs.isDir(sPath) then
|
|
||||||
return sPath
|
|
||||||
else
|
|
||||||
local sPathLua = pathWithExtension(sPath, "lua")
|
|
||||||
if fs.exists(sPathLua) and not fs.isDir(sPathLua) then
|
|
||||||
return sPathLua
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Not found
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Return a list of all programs on the @{shell.path|path}.
|
|
||||||
--
|
|
||||||
-- @tparam[opt] boolean include_hidden Include hidden files. Namely, any which
|
|
||||||
-- start with `.`.
|
|
||||||
-- @treturn { string } A list of available programs.
|
|
||||||
-- @usage textutils.tabulate(shell.programs())
|
|
||||||
-- @since 1.2
|
|
||||||
function shell.programs(include_hidden)
|
|
||||||
expect(1, include_hidden, "boolean", "nil")
|
|
||||||
|
|
||||||
local tItems = {}
|
|
||||||
|
|
||||||
-- Add programs from the path
|
|
||||||
for sPath in string.gmatch(sPath, "[^:]+") do
|
|
||||||
sPath = shell.resolve(sPath)
|
|
||||||
if fs.isDir(sPath) then
|
|
||||||
local tList = fs.list(sPath)
|
|
||||||
for n = 1, #tList do
|
|
||||||
local sFile = tList[n]
|
|
||||||
if not fs.isDir(fs.combine(sPath, sFile)) and
|
|
||||||
(include_hidden or string.sub(sFile, 1, 1) ~= ".") then
|
|
||||||
if #sFile > 4 and sFile:sub(-4) == ".lua" then
|
|
||||||
sFile = sFile:sub(1, -5)
|
|
||||||
end
|
|
||||||
tItems[sFile] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Sort and return
|
|
||||||
local tItemList = {}
|
|
||||||
for sItem in pairs(tItems) do
|
|
||||||
table.insert(tItemList, sItem)
|
|
||||||
end
|
|
||||||
table.sort(tItemList)
|
|
||||||
return tItemList
|
|
||||||
end
|
|
||||||
|
|
||||||
local function completeProgram(sLine)
|
|
||||||
local bIncludeHidden = settings.get("shell.autocomplete_hidden")
|
|
||||||
if #sLine > 0 and (sLine:find("/") or sLine:find("\\")) then
|
|
||||||
-- Add programs from the root
|
|
||||||
return fs.complete(sLine, sDir, {
|
|
||||||
include_files = true,
|
|
||||||
include_dirs = false,
|
|
||||||
include_hidden = bIncludeHidden,
|
|
||||||
})
|
|
||||||
|
|
||||||
else
|
|
||||||
local tResults = {}
|
|
||||||
local tSeen = {}
|
|
||||||
|
|
||||||
-- Add aliases
|
|
||||||
for sAlias in pairs(tAliases) do
|
|
||||||
if #sAlias > #sLine and string.sub(sAlias, 1, #sLine) == sLine then
|
|
||||||
local sResult = string.sub(sAlias, #sLine + 1)
|
|
||||||
if not tSeen[sResult] then
|
|
||||||
table.insert(tResults, sResult)
|
|
||||||
tSeen[sResult] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Add all subdirectories. We don't include files as they will be added in the block below
|
|
||||||
local tDirs = fs.complete(sLine, sDir, {
|
|
||||||
include_files = false,
|
|
||||||
include_dirs = false,
|
|
||||||
include_hidden = bIncludeHidden,
|
|
||||||
})
|
|
||||||
for i = 1, #tDirs do
|
|
||||||
local sResult = tDirs[i]
|
|
||||||
if not tSeen[sResult] then
|
|
||||||
table.insert (tResults, sResult)
|
|
||||||
tSeen [sResult] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Add programs from the path
|
|
||||||
local tPrograms = shell.programs()
|
|
||||||
for n = 1, #tPrograms do
|
|
||||||
local sProgram = tPrograms[n]
|
|
||||||
if #sProgram > #sLine and string.sub(sProgram, 1, #sLine) == sLine then
|
|
||||||
local sResult = string.sub(sProgram, #sLine + 1)
|
|
||||||
if not tSeen[sResult] then
|
|
||||||
table.insert(tResults, sResult)
|
|
||||||
tSeen[sResult] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Sort and return
|
|
||||||
table.sort(tResults)
|
|
||||||
return tResults
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function completeProgramArgument(sProgram, nArgument, sPart, tPreviousParts)
|
|
||||||
local tInfo = tCompletionInfo[sProgram]
|
|
||||||
if tInfo then
|
|
||||||
return tInfo.fnComplete(shell, nArgument, sPart, tPreviousParts)
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Complete a shell command line.
|
|
||||||
--
|
|
||||||
-- This accepts an incomplete command, and completes the program name or
|
|
||||||
-- arguments. For instance, `l` will be completed to `ls`, and `ls ro` will be
|
|
||||||
-- completed to `ls rom/`.
|
|
||||||
--
|
|
||||||
-- Completion handlers for your program may be registered with
|
|
||||||
-- @{shell.setCompletionFunction}.
|
|
||||||
--
|
|
||||||
-- @tparam string sLine The input to complete.
|
|
||||||
-- @treturn { string }|nil The list of possible completions.
|
|
||||||
-- @see _G.read For more information about completion.
|
|
||||||
-- @see shell.completeProgram
|
|
||||||
-- @see shell.setCompletionFunction
|
|
||||||
-- @see shell.getCompletionInfo
|
|
||||||
-- @since 1.74
|
|
||||||
function shell.complete(sLine)
|
|
||||||
expect(1, sLine, "string")
|
|
||||||
if #sLine > 0 then
|
|
||||||
local tWords = tokenise(sLine)
|
|
||||||
local nIndex = #tWords
|
|
||||||
if string.sub(sLine, #sLine, #sLine) == " " then
|
|
||||||
nIndex = nIndex + 1
|
|
||||||
end
|
|
||||||
if nIndex == 1 then
|
|
||||||
local sBit = tWords[1] or ""
|
|
||||||
local sPath = shell.resolveProgram(sBit)
|
|
||||||
if tCompletionInfo[sPath] then
|
|
||||||
return { " " }
|
|
||||||
else
|
|
||||||
local tResults = completeProgram(sBit)
|
|
||||||
for n = 1, #tResults do
|
|
||||||
local sResult = tResults[n]
|
|
||||||
local sPath = shell.resolveProgram(sBit .. sResult)
|
|
||||||
if tCompletionInfo[sPath] then
|
|
||||||
tResults[n] = sResult .. " "
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return tResults
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif nIndex > 1 then
|
|
||||||
local sPath = shell.resolveProgram(tWords[1])
|
|
||||||
local sPart = tWords[nIndex] or ""
|
|
||||||
local tPreviousParts = tWords
|
|
||||||
tPreviousParts[nIndex] = nil
|
|
||||||
return completeProgramArgument(sPath , nIndex - 1, sPart, tPreviousParts)
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Complete the name of a program.
|
|
||||||
--
|
|
||||||
-- @tparam string program The name of a program to complete.
|
|
||||||
-- @treturn { string } A list of possible completions.
|
|
||||||
-- @see cc.shell.completion.program
|
|
||||||
function shell.completeProgram(program)
|
|
||||||
expect(1, program, "string")
|
|
||||||
return completeProgram(program)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set the completion function for a program. When the program is entered on
|
|
||||||
-- the command line, this program will be called to provide auto-complete
|
|
||||||
-- information.
|
|
||||||
--
|
|
||||||
-- The completion function accepts four arguments:
|
|
||||||
--
|
|
||||||
-- 1. The current shell. As completion functions are inherited, this is not
|
|
||||||
-- guaranteed to be the shell you registered this function in.
|
|
||||||
-- 2. The index of the argument currently being completed.
|
|
||||||
-- 3. The current argument. This may be the empty string.
|
|
||||||
-- 4. A list of the previous arguments.
|
|
||||||
--
|
|
||||||
-- For instance, when completing `pastebin put rom/st` our pastebin completion
|
|
||||||
-- function will receive the shell API, an index of 2, `rom/st` as the current
|
|
||||||
-- argument, and a "previous" table of `{ "put" }`. This function may then wish
|
|
||||||
-- to return a table containing `artup.lua`, indicating the entire command
|
|
||||||
-- should be completed to `pastebin put rom/startup.lua`.
|
|
||||||
--
|
|
||||||
-- You completion entries may also be followed by a space, if you wish to
|
|
||||||
-- indicate another argument is expected.
|
|
||||||
--
|
|
||||||
-- @tparam string program The path to the program. This should be an absolute path
|
|
||||||
-- _without_ the leading `/`.
|
|
||||||
-- @tparam function(shell: table, index: number, argument: string, previous: { string }):({ string }|nil) complete
|
|
||||||
-- The completion function.
|
|
||||||
-- @see cc.shell.completion Various utilities to help with writing completion functions.
|
|
||||||
-- @see shell.complete
|
|
||||||
-- @see _G.read For more information about completion.
|
|
||||||
-- @since 1.74
|
|
||||||
function shell.setCompletionFunction(program, complete)
|
|
||||||
expect(1, program, "string")
|
|
||||||
expect(2, complete, "function")
|
|
||||||
tCompletionInfo[program] = {
|
|
||||||
fnComplete = complete,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get a table containing all completion functions.
|
|
||||||
--
|
|
||||||
-- This should only be needed when building custom shells. Use
|
|
||||||
-- @{setCompletionFunction} to add a completion function.
|
|
||||||
--
|
|
||||||
-- @treturn { [string] = { fnComplete = function } } A table mapping the
|
|
||||||
-- absolute path of programs, to their completion functions.
|
|
||||||
function shell.getCompletionInfo()
|
|
||||||
return tCompletionInfo
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns the path to the currently running program.
|
|
||||||
--
|
|
||||||
-- @treturn string The absolute path to the running program.
|
|
||||||
-- @since 1.3
|
|
||||||
function shell.getRunningProgram()
|
|
||||||
if #tProgramStack > 0 then
|
|
||||||
return tProgramStack[#tProgramStack]
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Add an alias for a program.
|
|
||||||
--
|
|
||||||
-- @tparam string command The name of the alias to add.
|
|
||||||
-- @tparam string program The name or path to the program.
|
|
||||||
-- @since 1.2
|
|
||||||
-- @usage Alias `vim` to the `edit` program
|
|
||||||
--
|
|
||||||
-- shell.setAlias("vim", "edit")
|
|
||||||
function shell.setAlias(command, program)
|
|
||||||
expect(1, command, "string")
|
|
||||||
expect(2, program, "string")
|
|
||||||
tAliases[command] = program
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Remove an alias.
|
|
||||||
--
|
|
||||||
-- @tparam string command The alias name to remove.
|
|
||||||
function shell.clearAlias(command)
|
|
||||||
expect(1, command, "string")
|
|
||||||
tAliases[command] = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get the current aliases for this shell.
|
|
||||||
--
|
|
||||||
-- Aliases are used to allow multiple commands to refer to a single program. For
|
|
||||||
-- instance, the `list` program is aliased to `dir` or `ls`. Running `ls`, `dir`
|
|
||||||
-- or `list` in the shell will all run the `list` program.
|
|
||||||
--
|
|
||||||
-- @treturn { [string] = string } A table, where the keys are the names of
|
|
||||||
-- aliases, and the values are the path to the program.
|
|
||||||
-- @see shell.setAlias
|
|
||||||
-- @see shell.resolveProgram This uses aliases when resolving a program name to
|
|
||||||
-- an absolute path.
|
|
||||||
function shell.aliases()
|
|
||||||
-- Copy aliases
|
|
||||||
local tCopy = {}
|
|
||||||
for sAlias, sCommand in pairs(tAliases) do
|
|
||||||
tCopy[sAlias] = sCommand
|
|
||||||
end
|
|
||||||
return tCopy
|
|
||||||
end
|
|
||||||
|
|
||||||
if multishell then
|
|
||||||
--- Open a new @{multishell} tab running a command.
|
|
||||||
--
|
|
||||||
-- This behaves similarly to @{shell.run}, but instead returns the process
|
|
||||||
-- index.
|
|
||||||
--
|
|
||||||
-- This function is only available if the @{multishell} API is.
|
|
||||||
--
|
|
||||||
-- @tparam string ... The command line to run.
|
|
||||||
-- @see shell.run
|
|
||||||
-- @see multishell.launch
|
|
||||||
-- @since 1.6
|
|
||||||
-- @usage Launch the Lua interpreter and switch to it.
|
|
||||||
--
|
|
||||||
-- local id = shell.openTab("lua")
|
|
||||||
-- shell.switchTab(id)
|
|
||||||
function shell.openTab(...)
|
|
||||||
local tWords = tokenise(...)
|
|
||||||
local sCommand = tWords[1]
|
|
||||||
if sCommand then
|
|
||||||
local sPath = shell.resolveProgram(sCommand)
|
|
||||||
if sPath == "rom/programs/shell.lua" then
|
|
||||||
return multishell.launch(createShellEnv("rom/programs"), sPath, table.unpack(tWords, 2))
|
|
||||||
elseif sPath ~= nil then
|
|
||||||
return multishell.launch(createShellEnv("rom/programs"), "rom/programs/shell.lua", sCommand, table.unpack(tWords, 2))
|
|
||||||
else
|
|
||||||
printError("No such program")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Switch to the @{multishell} tab with the given index.
|
|
||||||
--
|
|
||||||
-- @tparam number id The tab to switch to.
|
|
||||||
-- @see multishell.setFocus
|
|
||||||
-- @since 1.6
|
|
||||||
function shell.switchTab(id)
|
|
||||||
expect(1, id, "number")
|
|
||||||
multishell.setFocus(id)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local tArgs = { ... }
|
|
||||||
if #tArgs > 0 then
|
|
||||||
-- "shell x y z"
|
|
||||||
-- Run the program specified on the commandline
|
|
||||||
shell.run(...)
|
|
||||||
|
|
||||||
else
|
|
||||||
local function show_prompt()
|
|
||||||
term.setBackgroundColor(bgColour)
|
|
||||||
term.setTextColour(promptColour)
|
|
||||||
write(shell.dir() .. "> ")
|
|
||||||
term.setTextColour(textColour)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- "shell"
|
|
||||||
-- Print the header
|
|
||||||
term.setBackgroundColor(bgColour)
|
|
||||||
term.setTextColour(promptColour)
|
|
||||||
print(os.version())
|
|
||||||
term.setTextColour(textColour)
|
|
||||||
|
|
||||||
-- Run the startup program
|
|
||||||
if parentShell == nil then
|
|
||||||
shell.run("/rom/startup.lua")
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Read commands and execute them
|
|
||||||
local tCommandHistory = {}
|
|
||||||
while not bExit do
|
|
||||||
term.redirect(parentTerm)
|
|
||||||
if term.setGraphicsMode then term.setGraphicsMode(0) end
|
|
||||||
show_prompt()
|
|
||||||
|
|
||||||
|
|
||||||
local complete
|
|
||||||
if settings.get("shell.autocomplete") then complete = shell.complete end
|
|
||||||
|
|
||||||
local ok, result
|
|
||||||
local co = coroutine.create(read)
|
|
||||||
assert(coroutine.resume(co, nil, tCommandHistory, complete))
|
|
||||||
|
|
||||||
while coroutine.status(co) ~= "dead" do
|
|
||||||
local event = table.pack(os.pullEvent())
|
|
||||||
if event[1] == "file_transfer" then
|
|
||||||
-- Abandon the current prompt
|
|
||||||
local _, h = term.getSize()
|
|
||||||
local _, y = term.getCursorPos()
|
|
||||||
if y == h then
|
|
||||||
term.scroll(1)
|
|
||||||
term.setCursorPos(1, y)
|
|
||||||
else
|
|
||||||
term.setCursorPos(1, y + 1)
|
|
||||||
end
|
|
||||||
term.setCursorBlink(false)
|
|
||||||
|
|
||||||
-- Run the import script with the provided files
|
|
||||||
local ok, err = require("cc.internal.import")(event[2].getFiles())
|
|
||||||
if not ok and err then printError(err) end
|
|
||||||
|
|
||||||
-- And attempt to restore the prompt.
|
|
||||||
show_prompt()
|
|
||||||
term.setCursorBlink(true)
|
|
||||||
event = { "term_resize", n = 1 } -- Nasty hack to force read() to redraw.
|
|
||||||
end
|
|
||||||
|
|
||||||
if result == nil or event[1] == result or event[1] == "terminate" then
|
|
||||||
ok, result = coroutine.resume(co, table.unpack(event, 1, event.n))
|
|
||||||
if not ok then error(result, 0) end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if result:match("%S") and tCommandHistory[#tCommandHistory] ~= result then
|
|
||||||
table.insert(tCommandHistory, result)
|
|
||||||
end
|
|
||||||
shell.run(result)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
local args = {...}
|
|
||||||
local apis = args[2]
|
|
||||||
local term = args[4]
|
|
||||||
local getfile = args[5]
|
|
||||||
local computer = args[7]
|
|
||||||
local timeout = computer.time() + 5000
|
|
||||||
|
|
||||||
term.print("HBoot V1.0.0 //\n")
|
|
||||||
local w, h = term.getSize()
|
|
||||||
|
|
||||||
local kernel = load(getfile("/boot/Hyprkrnl.sys").readAllText())
|
|
||||||
local recovery = load(getfile("/boot/util/shell").readAllText())
|
|
||||||
|
|
||||||
-- Predeclare dbg so entries can reference it
|
|
||||||
local dbg = {}
|
|
||||||
local entries = {
|
|
||||||
{"HyperionOS", function() kernel(args, nil, "/sbin/init") end},
|
|
||||||
{"HyperionOS (Debug options)", dbg}
|
|
||||||
}
|
|
||||||
|
|
||||||
dbg[1] = {"Back", "BACK"}
|
|
||||||
dbg[2] = {"Boot HyperionOS in debug mode", function() kernel(args, true) end}
|
|
||||||
dbg[3] = {"Boot as shell", function() kernel(args, true, "/bin/bash") end}
|
|
||||||
dbg[4] = {"Boot in recovery", function() recovery(args) end}
|
|
||||||
|
|
||||||
local function render(tbl, selected)
|
|
||||||
term.clear()
|
|
||||||
term.print("HBoot V1.0.0 //\n\n")
|
|
||||||
for i, v in ipairs(tbl) do
|
|
||||||
if selected == i then
|
|
||||||
term.print("> " .. v[1] .. "\n")
|
|
||||||
else
|
|
||||||
term.print(" " .. v[1] .. "\n")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Initial render
|
|
||||||
render(entries, 1)
|
|
||||||
|
|
||||||
-- Wait for keypress or timeout
|
|
||||||
local exit = false
|
|
||||||
while not exit do
|
|
||||||
local ret = {computer.getMachineEvent()}
|
|
||||||
if ret[1] == "keyPressed" then
|
|
||||||
timeout = math.huge
|
|
||||||
break
|
|
||||||
end
|
|
||||||
if timeout <= computer.time() then
|
|
||||||
exit = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Menu handling
|
|
||||||
if not exit then
|
|
||||||
local menuStack = {}
|
|
||||||
local currentMenu = entries
|
|
||||||
local selected = 1
|
|
||||||
render(currentMenu, selected)
|
|
||||||
|
|
||||||
while true do
|
|
||||||
local ret = {computer.getMachineEvent()}
|
|
||||||
if ret[1] == "keyTyped" then
|
|
||||||
if ret[3] == "\n" then
|
|
||||||
local entry = currentMenu[selected]
|
|
||||||
if entry then
|
|
||||||
if type(entry[2]) == "function" then
|
|
||||||
entry[2]()
|
|
||||||
elseif type(entry[2]) == "table" then
|
|
||||||
table.insert(menuStack, {currentMenu, selected})
|
|
||||||
currentMenu = entry[2]
|
|
||||||
selected = 1
|
|
||||||
render(currentMenu, selected)
|
|
||||||
elseif entry[2] == "BACK" then
|
|
||||||
if #menuStack > 0 then
|
|
||||||
local prev = table.remove(menuStack)
|
|
||||||
currentMenu, selected = prev[1], prev[2]
|
|
||||||
render(currentMenu, selected)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elseif ret[3] == "\x1b[A" then -- Up arrow
|
|
||||||
if selected > 1 then
|
|
||||||
selected = selected - 1
|
|
||||||
render(currentMenu, selected)
|
|
||||||
end
|
|
||||||
elseif ret[3] == "\x1b[B" then -- Down arrow
|
|
||||||
if selected < #currentMenu then
|
|
||||||
selected = selected + 1
|
|
||||||
render(currentMenu, selected)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
kernel(args)
|
|
||||||
end
|
|
||||||
@@ -1,230 +0,0 @@
|
|||||||
local args={...}
|
|
||||||
local bootLoader=args[1]
|
|
||||||
local MODE=bootLoader[1]
|
|
||||||
local apis=bootLoader[2]
|
|
||||||
local bootDisk=bootLoader[3]
|
|
||||||
local term=bootLoader[4]
|
|
||||||
local getFile=bootLoader[5]
|
|
||||||
local bootData
|
|
||||||
do
|
|
||||||
local tmp=load("return "..(getFile("/var/log/kernel/bootData").readAllText() or "{}"))
|
|
||||||
if not tmp then error("Bootdata failed to load") end
|
|
||||||
bootData=tmp()
|
|
||||||
end
|
|
||||||
local list=bootLoader[6]
|
|
||||||
local computer=bootLoader[7]
|
|
||||||
local startup=true
|
|
||||||
local osleep=sleep
|
|
||||||
_G._SYSDEBUG=args[2]
|
|
||||||
bootData.debug=args[2]
|
|
||||||
local drivers={}
|
|
||||||
local eventCache={}
|
|
||||||
|
|
||||||
while true do
|
|
||||||
local event={computer.getMachineEvent()}
|
|
||||||
if event[1]==nil then break end
|
|
||||||
eventCache[#eventCache+1] = event
|
|
||||||
end
|
|
||||||
|
|
||||||
term.clear()
|
|
||||||
term.print("Welcome to Hyperion OS")
|
|
||||||
term.print("Creating logger")
|
|
||||||
osleep(1)
|
|
||||||
local log=load(getFile("/sys/util/logger.lua").readAllText())(computer)
|
|
||||||
term.clear()
|
|
||||||
local logHook=log.setHook(term.print)
|
|
||||||
log.api.log("Created logger")
|
|
||||||
local function saveLog()
|
|
||||||
local logNum=bootData.logNum
|
|
||||||
getFile("/var/log/kernel/"..tostring(logNum)..".log").writeAllText(log.api.get())
|
|
||||||
getFile("/var/log/kernel/latest.log").writeAllText(log.api.get())
|
|
||||||
if bootData.logNum==10 then
|
|
||||||
bootData.logNum=0
|
|
||||||
else
|
|
||||||
bootData.logNum=bootData.logNum+1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if bootData.debug then _G.saveLog=saveLog end
|
|
||||||
|
|
||||||
local function t2t(table)
|
|
||||||
local output = "{"
|
|
||||||
for i,v in pairs(table) do
|
|
||||||
local coma=true
|
|
||||||
if type(i) == "string" then
|
|
||||||
output=output.."[\""..i.."\"]="
|
|
||||||
end
|
|
||||||
if type(v) == "table" then
|
|
||||||
if v == table then
|
|
||||||
output=string.sub(output,1,#output-(#i+1))
|
|
||||||
coma=false
|
|
||||||
else
|
|
||||||
output=output..t2t(v)
|
|
||||||
end
|
|
||||||
elseif type(v) == "string" then
|
|
||||||
output=output.."[=["..v.."]=]"
|
|
||||||
elseif type(v) == "number" then
|
|
||||||
output=output..tostring(v)
|
|
||||||
elseif type(v) == "boolean" then
|
|
||||||
if v == true then
|
|
||||||
output=output.."true"
|
|
||||||
else
|
|
||||||
output=output.."false"
|
|
||||||
end
|
|
||||||
elseif type(v) == "function" then
|
|
||||||
output=output.."function()"
|
|
||||||
else
|
|
||||||
error("serialization of type \""..type(v).."\" is not supported")
|
|
||||||
end
|
|
||||||
if coma then
|
|
||||||
output=output..","
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if #table>0 or string.sub(output,#output,#output) == "," then
|
|
||||||
output=string.sub(output,1,#output-1)
|
|
||||||
end
|
|
||||||
output=output.."}"
|
|
||||||
return output
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Make PANIC
|
|
||||||
local function PANIC(err)
|
|
||||||
term.clear()
|
|
||||||
term.print(log.api.get())
|
|
||||||
saveLog()
|
|
||||||
if err==bootData.prevError then
|
|
||||||
bootData.errorCount=bootData.errorCount+1
|
|
||||||
else
|
|
||||||
bootData.prevError=err
|
|
||||||
bootData.errorCount=0
|
|
||||||
end
|
|
||||||
getFile("/var/log/kernel/bootData").writeAllText(t2t(bootData))
|
|
||||||
term.print("KERNEL PANIC: "..err)
|
|
||||||
term.print("Log saved to /var/log/kernel/"..tostring(bootData.logNum)..".log\n")
|
|
||||||
term.print("Press enter to continue...")
|
|
||||||
while true do
|
|
||||||
local event = {computer.getMachineEvent()}
|
|
||||||
if event[1]~=nil then
|
|
||||||
term.print(table.concat(event, " "))
|
|
||||||
end
|
|
||||||
if event[1] == "keyTyped" then
|
|
||||||
if event[3] == "\n" then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
computer.reboot()
|
|
||||||
end
|
|
||||||
|
|
||||||
local function runAsKernel(path, ...)
|
|
||||||
local func, err = load(getFile(path).readAllText(), path, "t", _G)
|
|
||||||
if not func then return false, "\t"..err end
|
|
||||||
local ret = {xpcall(func, debug.traceback, ...)}
|
|
||||||
if not ret[1] then
|
|
||||||
return false, ret[2]
|
|
||||||
end
|
|
||||||
return true, table.unpack(ret, 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
log.api.log("Loading globals...")
|
|
||||||
for i,v in ipairs(list("/sys/api/")) do
|
|
||||||
if bootData.debug then log.api.debug("Loading "..v) end
|
|
||||||
local ok, err = runAsKernel("/sys/api/"..v, getFile, log)
|
|
||||||
if not ok then log.api.warn(err) end
|
|
||||||
end
|
|
||||||
|
|
||||||
local driverutil={}
|
|
||||||
function driverutil.getFirst(type)
|
|
||||||
if drivers[type] then
|
|
||||||
if drivers[type][1] then
|
|
||||||
return drivers[type][1]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function driverutil.list(type)
|
|
||||||
if not type then
|
|
||||||
local tmp={}
|
|
||||||
for i,v in ipairs(drivers.raw) do
|
|
||||||
tmp[#tmp+1] = {type=v.type, obj=v}
|
|
||||||
end
|
|
||||||
local i=0
|
|
||||||
return function()
|
|
||||||
i=i+1
|
|
||||||
if tmp[i]==nil then return end
|
|
||||||
return tmp[i].type, tmp[i].obj
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local tmp={}
|
|
||||||
for i,v in ipairs(drivers[type]) do
|
|
||||||
tmp[#tmp+1] = {type=v.type, obj=v}
|
|
||||||
end
|
|
||||||
local i=0
|
|
||||||
return function()
|
|
||||||
i=i+1
|
|
||||||
if tmp[i]==nil then return end
|
|
||||||
return tmp[i].type, tmp[i].obj
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
log.api.log("Loading drivers...")
|
|
||||||
for i,v in ipairs(list("/sys/modules/")) do
|
|
||||||
if bootData.debug then log.api.debug("Loading module "..v) end
|
|
||||||
local ok, err = runAsKernel("/sys/modules/"..v, apis, drivers, log, driverutil)
|
|
||||||
if not ok then log.api.warn("["..v.."] exited with ERR:\n"..err) end
|
|
||||||
end
|
|
||||||
|
|
||||||
log.api.log("Unloading non \""..MODE.."\" specific drivers...")
|
|
||||||
do
|
|
||||||
local tmp={}
|
|
||||||
for i,v in ipairs(drivers) do
|
|
||||||
if type(v.arch)=="table" then
|
|
||||||
for i2,v2 in ipairs(v.arch) do
|
|
||||||
if v2==MODE or v2=="ANY" then
|
|
||||||
tmp[#tmp+1] = v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if v.arch==MODE or v.arch=="ANY" then
|
|
||||||
tmp[#tmp+1] = v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
drivers={}
|
|
||||||
drivers.raw=tmp
|
|
||||||
end
|
|
||||||
|
|
||||||
if bootData.debug then log.api.debug("Sorting drivers...") end
|
|
||||||
for i,v in ipairs(drivers.raw) do
|
|
||||||
if not drivers[v.type] then drivers[v.type]={} end
|
|
||||||
drivers[v.type][#drivers[v.type]+1] = v
|
|
||||||
end
|
|
||||||
|
|
||||||
if bootData.debug then log.api.debug("Initializing drivers...") end
|
|
||||||
for i,v in ipairs(drivers.raw) do
|
|
||||||
if v.init then
|
|
||||||
local ok, err = xpcall(v.init, debug.traceback)
|
|
||||||
if not ok then
|
|
||||||
log.api.warn("["..v.name.."]: Init function ERR:\n"..err)
|
|
||||||
if bootData.debug then log.api.debug("Removing driver ["..v.name.."]") end
|
|
||||||
table.remove(drivers.raw, i)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
log.api.log("Loaded "..tostring(#drivers.raw).." drivers")
|
|
||||||
|
|
||||||
log.api.log("Loading filesystem...")
|
|
||||||
local ok, fs = runAsKernel("/sys/fs/init", drivers, log, bootDisk, driverutil)
|
|
||||||
if not ok then PANIC(fs) end
|
|
||||||
if not fs then PANIC("filesystem failed to load") end
|
|
||||||
fs.delete("/tmp")
|
|
||||||
fs.mkDir("/tmp")
|
|
||||||
|
|
||||||
log.api.log("Loading system...")
|
|
||||||
local ok, err = runAsKernel("/sys/Hyperion.sys", drivers, log)
|
|
||||||
if not ok then PANIC(err) end
|
|
||||||
local hyperion = err
|
|
||||||
if type(hyperion)~="function" then PANIC("Hyperion failed to load:\nHyperion was: "..tostring(hyperion)) end
|
|
||||||
hyperion(fs, log, drivers, PANIC, driverutil)
|
|
||||||
|
|
||||||
PANIC("OS EXITED MAIN()")
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
local biosData = ({...})[1]
|
|
||||||
local apis = {}
|
|
||||||
|
|
||||||
local lua = {
|
|
||||||
coroutine = true,
|
|
||||||
debug = true,
|
|
||||||
_HOST = true,
|
|
||||||
_VERSION = true,
|
|
||||||
assert = true,
|
|
||||||
collectgarbage = true,
|
|
||||||
error = true,
|
|
||||||
gcinfo = true,
|
|
||||||
getfenv = true,
|
|
||||||
getmetatable = true,
|
|
||||||
ipairs = true,
|
|
||||||
__inext = true,
|
|
||||||
load = true,
|
|
||||||
math = true,
|
|
||||||
next = true,
|
|
||||||
pairs = true,
|
|
||||||
pcall = true,
|
|
||||||
rawequal = true,
|
|
||||||
rawget = true,
|
|
||||||
rawlen = true,
|
|
||||||
rawset = true,
|
|
||||||
select = true,
|
|
||||||
setfenv = true,
|
|
||||||
setmetatable = true,
|
|
||||||
string = true,
|
|
||||||
table = true,
|
|
||||||
tonumber = true,
|
|
||||||
tostring = true,
|
|
||||||
type = true,
|
|
||||||
xpcall = true,
|
|
||||||
_G = true
|
|
||||||
}
|
|
||||||
|
|
||||||
local print=component.getFirst("screen").print
|
|
||||||
local comp=component
|
|
||||||
-- Sandbox globals
|
|
||||||
local _REAL_G = _G
|
|
||||||
local _PAIRS = pairs
|
|
||||||
|
|
||||||
if type(_REAL_G) ~= "table" then
|
|
||||||
error("Global environment (_G) is not a table")
|
|
||||||
end
|
|
||||||
|
|
||||||
for i, v in _PAIRS(_REAL_G) do
|
|
||||||
if not lua[i] then
|
|
||||||
apis[i] = v
|
|
||||||
_REAL_G[i] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
apis.component=comp
|
|
||||||
|
|
||||||
-- File abstraction compatible with open() -> {read,write,append}
|
|
||||||
local function getFile(path)
|
|
||||||
return {
|
|
||||||
readAllText = function()
|
|
||||||
local handle = biosData.bootDrive:open(path)
|
|
||||||
if not handle or type(handle.read) ~= "function" then
|
|
||||||
error("Cannot open file for reading: " .. tostring(path))
|
|
||||||
end
|
|
||||||
return handle.read() or ""
|
|
||||||
end,
|
|
||||||
writeAllText = function(text)
|
|
||||||
if not biosData.bootDrive:fileExists(path) then
|
|
||||||
biosData.bootDrive:createFile(path)
|
|
||||||
end
|
|
||||||
local handle = biosData.bootDrive:open(path)
|
|
||||||
if not handle or type(handle.write) ~= "function" then
|
|
||||||
error("Cannot open file for writing: " .. tostring(path))
|
|
||||||
end
|
|
||||||
handle.write(text)
|
|
||||||
end,
|
|
||||||
appendText = function(text)
|
|
||||||
local handle = biosData.bootDrive:open(path)
|
|
||||||
if not handle or type(handle.append) ~= "function" then
|
|
||||||
error("Cannot open file for appending: " .. tostring(path))
|
|
||||||
end
|
|
||||||
handle.append(text)
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
local function list(path)
|
|
||||||
return biosData.bootDrive:list(path)
|
|
||||||
end
|
|
||||||
|
|
||||||
function coroutine.resumeWithTimeout(CORO, LINES, ...)
|
|
||||||
local ret = { coroutine.resume(CORO, ...) }
|
|
||||||
if math.random(0, 1) == 0 then
|
|
||||||
return false, table.unpack(ret)
|
|
||||||
else
|
|
||||||
return true, table.unpack(ret)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Safety: verify APIs exist
|
|
||||||
if not apis.component then
|
|
||||||
error("Component API missing in environment")
|
|
||||||
end
|
|
||||||
if not biosData.bootDrive then
|
|
||||||
error("bootDrive missing from biosData")
|
|
||||||
end
|
|
||||||
|
|
||||||
local computer = apis.component.getFirst("computer")
|
|
||||||
|
|
||||||
-- Read kernel file correctly
|
|
||||||
local kernelSource = getFile("/boot/Hyprkrnl.sys").readAllText()
|
|
||||||
if not kernelSource or kernelSource == "" then
|
|
||||||
error("Kernel file empty or unreadable")
|
|
||||||
end
|
|
||||||
|
|
||||||
local kernel, err = load(kernelSource, "@kernel", "t", _G)
|
|
||||||
if not kernel then
|
|
||||||
error("Failed to load kernel: " .. tostring(err))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Run kernel safely
|
|
||||||
local ok, perr = xpcall(function()
|
|
||||||
kernel(
|
|
||||||
"ac",
|
|
||||||
apis,
|
|
||||||
biosData.bootDrive.id,
|
|
||||||
apis.component.getFirst("screen"),
|
|
||||||
getFile,
|
|
||||||
list,
|
|
||||||
apis.component.getFirst("computer")
|
|
||||||
)
|
|
||||||
end, debug.traceback)
|
|
||||||
|
|
||||||
if not ok then
|
|
||||||
error("Kernel execution failed: " .. tostring(perr))
|
|
||||||
end
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
-- UnBIOS by JackMacWindows
|
|
||||||
-- This will undo most of the changes/additions made in the BIOS, but some things may remain wrapped if `debug` is unavailable
|
|
||||||
-- To use, just place a `bios.lua` in the root of the drive, and run this program
|
|
||||||
-- Here's a list of things that are irreversibly changed:
|
|
||||||
-- * both `bit` and `bit32` are kept for compatibility
|
|
||||||
-- * string metatable blocking (on old versions of CC)
|
|
||||||
-- In addition, if `debug` is not available these things are also irreversibly changed:
|
|
||||||
-- * old Lua 5.1 `load` function (for loading from a function)
|
|
||||||
-- * `loadstring` prefixing (before CC:T 1.96.0)
|
|
||||||
-- * `http.request`
|
|
||||||
-- * `os.shutdown` and `os.reboot`
|
|
||||||
-- * `peripheral`
|
|
||||||
-- * `turtle.equip[Left|Right]`
|
|
||||||
-- Licensed under the MIT license
|
|
||||||
local args = {...}
|
|
||||||
if _HOST:find("UnBIOS") then return end
|
|
||||||
local keptAPIs = {keys=true, bit32 = true, bit = true, ccemux = true, config = true, coroutine = true, debug = true, fs = true, http = true, mounter = true, os = true, periphemu = true, peripheral = true, redstone = true, rs = true, term = true, utf8 = true, _HOST = true, _CC_DEFAULT_SETTINGS = true, _CC_DISABLE_LUA51_FEATURES = true, _VERSION = true, assert = true, collectgarbage = true, error = true, gcinfo = true, getfenv = true, getmetatable = true, ipairs = true, __inext = true,load = true, loadstring = true, math = true, newproxy = true, next = true, pairs = true, pcall = true, rawequal = true, rawget = true, rawlen = true, rawset = true, select = true, setfenv = true, setmetatable = true, string = true, table = true, tonumber = true, tostring = true, type = true, unpack = true, xpcall = true, turtle = true, pocket = true, commands = true, _G = true}
|
|
||||||
local t = {}
|
|
||||||
for k in pairs(_G) do if not keptAPIs[k] then table.insert(t, k) end end
|
|
||||||
for _,k in ipairs(t) do _G[k] = nil end
|
|
||||||
local native = _G.term.native()
|
|
||||||
for _, method in ipairs {"nativePaletteColor", "nativePaletteColour", "screenshot"} do native[method] = _G.term[method] end
|
|
||||||
_G.term = native
|
|
||||||
if _G.http then
|
|
||||||
_G.http.checkURL = _G.http.checkURLAsync
|
|
||||||
_G.http.websocket = _G.http.websocketAsync
|
|
||||||
end
|
|
||||||
if _G.commands then _G.commands = _G.commands.native end
|
|
||||||
if _G.turtle then _G.turtle.native, _G.turtle.craft = nil end
|
|
||||||
local delete = {os = {"version", "pullEventRaw", "pullEvent", "run", "loadAPI", "unloadAPI", "sleep"}, http = _G.http and {"get", "post", "put", "delete", "patch", "options", "head", "trace", "listen", "checkURLAsync", "websocketAsync"}, fs = {"complete", "isDriveRoot"}}
|
|
||||||
for k,v in pairs(delete) do for _,a in ipairs(v) do _G[k][a] = nil end end
|
|
||||||
_G._HOST = _G._HOST .. " (UnBIOS)"
|
|
||||||
-- Set up TLCO
|
|
||||||
-- This functions by crashing `rednet.run` by removing `os.pullEventRaw`. Normally
|
|
||||||
-- this would cause `parallel` to throw an error, but we replace `error` with an
|
|
||||||
-- empty placeholder to let it continue and return without throwing. This results
|
|
||||||
-- in the `pcall` returning successfully, preventing the error-displaying code
|
|
||||||
-- from running - essentially making it so that `os.shutdown` is called immediately
|
|
||||||
-- after the new BIOS exits.
|
|
||||||
--
|
|
||||||
-- From there, the setup code is placed in `term.native` since it's the first
|
|
||||||
-- thing called after `parallel` exits. This loads the new BIOS and prepares it
|
|
||||||
-- for execution. Finally, it overwrites `os.shutdown` with the new function to
|
|
||||||
-- allow it to be the last function called in the original BIOS, and returns.
|
|
||||||
-- From there execution continues, calling the `term.redirect` dummy, skipping
|
|
||||||
-- over the error-handling code (since `pcall` returned ok), and calling
|
|
||||||
-- `os.shutdown()`. The real `os.shutdown` is re-added, and the new BIOS is tail
|
|
||||||
-- called, which effectively makes it run as the main chunk.
|
|
||||||
local olderror = error
|
|
||||||
_G.error = function() end
|
|
||||||
_G.term.redirect = function() end
|
|
||||||
function _G.term.native()
|
|
||||||
_G.term.native = nil
|
|
||||||
_G.term.redirect = nil
|
|
||||||
_G.error = olderror
|
|
||||||
term.setBackgroundColor(32768)
|
|
||||||
term.setTextColor(1)
|
|
||||||
term.setCursorPos(1, 1)
|
|
||||||
term.setCursorBlink(true)
|
|
||||||
term.clear()
|
|
||||||
local file = fs.open("/disk/boot/cc/preboot.cc", "r")
|
|
||||||
if file == nil then
|
|
||||||
term.setCursorBlink(false)
|
|
||||||
term.setTextColor(16384)
|
|
||||||
term.write("Could not find /boot/cc/bootloader.cc. UnBIOS cannot continue.")
|
|
||||||
term.setCursorPos(1, 2)
|
|
||||||
term.write("Press any key to continue")
|
|
||||||
coroutine.yield("key")
|
|
||||||
os.shutdown()
|
|
||||||
end
|
|
||||||
local fn, err = loadstring(file.readAll(), "@preboot.cc")
|
|
||||||
file.close()
|
|
||||||
if fn == nil then
|
|
||||||
term.setCursorBlink(false)
|
|
||||||
term.setTextColor(16384)
|
|
||||||
term.write("Could not load /boot/cc/bootloader.cc. UnBIOS cannot continue.")
|
|
||||||
term.setCursorPos(1, 2)
|
|
||||||
term.write(err)
|
|
||||||
term.setCursorPos(1, 3)
|
|
||||||
term.write("Press any key to continue")
|
|
||||||
coroutine.yield("key")
|
|
||||||
os.shutdown()
|
|
||||||
end
|
|
||||||
setfenv(fn, _G)
|
|
||||||
local oldshutdown = os.shutdown
|
|
||||||
os.shutdown = function()
|
|
||||||
os.shutdown = oldshutdown
|
|
||||||
return fn(table.unpack(args))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if debug then
|
|
||||||
-- Restore functions that were overwritten in the BIOS
|
|
||||||
-- Apparently this has to be done *after* redefining term.native
|
|
||||||
local function restoreValue(tab, idx, name, hint)
|
|
||||||
local i, key, value = 1, debug.getupvalue(tab[idx], hint)
|
|
||||||
while key ~= name and key ~= nil do
|
|
||||||
key, value = debug.getupvalue(tab[idx], i)
|
|
||||||
i=i+1
|
|
||||||
end
|
|
||||||
tab[idx] = value or tab[idx]
|
|
||||||
end
|
|
||||||
restoreValue(_G, "loadstring", "nativeloadstring", 1)
|
|
||||||
restoreValue(_G, "load", "nativeload", 5)
|
|
||||||
if http then restoreValue(http, "request", "nativeHTTPRequest", 3) end
|
|
||||||
restoreValue(os, "shutdown", "nativeShutdown", 1)
|
|
||||||
restoreValue(os, "reboot", "nativeReboot", 1)
|
|
||||||
if turtle then
|
|
||||||
restoreValue(turtle, "equipLeft", "v", 1)
|
|
||||||
restoreValue(turtle, "equipRight", "v", 1)
|
|
||||||
end
|
|
||||||
do
|
|
||||||
local i, key, value = 1, debug.getupvalue(peripheral.isPresent, 2)
|
|
||||||
while key ~= "native" and key ~= nil do
|
|
||||||
key, value = debug.getupvalue(peripheral.isPresent, i)
|
|
||||||
i=i+1
|
|
||||||
end
|
|
||||||
_G.peripheral = value or peripheral
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,240 +0,0 @@
|
|||||||
local apis={}
|
|
||||||
|
|
||||||
local lua = {
|
|
||||||
coroutine = true,
|
|
||||||
debug = true,
|
|
||||||
_HOST = true,
|
|
||||||
_VERSION = true,
|
|
||||||
assert = true,
|
|
||||||
collectgarbage = true,
|
|
||||||
error = true,
|
|
||||||
gcinfo = true,
|
|
||||||
getfenv = true,
|
|
||||||
getmetatable = true,
|
|
||||||
ipairs = true,
|
|
||||||
__inext = true,
|
|
||||||
load = true,
|
|
||||||
math = true,
|
|
||||||
next = true,
|
|
||||||
pairs = true,
|
|
||||||
pcall = true,
|
|
||||||
rawequal = true,
|
|
||||||
rawget = true,
|
|
||||||
rawlen = true,
|
|
||||||
rawset = true,
|
|
||||||
select = true,
|
|
||||||
setfenv = true,
|
|
||||||
setmetatable = true,
|
|
||||||
string = true,
|
|
||||||
table = true,
|
|
||||||
tonumber = true,
|
|
||||||
tostring = true,
|
|
||||||
type = true,
|
|
||||||
xpcall = true,
|
|
||||||
_G=true
|
|
||||||
}
|
|
||||||
|
|
||||||
for i,v in pairs(_G) do
|
|
||||||
if not lua[i] or lua[i]==nil then
|
|
||||||
apis[i]=v
|
|
||||||
_G[i]=nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function sleep(time)
|
|
||||||
coroutine.yield("CC_TIMER", time)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function catErr(text)
|
|
||||||
apis.term.setCursorPos(1,1)
|
|
||||||
apis.term.write(text)
|
|
||||||
while true do
|
|
||||||
coroutine.yield()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function getFile(path)
|
|
||||||
if path:sub(1,1) ~= "/" then
|
|
||||||
path="/"..path
|
|
||||||
end
|
|
||||||
path="/disk"..path
|
|
||||||
if not apis.fs.exists(path) then error("File does not exist") end
|
|
||||||
if apis.fs.isDir(path) then error("Cannot open a directory") end
|
|
||||||
return {
|
|
||||||
readAllText=function()
|
|
||||||
local file = apis.fs.open(path, "r")
|
|
||||||
local text = file.readAll()
|
|
||||||
file.close()
|
|
||||||
return text
|
|
||||||
end,
|
|
||||||
writeAllText=function(text)
|
|
||||||
local file = apis.fs.open(path, "w")
|
|
||||||
file.write(text)
|
|
||||||
file.close()
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Prints text handling \n, \t, and \b with scrolling (no wrapping)
|
|
||||||
local function write(text)
|
|
||||||
local x, y = apis.term.getCursorPos()
|
|
||||||
local w, h = apis.term.getSize()
|
|
||||||
|
|
||||||
for i = 1, #text do
|
|
||||||
local c = text:sub(i, i)
|
|
||||||
|
|
||||||
if c == "\n" then
|
|
||||||
y = y + 1
|
|
||||||
x = 1
|
|
||||||
elseif c == "\t" then
|
|
||||||
local tabSize = 4
|
|
||||||
local spaces = tabSize - ((x - 1) % tabSize)
|
|
||||||
apis.term.write(string.rep(" ", spaces))
|
|
||||||
x = x + spaces
|
|
||||||
elseif c == "\b" then
|
|
||||||
if x > 1 then
|
|
||||||
x = x - 1
|
|
||||||
apis.term.setCursorPos(x, y)
|
|
||||||
apis.term.write(" ")
|
|
||||||
apis.term.setCursorPos(x, y)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if x <= w and y <= h then
|
|
||||||
apis.term.setCursorPos(x, y)
|
|
||||||
apis.term.write(c)
|
|
||||||
x = x + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Handle scrolling if we go past bottom
|
|
||||||
if y > h then
|
|
||||||
apis.term.scroll(1)
|
|
||||||
y = h
|
|
||||||
apis.term.setCursorPos(x, y)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
apis.term.setCursorPos(x, y)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local event_queue = {}
|
|
||||||
local function addEventRaw(...)
|
|
||||||
event_queue[#event_queue+1] = {...}
|
|
||||||
end
|
|
||||||
|
|
||||||
local function getEvent()
|
|
||||||
local event = event_queue[1]
|
|
||||||
event_queue = {table.unpack(event_queue, 2)}
|
|
||||||
return table.unpack(event or {})
|
|
||||||
end
|
|
||||||
|
|
||||||
local lkeys={}
|
|
||||||
lkeys[apis.keys.enter]="\n"
|
|
||||||
lkeys[apis.keys.backspace]="\b"
|
|
||||||
lkeys[apis.keys.tab]="\t"
|
|
||||||
lkeys[apis.keys.up]="\x1b[A"
|
|
||||||
lkeys[apis.keys.down]="\x1b[B"
|
|
||||||
lkeys[apis.keys.right]="\x1b[C"
|
|
||||||
lkeys[apis.keys.left]="\x1b[D"
|
|
||||||
|
|
||||||
local computer={}
|
|
||||||
computer.beep=function() end
|
|
||||||
computer.shutdown=apis.os.shutdown
|
|
||||||
computer.reboot=apis.os.reboot
|
|
||||||
computer.time=function()
|
|
||||||
return apis.os.epoch("utc")
|
|
||||||
end
|
|
||||||
computer.getMachineEvent=getEvent
|
|
||||||
computer.date=apis.os.date
|
|
||||||
|
|
||||||
local function list(path)
|
|
||||||
if path:sub(1,1) ~= "/" then
|
|
||||||
path="/"..path
|
|
||||||
end
|
|
||||||
path="/disk"..path
|
|
||||||
if not apis.fs.isDir(path) then return {} end
|
|
||||||
return apis.fs.list(path)
|
|
||||||
end
|
|
||||||
|
|
||||||
function coroutine.resumeWithTimeout(CORO, LINES, ...)
|
|
||||||
local yeildKey = {}
|
|
||||||
debug.sethook(CORO, function()
|
|
||||||
coroutine.yield(yeildKey)
|
|
||||||
end, "l", LINES)
|
|
||||||
local ret = {coroutine.resume(CORO, ...)}
|
|
||||||
debug.sethook(CORO)
|
|
||||||
if ret[2]==yeildKey then return false else return true, table.unpack(ret, 2) end
|
|
||||||
end
|
|
||||||
|
|
||||||
local kernel = load(getFile("/boot/HBoot.sys").readAllText(), "@kernel", "t", _G)
|
|
||||||
if not kernel then
|
|
||||||
catErr("BOOT COMPILE ERR")
|
|
||||||
end
|
|
||||||
local kernel_coro = coroutine.create(function()
|
|
||||||
local ok,err = pcall(function()
|
|
||||||
local ok, err=xpcall(kernel, debug.traceback, "cc", apis, "disk", {
|
|
||||||
print=function(text)
|
|
||||||
write(text.."\n")
|
|
||||||
end,
|
|
||||||
printInline=function(text)
|
|
||||||
write(text)
|
|
||||||
end,
|
|
||||||
clear=function()
|
|
||||||
apis.term.clear()
|
|
||||||
apis.term.setCursorPos(1,1)
|
|
||||||
end,
|
|
||||||
getSize=function ()
|
|
||||||
return apis.term.getSize()
|
|
||||||
end
|
|
||||||
}, getFile, list, computer)
|
|
||||||
if not ok then
|
|
||||||
write(err)
|
|
||||||
while true do
|
|
||||||
coroutine.yield()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
if not ok then
|
|
||||||
catErr(err)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
apis.term.setCursorBlink(false)
|
|
||||||
while true do
|
|
||||||
local ret = {coroutine.resumeWithTimeout(kernel_coro, 200)}
|
|
||||||
if coroutine.status(kernel_coro) == "dead" then
|
|
||||||
catErr("KERNEL EXITED")
|
|
||||||
end
|
|
||||||
if ret[1] then
|
|
||||||
if ret[2]=="CC_TIMER" and ret[3]~=nil and type(ret[3])=="number" then
|
|
||||||
local timer = apis.os.startTimer(ret[3])
|
|
||||||
repeat
|
|
||||||
local _, param = coroutine.yield("timer")
|
|
||||||
until param == timer
|
|
||||||
end
|
|
||||||
end
|
|
||||||
apis.os.queueEvent("nosleep")
|
|
||||||
local exit = false
|
|
||||||
repeat
|
|
||||||
local event = {coroutine.yield()}
|
|
||||||
if event[1] == "nosleep" then
|
|
||||||
exit=true
|
|
||||||
elseif event[1]==nil then
|
|
||||||
elseif event[1]=="key" then
|
|
||||||
addEventRaw("keyPressed", 1, event[2])
|
|
||||||
if lkeys[event[2]] then
|
|
||||||
addEventRaw("keyTyped", 1, lkeys[event[2]])
|
|
||||||
end
|
|
||||||
elseif event[1]=="char" then
|
|
||||||
addEventRaw("keyTyped", 1, event[2])
|
|
||||||
elseif event[1]=="key_up" then
|
|
||||||
addEventRaw("keyReleased", 1, event[2])
|
|
||||||
elseif event[1]=="disk" then
|
|
||||||
addEventRaw("componentAdded", "disk")
|
|
||||||
elseif event[1]=="disk_eject" then
|
|
||||||
addEventRaw("componentRemoved", "disk")
|
|
||||||
end
|
|
||||||
until exit
|
|
||||||
end
|
|
||||||
apis.os.reboot()
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +0,0 @@
|
|||||||
local lib = {}
|
|
||||||
|
|
||||||
function lib.create()
|
|
||||||
local array = {}
|
|
||||||
return setmetatable(array,{
|
|
||||||
__add=function(t1, t2)
|
|
||||||
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
local args={...}
|
|
||||||
local fs=args[1]
|
|
||||||
local log=args[2]
|
|
||||||
local drivers=args[3]
|
|
||||||
local PANIC=args[4]
|
|
||||||
local driverutil=args[5]
|
|
||||||
local sys={}
|
|
||||||
local task={}
|
|
||||||
|
|
||||||
sys._VERSION = "HyperionOS V1.0.4"
|
|
||||||
|
|
||||||
local function run(file, args)
|
|
||||||
local func, err=fs.loadAsFunc(file)
|
|
||||||
if not file then return 8, err end
|
|
||||||
local ret={xpcall(func, debug.traceback, table.unpack(args))}
|
|
||||||
if not ret[1] then return 1, ret[2] end
|
|
||||||
return 0, table.unpack(ret, 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
local exitcode, req=run("/sys/system/require", {sys})
|
|
||||||
if exitcode~=0 then PANIC(req) end
|
|
||||||
_G.require=req
|
|
||||||
|
|
||||||
local exitcode, hypervisor=run("/sys/system/hypervisor/init", {sys})
|
|
||||||
if exitcode~=0 then PANIC(hypervisor) end
|
|
||||||
_G.require=hypervisor
|
|
||||||
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
-- Copyright (C) 2025 ASTRONAND
|
|
||||||
function string.hasSuffix(str, suffix)
|
|
||||||
return string.sub(str, #suffix+1) == suffix
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.hasPrefix(str, prefix)
|
|
||||||
return string.sub(str, 1, #prefix) == prefix
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.getSuffix(str, prefix)
|
|
||||||
return string.sub(str, #prefix+1)
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.getPrefix(str, suffix)
|
|
||||||
return string.sub(str, 1, #suffix)
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.join(str, ...)
|
|
||||||
return table.concat(table.pack(str, ...))
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.delim(str, ...)
|
|
||||||
return table.concat(table.pack(...), str)
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.split(str, delim, maxResultCountOrNil)
|
|
||||||
assert(#delim == 1, "only delim len 1 supported for now")
|
|
||||||
maxResultCountOrNil = (maxResultCountOrNil or 0)-1
|
|
||||||
local rv = {}
|
|
||||||
local buf = ""
|
|
||||||
for i = 1, #str do
|
|
||||||
local c = string.sub(str,i,i)
|
|
||||||
if #rv ~= maxResultCountOrNil and c == delim then
|
|
||||||
table.insert(rv, buf)
|
|
||||||
buf = ""
|
|
||||||
else
|
|
||||||
buf = buf..c
|
|
||||||
end
|
|
||||||
end
|
|
||||||
table.insert(rv, buf)
|
|
||||||
return rv
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.replace(str, search, replacement)
|
|
||||||
local rv = ""
|
|
||||||
local consumedLen = 1
|
|
||||||
local i = 1
|
|
||||||
while i<#str do
|
|
||||||
if string.sub(str, i, i+#search-1) == search then
|
|
||||||
rv = rv .. string.sub(str, consumedLen, i-1) .. replacement
|
|
||||||
i=i+#search
|
|
||||||
consumedLen = i
|
|
||||||
end
|
|
||||||
i=i+1
|
|
||||||
end
|
|
||||||
return rv .. string.sub(str, consumedLen)
|
|
||||||
end
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
-- Copyright (C) 2025 ASTRONAND
|
|
||||||
function table.deepcopy(orig, copies)
|
|
||||||
copies = copies or {}
|
|
||||||
|
|
||||||
if type(orig) ~= 'table' then
|
|
||||||
return orig
|
|
||||||
elseif copies[orig] then
|
|
||||||
return copies[orig]
|
|
||||||
end
|
|
||||||
|
|
||||||
local copy = {}
|
|
||||||
copies[orig] = copy
|
|
||||||
|
|
||||||
for k, v in next, orig, nil do
|
|
||||||
local copied_key = table.deepcopy(k, copies)
|
|
||||||
local copied_val = table.deepcopy(v, copies)
|
|
||||||
copy[copied_key] = copied_val
|
|
||||||
end
|
|
||||||
|
|
||||||
return copy
|
|
||||||
end
|
|
||||||
|
|
||||||
function table.hasKey(tabl, query)
|
|
||||||
for i,v in pairs(tabl) do
|
|
||||||
if i==query then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
function table.hasVal(tabl, query)
|
|
||||||
for i,v in pairs(tabl) do
|
|
||||||
if v==query then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local function serialize(table)
|
|
||||||
local output = "{"
|
|
||||||
for i,v in pairs(table) do
|
|
||||||
local coma=true
|
|
||||||
if type(i) == "string" then
|
|
||||||
output=output.."[\""..i.."\"]="
|
|
||||||
end
|
|
||||||
if type(v) == "table" then
|
|
||||||
if v == table then
|
|
||||||
output=string.sub(output,1,#output-(#i+1))
|
|
||||||
coma=false
|
|
||||||
else
|
|
||||||
output=output..serialize(v)
|
|
||||||
end
|
|
||||||
elseif type(v) == "string" then
|
|
||||||
output=output.."[=["..v.."]=]"
|
|
||||||
elseif type(v) == "number" then
|
|
||||||
output=output..tostring(v)
|
|
||||||
elseif type(v) == "boolean" then
|
|
||||||
if v == true then
|
|
||||||
output=output.."true"
|
|
||||||
else
|
|
||||||
output=output.."false"
|
|
||||||
end
|
|
||||||
elseif type(v) == "function" then
|
|
||||||
output=output.."function() end"
|
|
||||||
else
|
|
||||||
error("serialization of type \""..type(v).."\" is not supported")
|
|
||||||
end
|
|
||||||
if coma then
|
|
||||||
output=output..","
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if #table>0 or string.sub(output,#output,#output) == "," then
|
|
||||||
output=string.sub(output,1,#output-1)
|
|
||||||
end
|
|
||||||
output=output.."}"
|
|
||||||
return output
|
|
||||||
end
|
|
||||||
|
|
||||||
table.serialize=serialize
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
local args={...}
|
|
||||||
local drivers=args[1]
|
|
||||||
local log=args[2]
|
|
||||||
local bootDisk=args[3]
|
|
||||||
local driverutil=args[4]
|
|
||||||
local wd="/"
|
|
||||||
log.api.log("Bootdrive is "..bootDisk)
|
|
||||||
if not drivers.disk then
|
|
||||||
error("WTF") -- ???
|
|
||||||
end
|
|
||||||
|
|
||||||
local disks={}
|
|
||||||
local mounts={
|
|
||||||
["/"]=bootDisk
|
|
||||||
}
|
|
||||||
local meta={}
|
|
||||||
|
|
||||||
local function refreshDisks()
|
|
||||||
local diskstmp={}
|
|
||||||
local tmp={}
|
|
||||||
for i,v in driverutil.list("disk") do
|
|
||||||
tmp[#tmp+1] = v
|
|
||||||
end
|
|
||||||
for _,d in ipairs(tmp) do
|
|
||||||
for i,v in d.api.list() do
|
|
||||||
if diskstmp[i]==nil then
|
|
||||||
diskstmp[i]=v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
disks=diskstmp
|
|
||||||
end
|
|
||||||
refreshDisks()
|
|
||||||
--[[
|
|
||||||
meta=load("return "..(disks[bootDisk].readAllText("/sys/fs/meta.ltn") or "{}"), "meta")()
|
|
||||||
if not meta then error("Meta failed to load") end
|
|
||||||
]]
|
|
||||||
local function resolve(path)
|
|
||||||
if path:sub(1,1)~="/" then path=wd..path end
|
|
||||||
local currmatch="/"
|
|
||||||
for i,_ in pairs(mounts) do
|
|
||||||
if string.hasPrefix(path, i) then
|
|
||||||
if #i>#currmatch then
|
|
||||||
currmatch=i
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local drive=disks[mounts[currmatch]]
|
|
||||||
local newPath=string.getSuffix(path, currmatch)
|
|
||||||
return drive, newPath
|
|
||||||
end
|
|
||||||
|
|
||||||
local fs={}
|
|
||||||
|
|
||||||
function fs.list(path)
|
|
||||||
local drive, newPath = resolve(path)
|
|
||||||
return drive.list(newPath)
|
|
||||||
end
|
|
||||||
|
|
||||||
function fs.readAllText(path)
|
|
||||||
local drive, newPath = resolve(path)
|
|
||||||
return drive.readAllText(newPath)
|
|
||||||
end
|
|
||||||
|
|
||||||
function fs.writeAllText(path, content)
|
|
||||||
local drive, newPath = resolve(path)
|
|
||||||
return drive.writeAllText(newPath, content)
|
|
||||||
end
|
|
||||||
|
|
||||||
function fs.delete(path)
|
|
||||||
local drive, newPath = resolve(path)
|
|
||||||
return drive.delete(newPath)
|
|
||||||
end
|
|
||||||
|
|
||||||
function fs.exists(path)
|
|
||||||
local drive, newPath = resolve(path)
|
|
||||||
return (drive.fileExists(newPath) or drive.directoryExists(newPath))
|
|
||||||
end
|
|
||||||
|
|
||||||
function fs.fileExists(path)
|
|
||||||
local drive, newPath = resolve(path)
|
|
||||||
return drive.fileExists(newPath)
|
|
||||||
end
|
|
||||||
|
|
||||||
function fs.directoryExists(path)
|
|
||||||
local drive, newPath = resolve(path)
|
|
||||||
return drive.directoryExists(newPath)
|
|
||||||
end
|
|
||||||
|
|
||||||
function fs.createFile(path)
|
|
||||||
local drive, newPath = resolve(path)
|
|
||||||
return drive.makeFile(newPath)
|
|
||||||
end
|
|
||||||
|
|
||||||
function fs.createDirectory(path)
|
|
||||||
local drive, newPath = resolve(path)
|
|
||||||
return drive.makeDirectory(newPath)
|
|
||||||
end
|
|
||||||
|
|
||||||
fs.mkDir=fs.createDirectory
|
|
||||||
fs.mkFile=fs.createFile
|
|
||||||
fs.isDir=fs.directoryExists
|
|
||||||
fs.isFile=fs.fileExists
|
|
||||||
|
|
||||||
function fs.getWorkingDir()
|
|
||||||
return wd
|
|
||||||
end
|
|
||||||
|
|
||||||
function fs.setWorkingDir(dir)
|
|
||||||
if type(dir)~="string" then error("Invailid path") end
|
|
||||||
if dir:sub(1,1)~="/" then dir=wd..dir end
|
|
||||||
if dir:sub(#dir,#dir)~="/" then dir=dir.."/" end
|
|
||||||
if not fs.isDir(dir) then error("Invailid path") end
|
|
||||||
end
|
|
||||||
|
|
||||||
function fs.loadAsFunc(path)
|
|
||||||
local file = fs.readAllText(path)
|
|
||||||
return load(file, path, "t", setmetatable({},{
|
|
||||||
__index=_G,
|
|
||||||
__metatable=false
|
|
||||||
}))
|
|
||||||
end
|
|
||||||
|
|
||||||
return fs
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
{["/sys/util/logger.lua"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/bin/hex.lua"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/opt"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/var/log/kernel"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/sys/modules/cc.component.kd"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/opt/astronand/ZDelta/init"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/sys/api"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/var/log/kernel/10.log"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/var/log/kernel/7.log"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/var/log/kernel/1.log"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/bin/BASIC"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/boot/cc/preboot.cc"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/boot/ac"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/sys"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/sys/fs/init"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/lib"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/sys/api/table.lua"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/var/log/kernel/5.log"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/usr/share/doc"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/var/log/kernel/3.log"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/opt/astronand/ZDelta"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/sys/hypervisor/init.sys"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/usr/share"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/sys/modules"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/var/log/kernel/6.log"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/sys/hypervisor"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/var/log/kernel/4.log"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/lib/array/math"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/var"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/sys/util/conhost.lua"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/boot/Hyprkrnl.sys"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/bin"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/sys/modules/ac.disks.kd"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/lib/array/x"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/sys/modules/cc.disks.kd"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/opt/astronand/dbg"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/usr"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/usr/share/doc/kernel/drivers"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/sys/util"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/var/log/kernel/8.log"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/var/log/kernel/9.log"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/var/log/kernel/latest.log"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/lib/array"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/boot/cc/boot.cc"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/home"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/usr/share/doc/kernel/drivers/disk.md"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/lib/LibDeflate"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/sys/fs/meta.ltn"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/var/log/kernel/0.log"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/var/log/kernel/bootData"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/sys/api/string.lua"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/var/log"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/bin/shell.hex"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/opt/astronand/dbg/init"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/boot/bootloader.sys"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/lib/array/2d"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/boot/cc"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/boot/ac/boot.ac"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/var/log/kernel/2.log"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/sys/modules/ccpc.disk.kd"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/sys/api/require.lua"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/bin/lua.lua"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/usr/share/doc/kernel"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/boot"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/sys/fs"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/var/system"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/sys/modules/cc.terminal.kd"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
,["/opt/astronand"]={["p"]=21,["o"]=0,["g"]=0}
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
local kernelArgs={...}
|
|
||||||
local apis=kernelArgs[1]
|
|
||||||
local drivers=kernelArgs[2]
|
|
||||||
local log=kernelArgs[3]
|
|
||||||
local driver={}
|
|
||||||
local disks = {}
|
|
||||||
|
|
||||||
driver.type = "disk"
|
|
||||||
driver.name = "AC:Disk"
|
|
||||||
driver.version = "1.0.0"
|
|
||||||
driver.apiVersion = 1
|
|
||||||
driver.description = "Driver for AC disks"
|
|
||||||
driver.arch = "ac"
|
|
||||||
driver.api = {}
|
|
||||||
|
|
||||||
local function refreshDisks()
|
|
||||||
local tmp={}
|
|
||||||
for i,v in apis.component.list() do
|
|
||||||
if i=="disk" then
|
|
||||||
tmp[v.id]={
|
|
||||||
readAllText=function(path)
|
|
||||||
return v:open(path).read()
|
|
||||||
end,
|
|
||||||
writeAllText=function(path, content)
|
|
||||||
return v:open(path).write(content)
|
|
||||||
end,
|
|
||||||
list=function(path)
|
|
||||||
return v:list(path)
|
|
||||||
end,
|
|
||||||
delete=function(path)
|
|
||||||
return v:delete(path)
|
|
||||||
end,
|
|
||||||
makeDirectory=function(path)
|
|
||||||
return v:makeDirectory(path)
|
|
||||||
end,
|
|
||||||
makeFile=function(path)
|
|
||||||
return v:makeFile(path)
|
|
||||||
end,
|
|
||||||
directoryExists=function(path)
|
|
||||||
return v:directoryExists(path)
|
|
||||||
end,
|
|
||||||
fileExists=function(path)
|
|
||||||
return v:fileExists(path)
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
disks=tmp
|
|
||||||
end
|
|
||||||
|
|
||||||
function driver.init()
|
|
||||||
refreshDisks()
|
|
||||||
end
|
|
||||||
|
|
||||||
function driver.api.list()
|
|
||||||
local tmp={}
|
|
||||||
for i,v in pairs(disks) do
|
|
||||||
tmp[#tmp+1]={id=i, obj=v}
|
|
||||||
end
|
|
||||||
local i=0
|
|
||||||
return function()
|
|
||||||
i=i+1
|
|
||||||
if tmp[i]==nil then return end
|
|
||||||
return tmp.id, tmp.obj
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function driver.main()
|
|
||||||
while true do
|
|
||||||
refreshDisks()
|
|
||||||
sleep(5)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
drivers[#drivers+1]=driver
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
local kernelArgs={...}
|
|
||||||
local apis=kernelArgs[1]
|
|
||||||
local drivers=kernelArgs[2]
|
|
||||||
local log=kernelArgs[3]
|
|
||||||
local driver={}
|
|
||||||
local disks={}
|
|
||||||
local driverutil=kernelArgs[4]
|
|
||||||
|
|
||||||
driver.type = "disk"
|
|
||||||
driver.name = "CC:Disks"
|
|
||||||
driver.version = "1.0.0"
|
|
||||||
driver.apiVersion = 1
|
|
||||||
driver.description = "Driver for CC:Tweaked disks"
|
|
||||||
driver.arch = "cc"
|
|
||||||
driver.api = {}
|
|
||||||
|
|
||||||
local function abs(path)
|
|
||||||
if path:sub(1,1)~="/" then path="/"..path end
|
|
||||||
return path
|
|
||||||
end
|
|
||||||
|
|
||||||
local function newDisk(root)
|
|
||||||
root="/"..root
|
|
||||||
return {
|
|
||||||
readAllText=function(path)
|
|
||||||
local file=apis.fs.open(root..abs(path),"r")
|
|
||||||
local text=file.readAll()
|
|
||||||
file.close()
|
|
||||||
return text
|
|
||||||
end,
|
|
||||||
writeAllText=function(path, content)
|
|
||||||
local file=apis.fs.open(root..abs(path),"w")
|
|
||||||
file.write(content)
|
|
||||||
file.close()
|
|
||||||
end,
|
|
||||||
list=function(path)
|
|
||||||
return apis.fs.list(root..abs(path))
|
|
||||||
end,
|
|
||||||
delete=function(path)
|
|
||||||
return apis.fs.delete(root..abs(path))
|
|
||||||
end,
|
|
||||||
makeDirectory=function(path)
|
|
||||||
return apis.fs.makeDir(root..abs(path))
|
|
||||||
end,
|
|
||||||
makeFile=function(path)
|
|
||||||
local file=apis.fs.open(root..abs(path),"w")
|
|
||||||
file.close()
|
|
||||||
end,
|
|
||||||
directoryExists=function(path)
|
|
||||||
return apis.fs.exists(root..abs(path)) and apis.fs.isDir(root..abs(path))
|
|
||||||
end,
|
|
||||||
fileExists=function(path)
|
|
||||||
return apis.fs.exists(root..abs(path)) and not apis.fs.isDir(root..abs(path))
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
local function refreshDisks(peripheral)
|
|
||||||
local tmp2={}
|
|
||||||
tmp2["disk"]=newDisk("disk")
|
|
||||||
for i,v in ipairs(peripheral.api.getNames()) do
|
|
||||||
if peripheral.api.isType(v, "drive") then
|
|
||||||
local p=peripheral.api.wrap(v)
|
|
||||||
if p.isDiskPresent() then
|
|
||||||
if p.getMountPath()~="disk" then
|
|
||||||
tmp2["disk_"..p.getID()] = newDisk(p.getMountPath())
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
disks=tmp2
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function driver.init()
|
|
||||||
local peripheral=driverutil.getFirst("component")
|
|
||||||
refreshDisks(peripheral)
|
|
||||||
end
|
|
||||||
|
|
||||||
function driver.api.list()
|
|
||||||
local tmp={}
|
|
||||||
for i,v in pairs(disks) do
|
|
||||||
tmp[#tmp+1]={id=i, obj=v}
|
|
||||||
end
|
|
||||||
local i=0
|
|
||||||
return function()
|
|
||||||
i=i+1
|
|
||||||
if tmp[i]==nil then return end
|
|
||||||
return tmp[i].id, tmp[i].obj
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function driver.main()
|
|
||||||
while true do
|
|
||||||
refreshDisks()
|
|
||||||
sleep(5)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
drivers[#drivers+1] = driver
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
local kernelArgs={...}
|
|
||||||
local apis=kernelArgs[1]
|
|
||||||
local drivers=kernelArgs[2]
|
|
||||||
local log=kernelArgs[3]
|
|
||||||
local driver={}
|
|
||||||
|
|
||||||
driver.type = "component"
|
|
||||||
driver.name = "CC:Periph"
|
|
||||||
driver.version = "1.0.0"
|
|
||||||
driver.apiVersion = 1
|
|
||||||
driver.description = "Driver for CC:Tweaked peripherals"
|
|
||||||
driver.arch = "cc"
|
|
||||||
driver.api = {}
|
|
||||||
|
|
||||||
local native,sides
|
|
||||||
if apis.peripheral then
|
|
||||||
native = apis.peripheral
|
|
||||||
sides = apis.rs.getSides()
|
|
||||||
end
|
|
||||||
|
|
||||||
function driver.api.getNames()
|
|
||||||
local results = {}
|
|
||||||
for n = 1, #sides do
|
|
||||||
local side = sides[n]
|
|
||||||
if native.isPresent(side) then
|
|
||||||
table.insert(results, side)
|
|
||||||
if native.hasType(side, "peripheral_hub") then
|
|
||||||
local remote = native.call(side, "getNamesRemote")
|
|
||||||
for _, name in ipairs(remote) do
|
|
||||||
table.insert(results, name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return results
|
|
||||||
end
|
|
||||||
|
|
||||||
function driver.api.getType(peripheral)
|
|
||||||
if type(peripheral) == "string" then -- Peripheral name passed
|
|
||||||
if native.isPresent(peripheral) then
|
|
||||||
return native.getType(peripheral)
|
|
||||||
end
|
|
||||||
for n = 1, #sides do
|
|
||||||
local side = sides[n]
|
|
||||||
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
|
|
||||||
return native.call(side, "getTypeRemote", peripheral)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
else
|
|
||||||
local mt = getmetatable(peripheral)
|
|
||||||
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
|
|
||||||
error("bad argument #1 (table is not a peripheral)", 2)
|
|
||||||
end
|
|
||||||
return table.unpack(mt.types)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function driver.api.isType(peripheral, peripheral_type)
|
|
||||||
if type(peripheral) == "string" then -- Peripheral name passed
|
|
||||||
if native.isPresent(peripheral) then
|
|
||||||
return native.hasType(peripheral, peripheral_type)
|
|
||||||
end
|
|
||||||
for n = 1, #sides do
|
|
||||||
local side = sides[n]
|
|
||||||
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
|
|
||||||
return native.call(side, "hasTypeRemote", peripheral, peripheral_type)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
else
|
|
||||||
local mt = getmetatable(peripheral)
|
|
||||||
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
|
|
||||||
error("bad argument #1 (table is not a peripheral)", 2)
|
|
||||||
end
|
|
||||||
return mt.types[peripheral_type] ~= nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function driver.api.getMethods(name)
|
|
||||||
if native.isPresent(name) then
|
|
||||||
return native.getMethods(name)
|
|
||||||
end
|
|
||||||
for n = 1, #sides do
|
|
||||||
local side = sides[n]
|
|
||||||
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
|
|
||||||
return native.call(side, "getMethodsRemote", name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function driver.api.call(name, method, ...)
|
|
||||||
if native.isPresent(name) then
|
|
||||||
return native.call(name, method, ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
for n = 1, #sides do
|
|
||||||
local side = sides[n]
|
|
||||||
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
|
|
||||||
return native.call(side, "callRemote", name, method, ...)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function driver.api.wrap(name)
|
|
||||||
local methods = driver.api.getMethods(name)
|
|
||||||
if not methods then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local types = { driver.api.getType(name) }
|
|
||||||
for i = 1, #types do types[types[i]] = true end
|
|
||||||
local result = setmetatable({}, {
|
|
||||||
__name = "peripheral",
|
|
||||||
name = name,
|
|
||||||
type = types[1],
|
|
||||||
types = types,
|
|
||||||
})
|
|
||||||
for _, method in ipairs(methods) do
|
|
||||||
result[method] = function(...)
|
|
||||||
return driver.api.call(name, method, ...)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
|
|
||||||
drivers[#drivers+1] = driver
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
local kernelArgs={...}
|
|
||||||
local apis=kernelArgs[1]
|
|
||||||
local drivers=kernelArgs[2]
|
|
||||||
local log=kernelArgs[3]
|
|
||||||
local driver={}
|
|
||||||
|
|
||||||
driver.type = "terminal"
|
|
||||||
driver.name = "CC:Term"
|
|
||||||
driver.version = "1.0.0"
|
|
||||||
driver.apiVersion = 1
|
|
||||||
driver.description = "Driver for CC:Tweaked screens"
|
|
||||||
driver.arch = "cc"
|
|
||||||
driver.api = {}
|
|
||||||
|
|
||||||
-- Prints text handling \n, \t, and \b with scrolling (no wrapping)
|
|
||||||
local function write(text)
|
|
||||||
local x, y = apis.term.getCursorPos()
|
|
||||||
local w, h = apis.term.getSize()
|
|
||||||
|
|
||||||
for i = 1, #text do
|
|
||||||
local c = text:sub(i, i)
|
|
||||||
|
|
||||||
if c == "\n" then
|
|
||||||
y = y + 1
|
|
||||||
x = 1
|
|
||||||
elseif c == "\t" then
|
|
||||||
local tabSize = 4
|
|
||||||
local spaces = tabSize - ((x - 1) % tabSize)
|
|
||||||
apis.term.write(string.rep(" ", spaces))
|
|
||||||
x = x + spaces
|
|
||||||
elseif c == "\b" then
|
|
||||||
if x > 1 then
|
|
||||||
x = x - 1
|
|
||||||
apis.term.setCursorPos(x, y)
|
|
||||||
apis.term.write(" ")
|
|
||||||
apis.term.setCursorPos(x, y)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if x <= w and y <= h then
|
|
||||||
apis.term.setCursorPos(x, y)
|
|
||||||
apis.term.write(c)
|
|
||||||
x = x + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Handle scrolling if we go past bottom
|
|
||||||
if y > h then
|
|
||||||
apis.term.scroll(1)
|
|
||||||
y = h
|
|
||||||
apis.term.setCursorPos(x, y)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
apis.term.setCursorPos(x, y)
|
|
||||||
end
|
|
||||||
|
|
||||||
function driver.api.print(text)
|
|
||||||
write(text.."\n")
|
|
||||||
end
|
|
||||||
|
|
||||||
function driver.api.printInline(text)
|
|
||||||
write(text)
|
|
||||||
end
|
|
||||||
|
|
||||||
function driver.api.clear()
|
|
||||||
apis.term.clear()
|
|
||||||
apis.term.setCursorPos(1,1)
|
|
||||||
end
|
|
||||||
|
|
||||||
function driver.api.getSize()
|
|
||||||
return apis.term.getSize()
|
|
||||||
end
|
|
||||||
|
|
||||||
drivers[#drivers+1] = driver
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
|
|
||||||
-- <!ARCH>
|
|
||||||
-- @ICON$101003000000000000092492492490080000000010082000000010080400000010080080000010080400000010082002492010080000000010092492492490000000000000092492492490080000000010080000000010092492492490000000000000
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
local args={...}
|
|
||||||
local computer=args[1]
|
|
||||||
local logs={["nil"]=""}
|
|
||||||
local hooks={["nil"]=function()end}
|
|
||||||
local log={api={}}
|
|
||||||
|
|
||||||
local function convert_epoch(epoch)
|
|
||||||
return computer.date("[%b %d %H:%M:%S]", epoch/1000)
|
|
||||||
end
|
|
||||||
|
|
||||||
function log.getProcess(func)
|
|
||||||
if type(func)=="function" then
|
|
||||||
log.getProcess=func
|
|
||||||
else
|
|
||||||
return "Hyprkrnl"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function log.api.log(text, logID)
|
|
||||||
local appendedText=convert_epoch(computer.time()).." "..log.getProcess()..":[IN] "..text
|
|
||||||
logs[tostring(logID)]=logs[tostring(logID)]..appendedText.."\n"
|
|
||||||
hooks[tostring(logID)](appendedText)
|
|
||||||
end
|
|
||||||
|
|
||||||
function log.api.warn(text, logID)
|
|
||||||
local appendedText=convert_epoch(computer.time()).." "..log.getProcess()..":[WN] "..text
|
|
||||||
logs[tostring(logID)]=logs[tostring(logID)]..appendedText.."\n"
|
|
||||||
hooks[tostring(logID)](appendedText)
|
|
||||||
end
|
|
||||||
|
|
||||||
function log.api.fail(text, logID)
|
|
||||||
local appendedText=convert_epoch(computer.time()).." "..log.getProcess()..":[FA] "..text
|
|
||||||
logs[tostring(logID)]=logs[tostring(logID)]..appendedText.."\n"
|
|
||||||
hooks[tostring(logID)](appendedText)
|
|
||||||
end
|
|
||||||
|
|
||||||
function log.api.debug(text, logID)
|
|
||||||
local appendedText=convert_epoch(computer.time()).." "..log.getProcess()..":[DE] "..text
|
|
||||||
logs[tostring(logID)]=logs[tostring(logID)]..appendedText.."\n"
|
|
||||||
hooks[tostring(logID)](appendedText)
|
|
||||||
end
|
|
||||||
|
|
||||||
function log.api.error(text, logID)
|
|
||||||
local appendedText=convert_epoch(computer.time()).." "..log.getProcess()..":[ER] "..text
|
|
||||||
logs[tostring(logID)]=logs[tostring(logID)]..appendedText.."\n"
|
|
||||||
hooks[tostring(logID)](appendedText)
|
|
||||||
end
|
|
||||||
|
|
||||||
function log.api.get(logID)
|
|
||||||
return logs[tostring(logID)]
|
|
||||||
end
|
|
||||||
|
|
||||||
function log.setHook(func, logID)
|
|
||||||
hooks[tostring(logID)]=func
|
|
||||||
return {
|
|
||||||
removeHook=function()
|
|
||||||
hooks[tostring(logID)]=function()end
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
local UUID = 0
|
|
||||||
function log.api.createLog(logID)
|
|
||||||
if logs[tostring(logID)]~=nil then error("cannot create duplicate log") end
|
|
||||||
if logID==nil then UUID=UUID+1; logID=UUID end
|
|
||||||
hooks[tostring(logID)]=function()end
|
|
||||||
logs[tostring(logID)]=""
|
|
||||||
end
|
|
||||||
|
|
||||||
return log
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
### API:
|
|
||||||
---
|
|
||||||
```
|
|
||||||
getDisks():id, obj
|
|
||||||
|
|
||||||
```
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
[Oct 31 18:33:08] Hyprkrnl:[IN] Created logger
|
|
||||||
[Oct 31 18:33:08] Hyprkrnl:[IN] Loading globals...
|
|
||||||
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading string.lua
|
|
||||||
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading table.lua
|
|
||||||
[Oct 31 18:33:08] Hyprkrnl:[IN] Loading drivers...
|
|
||||||
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module ac.disks.kd
|
|
||||||
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module cc.disks.kd
|
|
||||||
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module cc.periph.kd
|
|
||||||
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module cc.terminal.kd
|
|
||||||
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module ccpc.disk.kd
|
|
||||||
[Oct 31 18:33:08] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
|
||||||
[Oct 31 18:33:08] Hyprkrnl:[DE] Sorting drivers...
|
|
||||||
[Oct 31 18:33:08] Hyprkrnl:[DE] Initializing drivers...
|
|
||||||
[Oct 31 18:33:08] Hyprkrnl:[IN] Loaded 3 drivers
|
|
||||||
[Oct 31 18:33:08] Hyprkrnl:[IN] Loading filesystem...
|
|
||||||
[Oct 31 18:33:08] Hyprkrnl:[IN] Bootdrive is disk
|
|
||||||
[Oct 31 18:33:08] Hyprkrnl:[IN] Loading system...
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
[Nov 12 22:17:07] Hyprkrnl:[IN] Created logger
|
|
||||||
[Nov 12 22:17:07] Hyprkrnl:[IN] Loading globals...
|
|
||||||
[Nov 12 22:17:07] Hyprkrnl:[IN] Loading drivers...
|
|
||||||
[Nov 12 22:17:07] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
|
||||||
[Nov 12 22:17:07] Hyprkrnl:[IN] Loaded 3 drivers
|
|
||||||
[Nov 12 22:17:07] Hyprkrnl:[IN] Loading filesystem...
|
|
||||||
[Nov 12 22:17:07] Hyprkrnl:[IN] Bootdrive is disk
|
|
||||||
[Nov 12 22:17:07] Hyprkrnl:[IN] Loading system...
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
[Oct 30 18:13:15] Hyprkrnl:[IN] Created logger
|
|
||||||
[Oct 30 18:13:15] Hyprkrnl:[IN] Loading globals...
|
|
||||||
[Oct 30 18:13:15] Hyprkrnl:[DE] Loading string.lua
|
|
||||||
[Oct 30 18:13:15] Hyprkrnl:[DE] Loading table.lua
|
|
||||||
[Oct 30 18:13:15] Hyprkrnl:[IN] Loading drivers...
|
|
||||||
[Oct 30 18:13:15] Hyprkrnl:[DE] Loading module ac.disks.kd
|
|
||||||
[Oct 30 18:13:15] Hyprkrnl:[DE] Loading module cc.disks.kd
|
|
||||||
[Oct 30 18:13:15] Hyprkrnl:[DE] Loading module cc.periph.kd
|
|
||||||
[Oct 30 18:13:15] Hyprkrnl:[DE] Loading module cc.terminal.kd
|
|
||||||
[Oct 30 18:13:15] Hyprkrnl:[DE] Loading module ccpc.disk.kd
|
|
||||||
[Oct 30 18:13:15] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
|
||||||
[Oct 30 18:13:15] Hyprkrnl:[DE] Sorting drivers...
|
|
||||||
[Oct 30 18:13:15] Hyprkrnl:[DE] Initializing drivers...
|
|
||||||
[Oct 30 18:13:15] Hyprkrnl:[IN] Loaded 3 drivers
|
|
||||||
[Oct 30 18:13:15] Hyprkrnl:[IN] Loading filesystem...
|
|
||||||
[Oct 30 18:13:15] Hyprkrnl:[IN] Bootdrive is disk
|
|
||||||
[Oct 30 18:13:15] Hyprkrnl:[IN] Loading system...
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
[Nov 13 20:06:54] Hyprkrnl:[IN] Created logger
|
|
||||||
[Nov 13 20:06:54] Hyprkrnl:[IN] Loading globals...
|
|
||||||
[Nov 13 20:06:54] Hyprkrnl:[IN] Loading drivers...
|
|
||||||
[Nov 13 20:06:54] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
|
||||||
[Nov 13 20:06:54] Hyprkrnl:[IN] Loaded 3 drivers
|
|
||||||
[Nov 13 20:06:54] Hyprkrnl:[IN] Loading filesystem...
|
|
||||||
[Nov 13 20:06:54] Hyprkrnl:[IN] Bootdrive is disk
|
|
||||||
[Nov 13 20:06:54] Hyprkrnl:[IN] Loading system...
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
[Nov 13 20:07:50] Hyprkrnl:[IN] Created logger
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[IN] Loading globals...
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[DE] Loading string.lua
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[DE] Loading table.lua
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[IN] Loading drivers...
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module ac.disks.kd
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module cc.disks.kd
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module cc.periph.kd
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module cc.terminal.kd
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module ccpc.disk.kd
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[DE] Sorting drivers...
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[DE] Initializing drivers...
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[IN] Loaded 3 drivers
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[IN] Loading filesystem...
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[IN] Bootdrive is disk
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[IN] Loading system...
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
[Oct 30 17:41:54] Hyprkrnl:[IN] Created logger
|
|
||||||
[Oct 30 17:41:54] Hyprkrnl:[IN] Loading globals...
|
|
||||||
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading require.lua
|
|
||||||
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading string.lua
|
|
||||||
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading table.lua
|
|
||||||
[Oct 30 17:41:54] Hyprkrnl:[IN] Loading drivers...
|
|
||||||
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading module ac.disks.kd
|
|
||||||
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading module cc.disks.kd
|
|
||||||
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading module cc.periph.kd
|
|
||||||
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading module cc.terminal.kd
|
|
||||||
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading module ccpc.disk.kd
|
|
||||||
[Oct 30 17:41:54] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
|
||||||
[Oct 30 17:41:54] Hyprkrnl:[DE] Sorting drivers...
|
|
||||||
[Oct 30 17:41:54] Hyprkrnl:[DE] Initializing drivers...
|
|
||||||
[Oct 30 17:41:54] Hyprkrnl:[IN] Loaded 3 drivers
|
|
||||||
[Oct 30 17:41:54] Hyprkrnl:[IN] Loading filesystem...
|
|
||||||
[Oct 30 17:41:54] Hyprkrnl:[IN] Bootdrive is disk
|
|
||||||
[Oct 30 17:41:54] Hyprkrnl:[IN] [REQUIRE]: Initialized FS
|
|
||||||
[Oct 30 17:41:54] Hyprkrnl:[IN] Loading hypervisor...
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
[Oct 30 17:43:09] Hyprkrnl:[IN] Created logger
|
|
||||||
[Oct 30 17:43:09] Hyprkrnl:[IN] Loading globals...
|
|
||||||
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading require.lua
|
|
||||||
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading string.lua
|
|
||||||
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading table.lua
|
|
||||||
[Oct 30 17:43:09] Hyprkrnl:[IN] Loading drivers...
|
|
||||||
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading module ac.disks.kd
|
|
||||||
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading module cc.disks.kd
|
|
||||||
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading module cc.periph.kd
|
|
||||||
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading module cc.terminal.kd
|
|
||||||
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading module ccpc.disk.kd
|
|
||||||
[Oct 30 17:43:09] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
|
||||||
[Oct 30 17:43:09] Hyprkrnl:[DE] Sorting drivers...
|
|
||||||
[Oct 30 17:43:09] Hyprkrnl:[DE] Initializing drivers...
|
|
||||||
[Oct 30 17:43:09] Hyprkrnl:[IN] Loaded 3 drivers
|
|
||||||
[Oct 30 17:43:09] Hyprkrnl:[IN] Loading filesystem...
|
|
||||||
[Oct 30 17:43:09] Hyprkrnl:[IN] Bootdrive is disk
|
|
||||||
[Oct 30 17:43:09] Hyprkrnl:[IN] [REQUIRE]: Initialized FS
|
|
||||||
[Oct 30 17:43:09] Hyprkrnl:[IN] Loading hypervisor...
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
[Oct 30 17:44:55] Hyprkrnl:[IN] Created logger
|
|
||||||
[Oct 30 17:44:55] Hyprkrnl:[IN] Loading globals...
|
|
||||||
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading require.lua
|
|
||||||
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading string.lua
|
|
||||||
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading table.lua
|
|
||||||
[Oct 30 17:44:55] Hyprkrnl:[IN] Loading drivers...
|
|
||||||
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading module ac.disks.kd
|
|
||||||
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading module cc.disks.kd
|
|
||||||
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading module cc.periph.kd
|
|
||||||
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading module cc.terminal.kd
|
|
||||||
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading module ccpc.disk.kd
|
|
||||||
[Oct 30 17:44:55] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
|
||||||
[Oct 30 17:44:55] Hyprkrnl:[DE] Sorting drivers...
|
|
||||||
[Oct 30 17:44:55] Hyprkrnl:[DE] Initializing drivers...
|
|
||||||
[Oct 30 17:44:55] Hyprkrnl:[IN] Loaded 3 drivers
|
|
||||||
[Oct 30 17:44:55] Hyprkrnl:[IN] Loading filesystem...
|
|
||||||
[Oct 30 17:44:55] Hyprkrnl:[IN] Bootdrive is disk
|
|
||||||
[Oct 30 17:44:55] Hyprkrnl:[IN] [REQUIRE]: Initialized FS
|
|
||||||
[Oct 30 17:44:55] Hyprkrnl:[IN] Loading hypervisor...
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
[Oct 30 17:45:15] Hyprkrnl:[IN] Created logger
|
|
||||||
[Oct 30 17:45:15] Hyprkrnl:[IN] Loading globals...
|
|
||||||
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading require.lua
|
|
||||||
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading string.lua
|
|
||||||
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading table.lua
|
|
||||||
[Oct 30 17:45:15] Hyprkrnl:[IN] Loading drivers...
|
|
||||||
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading module ac.disks.kd
|
|
||||||
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading module cc.disks.kd
|
|
||||||
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading module cc.periph.kd
|
|
||||||
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading module cc.terminal.kd
|
|
||||||
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading module ccpc.disk.kd
|
|
||||||
[Oct 30 17:45:15] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
|
||||||
[Oct 30 17:45:15] Hyprkrnl:[DE] Sorting drivers...
|
|
||||||
[Oct 30 17:45:15] Hyprkrnl:[DE] Initializing drivers...
|
|
||||||
[Oct 30 17:45:15] Hyprkrnl:[IN] Loaded 3 drivers
|
|
||||||
[Oct 30 17:45:15] Hyprkrnl:[IN] Loading filesystem...
|
|
||||||
[Oct 30 17:45:15] Hyprkrnl:[IN] Bootdrive is disk
|
|
||||||
[Oct 30 17:45:15] Hyprkrnl:[IN] [REQUIRE]: Initialized FS
|
|
||||||
[Oct 30 17:45:15] Hyprkrnl:[IN] Loading hypervisor...
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
[Oct 30 18:02:54] Hyprkrnl:[IN] Created logger
|
|
||||||
[Oct 30 18:02:54] Hyprkrnl:[IN] Loading globals...
|
|
||||||
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading require.lua
|
|
||||||
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading string.lua
|
|
||||||
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading table.lua
|
|
||||||
[Oct 30 18:02:54] Hyprkrnl:[IN] Loading drivers...
|
|
||||||
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading module ac.disks.kd
|
|
||||||
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading module cc.disks.kd
|
|
||||||
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading module cc.periph.kd
|
|
||||||
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading module cc.terminal.kd
|
|
||||||
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading module ccpc.disk.kd
|
|
||||||
[Oct 30 18:02:54] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
|
||||||
[Oct 30 18:02:54] Hyprkrnl:[DE] Sorting drivers...
|
|
||||||
[Oct 30 18:02:54] Hyprkrnl:[DE] Initializing drivers...
|
|
||||||
[Oct 30 18:02:54] Hyprkrnl:[IN] Loaded 3 drivers
|
|
||||||
[Oct 30 18:02:54] Hyprkrnl:[IN] Loading filesystem...
|
|
||||||
[Oct 30 18:02:54] Hyprkrnl:[IN] Bootdrive is disk
|
|
||||||
[Oct 30 18:02:54] Hyprkrnl:[IN] [REQUIRE]: Initialized FS
|
|
||||||
[Oct 30 18:02:54] Hyprkrnl:[IN] Loading hypervisor...
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
[Oct 30 18:03:46] Hyprkrnl:[IN] Created logger
|
|
||||||
[Oct 30 18:03:46] Hyprkrnl:[IN] Loading globals...
|
|
||||||
[Oct 30 18:03:46] Hyprkrnl:[DE] Loading require.lua
|
|
||||||
[Oct 30 18:03:46] Hyprkrnl:[DE] Loading string.lua
|
|
||||||
[Oct 30 18:03:46] Hyprkrnl:[DE] Loading table.lua
|
|
||||||
[Oct 30 18:03:46] Hyprkrnl:[IN] Loading drivers...
|
|
||||||
[Oct 30 18:03:46] Hyprkrnl:[DE] Loading module ac.disks.kd
|
|
||||||
[Oct 30 18:03:46] Hyprkrnl:[DE] Loading module cc.disks.kd
|
|
||||||
[Oct 30 18:03:46] Hyprkrnl:[DE] Loading module cc.periph.kd
|
|
||||||
[Oct 30 18:03:46] Hyprkrnl:[DE] Loading module cc.terminal.kd
|
|
||||||
[Oct 30 18:03:46] Hyprkrnl:[DE] Loading module ccpc.disk.kd
|
|
||||||
[Oct 30 18:03:46] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
|
||||||
[Oct 30 18:03:46] Hyprkrnl:[DE] Sorting drivers...
|
|
||||||
[Oct 30 18:03:46] Hyprkrnl:[DE] Initializing drivers...
|
|
||||||
[Oct 30 18:03:46] Hyprkrnl:[IN] Loaded 3 drivers
|
|
||||||
[Oct 30 18:03:46] Hyprkrnl:[IN] Loading filesystem...
|
|
||||||
[Oct 30 18:03:46] Hyprkrnl:[IN] Bootdrive is disk
|
|
||||||
[Oct 30 18:03:46] Hyprkrnl:[IN] [REQUIRE]: Initialized FS
|
|
||||||
[Oct 30 18:03:46] Hyprkrnl:[IN] Loading hypervisor...
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
{["debug"]=true,["prevError"]=[=[[string "/sys/Hyperion.s..."]:13: attempt to call field 'loadAsFunc' (a nil value)
|
|
||||||
stack traceback:
|
|
||||||
[string "/sys/Hyperion.s..."]:13: in function 'run'
|
|
||||||
[string "/sys/Hyperion.s..."]:20: in main chunk
|
|
||||||
[C]: in function 'xpcall'
|
|
||||||
[string "local args={......"]:121: in function 'runAsKernel'
|
|
||||||
[string "local args={......"]:224: in function 'kernel'
|
|
||||||
kernel:22: in function '?'
|
|
||||||
kernel:69: in main chunk
|
|
||||||
[C]: in function 'xpcall'
|
|
||||||
preboot.cc:176: in function <preboot.cc:175>
|
|
||||||
[C]: in function 'pcall'
|
|
||||||
preboot.cc:175: in function <preboot.cc:174>]=],["logNum"]=4,["errorCount"]=0}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
[Nov 13 20:07:50] Hyprkrnl:[IN] Created logger
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[IN] Loading globals...
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[DE] Loading string.lua
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[DE] Loading table.lua
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[IN] Loading drivers...
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module ac.disks.kd
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module cc.disks.kd
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module cc.periph.kd
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module cc.terminal.kd
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module ccpc.disk.kd
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[DE] Sorting drivers...
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[DE] Initializing drivers...
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[IN] Loaded 3 drivers
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[IN] Loading filesystem...
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[IN] Bootdrive is disk
|
|
||||||
[Nov 13 20:07:50] Hyprkrnl:[IN] Loading system...
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
local biosData = ({...})[1]
|
|
||||||
local disks = {}
|
|
||||||
|
|
||||||
for i,v in component.list() do
|
|
||||||
if i == "disk" then
|
|
||||||
disks[v.id]=v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local bootDisk = disks[biosData.bootDrive.open("/config").read()]
|
|
||||||
|
|
||||||
if not bootDisk.type=="udd" then
|
|
||||||
error("invalid")
|
|
||||||
end
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
disk_56
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
local biosData = ({...})[1]
|
|
||||||
local apis={}
|
|
||||||
|
|
||||||
local lua = {
|
|
||||||
coroutine = true,
|
|
||||||
debug = true,
|
|
||||||
_HOST = true,
|
|
||||||
_VERSION = true,
|
|
||||||
assert = true,
|
|
||||||
collectgarbage = true,
|
|
||||||
error = true,
|
|
||||||
gcinfo = true,
|
|
||||||
getfenv = true,
|
|
||||||
getmetatable = true,
|
|
||||||
ipairs = true,
|
|
||||||
__inext = true,
|
|
||||||
load = true,
|
|
||||||
math = true,
|
|
||||||
next = true,
|
|
||||||
pairs = true,
|
|
||||||
pcall = true,
|
|
||||||
rawequal = true,
|
|
||||||
rawget = true,
|
|
||||||
rawlen = true,
|
|
||||||
rawset = true,
|
|
||||||
select = true,
|
|
||||||
setfenv = true,
|
|
||||||
setmetatable = true,
|
|
||||||
string = true,
|
|
||||||
table = true,
|
|
||||||
tonumber = true,
|
|
||||||
tostring = true,
|
|
||||||
type = true,
|
|
||||||
xpcall = true
|
|
||||||
}
|
|
||||||
|
|
||||||
for i,v in ipairs(_G) do
|
|
||||||
if not lua[i] then
|
|
||||||
apis[i]=v
|
|
||||||
_G[i]=nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function getFile(path)
|
|
||||||
return biosData.bootDrive:open(path).read()
|
|
||||||
end
|
|
||||||
|
|
||||||
local computer = apis.component.getFirst("computer")
|
|
||||||
local kernel = load(getFile("/boot/Hyprkrnl.sys"), "@kernel", "t", _G)
|
|
||||||
kernel("ac", apis, biosData.bootDrive.id, apis.component.getFirst("screen"), computer.getMachineEvent)
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
-- UnBIOS by JackMacWindows
|
|
||||||
-- This will undo most of the changes/additions made in the BIOS, but some things may remain wrapped if `debug` is unavailable
|
|
||||||
-- To use, just place a `bios.lua` in the root of the drive, and run this program
|
|
||||||
-- Here's a list of things that are irreversibly changed:
|
|
||||||
-- * both `bit` and `bit32` are kept for compatibility
|
|
||||||
-- * string metatable blocking (on old versions of CC)
|
|
||||||
-- In addition, if `debug` is not available these things are also irreversibly changed:
|
|
||||||
-- * old Lua 5.1 `load` function (for loading from a function)
|
|
||||||
-- * `loadstring` prefixing (before CC:T 1.96.0)
|
|
||||||
-- * `http.request`
|
|
||||||
-- * `os.shutdown` and `os.reboot`
|
|
||||||
-- * `peripheral`
|
|
||||||
-- * `turtle.equip[Left|Right]`
|
|
||||||
-- Licensed under the MIT license
|
|
||||||
if _HOST:find("UnBIOS") then return end
|
|
||||||
local keptAPIs = {keys=true, bit32 = true, bit = true, ccemux = true, config = true, coroutine = true, debug = true, fs = true, http = true, mounter = true, os = true, periphemu = true, peripheral = true, redstone = true, rs = true, term = true, utf8 = true, _HOST = true, _CC_DEFAULT_SETTINGS = true, _CC_DISABLE_LUA51_FEATURES = true, _VERSION = true, assert = true, collectgarbage = true, error = true, gcinfo = true, getfenv = true, getmetatable = true, ipairs = true, __inext = true,load = true, loadstring = true, math = true, newproxy = true, next = true, pairs = true, pcall = true, rawequal = true, rawget = true, rawlen = true, rawset = true, select = true, setfenv = true, setmetatable = true, string = true, table = true, tonumber = true, tostring = true, type = true, unpack = true, xpcall = true, turtle = true, pocket = true, commands = true, _G = true}
|
|
||||||
local t = {}
|
|
||||||
for k in pairs(_G) do if not keptAPIs[k] then table.insert(t, k) end end
|
|
||||||
for _,k in ipairs(t) do _G[k] = nil end
|
|
||||||
local native = _G.term.native()
|
|
||||||
for _, method in ipairs {"nativePaletteColor", "nativePaletteColour", "screenshot"} do native[method] = _G.term[method] end
|
|
||||||
_G.term = native
|
|
||||||
if _G.http then
|
|
||||||
_G.http.checkURL = _G.http.checkURLAsync
|
|
||||||
_G.http.websocket = _G.http.websocketAsync
|
|
||||||
end
|
|
||||||
if _G.commands then _G.commands = _G.commands.native end
|
|
||||||
if _G.turtle then _G.turtle.native, _G.turtle.craft = nil end
|
|
||||||
local delete = {os = {"version", "pullEventRaw", "pullEvent", "run", "loadAPI", "unloadAPI", "sleep"}, http = _G.http and {"get", "post", "put", "delete", "patch", "options", "head", "trace", "listen", "checkURLAsync", "websocketAsync"}, fs = {"complete", "isDriveRoot"}}
|
|
||||||
for k,v in pairs(delete) do for _,a in ipairs(v) do _G[k][a] = nil end end
|
|
||||||
_G._HOST = _G._HOST .. " (UnBIOS)"
|
|
||||||
-- Set up TLCO
|
|
||||||
-- This functions by crashing `rednet.run` by removing `os.pullEventRaw`. Normally
|
|
||||||
-- this would cause `parallel` to throw an error, but we replace `error` with an
|
|
||||||
-- empty placeholder to let it continue and return without throwing. This results
|
|
||||||
-- in the `pcall` returning successfully, preventing the error-displaying code
|
|
||||||
-- from running - essentially making it so that `os.shutdown` is called immediately
|
|
||||||
-- after the new BIOS exits.
|
|
||||||
--
|
|
||||||
-- From there, the setup code is placed in `term.native` since it's the first
|
|
||||||
-- thing called after `parallel` exits. This loads the new BIOS and prepares it
|
|
||||||
-- for execution. Finally, it overwrites `os.shutdown` with the new function to
|
|
||||||
-- allow it to be the last function called in the original BIOS, and returns.
|
|
||||||
-- From there execution continues, calling the `term.redirect` dummy, skipping
|
|
||||||
-- over the error-handling code (since `pcall` returned ok), and calling
|
|
||||||
-- `os.shutdown()`. The real `os.shutdown` is re-added, and the new BIOS is tail
|
|
||||||
-- called, which effectively makes it run as the main chunk.
|
|
||||||
local olderror = error
|
|
||||||
_G.error = function() end
|
|
||||||
_G.term.redirect = function() end
|
|
||||||
function _G.term.native()
|
|
||||||
_G.term.native = nil
|
|
||||||
_G.term.redirect = nil
|
|
||||||
_G.error = olderror
|
|
||||||
term.setBackgroundColor(32768)
|
|
||||||
term.setTextColor(1)
|
|
||||||
term.setCursorPos(1, 1)
|
|
||||||
term.setCursorBlink(true)
|
|
||||||
term.clear()
|
|
||||||
local file = fs.open("/boot/cc/bootloader.cc", "r")
|
|
||||||
if file == nil then
|
|
||||||
term.setCursorBlink(false)
|
|
||||||
term.setTextColor(16384)
|
|
||||||
term.write("Could not find /boot/cc/bootloader.cc. UnBIOS cannot continue.")
|
|
||||||
term.setCursorPos(1, 2)
|
|
||||||
term.write("Press any key to continue")
|
|
||||||
coroutine.yield("key")
|
|
||||||
os.shutdown()
|
|
||||||
end
|
|
||||||
local fn, err = loadstring(file.readAll(), "@bootloader.cc")
|
|
||||||
file.close()
|
|
||||||
if fn == nil then
|
|
||||||
term.setCursorBlink(false)
|
|
||||||
term.setTextColor(16384)
|
|
||||||
term.write("Could not load /boot/cc/bootloader.cc. UnBIOS cannot continue.")
|
|
||||||
term.setCursorPos(1, 2)
|
|
||||||
term.write(err)
|
|
||||||
term.setCursorPos(1, 3)
|
|
||||||
term.write("Press any key to continue")
|
|
||||||
coroutine.yield("key")
|
|
||||||
os.shutdown()
|
|
||||||
end
|
|
||||||
setfenv(fn, _G)
|
|
||||||
local oldshutdown = os.shutdown
|
|
||||||
os.shutdown = function()
|
|
||||||
os.shutdown = oldshutdown
|
|
||||||
return fn()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if debug then
|
|
||||||
-- Restore functions that were overwritten in the BIOS
|
|
||||||
-- Apparently this has to be done *after* redefining term.native
|
|
||||||
local function restoreValue(tab, idx, name, hint)
|
|
||||||
local i, key, value = 1, debug.getupvalue(tab[idx], hint)
|
|
||||||
while key ~= name and key ~= nil do
|
|
||||||
key, value = debug.getupvalue(tab[idx], i)
|
|
||||||
i=i+1
|
|
||||||
end
|
|
||||||
tab[idx] = value or tab[idx]
|
|
||||||
end
|
|
||||||
restoreValue(_G, "loadstring", "nativeloadstring", 1)
|
|
||||||
restoreValue(_G, "load", "nativeload", 5)
|
|
||||||
if http then restoreValue(http, "request", "nativeHTTPRequest", 3) end
|
|
||||||
restoreValue(os, "shutdown", "nativeShutdown", 1)
|
|
||||||
restoreValue(os, "reboot", "nativeReboot", 1)
|
|
||||||
if turtle then
|
|
||||||
restoreValue(turtle, "equipLeft", "v", 1)
|
|
||||||
restoreValue(turtle, "equipRight", "v", 1)
|
|
||||||
end
|
|
||||||
do
|
|
||||||
local i, key, value = 1, debug.getupvalue(peripheral.isPresent, 2)
|
|
||||||
while key ~= "native" and key ~= nil do
|
|
||||||
key, value = debug.getupvalue(peripheral.isPresent, i)
|
|
||||||
i=i+1
|
|
||||||
end
|
|
||||||
_G.peripheral = value or peripheral
|
|
||||||
end
|
|
||||||
end
|
|
||||||
os.shutdown()
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
local apis={}
|
|
||||||
|
|
||||||
local lua = {
|
|
||||||
coroutine = true,
|
|
||||||
debug = true,
|
|
||||||
_HOST = true,
|
|
||||||
_VERSION = true,
|
|
||||||
assert = true,
|
|
||||||
collectgarbage = true,
|
|
||||||
error = true,
|
|
||||||
gcinfo = true,
|
|
||||||
getfenv = true,
|
|
||||||
getmetatable = true,
|
|
||||||
ipairs = true,
|
|
||||||
__inext = true,
|
|
||||||
load = true,
|
|
||||||
math = true,
|
|
||||||
next = true,
|
|
||||||
pairs = true,
|
|
||||||
pcall = true,
|
|
||||||
rawequal = true,
|
|
||||||
rawget = true,
|
|
||||||
rawlen = true,
|
|
||||||
rawset = true,
|
|
||||||
select = true,
|
|
||||||
setfenv = true,
|
|
||||||
setmetatable = true,
|
|
||||||
string = true,
|
|
||||||
table = true,
|
|
||||||
tonumber = true,
|
|
||||||
tostring = true,
|
|
||||||
type = true,
|
|
||||||
xpcall = true
|
|
||||||
}
|
|
||||||
|
|
||||||
for i,v in ipairs(_G) do
|
|
||||||
if not lua[i] then
|
|
||||||
apis[i]=v
|
|
||||||
_G[i]=nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function getFile(path)
|
|
||||||
if path:sub(1,1) ~= "/" then
|
|
||||||
path="/"..path
|
|
||||||
end
|
|
||||||
local file = apis.fs.open("/root"..path)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function write(text)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
local event_queue = {}
|
|
||||||
local function addEventRaw(...)
|
|
||||||
event_queue[#event_queue+1] = {...}
|
|
||||||
end
|
|
||||||
|
|
||||||
local function getEvent()
|
|
||||||
local event = event_queue[1]
|
|
||||||
event_queue = {table.unpack(event_queue, 2)}
|
|
||||||
return table.unpack(event)
|
|
||||||
end
|
|
||||||
|
|
||||||
local lkeys={}
|
|
||||||
lkeys[keys.enter]="\n"
|
|
||||||
lkeys[keys.backspace]="\b"
|
|
||||||
lkeys[keys.tab]="\t"
|
|
||||||
|
|
||||||
local kernel = load(getFile("/boot/Hyprkrnl.sys"), "@kernel", "t", _G)
|
|
||||||
local kernel_coro = coroutine.create(function()
|
|
||||||
kernel("cc", apis, "internal", {
|
|
||||||
print=function(text)
|
|
||||||
write(text)
|
|
||||||
write("\n")
|
|
||||||
end,
|
|
||||||
printInline=function(text)
|
|
||||||
write(text)
|
|
||||||
end,
|
|
||||||
clear=function()
|
|
||||||
apis.term.clear()
|
|
||||||
apis.term.setCursorPos(1,1)
|
|
||||||
end
|
|
||||||
}, getEvent)
|
|
||||||
end)
|
|
||||||
|
|
||||||
debug.sethook(kernel_coro, function() coroutine.yield("CC:TWEAKED", "CORO_TIMEOUT") end, "l", 3000)
|
|
||||||
while true do
|
|
||||||
local ret = {coroutine.resume(kernel_coro)}
|
|
||||||
if coroutine.status(kernel_coro) == "dead" then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
local timer = os.startTimer(0)
|
|
||||||
local exit = false
|
|
||||||
repeat
|
|
||||||
local event = {coroutine.yield()}
|
|
||||||
if event[1] == "timer" and event[2]==timer then
|
|
||||||
exit=true
|
|
||||||
elseif event[1]==nil then
|
|
||||||
elseif event[1]=="key" then
|
|
||||||
addEventRaw("keyPressed", 1, event[2])
|
|
||||||
if lkeys[event[2]] then
|
|
||||||
addEventRaw("keyTyped", 1, lkeys[event[2]])
|
|
||||||
end
|
|
||||||
elseif event[1]=="char" then
|
|
||||||
addEventRaw("keyTyped", 1, event[2])
|
|
||||||
elseif event[1]=="key_up" then
|
|
||||||
addEventRaw("keyReleased", 1, event[2])
|
|
||||||
elseif event[1]=="disk" then
|
|
||||||
addEventRaw("componentAdded", "disk", sandboxedFS.new(api.disk.getMountPath(event[2]), apis.disk.getID(event[2])))
|
|
||||||
elseif event[1]=="disk_eject" then
|
|
||||||
addEventRaw("componentRemoved", "disk")
|
|
||||||
end
|
|
||||||
until exit
|
|
||||||
end
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
local computer=component.getFirst("computer")
|
|
||||||
computer.beep(800, 0.2, 1)
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
local term=component.getFirst("screen")
|
|
||||||
term.clear()
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
local args={...}
|
|
||||||
local term=component.getFirst("screen")
|
|
||||||
local hpv=require("hypervisor")
|
|
||||||
local fs=require("filesystem")
|
|
||||||
if not (fs.exists("/bin/"..args[1]) and (not fs.isDir("/bin/"..args[1]))) then error("not a file") end
|
|
||||||
local handle = hpv.createProcessFromFile("/bin/"..args[1], args[1], table.unpack(args, 2))
|
|
||||||
local pid=handle.getID()
|
|
||||||
local debugger=hpv.attachDebugger(handle)
|
|
||||||
debugger.addEvent("threadReturn", function(...)
|
|
||||||
term.print("threadReturn", ...)
|
|
||||||
end)
|
|
||||||
debugger.addEvent("threadError", function(...)
|
|
||||||
term.print("threadError", ...)
|
|
||||||
end)
|
|
||||||
while hpv.isrunning(pid) do
|
|
||||||
sleep(0.5)
|
|
||||||
end
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
local term=component.getFirst("screen")
|
|
||||||
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | root@hyperion ")
|
|
||||||
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ------------- ")
|
|
||||||
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | OS: Hyperion AC ")
|
|
||||||
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | Host: $Computer_id ")
|
|
||||||
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | Kernel: Hyprkrnl 1.0.0 ")
|
|
||||||
term.print("⠀⢷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⡞⠀ | Uptime: 2:00 ")
|
|
||||||
term.print("⠀⠈⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⠁⠀ | Packages: 204 ")
|
|
||||||
term.print("⠀⠀⠘⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⣿⣿⠃⠀⠀ | Shell: DoomieShell ")
|
|
||||||
term.print("⠀⠀⠀⢹⣿⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⡏⠀⠀⠀ | Resolution: $monitor_size ")
|
|
||||||
term.print("⠀⠀⠀⠀⢻⣿⣿⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⣿⡟⠀⠀⠀⠀ | DE: ComputeX ")
|
|
||||||
term.print("⠀⠀⠀⠀⠈⢿⣿⣿⣿⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠀ | WM: HWMS ")
|
|
||||||
term.print("⠀⠀⠀⠀⠀⠈⠛⢿⣿⣿⣿⣿⣿⣦⡀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⣿⣿⡿⠋⠁⠀⠀⠀⠀⠀ | WM Theme: Standard dark ")
|
|
||||||
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⢿⣿⣿⣿⣿⣦⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⣠⣿⣿⣿⣿⡿⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀ | Theme: Standard dark ")
|
|
||||||
term.print("⠀⠀⠀⠀⠀⠀⠀⢠⣀⠀⠀⠈⠛⢿⣿⣿⣷⣄⠀⠀⣿⣿⣿⣿⣿⣿⠀⠀⣠⣾⣿⣿⡿⠛⠁⠀⠀⣀⡄⠀⠀⠀⠀⠀⠀⠀ | Icons: Standard ")
|
|
||||||
term.print("⠀⠀⠀⠀⠀⠀⠀⠈⢿⣿⣶⣤⣀⠀⠈⠛⢿⣿⠀⠀⣿⣿⣿⣿⣿⣿⠀⠀⣿⡿⠛⠁⠀⣀⣤⣶⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀ | Terminal: Goterm ")
|
|
||||||
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣶⡄⢸⣿⠀⠀⠸⣿⣿⣿⣿⡏⠀⠀⣿⡇⢠⣶⣿⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀ | ")
|
|
||||||
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⠿⠿⠿⠟⠛⠃⢸⣿⠀⠀⠀⠹⣿⣿⡟⠀⠀⠀⣿⡇⠘⠛⠻⠿⠿⠿⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ")
|
|
||||||
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⡄⢸⣿⡀⠀⠀⠀⢻⡿⠁⠀⠀⢀⣿⡇⢠⣤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ")
|
|
||||||
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⠇⠘⢿⣿⣦⡀⠀⠀⠁⠀⢀⣴⣿⡿⠃⠸⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ")
|
|
||||||
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⡿⠋⠀⠀⠀⠀⠙⣿⣿⣦⡀⢀⣴⣿⡿⠋⠀⠀⠀⠈⠙⠿⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ")
|
|
||||||
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣿⣿⣿⣿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ")
|
|
||||||
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ")
|
|
||||||
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ")
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
local function func(tble,space)
|
|
||||||
space=space or ""
|
|
||||||
for i,v in pairs(tble) do
|
|
||||||
print(space..tostring(i).." | "..tostring(v))
|
|
||||||
if type(v) == "table" then
|
|
||||||
if i=="_G" then else
|
|
||||||
func(v,space.." ")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
func(_G)
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
local computer=component.getFirst("computer")
|
|
||||||
computer.reboot()
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
local stringBuffer=""
|
|
||||||
local hpv = require("hypervisor")
|
|
||||||
local fs = require("filesystem")
|
|
||||||
local term=component.getFirst("screen")
|
|
||||||
local captureInput=true
|
|
||||||
local exit=false
|
|
||||||
local function printPrefix()
|
|
||||||
term.printInline("root@testharness:/& ")
|
|
||||||
end
|
|
||||||
|
|
||||||
local function tokenize(str)
|
|
||||||
return string.split(str, " ")
|
|
||||||
end
|
|
||||||
|
|
||||||
hpv.addEvent("keyTyped",function(...)
|
|
||||||
if not captureInput then return end
|
|
||||||
local char=({...})[1]
|
|
||||||
if char == "\n" then
|
|
||||||
captureInput=false
|
|
||||||
term.print("")
|
|
||||||
elseif char == "\b" then
|
|
||||||
if #stringBuffer > 0 then
|
|
||||||
stringBuffer=stringBuffer:sub(1,#stringBuffer-1)
|
|
||||||
term.printInline(char)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
stringBuffer=stringBuffer..char
|
|
||||||
term.printInline(char)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
printPrefix()
|
|
||||||
while not exit do
|
|
||||||
while captureInput do
|
|
||||||
sleep(1)
|
|
||||||
end
|
|
||||||
local token = tokenize(stringBuffer)
|
|
||||||
if token[1] == "exit" then
|
|
||||||
exit=true
|
|
||||||
elseif fs.exists("/bin/"..token[1]) and (not fs.isDir("/bin/"..token[1])) then
|
|
||||||
local handle = hpv.createProcessFromFile("/bin/"..token[1], token[1], table.unpack(token, 2))
|
|
||||||
local pid=handle.getID()
|
|
||||||
while hpv.isrunning(pid) do
|
|
||||||
sleep(0.5)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
term.print("Command not recognized")
|
|
||||||
end
|
|
||||||
stringBuffer=""
|
|
||||||
printPrefix()
|
|
||||||
captureInput=true
|
|
||||||
end
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
local print=component.getFirst("screen").print
|
|
||||||
print("test")
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
local hpv=require("hypervisor")
|
|
||||||
local term=component.getFirst("screen")
|
|
||||||
|
|
||||||
term.clear()
|
|
||||||
local function m(str, m)
|
|
||||||
if #str>m then
|
|
||||||
return str:sub(1,m-1).."- "
|
|
||||||
else
|
|
||||||
while #str~=m do
|
|
||||||
str=str.." "
|
|
||||||
end
|
|
||||||
return str.." "
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for i in hpv.listProc() do
|
|
||||||
term.print(m(i.name, 15)..m(i.status, 7)..m(i.pid, 4))
|
|
||||||
for _,v in ipairs(i.threads) do
|
|
||||||
if v.name~="main" then
|
|
||||||
term.print(" "..m(v.name, 12)..m(v.status, 7))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
local errors={}
|
|
||||||
local function tables_equal(t1, t2)
|
|
||||||
if #t1 ~= #t2 then return false end
|
|
||||||
for i = 1, #t1 do
|
|
||||||
if t1[i] ~= t2[i] then return false end
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
local function run_test(name, test_func)
|
|
||||||
local status, err = pcall(test_func)
|
|
||||||
if status then
|
|
||||||
print("[PASS] " .. name)
|
|
||||||
else
|
|
||||||
print("[FAIL] " .. name .. ": " .. err)
|
|
||||||
errors[name]=err
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@@ -1,215 +0,0 @@
|
|||||||
local function rand()
|
|
||||||
if math.random(0,1)==0 then return true else return false end
|
|
||||||
end
|
|
||||||
function coroutine.resumeWithTimeout(CORO, TIME, ...)
|
|
||||||
return rand(), coroutine.resume(CORO, ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Copyright (C) 2025 ASTRONAND
|
|
||||||
-- Get boot arguments
|
|
||||||
local bootArgs=({...})[1]
|
|
||||||
local bootDrive=bootArgs.bootDrive
|
|
||||||
local LOG_TEXT=""
|
|
||||||
local log={}
|
|
||||||
local term
|
|
||||||
local bootData=load("return "..(bootDrive:open("var/log/kernel/bootData").read() or "{}"))()
|
|
||||||
local computer=component.getFirst("computer")
|
|
||||||
local startup=true
|
|
||||||
local osleep=sleep
|
|
||||||
local oldYield=coroutine.yield
|
|
||||||
|
|
||||||
function coroutine.yield(...)
|
|
||||||
if not startup then
|
|
||||||
if coroutine.isyieldable(coroutine.running()) then
|
|
||||||
oldYield(...)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Find terminal(s)
|
|
||||||
local terminals={}
|
|
||||||
for i,v in component.list() do
|
|
||||||
if i == "screen" then
|
|
||||||
terminals[#terminals+1] = v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
term={
|
|
||||||
print=function(...)
|
|
||||||
for _,v in ipairs(terminals) do
|
|
||||||
v.print(...)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
printInline=function(...)
|
|
||||||
for _,v in ipairs(terminals) do
|
|
||||||
v.printInline(...)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
clear=function(...)
|
|
||||||
for _,v in ipairs(terminals) do
|
|
||||||
v.clear(...)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
term.print("Welcome to Hyperion OS")
|
|
||||||
-- Difine logging lib
|
|
||||||
local function getPName(func)
|
|
||||||
if type(func) == "function" then
|
|
||||||
getPName=func
|
|
||||||
end
|
|
||||||
return "Hyprkrnl"
|
|
||||||
end
|
|
||||||
|
|
||||||
function log.log(text)
|
|
||||||
if startup then term.print("[ OK ] "..getPName()..": "..text) end
|
|
||||||
LOG_TEXT=LOG_TEXT.."[ OK ] "..getPName()..": "..text.."\n"
|
|
||||||
end
|
|
||||||
|
|
||||||
function log.error(text)
|
|
||||||
if startup then term.print("[FAILED] "..getPName()..": "..text) end
|
|
||||||
LOG_TEXT=LOG_TEXT.."[FAILED] "..getPName()..": "..text.."\n"
|
|
||||||
end
|
|
||||||
|
|
||||||
function log.warn(text)
|
|
||||||
if startup then term.print("[ WARN ] "..getPName()..": "..text) end
|
|
||||||
LOG_TEXT=LOG_TEXT.."[ WARN ] "..getPName()..": "..text.."\n"
|
|
||||||
end
|
|
||||||
|
|
||||||
function log.raw(text)
|
|
||||||
if startup then term.print(" "..getPName()..": "..text) end
|
|
||||||
LOG_TEXT=LOG_TEXT.." "..getPName()..": "..text.."\n"
|
|
||||||
end
|
|
||||||
|
|
||||||
function log.get()
|
|
||||||
return LOG_TEXT
|
|
||||||
end
|
|
||||||
|
|
||||||
local function t2t(table)
|
|
||||||
local output = "{"
|
|
||||||
for i,v in pairs(table) do
|
|
||||||
local coma=true
|
|
||||||
if type(i) == "string" then
|
|
||||||
output=output.."[\""..i.."\"]="
|
|
||||||
end
|
|
||||||
if type(v) == "table" then
|
|
||||||
if v == table then
|
|
||||||
output=string.sub(output,1,#output-(#i+1))
|
|
||||||
coma=false
|
|
||||||
else
|
|
||||||
output=output..t2t(v)
|
|
||||||
end
|
|
||||||
elseif type(v) == "string" then
|
|
||||||
output=output.."[=["..v.."]=]"
|
|
||||||
elseif type(v) == "number" then
|
|
||||||
output=output..tostring(v)
|
|
||||||
elseif type(v) == "function" then
|
|
||||||
output=string.sub(output,1,#output-(#i+1))
|
|
||||||
coma=false
|
|
||||||
end
|
|
||||||
if coma then
|
|
||||||
output=output..","
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if #table>0 or string.sub(output,#output,#output) == "," then
|
|
||||||
output=string.sub(output,1,#output-1)
|
|
||||||
end
|
|
||||||
output=output.."}"
|
|
||||||
return output
|
|
||||||
end
|
|
||||||
|
|
||||||
-- My favorite function
|
|
||||||
local function PANIC(err,lvl)
|
|
||||||
term.clear()
|
|
||||||
term.print(LOG_TEXT)
|
|
||||||
term.printInline("KERNEL PANIC: "..err)
|
|
||||||
computer.beep(800,0.2)
|
|
||||||
osleep(0.02)
|
|
||||||
if err==bootData.prevError then
|
|
||||||
bootData.errorCount=bootData.errorCount+1
|
|
||||||
else
|
|
||||||
bootData.prevError=err
|
|
||||||
bootData.errorCount=0
|
|
||||||
end
|
|
||||||
bootDrive:open("var/log/kernel/bootData").write(t2t(bootData))
|
|
||||||
if bootData.errorCount < 4 then
|
|
||||||
term.print("")
|
|
||||||
term.print("Atempting reboot...")
|
|
||||||
osleep(0.5)
|
|
||||||
computer.reboot()
|
|
||||||
elseif bootData.errorCount > 3 then
|
|
||||||
term.print("")
|
|
||||||
term.print("boot determined to be unrecoverable...")
|
|
||||||
osleep(0.5)
|
|
||||||
computer.shutdown()
|
|
||||||
end
|
|
||||||
while true do
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function runAsKernel(path, args)
|
|
||||||
local ok,err,extra = pcall(load(bootDrive:open(path):read()), args)
|
|
||||||
if not ok then
|
|
||||||
PANIC(path.." failed to load/execute err:\n"..(err or ""))
|
|
||||||
end
|
|
||||||
return err,extra
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Add libray modifications+
|
|
||||||
for _,v in ipairs(bootDrive:list("/sys/kernel/glib")) do
|
|
||||||
log.raw("running "..v)
|
|
||||||
runAsKernel("/sys/kernel/glib/"..v)
|
|
||||||
log.log("Loaded "..v)
|
|
||||||
end
|
|
||||||
log.log("Finished loading global librarys")
|
|
||||||
local sudoMaster={}
|
|
||||||
local auth=runAsKernel("sys/kernel/userManager.sys",{masterKey=sudoMaster,bootDrive=bootDrive})
|
|
||||||
log.log("Created UE Manager")
|
|
||||||
local fs=runAsKernel("sys/kernel/filesystem.sys",{bootDrive=bootDrive,auth=auth})
|
|
||||||
log.log("Initailized filesystem")
|
|
||||||
local io=runAsKernel("sys/kernel/ioManager.sys",{masterKey=sudoMaster})
|
|
||||||
log.log("Started ioManager")
|
|
||||||
local packages={filesystem=fs, auth=auth, logging=log, term=term}
|
|
||||||
local req=runAsKernel("sys/modules/require",{filesystem=fs,logging=log, preload=packages})
|
|
||||||
log.log("Loaded require")
|
|
||||||
local setRequire
|
|
||||||
local requ=req.makeRequire("lib/?;lib/?/init;sys/modules/?;sys/modules/?/init",packages)
|
|
||||||
_G.require, setRequire = requ.require, requ.load
|
|
||||||
setRequire("require",req)
|
|
||||||
log.log("Initailized require")
|
|
||||||
|
|
||||||
local code=fs.open("sys/kernel/hypervisor.sys","xe", _G)
|
|
||||||
|
|
||||||
if not code then
|
|
||||||
PANIC("System failed to load")
|
|
||||||
end
|
|
||||||
local ok, system=pcall(code, {masterKey=sudoMaster, setRequire=setRequire, pname=getPName})
|
|
||||||
if not ok then
|
|
||||||
PANIC("Hypervisor failed to execute ERR:\n"..hypervisor)
|
|
||||||
end
|
|
||||||
log.log("Loaded hypervisor")
|
|
||||||
log.raw("Making kernel process")
|
|
||||||
|
|
||||||
hypervisor(function()
|
|
||||||
local hpv=require("hypervisor")
|
|
||||||
local thread=require("thread")
|
|
||||||
log.log("Created kernel process")
|
|
||||||
hpv.createProcessFromFile("sys/os/init.lua", "systemd")
|
|
||||||
thread.create(function()
|
|
||||||
while true do
|
|
||||||
local event = {computer.getMachineEvent()}
|
|
||||||
if event[1] == nil then
|
|
||||||
coroutine.yield()
|
|
||||||
else
|
|
||||||
hpv.triggerEvent("all", event[1], table.unpack(event,2))
|
|
||||||
coroutine.yield()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end, "eventHandler")
|
|
||||||
|
|
||||||
while true do
|
|
||||||
coroutine.yield()
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
term.print("Goodbye :)")
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
if
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
root:0:root
|
|
||||||
sudo:1:root
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
root:x:0:0::/root:/bin/pshell
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
root:$5$9a7f8e2b4cd01ac18d7cbb4da74f5c1e$53326d6a24ef6a050b5ef88dbbe5906d4afbcf191725f9750e44a818ab22bd62:0
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
https://git.astronand.dev/Hyperion-OS/packages/raw/branch/main/spm/
|
|
||||||
https://git.astronand.dev/Hyperion-OS/packages/raw/branch/main/ac/
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
root
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=Shutdown of system
|
|
||||||
Conflicts=reboot.target halt.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
function color.screen8(r, g, b)
|
|
||||||
-- Ensure input is within valid 0-255 range
|
|
||||||
r = math.max(0, math.min(255, r))
|
|
||||||
g = math.max(0, math.min(255, g))
|
|
||||||
b = math.max(0, math.min(255, b))
|
|
||||||
|
|
||||||
-- Convert 8-bit to reduced bit depth
|
|
||||||
local r3 = math.floor(r / 32) -- 8-bit to 3-bit
|
|
||||||
local g3 = math.floor(g / 32) -- 8-bit to 3-bit
|
|
||||||
local b2 = math.floor(b / 64) -- 8-bit to 2-bit
|
|
||||||
|
|
||||||
-- Pack into a single 8-bit value: RRR GGG BB
|
|
||||||
local rgb332 = (r3 << 5) | (g3 << 2) | b2
|
|
||||||
|
|
||||||
return rgb332
|
|
||||||
end
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
-- Copyright (C) 2025 ASTRONAND
|
|
||||||
local ini = {}
|
|
||||||
local fs=require("filesystem")
|
|
||||||
|
|
||||||
local function trim(s)
|
|
||||||
local i, j = 1, #s
|
|
||||||
while i <= j and (s:sub(i,i) == " " or s:sub(i,i) == "\t") do
|
|
||||||
i = i + 1
|
|
||||||
end
|
|
||||||
while j >= i and (s:sub(j,j) == " " or s:sub(j,j) == "\t") do
|
|
||||||
j = j - 1
|
|
||||||
end
|
|
||||||
return s:sub(i, j)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function parse(list)
|
|
||||||
local lines=function ()
|
|
||||||
local i=0
|
|
||||||
return function()
|
|
||||||
i=i+1
|
|
||||||
return list[i]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local data = {}
|
|
||||||
local section = data
|
|
||||||
for line in lines() do
|
|
||||||
line = trim(line)
|
|
||||||
|
|
||||||
if line ~= "" and line:sub(1,1) ~= ";" and line:sub(1,1) ~= "#" then
|
|
||||||
if line:sub(1,1) == "[" and line:sub(-1) == "]" then
|
|
||||||
local secName = trim(line:sub(2, -2))
|
|
||||||
if secName ~= "" then
|
|
||||||
data[secName] = data[secName] or {}
|
|
||||||
section = data[secName]
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local eq
|
|
||||||
for i = 1, #line do
|
|
||||||
if line:sub(i,i) == "=" then
|
|
||||||
eq = i
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if eq then
|
|
||||||
local key = trim(line:sub(1, eq-1))
|
|
||||||
local value = trim(line:sub(eq+1))
|
|
||||||
|
|
||||||
local lower = value:lower()
|
|
||||||
if tonumber(value) then
|
|
||||||
value = tonumber(value)
|
|
||||||
elseif lower == "true" then
|
|
||||||
value = true
|
|
||||||
elseif lower == "false" then
|
|
||||||
value = false
|
|
||||||
end
|
|
||||||
section[key] = value
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return data
|
|
||||||
end
|
|
||||||
|
|
||||||
function ini.read(path)
|
|
||||||
local file, err = fs.open(path, "r")
|
|
||||||
if not file then return nil, err end
|
|
||||||
local list={}
|
|
||||||
for i in file.lines() do
|
|
||||||
list[#list+1] = i
|
|
||||||
end
|
|
||||||
file.close()
|
|
||||||
return parse(list)
|
|
||||||
end
|
|
||||||
|
|
||||||
function ini.get(text)
|
|
||||||
return parse(string.split(text, "\n"))
|
|
||||||
end
|
|
||||||
|
|
||||||
local function write(data)
|
|
||||||
local text=""
|
|
||||||
for k,v in pairs(data) do
|
|
||||||
if type(v) ~= "table" then
|
|
||||||
text=text..k .. " = " .. tostring(v) .. "\n"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for sec, tbl in pairs(data) do
|
|
||||||
if type(tbl) == "table" then
|
|
||||||
text=text.."\n[" .. sec .. "]\n"
|
|
||||||
for k,v in pairs(tbl) do
|
|
||||||
text=text..k .. " = " .. tostring(v) .. "\n"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return text
|
|
||||||
end
|
|
||||||
|
|
||||||
function ini.write(path, data)
|
|
||||||
local file=fs.open(path, "w")
|
|
||||||
file.write(write(data))
|
|
||||||
file.close()
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function ini.make(data)
|
|
||||||
return write(data)
|
|
||||||
end
|
|
||||||
|
|
||||||
return ini
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
-- Copyright (C) 2025 ASTRONAND
|
|
||||||
local lib={}
|
|
||||||
|
|
||||||
function lib.create(def)
|
|
||||||
local function func(fun)
|
|
||||||
if type(fun)=="function" then
|
|
||||||
func=fun
|
|
||||||
end
|
|
||||||
return def
|
|
||||||
end
|
|
||||||
return func
|
|
||||||
end
|
|
||||||
|
|
||||||
return lib
|
|
||||||
@@ -1,193 +0,0 @@
|
|||||||
-- From http://pastebin.com/gsFrNjbt linked from http://www.computercraft.info/forums2/index.php?/topic/8169-sha-256-in-pure-lua/
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Adaptation of the Secure Hashing Algorithm (SHA-244/256)
|
|
||||||
-- Found Here: http://lua-users.org/wiki/SecureHashAlgorithm
|
|
||||||
--
|
|
||||||
-- Using an adapted version of the bit library
|
|
||||||
-- Found Here: https://bitbucket.org/Boolsheet/bslf/src/1ee664885805/bit.lua
|
|
||||||
--
|
|
||||||
|
|
||||||
local MOD = 2^32
|
|
||||||
local MODM = MOD-1
|
|
||||||
|
|
||||||
local function memoize(f)
|
|
||||||
local mt = {}
|
|
||||||
local t = setmetatable({}, mt)
|
|
||||||
function mt:__index(k)
|
|
||||||
local v = f(k)
|
|
||||||
t[k] = v
|
|
||||||
return v
|
|
||||||
end
|
|
||||||
return t
|
|
||||||
end
|
|
||||||
|
|
||||||
local function make_bitop_uncached(t, m)
|
|
||||||
local function bitop(a, b)
|
|
||||||
local res,p = 0,1
|
|
||||||
while a ~= 0 and b ~= 0 do
|
|
||||||
local am, bm = a % m, b % m
|
|
||||||
res = res + t[am][bm] * p
|
|
||||||
a = (a - am) / m
|
|
||||||
b = (b - bm) / m
|
|
||||||
p = p*m
|
|
||||||
end
|
|
||||||
res = res + (a + b) * p
|
|
||||||
return res
|
|
||||||
end
|
|
||||||
return bitop
|
|
||||||
end
|
|
||||||
|
|
||||||
local function make_bitop(t)
|
|
||||||
local op1 = make_bitop_uncached(t,2^1)
|
|
||||||
local op2 = memoize(function(a) return memoize(function(b) return op1(a, b) end) end)
|
|
||||||
return make_bitop_uncached(op2, 2 ^ (t.n or 1))
|
|
||||||
end
|
|
||||||
|
|
||||||
local bxor1 = make_bitop({[0] = {[0] = 0,[1] = 1}, [1] = {[0] = 1, [1] = 0}, n = 4})
|
|
||||||
|
|
||||||
local function bxor(a, b, c, ...)
|
|
||||||
local z = nil
|
|
||||||
if b then
|
|
||||||
a = a % MOD
|
|
||||||
b = b % MOD
|
|
||||||
z = bxor1(a, b)
|
|
||||||
if c then z = bxor(z, c, ...) end
|
|
||||||
return z
|
|
||||||
elseif a then return a % MOD
|
|
||||||
else return 0 end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function band(a, b, c, ...)
|
|
||||||
local z
|
|
||||||
if b then
|
|
||||||
a = a % MOD
|
|
||||||
b = b % MOD
|
|
||||||
z = ((a + b) - bxor1(a,b)) / 2
|
|
||||||
if c then z = bit32_band(z, c, ...) end
|
|
||||||
return z
|
|
||||||
elseif a then return a % MOD
|
|
||||||
else return MODM end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function bnot(x) return (-1 - x) % MOD end
|
|
||||||
|
|
||||||
local function rshift1(a, disp)
|
|
||||||
if disp < 0 then return lshift(a,-disp) end
|
|
||||||
return math.floor(a % 2 ^ 32 / 2 ^ disp)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function rshift(x, disp)
|
|
||||||
if disp > 31 or disp < -31 then return 0 end
|
|
||||||
return rshift1(x % MOD, disp)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function lshift(a, disp)
|
|
||||||
if disp < 0 then return rshift(a,-disp) end
|
|
||||||
return (a * 2 ^ disp) % 2 ^ 32
|
|
||||||
end
|
|
||||||
|
|
||||||
local function rrotate(x, disp)
|
|
||||||
x = x % MOD
|
|
||||||
disp = disp % 32
|
|
||||||
local low = band(x, 2 ^ disp - 1)
|
|
||||||
return rshift(x, disp) + lshift(low, 32 - disp)
|
|
||||||
end
|
|
||||||
|
|
||||||
local k = {
|
|
||||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
|
||||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
||||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
|
||||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
||||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
|
||||||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
||||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
|
||||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
||||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
|
||||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
||||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
|
||||||
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
||||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
|
||||||
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
||||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
|
||||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
|
|
||||||
}
|
|
||||||
|
|
||||||
local function str2hexa(s)
|
|
||||||
return (string.gsub(s, ".", function(c) return string.format("%02x", string.byte(c)) end))
|
|
||||||
end
|
|
||||||
|
|
||||||
local function num2s(l, n)
|
|
||||||
local s = ""
|
|
||||||
for i = 1, n do
|
|
||||||
local rem = l % 256
|
|
||||||
s = string.char(rem) .. s
|
|
||||||
l = (l - rem) / 256
|
|
||||||
end
|
|
||||||
return s
|
|
||||||
end
|
|
||||||
|
|
||||||
local function s232num(s, i)
|
|
||||||
local n = 0
|
|
||||||
for i = i, i + 3 do n = n*256 + string.byte(s, i) end
|
|
||||||
return n
|
|
||||||
end
|
|
||||||
|
|
||||||
local function preproc(msg, len)
|
|
||||||
local extra = 64 - ((len + 9) % 64)
|
|
||||||
len = num2s(8 * len, 8)
|
|
||||||
msg = msg .. "\128" .. string.rep("\0", extra) .. len
|
|
||||||
assert(#msg % 64 == 0)
|
|
||||||
return msg
|
|
||||||
end
|
|
||||||
|
|
||||||
local function initH256(H)
|
|
||||||
H[1] = 0x6a09e667
|
|
||||||
H[2] = 0xbb67ae85
|
|
||||||
H[3] = 0x3c6ef372
|
|
||||||
H[4] = 0xa54ff53a
|
|
||||||
H[5] = 0x510e527f
|
|
||||||
H[6] = 0x9b05688c
|
|
||||||
H[7] = 0x1f83d9ab
|
|
||||||
H[8] = 0x5be0cd19
|
|
||||||
return H
|
|
||||||
end
|
|
||||||
|
|
||||||
local function digestblock(msg, i, H)
|
|
||||||
local w = {}
|
|
||||||
for j = 1, 16 do w[j] = s232num(msg, i + (j - 1)*4) end
|
|
||||||
for j = 17, 64 do
|
|
||||||
local v = w[j - 15]
|
|
||||||
local s0 = bxor(rrotate(v, 7), rrotate(v, 18), rshift(v, 3))
|
|
||||||
v = w[j - 2]
|
|
||||||
w[j] = w[j - 16] + s0 + w[j - 7] + bxor(rrotate(v, 17), rrotate(v, 19), rshift(v, 10))
|
|
||||||
end
|
|
||||||
|
|
||||||
local a, b, c, d, e, f, g, h = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
|
|
||||||
for i = 1, 64 do
|
|
||||||
local s0 = bxor(rrotate(a, 2), rrotate(a, 13), rrotate(a, 22))
|
|
||||||
local maj = bxor(band(a, b), band(a, c), band(b, c))
|
|
||||||
local t2 = s0 + maj
|
|
||||||
local s1 = bxor(rrotate(e, 6), rrotate(e, 11), rrotate(e, 25))
|
|
||||||
local ch = bxor (band(e, f), band(bnot(e), g))
|
|
||||||
local t1 = h + s1 + ch + k[i] + w[i]
|
|
||||||
h, g, f, e, d, c, b, a = g, f, e, d + t1, c, b, a, t1 + t2
|
|
||||||
end
|
|
||||||
|
|
||||||
H[1] = band(H[1] + a)
|
|
||||||
H[2] = band(H[2] + b)
|
|
||||||
H[3] = band(H[3] + c)
|
|
||||||
H[4] = band(H[4] + d)
|
|
||||||
H[5] = band(H[5] + e)
|
|
||||||
H[6] = band(H[6] + f)
|
|
||||||
H[7] = band(H[7] + g)
|
|
||||||
H[8] = band(H[8] + h)
|
|
||||||
end
|
|
||||||
|
|
||||||
return function(msg)
|
|
||||||
msg = preproc(msg, #msg)
|
|
||||||
local H = initH256({})
|
|
||||||
for i = 1, #msg, 64 do digestblock(msg, i, H) end
|
|
||||||
return str2hexa(num2s(H[1], 4) .. num2s(H[2], 4) .. num2s(H[3], 4) .. num2s(H[4], 4) ..
|
|
||||||
num2s(H[5], 4) .. num2s(H[6], 4) .. num2s(H[7], 4) .. num2s(H[8], 4))
|
|
||||||
end
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
-- Copyright (C) 2025 ASTRONAND
|
|
||||||
local pipes={}
|
|
||||||
local ports={}
|
|
||||||
local sharedObjects={}
|
|
||||||
local net=require("net")
|
|
||||||
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
-- Copyright (C) 2025 ASTRONAND
|
|
||||||
local args = {...}
|
|
||||||
local os = require("system")
|
|
||||||
local fs=require("filesystem")
|
|
||||||
local term = os.getEnvar("term")
|
|
||||||
|
|
||||||
if args[1] == "help" or args[1] == "-h" then
|
|
||||||
term.print("SPM V1.0.0")
|
|
||||||
term.print("Usage:")
|
|
||||||
term.print(" install <package> : searches for package and installs it")
|
|
||||||
term.print(" add-repo <URL> : adds repo to search list appends package to end of URL")
|
|
||||||
term.print(" download <URL> : downloads package from URL")
|
|
||||||
term.print(" local <dir> : downloads package from file")
|
|
||||||
term.print(" get <dir> : executes commands from list")
|
|
||||||
end
|
|
||||||
|
|
||||||
local function install(package)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
local function addRepo(url)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
local function download(url)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
local function localPackage(dir)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
local function run(command)
|
|
||||||
local list = string.split(command, " ")
|
|
||||||
if list[1] == "install" then
|
|
||||||
install(list[2])
|
|
||||||
elseif list[1] == "add-repo" then
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if args[1] == "get" then
|
|
||||||
local list=string.split(fs.readAllText(args[2]), "\n")
|
|
||||||
for i, v in ipairs(list) do
|
|
||||||
|
|
||||||
end
|
|
||||||
else run(args) end
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user