hotfix
This commit is contained in:
@@ -1 +0,0 @@
|
|||||||
print("hello from hello.lua")
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +1,122 @@
|
|||||||
sleep(1)local a="/$"local b={...}if _HOST:find("UnBIOS")then return end;local c={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 d={}for e in pairs(_G)do if not c[e]then table.insert(d,e)end end;for f,e in ipairs(d)do _G[e]=nil end;local g=_G.term.native()for f,h in ipairs{"nativePaletteColor","nativePaletteColour","screenshot"}do g[h]=_G.term[h]end;_G.term=g;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 i={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 e,j in pairs(i)do for f,k in ipairs(j)do _G[e][k]=nil end end;_G._HOST=_G._HOST.." (UnBIOS)"local l=error;_G.error=function()end;_G.term.redirect=function()end;function _G.term.native()_G.term.native=nil;_G.term.redirect=nil;_G.error=l;term.setBackgroundColor(32768)term.setTextColor(1)term.setCursorPos(1,1)term.setCursorBlink(true)term.clear()local m=fs.open(a.."/boot/cct/boot.lua","r")if m==nil then term.setCursorBlink(false)term.setTextColor(16384)term.write("Could not find /boot/cct/boot.lua. UnBIOS cannot continue.")term.setCursorPos(1,2)term.write("Press any key to continue")coroutine.yield("key")os.shutdown()end;local n,o=loadstring(m.readAll(),"@bootloader")m.close()if n==nil then term.setCursorBlink(false)term.setTextColor(16384)term.write("Could not load /boot/cc/boot.lua. UnBIOS cannot continue.")term.setCursorPos(1,2)term.write(o)term.setCursorPos(1,3)term.write("Press any key to continue")coroutine.yield("key")os.shutdown()end;setfenv(n,_G)local p=os.shutdown;os.shutdown=function()os.shutdown=p;return n(table.unpack(b))end end;if debug then local function q(r,s,t,u)local v,w,x=1,debug.getupvalue(r[s],u)while w~=t and w~=nil do w,x=debug.getupvalue(r[s],v)v=v+1 end;r[s]=x or r[s]end;q(_G,"loadstring","nativeloadstring",1)q(_G,"load","nativeload",5)if http then q(http,"request","nativeHTTPRequest",3)end;q(os,"shutdown","nativeShutdown",1)q(os,"reboot","nativeReboot",1)if turtle then q(turtle,"equipLeft","v",1)q(turtle,"equipRight","v",1)end;do local v,w,x=1,debug.getupvalue(peripheral.isPresent,2)while w~="native"and w~=nil do w,x=debug.getupvalue(peripheral.isPresent,v)v=v+1 end;_G.peripheral=x or peripheral end end
|
--:Minify:--
|
||||||
|
sleep(1)
|
||||||
|
local BOOT_DRIVE_PATH="/$"
|
||||||
|
-- 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(BOOT_DRIVE_PATH.."/boot/cct/boot.lua", "r")
|
||||||
|
if file == nil then
|
||||||
|
term.setCursorBlink(false)
|
||||||
|
term.setTextColor(16384)
|
||||||
|
term.write("Could not find /boot/cct/boot.lua. 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")
|
||||||
|
file.close()
|
||||||
|
if fn == nil then
|
||||||
|
term.setCursorBlink(false)
|
||||||
|
term.setTextColor(16384)
|
||||||
|
term.write("Could not load /boot/cc/boot.lua. 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 +1,192 @@
|
|||||||
local a=({...})[1]local b="/$"local c=a.fs;local d=a.peripheral;local e={}local f={"top","bottom","left","right","front","back"}function e.getType(g)if d.isPresent(g)then return d.getType(g)end;for h=1,#f do local i=f[h]if d.hasType(i,"peripheral_hub")and d.call(i,"isPresentRemote",g)then return d.call(i,"getTypeRemote",g)end end;return nil end;function e.getNames()local j={}for h=1,#f do local i=f[h]if d.isPresent(i)then table.insert(j,i)end;if d.hasType(i,"peripheral_hub")then local k=d.call(i,"getConnectedSides")for l,m in ipairs(k)do table.insert(j,m)end end end;return j end;local n={}local o={}local function p(q)if not q or q==""then return"/"end;return c.combine("/",q)end;local function r(s,t,u,v)t=p(t)local disk={address=s,isReadOnly=function()return u end}function disk:spaceUsed()return c.getCapacity(t)-c.getFreeSpace(t)end;function disk:spaceTotal()return c.getCapacity(t)end;function disk:list(q)local w=c.combine(t,q)if not c.exists(w)or not c.isDir(w)then return nil,"not directory"end;return c.list(w)end;function disk:fileExists(q)local w=c.combine(t,q)return c.exists(w)and not c.isDir(w)end;function disk:directoryExists(q)local w=c.combine(t,q)return c.exists(w)and c.isDir(w)end;function disk:type(q)local w=c.combine(t,q)if not c.exists(w)then return nil elseif c.isDir(w)then return"directory"else return"file"end end;function disk:makeDirectory(q)local w=c.combine(t,q)c.makeDir(w)return true end;function disk:remove(q)local w=c.combine(t,q)if c.exists(w)then c.delete(w)end;return true end;function disk:setLabel(x)v.setLabel(x)end;function disk:getLabel(x)return v.getLabel()end;function disk:attributes(q)local w=c.combine(t,q)return c.attributes(w)end;function disk:open(q,y)local w=c.combine(t,q)return c.open(w,y)end;return disk end;o["$"]=r("$",b,false,{setLabel=function(x)local z=c.open("/.label","w")z.write(x)z.close()end,getLabel=function()local z=c.open("/.label","r")local x=z.readAll()z.close()return x end})local function A()for s,l in pairs(n)do if not e.getType(s)then n[s]=nil end end;for l,g in ipairs(e.getNames())do if e.getType(g)=="disk"then if not n[g]then local B=disk.getMountPath(g)if B then n[g]=r(g,B,false,disk)end end end end end;local function C()A()local D={}for s,E in pairs(o)do D[s]=E end;for s,E in pairs(n)do D[s]=E end;return pairs(D)end;return{refresh=A,list=C}
|
--:Minify:--
|
||||||
|
local apis = ({...})[1]
|
||||||
|
local BOOT_DRIVE_PATH="/$"
|
||||||
|
local fs = apis.fs
|
||||||
|
local native = apis.peripheral
|
||||||
|
local peripheral = {}
|
||||||
|
local sides = {"top", "bottom", "left", "right", "front", "back"}
|
||||||
|
|
||||||
|
function peripheral.getType(name)
|
||||||
|
if native.isPresent(name) then
|
||||||
|
return native.getType(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, "getTypeRemote", name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function peripheral.getNames()
|
||||||
|
local names = {}
|
||||||
|
for n = 1, #sides do
|
||||||
|
local side = sides[n]
|
||||||
|
if native.isPresent(side) then
|
||||||
|
table.insert(names, side)
|
||||||
|
end
|
||||||
|
if native.hasType(side, "peripheral_hub") then
|
||||||
|
local hubSides = native.call(side, "getConnectedSides")
|
||||||
|
for _, hubSide in ipairs(hubSides) do
|
||||||
|
table.insert(names, hubSide)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return names
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
-- STORAGE
|
||||||
|
---------------------------------------------------------
|
||||||
|
local disks = {} -- real disks
|
||||||
|
local internal = {} -- "$" disk
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
-- HELPERS
|
||||||
|
---------------------------------------------------------
|
||||||
|
local function norm(path)
|
||||||
|
if not path or path == "" then return "/" end
|
||||||
|
return fs.combine("/", path)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Creates a disk object given a base path
|
||||||
|
local function createDisk(id, basePath, readonly, periph)
|
||||||
|
basePath = norm(basePath)
|
||||||
|
|
||||||
|
local disk = {address=id,isReadOnly=function() return readonly end}
|
||||||
|
|
||||||
|
function disk:spaceUsed()
|
||||||
|
return fs.getCapacity(basePath) - fs.getFreeSpace(basePath)
|
||||||
|
end
|
||||||
|
|
||||||
|
function disk:spaceTotal()
|
||||||
|
return fs.getCapacity(basePath)
|
||||||
|
end
|
||||||
|
|
||||||
|
function disk:list(path)
|
||||||
|
local p = fs.combine(basePath, path)
|
||||||
|
if not fs.exists(p) or not fs.isDir(p) then return nil, "not directory" end
|
||||||
|
return fs.list(p)
|
||||||
|
end
|
||||||
|
|
||||||
|
function disk:fileExists(path)
|
||||||
|
local p = fs.combine(basePath, path)
|
||||||
|
return fs.exists(p) and not fs.isDir(p)
|
||||||
|
end
|
||||||
|
|
||||||
|
function disk:directoryExists(path)
|
||||||
|
local p = fs.combine(basePath, path)
|
||||||
|
return fs.exists(p) and fs.isDir(p)
|
||||||
|
end
|
||||||
|
|
||||||
|
function disk:type(path)
|
||||||
|
local p = fs.combine(basePath, path)
|
||||||
|
if not fs.exists(p) then
|
||||||
|
return nil
|
||||||
|
elseif fs.isDir(p) then
|
||||||
|
return "directory"
|
||||||
|
else
|
||||||
|
return "file"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function disk:makeDirectory(path)
|
||||||
|
local p = fs.combine(basePath, path)
|
||||||
|
fs.makeDir(p)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function disk:remove(path)
|
||||||
|
local p = fs.combine(basePath, path)
|
||||||
|
if fs.exists(p) then fs.delete(p) end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function disk:setLabel(label)
|
||||||
|
periph.setLabel(label)
|
||||||
|
end
|
||||||
|
|
||||||
|
function disk:getLabel(label)
|
||||||
|
return periph.getLabel()
|
||||||
|
end
|
||||||
|
|
||||||
|
function disk:attributes(path)
|
||||||
|
local p = fs.combine(basePath, path)
|
||||||
|
return fs.attributes(p)
|
||||||
|
end
|
||||||
|
|
||||||
|
function disk:open(path, mode)
|
||||||
|
local p = fs.combine(basePath, path)
|
||||||
|
return fs.open(p, mode)
|
||||||
|
end
|
||||||
|
|
||||||
|
return disk
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
-- INTERNAL DISK "$" (mapped to "/")
|
||||||
|
---------------------------------------------------------
|
||||||
|
internal["$"] = createDisk("$", BOOT_DRIVE_PATH, false, {
|
||||||
|
setLabel=function(label)
|
||||||
|
local h = fs.open("/.label", "w")
|
||||||
|
h.write(label)
|
||||||
|
h.close()
|
||||||
|
end,
|
||||||
|
getLabel=function()
|
||||||
|
local h = fs.open("/.label", "r")
|
||||||
|
local label = h.readAll()
|
||||||
|
h.close()
|
||||||
|
return label
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
-- SCAN REAL DISK PERIPHERALS
|
||||||
|
---------------------------------------------------------
|
||||||
|
local function refresh()
|
||||||
|
-- remove disks that no longer exist
|
||||||
|
for id, _ in pairs(disks) do
|
||||||
|
if not peripheral.getType(id) then
|
||||||
|
disks[id] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- detect new disks
|
||||||
|
for _, name in ipairs(peripheral.getNames()) do
|
||||||
|
if peripheral.getType(name) == "disk" then
|
||||||
|
if not disks[name] then
|
||||||
|
local mount = disk.getMountPath(name)
|
||||||
|
if mount then
|
||||||
|
disks[name] = createDisk(name, mount, false, disk)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
-- ITERATOR
|
||||||
|
---------------------------------------------------------
|
||||||
|
local function iter()
|
||||||
|
refresh()
|
||||||
|
-- first internal
|
||||||
|
local combined = {}
|
||||||
|
|
||||||
|
for id, obj in pairs(internal) do
|
||||||
|
combined[id] = obj
|
||||||
|
end
|
||||||
|
for id, obj in pairs(disks) do
|
||||||
|
combined[id] = obj
|
||||||
|
end
|
||||||
|
|
||||||
|
return pairs(combined)
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
-- MODULE RETURN
|
||||||
|
---------------------------------------------------------
|
||||||
|
return {
|
||||||
|
refresh = refresh,
|
||||||
|
list = iter
|
||||||
|
}
|
||||||
|
|||||||
@@ -1 +1,78 @@
|
|||||||
local a={}local b={}local c={}local function d(e)local f="/"for g,h in pairs(c)do if e:sub(1,#g)==g then if not f or#g>#f then f=g end end end;local i=e:sub(#f+1)return b[c[f]],i end;function a.update(j)b={}for k,l in j.list()do b[k]=l end end;function a.exists(e)local h,i=d(e)return h:directoryExists(i)or h:fileExists(i)end;function a.isFile(e)local h,i=d(e)return h:fileExists(i)end;function a.isDir(e)local h,i=d(e)return h:directoryExists(i)end;function a.list(e)local h,i=d(e)return h:list(i)end;function a.makeDir(e)local h,i=d(e)return h:makeDirectory(i)end;function a.remove(e)local h,i=d(e)return h:remove(i)end;function a.readAllText(e)local h,i=d(e)local m=h:open(i,"r")if not m then return nil end;local n=m.readAll()m.close()return n end;function a.writeAllText(e,o)local h,i=d(e)local m=h:open(i,"w")m.write(o)m.close()end;function a.appendAllText(e,o)local h,i=d(e)local m=h:open(i,"a")m.write(o)m.close()end;function a.load(e)return load(a.readAllText(e),e)end;function a.mount(h,f)if not b[h]then return end;c[f]=h end;return a
|
--:Minify:--
|
||||||
|
local fs = {}
|
||||||
|
local disks = {}
|
||||||
|
local mounts = {}
|
||||||
|
|
||||||
|
local function resolve(path)
|
||||||
|
local mountPoint = "/"
|
||||||
|
for mount, disk in pairs(mounts) do
|
||||||
|
if path:sub(1, #mount) == mount then
|
||||||
|
if not mountPoint or #mount > #mountPoint then
|
||||||
|
mountPoint = mount
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local newPath = path:sub(#mountPoint + 1)
|
||||||
|
return disks[mounts[mountPoint]], newPath
|
||||||
|
end
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
function fs.update(initdisks)
|
||||||
|
disks = {}
|
||||||
|
for k, v in initdisks.list() do
|
||||||
|
disks[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function fs.exists(path)
|
||||||
|
local disk, newPath = resolve(path)
|
||||||
|
return disk:directoryExists(newPath) or disk:fileExists(newPath)
|
||||||
|
end
|
||||||
|
function fs.isFile(path)
|
||||||
|
local disk, newPath = resolve(path)
|
||||||
|
return disk:fileExists(newPath)
|
||||||
|
end
|
||||||
|
function fs.isDir(path)
|
||||||
|
local disk, newPath = resolve(path)
|
||||||
|
return disk:directoryExists(newPath)
|
||||||
|
end
|
||||||
|
function fs.list(path)
|
||||||
|
local disk, newPath = resolve(path)
|
||||||
|
return disk:list(newPath)
|
||||||
|
end
|
||||||
|
function fs.makeDir(path)
|
||||||
|
local disk, newPath = resolve(path)
|
||||||
|
return disk:makeDirectory(newPath)
|
||||||
|
end
|
||||||
|
function fs.remove(path)
|
||||||
|
local disk, newPath = resolve(path)
|
||||||
|
return disk:remove(newPath)
|
||||||
|
end
|
||||||
|
function fs.readAllText(path)
|
||||||
|
local disk, newPath = resolve(path)
|
||||||
|
local handle = disk:open(newPath, "r")
|
||||||
|
if not handle then return nil end
|
||||||
|
local content = handle.readAll()
|
||||||
|
handle.close()
|
||||||
|
return content
|
||||||
|
end
|
||||||
|
function fs.writeAllText(path, text)
|
||||||
|
local disk, newPath = resolve(path)
|
||||||
|
local handle = disk:open(newPath, "w")
|
||||||
|
handle.write(text)
|
||||||
|
handle.close()
|
||||||
|
end
|
||||||
|
function fs.appendAllText(path, text)
|
||||||
|
local disk, newPath = resolve(path)
|
||||||
|
local handle = disk:open(newPath, "a")
|
||||||
|
handle.write(text)
|
||||||
|
handle.close()
|
||||||
|
end
|
||||||
|
function fs.load(path)
|
||||||
|
return load(fs.readAllText(path), path)
|
||||||
|
end
|
||||||
|
function fs.mount(disk, mountPoint)
|
||||||
|
if not disks[disk] then return end
|
||||||
|
mounts[mountPoint] = disk
|
||||||
|
end
|
||||||
|
return fs
|
||||||
@@ -1 +1,243 @@
|
|||||||
local a={...}local b=a[1]local c=a[2]local d=a[3]local e=a[5]local f=a[6]local g=a[7]local h=""local i={}i.process="Kernel"i.user="root"i.group="root"i.groups={0}i.uid=0;i.gid=0;i.status="start"i.key={}i.cache={}i.cache.preload={}i._G=_G;i.sleep=sleep;_G.sleep=nil;local j=false;function i.log(k,l)h=h..tostring(f:time()).." "..i.user.." "..i.process.."["..tostring(l or"INFO").."]: "..k.."\n"if i.status=="start"then e:print(tostring(f:time()).." "..i.user.." "..i.process.."["..tostring(l or"INFO").."]: "..k)elseif i.status=="init"then i.standbyTask=i.currentTask;i.currentTask=i.kernelTask;i.tty.print(tostring(f:time()).." "..i.user.." "..i.process.."["..tostring(l or"INFO").."]: "..k)i.currentTask=i.standbyTask end end;function i.PANIC(k)if i.status~="Panic"then i.log("PANIC: "..k,"PANIC")pcall(i["saveLog"])i.status="Panic"i.reason=k;e:setTextColor(2)e:setBackgroundColor(0)e:clear()e:setCursorPos(1,1)e:print(h)e:print("KERNEL PANIC!\n"..k.."\nSystem halted.")e:print("Press any key to continue...")end;while true do local m={f:getMachineEvent()}if m[1]=="keyPressed"then break end end;f:reboot()end;i.panic=i.PANIC;if j then e:setTextColor(1)e:setBackgroundColor(4)e:clear()local n,o=e:getSize()e:setCursorPos(3,5)e:print(":(")e:setCursorPos(3,7)e:print("Your PC ran into a problem and needs to restart. We're just collecting some error")e:setCursorPos(3,8)e:print("info, and then we'll restart for you.\n")e:setCursorPos(3,o-5)e:print("Stop code: average windows experience")e:setCursorPos(1,o)e:print("Press any key to continue... jk reboot it yourself lazy")while true do end end;i.log("Kernel loaded.")i.log("Mounting init disks...")c.refresh()g.update(c)i.disks={}for p,q in c.list()do i.disks[q.address]=q end;g.mount("$","/")local r=g.readAllText("/boot/fstab")local s=function(t,u,v)assert(#u==1,"only delim len 1 supported for now")v=(v or 0)-1;local w={}local x=""for y=1,#t do local z=string.sub(t,y,y)if#w~=v and z==u then table.insert(w,x)x=""else x=x..z end end;table.insert(w,x)return w end;if not g.isFile("/boot/boot.cfg")then i.log("boot.cfg missing or corrupted!, Attempting to write recovery boot.cfg","ERROR")g.writeAllText("/boot/boot.cfg",g.readAllText("/boot/safeboot.cfg"))end;local A,B=load(g.readAllText("/boot/boot.cfg"),"@boot.cfg")if not A then i.PANIC("Failed to load /boot/boot.cfg: "..tostring(B))end;local C,D=pcall(A)if not C then i.PANIC("Error in /boot/boot.cfg: "..tostring(D))end;i.config=D;for y,q in ipairs(s(r,"\n"))do if q:sub(1,1)=="U"then local E=""for y=3,#q do if q:sub(y,y)==";"then if y==3 then i.log("Invalid fstab line... Skipping.","WARN")goto F end;E=q:sub(3,y-1)end end;local G=q:sub(#E+4)g.mount(E,G)::F::end end;i.log("Disks initialized")function i.saveLog()g.writeAllText("/var/log/syslog.log",h)end;g.remove("/tmp")g.makeDir("/tmp")function i.newFifo()local H={}H.push=function(I)table.insert(I)end;H.pop=function()return table.remove(H,1)end;return H end;function i.newUUID()local J="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"local K=""for y=1,#J do local z=J:sub(y,y)if z=="x"then K=K..string.format("%x",math.random(0,15))elseif z=="y"then K=K..string.format("%x",math.random(8,11))else K=K..z end end;return K end;i.syscalls={}local L={[0]={}}for y=0,100 do L[y]={}end;i.log("Gathering modules")for p,y in ipairs(g.list("/lib/modules"))do for p,q in ipairs(g.list("/lib/modules/"..y))do local M=tonumber(q:sub(1,2))L[M+1][#L[M+1]+1]="/lib/modules/"..y.."/"..q end end;i.ifs=g;i.apis=b;i.computer=f;i.arch=d;i.initdisks=c;i.screen=e;i.processes={}i.fstab=r;i.kernelTask={name="kernel",status="R",pid=0,tgid=0,user="root",uid=0,fd={},exit="",sleep=0,ivs=0,vs=0,children={},syscallReturn={},cwd="/",timeSlice=0,lastTime=0,totalTime=0,numRuns=0}i.currentTask=i.kernelTask;i.syscalls["OS_time"]=function()return i.computer:time()end;i.syscalls["OS_log"]=i.log;i.log("Running modules")for p,N in ipairs(L)do for p,q in ipairs(N)do local O=g.readAllText(q)if not O then i.log("ModuReadErr: "..q,"WARN")goto P end;local Q,B=load(O,"@"..q)if not Q then i.panic("ModuLoadErr: "..tostring(B))goto P end;local R,B=xpcall(Q,debug.traceback,i)if not R then i.panic("ModuRunErr: "..tostring(B))end::P::end end;i.log("Kernel initialized successfully.")i.main()i.PANIC("Execution complete")
|
--:Minify:--
|
||||||
|
local args = {...}
|
||||||
|
local apis = args[1]
|
||||||
|
local disks = args[2]
|
||||||
|
local arch = args[3]
|
||||||
|
local screen = args[5]
|
||||||
|
local computer = args[6]
|
||||||
|
local ifs = args[7]
|
||||||
|
local LOG_Text = ""
|
||||||
|
local kernel = {}
|
||||||
|
kernel.process = "Kernel"
|
||||||
|
kernel.user = "root"
|
||||||
|
kernel.group = "root"
|
||||||
|
kernel.groups = {0}
|
||||||
|
kernel.uid = 0
|
||||||
|
kernel.gid = 0
|
||||||
|
kernel.status = "start"
|
||||||
|
kernel.key = {}
|
||||||
|
kernel.cache = {}
|
||||||
|
kernel.cache.preload = {}
|
||||||
|
kernel._G=_G
|
||||||
|
kernel.sleep=sleep
|
||||||
|
|
||||||
|
_G.sleep=nil
|
||||||
|
local windowsExp = false
|
||||||
|
|
||||||
|
function kernel.log(msg, level)
|
||||||
|
LOG_Text = LOG_Text..tostring(computer:time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n"
|
||||||
|
if kernel.status == "start" then
|
||||||
|
screen:print(tostring(computer:time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg)
|
||||||
|
elseif kernel.status == "init" then
|
||||||
|
kernel.standbyTask=kernel.currentTask
|
||||||
|
kernel.currentTask=kernel.kernelTask
|
||||||
|
kernel.tty.print(tostring(computer:time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg)
|
||||||
|
kernel.currentTask=kernel.standbyTask
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function kernel.PANIC(msg)
|
||||||
|
if kernel.status~="Panic" then
|
||||||
|
kernel.log("PANIC: "..msg, "PANIC")
|
||||||
|
pcall(kernel["saveLog"])
|
||||||
|
kernel.status="Panic"
|
||||||
|
kernel.reason=msg
|
||||||
|
screen:setTextColor(2)
|
||||||
|
screen:setBackgroundColor(0)
|
||||||
|
screen:clear()
|
||||||
|
screen:setCursorPos(1,1)
|
||||||
|
screen:print(LOG_Text)
|
||||||
|
screen:print("KERNEL PANIC!\n"..msg.."\nSystem halted.")
|
||||||
|
screen:print("Press any key to continue...")
|
||||||
|
end
|
||||||
|
while true do
|
||||||
|
local event={computer:getMachineEvent()}
|
||||||
|
if event[1]=="keyPressed" then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
computer:reboot()
|
||||||
|
end
|
||||||
|
kernel.panic=kernel.PANIC
|
||||||
|
|
||||||
|
if windowsExp then
|
||||||
|
screen:setTextColor(1)
|
||||||
|
screen:setBackgroundColor(4)
|
||||||
|
screen:clear()
|
||||||
|
local w,h = screen:getSize()
|
||||||
|
screen:setCursorPos(3,5)
|
||||||
|
screen:print(":(")
|
||||||
|
screen:setCursorPos(3,7)
|
||||||
|
screen:print("Your PC ran into a problem and needs to restart. We're just collecting some error")
|
||||||
|
screen:setCursorPos(3,8)
|
||||||
|
screen:print("info, and then we'll restart for you.\n")
|
||||||
|
screen:setCursorPos(3,h-5)
|
||||||
|
screen:print("Stop code: average windows experience")
|
||||||
|
screen:setCursorPos(1,h)
|
||||||
|
screen:print("Press any key to continue... jk reboot it yourself lazy")
|
||||||
|
while true do end
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.log("Kernel loaded.")
|
||||||
|
kernel.log("Mounting init disks...")
|
||||||
|
disks.refresh()
|
||||||
|
ifs.update(disks)
|
||||||
|
kernel.disks={}
|
||||||
|
for _,v in disks.list() do
|
||||||
|
kernel.disks[v.address] = v
|
||||||
|
end
|
||||||
|
ifs.mount("$", "/")
|
||||||
|
|
||||||
|
local fstab=ifs.readAllText("/boot/fstab")
|
||||||
|
local split = function(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
|
||||||
|
|
||||||
|
if not ifs.isFile("/boot/boot.cfg") then
|
||||||
|
kernel.log("boot.cfg missing or corrupted!, Attempting to write recovery boot.cfg", "ERROR")
|
||||||
|
ifs.writeAllText("/boot/boot.cfg",ifs.readAllText("/boot/safeboot.cfg"))
|
||||||
|
end
|
||||||
|
|
||||||
|
local initCfgFunc, err = load(ifs.readAllText("/boot/boot.cfg"), "@boot.cfg")
|
||||||
|
if not initCfgFunc then
|
||||||
|
kernel.PANIC("Failed to load /boot/boot.cfg: "..tostring(err))
|
||||||
|
end
|
||||||
|
|
||||||
|
local initCfgStatus, config = pcall(initCfgFunc)
|
||||||
|
if not initCfgStatus then
|
||||||
|
kernel.PANIC("Error in /boot/boot.cfg: "..tostring(config))
|
||||||
|
end
|
||||||
|
kernel.config = config
|
||||||
|
|
||||||
|
for i,v in ipairs(split(fstab,"\n")) do
|
||||||
|
if v:sub(1,1)=="U" then
|
||||||
|
local id=""
|
||||||
|
for i=3,#v do
|
||||||
|
if v:sub(i,i)==";" then
|
||||||
|
if i==3 then kernel.log("Invalid fstab line... Skipping.","WARN") goto endline end
|
||||||
|
id=v:sub(3,i-1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local path=v:sub(#id+4)
|
||||||
|
ifs.mount(id,path)
|
||||||
|
::endline::
|
||||||
|
end
|
||||||
|
end
|
||||||
|
kernel.log("Disks initialized")
|
||||||
|
|
||||||
|
function kernel.saveLog()
|
||||||
|
ifs.writeAllText("/var/log/syslog.log", LOG_Text)
|
||||||
|
end
|
||||||
|
|
||||||
|
ifs.remove("/tmp")
|
||||||
|
ifs.makeDir("/tmp")
|
||||||
|
|
||||||
|
function kernel.newFifo()
|
||||||
|
local fifo = {}
|
||||||
|
fifo.push=function(data)
|
||||||
|
table.insert(data)
|
||||||
|
end
|
||||||
|
fifo.pop=function()
|
||||||
|
return table.remove(fifo,1)
|
||||||
|
end
|
||||||
|
return fifo
|
||||||
|
end
|
||||||
|
|
||||||
|
function kernel.newUUID()
|
||||||
|
local template = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
|
||||||
|
local uuid = ""
|
||||||
|
for i = 1, #template do
|
||||||
|
local c = template:sub(i,i)
|
||||||
|
if c == "x" then
|
||||||
|
uuid = uuid .. string.format("%x", math.random(0, 15))
|
||||||
|
elseif c == "y" then
|
||||||
|
uuid = uuid .. string.format("%x", math.random(8, 11))
|
||||||
|
else
|
||||||
|
uuid = uuid .. c
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return uuid
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.syscalls={}
|
||||||
|
local modules={[0]={}}
|
||||||
|
for i=0, 100 do
|
||||||
|
modules[i]={}
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.log("Gathering modules")
|
||||||
|
for _, i in ipairs(ifs.list("/lib/modules")) do
|
||||||
|
for _,v in ipairs(ifs.list("/lib/modules/"..i)) do
|
||||||
|
local prior=tonumber(v:sub(1,2))
|
||||||
|
modules[prior+1][#modules[prior+1]+1]="/lib/modules/"..i.."/"..v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.ifs=ifs
|
||||||
|
kernel.apis=apis
|
||||||
|
kernel.computer=computer
|
||||||
|
kernel.arch=arch
|
||||||
|
kernel.initdisks=disks
|
||||||
|
kernel.screen=screen
|
||||||
|
kernel.processes={}
|
||||||
|
kernel.fstab=fstab
|
||||||
|
|
||||||
|
kernel.kernelTask = {
|
||||||
|
name="kernel",
|
||||||
|
status="R",
|
||||||
|
pid=0,
|
||||||
|
tgid=0,
|
||||||
|
user="root",
|
||||||
|
uid=0,
|
||||||
|
fd={},
|
||||||
|
exit="",
|
||||||
|
sleep=0,
|
||||||
|
ivs=0,
|
||||||
|
vs=0,
|
||||||
|
children={},
|
||||||
|
syscallReturn={},
|
||||||
|
cwd="/",
|
||||||
|
timeSlice=0,
|
||||||
|
lastTime=0,
|
||||||
|
totalTime=0,
|
||||||
|
numRuns=0
|
||||||
|
}
|
||||||
|
kernel.currentTask = kernel.kernelTask
|
||||||
|
|
||||||
|
kernel.syscalls["OS_time"]=function() return kernel.computer:time() end
|
||||||
|
kernel.syscalls["OS_log"]=kernel.log
|
||||||
|
|
||||||
|
kernel.log("Running modules")
|
||||||
|
for _,p in ipairs(modules) do
|
||||||
|
for _,v in ipairs(p) do
|
||||||
|
local code=ifs.readAllText(v)
|
||||||
|
if not code then
|
||||||
|
kernel.log("ModuReadErr: "..v, "WARN")
|
||||||
|
goto skip
|
||||||
|
end
|
||||||
|
local func,err=load(code,"@"..v)
|
||||||
|
if not func then kernel.panic("ModuLoadErr: "..tostring(err)) goto skip end
|
||||||
|
local status, err = xpcall(func,debug.traceback, kernel)
|
||||||
|
if not status then kernel.panic("ModuRunErr: "..tostring(err)) end
|
||||||
|
::skip::
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.log("Kernel initialized successfully.")
|
||||||
|
--kernel.status="running"
|
||||||
|
kernel.main()
|
||||||
|
kernel.PANIC("Execution complete")
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
-- DOING SO MAY RENDER YOUR SYSTEM UNBOOTABLE!
|
-- DOING SO MAY RENDER YOUR SYSTEM UNBOOTABLE!
|
||||||
|
|
||||||
-- This file is auto-generated during the build process.
|
-- This file is auto-generated during the build process.
|
||||||
-- RECOVERY BOOT CONFIGURATION FILE
|
-- DEFAULT BOOT CONFIGURATION FILE
|
||||||
return {
|
return {
|
||||||
initPath = "/sbin/init.lua",
|
initPath = "/sbin/init.lua",
|
||||||
maxOpenFiles = 128,
|
maxOpenFiles = 128,
|
||||||
|
|||||||
@@ -1 +1,182 @@
|
|||||||
local a=...local b=a.apis;local c=b.term;local d=b.peripheral;local e={"top","bottom","left","right","front","back"}local function f(g)if d.isPresent(g)then return d.getType(g)end;for h=1,#e do local i=e[h]if d.hasType(i,"peripheral_hub")and d.call(i,"isPresentRemote",g)then return d.call(i,"getTypeRemote",g)end end;return nil end;local function j()local k={}for h=1,#e do local i=e[h]if d.isPresent(i)then table.insert(k,i)end;if d.hasType(i,"peripheral_hub")then local l=d.call(i,"getConnectedSides")for m,n in ipairs(l)do table.insert(k,n)end end end;return k end;local function o(g)if d.isPresent(g)then return o(g)end;for h=1,#e do local i=e[h]if d.hasType(i,"peripheral_hub")and d.call(i,"isPresentRemote",g)then return d.call(i,"wrapRemote",g)end end;return nil end;local p={[0]=0x000000,0xFFFFFF,0xFF0000,0x00FF00,0x0000FF,0x00FFFF,0xFF00FF,0xFFFF00,0xFF6D00,0x6DFF55,0x24FFFF,0x924900,0x6D6D55,0xDBDBAA,0x6D00FF,0xB6FF00}local q={[0x1]=0,[0x2]=1,[0x4]=2,[0x8]=3,[0x10]=4,[0x20]=5,[0x40]=6,[0x80]=7,[0x100]=8,[0x200]=9,[0x400]=10,[0x800]=11,[0x1000]=12,[0x2000]=13,[0x4000]=14,[0x8000]=15}local function r(s,t)local u,v=t.getCursorPos()local w,x=t.getSize()for y=1,#s do local z=s:sub(y,y)if z=="\n"then v=v+1;u=1 elseif z=="\t"then local A=4;local B=A-(u-1)%A;t.write(string.rep(" ",B))u=u+B elseif z=="\b"then if u>1 then u=u-1;t.setCursorPos(u,v)t.write(" ")t.setCursorPos(u,v)end else if u<=w and v<=x then t.setCursorPos(u,v)t.write(z)u=u+1 end end;if u>w then u=1;v=v+1 end;if v-1>x then t.scroll(1)v=x;t.setCursorPos(u,v)end end;t.setCursorPos(u,v)end;local function C(t)local D={}function D.print(s)r(s.."\n",t)end;function D.printInline(s)r(s,t)end;function D.clear()t.clear()t.setCursorPos(1,1)end;function D.setCursorPos(u,v)t.setCursorPos(u,v)end;function D.getCursorPos()return t.getCursorPos()end;function D.getSize()return t.getSize()end;function D.setBackgroundColor(E)t.setBackgroundColor(p[E])end;function D.setTextColor(E)t.setTextColor(p[E])end;function D.getBackgroundColor()return q[t.getBackgroundColor()]end;function D.getTextColor()return q[t.getTextColor()]end;return D end;a.tty.register("tty0",C(c))for m,g in ipairs(j())do local F=f(g)if F=="monitor"then local G=o(g)G.setTextScale(0.5)a.tty.register(g,C(G))end end
|
--:Minify:--
|
||||||
|
local kernel=...
|
||||||
|
local apis=kernel.apis
|
||||||
|
local main=apis.term
|
||||||
|
local native=apis.peripheral
|
||||||
|
local sides = {"top", "bottom", "left", "right", "front", "back"}
|
||||||
|
|
||||||
|
local function getType(name)
|
||||||
|
if native.isPresent(name) then
|
||||||
|
return native.getType(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, "getTypeRemote", name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getNames()
|
||||||
|
local names = {}
|
||||||
|
for n = 1, #sides do
|
||||||
|
local side = sides[n]
|
||||||
|
if native.isPresent(side) then
|
||||||
|
table.insert(names, side)
|
||||||
|
end
|
||||||
|
if native.hasType(side, "peripheral_hub") then
|
||||||
|
local hubSides = native.call(side, "getConnectedSides")
|
||||||
|
for _, hubSide in ipairs(hubSides) do
|
||||||
|
table.insert(names, hubSide)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return names
|
||||||
|
end
|
||||||
|
|
||||||
|
local function wrapPeripheral(name)
|
||||||
|
if native.isPresent(name) then
|
||||||
|
return wrapPeripheral(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, "wrapRemote", name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local colors={
|
||||||
|
[0]=0x000000, -- #000000
|
||||||
|
0xFFFFFF, -- #FFFFFF
|
||||||
|
0xFF0000, -- #FF0000
|
||||||
|
0x00FF00, -- #00FF00
|
||||||
|
0x0000FF, -- #0000FF
|
||||||
|
0x00FFFF, -- #00FFFF
|
||||||
|
0xFF00FF, -- #FF00FF
|
||||||
|
0xFFFF00, -- #FFFF00
|
||||||
|
0xFF6D00, -- #FF6D00
|
||||||
|
0x6DFF55, -- #6DFF55
|
||||||
|
0x24FFFF, -- #24FFFF
|
||||||
|
0x924900, -- #924900
|
||||||
|
0x6D6D55, -- #6D6D55
|
||||||
|
0xDBDBAA, -- #DBDBAA
|
||||||
|
0x6D00FF, -- #6D00FF
|
||||||
|
0xB6FF00 -- #B6FF00
|
||||||
|
}
|
||||||
|
|
||||||
|
local icolors={
|
||||||
|
[0x1] =0, -- #000000
|
||||||
|
[0x2] =1, -- #FFFFFF
|
||||||
|
[0x4] =2, -- #FF0000
|
||||||
|
[0x8] =3, -- #00FF00
|
||||||
|
[0x10] =4, -- #0000FF
|
||||||
|
[0x20] =5, -- #00FFFF
|
||||||
|
[0x40] =6, -- #FF00FF
|
||||||
|
[0x80] =7, -- #FFFF00
|
||||||
|
[0x100] =8, -- #FF6D00
|
||||||
|
[0x200] =9, -- #6DFF55
|
||||||
|
[0x400] =10, -- #24FFFF
|
||||||
|
[0x800] =11, -- #924900
|
||||||
|
[0x1000] =12, -- #6D6D55
|
||||||
|
[0x2000] =13, -- #DBDBAA
|
||||||
|
[0x4000] =14, -- #6D00FF
|
||||||
|
[0x8000] =15 -- #B6FF00
|
||||||
|
}
|
||||||
|
|
||||||
|
local function write(text, term)
|
||||||
|
local x, y = term.getCursorPos()
|
||||||
|
local w, h = 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)
|
||||||
|
term.write(string.rep(" ", spaces))
|
||||||
|
x = x + spaces
|
||||||
|
elseif c == "\b" then
|
||||||
|
if x > 1 then
|
||||||
|
x = x - 1
|
||||||
|
term.setCursorPos(x, y)
|
||||||
|
term.write(" ")
|
||||||
|
term.setCursorPos(x, y)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if x <= w and y <= h then
|
||||||
|
term.setCursorPos(x, y)
|
||||||
|
term.write(c)
|
||||||
|
x = x + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Handle wrapping if we go past right edge
|
||||||
|
if x > w then
|
||||||
|
x = 1
|
||||||
|
y = y + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Handle scrolling if we go past bottom
|
||||||
|
if y-1 > h then
|
||||||
|
term.scroll(1)
|
||||||
|
y = h
|
||||||
|
term.setCursorPos(x, y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
term.setCursorPos(x, y)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function newTTY(term)
|
||||||
|
local ret={}
|
||||||
|
function ret.print(text)
|
||||||
|
write(text.."\n", term)
|
||||||
|
end
|
||||||
|
function ret.printInline(text)
|
||||||
|
write(text, term)
|
||||||
|
end
|
||||||
|
function ret.clear()
|
||||||
|
term.clear()
|
||||||
|
term.setCursorPos(1,1)
|
||||||
|
end
|
||||||
|
function ret.setCursorPos(x,y)
|
||||||
|
term.setCursorPos(x,y)
|
||||||
|
end
|
||||||
|
function ret.getCursorPos()
|
||||||
|
return term.getCursorPos()
|
||||||
|
end
|
||||||
|
function ret.getSize()
|
||||||
|
return term.getSize()
|
||||||
|
end
|
||||||
|
function ret.setBackgroundColor(color)
|
||||||
|
term.setBackgroundColor(colors[color])
|
||||||
|
end
|
||||||
|
function ret.setTextColor(color)
|
||||||
|
term.setTextColor(colors[color])
|
||||||
|
end
|
||||||
|
function ret.getBackgroundColor()
|
||||||
|
return icolors[term.getBackgroundColor()]
|
||||||
|
end
|
||||||
|
function ret.getTextColor()
|
||||||
|
return icolors[term.getTextColor()]
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.tty.register("tty0", newTTY(main))
|
||||||
|
|
||||||
|
for _, name in ipairs(getNames()) do
|
||||||
|
local t = getType(name)
|
||||||
|
if t == "monitor" then
|
||||||
|
local monitorTerm = wrapPeripheral(name)
|
||||||
|
monitorTerm.setTextScale(0.5)
|
||||||
|
kernel.tty.register(name, newTTY(monitorTerm))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1,285 @@
|
|||||||
function string.hasSuffix(a,b)return string.sub(a,#b+1)==b end;function string.hasPrefix(a,c)return string.sub(a,1,#c)==c end;function string.getSuffix(a,c)return string.sub(a,#c+1)end;function string.getPrefix(a,b)return string.sub(a,1,#b)end;function string.join(a,...)return table.concat(table.pack(a,...))end;function string.delim(a,...)return table.concat(table.pack(...),a)end;function string.split(a,d,e)assert(#d==1,"only delim len 1 supported for now")e=(e or 0)-1;local f={}local g=""for h=1,#a do local i=string.sub(a,h,h)if#f~=e and i==d then table.insert(f,g)g=""else g=g..i end end;table.insert(f,g)return f end;function string.replace(a,j,k)local f=""local l=1;local h=1;while h<#a do if string.sub(a,h,h+#j-1)==j then f=f..string.sub(a,l,h-1)..k;h=h+#j;l=h end;h=h+1 end;return f..string.sub(a,l)end;function table.deepcopy(m,n)n=n or{}if type(m)~='table'then return m elseif n[m]then return n[m]end;local o={}n[m]=o;for p,q in next,m,nil do local r=table.deepcopy(p,n)local s=table.deepcopy(q,n)o[r]=s end;return o end;function table.hasKey(t,u)for h,q in pairs(t)do if h==u then return true end end;return false end;function table.hasVal(t,u)for h,q in pairs(t)do if q==u then return true end end;return false end;function table.proxy(v)local w=setmetatable({},{__mode="k"})local function x(y)if type(y)~="table"then return y end;if w[y]then return w[y]end;local z={}w[y]=z;local A;A={__index=function(B,p)local C=y[p]if type(C)=="table"then return x(C)else return C end end,__newindex=function()error("Attempt to modify table proxy",2)end,__pairs=function()return function(B,p)local D,E=next(y,p)if type(E)=="table"then E=x(E)end;return D,E end,nil,nil end,__ipairs=function()local h=0;local F=#y;return function()h=h+1;if h<=F then local q=y[h]if type(q)=="table"then q=x(q)end;return h,q end end end,__metatable=false}setmetatable(z,A)return z end;return x(v)end;local function G(table)local H="{"for h,q in pairs(table)do local I=true;if type(h)=="string"then H=H.."[\""..h.."\"]="elseif type(h)=="number"then H=H.."["..tostring(h).."]="end;if type(q)=="table"then if q==table then H=string.sub(H,1,#H-(#h+1))I=false else H=H..G(q)end elseif type(q)=="string"then H=H.."[=["..q.."]=]"elseif type(q)=="number"then H=H..tostring(q)elseif type(q)=="boolean"then if q==true then H=H.."true"else H=H.."false"end elseif type(q)=="function"then H=H..tostring(q)else error("serialization of type \""..type(q).."\" is not supported")end;if I then H=H..","end end;if#table>0 or string.sub(H,#H,#H)==","then H=string.sub(H,1,#H-1)end;H=H.."}"return H end;local J=type;local K=getmetatable;function type(L,M)if M then return J(L)end;if J(L)~="table"then return J(L)else if J(K(L))=="table"then local N=K(L)if N.__type then return N.__type end else return"table"end end end;function getmetatable(L)if J(L)~="table"then return end;if J(K(L))=="table"then if K(L).__isuserdata then if J(K(L).__usermeta)=="function"then return K(L).__usermeta()else return K(L).__usermeta end else return K(L)end else return K(L)end end;function isEqualToAny(O,...)local P={...}for h=0,#P do if O==P[h]then return true end end;return false end;function isEqualToAll(O,...)local P={...}for h=0,#P do if O~=P[h]then return false end end;return true end;function table.keys(y)local O={}for F in pairs(y)do table.insert(O,F)end;return O end;function table.values(y)local O={}for B,F in pairs(y)do table.insert(O,F)end;return O end;function table.indexOf(y,C)for h,q in ipairs(y)do if q==C then return h end end;return-1 end;syscall=setmetatable({},{__index=function(self,Q)return function(...)local R=table.pack(coroutine.yield("syscall",Q,...))if R[1]then return table.unpack(R,2,R.n)else error(R[2],2)end end end})table.serialize=G
|
--:Minify:--
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
function table.proxy(tbl)
|
||||||
|
local proxies = setmetatable({}, {__mode = "k"}) -- Weak table to avoid cycles
|
||||||
|
|
||||||
|
local function createProxy(t)
|
||||||
|
if type(t) ~= "table" then return t end
|
||||||
|
if proxies[t] then return proxies[t] end -- reuse proxy for the same table (handle cycles)
|
||||||
|
|
||||||
|
local proxy = {}
|
||||||
|
proxies[t] = proxy
|
||||||
|
|
||||||
|
local mt
|
||||||
|
mt = {
|
||||||
|
__index = function(_, k)
|
||||||
|
local value = t[k]
|
||||||
|
if type(value) == "table" then
|
||||||
|
return createProxy(value) -- recursively proxy subtables
|
||||||
|
else
|
||||||
|
return value
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
__newindex = function()
|
||||||
|
error("Attempt to modify table proxy", 2)
|
||||||
|
end,
|
||||||
|
__pairs = function()
|
||||||
|
return function(_, k)
|
||||||
|
local nextKey, nextValue = next(t, k)
|
||||||
|
if type(nextValue) == "table" then
|
||||||
|
nextValue = createProxy(nextValue)
|
||||||
|
end
|
||||||
|
return nextKey, nextValue
|
||||||
|
end, nil, nil
|
||||||
|
end,
|
||||||
|
__ipairs = function()
|
||||||
|
local i = 0
|
||||||
|
local n = #t
|
||||||
|
return function()
|
||||||
|
i = i + 1
|
||||||
|
if i <= n then
|
||||||
|
local v = t[i]
|
||||||
|
if type(v) == "table" then
|
||||||
|
v = createProxy(v)
|
||||||
|
end
|
||||||
|
return i, v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
__metatable = false
|
||||||
|
}
|
||||||
|
|
||||||
|
setmetatable(proxy, mt)
|
||||||
|
return proxy
|
||||||
|
end
|
||||||
|
|
||||||
|
return createProxy(tbl)
|
||||||
|
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.."\"]="
|
||||||
|
elseif type(i) == "number" then
|
||||||
|
output=output.."["..tostring(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..tostring(v)
|
||||||
|
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
|
||||||
|
|
||||||
|
local oldtype=type
|
||||||
|
local oldgetmetatable=getmetatable
|
||||||
|
function type(object, trueType)
|
||||||
|
if trueType then
|
||||||
|
return oldtype(object)
|
||||||
|
end
|
||||||
|
if oldtype(object)~="table" then
|
||||||
|
return oldtype(object)
|
||||||
|
else
|
||||||
|
if oldtype(oldgetmetatable(object))=="table" then
|
||||||
|
local metatable = oldgetmetatable(object)
|
||||||
|
if metatable.__type then return metatable.__type end
|
||||||
|
else
|
||||||
|
return "table"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function getmetatable(object)
|
||||||
|
if oldtype(object)~="table" then return end
|
||||||
|
if oldtype(oldgetmetatable(object))=="table" then
|
||||||
|
if oldgetmetatable(object).__isuserdata then
|
||||||
|
if oldtype(oldgetmetatable(object).__usermeta)=="function" then
|
||||||
|
return oldgetmetatable(object).__usermeta()
|
||||||
|
else
|
||||||
|
return oldgetmetatable(object).__usermeta
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return oldgetmetatable(object)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return oldgetmetatable(object)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function isEqualToAny(a, ...)
|
||||||
|
local args={...}
|
||||||
|
for i=0, #args do
|
||||||
|
if a==args[i] then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function isEqualToAll(a, ...)
|
||||||
|
local args={...}
|
||||||
|
for i=0, #args do
|
||||||
|
if a~=args[i] then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.keys(t)
|
||||||
|
local a = {}
|
||||||
|
for n in pairs(t) do table.insert(a, n) end
|
||||||
|
return a
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.values(t)
|
||||||
|
local a = {}
|
||||||
|
for _, n in pairs(t) do table.insert(a, n) end
|
||||||
|
return a
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.indexOf(t, value)
|
||||||
|
for i,v in ipairs(t) do
|
||||||
|
if v==value then
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return -1
|
||||||
|
end
|
||||||
|
|
||||||
|
syscall = setmetatable({}, {
|
||||||
|
__index = function(self, name)
|
||||||
|
return function(...)
|
||||||
|
local res = table.pack(coroutine.yield("syscall", name, ...))
|
||||||
|
if res[1] then
|
||||||
|
return table.unpack(res, 2, res.n)
|
||||||
|
else
|
||||||
|
error(res[2], 2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
table.serialize=serialize
|
||||||
@@ -1 +1,278 @@
|
|||||||
local a=...local b={}b.mounts={["$"]="/"}local c=a.disks;local function d(e)local f={}for g in e:gmatch("[^/]+")do if g==".."then if#f>0 then table.remove(f)end elseif g~="."and g~=""then table.insert(f,g)end end;return"/"..table.concat(f,"/")..(e:sub(-1)=="/"and"/"or"")end;local function h(e)local i=a.currentTask;local j=i.cwd or"/"if e:sub(1,1)~="/"then e=j..e end;e=d(e)local k="/"local l="$"for m,n in pairs(b.mounts)do if e:sub(1,#n)==n and#n>#k then k=n;l=m end end;local o=e:sub(#k+1)return c[l],o end;local function p(q,r,s,e)return{disk=q,handle=r,mode=s,path=e,refcount=1}end;local function t(i)local u=0;while i.fd[u]do u=u+1 end;return u end;local function t(i)local v=0;for w in pairs(i.fd)do v=v+1 end;if v>=a.config.maxFilesPerTask then error("EMFILE")end;local u=0;while i.fd[u]do u=u+1 end;return u end;local function x()local y=0;for w,i in pairs(a.tasks or{})do for w in pairs(i.fd)do y=y+1 end end;if y>=a.config.maxOpenFiles then error("ENFILE")end end;function b.open(e,s)local i=a.currentTask;x()local q,o=h(e)if not q then error("No disk mounted for path '"..e.."'")end;local r=q:open(o,s)if not r then return nil end;local z=p(q.address,r,s,e)local u=t(i)i.fd[u]=z;return u end;function b.close(u)local i=a.currentTask;local z=i.fd[u]if not z then error("EBADF")end;i.fd[u]=nil;z.refcount=z.refcount-1;if z.refcount==0 then z.handle.close()end;return true end;function b.read(u,v)local z=a.currentTask.fd[u]if not z then error("EBADF")end;if not z.mode:find("r")then error("File not open for reading")end;return z.handle.read(v)end;function b.write(u,A)local z=a.currentTask.fd[u]if not z then error("EBADF")end;if not z.mode:find("w")then error("File not open for writing")end;return z.handle.write(A)end;function b.whereis(u)local z=a.currentTask.fd[u]if not z then error("EBADF")end;return z.path end;function b.mkdir(e)local q,o=h(e)if not q then error("No disk mounted")end;return q:makeDirectory(o)end;function b.remove(e)local q,o=h(e)if not q then error("No disk mounted")end;return q:remove(o)end;function b.attributes(e)if type(e)=="number"then local z=a.currentTask.fd[e]if not z then error("EBADF")end;return c[z.disk]:attributes(z.path)end;local q,o=h(e)if not q then error("No disk mounted")end;return q:attributes(o)end;function b.list(e)local q,o=h(e)if not q then error("No disk mounted")end;return q:list(o)end;function b.exists(e)local q,o=h(e)if not q then return false end;return q:directoryExists(o)or q:fileExists(o)end;function b.type(e)if type(e)=="number"then local z=a.currentTask.fd[e]if not z then error("EBADF")end;return c[z.disk]:type(z.path)end;local q,o=h(e)if not q then error("No disk mounted")end;return q:type(o)end;function b.getcwd()return a.currentTask.cwd end;function b.setcwd(e)if e:sub(-1)~="/"then e=e.."/"end;if e:sub(1,1)~="/"then e="/"..e end;a.currentTask.cwd=d(e)end;function b.mount(B,e)if a.uid~=0 then error("Permission denied")end;if not c[B]then error("Unknown disk '"..B.."'")end;if e:sub(-1)~="/"then e=e.."/"end;for w,n in pairs(b.mounts)do if n==e then error("Mount point already used")end end;b.mounts[B]=e end;function b.unmount(e)if a.uid~=0 then error("Permission denied")end;for m,n in pairs(b.mounts)do if n==e then b.mounts[m]=nil;return true end end;return false end;function b.getMounts()return b.mounts end;function b.virtdisk(C)a.disks[C.address]=C;a.log("Registered virtual disk at "..C.address)end;function b.dup(D)local i=a.currentTask;local z=i.fd[D]if not z then error("EBADF")end;local E=t(i)i.fd[E]=z;z.refcount=z.refcount+1;return E end;function b.dup2(D,E)local i=a.currentTask;local z=i.fd[D]if not z then error("EBADF")end;if D==E then return E end;if i.fd[E]then b.close(E)end;i.fd[E]=z;z.refcount=z.refcount+1;return E end;a.vfs=b;a.syscalls["VFS_open"]=b.open;a.syscalls["VFS_read"]=b.read;a.syscalls["VFS_write"]=b.write;a.syscalls["VFS_close"]=b.close;a.syscalls["VFS_list"]=b.list;a.syscalls["VFS_type"]=b.type;a.syscalls["VFS_attributes"]=b.attributes;a.syscalls["VFS_mkdir"]=b.mkdir;a.syscalls["VFS_remove"]=b.remove;a.syscalls["VFS_exists"]=b.exists;a.syscalls["VFS_mount"]=b.mount;a.syscalls["VFS_unmount"]=b.unmount;a.syscalls["VFS_getcwd"]=b.getcwd;a.syscalls["VFS_setcwd"]=b.setcwd;a.syscalls["VFS_whereis"]=b.whereis;a.syscalls["VFS_dup"]=b.dup;a.syscalls["VFS_dup2"]=b.dup2;a.log("VFS module loaded")
|
--:Minify:--
|
||||||
|
local kernel = ...
|
||||||
|
local vfs = {}
|
||||||
|
vfs.mounts = { ["$"] = "/" }
|
||||||
|
local disks = kernel.disks
|
||||||
|
|
||||||
|
-- Path handling
|
||||||
|
local function normalizePath(path)
|
||||||
|
local parts = {}
|
||||||
|
for part in path:gmatch("[^/]+") do
|
||||||
|
if part == ".." then
|
||||||
|
if #parts > 0 then table.remove(parts) end
|
||||||
|
elseif part ~= "." and part ~= "" then
|
||||||
|
table.insert(parts, part)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return "/" .. table.concat(parts, "/") .. (path:sub(-1) == "/" and "/" or "")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function resolvePath(path)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local cwd = task.cwd or "/"
|
||||||
|
|
||||||
|
if path:sub(1,1) ~= "/" then
|
||||||
|
path = cwd .. path
|
||||||
|
end
|
||||||
|
|
||||||
|
path = normalizePath(path)
|
||||||
|
|
||||||
|
local mountPoint = "/"
|
||||||
|
local mountId = "$"
|
||||||
|
for k,v in pairs(vfs.mounts) do
|
||||||
|
if path:sub(1,#v) == v and #v > #mountPoint then
|
||||||
|
mountPoint = v
|
||||||
|
mountId = k
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local diskPath = path:sub(#mountPoint + 1)
|
||||||
|
return disks[mountId], diskPath
|
||||||
|
end
|
||||||
|
|
||||||
|
-- File object creation
|
||||||
|
local function newFileObject(disk, handle, mode, path)
|
||||||
|
return {
|
||||||
|
disk = disk,
|
||||||
|
handle = handle,
|
||||||
|
mode = mode,
|
||||||
|
path = path,
|
||||||
|
refcount = 1
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local function allocFD(task)
|
||||||
|
local fd = 0
|
||||||
|
while task.fd[fd] do fd = fd + 1 end
|
||||||
|
return fd
|
||||||
|
end
|
||||||
|
|
||||||
|
local function allocFD(task)
|
||||||
|
-- enforce per-task limit
|
||||||
|
local count = 0
|
||||||
|
for _ in pairs(task.fd) do count = count + 1 end
|
||||||
|
if count >= kernel.config.maxFilesPerTask then
|
||||||
|
error("EMFILE") -- Too many open files in this task
|
||||||
|
end
|
||||||
|
|
||||||
|
-- find first free FD
|
||||||
|
local fd = 0
|
||||||
|
while task.fd[fd] do fd = fd + 1 end
|
||||||
|
return fd
|
||||||
|
end
|
||||||
|
|
||||||
|
local function checkSystemLimit()
|
||||||
|
-- enforce system-wide limit
|
||||||
|
local total = 0
|
||||||
|
for _, task in pairs(kernel.tasks or {}) do
|
||||||
|
for _ in pairs(task.fd) do total = total + 1 end
|
||||||
|
end
|
||||||
|
if total >= kernel.config.maxOpenFiles then
|
||||||
|
error("ENFILE") -- Too many open files in the system
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- VFS syscalls
|
||||||
|
function vfs.open(path, mode)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
|
||||||
|
-- check limits
|
||||||
|
checkSystemLimit()
|
||||||
|
|
||||||
|
local disk, diskPath = resolvePath(path)
|
||||||
|
if not disk then
|
||||||
|
error("No disk mounted for path '"..path.."'")
|
||||||
|
end
|
||||||
|
|
||||||
|
local handle = disk:open(diskPath, mode)
|
||||||
|
if not handle then return nil end
|
||||||
|
|
||||||
|
local file = newFileObject(disk.address, handle, mode, path)
|
||||||
|
local fd = allocFD(task)
|
||||||
|
task.fd[fd] = file
|
||||||
|
|
||||||
|
return fd
|
||||||
|
end
|
||||||
|
|
||||||
|
function vfs.close(fd)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local file = task.fd[fd]
|
||||||
|
if not file then error("EBADF") end
|
||||||
|
|
||||||
|
task.fd[fd] = nil
|
||||||
|
file.refcount = file.refcount - 1
|
||||||
|
if file.refcount == 0 then
|
||||||
|
file.handle.close()
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function vfs.read(fd, count)
|
||||||
|
local file = kernel.currentTask.fd[fd]
|
||||||
|
if not file then error("EBADF") end
|
||||||
|
if not file.mode:find("r") then error("File not open for reading") end
|
||||||
|
return file.handle.read(count)
|
||||||
|
end
|
||||||
|
|
||||||
|
function vfs.write(fd, data)
|
||||||
|
local file = kernel.currentTask.fd[fd]
|
||||||
|
if not file then error("EBADF") end
|
||||||
|
if not file.mode:find("w") then error("File not open for writing") end
|
||||||
|
return file.handle.write(data)
|
||||||
|
end
|
||||||
|
|
||||||
|
function vfs.whereis(fd)
|
||||||
|
local file = kernel.currentTask.fd[fd]
|
||||||
|
if not file then error("EBADF") end
|
||||||
|
return file.path
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Filesystem operations
|
||||||
|
function vfs.mkdir(path)
|
||||||
|
local disk, diskPath = resolvePath(path)
|
||||||
|
if not disk then error("No disk mounted") end
|
||||||
|
return disk:makeDirectory(diskPath)
|
||||||
|
end
|
||||||
|
|
||||||
|
function vfs.remove(path)
|
||||||
|
local disk, diskPath = resolvePath(path)
|
||||||
|
if not disk then error("No disk mounted") end
|
||||||
|
return disk:remove(diskPath)
|
||||||
|
end
|
||||||
|
|
||||||
|
function vfs.attributes(path)
|
||||||
|
if type(path) == "number" then
|
||||||
|
local file = kernel.currentTask.fd[path]
|
||||||
|
if not file then error("EBADF") end
|
||||||
|
return disks[file.disk]:attributes(file.path)
|
||||||
|
end
|
||||||
|
local disk, diskPath = resolvePath(path)
|
||||||
|
if not disk then error("No disk mounted") end
|
||||||
|
return disk:attributes(diskPath)
|
||||||
|
end
|
||||||
|
|
||||||
|
function vfs.list(path)
|
||||||
|
local disk, diskPath = resolvePath(path)
|
||||||
|
if not disk then error("No disk mounted") end
|
||||||
|
return disk:list(diskPath)
|
||||||
|
end
|
||||||
|
|
||||||
|
function vfs.exists(path)
|
||||||
|
local disk, diskPath = resolvePath(path)
|
||||||
|
if not disk then return false end
|
||||||
|
return disk:directoryExists(diskPath) or disk:fileExists(diskPath)
|
||||||
|
end
|
||||||
|
|
||||||
|
function vfs.type(path)
|
||||||
|
if type(path) == "number" then
|
||||||
|
local file = kernel.currentTask.fd[path]
|
||||||
|
if not file then error("EBADF") end
|
||||||
|
return disks[file.disk]:type(file.path)
|
||||||
|
end
|
||||||
|
local disk, diskPath = resolvePath(path)
|
||||||
|
if not disk then error("No disk mounted") end
|
||||||
|
return disk:type(diskPath)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- CWD
|
||||||
|
function vfs.getcwd()
|
||||||
|
return kernel.currentTask.cwd
|
||||||
|
end
|
||||||
|
|
||||||
|
function vfs.setcwd(path)
|
||||||
|
if path:sub(-1) ~= "/" then path = path .. "/" end
|
||||||
|
if path:sub(1,1) ~= "/" then path = "/" .. path end
|
||||||
|
kernel.currentTask.cwd = normalizePath(path)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Mounting
|
||||||
|
function vfs.mount(diskId, path)
|
||||||
|
if kernel.uid ~= 0 then error("Permission denied") end
|
||||||
|
if not disks[diskId] then error("Unknown disk '"..diskId.."'") end
|
||||||
|
if path:sub(-1) ~= "/" then path = path .. "/" end
|
||||||
|
|
||||||
|
for _,v in pairs(vfs.mounts) do
|
||||||
|
if v == path then error("Mount point already used") end
|
||||||
|
end
|
||||||
|
vfs.mounts[diskId] = path
|
||||||
|
end
|
||||||
|
|
||||||
|
function vfs.unmount(path)
|
||||||
|
if kernel.uid ~= 0 then error("Permission denied") end
|
||||||
|
for k,v in pairs(vfs.mounts) do
|
||||||
|
if v == path then
|
||||||
|
vfs.mounts[k] = nil
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function vfs.getMounts()
|
||||||
|
return vfs.mounts
|
||||||
|
end
|
||||||
|
|
||||||
|
function vfs.virtdisk(obj)
|
||||||
|
kernel.disks[obj.address] = obj
|
||||||
|
kernel.log("Registered virtual disk at "..obj.address)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Redirect file operations to VFS
|
||||||
|
function vfs.dup(oldfd)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local file = task.fd[oldfd]
|
||||||
|
if not file then error("EBADF") end
|
||||||
|
|
||||||
|
local newfd = allocFD(task)
|
||||||
|
task.fd[newfd] = file
|
||||||
|
file.refcount = file.refcount + 1
|
||||||
|
return newfd
|
||||||
|
end
|
||||||
|
|
||||||
|
function vfs.dup2(oldfd, newfd)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local file = task.fd[oldfd]
|
||||||
|
if not file then error("EBADF") end
|
||||||
|
|
||||||
|
if oldfd == newfd then return newfd end
|
||||||
|
|
||||||
|
if task.fd[newfd] then
|
||||||
|
vfs.close(newfd)
|
||||||
|
end
|
||||||
|
|
||||||
|
task.fd[newfd] = file
|
||||||
|
file.refcount = file.refcount + 1
|
||||||
|
return newfd
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Syscall registration
|
||||||
|
kernel.vfs = vfs
|
||||||
|
kernel.syscalls["VFS_open"] = vfs.open
|
||||||
|
kernel.syscalls["VFS_read"] = vfs.read
|
||||||
|
kernel.syscalls["VFS_write"] = vfs.write
|
||||||
|
kernel.syscalls["VFS_close"] = vfs.close
|
||||||
|
kernel.syscalls["VFS_list"] = vfs.list
|
||||||
|
kernel.syscalls["VFS_type"] = vfs.type
|
||||||
|
kernel.syscalls["VFS_attributes"] = vfs.attributes
|
||||||
|
kernel.syscalls["VFS_mkdir"] = vfs.mkdir
|
||||||
|
kernel.syscalls["VFS_remove"] = vfs.remove
|
||||||
|
kernel.syscalls["VFS_exists"] = vfs.exists
|
||||||
|
kernel.syscalls["VFS_mount"] = vfs.mount
|
||||||
|
kernel.syscalls["VFS_unmount"] = vfs.unmount
|
||||||
|
kernel.syscalls["VFS_getcwd"] = vfs.getcwd
|
||||||
|
kernel.syscalls["VFS_setcwd"] = vfs.setcwd
|
||||||
|
kernel.syscalls["VFS_whereis"] = vfs.whereis
|
||||||
|
kernel.syscalls["VFS_dup"] = vfs.dup
|
||||||
|
kernel.syscalls["VFS_dup2"] = vfs.dup2
|
||||||
|
|
||||||
|
kernel.log("VFS module loaded")
|
||||||
|
|||||||
@@ -1 +1,43 @@
|
|||||||
local a=...local b={}local c={"/lib/?.lua","/lib/?","/usr/lib/?.lua","/usr/lib/?","/usr/local/lib/?.lua","/usr/local/lib/?","?.lua","?"}function require(d,...)if b[d]then return b[d]end;local e=d:gsub("%.","/")local f={}for g,h in ipairs(c)do local i=string.gsub(h,"%?",e)if i:sub(1,1)~="/"then i=a.currentTask.cwd..i end;if a.vfs.exists(i)then if a.vfs.type(i)=="directory"then i=i.."/init"end;if a.vfs.exists(i)then local j=a.vfs.open(i,"r")local k=a.vfs.read(j,1024*1024*4)a.vfs.close(j)return assert(load(k,i,"t",a._U))(...)else table.insert(f,i)end else table.insert(f,i)end end;error("Module not found: "..d.." (searched paths: "..table.concat(f,", ")..")")end
|
--:Minify:--
|
||||||
|
local kernel = ...
|
||||||
|
local cache = {}
|
||||||
|
local searchpaths = {
|
||||||
|
"/lib/?.lua",
|
||||||
|
"/lib/?",
|
||||||
|
"/usr/lib/?.lua",
|
||||||
|
"/usr/lib/?",
|
||||||
|
"/usr/local/lib/?.lua",
|
||||||
|
"/usr/local/lib/?",
|
||||||
|
"?.lua",
|
||||||
|
"?"
|
||||||
|
}
|
||||||
|
|
||||||
|
function require(module,...)
|
||||||
|
if cache[module] then
|
||||||
|
return cache[module]
|
||||||
|
end
|
||||||
|
local modpath = module:gsub("%.", "/")
|
||||||
|
local failed = {}
|
||||||
|
for _, path in ipairs(searchpaths) do
|
||||||
|
local full_path = string.gsub(path, "%?", modpath)
|
||||||
|
if full_path:sub(1,1)~="/" then
|
||||||
|
full_path=kernel.currentTask.cwd..full_path
|
||||||
|
end
|
||||||
|
if kernel.vfs.exists(full_path) then
|
||||||
|
if kernel.vfs.type(full_path)=="directory" then
|
||||||
|
full_path = full_path .. "/init"
|
||||||
|
end
|
||||||
|
if kernel.vfs.exists(full_path) then
|
||||||
|
local handle = kernel.vfs.open(full_path, "r")
|
||||||
|
local file_content = kernel.vfs.read(handle, 1024 * 1024 * 4)
|
||||||
|
kernel.vfs.close(handle)
|
||||||
|
return assert(load(file_content, full_path, "t", kernel._U))(...)
|
||||||
|
else
|
||||||
|
table.insert(failed, full_path)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
table.insert(failed, full_path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
error("Module not found: " .. module .. " (searched paths: " .. table.concat(failed, ", ") .. ")")
|
||||||
|
end
|
||||||
@@ -1 +1,173 @@
|
|||||||
local a=...local b={}local c={}b.address="devfs0000"b.isReadOnly=false;b.spaceUsed=function()return 0 end;b.spaceTotal=function()return 0 end;b.makeDirectory=function()error("Permission denied")end;b.remove=function()error("Permission denied")end;b.setLabel=function()error("Permission denied")end;b.getLabel=function()return"devfs"end;b.attributes=function(d)return{type=b.type(d),isReadOnly=false,size=0,lastModified=0,created=0,Permissions="666",owner="root",group="root"}end;local function e(d)local f=string.split(d,"/")if f[1]==""then table.remove(f,1)end;local g=c;for h,i in ipairs(f)do if g[i]then g=g[i]else return nil end end;return g end;b.type=function(d)local g=e(d)if g then return g.type else return nil end end;b.list=function(d)local g=e(d)if g and g.type=="directory"then local j=table.keys(g)table.remove(j,table.indexOf(j,"type"))return j else error("Not a directory")end end;b.open=function(d,k)local g=e(d)if g and(g.type=="file"or g.type=="character device")then if k=="r"then return{read=g.read,close=function()end}elseif k=="w"then return{write=g.write,close=function()end}else error("Invalid mode")end else error("Not a file"..type(g))end end;local function l(j)return{type="file",read=function()return j end,write=function(m)j=m end}end;local function n()return{type="directory"}end;c["random"]={type="character device",read=function(o)local p=""for h=1,o do p=p..string.char(math.random(0,255))end;return p end,write=function()error("Permission denied")end}c["null"]={type="character device",read=function()return""end,write=function()end}c["zero"]={type="character device",read=function(o)return string.rep("\0",o)end,write=function()error("Permission denied")end}c["rtc"]={type="character device",read=function()return a.computer:time()end,write=function()error("Permission denied")end}c["rtc0"]={type="character device",read=function()return a.computer:time()end,write=function()error("Permission denied")end}c["eeprom"]={type="character device",read=function()return a.computer:getEEPROM()end,write=function(c)if a.uid~=0 then error("Permission denied")end;a.computer:setEEPROM(c)end}local q=a.newFifo()local r=a.newFifo()c["input"]=n()c["input"]["keyboard"]={type="pipe",read=function(o)return q.pop()end,write=function()error("Permission denied")end}c["input"]["mouse"]={type="pipe",read=function(o)return r.pop()end,write=function()error("Permission denied")end}c["pts"]=n()a.devfs={}a.devfs.keyboard=q;a.devfs.mouse=r;a.devfs.proxy=b;a.devfs.data=c;a.vfs.virtdisk(b)
|
--:Minify:--
|
||||||
|
local kernel = ...
|
||||||
|
|
||||||
|
local proxy = {}
|
||||||
|
local data = {}
|
||||||
|
|
||||||
|
proxy.address = "devfs0000"
|
||||||
|
proxy.isReadOnly = false
|
||||||
|
proxy.spaceUsed = function() return 0 end
|
||||||
|
proxy.spaceTotal = function() return 0 end
|
||||||
|
proxy.makeDirectory = function() error("Permission denied") end
|
||||||
|
proxy.remove = function() error("Permission denied") end
|
||||||
|
proxy.setLabel = function() error("Permission denied") end
|
||||||
|
proxy.getLabel = function() return "devfs" end
|
||||||
|
proxy.attributes = function(path) return {
|
||||||
|
type = proxy.type(path),
|
||||||
|
isReadOnly = false,
|
||||||
|
size = 0,
|
||||||
|
lastModified = 0,
|
||||||
|
created = 0,
|
||||||
|
Permissions = "666",
|
||||||
|
owner = "root",
|
||||||
|
group = "root"
|
||||||
|
} end
|
||||||
|
|
||||||
|
local function getNode(path)
|
||||||
|
local parts = string.split(path, "/")
|
||||||
|
if parts[1] == "" then
|
||||||
|
table.remove(parts, 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
local node = data
|
||||||
|
for _, part in ipairs(parts) do
|
||||||
|
if node[part] then
|
||||||
|
node = node[part]
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return node
|
||||||
|
end
|
||||||
|
|
||||||
|
proxy.type = function(path)
|
||||||
|
local node = getNode(path)
|
||||||
|
if node then
|
||||||
|
return node.type
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
proxy.list = function(path)
|
||||||
|
local node = getNode(path)
|
||||||
|
if node and node.type == "directory" then
|
||||||
|
local content = table.keys(node)
|
||||||
|
table.remove(content, table.indexOf(content, "type"))
|
||||||
|
return content
|
||||||
|
else
|
||||||
|
error("Not a directory")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
proxy.open = function(path, mode)
|
||||||
|
local node = getNode(path)
|
||||||
|
if node and (node.type == "file" or node.type == "character device") then
|
||||||
|
if mode == "r" then
|
||||||
|
return {
|
||||||
|
read = node.read,
|
||||||
|
close = function() end
|
||||||
|
}
|
||||||
|
elseif mode == "w" then
|
||||||
|
return {
|
||||||
|
write = node.write,
|
||||||
|
close = function() end
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error("Invalid mode")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
error("Not a file"..type(node))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function newStringFile(content)
|
||||||
|
return {
|
||||||
|
type = "file",
|
||||||
|
read = function() return content end,
|
||||||
|
write = function(newContent) content = newContent end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local function newDirectory()
|
||||||
|
return {
|
||||||
|
type = "directory"
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
data["random"] = {
|
||||||
|
type = "character device",
|
||||||
|
read = function(amount)
|
||||||
|
local result = ""
|
||||||
|
for _ = 1, amount do
|
||||||
|
result = result .. string.char(math.random(0, 255))
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end,
|
||||||
|
write = function() error("Permission denied") end
|
||||||
|
}
|
||||||
|
|
||||||
|
data["null"] = {
|
||||||
|
type = "character device",
|
||||||
|
read = function() return "" end,
|
||||||
|
write = function() end
|
||||||
|
}
|
||||||
|
|
||||||
|
data["zero"] = {
|
||||||
|
type = "character device",
|
||||||
|
read = function(amount)
|
||||||
|
return string.rep("\0", amount)
|
||||||
|
end,
|
||||||
|
write = function() error("Permission denied") end
|
||||||
|
}
|
||||||
|
|
||||||
|
data["rtc"] = {
|
||||||
|
type = "character device",
|
||||||
|
read = function() return kernel.computer:time() end,
|
||||||
|
write = function() error("Permission denied") end
|
||||||
|
}
|
||||||
|
|
||||||
|
data["rtc0"] = {
|
||||||
|
type = "character device",
|
||||||
|
read = function() return kernel.computer:time() end,
|
||||||
|
write = function() error("Permission denied") end
|
||||||
|
}
|
||||||
|
|
||||||
|
data["eeprom"] = {
|
||||||
|
type = "character device",
|
||||||
|
read = function() return kernel.computer:getEEPROM() end,
|
||||||
|
write = function(data)
|
||||||
|
if kernel.uid ~= 0 then
|
||||||
|
error("Permission denied")
|
||||||
|
end
|
||||||
|
kernel.computer:setEEPROM(data)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
local keyboard = kernel.newFifo()
|
||||||
|
local mouse = kernel.newFifo()
|
||||||
|
data["input"] = newDirectory()
|
||||||
|
data["input"]["keyboard"] = {
|
||||||
|
type = "pipe",
|
||||||
|
read = function(amount)
|
||||||
|
return keyboard.pop()
|
||||||
|
end,
|
||||||
|
write = function() error("Permission denied") end
|
||||||
|
}
|
||||||
|
data["input"]["mouse"] = {
|
||||||
|
type = "pipe",
|
||||||
|
read = function(amount)
|
||||||
|
return mouse.pop()
|
||||||
|
end,
|
||||||
|
write = function() error("Permission denied") end
|
||||||
|
}
|
||||||
|
|
||||||
|
data["pts"] = newDirectory()
|
||||||
|
|
||||||
|
kernel.devfs = {}
|
||||||
|
kernel.devfs.keyboard = keyboard
|
||||||
|
kernel.devfs.mouse = mouse
|
||||||
|
kernel.devfs.proxy = proxy
|
||||||
|
kernel.devfs.data = data
|
||||||
|
kernel.vfs.virtdisk(proxy)
|
||||||
@@ -1 +1,14 @@
|
|||||||
local a=...a.processes.keventd=function()while true do local b={a.computer:getMachineEvent()}if b[1]then if b[1]=="key"or b[1]=="keyPressed"or b[1]=="keyReleased"then a.devfs.keyboard.push(b)end end end end
|
--:Minify:--
|
||||||
|
local kernel = ...
|
||||||
|
local events = kernel.newFifo()
|
||||||
|
|
||||||
|
kernel.processes.keventd = function()
|
||||||
|
while true do
|
||||||
|
local event = {kernel.computer:getMachineEvent()}
|
||||||
|
if event[1] then
|
||||||
|
events.push(event)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.syscalls["IO_getEventAny"]=events.pop
|
||||||
|
|||||||
@@ -1 +1,18 @@
|
|||||||
local a=...for b,c in ipairs(string.split(a.fstab,"\n"))do if c:sub(1,1)=="U"then local d=""for b=3,#c do if c:sub(b,b)==";"then if b==3 then a.log("Invalid fstab line... Skipping.","WARN")goto e end;d=c:sub(3,b-1)end end;local f=c:sub(#d+4)if d~="$"then a.vfs.mount(d,f)end::e::end end
|
--:Minify:--
|
||||||
|
local kernel=...
|
||||||
|
for i,v in ipairs(string.split(kernel.fstab,"\n")) do
|
||||||
|
if v:sub(1,1)=="U" then
|
||||||
|
local id=""
|
||||||
|
for i=3,#v do
|
||||||
|
if v:sub(i,i)==";" then
|
||||||
|
if i==3 then kernel.log("Invalid fstab line... Skipping.","WARN") goto endline end
|
||||||
|
id=v:sub(3,i-1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local path=v:sub(#id+4)
|
||||||
|
if id~="$" then
|
||||||
|
kernel.vfs.mount(id,path)
|
||||||
|
end
|
||||||
|
::endline::
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1 +1,76 @@
|
|||||||
local a=...local b={}local c={}local d={}function d.open(e)if not b[e]then local f=a.newUUID()b[e]={owner=a.currentProcess.pid,handle=f,messages={}}return b[e].handle end;error("Port already opened")end;function d.close(e)if b[e]then if b[e].owner==a.currentProcess.pid then b[e]=nil;return true else error("Cannot close port you do not own")end end;error("Port not opened")end;function d.send(e,g)if b[e]then table.insert(b[e].messages,{from=a.currentProcess.pid,message=g})if c[b[e].owner]then c[b[e].owner](e,g)end;return true end;error("Port not opened")end;function d.receive(e)if b[e]then if#b[e].messages>0 then return table.remove(b[e].messages,1)else return nil end end;error("Port not opened")end;function d.setSignalHandler(h,i)c[h]=i end;function d.clearSignalHandler(h)c[h]=nil end;function d.sendSignal(h,...)coroutine.resumeWithTimeout(coroutine.create(function(...)if c[h]then c[h](...)return true end end),100)return false end;a.ipc=d;a.syscalls["ipc_open"]=d.open;a.syscalls["ipc_close"]=d.close;a.syscalls["ipc_send"]=d.send;a.syscalls["ipc_receive"]=d.receive;a.syscalls["ipc_setSignalHandler"]=d.setSignalHandler;a.syscalls["ipc_clearSignalHandler"]=d.clearSignalHandler;a.syscalls["ipc_sendSignal"]=d.sendSignal;a.log("Loaded IPC module")
|
--:Minify:--
|
||||||
|
local kernel = ...
|
||||||
|
local ports = {}
|
||||||
|
local signals = {}
|
||||||
|
local ipc = {}
|
||||||
|
|
||||||
|
function ipc.open(port)
|
||||||
|
if not ports[port] then
|
||||||
|
local handle = kernel.newUUID()
|
||||||
|
ports[port] = {owner = kernel.currentProcess.pid, handle = handle, messages = {}}
|
||||||
|
return ports[port].handle
|
||||||
|
end
|
||||||
|
error("Port already opened")
|
||||||
|
end
|
||||||
|
|
||||||
|
function ipc.close(port)
|
||||||
|
if ports[port] then
|
||||||
|
if ports[port].owner == kernel.currentProcess.pid then
|
||||||
|
ports[port] = nil
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
error("Cannot close port you do not own")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
error("Port not opened")
|
||||||
|
end
|
||||||
|
|
||||||
|
function ipc.send(port, message)
|
||||||
|
if ports[port] then
|
||||||
|
table.insert(ports[port].messages, {from = kernel.currentProcess.pid, message = message})
|
||||||
|
if signals[ports[port].owner] then
|
||||||
|
signals[ports[port].owner](port, message)
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
error("Port not opened")
|
||||||
|
end
|
||||||
|
|
||||||
|
function ipc.receive(port)
|
||||||
|
if ports[port] then
|
||||||
|
if #ports[port].messages > 0 then
|
||||||
|
return table.remove(ports[port].messages, 1)
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
error("Port not opened")
|
||||||
|
end
|
||||||
|
|
||||||
|
function ipc.setSignalHandler(pid, handler)
|
||||||
|
signals[pid] = handler
|
||||||
|
end
|
||||||
|
|
||||||
|
function ipc.clearSignalHandler(pid)
|
||||||
|
signals[pid] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function ipc.sendSignal(pid, ...)
|
||||||
|
coroutine.resumeWithTimeout(coroutine.create(function(...)
|
||||||
|
if signals[pid] then
|
||||||
|
signals[pid](...)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end), 100)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.ipc = ipc
|
||||||
|
kernel.syscalls["ipc_open"] = ipc.open
|
||||||
|
kernel.syscalls["ipc_close"] = ipc.close
|
||||||
|
kernel.syscalls["ipc_send"] = ipc.send
|
||||||
|
kernel.syscalls["ipc_receive"] = ipc.receive
|
||||||
|
kernel.syscalls["ipc_setSignalHandler"] = ipc.setSignalHandler
|
||||||
|
kernel.syscalls["ipc_clearSignalHandler"] = ipc.clearSignalHandler
|
||||||
|
kernel.syscalls["ipc_sendSignal"] = ipc.sendSignal
|
||||||
|
kernel.log("Loaded IPC module")
|
||||||
@@ -1 +1,18 @@
|
|||||||
local a={...}local b=a[1]b._G=_G;b._U=setmetatable({},{__index=b._G,__newindex=function(c,d,e)if b.config.allowGlobalOverwrites or b.allowGlobalOverwrites then rawset(c,d,e)return end;error("Attempt to modify global variable '"..d.."'",2)end,__metatable=false})b.allowGlobalOverwrites=true;b._U._G=b._U;b.allowGlobalOverwrites=false
|
--:Minify:--
|
||||||
|
local args={...}
|
||||||
|
local kernel=args[1]
|
||||||
|
kernel._G=_G
|
||||||
|
kernel._U=setmetatable({},{
|
||||||
|
__index = kernel._G,
|
||||||
|
__newindex = function(t,k,v)
|
||||||
|
if kernel.config.allowGlobalOverwrites or kernel.allowGlobalOverwrites then
|
||||||
|
rawset(t,k,v)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
error("Attempt to modify global variable '"..k.."'",2)
|
||||||
|
end,
|
||||||
|
__metatable = false
|
||||||
|
})
|
||||||
|
kernel.allowGlobalOverwrites=true
|
||||||
|
kernel._U._G=kernel._U
|
||||||
|
kernel.allowGlobalOverwrites=false
|
||||||
@@ -1 +1,66 @@
|
|||||||
local a=...local b={}a.pam=b;local c={}local function d(e)local f=a.vfs.open(e,"r")if not f then error("Failed to open file: "..e)end;local g=a.vfs.read(f,1024000)a.vfs.close(f)return g end;local h=require("crypto.blake2s")if not h then error("Failed to load blake2s")end;if not a.vfs.exists("/etc/pam.d/secret")then local i=""for j=1,256 do i=i..string.char(math.random(1,255))end;local k=a.vfs.open("/etc/pam.d/secret","w")a.vfs.write(k,i)a.vfs.close(k)end;local l=d("/etc/pam.d/secret")function b.authenticate(m,n)local o=d("/etc/passwd")local p=d("/etc/shadow")local q=string.split(o,"\n")local r=string.split(p,"\n")local s={}local t={}for u,v in ipairs(q)do local w=string.split(v,":")s[w[1]]=w end;for u,v in ipairs(r)do local w=string.split(v,":")t[w[1]]=w end;for x,w in pairs(s)do if x==m then local y=string.split(t[x][2],"$")local z=y[2]local A=h(n..z,l)if A==y[3]then c[m]=a.newUUID()return c[m]else return false end end end end;function b.authToken(m,B)return c[m]==B end
|
--:Minify:--
|
||||||
|
local kernel = ...
|
||||||
|
local pam = {}
|
||||||
|
kernel.pam = pam
|
||||||
|
local loggedIn = {}
|
||||||
|
|
||||||
|
local function getFile(path)
|
||||||
|
local file = kernel.vfs.open(path, "r")
|
||||||
|
if not file then error("Failed to open file: "..path) end
|
||||||
|
local content = kernel.vfs.read(file, 1024000)
|
||||||
|
kernel.vfs.close(file)
|
||||||
|
return content
|
||||||
|
end
|
||||||
|
|
||||||
|
local blake2s = require("crypto.blake2s")
|
||||||
|
if not blake2s then error("Failed to load blake2s") end
|
||||||
|
|
||||||
|
if not kernel.vfs.exists("/etc/pam.d/secret") then
|
||||||
|
local key = ""
|
||||||
|
for i=1, 256 do
|
||||||
|
key=key..string.char(math.random(1,255))
|
||||||
|
end
|
||||||
|
local handle = kernel.vfs.open("/etc/pam.d/secret", "w")
|
||||||
|
kernel.vfs.write(handle, key)
|
||||||
|
kernel.vfs.close(handle)
|
||||||
|
end
|
||||||
|
|
||||||
|
local pepper = getFile("/etc/pam.d/secret")
|
||||||
|
|
||||||
|
function pam.authenticate(username, password)
|
||||||
|
local fpasswd = getFile("/etc/passwd")
|
||||||
|
local fshadow = getFile("/etc/shadow")
|
||||||
|
|
||||||
|
local passwdLines = string.split(fpasswd, "\n")
|
||||||
|
local shadowLines = string.split(fshadow, "\n")
|
||||||
|
|
||||||
|
local passwd = {}
|
||||||
|
local shadow = {}
|
||||||
|
for _, line in ipairs(passwdLines) do
|
||||||
|
local fields = string.split(line, ":")
|
||||||
|
passwd[fields[1]] = fields
|
||||||
|
end
|
||||||
|
for _, line in ipairs(shadowLines) do
|
||||||
|
local fields = string.split(line, ":")
|
||||||
|
shadow[fields[1]] = fields
|
||||||
|
end
|
||||||
|
|
||||||
|
for user, fields in pairs(passwd) do
|
||||||
|
if user == username then
|
||||||
|
local shadowPasswd = string.split(shadow[user][2], "$")
|
||||||
|
local salt = shadowPasswd[2]
|
||||||
|
local hashedPassword = blake2s(password .. salt, pepper)
|
||||||
|
if hashedPassword == shadowPasswd[3] then
|
||||||
|
loggedIn[username] = kernel.newUUID()
|
||||||
|
return loggedIn[username]
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function pam.authToken(username, token)
|
||||||
|
return loggedIn[username] == token
|
||||||
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1,213 @@
|
|||||||
local a=...local b={}local c={}local d=2;a.exitMain=false;function c.spawn(e,f,g,h,i,j)local k=d;d=d+1;b[tostring(k)]={coro=coroutine.create(function()local l,m=xpcall(e,debug.traceback,table.unpack(h or{}))if not l then b[tostring(k)].status="Z"b[tostring(k)].exit=tostring(m)else b[tostring(k)].status="Z"b[tostring(k)].exit=m end end),name=f or"task"..tostring(k),envars=g or{},args=h or{},status="R",pid=k,tgid=i or a.currentTask.tgid,user=a.user,uid=a.uid,fd=j or{},exit="",sleep=0,ivs=0,vs=0,children={},parent=a.currentTask,siblings=a.currentTask.children,syscallReturn={},cwd=a.currentTask.cwd,term=a.currentTask.term,timeSlice=0,lastTime=0,totalTime=0,numRuns=0}table.insert(a.currentTask.children,b[tostring(k)])end;function c.sleep(n)a.currentTask.status="S"a.currentTask.sleep=a.computer:time()+n;coroutine.yield()end;a.syscalls["HPV_spawn"]=c.spawn;a.syscalls["HPV_sleep"]=c.sleep;a._G.sleep=function(...)coroutine.yield("syscall","HPV_sleep",...)end;local function o()for p,q in pairs(b)do if q.status=="Z"and not q.reapTime then q.coro=nil;q.ivs=nil;q.vs=nil;q.args=nil;q.envars=nil;q.cwd=nil;q.term=nil;q.numRuns=nil;q.totalTime=nil;q.lastTime=nil;q.timeSlice=nil;q.syscallReturn=nil;q.sleep=nil;for r,s in pairs(q.fd)do a.vfs.close(s)end;q.fd=nil;q.reapTime=a.computer:time()+30000 elseif q.reapTime and a.computer:time()>q.reapTime then for t,u in ipairs(q.children)do u.parent=b["1"]u.siblings=b["1"].children;table.insert(b["1"].children,u)end;for v,w in ipairs(q.siblings)do if w.pid==q.pid then table.remove(q.siblings,v)break end end;b[p]=nil end end end;local x=0.85;local y=0.01;local z=0.0005;local A=0.5;local B=0.08;local C=0.03;local D=0.02;local E=0.5;local F=0.5;local G=0.01;function a.main()while not a.exitMain do local H=0;local I=0;local J=0;local K=0;local L={}for p,q in pairs(b)do if q.status=="S"then if a.computer:time()>=q.sleep then q.status="R"q.sleep=0 end end;if q.status=="R"then a.currentTask=q;a.vfs.cwd=q.cwd;a.user=q.user;a.uid=q.uid;H=H+1;q.timeSlice=math.min(A,math.max(z,G/H^x))local M=a.computer:time()local N;if a.config.preempt then N={coroutine.resumeWithTimeout(q.coro,q.timeSlice,table.unpack(q.syscallReturn))}else N={coroutine.resume(q.coro,table.unpack(q.syscallReturn))}end;local O=a.computer:time()-M;q.lastTime=O;q.totalTime=(q.totalTime or 0)+O;q.numRuns=(q.numRuns or 0)+1;L[#L+1]=O;K=K+O;if O<=z then I=I+1 end;if O>=A then J=J+1 end;if N[1]=="error"then a.log("processHandlerException: "..N[2])q.status="Z"q.exit="processHandlerException: "..N[2]elseif N[1]=="timeout"then q.ivs=q.ivs+1;q.syscallReturn={}elseif N[1]=="success"then q.vs=q.vs+1;if N[2]=="syscall"then if a.syscalls[N[3]]then if a.config.debugSyscalls then a.log("Task "..q.pid.." invoking syscall: "..N[3],"DBUG")end;local P={xpcall(a.syscalls[N[3]],debug.traceback,table.unpack(N,4))}if a.config.debugSyscalls then if not P[1]then a.log("Task "..q.pid.." syscall "..N[3].." failed: "..tostring(P[2]))else a.log("Task "..q.pid.." syscall "..N[3].." completed returning "..tostring(#P-1).." values","DBUG")for v=2,#P do a.log(" retval["..tostring(v-1).."] = "..tostring(P[v]),"DBUG")end end end;if not P[1]then q.syscallReturn={false,P[2]}else q.syscallReturn={true,table.unpack(P,2)}end else q.syscallReturn={false,"Unknown syscall: "..tostring(N[3])}end end end end end;local Q=H>0 and K/H or 0;local R=0;for t,S in ipairs(L)do R=R+(S-Q)^2 end;if H>0 then R=R/H end;if H>0 then local T=E*I/H-F*J/H;local U=y*H^(x-1)/math.max(Q,1e-8)G=G+B*(U-G)+C*T-D*R end;o()end end;a.tasks=b;a.hpv=c
|
--:Minify:--
|
||||||
|
local kernel = ...
|
||||||
|
local tasks = {}
|
||||||
|
local sys = {}
|
||||||
|
local nextpid = 2
|
||||||
|
kernel.exitMain=false
|
||||||
|
|
||||||
|
function sys.spawn(func, name, envars, args, tgid)
|
||||||
|
local id = nextpid
|
||||||
|
nextpid = nextpid + 1
|
||||||
|
tasks[tostring(id)] = {
|
||||||
|
coro=coroutine.create(function()
|
||||||
|
local ok, err = xpcall(func, debug.traceback, table.unpack(args or {}))
|
||||||
|
if not ok then
|
||||||
|
tasks[tostring(id)].status="Z"
|
||||||
|
tasks[tostring(id)].exit=tostring(err)
|
||||||
|
else
|
||||||
|
tasks[tostring(id)].status="Z"
|
||||||
|
tasks[tostring(id)].exit=err
|
||||||
|
end
|
||||||
|
end),
|
||||||
|
name=name or "task"..tostring(id),
|
||||||
|
envars=envars or {},
|
||||||
|
args=args or {},
|
||||||
|
status="R",
|
||||||
|
pid=id,
|
||||||
|
tgid=tgid or kernel.currentTask.tgid,
|
||||||
|
user=kernel.user,
|
||||||
|
uid=kernel.uid,
|
||||||
|
fd={},
|
||||||
|
exit="",
|
||||||
|
sleep=0,
|
||||||
|
ivs=0,
|
||||||
|
vs=0,
|
||||||
|
children={},
|
||||||
|
parent=kernel.currentTask,
|
||||||
|
siblings=kernel.currentTask.children,
|
||||||
|
syscallReturn={},
|
||||||
|
cwd=kernel.currentTask.cwd,
|
||||||
|
term=kernel.currentTask.term,
|
||||||
|
timeSlice=0,
|
||||||
|
lastTime=0,
|
||||||
|
totalTime=0,
|
||||||
|
numRuns=0
|
||||||
|
}
|
||||||
|
table.insert(kernel.currentTask.children, tasks[tostring(id)])
|
||||||
|
end
|
||||||
|
|
||||||
|
function sys.sleep(ms)
|
||||||
|
kernel.currentTask.status="S"
|
||||||
|
kernel.currentTask.sleep=kernel.computer:time()+ms
|
||||||
|
coroutine.yield()
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.syscalls["HPV_spawn"]=sys.spawn
|
||||||
|
kernel.syscalls["HPV_sleep"]=sys.sleep
|
||||||
|
kernel._G.sleep=function(...)coroutine.yield("syscall","HPV_sleep",...)end
|
||||||
|
|
||||||
|
local function reapDeadTasks()
|
||||||
|
for pid, task in pairs(tasks) do
|
||||||
|
if task.status == "Z" and not task.reapTime then
|
||||||
|
task.coro = nil
|
||||||
|
task.ivs = nil
|
||||||
|
task.vs = nil
|
||||||
|
task.args = nil
|
||||||
|
task.envars = nil
|
||||||
|
task.cwd = nil
|
||||||
|
task.term = nil
|
||||||
|
task.numRuns = nil
|
||||||
|
task.totalTime = nil
|
||||||
|
task.lastTime = nil
|
||||||
|
task.timeSlice = nil
|
||||||
|
task.syscallReturn = nil
|
||||||
|
task.sleep = nil
|
||||||
|
for k,v in pairs(task.fd) do
|
||||||
|
kernel.vfs.close(v)
|
||||||
|
end
|
||||||
|
task.fd = nil
|
||||||
|
task.reapTime = kernel.computer:time() + 30000
|
||||||
|
elseif task.reapTime and kernel.computer:time() > task.reapTime then
|
||||||
|
for _,child in ipairs(task.children) do
|
||||||
|
child.parent = tasks["1"]
|
||||||
|
child.siblings = tasks["1"].children
|
||||||
|
table.insert(tasks["1"].children, child)
|
||||||
|
end
|
||||||
|
for i, sibling in ipairs(task.siblings) do
|
||||||
|
if sibling.pid == task.pid then
|
||||||
|
table.remove(task.siblings, i)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
tasks[pid] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local alpha = 0.85
|
||||||
|
local C_target = 0.01
|
||||||
|
local Tmin = 0.0005
|
||||||
|
local Tmax = 0.5
|
||||||
|
local lambda_budget = 0.08
|
||||||
|
local lambda_clamp = 0.03
|
||||||
|
local lambda_var = 0.02
|
||||||
|
local k_min = 0.5
|
||||||
|
local k_max = 0.5
|
||||||
|
local B = 0.01
|
||||||
|
|
||||||
|
function kernel.main()
|
||||||
|
while not kernel.exitMain do
|
||||||
|
local N = 0
|
||||||
|
local Tmin_hit = 0
|
||||||
|
local Tmax_hit = 0
|
||||||
|
local totalTaskTime = 0
|
||||||
|
local taskTimes = {}
|
||||||
|
|
||||||
|
for pid, task in pairs(tasks) do
|
||||||
|
if task.status == "S" then
|
||||||
|
if kernel.computer:time() >= task.sleep then
|
||||||
|
task.status="R"
|
||||||
|
task.sleep=0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if task.status == "R" then
|
||||||
|
kernel.currentTask = task
|
||||||
|
kernel.vfs.cwd = task.cwd
|
||||||
|
kernel.user = task.user
|
||||||
|
kernel.uid = task.uid
|
||||||
|
N = N + 1
|
||||||
|
|
||||||
|
-- assign adaptive time slice
|
||||||
|
task.timeSlice = math.min(Tmax, math.max(Tmin, B / (N ^ alpha)))
|
||||||
|
|
||||||
|
-- measure execution time
|
||||||
|
local startTime = kernel.computer:time()
|
||||||
|
local ret
|
||||||
|
if kernel.config.preempt then
|
||||||
|
ret = {coroutine.resumeWithTimeout(task.coro, task.timeSlice, table.unpack(task.syscallReturn))}
|
||||||
|
else
|
||||||
|
ret = {coroutine.resume(task.coro, table.unpack(task.syscallReturn))}
|
||||||
|
end
|
||||||
|
|
||||||
|
local elapsed = kernel.computer:time() - startTime
|
||||||
|
task.lastTime = elapsed
|
||||||
|
task.totalTime = (task.totalTime or 0) + elapsed
|
||||||
|
task.numRuns = (task.numRuns or 0) + 1
|
||||||
|
|
||||||
|
taskTimes[#taskTimes + 1] = elapsed
|
||||||
|
totalTaskTime = totalTaskTime + elapsed
|
||||||
|
|
||||||
|
if elapsed <= Tmin then Tmin_hit = Tmin_hit + 1 end
|
||||||
|
if elapsed >= Tmax then Tmax_hit = Tmax_hit + 1 end
|
||||||
|
|
||||||
|
-- handle task results
|
||||||
|
if ret[1] == "error" then
|
||||||
|
kernel.log("processHandlerException: "..ret[2])
|
||||||
|
task.status = "Z"
|
||||||
|
task.exit = "processHandlerException: "..ret[2]
|
||||||
|
elseif ret[1] == "timeout" then
|
||||||
|
task.ivs=task.ivs+1
|
||||||
|
task.syscallReturn = {}
|
||||||
|
elseif ret[1] == "success" then
|
||||||
|
task.vs=task.vs+1
|
||||||
|
if ret[2]=="syscall" then
|
||||||
|
if kernel.syscalls[ret[3]] then
|
||||||
|
if kernel.config.debugSyscalls then
|
||||||
|
kernel.log("Task "..task.pid.." invoking syscall: "..ret[3], "DBUG")
|
||||||
|
end
|
||||||
|
local sysret = {xpcall(kernel.syscalls[ret[3]], debug.traceback, table.unpack(ret, 4))}
|
||||||
|
if kernel.config.debugSyscalls then
|
||||||
|
if not sysret[1] then
|
||||||
|
kernel.log("Task "..task.pid.." syscall "..ret[3].." failed: "..tostring(sysret[2]))
|
||||||
|
else
|
||||||
|
kernel.log("Task "..task.pid.." syscall "..ret[3].." completed returning "..tostring(#sysret-1).." values", "DBUG")
|
||||||
|
for i=2,#sysret do
|
||||||
|
kernel.log(" retval["..tostring(i-1).."] = "..tostring(sysret[i]), "DBUG")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not sysret[1] then
|
||||||
|
task.syscallReturn={false, sysret[2]}
|
||||||
|
else
|
||||||
|
task.syscallReturn={true, table.unpack(sysret,2)}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
task.syscallReturn={false, "Unknown syscall: "..tostring(ret[3])}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local T_prev_avg = (N > 0) and (totalTaskTime / N) or 0
|
||||||
|
local T_prev_var = 0
|
||||||
|
for _, t in ipairs(taskTimes) do
|
||||||
|
T_prev_var = T_prev_var + (t - T_prev_avg)^2
|
||||||
|
end
|
||||||
|
if N > 0 then T_prev_var = T_prev_var / N end
|
||||||
|
|
||||||
|
if N > 0 then
|
||||||
|
local f_clamp = k_min*(Tmin_hit/N) - k_max*(Tmax_hit/N)
|
||||||
|
local B_budget = (C_target * (N^(alpha-1))) / math.max(T_prev_avg, 1e-8)
|
||||||
|
B = B + lambda_budget * (B_budget - B)
|
||||||
|
+ lambda_clamp * f_clamp
|
||||||
|
- lambda_var * T_prev_var
|
||||||
|
end
|
||||||
|
|
||||||
|
-- clean up dead tasks
|
||||||
|
reapDeadTasks()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.tasks=tasks
|
||||||
|
kernel.hpv=sys
|
||||||
@@ -1 +1,7 @@
|
|||||||
local a=...local debug=debug;a._G.debug={getinfo=debug.getinfo,traceback=debug.traceback}
|
--:Minify:--
|
||||||
|
local kernel=...
|
||||||
|
local debug=debug
|
||||||
|
kernel._G.debug={
|
||||||
|
getinfo=debug.getinfo,
|
||||||
|
traceback=debug.traceback
|
||||||
|
}
|
||||||
@@ -1 +1,126 @@
|
|||||||
local a=...a.tty={}function a.tty.register(b,c)a.tty[b]=c end;function a.tty.print(d)local e=a.currentTask.term;if e and a.tty[e]then a.tty[e].print(d)end end;function a.tty.printInline(d)local e=a.currentTask.term;if e and a.tty[e]then a.tty[e].printInline(d)end end;function a.tty.size()local e=a.currentTask.term;if e and a.tty[e]then return a.tty[e].size()end end;function a.tty.setCursorPos(f,g)local e=a.currentTask.term;if e and a.tty[e]then return a.tty[e].setCursorPos(f,g)end end;function a.tty.getCursorPos()local e=a.currentTask.term;if e and a.tty[e]then return a.tty[e].getCursorPos()end end;function a.tty.clear()local e=a.currentTask.term;if e and a.tty[e]then return a.tty[e].clear()end end;function a.tty.setTextColor(h)local e=a.currentTask.term;if e and a.tty[e]then return a.tty[e].setTextColor(h)end end;function a.tty.setBackgroundColor(h)local e=a.currentTask.term;if e and a.tty[e]then return a.tty[e].setBackgroundColor(h)end end;function a.tty.scroll(i)local e=a.currentTask.term;if e and a.tty[e]then return a.tty[e].scroll(i)end end;function a.tty.getTextColor()local e=a.currentTask.term;if e and a.tty[e]and a.tty[e].getTextColor then return a.tty[e].getTextColor()end end;function a.tty.getBackgroundColor()local e=a.currentTask.term;if e and a.tty[e]and a.tty[e].getBackgroundColor then return a.tty[e].getBackgroundColor()end end;function a.tty.bind(j)if not j then return false,"No TTY ID specified"end;if not a.tty[j]then return false,"TTY "..tostring(j).." not registered"end;a.currentTask.term=j;return true end;function a.tty.unbind()a.currentTask.term=false end;function a.tty.isBound()return a.currentTask.term~=nil end;function a.tty.getBoundTTY()return a.currentTask.term end;a.syscalls["TTY_print"]=a.tty.print;a.syscalls["TTY_printInline"]=a.tty.printInline;a.syscalls["TTY_size"]=a.tty.size;a.syscalls["TTY_setCursorPos"]=a.tty.setCursorPos;a.syscalls["TTY_getCursorPos"]=a.tty.getCursorPos;a.syscalls["TTY_clear"]=a.tty.clear;a.syscalls["TTY_setTextColor"]=a.tty.setTextColor;a.syscalls["TTY_setBackgroundColor"]=a.tty.setBackgroundColor;a.syscalls["TTY_scroll"]=a.tty.scroll;a.syscalls["TTY_getTextColor"]=a.tty.getTextColor;a.syscalls["TTY_getBackgroundColor"]=a.tty.getBackgroundColor;a.syscalls["TTY_bind"]=a.tty.bind;a.syscalls["TTY_unbind"]=a.tty.unbind;a.syscalls["TTY_isBound"]=a.tty.isBound;a.syscalls["TTY_getBoundTTY"]=a.tty.getBoundTTY;a.log("TTY module loaded attempting to register console tty")a.status="init"
|
--:Minify:--
|
||||||
|
local kernel=...
|
||||||
|
kernel.tty={}
|
||||||
|
|
||||||
|
function kernel.tty.register(tty, ttyo)
|
||||||
|
kernel.tty[tty]=ttyo
|
||||||
|
end
|
||||||
|
|
||||||
|
function kernel.tty.print(text)
|
||||||
|
local term=kernel.currentTask.term
|
||||||
|
if term and kernel.tty[term] then
|
||||||
|
kernel.tty[term].print(text)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function kernel.tty.printInline(text)
|
||||||
|
local term=kernel.currentTask.term
|
||||||
|
if term and kernel.tty[term] then
|
||||||
|
kernel.tty[term].printInline(text)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function kernel.tty.size()
|
||||||
|
local term=kernel.currentTask.term
|
||||||
|
if term and kernel.tty[term] then
|
||||||
|
return kernel.tty[term].size()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function kernel.tty.setCursorPos(x,y)
|
||||||
|
local term=kernel.currentTask.term
|
||||||
|
if term and kernel.tty[term] then
|
||||||
|
return kernel.tty[term].setCursorPos(x,y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function kernel.tty.getCursorPos()
|
||||||
|
local term=kernel.currentTask.term
|
||||||
|
if term and kernel.tty[term] then
|
||||||
|
return kernel.tty[term].getCursorPos()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function kernel.tty.clear()
|
||||||
|
local term=kernel.currentTask.term
|
||||||
|
if term and kernel.tty[term] then
|
||||||
|
return kernel.tty[term].clear()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function kernel.tty.setTextColor(color)
|
||||||
|
local term=kernel.currentTask.term
|
||||||
|
if term and kernel.tty[term] then
|
||||||
|
return kernel.tty[term].setTextColor(color)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function kernel.tty.setBackgroundColor(color)
|
||||||
|
local term=kernel.currentTask.term
|
||||||
|
if term and kernel.tty[term] then
|
||||||
|
return kernel.tty[term].setBackgroundColor(color)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function kernel.tty.scroll(n)
|
||||||
|
local term=kernel.currentTask.term
|
||||||
|
if term and kernel.tty[term] then
|
||||||
|
return kernel.tty[term].scroll(n)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function kernel.tty.getTextColor()
|
||||||
|
local term=kernel.currentTask.term
|
||||||
|
if term and kernel.tty[term] and kernel.tty[term].getTextColor then
|
||||||
|
return kernel.tty[term].getTextColor()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function kernel.tty.getBackgroundColor()
|
||||||
|
local term=kernel.currentTask.term
|
||||||
|
if term and kernel.tty[term] and kernel.tty[term].getBackgroundColor then
|
||||||
|
return kernel.tty[term].getBackgroundColor()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function kernel.tty.bind(ttyid)
|
||||||
|
if not ttyid then
|
||||||
|
return false, "No TTY ID specified"
|
||||||
|
end
|
||||||
|
if not kernel.tty[ttyid] then
|
||||||
|
return false, "TTY "..tostring(ttyid).." not registered"
|
||||||
|
end
|
||||||
|
kernel.currentTask.term=ttyid
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function kernel.tty.unbind()
|
||||||
|
kernel.currentTask.term=false
|
||||||
|
end
|
||||||
|
|
||||||
|
function kernel.tty.isBound()
|
||||||
|
return kernel.currentTask.term ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function kernel.tty.getBoundTTY()
|
||||||
|
return kernel.currentTask.term
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.syscalls["TTY_print"]=kernel.tty.print
|
||||||
|
kernel.syscalls["TTY_printInline"]=kernel.tty.printInline
|
||||||
|
kernel.syscalls["TTY_size"]=kernel.tty.size
|
||||||
|
kernel.syscalls["TTY_setCursorPos"]=kernel.tty.setCursorPos
|
||||||
|
kernel.syscalls["TTY_getCursorPos"]=kernel.tty.getCursorPos
|
||||||
|
kernel.syscalls["TTY_clear"]=kernel.tty.clear
|
||||||
|
kernel.syscalls["TTY_setTextColor"]=kernel.tty.setTextColor
|
||||||
|
kernel.syscalls["TTY_setBackgroundColor"]=kernel.tty.setBackgroundColor
|
||||||
|
kernel.syscalls["TTY_scroll"]=kernel.tty.scroll
|
||||||
|
kernel.syscalls["TTY_getTextColor"]=kernel.tty.getTextColor
|
||||||
|
kernel.syscalls["TTY_getBackgroundColor"]=kernel.tty.getBackgroundColor
|
||||||
|
kernel.syscalls["TTY_bind"]=kernel.tty.bind
|
||||||
|
kernel.syscalls["TTY_unbind"]=kernel.tty.unbind
|
||||||
|
kernel.syscalls["TTY_isBound"]=kernel.tty.isBound
|
||||||
|
kernel.syscalls["TTY_getBoundTTY"]=kernel.tty.getBoundTTY
|
||||||
|
|
||||||
|
kernel.log("TTY module loaded attempting to register console tty")
|
||||||
|
kernel.status="init"
|
||||||
@@ -1 +1,3 @@
|
|||||||
local a=...a.tty.bind("tty0")
|
--:Minify:--
|
||||||
|
local kernel=...
|
||||||
|
kernel.tty.bind("tty0")
|
||||||
@@ -1 +1,28 @@
|
|||||||
local a=...function print(...)coroutine.yield()local b={...}local c=""for d=1,#b do c=c..tostring(b[d]).."\t"end;c=c:sub(1,-2)a.tty.print(c)end;function printf(e,...)coroutine.yield()local c=string.format(e,...)a.tty.print(c)end;function printInline(...)coroutine.yield()local b={...}local c=""for d=1,#b do c=c..tostring(b[d]).."\t"end;c=c:sub(1,-2)a.tty.printInline(c)end
|
--:Minify:--
|
||||||
|
local kernel=...
|
||||||
|
function print(...)
|
||||||
|
local args={...}
|
||||||
|
local output=""
|
||||||
|
for i=1,#args do
|
||||||
|
output=output..tostring(args[i]).."\t"
|
||||||
|
end
|
||||||
|
output=output:sub(1,-2)
|
||||||
|
syscall.TTY_print(output)
|
||||||
|
end
|
||||||
|
|
||||||
|
function printf(fmt, ...)
|
||||||
|
coroutine.yield()
|
||||||
|
local output=string.format(fmt,...)
|
||||||
|
syscall.TTY_print(output)
|
||||||
|
end
|
||||||
|
|
||||||
|
function printInline(...)
|
||||||
|
coroutine.yield()
|
||||||
|
local args={...}
|
||||||
|
local output=""
|
||||||
|
for i=1,#args do
|
||||||
|
output=output..tostring(args[i]).."\t"
|
||||||
|
end
|
||||||
|
output=output:sub(1,-2)
|
||||||
|
syscall.TTY_printInline(output)
|
||||||
|
end
|
||||||
@@ -1 +1,45 @@
|
|||||||
local a=...a.log("Loading init system...")a.log("InitPath: "..a.config.initPath)local b=a.vfs.open(a.config.initPath,"r")local c=a.vfs.read(b,1024*1024*4)a.vfs.close(b)local d,e=load(c,"@sysinit")if not d then error("Failed to load init system: "..e)end;a.tasks["1"]={coro=coroutine.create(function()local f,e=xpcall(d,debug.traceback,a)if not f then a.panic("Init system crashed: "..tostring(e))else a.panic("Init system exited: "..tostring(e))end end),name="sysinit",status="R",pid=1,tgid=1,user="root",uid=0,fd={},exit="",sleep=0,ivs=0,vs=0,parent=a.kernelTask,siblings=a.kernelTask.children,children={},syscallReturn={},cwd="/",timeSlice=0,lastTime=0,totalTime=0,numRuns=0}a.log("created init task with PID 1")a.log("Initializing init system...")
|
--:Minify:--
|
||||||
|
local kernel = ...
|
||||||
|
kernel.log("Loading init system...")
|
||||||
|
kernel.log("InitPath: "..kernel.config.initPath)
|
||||||
|
local handle = kernel.vfs.open(kernel.config.initPath, "r")
|
||||||
|
local data = kernel.vfs.read(handle, 1024 * 1024 * 4)
|
||||||
|
kernel.vfs.close(handle)
|
||||||
|
|
||||||
|
local initFunc, err = load(data, "@sysinit")
|
||||||
|
if not initFunc then
|
||||||
|
error("Failed to load init system: "..err)
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.tasks["1"] = {
|
||||||
|
coro=coroutine.create(function()
|
||||||
|
local ok, err = xpcall(initFunc, debug.traceback, kernel)
|
||||||
|
if not ok then
|
||||||
|
kernel.panic("Init system crashed: "..tostring(err))
|
||||||
|
else
|
||||||
|
kernel.panic("Init system exited: "..tostring(err))
|
||||||
|
end
|
||||||
|
end),
|
||||||
|
name="sysinit",
|
||||||
|
status="R",
|
||||||
|
pid=1,
|
||||||
|
tgid=1,
|
||||||
|
user="root",
|
||||||
|
uid=0,
|
||||||
|
fd={},
|
||||||
|
exit="",
|
||||||
|
sleep=0,
|
||||||
|
ivs=0,
|
||||||
|
vs=0,
|
||||||
|
parent=kernel.kernelTask,
|
||||||
|
siblings=kernel.kernelTask.children,
|
||||||
|
children={},
|
||||||
|
syscallReturn={},
|
||||||
|
cwd="/",
|
||||||
|
timeSlice=0,
|
||||||
|
lastTime=0,
|
||||||
|
totalTime=0,
|
||||||
|
numRuns=0
|
||||||
|
}
|
||||||
|
kernel.log("created init task with PID 1")
|
||||||
|
kernel.log("Initializing init system...")
|
||||||
File diff suppressed because one or more lines are too long
@@ -2,6 +2,18 @@ local kernel=...
|
|||||||
local fs=require("sys.fs")
|
local fs=require("sys.fs")
|
||||||
syscall.TTY_bind("tty0")
|
syscall.TTY_bind("tty0")
|
||||||
|
|
||||||
|
for i,v in pairs(kernel.processes) do
|
||||||
|
kernel.log("Spawning kernel task "..i)
|
||||||
|
syscall.HPV_spawn(function()
|
||||||
|
local status, err = pcall(v)
|
||||||
|
if not status then
|
||||||
|
kernel.log("Error executing kernel task '" .. i .. "': " .. err, "ERROR")
|
||||||
|
else
|
||||||
|
kernel.log("Successfully executed kernel task: " .. i, "INFO")
|
||||||
|
end
|
||||||
|
end, i)
|
||||||
|
end
|
||||||
|
|
||||||
local files = fs.list("/bin/startup")
|
local files = fs.list("/bin/startup")
|
||||||
if not files then error("Failed to list /bin/startup") end
|
if not files then error("Failed to list /bin/startup") end
|
||||||
for i,v in ipairs(files) do
|
for i,v in ipairs(files) do
|
||||||
@@ -12,7 +24,7 @@ for i,v in ipairs(files) do
|
|||||||
if not startupFunc then
|
if not startupFunc then
|
||||||
kernel.log("Error loading startup script '" .. filepath .. "': " .. err, "ERROR")
|
kernel.log("Error loading startup script '" .. filepath .. "': " .. err, "ERROR")
|
||||||
else
|
else
|
||||||
kernel.hpv.spawn(function()
|
syscall.HPV_spawn(function()
|
||||||
local status, err = pcall(startupFunc)
|
local status, err = pcall(startupFunc)
|
||||||
if not status then
|
if not status then
|
||||||
kernel.log("Error executing startup script '" .. filepath .. "': " .. err, "ERROR")
|
kernel.log("Error executing startup script '" .. filepath .. "': " .. err, "ERROR")
|
||||||
@@ -24,59 +36,7 @@ for i,v in ipairs(files) do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function serialize(table, seen)
|
|
||||||
seen = seen or {}
|
|
||||||
if seen[tostring(table)] then
|
|
||||||
return "\"<circular reference>\""
|
|
||||||
end
|
|
||||||
seen[tostring(table)] = true
|
|
||||||
local output = "{"
|
|
||||||
for i,v in pairs(table) do
|
|
||||||
local coma=true
|
|
||||||
if type(i) == "string" then
|
|
||||||
output=output.."[\""..i.."\"]="
|
|
||||||
elseif type(i) == "number" then
|
|
||||||
output=output.."["..tostring(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, seen)
|
|
||||||
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..tostring(v)
|
|
||||||
elseif type(v) == "userdata" then
|
|
||||||
output=output..tostring(v)
|
|
||||||
elseif type(v) == "thread" then
|
|
||||||
output=output..tostring(v)
|
|
||||||
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
|
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
--kernel.log(serialize(kernel.tasks))
|
|
||||||
kernel.saveLog()
|
kernel.saveLog()
|
||||||
sleep(1000)
|
sleep(1000)
|
||||||
end
|
end
|
||||||
@@ -5,11 +5,11 @@ syscall.TTY_bind("tty0")
|
|||||||
for i,v in pairs(kernel.processes) do
|
for i,v in pairs(kernel.processes) do
|
||||||
kernel.log("Spawning kernel task "..i)
|
kernel.log("Spawning kernel task "..i)
|
||||||
syscall.HPV_spawn(function()
|
syscall.HPV_spawn(function()
|
||||||
local status, err = pcall(startupFunc)
|
local status, err = pcall(v)
|
||||||
if not status then
|
if not status then
|
||||||
kernel.log("Error executing kernel task '" .. filepath .. "': " .. err, "ERROR")
|
kernel.log("Error executing kernel task '" .. i .. "': " .. err, "ERROR")
|
||||||
else
|
else
|
||||||
kernel.log("Successfully executed kernel task: " .. filepath, "INFO")
|
kernel.log("Successfully executed kernel task: " .. i, "INFO")
|
||||||
end
|
end
|
||||||
end, i)
|
end, i)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ ifs.makeDir("/tmp")
|
|||||||
function kernel.newFifo()
|
function kernel.newFifo()
|
||||||
local fifo = {}
|
local fifo = {}
|
||||||
fifo.push=function(data)
|
fifo.push=function(data)
|
||||||
table.insert(data)
|
table.insert(fifo, data)
|
||||||
end
|
end
|
||||||
fifo.pop=function()
|
fifo.pop=function()
|
||||||
return table.remove(fifo,1)
|
return table.remove(fifo,1)
|
||||||
@@ -238,6 +238,6 @@ for _,p in ipairs(modules) do
|
|||||||
end
|
end
|
||||||
|
|
||||||
kernel.log("Kernel initialized successfully.")
|
kernel.log("Kernel initialized successfully.")
|
||||||
--kernel.status="running"
|
kernel.status="running"
|
||||||
kernel.main()
|
kernel.main()
|
||||||
kernel.PANIC("Execution complete")
|
kernel.PANIC("Execution complete")
|
||||||
Reference in New Issue
Block a user