diff --git a/src/main/resources/assets/opencomputers/loot/openos/bin/lua.lua b/src/main/resources/assets/opencomputers/loot/openos/bin/lua.lua index c6eba31d4..d95547020 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/bin/lua.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/bin/lua.lua @@ -5,13 +5,23 @@ if #args == 0 then args = {"/opt/core/lua_shell.lua"} end -local script, reason = loadfile(args[1], nil, setmetatable({},{__index=_ENV})) +local filename = args[1] +local buffer, script, reason +buffer = io.lines(filename, "*a")() +if buffer then + buffer = buffer:gsub("^#![^\n]+", "") -- remove shebang if any + script, reason = load(buffer, "="..filename) +else + reason = string.format("could not open %s for reading", filename) +end + if not script then io.stderr:write(tostring(reason) .. "\n") os.exit(false) end -local result, reason = pcall(script, table.unpack(args, 2)) -if not result then + +buffer, reason = pcall(script, table.unpack(args, 2)) +if not buffer then io.stderr:write(reason, "\n") os.exit(false) end diff --git a/src/main/resources/assets/opencomputers/loot/openos/boot/00_base.lua b/src/main/resources/assets/opencomputers/loot/openos/boot/00_base.lua index ccf951e45..50fe336b7 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/boot/00_base.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/boot/00_base.lua @@ -1,4 +1,4 @@ -function loadfile(filename, mode, env) +function loadfile(filename, ...) if filename:sub(1,1) ~= "/" then filename = (os.getenv("PWD") or "/") .. "/" .. filename end @@ -16,11 +16,9 @@ function loadfile(filename, mode, env) end break end - table.insert(buffer, data) + buffer[#buffer + 1] = data end - buffer[1] = (buffer[1] or ""):gsub("^#![^\n]+", "") -- remove shebang if any - buffer = table.concat(buffer) - return load(buffer, "=" .. filename, mode, env) + return load(table.concat(buffer), "=" .. filename, ...) end function dofile(filename) @@ -35,12 +33,10 @@ function print(...) local args = table.pack(...) local stdout = io.stdout stdout:setvbuf("line") + local pre = "" for i = 1, args.n do - local arg = tostring(args[i]) - if i > 1 then - arg = "\t" .. arg - end - stdout:write(arg) + stdout:write(pre, tostring(args[i])) + pre = "\t" end stdout:write("\n") stdout:setvbuf("no") diff --git a/src/main/resources/assets/opencomputers/loot/openos/boot/01_process.lua b/src/main/resources/assets/opencomputers/loot/openos/boot/01_process.lua index 4656a4bca..b514508bd 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/boot/01_process.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/boot/01_process.lua @@ -27,10 +27,18 @@ local kernel_load = _G.load local intercept_load intercept_load = function(source, label, mode, env) if env then - env.load = kernel_load([[ - local source, label, mode, env = ... - return load(source, label, mode, env or fenv) - ]], "=load", "t", {fenv=env, load=intercept_load}) + local loader = setmetatable( + { + env = env, + load = intercept_load, + }, + {__call = function(tbl, _source, _label, _mode, _env) + return tbl.load(_source, _label, _mode, _env or tbl.env) + end}) + if env.load and (type(env.load) ~= "table" or env.load.load ~= intercept_load) then + loader.load = env.load + end + env.load = loader end return kernel_load(source, label, mode, env or process.info().env) end diff --git a/src/main/resources/assets/opencomputers/loot/openos/boot/02_os.lua b/src/main/resources/assets/opencomputers/loot/openos/boot/02_os.lua index f9c6acf00..015a225ca 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/boot/02_os.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/boot/02_os.lua @@ -2,11 +2,7 @@ local computer = require("computer") local event = require("event") local fs = require("filesystem") local shell = require("shell") -local process = require("process") - -local function env() - return process.info().data.vars -end +local info = require("process").info os.execute = function(command) if not command then @@ -20,7 +16,7 @@ function os.exit(code) end function os.getenv(varname) - local env = env() + local env = info().data.vars if not varname then return env elseif varname == '#' then @@ -34,7 +30,7 @@ function os.setenv(varname, value) if value ~= nil then value = tostring(value) end - env()[varname] = value + info().data.vars[varname] = value return value end diff --git a/src/main/resources/assets/opencomputers/loot/openos/boot/03_io.lua b/src/main/resources/assets/opencomputers/loot/openos/boot/03_io.lua index bf637e580..e6c46dd45 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/boot/03_io.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/boot/03_io.lua @@ -1,11 +1,6 @@ local buffer = require("buffer") local tty = require("tty") -local io_open = io.open -function io.open(path, mode) - return io_open(require("shell").resolve(path), mode) -end - local stdinStream = {handle="stdin"} local stdoutStream = {handle="stdout"} local stderrStream = {handle="stderr"} @@ -15,13 +10,13 @@ local function badFileDescriptor() return nil, "bad file descriptor" end -function stdinStream:close() +function stdinStream.close() return nil, "cannot close standard file" end stdoutStream.close = stdinStream.close stderrStream.close = stdinStream.close -function stdinStream:read() +function stdinStream.read() return tty.read(stdinHistory) end diff --git a/src/main/resources/assets/opencomputers/loot/openos/etc/motd b/src/main/resources/assets/opencomputers/loot/openos/etc/motd index 4a839de7e..85ec4759f 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/etc/motd +++ b/src/main/resources/assets/opencomputers/loot/openos/etc/motd @@ -1,5 +1,3 @@ -#!/bin/lua - local component = require("component") local computer = require("computer") local text = require("text") diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/io.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/io.lua index 525f40af9..306ce1874 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/io.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/io.lua @@ -36,7 +36,8 @@ end function io.open(path, mode) -- These requires are not on top because this is a bootstrapped file. - local stream, result = require("filesystem").open(path, mode) + local resolved_path = require("shell").resolve(path) + local stream, result = require("filesystem").open(resolved_path, mode) if stream then return require("buffer").new(mode, stream) else diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/keyboard.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/keyboard.lua index b7112f1dd..f77d5c3d8 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/keyboard.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/keyboard.lua @@ -1,5 +1,3 @@ -local component = require("component") - local keyboard = {pressedChars = {}, pressedCodes = {}} -- these key definitions are only a subset of all the defined keys @@ -32,16 +30,6 @@ keyboard.keys = { numpadenter = 0x9C, } --- Create inverse mapping for name lookup. -setmetatable(keyboard.keys, -{ - __index = function(tbl, k) - getmetatable(keyboard.keys).__index = nil -- to be safe - loadfile(package.searchpath("tools/keyboard_full", package.path), "t", setmetatable({keyboard=keyboard},{__index=_G}))() - return tbl[k] - end -}) - ------------------------------------------------------------------------------- local function getKeyboardAddress(address) @@ -94,4 +82,13 @@ end ------------------------------------------------------------------------------- +setmetatable(keyboard.keys, +{ + __index = function(tbl, key) + setmetatable(tbl, nil) + dofile("/opt/core/full_keyboard.lua") + return tbl[key] -- some keyboard keys are handled by __index by design + end +}) + return keyboard diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/package.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/package.lua index 10670c257..732213568 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/package.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/package.lua @@ -16,11 +16,6 @@ local loaded = { } package.loaded = loaded -local preload = {} -package.preload = preload - -package.searchers = {} - function package.searchpath(name, path, sep, rep) checkArg(1, name, "string") checkArg(2, path, "string") @@ -47,67 +42,28 @@ function package.searchpath(name, path, sep, rep) return nil, table.concat(errorFiles, "\n") end -local function preloadSearcher(module) - if preload[module] ~= nil then - return preload[module] - else - return "\tno field package.preload['" .. module .. "']" - end -end - -local function pathSearcher(module) - local filepath, reason = package.searchpath(module, package.path) - if filepath then - local loader, reason = loadfile(filepath, "bt", _G) - if loader then - return loader, filepath - else - return reason - end - else - return reason - end -end - -table.insert(package.searchers, preloadSearcher) -table.insert(package.searchers, pathSearcher) - function require(module) checkArg(1, module, "string") if loaded[module] ~= nil then return loaded[module] elseif not loading[module] then - loading[module] = true - local loader, value, errorMsg = nil, nil, {"module '" .. module .. "' not found:"} - for i = 1, #package.searchers do - -- the pcall is mostly for out of memory errors - local ok, f, extra = pcall(package.searchers[i], module) - if not ok then - table.insert(errorMsg, "\t" .. (f or "nil")) - elseif f and type(f) ~= "string" then - loader = f - value = extra - break - elseif f then - table.insert(errorMsg, f) - end + local library, status, step + + step, library, status = "not found", package.searchpath(module, package.path) + + if library then + step, library, status = "loadfile failed", loadfile(library) end - if loader then - local success, result = pcall(loader, module, value) + + if library then + loading[module] = true + step, library, status = "load failed", pcall(library, module) loading[module] = false - if not success then - error(result, 2) - end - if result then - loaded[module] = result - elseif not loaded[module] then - loaded[module] = true - end - return loaded[module] - else - loading[module] = false - error(table.concat(errorMsg, "\n"), 2) end + + assert(library, string.format("module '%s' %s:\n%s", module, step, status)) + loaded[module] = status + return status else error("already loading: " .. module .. "\n" .. debug.traceback(), 2) end diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/pipes.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/pipes.lua index 0fe5c919f..cffda718e 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/pipes.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/pipes.lua @@ -371,11 +371,14 @@ function plib.popen(prog, mode, env) return pfd end -function plib.create(fp, name) - checkArg(1, fp, "function") - checkArg(2, name, "string", "nil") - local pco = plib.internal.create(fp, nil, name) - return pco.stack[1] -end +-- function plib.create(fp, name) +-- checkArg(1, fp, "function") +-- checkArg(2, name, "string", "nil") + +-- local pco = plib.internal.create(fp, function()end, name) +-- -- process.info(pco.stack[1]).data.event = nil + +-- return pco.stack[1] +-- end return plib diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/process.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/process.lua index 5a51ada9d..1f19a0b4a 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/process.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/process.lua @@ -32,10 +32,10 @@ function process.load(path, env, init, name) local p = process.findProcess() env = env or p.env local code - if type(path) == 'string' then + if type(path) == "string" then code = function(...) local fs, shell = require("filesystem"), require("shell") - local program, reason = shell.resolve(path, 'lua') + local program, reason = shell.resolve(path, "lua") if not program then if fs.isDirectory(shell.resolve(path)) then io.stderr:write(path .. ": is a directory\n") @@ -48,7 +48,7 @@ function process.load(path, env, init, name) os.setenv("_", program) local f = fs.open(program) if f then - local shebang = f:read(1024):match("^#!([^\n]+)") + local shebang = (f:read(1024) or ""):match("^#!([^\n]+)") f:close() if shebang then local result = table.pack(shell.execute(shebang:gsub("%s",""), env, program, ...)) @@ -59,7 +59,7 @@ function process.load(path, env, init, name) local command command, reason = loadfile(program, "bt", env) if not command then - io.stderr:write(program..(reason or ""):gsub("^[^:]*", "").."\n") + io.stderr:write(program, " ", reason or "", "\n") return 128 end return command(...) @@ -80,14 +80,14 @@ function process.load(path, env, init, name) end, function(msg) -- msg can be a custom error object - if type(msg) == 'table' then + if type(msg) == "table" then if msg.reason ~= "terminated" then io.stderr:write(msg.reason.."\n") end return msg.code or 0 end - local stack = debug.traceback():gsub('^([^\n]*\n)[^\n]*\n[^\n]*\n','%1') - io.stderr:write(string.format('%s:\n%s', msg or '', stack)) + local stack = debug.traceback():gsub("^([^\n]*\n)[^\n]*\n[^\n]*\n","%1") + io.stderr:write(string.format("%s:\n%s", msg or "", stack)) return 128 -- syserr end, ...) } @@ -107,13 +107,11 @@ function process.load(path, env, init, name) { handles = {}, io = {}, - coroutine_handler = {} }, parent = p, instances = setmetatable({}, {__mode="v"}), } setmetatable(new_proc.data.io, {__index=p.data.io}) - setmetatable(new_proc.data.coroutine_handler, {__index=p.data.coroutine_handler}) setmetatable(new_proc.data, {__index=p.data}) process.list[thread] = new_proc diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/sh.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/sh.lua index f18b68d45..9f6e6257e 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/sh.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/sh.lua @@ -246,12 +246,12 @@ function sh.internal.createThreads(commands, env, start_args) local thread_env = type(program) == "string" and env or nil local thread, reason = process.load(program, thread_env, function(...) local cdata = process.info().data.command - local args, has_tokens, start_args = cdata.args, cdata.has_tokens, cdata.start_args + local args, has_tokens, c_start_args = cdata.args, cdata.has_tokens, cdata.start_args if has_tokens then args = sh.internal.buildCommandRedirects(args) end - sh.internal.concatn(args, start_args) + sh.internal.concatn(args, c_start_args) sh.internal.concatn(args, {...}, select('#', ...)) -- popen expects each process to first write an empty string diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/shell.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/shell.lua index e38d651cc..feac9acff 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/shell.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/shell.lua @@ -18,60 +18,13 @@ function shell.getShell() if shells[shellName] then return shells[shellName] end - local sh, reason = loadfile(shellName, "t") + local sh, reason = loadfile(shellName) if sh then shells[shellName] = sh end return sh, reason end -local function findFile(name, ext) - checkArg(1, name, "string") - local function findIn(dir) - if dir:sub(1, 1) ~= "/" then - dir = shell.resolve(dir) - end - dir = fs.concat(fs.concat(dir, name), "..") - local name = fs.name(name) - local list = fs.list(dir) - if list and name then - local files = {} - for file in list do - files[file] = true - end - if ext and name:sub(-(1 + ext:len())) == "." .. ext then - -- Name already contains extension, prioritize. - if files[name] then - return true, fs.concat(dir, name) - end - elseif files[name] then - -- Check exact name. - return true, fs.concat(dir, name) - elseif ext then - -- Check name with automatially added extension. - local name = name .. "." .. ext - if files[name] then - return true, fs.concat(dir, name) - end - end - end - return false - end - if name:sub(1, 1) == "/" then - local found, where = findIn("/") - if found then return where end - elseif name:sub(1, 2) == "./" then - local found, where = findIn(shell.getWorkingDirectory()) - if found then return where end - else - for path in string.gmatch(shell.getPath(), "[^:]+") do - local found, where = findIn(path) - if found then return where end - end - end - return false -end - ------------------------------------------------------------------------------- function shell.prime() @@ -133,21 +86,37 @@ function shell.setPath(value) end function shell.resolve(path, ext) - if ext then + checkArg(1, path, "string") + + local dir = path + if dir:find("/") ~= 1 then + dir = fs.concat(shell.getWorkingDirectory(), dir) + end + local name = fs.name(path) + dir = fs[name and "path" or "canonical"](dir) + local fullname = fs.concat(dir, name or "") + + if not ext then + return fullname + elseif name then checkArg(2, ext, "string") - local where = findFile(path, ext) - if where then - return where - else - return nil, "file not found" - end - else - if path:sub(1, 1) == "/" then - return fs.canonical(path) - else - return fs.concat(shell.getWorkingDirectory(), path) + -- search for name in PATH if no dir was given + -- no dir was given if path has no / + local search_in = path:find("/") and dir or shell.getPath() + for search_path in string.gmatch(search_in, "[^:]+") do + -- resolve search_path because they may be relative + local search_name = fs.concat(shell.resolve(search_path), name) + if not fs.exists(search_name) then + search_name = search_name .. "." .. ext + end + -- extensions are provided when the caller is looking for a file + if fs.exists(search_name) and not fs.isDirectory(search_name) then + return search_name + end end end + + return nil, "file not found" end function shell.execute(command, env, ...) @@ -179,11 +148,11 @@ function shell.parse(...) if param == "--" then doneWithOptions = true -- stop processing options at `--` elseif param:sub(1, 2) == "--" then - if param:match("%-%-(.-)=") ~= nil then - options[param:match("%-%-(.-)=")] = param:match("=(.*)") - else - options[param:sub(3)] = true + local key, value = param:match("%-%-(.-)=(.*)") + if not key then + key, value = param:sub(3), true end + options[key] = value elseif param:sub(1, 1) == "-" and param ~= "-" then for j = 2, unicode.len(param) do options[unicode.sub(param, j, j)] = true diff --git a/src/main/resources/assets/opencomputers/loot/openos/opt/core/boot.lua b/src/main/resources/assets/opencomputers/loot/openos/opt/core/boot.lua index 7165207e1..7403ad248 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/opt/core/boot.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/opt/core/boot.lua @@ -1,7 +1,7 @@ -- called from /init.lua local raw_loadfile = ... -_G._OSVERSION = "OpenOS 1.6.2" +_G._OSVERSION = "OpenOS 1.6.3" local component = component local computer = computer @@ -96,11 +96,11 @@ do package.loaded.component = component package.loaded.computer = computer package.loaded.unicode = unicode - package.preload["buffer"] = loadfile("/lib/buffer.lua") - package.preload["filesystem"] = loadfile("/lib/filesystem.lua") + package.loaded.buffer = assert(loadfile("/lib/buffer.lua"))() + package.loaded.filesystem = assert(loadfile("/lib/filesystem.lua"))() -- Inject the io modules - _G.io = loadfile("/lib/io.lua")() + _G.io = assert(loadfile("/lib/io.lua"))() end status("Initializing file system...") diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/tools/keyboard_full.lua b/src/main/resources/assets/opencomputers/loot/openos/opt/core/full_keyboard.lua similarity index 98% rename from src/main/resources/assets/opencomputers/loot/openos/lib/tools/keyboard_full.lua rename to src/main/resources/assets/opencomputers/loot/openos/opt/core/full_keyboard.lua index 2270420b3..f458c3a4d 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/tools/keyboard_full.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/opt/core/full_keyboard.lua @@ -1,3 +1,5 @@ +local keyboard = require("keyboard") + keyboard.keys["1"] = 0x02 keyboard.keys["2"] = 0x03 keyboard.keys["3"] = 0x04 @@ -132,7 +134,7 @@ setmetatable(keyboard.keys, { __index = function(tbl, k) if type(k) ~= "number" then return end - for name,value in pairs(keyboard.keys) do + for name,value in pairs(tbl.keys) do if value == k then return name end