mirror of
https://github.com/20kdc/OC-KittenOS.git
synced 2024-11-17 16:08:06 +11:00
157 lines
3.9 KiB
Lua
157 lines
3.9 KiB
Lua
|
-- This is released into the public domain.
|
||
|
-- No warranty is provided, implied or otherwise.
|
||
|
|
||
|
-- svc-virtudev.lua : Virtual Device interface
|
||
|
-- Authors: 20kdc
|
||
|
|
||
|
local ic = neo.requireAccess("x.neo.pub.base", "to lock x.svc.virtudev")
|
||
|
-- this is a pretty powerful permission, and PROBABLY EXPLOITABLE
|
||
|
ic.lockPerm("x.svc.virtudev")
|
||
|
local r = neo.requireAccess("r.svc.virtudev", "api endpoint")
|
||
|
|
||
|
local root = neo.requireAccess("k.root", "the ability to modify the component API")
|
||
|
|
||
|
local proxies = {}
|
||
|
local types = {}
|
||
|
|
||
|
local function uninstall(k)
|
||
|
proxies[k] = nil
|
||
|
types[k] = nil
|
||
|
root.computer.pushSignal("component_removed", k, types[k])
|
||
|
end
|
||
|
|
||
|
local users = {}
|
||
|
local userCount = 0
|
||
|
|
||
|
r(function (pkg, pid, sendSig)
|
||
|
local userAddresses = {}
|
||
|
users[pid] = userAddresses
|
||
|
userCount = userCount + 1
|
||
|
return {
|
||
|
install = function (proxy)
|
||
|
local proxyAddress = proxy.address
|
||
|
local proxyType = proxy.type
|
||
|
assert(type(proxyAddress) == "string")
|
||
|
assert(type(proxyType) == "string")
|
||
|
assert(not proxies[proxyAddress], "proxy address in use: " .. proxyAddress)
|
||
|
proxies[proxyAddress] = proxy
|
||
|
types[proxyAddress] = proxyType
|
||
|
userAddresses[proxyAddress] = true
|
||
|
root.computer.pushSignal("component_added", proxyAddress, proxyType)
|
||
|
return function (a, ...)
|
||
|
root.computer.pushSignal(a, proxyAddress, ...)
|
||
|
end
|
||
|
end,
|
||
|
uninstall = function (k)
|
||
|
if userAddresses[k] then
|
||
|
uninstall(k)
|
||
|
userAddresses[k] = nil
|
||
|
end
|
||
|
end
|
||
|
}
|
||
|
end)
|
||
|
|
||
|
local componentProxyRaw = root.component.proxy
|
||
|
local componentTypeRaw = root.component.type
|
||
|
local componentMethodsRaw = root.component.methods
|
||
|
local componentFieldsRaw = root.component.fields
|
||
|
local componentDocRaw = root.component.doc
|
||
|
local componentInvokeRaw = root.component.invoke
|
||
|
local componentListRaw = root.component.list
|
||
|
|
||
|
root.component.proxy = function (address)
|
||
|
if proxies[address] then
|
||
|
return proxies[address]
|
||
|
end
|
||
|
return componentProxyRaw(address)
|
||
|
end
|
||
|
|
||
|
root.component.type = function (address)
|
||
|
if types[address] then
|
||
|
return types[address]
|
||
|
end
|
||
|
return componentTypeRaw(address)
|
||
|
end
|
||
|
|
||
|
local function methodsFieldsHandler(address, methods)
|
||
|
if proxies[address] then
|
||
|
local mt = {}
|
||
|
for k, v in pairs(proxies[address]) do
|
||
|
if (type(v) == "function") == methods then
|
||
|
mt[k] = true
|
||
|
end
|
||
|
end
|
||
|
return mt
|
||
|
end
|
||
|
if methods then
|
||
|
return componentMethodsRaw(address)
|
||
|
else
|
||
|
return componentFieldsRaw(address)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
root.component.methods = function (address) return methodsFieldsHandler(address, true) end
|
||
|
root.component.fields = function (address) return methodsFieldsHandler(address, false) end
|
||
|
root.component.doc = function (address, method)
|
||
|
if proxies[address] then
|
||
|
return tostring(proxies[address][method])
|
||
|
end
|
||
|
return componentDocRaw(address, method)
|
||
|
end
|
||
|
root.component.invoke = function (address, method, ...)
|
||
|
if proxies[address] then
|
||
|
return proxies[address][method](...)
|
||
|
end
|
||
|
return componentInvokeRaw(address, method, ...)
|
||
|
end
|
||
|
|
||
|
root.component.list = function (f, e)
|
||
|
local iter = componentListRaw(f, e)
|
||
|
local ended = false
|
||
|
local others = {}
|
||
|
for k, v in pairs(types) do
|
||
|
if (f == v) or ((not e) and v:find(f, 1, true)) then
|
||
|
table.insert(others, {k, v})
|
||
|
end
|
||
|
end
|
||
|
return function ()
|
||
|
if not ended then
|
||
|
local a, t = iter()
|
||
|
if not a then
|
||
|
ended = true
|
||
|
else
|
||
|
return a, t
|
||
|
end
|
||
|
end
|
||
|
-- at end of that, so what about others
|
||
|
local ent = table.remove(others, 1)
|
||
|
if ent then
|
||
|
return table.unpack(ent)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
while true do
|
||
|
local e1, e2, e3 = coroutine.yield()
|
||
|
if e1 == "k.procdie" then
|
||
|
if users[e3] then
|
||
|
for k, _ in pairs(users[e3]) do
|
||
|
uninstall(k)
|
||
|
end
|
||
|
users[e3] = nil
|
||
|
userCount = userCount - 1
|
||
|
if userCount == 0 then
|
||
|
break
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
root.component.proxy = componentProxyRaw
|
||
|
root.component.type = componentTypeRaw
|
||
|
root.component.methods = componentMethodsRaw
|
||
|
root.component.fields = componentFieldsRaw
|
||
|
root.component.doc = componentDocRaw
|
||
|
root.component.invoke = componentInvokeRaw
|
||
|
root.component.list = componentListRaw
|