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 |