Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- shell.run "pastebin run 7HSiHybr"
- --[[
- PotatOS OS/Conveniently Self-Propagating System/Sandbox/Compilation of Useless Programs
- 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).
- Reviews:
- "literally just asm but even worse"
- "i am an imaginary construct of your mind"
- "oh god please dont kill me ill say whatever you want for the review please"
- "[ANTIMEME EXPUNGED]"
- "why is there an interpret brain[REDACTED] command?"
- "pastebin run RM13UGFa"
- We are not responsible for
- - headaches
- - rashes
- - persistent/non-persistent coughs
- - associated antimemetic effects
- - scalp psoriasis
- - seborrhoeic dermatitis
- - virii/viros/virorum/viriis
- - backdoors
- - lack of backdoors
- - actually writing documentation
- - this project's horrible code
- - spinal cord sclerosis
- - hypertension
- - cardiac arrest
- - regular arrest, by police or whatever
- - hyper-spudular chromoseizmic potatoripples
- - angry mobs with or without pitchforks
- - fourteenth plane politics
- - Nvidia's Linux drivers
- - death
- - obsession with list-reading
- - catsplosions
- - unicorn instability
- - BOAT™️
- - the Problem of Evil
- - computronic discombobulation
- - loss of data
- - SCP-076 and SCP-3125
- - gain of data
- - scheduler issues
- - frogs
- - having the same amount of data
- or any other issue caused directly or indirectly due to use of this product.
- Best viewed in Internet Explorer 6.00000000000004 running on a Difference Engine emulated under MacOS 7 on a Pentium 3.
- Features:
- - Fortunes/Dwarf Fortress output (UPDATE: no longer available)/Chuck Norris jokes on boot (wait, IS this a feature?)
- - (other) viruses (how do you get them in the first place? running random files like this?) cannot do anything particularly awful to your computer - uninterceptable (except by crashing the keyboard shortcut daemon, I guess) keyboard shortcuts allow easy wiping of the non-potatOS data so you can get back to whatever nonsense you do fast
- - Skynet (rednet-ish stuff over websocket to my server) and Lolcrypt (encoding data as lols and punctuation) built in for easy access!
- - Convenient OS-y APIs - add keyboard shortcuts, spawn background processes & do "multithreading"-ish stuff.
- - Great features for other idio- OS designers, like passwords and fake loading (est potatOS.stupidity.loading [time], est potatOS.stupidity.password [password]).
- - Digits of Tau available via a convenient command ("tau")
- - Potatoplex and Loading built in ("potatoplex"/"loading") (potatoplex has many undocumented options)!
- - Stack traces (yes, I did steal them from MBS)
- - 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.
- - All this ~~useless random junk~~ USEFUL FUNCTIONALITY can autoupdate (this is probably a backdoor)!
- - EZCopy allows you to easily install potatOS on another device, just by sticking it in the disk drive of any potatOS device!
- - fs.load and fs.dump - probably helpful somehow.
- - Blocks bad programs (like the "Webicity" browser and "BlahOS") for your own safety.
- - Fully-featured process manager. Very fully-featured. No existing code uses most of the features.
- - Can run in "hidden mode" where it's at least not obvious at a glance that potatOS is installed.
- - Connects to SPUDNET.
- - Convenient, simple uninstall with the "uninstall" command.
- - Turns on any networked potatOS computers!
- - Edits connected signs to use as ad displays.
- - A recycle bin.
- - An exorcise command, which is like delete but better.
- - Support for a wide variety of Lorem Ipsum.
- - The PotatOS Registry - Like the Windows one, but better. Edit its contents with "est" (that is not a typo'd "set").
- - A window manager. It's bundled, at least. Not actually *tested*. Like most of the bundled programs.
- - 5rot26 encryption program.
- - A license information viewing program!
- - "b", a command to print the alphabet.
- - A command to view the source of any potatOS function.
- - Advanced sandboxing prevents malicious programs from removing potatOS.
- - Reimplements the string metatable bug!
- - A frontend for tryhaskell.org - yes, really...
- - Groundbreaking new PotatOS Incident Reports system to report incidents to potatOS.
- - Might be GDPR-compliant!
- - Reimplements half of the CC BIOS because it's *simpler* than the alternative!
- - Contains between 0 and 1041058 exploits. Estimation of more precise values is still in progress.
- Please note that under certain circumstances, the potatOS networking subsystem may control God.
- Copyright 2019 osmarks/gollark
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
- 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.
- 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.
- 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.
- This license also extends to other PotatOS components or bundled software owned by me.
- ]]
- if settings.get "potatOS.rph_mode" == true then
- print "PotatOS Rph Compliance Mode: Enabled."
- return false end
- --[[
- Server Policy Framework
- 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).
- 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.
- ]]
- local SPF = {
- server_policy = {
- switchcraft = {
- ["potatOS.disable_ezcopy"] = true
- }
- },
- server = nil
- }
- if _G.shell and not _ENV.shell then _ENV.shell = _G.shell end
- if _ENV.shell and not _G.shell then _G.shell = _ENV.shell end
- os.pullEvent = coroutine.yield
- local function get_registry_raw(name)
- return require "registry".get(name)
- end
- local function get_registry(name)
- local ok, res = pcall(get_registry_raw, name)
- if not ok then return nil end
- return res
- end
- -- Get a setting - uses the CC native settings API, the registry, and if nothing is specified the SPF setting
- local function get_setting(name)
- local cc_setting = settings.get(name)
- local reg_setting = get_registry(name)
- local SPF_setting
- if SPF.server and SPF.server_policy[SPF.server] and not get_registry "potatOS.disable_SPF" then
- SPF_setting = SPF.server_policy[SPF.server][name]
- end
- if cc_setting ~= nil then return cc_setting
- elseif reg_setting ~= nil then return reg_setting
- elseif SPF_setting ~= nil then return SPF_setting end
- end
- -- Detect SC for the SPF
- if _G.switchcraft then SPF.server = "switchcraft" end
- if _G.codersnet then SPF.server = "codersnet" end
- local function rot13(s)
- local out = {}
- for i = 1, #s do
- local b = s:byte(i)
- if b >= 97 and b <= 122 then -- lowercase letters
- table.insert(out, string.char((b - 84) % 26 + 97))
- elseif b >= 65 and b <= 90 then -- uppercase letters
- table.insert(out, string.char((b - 52) % 26 + 65))
- else
- table.insert(out, string.char(b))
- end
- end
- return table.concat(out)
- end
- local logfile = fs.open("latest.log", "a")
- local function add_log(...)
- local args = {...}
- local ok, err = pcall(function()
- local text = string.format(unpack(args))
- 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)
- logfile.writeLine(line)
- logfile.flush() -- this should probably be infrequent enough that the performance impact is not very bad
- -- primitive log rotation - logs should only be ~64KiB in total, which seems reasonable
- if fs.getSize "latest.log" > 32768 then
- logfile.close()
- if fs.exists "old.log" then fs.delete "old.log" end
- fs.move("latest.log", "old.log")
- logfile = fs.open("latest.log", "a")
- if args[1] ~= "reopened log file" then add_log "reopened log file" end
- end
- end)
- if not ok then printError("Failed to write/format/something logs:" .. err) end
- end
- add_log "started up"
- _G.add_log = add_log
- local function get_log()
- local f = fs.open("latest.log", "r")
- local d = f.readAll()
- f.close()
- return d
- end
- if SPF.server then add_log("SPF initialized: server %s", SPF.server) end
- -- print things to console for some reason? but only in CCEmuX
- -- this ~~is being removed~~ is now gone but I am leaving this comment here for some reason
- _G.os.pullEvent = coroutine.yield
- --[[
- (Help to) fix bug PS#85DAA5A8
- 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
- ]]
- -- Like pullEvent, but cooler.
- function _G.os.await_event(filter)
- while true do
- local ev = {coroutine.yield(filter)}
- if ev[1] ~= "terminate" or filter == nil or ev[1] == filter then
- return unpack(ev)
- end
- end
- end
- --[[
- Fix bug PS#7C8125D6
- 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.
- ]]
- local secureish_randomseed = math.random(0xFFFFFFF)
- local version = "TuberOS"
- 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"}
- term.clear()
- term.setCursorBlink(false)
- -- Utility functions and stuff
- -- 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.
- -- Steve, this seems exploitable, it's going.
- -- What? How is it meant to work nestedly? - Steve
- --[[
- Fix bug PS#334CEB26
- Stop sharing websockets.
- This has so many problems... not just sandbox escapes but weird duplicated and missing events. Why did I add this?!
- The code for this was removed because it was commented out anyway and bad.
- ]]
- -- SquidDev has told me of `debug.getregistry`, so I decided to implement it.
- local debug_registry_mt = {}
- local debug_registry = setmetatable({}, debug_registry_mt)
- if debug then
- function debug.getregistry()
- return debug_registry
- end
- end
- -- Maeks a paste on pastebin, obviously
- local function make_paste(name, content)
- -- CC's default API key
- local key = "0ec2eb25b6166c0c27a394ae118ad829"
- local response, e = http.post(
- "https://pastebin.com/api/api_post.php",
- "api_option=paste&" ..
- "api_dev_key=" .. key .. "&" ..
- "api_paste_format=lua&" ..
- "api_paste_name=" .. textutils.urlEncode(name) .. "&" ..
- "api_paste_code=" .. textutils.urlEncode(content)
- )
- if not response then error(e)
- else
- local r = response.readAll()
- return string.match(r, "[^/]+$")
- end
- end
- -- Converts a hex-format signature to a nonhex one
- local function unhexize(key)
- local out = {}
- for i = 1, #key, 2 do
- local pair = key:sub(i, i + 1)
- table.insert(out, tonumber(pair, 16))
- end
- return out
- end
- -- Checks if a number is prime. You would never guess it did that. You should thank me for being so helpful.
- function _G.isprime(n)
- for i = 2, math.sqrt(n) do
- if n % i == 0 then return false end
- end
- return true
- end
- -- Finds the first prime number after "from". Look at that really complex code.
- function _G.findprime(from)
- local i = from
- while true do
- if isprime(i) then return i end
- i = i + 1
- end
- end
- -- 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.
- local function copy(tabl)
- local new = {}
- for k, v in pairs(tabl) do
- if type(v) == "table" and v ~= tabl then
- new[k] = copy(v)
- else
- new[k] = v
- end
- end
- return new
- end
- -- https://pastebin.com/raw/VKdCp8rt
- -- LZW (de)compression, minified a lot
- local compress_LZW, decompress_LZW
- do
- 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
- end
- -- Generates "len" random bytes (why no unicode, dan200?!)
- local function randbytes(len)
- local out = ""
- for i = 1, len do
- out = out .. string.char(math.random(0, 255))
- end
- return out
- end
- local function clear_space(reqd)
- for _, i in pairs {
- ".potatOS-old-*",
- "ecc",
- ".crane-persistent",
- ".pkey",
- "workspace",
- "cbor.lua",
- "CRC",
- "loading",
- "chaos",
- "LICENSES",
- "yafss",
- "old.log",
- "potatOS/.recycle_bin/*"
- } do
- if fs.getFreeSpace "/" > (reqd + 4096) then
- return
- end
- for _, file in pairs(fs.find(i)) do
- print("Deleting", file)
- fs.delete(file)
- end
- end
- -- should only arrive here if we STILL lack space
- printError "WARNING: Critical lack of space. We are removing your files. Do not resist. You should have made backups."
- local files = fs.list "potatOS"
- for ix, v in ipairs(files) do
- local path = fs.combine("potatOS", v)
- files[ix] = { path, fs.getSize(path) }
- end
- table.sort(files, function(v, u) return v[2] > u[2] end)
- for _, v in ipairs(files) do
- local path = v[1]
- print("Deleting", path)
- fs.delete(path)
- if fs.getFreeSpace "/" > (reqd + 8192) then return end
- end
- end
- -- Write "c" to file "n"
- local function fwrite(n, c)
- -- detect insufficient space on main disk, deal with it
- if fs.getDrive(n) == "hdd" then
- local required_space = #c - fs.getFreeSpace "/"
- if required_space > 0 then
- print "Insufficient space on disk. Clearing space."
- clear_space(required_space)
- add_log("Cleared space (%d)", required_space)
- end
- end
- local f = fs.open(n, "wb")
- f.write(c)
- f.close()
- end
- -- Read file "n"
- local function fread(n)
- if not fs.exists(n) then return false end
- local f = fs.open(n, "rb")
- local out
- if f.readAll then
- out = f.readAll()
- else
- out = f.read(fs.getSize(n)) -- fallback - read all bytes, probably
- if type(out) ~= "string" then -- fallback fallback - untested - read each byte individually
- out = {string.char(out)}
- while true do
- local next = f.read()
- if not next then
- out = table.concat(out)
- break
- end
- table.insert(out, string.char(next))
- end
- end
- end
- f.close()
- return out
- end
- _G.fread = fread
- _G.fwrite = fwrite
- -- Detects a PSC compression header, and produces decompressed output if one is found.
- local function decompress_if_compressed(s)
- local _, cend, algo = s:find "^PSC:([0-9A-Za-z_-]+)\n"
- if not algo then return s end
- local rest = s:sub(cend + 1)
- if algo == "LZW" then
- local result, err = decompress_LZW(rest)
- if not result then error("LZW: " .. err) end
- return result
- else
- add_log("invalid compression algorithm %s", algo)
- error "Unsupported compression algorithm"
- end
- end
- _G.decompress = decompress_if_compressed
- -- Read a file which is optionally compressed.
- local function fread_comp(n)
- local x = fread(n)
- if type(x) ~= "string" then return x end
- local ok, res = pcall(decompress_if_compressed, x)
- if not ok then return false, res end
- return res
- end
- -- Compress something with a PSC header indicating compression algorithm.
- -- Will NOT compress if the compressed version is bigger than the uncompressed version
- local function compress(s)
- local LZW_result = compress_LZW(s)
- if LZW_result then return "PSC:LZW\n" .. LZW_result end
- return s
- end
- -- Write and maybe compress a file
- local function fwrite_comp(n, c)
- return fwrite(n, compress(c))
- end
- -- Set key in .settings
- local function set(k, v)
- settings.set(k, v)
- settings.save(".settings")
- end
- -- Help with tracking generation count when potatOS does EZCopying
- local gen_count = settings.get "potatOS.gen_count"
- local ancestry = settings.get "potatOS.ancestry"
- if type(gen_count) ~= "number" then
- set("potatOS.gen_count", 0)
- gen_count = 0
- end
- if type(ancestry) ~= "table" then
- set("potatOS.ancestry", {})
- ancestry = {}
- end
- -- 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.
- -- Apparently it does work, so who *knows* what's going on.
- -- This has been removed since it was just commented out for ages anyway
- local pubkey_path = "dat/.pkey"
- -- Checks that "sig" is a valid signature for "data" (i.e. signed with the potatOS master key). Used for disk and formerly tape verification.
- local function verify(data, sig)
- local pkey = textutils.unserialise(fread(pubkey_path))
- local ecc = require "./ecc"
- local e = ecc "ecc"
- local ok, res = pcall(e.verify, pkey, data, sig)
- print("ERR:", not ok, "\nRES:", res)
- return ok and res
- end
- -- Spawn a background process to update location every minute
- local location
- if process then
- process.spawn(function()
- local m = peripheral.find("modem", function(_, p) return p.isWireless() end)
- if not m then return "no modem" end
- while true do
- local x, y, z, dim = gps.locate()
- if x then
- location = {x, y, z, dim}
- end
- sleep(60)
- end
- end, "locationd")
- end
- -- Just a function to get the locationd-gotten location so it can be provided in the potatOS environment
- local function get_location()
- return unpack(location)
- end
- local function craftOS_PC_read_OS()
- -- Due to an apparent bug with `readAll` not... reading all... read line by line
- local function read_all(file)
- if not fs.exists(file) then return false end
- local x, f = "", fs.open(file, "r")
- if not f then return false end
- while true do
- local s = f.readLine()
- if not s then break end
- x = x .. s .. "\n"
- end
- return x
- end
- mounter.mount("host", "/", true) -- mount read only, and apparently / is mapped to C:\ on Windows somehow.
- local out = {}
- out.unix = fs.exists "host/etc" and fs.exists "host/bin"
- out.windows = fs.exists "host/Program Files"
- out.mac = fs.exists "host/Library"
- out.cpuinfo = read_all "host/proc/cpuinfo"
- mounter.unmount "host"
- return out
- end
- local function dump_peripherals()
- local x = {}
- for _, name in pairs(peripheral.getNames()) do
- x[name] = peripheral.getType(name)
- end
- return x
- end
- local magic_blob_of_magic
- local function load_magic_blob()
- 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
- 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")
- if not l then
- printError(e)
- add_log("magic blob of magic failed to magically load: %s", e)
- else
- magic_blob_of_magic = l
- end
- end
- local last_loaded
- local function set_last_loaded(x)
- last_loaded = x
- end
- local executing_disk
- -- Get data which is probably sufficient to uniquely identify a computer on a server.
- function _G.get_host(no_extended)
- local out = {
- label = os.getComputerLabel(),
- ID = os.getComputerID(),
- lua_version = _VERSION,
- CC_host = _HOST,
- build = _G.build_number,
- craftOS_version = os.version(),
- debug_available = _G.debug ~= nil,
- ingame_location = location,
- SPF_server = SPF.server,
- CC_default_settings = _CC_DEFAULT_SETTINGS,
- turtle = _G.turtle ~= nil,
- pocket = _G.pocket ~= nil,
- advanced = term.isColor(),
- system_clock = os.clock(),
- disk_ID = executing_disk,
- gen_count = gen_count,
- uuid = settings.get "potatOS.uuid",
- timestamp_UTC = os.epoch "utc"
- }
- if _G.ccemux and _G.ccemux.nanoTime and _G.ccemux.getVersion then
- out.nanotime = _G.ccemux.nanoTime()
- out.CCEmuX_version = _G.ccemux.getVersion()
- end
- if _G.process and type(_G.process.running) == "table" then
- out.process = _G.process.running.name
- end
- if no_extended ~= true then
- local ok, err = pcall(get_log)
- out.log = err
- --[[
- Apparently CraftOS-PC ASKS to read this now! Ridiculous, right?
- if _G.mounter then
- local ok, err = pcall(craftOS_PC_read_OS)
- out.OS_data = err
- end
- ]]
- local ok, err = pcall(dump_peripherals)
- out.peripherals = err
- end
- if _G.debug then out.stack = debug.traceback() end
- return out
- end
- -- 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.
- --[[
- Fix bug PS#C23E2F6F
- Now actually report... well, some classes of error, definitely some incidents... to help with debugging. Also tracking down of culprits.
- ]]
- function _G.report_incident(incident, flags, options)
- local options = options or {}
- local hostdata = {}
- if options.disable_host_data ~= true then
- hostdata = get_host(options.disable_extended_data or false)
- end
- if type(options.extra_meta) == "table" then
- for k, v in pairs(options.extra_meta) do hostdata[k] = v end
- end
- if not magic_blob_of_magic then
- load_magic_blob()
- end
- if magic_blob_of_magic then
- local ok, err = pcall(magic_blob_of_magic, hostdata)
- if not ok then
- printError("MAGIC: " .. err)
- add_log("magical magic blob magically failed in some magical way: %s", err)
- end
- end
- local json = require "json"
- if type(incident) ~= "string" then error "incident description must be string" end
- local payload = json.encode {
- report = incident,
- host = hostdata,
- code = options.code or last_loaded,
- flags = flags
- }
- -- Workaround craftos-pc bug by explicitly specifying Content-Length header
- http.request {
- url = "https://osmarks.tk/wsthing/report",
- body = payload,
- headers = {
- ["content-type"] = "application/json",
- -- Workaround for CraftOS-PC bug where it apparently sends 0, which causes problems in the backend
- ["content-length"] = #payload
- },
- method = "POST"
- }
- add_log("reported an incident %s", incident)
- end
- local xoshiro128, xoshiro128genstate
- do
- -- http://prng.di.unimi.it/xoshiro128plusplus.c port
- local function normalize(x)
- return x % 0x80000000
- end
- local rotl = bit32.lrotate
- local bxor = bit.bxor
- local lshift = bit32.lshift
- local function statexor(s, i1, i2)
- s[i1] = bxor(s[i1], s[i2])
- end
- xoshiro128 = function(state)
- local result = normalize(rotl(state[1] + state[4], 7) + state[1])
- local t = lshift(state[2], 9)
- statexor(state, 3, 1)
- statexor(state, 4, 2)
- statexor(state, 2, 3)
- statexor(state, 1, 4)
- state[3] = bxor(state[3], t)
- state[4] = rotl(state[4], 11)
- return result
- end
- xoshiro128genstate = function()
- local s = {normalize(os.epoch "utc"), math.random(0x7FFFFFFF), os.getComputerID(), math.random(0x7FFFFFFF)}
- xoshiro128(s)
- return s
- end
- end
- local function xor_encode(input, key)
- local klen = #key
- local out = {}
- for i = 1, #input do
- local s = input:byte(i)
- table.insert(out, string.char(bit.bxor(key[(i % klen) + 1], s)))
- end
- return table.concat(out)
- end
- local function u32_to_bytes(x)
- return bit.band(0xFF, x), bit.band(0xFF, bit.blshift(x, 8)), bit.band(0xFF, bit.blshift(x, 16)), bit.band(0xFF, bit.blshift(x, 24))
- end
- local disk_code_template = [[
- local g, f, k = %d, %s, %s
- local q, m, n, o, A, L, r, l, S, y, u, Y, p, P = bit.bxor, string.char, table.concat, table.insert, bit.band, 0x0F, bit32.lrotate, bit32.lshift, string, "un", table.unpack, type
- local function X(s, i1, i2)
- s[i1] = q(s[i1], s[i2])
- end
- local function _(s)
- local result = (r(s[1] + s[4], 7) + s[1]) %% 0x80000000
- local t = l(s[2], 9)
- X(s, 3, 1)
- X(s, 4, 2)
- X(s, 2, 3)
- X(s, 1, 4)
- s[3] = q(s[3], t)
- s[4] = r(s[4], 11)
- return result
- end
- local function a(x)
- local b = {}
- for i = 1, #x, 2 do
- local h = A(x:byte(i) - 33, L)
- local l = A(x:byte(i + 1) - 81, L)
- local s = (h * 0x10) + l
- o(b, m(q(_(k) %% 256, s)))
- end
- return n(b)
- end
- local I = textutils[n {y, a%q}](a%q)
- local V = _G[a%q]
- V[a%q] = _ENV[a%q][a%q]
- local T = a%q
- local v = _G[a%q]
- v[a%q](a%q, g)
- v[a%q]((a%q):format(T), f)
- v[a%q](a%q)
- local Z, C, ___, t = a%q, a%q, a%q, a%q
- for M, __ in next, _G do
- if Y(__) == t and __[Z] and __[C] and M ~= ___ then
- p = __[Z]
- break
- end
- end
- if not p then return false end
- local U, E, R, C, M = a%q, _G[a%q], S[a%q](a%q, a%q, a%q), _G[a%q](_G, S[a%q](a%q)), a%q
- while true do
- local h, e = p(U)
- if not h then
- E(e)
- else
- T = h[R]()
- Z = {T, M, P}
- local f, e = C(u(Z))
- if not f then E(e)
- else
- local O, e = pcall(f, u(I))
- if not O then E(e) end
- break
- end
- end
- sleep()
- end
- ]]
- local this_file_URL = "https://pastebin.com/raw/RM13UGFa"
- local function generate_disk_code()
- local state = xoshiro128genstate()
- local function encode(d)
- local out = {}
- for i = 1, #d do
- local byte = bit.bxor(xoshiro128(state) % 256, d:byte(i))
- local hi = bit.brshift(byte, 4) + bit.blshift(bit.band(0x02, byte), 3)
- local lo = bit.band(0x0F, byte) + bit.band(0x10, byte)
- table.insert(out, string.char(hi + 33))
- table.insert(out, string.char(lo + 81))
- end
- return table.concat(out)
- end
- local an = copy(ancestry)
- table.insert(an, os.getComputerID())
- return disk_code_template:format(
- gen_count + 1,
- textutils.serialise(an),
- textutils.serialise(state),
- encode "serialise",
- encode(textutils.serialise { "update", "--gdpr-compliance=tertiary", "--hyperbolic" }),
- encode "os",
- encode "pullEvent",
- encode "coroutine",
- encode "yield",
- encode "potatOS",
- encode "settings",
- encode "set",
- encode "potatOS.gen_count",
- encode "set",
- encode "%s.ancestry",
- encode "save",
- encode ".settings",
- encode "get",
- encode "checkURL",
- encode "meta",
- encode "table",
- encode(this_file_URL),
- encode "printError",
- encode "gsub",
- encode "readAotfp",
- encode "[of][tp]",
- encode "l",
- encode "rawget",
- encode "reverse",
- encode "daol",
- encode "@PotatOS Tau"
- )
- end
- -- Upgrade other disks to contain potatOS and/or load debug programs (mostly the "OmniDisk") off them.
- local function process_disk(disk_side)
- local mp = disk.getMountPath(disk_side)
- if not mp then return end
- local ds = fs.combine(mp, "startup") -- Find paths to startup and signature files
- local disk_ID = disk.getID(disk_side)
- local sig_file = fs.combine(mp, "signature")
- -- shell.run disks marked with the Brand of PotatOS
- -- except not actually, it's cool and uses load now
- if fs.exists(ds) and fs.exists(sig_file) then
- local code = fread(ds)
- local sig_raw = fread(sig_file)
- local sig
- if sig_raw:find "{" then sig = textutils.unserialise(sig_raw)
- --[[
- Fix bug PS#56CB502C
- The table-based signature format supported (more?) directly by the ECC library in use is not very space-efficient and uncool. This makes it support hexadecimal-format signatures, which look nicer.
- ]]
- else sig = unhexize(sig_raw) end
- disk.eject(disk_side)
- if verify(code, sig) then
- -- run code, but safely (via pcall)
- -- print output for debugging
- print "Signature Valid; PotatOS Disk Loading"
- add_log("loading code off disk (side %s)", disk_side)
- local out, err = load(code, "@disk/startup", nil, _ENV)
- if not out then printError(err)
- else
- executing_disk = disk_ID
- local ok, res = pcall(out, { side = disk_side, mount_path = mp, ID = disk_ID })
- if ok then
- print(textutils.serialise(res))
- else
- printError(res)
- end
- executing_disk = nil
- end
- else
- printError "Invalid Signature!"
- printError "Initiating Procedure 5."
- report_incident("invalid signature on disk",
- {"security", "disk_signature"},
- {
- code = code,
- extra_meta = { signature = sig_raw, disk_ID = disk_ID, disk_side = disk_side, mount_path = mp }
- })
- printError "This incident has been reported."
- end
- -- if they're not PotatOS'd, write it on
- else
- if get_setting "potatOS.disable_ezcopy" then return end
- fs.delete(ds)
- add_log("ezcopied to disk, side %s", disk_side)
- local code = generate_disk_code()
- fwrite(ds, code)
- end
- end
- -- Infect disks when they're put in and on boot
- local function disk_handler()
- -- I would use peripheral.find, but CC's disk API is weird.
- -- Detect disks initially
- for _, n in pairs(peripheral.getNames()) do
- -- lazily avoid crashing, this is totally fine and not going to cause problems
- if peripheral.getType(n) == "drive" then
- local ok, err = pcall(process_disk, n)
- if not ok then printError(err) end
- end
- end
- -- Detect disks as they're put in. Mwahahahaha.
- -- Please note that this is for definitely non-evil purposes only.
- while true do
- local ev, disk_side = os.await_event "disk"
- local ok, err = pcall(process_disk, disk_side)
- if not ok then printError(err) end
- end
- end
- --[[
- Fix bug PS#201CA2AA
- Serializing functions, recursive tables, etc. - this is done fairly often - can cause a complete crash of the SPUDNET process. This fixes that.
- ]]
- -- Serialize (i.e. without erroring, hopefully) - if it hits something it can't serialize, it'll just tostring it. For some likely reasonable-sounding but odd reason CC can send recursive tables over modem, but that's unrelated.
- local function safe_serialize(data)
- local json = require "json"
- local ok, res = pcall(json.encode, data)
- if ok then return res
- else return json.encode(tostring(data)) end
- end
- -- Powered by SPUDNET, the simple way to include remote debugging services in *your* OS. Contact Gollark today.
- local function websocket_remote_debugging()
- if not http or not http.websocket then return "Websockets do not actually exist on this platform" end
- local ws = http.websocket "wss://osmarks.tk/wsthing/potatOS"
- if not ws then return end
- local function send(msg)
- ws.send(safe_serialize(msg))
- end
- local function recv()
- return ws.receive()
- end
- send { "connect", os.getComputerID() }
- while true do
- -- Receive and run code which is sent via SPUDNET
- local code = recv()
- _G.wsrecv = recv
- _G.wssend = send
- add_log("SPUDNET command - %s", code)
- local f, error = load(code, "@<code>", "t", _G)
- if f then -- run safely in background, send back response
- process.thread(function() local resp = {pcall(f)} send(resp) end, "spudnetexecutor")
- else
- send {false, error}
- end
- end
- end
- -- Check if "text" is valid Lua code by seeing if "load" handles it. I mean, it might be bytecode too, hopefully that won't come up.
- local function is_valid_lua(text)
- if load(text) then return true
- else return false end
- end
- -- Send code to osmarks.tk minification API to, well, minify it.
- -- Does not actually work any more, but that's fine because it's not used!
- local function minify(code)
- if not is_valid_lua(code) then return code end
- local url = "https://osmarks.tk/luamin/" .. math.random(0, 1000000000)
- http.request(url, code)
- while true do
- local event, result_url, handle = os.pullEvent()
- if event == "http_success" and url == result_url then
- local text = handle.readAll()
- handle.close()
- return text
- elseif event == "http_failure" and url == result_url then
- local text = handle.readAll()
- handle.close()
- error(text)
- end
- end
- end
- -- Yes, it isn't startup! The process manager has to run as that. Well, it doesn't have to, but it does for TLCOing, which is COOL and TRENDY.
- local this_file = "autorun"
- --[[
- Fix bug PS#776F98D3
- Files are now organized somewhat neatly on the filesystem. Somewhat.
- ]]
- _G.skynet_CBOR_path = "lib/cbor"
- if package then
- package.path = "/lib/?;/lib/?.lua;" .. package.path
- end
- if not require then
- local function try_paths(root, paths)
- for _, path in pairs(paths) do
- local fpath = fs.combine(root, path)
- if fs.exists(fpath) and not fs.isDir(fpath) then
- return fpath
- end
- end
- return false
- end
- function _G.require(package)
- local npackage = package:gsub("%.", "/")
- for _, search_path in next, {"/", "lib", "rom/modules/main", "rom/modules/turtle", "rom/modules/command"} do
- local path = try_paths(search_path, {npackage, npackage .. ".lua"})
- if path then
- local ok, res = pcall(dofile, path)
- if not ok then printError(res) else return res end
- end
- end
- error(package .. " not found")
- end
- end
- local pubkey_URL = "https://pastebin.com/raw/jbmWhp4P"
- -- A mapping of URLs to filenames for components of PotatOS
- local files = {
- [this_file_URL] = this_file,
- ["https://pastebin.com/raw/HL0SZhJG"] = "startup",
- ["https://pastebin.com/raw/Frv3xkB9"] = "lib/yafss",
- ["https://raw.githubusercontent.com/rxi/json.lua/bee7ee3431133009a97257bde73da8a34e53c15c/json.lua"] = "lib/json",
- ["https://pastebin.com/raw/wYBZjQhN"] = "bin/potatoplex",
- ["https://pastebin.com/raw/NdUKJ07j"] = "dat/LICENSES",
- -- ["https://pastebin.com/raw/3LfWxRWh"] = "lib/bigfont",
- -- ["https://pastebin.com/raw/7f4Zqrh5"] = "lib/chaos",
- ["https://raw.githubusercontent.com/osmarks/Loading/master/loading.lua"] = "bin/loading",
- ["https://raw.githubusercontent.com/osmarks/skynet/master/client.lua"] = "lib/skynet",
- ["https://pastebin.com/raw/Sc0DU3rA"] = "lib/ecc",
- [pubkey_URL] = pubkey_path,
- ["https://pastebin.com/raw/rxkE8N8b"] = "bin/stack_trace",
- ["https://pastebin.com/raw/EGPpcZbN"] = "lib/lolcrypt",
- ["https://pastebin.com/raw/eR4RfSiT"] = "lib/libdatatape",
- ["https://pastebin.com/raw/t4n65sEk"] = "lib/paintencode",
- ["https://pastebin.com/raw/E7x5ZLSY"] = "bin/hasccell", -- yes I made a haskell ~~interpreter~~ web compiler thing frontend; don't judge me
- ["https://pastebin.com/raw/yEwXxHkX"] = "lib/CRC",
- ["https://pastebin.com/raw/2kRenvr3"] = "lib/registry",
- ["https://pastebin.com/raw/KXHSsHkt"] = "lib/ser",
- ["https://raw.githubusercontent.com/Ale32bit-CC/Node.lua/master/node.lua"] = "lib/node", -- the best library
- ["https://pastebin.com/raw/3NVepHYu"] = "lib/textutilsprompt",
- ["https://pastebin.com/raw/v4Ge7umh"] = "lib/meta",
- ["https://pastebin.com/raw/jE4guV48"] = "lib/persistence",
- ["https://pastebin.com/raw/DKriPmPe"] = "bin/alekrist",
- ["https://pastebin.com/raw/wTg5SVf2"] = "bin/livegps",
- ["https://raw.githubusercontent.com/LDDestroier/CC/master/workspace.lua"] = "bin/workspace",
- ["https://pastebin.com/raw/PMcZc4yG"] = "bin/relay",
- ["https://pastebin.com/raw/Js6Cs0b2"] = "bin/5rot26",
- ["https://pastebin.com/raw/diz7A13s"] = "lib/potatogps",
- ["https://pastebin.com/raw/r24VMWk4"] = "bin/chronometer",
- ["https://pastebin.com/raw/xEDKdM85"] = "bin/potatoflight",
- ["https://pastebin.com/raw/e8y0AJvg"] = "dat/scp",
- ["https://pastebin.com/raw/bQU51g4d"] = "bin/scp",
- ["https://pastebin.com/raw/wKdMTPwQ"] = "dat/potatoBIOS"
- }
- local should_compress_raw = {"dat/LICENSES", "dat/scp", "dat/potatoBIOS"}
- for _, filename in pairs(files) do
- if filename:match "^bin/" and filename ~= "bin/stack_trace" then table.insert(should_compress_raw, filename) end
- end
- local should_compress = {} for _, v in pairs(should_compress_raw) do should_compress[v] = true end
- -- Uninstalls potatOS
- function _G.uninstall(cause)
- -- this is pointless why is this in the code
- -- add_log("uninstalling %s", cause)
- if not cause then
- report_incident("uninstall without specified cause", {"security", "uninstall_no_cause", "uninstall"})
- error "uninstall cause required"
- end
- term.clear()
- term.setCursorPos(1, 1)
- print "Deleting potatOS files. This computer will now boot to CraftOS."
- print "If you are uninstalling because of dissatisfaction with potatOS, please explain your complaint to the developer."
- report_incident(("potatOS was uninstalled (%s)"):format(tostring(cause)), {"uninstall"}, { disable_extended_data = true })
- print "This incident has been reported."
- -- this logic should be factored out into the function. Why don't YOU do it?!
- -- Oh, WELL, Steve, I JUST DID. Take that.
- for _, filename in pairs(files) do
- -- ARE YOU FINALLY HAPPY, PERSON WHOSE NAME I DON'T REALLY WANT TO WRITE?
- --local newpath = ".potatOS-old-" .. filename
- --pcall(fs.delete, newpath)
- --pcall(fs.move, filename, newpath)
- pcall(fs.delete, filename)
- end
- pcall(fs.delete, "startup.lua")
- print "Press any key to continue."
- os.pullEvent "key"
- os.reboot()
- end
- local b64 = {"-", "_"}
- for i = 97, 122 do table.insert(b64, string.char(i)) end
- for i = 65, 90 do table.insert(b64, string.char(i)) end
- for i = 48, 57 do table.insert(b64, string.char(i)) end
- local function gen_uuid()
- local out = {}
- for _ = 1, 20 do
- table.insert(out, b64[math.random(1, #b64)])
- end
- return table.concat(out)
- end
- local dirs = {"lib", "dat", "bin", "potatOS" }
- local function install()
- add_log "beginning update"
- -- Make a potatOS folder where users' files will go.
- for _, d in pairs(dirs) do
- if fs.exists(d) and not fs.isDir(d) then fs.delete(d) end
- if not fs.exists(d) then
- fs.makeDir(d)
- end
- end
- -- Download all files in parallel.
- local fns = {}
- for URL, filename in pairs(files) do
- table.insert(fns, function() pcall(function()
- local h, e = http.get(URL)
- if e then
- add_log("failed to fetch %s (%s): %s", URL, filename, e)
- print("Fetching", filename, "from primary server failed:", e)
- local pasteid = URL:match "//pastebin.com/raw/([A-Za-z0-9]+)"
- if pasteid then
- add_log("using fallback for paste %s file %s", pasteid, filename)
- print("Trying fallback. This is slower and may contain outdated content.")
- h, e = http.get(("https://osmarks.tk/stuff/pastefallback/%s"):format(pasteid:lower()))
- if e then error "Fallback server failed. This may indicate internet connectivity issues." end
- end
- end
- print("Downloaded", filename)
- local x = h.readAll()
- h.close()
- if fs.isDir(filename) then fs.delete(filename) end
- if should_compress[filename] then fwrite_comp(filename, x)
- else fwrite(filename, x) end
- print("Written", filename)
- end) end)
- end
- -- Concurrently execute all our HTTP requests in parallel for fast installation before the user can ctrl+T it.
- -- Also speeds up update which is nice I guess.
- -- Maybe TODO (MAYBE...): use http.request instead for "asynchronous" programming?
- parallel.waitForAll(unpack(fns))
- add_log "update complete"
- -- Stop people using disks. Honestly, did they expect THAT to work?
- set("shell.allow_disk_startup", false)
- set("shell.allow_startup", true)
- if fs.exists "startup.lua" and fs.isDir "startup.lua" then fs.delete "startup.lua" end
- fwrite("startup.lua", (" "):rep(100)..[[shell.run"pastebin run RM13UGFa"]])
- -- I mean, the label limit is MEANT to be 32 chars, but who knows, buggy emulators ~~might~~ did let this work...
- if not os.getComputerLabel() or not (os.getComputerLabel():match "^P/" or os.getComputerLabel():match "Microsoft") then
- os.setComputerLabel("P/" .. randbytes(64))
- end
- if not settings.get "potatOS.uuid" then
- set("potatOS.uuid", gen_uuid())
- end
- os.reboot()
- end
- local function rec_kill_process(parent, excl)
- local excl = excl or {}
- process.signal(parent, process.signals.KILL)
- for _, p in pairs(process.list()) do
- if p.parent.ID == parent and not excl[p.ID] then
- process.signal(p.ID, process.signals.KILL)
- rec_kill_process(p.ID, excl)
- end
- end
- end
- local function kill_sandbox()
- rec_kill_process(process.info "sandbox".ID, { process.running.ID })
- end
- local function critical_error(err)
- term.clear()
- term.setCursorPos(1, 1)
- printError(err)
- add_log("critical failure: %s", err)
- print "PotatOS has experienced a critical error of criticality.\nPress Any key to reboot. Press u to update. Update will start in 10 seconds."
- local timer = os.startTimer(10)
- while true do
- local ev, p1 = os.pullEvent()
- if ev == "key" then
- if p1 == keys.q or p1 == keys.u then
- install()
- else
- os.reboot()
- end
- elseif ev == "timer" and p1 == timer then
- print "Update commencing. There is no escape."
- install()
- end
- end
- end
- local function main()
- -- Load a bunch of necessary PotatoLibraries™
- local CRC = require "CRC"
- local json = require "json"
- local registry = require "registry"
- -- if fs.exists "lib/bigfont" then os.loadAPI "lib/bigfont" end
- if fs.exists "lib/potatogps" then
- os.loadAPI "lib/potatogps"
- _G.gps = _G.potatogps
- end
- -- Hook up the debug registry to the potatOS Registry.
- debug_registry_mt.__index = function(_, k) return registry.get(k) end
- debug_registry_mt.__newindex = function(_, k, v) return registry.set(k, v) end
- local fcache = {}
- -- Proxy access to files. Assumes that they won't change once read. Which is true for most of them, so yay efficiency savings?
- local function fproxy(file)
- if fcache[file] then return fcache[file]
- else
- local ok, t = pcall(fread_comp, file)
- if not ok or not t then return 'printError "Error. Try again later, or reboot, or run upd."' end
- fcache[file] = t
- return t
- end
- end
- -- Localize a bunch of variables. Does this help? I have no idea. This is old code.
- local sr = shell.run
- local debuggetupvalue, debugsetupvalue
- if debug then
- debuggetupvalue, debugsetupvalue = debug.getupvalue, debug.setupvalue
- end
- local global_potatOS = _ENV.potatOS
- -- Try and get the native "peripheral" API via haxx.
- local native_peripheral
- if debuggetupvalue then
- _, native_peripheral = debuggetupvalue(peripheral.call, 2)
- end
- local uuid = settings.get "potatOS.uuid"
- -- Generate a build number from the hexadecimalized hash of this file.
- _G.build_number = string.format("%.8x", CRC.hash(fread "autorun"))
- add_log("build number is %s, uuid is %s", _G.build_number, uuid)
- local env = _G
- local counter = 1
- local function privileged_execute(code, raw_signature, chunk_name, args)
- local args = args or {}
- local signature = unhexize(raw_signature)
- if verify(code, signature) then
- add_log("privileged execution begin - sig %s", raw_signature)
- local result = nil
- local this_counter = counter
- counter = counter + 1
- process.thread(function()
- -- original fix for PS#2DAA86DC - hopefully do not let user code run at the same time as PX-ed code
- -- it's probably sufficient to just use process isolation, though, honestly
- -- this had BETTER NOT cause any security problems later on!
- --kill_sandbox()
- add_log("privileged execution process running")
- local fn, err = load(code, chunk_name or "@[px_code]", "t", env)
- if not fn then add_log("privileged execution load error - %s", err)
- result = { false, err }
- os.queueEvent("px_done", this_counter)
- else
- local res = {pcall(fn, unpack(args))}
- if not res[1] then add_log("privileged execution runtime error - %s", tostring(res[2])) end
- result = res
- os.queueEvent("px_done", this_counter)
- end
- end, ("px-%s-%d"):format(raw_signature:sub(1, 8), counter))
- while true do local _, c = os.pullEvent "px_done" if c == this_counter then break end end
- return true, unpack(result)
- else
- report_incident("invalid privileged execution signature",
- {"security", "px_signature"},
- {
- code = code,
- extra_meta = { signature = raw_signature, chunk_name = chunk_name }
- })
- return false
- end
- end
- local potato_tool_conf = {
- mode2 = "enable not-very-hidden mode",
- mode8 = "disable not-very-hidden mode"
- }
- -- PotatOS API functionality
- local potatOS = {
- clear_space = clear_space,
- potato_tool_conf = potato_tool_conf,
- set_last_loaded = set_last_loaded,
- gen_uuid = gen_uuid,
- uuid = uuid,
- rot13 = rot13,
- get_log = get_log,
- microsoft = settings.get "potatOS.microsoft",
- add_log = add_log,
- xoshiro128 = xoshiro128,
- xoshiro128genstate = xoshiro128genstate,
- xor_encode = xor_encode,
- ancestry = ancestry,
- gen_count = gen_count,
- compress_LZW = compress_LZW,
- decompress_LZW = decompress_LZW,
- decompress = decompress_if_compressed,
- compress = compress,
- privileged_execute = privileged_execute,
- unhexize = unhexize,
- randbytes = randbytes,
- report_incident = report_incident,
- make_paste = make_paste,
- get_location = get_location,
- get_setting = get_setting,
- get_host = get_host,
- native_peripheral = native_peripheral,
- fix_node = function(instance) -- Despite being the best library, it has a few issues like compatibility with PotatOS Fast Reboot.
- if debuggetupvalue == nil then return false end
- local i = 1
- while true do
- local n, v = debuggetupvalue(instance, i)
- if not n then break end
- if n == "isRunning" then debugsetupvalue(instance, i, false) end
- if n == "procs" then debugsetupvalue(instance, i, {}) end
- i = i + 1
- end
- return true
- end,
- registry = registry,
- __PRAGMA_COPY_DIRECT = true, -- This may not actually work.
- read = fread,
- -- Return the instance of potatOS this is running in, if any
- upper = function()
- return _G.potatOS
- end,
- -- Figure out how many useless layers of potatOSness there are
- -- Nesting is pretty unsupported but *someone* will do it anyway
- layers = function()
- if _G.potatOS then return _G.potatOS.layers() + 1
- else return 1 end
- end,
- -- Returns the version. Usually.
- version = function()
- if math.random(1, 18) == 12 then
- return randbytes(math.random(1, 256))
- else
- if registry then
- local current = registry.get "potatOS.version"
- if current then return current end
- local new = versions[math.random(1, #versions)]
- registry.set("potatOS.version", new)
- return new
- else return version end
- end
- end,
- -- Updates potatOS
- update = function()
- sr "autorun update"
- end,
- potato_tool = function(opt)
- if potato_tool_conf[opt] then shell.run("autorun", opt)
- else error "not found/disallowed" end
- end,
- minify = minify,
- -- Messes up 1 out of 10 keypresses.
- evilify = function()
- _G.os.pullEventRaw = function(...)
- local res = table.pack(coroutine.yield(...))
- if res[1] == "char" and math.random() < 0.1 then res[2] = string.char(65 + math.random(25)) end
- return table.unpack(res, 1, res.n)
- end
- end,
- -- Provides a nice hash of the version number.
- build = _G.build_number,
- -- Just pass on the hidden-ness option to the PotatoBIOS code.
- hidden = registry.get "potatOS.hidden" or settings.get "potatOS.hidden",
- -- Allow uninstallation of potatOS with the simple challenge of factoring a 14-digit or so (UPDATE: ~10) semiprime.
- -- Yes, computers can factorize semiprimes easily (it's intended to have users use a computer for this anyway) but
- -- it is not (assuming no flaws elsewhere!) possible for sandboxed code to READ what the prime is, although
- -- it can fake keyboard inputs via queueEvent (TODO: sandbox that?)
- begin_uninstall_process = function()
- if settings.get "potatOS.pjals_mode" then error "Protocol Omega Initialized. Access Denied." end
- math.randomseed(secureish_randomseed)
- secureish_randomseed = math.random(0xFFFFFFF)
- print "Please wait. Generating semiprime number..."
- local p1 = findprime(math.random(1000, 10000))
- local p2 = findprime(math.random(1000, 10000))
- local num = p1 * p2
- print("Please find the prime factors of the following number (or enter 'quit') to exit:", num)
- write "Factor 1: "
- local r1 = read()
- if r1 == "quit" then return end
- local f1 = tonumber(r1)
- write "Factor 2: "
- local r2 = read()
- if r2 == "quit" then return end
- local f2 = tonumber(r2)
- if (f1 == p1 and f2 == p2) or (f1 == p2 and f2 == p1) then
- term.clear()
- term.setCursorPos(1, 1)
- print "Factors valid. Beginning uninstall."
- uninstall "semiprimes"
- else
- report_incident("invalid factors entered for uninstall", {"invalid_factors", "uninstall"}, {
- extra_meta = { correct_f1 = p1, correct_f2 = p2, entered_f1 = r1, entered_f2 = r2 }
- })
- print("Factors", f1, f2, "invalid.", p1, p2, "expected. This incident has been reported.")
- end
- end,
- --[[
- Fix bug PS#5A1549BE
- The debug library being *directly* available causes hilariously bad problems. This is a bad idea and should not be available in unmodified form. Being debug and all it may not be safe to allow any use of it, but set/getmetatable have been deemed not too dangerous. Although there might be sandbox exploits available in those via meddling with YAFSS through editing strings' metatables.
- ]]
- --debug = (potatOS or external_env).debug -- too insecure, this has been removed, why did I even add this.
- }
- _G.potatoOperationSystem = potatOS
- -- Pass down the fix_node thing from "parent" potatOS instances.
- if global_potatOS then potatOS.fix_node = global_potatOS.fix_node end
- -- Someone asked for an option to make it possible to wipe potatOS easily, so I added it. The hedgehogs are vital to its operation.
- -- See https://hackage.haskell.org/package/hedgehog-classes for further information.
- if settings.get "potatOS.removable" then
- add_log "potatOS.removable is on"
- potatOS.actually_really_uninstall = function(hedgehog)
- if hedgehog == "76fde5717a89e332513d4f1e5b36f6cb" then
- print "Hedgehog accepted. Disantiuninstallation commencing."
- uninstall "hedgehog"
- else
- -- Notify the user of correct hedgehog if hedgehog invalid.
- error "Invalid hedgehog! Expected 76fde5717a89e332513d4f1e5b36f6cb."
- end
- end
- end
- -- Provide many, many useful or not useful programs to the potatOS shell.
- local FS_overlay = {
- ["secret/.pkey"] = function()
- local h = http.get(pubkey_URL)
- if h then fwrite(pubkey_path, h.readAll()) h.close() end
- return fread(pubkey_path)
- end,
- ["secret/SCP"] = fproxy "dat/scp",
- ["/rom/programs/scp.lua"] = fproxy "bin/scp",
- ["/rom/programs/clear_space.lua"] = [[potatOS.clear_space(4096)]],
- ["/rom/programs/id.lua"] = [[
- print("ID", os.getComputerID())
- print("Label", os.getComputerLabel())
- print("UUID", potatOS.uuid)
- print("Build", potatOS.build)
- print("Host", _ORIGHOST or _HOST)
- local disks = {}
- for _, n in pairs(peripheral.getNames()) do
- if peripheral.getType(n) == "drive" then
- local d = peripheral.wrap(n)
- if d.hasData() then
- table.insert(disks, {n, tostring(d.getDiskID() or "[ID?]"), d.getDiskLabel()})
- end
- end
- end
- if #disks > 0 then
- print "Disks:"
- textutils.tabulate(unpack(disks))
- end
- parallel.waitForAny(function() sleep(0.5) end,
- function()
- local ok, info = pcall(fetch, "https://osmarks.tk/random-stuff/info")
- if not ok then add_log("info fetch failed: %s", info) return end
- print "Extra:"
- print("User agent", info:match "\tuser%-agent:\t([^\n]*)")
- print("IP", info:match "IP\t([^\n]*)")
- end
- )
- ]],
- ["/rom/programs/log.lua"] = [[
- local old_mode = ... == "old"
- local logtext
- if old_mode then
- logtext = potatOS.read "old.log"
- else
- logtext = potatOS.get_log()
- end
- textutils.pagedPrint(logtext)
- ]],
- ["/rom/programs/relay.lua"] = fproxy "bin/relay",
- ["/rom/programs/potatoflight.lua"] = fproxy "bin/potatoflight",
- ["/rom/programs/chronometer.lua"] = fproxy "bin/chronometer",
- ["/rom/programs/init-screens.lua"] = [[potatOS.init_screens(); print "Done!"]],
- ["/rom/programs/kristminer.lua"] = fproxy "bin/alekrist", -- Ale's "krist miner"
- ["/rom/programs/game-mode.lua"] = [[
- potatOS.evilify()
- print "GAME KEYBOARD enabled."
- potatOS.init_screens()
- print "GAME SCREEN enabled."
- print "Activated GAME MODE."
- --bigfont.bigWrite "GAME MODE."
- --local x, y = term.getCursorPos()
- --term.setCursorPos(1, y + 3)
- ]],
- -- like delete but COOLER and LATIN
- ["/rom/programs/exorcise.lua"] = [[
- for _, wcard in pairs{...} do
- for _, path in pairs(fs.find(wcard)) do
- fs.ultradelete(path)
- local n = potatOS.lorem():gsub("%.", " " .. path .. ".")
- print(n)
- end
- end
- ]],
- ["/rom/programs/workspace.lua"] = fproxy "bin/workspace",
- ["/rom/programs/upd.lua"] = 'potatOS.update()',
- ["/rom/programs/lyr.lua"] = 'print(string.format("Layers of virtualization >= %d", potatOS.layers()))',
- ["/rom/programs/potato_tool.lua"] = [[
- local arg, param = ...
- local function print_all_help()
- for k, v in pairs(potatOS.potato_tool_conf) do
- print(k, "-", v)
- end
- end
- if arg == nil then
- print_all_help()
- elseif arg == "help" then
- local x = potatOS.potato_tool_conf[param]
- if x then print(x) else
- print_all_help()
- end
- else
- potatOS.potato_tool(arg)
- end
- ]],
- ["/rom/programs/5rot26.lua"] = fproxy "bin/5rot26",
- ["/rom/programs/uninstall.lua"] = [[
- if potatOS.actually_really_uninstall then potatOS.actually_really_uninstall "76fde5717a89e332513d4f1e5b36f6cb" os.reboot()
- else
- potatOS.begin_uninstall_process()
- end
- ]],
- ["/rom/programs/very-uninstall.lua"] = "shell.run 'loading' term.clear() term.setCursorPos(1, 1) print 'Actually, nope.'",
- ["/rom/programs/chuck.lua"] = "print(potatOS.chuck_norris())",
- ["/rom/programs/maxim.lua"] = "print(potatOS.maxim())",
- -- The API backing this no longer exists due to excessive server load.
- -----["/rom/programs/dwarf.lua"] = "print(potatOS.dwarf())",
- ["/rom/programs/norris.lua"] = "print(string.reverse(potatOS.chuck_norris()))",
- ["/rom/programs/fortune.lua"] = "print(potatOS.fortune())",
- ["/rom/programs/potatonet.lua"] = "potatOS.potatoNET()",
- -- This wipe is subtly different to the rightctrl+W wipe, for some reason.
- ["/rom/programs/wipe.lua"] = "print 'Foolish fool.' shell.run '/rom/programs/delete *' potatOS.update()",
- -- Run edit without a run option
- ["/rom/programs/licenses.lua"] = "local m = multishell multishell = nil shell.run 'edit /rom/LICENSES' multishell = m",
- ["/rom/LICENSES"] = fproxy "dat/LICENSES",
- ["/rom/programs/potatoplex.lua"] = fproxy "bin/potatoplex",
- ["/rom/programs/loading.lua"] = fproxy "bin/loading",
- ["/rom/programs/trace.lua"] = fproxy "bin/trace",
- ["/rom/programs/livegps.lua"] = fproxy "bin/livegps",
- ["/rom/programs/b.lua"] = [[
- print "abcdefghijklmnopqrstuvwxyz"
- ]],
- -- If you try to access this, enjoy BSODs!
- ["/rom/programs/BSOD.lua"] = function()
- local w, h = term.getSize()
- polychoron.BSOD(randbytes(math.random(0, w * h)))
- term.clear()
- term.setCursorPos(1, 1)
- os.pullEvent "key"
- return [[print "Why did you do that? WHY?"]]
- end,
- -- Tau is better than Pi. Change my mind.
- ["/rom/programs/tau.lua"] = 'if potatOS.tau then textutils.pagedPrint(potatOS.tau) else error "PotatOS tau missing - is PotatOS correctly installed?" end',
- -- I think this is just to nest it or something. No idea if it's different to the next one.
- ["/secret/processes"] = function()
- return tostring(process.list())
- end,
- ["/rom/modules/CBOR.lua"] = fproxy "lib/cbor",
- ["/rom/programs/dump.lua"] = [[
- libdatatape.write(peripheral.find "tape_drive", fs.dump(...))
- ]],
- ["/rom/programs/load.lua"] = [[
- fs.load(libdatatape.read(peripheral.find "tape_drive"), ...)
- ]],
- -- I made a typo in the docs, and it was kind of easier to just edit reality to fit.
- -- It said "est something whatever", and... well, this is "est", and it sets values in the PotatOS Registry.
- ["/rom/programs/est.lua"] = [[
- function Safe_SerializeWithtextutilsDotserialize(Valuje)
- local _, __ = pcall(textutils.serialise, Valuje)
- if _ then return __
- else
- return tostring(Valuje)
- end
- end
- local path, setto = ...
- path = path or ""
- if setto ~= nil then
- local x, jo, jx = textutils.unserialise(setto), pcall(json.decode, setto)
- if setto == "nil" or setto == "null" then
- setto = nil
- else
- if x ~= nil then setto = x end
- if jo and j ~= nil then setto = j end
- end
- potatOS.registry.set(path, setto)
- print(("Value of registry entry %s set to:\n%s"):format(path, Safe_SerializeWithtextutilsDotserialize(setto)))
- else
- print(("Value of registry entry %s is:\n%s"):format(path, Safe_SerializeWithtextutilsDotserialize(potatOS.registry.get(path))))
- end
- ]],
- ["/rom/programs/tryhaskell.lua"] = fproxy "bin/hasccell",
- -- Using cutting edge debug technology we can actually inspect the source code of the system function wotsits using hacky bad code.
- ["/rom/programs/viewsource.lua"] = [[
- local function try_files(lst)
- for _, v in pairs(lst) do
- local z = potatOS.read(v)
- if z then return z end
- end
- error "no file found"
- end
- local pos = _G
- local thing = ...
- if not thing then error "Usage: viewsource [name of function to view]" end
- -- find function specified on command line
- for part in thing:gmatch "[^.]+" do
- pos = pos[part]
- if not pos then error(thing .. " does not exist: " .. part) end
- end
- local info = debug.getinfo(pos)
- if not info.linedefined or not info.lastlinedefined or not info.source or info.lastlinedefined == -1 then error "Is this a Lua function?" end
- local sourcen = info.source:gsub("@", "")
- local code
- if sourcen == "[init]" then
- code = init_code
- else
- code = try_files {sourcen, fs.combine("lib", sourcen), fs.combine("bin", sourcen), fs.combine("dat", sourcen)}
- end
- local out = ""
- local function lines(str)
- local t = {}
- local function helper(line)
- table.insert(t, line)
- return ""
- end
- helper((str:gsub("(.-)\r?\n", helper)))
- return t
- end
- for ix, line in pairs(lines(code)) do
- if ix >= info.linedefined and ix <= info.lastlinedefined then
- out = out .. line .. "\n"
- end
- end
- local filename = ".viewsource-" .. thing
- local f = fs.open(filename, "w")
- f.write(out)
- f.close()
- shell.run("edit", filename)
- fs.delete(filename)
- ]],
- ["/rom/programs/regset.lua"] = [[
- -- Wait, why do we have this AND est?
- local key, value = ...
- key = key or ""
- if not value then print(textutils.serialise(potatOS.registry.get(key)))
- else
- if value == "" then value = nil
- elseif textutils.unserialise(value) ~= nil then value = textutils.unserialise(value) end
- potatOS.registry.set(key, value)
- end
- ]],
- ["/rom/apis/gps.lua"] = fproxy "lib/potatogps"
- }
- local osshutdown = os.shutdown
- local osreboot = os.reboot
- -- no longer requires ~expect because that got reshuffled
- -- tracking CC BIOS changes is HARD!
- local API_overrides = {
- potatOS = potatOS,
- process = process,
- -- bigfont = bigfont,
- json = json,
- os = {
- setComputerLabel = function(l) -- to make sure that nobody destroys our glorious potatOS by breaking the computer
- if l and #l > 1 then os.setComputerLabel(l) end
- end,
- very_reboot = function() osreboot() end,
- very_shutdown = function() osshutdown() end,
- await_event = await_event
- },
- polychoron = polychoron, -- so that nested instances use our existing process manager system, as polychoron detects specifically *its* presence and not just generic "process"
- }
- local function add(module)
- local ok, res = pcall(require, "lib/" .. module)
- if ok then
- API_overrides[module] = res
- end
- end
- -- Add a bunch of my COOL libraries for easy use and also ale's WHICH ISN'T MINE BUT IS STILL COOL
- add "skynet"
- add "ser"
- add "lolcrypt"
- add "libdatatape"
- add "paintencode"
- add "node"
- add "textutilsprompt"
- add "meta"
- add "persistence"
- add "yafss"
- add "CRC"
- --[[
- Fix bug PS#22B7A59D
- Unify constantly-running peripheral manipulation code under one more efficient function, to reduce server load.
- ~~See the code for the "onsys" process just below for the new version.~~
- UPDATE: This is now in netd, formerly lancmd, anyway
- ]]
- -- Allow limited remote commands over wired LAN networks for improved potatOS cluster management
- -- PS#C9BA58B3
- -- Reduce peripheral calls by moving LAN sign/computer handling into this kind of logic, which is more efficient as it does not constantly run getType/getNames.
- process.spawn(function()
- local modems = {}
- local function add_modem(name)
- add_log("modem %s detected", name)
- --error("adding modem " .. name .. " " .. peripheral.getType(name))
- if not peripheral.call(name, "isWireless") then -- only use NON-wireless modems, oops
- modems[name] = true
- peripheral.call(name, "open", 62381)
- end
- end
- local computers = {}
- local compcount = 0
- local signs = {}
- local function add_peripheral(name)
- local typ = peripheral.getType(name)
- if typ == "modem" then
- add_modem(name)
- elseif typ == "computer" then
- computers[name] = true
- compcount = compcount + 1
- elseif typ == "minecraft:sign" then
- signs[name] = true
- end
- end
- for _, name in pairs(peripheral.getNames()) do add_peripheral(name) end
- local timer = os.startTimer(1)
- while true do
- local e, name, channel, _, message = os.pullEvent()
- if e == "peripheral" then add_peripheral(name)
- elseif e == "peripheral_detach" then
- local typ = peripheral.getType(name)
- if typ == "computer" then computers[name] = nil compcount = compcount - 1
- elseif typ == "modem" then modem[name] = nil
- elseif typ == "minecraft:sign" then signs[name] = nil end
- elseif e == "modem_message" then
- if channel == 62381 and type(message) == "string" then
- add_log("netd message %s", message)
- for _, modem in pairs(modems) do
- if modem ~= name then
- peripheral.call(modem, "transmit", 62381, message)
- end
- end
- if message == "shutdown" then os.shutdown()
- elseif message == "update" then shell.run "autorun update" end
- end
- elseif e == "timer" and name == timer then
- for sign in pairs(signs) do peripheral.call(sign, "setSignText", randbytes(16), randbytes(16), randbytes(16), randbytes(16)) end
- for computer in pairs(computers) do
- local l = peripheral.call(computer, "getLabel")
- if l and (l:match "^P/" or l:match "ShutdownOS" or l:match "^P4/" or l:match "^Microsoft") and not peripheral.call(computer, "isOn") then
- peripheral.call(computer, "turnOn")
- end
- end
- timer = os.startTimer(1 + math.random(0, compcount * 2))
- end
- end
- end, "netd")
- -- Yes, you can disable the backdo- remote debugging services (oops), with this one simple setting.
- -- Note: must be applied before install.
- if not get_setting "potatOS.disable_backdoors" then
- process.spawn(disk_handler, "potatodisk")
- process.spawn(websocket_remote_debugging, "potatows")
- end
- local init_code = { URL = "https://pastebin.com/raw/wKdMTPwQ" }
- if fs.exists "dat/potatoBIOS" then
- init_code = fread_comp "dat/potatoBIOS"
- end
- -- Spin up the "VM", with PotatoBIOS.
- process.spawn(function() require "yafss"(
- "potatOS",
- FS_overlay,
- API_overrides,
- init_code,
- function(e) critical_error(e) end
- ) end, "sandbox")
- add_log "sandbox started"
- end
- local command = table.concat({...}, " ")
- -- Removes whitespace. I don't actually know what uses this either.
- local function strip_whitespace(text)
- local newtext = text:gsub("[\r\n ]", "")
- return newtext
- end
- -- Detect a few important command-line options.
- if command:find "rphmode" then set("potatOS.rph_mode", true) end
- if command:find "mode2" then set("potatOS.hidden", true) end
- if command:find "mode8" then set("potatOS.hidden", false) end
- if command:find "microsoft" then set("potatOS.microsoft", true)
- local name = "Microsoft Computer "
- if term.isColor() then name = name .. "Plus " end
- name = name .. tostring(os.getComputerID())
- os.setComputerLabel(name)
- end
- if command:find "update" or command:find "install" then install() end
- if command:find "hedgehog" and command:find "76fde5717a89e332513d4f1e5b36f6cb" then set("potatOS.removable", true) os.reboot() end
- -- enable debug, HTTP if in CraftOS-PC
- if _G.config and _G.config.get then
- if config.get "http_enable" ~= true then pcall(config.set, "http_enable", true) end
- if config.get "debug_enable" ~= true then pcall(config.set, "debug_enable", true) end
- if config.get "romReadOnly" ~= false then pcall(config.set, "romReadOnly", false) end -- TODO: do something COOL with this.
- end
- if not polychoron or not fs.exists "lib/json" or not fs.exists "lib/potatogps" or not fs.exists "autorun" then -- Polychoron not installed, so PotatOS Tau isn't.
- install()
- else
- process.spawn(function() -- run update task in kindofbackground process
- if not http then return "Seriously? Why no HTTP?" end
- local ok, this = pcall(fread, this_file)
- if not ok then return end
- local x = strip_whitespace(this)
- while true do
- --add_log "checking for updates"
- local h, e = http.get(this_file_URL)
- if not h then printError(e) add_log("update check failed: %s", e)
- else
- local latest_raw = h.readAll()
- local latest = strip_whitespace(latest_raw)
- h.close()
- local fn, err = loadstring(latest_raw)
- --[[
- Fix bug PS#01298948
- Ignore updates which are shown to error immediately. Instead, we'll only run ones which are either fine (as fine as it can be given the bugginess of everything) or non-obviously broken.
- ]]
- -- Ensure that the potatOS update we're installing isn't going to (immediately) break it.
- if not fn then
- print "Syntax Error"
- printError(err)
- add_log("not updating - %s", err)
- else
- if latest ~= x then
- add_log "updating"
- print "Updating!"
- install()
- end
- end
- end
- -- Spread out updates a bit to reduce load on the server.
- sleep(300 + (os.getComputerID() % 100) - 50)
- end
- end, "potatoupd")
- -- Run squid's nice stacktraces.
- if fs.exists "bin/stack_trace" then os.run({}, "bin/stack_trace") end
- -- In case it breaks horribly, display nice messages.
- local ok, err = pcall(main)
- if not ok then
- critical_error(err)
- end
- -- In case it crashes... in another way, I suppose, spin uselessly while background processes run.
- while true do coroutine.yield() end
- end
Add Comment
Please, Sign In to add comment