OC-PsychOS/modules/base/header.lua

203 lines
4.7 KiB
Lua

do -- so local works
-- task format:
-- {
-- ["n"] = "name",
-- ["c"] = coroutine of task,
-- ["e"] = { table, of, environment, variables },
-- ["p"] = parent pid,
-- ["u"] = user ID,
-- ["ep"]= event queue pointer
-- }
local tT,nP,rg,eq,p = {},1,_G,{},1 -- taskTable,nextPid,real _G,event queue
_G.cT,sbt,C,T,io = 0,{},coroutine,table,io -- currentTask,sandboxTable
function _G.spawn(n,f,e)
tT[nP] = {}
local function nf()
log(xpcall(f))
end
tT[nP].c = coroutine.create(nf)
tT[nP].n = n
tT[nP].p = cT or -1
if tT[cT] then
tT[nP].u,tT[nP].ep,tT[nP].e = tT[cT].u,tT[cT].ep,e or tT[cT].e or {["PWD"]="/boot",["PATH"]="/boot/exec:."}
else
tT[nP].u,tT[nP].ep,tT[nP].e = "superuser",1,{["PWD"]="/boot",["PATH"]="/boot/exec:."}
end
nP = nP + 1
return nP-1
end
function _G.sched()
_G.sched = nil
while #tT > 0 do
eq[#eq+1]={computer.pullSignal(p)} -- add the latest event to the eq
if #eq > 16 then
table.remove(eq,1) -- remove the earliest if the eq is full
for pid,proc in pairs(tT) do
if proc.ep > 1 then
proc.ep = proc.ep - 1 -- decrement pointers for tasks to keep them on the same ones
end
end
end
for pid,proc in pairs(tT) do
if coroutine.status(proc.c) == "dead" then
tT[pid] = nil
else
cT=pid
for i = 1,tT[pid].ep, #eq do
_G.ev = eq[#eq] -- make an ev for MultICE compat
coroutine.resume(proc.c)
end
end
end
end
end
_G.event = {}
function event.get() -- get the next event in the queue, or nil
if eq[tT[cT].ep] then
tT[cT].ep = tT[cT].ep + 1
if tT[cT].ep > 17 then
tT[cT].ep = 17
end
return eq[tT[cT].ep - 1]
end
end
function event.pull(t,time) -- return or wait for the next event, optionally with the first param matching t
time = time or math.huge
time = time + computer.uptime()
while computer.uptime() < time do
local e = event.get()
if e then
if t then
if e[1] == t then
return table.unpack(e)
end
else
return table.unpack(e)
end
end
coroutine.yield()
end
end
event.push = computer.pushSignal
function os.getenv(k) -- gets an envionment variable from tT[cT].e
if tT[cT] then
return tT[cT].e[k]
end
end
function os.setenv(k,v) -- sets "
if tT[cT] then
tT[cT].e[k] = v
end
end
function os.tasks() -- returns a table of tasks running on the system
local t = {}
for k,v in pairs(tT) do
t[k] = v.n
end
return t
end
function os.taskinfo(pid) -- returns info on a task
if tT[pid] then
return tT[pid].n,tT[pid].p,tT[pid].u
end
end
function os.genenv()
local et = {}
setmetatable(et,{__index=_G})
return et
end
-- user stuff from here
local ut = {}
local function flushut()
local f = fs.open("/boot/sys/users.dat","wb")
if f then
for k,v in pairs(ut) do
for l,m in pairs(v) do
fs.write(f,k.."\t"..l.."\t"..m.."\n")
end
end
fs.close(f)
return true
end
return false
end
local function readut()
local f=fs.open("/boot/sys/users.dat","rb")
if not f then return false end
local C=fs.readall(f)
fs.close(f)
for line in C:gmatch("[^\n]+") do
local username,field,val = line:match("(.+)\t(.+)\t(.+)")
if username and field and val then
if not ut[username] then ut[username] = {} end
ut[username][field] = val
end
end
end
function os.setuid(user)
if tT[cT].u == "superuser" and ut[user] then
tT[cT].u = user
return true
end
return false
end
function os.getuid(pid)
pid = pid or cT
if not tT[pid] then return "superuser" end
return tT[pid].u
end
function os.users()
local t = {}
for k,v in pairs(ut) do
t[#t+1] = k
end
return t
end
function os.verifyuser(username,pass)
if sha then
if ut[username] then
if not os.getuattr(username,"hpass") or not os.getuattr(username,"salt") then return true end
if sha.sha256(pass..ut[username].salt) == ut[username].hpass then
return true
end
end
return false
end
return true
end
function os.gensalt(len)
local S = ""
for i = 1, len do
S=S..string.char(math.random(32,126))
end
return S
end
function os.setuattr(username,field,val)
if os.getuid() == "superuser" or os.getuid() == username then
if not field then
ut[username] = nil
else
if not ut[username] then ut[username] = {} end
ut[username][field] = val
log("set "..username.."."..field.." to "..val)
flushut()
end
end
end
function os.getuattr(username,field)
if os.getuid() == "superuser" or os.getuid() == username then
local uT = ut[username] or {}
return uT[field]
end
end
function os.su(user,pass)
if os.verifyuser(user,pass) then
log(tT[cT].u .. " su'd to "..user,6,1,true)
tT[cT].u = user
return true
end
return false
end
spawn("read users",readut)
end