Browse Source

fuck knows

Izaya 1 month ago
parent
commit
2f48091a07
17 changed files with 1082 additions and 0 deletions
  1. 7
    0
      build.sh
  2. 432
    0
      build/psychos.lua
  3. 2
    0
      exec/free.lua
  4. 4
    0
      exec/ps.lua
  5. 9
    0
      exec/shell.lua
  6. 8
    0
      mkmods.sh
  7. 88
    0
      mod-service/microtel-3.lua
  8. 114
    0
      module/fs.lua
  9. 17
    0
      module/init.lua
  10. 28
    0
      module/io.lua
  11. 12
    0
      module/loadfile.lua
  12. 88
    0
      module/microtel-3.lua
  13. 22
    0
      module/sched.lua
  14. 15
    0
      module/spawnprompt.lua
  15. 43
    0
      module/vt-task.lua
  16. 107
    0
      module/vt100.lua
  17. 86
    0
      service/microtel-3.lua

+ 7
- 0
build.sh View File

@@ -0,0 +1,7 @@
1
+#!/usr/bin/env bash
2
+mkdir build
3
+cd module
4
+cat sched.lua vt100.lua fs.lua loadfile.lua vt-task.lua io.lua microtel-3.lua init.lua > ../build/psychos.lua
5
+cd ..
6
+echo '_OSVERSION="PsychOS 2.0a0"' >> build/*
7
+echo sched\(\) >> build/*

+ 432
- 0
build/psychos.lua View File

@@ -0,0 +1,432 @@
1
+tTasks,nPid,nTimeout,cPid = {},1,1,0
2
+function os.spawn(f,n)
3
+ tTasks[nPid] = {["c"]=coroutine.create(f),["n"]=n,["p"]=nPid}
4
+ for k,v in pairs(tTasks[cPid] or {}) do
5
+  tTasks[nPid][k] = tTasks[nPid][k] or v
6
+ end
7
+ nPid = nPid + 1
8
+ return nPid - 1
9
+end
10
+function sched()
11
+ while #tTasks > 0 do
12
+  local tEv = {computer.pullSignal(nTimeout)}
13
+  for k,v in pairs(tTasks) do
14
+   if coroutine.status(v.c) ~= "dead" then
15
+    cPid = k
16
+    coroutine.resume(v.c,table.unpack(tEv))
17
+   else
18
+    tTasks[k] = nil
19
+   end
20
+  end
21
+ end
22
+end
23
+function vt100emu(gpu)
24
+ local mx, my = gpu.maxResolution()
25
+ local cx, cy = 1, 1
26
+ local pc = " "
27
+ local lc = ""
28
+ local mode = "n"
29
+ local lw = true
30
+ local sx, sy = 1,1
31
+ local cs = ""
32
+
33
+ -- setup
34
+ gpu.setResolution(mx,my)
35
+ gpu.fill(1,1,mx,my," ")
36
+
37
+ function termwrite(s)
38
+  s=s:gsub("\8","\27[D")
39
+  pc = gpu.get(cx,cy)
40
+  gpu.setForeground(0xFFFFFF)
41
+  gpu.setBackground(0)
42
+  gpu.set(cx,cy,pc)
43
+  for i = 1, s:len() do
44
+   local cc = s:sub(i,i)
45
+
46
+   if mode == "n" then
47
+    if cc == "\n" then -- line feed
48
+     cx, cy = 1, cy+1
49
+    elseif cc == "\r" then -- cursor home
50
+     cx = 1
51
+    elseif cc == "\27" then -- escape
52
+     mode = "e"
53
+    elseif string.byte(cc) > 31 and string.byte(cc) < 127 then -- printable, I guess
54
+     gpu.set(cx, cy, cc)
55
+     cx = cx + 1
56
+    end
57
+
58
+   elseif mode == "e" then
59
+    if cc == "[" then
60
+     mode = "v"
61
+     cs = ""
62
+    elseif cc == "D" then -- scroll down
63
+     gpu.copy(1,2,mx,my-1,0,-1)
64
+     gpu.fill(1,my,mx,1," ")
65
+     cy=cy+1
66
+     mode = "n"
67
+    elseif cc == "M" then -- scroll up
68
+     gpu.copy(1,1,mx,my-1,0,1)
69
+     gpu.fill(1,1,mx,1," ")
70
+     mode = "n"
71
+    end
72
+
73
+   elseif mode == "v" then -- save cursor
74
+    local n = cs:sub(cs:len(),cs:len())
75
+    if n == "" then n = "\1" end
76
+    if cc == "s" then
77
+     sx, sy = cx, cy
78
+     mode = "n"
79
+    elseif cc == "u" then -- restore cursor
80
+     cx, cy = sx, sy
81
+     mode = "n"
82
+    elseif cc == "H" then -- cursor home or to
83
+     local tx, ty = cs:match("(.);(.)")
84
+     tx, ty = tx or "\1", ty or "\1"
85
+     cx, cy = string.byte(tx), string.byte(ty)
86
+     mode = "n"
87
+    elseif cc == "A" then -- cursor up
88
+     cy = cy - string.byte(n)
89
+     mode = "n"
90
+    elseif cc == "B" then -- cursor down
91
+     cy = cy + string.byte(n)
92
+     mode = "n"
93
+    elseif cc == "C" then -- cursor right
94
+     cx = cx + string.byte(n)
95
+     mode = "n"
96
+    elseif cc == "D" then -- cursor left
97
+     cx = cx - string.byte(n)
98
+     mode = "n"
99
+    elseif cc == "h" and lc == "7" then -- enable line wrap
100
+     lw = true
101
+    elseif cc == "l" and lc == "7" then -- disable line wrap
102
+     lw = false
103
+    end
104
+    cs = cs .. cc
105
+   end
106
+
107
+   if cx > mx and lw then
108
+    cx, cy = 1, cy+1
109
+   end
110
+   if cy > my then
111
+    gpu.copy(1,2,mx,my-1,0,-1)
112
+    gpu.fill(1,my,mx,1," ")
113
+    cy=my
114
+   end
115
+   if cy < 1 then cy = 1 end
116
+   if cx < 1 then cx = 1 end
117
+
118
+   lc = cc
119
+  end
120
+  pc = gpu.get(cx,cy)
121
+  gpu.setForeground(0)
122
+  gpu.setBackground(0xFFFFFF)
123
+  gpu.set(cx,cy,pc)
124
+  gpu.setForeground(0xFFFFFF)
125
+  gpu.setBackground(0)
126
+ end
127
+
128
+ return termwrite
129
+end
130
+fs = {}
131
+fs.mounts = {}
132
+
133
+-- basics
134
+function fs.segments(path)
135
+ local segments = {}
136
+ for segment in path:gmatch("[^/]+") do
137
+  segments[#segments+1] = segment
138
+ end
139
+ return segments
140
+end
141
+function fs.resolve(path)
142
+ local segments, rpath = fs.segments(path), "/"
143
+ for i = 2, #segments do
144
+  rpath = rpath .. segments[i] .. "/"
145
+ end
146
+ rpath = rpath:match("(.+)/") or rpath
147
+ return segments[1] or "root",rpath
148
+end
149
+
150
+-- generate some simple functions
151
+for k,v in pairs({"makeDirectory","exists","isDirectory","list","lastModified","remove","size","spaceUsed","isReadOnly","getLabel"}) do
152
+ fs[v] = function(path)
153
+  local fsi,path = fs.resolve(path)
154
+  return fs.mounts[fsi][v](path)
155
+ end
156
+end
157
+
158
+local function fread(self,length)
159
+ if length == "*a" then
160
+  length = math.huge
161
+ end
162
+ local rstr, lstr = "", ""
163
+ repeat
164
+  lstr = fs.mounts[self.fs].read(self.fid,math.min(2^16,length-rstr:len())) or ""
165
+  rstr = rstr .. lstr
166
+ until rstr:len() == length or lstr == ""
167
+ return rstr
168
+end
169
+local function fwrite(self,data)
170
+ fs.mounts[self.fs].write(self.fid,data)
171
+end
172
+local function fclose(self)
173
+ fs.mounts[self.fs].close(self.fid)
174
+end
175
+
176
+function fs.open(path,mode)
177
+ mode = mode or "rb"
178
+ local fsi,path = fs.resolve(path)
179
+ if not fs.mounts[fsi] then return false end
180
+ local fid = fs.mounts[fsi].open(path,mode)
181
+ if fid then
182
+  local fobj = {["fs"]=fsi,["fid"]=fid,["close"]=fclose}
183
+  if mode:sub(1,1) == "r" then
184
+   fobj.read = fread
185
+  else
186
+   fobj.write = fwrite
187
+  end
188
+  return fobj
189
+ end
190
+ return false
191
+end
192
+
193
+function fs.copy(from,to)
194
+ local of = fs.open(from,"rb")
195
+ local df = fs.open(to,"wb")
196
+ if not of or not df then
197
+  return false
198
+ end
199
+ df:write(of:read("*a"))
200
+ df:close()
201
+ of:close()
202
+end
203
+
204
+function fs.rename(from,to)
205
+ local ofsi, opath = fs.resolve(from)
206
+ local dfsi, dpath = fs.resolve(to)
207
+ if ofsi == dfsi then
208
+  fs.mounts[ofsi].rename(opath,dpath)
209
+  return true
210
+ end
211
+ fs.copy(from,to)
212
+ fs.remove(from)
213
+ return true
214
+end
215
+
216
+
217
+fs.mounts.temp = component.proxy(computer.tmpAddress())
218
+if computer.getBootAddress then
219
+ fs.mounts.boot = component.proxy(computer.getBootAddress())
220
+end
221
+for addr, _ in component.list("filesystem") do
222
+ fs.mounts[addr:sub(1,3)] = component.proxy(addr)
223
+end
224
+
225
+local function rf()
226
+ return false
227
+end
228
+fs.mounts.root = {}
229
+
230
+for k,v in pairs(fs.mounts.temp) do
231
+ fs.mounts.root[k] = rf
232
+end
233
+function fs.mounts.root.list()
234
+ local t = {}
235
+ for k,v in pairs(fs.mounts) do
236
+  t[#t+1] = k
237
+ end
238
+ t.n = #t
239
+ return t
240
+end
241
+function fs.mounts.root.isReadOnly()
242
+ return true
243
+end
244
+function loadfile(p)
245
+ local f = fs.open(p,"rb")
246
+ local c = f:read("*a")
247
+ f:close()
248
+ return load(c,p,"t")
249
+end
250
+function runfile(p,...)
251
+ loadfile(p)(...)
252
+end
253
+function spawnfile(p,n)
254
+ os.spawn(loadfile(p),n)
255
+end
256
+function vtemu(gpua,scra)
257
+ local gpu,scr = component.proxy(gpua),component.proxy(scra)
258
+ gpu.bind(scra)
259
+ local write = vt100emu(gpu)
260
+ local kba = {}
261
+ for k,v in ipairs(scr.getKeyboards()) do
262
+  kba[v]=true
263
+ end
264
+ local buf = ""
265
+ os.spawn(function()
266
+  while true do
267
+   local ty,ka,ch = coroutine.yield()
268
+   if ty == "key_down" and kba[ka] then
269
+    if ch == 13 then ch = 10 end
270
+    if ch == 8 and buf:len() > 0 then
271
+     write("\8 \8")
272
+     buf = buf:sub(1,-2)
273
+    elseif ch > 0 then
274
+     write(string.char(ch))
275
+     buf = buf .. string.char(ch)
276
+    end
277
+   end
278
+  end
279
+ end,"keyboard daemon for "..gpua:sub(1,8)..":"..scra:sub(1,8))
280
+ local function read(n)
281
+  n = n or "\n"
282
+  local rdata = ""
283
+  if type(n) == "number" then
284
+   rdata = buf:sub(1,n)
285
+   return rdata
286
+  else
287
+   if n == "*a" then
288
+    rdata = buf
289
+    buf = ""
290
+    return rdata
291
+   end
292
+   local pr,po = buf:match("(.-)"..n.."(.*)")
293
+   buf = po or buf
294
+   return pr
295
+  end
296
+ end
297
+ return read,write
298
+end
299
+_G.fd,_G.io = {},{}
300
+do
301
+function io.write(d)
302
+ fd[tTasks[cPid].t or 1].w(d)
303
+end
304
+function io.read(d,b)
305
+ local r = ""
306
+ repeat
307
+  r=fd[tTasks[cPid].t or 1].r(d)
308
+  coroutine.yield()
309
+ until r or b
310
+ return r
311
+end
312
+function print(...)
313
+ for k,v in pairs({...}) do
314
+  io.write(tostring(v).."\n")
315
+ end
316
+end
317
+
318
+local ts = {}
319
+for a,_ in component.list("screen") do
320
+ ts[#ts+1] = a
321
+end
322
+for a,_ in component.list("gpu") do
323
+ local r,w = vtemu(a,table.remove(ts,1))
324
+ fd[#fd+1] = {["r"]=r,["w"]=w,["t"]="t"}
325
+end
326
+end
327
+_G.net={}
328
+
329
+do
330
+local modems,packetQueue,packetCache,routeCache,C,Y = {},{},{},{},COMPUTER,UNPACK
331
+net.port,net.hostname,net.route,net.hook,U=4096,computer.address():sub(1,8),true,{},UPTIME
332
+
333
+for a in component.list("modem") do
334
+ modems[a] = component.proxy(a)
335
+ modems[a].open(net.port)
336
+end
337
+
338
+local function genPacketID()
339
+ local packetID = ""
340
+ for i = 1, 16 do
341
+  packetID = packetID .. string.char(math.random(32,126))
342
+ end
343
+ return packetID
344
+end
345
+
346
+local function rawSendPacket(packetID,packetType,to,from,vport,data)
347
+ if routeCache[to] then
348
+  modems[routeCache[to][1]].send(routeCache[to][2],net.port,packetID,packetType,to,from,vport,data)
349
+ else
350
+  for k,v in pairs(modems) do
351
+   v.broadcast(net.port,packetID,packetType,to,from,vport,data)
352
+  end
353
+ end
354
+end
355
+
356
+local function sendPacket(packetID,packetType,to,vport,data)
357
+ packetCache[packetID] = computer.uptime()
358
+ rawSendPacket(packetID,packetType,to,net.hostname,vport,data)
359
+end
360
+
361
+function net.send(to,vport,data,packetType,packetID)
362
+ packetType,packetID = packetType or 1, packetID or genPacketID()
363
+ packetQueue[packetID] = {packetType,to,vport,data,0}
364
+ sendPacket(packetID,packetType,to,vport,data)
365
+end
366
+
367
+local function checkCache(packetID)
368
+ for k,v in pairs(packetCache) do
369
+  if k == packetID then
370
+   return false
371
+  end
372
+ end
373
+ return true
374
+end
375
+
376
+os.spawn(function()
377
+ while true do
378
+  local eventTab = {coroutine.yield()}
379
+  if eventTab[1] == "modem_message" and (eventTab[4] == net.port or eventTab[4] == 0) and checkCache(eventTab[6]) then
380
+   for k,v in pairs(packetCache) do
381
+    if computer.uptime() > v+30 then
382
+     packetCache[k] = nil
383
+    end
384
+   end
385
+   for k,v in pairs(routeCache) do
386
+    if computer.uptime() > v[3]+30 then
387
+     routeCache[k] = nil
388
+    end
389
+   end
390
+   routeCache[eventTab[9]] = {eventTab[2],eventTab[3],computer.uptime()}
391
+   if eventTab[8] == net.hostname then
392
+    if eventTab[7] ~= 2 then
393
+     computer.pushSignal("net_msg",eventTab[9],eventTab[10],eventTab[11])
394
+     if eventTab[7] == 1 then
395
+      sendPacket(genPacketID(),2,eventTab[9],eventTab[10],eventTab[6])
396
+     end
397
+    else
398
+     packetQueue[eventTab[11]] = nil
399
+    end
400
+   elseif net.route and checkCache(eventTab[6]) then
401
+    rawSendPacket(eventTab[6],eventTab[7],eventTab[8],eventTab[9],eventTab[10],eventTab[11])
402
+   end
403
+   packetCache[eventTab[6]] = computer.uptime()
404
+  end
405
+  for k,v in pairs(packetQueue) do
406
+   if computer.uptime() > v[5] then
407
+    sendPacket(k,table.unpack(v))
408
+    v[5]=computer.uptime()+30
409
+   end
410
+  end
411
+ end
412
+end,"minitel.3")
413
+
414
+end
415
+os.spawn(function() print(pcall(function()
416
+print(_OSVERSION,tostring(computer.totalMemory()/1024).."K memory")
417
+local f = fs.open("/boot/init.txt","rb")
418
+local fc = f:read("*a")
419
+f:close()
420
+for line in fc:gmatch("[^\n]+") do
421
+ print(line)
422
+end
423
+for k,v in pairs(fd) do
424
+ if v.t == "t" then
425
+  tTasks[cPid].t = k
426
+  print("Spawning a shell for terminal #"..tostring(k))
427
+  spawnfile("/boot/exec/shell.lua","shell #"..tostring(k))
428
+ end
429
+end
430
+end)) end,"init")
431
+_OSVERSION="PsychOS 2.0a0"
432
+sched()

+ 2
- 0
exec/free.lua View File

@@ -0,0 +1,2 @@
1
+print("Total  Used  Free")
2
+print(string.format("%4dK %4dK %4dK",computer.totalMemory()/1024,math.floor((computer.totalMemory()-computer.freeMemory())/1024),math.floor(computer.freeMemory()/1024)))

+ 4
- 0
exec/ps.lua View File

@@ -0,0 +1,4 @@
1
+print("PID# VTY# Name")
2
+for k,v in pairs(tTasks) do
3
+ print(string.format("%4d %4d %s",k,v.t or 1,v.n))
4
+end

+ 9
- 0
exec/shell.lua View File

@@ -0,0 +1,9 @@
1
+local shenv = {}
2
+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})
3
+while true do
4
+ io.write(_VERSION.."> ")
5
+ tResult = {pcall(load(io.read(),"shell","t",shenv))}
6
+ for k,v in pairs(tResult) do
7
+  print(v)
8
+ end
9
+end

+ 8
- 0
mkmods.sh View File

@@ -0,0 +1,8 @@
1
+#!/bin/bash
2
+for f in service/*; do
3
+ nf=$(echo $f | cut -d '/' -f 2)
4
+ echo $nf
5
+ echo os.spawn\(function\(\) >mod-service/$nf
6
+ cat $f >> mod-service/$nf
7
+ echo end,\"$nf\"\) >> mod-service/$nf
8
+done

+ 88
- 0
mod-service/microtel-3.lua View File

@@ -0,0 +1,88 @@
1
+os.spawn(function()
2
+_G.net={}
3
+
4
+do
5
+local modems,packetQueue,packetCache,routeCache,C,Y = {},{},{},{},COMPUTER,UNPACK
6
+net.port,net.hostname,net.route,net.hook,U=4096,computer.address():sub(1,8),true,{},UPTIME
7
+
8
+for a in component.list("modem") do
9
+ modems[a] = component.proxy(a)
10
+ modems[a].open(net.port)
11
+end
12
+
13
+local function genPacketID()
14
+ local packetID = ""
15
+ for i = 1, 16 do
16
+  packetID = packetID .. string.char(math.random(32,126))
17
+ end
18
+ return packetID
19
+end
20
+
21
+local function rawSendPacket(packetID,packetType,to,from,vport,data)
22
+ if routeCache[to] then
23
+  modems[routeCache[to][1]].send(routeCache[to][2],net.port,packetID,packetType,to,from,vport,data)
24
+ else
25
+  for k,v in pairs(modems) do
26
+   v.broadcast(net.port,packetID,packetType,to,from,vport,data)
27
+  end
28
+ end
29
+end
30
+
31
+local function sendPacket(packetID,packetType,to,vport,data)
32
+ packetCache[packetID] = computer.uptime()
33
+ rawSendPacket(packetID,packetType,to,net.hostname,vport,data)
34
+end
35
+
36
+function net.send(to,vport,data,packetType,packetID)
37
+ packetType,packetID = packetType or 1, packetID or genPacketID()
38
+ packetQueue[packetID] = {packetType,to,vport,data,0}
39
+ sendPacket(packetID,packetType,to,vport,data)
40
+end
41
+
42
+local function checkCache(packetID)
43
+ for k,v in pairs(packetCache) do
44
+  if k == packetID then
45
+   return false
46
+  end
47
+ end
48
+ return true
49
+end
50
+
51
+while true do
52
+ local eventTab = {coroutine.yield()}
53
+ if eventTab[1] == "modem_message" and (eventTab[4] == net.port or eventTab[4] == 0) and checkCache(eventTab[6]) then
54
+  for k,v in pairs(packetCache) do
55
+   if computer.uptime() > v+30 then
56
+    packetCache[k] = nil
57
+   end
58
+  end
59
+  for k,v in pairs(routeCache) do
60
+   if computer.uptime() > v[3]+30 then
61
+    routeCache[k] = nil
62
+   end
63
+  end
64
+  routeCache[eventTab[9]] = {eventTab[2],eventTab[3],computer.uptime()}
65
+  if eventTab[8] == net.hostname then
66
+   if eventTab[7] ~= 2 then
67
+    computer.pushSignal("net_msg",eventTab[9],eventTab[10],eventTab[11])
68
+    if eventTab[7] == 1 then
69
+     sendPacket(genPacketID(),2,eventTab[9],eventTab[10],eventTab[6])
70
+    end
71
+   else
72
+    packetQueue[eventTab[11]] = nil
73
+   end
74
+  elseif net.route and checkCache(eventTab[6]) then
75
+   rawSendPacket(eventTab[6],eventTab[7],eventTab[8],eventTab[9],eventTab[10],eventTab[11])
76
+  end
77
+  packetCache[eventTab[6]] = computer.uptime()
78
+ end
79
+ for k,v in pairs(packetQueue) do
80
+  if computer.uptime() > v[5] then
81
+   sendPacket(k,table.unpack(v))
82
+   v[5]=computer.uptime()+30
83
+  end
84
+ end
85
+end
86
+
87
+end
88
+end,"microtel-3.lua")

+ 114
- 0
module/fs.lua View File

@@ -0,0 +1,114 @@
1
+fs = {}
2
+fs.mounts = {}
3
+
4
+-- basics
5
+function fs.segments(path)
6
+ local segments = {}
7
+ for segment in path:gmatch("[^/]+") do
8
+  segments[#segments+1] = segment
9
+ end
10
+ return segments
11
+end
12
+function fs.resolve(path)
13
+ local segments, rpath = fs.segments(path), "/"
14
+ for i = 2, #segments do
15
+  rpath = rpath .. segments[i] .. "/"
16
+ end
17
+ rpath = rpath:match("(.+)/") or rpath
18
+ return segments[1] or "root",rpath
19
+end
20
+
21
+-- generate some simple functions
22
+for k,v in pairs({"makeDirectory","exists","isDirectory","list","lastModified","remove","size","spaceUsed","isReadOnly","getLabel"}) do
23
+ fs[v] = function(path)
24
+  local fsi,path = fs.resolve(path)
25
+  return fs.mounts[fsi][v](path)
26
+ end
27
+end
28
+
29
+local function fread(self,length)
30
+ if length == "*a" then
31
+  length = math.huge
32
+ end
33
+ local rstr, lstr = "", ""
34
+ repeat
35
+  lstr = fs.mounts[self.fs].read(self.fid,math.min(2^16,length-rstr:len())) or ""
36
+  rstr = rstr .. lstr
37
+ until rstr:len() == length or lstr == ""
38
+ return rstr
39
+end
40
+local function fwrite(self,data)
41
+ fs.mounts[self.fs].write(self.fid,data)
42
+end
43
+local function fclose(self)
44
+ fs.mounts[self.fs].close(self.fid)
45
+end
46
+
47
+function fs.open(path,mode)
48
+ mode = mode or "rb"
49
+ local fsi,path = fs.resolve(path)
50
+ if not fs.mounts[fsi] then return false end
51
+ local fid = fs.mounts[fsi].open(path,mode)
52
+ if fid then
53
+  local fobj = {["fs"]=fsi,["fid"]=fid,["close"]=fclose}
54
+  if mode:sub(1,1) == "r" then
55
+   fobj.read = fread
56
+  else
57
+   fobj.write = fwrite
58
+  end
59
+  return fobj
60
+ end
61
+ return false
62
+end
63
+
64
+function fs.copy(from,to)
65
+ local of = fs.open(from,"rb")
66
+ local df = fs.open(to,"wb")
67
+ if not of or not df then
68
+  return false
69
+ end
70
+ df:write(of:read("*a"))
71
+ df:close()
72
+ of:close()
73
+end
74
+
75
+function fs.rename(from,to)
76
+ local ofsi, opath = fs.resolve(from)
77
+ local dfsi, dpath = fs.resolve(to)
78
+ if ofsi == dfsi then
79
+  fs.mounts[ofsi].rename(opath,dpath)
80
+  return true
81
+ end
82
+ fs.copy(from,to)
83
+ fs.remove(from)
84
+ return true
85
+end
86
+
87
+
88
+fs.mounts.temp = component.proxy(computer.tmpAddress())
89
+if computer.getBootAddress then
90
+ fs.mounts.boot = component.proxy(computer.getBootAddress())
91
+end
92
+for addr, _ in component.list("filesystem") do
93
+ fs.mounts[addr:sub(1,3)] = component.proxy(addr)
94
+end
95
+
96
+local function rf()
97
+ return false
98
+end
99
+fs.mounts.root = {}
100
+
101
+for k,v in pairs(fs.mounts.temp) do
102
+ fs.mounts.root[k] = rf
103
+end
104
+function fs.mounts.root.list()
105
+ local t = {}
106
+ for k,v in pairs(fs.mounts) do
107
+  t[#t+1] = k
108
+ end
109
+ t.n = #t
110
+ return t
111
+end
112
+function fs.mounts.root.isReadOnly()
113
+ return true
114
+end

+ 17
- 0
module/init.lua View File

@@ -0,0 +1,17 @@
1
+os.spawn(function() print(pcall(function()
2
+print(_OSVERSION,tostring(math.floor(computer.totalMemory()/1024)).."K memory")
3
+local f = fs.open("/boot/init.txt","rb")
4
+local fc = f:read("*a")
5
+f:close()
6
+for line in fc:gmatch("[^\n]+") do
7
+ print("Starting service "..line)
8
+ spawnfile("/boot/service/"..line)
9
+end
10
+for k,v in pairs(fd) do
11
+ if v.t == "t" then
12
+  tTasks[cPid].t = k
13
+  print("Spawning a shell for terminal #"..tostring(k))
14
+  spawnfile("/boot/exec/shell.lua","shell #"..tostring(k))
15
+ end
16
+end
17
+end)) end,"init")

+ 28
- 0
module/io.lua View File

@@ -0,0 +1,28 @@
1
+_G.fd,_G.io = {},{}
2
+do
3
+function io.write(d)
4
+ fd[tTasks[cPid].t or 1].w(d)
5
+end
6
+function io.read(d,b)
7
+ local r = ""
8
+ repeat
9
+  r=fd[tTasks[cPid].t or 1].r(d)
10
+  coroutine.yield()
11
+ until r or b
12
+ return r
13
+end
14
+function print(...)
15
+ for k,v in pairs({...}) do
16
+  io.write(tostring(v).."\n")
17
+ end
18
+end
19
+
20
+local ts = {}
21
+for a,_ in component.list("screen") do
22
+ ts[#ts+1] = a
23
+end
24
+for a,_ in component.list("gpu") do
25
+ local r,w = vtemu(a,table.remove(ts,1))
26
+ fd[#fd+1] = {["r"]=r,["w"]=w,["t"]="t"}
27
+end
28
+end

+ 12
- 0
module/loadfile.lua View File

@@ -0,0 +1,12 @@
1
+function loadfile(p)
2
+ local f = fs.open(p,"rb")
3
+ local c = f:read("*a")
4
+ f:close()
5
+ return load(c,p,"t")
6
+end
7
+function runfile(p,...)
8
+ loadfile(p)(...)
9
+end
10
+function spawnfile(p,n)
11
+ os.spawn(loadfile(p),n)
12
+end

+ 88
- 0
module/microtel-3.lua View File

@@ -0,0 +1,88 @@
1
+_G.net={}
2
+
3
+do
4
+local modems,packetQueue,packetCache,routeCache,C,Y = {},{},{},{},COMPUTER,UNPACK
5
+net.port,net.hostname,net.route,net.hook,U=4096,computer.address():sub(1,8),true,{},UPTIME
6
+
7
+for a in component.list("modem") do
8
+ modems[a] = component.proxy(a)
9
+ modems[a].open(net.port)
10
+end
11
+
12
+local function genPacketID()
13
+ local packetID = ""
14
+ for i = 1, 16 do
15
+  packetID = packetID .. string.char(math.random(32,126))
16
+ end
17
+ return packetID
18
+end
19
+
20
+local function rawSendPacket(packetID,packetType,to,from,vport,data)
21
+ if routeCache[to] then
22
+  modems[routeCache[to][1]].send(routeCache[to][2],net.port,packetID,packetType,to,from,vport,data)
23
+ else
24
+  for k,v in pairs(modems) do
25
+   v.broadcast(net.port,packetID,packetType,to,from,vport,data)
26
+  end
27
+ end
28
+end
29
+
30
+local function sendPacket(packetID,packetType,to,vport,data)
31
+ packetCache[packetID] = computer.uptime()
32
+ rawSendPacket(packetID,packetType,to,net.hostname,vport,data)
33
+end
34
+
35
+function net.send(to,vport,data,packetType,packetID)
36
+ packetType,packetID = packetType or 1, packetID or genPacketID()
37
+ packetQueue[packetID] = {packetType,to,vport,data,0}
38
+ sendPacket(packetID,packetType,to,vport,data)
39
+end
40
+
41
+local function checkCache(packetID)
42
+ for k,v in pairs(packetCache) do
43
+  if k == packetID then
44
+   return false
45
+  end
46
+ end
47
+ return true
48
+end
49
+
50
+os.spawn(function()
51
+ while true do
52
+  local eventTab = {coroutine.yield()}
53
+  if eventTab[1] == "modem_message" and (eventTab[4] == net.port or eventTab[4] == 0) and checkCache(eventTab[6]) then
54
+   for k,v in pairs(packetCache) do
55
+    if computer.uptime() > v+30 then
56
+     packetCache[k] = nil
57
+    end
58
+   end
59
+   for k,v in pairs(routeCache) do
60
+    if computer.uptime() > v[3]+30 then
61
+     routeCache[k] = nil
62
+    end
63
+   end
64
+   routeCache[eventTab[9]] = {eventTab[2],eventTab[3],computer.uptime()}
65
+   if eventTab[8] == net.hostname then
66
+    if eventTab[7] ~= 2 then
67
+     computer.pushSignal("net_msg",eventTab[9],eventTab[10],eventTab[11])
68
+     if eventTab[7] == 1 then
69
+      sendPacket(genPacketID(),2,eventTab[9],eventTab[10],eventTab[6])
70
+     end
71
+    else
72
+     packetQueue[eventTab[11]] = nil
73
+    end
74
+   elseif net.route and checkCache(eventTab[6]) then
75
+    rawSendPacket(eventTab[6],eventTab[7],eventTab[8],eventTab[9],eventTab[10],eventTab[11])
76
+   end
77
+   packetCache[eventTab[6]] = computer.uptime()
78
+  end
79
+  for k,v in pairs(packetQueue) do
80
+   if computer.uptime() > v[5] then
81
+    sendPacket(k,table.unpack(v))
82
+    v[5]=computer.uptime()+30
83
+   end
84
+  end
85
+ end
86
+end,"minitel.3")
87
+
88
+end

+ 22
- 0
module/sched.lua View File

@@ -0,0 +1,22 @@
1
+tTasks,nPid,nTimeout,cPid = {},1,1,0
2
+function os.spawn(f,n)
3
+ tTasks[nPid] = {["c"]=coroutine.create(f),["n"]=n,["p"]=nPid}
4
+ for k,v in pairs(tTasks[cPid] or {}) do
5
+  tTasks[nPid][k] = tTasks[nPid][k] or v
6
+ end
7
+ nPid = nPid + 1
8
+ return nPid - 1
9
+end
10
+function sched()
11
+ while #tTasks > 0 do
12
+  local tEv = {computer.pullSignal(nTimeout)}
13
+  for k,v in pairs(tTasks) do
14
+   if coroutine.status(v.c) ~= "dead" then
15
+    cPid = k
16
+    coroutine.resume(v.c,table.unpack(tEv))
17
+   else
18
+    tTasks[k] = nil
19
+   end
20
+  end
21
+ end
22
+end

+ 15
- 0
module/spawnprompt.lua View File

@@ -0,0 +1,15 @@
1
+os.spawn(function()
2
+print(_OSVERSION,tostring(computer.totalMemory()/1024).."K memory")
3
+for k,v in pairs(fd) do
4
+ if v.t == "t" then
5
+  tTasks[cPid].t = k
6
+  print("Spawning Lua prompt for "..tostring(k))
7
+  os.spawn(function() print(pcall(function() while true do
8
+   io.write(_VERSION.."> ")
9
+   tResult = {pcall(load(io.read()))}
10
+   for k,v in pairs(tResult) do
11
+    print(v)
12
+   end
13
+  end end)) end,"lua prompt")
14
+ end
15
+end end,"init")

+ 43
- 0
module/vt-task.lua View File

@@ -0,0 +1,43 @@
1
+function vtemu(gpua,scra)
2
+ local gpu,scr = component.proxy(gpua),component.proxy(scra)
3
+ gpu.bind(scra)
4
+ local write = vt100emu(gpu)
5
+ local kba = {}
6
+ for k,v in ipairs(scr.getKeyboards()) do
7
+  kba[v]=true
8
+ end
9
+ local buf = ""
10
+ os.spawn(function()
11
+  while true do
12
+   local ty,ka,ch = coroutine.yield()
13
+   if ty == "key_down" and kba[ka] then
14
+    if ch == 13 then ch = 10 end
15
+    if ch == 8 and buf:len() > 0 then
16
+     write("\8 \8")
17
+     buf = buf:sub(1,-2)
18
+    elseif ch > 0 then
19
+     write(string.char(ch))
20
+     buf = buf .. string.char(ch)
21
+    end
22
+   end
23
+  end
24
+ end,"keyboard daemon for "..gpua:sub(1,8)..":"..scra:sub(1,8))
25
+ local function read(n)
26
+  n = n or "\n"
27
+  local rdata = ""
28
+  if type(n) == "number" then
29
+   rdata = buf:sub(1,n)
30
+   return rdata
31
+  else
32
+   if n == "*a" then
33
+    rdata = buf
34
+    buf = ""
35
+    return rdata
36
+   end
37
+   local pr,po = buf:match("(.-)"..n.."(.*)")
38
+   buf = po or buf
39
+   return pr
40
+  end
41
+ end
42
+ return read,write
43
+end

+ 107
- 0
module/vt100.lua View File

@@ -0,0 +1,107 @@
1
+function vt100emu(gpu)
2
+ local mx, my = gpu.maxResolution()
3
+ local cx, cy = 1, 1
4
+ local pc = " "
5
+ local lc = ""
6
+ local mode = "n"
7
+ local lw = true
8
+ local sx, sy = 1,1
9
+ local cs = ""
10
+
11
+ -- setup
12
+ gpu.setResolution(mx,my)
13
+ gpu.fill(1,1,mx,my," ")
14
+
15
+ function termwrite(s)
16
+  s=s:gsub("\8","\27[D")
17
+  pc = gpu.get(cx,cy)
18
+  gpu.setForeground(0xFFFFFF)
19
+  gpu.setBackground(0)
20
+  gpu.set(cx,cy,pc)
21
+  for i = 1, s:len() do
22
+   local cc = s:sub(i,i)
23
+
24
+   if mode == "n" then
25
+    if cc == "\n" then -- line feed
26
+     cx, cy = 1, cy+1
27
+    elseif cc == "\r" then -- cursor home
28
+     cx = 1
29
+    elseif cc == "\27" then -- escape
30
+     mode = "e"
31
+    elseif string.byte(cc) > 31 and string.byte(cc) < 127 then -- printable, I guess
32
+     gpu.set(cx, cy, cc)
33
+     cx = cx + 1
34
+    end
35
+
36
+   elseif mode == "e" then
37
+    if cc == "[" then
38
+     mode = "v"
39
+     cs = ""
40
+    elseif cc == "D" then -- scroll down
41
+     gpu.copy(1,2,mx,my-1,0,-1)
42
+     gpu.fill(1,my,mx,1," ")
43
+     cy=cy+1
44
+     mode = "n"
45
+    elseif cc == "M" then -- scroll up
46
+     gpu.copy(1,1,mx,my-1,0,1)
47
+     gpu.fill(1,1,mx,1," ")
48
+     mode = "n"
49
+    end
50
+
51
+   elseif mode == "v" then -- save cursor
52
+    local n = cs:sub(cs:len(),cs:len())
53
+    if n == "" then n = "\1" end
54
+    if cc == "s" then
55
+     sx, sy = cx, cy
56
+     mode = "n"
57
+    elseif cc == "u" then -- restore cursor
58
+     cx, cy = sx, sy
59
+     mode = "n"
60
+    elseif cc == "H" then -- cursor home or to
61
+     local tx, ty = cs:match("(.);(.)")
62
+     tx, ty = tx or "\1", ty or "\1"
63
+     cx, cy = string.byte(tx), string.byte(ty)
64
+     mode = "n"
65
+    elseif cc == "A" then -- cursor up
66
+     cy = cy - string.byte(n)
67
+     mode = "n"
68
+    elseif cc == "B" then -- cursor down
69
+     cy = cy + string.byte(n)
70
+     mode = "n"
71
+    elseif cc == "C" then -- cursor right
72
+     cx = cx + string.byte(n)
73
+     mode = "n"
74
+    elseif cc == "D" then -- cursor left
75
+     cx = cx - string.byte(n)
76
+     mode = "n"
77
+    elseif cc == "h" and lc == "7" then -- enable line wrap
78
+     lw = true
79
+    elseif cc == "l" and lc == "7" then -- disable line wrap
80
+     lw = false
81
+    end
82
+    cs = cs .. cc
83
+   end
84
+
85
+   if cx > mx and lw then
86
+    cx, cy = 1, cy+1
87
+   end
88
+   if cy > my then
89
+    gpu.copy(1,2,mx,my-1,0,-1)
90
+    gpu.fill(1,my,mx,1," ")
91
+    cy=my
92
+   end
93
+   if cy < 1 then cy = 1 end
94
+   if cx < 1 then cx = 1 end
95
+
96
+   lc = cc
97
+  end
98
+  pc = gpu.get(cx,cy)
99
+  gpu.setForeground(0)
100
+  gpu.setBackground(0xFFFFFF)
101
+  gpu.set(cx,cy,pc)
102
+  gpu.setForeground(0xFFFFFF)
103
+  gpu.setBackground(0)
104
+ end
105
+
106
+ return termwrite
107
+end

+ 86
- 0
service/microtel-3.lua View File

@@ -0,0 +1,86 @@
1
+_G.net={}
2
+
3
+do
4
+local modems,packetQueue,packetCache,routeCache,C,Y = {},{},{},{},COMPUTER,UNPACK
5
+net.port,net.hostname,net.route,net.hook,U=4096,computer.address():sub(1,8),true,{},UPTIME
6
+
7
+for a in component.list("modem") do
8
+ modems[a] = component.proxy(a)
9
+ modems[a].open(net.port)
10
+end
11
+
12
+local function genPacketID()
13
+ local packetID = ""
14
+ for i = 1, 16 do
15
+  packetID = packetID .. string.char(math.random(32,126))
16
+ end
17
+ return packetID
18
+end
19
+
20
+local function rawSendPacket(packetID,packetType,to,from,vport,data)
21
+ if routeCache[to] then
22
+  modems[routeCache[to][1]].send(routeCache[to][2],net.port,packetID,packetType,to,from,vport,data)
23
+ else
24
+  for k,v in pairs(modems) do
25
+   v.broadcast(net.port,packetID,packetType,to,from,vport,data)
26
+  end
27
+ end
28
+end
29
+
30
+local function sendPacket(packetID,packetType,to,vport,data)
31
+ packetCache[packetID] = computer.uptime()
32
+ rawSendPacket(packetID,packetType,to,net.hostname,vport,data)
33
+end
34
+
35
+function net.send(to,vport,data,packetType,packetID)
36
+ packetType,packetID = packetType or 1, packetID or genPacketID()
37
+ packetQueue[packetID] = {packetType,to,vport,data,0}
38
+ sendPacket(packetID,packetType,to,vport,data)
39
+end
40
+
41
+local function checkCache(packetID)
42
+ for k,v in pairs(packetCache) do
43
+  if k == packetID then
44
+   return false
45
+  end
46
+ end
47
+ return true
48
+end
49
+
50
+while true do
51
+ local eventTab = {coroutine.yield()}
52
+ if eventTab[1] == "modem_message" and (eventTab[4] == net.port or eventTab[4] == 0) and checkCache(eventTab[6]) then
53
+  for k,v in pairs(packetCache) do
54
+   if computer.uptime() > v+30 then
55
+    packetCache[k] = nil
56
+   end
57
+  end
58
+  for k,v in pairs(routeCache) do
59
+   if computer.uptime() > v[3]+30 then
60
+    routeCache[k] = nil
61
+   end
62
+  end
63
+  routeCache[eventTab[9]] = {eventTab[2],eventTab[3],computer.uptime()}
64
+  if eventTab[8] == net.hostname then
65
+   if eventTab[7] ~= 2 then
66
+    computer.pushSignal("net_msg",eventTab[9],eventTab[10],eventTab[11])
67
+    if eventTab[7] == 1 then
68
+     sendPacket(genPacketID(),2,eventTab[9],eventTab[10],eventTab[6])
69
+    end
70
+   else
71
+    packetQueue[eventTab[11]] = nil
72
+   end
73
+  elseif net.route and checkCache(eventTab[6]) then
74
+   rawSendPacket(eventTab[6],eventTab[7],eventTab[8],eventTab[9],eventTab[10],eventTab[11])
75
+  end
76
+  packetCache[eventTab[6]] = computer.uptime()
77
+ end
78
+ for k,v in pairs(packetQueue) do
79
+  if computer.uptime() > v[5] then
80
+   sendPacket(k,table.unpack(v))
81
+   v[5]=computer.uptime()+30
82
+  end
83
+ end
84
+end
85
+
86
+end