|
|
@@ -1,432 +0,0 @@ |
|
|
|
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 = {} |
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
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() |