|
- 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()
|