diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/bin/cat.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/bin/cat.lua index b292f2291..d1fd62ba5 100644 --- a/src/main/resources/assets/opencomputers/loot/Plan9k/bin/cat.lua +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/bin/cat.lua @@ -8,7 +8,7 @@ if #args == 0 then until not read else for i = 1, #args do - local file, reason = io.open(args[i]) + local file, reason = io.open(args[i],"rb")--TODO: make b an option if not file then io.stderr:write(reason .. "\n") return diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/bin/dd.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/bin/dd.lua index de4509434..afcf298c0 100644 --- a/src/main/resources/assets/opencomputers/loot/Plan9k/bin/dd.lua +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/bin/dd.lua @@ -67,6 +67,8 @@ for n = 1, options.count do end if options.wait then os.sleep(tonumber(options.wait)) + else + os.sleep(0) end end diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/bin/df.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/bin/df.lua index 9cbc74107..041514da9 100644 --- a/src/main/resources/assets/opencomputers/loot/Plan9k/bin/df.lua +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/bin/df.lua @@ -5,7 +5,8 @@ local text = require("text") local args, options = shell.parse(...) local function formatSize(size) - if not options.h then + size = tonumber(size) or size + if not options.h or type(size) ~= "number" then return tostring(size) end local sizes = {"", "K", "M", "G"} diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/bin/edit.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/bin/edit.lua index f178f7eec..c1943cd7c 100644 --- a/src/main/resources/assets/opencomputers/loot/Plan9k/bin/edit.lua +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/bin/edit.lua @@ -73,6 +73,7 @@ local code = "" codeHandler = function(char) if char == "[" then code = code .. char elseif char == "0" then code = code .. char + elseif char == "3" then code = code .. char elseif code == "[" and char == "A" then charHandler = baseHandler if y - 1 < 1 then return end @@ -139,6 +140,16 @@ codeHandler = function(char) out:write(text) out:close() end + elseif code == "[3" and char == "~" then + charHandler = baseHandler + if x > unicode.len(lines[y]) then + lines[y] = lines[y] .. (lines[y + 1] or "") + table.remove(lines, y + 1) + render(y, atline + edith - y) + return + end + lines[y] = lines[y]:sub(1, x-1) .. lines[y]:sub(x+1) + render(y, 1) else charHandler = baseHandler end @@ -149,7 +160,7 @@ baseHandler = function(char) code = "" charHandler = codeHandler elseif char == "\n" then - line = lines[y] + local line = lines[y] lines[y] = unicode.sub(line or "", 1, x - 1) table.insert(lines, y + 1, unicode.sub(line or "", x)) x = 1 diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/bin/getty.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/bin/getty.lua index 2f2a21992..9cedb28e2 100644 --- a/src/main/resources/assets/opencomputers/loot/Plan9k/bin/getty.lua +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/bin/getty.lua @@ -199,6 +199,8 @@ local commandList = {} -- \x1b9[Row];[Col];[Height];[Width]F -- fill -- \x1b9[Row];[Col];[Height];[Width];[Dest Row];[Dest Col]c -- copy +--Add fake gpu component for compat(?) + function charHandlers.control(char) if char == "\x1b" then commandList = {} diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/bin/ifconfig.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/bin/ifconfig.lua index e7a9ba5cd..42a9f4862 100644 --- a/src/main/resources/assets/opencomputers/loot/Plan9k/bin/ifconfig.lua +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/bin/ifconfig.lua @@ -2,6 +2,21 @@ local network = require "network" local computer = require "computer" local args = {...} +local function formatSize(size) + size = tonumber(size) or size + if type(size) ~= "number" then + return tostring(size) + end + local sizes = {"", "K", "M", "G"} + local unit = 1 + local power = 1024 + while size > power and unit < #sizes do + unit = unit + 1 + size = size / power + end + return math.floor(size * 10) / 10 .. sizes[unit] +end + local function align(txt)return txt .. (" "):sub(#txt+1)end if #args < 1 then @@ -14,7 +29,7 @@ if #args < 1 then local pktIn, pktOut, bytesIn, bytesOut = network.info.getInterfaceInfo(node) print(" RX packets:"..tostring(pktIn)) print(" TX packets:"..tostring(pktOut)) - print(" RX bytes:"..tostring(bytesIn).." TX bytes:"..tostring(bytesOut)) + print(" RX bytes: ".. tostring(bytesIn) .. " (" ..formatSize(bytesIn).. ") TX bytes: " ..tostring(bytesOut) .. " (".. formatSize(bytesOut) .. ")") end elseif args[1] == "bind" and args[2] then print("Address attached") diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/bin/init.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/bin/init.lua index 71146c458..02a8042b3 100644 --- a/src/main/resources/assets/opencomputers/loot/Plan9k/bin/init.lua +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/bin/init.lua @@ -1,13 +1,28 @@ --Plan9k userspace init for pipes kernel + +--TODO: pcall all + emergency shell(or do it higher, in pipes) + local pipes = require("pipes") -local component = require("component") local filesystem = require("filesystem") +local component = require("component") os.setenv("LIBPATH", "/lib/?.lua;/usr/lib/?.lua;/home/lib/?.lua;./?.lua;/lib/?/init.lua;/usr/lib/?/init.lua;/home/lib/?/init.lua;./?/init.lua") os.setenv("PATH", "/usr/local/bin:/usr/bin:/bin:.") os.setenv("PWD", "/") os.setenv("PS1", "\x1b[33m$PWD\x1b[31m#\x1b[39m ") +pipes.log("INIT: Mounting filesystems") + +if filesystem.exists("/etc/fstab") then + for entry in io.lines("/etc/fstab") do + if entry:sub(1,1) ~= "#" then + + end + end +end + +pipes.log("INIT: Starting terminals") + if not filesystem.exists("/root") then filesystem.makeDirectory("/root") end @@ -37,7 +52,6 @@ end local sin, sout - local screens = component.list("screen") for gpu in component.list("gpu") do local screen = screens() @@ -85,7 +99,11 @@ end pcall(services) local kout = io.popen(function() - pipes.setThreadName("/bin/tee.lua") + if filesystem.exists("/kern.log") then + filesystem.remove("/kern.log.old") + filesystem.rename("/kern.log", "/kern.log.old") + end + pipes.setThreadName("[init]/logd") io.output(sout) loadfile("/bin/tee.lua", nil, _G)("/kern.log") end, "w") diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/bin/lua.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/bin/lua.lua index fe946e194..f00045057 100644 --- a/src/main/resources/assets/opencomputers/loot/Plan9k/bin/lua.lua +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/bin/lua.lua @@ -1,5 +1,8 @@ local serialization = require("serialization") local term = require("term") +local fs = require("filesystem") + +local args = {...} local env = setmetatable({}, {__index = _ENV}) @@ -10,6 +13,13 @@ local function optrequire(...) end end +if args[1] and fs.exists(args[1]) then --non standard, require -i !!! + local f = io.open(args[1]) + local code = load(f:read("*all"), "="..args[1], "t", env) + f:close() + xpcall(code, debug.traceback) +end + local hist = {} while true do io.write(tostring(env._PROMPT or "lua> ")) diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/bin/more.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/bin/more.lua new file mode 100644 index 000000000..648ef31c5 --- /dev/null +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/bin/more.lua @@ -0,0 +1,44 @@ +local term = require("term") + +function usage() + print( +[[Usage: + more [options] ... + +A file perusal filter for CRT viewing.]]) +end + +local args = {...} +local file = args[1] +if not file then usage() return end + +file = io.open(file) + +if not file then + print("File not found") + return +end + +term.clear() +local _, h = term.getResolution() +io.write("\x1b[1;1H") +print("...",h) +for i = 1, h - 2 do + local line = file:read("*l") + if not line then print("input end")return end + print(line) +end + +io.write("\x1b47m\x1b30m--More--\x1b39m\x1b49m") + +while true do + local c = io.read(1) + if c == "\n" then + local line = file:read("*l") + if not line then return end + print("\r\x1b[K" .. line) + io.write("\x1b47m\x1b30m--More--\x1b39m\x1b49m") + elseif c == "q" then + return + end +end diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/bin/sh.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/bin/sh.lua index 5fb8c378c..db4c3b3ef 100644 --- a/src/main/resources/assets/opencomputers/loot/Plan9k/bin/sh.lua +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/bin/sh.lua @@ -203,6 +203,7 @@ while run do if term.getCursor() > 1 then io.write("\n") end + io.write("\x1b49m\x1b39m") io.write(expand(os.getenv("PS1"))) local cmd = term.read(history)--io.read("*l") --print("--IN: ", cmd) diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/bin/tee.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/bin/tee.lua index 828335ac3..41e324564 100644 --- a/src/main/resources/assets/opencomputers/loot/Plan9k/bin/tee.lua +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/bin/tee.lua @@ -3,7 +3,7 @@ local args = {...} local f = io.open(args[1], "a") while true do - local data = io.read(1) + local data = io.read("*L") if not data then f:close() return @@ -11,7 +11,7 @@ while true do if io.input().remaining() > 0 then data = data .. io.read(io.input().remaining()) end + io.write(data) f:write(data) f:flush() - io.write(data) end diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/10_devfs.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/10_devfs.lua index 806a414c6..61b03bd22 100644 --- a/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/10_devfs.lua +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/10_devfs.lua @@ -9,7 +9,6 @@ proxy.isReadOnly = function() return true end proxy.rename = function() error("Permission Denied") end proxy.remove = function() error("Permission Denied") end proxy.setLabel = function() error("Permission Denied") end -proxy.seek = function() error("Not supported") end proxy.size = function(path) local seg = kernel.modules.vfs.segments(path) local file = data @@ -22,7 +21,17 @@ proxy.getLabel = function() return "devfs" end local allocator, handles = kernel.modules.util.getAllocator() -proxy.exists = function()end +proxy.exists = function(path) + local seg = kernel.modules.vfs.segments(path) + local file = data + for _, d in pairs(seg) do + if not file[d] then + return false + end + file = file[d] + end + return file and true or false +end proxy.open = function(path) local seg = kernel.modules.vfs.segments(path) local file = data @@ -48,6 +57,9 @@ end proxy.write = function(h, ...) return handles[h].file.write(handles[h], ...) end +proxy.seek = function(h, ...) + return handles[h].file.seek(handles[h], ...) +end proxy.isDirectory = function(path) local seg = kernel.modules.vfs.segments(path) local dir = data @@ -69,8 +81,8 @@ proxy.list = function(path) error("File is not a directory") end local list = {} - for f in pairs(dir) do - list[#list + 1] = f + for f, node in pairs(dir) do + list[#list + 1] = f .. (node.__type and "" or "/") end return list end @@ -80,6 +92,12 @@ data.null = { __type = "f", write = function()end } +data.kmsg = { + __type = "f", + write = function(h, data) + kernel.io.println(data) + end +} data.zero = { __type = "f", read = function(h, c) diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/10_procfs.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/10_procfs.lua index 7c60579b2..91a41d1a1 100644 --- a/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/10_procfs.lua +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/10_procfs.lua @@ -15,6 +15,7 @@ proxy.getLabel = function() return "procfs" end local allocator, handles = kernel.modules.util.getAllocator() proxy.exists = function()end + proxy.open = function(path) local seg = kernel.modules.vfs.segments(path) local file = data @@ -32,16 +33,21 @@ proxy.open = function(path) end return hnd.id end + proxy.read = function(h, n) return handles[h]:read(n) end + proxy.close = function(h) allocator:unset(handles[h]) end + proxy.write = function() error("Permission Denied") end + proxy.isDirectory = function() end + proxy.list = function(path) local seg = kernel.modules.vfs.segments(path) local dir = data @@ -51,11 +57,11 @@ proxy.list = function(path) local list = {} for pid, thr in pairs(kernel.modules.threading.threads) do if thr.coro and dir == data then - list[#list + 1] = tostring(pid) + list[#list + 1] = tostring(pid) .. "/" end end - for f in pairs(dir) do - list[#list + 1] = f + for f, node in pairs(dir) do + list[#list + 1] = f .. (type(node) == "table" and "/" or "") end return list end @@ -72,13 +78,36 @@ data.cpuinfo = function() "cpu family : 1\n" .. "model : 1\n" .. "model name : OpenComputers Lua CPU @ unkown Tier\n" .. - "microcode : 0x52\n" .. + "microcode : " .. (string.pack and "0x53" or "0x52") .. "\n" .. "physical id : 0\n" end +data.uptime = function() + return tostring(computer.uptime()) +end + setmetatable(data, {__index = function(_, k) if tonumber(k) and kernel.modules.threading.threads[tonumber(k)] and kernel.modules.threading.threads[tonumber(k)].coro then - return {comm = function()return kernel.modules.threading.threads[tonumber(k)].name end} + return { + comm = function()return kernel.modules.threading.threads[tonumber(k)].name end, + limits = function() + local limits = "Limit Units Soft Limit\n" + limits = limits .. "Max pending signals signals " .. kernel.modules.threading.threads[tonumber(k)].maxPendingSignals .. "\n" + limits = limits .. "Max open files files " .. kernel.modules.threading.threads[tonumber(k)].maxOpenFiles .. "\n" + return limits + end, + status = function() + local status = "" + status = status .. "Name: " .. kernel.modules.threading.threads[tonumber(k)].name .. "\n" + status = status .. "State: " .. coroutine.status(kernel.modules.threading.threads[tonumber(k)].coro) .. "\n" + status = status .. "Pid: " .. kernel.modules.threading.threads[tonumber(k)].pid .. "\n" + status = status .. "Uid: " .. kernel.modules.threading.threads[tonumber(k)].uid .. "\n" + + --TODO: count actual signals + status = status .. "SigQ: " .. #kernel.modules.threading.threads[tonumber(k)].eventQueue .. "/" .. kernel.modules.threading.threads[tonumber(k)].maxPendingSignals .. "\n" + return status + end + } end end}) diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/15_userspace.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/15_userspace.lua index 5efd66a64..4be9c6c50 100644 --- a/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/15_userspace.lua +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/15_userspace.lua @@ -51,6 +51,7 @@ function kernel.userspace.os.spawn(prog, ...) local thread = kernel.modules.threading.spawn(prog, 0, name, isThread, _, ...) thread.io_output = kernel.modules.threading.currentThread.io_output thread.io_input = kernel.modules.threading.currentThread.io_input + thread.io_error = kernel.modules.threading.currentThread.io_error return thread.pid end @@ -78,6 +79,7 @@ end function kernel.userspace.os.exit() kernel.modules.threading.kill(kernel.modules.threading.currentThread.pid) + coroutine.yield("yield", 0) end function kernel.userspace.os.sleep(time) @@ -142,7 +144,12 @@ end kernel.userspace.coroutine = {} -kernel.userspace.coroutine.yield = function(...) - return coroutine.yield(...)--TODO: FIX; move to debug -end - +--lua 5.3 <-> 5.2 compat +kernel.userspace.bit32 = bit32 or load([[return { + band = function(a, b) return a & b end, + bor = function(a, b) return a | b end, + bxor = function(a, b) return a ~ b end, + bnot = function(a) return ~a end, + rshift = function(a, n) return a >> n end, + lshift = function(a, n) return a << n end, +}]])() diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/16_require.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/16_require.lua index bb72e1a5a..e25ba7113 100644 --- a/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/16_require.lua +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/16_require.lua @@ -39,18 +39,17 @@ end local function pathSearcher(module) local filepath, reason = kernel.userspace.package.searchpath(module, kernel.userspace.os.getenv("LIBPATH")) if filepath then - local loader, reason = kernel.userspace.loadfile(filepath, "bt", setmetatable({},{__index = kernel.userspace})) + local loader + loader, reason = kernel.userspace.loadfile(filepath, "bt", setmetatable({},{__index = kernel.userspace})) if loader then - local state, mod = pcall(loader) + local state + state, reason = pcall(loader) if state then - return mod - else - kernel.io.println("Module '" .. tostring(module) .. "' loading failed: " .. tostring(mod)) + return reason end end - else - return nil, reason end + return nil, reason end kernel.userspace.package.searchers[#kernel.userspace.package.searchers + 1] = preloadSearcher @@ -65,19 +64,23 @@ kernel.userspace.require = function(module) if kernel.userspace.package.loading[module] then error("Already loading "..tostring(module)) else + local reason + kernel.userspace.package.loading[module] = true for _, searcher in ipairs(kernel.userspace.package.searchers) do - local res, mod, reason = pcall(searcher, module) - if res and mod then + local success, mod, res = pcall(searcher, module) + if success and mod then kernel.userspace.package.loading[module] = nil kernel.userspace.package.loaded[module] = mod return mod - elseif not mod and reason then - kernel.io.println("Searcher for '" .. tostring(module) .. "' loading failed: " .. tostring(reason)) + elseif (not success) and mod then + reason = mod + elseif res then + reason = res end end kernel.userspace.package.loading[module] = nil - error("Could not load module " .. tostring(module)) + error(string.format("Could not load module '%s': %s", module, reason or "module returned nil")) end end end diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/17_data.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/17_data.lua new file mode 100644 index 000000000..4676746f4 --- /dev/null +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/17_data.lua @@ -0,0 +1,47 @@ +cards = {} + + +local function buildDevfs() + for file in pairs(kernel.modules.devfs.data) do + if file == "urandom" then + kernel.modules.devfs.data[file] = nil + end + end + + kernel.modules.devfs.data["urandom"] = { + __type = "f", + read = function(h, len) + return component.invoke(cards[1], "random", len) + end + } +end + +local function onComponentAdded(_, address, componentType) + if componentType == "data" then + cards[#cards + 1] = address + buildDevfs() + end +end + +local function onComponentRemoved(_, address, componentType) + if componentType == "data" then + local t + for i, card in ipairs(cards) do + if card == address then + t = i + break + end + end + table.remove(cards, t) + buildDevfs() + end +end + +--function start() + --for card, t in component.list("data") do + -- onComponentAdded(_, card, t) + --end +--end + +kernel.modules.keventd.listen("component_added", onComponentAdded) +kernel.modules.keventd.listen("component_removed", onComponentRemoved) diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/17_drive.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/17_drive.lua new file mode 100644 index 000000000..a080514d7 --- /dev/null +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/17_drive.lua @@ -0,0 +1,117 @@ +drives = {} + +function writeSectors(drive, data, at) + local sectorSize = component.invoke(drive, "getSectorSize") + repeat + local atSector = math.floor((at - 1) / sectorSize) + 1 + + local inSectorStart = (at - 1) % sectorSize + 1 + local writable = math.min(#data, sectorSize - inSectorStart + 1) + + local old = component.invoke(drive, "readSector", atSector) + + local before = old:sub(0, inSectorStart - 1) + local after = old:sub(inSectorStart + writable) + + local toWrite = before .. data:sub(1, writable) .. after + data = data:sub(writable + 1) + + kernel.io.println("Wd: " .. atSector .. "/" .. #toWrite .. ": "..inSectorStart.." [ " .. writable .. " ] "..(inSectorStart + writable) .. " #old="..#old) + component.invoke(drive, "writeSector", atSector, toWrite) + + at = at + writable + until #data < 1 +end + +function readSectors(drive, at, len) + local data = "" + local sectorSize = component.invoke(drive, "getSectorSize") + repeat + local atSector = math.floor(at / sectorSize) + 1 + + sector = component.invoke(drive, "readSector", atSector) + kernel.io.println("Rsect " .. atSector .. ": " .. tostring((at - 1) % sectorSize + 1) .. " -> " .. tostring(math.min((at - 1) % sectorSize + len - #data, sectorSize))) + local read = sector:sub((at - 1) % sectorSize + 1, math.min((at - 1) % sectorSize + len - #data, sectorSize)) + + data = data .. read + at = at + #read + until #data >= len + return data +end + +local function buildDevfs() + for file in pairs(kernel.modules.devfs.data) do + if file:match("^sd") then + kernel.modules.devfs.data[file] = nil + end + end + for k, drive in ipairs(drives) do + kernel.modules.devfs.data["sd" .. string.char(k + 96)] = { + __type = "f", + open = function(hnd) + --component.invoke(drive, "seek", -math.huge) + hnd.drive = drive + hnd.pos = 1 + --kernel.io.println("Od: " .. hnd.pos .. "/" .. component.invoke(drive, "getCapacity")) + end, + size = function() + return component.invoke(drive, "getCapacity") + end, + write = function(h, data) + + writeSectors(drive, data, h.pos) + --kernel.io.println("Wd: " .. h.pos .. "(+" .. #data .. ")/" .. component.invoke(drive, "getCapacity")) + h.pos = h.pos + #data + return not (h.pos >= component.invoke(drive, "getCapacity")) + --TODO: do this correctly + end, + read = function(h, len) + len = math.ceil(len) + kernel.io.println("Rd " .. tostring(len) .. ": " .. h.pos .. "/" .. component.invoke(drive, "getCapacity")) + if h.pos >= component.invoke(drive, "getCapacity") then + return + end + local data = readSectors(drive, h.pos, len) + h.pos = h.pos + len + return data + end, + seek = function(h, whence, offset) + offset = offset or 0 + if whence == "end" then + h.pos = math.min(component.invoke(drive, "getCapacity"), math.max(1, component.invoke(drive, "getCapacity") - offset)) + return h.pos - 1 + elseif whence == "set" then + h.pos = math.min(component.invoke(drive, "getCapacity"), math.max(1, 1 + offset)) + return h.pos - 1 + else + h.pos = math.min(component.invoke(drive, "getCapacity"), math.max(1, h.pos + offset)) + return h.pos - 1 + end + return math.floor(h.pos) + end + } + end +end + +local function onComponentAdded(_, address, componentType) + if componentType == "drive" then + drives[#drives + 1] = address + buildDevfs() + end +end + +local function onComponentRemoved(_, address, componentType) + if componentType == "drive" then + local t + for i, drive in ipairs(drives) do + if drive == address then + t = i + break + end + end + table.remove(drives, t) + buildDevfs() + end +end +kernel.modules.keventd.listen("component_added", onComponentAdded) +kernel.modules.keventd.listen("component_removed", onComponentRemoved) diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/17_network.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/17_network.lua index 33ad4d5ff..84ba412ed 100644 --- a/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/17_network.lua +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/17_network.lua @@ -321,6 +321,7 @@ startNetwork = function() end sent = nil else + --we've already requested this addr so if we get the route --we'll respond routeRequests[dest][#routeRequests[dest]+1] = {type = "R", host = origin} diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/17_tape.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/17_tape.lua index faaf7efe9..359163dde 100644 --- a/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/17_tape.lua +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/17_tape.lua @@ -15,20 +15,33 @@ local function buildDevfs() end component.invoke(tape, "seek", -math.huge) hnd.tape = tape + hnd.pos = 0 end, size = function() return component.invoke(tape, "getSize") end, write = function(h, data) component.invoke(tape, "write", data) - return not component.invoke(tape, "isEnd", data) + h.pos = h.pos + #data + return not (h.pos >= component.invoke(tape, "getSize")) --TODO: do this correctly end, read = function(h, len) - if component.invoke(tape, "isEnd", data) then + if h.pos >= component.invoke(tape, "getSize") then return end + h.pos = h.pos + len return component.invoke(tape, "read", len) + end, + seek = function(h, whence, offset) + if whence == "end" then + h.pos = h.pos + component.invoke(tape, "seek", component.invoke(tape, "getSize") - h.pos - (offset or 0)) + elseif whence == "set" then + h.pos = h.pos + component.invoke(tape, "seek", (offset or 0) - h.pos) + else + h.pos = h.pos + component.invoke(tape, "seek", offset or 0) + end + return math.floor(h.pos) end } end @@ -55,11 +68,11 @@ local function onComponentRemoved(_, address, componentType) end end -function start() - for tape, t in component.list("tape_drive") do - onComponentAdded(_, tape, t) - end -end +--function start() +-- for tape, t in component.list("tape_drive") do +-- onComponentAdded(_, tape, t) +-- end +--end kernel.modules.keventd.listen("component_added", onComponentAdded) kernel.modules.keventd.listen("component_removed", onComponentRemoved) diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/20_threading.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/20_threading.lua index 8dd4b8f2a..7d7015ed3 100644 --- a/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/20_threading.lua +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/20_threading.lua @@ -71,6 +71,8 @@ function spawn(exec, child, name, isthread, _, ...) currentHandlerArg = nil, eventQueue = {{"arg", ...}}, name = name or "unnamed", + maxPendingSignals = 32, + maxOpenFiles = 8, uid = nextUid } @@ -132,7 +134,7 @@ local function processSignals() for _, thread in ipairs(threads) do if thread.coro then local nsig, oldest = countThreadSignals(thread, "signal") - if nsig > 32 then --TODO: make it a bit more intelligent + if nsig > thread.maxPendingSignals then --TODO: make it a bit more intelligent table.remove(thread.eventQueue, oldest) end if thread.currentHandler == "yield" then diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/21_threadUtil.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/21_threadUtil.lua index d755e06ad..8c473878c 100644 --- a/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/21_threadUtil.lua +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/lib/modules/base/21_threadUtil.lua @@ -1,4 +1,5 @@ function joinThread(pid) + --coroutine.yield("yield", 0) while true do local dead = coroutine.yield("kill") if pid == dead then @@ -30,7 +31,7 @@ function userKill(pid, signal, ...) local args = {...} local thread = kernel.modules.threading.threads[pid] kernel.modules.manageg.protect(thread.sandbox) - --TODO: probably ser threading.currentThread here + --TODO: probably set threading.currentThread here local res, reason = pcall(function() thread.kill[signal](table.unpack(args)) end) @@ -41,7 +42,7 @@ function userKill(pid, signal, ...) return true end -function setKillHandler(signal, handler) +function setKillHandler(signal, handler) --WAT if not kernel.modules.threading.threads[pid] or not kernel.modules.threading.threads[pid].coro then return nil, "Thread does not exists" diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/lib/term.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/lib/term.lua index 21fda1bf1..5942d8322 100644 --- a/src/main/resources/assets/opencomputers/loot/Plan9k/lib/term.lua +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/lib/term.lua @@ -1,6 +1,8 @@ local term = {} -local function read(from, to) +term.escape = "\x1b" +local write = function(text) io.write(term.escape..text) end +local read = function(from, to) local started, data while true do local char = io.read(1) @@ -19,6 +21,279 @@ local function read(from, to) end end end + +term.color={} +term.color.black=30 +term.color.red=31 +term.color.green=32 +term.color.yellow=33 +term.color.blue=34 +term.color.magenta=35 +term.color.cyan=36 +term.color.white=37 + +term.attr={} +term.attr.resetAllAttr=0 +term.attr.bright=1 +term.attr.dim=2 +term.attr.blink=5 +term.attr.reverse=7 +term.attr.hidden=8 + +------------------------------------------ +--Set Display Attributes +------------------------------------------ + +--Set Attribute Mode *ESC*[{attr1};...;{attrn}m +function term.setAttr(attr) + write(attr.."m") +end + +function term.setForeground(color) + write(color.."m") +end + +function term.setBackground(color) + write((color+10).."m") +end + +------------------------------------------ +--Erasing Text +------------------------------------------ + +--Erase End of Line *ESC*[K +--Erases from the current cursor position to the end of the current line. +function term.eraseEndOfLine() + write("[K") +end + +--Erase Start of Line *ESC*[1K +--Erases from the current cursor position to the start of the current line. +function term.eraseStartOfLine() + write("[1K") +end + +--Erase Line *ESC*[2K +--Erases the entire current line. +function term.eraseLine() + write("[2K") +end +term.clearLine = term.eraseLine + +--Erase Down *ESC*[J +--Erases the screen from the current line down to the bottom of the screen. +function term.eraseDown() + write("[J") +end + +--Erase Up *ESC*[1J +--Erases the screen from the current line up to the top of the screen. +function term.eraseUp() + write("[1J") +end + +--Erase Screen *ESC*[2J +--Erases the screen with the background colour and moves the cursor to home. +function term.clear() + write("[2J") +end + + +------------------------------------------- +--Tab Control +------------------------------------------ + +--Set Tab *ESC*H +--Sets a tab at the current position. +function term.tab() + write("[H") +end + +--Clear Tab *ESC*[g +--Clears tab at the current position. +function term.clearTab() + write("[g") +end + +--Clear All Tabs *ESC*[3g +--Clears all tabs. +function term.clearTabs() + write("[3g") +end + + +------------------------------------------ +--Scrolling +------------------------------------------ + +--Scroll Screen *ESC*[r +--Enable scrolling for entire display. +function term.enableScroll() + write("[r") +end + +--Scroll Screen *ESC*[{start};{end}r +--Enable scrolling from row {start} to row {end}. +function term.scrollScreen(from,to) + write(string.format("[%d;%dr",from,to)) +end + +--Scroll Down *ESC*D +--Scroll display down one line. +function term.scrollScreenDown() + write("D") +end + +--Scroll Up *ESC*M +--Scroll display up one line. +function term.scrollScreenUp() + write("M") +end + + +------------------------------------------ +--Cursor Control +------------------------------------------ + +--Cursor Home *ESC*[{ROW};{COLUMN}H +--Sets the cursor position where subsequent text will begin. If no row/column parameters are provided (ie. *ESC*[H), the cursor will move to the home position, at the upper left of the screen. +function term.setCursorPosition(row,col) + write(string.format("[%d;%dH", row, col)) +end + +function term.resetCursor() + write("[H") +end + +--Cursor Up *ESC*[{COUNT}A +--Moves the cursor up by COUNT rows; the default count is 1. +function term.cursorUp(count) + write(string.format("[%dA",(count or 1))) +end + +--Cursor Down *ESC*[{COUNT}B +--Moves the cursor down by COUNT rows; the default count is 1. +function term.cursorDown(count) + write(string.format("[%dB",(count or 1))) +end + +--Cursor Forward *ESC*[{COUNT}C +--Moves the cursor forward by COUNT columns; the default count is 1. +function term.cursorForward(count) + write(string.format("[%dC",(count or 1))) +end + +--Cursor Backward *ESC*[{COUNT}D +--Moves the cursor backward by COUNT columns; the default count is 1. +function term.cursorBackward(count) + write(string.format("[%dD",(count or 1))) +end + +--Force Cursor Position *ESC*[{ROW};{COLUMN}f +--Identical to Cursor Home. +function term.forceCursorPosition(row, col) + write(string.format("[%d;%df", row, col)) +end + +--Save Cursor *ESC*[s +--Save current cursor position. +function term.saveCursor() + write("[s") +end + +--Unsave Cursor *ESC*[u +--Restores cursor position after a Save Cursor. +function term.restoreCursor() + write("[u") +end + +--Save Cursor & Attrs *ESC*7 +--Save current cursor position. +function term.saveCursorAndAttr() + write("7") +end + +--Restore Cursor & Attrs *ESC*8 +--Restores cursor position after a Save Cursor. +function term.restoreCursorAndAttr() + write("8") +end + + +------------------------------------------ +--Terminal Setup +------------------------------------------ + +--Reset Device *ESC*c +--Reset all terminal settings to default. +function term.reset() + write("c") +end + +--Enable Line Wrap *ESC*[7h +--Text wraps to next line if longer than the length of the display area. +function term.enableLineWrap() + write("[7h") +end + +--Disable Line Wrap *ESC*[7l +--Disables line wrapping. +function term.disableLineWrap() + write("[7l") +end + +------------------------------------------ +--Plan9k codes +------------------------------------------ + +-- \x1b9[H];[W]R - set resolution +function term.setResolution(height,width) + write(string.format("9%d;%dR", height, width)) +end + +-- \x1b9[Row];[Col];[Height];[Width]F -- fill +function term.fill(row, col, height, width) + write(string.format("9%d;%d;%d;%dF", row, col, height, width)) +end + +-- \x1b9[Row];[Col];[Height];[Width];[Dest Row];[Dest Col]c -- copy +function term.copy(row, col, height, width, destRow, destCol) + write(string.format("9%d;%d;%d;%d;%d;%dc", row, col, height, width, destRow, destCol )) +end + +--get resolution +function term.getResolution() + local y, x = term.getCursorPosition() + term.setCursorPosition(999,999) + local h, w = term.getCursorPosition() + term.setCursorPosition(y,x) + return tonumber(h), tonumber(w) +end + + + + + + + + + + + + + + + + + + + + + + + + + function term.clear() io.write("\x1b[2J") diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/usr/bin/base64.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/usr/bin/base64.lua new file mode 100644 index 000000000..2a5d9d58f --- /dev/null +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/usr/bin/base64.lua @@ -0,0 +1,42 @@ +local shell = require("shell") +local data = require("data") + + +local args, parms = shell.parse(...) +if parms.h or parms.help then + io.stderr:write("See: man base64" .. "\n") + os.exit(true) +end +local encodingfun = nil +local encode +if parms.d or parms.decode then + encodingfun = data.decode64 + encode = false +else + encodingfun = data.encode64 + encode = true +end + +if #args == 0 then + repeat + local read = io.read(encode and 3 or 4) + if read then + io.write(encodingfun(read)) + end + until not read +else + for i = 1, #args do + local file, reason = io.open(shell.resolve(args[i])) + if not file then + io.stderr:write(tostring(reason) .. "\n") + os.exit(false) + end + repeat + local line = file:read(encode and 3 or 4) + if line then + io.write(encodingfun(line)) + end + until not line + file:close() + end +end diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/usr/bin/deflate.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/usr/bin/deflate.lua new file mode 100644 index 000000000..cd8660ac2 --- /dev/null +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/usr/bin/deflate.lua @@ -0,0 +1,25 @@ +local shell = require("shell") +local data = require("data") + +local args = shell.parse(...) +if #args == 0 then + local read = "" + repeat + local current = io.read("*a") + read = read .. current + until current ~= "" + io.write(data.deflate(read)) +else + local read = "" + local file, reason = io.open(shell.resolve(args[1])) + if not file then + io.stderr:write(tostring(reason) .. "\n") + os.exit(false) + end + repeat + local current = file:read("*a") + read = read .. current + until current ~= "" + file:close() + io.write(data.deflate(read)) +end diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/usr/bin/gpg.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/usr/bin/gpg.lua new file mode 100644 index 000000000..5b2f5ad41 --- /dev/null +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/usr/bin/gpg.lua @@ -0,0 +1,244 @@ +--[[ +-- A program that allows user to perform all crypto operations provided by Tier II / Tier III data cards +-- Author: makkarpov +--]] + +local shell = require("shell") +local data = require("data") +local term = require("term") +local filesystem = require("filesystem") +local serialization = require("serialization") + +local args, options = shell.parse(...) + +local function writeFile(path, data) + if filesystem.exists(path) then + io.stderr:write("gpg: failed to write file: " .. path .. "\n") + io.stderr:write("gpg: error was: file already exists\n") + return false + end + + if type(data) == "table" then + data = serialization.serialize(data) + end + + local h, err = io.open(path, "wb") + + if not h then + io.stderr:write("gpg: failed to write file: " .. path .. "\n") + io.stderr:write("gpg: error was: " .. err .. "\n") + return false + end + + h:write(data) + h:close() + return true +end + +local function readFile(path, deserialize) + local h = io.open(path, "rb") + local r = h:read("*a") + h:close() + + if deserialize then + r = serialization.unserialize(r) + end + + return r +end + +local function parseKey(path, isPublic) + local d = readFile(path, true) + local k, err = data.deserializeKey(d.d, d.t) + + if not k then + io.stderr:write("gpg: failed to parse key: " .. err .. "\n") + return nil + end + + if k.isPublic() ~= isPublic then + io.stderr:write("gpg: wrong key type\n") + return nil + end + + return k +end + +local function deriveName(base, encrypt) + if encrypt then + return base .. ".gpg" + else + local d = base:gsub(".gpg", "") + if d == base then + d = d .. ".dec" + io.write("gpg: decrypting to " .. d .. "\n") + end + return d + end +end + +local function ensureMethods(...) + if not require("component").isAvailable("data") then + io.stderr:write("gpg: you must have data card in order to run this program\n") + error("data card is absent") + end + + local names = table.pack(...) + for i = 1, names.n do + if names[i] and not data[names[i]] then + io.stderr:write("gpg: method " .. names[i] .. " required on data card to run this program\n") + error("data card tier insufficient") + end + end +end + +if options['g'] and (#args == 2) then + ensureMethods("generateKeyPair") + local pub, priv = data.generateKeyPair(384) + + priv = { t = priv.keyType(), d = priv.serialize() } + pub = { t = pub.keyType(), d = pub.serialize() } + + if not writeFile(args[1], priv) then + io.stderr:write("gpg: failed to write private key, aborting\n") + return false + end + + if not writeFile(args[2], pub) then + io.stderr:write("gpg: failed to write public key, aborting\n") + return false + end + + return true +end + +if options['c'] and (options['e'] or options['d']) and (#args == 1) then + ensureMethods("md5", "sha256", "encrypt", "decrypt", "random") + if options['d'] and options['e'] then + io.stderr:write("gpg: please specify either -d or -e\n") + return false + end + + io.write("gpg: enter password: ") + local aesKey = data.md5(term.read(nil, nil, nil, "*")) + local checkValue = data.sha256(aesKey) + + if options['e'] then + local iv = data.random(16) + local d = data.encrypt(readFile(args[1]), aesKey, iv) + + return writeFile(deriveName(args[1], true), { + t = "pwd", + kdf = "md5", + iv = iv, + cv = checkValue, + d = d + }) + else + local d = readFile(args[1], true) + + if d.t ~= "pwd" then + io.stderr:write("gpg: file is not encrypted with a password\n") + return false + end + + if checkValue ~= d.cv then + io.stderr:write("gpg: password incorrect\n") + return false + end + + return writeFile(deriveName(args[1], false), data.decrypt(d.d, aesKey, d.iv)) + end +end + +if (options['d'] or options['e']) and (#args == 2) then + ensureMethods("md5", "sha256", "encrypt", "decrypt", "random", "generateKeyPair", "deserializeKey", "ecdh") + if options['d'] and options['e'] then + io.stderr:write("gpg: please specify either -d or -e\n") + return false + end + + if options['e'] then + local userPub = parseKey(args[1], true) + local tmpPub, tmpPriv = data.generateKeyPair(384) + local aesKey = data.md5(data.ecdh(tmpPriv, userPub)) + local checkValue = data.sha256(aesKey) + local iv = data.random(16) + + local d = data.encrypt(readFile(args[2]), aesKey, iv) + return writeFile(deriveName(args[2], true), { + t = "ecdh", + kdf = "md5", + iv = iv, + cv = checkValue, + k = { + t = tmpPub.keyType(), + d = tmpPub.serialize() + }, + d = d + }) + else + local userPriv = parseKey(args[1], false) + local d = readFile(args[2], true) + + if d.t ~= "ecdh" then + io.stderr:write("gpg: file is not encrypted with a key\n") + return false + end + + local tmpPub = data.deserializeKey(d.k.d, d.k.t) + local aesKey = data.md5(data.ecdh(userPriv, tmpPub)) + + if d.cv ~= data.sha256(aesKey) then + io.stderr:write("gpg: invalid key\n") + return false + end + + return writeFile(deriveName(args[2], false), data.decrypt(d.d, aesKey, d.iv)) + end +end + +if (options['s'] or options['v']) and (#args == 2) then + ensureMethods("deserializeKey", "ecdsa") + if options['s'] and options['v'] then + io.stderr:write("gpg: please specify either -s or -v\n") + return false + end + + if options['s'] then + local userPriv = parseKey(args[1], false) + local sign = data.ecdsa(readFile(args[2]), userPriv) + + return writeFile(args[2] .. ".sig", { + t = "ecdsa", + s = sign + }) + else + local userPub = parseKey(args[1], true) + local sign = readFile(args[2] .. ".sig", true) + + if sign.t ~= "ecdsa" then + io.stderr:write("gpg: unsupported signature type\n") + return false + end + + if not data.ecdsa(readFile(args[2]), userPub, sign.s) then + io.stderr:write("gpg: signature verification failed\n") + return false + end + + io.write("gpg: signature is valid\n") + + return true + end +end + +io.write("Usages:\n") +io.write("gpg -ce -- encrypt file with password\n") +io.write("gpg -cd -- decrypt file with password\n") +io.write("gpg -e -- encrypt file\n") +io.write("gpg -d -- decrypt file\n") +io.write("gpg -g -- generate keypair\n") +io.write("gpg -s -- sign file\n") +io.write("gpg -v -- verify file\n") +return false diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/usr/bin/inflate.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/usr/bin/inflate.lua new file mode 100644 index 000000000..349c5f18b --- /dev/null +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/usr/bin/inflate.lua @@ -0,0 +1,25 @@ +local shell = require("shell") +local data = require("data") + +local args = shell.parse(...) +if #args == 0 then + local read = "" + repeat + local current = io.read("*a") + read = read .. current + until current ~= "" + io.write(data.inflate(read)) +else + local read = "" + local file, reason = io.open(shell.resolve(args[1])) + if not file then + io.stderr:write(tostring(reason) .. "\n") + os.exit(false) + end + repeat + local current = file:read("*a") + read = read .. current + until current ~= "" + file:close() + io.write(data.inflate(read)) +end diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/usr/bin/md5sum.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/usr/bin/md5sum.lua new file mode 100644 index 000000000..37cba695f --- /dev/null +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/usr/bin/md5sum.lua @@ -0,0 +1,27 @@ +local shell = require("shell") +local data = require("data") + +local args = shell.parse(...) +if #args == 0 then + local read = "" + repeat + local current = io.read("*a") + read = read .. current + until current ~= "" + io.write(data.toHex(data.md5(read))) +else + for i = 1, #args do + local read = "" + local file, reason = io.open(args[i]) + if not file then + io.stderr:write(tostring(reason) .. "\n") + os.exit(false) + end + repeat + local current = file:read("*a") + read = read .. current + until current ~= "" + file:close() + io.write(data.toHex(data.md5(read)) .. "\t".. args[i] .. "\n") + end +end diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/usr/bin/mpt.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/usr/bin/mpt.lua index 5f9ef04de..49cdb030e 100644 --- a/src/main/resources/assets/opencomputers/loot/Plan9k/usr/bin/mpt.lua +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/usr/bin/mpt.lua @@ -81,17 +81,25 @@ ocBackend = { print(" Upgrade all packages that are out-of-date on the") print(" local system. Only package versions are used to find outdated packages;") print(" replacements are not checked here. This is a ?remove-then-add? process.") + print(" -f, --force") + print(" Force operation, in case of upgrade it redownloads all packages") print(" --root='/some/dir'") print(" Set alternative root directory") print(" -v") print(" More output") print(" -y") print(" Don't ask any questions, answer automatically") + print(" -r, --reboot") + print(" reboot after operation") return end if options.v then loglevel = 0 end + if options.f or options.force then + core.data.force = true + end + if options.S or options.sync then for _, pack in ipairs(args) do core.install(pack) @@ -114,6 +122,8 @@ ocBackend = { if options.y then ocBackend.prompt = function()return true end end + + core.reboot = optionsr or options.reboot core.doWork() end, @@ -208,7 +218,8 @@ ocBackend = { if p:sub(1,1):upper() ~= "Y" then error("User stopped") end - end + end, + reboot = function()computer.shutdown(true) end } local mptFrontend @@ -249,7 +260,7 @@ mptFrontend = { local toCheck = {} for pack, data in pairs(base.installed) do if data.frontend == mptFrontend.name then - toCheck[pack] = base.installed[pack].data.checksum + toCheck[pack] = base.installed[pack].data.checksum .. (core.data.force and "WAT" or "") end end local updateResp = backend.getText(config.frontend.mpt.api.."update", toCheck) @@ -368,6 +379,8 @@ core = { upgrade = false, remove = false, + force = false, + --User requested packages userInstall = {}, @@ -603,7 +616,8 @@ end core.log(1, "Main", "> Saving settings") core.finalize() - - +if core.reboot then + backend.reboot() +end diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/usr/bin/sha256sum.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/usr/bin/sha256sum.lua new file mode 100644 index 000000000..33d5b25c7 --- /dev/null +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/usr/bin/sha256sum.lua @@ -0,0 +1,27 @@ +local shell = require("shell") +local data = require("data") + +local args = shell.parse(...) +if #args == 0 then + local read = "" + repeat + local current = io.read("*a") + read = read .. current + until current ~= "" + io.write(data.toHex(data.sha256(read))) +else + for i = 1, #args do + local read = "" + local file, reason = io.open(shell.resolve(args[i])) + if not file then + io.stderr:write(tostring(reason) .. "\n") + os.exit(false) + end + repeat + local current = file:read("*a") + read = read .. current + until current ~= "" + file:close() + io.write(data.toHex(data.sha256(read)) .. "\t".. args[i] .. "\n") + end +end diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/usr/lib/data.lua b/src/main/resources/assets/opencomputers/loot/Plan9k/usr/lib/data.lua new file mode 100644 index 000000000..04fa9ff9c --- /dev/null +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/usr/lib/data.lua @@ -0,0 +1,26 @@ +local component = require("component") + +local data = {} + +------------------------------------------------------------------------------- + +-- Converts binary data into hexadecimal string. +function data.toHex(data) + return (data:gsub('.', function (c) + return string.format('%02X', string.byte(c)) + end)) +end + +-- Converts hexadecimal string into binary data. +function data.fromHex(hex) + return (hex:gsub('..', function (cc) + return string.char(tonumber(cc, 16)) + end)) +end + +-- Forward everything else to the primary data card. +setmetatable(data, { __index = function(_, key) return component.data[key] end }) + +------------------------------------------------------------------------------- + +return data diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/var/lib/mpt/config.db b/src/main/resources/assets/opencomputers/loot/Plan9k/var/lib/mpt/config.db index 92ac3946c..3ecc57b30 100644 --- a/src/main/resources/assets/opencomputers/loot/Plan9k/var/lib/mpt/config.db +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/var/lib/mpt/config.db @@ -1 +1 @@ -{cacheDir="/var/lib/mpt/cache/",database="/var/lib/mpt/base.db",frontend={mpt={api="http://mpt.magik6k.net/api/"}}} \ No newline at end of file +{database="/var/lib/mpt/base.db",cacheDir="/var/lib/mpt/cache/",frontend={mpt={api="http://mpt.magik6k.net/api/"}}} \ No newline at end of file diff --git a/src/main/resources/assets/opencomputers/loot/Plan9k/var/lib/mpt/mpt.db b/src/main/resources/assets/opencomputers/loot/Plan9k/var/lib/mpt/mpt.db index 4c7665a18..d64373528 100644 --- a/src/main/resources/assets/opencomputers/loot/Plan9k/var/lib/mpt/mpt.db +++ b/src/main/resources/assets/opencomputers/loot/Plan9k/var/lib/mpt/mpt.db @@ -1 +1 @@ -{installed={["plan9k-drivers"]={frontend="MPT",data={name="plan9k-drivers",repo="plan9k",checksum="-2327b14292d5c08f547d24e9b5122349",files={"/lib/modules/base/17_tape.lua","/lib/modules/base/17_eeprom.lua","/lib/modules/base/17_nfc.lua","/lib/modules/base/17_chatbox.lua"},dependencies={}},deps={}},["plan9k-shell"]={frontend="MPT",data={name="plan9k-shell",repo="plan9k",checksum="-4ebb18f6dedde575d4d61460494b3bbb",files={"/bin/sh.lua"},dependencies={}},deps={}},["plan9k-corelibs"]={frontend="MPT",data={name="plan9k-corelibs",repo="plan9k",checksum="1d01d437b10e8561a39cb9f108cc3d47",files={"/lib/serialization.lua","/lib/term.lua","/lib/text.lua","/lib/shell.lua","/lib/event.lua"},dependencies={}},deps={}},mpt={frontend="MPT",data={name="mpt",repo="mpt",checksum="f9d7744571e5c46c658f405043c656",files={"/usr/bin/mpt.lua"},dependencies={}},deps={}},["plan9k-fsutil"]={frontend="MPT",data={name="plan9k-fsutil",repo="plan9k",checksum="aded7c8083efcdcfe43908183370687",files={"/bin/cat.lua","/bin/ln.lua","/bin/ls.lua","/bin/mv.lua","/bin/rm.lua","/bin/tee.lua","/bin/df.lua","/bin/dd.lua","/bin/cp.lua","/bin/touch.lua","/bin/mount.lua","/bin/mount.cow.lua","/bin/mkdir.lua","/bin/pwd.lua"},dependencies={"plan9k-corelibs"}},deps={"plan9k-corelibs"}},["plan9k-network"]={frontend="MPT",data={name="plan9k-network",repo="plan9k",checksum="-29d10c88b7ed4116d5b4eacd019d5ad9",files={"/lib/internet.lua","/bin/pastebin.lua","/bin/wget.lua","/lib/modules/base/17_network.lua","/lib/modules/base/19_libnetwork.lua","/bin/arp.lua","/bin/ifconfig.lua","/bin/ping.lua","/bin/route.lua","/lib/modules/network/loopback.lua","/lib/modules/network/modem.lua","/usr/bin/nc.lua","/lib/modules/network/tunnel.lua"},dependencies={}},deps={}},pipes={frontend="MPT",data={name="pipes",repo="plan9k",checksum="6d088970fd4fb29b78279eef4d417646",files={"/boot/kernel/pipes","/lib/modules/base/05_vfs.lua","/lib/modules/base/20_threading.lua","/lib/modules/base/19_manageg.lua","/lib/modules/base/25_init.lua","/lib/modules/base/15_userspace.lua","/usr/man/pipes","/lib/modules/base/16_buffer.lua","/lib/modules/base/17_io.lua","/lib/modules/base/16_require.lua","/lib/modules/base/18_syscall.lua","/lib/modules/base/21_threadUtil.lua","/lib/modules/base/21_timer.lua","/lib/modules/base/16_component.lua","/lib/modules/base/15_keventd.lua","/lib/modules/base/10_procfs.lua","/lib/modules/base/01_util.lua","/lib/modules/base/10_devfs.lua","/lib/modules/base/18_pty.lua","/lib/modules/base/17_keyboard.lua","/lib/modules/base/06_cowfs.lua","/lib/modules/base/09_rootfs.lua","/lib/modules/base/01_gc.lua"},dependencies={"openloader-init"}},deps={"openloader-init"}},["plan9k-edit"]={frontend="MPT",data={name="plan9k-edit",repo="plan9k",checksum="fed5f4ee1212297b07247afa1cfe3a2",files={"/bin/edit.lua"},dependencies={}},deps={}},["plan9k-core"]={frontend="MPT",data={name="plan9k-core",repo="plan9k",checksum="-4f5e4f44875482035444a2b61e96243d",files={"/bin/init.lua","/bin/getty.lua","/bin/readkey.lua","/lib/rc.lua","/bin/rc.lua"},dependencies={"pipes","plan9k-coreutil","plan9k-shell"}},deps={"pipes","plan9k-coreutil","plan9k-shell"}},plan9k={frontend="MPT",data={name="plan9k",repo="plan9k",checksum="-c16ccdf21a1ff13be8f6258d1a17d89",files={},dependencies={"plan9k-core","plan9k-network","plan9k-drivers","plan9k-edit"}},deps={"plan9k-core","plan9k-network","plan9k-drivers","plan9k-edit"}},["plan9k-installer"]={frontend="MPT",data={name="plan9k-installer",repo="plan9k",checksum="52c8f82357c966ce3e19c97bf3942012",files={"/bin/install.lua"},dependencies={"plan9k","mpt"}},deps={"plan9k","mpt"}},["openloader-init"]={frontend="MPT",data={name="openloader-init",repo="disks",checksum="-45e6d7b1e41468c1d335952ee3b89e13",files={"/init.lua"},dependencies={}},deps={}},["plan9k-coreutil"]={frontend="MPT",data={name="plan9k-coreutil",repo="plan9k",checksum="-50d3cee571b07b6cb05f6fb01989997c",files={"/bin/echo.lua","/bin/wc.lua","/bin/ps.lua","/bin/lua.lua","/bin/kill.lua","/bin/reboot.lua","/bin/sleep.lua","/bin/clear.lua","/bin/components.lua","/bin/hostname.lua","/bin/dmesg.lua","/bin/shutdown.lua","/bin/label.lua","/bin/uptime.lua","/bin/resolution.lua"},dependencies={"plan9k-corelibs","plan9k-fsutil"}},deps={"plan9k-corelibs","plan9k-fsutil"}}}} \ No newline at end of file +{installed={["plan9k-shell"]={deps={},frontend="MPT",data={checksum="517b9e0693e734a4ab516f12a6798f14",files={"/bin/sh.lua"},name="plan9k-shell",repo="plan9k",dependencies={}}},plan9k={deps={"plan9k-core","plan9k-network","plan9k-drivers","plan9k-edit","plan9k-data"},frontend="MPT",data={checksum="-2d8f4b84ea60b0c9d5846f57e9f1691c",files={},name="plan9k",repo="plan9k",dependencies={"plan9k-core","plan9k-network","plan9k-drivers","plan9k-edit","plan9k-data"}}},["plan9k-fsutil"]={deps={"plan9k-corelibs"},frontend="MPT",data={checksum="6a974a71f62315e6e2294eae132d1751",files={"/bin/cat.lua","/bin/ln.lua","/bin/ls.lua","/bin/mv.lua","/bin/rm.lua","/bin/tee.lua","/bin/df.lua","/bin/dd.lua","/bin/cp.lua","/bin/touch.lua","/bin/mount.lua","/bin/mount.cow.lua","/bin/mkdir.lua","/bin/pwd.lua","/bin/more.lua"},name="plan9k-fsutil",repo="plan9k",dependencies={"plan9k-corelibs"}}},["plan9k-edit"]={deps={},frontend="MPT",data={checksum="34b1046ac9b7a87a1cdd74f8c03f27ea",files={"/bin/edit.lua"},name="plan9k-edit",repo="plan9k",dependencies={}}},["plan9k-core"]={deps={"pipes","plan9k-coreutil","plan9k-shell"},frontend="MPT",data={checksum="-6f77a020200f96eefd1559dcd8af14a5",files={"/bin/init.lua","/bin/getty.lua","/bin/readkey.lua","/lib/rc.lua","/bin/rc.lua"},name="plan9k-core",repo="plan9k",dependencies={"pipes","plan9k-coreutil","plan9k-shell"}}},["plan9k-installer"]={deps={"plan9k","mpt"},frontend="MPT",data={checksum="52c8f82357c966ce3e19c97bf3942012",files={"/bin/install.lua"},name="plan9k-installer",repo="plan9k",dependencies={"plan9k","mpt"}}},["plan9k-drivers"]={deps={},frontend="MPT",data={checksum="-35f098652460458c13f83499b4633e2d",files={"/lib/modules/base/17_tape.lua","/lib/modules/base/17_eeprom.lua","/lib/modules/base/17_nfc.lua","/lib/modules/base/17_chatbox.lua","/lib/modules/base/17_data.lua","/lib/modules/base/17_drive.lua"},name="plan9k-drivers",repo="plan9k",dependencies={}}},["plan9k-coreutil"]={deps={"plan9k-corelibs","plan9k-fsutil"},frontend="MPT",data={checksum="5fa7e70e3aba17fef97ed65489efb0ca",files={"/bin/echo.lua","/bin/wc.lua","/bin/ps.lua","/bin/lua.lua","/bin/kill.lua","/bin/reboot.lua","/bin/sleep.lua","/bin/clear.lua","/bin/components.lua","/bin/hostname.lua","/bin/dmesg.lua","/bin/shutdown.lua","/bin/label.lua","/bin/uptime.lua","/bin/resolution.lua"},name="plan9k-coreutil",repo="plan9k",dependencies={"plan9k-corelibs","plan9k-fsutil"}}},["openloader-init"]={deps={},frontend="MPT",data={checksum="-45e6d7b1e41468c1d335952ee3b89e13",files={"/init.lua"},name="openloader-init",repo="disks",dependencies={}}},mpt={deps={},frontend="MPT",data={checksum="-3435ded79cf9de20e7185f403eee4a28",files={"/usr/bin/mpt.lua"},name="mpt",repo="mpt",dependencies={}}},pipes={deps={"openloader-init"},frontend="MPT",data={checksum="123b56992859cf05cd03af825437d734",files={"/boot/kernel/pipes","/lib/modules/base/05_vfs.lua","/lib/modules/base/20_threading.lua","/lib/modules/base/19_manageg.lua","/lib/modules/base/25_init.lua","/lib/modules/base/15_userspace.lua","/usr/man/pipes","/lib/modules/base/16_buffer.lua","/lib/modules/base/17_io.lua","/lib/modules/base/16_require.lua","/lib/modules/base/18_syscall.lua","/lib/modules/base/21_threadUtil.lua","/lib/modules/base/21_timer.lua","/lib/modules/base/16_component.lua","/lib/modules/base/15_keventd.lua","/lib/modules/base/10_procfs.lua","/lib/modules/base/01_util.lua","/lib/modules/base/10_devfs.lua","/lib/modules/base/18_pty.lua","/lib/modules/base/17_keyboard.lua","/lib/modules/base/06_cowfs.lua","/lib/modules/base/09_rootfs.lua","/lib/modules/base/01_gc.lua"},name="pipes",repo="plan9k",dependencies={"openloader-init"}}},["plan9k-corelibs"]={deps={},frontend="MPT",data={checksum="1cb7fa12e1a1a35fc168409b60cfe552",files={"/lib/serialization.lua","/lib/term.lua","/lib/text.lua","/lib/shell.lua","/lib/event.lua"},name="plan9k-corelibs",repo="plan9k",dependencies={}}},["plan9k-data"]={deps={},frontend="MPT",data={checksum="480a898a741b2bf424f9e0e86e5072ba",files={"/usr/bin/base64.lua","/usr/lib/data.lua","/usr/bin/deflate.lua","/usr/bin/inflate.lua","/usr/bin/md5sum.lua","/usr/bin/sha256sum.lua","/usr/bin/gpg.lua"},name="plan9k-data",repo="plan9k",dependencies={}}},["plan9k-network"]={deps={},frontend="MPT",data={checksum="6e06e6cf5028583fe54047ba9e19abc6",files={"/lib/internet.lua","/bin/pastebin.lua","/bin/wget.lua","/lib/modules/base/17_network.lua","/lib/modules/base/19_libnetwork.lua","/bin/arp.lua","/bin/ifconfig.lua","/bin/ping.lua","/bin/route.lua","/lib/modules/network/loopback.lua","/lib/modules/network/modem.lua","/usr/bin/nc.lua","/lib/modules/network/tunnel.lua"},name="plan9k-network",repo="plan9k",dependencies={}}}}} \ No newline at end of file