33 Commits

Author SHA1 Message Date
22b5021e9d fixed boot crash 2026-03-21 01:10:47 -04:00
462c74686a fixed the installer 2026-03-21 01:04:27 -04:00
0072547beb updated package list 2026-03-21 00:59:46 -04:00
7deefc83ca made newer installer that does not require tar stuff 2026-03-21 00:54:39 -04:00
df62414229 made system use full salt+pepper 2026-03-19 14:10:17 -04:00
055dd4e606 fixed again 2026-03-19 12:10:31 -04:00
5755dd9cbe fixed 2026-03-19 11:32:48 -04:00
8e11faf9ec updated again 2026-03-19 11:23:24 -04:00
0ea42f9454 Updated installer 2026-03-19 11:21:08 -04:00
d0f26a937f made installer 2026-03-19 11:16:05 -04:00
9b338328f0 made unified colors and stuff 2026-03-19 08:33:47 -04:00
4f9eebade2 update tar 2026-03-12 20:54:27 -04:00
d08935b68a remove gotos 2026-03-12 19:31:37 -04:00
45b46cf3c4 Merge pull request 'main' (#10) from main into 1.2-dev
Reviewed-on: #10
2026-03-12 19:27:44 -04:00
aeea68bc9b Update install/data/tarbad 2026-03-12 12:12:48 -04:00
f983b13d56 Update install/installcc.lua
make it use right stuff
2026-03-12 12:10:37 -04:00
03c5b106c4 Update Src/Hyperion-kernel/boot/kernel.lua 2026-03-12 11:59:35 -04:00
08323e00ff Update install/data/tarbad 2026-03-12 11:56:58 -04:00
5e3cdbe40c Update install/installcc.lua 2026-03-12 11:51:55 -04:00
8762b8f022 Merge pull request '1.2-dev' (#9) from 1.2-dev into main
Reviewed-on: #9
2026-03-11 10:37:44 -04:00
677b2cccec user login fixed 2026-03-11 10:37:13 -04:00
a5e8624368 forgot to edit login 2026-03-11 08:54:47 -04:00
bbda3b3937 fixed elevate VULN 2026-03-11 08:52:41 -04:00
585d39bec2 Merge pull request '1.2-dev' (#8) from 1.2-dev into main
Reviewed-on: #8
2026-03-11 08:23:21 -04:00
b08b14763a i am a we bit stupid (fixed cct bug) 2026-03-11 08:22:53 -04:00
de6696003b fix capitaization part 2 2026-03-11 07:26:38 -04:00
9220281365 fix capitalization part 1 2026-03-11 07:25:52 -04:00
813ddabd9d fixed disk detection i think 2026-03-10 21:13:52 -04:00
5177639d71 Merge pull request 'update build.tar' (#7) from 1.2-dev into main
Reviewed-on: #7
i was dumb
2026-03-10 20:05:26 -04:00
528b4f31bd update build.tar 2026-03-10 20:04:53 -04:00
60162c7c57 Merge pull request '1.2.4' (#6) from 1.2-dev into main
Reviewed-on: #6
2026-03-10 20:02:20 -04:00
18f5c454bb fixed bug where cct drivers are inaccessable 2026-03-10 20:00:21 -04:00
849ecb7dd6 made procfs self 2026-03-10 19:41:54 -04:00
145 changed files with 3427 additions and 1972 deletions

View File

@@ -0,0 +1,18 @@
--:Minify:--
return {
white=0xFFFFFF,
red=0xFF0000,
green=0x00FF00,
blue=0x0000FF,
cyan=0x00FFFF,
yellow=0xFFFF00,
purple=0xFF00FF,
black=0x000000,
gray=0x888888,
lightgrey=0xBBBBBB,
darkgrey=0x444444,
orange=0xFF8800,
mint=0x00FF88,
brown=0xa52a2a,
chocolate=0xd2691e
}

View File

@@ -0,0 +1,344 @@
--:Minify:--
local args={...}
local bootdrive=args[1]
local gpu=components:getFirst("gpu")
local screenTextBuffer=nil
local cursorX,cursorY=0,0
local screenSizeX,screenSizeY=128,25
if gpu then
screenTextBuffer=gpu:newBuffer(screenSizeX,screenSizeY)
for t,v in components:list() do
if t == "screen" then
gpu:assignBuffer(screenTextBuffer, v)
end
end
end
local function write(text)
cursorX, cursorY = screenTextBuffer:pasteText(cursorX, cursorY, "SCROLL_SPILL_CLEAR", text)
cursorY = cursorY + 1
cursorX = 0
if cursorY >= screenSizeY then
cursorY = screenSizeY-1
screenTextBuffer:newline()
end
end
local function displaySuperBadError(err)
gpu:freeAllBuffers()
screenTextBuffer=gpu:newBuffer(screenSizeX,screenSizeY)
for t,v in components:list() do
if t == "screen" then
gpu:assignBuffer(screenTextBuffer, v)
end
end
term.setBackgroundColor(0x1)
term.setTextColor(0x4)
term.clear()
term.setCursorPos(1, 1)
term.write("A critical error occurred while loading the system:")
term.setCursorPos(1, 3)
write(err)
while true do end
end
local ok, err = xpcall(function()
local apis = {}
local lua = {
coroutine = true,
debug = true,
_VERSION = true,
assert = true,
collectgarbage = true,
error = true,
gcinfo = true,
getmetatable = true,
ipairs = true,
__inext = true,
load = true,
math = true,
next = true,
pairs = true,
pcall = true,
rawequal = true,
rawget = true,
rawlen = true,
rawset = true,
select = true,
setmetatable = true,
string = true,
table = true,
tonumber = true,
tostring = true,
type = true,
xpcall = true,
_G = true
}
local debug = debug
for i, v in pairs(_G) do
if not lua[i] or lua[i] == nil then
apis[i] = v
_G[i] = nil
end
end
local function string_file(file)
local str = file:read()
local buf = {str or ""}
local pos = 1
local closed = false
local function content()
return table.concat(buf)
end
local function set_content(s)
buf = {s}
end
local function flush()
file.write(content())
end
local file = {}
function file:read(n)
assert(not closed, "file is closed")
local s = content()
local len = #s
if not n then
local out = s:sub(pos)
pos = len + 1
return out
end
local out = s:sub(pos, pos + n - 1)
pos = pos + #out
return out
end
function file:write(data)
assert(not closed, "file is closed")
local s = content()
local before = s:sub(1, pos - 1)
local after = s:sub(pos + #data)
set_content(before .. data .. after)
pos = pos + #data
return true
end
function file:seek(whence, offset)
assert(not closed, "file is closed")
local s = content()
local len = #s
whence = whence or "cur"
offset = offset or 0
if whence == "set" then
pos = offset + 1
elseif whence == "cur" then
pos = pos + offset
elseif whence == "end" then
pos = len + offset + 1
else
error("invalid whence")
end
if pos < 1 then pos = 1 end
if pos > len + 1 then pos = len + 1 end
return pos - 1
end
function file:close()
assert(not closed, "file is closed")
flush()
closed = true
end
function file:flush()
assert(not closed, "file is closed")
flush()
end
return file
end
local function getFile(path)
local file = bootdrive:open(path, "r")
if not file then
displaySuperBadError("Could not open file: " .. path)
end
local content = file:read()
return content
end
local Kernel = load(getFile("/boot/kernel.lua"),"@Kernel")
local initFs = load(getFile("/boot/ac/initdisks"),"@Init_disks")(apis)
local fs = load(getFile("/boot/initfs"), "@InitFs")()
if not Kernel then displaySuperBadError("Could not load kernel.") end
if not initFs then displaySuperBadError("Could not load initdisks.") end
if not fs then displaySuperBadError("Could not load initfs.") end
local computercomp=apis.components:getFirst("computer")
local uefi=apis.components:getFirst("uefi")
local computer = {
time = function() return apis.os.epoch("utc") end,
clock = function() return apis.os.clock() * 1000 end,
shutdown = apis.os.shutdown,
reboot = apis.os.reboot,
getMachineEvent = function()
return computercomp:getMachineEvent()
end,
getEEPROM = function() return uefi.data end,
setEEPROM = function(_, text)
uefi.data=text
end
}
local icolors = {
[0x1] = 1, -- #000000
[0x2] = 2, -- #FFFFFF
[0x4] = 3, -- #FF0000
[0x8] = 4, -- #00FF00
[0x10] = 5, -- #0000FF
[0x20] = 6, -- #00FFFF
[0x40] = 7, -- #FF00FF
[0x80] = 8, -- #FFFF00
[0x100] = 9, -- #FF6D00
[0x200] = 10, -- #6DFF55
[0x400] = 11, -- #24FFFF
[0x800] = 12, -- #924900
[0x1000] = 13, -- #6D6D55
[0x2000] = 14, -- #DBDBAA
[0x4000] = 15, -- #6D00FF
[0x8000] = 16 -- #B6FF00
}
local colors = {
0x0001, -- #000000
0x0002, -- #FFFFFF
0x0004, -- #FF0000
0x0008, -- #00FF00
0x0010, -- #0000FF
0x0020, -- #00FFFF
0x0040, -- #FF00FF
0x0080, -- #FFFF00
0x0100, -- #FF6D00
0x0200, -- #6DFF55
0x0400, -- #24FFFF
0x0800, -- #924900
0x1000, -- #6D6D55
0x2000, -- #DBDBAA
0x4000, -- #6D00FF
0x8000 -- #B6FF00
}
apis.term.setBackgroundColor(0x8000)
apis.term.setTextColor(0x1000)
apis.term.clear()
apis.term.setCursorPos(1, 1)
local kernelCoro = coroutine.create(function()
---@diagnostic disable-next-line: param-type-mismatch
local ok, err = xpcall(Kernel, debug.traceback, apis, initFs, "cct", "/sbin/init",
{
print = function(_, text) write(text .. "\n") end,
printInline = function(_, text) write(text) end,
clear = function()
apis.term.clear()
apis.term.setCursorPos(1, 1)
end,
setCursorPos = function(_, x, y)
apis.term.setCursorPos(x, y)
end,
getCursorPos = function() return apis.term.getCursorPos() end,
getSize = function() return apis.term.getSize() end,
setBackgroundColor = function(_, color)
apis.term.setBackgroundColor(colors[color])
end,
setTextColor = function(_, color)
apis.term.setTextColor(colors[color])
end,
getBackgroundColor = function()
return icolors[apis.term.getBackgroundColor()]
end,
getTextColor = function()
return icolors[apis.term.getTextColor()]
end
}, computer, fs, "$")
if not ok then displaySuperBadError(err) end
end)
function coroutine.resumeWithTimeout(co, timeout, ...)
local startTime = computer.time()
debug.sethook(co, function()
if computer.time() > startTime + timeout then
return coroutine.yield("timeout")
end
end, "", 1000)
local ret = {coroutine.resume(co, ...)}
if ret[1] and ret[2] == "timeout" then
return "timeout"
elseif ret[1] == false then
return "error", ret[2]
else
debug.sethook(co)
return "success", table.unpack(ret, 2)
end
end
write("Loaded in " .. tostring(apis.os.clock()) .. " seconds.\n")
while true do
local status, err = coroutine.resumeWithTimeout(kernelCoro, 50)
apis.os.queueEvent("NoSleep")
local exit = false
while not exit do
local event = {coroutine.yield()}
if event[1] == "key" then
queueEvent("keyPressed", 1, event[2])
if acekeys[event[2]] then
queueEvent("keyTyped", 1, acekeys[event[2]])
end
elseif event[1] == "char" then
queueEvent("keyTyped", 1, event[2])
elseif event[1] == "key_up" then
queueEvent("keyReleased", 1, event[2])
elseif event[1] == "disk" then
queueEvent("componentAdded", "disk")
elseif event[1] == "disk_eject" then
queueEvent("componentRemoved", "disk")
elseif event[1] == "modem_message" then
queueEvent("modem_message", table.unpack(event, 2))
elseif event[1] == "rednet_message" then
queueEvent("rednet_message", table.unpack(event, 2))
elseif event[1] == "http_success" then
queueEvent("http_success", table.unpack(event, 2))
elseif event[1] == "http_failure" then
queueEvent("http_failure", table.unpack(event, 2))
elseif event[1] == "NoSleep" then
exit = true
end
end
if status == "error" or coroutine.status(kernelCoro) == "dead" then
displaySuperBadError("Kernel error: " .. tostring(err))
coroutine.yield("key")
end
end
end, debug.traceback)
if not ok then displaySuperBadError("Fatal error during boot: " .. err) end
while true do coroutine.yield() end

View File

@@ -1,4 +1,4 @@
-- :Minify:--
--:Minify:--
local BOOT_DRIVE_PATH = ({...})[1] or "/$"
---@diagnostic disable-next-line: undefined-global
local term = term
@@ -71,7 +71,6 @@ local ok, err = xpcall(function()
collectgarbage = true,
error = true,
gcinfo = true,
getfenv = true,
getmetatable = true,
ipairs = true,
__inext = true,
@@ -85,7 +84,6 @@ local ok, err = xpcall(function()
rawlen = true,
rawset = true,
select = true,
setfenv = true,
setmetatable = true,
string = true,
table = true,
@@ -154,17 +152,106 @@ local ok, err = xpcall(function()
if not initFs then displaySuperBadError("Could not load initdisks.") end
if not fs then displaySuperBadError("Could not load initfs.") end
if not apis.fs.exists("/nvram.dat") then
local file = apis.fs.open("/nvram.dat", "w")
file.write("Hello, World!")
file.close()
end
local eeprom
if apis.fs.exists("/startup.lua") then
eeprom="/startup.lua"
elseif apis.fs.exists("/eeprom") then
eeprom="/eeprom"
end
local eventQueue = {}
local function queueEvent(event, ...)
table.insert(eventQueue, {event, ...})
end
local computer = {
time = function() return apis.os.epoch("utc") end,
clock = function() return apis.os.clock() * 1000 end,
shutdown = apis.os.shutdown,
reboot = apis.os.reboot,
local colors = {
[0x000000]=0x0001,
[0xFFFFFF]=0x0002,
[0xFF0000]=0x0004,
[0x00FF00]=0x0008,
[0x0000FF]=0x0010,
[0x00FFFF]=0x0020,
[0xFF00FF]=0x0040,
[0xFFFF00]=0x0080,
[0xFF6D00]=0x0100,
[0x6DFF55]=0x0200,
[0x24FFFF]=0x0400,
[0x924900]=0x0800,
[0x6D6D55]=0x1000,
[0xDBDBAA]=0x2000,
[0x6D00FF]=0x4000,
[0xB6FF00]=0x8000
}
local fg,bg=0x6D6D55,0x000000
local l1f,l1d,l2,ops={},{},{},0
local function findClosest(tbl, target)
local closest = nil
local smallestDiff = math.huge
for k, _ in pairs(tbl) do
local diff = math.abs(k - target)
if diff < smallestDiff then
smallestDiff = diff
closest = k
end
end
return closest
end
local function aprox(c24)
ops = ops + 1
if ops % 1024 == 0 then
l1d = {}
l1f = {}
end
if ops % 8192 == 0 then
l2 = {}
end
if l2[c24] ~= nil then
return l2[c24]
end
if l1d[c24] ~= nil then
l1f[c24] = l1f[c24] + 1
if l1f[c24] >= 16 then
l2[c24] = l1d[c24]
l1d[c24] = nil
l1f[c24] = nil
return l2[c24]
end
return l1d[c24]
end
local closestKey = findClosest(colors, c24)
if not closestKey then return nil end
local value = colors[closestKey]
l1d[c24] = value
l1f[c24] = 1
return value
end
local EFI = {
getEpochMs = function() return apis.os.epoch("utc") end,
getUptime = function() return apis.os.clock() * 1000 end,
date = function() return apis.os.date("!%Y-%m-%dT%H:%M:%SZ", apis.os.epoch("utc") / 1000) end,
getMachineEvent = function()
if #eventQueue > 0 then
return table.unpack(table.remove(eventQueue, 1))
@@ -172,61 +259,15 @@ local ok, err = xpcall(function()
return nil
end
end,
getEEPROM = function() return getFile("/startup.lua") end,
getEEPROM = function() return getFile(eeprom) end,
setEEPROM = function(_, text)
local h = apis.fs.open("/startup.lua", "w")
local h = apis.fs.open(eeprom, "w")
h.write(text)
h.close()
end
}
local icolors = {
[0x1] = 1, -- #000000
[0x2] = 2, -- #FFFFFF
[0x4] = 3, -- #FF0000
[0x8] = 4, -- #00FF00
[0x10] = 5, -- #0000FF
[0x20] = 6, -- #00FFFF
[0x40] = 7, -- #FF00FF
[0x80] = 8, -- #FFFF00
[0x100] = 9, -- #FF6D00
[0x200] = 10, -- #6DFF55
[0x400] = 11, -- #24FFFF
[0x800] = 12, -- #924900
[0x1000] = 13, -- #6D6D55
[0x2000] = 14, -- #DBDBAA
[0x4000] = 15, -- #6D00FF
[0x8000] = 16 -- #B6FF00
}
local colors = {
0x0001, -- #000000
0x0002, -- #FFFFFF
0x0004, -- #FF0000
0x0008, -- #00FF00
0x0010, -- #0000FF
0x0020, -- #00FFFF
0x0040, -- #FF00FF
0x0080, -- #FFFF00
0x0100, -- #FF6D00
0x0200, -- #6DFF55
0x0400, -- #24FFFF
0x0800, -- #924900
0x1000, -- #6D6D55
0x2000, -- #DBDBAA
0x4000, -- #6D00FF
0x8000 -- #B6FF00
}
apis.term.setBackgroundColor(0x8000)
apis.term.setTextColor(0x1000)
apis.term.clear()
apis.term.setCursorPos(1, 1)
local kernelCoro = coroutine.create(function()
---@diagnostic disable-next-line: param-type-mismatch
local ok, err = xpcall(Kernel, debug.traceback, apis, initFs, "cct", "/sbin/init",
{
end,
initfs=fs,
disks=initFs,
screenCtl={
print = function(_, text) write(text .. "\n") end,
printInline = function(_, text) write(text) end,
clear = function()
@@ -239,25 +280,51 @@ local ok, err = xpcall(function()
getCursorPos = function() return apis.term.getCursorPos() end,
getSize = function() return apis.term.getSize() end,
setBackgroundColor = function(_, color)
apis.term.setBackgroundColor(colors[color])
apis.term.setBackgroundColor(aprox(color))
end,
setTextColor = function(_, color)
apis.term.setTextColor(colors[color])
apis.term.setTextColor(aprox(color))
end,
getBackgroundColor = function()
return icolors[apis.term.getBackgroundColor()]
return bg
end,
getTextColor = function()
return icolors[apis.term.getTextColor()]
end
}, computer, fs, "$")
if not ok then displaySuperBadError(err) end
return fg
end,
enable=function() end,
disable=function() end
},
architecture="cct",
getNvram = function() return getFile("/nvram.dat") end,
setNvram = function(_, text)
local h = apis.fs.open("/nvram.dat", "w")
h.write(text)
h.close()
end,
firmware=apis,
reboot=false
}
apis.term.setBackgroundColor(0x8000)
apis.term.setTextColor(0x1000)
apis.term.clear()
apis.term.setCursorPos(1, 1)
local kernelCoro = coroutine.create(function()
---@diagnostic disable-next-line: param-type-mismatch
local ok, err = xpcall(Kernel, debug.traceback, EFI)
if not ok and not EFI.reboot then displaySuperBadError(err) end
if err then
apis.os.reboot()
else
apis.os.shutdown()
end
end)
function coroutine.resumeWithTimeout(co, timeout, ...)
local startTime = computer.time()
local startTime = EFI.getEpochMs()
debug.sethook(co, function()
if computer.time() > startTime + timeout then
if EFI.getEpochMs() > startTime + timeout then
return coroutine.yield("timeout")
end
end, "", 1000)
@@ -306,11 +373,15 @@ local ok, err = xpcall(function()
end
end
if status == "error" or coroutine.status(kernelCoro) == "dead" then
if EFI.reboot then
apis.os.reboot()
end
displaySuperBadError("Kernel error: " .. tostring(err))
coroutine.yield("key")
end
initFs:refresh()
end
end, debug.traceback)
if not ok then displaySuperBadError("Fatal error during boot: " .. err) end
while true do coroutine.yield() end
while true do coroutine.yield("key") end

View File

@@ -0,0 +1,272 @@
--:Minify:--
local apis = ({...})[1]
local BOOT_DRIVE_PATH = apis.BOOT_DRIVE_PATH
local fs = apis.fs
local native = apis.peripheral
local peripheral = {}
local sides = {"top", "bottom", "left", "right", "front", "back"}
function peripheral.getNames()
local results = {}
for n = 1, #sides do
local side = sides[n]
if native.isPresent(side) then
table.insert(results, side)
if native.hasType(side, "peripheral_hub") then
local remote = native.call(side, "getNamesRemote")
for _, name in ipairs(remote) do
table.insert(results, name)
end
end
end
end
return results
end
function peripheral.isPresent(name)
if native.isPresent(name) then
return true
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return true
end
end
return false
end
function peripheral.getType(peripheral)
if type(peripheral) == "string" then
if native.isPresent(peripheral) then
return native.getType(peripheral)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
return native.call(side, "getTypeRemote", peripheral)
end
end
return nil
else
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return table.unpack(mt.types)
end
end
function peripheral.hasType(peripheral, peripheral_type)
if type(peripheral) == "string" then
if native.isPresent(peripheral) then
return native.hasType(peripheral, peripheral_type)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
return native.call(side, "hasTypeRemote", peripheral, peripheral_type)
end
end
return nil
else
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return mt.types[peripheral_type] ~= nil
end
end
function peripheral.getMethods(name)
if native.isPresent(name) then
return native.getMethods(name)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return native.call(side, "getMethodsRemote", name)
end
end
return nil
end
function peripheral.getName(peripheral)
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.name) ~= "string" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return mt.name
end
function peripheral.call(name, method, ...)
if native.isPresent(name) then
return native.call(name, method, ...)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return native.call(side, "callRemote", name, method, ...)
end
end
return nil
end
function peripheral.wrap(name)
local methods = peripheral.getMethods(name)
if not methods then
return nil
end
local types = { peripheral.getType(name) }
for i = 1, #types do types[types[i]] = true end
local result = setmetatable({}, {
__name = "peripheral",
name = name,
type = types[1],
types = types,
})
for _, method in ipairs(methods) do
result[method] = function(...)
return peripheral.call(name, method, ...)
end
end
return result
end
function peripheral.find(ty, filter)
local results = {}
for _, name in ipairs(peripheral.getNames()) do
if peripheral.hasType(name, ty) then
local wrapped = peripheral.wrap(name)
if filter == nil or filter(name, wrapped) then
table.insert(results, wrapped)
end
end
end
return table.unpack(results)
end
local disks = {}
local internal = {}
local function norm(path)
if not path or path == "" then return "/" end
return fs.combine("/", path)
end
local function createDisk(id, basePath, readonly, periph)
basePath = norm(basePath)
local disk = {address = id, isReadOnly = function() return readonly end}
function disk:spaceUsed()
return fs.getCapacity(basePath) - fs.getFreeSpace(basePath)
end
function disk:spaceTotal() return fs.getCapacity(basePath) end
function disk:list(path)
local p = fs.combine(basePath, path)
if not fs.exists(p) or not fs.isDir(p) then
return nil, "not directory"
end
return fs.list(p)
end
function disk:fileExists(path)
local p = fs.combine(basePath, path)
return fs.exists(p) and not fs.isDir(p)
end
function disk:directoryExists(path)
local p = fs.combine(basePath, path)
return fs.exists(p) and fs.isDir(p)
end
function disk:type(path)
local p = fs.combine(basePath, path)
if not fs.exists(p) then
return nil
elseif fs.isDir(p) then
return "directory"
else
return "file"
end
end
function disk:makeDirectory(path)
local p = fs.combine(basePath, path)
fs.makeDir(p)
return true
end
function disk:remove(path)
local p = fs.combine(basePath, path)
if fs.exists(p) then fs.delete(p) end
return true
end
function disk:setLabel(label) periph.setLabel(label) end
function disk:getLabel(label) return periph.getLabel() end
function disk:attributes(path)
local p = fs.combine(basePath, path)
return fs.attributes(p)
end
function disk:open(path, mode)
local p = fs.combine(basePath, path)
return fs.open(p, mode)
end
return disk
end
internal["$"] = createDisk("$", BOOT_DRIVE_PATH, false, {
setLabel = function(label)
local h = fs.open("/.label", "w")
h.write(label)
h.close()
end,
getLabel = function()
local h = fs.open("/.label", "r")
if not h then return "$" end
local label = h.readAll()
h.close()
return label
end
})
internal["rom"] = createDisk("rom", "/rom", true, {
setLabel = function(label)
error("Device is read-only")
end,
getLabel = function()
return "cctrom"
end
})
local function refresh()
disks={}
for _, disk in ipairs({peripheral.find("drive")}) do
if disk.isDiskPresent() then
disks[tostring(disk.getDiskID())]=createDisk("cctdisk"..tostring(disk.getDiskID()), disk.getMountPath(), false, fs)
end
end
end
local function iter()
refresh()
local combined = {}
for id, obj in pairs(internal) do combined[id] = obj end
for id, obj in pairs(disks) do combined[id] = obj end
return pairs(combined)
end
return {refresh = refresh, list = iter}

View File

@@ -1,155 +0,0 @@
-- :Minify:--
local apis = ({...})[1]
local BOOT_DRIVE_PATH = apis.BOOT_DRIVE_PATH or "/$"
local fs = apis.fs
local native = apis.peripheral
local peripheral = {}
local sides = {"top", "bottom", "left", "right", "front", "back"}
function peripheral.getType(name)
if native.isPresent(name) then return native.getType(name) end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and
native.call(side, "isPresentRemote", name) then
return native.call(side, "getTypeRemote", name)
end
end
return nil
end
function peripheral.getNames()
local names = {}
for n = 1, #sides do
local side = sides[n]
if native.isPresent(side) then table.insert(names, side) end
if native.hasType(side, "peripheral_hub") then
local hubSides = native.call(side, "getConnectedSides")
for _, hubSide in ipairs(hubSides) do
table.insert(names, hubSide)
end
end
end
return names
end
local disks = {}
local internal = {}
local function norm(path)
if not path or path == "" then return "/" end
return fs.combine("/", path)
end
local function createDisk(id, basePath, readonly, periph)
basePath = norm(basePath)
local disk = {address = id, isReadOnly = function() return readonly end}
function disk:spaceUsed()
return fs.getCapacity(basePath) - fs.getFreeSpace(basePath)
end
function disk:spaceTotal() return fs.getCapacity(basePath) end
function disk:list(path)
local p = fs.combine(basePath, path)
if not fs.exists(p) or not fs.isDir(p) then
return nil, "not directory"
end
return fs.list(p)
end
function disk:fileExists(path)
local p = fs.combine(basePath, path)
return fs.exists(p) and not fs.isDir(p)
end
function disk:directoryExists(path)
local p = fs.combine(basePath, path)
return fs.exists(p) and fs.isDir(p)
end
function disk:type(path)
local p = fs.combine(basePath, path)
if not fs.exists(p) then
return nil
elseif fs.isDir(p) then
return "directory"
else
return "file"
end
end
function disk:makeDirectory(path)
local p = fs.combine(basePath, path)
fs.makeDir(p)
return true
end
function disk:remove(path)
local p = fs.combine(basePath, path)
if fs.exists(p) then fs.delete(p) end
return true
end
function disk:setLabel(label) periph.setLabel(label) end
function disk:getLabel(label) return periph.getLabel() end
function disk:attributes(path)
local p = fs.combine(basePath, path)
return fs.attributes(p)
end
function disk:open(path, mode)
local p = fs.combine(basePath, path)
return fs.open(p, mode)
end
return disk
end
internal["$"] = createDisk("$", BOOT_DRIVE_PATH, false, {
setLabel = function(label)
local h = fs.open("/.label", "w")
h.write(label)
h.close()
end,
getLabel = function()
local h = fs.open("/.label", "r")
if not h then return "$" end
local label = h.readAll()
h.close()
return label
end
})
local function refresh()
for id, _ in pairs(disks) do
if not peripheral.getType(id) then disks[id] = nil end
end
for _, name in ipairs(peripheral.getNames()) do
if peripheral.getType(name) == "disk" then
if not disks[name] then
local mount = disk.getMountPath(name)
if mount then
disks[name] = createDisk(name, mount, false, disk)
end
end
end
end
end
local function iter()
refresh()
local combined = {}
for id, obj in pairs(internal) do combined[id] = obj end
for id, obj in pairs(disks) do combined[id] = obj end
return pairs(combined)
end
return {refresh = refresh, list = iter}

View File

@@ -1,26 +0,0 @@
local args={...}
local kernel=args[1]
local driver={}
driver.name="CCT Term Module"
driver.version="0.1.0"
driver.type="gpio"
driver.description="CCT redstone Module Kernel Module"
driver.arch="cct"
driver.author="HyperionOS Dev Team"
driver.license="MIT"
driver.api={}
function driver.load()
-- will
end
function driver.unload()
-- Nothing to unload
end
function driver.main()
-- Nothing to run
end
-- kernel.drivers.register(driver)

View File

@@ -311,7 +311,7 @@ local fifo = kernel.newFifo()
kernel.processes.cctmond = function()
local timeout = false
while true do
local event = {kernel.computer:getMachineEvent()}
local event = {kernel.EFI:getMachineEvent()}
if event[1] then
local eventType = event[1]

View File

@@ -1,4 +1,4 @@
-- :Minify:--
--:Minify:--
local BOOT_DRIVE_PATH = ({...})[1] or "/$"
---@diagnostic disable-next-line: undefined-global
local term = term
@@ -152,17 +152,262 @@ local ok, err = xpcall(function()
if not initFs then displaySuperBadError("Could not load initdisks.") end
if not fs then displaySuperBadError("Could not load initfs.") end
if not apis.fs.exists("/nvram.dat") then
local file = apis.fs.open("/nvram.dat", "w")
file.write("Hello, World!")
file.close()
end
local eeprom
if apis.fs.exists("/startup.lua") then
eeprom="/startup.lua"
elseif apis.fs.exists("/eeprom") then
eeprom="/eeprom"
end
local eventQueue = {}
local function queueEvent(event, ...)
table.insert(eventQueue, {event, ...})
end
local computer = {
time = function() return apis.os.epoch("utc") end,
clock = function() return apis.os.clock() * 1000 end,
shutdown = apis.os.shutdown,
reboot = apis.os.reboot,
local colors = {
[0x000000]=0x0001,
[0xFFFFFF]=0x0002,
[0xFF0000]=0x0004,
[0x00FF00]=0x0008,
[0x0000FF]=0x0010,
[0x00FFFF]=0x0020,
[0xFF00FF]=0x0040,
[0xFFFF00]=0x0080,
[0xFF6D00]=0x0100,
[0x6DFF55]=0x0200,
[0x24FFFF]=0x0400,
[0x924900]=0x0800,
[0x6D6D55]=0x1000,
[0xDBDBAA]=0x2000,
[0x6D00FF]=0x4000,
[0xB6FF00]=0x8000
}
local fg,bg=0x6D6D55,0x000000
local l1f,l1d,l2,ops={},{},{},0
local function findClosest(tbl, target)
local closest = nil
local smallestDiff = math.huge
for k, _ in pairs(tbl) do
if k==target then return k end
local diff = math.abs(k - target)
if diff < smallestDiff then
smallestDiff = diff
closest = k
end
end
return closest
end
local function aprox(c24)
ops = ops + 1
if ops % 1024 == 0 then
l1d = {}
l1f = {}
end
if ops % 8192 == 0 then
l2 = {}
end
if l2[c24] ~= nil then
return l2[c24]
end
if l1d[c24] ~= nil then
l1f[c24] = l1f[c24] + 1
if l1f[c24] >= 16 then
l2[c24] = l1d[c24]
l1d[c24] = nil
l1f[c24] = nil
return l2[c24]
end
return l1d[c24]
end
local closestKey = findClosest(colors, c24)
if not closestKey then return nil end
local value = colors[closestKey]
l1d[c24] = value
l1f[c24] = 1
return value
end
local peripheral={}
local native = apis.peripheral
local sides = {"top", "bottom", "left", "right", "front", "back"}
function peripheral.getNames()
local results = {}
for n = 1, #sides do
local side = sides[n]
if native.isPresent(side) then
table.insert(results, side)
if native.hasType(side, "peripheral_hub") then
local remote = native.call(side, "getNamesRemote")
for _, name in ipairs(remote) do
table.insert(results, name)
end
end
end
end
return results
end
function peripheral.isPresent(name)
if native.isPresent(name) then
return true
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return true
end
end
return false
end
function peripheral.getType(peripheral)
if type(peripheral) == "string" then
if native.isPresent(peripheral) then
return native.getType(peripheral)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
return native.call(side, "getTypeRemote", peripheral)
end
end
return nil
else
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return table.unpack(mt.types)
end
end
function peripheral.hasType(peripheral, peripheral_type)
if type(peripheral) == "string" then
if native.isPresent(peripheral) then
return native.hasType(peripheral, peripheral_type)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
return native.call(side, "hasTypeRemote", peripheral, peripheral_type)
end
end
return nil
else
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return mt.types[peripheral_type] ~= nil
end
end
function peripheral.getMethods(name)
if native.isPresent(name) then
return native.getMethods(name)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return native.call(side, "getMethodsRemote", name)
end
end
return nil
end
function peripheral.getName(peripheral)
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.name) ~= "string" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return mt.name
end
function peripheral.call(name, method, ...)
if native.isPresent(name) then
return native.call(name, method, ...)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return native.call(side, "callRemote", name, method, ...)
end
end
return nil
end
function peripheral.wrap(name)
local methods = peripheral.getMethods(name)
if not methods then
return nil
end
local types = { peripheral.getType(name) }
for i = 1, #types do types[types[i]] = true end
local result = setmetatable({}, {
__name = "peripheral",
name = name,
type = types[1],
types = types,
})
for _, method in ipairs(methods) do
result[method] = function(...)
return peripheral.call(name, method, ...)
end
end
return result
end
function peripheral.find(ty, filter)
local results = {}
for _, name in ipairs(peripheral.getNames()) do
if peripheral.hasType(name, ty) then
local wrapped = peripheral.wrap(name)
if filter == nil or filter(name, wrapped) then
table.insert(results, wrapped)
end
end
end
return table.unpack(results)
end
local allscreens = {peripheral.find("monitor")}
for i=1, #allscreens do
allscreens[i].setTextScale(.5)
allscreens[i].clear()
allscreens[i].setCursorPos(1,1)
allscreens[i].write("Initializing...")
end
local EFI = {
getEpochMs = function() return apis.os.epoch("utc") end,
getUptime = function() return apis.os.clock() * 1000 end,
date = function() return apis.os.date("!%Y-%m-%dT%H:%M:%SZ", apis.os.epoch("utc") / 1000) end,
getMachineEvent = function()
if #eventQueue > 0 then
return table.unpack(table.remove(eventQueue, 1))
@@ -170,61 +415,15 @@ local ok, err = xpcall(function()
return nil
end
end,
getEEPROM = function() return getFile("/startup.lua") end,
getEEPROM = function() return getFile(eeprom) end,
setEEPROM = function(_, text)
local h = apis.fs.open("/startup.lua", "w")
local h = apis.fs.open(eeprom, "w")
h.write(text)
h.close()
end
}
local icolors = {
[0x1] = 1, -- #000000
[0x2] = 2, -- #FFFFFF
[0x4] = 3, -- #FF0000
[0x8] = 4, -- #00FF00
[0x10] = 5, -- #0000FF
[0x20] = 6, -- #00FFFF
[0x40] = 7, -- #FF00FF
[0x80] = 8, -- #FFFF00
[0x100] = 9, -- #FF6D00
[0x200] = 10, -- #6DFF55
[0x400] = 11, -- #24FFFF
[0x800] = 12, -- #924900
[0x1000] = 13, -- #6D6D55
[0x2000] = 14, -- #DBDBAA
[0x4000] = 15, -- #6D00FF
[0x8000] = 16 -- #B6FF00
}
local colors = {
0x0001, -- #000000
0x0002, -- #FFFFFF
0x0004, -- #FF0000
0x0008, -- #00FF00
0x0010, -- #0000FF
0x0020, -- #00FFFF
0x0040, -- #FF00FF
0x0080, -- #FFFF00
0x0100, -- #FF6D00
0x0200, -- #6DFF55
0x0400, -- #24FFFF
0x0800, -- #924900
0x1000, -- #6D6D55
0x2000, -- #DBDBAA
0x4000, -- #6D00FF
0x8000 -- #B6FF00
}
apis.term.setBackgroundColor(0x8000)
apis.term.setTextColor(0x1000)
apis.term.clear()
apis.term.setCursorPos(1, 1)
local kernelCoro = coroutine.create(function()
---@diagnostic disable-next-line: param-type-mismatch
local ok, err = xpcall(Kernel, debug.traceback, apis, initFs, "cct", "/sbin/init",
{
end,
initfs=fs,
disks=initFs,
screenCtl={
print = function(_, text) write(text .. "\n") end,
printInline = function(_, text) write(text) end,
clear = function()
@@ -237,25 +436,52 @@ local ok, err = xpcall(function()
getCursorPos = function() return apis.term.getCursorPos() end,
getSize = function() return apis.term.getSize() end,
setBackgroundColor = function(_, color)
apis.term.setBackgroundColor(colors[color])
apis.term.setBackgroundColor(aprox(color))
end,
setTextColor = function(_, color)
apis.term.setTextColor(colors[color])
apis.term.setTextColor(aprox(color))
end,
getBackgroundColor = function()
return icolors[apis.term.getBackgroundColor()]
return bg
end,
getTextColor = function()
return icolors[apis.term.getTextColor()]
end
}, computer, fs, "$")
if not ok then displaySuperBadError(err) end
return fg
end,
enable=function() end,
disable=function() end
},
architecture="cct",
getNvram = function() return getFile("/nvram.dat") end,
setNvram = function(_, text)
local h = apis.fs.open("/nvram.dat", "w")
h.write(text)
h.close()
end,
firmware=apis,
reboot=false,
beep=function() end
}
apis.term.setBackgroundColor(0x8000)
apis.term.setTextColor(0x1000)
apis.term.clear()
apis.term.setCursorPos(1, 1)
local kernelCoro = coroutine.create(function()
---@diagnostic disable-next-line: param-type-mismatch
local ok, err = xpcall(Kernel, debug.traceback, EFI)
if not ok and not EFI.reboot then displaySuperBadError(err) end
if err then
apis.os.reboot()
else
apis.os.shutdown()
end
end)
function coroutine.resumeWithTimeout(co, timeout, ...)
local startTime = computer.time()
local startTime = EFI.getEpochMs()
debug.sethook(co, function()
if computer.time() > startTime + timeout then
if EFI.getEpochMs() > startTime + timeout then
return coroutine.yield("timeout")
end
end, "", 1000)
@@ -270,7 +496,7 @@ local ok, err = xpcall(function()
end
end
write("Loaded in " .. tostring(apis.os.clock()) .. " seconds.\n")
EFI.screenCtl:print("Loaded in " .. tostring(apis.os.clock()) .. " seconds.\n")
while true do
local status, err = coroutine.resumeWithTimeout(kernelCoro, 50)
@@ -304,11 +530,15 @@ local ok, err = xpcall(function()
end
end
if status == "error" or coroutine.status(kernelCoro) == "dead" then
if EFI.reboot then
apis.os.reboot()
end
displaySuperBadError("Kernel error: " .. tostring(err))
coroutine.yield("key")
end
initFs:refresh()
end
end, debug.traceback)
if not ok then displaySuperBadError("Fatal error during boot: " .. err) end
while true do coroutine.yield() end
while true do coroutine.yield("key") end

View File

@@ -1,36 +1,152 @@
-- :Minify:--
--:Minify:--
local apis = ({...})[1]
local BOOT_DRIVE_PATH = apis.BOOT_DRIVE_PATH or "/$"
local BOOT_DRIVE_PATH = apis.BOOT_DRIVE_PATH
local fs = apis.fs
local native = apis.peripheral
local peripheral = {}
local sides = {"top", "bottom", "left", "right", "front", "back"}
function peripheral.getType(name)
if native.isPresent(name) then return native.getType(name) end
function peripheral.getNames()
local results = {}
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and
native.call(side, "isPresentRemote", name) then
return native.call(side, "getTypeRemote", name)
if native.isPresent(side) then
table.insert(results, side)
if native.hasType(side, "peripheral_hub") then
local remote = native.call(side, "getNamesRemote")
for _, name in ipairs(remote) do
table.insert(results, name)
end
end
end
end
return results
end
function peripheral.isPresent(name)
if native.isPresent(name) then
return true
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return true
end
end
return false
end
function peripheral.getType(peripheral)
if type(peripheral) == "string" then
if native.isPresent(peripheral) then
return native.getType(peripheral)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
return native.call(side, "getTypeRemote", peripheral)
end
end
return nil
else
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return table.unpack(mt.types)
end
end
function peripheral.hasType(peripheral, peripheral_type)
if type(peripheral) == "string" then
if native.isPresent(peripheral) then
return native.hasType(peripheral, peripheral_type)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
return native.call(side, "hasTypeRemote", peripheral, peripheral_type)
end
end
return nil
else
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return mt.types[peripheral_type] ~= nil
end
end
function peripheral.getMethods(name)
if native.isPresent(name) then
return native.getMethods(name)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return native.call(side, "getMethodsRemote", name)
end
end
return nil
end
function peripheral.getNames()
local names = {}
function peripheral.getName(peripheral)
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.name) ~= "string" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return mt.name
end
function peripheral.call(name, method, ...)
if native.isPresent(name) then
return native.call(name, method, ...)
end
for n = 1, #sides do
local side = sides[n]
if native.isPresent(side) then table.insert(names, side) end
if native.hasType(side, "peripheral_hub") then
local hubSides = native.call(side, "getConnectedSides")
for _, hubSide in ipairs(hubSides) do
table.insert(names, hubSide)
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return native.call(side, "callRemote", name, method, ...)
end
end
return nil
end
function peripheral.wrap(name)
local methods = peripheral.getMethods(name)
if not methods then
return nil
end
local types = { peripheral.getType(name) }
for i = 1, #types do types[types[i]] = true end
local result = setmetatable({}, {
__name = "peripheral",
name = name,
type = types[1],
types = types,
})
for _, method in ipairs(methods) do
result[method] = function(...)
return peripheral.call(name, method, ...)
end
end
return result
end
function peripheral.find(ty, filter)
local results = {}
for _, name in ipairs(peripheral.getNames()) do
if peripheral.hasType(name, ty) then
local wrapped = peripheral.wrap(name)
if filter == nil or filter(name, wrapped) then
table.insert(results, wrapped)
end
end
end
return names
return table.unpack(results)
end
local disks = {}
@@ -125,19 +241,20 @@ internal["$"] = createDisk("$", BOOT_DRIVE_PATH, false, {
end
})
local function refresh()
for id, _ in pairs(disks) do
if not peripheral.getType(id) then disks[id] = nil end
internal["rom"] = createDisk("rom", "/rom", true, {
setLabel = function(label)
error("Device is read-only")
end,
getLabel = function()
return "cctrom"
end
})
for _, name in ipairs(peripheral.getNames()) do
if peripheral.getType(name) == "disk" then
if not disks[name] then
local mount = disk.getMountPath(name)
if mount then
disks[name] = createDisk(name, mount, false, disk)
end
end
local function refresh()
disks={}
for _, disk in ipairs({peripheral.find("drive")}) do
if disk.isDiskPresent() then
disks[tostring(disk.getDiskID())]=createDisk("cctdisk"..tostring(disk.getDiskID()), disk.getMountPath(), false, fs)
end
end
end

View File

@@ -1,410 +0,0 @@
--:Minify:--
local kernel = ...
local apis = kernel.apis
local native = apis.peripheral
local sides = {"top", "bottom", "left", "right", "front", "back"}
local peripheral={}
function peripheral.getNames()
local results = {}
for n = 1, #sides do
local side = sides[n]
if native.isPresent(side) then
table.insert(results, side)
if native.hasType(side, "peripheral_hub") then
local remote = native.call(side, "getNamesRemote")
for _, name in ipairs(remote) do
table.insert(results, name)
end
end
end
end
return results
end
function peripheral.isPresent(name)
if native.isPresent(name) then
return true
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return true
end
end
return false
end
function peripheral.getType(peripheral)
if type(peripheral) == "string" then
if native.isPresent(peripheral) then
return native.getType(peripheral)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
return native.call(side, "getTypeRemote", peripheral)
end
end
return nil
else
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return table.unpack(mt.types)
end
end
function peripheral.hasType(peripheral, peripheral_type)
if type(peripheral) == "string" then
if native.isPresent(peripheral) then
return native.hasType(peripheral, peripheral_type)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
return native.call(side, "hasTypeRemote", peripheral, peripheral_type)
end
end
return nil
else
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return mt.types[peripheral_type] ~= nil
end
end
function peripheral.getMethods(name)
if native.isPresent(name) then
return native.getMethods(name)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return native.call(side, "getMethodsRemote", name)
end
end
return nil
end
function peripheral.getName(peripheral)
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.name) ~= "string" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return mt.name
end
function peripheral.call(name, method, ...)
if native.isPresent(name) then
return native.call(name, method, ...)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return native.call(side, "callRemote", name, method, ...)
end
end
return nil
end
function peripheral.wrap(name)
local methods = peripheral.getMethods(name)
if not methods then
return nil
end
local types = { peripheral.getType(name) }
for i = 1, #types do types[types[i]] = true end
local result = setmetatable({}, {
__name = "peripheral",
name = name,
type = types[1],
types = types,
})
for _, method in ipairs(methods) do
result[method] = function(...)
return peripheral.call(name, method, ...)
end
end
return result
end
function peripheral.find(ty, filter)
local results = {}
for _, name in ipairs(peripheral.getNames()) do
if peripheral.hasType(name, ty) then
local wrapped = peripheral.wrap(name)
if filter == nil or filter(name, wrapped) then
table.insert(results, wrapped)
end
end
end
return table.unpack(results)
end
local icolors = {
[0x1] = 1, -- #000000
[0x2] = 2, -- #FFFFFF
[0x4] = 3, -- #FF0000
[0x8] = 4, -- #00FF00
[0x10] = 5, -- #0000FF
[0x20] = 6, -- #00FFFF
[0x40] = 7, -- #FF00FF
[0x80] = 8, -- #FFFF00
[0x100] = 9, -- #FF6D00
[0x200] = 10, -- #6DFF55
[0x400] = 11, -- #24FFFF
[0x800] = 12, -- #924900
[0x1000] = 13, -- #6D6D55
[0x2000] = 14, -- #DBDBAA
[0x4000] = 15, -- #6D00FF
[0x8000] = 16 -- #B6FF00
}
local colors = {
0x0001, -- #000000
0x0002, -- #FFFFFF
0x0004, -- #FF0000
0x0008, -- #00FF00
0x0010, -- #0000FF
0x0020, -- #00FFFF
0x0040, -- #FF00FF
0x0080, -- #FFFF00
0x0100, -- #FF6D00
0x0200, -- #6DFF55
0x0400, -- #24FFFF
0x0800, -- #924900
0x1000, -- #6D6D55
0x2000, -- #DBDBAA
0x4000, -- #6D00FF
0x8000 -- #B6FF00
}
local function write(text, term)
local x, y = term.getCursorPos()
local w, h = term.getSize()
for i = 1, #text do
local c = text:sub(i, i)
if c == "\n" then
y = y + 1
x = 1
elseif c == "\t" then
local tabSize = 4
local spaces = tabSize - ((x - 1) % tabSize)
term.write(string.rep(" ", spaces))
x = x + spaces
elseif c == "\b" then
if x > 1 then
x = x - 1
term.setCursorPos(x, y)
term.write(" ")
term.setCursorPos(x, y)
end
else
if x <= w and y <= h then
term.setCursorPos(x, y)
term.write(c)
x = x + 1
end
end
if x > w then
x = 1
y = y + 1
end
if y - 1 >= h then
term.scroll(1)
y = h
term.setCursorPos(x, y)
end
end
term.setCursorPos(x, y)
end
kernel.devfs.data.tty={}
local ctrl,alt = false, false
local function serializeBool(bool)
if bool then
return "T"
else
return "F"
end
end
local function newtty(obj, id, ev)
obj.setPaletteColor(0x1, 0xFFFFFF) -- #000000
obj.setPaletteColor(0x2, 0xFF0000) -- #FFFFFF
obj.setPaletteColor(0x4, 0x00FF00) -- #FF0000
obj.setPaletteColor(0x8, 0x0000FF) -- #00FF00
obj.setPaletteColor(0x10, 0x00FFFF) -- #0000FF
obj.setPaletteColor(0x20, 0xFF00FF) -- #00FFFF
obj.setPaletteColor(0x40, 0xFFFF00) -- #FF00FF
obj.setPaletteColor(0x80, 0xFF6D00) -- #FFFF00
obj.setPaletteColor(0x100, 0x6DFF55) -- #FF6D00
obj.setPaletteColor(0x200, 0x24FFFF) -- #6DFF55
obj.setPaletteColor(0x400, 0x924900) -- #24FFFF
obj.setPaletteColor(0x800, 0x6D6D55) -- #924900
obj.setPaletteColor(0x1000, 0xDBDBAA) -- #6D6D55
obj.setPaletteColor(0x2000, 0x6D00FF) -- #DBDBAA
obj.setPaletteColor(0x4000, 0xB6FF00) -- #6D00FF
obj.setPaletteColor(0x8000, 0x000000) -- #B6FF00
kernel.devfs.data["tty"][id] = function(op, mode)
if op=="type" then
return "character device"
elseif op=="open" then
local h = {
read=function(amount)
local rv=""
for i=1, amount or 1 do
local event = {ev()}
if event[1] then
rv=rv..event[1]
end
end
if rv=="" then rv=nil end
return rv
end,
write=function(content)
write(content, obj)
end,
size=function()
local s={obj.getSize()}
return table.concat(s,";")
end,
clear=function()
obj.clear()
obj.setCursorPos(1,1)
end,
gpos=function()
local s={obj.getCursorPos()}
return table.concat(s,";")
end,
spos=function(x,y)
return obj.setCursorPos(x,y)
end,
sfgc=function(c)
return obj.setTextColor(colors[c])
end,
sbgc=function(c)
return obj.setBackgroundColor(colors[c])
end,
gfgc=function()
return icolors[obj.getTextColor()]
end,
gbgc=function()
return icolors[obj.getBackgroundColor()]
end,
gctrl=function()
return serializeBool(ctrl)..";"..serializeBool(alt)
end
}
if mode=="rw" then
return h
elseif mode=="r" then
h["write"]=nil
return h
elseif mode=="w" then
h["read"]=nil
return h
end
end
end
end
local fifo = kernel.newFifo()
kernel.processes.cctmond = function()
local timeout = false
while true do
local event = {kernel.computer:getMachineEvent()}
if event[1] then
local eventType = event[1]
local charOrKey = event[3]
local ctrlKeyMap = {
[apis.keys.a]=1, [apis.keys.b]=2, [apis.keys.c]=3,
[apis.keys.d]=4, [apis.keys.e]=5, [apis.keys.f]=6,
[apis.keys.g]=7, [apis.keys.h]=8, [apis.keys.i]=9,
[apis.keys.j]=10, [apis.keys.k]=11, [apis.keys.l]=12,
[apis.keys.m]=13, [apis.keys.n]=14, [apis.keys.o]=15,
[apis.keys.p]=16, [apis.keys.q]=17, [apis.keys.r]=18,
[apis.keys.s]=19, [apis.keys.t]=20, [apis.keys.u]=21,
[apis.keys.v]=22, [apis.keys.w]=23, [apis.keys.x]=24,
[apis.keys.y]=25, [apis.keys.z]=26,
}
if eventType == "keyPressed" then
if charOrKey == apis.keys.leftCtrl or charOrKey == apis.keys.rightCtrl then
ctrl = true
elseif charOrKey == apis.keys.leftAlt or charOrKey == apis.keys.rightAlt then
alt = true
end
if ctrl then
local ctrlByte = ctrlKeyMap[charOrKey]
if ctrlByte then
if ctrlByte == 3 then
for _, task in ipairs(syscall.getTasks()) do
syscall.sigsend(task, 1)
end
else
fifo.push(string.char(ctrlByte))
end
end
else
local specialKeyMap = {
[apis.keys.up] = "",
[apis.keys.down] = "",
[apis.keys.right] = "",
[apis.keys.left] = "",
[apis.keys.home] = "",
[apis.keys["end"]] = "",
[apis.keys.pageUp] = "[5~",
[apis.keys.pageDown] = "[6~",
[apis.keys.delete] = "[3~",
}
local special = specialKeyMap[charOrKey]
if special then fifo.push(special) end
end
elseif eventType == "keyReleased" then
if charOrKey == apis.keys.leftCtrl or charOrKey == apis.keys.rightCtrl then
ctrl = false
elseif charOrKey == apis.keys.leftAlt or charOrKey == apis.keys.rightAlt then
alt = false
end
elseif eventType == "keyTyped" then
if charOrKey then fifo.push(charOrKey) end
end
timeout = false
else
timeout = true
end
if timeout then
sleep(0.05)
end
end
end
newtty(apis.term, "1", fifo.pop)
for i,v in ipairs({peripheral.find("monitor")}) do
v.setTextScale(.5)
v.write("Initializing...")
newtty(v,tostring(i+1),function () end)
end

View File

@@ -1,26 +0,0 @@
local args={...}
local kernel=args[1]
local driver={}
driver.name="CCT Term Module"
driver.version="0.1.0"
driver.type="gpio"
driver.description="CCT redstone Module Kernel Module"
driver.arch="cct"
driver.author="HyperionOS Dev Team"
driver.license="MIT"
driver.api={}
function driver.load()
-- will
end
function driver.unload()
-- Nothing to unload
end
function driver.main()
-- Nothing to run
end
-- kernel.drivers.register(driver)

View File

@@ -0,0 +1,152 @@
--:Minify:--
-- CCT driver peripheral helper
local kernel=...
kernel.cct={}
kernel.cct.peripheral={}
local peripheral=kernel.cct.peripheral
local apis = kernel.apis
local native = apis.peripheral
local sides = {"top", "bottom", "left", "right", "front", "back"}
function peripheral.getNames()
local results = {}
for n = 1, #sides do
local side = sides[n]
if native.isPresent(side) then
table.insert(results, side)
if native.hasType(side, "peripheral_hub") then
local remote = native.call(side, "getNamesRemote")
for _, name in ipairs(remote) do
table.insert(results, name)
end
end
end
end
return results
end
function peripheral.isPresent(name)
if native.isPresent(name) then
return true
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return true
end
end
return false
end
function peripheral.getType(peripheral)
if type(peripheral) == "string" then
if native.isPresent(peripheral) then
return native.getType(peripheral)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
return native.call(side, "getTypeRemote", peripheral)
end
end
return nil
else
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return table.unpack(mt.types)
end
end
function peripheral.hasType(peripheral, peripheral_type)
if type(peripheral) == "string" then
if native.isPresent(peripheral) then
return native.hasType(peripheral, peripheral_type)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
return native.call(side, "hasTypeRemote", peripheral, peripheral_type)
end
end
return nil
else
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return mt.types[peripheral_type] ~= nil
end
end
function peripheral.getMethods(name)
if native.isPresent(name) then
return native.getMethods(name)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return native.call(side, "getMethodsRemote", name)
end
end
return nil
end
function peripheral.getName(peripheral)
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.name) ~= "string" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return mt.name
end
function peripheral.call(name, method, ...)
if native.isPresent(name) then
return native.call(name, method, ...)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return native.call(side, "callRemote", name, method, ...)
end
end
return nil
end
function peripheral.wrap(name)
local methods = peripheral.getMethods(name)
if not methods then
return nil
end
local types = { peripheral.getType(name) }
for i = 1, #types do types[types[i]] = true end
local result = setmetatable({}, {
__name = "peripheral",
name = name,
type = types[1],
types = types,
})
for _, method in ipairs(methods) do
result[method] = function(...)
return peripheral.call(name, method, ...)
end
end
return result
end
function peripheral.find(ty, filter)
local results = {}
for _, name in ipairs(peripheral.getNames()) do
if peripheral.hasType(name, ty) then
local wrapped = peripheral.wrap(name)
if filter == nil or filter(name, wrapped) then
table.insert(results, wrapped)
end
end
end
return table.unpack(results)
end

View File

@@ -0,0 +1,252 @@
--:Minify:--
local kernel = ...
local peripheral=kernel.cct.peripheral
local colors = {
[0xFFFFFF]=0x0001,
[0xFF0000]=0x0002,
[0x00FF00]=0x0004,
[0x0000FF]=0x0008,
[0x00FFFF]=0x0010,
[0xFF00FF]=0x0020,
[0xFFFF00]=0x0040,
[0xFF6D00]=0x0080,
[0x6DFF55]=0x0100,
[0x24FFFF]=0x0200,
[0x924900]=0x0400,
[0x6D6D55]=0x0800,
[0xDBDBAA]=0x1000,
[0x6D00FF]=0x2000,
[0xB6FF00]=0x4000,
[0x000000]=0x8000
}
local plt = {
0xFFFFFF,
0xFF0000,
0x00FF00,
0x0000FF,
0x00FFFF,
0xFF00FF,
0xFFFF00,
0xFF6D00,
0x6DFF55,
0x24FFFF,
0x924900,
0x6D6D55,
0xDBDBAA,
0x6D00FF,
0xB6FF00,
0x000000
}
local fg,bg=0x6D6D55,0x000000
local l1f,l1d,l2,ops={},{},{},0
local function findClosest(tbl, target)
local closest = nil
local smallestDiff = math.huge
for k, _ in pairs(tbl) do
if k==target then return k end
local diff = math.abs(k - target)
if diff < smallestDiff then
smallestDiff = diff
closest = k
end
end
return closest
end
local function aprox(c24)
ops = ops + 1
if ops % 1024 == 0 then
l1d = {}
l1f = {}
end
if ops % 8192 == 0 then
l2 = {}
end
if l2[c24] ~= nil then
return l2[c24]
end
if l1d[c24] ~= nil then
l1f[c24] = l1f[c24] + 1
if l1f[c24] >= 16 then
l2[c24] = l1d[c24]
l1d[c24] = nil
l1f[c24] = nil
return l2[c24]
end
return l1d[c24]
end
local closestKey = findClosest(colors, c24)
if not closestKey then return nil end
local value = colors[closestKey]
l1d[c24] = value
l1f[c24] = 1
return value
end
local function write(text, term)
local x, y = term.getCursorPos()
local w, h = term.getSize()
for i = 1, #text do
local c = text:sub(i, i)
if c == "\n" then
y = y + 1
x = 1
elseif c == "\t" then
local tabSize = 4
local spaces = tabSize - ((x - 1) % tabSize)
term.write(string.rep(" ", spaces))
x = x + spaces
elseif c == "\b" then
if x > 1 then
x = x - 1
term.setCursorPos(x, y)
term.write(" ")
term.setCursorPos(x, y)
end
else
if x <= w and y <= h then
term.setCursorPos(x, y)
term.write(c)
x = x + 1
end
end
if x > w then
x = 1
y = y + 1
end
if y - 1 >= h then
term.scroll(1)
y = h
term.setCursorPos(x, y)
end
end
term.setCursorPos(x, y)
end
kernel.devfs.data.tty={}
kernel.cct.ctrl,kernel.cct.alt = false, false
local function serializeBool(bool)
if bool then
return "T"
else
return "F"
end
end
local function newtty(obj, id, ev)
obj.setPaletteColor(0x1, 0xFFFFFF) -- #000000
obj.setPaletteColor(0x2, 0xFF0000) -- #FFFFFF
obj.setPaletteColor(0x4, 0x00FF00) -- #FF0000
obj.setPaletteColor(0x8, 0x0000FF) -- #00FF00
obj.setPaletteColor(0x10, 0x00FFFF) -- #0000FF
obj.setPaletteColor(0x20, 0xFF00FF) -- #00FFFF
obj.setPaletteColor(0x40, 0xFFFF00) -- #FF00FF
obj.setPaletteColor(0x80, 0xFF6D00) -- #FFFF00
obj.setPaletteColor(0x100, 0x6DFF55) -- #FF6D00
obj.setPaletteColor(0x200, 0x24FFFF) -- #6DFF55
obj.setPaletteColor(0x400, 0x924900) -- #24FFFF
obj.setPaletteColor(0x800, 0x6D6D55) -- #924900
obj.setPaletteColor(0x1000, 0xDBDBAA) -- #6D6D55
obj.setPaletteColor(0x2000, 0x6D00FF) -- #DBDBAA
obj.setPaletteColor(0x4000, 0xB6FF00) -- #6D00FF
obj.setPaletteColor(0x8000, 0x000000) -- #B6FF00
kernel.devfs.data["tty"][id] = function(op, mode)
if op=="type" then
return "Terminal"
elseif op=="open" then
local h = {
read=function(amount)
local rv=""
for i=1, amount or 1 do
local event = {ev()}
if event[1] then
rv=rv..event[1]
end
end
if rv=="" then rv=nil end
return rv
end,
write=function(content)
write(content, obj)
end,
size=function()
local s={obj.getSize()}
return table.concat(s,";")
end,
clear=function()
obj.clear()
obj.setCursorPos(1,1)
end,
gpos=function()
local s={obj.getCursorPos()}
return table.concat(s,";")
end,
spos=function(x,y)
return obj.setCursorPos(x,y)
end,
sfgc=function(c)
fg=c
return obj.setTextColor(aprox(c))
end,
sbgc=function(c)
bg=c
return obj.setBackgroundColor(aprox(c))
end,
gfgc=function()
return fg
end,
gbgc=function()
return bg
end,
gctrl=function()
return serializeBool(kernel.cct.ctrl)..";"..serializeBool(kernel.cct.alt)
end,
gplt=function()
return plt
end
}
if mode=="rw" then
return h
elseif mode=="r" then
h["write"]=nil
return h
elseif mode=="w" then
h["read"]=nil
return h
end
end
end
end
local fifo = kernel.newFifo()
kernel.cct.fifo=fifo
newtty(kernel.apis.term, "1", fifo.pop)
for i,v in ipairs({peripheral.find("monitor")}) do
v.setTextScale(.5)
v.write("Initializing...")
newtty(v,tostring(i+1),function () end)
end

View File

@@ -0,0 +1,86 @@
--:Minify:--
local kernel=...
local keys=kernel.apis.keys
kernel.processes.cctdeamon = function()
local timeout = false
while true do
local event = {kernel.EFI:getMachineEvent()}
if event[1] then
local eventType = event[1]
local charOrKey = event[3]
local ctrlKeyMap = {
[keys.a]=1, [keys.b]=2, [keys.c]=3,
[keys.d]=4, [keys.e]=5, [keys.f]=6,
[keys.g]=7, [keys.h]=8, [keys.i]=9,
[keys.j]=10, [keys.k]=11, [keys.l]=12,
[keys.m]=13, [keys.n]=14, [keys.o]=15,
[keys.p]=16, [keys.q]=17, [keys.r]=18,
[keys.s]=19, [keys.t]=20, [keys.u]=21,
[keys.v]=22, [keys.w]=23, [keys.x]=24,
[keys.y]=25, [keys.z]=26,
}
if eventType == "keyPressed" then
if charOrKey == keys.leftCtrl or charOrKey == keys.rightCtrl then
kernel.cct.ctrl = true
elseif charOrKey == keys.leftAlt or charOrKey == keys.rightAlt then
kernel.cct.alt = true
end
if kernel.cct.ctrl then
local ctrlByte = ctrlKeyMap[charOrKey]
if ctrlByte then
if ctrlByte == 3 then
for _, task in ipairs(syscall.getTasks()) do
syscall.sigsend(task, 1)
end
else
kernel.cct.fifo.push(string.char(ctrlByte))
end
end
else
local specialKeyMap = {
[keys.up] = "",
[keys.down] = "",
[keys.right] = "",
[keys.left] = "",
[keys.home] = "",
[keys["end"]] = "",
[keys.pageUp] = "[5~",
[keys.pageDown] = "[6~",
[keys.delete] = "[3~",
}
local special = specialKeyMap[charOrKey]
if special then kernel.cct.fifo.push(special) end
end
elseif eventType == "keyReleased" then
if charOrKey == keys.leftCtrl or charOrKey == keys.rightCtrl then
kernel.cct.ctrl = false
elseif charOrKey == keys.leftAlt or charOrKey == keys.rightAlt then
kernel.cct.alt = false
end
elseif eventType == "keyTyped" then
if charOrKey then kernel.cct.fifo.push(charOrKey) end
elseif eventType == "http_success" then
kernel.cct.httpqueue[event[2]]=nil
kernel.cct.httpresponse[event[2]]=event[3]
elseif eventType == "http_failure" then
kernel.cct.httpqueue[event[2]]=nil
kernel.cct.httperror[event[2]]=event[3]
end
timeout = false
else
timeout = true
end
if timeout then
sleep(0.05)
end
end
end

View File

@@ -0,0 +1,25 @@
--:Minify:--
local kernel=...
local rs=kernel.apis.rs
local sides = {top=1, bottom=2, left=3, right=4, front=5, back=6}
local function newGPIO(side)
return function(mode, data)
if mode=="w" then
if type(data)~="boolean" then error("data: expected bool") end
rs.setOutput(side, data)
elseif mode=="wa" then
if type(data)~="number" then error("data: expected bool") end
rs.setAnalogOutput(side, data)
elseif mode=="r" then
return rs.getInput(side)
elseif mode=="ra" then
return rs.getAnalogInput(side)
end
end
end
for side, alt in pairs(sides) do
local func=newGPIO(side)
kernel.gpio[side]=func
kernel.gpio[alt]=func
end

View File

@@ -1,14 +1,13 @@
--:Minify:--
local args = {...}
local apis = args[1]
local disks = args[2]
local arch = args[3]
local screen = args[5]
local computer = args[6]
local ifs = args[7]
local EFI=...
EFI.beep(440, 500)
local screen=EFI.screenCtl
local ifs=EFI.initfs
local disks=EFI.disks
local arch=EFI.architecture
local kernel = {}
kernel.LOG_Text=""
kernel.version="HyperionOS V1.2.3"
kernel.version="HyperionOS V1.2.4"
kernel.process = "Kernel"
kernel.users={[0]="root",[1]="User"}
kernel.hostname = "hyperion"
@@ -26,28 +25,31 @@ _G.sleep=nil
local windowsExp = false
function kernel.log(msg, level, c)
c=c or 12
kernel.LOG_Text = kernel.LOG_Text..string.format("%X",c-1).." "..tostring(computer:time()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n"
c=c or 0x6D6D6D
kernel.LOG_Text = kernel.LOG_Text..tostring(EFI:date()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n"
if kernel.status == "start" then
screen:setTextColor(c)
screen:print(tostring(computer:time()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg)
screen:print(tostring(EFI:date()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg)
elseif kernel.status == "term" then
kernel.standbyTask=kernel.currentTask
kernel.currentTask=kernel.kernelTask
kernel.vfs.devctl(1,"sfgc",c)
kernel.vfs.write(1,tostring(computer:time()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n")
local file=kernel.vfs.open("/dev/console", "w")
kernel.vfs.devctl(file,"sfgc",c)
kernel.vfs.write(file,tostring(EFI:date()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n")
kernel.vfs.close(file)
kernel.currentTask=kernel.standbyTask
end
end
function kernel.PANIC(msg)
if kernel.status~="Panic" then
kernel.log("PANIC: "..msg, "PANIC")
kernel.log("PANIC: "..msg, "PANIC", 0xFF0000)
pcall(kernel["saveLog"])
kernel.status="Panic"
kernel.reason=msg
screen:setTextColor(2)
screen:setBackgroundColor(16)
screen:enable()
screen:setTextColor(0xFF0000)
screen:setBackgroundColor(0x000000)
screen:clear()
screen:setCursorPos(1,1)
screen:print(kernel.LOG_Text)
@@ -56,18 +58,19 @@ function kernel.PANIC(msg)
kernel.exitMain = true
end
while true do
local event={computer:getMachineEvent()}
local event={EFI:getMachineEvent()}
if event[1]=="keyPressed" then
break
end
end
computer:reboot()
EFI.reboot=true
error("KERNEL PANIC")
end
kernel.panic=kernel.PANIC
if windowsExp then
screen:setTextColor(1)
screen:setBackgroundColor(4)
screen:setTextColor(0xFFFFFF)
screen:setBackgroundColor(0x0000FF)
screen:clear()
local w,h = screen:getSize()
screen:setCursorPos(3,5)
@@ -113,7 +116,7 @@ local split = function(str, delim, maxResultCountOrNil)
end
if not ifs.isFile("/boot/boot.cfg") then
kernel.log("First boot detected writing boot.cfg", "INFO", 3)
kernel.log("First boot detected writing boot.cfg", "INFO", 0x00FF00)
ifs.writeAllText("/boot/boot.cfg",ifs.readAllText("/boot/safeboot.cfg"))
kernel.firstBoot=true
end
@@ -130,24 +133,34 @@ if not initCfgStatus then
end
kernel.config = config
local skip=false
for i,v in ipairs(split(fstab,"\n")) do
if v:sub(1,1)=="U" then
local id=""
for i=3,#v do
if v:sub(i,i)==";" then
if i==3 then kernel.log("Invalid fstab line... Skipping.","WARN") goto endline end
if i==3 then kernel.log("Invalid fstab line... Skipping.","WARN", 0xFF8800) skip = true break end
id=v:sub(3,i-1)
end
end
local path=v:sub(#id+4)
ifs.mount(id,path)
::endline::
if not skip then
local path=v:sub(#id+4)
ifs.mount(id,path)
else
skip=false
end
end
end
kernel.log("Disks initialized")
function kernel.saveLog()
ifs.writeAllText("/var/log/syslog.log", kernel.LOG_Text)
if kernel.status=="running" then
local file = kernel.vfs.open("/var/log/syslog.log", "w")
kernel.vfs.write(file, kernel.LOG_Text)
kernel.vfs.close(file)
else
ifs.writeAllText("/var/log/syslog.log", kernel.LOG_Text)
end
end
function kernel.newFifo()
@@ -187,7 +200,7 @@ kernel.log("Gathering modules")
for _, i in ipairs(ifs.list("/lib/modules")) do
local modlist = ifs.list("/lib/modules/"..i)
if not modlist then
kernel.log("WARNING: could not list /lib/modules/"..i.." (skipping)", "WARN", 8)
kernel.log("WARNING: could not list /lib/modules/"..i.." (skipping)", "WARN", 0xFF8800)
else
for _,v in ipairs(modlist) do
local prior=tonumber(v:sub(1,2))
@@ -199,8 +212,8 @@ for _, i in ipairs(ifs.list("/lib/modules")) do
end
kernel.ifs=ifs
kernel.apis=apis
kernel.computer=computer
kernel.apis=EFI.firmware
kernel.EFI=EFI
kernel.arch=arch
kernel.initdisks=disks
kernel.screen=screen
@@ -229,16 +242,19 @@ kernel.kernelTask = {
kernel.currentTask = kernel.kernelTask
function kernel.shutdown()
kernel.computer:shutdown()
kernel.exitMain=true
kernel.status="shutdown"
end
function kernel.reboot()
kernel.computer:reboot()
kernel.exitMain=true
kernel.status="reboot"
end
kernel.syscalls["time"]=function() return kernel.computer:time() end
kernel.syscalls["time"]=function() return kernel.EFI:getEpochMs() end
kernel.syscalls["date"]=function() return kernel.EFI:date() end
kernel.syscalls["log"]=kernel.log
kernel.syscalls["getUptime"]=function() return kernel.computer:clock() end
kernel.syscalls["getUptime"]=function() return kernel.EFI:getUptime() end
kernel.syscalls["getUsername"]=function(uid) return kernel.users[uid or kernel.uid] end
kernel.syscalls["getHostname"]=function() return kernel.hostname end
kernel.syscalls["getHost"]=function() return kernel.apis._HOST end
@@ -252,36 +268,34 @@ kernel.syscalls["sysdump"]=function()
end
return rv
end
kernel.syscalls["reboot"]=function()
kernel.computer:reboot()
end
kernel.syscalls["shutdown"]=function()
kernel.computer:reboot()
end
kernel.syscalls["reboot"]=kernel.reboot
kernel.syscalls["shutdown"]=kernel.shutdown
kernel.log("Running modules")
for _,p in ipairs(modules) do
for _,v in ipairs(p) do
if kernel.config.showModLoad then kernel.log("Loading module "..v, "DBUG", 5) end
if kernel.config.showModLoad then kernel.log("Loading module "..v, "DBUG", 0x00FFFF) end
local code=ifs.readAllText(v)
if not code then
kernel.log("ModuReadErr: "..v, "WARN", 8)
goto skip
kernel.panic("Failed to read module "..v)
end
local func,err=load(code,"@"..v)
if not func then kernel.panic("ModuLoadErr: "..tostring(err)) goto skip end
if not func then kernel.panic("ModuLoadErr: "..tostring(err)) end
local status, err = xpcall(func,debug.traceback, kernel)
if not status then kernel.panic("ModuRunErr: "..tostring(err)) end
if kernel.config.showModLoad then kernel.log("Loaded module "..v, "DBUG", 5) end
::skip::
if kernel.config.showModLoad then kernel.log("Loaded module "..v, "DBUG", 0x00FFFF) end
end
end
kernel.log("Kernel initialized successfully.")
kernel.saveLog()
kernel.status="running"
screen:disable()
kernel.main()
if kernel.status=="panic" then
kernel.panic()
kernel.panic(kernel.reason)
end
kernel.PANIC("Execution complete")
if kernel.status=="reboot" then
EFI.reboot=true
return true
end

View File

@@ -7,5 +7,6 @@ return {
initPath = "/sbin/init",
maxOpenFiles = 128,
maxFilesPerTask = 16,
preempt=true
preempt=true,
logTaskExit=true
}

View File

@@ -499,7 +499,7 @@ local function checkperms(meta, mode)
local bitmap = {
r = {owner = 5, group = 3, everyone = 1},
w = {owner = 4, group = 2, everyone = 0},
a = {owner = 4, group = 2, everyone = 0},
a = {owner = 4, group = 2, everyone = 0}
}
local m = bitmap[mode]
if not m then error("EINVAL") end
@@ -544,7 +544,6 @@ local function newFileObj(handle, mode, path, meta, ftype)
end
function vfs.newfd(fdobj)
checkSystemLimit(); total = total + 1
local fd = allocFD(kernel.currentTask)
kernel.currentTask.fd[fd] = fdobj
return fd
@@ -555,8 +554,9 @@ function vfs.mount(target, diskOrId)
if _euid ~= 0 then error("EPERM") end
if not target then error("EINVAL") end
target = normalizeMountPoint(target)
if not vfs.exists(target) then vfs.mkdir(target) end
if vfs.type(target) ~= "directory" then error("EINVAL") end
local drive, path = resolvePath(target)
if not drive:directoryExists(path) then drive:makeDirectory(path) end
if drive:type(target) ~= "directory" then error("EINVAL") end
local disk, id
if type(diskOrId) == "string" then
@@ -594,6 +594,21 @@ function vfs.open(path, mode)
local fd = allocFD(task)
local disk, diskPath = resolvePath(path)
if not disk then error("NODISK") end
if (mode=="w" or mode=="a") and disk:isReadOnly() then error("ERDONLY") end
if kernel.unixSockets[normalizePath(path)] then
local meta = kernel.unixSockets[normalizePath(path)].meta
if kernel.uid~=0 or kernel.uid~=meta.owner then
local groups = (task and task.groups) or kernel.groups or {}
local access=false
for _, gid in ipairs(groups) do
if gid == meta.group then access=true end
end
if not access then error("EACCES") end
end
task[fd]=kernel.unixSockets[normalizePath(path)]
return fd
end
local meta = getFileMeta(path)
local isNew = (mode == "w" or mode == "a") and not disk:fileExists(diskPath)
@@ -695,10 +710,18 @@ function vfs.sendfile(outfd, infd, count)
end
function vfs.stat(path)
local disk, diskPath = resolvePath(path)
local meta = getFileMeta(path)
local ok, attrs = pcall(disk.attributes, disk, diskPath)
if not ok then attrs = { size=0, modified=0, created=0 } end
local attrs
local meta
if meta.etype == 0x02 then
attrs = { size=0, modified=0, created=0 }
else
local disk, diskPath = resolvePath(path)
meta = getFileMeta(path)
local ok
ok, attrs = pcall(disk.attributes, disk, diskPath)
if not ok then attrs = { size=0, modified=0, created=0 } end
end
return {
size = attrs.size,
modified = attrs.modified,
@@ -713,15 +736,15 @@ end
function vfs.lstat(path)
local meta = getFileMeta(path, true)
local attrs
if meta.etype == 0x01 then
if meta.etype == 0x01 or meta.etype == 0x02 then
attrs = { size=0, modified=0, created=0 }
else
local disk, diskPath = resolvePath(path, true)
local ok, a = pcall(disk.attributes, disk, diskPath)
attrs = ok and a or { size=0, modified=0, created=0 }
end
return {
size = attrs.size,
modified = attrs.modified,
@@ -738,8 +761,15 @@ end
function vfs.fstat(fd)
local file = kernel.currentTask.fd[fd]
if not file then error("EBADF") end
local disk, diskPath = resolvePath(file.path)
local attrs = disk:attributes(diskPath)
local attrs
if file.meta.etype == 0x02 then
attrs = { size=0, modified=0, created=0 }
else
local disk, diskPath = resolvePath(file.path, true)
local ok, a = pcall(disk.attributes, disk, diskPath)
attrs = ok and a or { size=0, modified=0, created=0 }
end
return {
size = attrs.size,
modified = attrs.modified,
@@ -768,6 +798,14 @@ function vfs.listdir(path)
end
end
for k,v in pairs(kernel.unixSockets) do
local p=normalizePath(path)
if k:match("^(.*)/[^/]+$")==p then
seen[v.name]=true
table.insert(out, v.name)
end
end
local mp
if diskPath == "/" then
mp = ".meta"
@@ -796,6 +834,7 @@ function vfs.mkdir(path)
local parentMeta = getFileMeta(parent)
checkperms(parentMeta, "w")
local disk, diskPath = resolvePath(path)
if disk:isReadOnly() then error("ERDONLY") end
disk:makeDirectory(diskPath)
local task = kernel.currentTask
local euid = (task and (task.euid or task.uid)) or kernel.uid
@@ -817,8 +856,13 @@ function vfs.remove(path)
local meta = getFileMeta(path, true)
if kernel.unixSockets and kernel.unixSockets[path] then
kernel.unixSockets[path] = nil
if kernel.unixSockets and kernel.unixSockets[normalizePath(path)] then
if kernel.uid ~= 0 then
if kernel.unixSockets[normalizePath(path)].meta.owner~=kernel.uid then
error("EACCES")
end
end
kernel.unixSockets[normalizePath(path)] = nil
end
if meta.etype == 0x01 then
@@ -827,6 +871,7 @@ function vfs.remove(path)
if parent == "" then parent = "/" end
local name = norm:match("[^/]+$")
local disk, parentDiskPath = resolveMount(parent)
if disk:isReadOnly() then error("ERDONLY") end
local mp
if parentDiskPath == "/" then mp = ".meta"
else mp = parentDiskPath:gsub("^/+", "") .. "/.meta" end
@@ -843,6 +888,7 @@ function vfs.remove(path)
if f2.close then f2.close() end
else
local disk, diskPath = resolvePath(path)
if disk:isReadOnly() then error("ERDONLY") end
disk:remove(diskPath)
end
end
@@ -851,6 +897,8 @@ function vfs.symlink(target, linkPath)
if type(target) ~= "string" or type(linkPath) ~= "string" then error("EINVAL") end
local norm = normalizePath(linkPath)
local parent = norm:match("^(.*)/[^/]+$") or "/"
local disk = resolveMount(linkPath)
if disk:isReadOnly() then error("ERDONLY") end
if parent == "" then parent = "/" end
local name = norm:match("[^/]+$")
if not name then error("EINVAL") end
@@ -880,7 +928,13 @@ function vfs.readlink(path)
end
function vfs.access(path, mode)
local meta = getFileMeta(path)
local meta
if kernel.unixSockets[normalizePath(path)] then
meta = kernel.unixSockets[normalizePath(path)].meta
else
meta = getFileMeta(path)
end
for i = 1, #mode do
checkperms(meta, mode:sub(i,i))
end
@@ -891,6 +945,8 @@ local function updateMeta(path, fn, noFollow)
local real = namei(path, noFollow)
local norm = real
local parent = norm:match("^(.*)/[^/]+$") or "/"
local disk = resolveMount(path)
if disk:isReadOnly() then error("ERDONLY") end
if parent == "" then parent = "/" end
local name = norm:match("[^/]+$")
if not name then error("EINVAL") end
@@ -917,6 +973,9 @@ local function updateMeta(path, fn, noFollow)
end
function vfs.chmod(path, perms)
if kernel.unixSockets[normalizePath(path)] then error("EINVAL") end
local disk = resolveMount(path)
if disk:isReadOnly() then error("ERDONLY") end
local meta = getFileMeta(path)
local euid = (kernel.currentTask and (kernel.currentTask.euid or kernel.currentTask.uid)) or kernel.uid
if euid ~= 0 and euid ~= meta.owner then error("EACCES") end
@@ -926,10 +985,14 @@ end
function vfs.fchmod(fd, perms)
local file = kernel.currentTask.fd[fd]
if not file then error("EBADF") end
if file.etype==0x02 then error("EINVAL") end
vfs.chmod(file.path, perms)
end
function vfs.chown(path, uid, gid)
if kernel.unixSockets[normalizePath(path)] then error("EINVAL") end
local disk = resolveMount(path)
if disk:isReadOnly() then error("ERDONLY") end
local _euid = (kernel.currentTask and (kernel.currentTask.euid or kernel.currentTask.uid)) or kernel.uid
if _euid ~= 0 then error("EPERM") end
updateMeta(path, function(e) e.owner = uid; e.group = gid end)
@@ -938,20 +1001,29 @@ end
function vfs.fchown(fd, uid, gid)
local file = kernel.currentTask.fd[fd]
if not file then error("EBADF") end
if file.etype==0x02 then error("EINVAL") end
vfs.chown(file.path, uid, gid)
end
function vfs.exists(path)
if kernel.unixSockets[normalizePath(path)] then return true end
local meta = getFileMeta(path, true)
if meta.etype == 0x01 then return true end
local ok, disk, diskPath = pcall(resolvePath, path)
if not ok then return false end
return disk:fileExists(diskPath)
if disk:type(diskPath) then
return true
else
return false
end
end
function vfs.type(path)
local meta = getFileMeta(path, true)
if meta.etype == 0x01 then return "symlink" end
if kernel.unixSockets[normalizePath(path)] then
return "socket"
end
local ok, disk, diskPath = pcall(resolvePath, path)
if not ok then return nil end
return disk:type(diskPath)

View File

@@ -50,7 +50,7 @@ function proxy:type(path, mode)
if type(step[steps[#steps]]) == "table" then
return "directory"
end
error("ENOENT")
error(type(step[steps[#steps]]))
end
function proxy:list(path)
@@ -140,6 +140,82 @@ function data.zero(op, mode)
end
end
if kernel.EFI:getEEPROM() then
function data.eeprom(op, mode)
if op=="type" then
return "character device"
elseif op=="open" then
if mode=="r" then
local ptr,eeprom=1,kernel.EFI:getEEPROM()
return {
read=function(amount)
ptr=ptr+amount
return eeprom:sub(ptr-amount, ptr)
end
}
elseif mode=="w" then
if kernel.uid~=0 then error("EACCES") end
local firstwrite=true
return {
write=function(data)
if firstwrite then
kernel.EFI:setEEPROM(data)
else
kernel.EFI:setEEPROM(kernel.EFI:getEEPROM()..data)
end
end
}
elseif mode=="a" then
if kernel.uid~=0 then error("EACCES") end
return {
write=function(data)
kernel.EFI:setEEPROM(kernel.EFI:getEEPROM()..data)
end
}
else error("EACCES")
end
end
end
end
if kernel.EFI:getNvram() then
function data.nvram(op, mode)
if op=="type" then
return "character device"
elseif op=="open" then
if mode=="r" then
local ptr,nvram=1,kernel.EFI:getNvram()
return {
read=function(amount)
ptr=ptr+amount
return nvram:sub(ptr-amount, ptr)
end
}
elseif mode=="w" then
if kernel.uid~=0 then error("EACCES") end
local firstwrite=true
return {
write=function(data)
if firstwrite then
kernel.EFI:setNvram(data)
else
kernel.EFI:setNvram(kernel.EFI:getNvram()..data)
end
end
}
elseif mode=="a" then
if kernel.uid~=0 then error("EACCES") end
return {
write=function(data)
kernel.EFI:setNvram(kernel.EFI:getNvram()..data)
end
}
else error("EACCES")
end
end
end
end
data["disk"]={}
kernel.devfs={}
kernel.devfs.data=data

View File

@@ -6,7 +6,7 @@ local data = {}
proxy.address = "procfs0000"
proxy.isvirt = true
proxy.isReadOnly = function() return false end
proxy.isReadOnly = function() return true end
proxy.spaceUsed = function() return 0 end
proxy.spaceTotal = function() return 0 end
proxy.makeDirectory = function() error("EACCES") end
@@ -132,6 +132,17 @@ function proxy:open(path, mode)
if type(step[steps[#steps]]) == "function" then
return step[steps[#steps]]("open", mode)
end
elseif tostring(steps[1])=="self" then
local task=kernel.currentTask
local step = newtaskproxy(task)
for i=2, #steps-1 do
local dat = step[steps[i]]
if type(dat) ~= "table" then error("ENFILE") end
step=dat
end
if type(step[steps[#steps]]) == "function" then
return step[steps[#steps]]("open", mode)
end
else
for i=1, #steps-1 do
local dat = step[steps[i]]
@@ -166,6 +177,21 @@ function proxy:type(path, mode)
if type(step[steps[#steps]]) == "table" then
return "directory"
end
elseif tostring(steps[1])=="self" then
local task=kernel.currentTask
if #steps==1 then return "directory" end
local step = newtaskproxy(task)
for i=2, #steps-1 do
local dat = step[steps[i]]
if type(dat) ~= "table" then error("ENFILE") end
step=dat
end
if type(step[steps[#steps]]) == "function" then
return step[steps[#steps]]("type", mode)
end
if type(step[steps[#steps]]) == "table" then
return "directory"
end
else
for i=1, #steps-1 do
local dat = step[steps[i]]
@@ -186,7 +212,7 @@ function proxy:list(path)
local steps = kernel.vfs.splitPath(path)
local step = data
if #steps == 0 then
return table.merge(table.keys(data),table.keys(kernel.tasks))
return table.merge(table.keys(data),table.keys(kernel.tasks),{"self"})
end
if tonumber(steps[1]) then
local task=kernel.tasks[steps[1]]
@@ -200,6 +226,18 @@ function proxy:list(path)
if type(step[steps[#steps]]) == "table" then
return table.keys(step[steps[#steps]])
end
elseif tostring(steps[1])=="self" then
local task=kernel.currentTask
local step = newtaskproxy(task)
if #steps==1 then return table.keys(step) end
for i=2, #steps-1 do
local dat = step[steps[i]]
if type(dat) ~= "table" then error("ENOENT") end
step=dat
end
if type(step[steps[#steps]]) == "table" then
return table.keys(step[steps[#steps]])
end
else
for i=1, #steps-1 do
local dat = step[steps[i]]
@@ -220,7 +258,7 @@ function proxy:fileExists(path)
return ok
end
data.uptime=simpleFile(function()return tostring(kernel.computer:getUptime())end,function()error("EACCES")end)
data.uptime=simpleFile(function()return tostring(kernel.EFI:getUptime())end,function()error("EACCES")end)
kernel.procfs={}
kernel.procfs.data=data
kernel.procfs.proxy=proxy

View File

@@ -21,7 +21,7 @@ for _, line in ipairs(string.split(kernel.fstab, "\n")) do
end
if not semicolon_pos or semicolon_pos == 3 then
kernel.log("Invalid fstab line: "..line.." ... Skipping.", "WARN", 8)
kernel.log("Invalid fstab line: "..line.." ... Skipping.", "WARN", 0xFF8800)
else
local id = line:sub(3, semicolon_pos - 1)
local path = trim(line:sub(semicolon_pos + 1))

View File

@@ -12,13 +12,24 @@ function signal.sigsend(pid, sig)
end
function signal.sigcatch(handler)
kernel.currentTask.sigh=handler
if not kernel.currentTask.sigq then kernel.currentTask.sigq={} end
local task=kernel.currentTask
task.sigh=handler
if not task.sigq then task.sigq={} end
local handle={
error="",
active=true
}
if task.sigd then task.sigd.active=false; end
task.sigd=handle
return handle
end
function signal.sigignore()
kernel.currentTask.sigh=nil
kernel.currentTask.sigq=nil
local task=kernel.currentTask
task.sigh=nil
task.sigq=nil
if task.sigd then task.sigd.active=false end
task.sigd=nil
end
local s=kernel.syscalls

View File

@@ -2,10 +2,7 @@
-- Supports:
-- AF_UNIX - local IPC via /var/run/*.sock paths
-- AF_INET - network sockets with three backends:
-- rednet://0.0.B.C or rednet+PROTO://0.0.B.C -> CC rednet (computer B*256+C)
-- modem://0.0.B.C -> raw CC modem frames
-- http://host/path or https://... -> HTTP via CC http API
-- A.B.C.D (dotted quad, non-zero A) -> HTTP
-- Implemented by drivers but expect http:// and https://
--
-- Socket lifecycle:
-- fd = syscall.socket(domain, socktype) -- "unix"/"inet", "stream"/"dgram"
@@ -18,539 +15,44 @@
-- syscall.sockshutdown(fd) -- half-close send side
-- -- normal vfs.close(fd) closes the socket
local kernel = ...
local kernel=...
local socket={}
socket.handlers={}
kernel.socket=socket
local sockets = {}
local unixSocks = {}
local nextSockId = 1
local function allocSockId()
local id = nextSockId
nextSockId = nextSockId + 1
return id
function socket.registerProtocal(protocal, handler)
socket.handlers[protocal] = handler
end
local function parseAddress(addr)
if not addr then error("EINVAL") end
function socket.socket()
local P=kernel.vfs.P
local data=kernel.newFifo()
local isClosed=false
kernel.vfs.newfd({
handle={
read=function() if isClosed then error("ECCON") end return data.read() end,
write=function() if isClosed then error("ECCON") end return data.write() end,
close=function() isClosed = true end
},
type="socket",
refcount=1,
if addr:sub(1,1) == "/" or addr:sub(1,5) == "unix:" then
local path = addr:sub(1,5) == "unix:" and addr:sub(6) or addr
return { backend="unix", path=path }
end
local rproto, raddr = addr:match("^rednet%+?([^:/]*)://(.+)$")
if raddr then
local a,b,c,d = raddr:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)$")
if not a then error("EINVAL: bad rednet address " .. raddr) end
local compId = tonumber(c)*256 + tonumber(d)
return { backend="rednet", compId=compId,
protocol=(rproto ~= "" and rproto or "hyperion") }
end
local maddr = addr:match("^modem://(.+)$")
if maddr then
local a,b,c,d = maddr:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)$")
if not a then error("EINVAL: bad modem address " .. maddr) end
local compId = tonumber(c)*256 + tonumber(d)
local port = tonumber(maddr:match(":(%d+)$")) or 0
return { backend="modem", compId=compId, port=port }
end
local scheme, rest = addr:match("^(https?)://(.+)$")
if scheme then
return { backend=scheme, url=addr }
end
local a,b,c,d = addr:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)")
if a and tonumber(a) ~= 0 then
return { backend="http", url="http://" .. addr }
end
error("EINVAL: unrecognised address format: " .. tostring(addr))
end
local rednetOpen = false
local function ensureRednet()
if rednetOpen then return end
local rn = kernel.apis and kernel.apis.rednet
if not rn then error("ENODEV: no rednet API available") end
local peripheral = kernel.apis.peripheral
if peripheral then
for _, name in ipairs(peripheral.getNames and peripheral.getNames() or {}) do
if peripheral.getType(name) == "modem" then
pcall(rn.open, name)
end
end
end
rednetOpen = true
end
local function getModem()
local peripheral = kernel.apis and kernel.apis.peripheral
if not peripheral then error("ENODEV") end
for _, name in ipairs(peripheral.getNames and peripheral.getNames() or {}) do
if peripheral.getType(name) == "modem" then
local m = peripheral.wrap(name)
if m then return m, name end
end
end
error("ENODEV: no modem peripheral found")
end
local function pumpEvents()
local ev = kernel.computer:getMachineEvent()
while ev do
if ev == "rednet_message" then
for _, sock in pairs(sockets) do
if sock.backend == "rednet" and sock.bound then
if sock.address.protocol == tostring(select(4, table.unpack({ev}))) or
sock.address.protocol == "hyperion" then
end
end
end
end
ev = kernel.computer:getMachineEvent()
end
end
local function pollEvent()
local results = table.pack(kernel.computer:getMachineEvent())
if results.n == 0 or results[1] == nil then return nil end
return results
end
local function dispatchEvent(ev)
if not ev then return end
local evtype = ev[1]
if evtype == "rednet_message" then
local senderId = ev[2]
local message = ev[3]
local protocol = ev[4] or "hyperion"
for _, sock in pairs(sockets) do
if sock.backend == "rednet" and (sock.listening or sock.connected) then
if sock.address and sock.address.protocol == protocol then
table.insert(sock.rxbuf, { from=senderId, data=message })
end
end
end
elseif evtype == "modem_message" then
local channel = ev[3]
local msg = ev[5]
local fromCh = ev[4]
for _, sock in pairs(sockets) do
if sock.backend == "modem" and sock.modemChannel == channel then
table.insert(sock.rxbuf, { from=fromCh, data=msg })
end
end
elseif evtype == "http_success" then
local url = ev[2]
local handle = ev[3]
for _, sock in pairs(sockets) do
if sock.backend == "http" or sock.backend == "https" then
if sock.pendingUrl == url then
local body = handle.readAll and handle.readAll() or ""
handle.close()
table.insert(sock.rxbuf, { data=body, done=true })
sock.pendingUrl = nil
sock.connected = true
end
end
end
elseif evtype == "http_failure" then
local url = ev[2]
local err = ev[3]
for _, sock in pairs(sockets) do
if (sock.backend == "http" or sock.backend == "https") and
sock.pendingUrl == url then
sock.error = err
sock.pendingUrl = nil
end
end
end
end
local function pumpAll()
local ev = pollEvent()
while ev do
dispatchEvent(ev)
ev = pollEvent()
end
end
local function newSocket(domain, socktype)
local sock = {
id = allocSockId(),
domain = domain, -- "unix" | "inet"
socktype = socktype, -- "stream" | "dgram"
backend = nil,
state = "idle", -- idle | bound | listening | connected | closed
rxbuf = {},
txbuf = {},
backlog = {},
address = nil,
peer = nil,
modemChannel = nil,
modem = nil,
pendingUrl = nil,
bound = false,
listening = false,
connected = false,
error = nil,
}
sockets[sock.id] = sock
return sock
end
local sockSend, sockClose
local function socketToFd(sock)
return {
isSocket = true,
sockId = sock.id,
mode = "rw",
meta = { etype=0, owner=0, group=0, perms=0x1FF, cmeta="" },
type = "socket",
refcount = 1,
handle = {
read = function(count)
pumpAll()
if #sock.rxbuf == 0 then return "" end
local item = table.remove(sock.rxbuf, 1)
local data = type(item) == "table" and (item.data or "") or tostring(item)
if count and #data > count then
table.insert(sock.rxbuf, 1, { data=data:sub(count+1), from=item.from })
data = data:sub(1, count)
end
return data
end,
write = function(data)
if sock.state == "closed" then error("EBADF") end
return sockSend(sock, data)
end,
close = function()
sockClose(sock)
end,
}
}
end
sockSend = function(sock, data)
if sock.backend == "unix" then
local peer = sock.peer
if not peer then error("ENOTCONN") end
table.insert(peer.rxbuf, { data=data })
return #data
elseif sock.backend == "rednet" then
ensureRednet()
local rn = kernel.apis.rednet
rn.send(sock.address.compId, data, sock.address.protocol)
return #data
elseif sock.backend == "modem" then
local modem = sock.modem
if not modem then error("ENOTCONN") end
modem.transmit(sock.address.port, sock.modemChannel or 0, data)
return #data
elseif sock.backend == "http" or sock.backend == "https" then
local http = kernel.apis and kernel.apis.http
if not http then error("ENODEV: no http API") end
local url = sock.address.url
local ok, err = pcall(http.request, url, data, {
["Content-Type"] = "application/octet-stream"
})
if not ok then error("ENETDOWN: " .. tostring(err)) end
sock.pendingUrl = url
return #data
end
error("EPROTONOSUPPORT")
end
sockClose = function(sock)
if sock.state == "closed" then return end
sock.state = "closed"
if sock.backend == "unix" then
if sock.peer then
sock.peer.peer = nil
sock.peer.state = "closed"
end
if sock.bound and sock.address and sock.address.path then
unixSocks[sock.address.path] = nil
end
elseif sock.backend == "modem" and sock.modem and sock.modemChannel then
pcall(sock.modem.close, sock.modemChannel)
elseif sock.backend == "rednet" then
end
sockets[sock.id] = nil
end
kernel.syscalls["socket"] = function(domain, socktype)
domain = domain or "inet"
socktype = socktype or "stream"
if domain ~= "unix" and domain ~= "inet" then error("EAFNOSUPPORT") end
if socktype ~= "stream" and socktype ~= "dgram" then error("EPROTOTYPE") end
local sock = newSocket(domain, socktype)
local fdobj = socketToFd(sock)
local fd = kernel.vfs.newfd(fdobj)
return fd
end
kernel.syscalls["bind"] = function(fd, address)
local task = kernel.currentTask
local fdobj = task.fd[fd]
if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end
local sock = sockets[fdobj.sockId]
if not sock then error("EBADF") end
if sock.bound then error("EINVAL") end
local parsed = parseAddress(address)
if parsed.backend == "unix" then
local existing = unixSocks[parsed.path]
if existing then
if existing.state == "closed" then
unixSocks[parsed.path] = nil
else
error("EADDRINUSE")
end
end
sock.backend = "unix"
sock.address = parsed
sock.bound = true
sock.state = "bound"
unixSocks[parsed.path] = sock
elseif parsed.backend == "rednet" then
ensureRednet()
sock.backend = "rednet"
sock.address = parsed
sock.bound = true
sock.state = "bound"
elseif parsed.backend == "modem" then
local modem, side = getModem()
sock.backend = "modem"
sock.address = parsed
sock.modem = modem
sock.modemChannel = parsed.port
sock.bound = true
sock.state = "bound"
modem.open(parsed.port)
else
error("EOPNOTSUPP: cannot bind to " .. parsed.backend .. " address")
end
end
kernel.syscalls["listen"] = function(fd, backlog)
local task = kernel.currentTask
local fdobj = task.fd[fd]
if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end
local sock = sockets[fdobj.sockId]
if not sock then error("EBADF") end
if not sock.bound then error("EDESTADDRREQ") end
sock.listening = true
sock.state = "listening"
sock.maxBacklog = backlog or 5
end
kernel.syscalls["accept"] = function(fd)
local task = kernel.currentTask
local fdobj = task.fd[fd]
if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end
local sock = sockets[fdobj.sockId]
if not sock then error("EBADF") end
if not sock.listening then error("EINVAL") end
local deadline = kernel.computer:time() + 30000
while #sock.backlog == 0 do
pumpAll()
if kernel.computer:time() > deadline then error("ETIMEDOUT") end
coroutine.yield()
end
local clientSock = table.remove(sock.backlog, 1)
local cfdobj = socketToFd(clientSock)
local newfd = kernel.vfs.newfd(cfdobj)
return newfd
end
kernel.syscalls["connect"] = function(fd, address)
local task = kernel.currentTask
local fdobj = task.fd[fd]
if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end
local sock = sockets[fdobj.sockId]
if not sock then error("EBADF") end
if sock.connected then error("EISCONN") end
local parsed = parseAddress(address)
sock.address = parsed
sock.backend = parsed.backend
if parsed.backend == "unix" then
local server = unixSocks[parsed.path]
if not server then error("ECONNREFUSED") end
if not server.listening then error("ECONNREFUSED") end
if #server.backlog >= (server.maxBacklog or 5) then error("ECONNREFUSED") end
local serverPeer = newSocket("unix", sock.socktype)
serverPeer.backend = "unix"
serverPeer.connected = true
serverPeer.state = "connected"
serverPeer.peer = sock
sock.peer = serverPeer
sock.connected = true
sock.state = "connected"
table.insert(server.backlog, serverPeer)
elseif parsed.backend == "rednet" then
ensureRednet()
sock.connected = true
sock.state = "connected"
elseif parsed.backend == "modem" then
local modem, side = getModem()
local replyChannel = math.random(1024, 65534)
sock.modem = modem
sock.modemChannel = replyChannel
sock.connected = true
sock.state = "connected"
modem.open(replyChannel)
elseif parsed.backend == "http" or parsed.backend == "https" then
sock.connected = true
sock.state = "connected"
else
error("EAFNOSUPPORT")
end
end
kernel.syscalls["send"] = function(fd, data)
local task = kernel.currentTask
local fdobj = task.fd[fd]
if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end
local sock = sockets[fdobj.sockId]
if not sock then error("EBADF") end
return sockSend(sock, data)
end
kernel.syscalls["recv"] = function(fd, maxlen, timeout_ms)
local task = kernel.currentTask
local fdobj = task.fd[fd]
if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end
local sock = sockets[fdobj.sockId]
if not sock then error("EBADF") end
local deadline = kernel.computer:time() + (timeout_ms or 10000)
while #sock.rxbuf == 0 do
pumpAll()
if #sock.rxbuf > 0 then break end
if sock.state == "closed" or sock.error then
if sock.error then error("ECONNRESET: " .. tostring(sock.error)) end
return ""
end
if kernel.computer:time() > deadline then return "" end
coroutine.yield()
end
local item = table.remove(sock.rxbuf, 1)
local data = type(item) == "table" and (item.data or "") or tostring(item)
if maxlen and #data > maxlen then
table.insert(sock.rxbuf, 1, { data=data:sub(maxlen+1), from=item and item.from })
data = data:sub(1, maxlen)
end
return data
end
kernel.syscalls["sockshutdown"] = function(fd)
local task = kernel.currentTask
local fdobj = task.fd[fd]
if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end
local sock = sockets[fdobj.sockId]
if sock then sockClose(sock) end
end
kernel.syscalls["getpeername"] = function(fd)
local task = kernel.currentTask
local fdobj = task.fd[fd]
if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end
local sock = sockets[fdobj.sockId]
if not sock or not sock.connected then error("ENOTCONN") end
if sock.address then return sock.address end
return nil
end
kernel.syscalls["getsockname"] = function(fd)
local task = kernel.currentTask
local fdobj = task.fd[fd]
if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end
local sock = sockets[fdobj.sockId]
if not sock then error("EBADF") end
return sock.address
end
kernel.syscalls["httpget"] = function(url, headers)
local http = kernel.apis and kernel.apis.http
if not http then error("ENODEV: no http API") end
local ok, err = pcall(http.request, url, nil, headers)
if not ok then error("ENETDOWN: " .. tostring(err)) end
local deadline = kernel.computer:time() + 15000
while true do
local ev = pollEvent()
if ev then
if ev[1] == "http_success" and ev[2] == url then
local handle = ev[3]
local body = handle.readAll and handle.readAll() or ""
handle.close()
return body
elseif ev[1] == "http_failure" and ev[2] == url then
error("ECONNREFUSED: " .. tostring(ev[3]))
else
dispatchEvent(ev)
end
end
if kernel.computer:time() > deadline then error("ETIMEDOUT") end
coroutine.yield()
end
end
kernel.syscalls["resolve"] = function(hostname)
if hostname:match("^%d+%.%d+%.%d+%.%d+$") then return hostname end
local a,b,c,d = hostname:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)$")
if a and tonumber(a) == 0 and tonumber(b) == 0 then
return hostname
end
local http = kernel.apis and kernel.apis.http
if not http then error("ENODEV: no http API for DNS") end
local url = "https://cloudflare-dns.com/dns-query?name=" .. hostname .. "&type=A"
local body = kernel.syscalls["httpget"](url, {
["Accept"] = "application/dns-json"
meta={
owner=kernel.currentTask.uid,
group=kernel.currentTask.uid,
etype=2,
perms=P.OWNER_R+P.OWNER_W+P.GROUP_R+P.GROUP_W
},
isvirt=true
})
local ip = body:match('"type":1[^}]*"data":"([%d%.]+)"')
if not ip then error("ENOENT: could not resolve " .. hostname) end
return ip
end
kernel.sockets = sockets
kernel.unixSockets = unixSocks
function socket.connect(fd, address)
end
function socket.listen(fd, backlog)
end
kernel.log("Loaded socket module")

View File

@@ -0,0 +1,3 @@
--:Minify:--
local kernel=...
kernel.unixSockets={}

View File

@@ -139,7 +139,7 @@ end
if not blake2s then error("Failed to load blake2s") end
if not kernel.vfs.exists("/etc/pam.d/secret") then
kernel.log("PAM SECRET REGENERATING PLEASE USE ROOT")
kernel.log("PAM SECRET REGENERATING PLEASE USE ROOT", "WARN", 0xFF8800)
local key = ""
for i = 1, 256 do key = key .. string.char(math.random(0, 255)) end
local handle = kernel.vfs.open("/etc/pam.d/secret", "w")
@@ -150,16 +150,11 @@ end
local pepper = getFile("/etc/pam.d/secret")
local function genSalt()
local chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./"
local s = ""
for i = 1, 16 do
s = s .. chars:sub(math.random(1, #chars), math.random(1, #chars))
end
return s
return toHex(math.random(0,2^32))
end
local function hashPassword(password, salt)
local key = (pepper .. salt):sub(1, 32)
local key = (pepper .. salt)
return blake2s(password, key)
end
@@ -236,19 +231,18 @@ local function nextUID()
return max + 1
end
function auth.login(username, password)
if type(username) ~= "string" or type(password) ~= "string" then
function auth.login(uid, password)
if type(uid) ~= "number" or type(password) ~= "string" then
return nil, "Authentication failure"
end
local entry = getPasswdByUsername(username)
local entry = getPasswdByUID(uid)
if not entry then
-- timing attack resistance
hashPassword(password, "aaaaaaaaaaaaaaaa")
return nil, "Authentication failure"
end
local uid = tonumber(entry[1])
local sEntry = getShadowByUID(uid)
if not sEntry then
hashPassword(password, "aaaaaaaaaaaaaaaa")
@@ -273,7 +267,7 @@ function auth.login(username, password)
_task.egid = tonumber(entry[2]) or uid
end
kernel.log("AUTH: login uid=" .. tostring(uid) .. " (" .. username .. ")")
kernel.log("AUTH: login uid=" .. tostring(uid) .. " (" .. getPasswdByUID(uid)[3] .. ")")
return true
end
@@ -619,4 +613,4 @@ if kernel.syscalls then
kernel.syscalls["setshell"] = auth.setShell
kernel.syscalls["sethomedir"] = auth.setHomedir
kernel.syscalls["setgid"] = auth.setGID
end
end

View File

@@ -41,11 +41,11 @@ local function createTask(func, name, envars, args, tgid, real_uid, eff_uid)
if kernel.config.logTaskExit then
if not ok then
kernel.log("Task " .. tostring(id) .. " exited with err: " .. tostring(err), "ERROR", 2)
kernel.log("Task " .. tostring(id) .. " exited with err: " .. tostring(err), "ERROR", 0xFF0000)
elseif err then
kernel.log("Task " .. tostring(id) .. " exited with code: " .. tostring(err), "INFO")
kernel.log("Task " .. tostring(id) .. " exited with code: " .. tostring(err), "DBUG", 0x00FFFF)
else
kernel.log("Task " .. tostring(id) .. " exited without code", "INFO")
kernel.log("Task " .. tostring(id) .. " exited without code", "DBUG", 0x00FFFF)
end
end
@@ -110,7 +110,7 @@ function sys.execspawn(path, name, envars, args, tgid)
kernel.log(
"execspawn: suid exec '" .. path ..
"' caller_uid=" .. tostring(real_uid) ..
" -> euid=" .. tostring(euid), "INFO"
" -> euid=" .. tostring(euid)
)
end
@@ -136,9 +136,9 @@ function sys.exec(path, args, envars)
local ok, err = xpcall(func, debug.traceback, table.unpack(task.args))
if kernel.config.logTaskExit then
if not ok then
kernel.log("Task " .. tostring(task.pid) .. " exec '" .. path .. "' err: " .. tostring(err), "ERROR", 2)
kernel.log("Task " .. tostring(task.pid) .. " exec '" .. path .. "' err: " .. tostring(err), "ERROR", 0xFF0000)
else
kernel.log("Task " .. tostring(task.pid) .. " exec '" .. path .. "' exited: " .. tostring(err), "INFO")
kernel.log("Task " .. tostring(task.pid) .. " exec '" .. path .. "' exited: " .. tostring(err), "DBUG", 0x00FFFF)
end
end
if type(err) == "number" then tasks[tostring(task.pid)].exit = err end
@@ -155,8 +155,7 @@ end
function sys.sleep(s)
kernel.currentTask.status = "S"
kernel.currentTask.sleep = kernel.computer:time() + s * 1000
coroutine.yield()
kernel.currentTask.sleep = kernel.EFI:getEpochMs() + s * 1000
end
function sys.getTask(pid)
@@ -260,9 +259,9 @@ function sys.exit(code)
local task = kernel.currentTask
if kernel.config.logTaskExit then
if code then
kernel.log("Task " .. tostring(task.pid) .. " exited with code: " .. tostring(code), "INFO")
kernel.log("Task " .. tostring(task.pid) .. " exited with code: " .. tostring(code), "DBUG", 0x00FFFF)
else
kernel.log("Task " .. tostring(task.pid) .. " exited without code", "INFO")
kernel.log("Task " .. tostring(task.pid) .. " exited without code", "DBUG", 0x00FFFF)
end
end
tasks[tostring(task.pid)].status = "Z"
@@ -303,9 +302,9 @@ local function reapDeadTasks()
task.syscallReturn = nil
task.sleep = nil
task.fd = nil
task.reapTime = kernel.computer:time() + 30000
task.reapTime = kernel.EFI:getEpochMs() + 30000
elseif task.reapTime and kernel.computer:time() > task.reapTime
elseif task.reapTime and kernel.EFI:getEpochMs() > task.reapTime
and task.status == "Z" then
for _, child in ipairs(task.children) do
child.parent = tasks["1"]
@@ -343,55 +342,61 @@ function kernel.main()
local taskTimes = {}
for pid, task in pairs(tasks) do
if task.status == "S" and kernel.computer:time() >= task.sleep then
kernel.currentTask = task
kernel.uid = task.euid or task.uid
kernel.process = task.name
if task.status == "S" and kernel.EFI:getEpochMs() >= task.sleep then
task.status = "R"
task.sleep = 0
end
if task.status == "R" then
kernel.currentTask = task
if task.status == "D" then
if task.ksh then
coroutine.resume(task.ksh)
end
end
kernel.uid = task.euid or task.uid
kernel.process = task.name
if task.status == "R" then
N = N + 1
task.timeSlice = math.min(Tmax, math.max(Tmin, B / (N ^ alpha)))
if task.sigq and #task.sigq ~= 0 and task.sigh then
local coro = coroutine.create(task.sigh)
local sigret = { coroutine.resume(coro, table.remove(task.sigq, 1)) }
while coroutine.status(coro) ~= "dead" do
if sigret[1] == false then break end
if sigret[2] == "syscall" then
local scname = sigret[3]
local sysret
if kernel.syscalls[scname] then
sysret = { xpcall(kernel.syscalls[scname], debug.traceback, table.unpack(sigret, 4)) }
else
sysret = { false, "Unknown syscall: " .. tostring(scname) }
end
if not sysret[1] then
sigret = { coroutine.resume(coro, false, sysret[2]) }
else
sigret = { coroutine.resume(coro, true, table.unpack(sysret, 2)) }
end
else
sigret = { coroutine.resume(coro) }
local status,err=coroutine.resumeWithTimeout(coro, 100, table.remove(task.sigq, 1))
if status=="error" then
task.sigd.error=err
task.sigd.active=false
task.sigh=nil
task.sigq=nil
task.sigd=nil
elseif status=="success" then
if err=="syscall" then
task.sigd.error="Cannot execute syscalls from signals"
task.sigd.active=false
task.sigh=nil
task.sigq=nil
task.sigd=nil
end
end
end
if task.status == "R" then
local startTime = kernel.computer:time()
local startTime = kernel.EFI:getEpochMs()
local ret
if kernel.config.preempt then
ret = { resumeWithTimeout(task.coro, task.timeSlice, table.unpack(task.syscallReturn)) }
if not task.debugger then
ret = { resumeWithTimeout(task.coro, task.timeSlice, table.unpack(task.syscallReturn)) }
else
ret = { coroutine.resume(task.coro, table.unpack(task.syscallReturn)) }
end
else
ret = { coroutine.resume(task.coro, table.unpack(task.syscallReturn)) }
end
local elapsed = kernel.computer:time() - startTime
local elapsed = kernel.EFI:getEpochMs() - startTime
task.lastTime = elapsed
task.totalTime = (task.totalTime or 0) + elapsed
task.numRuns = (task.numRuns or 0) + 1
@@ -403,7 +408,7 @@ function kernel.main()
if elapsed >= Tmax then Tmax_hit = Tmax_hit + 1 end
if ret[1] == "error" or ret[1] == false then
kernel.log("processHandlerException: " .. tostring(ret[2]), "ERROR", 2)
kernel.log("processHandlerException: " .. tostring(ret[2]), "ERROR", 0xFF0000)
task.status = "Z"
task.exit = "processHandlerException: " .. tostring(ret[2])
@@ -418,9 +423,9 @@ function kernel.main()
local scname = ret[3]
if kernel.syscalls[scname] then
if kernel.config.debugSyscalls then
kernel.log("Task " .. task.pid .. " syscall: " .. scname, "DBUG", 5)
kernel.log("Task " .. task.pid .. " syscall: " .. scname, "DBUG", 0x00FFFF)
for i = 4, #ret do
kernel.log(" inval[" .. (i-3) .. "] = " .. tostring(ret[i]), "DBUG", 5)
kernel.log(" inval[" .. (i-3) .. "] = " .. tostring(ret[i]), "DBUG", 0x00FFFF)
end
end
@@ -428,12 +433,12 @@ function kernel.main()
if kernel.config.debugSyscalls then
if not sysret[1] then
kernel.log("Task " .. task.pid .. " syscall " .. scname .. " failed: " .. tostring(sysret[2]), "ERROR", 2)
kernel.log("Task " .. task.pid .. " syscall " .. scname .. " failed: " .. tostring(sysret[2]), "ERROR", 0xFF0000)
else
kernel.log("Task " .. task.pid .. " syscall " .. scname .. " ok, " .. (#sysret-1) .. " retvals", "DBUG", 5)
kernel.log("Task " .. task.pid .. " syscall " .. scname .. " ok, " .. (#sysret-1) .. " retvals", "DBUG", 0x00FFFF)
for i = 2, #sysret do
local v = type(sysret[i]) == "table" and table.serialize(sysret[i]) or tostring(sysret[i])
kernel.log(" retval[" .. (i-1) .. "] = " .. v, "DBUG", 5)
kernel.log(" retval[" .. (i-1) .. "] = " .. v, "DBUG", 0x00FFFF)
end
end
end

View File

@@ -9,8 +9,20 @@ sysc["gpio_write"]=function(pin, data)
end
end
sysc["gpio_writeAnalog"]=function(pin, data)
if kernel.gpio[pin] then
return kernel.gpio[pin]("wa", data)
end
end
sysc["gpio_read"]=function(pin)
if kernel.gpio[pin] then
return kernel.gpio[pin]("r")
end
end
sysc["gpio_readAnalog"]=function(pin)
if kernel.gpio[pin] then
return kernel.gpio[pin]("ra")
end
end

View File

@@ -9,11 +9,13 @@ if not initOk then
end
local handle = kernel.vfs.open(kernel.config.initPath, "r")
if not handle then kernel.panic("Failed to open "..kernel.config.initPath) end
local data = kernel.vfs.read(handle, 1024 * 1024 * 4)
if not handle then kernel.panic("Failed to read "..kernel.config.initPath) end
kernel.vfs.close(handle)
local initFunc, err = load(data, "@sysinit", "t", kernel._U)
if not initFunc then error("Failed to load init system: " .. err) end
if not initFunc then kernel.PANIC("Failed to load init system: " .. err) end
kernel.tasks["1"] = {
coro = coroutine.create(function()

View File

@@ -1,9 +1,10 @@
--:Minify:--
local kernel = ...
if not kernel.vfs.exists("/root") then kernel.vfs.mkdir("/root") end
kernel.processes.login = function()
local ok, err = pcall(kernel.hpv.execspawn, "/bin/login", "login")
if not ok then
kernel.log("Failed to exec /bin/login: " .. tostring(err), "ERROR", 2)
kernel.log("Failed to exec /bin/login: " .. tostring(err), "ERROR", 0xFF0000)
end
end

View File

@@ -1,88 +1,88 @@
--:Minify:--
local kernel = ...
local P = kernel.vfs.P
local PERM = kernel.vfs.PERM
local RW_R_R = P.OWNER_R + P.OWNER_W + P.GROUP_R + P.WORLD_R
local RWX_RX_RX = P.OWNER_R + P.OWNER_W + P.OWNER_X
+ P.GROUP_R + P.GROUP_X
+ P.WORLD_R + P.WORLD_X
local RW_R__ = P.OWNER_R + P.OWNER_W + P.GROUP_R
local RW____ = P.OWNER_R + P.OWNER_W
local RWXRWXRWX = PERM.RWXRWXRWX
local SUID_755 = PERM.SUID_755
local META_VERSION = 0x02
local rootDisk = kernel.disks["$"]
local function makeEntry(name, etype, owner, group, perms, cmeta)
cmeta = cmeta or ""
local plo = perms % 256
local phi = math.floor(perms / 256) % 256
local olo = (owner or 0) % 256
local ohi = math.floor((owner or 0) / 256) % 256
local glo = (group or 0) % 256
local ghi = math.floor((group or 0) / 256) % 256
return string.char(#name) .. name
.. string.char(etype, olo, ohi, glo, ghi, plo, phi)
.. string.char(#cmeta) .. cmeta
end
local REG = 0x00
local function mergeMeta(dir, entries)
local diskDir = dir
if diskDir:sub(1,1) == "/" then diskDir = diskDir:sub(2) end
local metaPath = (diskDir == "" and ".meta" or diskDir .. "/.meta")
local existing = {}
local rok, rf = pcall(function() return rootDisk:open(metaPath, "r") end)
if rok and rf then
local raw = rf.read(65535)
if rf.close then rf.close() end
existing = (kernel.vfs._parseMetafile and kernel.vfs._parseMetafile(raw)) or {}
end
for _, e in ipairs(entries) do
local name = e[1]
local etype = e[2] or REG
local owner = e[3] or 0
local group = e[4] or 0
local perms = e[5] or RWX_RX_RX
local cmeta = e[6] or ""
existing[name] = {
etype = etype,
owner = owner,
group = group,
perms = perms,
cmeta = cmeta,
}
end
local data = string.char(META_VERSION)
for name, m in pairs(existing) do
data = data .. makeEntry(
name,
m.etype or REG,
m.owner or 0,
m.group or 0,
m.perms or RWX_RX_RX,
m.cmeta or ""
)
end
local ok, err = pcall(function()
local f = rootDisk:open(metaPath, "w")
f.write(data)
f.close()
end)
if not ok then
kernel.log("permissions: failed to write " .. metaPath .. ": " .. tostring(err), "WARN", 8)
end
end
if kernel.firstBoot then
local P = kernel.vfs.P
local PERM = kernel.vfs.PERM
local RW_R_R = P.OWNER_R + P.OWNER_W + P.GROUP_R + P.WORLD_R
local RWX_RX_RX = P.OWNER_R + P.OWNER_W + P.OWNER_X
+ P.GROUP_R + P.GROUP_X
+ P.WORLD_R + P.WORLD_X
local RW_R__ = P.OWNER_R + P.OWNER_W + P.GROUP_R
local RW____ = P.OWNER_R + P.OWNER_W
local RWXRWXRWX = PERM.RWXRWXRWX
local SUID_755 = PERM.SUID_755
local META_VERSION = 0x02
local rootDisk = kernel.disks["$"]
local function makeEntry(name, etype, owner, group, perms, cmeta)
cmeta = cmeta or ""
local plo = perms % 256
local phi = math.floor(perms / 256) % 256
local olo = (owner or 0) % 256
local ohi = math.floor((owner or 0) / 256) % 256
local glo = (group or 0) % 256
local ghi = math.floor((group or 0) / 256) % 256
return string.char(#name) .. name
.. string.char(etype, olo, ohi, glo, ghi, plo, phi)
.. string.char(#cmeta) .. cmeta
end
local REG = 0x00
local function mergeMeta(dir, entries)
local diskDir = dir
if diskDir:sub(1,1) == "/" then diskDir = diskDir:sub(2) end
local metaPath = (diskDir == "" and ".meta" or diskDir .. "/.meta")
local existing = {}
local rok, rf = pcall(function() return rootDisk:open(metaPath, "r") end)
if rok and rf then
local raw = rf.read(65535)
if rf.close then rf.close() end
existing = (kernel.vfs._parseMetafile and kernel.vfs._parseMetafile(raw)) or {}
end
for _, e in ipairs(entries) do
local name = e[1]
local etype = e[2] or REG
local owner = e[3] or 0
local group = e[4] or 0
local perms = e[5] or RWX_RX_RX
local cmeta = e[6] or ""
existing[name] = {
etype = etype,
owner = owner,
group = group,
perms = perms,
cmeta = cmeta,
}
end
local data = string.char(META_VERSION)
for name, m in pairs(existing) do
data = data .. makeEntry(
name,
m.etype or REG,
m.owner or 0,
m.group or 0,
m.perms or RWX_RX_RX,
m.cmeta or ""
)
end
local ok, err = pcall(function()
local f = rootDisk:open(metaPath, "w")
f.write(data)
f.close()
end)
if not ok then
kernel.log("permissions: failed to write " .. metaPath .. ": " .. tostring(err), "WARN", 0xFF8800)
end
end
kernel.log("Seeding filesystem permissions...")
mergeMeta("/", {
@@ -92,12 +92,13 @@ if kernel.firstBoot then
{"etc", REG, 0, 0, RWX_RX_RX},
{"home", REG, 0, 0, RWX_RX_RX},
{"lib", REG, 0, 0, RWX_RX_RX},
{"proc", REG, 0, 0, RWXRWXRWX},
{"root", REG, 0, 0, RW____ },
{"sbin", REG, 0, 0, RWX_RX_RX},
{"tmp", REG, 0, 0, RWXRWXRWX},
{"usr", REG, 0, 0, RWX_RX_RX},
{"var", REG, 0, 0, RWX_RX_RX},
{"opt", REG, 0, 0, RWXRWXRWX},
{"var", REG, 0, 0, RWXRWXRWX},
{"opt", REG, 0, 0, RWX_RX_RX},
})
mergeMeta("/bin", {
@@ -117,4 +118,4 @@ if kernel.firstBoot then
})
kernel.log("Filesystem permissions seeded.")
end
end

View File

@@ -261,16 +261,16 @@ local function render()
syscall.write(1, "\n")
end
end
syscall.devctl(1, "sfgc", 16)
syscall.devctl(1, "sbgc", 13)
syscall.devctl(1, "sfgc", 0x000000)
syscall.devctl(1, "sbgc", 0xDBDBDB)
local pct = math.floor(math.min(100, (scroll + pageSize) / totalLines * 100))
local status = string.format(" help -- line %d/%d (%d%%) [up/down: scroll q: quit] ",
scroll + 1, totalLines, pct)
if #status > screenW then status = status:sub(1, screenW) end
syscall.devctl(1, "spos", 1, screenH)
syscall.write(1, status .. string.rep(" ", screenW - #status))
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sbgc", 16)
syscall.devctl(1, "sfgc", 0xFFFFFF)
syscall.devctl(1, "sbgc", 0x000000)
dirty = false
end
@@ -281,7 +281,7 @@ if totalLines <= pageSize then
syscall.devctl(1, "sfgc", line[2])
syscall.write(1, line[1] .. "\n")
end
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
return
end
@@ -305,5 +305,5 @@ end
syscall.devctl(1, "clear")
syscall.devctl(1, "spos", 1, 1)
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sbgc", 16)
syscall.devctl(1, "sfgc", 0xFFFFFF)
syscall.devctl(1, "sbgc", 0x000000)

View File

@@ -3,11 +3,11 @@
-- 1=white, 2=red, 3=green, 4=blue, 5=cyan, 6=magenta, 7=yellow
-- 8=orange, 9=lime, 10=lightcyan, 11=brown, 12=darkgrey, 13=lightgrey, 14=purple, 15=chartreuse, 16=black
local C_LOGO = 5 -- cyan
local C_WHITE = 1 -- white
local C_LABEL = 13 -- light grey (key names)
local C_SEP = 12 -- dark grey (---- separator)
local C_USER = 3 -- green (user@host)
local C_LOGO = 0x00FFFF -- cyan
local C_WHITE = 0xFFFFFF -- white
local C_LABEL = 0xDBDBDB -- light grey (key names)
local C_SEP = 0x6D6D6D -- dark grey (---- separator)
local C_USER = 0x00FF00 -- green (user@host)
local function c(col) syscall.devctl(1, "sfgc", col) end

View File

@@ -8,7 +8,7 @@ local success, errorMsg = xpcall(function()
local fs = require("fs")
syscall.devctl(1,"clear")
syscall.devctl(1,"sfgc",1)
syscall.devctl(1,"sfgc",0xFFFFFF)
syscall.devctl(1,"spos",1,1)
print("HyperionOS hysh Shell")
@@ -26,8 +26,27 @@ else
end
local oldWD = ""
local colors = {
0xFFFFFF,
0xFF0000,
0x00FF00,
0x0000FF,
0x00FFFF,
0xFF00FF,
0xFFFF00,
0xFF6D00,
0x6DFF55,
0x24FFFF,
0x924900,
0x6D6D55,
0xDBDBAA,
0x6D00FF,
0xB6FF00,
0x000000
}
for i = 1, 16 do
syscall.devctl(1,"sbgc",i); printInline(" ")
syscall.devctl(1,"sbgc",colors[i]); printInline(" ")
end
print("\n")
@@ -221,7 +240,7 @@ end
builtinCmds.clear = function()
syscall.devctl(1,"clear")
syscall.devctl(1,"sfgc",1)
syscall.devctl(1,"sfgc",0xFFFFFF)
syscall.devctl(1,"spos",1,1)
end
@@ -429,7 +448,7 @@ builtinCmds.head = function(...)
local multi = #files > 1
local function dohead(text, label)
if multi then
syscall.devctl(1,"sfgc",4); print("==> "..label.." <=="); syscall.devctl(1,"sfgc",1)
syscall.devctl(1,"sfgc",0x0000FF); print("==> "..label.." <=="); syscall.devctl(1,"sfgc",0xFFFFFF)
end
local count = 0
for line in (text.."\n"):gmatch("([^\n]*)\n") do
@@ -468,7 +487,7 @@ builtinCmds.tail = function(...)
local multi = #files > 1
local function dotail(text, label)
if multi then
syscall.devctl(1,"sfgc",4); print("==> "..label.." <=="); syscall.devctl(1,"sfgc",1)
syscall.devctl(1,"sfgc",0x0000FF); print("==> "..label.." <=="); syscall.devctl(1,"sfgc",0xFFFFFF)
end
local lines = splitlines(text)
local start = math.max(1, #lines - n + 1)
@@ -963,13 +982,13 @@ local function doTabComplete(input, cursorPos)
end
local function getUserInput()
syscall.devctl(1,"sfgc",3)
syscall.devctl(1,"sfgc",0x00FF00)
syscall.write(1, userhost)
syscall.devctl(1,"sfgc",1)
syscall.devctl(1,"sfgc",0xFFFFFF)
syscall.write(1, ":")
syscall.devctl(1,"sfgc",10)
syscall.devctl(1,"sfgc",0x24FFFF)
syscall.write(1, syscall.getcwd())
syscall.devctl(1,"sfgc",1)
syscall.devctl(1,"sfgc",0xFFFFFF)
syscall.write(1, "$ ")
local curOffsetStr = syscall.devctl(1, "gpos")
local curOffsetX = tonumber(curOffsetStr:sub(1, curOffsetStr:find(";")-1))
@@ -1020,21 +1039,21 @@ local function getUserInput()
syscall.devctl(1,"spos",curOffsetX,curOffsetY)
syscall.write(1, string.sub(input, 1, cursorPos-1))
if blinkState then
syscall.devctl(1,"sfgc",16); syscall.devctl(1,"sbgc",1)
syscall.devctl(1,"sfgc",0x000000); syscall.devctl(1,"sbgc",0xFFFFFF)
end
if cursorPos > #input then
syscall.write(1, " ")
else
syscall.write(1, string.sub(input, cursorPos, cursorPos))
end
syscall.devctl(1,"sfgc",1); syscall.devctl(1,"sbgc",16)
syscall.devctl(1,"sfgc",0xFFFFFF); syscall.devctl(1,"sbgc",0x000000)
local after = string.sub(input, cursorPos+1)
syscall.write(1, after)
local ghost = getGhostSuffix()
if #ghost > 0 then
syscall.devctl(1,"sfgc",14)
syscall.devctl(1,"sfgc",0x6D00FF)
syscall.write(1, ghost)
syscall.devctl(1,"sfgc",1)
syscall.devctl(1,"sfgc",0xFFFFFF)
syscall.write(1, " ")
else
syscall.write(1, " ")
@@ -1082,10 +1101,10 @@ local function getUserInput()
syscall.write(1, string.rep(" ", tw))
syscall.devctl(1,"spos",1,py)
end
syscall.devctl(1,"sfgc",3); syscall.write(1, userhost)
syscall.devctl(1,"sfgc",1); syscall.write(1, ":")
syscall.devctl(1,"sfgc",10); syscall.write(1, syscall.getcwd())
syscall.devctl(1,"sfgc",1); syscall.write(1, "$ ")
syscall.devctl(1,"sfgc",0x00FF00); syscall.write(1, userhost)
syscall.devctl(1,"sfgc",0xFFFFFF); syscall.write(1, ":")
syscall.devctl(1,"sfgc",0x00FFFF); syscall.write(1, syscall.getcwd())
syscall.devctl(1,"sfgc",0xFFFFFF); syscall.write(1, "$ ")
posStr = syscall.devctl(1, "gpos")
sep = posStr:find(";")
curOffsetX = tonumber(posStr:sub(1, sep-1))
@@ -1098,7 +1117,7 @@ local function getUserInput()
cursorPos=cursorPos-1;dirty=true
end
elseif key=="\n" then
syscall.devctl(1,"sfgc",1);syscall.devctl(1,"sbgc",16)
syscall.devctl(1,"sfgc",0xFFFFFF);syscall.devctl(1,"sbgc",0x000000)
syscall.devctl(1,"spos",curOffsetX,curOffsetY)
syscall.write(1, input.." \n")
return input
@@ -1114,7 +1133,7 @@ local function getUserInput()
end
local function printError(progName, msg)
syscall.devctl(1,"sfgc",2)
syscall.devctl(1,"sfgc",0xFF0000)
local s = tostring(msg)
local line, rest = s:match("%]:(%d+): (.+)$")
if not line then line, rest = s:match(":(%d+): (.+)$") end
@@ -1123,7 +1142,7 @@ local function printError(progName, msg)
else
print(progName..": "..s)
end
syscall.devctl(1,"sfgc",1)
syscall.devctl(1,"sfgc",0xFFFFFF)
end
local function runCommand(command)
@@ -1171,7 +1190,7 @@ local function runCommand(command)
local xok, xerr = pcall(syscall.access, cmdPath, "x")
if not xok then
syscall.devctl(1,"sfgc",2); print(progName..": Permission denied"); syscall.devctl(1,"sfgc",1)
syscall.devctl(1,"sfgc",0xFF0000); print(progName..": Permission denied"); syscall.devctl(1,"sfgc",0xFFFFFF)
return
end
@@ -1195,8 +1214,8 @@ local function runCommand(command)
if terminate then
local ok2 = syscall.kill(proc)
if ok2 then
syscall.devctl(1,"sbgc",16); syscall.devctl(1,"sfgc",2)
print("\nProgram Terminated."); syscall.devctl(1,"sfgc",1)
syscall.devctl(1,"sbgc",16); syscall.devctl(1,"sfgc",0xFF0000)
print("\nProgram Terminated."); syscall.devctl(1,"sfgc",0xFFFFFF)
end
terminate = false; break
end
@@ -1218,8 +1237,8 @@ end, debug.traceback)
if not success then
syscall.log("Error running shell: "..errorMsg, "ERROR")
syscall.devctl(1,"sfgc",2)
syscall.devctl(1,"sbgc",16)
syscall.devctl(1,"sfgc",0xFF0000)
syscall.devctl(1,"sbgc",0x000000)
print()
print("Error running shell: ")
print(errorMsg)

View File

@@ -37,9 +37,9 @@ local function firstBoot()
syscall.devctl(1, "clear")
syscall.devctl(1, "spos", 1, 1)
syscall.devctl(1, "sfgc", 3)
syscall.devctl(1, "sfgc", 0x00FF00)
syscall.write(1, "HyperionOS First Boot Setup\n")
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
syscall.write(1, "No root password is set. Please create one now.\n\n")
while true do
@@ -49,25 +49,25 @@ local function firstBoot()
local pw2 = readLine("*")
if pw1 ~= pw2 then
syscall.devctl(1, "sfgc", 2)
syscall.devctl(1, "sfgc", 0xFF0000)
syscall.write(1, "Passwords do not match. Try again.\n\n")
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
elseif #pw1 < 6 then
syscall.devctl(1, "sfgc", 2)
syscall.devctl(1, "sfgc", 0xFF0000)
syscall.write(1, "Password too short (minimum 6 characters).\n\n")
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
else
local ok, err = syscall.setpassword(0, pw1)
if ok then
syscall.devctl(1, "sfgc", 3)
syscall.devctl(1, "sfgc", 0x00FF00)
syscall.write(1, "Root password set.\n\n")
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
sleep(0.5)
break
else
syscall.devctl(1, "sfgc", 2)
syscall.devctl(1, "sfgc", 0xFF0000)
syscall.write(1, "Error: " .. tostring(err) .. "\n")
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
end
end
end
@@ -112,8 +112,8 @@ end
local function doLogin()
syscall.devctl(1, "clear")
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sbgc", 16)
syscall.devctl(1, "sfgc", 0xFFFFFF)
syscall.devctl(1, "sbgc", 0x000000)
syscall.devctl(1, "spos", 1, 1)
local hostname = syscall.getHostname() or "hyperion"
@@ -122,44 +122,44 @@ local function doLogin()
local attempts = 0
while attempts < MAX_ATTEMPTS do
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
syscall.write(1, "Username: ")
local username = readLine(nil)
if username == "" then goto continue end
if username ~= "" then
syscall.write(1, "Password: ")
local password = readLine("*")
syscall.write(1, "Password: ")
local password = readLine("*")
local uid = syscall.getuidbyname(username)
local ok, err = syscall.login(username, password)
if ok then
local uid = syscall.getuid()
local pwent = syscall.getpasswd(uid)
local ok, err = syscall.login(uid, password)
if ok then
local uid = syscall.getuid()
local pwent = syscall.getpasswd(uid)
local shell = (pwent and pwent.shell) or "/bin/hysh"
local homedir = (pwent and pwent.homedir) or "/"
local shell = (pwent and pwent.shell) or "/bin/hysh"
local homedir = (pwent and pwent.homedir) or "/"
syscall.devctl(1, "sfgc", 3)
syscall.write(1, "\nWelcome, " .. username .. "!\n")
syscall.devctl(1, "sfgc", 1)
sleep(0.3)
syscall.devctl(1, "sfgc", 0x00FF00)
syscall.write(1, "\nWelcome, " .. username .. "!\n")
syscall.devctl(1, "sfgc", 0xFFFFFF)
sleep(0.3)
spawnShell(username, uid, shell, homedir)
return -- back to login prompt
else
attempts = attempts + 1
sleep(1)
syscall.devctl(1, "sfgc", 2)
syscall.write(1, "Login incorrect.\n\n")
syscall.devctl(1, "sfgc", 1)
spawnShell(username, uid, shell, homedir)
return -- back to login prompt
else
attempts = attempts + 1
sleep(1)
syscall.devctl(1, "sfgc", 0xFF0000)
syscall.write(1, "Login incorrect.\n\n")
syscall.devctl(1, "sfgc", 0xFFFFFF)
end
end
::continue::
end
syscall.devctl(1, "sfgc", 2)
syscall.devctl(1, "sfgc", 0xFF0000)
syscall.write(1, "Maximum login attempts exceeded.\n")
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
sleep(5)
end

View File

@@ -110,9 +110,9 @@ if opts.x then
pcall(syscall.umount, tmpMnt)
pcall(syscall.lodetach, loopId)
syscall.devctl(1, "sfgc", 10)
syscall.devctl(1, "sfgc", 0x00FFFF)
print(name..": extracted "..count.." file(s) to "..destPath)
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
return
end
@@ -150,8 +150,8 @@ local lineCount = 0
for _ in imgStr:gmatch("\n") do lineCount = lineCount + 1 end
local byteCount = #imgStr
syscall.devctl(1, "sfgc", 10)
syscall.devctl(1, "sfgc", 0x00FFFF)
print(name..": image written to "..imgPath)
syscall.devctl(1, "sfgc", 14)
syscall.devctl(1, "sfgc", 0x6D00FF)
print(string.format(" %d records, %d bytes", lineCount - 1, byteCount))
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)

View File

@@ -60,18 +60,18 @@ if opts.l then
local info = devs[id]
local mode = (type(info) == "table" and info.mode) or "bind"
local path = (type(info) == "table" and info.path) or tostring(info)
local colour = mode == "image" and 5 or 4
syscall.devctl(1, "sfgc", 3)
local colour = mode == "image" and 0x00FFFF or 0x0000FF
syscall.devctl(1, "sfgc", 0x00FF00)
printInline(string.format("%-10s", id))
syscall.devctl(1, "sfgc", colour)
printInline(string.format("%-7s", "["..mode.."]"))
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
print(" "..path)
end
if not any then
syscall.devctl(1, "sfgc", 14)
syscall.devctl(1, "sfgc", 0x6D00FF)
print(name..": no loop devices attached")
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
end
return
end
@@ -92,9 +92,9 @@ if opts.d then
end
print(name..": "..msg); syscall.exit(1); return
end
syscall.devctl(1, "sfgc", 10)
syscall.devctl(1, "sfgc", 0x00FFFF)
print(name..": detached "..id)
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
return
end

View File

@@ -110,10 +110,12 @@ if cloptions.l then
local stat = syscall.lstat and syscall.lstat(fullPath) or syscall.stat(fullPath)
local isDir = fs.isDir(fullPath)
local isSym = stat and stat.etype == 0x01
local isSock = stat and stat.etype == 0x02
local typeChar
if isSym then typeChar = "l"
if isSym then typeChar = "l"
elseif isDir then typeChar = "d"
elseif isSock then typeChar = "s"
else typeChar = "-" end
local pstr
@@ -136,26 +138,30 @@ if cloptions.l then
printInline(tostring(mtime) .. " ")
if isSym then
syscall.devctl(1, "sfgc", 6)
syscall.devctl(1, "sfgc", 0x00FFFF)
printInline(v)
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
local ok, target = pcall(syscall.readlink, fullPath)
if ok then
printInline(" -> ")
local targetExists = pcall(syscall.stat, fullPath)
syscall.devctl(1, "sfgc", targetExists and 6 or 2)
syscall.devctl(1, "sfgc", targetExists and 0x00FFFF or 0xFF0000)
printInline(target)
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
end
elseif isDir then
syscall.devctl(1, "sfgc", 14)
syscall.devctl(1, "sfgc", 0x6D00FF)
printInline(v)
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
elseif isSock then
syscall.devctl(1, "sfgc", 0xFF00FF)
printInline(v)
syscall.devctl(1, "sfgc", 0xFFFFFF)
else
local isExec = stat and stat.perms and (math.floor(stat.perms / (2^9)) % 2 == 1)
syscall.devctl(1, "sfgc", isExec and 3 or 1)
syscall.devctl(1, "sfgc", isExec and 0x00FF00 or 0xFFFFFF)
printInline(v)
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
end
print("")
end
@@ -175,16 +181,18 @@ for i, v in ipairs(list) do
local isSym = stat and stat.etype == 0x01
if isSym then
syscall.devctl(1, "sfgc", 6)
syscall.devctl(1, "sfgc", 0x00FFFF)
elseif isDir then
syscall.devctl(1, "sfgc", 14)
syscall.devctl(1, "sfgc", 0x6D00FF)
elseif isSock then
syscall.devctl(1, "sfgc", 0xFF00FF)
else
local isExec = stat and stat.perms and (math.floor(stat.perms / (2^9)) % 2 == 1)
syscall.devctl(1, "sfgc", isExec and 3 or 1)
syscall.devctl(1, "sfgc", isExec and 0x00FF00 or 0xFFFFFF)
end
printInline(v)
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
printInline((" "):rep(colWidth - #v))
if i % numCols == 0 then print("") end

View File

@@ -5,15 +5,15 @@ if not users or #users == 0 then
return
end
syscall.devctl(1,"sfgc",13)
syscall.devctl(1,"sfgc",0xDBDBDB)
print(string.format("%-6s %-6s %-16s %-20s %s", "UID", "GID", "Username", "Home", "Shell"))
print(string.rep("-", 65))
syscall.devctl(1,"sfgc",1)
syscall.devctl(1,"sfgc",0xFFFFFF)
for _, u in ipairs(users) do
local lock_marker = u.locked and " [locked]" or ""
if u.locked then syscall.devctl(1,"sfgc",2) end
if u.locked then syscall.devctl(1,"sfgc",0xFF0000) end
print(string.format("%-6d %-6d %-16s %-20s %s%s",
u.uid, u.gid, u.username, u.homedir, u.shell, lock_marker))
if u.locked then syscall.devctl(1,"sfgc",1) end
if u.locked then syscall.devctl(1,"sfgc",0xFFFFFF) end
end

View File

@@ -69,17 +69,17 @@ if #args == 0 and not opts.o then
end
if next(loDevs) == nil then
syscall.devctl(1, "sfgc", 14)
syscall.devctl(1, "sfgc", 0xFF00FF)
print("(no loop devices attached)")
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
return
end
for id, info in pairs(loDevs) do
local colour = info.mode == "image" and 5 or 4
local colour = info.mode == "image" and 0x00FFFF or 0x0000FF
syscall.devctl(1, "sfgc", colour)
printInline(info.mode.." "..id)
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
print(" on "..info.path)
end
return
@@ -119,9 +119,9 @@ if opts.o and opts.o:lower() == "loop" then
print(name..": mount: "..msg); syscall.exit(1); return
end
syscall.devctl(1, "sfgc", 10)
syscall.devctl(1, "sfgc", 0x00FFFF)
print(name..": "..loopId.." mounted at "..dest)
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
return
end
@@ -141,9 +141,9 @@ if #args == 2 then
print(name..": "..msg); syscall.exit(1); return
end
syscall.devctl(1, "sfgc", 10)
syscall.devctl(1, "sfgc", 0x00FFFF)
print(name..": "..loopId.." mounted at "..dest)
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
return
end

View File

@@ -9,7 +9,7 @@ local currentUid = syscall.getuid()
local targetUid
if targetName then
targetUid = syscall.getuid(targetName)
targetUid = syscall.getuid()
if not targetUid then
print("passwd: user '" .. targetName .. "' does not exist")
syscall.exit(1); return
@@ -36,7 +36,7 @@ if currentUid ~= 0 then
if #cur > 0 then cur=cur:sub(1,-2); syscall.write(1,"\b \b") end
else cur=cur..ch; syscall.write(1,"*") end
end
local ok, err = syscall.elevate(targetName, cur)
local ok, err = syscall.login(targetUid, cur)
if not ok then
sleep(1)
print("passwd: authentication failure")

View File

@@ -1,7 +1,15 @@
--:Minify:--
local targetUser = ({ ... })[1] or "root"
local targetUser = ({ ... })[1]
local currentUid = syscall.getuid()
local targetUid = syscall.getuidbyname(targetUser)
if syscall.geteuid()~=0 then
syscall.exec("/bin/su", {...})
end
local targetUid
if targetUser then
targetUid = syscall.getuidbyname(targetUser)
else
targetUid = 0
end
if not targetUid then
print("su: user '" .. targetUser .. "' does not exist")
@@ -25,20 +33,21 @@ if currentUid ~= 0 then
end
end
local ok, err = syscall.elevate(targetUser, pw)
local ok, err = syscall.login(targetUid, pw)
if not ok then
sleep(1)
print("su: Authentication failure")
syscall.exit(1)
return
end
else
syscall.setuid(targetUid)
end
syscall.setuid(targetUid)
local pwent = syscall.getpasswd(targetUid)
local shell = (pwent and pwent.shell) or "/bin/hysh"
local homedir = (pwent and pwent.homedir) or "/"
local username= (pwent and pwent.username)or "Unknown"
local ok_cd, err_cd = pcall(syscall.chdir, homedir)
if not ok_cd then
@@ -46,11 +55,11 @@ if not ok_cd then
syscall.chdir(homedir)
end
syscall.setEnviron("HOME", homedir)
syscall.setEnviron("USER", targetUser)
syscall.setEnviron("USER", username)
syscall.setEnviron("SHELL", shell)
local ok, err = pcall(syscall.exec, shell)
if not ok then
print("su: cannot exec shell '" .. shell .. "': " .. tostring(err))
syscall.exit(1)
end
end

View File

@@ -55,7 +55,7 @@ if currentUid ~= 0 then
end
end
local ok, err = syscall.elevate("root", pw)
local ok, err = syscall.login(0, pw)
if not ok then
sleep(1)
print("sudo: Authentication failure")

View File

@@ -59,9 +59,9 @@ if opts.l then
end
print(name..": "..msg); syscall.exit(1); return
end
syscall.devctl(1, "sfgc", 10)
syscall.devctl(1, "sfgc", 0x00FFFF)
print(name..": detached "..id)
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
return
end
@@ -95,17 +95,17 @@ if not ok then
print(name..": "..msg); syscall.exit(1); return
end
syscall.devctl(1, "sfgc", 10)
syscall.devctl(1, "sfgc", 0x00FFFF)
print(name..": unmounted "..mpt)
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
if loopIdToDetach then
for _, id in ipairs(loopIdToDetach) do
local dok = pcall(syscall.lodetach, id)
if dok then
syscall.devctl(1, "sfgc", 14)
syscall.devctl(1, "sfgc", 0xFF00FF)
print(name..": auto-detached "..id)
syscall.devctl(1, "sfgc", 1)
syscall.devctl(1, "sfgc", 0xFFFFFF)
end
end
end

View File

@@ -1,3 +1,4 @@
--:Minify:--
local ini = {}
function ini.parse(str)

8
Src/install.json Normal file
View File

@@ -0,0 +1,8 @@
[
"Hyperion-kernel",
"Hyperion-core",
"hysh",
"lua",
"micro",
"sysinit"
]

View File

@@ -1,14 +1,14 @@
--:Minify:--
local C_PROMPT = 7
local C_CONT = 13
local C_OUT = 5
local C_ERR = 2
local C_KEY = 3
local C_STR = 9
local C_NUM = 10
local C_BOOL = 8
local C_NIL = 12
local C_TABLE = 13
local C_PROMPT = 0xFFFF00
local C_CONT = 0xDBDBDB
local C_OUT = 0x00FFFF
local C_ERR = 0xFF0000
local C_KEY = 0x00FF00
local C_STR = 0x00FF88
local C_NUM = 0x24FFFF
local C_BOOL = 0xFF6D00
local C_NIL = 0x6D6D6D
local C_TABLE = 0xDBDBDB
local function c(col) syscall.devctl(1, "sfgc", col) end
local function w(s) syscall.write(1, tostring(s)) end
@@ -250,9 +250,9 @@ local function getUserInput(prompt, history)
local function redraw()
syscall.devctl(1, "spos", ox, oy)
w(input:sub(1, cursor-1))
if blink then syscall.devctl(1,"sfgc",16); syscall.devctl(1,"sbgc",1) end
if blink then syscall.devctl(1,"sfgc",0x000000); syscall.devctl(1,"sbgc",1) end
w(cursor > #input and " " or input:sub(cursor, cursor))
syscall.devctl(1,"sfgc",1); syscall.devctl(1,"sbgc",16)
syscall.devctl(1,"sfgc",0xFFFFFF); syscall.devctl(1,"sbgc",16)
w(input:sub(cursor+1) .. " ")
dirty = false
end
@@ -284,7 +284,7 @@ local function getUserInput(prompt, history)
cursor = cursor - 1; dirty = true
end
elseif key == "\n" then
syscall.devctl(1,"sfgc",1); syscall.devctl(1,"sbgc",16)
syscall.devctl(1,"sfgc",0xFFFFFF); syscall.devctl(1,"sbgc",16)
syscall.devctl(1,"spos",ox,oy)
w(input .. " \n")
return input
@@ -308,16 +308,16 @@ local history = {}
while true do
local code = getUserInput("lua> ", history)
if code == "" then goto continue end
if code ~= "" then
while isIncomplete(code) do
code = code .. "\n" .. getUserInput("... ", nil)
while isIncomplete(code) do
code = code .. "\n" .. getUserInput("... ", nil)
end
if code ~= history[#history] then
history[#history+1] = code
end
runCode(code)
end
if code ~= history[#history] then
history[#history+1] = code
end
runCode(code)
::continue::
end

View File

@@ -135,16 +135,16 @@ local function pad(s, w)
end
local function drawTop()
tpos(1,1); tbg(4); tfg(16)
tpos(1,1); tbg(0x0000FF); tfg(0x000000)
local left = " edit" .. (fname and (" - "..fname) or "")
if dirty then left = left .. " [+]" end
local right = tostring(cy)..","..tostring(cx).." "
twrite(pad(left..string.rep(" ", math.max(1, W-#left-#right))..right, W))
tbg(16); tfg(1)
tbg(0x000000); tfg(0xFFFFFF)
end
local function drawBottom()
tpos(1, H); tbg(4); tfg(16)
tpos(1, H); tbg(0x0000FF); tfg(0x000000)
if msg ~= "" then
if msgErr then tbg(2) end
twrite(pad(" "..msg, W))
@@ -152,7 +152,7 @@ local function drawBottom()
else
twrite(pad(" ^W Save ^X Quit+Save ^P Quit ^K Cut ^U Paste ^F Find ^G Go", W))
end
tbg(16); tfg(1)
tbg(0x000000); tfg(0xFFFFFF)
end
local function drawLines(map)
@@ -177,29 +177,29 @@ local function drawLines(map)
local curCh = ci > #seg and " " or seg:sub(ci, ci)
local after = seg:sub(ci+1)
tfg(1); tbg(16); twrite(before)
if blinkState then tfg(16); tbg(1) else tfg(1); tbg(16) end
tfg(0xFFFFFF); tbg(0x000000); twrite(before)
if blinkState then tfg(0x000000); tbg(0xFFFFFF) else tfg(0xFFFFFF); tbg(0x000000) end
twrite(curCh)
tfg(1); tbg(16); twrite(after)
tfg(0xFFFFFF); tbg(0x000000); twrite(after)
local drawn = #before + 1 + #after
if drawn < W then twrite(string.rep(" ", W - drawn)) end
else
if li == sLine and sPat ~= "" and entry[2] == 1 then
local s, e = seg:find(sPat)
if s then
tfg(1); tbg(16); twrite(seg:sub(1,s-1))
tfg(16); tbg(3); twrite(seg:sub(s,e))
tfg(1); tbg(16); twrite(seg:sub(e+1))
tfg(0xFFFFFF); tbg(0x000000); twrite(seg:sub(1,s-1))
tfg(0x000000); tbg(0x00FF00); twrite(seg:sub(s,e))
tfg(0xFFFFFF); tbg(0x000000); twrite(seg:sub(e+1))
twrite(string.rep(" ", W - #seg))
else
tfg(1); tbg(16); twrite(pad(seg, W))
tfg(0xFFFFFF); tbg(0x000000); twrite(pad(seg, W))
end
else
tfg(1); tbg(16); twrite(pad(seg, W))
tfg(0xFFFFFF); tbg(0x000000); twrite(pad(seg, W))
end
end
else
tfg(13); tbg(16); twrite(pad("~", W)); tfg(1)
tfg(0xDBDBDB); tbg(0x000000); twrite(pad("~", W)); tfg(0xFFFFFF)
end
end
end
@@ -212,15 +212,15 @@ local function redraw()
drawLines(map)
drawBottom()
tpos(1, H)
tbg(16); tfg(1)
tbg(0x000000); tfg(0xFFFFFF)
end
local function prompt(label, default)
local inp = default or ""
while true do
tpos(1, H); tbg(3); tfg(16)
tpos(1, H); tbg(0x00FF00); tfg(0x000000)
twrite(pad(" "..label..inp.." ", W))
tbg(16); tfg(1)
tbg(0x000000); tfg(0xFFFFFF)
local key = syscall.read(0)
if not key or key == "" then sleep(0.02)
elseif key == "" then return nil
@@ -415,5 +415,5 @@ while running do
end
end
tclear(); tfg(1); tbg(16); tpos(1,1)
tclear(); tfg(0xFFFFFF); tbg(0x000000); tpos(1,1)
print("edit: exited"..(fname and (" - "..fname) or ""))

View File

@@ -139,72 +139,68 @@ local function parseCommands(src)
local c = src:sub(pos, pos)
if c == "\n" or c == ";" then
pos = pos + 1
goto continue
end
if c == "#" then
elseif c == "#" then
while pos <= len and src:sub(pos,pos) ~= "\n" do pos = pos + 1 end
goto continue
end
local addr1, addr2
addr1, pos = parseAddr(src, pos)
skip()
if addr1 and pos <= len and src:sub(pos,pos) == "," then
pos = pos + 1
skip()
addr2, pos = parseAddr(src, pos)
end
skip()
if pos > len then break end
local cmd = src:sub(pos, pos)
pos = pos + 1
if cmd == "s" then
local delim = src:sub(pos, pos); pos = pos + 1
local pat, p1 = parseDelim(src, pos, delim); pos = p1
local repl, p2 = parseDelim(src, pos, delim); pos = p2
local flags = ""
while pos <= len and src:sub(pos,pos):match("[giIp]") do
flags = flags .. src:sub(pos,pos); pos = pos + 1
end
table.insert(cmds, { addr1=addr1, addr2=addr2, cmd="s",
pat=pat, repl=repl, flags=flags })
elseif cmd == "y" then
local delim = src:sub(pos, pos); pos = pos + 1
local srcch, p1 = parseDelim(src, pos, delim); pos = p1
local dstch, p2 = parseDelim(src, pos, delim); pos = p2
table.insert(cmds, { addr1=addr1, addr2=addr2, cmd="y",
src=srcch, dst=dstch })
elseif cmd == "d" or cmd == "p" or cmd == "q" or cmd == "=" then
table.insert(cmds, { addr1=addr1, addr2=addr2, cmd=cmd })
elseif cmd == "{" then
local depth = 1
local start = pos
while pos <= len and depth > 0 do
local ch = src:sub(pos,pos)
if ch == "{" then depth = depth + 1
elseif ch == "}" then depth = depth - 1 end
pos = pos + 1
end
local inner = src:sub(start, pos - 2)
local innerCmds = parseCommands(inner)
for _, ic in ipairs(innerCmds) do
ic.addr1 = ic.addr1 or addr1
ic.addr2 = ic.addr2 or addr2
end
for _, ic in ipairs(innerCmds) do
table.insert(cmds, ic)
end
elseif cmd == "\n" or cmd == ";" then
else
end
::continue::
local addr1, addr2
addr1, pos = parseAddr(src, pos)
skip()
if addr1 and pos <= len and src:sub(pos,pos) == "," then
pos = pos + 1
skip()
addr2, pos = parseAddr(src, pos)
end
skip()
if pos > len then break end
local cmd = src:sub(pos, pos)
pos = pos + 1
if cmd == "s" then
local delim = src:sub(pos, pos); pos = pos + 1
local pat, p1 = parseDelim(src, pos, delim); pos = p1
local repl, p2 = parseDelim(src, pos, delim); pos = p2
local flags = ""
while pos <= len and src:sub(pos,pos):match("[giIp]") do
flags = flags .. src:sub(pos,pos); pos = pos + 1
end
table.insert(cmds, { addr1=addr1, addr2=addr2, cmd="s",
pat=pat, repl=repl, flags=flags })
elseif cmd == "y" then
local delim = src:sub(pos, pos); pos = pos + 1
local srcch, p1 = parseDelim(src, pos, delim); pos = p1
local dstch, p2 = parseDelim(src, pos, delim); pos = p2
table.insert(cmds, { addr1=addr1, addr2=addr2, cmd="y",
src=srcch, dst=dstch })
elseif cmd == "d" or cmd == "p" or cmd == "q" or cmd == "=" then
table.insert(cmds, { addr1=addr1, addr2=addr2, cmd=cmd })
elseif cmd == "{" then
local depth = 1
local start = pos
while pos <= len and depth > 0 do
local ch = src:sub(pos,pos)
if ch == "{" then depth = depth + 1
elseif ch == "}" then depth = depth - 1 end
pos = pos + 1
end
local inner = src:sub(start, pos - 2)
local innerCmds = parseCommands(inner)
for _, ic in ipairs(innerCmds) do
ic.addr1 = ic.addr1 or addr1
ic.addr2 = ic.addr2 or addr2
end
for _, ic in ipairs(innerCmds) do
table.insert(cmds, ic)
end
elseif cmd == "\n" or cmd == ";" then
else
end
end
end
return cmds

View File

@@ -1,15 +1,16 @@
--:Minify:--
local kernel=...
local fs=require("fs")
kernel.log("Sysinit started...")
for i,v in pairs(kernel.processes) do
kernel.log("Spawning kernel task "..i)
syscall.spawn(function()
local status, err = pcall(v)
if not status then
kernel.log("Error executing kernel task '" .. i .. "': " .. err, "ERROR")
kernel.log("Error executing kernel task '" .. i .. "': " .. err, "ERROR", 0xFF0000)
else
kernel.log("Successfully executed kernel task: " .. i, "INFO")
kernel.log("Successfully executed kernel task: " .. i)
end
end, i)
end
@@ -17,23 +18,24 @@ end
if not fs.exists("/bin/startup") then
fs.mkdir("/bin/startup")
end
local files = fs.list("/bin/startup")
if not files then error("Failed to list /bin/startup") end
for i,v in ipairs(files) do
if v:sub(-4) == ".lua" then
local filepath = "/bin/startup/" .. v
kernel.log("Executing startup script: " .. filepath, "INFO")
kernel.log("Executing startup script: " .. filepath)
local startupFunc, err = load(fs.readAllText(filepath), "@" .. filepath)
if not startupFunc then
kernel.log("Error loading startup script '" .. filepath .. "': " .. err, "ERROR")
kernel.log("Error loading startup script '" .. filepath .. "': " .. err, "ERROR", 0xFF0000)
else
syscall.spawn(function()
syscall.setuid(1)
local status, err = pcall(startupFunc)
if not status then
kernel.log("Error executing startup script '" .. filepath .. "': " .. err, "ERROR")
kernel.log("Error executing startup script '" .. filepath .. "': " .. err, "ERROR", 0xFF0000)
else
kernel.log("Successfully executed startup script: " .. filepath, "INFO")
kernel.log("Successfully executed startup script: " .. filepath)
end
end, "startup:" .. v)
end

View File

@@ -11,6 +11,8 @@ Targets:
build-mini-test
build-micro-test
clean
prod
prod-mini
Arch flags:
--arch cct
@@ -32,6 +34,7 @@ PROJECT_ROOT = Path(__file__).resolve().parent
SRC_ROOT = PROJECT_ROOT / "Src"
TEST_ROOT = PROJECT_ROOT / "Test"
BUILD_ROOT = PROJECT_ROOT / "Build"
PROD_ROOT = PROJECT_ROOT / "prod"
ARCH_BOOT_DIR = {
"cct": Path("boot") / "cct",
@@ -46,6 +49,13 @@ def clean():
else:
print("Nothing to clean.")
def cleanprod():
if PROD_ROOT.exists():
print(f"Removing {PROD_ROOT} ...")
shutil.rmtree(PROD_ROOT)
else:
print("Nothing to clean.")
def has_minify_header(path: Path) -> bool:
try:
@@ -74,14 +84,19 @@ def compress_lz4(data: bytes) -> bytes:
return lz4.frame.compress(data)
def process_root(src_root: Path, out_root: Path, minify: bool, micro: bool):
def process_root(src_root: Path, out_root: Path, minify: bool, micro: bool, arch:Union[str, None], prod:bool):
print(f"Building from {src_root}")
print(f"Output to {out_root}")
print(f"Output to {out_root}")
print()
for pkg_dir in sorted(src_root.iterdir()):
if not pkg_dir.is_dir():
continue
if pkg_dir.name[:18] == "Hyperion-firmware-":
if pkg_dir.name != f"Hyperion-firmware-{arch}":
if prod != True:
continue
print(f"== Package: {pkg_dir.name} ==")
@@ -93,8 +108,11 @@ def process_root(src_root: Path, out_root: Path, minify: bool, micro: bool):
if rel.name=="$PKGCONFIG.ini":
continue
dst = out_root / rel
if prod:
dst = out_root / pkg_dir.name / rel
dst.parent.mkdir(parents=True, exist_ok=True)
print(f" Processing: {src.relative_to(src_root)}")
@@ -128,13 +146,19 @@ def install_bootloader(arch: str, release: bool):
shutil.copy2(eeprom, BUILD_ROOT / eeprom_dst_name)
def run_build(minify: bool, micro: bool, include_test: bool, arch: Union[str, None], release: bool):
def run_build(minify: bool, micro: bool, include_test: bool, arch: Union[str, None], release: bool, prod: bool):
clean()
BUILD_ROOT.mkdir()
if prod:
cleanprod()
PROD_ROOT.mkdir()
out_root = BUILD_ROOT / "$" if arch else BUILD_ROOT
process_root(SRC_ROOT, out_root, minify, micro)
process_root(SRC_ROOT, out_root, minify, micro, arch, False)
if prod:
process_root(SRC_ROOT, PROD_ROOT, minify, micro, arch, True)
if include_test:
process_root(TEST_ROOT, out_root, minify, micro)
@@ -196,9 +220,9 @@ def inject_makeusers(users, arch):
def main():
parser = argparse.ArgumentParser(description="HyperionOS build script")
parser.add_argument("target", choices=["build", "build-mini", "build-micro", "build-test", "build-mini-test", "build-micro-test", "clean"])
parser.add_argument("target", choices=["build", "build-mini", "build-micro", "build-test", "build-mini-test", "build-micro-test", "clean", "prod", "prod-mini"])
parser.add_argument("--arch", choices=["cct", "oc"], default=None,
help="Target architecture (cct or oc)")
help="Target architecture")
parser.add_argument("--release", dest="release", action="store_true", default=True,
help="Release build: eeprom placed as startup.lua (default)")
parser.add_argument("--dev", dest="release", action="store_false",
@@ -222,6 +246,7 @@ def main():
clean()
return
prod = "prod" in args.target
minify = "mini" in args.target or "micro" in args.target
micro = "micro" in args.target
include_test = "test" in args.target
@@ -229,7 +254,7 @@ def main():
if micro:
import lz4.block
run_build(minify=minify, micro=micro, include_test=include_test, arch=args.arch, release=args.release)
run_build(minify=minify, micro=micro, include_test=include_test, arch=args.arch, release=args.release, prod=prod)
if args.makeuser:
print("Injecting first-boot user setup ...")

Binary file not shown.

View File

@@ -1,157 +0,0 @@
local function octal_to_number(str)
str = str:gsub("%z", ""):match("^%s*(.-)%s*$")
return tonumber(str, 8) or 0
end
local function dedupe_path(path)
local parts = {}
for p in path:gmatch("[^/]+") do table.insert(parts, p) end
for prefix_len = 1, math.floor(#parts / 2) do
local ok = true
for i = 1, prefix_len do
if parts[i] ~= parts[i + prefix_len] then
ok = false
break
end
end
if ok then
local cleaned = {}
for i = 1, #parts - prefix_len do
cleaned[#cleaned + 1] = parts[i + prefix_len]
end
return table.concat(cleaned, "/")
end
end
return path
end
local function make_dirs(root, path)
local cur = root
for part in path:gmatch("([^/]+)/") do
if not cur[part] then
cur[part] = { __type = "dir", __entries = {} }
end
cur = cur[part].__entries
end
return cur
end
local function flatten(node, prefix)
local out = {}
prefix = prefix or ""
for name, obj in pairs(node) do
local full = prefix .. name
if obj.__type == "file" then
out[#out+1] = {
name = full,
type = "file",
contents = obj.__contents
}
elseif obj.__type == "dir" then
out[#out+1] = {
name = full .. "/",
type = "dir",
contents = flatten(obj.__entries, full .. "/")
}
end
end
return out
end
local function unpack_tar(tarstr)
local i = 1
local len = #tarstr
local root = {}
while i + 512 <= len do
local header = tarstr:sub(i, i + 511)
if header:match("^\0+$") then break end
local name_raw = header:sub(1, 100):gsub("%z.*", "")
local prefix_raw = header:sub(346, 500):gsub("%z.*", "")
local name
if prefix_raw ~= "" then
name = prefix_raw .. "/" .. name_raw
else
name = name_raw
end
name = name:gsub("^%./", ""):gsub("/+", "/")
name = dedupe_path(name)
local size = octal_to_number(header:sub(125,136))
local typeflag = header:sub(157,157)
i = i + 512
local contents = tarstr:sub(i, i + size - 1)
local pad = (512 - (size % 512)) % 512
i = i + size + pad
if name == "" then goto continue end
local is_dir = typeflag == "5" or name:sub(-1) == "/"
local clean_name = name:gsub("/$", "")
if clean_name == "" then goto continue end
local parent_path = clean_name:match("(.+)/")
local fname = clean_name:match("([^/]+)$")
if not fname then goto continue end
local parent = root
if parent_path then
parent = make_dirs(root, parent_path .. "/")
end
if is_dir then
parent[fname] = parent[fname] or { __type = "dir", __entries = {} }
else
parent[fname] = { __type = "file", __contents = contents }
end
::continue::
end
return flatten(root)
end
local function write_directory(prefix, items)
for _, v in ipairs(items) do
if v.type == "dir" then
fs.makeDir(prefix..v.name)
write_directory(prefix, v.contents)
elseif v.type == "file" then
local file = fs.open(prefix..v.name, "w")
file.write(v.contents)
file.close()
end
end
end
local in_tar = ({...})[1]
local out_dir = ({...})[2]
if not in_tar or not out_dir then
print("Usage: unpack_tar <tarfile> <output_dir>")
return
end
local f = fs.open(in_tar, "r")
local tarstr = f.readAll()
f.close()
local list = unpack_tar(tarstr)
write_directory(out_dir, list)
print("TAR extracted into: " .. out_dir)

View File

@@ -1,27 +0,0 @@
print("Hello, World!")
sleep(1)
term.clear()
print("Do you want to install HyperionOS? [Y/n]")
local input=read()
if input=="y" or input=="Y" or input=="" then
goto install
else
goto exit
end
::install::
print("Installing tar but bad...")
shell.run("wget https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/1.2-dev/install/data/tarbad /tar.lua")
print("Installing HyperionOS...")
print("Installing precompiled tar")
shell.run("wget https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/1.2-dev/install/data/Build.tar /Build.tar")
shell.run("tar Build.tar /")
print("Removing tar but bad...")
shell.run("rm /tar.lua")
shell.run("rm $")
shell.run("cp Build $")
shell.run("rm Build")
shell.run("rm Build.tar")
fs.copy("/$/boot/cct/eeprom","/startup.lua")
dofile("startup.lua")
::exit::

View File

@@ -0,0 +1,229 @@
term.clear()
term.setTextColor(colors.white)
term.setCursorPos(1,1)
print("HyperionOS CCT Installer //")
local w,h = term.getSize()
local exitall,releasename,packagelist=false,"",{}
local function printc(...)
local args={...}
for i=1, #args do
if type(args[i]) == "number" then
term.setTextColor(args[i])
else
term.write(args[i])
end
end
print("")
end
local function download(url)
printc(colors.gray, "[ ", colors.green, " FETCH ", colors.gray, " ] ", colors.white, url)
local data,err=http.get(url)
if not data then error(err) end
local text=data.readAll()
data.close()
return text
end
local function writeFile(path, data)
printc(colors.gray, "[ ", colors.green, "WRITING", colors.gray, " ] ", colors.white, path)
local file=fs.open(path, "w")
file.write(data)
file.close()
end
print("Installing JSON to /hyinstall/json...")
writeFile("/hyinstall/json",download("https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/misc/json"))
print("Loading JSON...")
local json=loadfile("/hyinstall/json")()
local function printTitle()
term.clear()
term.setCursorPos(1,1)
term.setTextColor(colors.white)
print("HyperionOS CCT Installer //")
print("Orange is prerelease...")
term.setCursorPos(1,h-1)
print("DESCLAIMER: This will wipe your system on install...")
term.write("Bspc: Back | Enter: execute | Tab: description")
end
printTitle()
local function pc(text, y, c)
local x=(w/2)-#text/2
term.setTextColor(c)
term.setCursorPos(x, y)
term.write(text)
end
local function drawMenu(menu, sel)
local y=(h/2)-#menu/2
for i,v in ipairs(menu) do
if i==sel then
pc("[ "..v.name.." ]", y+i, v.color)
else
pc(v.name, y+i, v.color)
end
end
end
local function desc(description)
term.clear()
term.setTextColor(colors.white)
term.setCursorPos(1,1)
print("HyperionOS CCT Installer //\n")
print(description)
term.setCursorPos(1,h)
term.write("Press enter to continue...")
while not exitall do
local _,key = os.pullEvent("key")
if key==keys.enter then
break
end
end
end
local function menu(m)
local exit,sel=false,1
while not exit and not exitall do
printTitle()
drawMenu(m, sel)
local _,key = os.pullEvent("key")
if key==keys.down then
if sel<#m then
sel=sel+1
end
elseif key==keys.up then
if sel>1 then
sel=sel-1
end
elseif key==keys.enter then
m[sel].func()
elseif key==keys.tab then
desc(m[sel].desc)
elseif key==keys.backspace then
exit=true
end
end
end
local releases,page={},1
while true do
local handle=http.get("https://git.astronand.dev/api/v1/repos/Hyperion/HyperionOS/releases?page="..tostring(page).."&limit=1")
local raw=handle.readAll()
handle.close()
if raw=="[]\n" then
break
end
releases[page]=json.decode(raw)[1]
page=page+1
end
local function makePage(start, num)
local m={}
for i=start, num do
if not releases[i] then break end
local release=releases[i]
m[#m+1]={
name=release.name,
desc=release.body,
color=release.prerelease and colors.orange or colors.white,
func=function()
local data=download("https://git.astronand.dev/Hyperion/HyperionOS/raw/tag/"..release.tag_name.."/Src/install.json")
if not data then
term.clear()
term.setCursorPos(1,1)
print("Unable to find package list for ver "..release.tag_name..":\n"..err)
sleep(3)
return
end
releasename=release.tag_name
packagelist=json.decode(data)
exitall=true
end
}
end
if #releases>start+num then
m[#m+1]={
name="Next",
desc="Next menu",
color=colors.cyan,
func=function()
local menudata=makePage(start+num, num)
menu(menudata)
end
}
end
return m
end
menu(makePage(1,5))
term.clear()
term.setCursorPos(1,1)
term.setTextColor(colors.white)
term.write("Formating disk in ")
for i=5, 1, -1 do
term.write(tostring(i))
sleep(.25)
for v=1, 3 do
term.write(".")
sleep(.25)
end
end
print("")
local function delDir(dir)
printc(colors.gray, "[ ", colors.green, " LSDIR ", colors.gray, " ] ", colors.white, dir)
local list=fs.list(dir)
printc(colors.gray, "[ ", colors.red, " DELET ", colors.gray, " ] ", colors.white, dir)
for i=1, #list do
if fs.isDir(dir..list[i]) then
if dir..list[i] ~= "/rom" then
delDir(dir..list[i].."/")
fs.delete(dir..list[i])
end
else
fs.delete(dir..list[i])
printc(colors.gray, "[ ", colors.red, " DELET ", colors.gray, " ] ", colors.white, dir..list[i])
end
sleep(.1)
end
end
delDir("/")
print("")
printc(colors.cyan, " \\\\Installing//")
print("")
printc(colors.white, "Getting package list...")
local function installdir(path, dir, pkg)
local data=json.decode(download("https://git.astronand.dev/api/v1/repos/Hyperion/HyperionOS/contents/prod/"..pkg..dir.."?ref="..releasename))
if not data then error("Uh Oh: JSON decode error...") end
for i=1, #data do
local entry=data[i]
if entry.type == "dir" then
installdir(path, dir..entry.name.."/", pkg)
elseif entry.type == "file" then
writeFile(path..dir..entry.name, download(entry.download_url))
else
error("Uh Oh: unknown entrytype "..entry.path)
end
end
end
local function installpkg(pkg)
installdir("/$", "/", pkg)
end
for i=1, #packagelist do
installpkg(packagelist[i])
end
installpkg("Hyperion-firmware-cct")
fs.copy("/$/boot/cct/eeprom", "/startup.lua")
printc(colors.white, "Rebooting...")
sleep(1)
os.reboot()

View File

@@ -3,6 +3,8 @@
--- @diagnostic disable: duplicate-set-field
syscall={}
--- @alias userinfo {username:string,homedir:string,shell:string,uid:number,gid:number}
--- Sets home directory of User with corresponding uid to homedir
--- @param uid integer
--- @param homedir string
@@ -142,9 +144,14 @@ syscall.dup=function(fd) end
--- Read GPIO pin
--- @param pin integer
--- @return number|nil
--- @return boolean|nil
syscall.gpio_read=function(pin) end
--- Read GPIO pin analog
--- @param pin integer
--- @return number|nil
syscall.gpio_readAnalog=function(pin) end
--- Get SUID bit from fd
--- @param fd integer
--- @return boolean
@@ -152,10 +159,14 @@ syscall.fget_suid=function(fd) end
--- Write GPIO pin
--- @param pin integer
--- @param data number
--- @return boolean
--- @param data boolean
syscall.gpio_write=function(pin, data) end
--- Write GPIO pin analog
--- @param pin integer
--- @param data number
syscall.gpio_writeAnalog=function(pin, data) end
--- Set password for user
--- @param uid integer
--- @param newPassword string
@@ -164,7 +175,7 @@ syscall.setpassword=function(uid, newPassword) end
--- Set environment variable
--- @param key string
--- @param value string
--- @param value any
--- @return boolean
syscall.setEnviron=function(key, value) end
@@ -197,7 +208,7 @@ syscall.exit=function(code) end
--- Get environment variable
--- @param key string
--- @return string|nil
--- @return any
syscall.getEnviron=function(key) end
--- Continue a stopped task
@@ -337,7 +348,7 @@ syscall.remove=function(path) end
--- @return string|nil
syscall.type=function(path) end
--- Elevate to another user with password
--- Elevate to root with password (Disabled due to VULN)
--- @param targetUsername string
--- @param password string
--- @return boolean
@@ -374,11 +385,11 @@ syscall.setusername=function(uid, newUsername) end
--- @return integer
syscall.geteuid=function() end
--- Login user
--- @param username string
--- Login as user
--- @param uid integer
--- @param password string
--- @return boolean
syscall.login=function(username, password) end
syscall.login=function(uid, password) end
--- Get system hostname
--- @return string
@@ -514,9 +525,9 @@ syscall.access=function(path, mode) end
--- Ignore current signal
syscall.sigignore=function() end
--- Get user password hash
--- Get user information
--- @param uid integer
--- @return string|nil
--- @return userinfo|nil
syscall.getpasswd=function(uid) end
--- Get OS version

388
misc/json Normal file
View File

@@ -0,0 +1,388 @@
--:Minify:--
-- json.lua
--
-- Copyright (c) 2020 rxi
--
-- Permission is hereby granted, free of charge, to any person obtaining a copy of
-- this software and associated documentation files (the "Software"), to deal in
-- the Software without restriction, including without limitation the rights to
-- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-- of the Software, and to permit persons to whom the Software is furnished to do
-- so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in all
-- copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-- SOFTWARE.
--
local json = { _version = "0.1.2" }
-------------------------------------------------------------------------------
-- Encode
-------------------------------------------------------------------------------
local encode
local escape_char_map = {
[ "\\" ] = "\\",
[ "\"" ] = "\"",
[ "\b" ] = "b",
[ "\f" ] = "f",
[ "\n" ] = "n",
[ "\r" ] = "r",
[ "\t" ] = "t",
}
local escape_char_map_inv = { [ "/" ] = "/" }
for k, v in pairs(escape_char_map) do
escape_char_map_inv[v] = k
end
local function escape_char(c)
return "\\" .. (escape_char_map[c] or string.format("u%04x", c:byte()))
end
local function encode_nil(val)
return "null"
end
local function encode_table(val, stack)
local res = {}
stack = stack or {}
-- Circular reference?
if stack[val] then error("circular reference") end
stack[val] = true
if rawget(val, 1) ~= nil or next(val) == nil then
-- Treat as array -- check keys are valid and it is not sparse
local n = 0
for k in pairs(val) do
if type(k) ~= "number" then
error("invalid table: mixed or invalid key types")
end
n = n + 1
end
if n ~= #val then
error("invalid table: sparse array")
end
-- Encode
for i, v in ipairs(val) do
table.insert(res, encode(v, stack))
end
stack[val] = nil
return "[" .. table.concat(res, ",") .. "]"
else
-- Treat as an object
for k, v in pairs(val) do
if type(k) ~= "string" then
error("invalid table: mixed or invalid key types")
end
table.insert(res, encode(k, stack) .. ":" .. encode(v, stack))
end
stack[val] = nil
return "{" .. table.concat(res, ",") .. "}"
end
end
local function encode_string(val)
return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"'
end
local function encode_number(val)
-- Check for NaN, -inf and inf
if val ~= val or val <= -math.huge or val >= math.huge then
error("unexpected number value '" .. tostring(val) .. "'")
end
return string.format("%.14g", val)
end
local type_func_map = {
[ "nil" ] = encode_nil,
[ "table" ] = encode_table,
[ "string" ] = encode_string,
[ "number" ] = encode_number,
[ "boolean" ] = tostring,
}
encode = function(val, stack)
local t = type(val)
local f = type_func_map[t]
if f then
return f(val, stack)
end
error("unexpected type '" .. t .. "'")
end
function json.encode(val)
return ( encode(val) )
end
-------------------------------------------------------------------------------
-- Decode
-------------------------------------------------------------------------------
local parse
local function create_set(...)
local res = {}
for i = 1, select("#", ...) do
res[ select(i, ...) ] = true
end
return res
end
local space_chars = create_set(" ", "\t", "\r", "\n")
local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",")
local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u")
local literals = create_set("true", "false", "null")
local literal_map = {
[ "true" ] = true,
[ "false" ] = false,
[ "null" ] = nil,
}
local function next_char(str, idx, set, negate)
for i = idx, #str do
if set[str:sub(i, i)] ~= negate then
return i
end
end
return #str + 1
end
local function decode_error(str, idx, msg)
local line_count = 1
local col_count = 1
for i = 1, idx - 1 do
col_count = col_count + 1
if str:sub(i, i) == "\n" then
line_count = line_count + 1
col_count = 1
end
end
error( string.format("%s at line %d col %d", msg, line_count, col_count) )
end
local function codepoint_to_utf8(n)
-- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa
local f = math.floor
if n <= 0x7f then
return string.char(n)
elseif n <= 0x7ff then
return string.char(f(n / 64) + 192, n % 64 + 128)
elseif n <= 0xffff then
return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128)
elseif n <= 0x10ffff then
return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128,
f(n % 4096 / 64) + 128, n % 64 + 128)
end
error( string.format("invalid unicode codepoint '%x'", n) )
end
local function parse_unicode_escape(s)
local n1 = tonumber( s:sub(1, 4), 16 )
local n2 = tonumber( s:sub(7, 10), 16 )
-- Surrogate pair?
if n2 then
return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000)
else
return codepoint_to_utf8(n1)
end
end
local function parse_string(str, i)
local res = ""
local j = i + 1
local k = j
while j <= #str do
local x = str:byte(j)
if x < 32 then
decode_error(str, j, "control character in string")
elseif x == 92 then -- `\`: Escape
res = res .. str:sub(k, j - 1)
j = j + 1
local c = str:sub(j, j)
if c == "u" then
local hex = str:match("^[dD][89aAbB]%x%x\\u%x%x%x%x", j + 1)
or str:match("^%x%x%x%x", j + 1)
or decode_error(str, j - 1, "invalid unicode escape in string")
res = res .. parse_unicode_escape(hex)
j = j + #hex
else
if not escape_chars[c] then
decode_error(str, j - 1, "invalid escape char '" .. c .. "' in string")
end
res = res .. escape_char_map_inv[c]
end
k = j + 1
elseif x == 34 then -- `"`: End of string
res = res .. str:sub(k, j - 1)
return res, j + 1
end
j = j + 1
end
decode_error(str, i, "expected closing quote for string")
end
local function parse_number(str, i)
local x = next_char(str, i, delim_chars)
local s = str:sub(i, x - 1)
local n = tonumber(s)
if not n then
decode_error(str, i, "invalid number '" .. s .. "'")
end
return n, x
end
local function parse_literal(str, i)
local x = next_char(str, i, delim_chars)
local word = str:sub(i, x - 1)
if not literals[word] then
decode_error(str, i, "invalid literal '" .. word .. "'")
end
return literal_map[word], x
end
local function parse_array(str, i)
local res = {}
local n = 1
i = i + 1
while 1 do
local x
i = next_char(str, i, space_chars, true)
-- Empty / end of array?
if str:sub(i, i) == "]" then
i = i + 1
break
end
-- Read token
x, i = parse(str, i)
res[n] = x
n = n + 1
-- Next token
i = next_char(str, i, space_chars, true)
local chr = str:sub(i, i)
i = i + 1
if chr == "]" then break end
if chr ~= "," then decode_error(str, i, "expected ']' or ','") end
end
return res, i
end
local function parse_object(str, i)
local res = {}
i = i + 1
while 1 do
local key, val
i = next_char(str, i, space_chars, true)
-- Empty / end of object?
if str:sub(i, i) == "}" then
i = i + 1
break
end
-- Read key
if str:sub(i, i) ~= '"' then
decode_error(str, i, "expected string for key")
end
key, i = parse(str, i)
-- Read ':' delimiter
i = next_char(str, i, space_chars, true)
if str:sub(i, i) ~= ":" then
decode_error(str, i, "expected ':' after key")
end
i = next_char(str, i + 1, space_chars, true)
-- Read value
val, i = parse(str, i)
-- Set
res[key] = val
-- Next token
i = next_char(str, i, space_chars, true)
local chr = str:sub(i, i)
i = i + 1
if chr == "}" then break end
if chr ~= "," then decode_error(str, i, "expected '}' or ','") end
end
return res, i
end
local char_func_map = {
[ '"' ] = parse_string,
[ "0" ] = parse_number,
[ "1" ] = parse_number,
[ "2" ] = parse_number,
[ "3" ] = parse_number,
[ "4" ] = parse_number,
[ "5" ] = parse_number,
[ "6" ] = parse_number,
[ "7" ] = parse_number,
[ "8" ] = parse_number,
[ "9" ] = parse_number,
[ "-" ] = parse_number,
[ "t" ] = parse_literal,
[ "f" ] = parse_literal,
[ "n" ] = parse_literal,
[ "[" ] = parse_array,
[ "{" ] = parse_object,
}
parse = function(str, idx)
local chr = str:sub(idx, idx)
local f = char_func_map[chr]
if f then
return f(str, idx)
end
decode_error(str, idx, "unexpected character '" .. chr .. "'")
end
function json.decode(str)
if type(str) ~= "string" then
error("expected argument of type string, got " .. type(str))
end
local res, idx = parse(str, next_char(str, 1, space_chars, true))
idx = next_char(str, idx, space_chars, true)
if idx <= #str then
decode_error(str, idx, "trailing garbage")
end
return res
end
return json

View File

@@ -0,0 +1 @@
return{white=0xFFFFFF,red=0xFF0000,green=0x00FF00,blue=0x0000FF,cyan=0x00FFFF,yellow=0xFFFF00,purple=0xFF00FF,black=0x000000,gray=0x888888,lightgrey=0xBBBBBB,darkgrey=0x444444,orange=0xFF8800,mint=0x00FF88,brown=0xa52a2a,chocolate=0xd2691e}

View File

@@ -0,0 +1 @@
local a={}function a.open(b,c)local d=syscall.open(b,c)local e={close=function()return syscall.close(d)end,flush=function()syscall.fsync(d)end}if c=="r"then e.read=function(f)local g=syscall.read(d,f)return g end;e.readAll=function(h)local i={}while true do local j=syscall.read(d,h or 65536)if j==nil or#j==0 then break end;table.insert(i,j)end;return table.concat(i)end;e.readLine=function(h)local k={}local l=""local m=h or 65536;local n=false;while true do local o=l:find("\n")if o then local p=l:sub(1,o-1)l=l:sub(o+1)return p end;if n then if l~=""then local q=l;l=""return q else return nil end end;local j=syscall.read(d,m)if not j or j==""then n=true else l=l..j end end end elseif c=="w"then e.write=function(g)return syscall.write(d,g)end elseif c=="a"then e.write=function(g)return syscall.write(d,g)end else error("Invalid mode '"..c.."'",2)end;return e end;function a.readAllText(b)local r=a.open(b,"r")if not r then return false end;local s=r.readAll()r.close()return s end;function a.writeAllText(b,g)local r=a.open(b,"w")r.write(g)r.close()end;function a.appendAllText(b,g)local r=a.open(b,"a")if not r then return false end;r.write(g)r.close()end;function a.mkdir(b)return syscall.mkdir(b)end;function a.remove(b)return syscall.remove(b)end;function a.list(b)return syscall.listdir(b)end;function a.type(b)return syscall.type(b)end;function a.stat(b)return syscall.stat(b)end;function a.exists(b)return syscall.exists(b)end;function a.getcwd()return syscall.getcwd()end;function a.chdir(b)return syscall.chdir(b)end;function a.isDir(b)return syscall.type(b)=="directory"end;return a

View File

@@ -0,0 +1,6 @@
local io = {}
local fs = require("fs")
function io.open(path, mode)
return fs.open(path, mode)
end

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
local a=({...})[1]or"/$"local b={...}local c={keys=true,bit32=true,bit=true,ccemux=true,config=true,coroutine=true,debug=true,fs=true,http=true,mounter=true,os=true,periphemu=true,peripheral=true,redstone=true,rs=true,term=true,utf8=true,_HOST=true,_CC_DEFAULT_SETTINGS=true,_CC_DISABLE_LUA51_FEATURES=true,_VERSION=true,assert=true,collectgarbage=true,error=true,gcinfo=true,getfenv=true,getmetatable=true,ipairs=true,__inext=true,load=true,loadstring=true,math=true,newproxy=true,next=true,pairs=true,pcall=true,rawequal=true,rawget=true,rawlen=true,rawset=true,select=true,setfenv=true,setmetatable=true,string=true,table=true,tonumber=true,tostring=true,type=true,unpack=true,xpcall=true,turtle=true,pocket=true,commands=true,_G=true}local d={}for e in pairs(_G)do if not c[e]then table.insert(d,e)end end;for f,e in ipairs(d)do _G[e]=nil end;local g=_G.term.native()for f,h in ipairs{"nativePaletteColor","nativePaletteColour","screenshot"}do g[h]=_G.term[h]end;_G.term=g;if _G.http then _G.http.checkURL=_G.http.checkURLAsync;_G.http.websocket=_G.http.websocketAsync end;if _G.commands then _G.commands=_G.commands.native end;if _G.turtle then _G.turtle.native,_G.turtle.craft=nil end;local i={os={"version","pullEventRaw","pullEvent","run","loadAPI","unloadAPI","sleep"},http=_G.http and{"get","post","put","delete","patch","options","head","trace","listen","checkURLAsync","websocketAsync"},fs={"complete","isDriveRoot"}}for e,j in pairs(i)do for f,k in ipairs(j)do _G[e][k]=nil end end;local l=error;_G.error=function()end;_G.term.redirect=function()end;function _G.term.native()_G.term.native=nil;_G.term.redirect=nil;_G.error=l;term.setBackgroundColor(32768)term.setTextColor(1)term.setCursorPos(1,1)term.setCursorBlink(true)term.clear()local m=fs.open(a.."/boot/cct/boot.lua","r")if m==nil then term.setCursorBlink(false)term.setTextColor(16384)term.write("Could not find /boot/cct/boot.lua. UnBIOS cannot continue.")term.setCursorPos(1,2)term.write("Press any key to continue")coroutine.yield("key")os.shutdown()end;local n,o=loadstring(m.readAll(),"@bootloader")m.close()if n==nil then term.setCursorBlink(false)term.setTextColor(16384)term.write("Could not load /boot/cc/boot.lua. UnBIOS cannot continue.")term.setCursorPos(1,2)term.write(o)term.setCursorPos(1,3)term.write("Press any key to continue")coroutine.yield("key")os.shutdown()end;setfenv(n,_G)local p=os.shutdown;os.shutdown=function()os.shutdown=p;return n(a)end end;if debug then local function q(r,s,t,u)local v,w,x=1,debug.getupvalue(r[s],u)while w~=t and w~=nil do w,x=debug.getupvalue(r[s],v)v=v+1 end;r[s]=x or r[s]end;q(_G,"loadstring","nativeloadstring",1)q(_G,"load","nativeload",5)if http then q(http,"request","nativeHTTPRequest",3)end;q(os,"shutdown","nativeShutdown",1)q(os,"reboot","nativeReboot",1)if turtle then q(turtle,"equipLeft","v",1)q(turtle,"equipRight","v",1)end;do local v,w,x=1,debug.getupvalue(peripheral.isPresent,2)while w~="native"and w~=nil do w,x=debug.getupvalue(peripheral.isPresent,v)v=v+1 end;_G.peripheral=x or peripheral end end

View File

@@ -0,0 +1 @@
local a=({...})[1]local b=a.BOOT_DRIVE_PATH;local c=a.fs;local d=a.peripheral;local e={}local f={"top","bottom","left","right","front","back"}function e.getNames()local g={}for h=1,#f do local i=f[h]if d.isPresent(i)then table.insert(g,i)if d.hasType(i,"peripheral_hub")then local j=d.call(i,"getNamesRemote")for k,l in ipairs(j)do table.insert(g,l)end end end end;return g end;function e.isPresent(l)if d.isPresent(l)then return true end;for h=1,#f do local i=f[h]if d.hasType(i,"peripheral_hub")and d.call(i,"isPresentRemote",l)then return true end end;return false end;function e.getType(e)if type(e)=="string"then if d.isPresent(e)then return d.getType(e)end;for h=1,#f do local i=f[h]if d.hasType(i,"peripheral_hub")and d.call(i,"isPresentRemote",e)then return d.call(i,"getTypeRemote",e)end end;return nil else local m=getmetatable(e)if not m or m.__name~="peripheral"or type(m.types)~="table"then error("bad argument #1 (table is not a peripheral)",2)end;return table.unpack(m.types)end end;function e.hasType(e,n)if type(e)=="string"then if d.isPresent(e)then return d.hasType(e,n)end;for h=1,#f do local i=f[h]if d.hasType(i,"peripheral_hub")and d.call(i,"isPresentRemote",e)then return d.call(i,"hasTypeRemote",e,n)end end;return nil else local m=getmetatable(e)if not m or m.__name~="peripheral"or type(m.types)~="table"then error("bad argument #1 (table is not a peripheral)",2)end;return m.types[n]~=nil end end;function e.getMethods(l)if d.isPresent(l)then return d.getMethods(l)end;for h=1,#f do local i=f[h]if d.hasType(i,"peripheral_hub")and d.call(i,"isPresentRemote",l)then return d.call(i,"getMethodsRemote",l)end end;return nil end;function e.getName(e)local m=getmetatable(e)if not m or m.__name~="peripheral"or type(m.name)~="string"then error("bad argument #1 (table is not a peripheral)",2)end;return m.name end;function e.call(l,o,...)if d.isPresent(l)then return d.call(l,o,...)end;for h=1,#f do local i=f[h]if d.hasType(i,"peripheral_hub")and d.call(i,"isPresentRemote",l)then return d.call(i,"callRemote",l,o,...)end end;return nil end;function e.wrap(l)local p=e.getMethods(l)if not p then return nil end;local q={e.getType(l)}for r=1,#q do q[q[r]]=true end;local s=setmetatable({},{__name="peripheral",name=l,type=q[1],types=q})for k,o in ipairs(p)do s[o]=function(...)return e.call(l,o,...)end end;return s end;function e.find(t,u)local g={}for k,l in ipairs(e.getNames())do if e.hasType(l,t)then local v=e.wrap(l)if u==nil or u(l,v)then table.insert(g,v)end end end;return table.unpack(g)end;local w={}local x={}local function y(z)if not z or z==""then return"/"end;return c.combine("/",z)end;local function A(B,C,D,E)C=y(C)local F={address=B,isReadOnly=function()return D end}function F:spaceUsed()return c.getCapacity(C)-c.getFreeSpace(C)end;function F:spaceTotal()return c.getCapacity(C)end;function F:list(z)local G=c.combine(C,z)if not c.exists(G)or not c.isDir(G)then return nil,"not directory"end;return c.list(G)end;function F:fileExists(z)local G=c.combine(C,z)return c.exists(G)and not c.isDir(G)end;function F:directoryExists(z)local G=c.combine(C,z)return c.exists(G)and c.isDir(G)end;function F:type(z)local G=c.combine(C,z)if not c.exists(G)then return nil elseif c.isDir(G)then return"directory"else return"file"end end;function F:makeDirectory(z)local G=c.combine(C,z)c.makeDir(G)return true end;function F:remove(z)local G=c.combine(C,z)if c.exists(G)then c.delete(G)end;return true end;function F:setLabel(H)E.setLabel(H)end;function F:getLabel(H)return E.getLabel()end;function F:attributes(z)local G=c.combine(C,z)return c.attributes(G)end;function F:open(z,I)local G=c.combine(C,z)return c.open(G,I)end;return F end;x["$"]=A("$",b,false,{setLabel=function(H)local J=c.open("/.label","w")J.write(H)J.close()end,getLabel=function()local J=c.open("/.label","r")if not J then return"$"end;local H=J.readAll()J.close()return H end})x["rom"]=A("rom","/rom",true,{setLabel=function(H)error("Device is read-only")end,getLabel=function()return"cctrom"end})local function K()w={}for k,F in ipairs({e.find("drive")})do if F.isDiskPresent()then w[tostring(F.getDiskID())]=A("cctdisk"..tostring(F.getDiskID()),F.getMountPath(),false,c)end end end;local function L()K()local M={}for B,N in pairs(x)do M[B]=N end;for B,N in pairs(w)do M[B]=N end;return pairs(M)end;return{refresh=K,list=L}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
local a=({...})[1]or"/$"local b={...}local c={keys=true,bit32=true,bit=true,ccemux=true,config=true,coroutine=true,debug=true,fs=true,http=true,mounter=true,os=true,periphemu=true,peripheral=true,redstone=true,rs=true,term=true,utf8=true,_HOST=true,_CC_DEFAULT_SETTINGS=true,_CC_DISABLE_LUA51_FEATURES=true,_VERSION=true,assert=true,collectgarbage=true,error=true,gcinfo=true,getfenv=true,getmetatable=true,ipairs=true,__inext=true,load=true,loadstring=true,math=true,newproxy=true,next=true,pairs=true,pcall=true,rawequal=true,rawget=true,rawlen=true,rawset=true,select=true,setfenv=true,setmetatable=true,string=true,table=true,tonumber=true,tostring=true,type=true,unpack=true,xpcall=true,turtle=true,pocket=true,commands=true,_G=true}local d={}for e in pairs(_G)do if not c[e]then table.insert(d,e)end end;for f,e in ipairs(d)do _G[e]=nil end;local g=_G.term.native()for f,h in ipairs{"nativePaletteColor","nativePaletteColour","screenshot"}do g[h]=_G.term[h]end;_G.term=g;if _G.http then _G.http.checkURL=_G.http.checkURLAsync;_G.http.websocket=_G.http.websocketAsync end;if _G.commands then _G.commands=_G.commands.native end;if _G.turtle then _G.turtle.native,_G.turtle.craft=nil end;local i={os={"version","pullEventRaw","pullEvent","run","loadAPI","unloadAPI","sleep"},http=_G.http and{"get","post","put","delete","patch","options","head","trace","listen","checkURLAsync","websocketAsync"},fs={"complete","isDriveRoot"}}for e,j in pairs(i)do for f,k in ipairs(j)do _G[e][k]=nil end end;local l=error;_G.error=function()end;_G.term.redirect=function()end;function _G.term.native()_G.term.native=nil;_G.term.redirect=nil;_G.error=l;term.setBackgroundColor(32768)term.setTextColor(1)term.setCursorPos(1,1)term.setCursorBlink(true)term.clear()local m=fs.open(a.."/boot/cct/boot.lua","r")if m==nil then term.setCursorBlink(false)term.setTextColor(16384)term.write("Could not find /boot/cct/boot.lua. UnBIOS cannot continue.")term.setCursorPos(1,2)term.write("Press any key to continue")coroutine.yield("key")os.shutdown()end;local n,o=loadstring(m.readAll(),"@bootloader")m.close()if n==nil then term.setCursorBlink(false)term.setTextColor(16384)term.write("Could not load /boot/cc/boot.lua. UnBIOS cannot continue.")term.setCursorPos(1,2)term.write(o)term.setCursorPos(1,3)term.write("Press any key to continue")coroutine.yield("key")os.shutdown()end;setfenv(n,_G)local p=os.shutdown;os.shutdown=function()os.shutdown=p;return n(a)end end;if debug then local function q(r,s,t,u)local v,w,x=1,debug.getupvalue(r[s],u)while w~=t and w~=nil do w,x=debug.getupvalue(r[s],v)v=v+1 end;r[s]=x or r[s]end;q(_G,"loadstring","nativeloadstring",1)q(_G,"load","nativeload",5)if http then q(http,"request","nativeHTTPRequest",3)end;q(os,"shutdown","nativeShutdown",1)q(os,"reboot","nativeReboot",1)if turtle then q(turtle,"equipLeft","v",1)q(turtle,"equipRight","v",1)end;do local v,w,x=1,debug.getupvalue(peripheral.isPresent,2)while w~="native"and w~=nil do w,x=debug.getupvalue(peripheral.isPresent,v)v=v+1 end;_G.peripheral=x or peripheral end end

View File

@@ -0,0 +1 @@
local a=({...})[1]local b=a.BOOT_DRIVE_PATH;local c=a.fs;local d=a.peripheral;local e={}local f={"top","bottom","left","right","front","back"}function e.getNames()local g={}for h=1,#f do local i=f[h]if d.isPresent(i)then table.insert(g,i)if d.hasType(i,"peripheral_hub")then local j=d.call(i,"getNamesRemote")for k,l in ipairs(j)do table.insert(g,l)end end end end;return g end;function e.isPresent(l)if d.isPresent(l)then return true end;for h=1,#f do local i=f[h]if d.hasType(i,"peripheral_hub")and d.call(i,"isPresentRemote",l)then return true end end;return false end;function e.getType(e)if type(e)=="string"then if d.isPresent(e)then return d.getType(e)end;for h=1,#f do local i=f[h]if d.hasType(i,"peripheral_hub")and d.call(i,"isPresentRemote",e)then return d.call(i,"getTypeRemote",e)end end;return nil else local m=getmetatable(e)if not m or m.__name~="peripheral"or type(m.types)~="table"then error("bad argument #1 (table is not a peripheral)",2)end;return table.unpack(m.types)end end;function e.hasType(e,n)if type(e)=="string"then if d.isPresent(e)then return d.hasType(e,n)end;for h=1,#f do local i=f[h]if d.hasType(i,"peripheral_hub")and d.call(i,"isPresentRemote",e)then return d.call(i,"hasTypeRemote",e,n)end end;return nil else local m=getmetatable(e)if not m or m.__name~="peripheral"or type(m.types)~="table"then error("bad argument #1 (table is not a peripheral)",2)end;return m.types[n]~=nil end end;function e.getMethods(l)if d.isPresent(l)then return d.getMethods(l)end;for h=1,#f do local i=f[h]if d.hasType(i,"peripheral_hub")and d.call(i,"isPresentRemote",l)then return d.call(i,"getMethodsRemote",l)end end;return nil end;function e.getName(e)local m=getmetatable(e)if not m or m.__name~="peripheral"or type(m.name)~="string"then error("bad argument #1 (table is not a peripheral)",2)end;return m.name end;function e.call(l,o,...)if d.isPresent(l)then return d.call(l,o,...)end;for h=1,#f do local i=f[h]if d.hasType(i,"peripheral_hub")and d.call(i,"isPresentRemote",l)then return d.call(i,"callRemote",l,o,...)end end;return nil end;function e.wrap(l)local p=e.getMethods(l)if not p then return nil end;local q={e.getType(l)}for r=1,#q do q[q[r]]=true end;local s=setmetatable({},{__name="peripheral",name=l,type=q[1],types=q})for k,o in ipairs(p)do s[o]=function(...)return e.call(l,o,...)end end;return s end;function e.find(t,u)local g={}for k,l in ipairs(e.getNames())do if e.hasType(l,t)then local v=e.wrap(l)if u==nil or u(l,v)then table.insert(g,v)end end end;return table.unpack(g)end;local w={}local x={}local function y(z)if not z or z==""then return"/"end;return c.combine("/",z)end;local function A(B,C,D,E)C=y(C)local F={address=B,isReadOnly=function()return D end}function F:spaceUsed()return c.getCapacity(C)-c.getFreeSpace(C)end;function F:spaceTotal()return c.getCapacity(C)end;function F:list(z)local G=c.combine(C,z)if not c.exists(G)or not c.isDir(G)then return nil,"not directory"end;return c.list(G)end;function F:fileExists(z)local G=c.combine(C,z)return c.exists(G)and not c.isDir(G)end;function F:directoryExists(z)local G=c.combine(C,z)return c.exists(G)and c.isDir(G)end;function F:type(z)local G=c.combine(C,z)if not c.exists(G)then return nil elseif c.isDir(G)then return"directory"else return"file"end end;function F:makeDirectory(z)local G=c.combine(C,z)c.makeDir(G)return true end;function F:remove(z)local G=c.combine(C,z)if c.exists(G)then c.delete(G)end;return true end;function F:setLabel(H)E.setLabel(H)end;function F:getLabel(H)return E.getLabel()end;function F:attributes(z)local G=c.combine(C,z)return c.attributes(G)end;function F:open(z,I)local G=c.combine(C,z)return c.open(G,I)end;return F end;x["$"]=A("$",b,false,{setLabel=function(H)local J=c.open("/.label","w")J.write(H)J.close()end,getLabel=function()local J=c.open("/.label","r")if not J then return"$"end;local H=J.readAll()J.close()return H end})x["rom"]=A("rom","/rom",true,{setLabel=function(H)error("Device is read-only")end,getLabel=function()return"cctrom"end})local function K()w={}for k,F in ipairs({e.find("drive")})do if F.isDiskPresent()then w[tostring(F.getDiskID())]=A("cctdisk"..tostring(F.getDiskID()),F.getMountPath(),false,c)end end end;local function L()K()local M={}for B,N in pairs(x)do M[B]=N end;for B,N in pairs(w)do M[B]=N end;return pairs(M)end;return{refresh=K,list=L}

View File

@@ -0,0 +1 @@
local a=...a.cct={}a.cct.peripheral={}local b=a.cct.peripheral;local c=a.apis;local d=c.peripheral;local e={"top","bottom","left","right","front","back"}function b.getNames()local f={}for g=1,#e do local h=e[g]if d.isPresent(h)then table.insert(f,h)if d.hasType(h,"peripheral_hub")then local i=d.call(h,"getNamesRemote")for j,k in ipairs(i)do table.insert(f,k)end end end end;return f end;function b.isPresent(k)if d.isPresent(k)then return true end;for g=1,#e do local h=e[g]if d.hasType(h,"peripheral_hub")and d.call(h,"isPresentRemote",k)then return true end end;return false end;function b.getType(b)if type(b)=="string"then if d.isPresent(b)then return d.getType(b)end;for g=1,#e do local h=e[g]if d.hasType(h,"peripheral_hub")and d.call(h,"isPresentRemote",b)then return d.call(h,"getTypeRemote",b)end end;return nil else local l=getmetatable(b)if not l or l.__name~="peripheral"or type(l.types)~="table"then error("bad argument #1 (table is not a peripheral)",2)end;return table.unpack(l.types)end end;function b.hasType(b,m)if type(b)=="string"then if d.isPresent(b)then return d.hasType(b,m)end;for g=1,#e do local h=e[g]if d.hasType(h,"peripheral_hub")and d.call(h,"isPresentRemote",b)then return d.call(h,"hasTypeRemote",b,m)end end;return nil else local l=getmetatable(b)if not l or l.__name~="peripheral"or type(l.types)~="table"then error("bad argument #1 (table is not a peripheral)",2)end;return l.types[m]~=nil end end;function b.getMethods(k)if d.isPresent(k)then return d.getMethods(k)end;for g=1,#e do local h=e[g]if d.hasType(h,"peripheral_hub")and d.call(h,"isPresentRemote",k)then return d.call(h,"getMethodsRemote",k)end end;return nil end;function b.getName(b)local l=getmetatable(b)if not l or l.__name~="peripheral"or type(l.name)~="string"then error("bad argument #1 (table is not a peripheral)",2)end;return l.name end;function b.call(k,n,...)if d.isPresent(k)then return d.call(k,n,...)end;for g=1,#e do local h=e[g]if d.hasType(h,"peripheral_hub")and d.call(h,"isPresentRemote",k)then return d.call(h,"callRemote",k,n,...)end end;return nil end;function b.wrap(k)local o=b.getMethods(k)if not o then return nil end;local p={b.getType(k)}for q=1,#p do p[p[q]]=true end;local r=setmetatable({},{__name="peripheral",name=k,type=p[1],types=p})for j,n in ipairs(o)do r[n]=function(...)return b.call(k,n,...)end end;return r end;function b.find(s,t)local f={}for j,k in ipairs(b.getNames())do if b.hasType(k,s)then local u=b.wrap(k)if t==nil or t(k,u)then table.insert(f,u)end end end;return table.unpack(f)end

View File

@@ -0,0 +1 @@
local a=...local b=a.cct.peripheral;local c={[0xFFFFFF]=0x0001,[0xFF0000]=0x0002,[0x00FF00]=0x0004,[0x0000FF]=0x0008,[0x00FFFF]=0x0010,[0xFF00FF]=0x0020,[0xFFFF00]=0x0040,[0xFF6D00]=0x0080,[0x6DFF55]=0x0100,[0x24FFFF]=0x0200,[0x924900]=0x0400,[0x6D6D55]=0x0800,[0xDBDBAA]=0x1000,[0x6D00FF]=0x2000,[0xB6FF00]=0x4000,[0x000000]=0x8000}local d={0xFFFFFF,0xFF0000,0x00FF00,0x0000FF,0x00FFFF,0xFF00FF,0xFFFF00,0xFF6D00,0x6DFF55,0x24FFFF,0x924900,0x6D6D55,0xDBDBAA,0x6D00FF,0xB6FF00,0x000000}local e,f=0x6D6D55,0x000000;local g,h,i,j={},{},{},0;local function k(l,m)local n=nil;local o=math.huge;for p,q in pairs(l)do if p==m then return p end;local r=math.abs(p-m)if r<o then o=r;n=p end end;return n end;local function s(t)j=j+1;if j%1024==0 then h={}g={}end;if j%8192==0 then i={}end;if i[t]~=nil then return i[t]end;if h[t]~=nil then g[t]=g[t]+1;if g[t]>=16 then i[t]=h[t]h[t]=nil;g[t]=nil;return i[t]end;return h[t]end;local u=k(c,t)if not u then return nil end;local v=c[u]h[t]=v;g[t]=1;return v end;local function w(x,y)local z,A=y.getCursorPos()local B,C=y.getSize()for D=1,#x do local E=x:sub(D,D)if E=="\n"then A=A+1;z=1 elseif E=="\t"then local F=4;local G=F-(z-1)%F;y.write(string.rep(" ",G))z=z+G elseif E=="\b"then if z>1 then z=z-1;y.setCursorPos(z,A)y.write(" ")y.setCursorPos(z,A)end else if z<=B and A<=C then y.setCursorPos(z,A)y.write(E)z=z+1 end end;if z>B then z=1;A=A+1 end;if A-1>=C then y.scroll(1)A=C;y.setCursorPos(z,A)end end;y.setCursorPos(z,A)end;a.devfs.data.tty={}a.cct.ctrl,a.cct.alt=false,false;local function H(I)if I then return"T"else return"F"end end;local function J(K,L,M)K.setPaletteColor(0x1,0xFFFFFF)K.setPaletteColor(0x2,0xFF0000)K.setPaletteColor(0x4,0x00FF00)K.setPaletteColor(0x8,0x0000FF)K.setPaletteColor(0x10,0x00FFFF)K.setPaletteColor(0x20,0xFF00FF)K.setPaletteColor(0x40,0xFFFF00)K.setPaletteColor(0x80,0xFF6D00)K.setPaletteColor(0x100,0x6DFF55)K.setPaletteColor(0x200,0x24FFFF)K.setPaletteColor(0x400,0x924900)K.setPaletteColor(0x800,0x6D6D55)K.setPaletteColor(0x1000,0xDBDBAA)K.setPaletteColor(0x2000,0x6D00FF)K.setPaletteColor(0x4000,0xB6FF00)K.setPaletteColor(0x8000,0x000000)a.devfs.data["tty"][L]=function(N,O)if N=="type"then return"Terminal"elseif N=="open"then local C={read=function(P)local Q=""for D=1,P or 1 do local R={M()}if R[1]then Q=Q..R[1]end end;if Q==""then Q=nil end;return Q end,write=function(S)w(S,K)end,size=function()local T={K.getSize()}return table.concat(T,";")end,clear=function()K.clear()K.setCursorPos(1,1)end,gpos=function()local T={K.getCursorPos()}return table.concat(T,";")end,spos=function(z,A)return K.setCursorPos(z,A)end,sfgc=function(E)e=E;return K.setTextColor(s(E))end,sbgc=function(E)f=E;return K.setBackgroundColor(s(E))end,gfgc=function()return e end,gbgc=function()return f end,gctrl=function()return H(a.cct.ctrl)..";"..H(a.cct.alt)end,gplt=function()return d end}if O=="rw"then return C elseif O=="r"then C["write"]=nil;return C elseif O=="w"then C["read"]=nil;return C end end end end;local U=a.newFifo()a.cct.fifo=U;J(a.apis.term,"1",U.pop)for D,V in ipairs({b.find("monitor")})do V.setTextScale(.5)V.write("Initializing...")J(V,tostring(D+1),function()end)end

View File

@@ -0,0 +1 @@
local a=...local b=a.apis.keys;a.processes.cctdeamon=function()local c=false;while true do local d={a.EFI:getMachineEvent()}if d[1]then local e=d[1]local f=d[3]local g={[b.a]=1,[b.b]=2,[b.c]=3,[b.d]=4,[b.e]=5,[b.f]=6,[b.g]=7,[b.h]=8,[b.i]=9,[b.j]=10,[b.k]=11,[b.l]=12,[b.m]=13,[b.n]=14,[b.o]=15,[b.p]=16,[b.q]=17,[b.r]=18,[b.s]=19,[b.t]=20,[b.u]=21,[b.v]=22,[b.w]=23,[b.x]=24,[b.y]=25,[b.z]=26}if e=="keyPressed"then if f==b.leftCtrl or f==b.rightCtrl then a.cct.ctrl=true elseif f==b.leftAlt or f==b.rightAlt then a.cct.alt=true end;if a.cct.ctrl then local h=g[f]if h then if h==3 then for i,j in ipairs(syscall.getTasks())do syscall.sigsend(j,1)end else a.cct.fifo.push(string.char(h))end end else local k={[b.up]="",[b.down]="",[b.right]="",[b.left]="",[b.home]="",[b["end"]]="",[b.pageUp]="[5~",[b.pageDown]="[6~",[b.delete]="[3~"}local l=k[f]if l then a.cct.fifo.push(l)end end elseif e=="keyReleased"then if f==b.leftCtrl or f==b.rightCtrl then a.cct.ctrl=false elseif f==b.leftAlt or f==b.rightAlt then a.cct.alt=false end elseif e=="keyTyped"then if f then a.cct.fifo.push(f)end elseif e=="http_success"then a.cct.httpqueue[d[2]]=nil;a.cct.httpresponse[d[2]]=d[3]elseif e=="http_failure"then a.cct.httpqueue[d[2]]=nil;a.cct.httperror[d[2]]=d[3]end;c=false else c=true end;if c then sleep(0.05)end end end

View File

@@ -0,0 +1 @@
local a=...local b=a.apis.rs;local c={top=1,bottom=2,left=3,right=4,front=5,back=6}local function d(e)return function(f,g)if f=="w"then if type(g)~="boolean"then error("data: expected bool")end;b.setOutput(e,g)elseif f=="wa"then if type(g)~="number"then error("data: expected bool")end;b.setAnalogOutput(e,g)elseif f=="r"then return b.getInput(e)elseif f=="ra"then return b.getAnalogInput(e)end end end;for e,h in pairs(c)do local i=d(e)a.gpio[e]=i;a.gpio[h]=i end

View File

@@ -0,0 +1,41 @@
local lua = {
coroutine = true,
debug = true,
_HOST = true,
_VERSION = true,
assert = true,
collectgarbage = true,
error = true,
gcinfo = true,
getfenv = true,
getmetatable = true,
ipairs = true,
__inext = true,
load = true,
math = true,
next = true,
pairs = true,
pcall = true,
rawequal = true,
rawget = true,
rawlen = true,
rawset = true,
select = true,
setfenv = true,
setmetatable = true,
string = true,
table = true,
tonumber = true,
tostring = true,
type = true,
xpcall = true,
_G=true
}
local apis={}
for i,v in pairs(_G) do
if not lua[i] or lua[i]==nil then
apis[i]=v
_G[i]=nil
end
end

View File

@@ -0,0 +1,18 @@
checkArg=nil
local oldcomputer=computer
_G.computer=nil
local os=os
_G.os=nil
function component.wrap(address)
local methods=oldcomponent.methods(address)
local object={}
for _,method in ipairs(methods) do
object[method]=function(_,...)
return oldcomponent.invoke(address,method,...)
end
end
return object
end
local

View File

@@ -0,0 +1 @@
local fs={}

View File

@@ -0,0 +1,4 @@
U $;/
U devfs0000;/dev/
U tmpfs0000;/tmp/
U procfs0000;/proc/

View File

@@ -0,0 +1,84 @@
-- :Minify:--
local fs = {}
local disks = {}
local mounts = {}
local function resolve(path)
local mountPoint = "/"
for mount, disk in pairs(mounts) do
if path:sub(1, #mount) == mount then
if not mountPoint or #mount > #mountPoint then
mountPoint = mount
end
end
end
local newPath = path:sub(#mountPoint + 1)
return disks[mounts[mountPoint]], newPath
end
function fs.update(initdisks)
disks = {}
for k, v in initdisks.list() do disks[k] = v end
end
function fs.exists(path)
local disk, newPath = resolve(path)
return disk:directoryExists(newPath) or disk:fileExists(newPath)
end
function fs.isFile(path)
local disk, newPath = resolve(path)
return disk:fileExists(newPath)
end
function fs.isDir(path)
local disk, newPath = resolve(path)
return disk:directoryExists(newPath)
end
function fs.list(path)
local disk, newPath = resolve(path)
return disk:list(newPath)
end
function fs.makeDir(path)
local disk, newPath = resolve(path)
return disk:makeDirectory(newPath)
end
function fs.remove(path)
local disk, newPath = resolve(path)
return disk:remove(newPath)
end
function fs.readAllText(path)
local disk, newPath = resolve(path)
local handle = disk:open(newPath, "r")
if not handle then return nil end
local content = handle.readAll()
handle.close()
return content
end
function fs.writeAllText(path, text)
local disk, newPath = resolve(path)
local handle = disk:open(newPath, "w")
handle.write(text)
handle.close()
end
function fs.appendAllText(path, text)
local disk, newPath = resolve(path)
local handle = disk:open(newPath, "a")
handle.write(text)
handle.close()
end
function fs.load(path) return load(fs.readAllText(path), path) end
function fs.mount(disk, mountPoint)
if not disks[disk] then return end
mounts[mountPoint] = disk
end
return fs

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,12 @@
-- DO NOT EDIT THIS FILE IF YOU DO NOT KNOW WHAT YOU ARE DOING!
-- DOING SO MAY RENDER YOUR SYSTEM UNBOOTABLE!
-- This file is auto-generated during the build process.
-- DEFAULT BOOT CONFIGURATION FILE
return {
initPath = "/sbin/init",
maxOpenFiles = 128,
maxFilesPerTask = 16,
preempt=true,
logTaskExit=true
}

View File

@@ -0,0 +1 @@
0:0:root:/root:/bin/hysh

View File

@@ -0,0 +1 @@
local a=...a.allowGlobalOverwrites=true;function string.hasSuffix(b,c)return string.sub(b,#c+1)==c end;function string.hasPrefix(b,d)return string.sub(b,1,#d)==d end;function string.getSuffix(b,d)return string.sub(b,#d+1)end;function string.getPrefix(b,c)return string.sub(b,1,#c)end;function string.join(b,...)return table.concat(table.pack(b,...))end;function string.delim(b,...)return table.concat(table.pack(...),b)end;function string.split(b,e,f)assert(#e==1,"only delim len 1 supported for now")if not b then return false end;f=(f or 0)-1;local g={}local h=""for i=1,#b do local j=string.sub(b,i,i)if#g~=f and j==e then table.insert(g,h)h=""else h=h..j end end;table.insert(g,h)return g end;function table.deepcopy(k,l)l=l or{}if type(k)~='table'then return k elseif l[k]then return l[k]end;local m={}l[k]=m;for n,o in next,k,nil do local p=table.deepcopy(n,l)local q=table.deepcopy(o,l)m[p]=q end;return m end;function table.hasKey(r,s)for i,o in pairs(r)do if i==s then return o end end;return false end;function table.hasVal(r,s)for i,o in pairs(r)do if o==s then return i end end;return false end;local function t(u,v)v=v or{}if v[u]then return'"[Circular Reference]"'end;v[u]=true;local w="{"local x=true;for i,o in pairs(u)do if not x then w=w..","end;x=false;if type(i)=="string"then w=w.."[\""..i.."\"]="elseif type(i)=="number"then w=w.."["..tostring(i).."]="end;if type(o)=="table"then w=w..t(o,v)elseif type(o)=="string"then w=w.."[=["..o.."]=]"elseif type(o)=="number"or type(o)=="boolean"then w=w..tostring(o)elseif type(o)=="function"then w=w.."\""..tostring(o).."\""elseif type(o)=="thread"then w=w.."\""..tostring(o).."\""else error("serialization of type \""..type(o).."\" is not supported")end end;v[u]=nil;w=w.."}"return w end;local y=type;local z=getmetatable;function type(A,B)if B then return y(A)end;if y(A)~="table"then return y(A)else if y(z(A))=="table"then local C=z(A)if C.__type then return C.__type end else return"table"end end end;function getmetatable(A)if y(A)~="table"then return end;if y(z(A))=="table"then if z(A).__isuserdata then if y(z(A).__usermeta)=="function"then return z(A).__usermeta()else return z(A).__usermeta end else return z(A)end else return z(A)end end;function isEqualToAny(D,...)local E={...}for i=0,#E do if D==E[i]then return true end end;return false end;function isEqualToAll(D,...)local E={...}for i=0,#E do if D~=E[i]then return false end end;return true end;function table.keys(F)local D={}for G in pairs(F)do table.insert(D,G)end;return D end;function table.values(F)local D={}for H,G in pairs(F)do table.insert(D,G)end;return D end;function table.indexOf(F,I)for i,o in ipairs(F)do if o==I then return i end end;return-1 end;function table.merge(...)local E={...}local J={}local K={}for H,F in ipairs(E)do for i,o in pairs(F)do J[i]=o end;for i,o in ipairs(F)do K[#K+1]=o end end;for i,o in ipairs(K)do J[i]=o end;return J end;function string.replace(L,M,N)local O={}local i=1;local G=#L;local P=#M;while i<=G do local Q=true;if i+P-1<=G then for R=1,P do if L:sub(i+R-1,i+R-1)~=M:sub(R,R)then Q=false;break end end else Q=false end;if Q then table.insert(O,N)i=i+P else table.insert(O,L:sub(i,i))i=i+1 end end;return table.concat(O)end;function toHex(S)return string.format("%X",S)end;local function T()local U={}return setmetatable(U,{__index=function(self,V)local W=rawget(self,V)if W~=nil then return W end;return function(...)local X=table.pack(coroutine.yield("syscall",V,...))if X[1]then return table.unpack(X,2,X.n)else error(X[2],2)end end end,__newindex=function(self,n,o)rawset(self,n,o)end,__metatable=false})end;syscall=T()_makeSyscallProxy=T;table.serialize=t

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
local a=...local b={}a.searchpaths={"/lib/?.lua","/lib/?","/usr/lib/?.lua","/usr/lib/?","/usr/local/lib/?.lua","/usr/local/lib/?","?.lua","?"}function require(c,...)if b[c]then return b[c]end;local d=c:gsub("%.","/")local e={}for f,g in ipairs(a.searchpaths)do local h=string.replace(g,"?",d)if h:sub(1,1)~="/"then h=a.currentTask.cwd..h end;if a.vfs.exists(h)then if a.vfs.type(h)=="directory"then h=h.."/init"end;if a.vfs.exists(h)then local i=a.vfs.open(h,"r")local j=a.vfs.read(i,1024*1024*4)a.vfs.close(i)return assert(load(j,h,"t",a._U))(...)else table.insert(e,h)end else table.insert(e,h)end end;error("Module not found: "..c.." (searched paths: "..table.concat(e,", ")..")")end

View File

@@ -0,0 +1 @@
local a=...local b={}local c={}b.address="devfs0000"b.isvirt=true;b.isReadOnly=function()return false end;b.spaceUsed=function()return 0 end;b.spaceTotal=function()return 0 end;b.makeDirectory=function()error("EACCES")end;b.remove=function()error("EACCES")end;b.setLabel=function()error("EACCES")end;b.getLabel=function()return"devfs"end;b.attributes=function(d)return{size=0,modified=0,created=0}end;function b:open(d,e)local f=a.vfs.splitPath(d)local g=c;for h=1,#f-1 do local i=g[f[h]]if type(i)~="table"then error("ENFILE")end;g=i end;if type(g[f[#f]])=="function"then return g[f[#f]]("open",e)end;error("ENFILE")end;function b:type(d,e)local f=a.vfs.splitPath(d)local g=c;if#f==0 then return"directory"end;for h=1,#f-1 do local i=g[f[h]]if type(i)~="table"then error("ENFILE")end;g=i end;if type(g[f[#f]])=="function"then return g[f[#f]]("type",e)end;if type(g[f[#f]])=="table"then return"directory"end;error(type(g[f[#f]]))end;function b:list(d)local f=a.vfs.splitPath(d)local g=c;if#f==0 then return table.keys(c)end;for h=1,#f-1 do local i=g[f[h]]if type(i)~="table"then error("ENOENT")end;g=i end;if type(g[f[#f]])=="table"then return table.keys(g[f[#f]])end;error("ENOENT")end;function b:fileExists(d)local j=pcall(function()return self:type(d)end)return j end;function c.random(k,e)if k=="type"then return"character device"elseif k=="open"then if e=="r"then return{read=function(l)local m=""for h=1,l or 1 do m=m..string.char(math.random(0,255))end;return m end}elseif e=="w"or e=="a"then return{write=function()end}else error("EACCES")end end end;function c.null(k,e)if k=="type"then return"character device"elseif k=="open"then if e=="r"then return{read=function(l)end}elseif e=="w"or e=="a"then return{write=function()end}else error("EACCES")end end end;function c.zero(k,e)if k=="type"then return"character device"elseif k=="open"then if e=="r"then return{read=function(l)local m=""for h=1,l or 1 do m=m..string.char(0)end;return m end}elseif e=="w"or e=="a"then return{write=function()end}else error("EACCES")end end end;if a.EFI:getEEPROM()then function c.eeprom(k,e)if k=="type"then return"character device"elseif k=="open"then if e=="r"then local n,o=1,a.EFI:getEEPROM()return{read=function(l)n=n+l;return o:sub(n-l,n)end}elseif e=="w"then if a.uid~=0 then error("EACCES")end;local p=true;return{write=function(c)if p then a.EFI:setEEPROM(c)else a.EFI:setEEPROM(a.EFI:getEEPROM()..c)end end}elseif e=="a"then if a.uid~=0 then error("EACCES")end;return{write=function(c)a.EFI:setEEPROM(a.EFI:getEEPROM()..c)end}else error("EACCES")end end end end;if a.EFI:getNvram()then function c.nvram(k,e)if k=="type"then return"character device"elseif k=="open"then if e=="r"then local n,q=1,a.EFI:getNvram()return{read=function(l)n=n+l;return q:sub(n-l,n)end}elseif e=="w"then if a.uid~=0 then error("EACCES")end;local p=true;return{write=function(c)if p then a.EFI:setNvram(c)else a.EFI:setNvram(a.EFI:getNvram()..c)end end}elseif e=="a"then if a.uid~=0 then error("EACCES")end;return{write=function(c)a.EFI:setNvram(a.EFI:getNvram()..c)end}else error("EACCES")end end end end;c["disk"]={}a.devfs={}a.devfs.data=c;a.devfs.proxy=b;a.disks["devfs0000"]=b

View File

@@ -0,0 +1 @@
local a=...local b={}local c={}b.address="procfs0000"b.isvirt=true;b.isReadOnly=function()return true end;b.spaceUsed=function()return 0 end;b.spaceTotal=function()return 0 end;b.makeDirectory=function()error("EACCES")end;b.remove=function()error("EACCES")end;b.setLabel=function()error("EACCES")end;b.getLabel=function()return"procfs"end;b.attributes=function(d)return{size=0,modified=0,created=0}end;local function e(f,g)g=g or{}local h=g.uid or 0;local i=g.gid or 0;local j=g.perms or 0x3F;local k={}table.insert(k,string.char(0x02))for d,l in pairs(f)do local m=d;local n=#m;if n>255 then error("Filename too long (>255 bytes): "..m)end;local o=0x00;local p=""if l and l~=""then o=0x01;p=l end;local q=#p;if q>255 then error("cmeta too long (>255 bytes) for "..m)end;table.insert(k,string.char(n))table.insert(k,m)table.insert(k,string.char(o))table.insert(k,string.char(h%256,math.floor(h/256)%256))table.insert(k,string.char(i%256,math.floor(i/256)%256))table.insert(k,string.char(j%256,math.floor(j/256)%256))table.insert(k,string.char(q))if q>0 then table.insert(k,p)end end;return table.concat(k)end;local function r(s,t)return function(u,v)if u=="type"then return"character device"elseif u=="open"then if v=="r"then return{read=s}elseif v=="w"then return{write=t}end end end end;local function w(x)local y=tostring(x)local z=1;return r(function(A)z=z+A;return y:sub(z-A,z)end,function()error("EACCES")end)end;local function B(C)local D,E,F={},{},{}if C.fd[0]then D["0"]=C.fd[0].path end;for G,H in ipairs(C.fd)do D[tostring(G)]=tostring(H.path)end;for G,H in ipairs(C.siblings)do E[tostring(H.pid)]="/proc/"..tostring(H.pid)end;for G,H in ipairs(C.children)do F[tostring(H.pid)]="/proc/"..tostring(H.pid)end;return{[".meta"]=w(e({cwd=C.cwd,parent="/proc/"..tostring(C.parent.pid)})),uid=w(C.uid),comm=w(C.name),fd={[".meta"]=w(e(D))},siblings={[".meta"]=w(e(E))},children={[".meta"]=w(e(F))}}end;function b:open(d,v)local I=a.vfs.splitPath(d)local J=c;if tonumber(I[1])then local C=a.tasks[tostring(I[1])]local J=B(C)for G=2,#I-1 do local y=J[I[G]]if type(y)~="table"then error("ENFILE")end;J=y end;if type(J[I[#I]])=="function"then return J[I[#I]]("open",v)end elseif tostring(I[1])=="self"then local C=a.currentTask;local J=B(C)for G=2,#I-1 do local y=J[I[G]]if type(y)~="table"then error("ENFILE")end;J=y end;if type(J[I[#I]])=="function"then return J[I[#I]]("open",v)end else for G=1,#I-1 do local y=J[I[G]]if type(y)~="table"then error("ENFILE")end;J=y end;if type(J[I[#I]])=="function"then return J[I[#I]]("open",v)end end;error("ENFILE")end;function b:type(d,v)local I=a.vfs.splitPath(d)local J=c;if#I==0 then return"directory"end;if tonumber(I[1])then local C=a.tasks[I[1]]if#I==1 then return"directory"end;local J=B(C)for G=2,#I-1 do local y=J[I[G]]if type(y)~="table"then error("ENFILE")end;J=y end;if type(J[I[#I]])=="function"then return J[I[#I]]("type",v)end;if type(J[I[#I]])=="table"then return"directory"end elseif tostring(I[1])=="self"then local C=a.currentTask;if#I==1 then return"directory"end;local J=B(C)for G=2,#I-1 do local y=J[I[G]]if type(y)~="table"then error("ENFILE")end;J=y end;if type(J[I[#I]])=="function"then return J[I[#I]]("type",v)end;if type(J[I[#I]])=="table"then return"directory"end else for G=1,#I-1 do local y=J[I[G]]if type(y)~="table"then error("ENFILE")end;J=y end;if type(J[I[#I]])=="function"then return J[I[#I]]("type",v)end;if type(J[I[#I]])=="table"then return"directory"end end;error("ENOENT")end;function b:list(d)local I=a.vfs.splitPath(d)local J=c;if#I==0 then return table.merge(table.keys(c),table.keys(a.tasks),{"self"})end;if tonumber(I[1])then local C=a.tasks[I[1]]local J=B(C)if#I==1 then return table.keys(J)end;for G=2,#I-1 do local y=J[I[G]]if type(y)~="table"then error("ENOENT")end;J=y end;if type(J[I[#I]])=="table"then return table.keys(J[I[#I]])end elseif tostring(I[1])=="self"then local C=a.currentTask;local J=B(C)if#I==1 then return table.keys(J)end;for G=2,#I-1 do local y=J[I[G]]if type(y)~="table"then error("ENOENT")end;J=y end;if type(J[I[#I]])=="table"then return table.keys(J[I[#I]])end else for G=1,#I-1 do local y=J[I[G]]if type(y)~="table"then error("ENOENT")end;J=y end;if type(J[I[#I]])=="table"then return table.keys(J[I[#I]])end end;error("ENOENT")end;function b:fileExists(d)local K=pcall(function()return self:type(d)end)return K end;c.uptime=r(function()return tostring(a.EFI:getUptime())end,function()error("EACCES")end)a.procfs={}a.procfs.data=c;a.procfs.proxy=b;a.disks["procfs0000"]=b

View File

@@ -0,0 +1 @@
local a=...local b={}local c={}b.address="tmpfs0000"b.isvirt=true;b.isReadOnly=function()return false end;b.spaceUsed=function()return 0 end;b.spaceTotal=function()return 0 end;b.makeDirectory=function(d,e)local f=a.vfs.splitPath(e)local g=c;for h=1,#f do if not g[f[h]]then g[f[h]]={}elseif type(g[f[h]])~="table"then error("ENOTDIR")end;g=g[f[h]]end end;b.remove=function(d,e)local f=a.vfs.splitPath(e)local g=c;for h=1,#f-1 do g=g[f[h]]if not g then error("ENOENT")end end;g[f[#f]]=nil end;b.setLabel=function(d,i)end;b.getLabel=function()return"tmpfs"end;b.attributes=function(d,e)local f=a.vfs.splitPath(e)local g=c;for h=1,#f do g=g[f[h]]if not g then error("ENOENT")end end;return{size=type(g)=="string"and#g or 0,modified=0,created=0}end;function b:open(e,j)local f=a.vfs.splitPath(e)local g=c;for h=1,#f-1 do if not g[f[h]]then if j=="w"then g[f[h]]={}else error("ENOENT")end elseif type(g[f[h]])~="table"then error("ENOTDIR")end;g=g[f[h]]end;local k=f[#f]if j=="r"then if type(g[k])~="string"then error("ENOENT")end;local l=g[k]local m=1;return{read=function(n)n=n or#l;local o=l:sub(m,m+n-1)m=m+#o;return o end,close=function()end}elseif j=="w"then g[k]=""local p={}return{write=function(q)p[#p+1]=q end,close=function()g[k]=table.concat(p)end}elseif j=="a"then if type(g[k])~="string"then g[k]=""end;return{write=function(q)g[k]=g[k]..q end,close=function()end}else error("EACCES")end end;function b:type(e)local f=a.vfs.splitPath(e)local g=c;if#f==0 then return"directory"end;for h=1,#f do g=g[f[h]]if not g then return false end end;if type(g)=="table"then return"directory"end;if type(g)=="string"then return"file"end end;function b:list(e)local f=a.vfs.splitPath(e)local g=c;for h=1,#f do g=g[f[h]]if not g then error("ENOENT")end end;if type(g)~="table"then error("ENOTDIR")end;local r={}for s,d in pairs(g)do table.insert(r,s)end;return r end;function b:fileExists(e)local t=self:type(e)return t=="file"or t=="directory"end;a.disks["tmpfs0000"]=b

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
local a=...local function b(c)local d,e=1,#c;while d<=e and(c:sub(d,d)==" "or c:sub(d,d)=="\t")do d=d+1 end;while e>=d and(c:sub(e,e)==" "or c:sub(e,e)=="\t"or c:sub(e,e)=="\n"or c:sub(e,e)=="\r")do e=e-1 end;if d>e then return""end;return c:sub(d,e)end;for f,g in ipairs(string.split(a.fstab,"\n"))do g=b(g)if g~=""and g:sub(1,1)=="U"then local h;for i=3,#g do if g:sub(i,i)==";"then h=i;break end end;if not h or h==3 then a.log("Invalid fstab line: "..g.." ... Skipping.","WARN",0xFF8800)else local j=g:sub(3,h-1)local k=b(g:sub(h+1))a.log("Mounted "..j.." to "..k)if j~="$"then a.vfs.mount(k,j)end end end end

View File

@@ -0,0 +1 @@
local a=...local b={}a.signal=b;function b.sigsend(c,d)if d<0 or d>256 then error("EINVAL")end;local e=a.tasks[tostring(c)]if not e then error("ENOENT")end;if not e.sigq then return end;e.sigq[#e.sigq+1]=d end;function b.sigcatch(f)local e=a.currentTask;e.sigh=f;if not e.sigq then e.sigq={}end;local g={error="",active=true}if e.sigd then e.sigd.active=false end;e.sigd=g;return g end;function b.sigignore()local e=a.currentTask;e.sigh=nil;e.sigq=nil;if e.sigd then e.sigd.active=false end;e.sigd=nil end;local h=a.syscalls;h["sigsend"]=b.sigsend;h["sigcatch"]=b.sigcatch;h["sigignore"]=b.sigignore

View File

@@ -0,0 +1 @@
local a=...local b={}b.handlers={}a.socket=b;function b.registerProtocal(c,d)b.handlers[c]=d end;function b.socket()local e=a.vfs.P;local f=a.newFifo()local g=false;a.vfs.newfd({handle={read=function()if g then error("ECCON")end;return f.read()end,write=function()if g then error("ECCON")end;return f.write()end,close=function()g=true end},type="socket",refcount=1,meta={owner=a.currentTask.uid,group=a.currentTask.uid,etype=2,perms=e.OWNER_R+e.OWNER_W+e.GROUP_R+e.GROUP_W},isvirt=true})end;function b.connect(h,i)end;function b.listen(h,j)end;a.log("Loaded socket module")

View File

@@ -0,0 +1 @@
local a=...a.unixSockets={}

View File

@@ -0,0 +1 @@
local a={...}local b=a[1]b._G=_G;local function c(d)return setmetatable({},{__index=function(e,f)local g=d[f]if type(g)=="table"then return c(g)end;return g end,__newindex=function(h,i,j)if b.config.allowGlobalOverwrites or b.allowGlobalOverwrites then rawset(d,i,j)return end;error("Attempt to modify global variable '"..i.."'",2)end,__pairs=function(self)local function k(e,f)local l,g=next(d,f)if type(g)=="table"then g=c(g)end;return l,g end;return k,self,nil end,__ipairs=function()local m=0;return function()m=m+1;local g=d[m]if g==nil then return end;if type(g)=="table"then g=c(g)end;return m,g end end,__len=function()return#d end,__metatable=false})end;local n=load;b._U=c(b._G)b._U._G=b._U;b._U.load=function(o,p,q,r)return n(o,p,q,r or b._U)end;function b.freshUserEnv()local s={}s.syscall=_makeSyscallProxy()local t=setmetatable(s,{__index=b._U,__newindex=function(e,i,j)rawset(s,i,j)end,__metatable=false})s._G=t;s.load=function(o,p,q,r)return n(o,p,q,r or t)end;return t end

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
local a=...local debug=debug;a._G.debug={getinfo=debug.getinfo,traceback=debug.traceback}

View File

@@ -0,0 +1 @@
local a=...local b=a.syscalls;a.gpio={}b["gpio_write"]=function(c,d)if a.gpio[c]then return a.gpio[c]("w",d)end end;b["gpio_writeAnalog"]=function(c,d)if a.gpio[c]then return a.gpio[c]("wa",d)end end;b["gpio_read"]=function(c)if a.gpio[c]then return a.gpio[c]("r")end end;b["gpio_readAnalog"]=function(c)if a.gpio[c]then return a.gpio[c]("ra")end end

Some files were not shown because too many files have changed in this diff Show More