diff --git a/conatiners.lua b/conatiners.lua index 78dcd88..f7e781a 100644 --- a/conatiners.lua +++ b/conatiners.lua @@ -872,12 +872,79 @@ function lib.getENV(fspath, has_http) global._G = global global.shell = nil global.multishell = nil + load_apis("rom/apis") if http and has_http then global.http = http load_apis("rom/apis/http") end return global end + +local exception = dofile("rom/modules/main/cc/internal/tiny_require.lua")("cc.internal.exception") + +local function create(...) + local barrier_ctx = { co = coroutine.running() } + + local functions = table.pack(...) + local threads = {} + for i = 1, functions.n, 1 do + local fn = functions[i] + if type(fn) ~= "function" then + error("bad argument #" .. i .. " (function expected, got " .. type(fn) .. ")", 3) + end + + threads[i] = { co = coroutine.create(function() return exception.try_barrier(barrier_ctx, fn) end), filter = nil } + end + + return threads +end + +local function runUntilLimit(threads, limit) + local count = #threads + if count < 1 then return 0 end + local living = count + + local event = { n = 0 } + while true do + for i = 1, count do + local thread = threads[i] + if thread and (thread.filter == nil or thread.filter == event[1] or event[1] == "terminate") then + local ok, param = coroutine.resume(thread.co, table.unpack(event, 1, event.n)) + if ok then + if param == "thread_shutdown" then + return {command=true,type="shutdown"} + elseif param == "thread_reboot" then + print("reboot") + return {command=true,type="reboot"} + else + thread.filter = param + + end + elseif type(param) == "string" and exception.can_wrap_errors() then + printError(exception.make_exception(param, thread.co)) + else + printError(param) + end + + if coroutine.status(thread.co) == "dead" then + threads[i] = false + living = living - 1 + if living <= limit then + return i + end + end + end + end + + event = table.pack(os.pullEventRaw()) + end +end + function lib.start(env) - local func = setfenv(function () + local command = nil + + env.os.reboot = function() command = "reboot" sleep() end + env.os.shutdown = function() command = "shutdown" sleep() end + local func = function () + command = nil settings.define("shell.allow_startup", { default = true, description = "Run startup files when the computer turns on.", @@ -953,14 +1020,19 @@ function lib.start(env) description = "Prevents assigning variables into a program's environment. Make sure you use the local keyword or assign to _G explicitly.", type = "boolean", }) + settings.define("bios.use_multishell", { + default = true, + description = "Allow running multiple program at once, through the use of the \"fg\" and \"bg\" programs..", + type = "boolean", + }) settings.define("shell.autocomplete_hidden", { default = false, description = [[Autocomplete hidden files and folders (those starting with ".").]], type = "boolean", }) - print("running container!") - local ok, err = pcall(parallel.waitForAny, - function() + print("running container!") + + return runUntilLimit(create(function() local sShell if term.isColour() and settings.get("bios.use_multishell") then sShell = "rom/programs/advanced/multishell.lua" @@ -969,10 +1041,21 @@ function lib.start(env) end os.run({}, sShell) os.run({}, "rom/programs/shutdown.lua") - end, - rednet.run - ) - end,env) - func() + + end,function () + while true do + sleep() + if command == "shutdown" then + while true do coroutine.yield("thread_shutdown") end + elseif command == "reboot" then + while true do coroutine.yield("thread_reboot") end + end + end + end),0) + end + local command = "starting" + while command == "starting" or (type(command) == "table" and command.command and command.type=="reboot") do + command = setfenv(func,deepcopy(env))() + end end return lib \ No newline at end of file