Compare commits
No commits in common. "master" and "master" have entirely different histories.
@ -93,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
|
||||
|
||||
|
@ -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
|
@ -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..."
|
||||
|
@ -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
|
||||
|
@ -77,10 +77,31 @@ 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
|
||||
@ -93,12 +114,19 @@ 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
|
||||
@ -106,7 +134,7 @@ 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
|
||||
@ -151,176 +179,98 @@ end
|
||||
|
||||
local this_level_env = _G
|
||||
|
||||
-- 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
|
||||
}
|
||||
end
|
||||
|
||||
local function create_FS(vfstree)
|
||||
-- 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](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)
|
||||
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.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
|
||||
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
|
||||
if src_vfs.isReadOnly(src_path) then error "Access denied" end
|
||||
new.copy(src, dest)
|
||||
src_vfs.delete(src_path)
|
||||
for _, v in pairs(ocontents) do
|
||||
table.insert(contents, v)
|
||||
end
|
||||
return contents
|
||||
end
|
||||
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()
|
||||
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
|
||||
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)
|
||||
end
|
||||
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
|
||||
@ -360,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
|
||||
@ -377,7 +327,7 @@ 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
|
||||
@ -455,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 = getfenv
|
||||
environment.setfenv = setfenv
|
||||
--[[
|
||||
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)
|
||||
@ -468,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")
|
||||
@ -515,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 }
|
92
src/main.lua
92
src/main.lua
@ -1297,61 +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 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
|
||||
function drive_mounts.vfs.getSize(path) return 0 end
|
||||
function drive_mounts.vfs.getFreeSpace(path) return 0 end
|
||||
function drive_mounts.vfs.makeDir(path) end
|
||||
function drive_mounts.vfs.delete(path) end
|
||||
function drive_mounts.vfs.isReadOnly(path) return true 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,
|
||||
@ -1388,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
|
||||
@ -1409,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)
|
||||
@ -1426,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)
|
||||
@ -1448,19 +1394,17 @@ 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, {
|
||||
"traceback",
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>"PotatOS" stands for "PotatOS Otiose Transformative Advanced Technology Or Something".
|
||||
<a href="https://git.osmarks.net/osmarks/potatOS">This repository</a> contains the source code for the latest version of PotatOS, "PotatOS Epenthesis".
|
||||
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user