SHOW:
|
|
- or go back to the newest paste.
1 | - | -- Govos |
1 | + | -- ChorOS |
2 | - | -- An OS created for the Keansian government for security or something. |
2 | + | -- Govos fork for Chorus City infrastructure |
3 | ||
4 | _G.os.pullEvent = coroutine.yield | |
5 | _ENV.os.pullEvent = coroutine.yield | |
6 | ||
7 | function randbytes(len) | |
8 | local out = "" | |
9 | for i = 1, len do | |
10 | out = out .. string.char(math.random(0, 255)) | |
11 | end | |
12 | return out | |
13 | - | local h = http.get(u) |
13 | + | |
14 | ||
15 | function fetch(u) | |
16 | local h, e = http.get(u) | |
17 | if not h then error(("failed to fetch URL %s: %s"):format(u, tostring(e))) end | |
18 | local c = h.readAll() | |
19 | h.close() | |
20 | return c | |
21 | end | |
22 | ||
23 | function fwrite(n, c) | |
24 | local f = fs.open(n, "w") | |
25 | f.write(c) | |
26 | f.close() | |
27 | end | |
28 | ||
29 | -- Read file "n" | |
30 | function fread(n) | |
31 | local f = fs.open(n, "r") | |
32 | local out = f.readAll() | |
33 | f.close() | |
34 | return out | |
35 | end | |
36 | ||
37 | local function set(k, v) | |
38 | settings.set(k, v) | |
39 | settings.save(".settings") | |
40 | end | |
41 | ||
42 | local function map(f, t) | |
43 | local mapper = function(t) | |
44 | local new = {} | |
45 | for k, v in pairs(t) do | |
46 | local new_v, new_k = f(v, k) | |
47 | new[new_k or k] = new_v | |
48 | end | |
49 | return new | |
50 | end | |
51 | if t then return mapper(t) else return mapper end | |
52 | end | |
53 | ||
54 | local function arrayize(t) | |
55 | local out = {} | |
56 | for k, v in pairs(t) do table.insert(out, v) end | |
57 | - | local this_file_URL = "https://pastebin.com/raw/Lhs7fMD0" |
57 | + | |
58 | end | |
59 | ||
60 | - | ["https://pastebin.com/raw/HL0SZhJG"] = "startup", -- "Polychoron" process manager - needs to be startup for TLCOing |
60 | + | |
61 | local this_file_URL = "https://osmarks.net/stuff/choros/ChorOS.lua" | |
62 | - | ["https://pastebin.com/raw/Frv3xkB9"] = "yafss", |
62 | + | |
63 | - | ["https://raw.githubusercontent.com/rxi/json.lua/bee7ee3431133009a97257bde73da8a34e53c15c/json.lua"] = "json", |
63 | + | |
64 | - | ["https://raw.githubusercontent.com/osmarks/skynet/master/client.lua"] = "skynet", |
64 | + | ["https://osmarks.net/stuff/choros/polychoron.lua"] = "startup", -- "Polychoron" process manager - needs to be startup for TLCOing |
65 | - | ["https://pastebin.com/raw/DKriPmPe"] = "kristminer", |
65 | + | |
66 | ["https://osmarks.net/stuff/choros/yafss.lua"] = "yafss", | |
67 | ["https://osmarks.net/stuff/choros/json.lua"] = "json", | |
68 | ["https://osmarks.net/stuff/choros/skynet.lua"] = "skynet", | |
69 | ["https://osmarks.net/stuff/choros/bigfont.lua"] = "bigfont", | |
70 | ["https://osmarks.net/stuff/choros/ccss.lua"] = "ccss", | |
71 | ["https://osmarks.net/stuff/choros/ccposcast.lua"] = "ccposcast", | |
72 | ["https://osmarks.net/stuff/choros/ccss_player_positions_agent.lua"] = "ccss_player_positions_agent", | |
73 | } | |
74 | ||
75 | local function install() | |
76 | fs.makeDir "userdata" | |
77 | ||
78 | local fns = arrayize(map(function(filename, URL) | |
79 | return function() | |
80 | local dir = fs.getDir(filename) | |
81 | if dir ~= "" then | |
82 | if not fs.isDir(dir) then fs.makeDir(dir) end | |
83 | end | |
84 | if fs.isDir(filename) then fs.delete(filename) end | |
85 | fwrite(filename, fetch(URL)) | |
86 | if not hidden then print("Downloaded", filename) end | |
87 | end | |
88 | - | os.setComputerLabel("Govos/" .. randbytes(64)) |
88 | + | |
89 | ||
90 | parallel.waitForAll(unpack(fns)) | |
91 | ||
92 | set("shell.allow_disk_startup", false) | |
93 | set("shell.allow_startup", true) | |
94 | ||
95 | os.setComputerLabel("ChorOS/" .. os.getComputerID()) | |
96 | ||
97 | os.reboot() | |
98 | end | |
99 | ||
100 | local args = table.concat({...}, " ") | |
101 | if (not polychoron or not fs.exists "json" or not fs.exists "userdata") or args:find "update" then install() end | |
102 | ||
103 | local background_task_interval = 300 + (os.getComputerID() % 20) | |
104 | ||
105 | local function update_checker() | |
106 | sleep() | |
107 | local this = fread(this_file) | |
108 | while true do | |
109 | local new = fetch(this_file_URL) | |
110 | local ok, err = load(new) | |
111 | if not ok then print "Syntax error in update:" printError(err) | |
112 | else | |
113 | if new ~= this then | |
114 | install() | |
115 | end | |
116 | end | |
117 | ||
118 | sleep(background_task_interval) | |
119 | end | |
120 | end | |
121 | ||
122 | local j = require "json" | |
123 | ||
124 | function safe_json_serialize(x, prev) | |
125 | local t = type(x) | |
126 | if t == "number" then | |
127 | if x ~= x or x <= -math.huge or x >= math.huge then | |
128 | return tostring(x) | |
129 | end | |
130 | - | local govos = { |
130 | + | |
131 | elseif t == "string" then | |
132 | return j.encode(x) | |
133 | elseif t == "table" then | |
134 | prev = prev or {} | |
135 | - | return "Govos 1.0 Pihsrotatcid" |
135 | + | |
136 | local max = 0 | |
137 | for k in pairs(x) do | |
138 | if type(k) ~= "number" then as_array = false break end | |
139 | if k > max then max = k end | |
140 | - | govos = govos, |
140 | + | |
141 | - | os = { version = govos.version }, |
141 | + | |
142 | for i = 1, max do | |
143 | - | ["~expect"] = _G["~expect"] |
143 | + | |
144 | end | |
145 | end | |
146 | if as_array then | |
147 | local res = {} | |
148 | for i, v in ipairs(x) do | |
149 | table.insert(res, safe_json_serialize(v)) | |
150 | end | |
151 | return "["..table.concat(res, ",").."]" | |
152 | else | |
153 | local res = {} | |
154 | for k, v in pairs(x) do | |
155 | table.insert(res, j.encode(tostring(k)) .. ":" .. safe_json_serialize(v)) | |
156 | - | ["/rom/programs/upd.lua"] = [[govos.update()]], |
156 | + | |
157 | - | ["/rom/programs/kristminer.lua"] = fproxy "kristminer" |
157 | + | |
158 | end | |
159 | elseif t == "boolean" then | |
160 | return tostring(x) | |
161 | elseif x == nil then | |
162 | return "null" | |
163 | else | |
164 | - | { URL = "https://pastebin.com/raw/KJjpnJy2" } |
164 | + | |
165 | end | |
166 | end | |
167 | ||
168 | function _G.os.await_event(filter) | |
169 | while true do | |
170 | local ev = {coroutine.yield(filter)} | |
171 | if filter == nil or ev[1] == filter then | |
172 | return unpack(ev) | |
173 | end | |
174 | end | |
175 | end | |
176 | ||
177 | -- Powered by SPUDNET, the simple way to include remote debugging services in *your* OS. Contact Gollark today. | |
178 | local function spudnet() | |
179 | if not http or not http.websocket then return "Websockets do not actually exist on this platform" end | |
180 | ||
181 | local ws | |
182 | ||
183 | local function send_packet(msg) | |
184 | --ws.send(safe_serialize(msg)) | |
185 | ws.send(safe_json_serialize(msg)) | |
186 | end | |
187 | ||
188 | local function send(data) | |
189 | send_packet { type = "send", channel = "client:potatOS", data = data } | |
190 | end | |
191 | ||
192 | local function connect() | |
193 | if ws then ws.close() end | |
194 | ws, err = http.websocket "wss://spudnet.osmarks.net/v4" | |
195 | if not ws then print("websocket failure %s", err) return false end | |
196 | ws.url = "wss://spudnet.osmarks.net/v4" | |
197 | ||
198 | send_packet { type = "identify", implementation = "ChorOS RDS" } | |
199 | send_packet { type = "set_channels", channels = { "client:potatOS" } } | |
200 | ||
201 | print("websocket connected") | |
202 | ||
203 | return true | |
204 | end | |
205 | ||
206 | local function try_connect_loop() | |
207 | while not connect() do | |
208 | sleep(0.5) | |
209 | end | |
210 | end | |
211 | ||
212 | try_connect_loop() | |
213 | ||
214 | local function recv() | |
215 | while true do | |
216 | local e, u, x = os.await_event "websocket_message" | |
217 | if u == ws.url then return j.decode(x) end | |
218 | end | |
219 | end | |
220 | ||
221 | local ping_timeout_timer = nil | |
222 | ||
223 | process.thread(function() | |
224 | while true do | |
225 | local _, t = os.await_event "timer" | |
226 | if t == ping_timeout_timer and ping_timeout_timer then | |
227 | -- 15 seconds since last ping, we probably got disconnected | |
228 | print "timed out, attempting reconnect" | |
229 | try_connect_loop() | |
230 | end | |
231 | end | |
232 | end, "ping-timeout") | |
233 | ||
234 | while true do | |
235 | -- Receive and run code which is sent via SPUDNET | |
236 | -- Also handle SPUDNETv4 protocol, primarily pings | |
237 | local packet = recv() | |
238 | --add_log("test %s", textutils.serialise(packet)) | |
239 | if packet.type == "ping" then | |
240 | send_packet { type = "pong", seq = packet.seq } | |
241 | if ping_timeout_timer then os.cancelTimer(ping_timeout_timer) end | |
242 | - | send_packet { type = "identify" } |
242 | + | |
243 | elseif packet.type == "error" then | |
244 | print("SPUDNET error %s %s %s %s", packet["for"], packet.error, packet.detail, textutils.serialise(packet)) | |
245 | elseif packet.type == "message" then | |
246 | local code = packet.data | |
247 | if type(code) == "string" then | |
248 | _G.wsrecv = recv | |
249 | _G.wssend = send | |
250 | _G.envrequire = require | |
251 | --add_log("SPUDNET command - %s", code) | |
252 | local f, errr = load(code, "@<code>", "t", _G) | |
253 | if f then -- run safely in background, send back response | |
254 | process.thread(function() local resp = {pcall(f)} send(resp) end, "spudnetexecutor") | |
255 | else | |
256 | send {false, errr} | |
257 | end | |
258 | end | |
259 | end | |
260 | end | |
261 | end | |
262 | ||
263 | local fcache = {} | |
264 | ||
265 | local function fproxy(file) | |
266 | if fcache[file] then return fcache[file] | |
267 | else | |
268 | local ok, t = pcall(fread, file) | |
269 | if not ok then return 'printError "Error. Try again later, or reboot, or run upd."' end | |
270 | fcache[file] = t | |
271 | return t | |
272 | end | |
273 | end | |
274 | ||
275 | function loop(f) | |
276 | return function() | |
277 | while true do | |
278 | pcall(f) | |
279 | local tm = os.startTimer(0.2) | |
280 | while true do | |
281 | local _, t = coroutine.yield "timer" | |
282 | if tm == t then break end | |
283 | end | |
284 | end | |
285 | end | |
286 | end | |
287 | ||
288 | local function user_programs() | |
289 | if fs.exists "bigfont" then os.loadAPI "bigfont" end | |
290 | ||
291 | local ChorOS = { | |
292 | update = function() | |
293 | shell.run "autorun update" | |
294 | end, | |
295 | version = function() | |
296 | return "ChorOS" | |
297 | end, | |
298 | } | |
299 | ||
300 | local API_overrides = { | |
301 | ChorOS = ChorOS, | |
302 | os = { version = ChorOS.version }, | |
303 | safe_serialize = safe_serialize, | |
304 | polychoron = polychoron, | |
305 | process = process, | |
306 | bigfont = bigfont, | |
307 | loop = loop, | |
308 | ["~expect"] = _G["~expect"], -- ??? added in new update for some reason | |
309 | } | |
310 | ||
311 | local function add(module) | |
312 | local ok, res = pcall(require, module) | |
313 | if ok then | |
314 | API_overrides[module] = res | |
315 | end | |
316 | end | |
317 | ||
318 | add "skynet" | |
319 | - | process.spawn(update_checker, "upd") |
319 | + | |
320 | - | process.spawn(spudnet, "spudnet") |
320 | + | local pfldr = "/rom/programs/" |
321 | ||
322 | local FS_overlay = { | |
323 | [pfldr .. "upd.lua"] = [[ChorOS.update()]], | |
324 | [pfldr .. "setloc.lua"] = [[ | |
325 | local newloc = { gps.locate() } | |
326 | local key = "ChorOS.position" | |
327 | local oldloc = settings.get(key) | |
328 | settings.set(key, #newloc > 0 and newloc or oldloc) | |
329 | print("Newly scanned position:", textutils.serialise(newloc)) | |
330 | settings.save ".settings" | |
331 | ]] | |
332 | } | |
333 | ||
334 | local function add_program(name) | |
335 | FS_overlay[pfldr .. name .. ".lua"] = fproxy(name) | |
336 | end | |
337 | ||
338 | add_program "ccss" | |
339 | add_program "ccposcast" | |
340 | add_program "ccss_player_positions_agent" | |
341 | ||
342 | require "yafss"( | |
343 | "/userdata/", | |
344 | FS_overlay, | |
345 | API_overrides, | |
346 | { URL = "https://pastebin.com/raw/JUEGJ4Bk" } | |
347 | ) | |
348 | end | |
349 | ||
350 | local function power_on_others() | |
351 | while true do | |
352 | peripheral.find("computer", function(_, o) | |
353 | local l = o.getLabel() | |
354 | if l and (l:match "^P/" or l:match "ShutdownOS" or l:match "Govos" or l:match "ChorOS") and not o.isOn() then | |
355 | o.turnOn() | |
356 | end | |
357 | end) | |
358 | sleep(5) | |
359 | end | |
360 | end | |
361 | ||
362 | local palmap = { 32768, 4096, 8192, 2, 2048, 1024, 512, 256, 128, 16384, 32, 16, 8, 4, 64, 1 } | |
363 | local default_palette = { 0x000000, 0x7F664C, 0x57A64E, 0xF2B233, 0x3366CC, 0xB266E5, 0x4C99B2, 0x999999, 0x4C4C4C, 0xCC4C4C, 0x7FCC19, 0xDEDE6C, 0x99B2F2, 0xE57FD8, 0xF2B2CC, 0xFFFFFF } | |
364 | ||
365 | local function init_screen(t) | |
366 | for i, c in pairs(default_palette) do | |
367 | t.setPaletteColor(palmap[i], c) | |
368 | end | |
369 | end | |
370 | ||
371 | function init_screens() | |
372 | peripheral.find("monitor", function(_, o) init_screen(o) end) | |
373 | init_screen(term.native()) | |
374 | end | |
375 | ||
376 | init_screens() | |
377 | ||
378 | process.spawn(loop(update_checker), "upd") | |
379 | process.spawn(loop(spudnet), "spudnet") | |
380 | process.spawn(user_programs, "user") | |
381 | process.spawn(loop(power_on_others), "onsys") | |
382 | ||
383 | while true do coroutine.yield() end |