Compare commits

..

No commits in common. "master" and "master" have entirely different histories.

13 changed files with 204 additions and 449 deletions

View File

@ -17,8 +17,6 @@ Thanks to technology, we're able to offer a live PotatOS instance in your browse
<button id="launch-demo">Experience PotatOS</button>
<div id="computer"></div>
(if the emulator gets stuck, please refresh this page)
<noscript>
Experiencing PotatOS requires JavaScript. Please enable it.
</noscript>
@ -74,7 +72,7 @@ Unlike most "OS"es for CC (primarily excluding Opus OS, which is actually useful
- To ease large-scale network management, PotatOS's networking daemon turns on any networked potatOS computers.
- Improves connected signs, if Plethora Peripherals is installed.
- Recycle bin capability stops accidental loss of files.
- `exorcise` command, which is like `delete` but better.
- `exorcise` command, which is like delete but better.
- Support for a wide variety of Lorem Ipsum integrated into the OS.
- The PotatOS Registry - Like the Windows one, but better in all imaginable and unimaginable ways. Edit and view its contents with the `est` command.
- Window manager shipped. I forgot what it is and how to use it.
@ -95,7 +93,6 @@ Unlike most "OS"es for CC (primarily excluding Opus OS, which is actually useful
- Live threat updates using our advanced algorithms.
- PotatOS Epenthesis' rewritten security model fixes many exploits and adds others while reducing boot times.
- IPC mechanism.
- Virtual filesystems abstraction.
## Architecture

File diff suppressed because one or more lines are too long

View File

@ -1,60 +1,3 @@
local prefixes = {
{-12, "p"},
{-9, "n"},
{-6, "u"},
{-3, "m"},
{0, ""},
{3, "k"},
{6, "M"}
}
local function SI_prefix(value, unit)
local x = math.log(value, 10)
local last
for _, t in ipairs(prefixes) do
if t[1] > x then
break
end
last = t
end
local dp = 2 - math.floor(x - last[1])
return (("%%.%df%%s%%s"):format(dp)):format(value / 10^(last[1]), last[2], unit)
end
local w = term.getSize()
local rows = {}
for _, info in pairs(process.list()) do
table.insert(rows, { info.name or tostring(info.ID), SI_prefix(info.execution_time, "s"), SI_prefix(info.ctime, "s") })
end
local max_width_per_column = {}
for _, row in ipairs(rows) do
for i, cell in ipairs(row) do
max_width_per_column[i] = math.max(max_width_per_column[i] or 0, cell:len() + 1)
end
end
local vw_width = 0
for i = #max_width_per_column, 1, -1 do
if i > 1 then
vw_width = vw_width + max_width_per_column[i]
end
end
local fw_start = w - vw_width
for _, row in ipairs(rows) do
local s
for i, cell in ipairs(row) do
if i == 1 then
s = cell:sub(1, fw_start - 1) .. (" "):rep((fw_start - 1) - cell:len())
else
cell = " " .. cell
s = s .. (" "):rep(max_width_per_column[i] - cell:len()) .. cell
end
end
textutils.pagedPrint(s)
textutils.pagedPrint(("%s %f %f"):format(info.name or info.ID, info.execution_time, info.ctime))
end

View File

@ -1,128 +0,0 @@
local vfs = {}
local getters = {"is", "has", "get"}
local setters = {"set"}
function vfs.list(path)
local segs = fs.segment(path)
if #segs == 0 then
return peripheral.getNames()
elseif #segs == 1 then
local methods = peripheral.getMethods(segs[1])
local out = {}
for _, v in pairs(methods) do
local set
for _, s in pairs(setters) do
local mat = v:match("^" .. s .. "([A-Z].+)")
if mat then
set = mat
break
end
end
local get
for _, g in pairs(getters) do
local mat = v:match("^" .. g .. "([A-Z].+)")
if mat then
get = mat
break
end
end
if get then table.insert(out, get)
elseif set then table.insert(out, set)
else table.insert(out, v) end
end
return out
elseif #segs == 2 then
end
end
local function write_handle(callback)
local buffer = ""
local r_write_handle = {}
function r_write_handle.write(text)
buffer = buffer .. text
end
function r_write_handle.close()
callback(buffer)
end
function r_write_handle.flush() end
function r_write_handle.writeLine(text) r_write_handle.write(text) r_write_handle.write("\n") end
return r_write_handle
end
local call_results = {}
function vfs.open(path, mode)
local segs = fs.segment(path)
if #segs == 2 and segs[2]:match "^[A-Z]" then -- getter/setter configuration
if mode:match "w" then
return write_handle(function(buffer)
local ok, res
for _, s in pairs(setters) do
local ok2, res2 = pcall(peripheral.call, segs[1], s .. segs[2], textutils.unserialise(buffer))
ok = ok or ok2
res = res or res2
end
if not ok then error(res) end
end)
else
-- TODO multiple returns
local result
for _, g in pairs(getters) do
local ok, res = pcall(peripheral.call, segs[1], g .. segs[2])
result = result or (ok and res)
end
local text = textutils.serialise(result)
return fs._make_handle(text)
end
elseif #segs == 2 then
if mode:match "^w" then
return write_handle(function(buffer)
call_results[fs.combine(path, "")] = peripheral.call(segs[1], segs[2], unpack(textutils.unserialise(buffer)))
end)
end
if mode:match "^r" then
local rp = fs.combine(path, "")
local h
if call_results[rp] then h = fs._make_handle(textutils.serialise(call_results[rp]))
else h = fs._make_handle("") end
call_results[rp] = nil
return h
end
error "invalid IO mode"
end
end
function vfs.exists(path)
local segs = fs.segment(path)
if #segs == 0 then
return true
else
return peripheral.getType(segs[1]) ~= nil
end
end
function vfs.isReadOnly(path)
local segs = fs.segment(path)
if #segs == 2 and segs[2]:match "^[A-Z]" then -- getter/setter configuration
local methods = peripheral.getMethods(segs[1])
for _, s in pairs(setters) do
for _, m in pairs(methods) do
if m == s .. segs[2] then
return false
end
end
end
return true
end
return false
end
function vfs.isDir(path)
local segs = fs.segment(path)
return #segs <= 1
end
function vfs.getDrive(path) return "devfs" end
fs.mountVFS(shell.resolve(...), vfs)

View File

@ -24,7 +24,7 @@ print()
print(snd)
print()
if arg == "headless" then
if ccemux then ccemux.echo "ready" end
ccemux.echo "ready"
while true do coroutine.yield() end
else
print "Press a key to continue..."

View File

@ -1 +0,0 @@
fs.unmountVFS(shell.resolve(...))

View File

@ -1,6 +1,6 @@
-- thanks to valued user 6_4 for the suggestion
local function different_from_global(candidate_fs)
local function different_to_global(candidate_fs)
local seen = {}
for _, i in pairs(fs.list "") do
seen[i] = true
@ -19,7 +19,7 @@ local function is_probably_filesystem(x)
for _, k in pairs(keys) do
if type(x[k]) ~= "function" then return false end
end
return different_from_global(x)
return different_to_global(x)
end
local function harvest_upvalues(fn)
@ -110,7 +110,7 @@ local escapes = {
i = i + 1
end
end,
scan_most_threads = function()
scan_most_threads = function()
if not debug then return end
if not (debug.getinfo and debug.getlocal) then return end
local running = coroutine.running()
@ -142,4 +142,4 @@ return function()
return err
end
end
end
end

View File

@ -13,11 +13,6 @@ end
function sandboxlib.dispatch_if_restricted(rkey, original, restricted)
local out = {}
for k, v in pairs(restricted) do
if not original[k] then
out[k] = v
end
end
for k, v in pairs(original) do
out[k] = function(...)
if processrestriction(rkey) then

View File

@ -11,6 +11,21 @@ local function copy(tabl)
return new
end
-- Deep-map all values in a table
local function deepmap(table, f, path)
local path = path or ""
local new = {}
for k, v in pairs(table) do
local thisp = path .. "." .. k
if type(v) == "table" and v ~= table then -- bodge it to not stackoverflow
new[k] = deepmap(v, f, thisp)
else
new[k] = f(v, k, thisp)
end
end
return new
end
-- Takes a list of keys to copy, returns a function which takes a table and copies the given keys to a new table
local function copy_some_keys(keys)
return function(from)
@ -26,6 +41,13 @@ local function copy_some_keys(keys)
end
end
-- Simple string operations
local function starts_with(s, with)
return string.sub(s, 1, #with) == with
end
local function ends_with(s, with)
return string.sub(s, -#with, -1) == with
end
local function contains(s, subs)
return string.find(s, subs) ~= nil
end
@ -55,18 +77,56 @@ local function add_to_table(t1, t2)
end
end
local fscombine, fsgetname, fsgetdir = fs.combine, fs.getName, fs.getDir
-- Convert path to canonical form
local function canonicalize(path)
return fscombine(path, "")
return fs.combine(path, "")
end
-- Checks whether a path is in a directory
local function path_in(p, dir)
return starts_with(canonicalize(p), canonicalize(dir))
end
local function make_mappings(root)
return {
["/disk"] = "/disk",
["/rom"] = "/rom",
default = root
}
end
local function get_root(path, mappings)
for mapfrom, mapto in pairs(mappings) do
if path_in(path, mapfrom) then
return mapto, mapfrom
end
end
return mappings.default, "/"
end
-- Escapes lua patterns in a string. Should not be needed, but lua is stupid so the only string.replace thing is gsub
local quotepattern = '(['..("%^$().[]*+-?"):gsub("(.)", "%%%1")..'])'
local function escape(str)
return str:gsub(quotepattern, "%%%1")
end
local function strip(p, root)
return p:gsub("^" .. escape(canonicalize(root)), "")
end
local function resolve_path(path, mappings)
local root, to_strip = get_root(path, mappings)
local newpath = strip(fs.combine(root, path), to_strip)
if path_in(newpath, root) then return newpath end
return resolve_path(newpath, mappings)
end
local function segments(path)
local segs, rest = {}, canonicalize(path)
if rest == "" then return {} end -- otherwise we'd get "root" and ".." for some broken reason
repeat
table.insert(segs, 1, fsgetname(rest))
rest = fsgetdir(rest)
table.insert(segs, 1, fs.getName(rest))
rest = fs.getDir(rest)
until rest == ""
return segs
end
@ -74,18 +134,18 @@ end
local function combine(segs)
local out = ""
for _, p in pairs(segs) do
out = fscombine(out, p)
out = fs.combine(out, p)
end
return out
end
local vfs_defaults = {}
function vfs_defaults.getSize(path) return 0 end
function vfs_defaults.getFreeSpace(path) return 0 end
function vfs_defaults.makeDir(path) error "Access denied" end
function vfs_defaults.delete(path) error "Access denied" end
function vfs_defaults.isReadOnly(path) return true end
-- Fetch the contents of URL "u"
local function fetch(u)
local h = http.get(u)
local c = h.readAll()
h.close()
return c
end
-- Make a read handle for a string
-- PS#8FE487EF: Incompletely implemented handle behaviour lead to strange bugs on recent CC
@ -112,176 +172,105 @@ local function make_handle(text)
return h
end
-- make virtual filesystem from files (no nested directories for simplicity)
local function vfs_from_files(files)
return {
list = function(path)
if path ~= "" then return {} end
local out = {}
for k, v in pairs(files) do
table.insert(out, k)
end
return out
end,
open = function(path, mode)
return make_handle(files[path])
end,
exists = function(path)
return files[path] ~= nil or path == ""
end,
isReadOnly = function(path)
return true
end,
isDir = function(path)
if path == "" then return true end
return false
end,
getDrive = function(_) return "memory" end,
getSize = function(path)
return #files[path]
end,
getFreeSpace = function() return 0 end,
makeDir = function() end,
delete = function() end,
move = function() end,
copy = function() end,
attributes = function(path)
return {
size = #files[path],
modification = os.epoch "utc"
}
end
}
-- Get a path from a filesystem overlay
local function path_in_overlay(overlay, path)
return overlay[canonicalize(path)]
end
local function create_FS(vfstree)
local this_level_env = _G
-- Create a modified FS table which confines you to root and has some extra read-only pseudofiles.
local function create_FS(root, overlay)
local fs = fs
local mappings = make_mappings(root)
local function is_usable_node(node)
return node.mount or node.vfs
end
local vfstree = {
mount = "potatOS",
children = {
["disk"] = { mount = "disk" },
["rom"] = { mount = "rom" },
--["virtual_test"] = { virtual = "bees" }
}
}
local function resolve(sandbox_path, ignore_usability)
local function resolve(sandbox_path)
local segs = segments(sandbox_path)
local current_tree = vfstree
local last_usable_node, last_segs = nil, nil
while true do
if is_usable_node(current_tree) then
last_usable_node = current_tree
last_segs = copy(segs)
end
local seg = segs[1]
if seg and current_tree.children and current_tree.children[seg] then
if current_tree.children and current_tree.children[seg] then
table.remove(segs, 1)
current_tree = current_tree.children[seg]
else break end
end
if ignore_usability then return current_tree, segs end
return last_usable_node, last_segs
end
local function resolve_node_segs(node, segs)
if node.mount then return fs, fscombine(node.mount, combine(segs)) end
return node.vfs, combine(segs)
end
local function resolve_path(sandbox_path)
local node, segs = resolve(sandbox_path)
return resolve_node_segs(node, segs)
local new_overlay = {}
for k, v in pairs(overlay) do
new_overlay[canonicalize(k)] = v
end
local function lift_to_sandbox(f, n)
return function(path)
local vfs, path = resolve_path(path)
return (vfs[n] or vfs_defaults[n])(path)
return function(...)
local args = map(function(x) return resolve_path(x, mappings) end, {...})
return f(table.unpack(args))
end
end
local new = copy_some_keys {"getDir", "getName", "combine", "complete"} (fs)
function new.isReadOnly(path)
return path_in_overlay(new_overlay, path) or starts_with(canonicalize(path), "rom")
end
function new.open(path, mode)
if (contains(mode, "w") or contains(mode, "a")) and new.isReadOnly(path) then
error "Access denied"
else
local vfs, path = resolve_path(path)
return vfs.open(path, mode)
local overlay_data = path_in_overlay(new_overlay, path)
if overlay_data then
if type(overlay_data) == "function" then overlay_data = overlay_data(this_level_env) end
return make_handle(overlay_data), "YAFSS overlay"
end
return fs.open(resolve_path(path, mappings), mode)
end
end
function new.move(src, dest)
local src_vfs, src_path = resolve_path(src)
local dest_vfs, dest_path = resolve_path(dest)
if src_vfs == dest_vfs then
return src_vfs.move(src_path, dest_path)
else
if src_vfs.isReadOnly(src_path) then error "Access denied" end
new.copy(src, dest)
src_vfs.delete(src_path)
end
function new.exists(path)
if path_in_overlay(new_overlay, path) ~= nil then return true end
return fs.exists(resolve_path(path, mappings))
end
function new.copy(src, dest)
local src_vfs, src_path = resolve_path(src)
local dest_vfs, dest_path = resolve_path(dest)
if src_vfs == dest_vfs then
return src_vfs.copy(src_path, dest_path)
else
if src_vfs.isDir(src_path) then
dest_vfs.makeDir(dest_path)
for _, f in pairs(src_vfs.list(src_path)) do
new.copy(fscombine(src, f), fscombine(dest, f))
end
else
local dest_fh = dest_vfs.open(dest_path, "wb")
local src_fh = src_vfs.open(src_path, "rb")
dest_fh.write(src_fh.readAll())
src_fh.close()
dest_fh.close()
function new.overlay()
return map(function(x)
if type(x) == "function" then return x(this_level_env)
else return x end
end, new_overlay)
end
function new.list(dir)
local sdir = canonicalize(resolve_path(dir, mappings))
local ocontents = {}
for opath in pairs(new_overlay) do
if fs.getDir(opath) == sdir then
table.insert(ocontents, fs.getName(opath))
end
end
end
function new.mountVFS(path, vfs)
local node, relpath = resolve(path)
while #relpath > 0 do
local seg = table.remove(relpath, 1)
if not node.children then node.children = {} end
if not node.children[seg] then node.children[seg] = {} end
node = node.children[seg]
end
node.vfs = vfs
end
function new.unmountVFS(path)
local node, relpath = resolve(path)
if #relpath == 0 then
node.vfs = nil
local ok, contents = pcall(fs.list, sdir)
-- in case of error (nonexistent dir, probably) return overlay contents
-- very awful temporary hack until I can get a nicer treeized VFS done
if not ok then
if #ocontents > 0 then return ocontents end
error(contents)
else
error "Not a mountpoint"
end
end
function new.list(path)
local node, segs = resolve(path, true)
local vfs, path = resolve_path(path)
if #segs > 0 then return vfs.list(path) end
local out = {}
local seen = {}
for k, v in pairs(node.children or {}) do
table.insert(out, k)
seen[k] = true
end
for _, v in pairs(vfs.list(path)) do
if not seen[v] then
table.insert(out, v)
for _, v in pairs(ocontents) do
table.insert(contents, v)
end
return contents
end
return out
end
add_to_table(new, map(lift_to_sandbox, copy_some_keys {"isDir", "getDrive", "getSize", "getFreeSpace", "makeDir", "delete", "isDriveRoot", "exists", "isReadOnly", "attributes"} (fs)))
add_to_table(new, map(lift_to_sandbox, copy_some_keys {"isDir", "getDrive", "getSize", "getFreeSpace", "makeDir", "move", "copy", "delete", "isDriveRoot"} (fs)))
function new.find(wildcard)
local function recurse_spec(results, path, spec) -- From here: https://github.com/Sorroko/cclite/blob/62677542ed63bd4db212f83da1357cb953e82ce3/src/emulator/native_api.lua
@ -321,7 +310,7 @@ local function create_FS(vfstree)
to_add.c = new.dump(path)
to_add.t = "d"
else
local fh = new.open(path, "rb")
local fh = new.open(path, "r")
to_add.c = fh.readAll()
fh.close()
end
@ -338,16 +327,13 @@ local function create_FS(vfstree)
new.makeDir(path)
new.load(f.c, path)
else
local fh = new.open(path, "wb")
local fh = new.open(path, "w")
fh.write(f.c)
fh.close()
end
end
end
new.segment = segments
new._make_handle = make_handle
return new
end
@ -419,11 +405,30 @@ local gf, sf = getfenv, setfenv
-- a map of paths to either strings containing their contents or functions returning them
-- and a table of extra APIs and partial overrides for existing APIs
local function make_environment(API_overrides, current_process)
local env_host = string.format("YAFSS on %s", _HOST)
local environment = copy_some_keys(allowed_APIs)(_G)
-- if function is not from within the VM, return env from within sandbox
function environment.getfenv(arg)
local env
if type(arg) == "number" then return gf() end
if not env or type(env._HOST) ~= "string" or not env._HOST == env_host then
return gf()
else
return env
end
end
-- I sure hope this doesn't readd the security issues!
environment.getfenv = gf
environment.setfenv = sf
--[[
Fix PS#AD2A532C
Allowing `setfenv` to operate on any function meant that privileged code could in some cases be manipulated to leak information or operate undesirably. Due to this, we restrict it, similarly to getfenv.
]]
function environment.setfenv(fn, env)
local nenv = gf(fn)
if not nenv or type(nenv._HOST) ~= "string" or not nenv._HOST == env_host then
return false
end
return sf(fn, env)
end
local load = load
function environment.load(code, file, mode, env)
@ -432,6 +437,7 @@ local function make_environment(API_overrides, current_process)
environment._G = environment
environment._ENV = environment
environment._HOST = env_host
function environment.os.shutdown()
process.IPC(current_process, "power_state", "shutdown")
@ -479,4 +485,4 @@ local function run(API_overrides, init, logger)
end
end
return { run = run, create_FS = create_FS, vfs_from_files = vfs_from_files }
return { run = run, create_FS = create_FS }

View File

@ -47,7 +47,8 @@ local registry = require "registry"
--[[
Server Policy Framework
On 12/01/2020 CE (this is probably overprecise and I doubt anyone will care, yes), the ID 0 bug resulted in potatOS improving a large quantity of turtles, apparently causing problems. In light of this, SC's admins have demanded some features be disabled (EZCopy). This is a reasonably generic way to handle server-specific special cases.
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 = {
@ -1296,56 +1297,26 @@ local function run_with_sandbox()
end or v
end
local yafss = require "yafss"
local drive_mounts = {
children = {},
vfs = {}
-- Provide many, many useful or not useful programs to the potatOS shell.
local FS_overlay = {
["secret/.pkey"] = fproxy "signing-key.tbl",
["secret/log"] = function() return potatOS_proxy.get_log() end,
-- The API backing this no longer exists due to excessive server load.
-----["/rom/programs/dwarf.lua"] = "print(potatOS.dwarf())",
["/secret/processes"] = function()
return tostring(process.list())
end,
["/rom/heavlisp_lib/stdlib.hvl"] = fproxy "stdlib.hvl"
}
function drive_mounts.vfs.list(path)
local out = {}
for k, v in pairs(drive_mounts.children) do
table.insert(out, k)
end
return out
for _, file in pairs(fs.list "bin") do
FS_overlay[fs.combine("rom/programs", file)] = fproxy(fs.combine("bin", file))
end
function drive_mounts.vfs.exists(path)
return path == "" or drive_mounts.children[path] ~= nil
for _, file in pairs(fs.list "xlib") do
FS_overlay[fs.combine("rom/potato_xlib", file)] = fproxy(fs.combine("xlib", file))
end
function drive_mounts.vfs.isDir(path) return true end
function drive_mounts.vfs.getDrive(path) return "disks" end
local vfstree = {
mount = "potatOS",
children = {
["rom"] = {
mount = "rom",
children = {
["potatOS_xlib"] = { mount = "/xlib" },
programs = {
children = {
["potatOS"] = { mount = "/bin" }
}
},
["autorun"] = {
vfs = yafss.vfs_from_files {
["fix_path.lua"] = [[shell.setPath("/rom/programs/potatOS:"..shell.path())]],
}
},
["heavlisp_lib"] = {
vfs = yafss.vfs_from_files {
["stdlib.hvl"] = fproxy "stdlib.hvl"
}
}
}
},
["disks"] = drive_mounts
}
}
local API_overrides = {
process = process,
json = json,
@ -1382,18 +1353,6 @@ local function run_with_sandbox()
local computers = {}
local compcount = 0
local signs = {}
local function mount_disk(drive_name)
local mountpoint = peripheral.call(drive_name, "getMountPath")
if mountpoint then
drive_mounts.children[drive_name] = { mount = mountpoint }
end
end
local function unmount_disk(drive_name)
drive_mounts.children[drive_name] = nil
end
local function add_peripheral(name)
local typ = peripheral.getType(name)
if typ == "modem" then
@ -1403,16 +1362,10 @@ local function run_with_sandbox()
compcount = compcount + 1
elseif typ == "minecraft:sign" then
signs[name] = true
elseif typ == "drive" then
if peripheral.call(name, "isDiskPresent") then
mount_disk(name)
end
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)
@ -1420,8 +1373,7 @@ local function run_with_sandbox()
local typ = peripheral.getType(name)
if typ == "computer" then computers[name] = nil compcount = compcount - 1
elseif typ == "modem" then modems[name] = nil
elseif typ == "minecraft:sign" then signs[name] = nil
elseif typ == "drive" then unmount_disk(name) end
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)
@ -1442,21 +1394,19 @@ local function run_with_sandbox()
end
end
timer = os.startTimer(1 + math.random(0, compcount * 2))
elseif e == "disk" then
mount_disk(name)
elseif e == "disk_eject" then
unmount_disk(name)
end
end
end, "netd", { grants = { [notermsentinel] = true }, restrictions = {} })
require "metatable_improvements"(potatOS_proxy.add_log, potatOS_proxy.report_incident)
local yafss = require "yafss"
local fss_sentinel = sandboxlib.create_sentinel "fs-sandbox"
local debug_sentinel = sandboxlib.create_sentinel "constrained-debug"
local sandbox_filesystem = yafss.create_FS(vfstree)
local sandbox_filesystem = yafss.create_FS("potatOS", FS_overlay)
_G.fs = sandboxlib.dispatch_if_restricted(fss_sentinel, _G.fs, sandbox_filesystem)
_G.debug = sandboxlib.allow_whitelisted(debug_sentinel, _G.debug or {}, {
_G.debug = sandboxlib.allow_whitelisted(debug_sentinel, _G.debug, {
"traceback",
"getinfo",
"getregistry"

View File

@ -459,18 +459,13 @@ local old_error = error
local old_os_shutdown = os.shutdown
local old_term_redirect = term.redirect
local old_term_native = term.native
local old_printError = printError
function error() end
function term.redirect() end
function term.native() end
function printError() end
function os.shutdown()
error = old_error
_G.error = old_error
_ENV.error = old_error
printError = old_printError
_G.printError = old_printError
_ENV.printError = old_printError
term.native = old_term_native
term.redirect = old_term_redirect
os.shutdown = old_os_shutdown

View File

@ -391,12 +391,6 @@ do
local native = term.native()
local last_redirected
-- horrors
local idmap = {}
local function termid(t)
return idmap[tostring(t.blit)]
end
local ix = 0
process.spawn(function()
while true do
@ -414,11 +408,17 @@ do
ix = ix + 1
process.queue_in(process.get_running().parent, "term_resize", true)
elseif ev == "ipc" and arg2 == "redraw_native" then
potatOS.framebuffers[termid(native)].redraw()
potatOS.framebuffers[native.id].redraw()
end
end
end, "termd")
-- horrors
local idmap = {}
local function termid(t)
return idmap[tostring(t.blit)]
end
local function assignid(t)
if not termid(t) then idmap[tostring(t.blit)] = potatOS.gen_uuid() end
end
@ -573,7 +573,7 @@ local function boot_require(package)
return pkg
end
local npackage = package:gsub("%.", "/")
for _, search_path in next, {"/", "lib", "rom/modules/main", "rom/modules/turtle", "rom/modules/command", "rom/potatOS_xlib"} do
for _, search_path in next, {"/", "lib", "rom/modules/main", "rom/modules/turtle", "rom/modules/command", "rom/potato_xlib"} do
local path = try_paths(search_path, {npackage, npackage .. ".lua"})
if path then
local ok, res = pcall(dofile, path)
@ -589,7 +589,7 @@ _G.require = boot_require
_ENV.require = boot_require
local libs = {}
for _, f in pairs(fs.list "rom/potatOS_xlib") do
for _, f in pairs(fs.list "rom/potato_xlib") do
table.insert(libs, f)
end
table.sort(libs)
@ -1245,8 +1245,7 @@ function potatOS.llm(prompt, max_tokens, stop_sequences)
local res, err = http.post("https://gpt.osmarks.net/v1/completions", json.encode {
prompt = prompt,
max_tokens = max_tokens,
stop = stop_sequences,
client = "potatOS"
stop = stop_sequences
}, {["content-type"]="application/json"}, true)
if err then
error("Server error: " .. err) -- is this right? I forgot.
@ -1609,7 +1608,7 @@ function potatOS.threat_update()
table.insert(out, description)
table.insert(out, "")
end
return "current threat level is" .. (potatOS.llm(table.concat(out, "\n") .. "\ncurrent threat level is", 100, {"\n\n"}):gsub("^\n", ""):gsub("\n$", ""))
return (potatOS.llm(table.concat(out, "\n"), 100, {"\n\n"}):gsub("^\n", ""):gsub("\n$", ""))
end
local fixed_context = {
@ -1759,7 +1758,7 @@ if potatOS.registry.get "potatOS.immutable_global_scope" then
end
process.spawn(keyboard_shortcuts, "kbsd")
if skynet and http.websocket then process.spawn(skynet.listen, "skynetd") process.spawn(potatoNET, "systemd-potatod") end
if http.websocket then process.spawn(skynet.listen, "skynetd") process.spawn(potatoNET, "systemd-potatod") end
local autorun = potatOS.registry.get "potatOS.autorun"
if type(autorun) == "string" then
autorun = load(autorun)
@ -1781,7 +1780,7 @@ local function run_shell()
term.clear()
term.setCursorPos(1, 1)
potatOS.add_log "starting user shell"
os.run({}, sShell )
os.run( {}, sShell )
end
if potatOS.registry.get "potatOS.extended_monitoring" then process.spawn(excessive_monitoring, "extended_monitoring") end

View File

@ -57,7 +57,7 @@ button {
<h1>Welcome to PotatOS!</h1>
<img src="/potatos.gif" id="im">
<div>
Current build: <code>9b5e8950</code> (new VFS layer), version 815, built 2024-09-03 11:37:01 (UTC).
Current build: <code>361bc871</code> (adjust LLM interface), version 771, built 2024-02-28 19:50:26 (UTC).
</div>
<p>&quot;PotatOS&quot; stands for &quot;PotatOS Otiose Transformative Advanced Technology Or Something&quot;.
<a href="https://git.osmarks.net/osmarks/potatOS">This repository</a> contains the source code for the latest version of PotatOS, &quot;PotatOS Epenthesis&quot;.
@ -132,7 +132,6 @@ AI will transform the ways we work, live, play, think, become paperclips, breath
<li>Live threat updates using our advanced algorithms.</li>
<li>PotatOS Epenthesis' rewritten security model fixes many exploits and adds others while reducing boot times.</li>
<li>IPC mechanism.</li>
<li>Virtual filesystems abstraction.</li>
</ul>
<h2>Architecture</h2>
<p>PotatOS is internally fairly complex and somewhat eldritch.