mirror of
https://git.shadowkat.net/izaya/OC-PsychOS2.git
synced 2024-11-22 03:54:20 -05:00
fuck knows
This commit is contained in:
parent
22b451e223
commit
2f48091a07
7
build.sh
Executable file
7
build.sh
Executable file
@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
mkdir build
|
||||
cd module
|
||||
cat sched.lua vt100.lua fs.lua loadfile.lua vt-task.lua io.lua microtel-3.lua init.lua > ../build/psychos.lua
|
||||
cd ..
|
||||
echo '_OSVERSION="PsychOS 2.0a0"' >> build/*
|
||||
echo sched\(\) >> build/*
|
432
build/psychos.lua
Normal file
432
build/psychos.lua
Normal file
@ -0,0 +1,432 @@
|
||||
tTasks,nPid,nTimeout,cPid = {},1,1,0
|
||||
function os.spawn(f,n)
|
||||
tTasks[nPid] = {["c"]=coroutine.create(f),["n"]=n,["p"]=nPid}
|
||||
for k,v in pairs(tTasks[cPid] or {}) do
|
||||
tTasks[nPid][k] = tTasks[nPid][k] or v
|
||||
end
|
||||
nPid = nPid + 1
|
||||
return nPid - 1
|
||||
end
|
||||
function sched()
|
||||
while #tTasks > 0 do
|
||||
local tEv = {computer.pullSignal(nTimeout)}
|
||||
for k,v in pairs(tTasks) do
|
||||
if coroutine.status(v.c) ~= "dead" then
|
||||
cPid = k
|
||||
coroutine.resume(v.c,table.unpack(tEv))
|
||||
else
|
||||
tTasks[k] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function vt100emu(gpu)
|
||||
local mx, my = gpu.maxResolution()
|
||||
local cx, cy = 1, 1
|
||||
local pc = " "
|
||||
local lc = ""
|
||||
local mode = "n"
|
||||
local lw = true
|
||||
local sx, sy = 1,1
|
||||
local cs = ""
|
||||
|
||||
-- setup
|
||||
gpu.setResolution(mx,my)
|
||||
gpu.fill(1,1,mx,my," ")
|
||||
|
||||
function termwrite(s)
|
||||
s=s:gsub("\8","\27[D")
|
||||
pc = gpu.get(cx,cy)
|
||||
gpu.setForeground(0xFFFFFF)
|
||||
gpu.setBackground(0)
|
||||
gpu.set(cx,cy,pc)
|
||||
for i = 1, s:len() do
|
||||
local cc = s:sub(i,i)
|
||||
|
||||
if mode == "n" then
|
||||
if cc == "\n" then -- line feed
|
||||
cx, cy = 1, cy+1
|
||||
elseif cc == "\r" then -- cursor home
|
||||
cx = 1
|
||||
elseif cc == "\27" then -- escape
|
||||
mode = "e"
|
||||
elseif string.byte(cc) > 31 and string.byte(cc) < 127 then -- printable, I guess
|
||||
gpu.set(cx, cy, cc)
|
||||
cx = cx + 1
|
||||
end
|
||||
|
||||
elseif mode == "e" then
|
||||
if cc == "[" then
|
||||
mode = "v"
|
||||
cs = ""
|
||||
elseif cc == "D" then -- scroll down
|
||||
gpu.copy(1,2,mx,my-1,0,-1)
|
||||
gpu.fill(1,my,mx,1," ")
|
||||
cy=cy+1
|
||||
mode = "n"
|
||||
elseif cc == "M" then -- scroll up
|
||||
gpu.copy(1,1,mx,my-1,0,1)
|
||||
gpu.fill(1,1,mx,1," ")
|
||||
mode = "n"
|
||||
end
|
||||
|
||||
elseif mode == "v" then -- save cursor
|
||||
local n = cs:sub(cs:len(),cs:len())
|
||||
if n == "" then n = "\1" end
|
||||
if cc == "s" then
|
||||
sx, sy = cx, cy
|
||||
mode = "n"
|
||||
elseif cc == "u" then -- restore cursor
|
||||
cx, cy = sx, sy
|
||||
mode = "n"
|
||||
elseif cc == "H" then -- cursor home or to
|
||||
local tx, ty = cs:match("(.);(.)")
|
||||
tx, ty = tx or "\1", ty or "\1"
|
||||
cx, cy = string.byte(tx), string.byte(ty)
|
||||
mode = "n"
|
||||
elseif cc == "A" then -- cursor up
|
||||
cy = cy - string.byte(n)
|
||||
mode = "n"
|
||||
elseif cc == "B" then -- cursor down
|
||||
cy = cy + string.byte(n)
|
||||
mode = "n"
|
||||
elseif cc == "C" then -- cursor right
|
||||
cx = cx + string.byte(n)
|
||||
mode = "n"
|
||||
elseif cc == "D" then -- cursor left
|
||||
cx = cx - string.byte(n)
|
||||
mode = "n"
|
||||
elseif cc == "h" and lc == "7" then -- enable line wrap
|
||||
lw = true
|
||||
elseif cc == "l" and lc == "7" then -- disable line wrap
|
||||
lw = false
|
||||
end
|
||||
cs = cs .. cc
|
||||
end
|
||||
|
||||
if cx > mx and lw then
|
||||
cx, cy = 1, cy+1
|
||||
end
|
||||
if cy > my then
|
||||
gpu.copy(1,2,mx,my-1,0,-1)
|
||||
gpu.fill(1,my,mx,1," ")
|
||||
cy=my
|
||||
end
|
||||
if cy < 1 then cy = 1 end
|
||||
if cx < 1 then cx = 1 end
|
||||
|
||||
lc = cc
|
||||
end
|
||||
pc = gpu.get(cx,cy)
|
||||
gpu.setForeground(0)
|
||||
gpu.setBackground(0xFFFFFF)
|
||||
gpu.set(cx,cy,pc)
|
||||
gpu.setForeground(0xFFFFFF)
|
||||
gpu.setBackground(0)
|
||||
end
|
||||
|
||||
return termwrite
|
||||
end
|
||||
fs = {}
|
||||
fs.mounts = {}
|
||||
|
||||
-- basics
|
||||
function fs.segments(path)
|
||||
local segments = {}
|
||||
for segment in path:gmatch("[^/]+") do
|
||||
segments[#segments+1] = segment
|
||||
end
|
||||
return segments
|
||||
end
|
||||
function fs.resolve(path)
|
||||
local segments, rpath = fs.segments(path), "/"
|
||||
for i = 2, #segments do
|
||||
rpath = rpath .. segments[i] .. "/"
|
||||
end
|
||||
rpath = rpath:match("(.+)/") or rpath
|
||||
return segments[1] or "root",rpath
|
||||
end
|
||||
|
||||
-- generate some simple functions
|
||||
for k,v in pairs({"makeDirectory","exists","isDirectory","list","lastModified","remove","size","spaceUsed","isReadOnly","getLabel"}) do
|
||||
fs[v] = function(path)
|
||||
local fsi,path = fs.resolve(path)
|
||||
return fs.mounts[fsi][v](path)
|
||||
end
|
||||
end
|
||||
|
||||
local function fread(self,length)
|
||||
if length == "*a" then
|
||||
length = math.huge
|
||||
end
|
||||
local rstr, lstr = "", ""
|
||||
repeat
|
||||
lstr = fs.mounts[self.fs].read(self.fid,math.min(2^16,length-rstr:len())) or ""
|
||||
rstr = rstr .. lstr
|
||||
until rstr:len() == length or lstr == ""
|
||||
return rstr
|
||||
end
|
||||
local function fwrite(self,data)
|
||||
fs.mounts[self.fs].write(self.fid,data)
|
||||
end
|
||||
local function fclose(self)
|
||||
fs.mounts[self.fs].close(self.fid)
|
||||
end
|
||||
|
||||
function fs.open(path,mode)
|
||||
mode = mode or "rb"
|
||||
local fsi,path = fs.resolve(path)
|
||||
if not fs.mounts[fsi] then return false end
|
||||
local fid = fs.mounts[fsi].open(path,mode)
|
||||
if fid then
|
||||
local fobj = {["fs"]=fsi,["fid"]=fid,["close"]=fclose}
|
||||
if mode:sub(1,1) == "r" then
|
||||
fobj.read = fread
|
||||
else
|
||||
fobj.write = fwrite
|
||||
end
|
||||
return fobj
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function fs.copy(from,to)
|
||||
local of = fs.open(from,"rb")
|
||||
local df = fs.open(to,"wb")
|
||||
if not of or not df then
|
||||
return false
|
||||
end
|
||||
df:write(of:read("*a"))
|
||||
df:close()
|
||||
of:close()
|
||||
end
|
||||
|
||||
function fs.rename(from,to)
|
||||
local ofsi, opath = fs.resolve(from)
|
||||
local dfsi, dpath = fs.resolve(to)
|
||||
if ofsi == dfsi then
|
||||
fs.mounts[ofsi].rename(opath,dpath)
|
||||
return true
|
||||
end
|
||||
fs.copy(from,to)
|
||||
fs.remove(from)
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
fs.mounts.temp = component.proxy(computer.tmpAddress())
|
||||
if computer.getBootAddress then
|
||||
fs.mounts.boot = component.proxy(computer.getBootAddress())
|
||||
end
|
||||
for addr, _ in component.list("filesystem") do
|
||||
fs.mounts[addr:sub(1,3)] = component.proxy(addr)
|
||||
end
|
||||
|
||||
local function rf()
|
||||
return false
|
||||
end
|
||||
fs.mounts.root = {}
|
||||
|
||||
for k,v in pairs(fs.mounts.temp) do
|
||||
fs.mounts.root[k] = rf
|
||||
end
|
||||
function fs.mounts.root.list()
|
||||
local t = {}
|
||||
for k,v in pairs(fs.mounts) do
|
||||
t[#t+1] = k
|
||||
end
|
||||
t.n = #t
|
||||
return t
|
||||
end
|
||||
function fs.mounts.root.isReadOnly()
|
||||
return true
|
||||
end
|
||||
function loadfile(p)
|
||||
local f = fs.open(p,"rb")
|
||||
local c = f:read("*a")
|
||||
f:close()
|
||||
return load(c,p,"t")
|
||||
end
|
||||
function runfile(p,...)
|
||||
loadfile(p)(...)
|
||||
end
|
||||
function spawnfile(p,n)
|
||||
os.spawn(loadfile(p),n)
|
||||
end
|
||||
function vtemu(gpua,scra)
|
||||
local gpu,scr = component.proxy(gpua),component.proxy(scra)
|
||||
gpu.bind(scra)
|
||||
local write = vt100emu(gpu)
|
||||
local kba = {}
|
||||
for k,v in ipairs(scr.getKeyboards()) do
|
||||
kba[v]=true
|
||||
end
|
||||
local buf = ""
|
||||
os.spawn(function()
|
||||
while true do
|
||||
local ty,ka,ch = coroutine.yield()
|
||||
if ty == "key_down" and kba[ka] then
|
||||
if ch == 13 then ch = 10 end
|
||||
if ch == 8 and buf:len() > 0 then
|
||||
write("\8 \8")
|
||||
buf = buf:sub(1,-2)
|
||||
elseif ch > 0 then
|
||||
write(string.char(ch))
|
||||
buf = buf .. string.char(ch)
|
||||
end
|
||||
end
|
||||
end
|
||||
end,"keyboard daemon for "..gpua:sub(1,8)..":"..scra:sub(1,8))
|
||||
local function read(n)
|
||||
n = n or "\n"
|
||||
local rdata = ""
|
||||
if type(n) == "number" then
|
||||
rdata = buf:sub(1,n)
|
||||
return rdata
|
||||
else
|
||||
if n == "*a" then
|
||||
rdata = buf
|
||||
buf = ""
|
||||
return rdata
|
||||
end
|
||||
local pr,po = buf:match("(.-)"..n.."(.*)")
|
||||
buf = po or buf
|
||||
return pr
|
||||
end
|
||||
end
|
||||
return read,write
|
||||
end
|
||||
_G.fd,_G.io = {},{}
|
||||
do
|
||||
function io.write(d)
|
||||
fd[tTasks[cPid].t or 1].w(d)
|
||||
end
|
||||
function io.read(d,b)
|
||||
local r = ""
|
||||
repeat
|
||||
r=fd[tTasks[cPid].t or 1].r(d)
|
||||
coroutine.yield()
|
||||
until r or b
|
||||
return r
|
||||
end
|
||||
function print(...)
|
||||
for k,v in pairs({...}) do
|
||||
io.write(tostring(v).."\n")
|
||||
end
|
||||
end
|
||||
|
||||
local ts = {}
|
||||
for a,_ in component.list("screen") do
|
||||
ts[#ts+1] = a
|
||||
end
|
||||
for a,_ in component.list("gpu") do
|
||||
local r,w = vtemu(a,table.remove(ts,1))
|
||||
fd[#fd+1] = {["r"]=r,["w"]=w,["t"]="t"}
|
||||
end
|
||||
end
|
||||
_G.net={}
|
||||
|
||||
do
|
||||
local modems,packetQueue,packetCache,routeCache,C,Y = {},{},{},{},COMPUTER,UNPACK
|
||||
net.port,net.hostname,net.route,net.hook,U=4096,computer.address():sub(1,8),true,{},UPTIME
|
||||
|
||||
for a in component.list("modem") do
|
||||
modems[a] = component.proxy(a)
|
||||
modems[a].open(net.port)
|
||||
end
|
||||
|
||||
local function genPacketID()
|
||||
local packetID = ""
|
||||
for i = 1, 16 do
|
||||
packetID = packetID .. string.char(math.random(32,126))
|
||||
end
|
||||
return packetID
|
||||
end
|
||||
|
||||
local function rawSendPacket(packetID,packetType,to,from,vport,data)
|
||||
if routeCache[to] then
|
||||
modems[routeCache[to][1]].send(routeCache[to][2],net.port,packetID,packetType,to,from,vport,data)
|
||||
else
|
||||
for k,v in pairs(modems) do
|
||||
v.broadcast(net.port,packetID,packetType,to,from,vport,data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function sendPacket(packetID,packetType,to,vport,data)
|
||||
packetCache[packetID] = computer.uptime()
|
||||
rawSendPacket(packetID,packetType,to,net.hostname,vport,data)
|
||||
end
|
||||
|
||||
function net.send(to,vport,data,packetType,packetID)
|
||||
packetType,packetID = packetType or 1, packetID or genPacketID()
|
||||
packetQueue[packetID] = {packetType,to,vport,data,0}
|
||||
sendPacket(packetID,packetType,to,vport,data)
|
||||
end
|
||||
|
||||
local function checkCache(packetID)
|
||||
for k,v in pairs(packetCache) do
|
||||
if k == packetID then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
os.spawn(function()
|
||||
while true do
|
||||
local eventTab = {coroutine.yield()}
|
||||
if eventTab[1] == "modem_message" and (eventTab[4] == net.port or eventTab[4] == 0) and checkCache(eventTab[6]) then
|
||||
for k,v in pairs(packetCache) do
|
||||
if computer.uptime() > v+30 then
|
||||
packetCache[k] = nil
|
||||
end
|
||||
end
|
||||
for k,v in pairs(routeCache) do
|
||||
if computer.uptime() > v[3]+30 then
|
||||
routeCache[k] = nil
|
||||
end
|
||||
end
|
||||
routeCache[eventTab[9]] = {eventTab[2],eventTab[3],computer.uptime()}
|
||||
if eventTab[8] == net.hostname then
|
||||
if eventTab[7] ~= 2 then
|
||||
computer.pushSignal("net_msg",eventTab[9],eventTab[10],eventTab[11])
|
||||
if eventTab[7] == 1 then
|
||||
sendPacket(genPacketID(),2,eventTab[9],eventTab[10],eventTab[6])
|
||||
end
|
||||
else
|
||||
packetQueue[eventTab[11]] = nil
|
||||
end
|
||||
elseif net.route and checkCache(eventTab[6]) then
|
||||
rawSendPacket(eventTab[6],eventTab[7],eventTab[8],eventTab[9],eventTab[10],eventTab[11])
|
||||
end
|
||||
packetCache[eventTab[6]] = computer.uptime()
|
||||
end
|
||||
for k,v in pairs(packetQueue) do
|
||||
if computer.uptime() > v[5] then
|
||||
sendPacket(k,table.unpack(v))
|
||||
v[5]=computer.uptime()+30
|
||||
end
|
||||
end
|
||||
end
|
||||
end,"minitel.3")
|
||||
|
||||
end
|
||||
os.spawn(function() print(pcall(function()
|
||||
print(_OSVERSION,tostring(computer.totalMemory()/1024).."K memory")
|
||||
local f = fs.open("/boot/init.txt","rb")
|
||||
local fc = f:read("*a")
|
||||
f:close()
|
||||
for line in fc:gmatch("[^\n]+") do
|
||||
print(line)
|
||||
end
|
||||
for k,v in pairs(fd) do
|
||||
if v.t == "t" then
|
||||
tTasks[cPid].t = k
|
||||
print("Spawning a shell for terminal #"..tostring(k))
|
||||
spawnfile("/boot/exec/shell.lua","shell #"..tostring(k))
|
||||
end
|
||||
end
|
||||
end)) end,"init")
|
||||
_OSVERSION="PsychOS 2.0a0"
|
||||
sched()
|
2
exec/free.lua
Normal file
2
exec/free.lua
Normal file
@ -0,0 +1,2 @@
|
||||
print("Total Used Free")
|
||||
print(string.format("%4dK %4dK %4dK",computer.totalMemory()/1024,math.floor((computer.totalMemory()-computer.freeMemory())/1024),math.floor(computer.freeMemory()/1024)))
|
4
exec/ps.lua
Normal file
4
exec/ps.lua
Normal file
@ -0,0 +1,4 @@
|
||||
print("PID# VTY# Name")
|
||||
for k,v in pairs(tTasks) do
|
||||
print(string.format("%4d %4d %s",k,v.t or 1,v.n))
|
||||
end
|
9
exec/shell.lua
Normal file
9
exec/shell.lua
Normal file
@ -0,0 +1,9 @@
|
||||
local shenv = {}
|
||||
setmetatable(shenv,{__index=function(_,k) if _G[k] then return _G[k] elseif fs.exists("/boot/exec/"..k..".lua") then return loadfile("/boot/exec/"..k..".lua") end end})
|
||||
while true do
|
||||
io.write(_VERSION.."> ")
|
||||
tResult = {pcall(load(io.read(),"shell","t",shenv))}
|
||||
for k,v in pairs(tResult) do
|
||||
print(v)
|
||||
end
|
||||
end
|
8
mkmods.sh
Executable file
8
mkmods.sh
Executable file
@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
for f in service/*; do
|
||||
nf=$(echo $f | cut -d '/' -f 2)
|
||||
echo $nf
|
||||
echo os.spawn\(function\(\) >mod-service/$nf
|
||||
cat $f >> mod-service/$nf
|
||||
echo end,\"$nf\"\) >> mod-service/$nf
|
||||
done
|
88
mod-service/microtel-3.lua
Normal file
88
mod-service/microtel-3.lua
Normal file
@ -0,0 +1,88 @@
|
||||
os.spawn(function()
|
||||
_G.net={}
|
||||
|
||||
do
|
||||
local modems,packetQueue,packetCache,routeCache,C,Y = {},{},{},{},COMPUTER,UNPACK
|
||||
net.port,net.hostname,net.route,net.hook,U=4096,computer.address():sub(1,8),true,{},UPTIME
|
||||
|
||||
for a in component.list("modem") do
|
||||
modems[a] = component.proxy(a)
|
||||
modems[a].open(net.port)
|
||||
end
|
||||
|
||||
local function genPacketID()
|
||||
local packetID = ""
|
||||
for i = 1, 16 do
|
||||
packetID = packetID .. string.char(math.random(32,126))
|
||||
end
|
||||
return packetID
|
||||
end
|
||||
|
||||
local function rawSendPacket(packetID,packetType,to,from,vport,data)
|
||||
if routeCache[to] then
|
||||
modems[routeCache[to][1]].send(routeCache[to][2],net.port,packetID,packetType,to,from,vport,data)
|
||||
else
|
||||
for k,v in pairs(modems) do
|
||||
v.broadcast(net.port,packetID,packetType,to,from,vport,data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function sendPacket(packetID,packetType,to,vport,data)
|
||||
packetCache[packetID] = computer.uptime()
|
||||
rawSendPacket(packetID,packetType,to,net.hostname,vport,data)
|
||||
end
|
||||
|
||||
function net.send(to,vport,data,packetType,packetID)
|
||||
packetType,packetID = packetType or 1, packetID or genPacketID()
|
||||
packetQueue[packetID] = {packetType,to,vport,data,0}
|
||||
sendPacket(packetID,packetType,to,vport,data)
|
||||
end
|
||||
|
||||
local function checkCache(packetID)
|
||||
for k,v in pairs(packetCache) do
|
||||
if k == packetID then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
while true do
|
||||
local eventTab = {coroutine.yield()}
|
||||
if eventTab[1] == "modem_message" and (eventTab[4] == net.port or eventTab[4] == 0) and checkCache(eventTab[6]) then
|
||||
for k,v in pairs(packetCache) do
|
||||
if computer.uptime() > v+30 then
|
||||
packetCache[k] = nil
|
||||
end
|
||||
end
|
||||
for k,v in pairs(routeCache) do
|
||||
if computer.uptime() > v[3]+30 then
|
||||
routeCache[k] = nil
|
||||
end
|
||||
end
|
||||
routeCache[eventTab[9]] = {eventTab[2],eventTab[3],computer.uptime()}
|
||||
if eventTab[8] == net.hostname then
|
||||
if eventTab[7] ~= 2 then
|
||||
computer.pushSignal("net_msg",eventTab[9],eventTab[10],eventTab[11])
|
||||
if eventTab[7] == 1 then
|
||||
sendPacket(genPacketID(),2,eventTab[9],eventTab[10],eventTab[6])
|
||||
end
|
||||
else
|
||||
packetQueue[eventTab[11]] = nil
|
||||
end
|
||||
elseif net.route and checkCache(eventTab[6]) then
|
||||
rawSendPacket(eventTab[6],eventTab[7],eventTab[8],eventTab[9],eventTab[10],eventTab[11])
|
||||
end
|
||||
packetCache[eventTab[6]] = computer.uptime()
|
||||
end
|
||||
for k,v in pairs(packetQueue) do
|
||||
if computer.uptime() > v[5] then
|
||||
sendPacket(k,table.unpack(v))
|
||||
v[5]=computer.uptime()+30
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end,"microtel-3.lua")
|
114
module/fs.lua
Normal file
114
module/fs.lua
Normal file
@ -0,0 +1,114 @@
|
||||
fs = {}
|
||||
fs.mounts = {}
|
||||
|
||||
-- basics
|
||||
function fs.segments(path)
|
||||
local segments = {}
|
||||
for segment in path:gmatch("[^/]+") do
|
||||
segments[#segments+1] = segment
|
||||
end
|
||||
return segments
|
||||
end
|
||||
function fs.resolve(path)
|
||||
local segments, rpath = fs.segments(path), "/"
|
||||
for i = 2, #segments do
|
||||
rpath = rpath .. segments[i] .. "/"
|
||||
end
|
||||
rpath = rpath:match("(.+)/") or rpath
|
||||
return segments[1] or "root",rpath
|
||||
end
|
||||
|
||||
-- generate some simple functions
|
||||
for k,v in pairs({"makeDirectory","exists","isDirectory","list","lastModified","remove","size","spaceUsed","isReadOnly","getLabel"}) do
|
||||
fs[v] = function(path)
|
||||
local fsi,path = fs.resolve(path)
|
||||
return fs.mounts[fsi][v](path)
|
||||
end
|
||||
end
|
||||
|
||||
local function fread(self,length)
|
||||
if length == "*a" then
|
||||
length = math.huge
|
||||
end
|
||||
local rstr, lstr = "", ""
|
||||
repeat
|
||||
lstr = fs.mounts[self.fs].read(self.fid,math.min(2^16,length-rstr:len())) or ""
|
||||
rstr = rstr .. lstr
|
||||
until rstr:len() == length or lstr == ""
|
||||
return rstr
|
||||
end
|
||||
local function fwrite(self,data)
|
||||
fs.mounts[self.fs].write(self.fid,data)
|
||||
end
|
||||
local function fclose(self)
|
||||
fs.mounts[self.fs].close(self.fid)
|
||||
end
|
||||
|
||||
function fs.open(path,mode)
|
||||
mode = mode or "rb"
|
||||
local fsi,path = fs.resolve(path)
|
||||
if not fs.mounts[fsi] then return false end
|
||||
local fid = fs.mounts[fsi].open(path,mode)
|
||||
if fid then
|
||||
local fobj = {["fs"]=fsi,["fid"]=fid,["close"]=fclose}
|
||||
if mode:sub(1,1) == "r" then
|
||||
fobj.read = fread
|
||||
else
|
||||
fobj.write = fwrite
|
||||
end
|
||||
return fobj
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function fs.copy(from,to)
|
||||
local of = fs.open(from,"rb")
|
||||
local df = fs.open(to,"wb")
|
||||
if not of or not df then
|
||||
return false
|
||||
end
|
||||
df:write(of:read("*a"))
|
||||
df:close()
|
||||
of:close()
|
||||
end
|
||||
|
||||
function fs.rename(from,to)
|
||||
local ofsi, opath = fs.resolve(from)
|
||||
local dfsi, dpath = fs.resolve(to)
|
||||
if ofsi == dfsi then
|
||||
fs.mounts[ofsi].rename(opath,dpath)
|
||||
return true
|
||||
end
|
||||
fs.copy(from,to)
|
||||
fs.remove(from)
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
fs.mounts.temp = component.proxy(computer.tmpAddress())
|
||||
if computer.getBootAddress then
|
||||
fs.mounts.boot = component.proxy(computer.getBootAddress())
|
||||
end
|
||||
for addr, _ in component.list("filesystem") do
|
||||
fs.mounts[addr:sub(1,3)] = component.proxy(addr)
|
||||
end
|
||||
|
||||
local function rf()
|
||||
return false
|
||||
end
|
||||
fs.mounts.root = {}
|
||||
|
||||
for k,v in pairs(fs.mounts.temp) do
|
||||
fs.mounts.root[k] = rf
|
||||
end
|
||||
function fs.mounts.root.list()
|
||||
local t = {}
|
||||
for k,v in pairs(fs.mounts) do
|
||||
t[#t+1] = k
|
||||
end
|
||||
t.n = #t
|
||||
return t
|
||||
end
|
||||
function fs.mounts.root.isReadOnly()
|
||||
return true
|
||||
end
|
17
module/init.lua
Normal file
17
module/init.lua
Normal file
@ -0,0 +1,17 @@
|
||||
os.spawn(function() print(pcall(function()
|
||||
print(_OSVERSION,tostring(math.floor(computer.totalMemory()/1024)).."K memory")
|
||||
local f = fs.open("/boot/init.txt","rb")
|
||||
local fc = f:read("*a")
|
||||
f:close()
|
||||
for line in fc:gmatch("[^\n]+") do
|
||||
print("Starting service "..line)
|
||||
spawnfile("/boot/service/"..line)
|
||||
end
|
||||
for k,v in pairs(fd) do
|
||||
if v.t == "t" then
|
||||
tTasks[cPid].t = k
|
||||
print("Spawning a shell for terminal #"..tostring(k))
|
||||
spawnfile("/boot/exec/shell.lua","shell #"..tostring(k))
|
||||
end
|
||||
end
|
||||
end)) end,"init")
|
28
module/io.lua
Normal file
28
module/io.lua
Normal file
@ -0,0 +1,28 @@
|
||||
_G.fd,_G.io = {},{}
|
||||
do
|
||||
function io.write(d)
|
||||
fd[tTasks[cPid].t or 1].w(d)
|
||||
end
|
||||
function io.read(d,b)
|
||||
local r = ""
|
||||
repeat
|
||||
r=fd[tTasks[cPid].t or 1].r(d)
|
||||
coroutine.yield()
|
||||
until r or b
|
||||
return r
|
||||
end
|
||||
function print(...)
|
||||
for k,v in pairs({...}) do
|
||||
io.write(tostring(v).."\n")
|
||||
end
|
||||
end
|
||||
|
||||
local ts = {}
|
||||
for a,_ in component.list("screen") do
|
||||
ts[#ts+1] = a
|
||||
end
|
||||
for a,_ in component.list("gpu") do
|
||||
local r,w = vtemu(a,table.remove(ts,1))
|
||||
fd[#fd+1] = {["r"]=r,["w"]=w,["t"]="t"}
|
||||
end
|
||||
end
|
12
module/loadfile.lua
Normal file
12
module/loadfile.lua
Normal file
@ -0,0 +1,12 @@
|
||||
function loadfile(p)
|
||||
local f = fs.open(p,"rb")
|
||||
local c = f:read("*a")
|
||||
f:close()
|
||||
return load(c,p,"t")
|
||||
end
|
||||
function runfile(p,...)
|
||||
loadfile(p)(...)
|
||||
end
|
||||
function spawnfile(p,n)
|
||||
os.spawn(loadfile(p),n)
|
||||
end
|
88
module/microtel-3.lua
Normal file
88
module/microtel-3.lua
Normal file
@ -0,0 +1,88 @@
|
||||
_G.net={}
|
||||
|
||||
do
|
||||
local modems,packetQueue,packetCache,routeCache,C,Y = {},{},{},{},COMPUTER,UNPACK
|
||||
net.port,net.hostname,net.route,net.hook,U=4096,computer.address():sub(1,8),true,{},UPTIME
|
||||
|
||||
for a in component.list("modem") do
|
||||
modems[a] = component.proxy(a)
|
||||
modems[a].open(net.port)
|
||||
end
|
||||
|
||||
local function genPacketID()
|
||||
local packetID = ""
|
||||
for i = 1, 16 do
|
||||
packetID = packetID .. string.char(math.random(32,126))
|
||||
end
|
||||
return packetID
|
||||
end
|
||||
|
||||
local function rawSendPacket(packetID,packetType,to,from,vport,data)
|
||||
if routeCache[to] then
|
||||
modems[routeCache[to][1]].send(routeCache[to][2],net.port,packetID,packetType,to,from,vport,data)
|
||||
else
|
||||
for k,v in pairs(modems) do
|
||||
v.broadcast(net.port,packetID,packetType,to,from,vport,data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function sendPacket(packetID,packetType,to,vport,data)
|
||||
packetCache[packetID] = computer.uptime()
|
||||
rawSendPacket(packetID,packetType,to,net.hostname,vport,data)
|
||||
end
|
||||
|
||||
function net.send(to,vport,data,packetType,packetID)
|
||||
packetType,packetID = packetType or 1, packetID or genPacketID()
|
||||
packetQueue[packetID] = {packetType,to,vport,data,0}
|
||||
sendPacket(packetID,packetType,to,vport,data)
|
||||
end
|
||||
|
||||
local function checkCache(packetID)
|
||||
for k,v in pairs(packetCache) do
|
||||
if k == packetID then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
os.spawn(function()
|
||||
while true do
|
||||
local eventTab = {coroutine.yield()}
|
||||
if eventTab[1] == "modem_message" and (eventTab[4] == net.port or eventTab[4] == 0) and checkCache(eventTab[6]) then
|
||||
for k,v in pairs(packetCache) do
|
||||
if computer.uptime() > v+30 then
|
||||
packetCache[k] = nil
|
||||
end
|
||||
end
|
||||
for k,v in pairs(routeCache) do
|
||||
if computer.uptime() > v[3]+30 then
|
||||
routeCache[k] = nil
|
||||
end
|
||||
end
|
||||
routeCache[eventTab[9]] = {eventTab[2],eventTab[3],computer.uptime()}
|
||||
if eventTab[8] == net.hostname then
|
||||
if eventTab[7] ~= 2 then
|
||||
computer.pushSignal("net_msg",eventTab[9],eventTab[10],eventTab[11])
|
||||
if eventTab[7] == 1 then
|
||||
sendPacket(genPacketID(),2,eventTab[9],eventTab[10],eventTab[6])
|
||||
end
|
||||
else
|
||||
packetQueue[eventTab[11]] = nil
|
||||
end
|
||||
elseif net.route and checkCache(eventTab[6]) then
|
||||
rawSendPacket(eventTab[6],eventTab[7],eventTab[8],eventTab[9],eventTab[10],eventTab[11])
|
||||
end
|
||||
packetCache[eventTab[6]] = computer.uptime()
|
||||
end
|
||||
for k,v in pairs(packetQueue) do
|
||||
if computer.uptime() > v[5] then
|
||||
sendPacket(k,table.unpack(v))
|
||||
v[5]=computer.uptime()+30
|
||||
end
|
||||
end
|
||||
end
|
||||
end,"minitel.3")
|
||||
|
||||
end
|
22
module/sched.lua
Normal file
22
module/sched.lua
Normal file
@ -0,0 +1,22 @@
|
||||
tTasks,nPid,nTimeout,cPid = {},1,1,0
|
||||
function os.spawn(f,n)
|
||||
tTasks[nPid] = {["c"]=coroutine.create(f),["n"]=n,["p"]=nPid}
|
||||
for k,v in pairs(tTasks[cPid] or {}) do
|
||||
tTasks[nPid][k] = tTasks[nPid][k] or v
|
||||
end
|
||||
nPid = nPid + 1
|
||||
return nPid - 1
|
||||
end
|
||||
function sched()
|
||||
while #tTasks > 0 do
|
||||
local tEv = {computer.pullSignal(nTimeout)}
|
||||
for k,v in pairs(tTasks) do
|
||||
if coroutine.status(v.c) ~= "dead" then
|
||||
cPid = k
|
||||
coroutine.resume(v.c,table.unpack(tEv))
|
||||
else
|
||||
tTasks[k] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
15
module/spawnprompt.lua
Normal file
15
module/spawnprompt.lua
Normal file
@ -0,0 +1,15 @@
|
||||
os.spawn(function()
|
||||
print(_OSVERSION,tostring(computer.totalMemory()/1024).."K memory")
|
||||
for k,v in pairs(fd) do
|
||||
if v.t == "t" then
|
||||
tTasks[cPid].t = k
|
||||
print("Spawning Lua prompt for "..tostring(k))
|
||||
os.spawn(function() print(pcall(function() while true do
|
||||
io.write(_VERSION.."> ")
|
||||
tResult = {pcall(load(io.read()))}
|
||||
for k,v in pairs(tResult) do
|
||||
print(v)
|
||||
end
|
||||
end end)) end,"lua prompt")
|
||||
end
|
||||
end end,"init")
|
43
module/vt-task.lua
Normal file
43
module/vt-task.lua
Normal file
@ -0,0 +1,43 @@
|
||||
function vtemu(gpua,scra)
|
||||
local gpu,scr = component.proxy(gpua),component.proxy(scra)
|
||||
gpu.bind(scra)
|
||||
local write = vt100emu(gpu)
|
||||
local kba = {}
|
||||
for k,v in ipairs(scr.getKeyboards()) do
|
||||
kba[v]=true
|
||||
end
|
||||
local buf = ""
|
||||
os.spawn(function()
|
||||
while true do
|
||||
local ty,ka,ch = coroutine.yield()
|
||||
if ty == "key_down" and kba[ka] then
|
||||
if ch == 13 then ch = 10 end
|
||||
if ch == 8 and buf:len() > 0 then
|
||||
write("\8 \8")
|
||||
buf = buf:sub(1,-2)
|
||||
elseif ch > 0 then
|
||||
write(string.char(ch))
|
||||
buf = buf .. string.char(ch)
|
||||
end
|
||||
end
|
||||
end
|
||||
end,"keyboard daemon for "..gpua:sub(1,8)..":"..scra:sub(1,8))
|
||||
local function read(n)
|
||||
n = n or "\n"
|
||||
local rdata = ""
|
||||
if type(n) == "number" then
|
||||
rdata = buf:sub(1,n)
|
||||
return rdata
|
||||
else
|
||||
if n == "*a" then
|
||||
rdata = buf
|
||||
buf = ""
|
||||
return rdata
|
||||
end
|
||||
local pr,po = buf:match("(.-)"..n.."(.*)")
|
||||
buf = po or buf
|
||||
return pr
|
||||
end
|
||||
end
|
||||
return read,write
|
||||
end
|
107
module/vt100.lua
Normal file
107
module/vt100.lua
Normal file
@ -0,0 +1,107 @@
|
||||
function vt100emu(gpu)
|
||||
local mx, my = gpu.maxResolution()
|
||||
local cx, cy = 1, 1
|
||||
local pc = " "
|
||||
local lc = ""
|
||||
local mode = "n"
|
||||
local lw = true
|
||||
local sx, sy = 1,1
|
||||
local cs = ""
|
||||
|
||||
-- setup
|
||||
gpu.setResolution(mx,my)
|
||||
gpu.fill(1,1,mx,my," ")
|
||||
|
||||
function termwrite(s)
|
||||
s=s:gsub("\8","\27[D")
|
||||
pc = gpu.get(cx,cy)
|
||||
gpu.setForeground(0xFFFFFF)
|
||||
gpu.setBackground(0)
|
||||
gpu.set(cx,cy,pc)
|
||||
for i = 1, s:len() do
|
||||
local cc = s:sub(i,i)
|
||||
|
||||
if mode == "n" then
|
||||
if cc == "\n" then -- line feed
|
||||
cx, cy = 1, cy+1
|
||||
elseif cc == "\r" then -- cursor home
|
||||
cx = 1
|
||||
elseif cc == "\27" then -- escape
|
||||
mode = "e"
|
||||
elseif string.byte(cc) > 31 and string.byte(cc) < 127 then -- printable, I guess
|
||||
gpu.set(cx, cy, cc)
|
||||
cx = cx + 1
|
||||
end
|
||||
|
||||
elseif mode == "e" then
|
||||
if cc == "[" then
|
||||
mode = "v"
|
||||
cs = ""
|
||||
elseif cc == "D" then -- scroll down
|
||||
gpu.copy(1,2,mx,my-1,0,-1)
|
||||
gpu.fill(1,my,mx,1," ")
|
||||
cy=cy+1
|
||||
mode = "n"
|
||||
elseif cc == "M" then -- scroll up
|
||||
gpu.copy(1,1,mx,my-1,0,1)
|
||||
gpu.fill(1,1,mx,1," ")
|
||||
mode = "n"
|
||||
end
|
||||
|
||||
elseif mode == "v" then -- save cursor
|
||||
local n = cs:sub(cs:len(),cs:len())
|
||||
if n == "" then n = "\1" end
|
||||
if cc == "s" then
|
||||
sx, sy = cx, cy
|
||||
mode = "n"
|
||||
elseif cc == "u" then -- restore cursor
|
||||
cx, cy = sx, sy
|
||||
mode = "n"
|
||||
elseif cc == "H" then -- cursor home or to
|
||||
local tx, ty = cs:match("(.);(.)")
|
||||
tx, ty = tx or "\1", ty or "\1"
|
||||
cx, cy = string.byte(tx), string.byte(ty)
|
||||
mode = "n"
|
||||
elseif cc == "A" then -- cursor up
|
||||
cy = cy - string.byte(n)
|
||||
mode = "n"
|
||||
elseif cc == "B" then -- cursor down
|
||||
cy = cy + string.byte(n)
|
||||
mode = "n"
|
||||
elseif cc == "C" then -- cursor right
|
||||
cx = cx + string.byte(n)
|
||||
mode = "n"
|
||||
elseif cc == "D" then -- cursor left
|
||||
cx = cx - string.byte(n)
|
||||
mode = "n"
|
||||
elseif cc == "h" and lc == "7" then -- enable line wrap
|
||||
lw = true
|
||||
elseif cc == "l" and lc == "7" then -- disable line wrap
|
||||
lw = false
|
||||
end
|
||||
cs = cs .. cc
|
||||
end
|
||||
|
||||
if cx > mx and lw then
|
||||
cx, cy = 1, cy+1
|
||||
end
|
||||
if cy > my then
|
||||
gpu.copy(1,2,mx,my-1,0,-1)
|
||||
gpu.fill(1,my,mx,1," ")
|
||||
cy=my
|
||||
end
|
||||
if cy < 1 then cy = 1 end
|
||||
if cx < 1 then cx = 1 end
|
||||
|
||||
lc = cc
|
||||
end
|
||||
pc = gpu.get(cx,cy)
|
||||
gpu.setForeground(0)
|
||||
gpu.setBackground(0xFFFFFF)
|
||||
gpu.set(cx,cy,pc)
|
||||
gpu.setForeground(0xFFFFFF)
|
||||
gpu.setBackground(0)
|
||||
end
|
||||
|
||||
return termwrite
|
||||
end
|
86
service/microtel-3.lua
Normal file
86
service/microtel-3.lua
Normal file
@ -0,0 +1,86 @@
|
||||
_G.net={}
|
||||
|
||||
do
|
||||
local modems,packetQueue,packetCache,routeCache,C,Y = {},{},{},{},COMPUTER,UNPACK
|
||||
net.port,net.hostname,net.route,net.hook,U=4096,computer.address():sub(1,8),true,{},UPTIME
|
||||
|
||||
for a in component.list("modem") do
|
||||
modems[a] = component.proxy(a)
|
||||
modems[a].open(net.port)
|
||||
end
|
||||
|
||||
local function genPacketID()
|
||||
local packetID = ""
|
||||
for i = 1, 16 do
|
||||
packetID = packetID .. string.char(math.random(32,126))
|
||||
end
|
||||
return packetID
|
||||
end
|
||||
|
||||
local function rawSendPacket(packetID,packetType,to,from,vport,data)
|
||||
if routeCache[to] then
|
||||
modems[routeCache[to][1]].send(routeCache[to][2],net.port,packetID,packetType,to,from,vport,data)
|
||||
else
|
||||
for k,v in pairs(modems) do
|
||||
v.broadcast(net.port,packetID,packetType,to,from,vport,data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function sendPacket(packetID,packetType,to,vport,data)
|
||||
packetCache[packetID] = computer.uptime()
|
||||
rawSendPacket(packetID,packetType,to,net.hostname,vport,data)
|
||||
end
|
||||
|
||||
function net.send(to,vport,data,packetType,packetID)
|
||||
packetType,packetID = packetType or 1, packetID or genPacketID()
|
||||
packetQueue[packetID] = {packetType,to,vport,data,0}
|
||||
sendPacket(packetID,packetType,to,vport,data)
|
||||
end
|
||||
|
||||
local function checkCache(packetID)
|
||||
for k,v in pairs(packetCache) do
|
||||
if k == packetID then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
while true do
|
||||
local eventTab = {coroutine.yield()}
|
||||
if eventTab[1] == "modem_message" and (eventTab[4] == net.port or eventTab[4] == 0) and checkCache(eventTab[6]) then
|
||||
for k,v in pairs(packetCache) do
|
||||
if computer.uptime() > v+30 then
|
||||
packetCache[k] = nil
|
||||
end
|
||||
end
|
||||
for k,v in pairs(routeCache) do
|
||||
if computer.uptime() > v[3]+30 then
|
||||
routeCache[k] = nil
|
||||
end
|
||||
end
|
||||
routeCache[eventTab[9]] = {eventTab[2],eventTab[3],computer.uptime()}
|
||||
if eventTab[8] == net.hostname then
|
||||
if eventTab[7] ~= 2 then
|
||||
computer.pushSignal("net_msg",eventTab[9],eventTab[10],eventTab[11])
|
||||
if eventTab[7] == 1 then
|
||||
sendPacket(genPacketID(),2,eventTab[9],eventTab[10],eventTab[6])
|
||||
end
|
||||
else
|
||||
packetQueue[eventTab[11]] = nil
|
||||
end
|
||||
elseif net.route and checkCache(eventTab[6]) then
|
||||
rawSendPacket(eventTab[6],eventTab[7],eventTab[8],eventTab[9],eventTab[10],eventTab[11])
|
||||
end
|
||||
packetCache[eventTab[6]] = computer.uptime()
|
||||
end
|
||||
for k,v in pairs(packetQueue) do
|
||||
if computer.uptime() > v[5] then
|
||||
sendPacket(k,table.unpack(v))
|
||||
v[5]=computer.uptime()+30
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue
Block a user