find, filter, skeletons

This commit is contained in:
Sam Roxanne 2020-06-03 15:06:58 -05:00
parent 50cfb2bbf2
commit 76de8ca302
16 changed files with 73 additions and 584 deletions

View File

@ -1 +1 @@
{enabled={"getty","minitel"}}
{enabled={"getty","minitel","clipboard","fsmanager"}}

View File

@ -1,128 +0,0 @@
local _,serial = pcall(require,"serialization")
local doc = {}
doc.searchers = {}
doc.tctab = {
["string"] = 31,
["table"] = 32,
["number"] = 33,
["boolean"] = 35,
["function"] = 36
}
function doc.parsefile(path) -- string -- table -- parses file from *path* to return a documentation table
local fdoc = {}
local f = io.open(path)
local lines = {}
for l in f:read("*a"):gmatch("[^\n]+") do
if l:find("function") and not l:find("local") then
lines[#lines+1] = l
end
end
for k,v in pairs(lines) do
local name, args, desc = v:match("function%s+(.+)%s*%((.*)%)%s*%-%-%s*(.+)")
if name and args and desc then
local fd = {["description"]=desc or desc,["args"]={},["atypes"]={}}
for word in args:gmatch("[^%s,]+") do
fd.args[#fd.args+1] = {word}
fd.atypes[word] = "unknown"
end
local argtypes, outtypes, description = desc:match("(.-)%-%-(.-)%-%-%s*(.+)")
if argtypes and outtypes and description then
local wc = 1
for word in argtypes:gmatch("%S+") do
fd.args[wc][2] = word
fd.atypes[fd.args[wc][1]] = word
wc = wc + 1
end
local wc = 1
for word in outtypes:gmatch("%S+") do
fd.outtypes = fd.outtypes or {}
fd.outtypes[#fd.outtypes+1] = word
end
fd.description = description
end
fdoc[name] = fd
end
end
return fdoc
end
function doc.format(fdoc) -- table -- string -- returns VT100 formatted documentation from documentation table *fdoc*
local rs = "" -- string to return
for fname,finfo in pairs(fdoc) do
if rs:len() > 0 then rs = rs .. "\n\n" end
local as = "" -- string containing arguments for a given function, with colours for type
for k,v in ipairs(finfo.args) do
local c = doc.tctab[v[2]] or 0
if k > 1 then
as = as .. ", "
end
if v[2] then
as = string.format("%s%s: \27[%im%s\27[0m",as,v[2],c,v[1])
else
as = string.format("%s\27[%im%s\27[0m",as,c,v[1])
end
end
local rv = ""
if finfo.outtypes then
rv = ": "
for k,v in ipairs(finfo.outtypes) do
if k > 1 then
rv = rv .. ", "
end
local c = doc.tctab[v] or 0
rv = string.format("%s\27[%im%s\27[0m",rv,c,v)
end
end
local nd = finfo.description
for k,v in pairs(finfo.atypes) do
local c = doc.tctab[v] or 7
nd=nd:gsub("%*"..k.."%*","\27["..tostring(c).."m"..k.."\27[0m")
end
rs = string.format("%s\27[36m%s\27[0m(%s)%s\n%s",rs,fname,as,rv,nd)
end
return rs
end
function doc.searchers.lib(name) -- string -- string string -- Tries to find a documentation from a library with *name*. Returns either a string of documentation, or false and a reason.
local lib = os.getenv("LIB") or "/boot/lib"
local dt
for d in lib:gmatch("[^\n]+") do
if fs.exists(d.."/"..name) then
dt = doc.parsefile(d.."/"..name)
elseif fs.exists(d.."/"..name..".lua") then
dt = doc.parsefile(d.."/"..name..".lua")
end
end
if not dt then return false, "unable to find documentation for "..tostring(name) end
return doc.format(dt)
end
function doc.searchers.cdoc(topic) -- string -- string string -- Searches for documentation labelled as *topic* in .dict files under /boot/doc/
if not serial then return end
for k,v in ipairs(fs.list("/boot/doc")) do
if v:sub(-5) == ".dict" then
local f=io.open("/boot/doc/"..v,"rb")
for line in f:lines() do
local mname, docs = line:match("^(.-)\t(.+)$")
if mname == topic or mname == topic..".lua" then
return doc.format(serial.unserialize(docs))
end
end
end
end
end
function doc.docs(topic) -- string -- boolean -- Displays the documentation for *topic*, returning true, or errors. Also callable as just doc().
local lib = os.getenv("LIB") or "/boot/lib"
local dt
for k,v in pairs(doc.searchers) do
dt=v(topic)
if dt then
print(dt)
return true
end
end
error("unable to find documentation for "..tostring(name))
end
return setmetatable(doc,{__call=function(_,topic) return doc.docs(topic) end})

0
lib/foxfs.lua Normal file
View File

View File

@ -1,63 +0,0 @@
local imt = {}
imt.ttypes = {}
imt.ttypes.string=1
imt.ttypes.number=2
imt.ftypes = {tostring,tonumber}
function imt.to16bn(n)
return string.char(math.floor(n/256))..string.char(math.floor(n%256))
end
function imt.from16bn(s)
return (string.byte(s,1,1)*256)+string.byte(s,2,2)
end
function imt.encodePacket(...)
local tArgs = {...}
local packet = string.char(#tArgs%256)
for _,segment in ipairs(tArgs) do
local segtype = type(segment)
segment = tostring(segment)
packet = packet .. imt.to16bn(segment:len()) .. string.char(imt.ttypes[segtype]) .. tostring(segment)
end
packet = imt.to16bn(packet:len()) .. packet
return packet
end
function imt.decodePacket(s)
local function getfirst(n)
local ns = s:sub(1,n)
s=s:sub(n+1)
return ns
end
if s:len() < 2 then return false end
local plen = imt.from16bn(getfirst(2))
local segments = {}
if s:len() < plen then return false end
local nsegments = string.byte(getfirst(1))
--print(tostring(plen).." bytes, "..tostring(nsegments).." segments")
for i = 1, nsegments do
local seglen = imt.from16bn(getfirst(2))
local segtype = imt.ftypes[string.byte(getfirst(1))]
local segment = segtype(getfirst(seglen))
--print(seglen,segtype,segment,type(segment))
segments[#segments+1] = segment
end
return table.unpack(segments)
end
function imt.getRemainder(s)
local function getfirst(n)
local ns = s:sub(1,n)
s=s:sub(n+1)
return ns
end
local plen = imt.from16bn(getfirst(2))
if s:len() > plen then
getfirst(plen)
return s
end
return nil
end
return imt

0
lib/osdi.lua Normal file
View File

View File

@ -2,7 +2,6 @@ local component = require "component"
local fs = require "fs"
local shell = require "shell"
local ed = require "ed"
local doc = require "doc"
local shutil = {}
shutil.ed = ed.interactive
shutil.vi = ed.visual
@ -124,4 +123,42 @@ shutil.mkdir = fs.makeDirectory
shutil.cp = fs.copy
shutil.rm = fs.remove
local function find_dir(t, dir)
local f = fs.list(dir)
for i=1, #f do
if (f[i]:sub(#f[i]) == "/") then
find_dir(t, dir..f[i])
end
t[#t+1] = dir..f[i]
end
end
function shutil.find(...)
local paths = {...}
if not paths[1] then paths = {"."} end
for i=1, #paths do
if (paths[i]:sub(#paths[i]) ~= "/") then
paths[i] = paths[i] .. "/"
end
end
local t = {}
for i=1, #paths do
if fs.isDirectory(paths[i]) then
find_dir(t, paths[i])
end
t[#t+1] = paths[i]
end
return t
end
function shutil.filter(t, func)
local t2 = {}
for i=1, #t do
if (func(t[i])) then
t2[#t2+1] = t[i]
end
end
return t2
end
return shutil

13
lib/tsar.lua Normal file
View File

@ -0,0 +1,13 @@
local tsar = package.loaded.tsar or {}
function tsar.extract(fd, path, ...)
end
function tsar.create(paths, fd)
end
function tsar.list(fd)
end

14
lib/tsuki.lua Normal file
View File

@ -0,0 +1,14 @@
local foxfs = require "foxfs"
local tsuki = {}
function tsuki.reset_security_node(path)
end
function tsuki.reset_dev_permissions(path)
end
function tsuki.make_security_node(path)
end

7
lib/velx.lua Normal file
View File

@ -0,0 +1,7 @@
local velx = package.loaded.velx or {}
function velx.parse(fd)
end
return velx

Binary file not shown.

View File

@ -1,95 +0,0 @@
local minitel = require "minitel"
local serial = require "serialization"
local cfg = {["path"]="/boot/srv/frequest",["port"]=70}
f=io.open("/boot/cfg/fserv.cfg","rb")
if f then
local ncfg = serial.unserialize(f:read("*a"))
f:close()
for k,v in pairs(ncfg) do
cfg[k] = v
end
end
local function fileHandler(socket,rtype,path)
syslog(string.format("[%s:%d] %s %s",socket.addr,socket.port,rtype,path),syslog.info,"fserv")
if rtype == "t" then
if fs.exists(path) and fs.isDirectory(path) then
socket:write("d")
for _,file in ipairs(fs.list(path)) do
socket:write(file.."\n")
end
elseif fs.exists(path) and not fs.isDirectory(path) then
local f,err = io.open(path,"rb")
if f then
socket:write("y")
while true do
local c = f:read(4096)
if not c or c == "" then break end
socket:write(c)
end
else
socket:write("fFailed to open file: "..err)
end
else
socket:write("nFile not found")
end
elseif rtype == "s" then
if fs.exists(path) then
local ftype = "f"
if fs.isDirectory(path) then
ftype = "d"
end
socket:write(string.format("y%s\n%d",ftype,fs.size(path)))
else
socket:write("nFile not found.")
end
else
socket:write("fUnknown request type")
end
end
local function httpHandler(socket,rtype,path)
local tPath = fs.segments(path)
local proto = table.remove(tPath,1)
local url = string.format("%s://%s",proto,table.concat(tPath,"/"))
local request = component.invoke(component.list("internet")(),"request",url)
repeat
coroutine.yield()
until request.finishConnect()
local code, message, headers = request.response()
if code < 200 or code > 299 then
socket:write(string.format("f%d\n%s",code,message))
else
local data = ""
repeat
coroutine.yield()
data = request.read()
if data then
socket:write(data)
end
until not data
end
end
local function socketHandler(socket)
return function()
local line = nil
repeat
coroutine.yield()
line = socket:read()
until line
local rtype, path = line:match("(.)(.+)")
if fs.segments(path)[1] == "http" or fs.segments(path)[1] == "https" then
httpHandler(socket,rtype,path)
else
path = (cfg.path .. "/" .. path:gsub("../","")):gsub("/+","/")
fileHandler(socket,rtype,path)
end
socket:close()
end
end
while true do
os.spawn(socketHandler(minitel.listen(70)),"fserv worker process")
end

View File

@ -1,25 +0,0 @@
local lastkey = computer.uptime()
local state = true
local delay = 60
function start()
return os.spawn(function()
while true do
tEv = {coroutine.yield()}
if tEv[1] == "key_down" then
lastkey = computer.uptime()
if not state then
for addr in component.list("screen") do
component.invoke(addr,"turnOn")
end
state = true
end
end
if computer.uptime() > lastkey + delay and state then
for addr in component.list("screen") do
component.invoke(addr,"turnOff")
end
state = false
end
end
end,"screenblank")
end

View File

@ -1,28 +0,0 @@
local counter = 0
local td = {}
local function addNode(addr)
devfs.register("tape"..tonumber(counter),function()
local tape = component.proxy(addr)
tape.seek(-math.huge)
return tape.read, tape.write, function() end, tape.seek
end)
devfs.register("tapen"..tonumber(counter),function()
local tape = component.proxy(addr)
return tape.read, tape.write, function() end, tape.seek
end)
td[addr] = counter
counter = counter + 1
end
for addr in component.list("tape_drive") do
addNode(addr)
end
while true do
local tE = {coroutine.yield()}
if tE[1] == "component_added" and tE[3] == "tape_drive" then
addNode(tE[2])
elseif tE[1] == "component_removed" and tE[3] == "tape_drive" then
if td[tE[2]] then
fs.remove("/dev/tape"..tostring(td[tE[2]]))
end
end
end

View File

@ -1,63 +0,0 @@
local minitel = require "minitel"
local shell = require "shell"
local port = 22
local function sread(self, len)
while true do
local d=self.sock:read(len)
if d then
return d
end
coroutine.yield()
end
end
local function swrite(self, data)
while self.flushing do
coroutine.yield()
end
if data and data:len() > 0 then
self.wb = self.wb .. (data or "")
end
end
local function sclose(self)
self.sock:close()
end
local function sflush(self)
self.flushing = true
self.sock:write(self.wb)
self.wb = ""
self.flushing = false
end
function start()
return os.spawn(function()
local oout = io.output()
local pname = os.taskInfo(os.pid()).name
while true do
local sock = minitel.listen(port)
print(string.format("Connection from %s:%d",sock.addr,sock.port))
os.spawn(function() _G.worked = {pcall(function()
local fh = {}
fh.sock = sock
fh.read = sread
fh.write = swrite
fh.close = sclose
fh.flush = sflush
fh.wb = ""
io.input(fh)
io.output(fh)
print(_OSVERSION.." - "..tostring(math.floor(computer.totalMemory()/1024)).."K RAM")
local pid = os.spawn(shell.interactive,string.format(pname.." shell [%s:%d]",sock.addr,sock.port))
repeat
coroutine.yield()
if fh.wb:len() > 0 then
fh:flush()
end
until sock.state ~= "open" or not os.taskInfo(pid)
sock:close()
os.kill(pid)
oout:write(string.format("Session %s:%d ended",sock.addr,sock.port))
end)} end,string.format(pname.." [%s:%d]",sock.addr,sock.port))
end
end,"termsrv")
end

View File

@ -1,162 +0,0 @@
local vcomponent = require "vcomponent"
local serial = require "serialization"
local component = require "component"
local computer = require "computer"
local event = require "event"
local imt = require "interminitel"
local cfg = {}
cfg.peers = {}
cfg.rtimer = 5
cfg.katimer = 30
local listeners = {}
local proxies = {}
local function loadcfg()
local f = io.open("/boot/cfg/vtunnel.cfg","rb")
if not f then return false end
for k,v in pairs(serial.unserialize(f:read("*a")) or {}) do
cfg[k] = v
end
f:close()
end
local function savecfg()
local f = io.open("/boot/cfg/vtunnel.cfg","wb")
if not f then
print("Warning: unable to save configuration.")
return false
end
f:write(serial.serialize(cfg))
f:close()
end
local function createTunnel(host,port,addr,raddr)
local proxy = {address=addr,buffer=""}
function proxy.connect()
if proxy.socket then
proxy.socket.close()
end
proxy.socket = component.invoke(component.list("internet")(),"connect",host,port)
local st = computer.uptime()
repeat
coroutine.yield()
until proxy.socket.finishConnect() or computer.uptime() > st+5
end
function proxy.send(...)
rt = 0
while not proxy.socket.write(imt.encodePacket(...)) and rt < 10 do
proxy.connect()
rt = rt + 1
end
proxy.last = computer.uptime()
end
function proxy.read()
local rb, r
local rt = 0
while true do
rb,r = proxy.socket.read(4096)
if rb or rt > 10 then break end
if type(rb) == "nil" then
proxy.connect()
end
rt = rt + 1
end
proxy.buffer = proxy.buffer .. rb
while imt.decodePacket(proxy.buffer) do
computer.pushSignal("modem_message",addr,raddr,0,0,imt.decodePacket(proxy.buffer))
proxy.buffer = imt.getRemainder(proxy.buffer) or ""
end
if computer.uptime() > proxy.last + cfg.katimer then
proxy.socket.write("\0\1\0")
proxy.last = computer.uptime()
end
end
function proxy.getWakeMessage()
return false
end
proxy.setWakeMessage = proxy.getWakeMessage
function proxy.maxPacketSize()
return 8192
end
function proxy.getChannel()
return host..":"..tostring(port)
end
proxy.connect()
proxy.last = computer.uptime()
return proxy
end
vt = {}
function start()
loadcfg()
for k,v in pairs(cfg.peers) do
print(string.format("Connecting to %s:%d",v.host,v.port))
v.addr = v.addr or vcomponent.uuid()
v.raddr = v.raddr or vcomponent.uuid()
local px = createTunnel(v.host, v.port, v.addr, v.raddr)
vcomponent.register(v.addr, "tunnel", px)
proxies[v.addr] = px
end
for k,v in pairs(os.tasks()) do
if os.taskInfo(v).name:match("minitel") then
os.kill(v)
end
end
end
function vt.stop()
for k,v in pairs(proxies) do
vcomponent.unregister(k)
end
end
function vt.listpeers()
for k,v in pairs(cfg.peers) do
print(string.format("#%d (%s:%d)\n Local address: %s\n Remote address: %s",k,v.host,v.port,v.addr,v.raddr))
end
end
function vt.addpeer(host,port)
port = tonumber(port) or 4096
local t = {}
t.host = host
t.port = port
t.addr = vcomponent.uuid()
t.raddr = vcomponent.uuid()
cfg.peers[#cfg.peers+1] = t
print(string.format("Added peer #%d (%s:%d) to the configuration.\nRestart to apply changes.",#cfg.peers,host,port))
savecfg()
end
function vt.delpeer(n)
n=tonumber(n)
if not n then
print("delpeer requires a number, representing the peer number, as an argument.")
return false
end
local dp = table.remove(cfg.peers, n)
savecfg()
print(string.format("Removed peer %s:%d",dp.host, dp.port))
end
function vt.settimer(time)
time = tonumber(time)
if not time then
print("Timer must be a number.")
return false
end
cfg.rtime = time
savecfg()
end
vt.start = start
_G.libs.vtunnel = vt
start()
local last = computer.uptime()
while true do
local tE = {coroutine.yield()}
if computer.uptime() > last + cfg.rtimer then
for k,v in pairs(proxies) do
v.read()
end
last = computer.uptime()
end
end

View File

@ -1,18 +0,0 @@
local delay = 60
local port = 3442
local message = "WoLBeacon"
for modem in component.list("modem") do
component.invoke(modem,"setWakeMessage",message)
end
local ltime = computer.uptime()
while true do
if computer.uptime() > ltime+delay then
for modem in component.list("modem") do
component.invoke(modem,"broadcast",port,message)
end
ltime=computer.uptime()
end
coroutine.yield()
end