mirror of
https://git.shadowkat.net/izaya/OC-PsychOS2.git
synced 2024-11-22 03:54:20 -05:00
Compare commits
21 Commits
b2d1379127
...
180a5a9a78
Author | SHA1 | Date | |
---|---|---|---|
|
180a5a9a78 | ||
|
37df78ffed | ||
|
80eea7142d | ||
|
256e05233a | ||
|
a219b5603e | ||
|
a97e3c93ee | ||
|
ec699518b5 | ||
|
faca451c57 | ||
|
aed9278433 | ||
|
6ad6880a6d | ||
|
1bd18f45b3 | ||
|
d23a25613d | ||
|
ac98d09b93 | ||
|
a335ff5c87 | ||
|
e9aac95dd7 | ||
|
150541d91b | ||
|
6b5677b870 | ||
|
5f8e4efe33 | ||
|
98e3581e6e | ||
|
23680afd75 | ||
|
69eae00ec1 |
4
build.sh
4
build.sh
@ -1,9 +1,11 @@
|
||||
#!/bin/sh
|
||||
rm -r target/*
|
||||
mkdir target
|
||||
mkdir target &>/dev/null
|
||||
mkdir target/cfg
|
||||
lua luapreproc.lua module/init.lua target/init.lua
|
||||
echo _OSVERSION=\"PsychOS 2.0a1-$(git rev-parse --short HEAD)\" > target/version.lua
|
||||
cat target/version.lua target/init.lua > target/tinit.lua
|
||||
mv target/tinit.lua target/init.lua
|
||||
cp -r exec/ service/ lib/ target/
|
||||
cp default-init.txt target/cfg/
|
||||
lua finddesc.lua $(find module/ -type f) $(find lib/ -type f) > apidoc.md
|
||||
|
@ -1,3 +1,2 @@
|
||||
minitel.lua
|
||||
tape-iofs.lua
|
||||
fsmanager.service
|
||||
getty.lua
|
||||
fsmanager.lua
|
||||
|
23
exec/df.lua
Normal file
23
exec/df.lua
Normal file
@ -0,0 +1,23 @@
|
||||
local mt = fs.mounts()
|
||||
local ml = 0
|
||||
for k,v in pairs(mt) do
|
||||
if v:len() > ml then
|
||||
ml = v:len()
|
||||
end
|
||||
end
|
||||
local scale = {"K","M","G","T","P"}
|
||||
local function wrapUnits(n)
|
||||
local count = 0
|
||||
while n > 1024 do
|
||||
count = count + 1
|
||||
if not scale[count] then return "inf" end
|
||||
n = n / 1024
|
||||
end
|
||||
return tostring(math.floor(n))..(scale[count] or "")
|
||||
end
|
||||
local fstr = "%-"..tostring(ml).."s %5s %5s"
|
||||
print("fs"..(" "):rep(ml-2).." size used")
|
||||
for k,v in pairs(mt) do
|
||||
local st, su = fs.spaceTotal(v), fs.spaceUsed(v)
|
||||
print(string.format(fstr,v,wrapUnits(st),wrapUnits(su)))
|
||||
end
|
@ -63,6 +63,7 @@ end
|
||||
function ct.append(np)
|
||||
ct.sp(np)
|
||||
p=p+1
|
||||
if #ft < 1 then p = 1 end
|
||||
ct.insert()
|
||||
end
|
||||
function ct.delete(np,n)
|
||||
|
@ -1,16 +1,25 @@
|
||||
xpcall(function()
|
||||
os.setenv("PWD","/boot")
|
||||
os.spawnfile("/boot/service/getty.lua")
|
||||
coroutine.yield()
|
||||
for k,v in pairs(fs.list("/dev/")) do
|
||||
if v:sub(1,3) == "tty" then
|
||||
dprint(tostring(io.input("/dev/"..v)))
|
||||
dprint(tostring(io.output("/dev/"..v)))
|
||||
print(_OSVERSION.." - "..tostring(math.floor(computer.totalMemory()/1024)).."K RAM")
|
||||
os.spawnfile("/boot/exec/shell.lua")
|
||||
end
|
||||
if os.taskInfo(1) and os.pid() ~= 1 then
|
||||
return false, "init already started"
|
||||
end
|
||||
os.setenv("PWD","/boot")
|
||||
io.input("/dev/null")
|
||||
io.output("/dev/syslog")
|
||||
local pids = {}
|
||||
local function loadlist()
|
||||
local f = io.open("/boot/cfg/init.txt","rb")
|
||||
if not f then return false end
|
||||
for line in f:read("*a"):gmatch("[^\r\n]+") do
|
||||
pids[line] = -1
|
||||
end
|
||||
f:close()
|
||||
end
|
||||
loadlist()
|
||||
while true do
|
||||
for k,v in pairs(pids) do
|
||||
if not os.taskInfo(v) then
|
||||
syslog("Starting service "..k)
|
||||
pids[k] = os.spawnfile("/boot/service/"..k)
|
||||
end
|
||||
end
|
||||
coroutine.yield()
|
||||
end
|
||||
end,function(e) dprint(e) end,"init")
|
||||
|
24
exec/mount.lua
Normal file
24
exec/mount.lua
Normal file
@ -0,0 +1,24 @@
|
||||
local tA = {...}
|
||||
if #tA < 1 then
|
||||
local mt = fs.mounts()
|
||||
for k,v in pairs(mt) do
|
||||
print(tostring(fs.address(v)).." on "..tostring(v).." type "..fs.type(v))
|
||||
end
|
||||
else
|
||||
local addr,path = tA[1],tA[2]
|
||||
local fscomp = component.list("filesystem")
|
||||
if not fscomp[addr] then
|
||||
for k,v in pairs(fscomp) do
|
||||
if k:find(addr) then
|
||||
print(tostring(addr).." not found, assuming you meant "..k)
|
||||
addr = k
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
local proxy = component.proxy(addr)
|
||||
if not proxy then
|
||||
return false, "no such filesystem component"
|
||||
end
|
||||
print(fs.mount(path,proxy))
|
||||
end
|
@ -1,5 +1,5 @@
|
||||
print("PID# Parent | Name")
|
||||
for k,v in pairs(os.tasks()) do
|
||||
local t = os.taskInfo(v)
|
||||
print(string.format("%4d %4d | %s",k,t.parent,t.name))
|
||||
print(string.format("%4d %4d | %s",v,t.parent,t.name))
|
||||
end
|
||||
|
@ -4,6 +4,7 @@ function shenv.quit()
|
||||
os.setenv("run",nil)
|
||||
end
|
||||
shenv.cd = os.chdir
|
||||
shenv.mkdir = fs.makeDirectory
|
||||
setmetatable(shenv,{__index=function(_,k)
|
||||
if _G[k] then
|
||||
return _G[k]
|
||||
|
@ -23,16 +23,13 @@ function event.pull(t,...) -- return an event, optionally with timeout *t* and f
|
||||
end
|
||||
|
||||
function event.listen(e,f) -- run function *f* for every occurance of event *e*
|
||||
local op = os.getenv("parent")
|
||||
os.setenv("parent",cPid)
|
||||
os.spawn(function() while true do
|
||||
local tEv = {coroutine.yield()}
|
||||
if tEv[1] == e then
|
||||
f(table.unpack(tEv))
|
||||
end
|
||||
if not tTasks[os.getenv("parent")] or (tEv[1] == "unlisten" and tEv[2] == e and tEv[3] == tostring(f)) then break end
|
||||
end end,string.format("[%d] %s listener",cPid,e))
|
||||
os.setenv("parent",op)
|
||||
if not os.taskInfo(os.taskInfo().parent) or (tEv[1] == "unlisten" and tEv[2] == e and tEv[3] == tostring(f)) then break end
|
||||
end end,string.format("[%d] %s listener",os.pid(),e))
|
||||
end
|
||||
|
||||
function event.ignore(e,f) -- stop function *f* running for every occurance of event *e*
|
||||
|
@ -1,145 +1,49 @@
|
||||
-- serialization lib borrowed from OpenOS
|
||||
local serialization = {}
|
||||
|
||||
-- delay loaded tables fail to deserialize cross [C] boundaries (such as when having to read files that cause yields)
|
||||
local local_pairs = function(tbl)
|
||||
local mt = getmetatable(tbl)
|
||||
return (mt and mt.__pairs or pairs)(tbl)
|
||||
local serial = {}
|
||||
local local_pairs=function(tbl)
|
||||
local mt=getmetatable(tbl)
|
||||
return (mt and mt.__pairs or pairs)(tbl)
|
||||
end
|
||||
|
||||
-- Important: pretty formatting will allow presenting non-serializable values
|
||||
-- but may generate output that cannot be unserialized back.
|
||||
function serialization.serialize(value, pretty) -- serialize *value* into a string, optionally in a nicely formatted manner when *pretty* is set
|
||||
local kw = {["and"]=true, ["break"]=true, ["do"]=true, ["else"]=true,
|
||||
["elseif"]=true, ["end"]=true, ["false"]=true, ["for"]=true,
|
||||
["function"]=true, ["goto"]=true, ["if"]=true, ["in"]=true,
|
||||
["local"]=true, ["nil"]=true, ["not"]=true, ["or"]=true,
|
||||
["repeat"]=true, ["return"]=true, ["then"]=true, ["true"]=true,
|
||||
["until"]=true, ["while"]=true}
|
||||
local id = "^[%a_][%w_]*$"
|
||||
local ts = {}
|
||||
local result_pack = {}
|
||||
local function recurse(current_value, depth)
|
||||
local t = type(current_value)
|
||||
if t == "number" then
|
||||
if current_value ~= current_value then
|
||||
table.insert(result_pack, "0/0")
|
||||
elseif current_value == math.huge then
|
||||
table.insert(result_pack, "math.huge")
|
||||
elseif current_value == -math.huge then
|
||||
table.insert(result_pack, "-math.huge")
|
||||
else
|
||||
table.insert(result_pack, tostring(current_value))
|
||||
end
|
||||
elseif t == "string" then
|
||||
table.insert(result_pack, (string.format("%q", current_value):gsub("\\\n","\\n")))
|
||||
elseif
|
||||
t == "nil" or
|
||||
t == "boolean" or
|
||||
pretty and (t ~= "table" or (getmetatable(current_value) or {}).__tostring) then
|
||||
table.insert(result_pack, tostring(current_value))
|
||||
elseif t == "table" then
|
||||
if ts[current_value] then
|
||||
if pretty then
|
||||
table.insert(result_pack, "recursion")
|
||||
return
|
||||
else
|
||||
error("tables with cycles are not supported")
|
||||
end
|
||||
end
|
||||
ts[current_value] = true
|
||||
local f
|
||||
if pretty then
|
||||
local ks, sks, oks = {}, {}, {}
|
||||
for k in local_pairs(current_value) do
|
||||
if type(k) == "number" then
|
||||
table.insert(ks, k)
|
||||
elseif type(k) == "string" then
|
||||
table.insert(sks, k)
|
||||
else
|
||||
table.insert(oks, k)
|
||||
end
|
||||
end
|
||||
table.sort(ks)
|
||||
table.sort(sks)
|
||||
for _, k in ipairs(sks) do
|
||||
table.insert(ks, k)
|
||||
end
|
||||
for _, k in ipairs(oks) do
|
||||
table.insert(ks, k)
|
||||
end
|
||||
local n = 0
|
||||
f = table.pack(function()
|
||||
n = n + 1
|
||||
local k = ks[n]
|
||||
if k ~= nil then
|
||||
return k, current_value[k]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end)
|
||||
else
|
||||
f = table.pack(local_pairs(current_value))
|
||||
end
|
||||
local i = 1
|
||||
local first = true
|
||||
table.insert(result_pack, "{")
|
||||
for k, v in table.unpack(f) do
|
||||
if not first then
|
||||
table.insert(result_pack, ",")
|
||||
if pretty then
|
||||
table.insert(result_pack, "\n" .. string.rep(" ", depth))
|
||||
end
|
||||
end
|
||||
first = nil
|
||||
local tk = type(k)
|
||||
if tk == "number" and k == i then
|
||||
i = i + 1
|
||||
recurse(v, depth + 1)
|
||||
else
|
||||
if tk == "string" and not kw[k] and string.match(k, id) then
|
||||
table.insert(result_pack, k)
|
||||
else
|
||||
table.insert(result_pack, "[")
|
||||
recurse(k, depth + 1)
|
||||
table.insert(result_pack, "]")
|
||||
end
|
||||
table.insert(result_pack, "=")
|
||||
recurse(v, depth + 1)
|
||||
end
|
||||
end
|
||||
ts[current_value] = nil -- allow writing same table more than once
|
||||
table.insert(result_pack, "}")
|
||||
function serial.serialize(value)
|
||||
local kw={["and"]=true,["break"]=true,["do"]=true,["else"]=true,["elseif"]=true,["end"]=true,["false"]=true,["for"]=true,["function"]=true,["goto"]=true,["if"]=true,["in"]=true,["local"]=true,["nil"]=true,["not"]=true,["or"]=true,["repeat"]=true,["return"]=true,["then"]=true,["true"]=true,["until"]=true,["while"]=true}
|
||||
local id="^[%a_][%w_]*$"
|
||||
local ts={}
|
||||
local function s(v,l)
|
||||
local t=type(v)
|
||||
if t=="nil" then return "nil"
|
||||
elseif t=="boolean" then return v and "true" or "false"
|
||||
elseif t=="number" then
|
||||
if v~=v then return "0/0"
|
||||
elseif v==math.huge then return "math.huge"
|
||||
elseif v==-math.huge then return "-math.huge"
|
||||
else return tostring(v) end
|
||||
elseif t=="string" then return string.format("%q",v):gsub("\\\n","\\n")
|
||||
elseif t=="table" then
|
||||
if ts[v] then error("tcyc") end
|
||||
ts[v]=true
|
||||
local i,r=1, nil
|
||||
local f=table.pack(local_pairs(v))
|
||||
for k,v in table.unpack(f) do
|
||||
if r then r=r..","..(("\n"..string.rep(" ",l)) or "")
|
||||
else r="{" end
|
||||
local tk=type(k)
|
||||
if tk=="number" and k==i then
|
||||
i=i+1
|
||||
r=r..s(v,l+1)
|
||||
else
|
||||
error("unsupported type: " .. t)
|
||||
end
|
||||
end
|
||||
recurse(value, 1)
|
||||
local result = table.concat(result_pack)
|
||||
if pretty then
|
||||
local limit = type(pretty) == "number" and pretty or 10
|
||||
local truncate = 0
|
||||
while limit > 0 and truncate do
|
||||
truncate = string.find(result, "\n", truncate + 1, true)
|
||||
limit = limit - 1
|
||||
end
|
||||
if truncate then
|
||||
return result:sub(1, truncate) .. "..."
|
||||
end
|
||||
end
|
||||
return result
|
||||
if tk == "string" and not kw[k] and string.match(k,id) then r=r..k
|
||||
else r=r.."["..s(k,l+1).."]" end
|
||||
r=r.."="..s(v,l+1) end end
|
||||
ts[v]=nil
|
||||
return (r or "{").."}"
|
||||
else error("ut "..t) end end
|
||||
return s(value, 1)
|
||||
end
|
||||
|
||||
function serialization.unserialize(data) -- returns the data contained in serialized string *data*
|
||||
local result, reason = load("return " .. data, "=data", nil, {math={huge=math.huge}})
|
||||
if not result then
|
||||
return nil, reason
|
||||
end
|
||||
local ok, output = pcall(result)
|
||||
if not ok then
|
||||
return nil, output
|
||||
end
|
||||
return output
|
||||
function serial.unserialize(data)
|
||||
checkArg(1, data, "string")
|
||||
local result, reason = load("return " .. data, "=data", _, {math={huge=math.huge}})
|
||||
if not result then return nil, reason end
|
||||
local ok, output = pcall(result)
|
||||
if not ok then return nil, output end
|
||||
return output
|
||||
end
|
||||
|
||||
return serialization
|
||||
return serial
|
||||
|
@ -7,10 +7,13 @@ devfs.component = {}
|
||||
local function rfalse()
|
||||
return false
|
||||
end
|
||||
local function rzero()
|
||||
return 0
|
||||
end
|
||||
function devfs.component.getLabel()
|
||||
return "devfs"
|
||||
end
|
||||
devfs.component.spaceUsed, devfs.component.spaceTotal, devfs.component.isReadOnly, devfs.component.isDirectory,devfs.component.size, devfs.component.setLabel = function() return computer.totalMemory()-computer.freeMemory() end, computer.totalMemory, rfalse, rfalse, rfalse, rfalse
|
||||
devfs.component.spaceUsed, devfs.component.spaceTotal, devfs.component.isReadOnly, devfs.component.isDirectory,devfs.component.size, devfs.component.setLabel = rzero, rzero, rfalse, rfalse, rzero, rfalse
|
||||
|
||||
function devfs.component.exists(fname)
|
||||
return devfs.files[fname] ~= nil
|
||||
|
@ -15,11 +15,8 @@ function fs.resolve(path) -- resolves *path* to a specific filesystem mount and
|
||||
if path:sub(1,1) ~= "/" then path=(os.getenv("PWD") or "").."/"..path end
|
||||
local segments, rpath, rfs= fs.segments(path)
|
||||
local rc = #segments
|
||||
dprint(rc)
|
||||
for i = #segments, 1, -1 do
|
||||
dprint("testing "..table.concat(segments, "/", 1, i),tostring(fsmounts[table.concat(segments, "/", 1, i)]))
|
||||
if fsmounts[table.concat(segments, "/", 1, i)] ~= nil then
|
||||
dprint("ret",table.concat(segments, "/", 1, i), table.concat(segments, "/", i+1))
|
||||
return table.concat(segments, "/", 1, i), table.concat(segments, "/", i+1)
|
||||
end
|
||||
end
|
||||
@ -27,7 +24,7 @@ function fs.resolve(path) -- resolves *path* to a specific filesystem mount and
|
||||
end
|
||||
|
||||
-- generate some simple functions
|
||||
for k,v in pairs({"makeDirectory","exists","isDirectory","list","lastModified","remove","size","spaceUsed","isReadOnly","getLabel"}) do
|
||||
for k,v in pairs({"makeDirectory","exists","isDirectory","list","lastModified","remove","size","spaceUsed","spaceTotal","isReadOnly","getLabel"}) do
|
||||
fs[v] = function(path)
|
||||
local fsi,path = fs.resolve(path)
|
||||
return fsmounts[fsi][v](path)
|
||||
@ -99,13 +96,34 @@ function fs.rename(from,to) -- moves file *from* to *to*
|
||||
return true
|
||||
end
|
||||
|
||||
function fs.mount(path,proxy)
|
||||
if fs.isDirectory(path) then
|
||||
function fs.mount(path,proxy) -- mounts the filesystem *proxy* to the mount point *path* if it is a directory. BYO proxy.
|
||||
if fs.isDirectory(path) and not fsmounts[table.concat(fs.segments(path),"/")] then
|
||||
fsmounts[table.concat(fs.segments(path),"/")] = proxy
|
||||
return true
|
||||
end
|
||||
return false, "path is not a directory"
|
||||
end
|
||||
function fs.umount(path)
|
||||
local fsi,_ = fs.resolve(path)
|
||||
fsmounts[fsi] = nil
|
||||
end
|
||||
|
||||
function fs.mounts() -- returns a table containing the mount points of all mounted filesystems
|
||||
local rt = {}
|
||||
for k,v in pairs(fsmounts) do
|
||||
rt[#rt+1] = k,v.address or "unknown"
|
||||
end
|
||||
return rt
|
||||
end
|
||||
|
||||
function fs.address(path) -- returns the address of the filesystem at a given path, if applicable
|
||||
local fsi,_ = fs.resolve(path)
|
||||
return fsmounts[fsi].address
|
||||
end
|
||||
function fs.type(path) -- returns the component type of the filesystem at a given path, if applicable
|
||||
local fsi,_ = fs.resolve(path)
|
||||
return fsmounts[fsi].type
|
||||
end
|
||||
|
||||
fsmounts["/"] = component.proxy(computer.tmpAddress())
|
||||
fs.makeDirectory("temp")
|
||||
@ -113,9 +131,5 @@ if computer.getBootAddress then
|
||||
fs.makeDirectory("boot")
|
||||
fs.mount("boot",component.proxy(computer.getBootAddress()))
|
||||
end
|
||||
for addr, _ in component.list("filesystem") do
|
||||
fs.makeDirectory(addr:sub(1,3))
|
||||
fs.mount(addr:sub(1,3),component.proxy(addr))
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -8,7 +8,6 @@ function runfile(p,...) -- runs file *p* with arbitrary arguments in the current
|
||||
return loadfile(p)(...)
|
||||
end
|
||||
function os.spawnfile(p,n) -- spawns a new process from file *p* with name *n*
|
||||
dprint(p,n)
|
||||
return os.spawn(function() xpcall(loadfile(p),function(e) dprint(e.."\n"..debug.traceback()) end) end,n or p)
|
||||
end
|
||||
function require(f) -- searches for a library with name *f* and returns what the library returns, if possible
|
||||
|
@ -30,6 +30,8 @@ function os.tasks()
|
||||
return rt
|
||||
end
|
||||
function os.taskInfo(pid)
|
||||
pid = pid or os.pid()
|
||||
if not tTasks[pid] then return false end
|
||||
return {name=tTasks[pid].n,parent=tTasks[pid].P}
|
||||
end
|
||||
function os.sched() -- the actual scheduler function
|
||||
|
@ -1,5 +1,4 @@
|
||||
dprint=dprint or function() end
|
||||
|
||||
do
|
||||
syslog = {}
|
||||
syslog.emergency = 0
|
||||
syslog.alert = 1
|
||||
@ -10,8 +9,15 @@ syslog.notice = 5
|
||||
syslog.info = 6
|
||||
syslog.debug = 7
|
||||
|
||||
local rdprint=dprint or function() end
|
||||
setmetatable(syslog,{__call = function(_,msg, level, service)
|
||||
level, service = level or syslog.info, service or os.taskInfo(os.pid()).name or "unknown"
|
||||
dprint(string.format("syslog: [%s:%d/%d] %s",service,os.pid(),level,msg))
|
||||
level, service = level or syslog.info, service or (os.taskInfo(os.pid()) or {}).name or "unknown"
|
||||
rdprint(string.format("syslog: [%s:%d/%d] %s",service,os.pid(),level,msg))
|
||||
computer.pushSignal("syslog",msg, level, service)
|
||||
end})
|
||||
function dprint(...)
|
||||
for k,v in pairs({...}) do
|
||||
syslog(v,syslog.debug)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -31,8 +31,7 @@ function vtemu(gpua,scra) -- creates a process to handle the GPU and screen addr
|
||||
coroutine.yield()
|
||||
end
|
||||
local n = buf:find("\n")
|
||||
r, buf = buf:sub(1,n), buf:sub(n+1)
|
||||
dprint("bread",r)
|
||||
r, buf = buf:sub(1,n-1), buf:sub(n+1)
|
||||
return r
|
||||
end
|
||||
return bread, write, function() io.write("\27[2J\27[H") end
|
||||
|
@ -1,11 +1,21 @@
|
||||
local function mount(addr)
|
||||
dest = component.invoke(addr,"getLabel") or "mnt/"..addr:sub(1,3)
|
||||
dest = "/"..dest
|
||||
syslog("Mounting "..addr.." to "..dest)
|
||||
fs.makeDirectory(dest)
|
||||
local w,r = fs.mount(dest,component.proxy(addr))
|
||||
if not w then
|
||||
syslog("Failed to mount: "..r)
|
||||
end
|
||||
end
|
||||
for addr, _ in component.list("filesystem") do
|
||||
mount(addr)
|
||||
end
|
||||
while true do
|
||||
local tE = {coroutine.yield()}
|
||||
if tE[1] == "component_added" and tE[3] == "filesystem" then
|
||||
local w, doesExist = pcall(fs.exists,"/"..tE[2]:sub(1,3))
|
||||
if not w or not doesExist then
|
||||
fs.mounts[tE[2]:sub(1,3)] = component.proxy(tE[2])
|
||||
end
|
||||
mount(tE[2])
|
||||
elseif tE[1] == "component_removed" and tE[3] == "filesystem" then
|
||||
fs.mounts[tE[2]:sub(1,3)] = nil
|
||||
fs.umount("/mnt/"..tE[2]:sub(1,3))
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
local gpus,screens,ttyn = {}, {}, 0
|
||||
local gpus,screens,ttyn,pids = {}, {}, 0, {}
|
||||
local function scan()
|
||||
local w,di = pcall(computer.getDeviceInfo)
|
||||
if w then
|
||||
@ -29,6 +29,14 @@ local function nextScreen(n)
|
||||
end
|
||||
return rt[n] or rt[8000] or rt[2000] or rt[600]
|
||||
end
|
||||
|
||||
local function spawnShell(fin,fout)
|
||||
io.input(fin)
|
||||
io.output(fout)
|
||||
print(_OSVERSION.." - "..tostring(math.floor(computer.totalMemory()/1024)).."K RAM")
|
||||
return os.spawnfile("/boot/exec/shell.lua")
|
||||
end
|
||||
|
||||
local function allocate()
|
||||
for k,v in pairs(gpus) do
|
||||
dprint(k)
|
||||
@ -38,13 +46,22 @@ local function allocate()
|
||||
devfs.register("tty"..tostring(ttyn), function() return r,w,function() end end)
|
||||
gpus[k][1] = true
|
||||
screens[sA][1] = true
|
||||
pids["tty"..tostring(ttyn)] = {-1}
|
||||
ttyn = ttyn + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
scan()
|
||||
allocate()
|
||||
dprint("screens ready")
|
||||
while true do
|
||||
coroutine.yield()
|
||||
for k,v in pairs(pids) do
|
||||
if not os.taskInfo(v[1]) then
|
||||
dprint("Spawning new shell for "..k)
|
||||
pids[k][1] = spawnShell(v[2] or "/dev/"..k, v[3] or "/dev/"..k)
|
||||
pids[k][2], pids[k][3] = pids[k][2] or io.input(), pids[k][3] or io.output()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user