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 |