diff --git a/code/apps/app-flash.lua b/code/apps/app-flash.lua index 8e48edb..40e1904 100644 --- a/code/apps/app-flash.lua +++ b/code/apps/app-flash.lua @@ -50,6 +50,7 @@ function regenCore() fd.close() busy = false neoux.startDialog("Got the data!", nil, true) + window.reset(regenCore()) end)) table.insert(elems, neoux.tcbutton(6, l + 1, "set", function (window) if busy then return end @@ -62,6 +63,7 @@ function regenCore() report = (wasOk and tostring(report)) or "Flash successful.\nI recommend relabelling the EEPROM." busy = false neoux.startDialog(report, nil, true) + window.reset(regenCore()) end)) local function dHandler(set, get, wd) local setter = v[set] @@ -85,5 +87,11 @@ end local window = neoux.create(regenCore()) while running do - event.pull() + local s = {event.pull()} + if (s[1] == "h.component_added" or s[1] == "h.component_removed") and busy then + -- Anything important? + if s[3] == "gpu" or s[3] == "screen" then + window.reset(regenCore()) + end + end end diff --git a/code/apps/sys-glacier.lua b/code/apps/sys-glacier.lua index 8077ea3..7591ccc 100644 --- a/code/apps/sys-glacier.lua +++ b/code/apps/sys-glacier.lua @@ -408,13 +408,8 @@ while true do -- always shutdown shutdownFin(shutdownMode) end - if s[1] == "h.component_added" then - -- Before doing anything, is it worth it? - if s[3] == "gpu" or s[3] == "screen" then - rescanDevs() - end - end - if s[1] == "h.component_removed" then + if s[1] == "h.component_added" or s[1] == "h.component_removed" then + -- Anything important? if s[3] == "gpu" or s[3] == "screen" then rescanDevs() end diff --git a/code/apps/sys-init.lua b/code/apps/sys-init.lua index 32329c1..c99cf8c 100644 --- a/code/apps/sys-init.lua +++ b/code/apps/sys-init.lua @@ -410,6 +410,8 @@ local function initializeSystem() else local v, err = neo.executeAsync(steps[w]) if not v then + neo.emergency(steps[w] .. " STF") + neo.emergency(err) table.insert(warnings, steps[w] .. " STF") table.insert(warnings, err) end diff --git a/code/data/app-claw/local.lua b/code/data/app-claw/local.lua index c94360d..e538ae1 100644 --- a/code/data/app-claw/local.lua +++ b/code/data/app-claw/local.lua @@ -1,3 +1,5 @@ +-- This is released into the public domain. +-- No warranty is provided, implied or otherwise. return { ["neo"] = { desc = "KittenOS NEO Kernel & Base Libs", @@ -123,7 +125,7 @@ return { }, ["app-flash"] = { desc = "KittenOS NEO EEPROM Flasher", - v = 0, + v = 2, deps = { "neo" }, diff --git a/code/init.lua b/code/init.lua index 736c93b..e297644 100644 --- a/code/init.lua +++ b/code/init.lua @@ -17,6 +17,16 @@ if ocemu then emergencyFunction = ocemu.log end +if load(string.dump(function()end)) then + -- This is your first and only warning. + -- allowBytecode has effects *outside the game.* + -- If it is enabled, any program with load can take over your host system. + -- I refuse to allow KittenOS NEO to operate in this environment for your safety. + -- If you are truly unable to change it, tell someone who can. + emergencyFunction("Please set allowBytecode = false in OCEmu config.") + error("Please set allowBytecode = false in OC config.") +end + primaryDisk = component.proxy(computer.getBootAddress()) -- {{time, func, arg1...}...} @@ -149,7 +159,7 @@ function ensureType(a, t) end function ensurePathComponent(s) - if not string.match(s, "^[a-zA-Z0-9_%-%+%,%#%~%@%'%;%[%]%(%)%&%%%$%! %=%{%}%^]+$") then error("chars disallowed") end + if not string.match(s, "^[a-zA-Z0-9_%-%+%,%.%#%~%@%'%;%[%]%(%)%&%%%$%! %=%{%}%^]+$") then error("chars disallowed: " .. s) end if s == "." then error("single dot disallowed") end if s == ".." then error("double dot disallowed") end end @@ -245,6 +255,7 @@ function loadLibraryInner(library) if l then local ok, al = pcall(l) if ok then + al = wrapMeta(al) libraries[library] = al return al else @@ -355,6 +366,15 @@ function runProgramPolicy(ipkg, pkg, pid, ...) return true end +-- This is hidden here to protect you. +-- I beg of you, don't remove it. +if load(string.dump(function()end)) then + local oldLoad = load + load = function (c, n, m, ...) + return oldLoad(c, n, "t", ...) + end +end + function retrieveAccess(perm, pkg, pid) -- Return the access lib and the death callback. @@ -467,7 +487,8 @@ function start(pkg, ...) local function startFromUser(ipkg, ...) ensureType(ipkg, "string") - ensurePathComponent(ipkg .. ".lua") + local ok, n = pcall(ensurePathComponent, ipkg .. ".lua") + if not ok then return nil, n end local k, r = runProgramPolicy(ipkg, pkg, pid, ...) if k then return start(ipkg, pkg, pid, ...) diff --git a/code/libs/braille.lua b/code/libs/braille.lua index 6aeb60b..9020967 100644 --- a/code/libs/braille.lua +++ b/code/libs/braille.lua @@ -1,8 +1,11 @@ -- This is released into the public domain. -- No warranty is provided, implied or otherwise. --- Braille Neoux Component --- Callbacks : +-- Braille Converter & NeoUX component +-- While the Neoux part isn't OS-independent, +-- the converter itself is. Enjoy. + +-- Braille Neoux Component Callbacks : -- selectable (boolean) -- key(window, update, a, c, d) -- touch(window, update, x, y, button) @@ -164,7 +167,7 @@ local function calcLine(x, y, w, span, get, colour) span(x, y, str, bg, fg) end end -heldRef = neo.wrapMeta({ +heldRef = { calcLine = calcLine, new = function (x, y, w, h, cbs, colour) local control @@ -189,5 +192,5 @@ heldRef = neo.wrapMeta({ } return control end, -}) +} return heldRef diff --git a/code/libs/fmttext.lua b/code/libs/fmttext.lua index bd5938b..eece183 100644 --- a/code/libs/fmttext.lua +++ b/code/libs/fmttext.lua @@ -18,6 +18,7 @@ fmt = { end return t end, + -- Expects safeTextFormat'd input fmtText = function (text, w) local nl = text:find("\n") if nl then @@ -67,4 +68,4 @@ fmt = { return {fmt.pad(text, w)} end } -return neo.wrapMeta(fmt) +return fmt diff --git a/code/libs/neoux.lua b/code/libs/neoux.lua index 00e2b10..06be233 100644 --- a/code/libs/neoux.lua +++ b/code/libs/neoux.lua @@ -82,7 +82,10 @@ newNeoux = function (event, neo) return window end -- Padding function - neoux.pad = require("fmttext").pad + neoux.pad = function (...) + local fmt = require("fmttext") + return fmt.pad(...) + end -- Text dialog formatting function. -- Assumes you've run unicode.safeTextFormat if need be neoux.fmtText = function (...) diff --git a/code/libs/serial.lua b/code/libs/serial.lua index 334db82..4e1034b 100644 --- a/code/libs/serial.lua +++ b/code/libs/serial.lua @@ -26,12 +26,16 @@ function doSerialize(s) end error("Cannot serialize " .. type(s)) end -return neo.wrapMeta({ +return { serialize = function (x) return "return " .. doSerialize(x) end, deserialize = function (s) - local r1, r2 = pcall(function() return load(s, "=serial", "t", {})() end) + local r1, r2 = pcall(function() + return load(s, "=serial", "t", {})() + end) if r1 then return r2 + else + return nil, tostring(r2) end end -}) +} diff --git a/code/libs/sys-secpolicy.lua b/code/libs/sys-secpolicy.lua index a54c9fd..05d6bfb 100644 --- a/code/libs/sys-secpolicy.lua +++ b/code/libs/sys-secpolicy.lua @@ -21,6 +21,10 @@ local actualPolicy = function (pkg, pid, perm) if perm:sub(1, 10) == "x.neo.pub." then return "allow" end + -- These signals are harmless, though they identify HW (as does everything in OC...) + if perm == "s.h.component_added" or perm == "s.h.component_removed" then + return "allow" + end -- This is to ensure the prefix naming scheme is FOLLOWED! -- sys- : System, part of KittenOS NEO and thus tries to present a "unified fragmented interface" in 'neo' -- app- : Application - these can have ad-hoc relationships. It is EXPECTED these have a GUI diff --git a/repository/data/app-claw/local.lua b/repository/data/app-claw/local.lua index fa42d2a..68caf78 100644 --- a/repository/data/app-claw/local.lua +++ b/repository/data/app-claw/local.lua @@ -33,8 +33,10 @@ return { "docs/kn-sched", "docs/kn-perms", "docs/us-perms", + "docs/us-nxapp", "docs/ul-seria", "docs/ul-event", + "docs/ul-fmttx", "docs/ul-neoux", "docs/ul-broil", "docs/gp-pedan" diff --git a/repository/docs/an-intro b/repository/docs/an-intro index 10409da..60def96 100644 --- a/repository/docs/an-intro +++ b/repository/docs/an-intro @@ -51,7 +51,11 @@ This is a critical memory management (This also means libraries can have security side-effects, but they always can in any system, arguably, - and it's worth it for the memory.) + and it's worth it for the memory. + Notably, library values get + wrapMeta'd automatically since R2, + in order to reduce NEO-specific + code.) The processes are applications and services, that communicate with the diff --git a/repository/docs/kn-refer b/repository/docs/kn-refer index 8e26d9b..ae41719 100644 --- a/repository/docs/kn-refer +++ b/repository/docs/kn-refer @@ -78,7 +78,21 @@ unicode is extended with: safe to pass to a GPU without any odd graphical glitches. -os is replaced with: +The KittenOS NEO kernel also reserves + the ability to take advantage of any + full de-UTF16'd support for Unicode + available on the system, but will + not include such support as a shim + for memory usage reasons. + +Programs that thus try to work around + this problem should delegate this + task to a library, in a separate + package, which can then be updated + as-needed if and when the issue is + resolved. + +os is replaced with (wrapMeta'd): totalMemory = computer.totalMemory, freeMemory = computer.freeMemory, energy = computer.energy, @@ -89,9 +103,9 @@ os is replaced with: uptime = computer.uptime, address = computer.address -The following are just wrapMeta'd - host functions - (*: wrapped for security): +The following are just host functions + (*: wrapped for security - these + functions detect metatable abuse): assert, ipairs, load, next*, pairs, pcall, xpcall, select, @@ -99,6 +113,20 @@ The following are just wrapMeta'd setmetatable, getmetatable*, rawset*, rawget, rawlen, rawequal +(NOTE: Before you consider that load + has no checks: The policy regarding + load is taken from the host system. + Which means bytecode loading is + almost certainly off. If it's not + off, then this is the user's fault, + as doing so is marked as a security + risk for very obvious reasons. + As for trying to use the environment + to bypass a metatable, I tested. + Metatables do apply to environments, + including global creation. + There is no way to win.) + "require" and "neo" are the parts of the environment where a NEO-specific nature presents itself. @@ -107,6 +135,13 @@ require takes a string, and returns the value returned by the library at "libs/" .. str .. ".lua" on the primary disk. + Since R2, the value is automatically + wrapMeta'd, just in case. + Before R2, libraries did this on + their own, but this caused NEO-only + code to crop up in libraries that + did not need NEO-only code. + The library name must be a valid path component, and the library path must also be valid - see @@ -285,4 +320,3 @@ With that, I hope I have documented the public domain. -- No warranty is provided, implied or otherwise. - diff --git a/repository/docs/ul-fmttx b/repository/docs/ul-fmttx new file mode 100644 index 0000000..21a6ea6 --- /dev/null +++ b/repository/docs/ul-fmttx @@ -0,0 +1,55 @@ +The "fmttext" library is used for + formatting text in various places in + KittenOS NEO. + +It's recommended that you only load + this library when you need it, and + release the value immediately after, + as it is rarely called, and has no + sticky objects that could cause + duplicated library issues. + +If using neoux, the pad and fmtText + functions are proxied there in a + load-on-demand form, such that you + can call them, and the library is + loaded for that call. + +Essentially, it's job is to take some + safeTextFormat'd text, and turn it + into a column of a given width. + +It has two functions for this task: + pad(text, len[, centre[, cut]]): + Pads the given safeTextFormat'd + string to a given width, returning + the resulting string. + If centre is true, then the text is + centred within the area given - + otherwise, it is left-justified. + (Values that are not nil or true + are reserved for future use.) + If cut is true, then the text may + be reduced in size if necessary. + Otherwise, text that is too long is + not reduced. + + fmtText(text, width): + Formats the given text to a given + width in a wrapping fashion. + Returns a series of lines that are + padded to the given width. + If there are newlines in the text, + these newlines are respected. + If possible, the wrapping is a word + wrap style, but words are broken + if necessary. + If the width is less than 2, then + this function may fail in various + ways, up to and including freezes. + +-- This is released into + the public domain. +-- No warranty is provided, + implied or otherwise. + diff --git a/repository/docs/ul-neoux b/repository/docs/ul-neoux index 38350e2..85bc970 100644 --- a/repository/docs/ul-neoux +++ b/repository/docs/ul-neoux @@ -1,4 +1,49 @@ -Hello World. +The "neoux" (aka NeoUX) library is a + UI framework for KittenOS NEO, meant + to provide a consistent set of + controls and a consistent way to + navigate the UI in any given case. + +Thus, it's not used by text editing + programs such as Neolithic. + +To get ahold of NeoUX in your app, + use code similar to: + +local event, neoux +event = require("event")(neo) +neoux = require("neoux")(event, neo) + +The neo table is used for retrieving + the required accesses for APIs. + +The NeoUX API is divided into three + parts - the part that connects it to + Everest & utility functions, the UI + framework's "tcwindow" root, and the + basic set of controls. + +The most reliable reference on the + API a control implements is given + at the top of libs/neoux.lua, and + for updatability reasons will not + be repeated here, except with the + note that "xI"/"yI" is within-char + position from 0 to 1. + + TODO, TODO, TODO, TODO, TODO, TODO + + neoux.fileDialog = function (forWrite, callback) + neoux.create = function (w, h, title, callback) + neoux.pad = require("fmttext").pad + neoux.fmtText = function (...) + neoux.tcwindow = function (w, h, controls, closing, bg, fg, selIndex) + neoux.tcrawview = function (x, y, lines) + neoux.tchdivider = function (x, y, w) + neoux.tcvdivider = function (x, y, h) + neoux.tcbutton = function (x, y, text, callback) + neoux.tcfield = function (x, y, w, textprop) + neoux.startDialog = function (fmt, title, wait) -- This is released into the public domain. diff --git a/repository/docs/ul-seria b/repository/docs/ul-seria index 38350e2..c29ee1e 100644 --- a/repository/docs/ul-seria +++ b/repository/docs/ul-seria @@ -1,4 +1,54 @@ -Hello World. +The "serial" library is a library to + serialize and deserialize Lua values + in a relatively safe* manner. + + * Serialization cannot handle a + recursive loop correctly, + and may error() if certain values + are passed to it. + The deserialization has unbounded + time and memory only limited by + the host. It is possible to kill + a process indirectly via a + poisonous file, but it is not + possible to directly break the + sandbox without Lua interpreter + bugs. + +It is not recommended to use serial + for data that is not from a known + source, but it is not dangerous to + system security (but certainly to + stability) to use it for other + data so long as no function that + originated from the data is ever + executed with objects that can be + used to elevate privilege. + +(In other words, don't call any + function if you can't tell where it + came from. This should be obvious.) + +The serial library has merely two + functions available to it. + + serialize(val): + Returns the serialized data as a + string. The serialized data will + be in the form of "return ", + followed by a Lua 5.2-parsable + value of some sort. + + deserialize(str): + Returns the deserialized data as a + Lua value. + A value of nil is an ambiguity: + it could be the actual data, or it + could be a deserialization error. + Check for this situation by reading + the second returned value. + If it is not nil, deserialization + failed with the given error. -- This is released into the public domain. diff --git a/repository/docs/us-nxapp b/repository/docs/us-nxapp new file mode 100644 index 0000000..0a84684 --- /dev/null +++ b/repository/docs/us-nxapp @@ -0,0 +1,35 @@ +A Quick Note On NeoUX Application + Structure + +A typical NeoUX application has one + window, which it uses .reset on in + order to change the window contents + to different things. + +This is typically achieved with a + callback to regenerate the window, + used like this: + +window = neoux.create(mainWin()) + + and to regenerate the window: + +window.reset(mainWin()) + +This allows a simple way to write big + UI trees without going totally nuts. + +A good example of this is app-flash, + but unlike most of the examples, it + does not change the regeneration + callback (it never has to - the + labelling window never needs to be + regenerated after it's switched to, + so the only regeneration is for the + main window) + +-- This is released into + the public domain. +-- No warranty is provided, + implied or otherwise. +