10 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
114 changed files with 1740 additions and 481 deletions

View File

@@ -71,7 +71,6 @@ local ok, err = xpcall(function()
collectgarbage = true, collectgarbage = true,
error = true, error = true,
gcinfo = true, gcinfo = true,
getfenv = true,
getmetatable = true, getmetatable = true,
ipairs = true, ipairs = true,
__inext = true, __inext = true,
@@ -85,7 +84,6 @@ local ok, err = xpcall(function()
rawlen = true, rawlen = true,
rawset = true, rawset = true,
select = true, select = true,
setfenv = true,
setmetatable = true, setmetatable = true,
string = true, string = true,
table = true, table = true,
@@ -154,17 +152,106 @@ local ok, err = xpcall(function()
if not initFs then displaySuperBadError("Could not load initdisks.") end if not initFs then displaySuperBadError("Could not load initdisks.") end
if not fs then displaySuperBadError("Could not load initfs.") 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 eventQueue = {}
local function queueEvent(event, ...) local function queueEvent(event, ...)
table.insert(eventQueue, {event, ...}) table.insert(eventQueue, {event, ...})
end end
local computer = { local colors = {
time = function() return apis.os.epoch("utc") end, [0x000000]=0x0001,
clock = function() return apis.os.clock() * 1000 end, [0xFFFFFF]=0x0002,
shutdown = apis.os.shutdown, [0xFF0000]=0x0004,
reboot = apis.os.reboot, [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() getMachineEvent = function()
if #eventQueue > 0 then if #eventQueue > 0 then
return table.unpack(table.remove(eventQueue, 1)) return table.unpack(table.remove(eventQueue, 1))
@@ -172,61 +259,15 @@ local ok, err = xpcall(function()
return nil return nil
end end
end, end,
getEEPROM = function() return getFile("/startup.lua") end, getEEPROM = function() return getFile(eeprom) end,
setEEPROM = function(_, text) setEEPROM = function(_, text)
local h = apis.fs.open("/startup.lua", "w") local h = apis.fs.open(eeprom, "w")
h.write(text) h.write(text)
h.close() h.close()
end end,
} initfs=fs,
disks=initFs,
local icolors = { screenCtl={
[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, print = function(_, text) write(text .. "\n") end,
printInline = function(_, text) write(text) end, printInline = function(_, text) write(text) end,
clear = function() clear = function()
@@ -239,25 +280,51 @@ local ok, err = xpcall(function()
getCursorPos = function() return apis.term.getCursorPos() end, getCursorPos = function() return apis.term.getCursorPos() end,
getSize = function() return apis.term.getSize() end, getSize = function() return apis.term.getSize() end,
setBackgroundColor = function(_, color) setBackgroundColor = function(_, color)
apis.term.setBackgroundColor(colors[color]) apis.term.setBackgroundColor(aprox(color))
end, end,
setTextColor = function(_, color) setTextColor = function(_, color)
apis.term.setTextColor(colors[color]) apis.term.setTextColor(aprox(color))
end, end,
getBackgroundColor = function() getBackgroundColor = function()
return icolors[apis.term.getBackgroundColor()] return bg
end, end,
getTextColor = function() getTextColor = function()
return icolors[apis.term.getTextColor()] 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
}, computer, fs, "$")
if not ok then displaySuperBadError(err) end
end) end)
function coroutine.resumeWithTimeout(co, timeout, ...) function coroutine.resumeWithTimeout(co, timeout, ...)
local startTime = computer.time() local startTime = EFI.getEpochMs()
debug.sethook(co, function() debug.sethook(co, function()
if computer.time() > startTime + timeout then if EFI.getEpochMs() > startTime + timeout then
return coroutine.yield("timeout") return coroutine.yield("timeout")
end end
end, "", 1000) end, "", 1000)
@@ -306,11 +373,15 @@ local ok, err = xpcall(function()
end end
end end
if status == "error" or coroutine.status(kernelCoro) == "dead" then if status == "error" or coroutine.status(kernelCoro) == "dead" then
if EFI.reboot then
apis.os.reboot()
end
displaySuperBadError("Kernel error: " .. tostring(err)) displaySuperBadError("Kernel error: " .. tostring(err))
coroutine.yield("key") coroutine.yield("key")
end end
initFs:refresh()
end end
end, debug.traceback) end, debug.traceback)
if not ok then displaySuperBadError("Fatal error during boot: " .. err) end 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 apis = ({...})[1]
local BOOT_DRIVE_PATH = apis.BOOT_DRIVE_PATH or "/$" local BOOT_DRIVE_PATH = apis.BOOT_DRIVE_PATH
local fs = apis.fs local fs = apis.fs
local native = apis.peripheral local native = apis.peripheral
local peripheral = {} local peripheral = {}
local sides = {"top", "bottom", "left", "right", "front", "back"} local sides = {"top", "bottom", "left", "right", "front", "back"}
function peripheral.getType(name) function peripheral.getNames()
if native.isPresent(name) then return native.getType(name) end local results = {}
for n = 1, #sides do for n = 1, #sides do
local side = sides[n] local side = sides[n]
if native.hasType(side, "peripheral_hub") and if native.isPresent(side) then
native.call(side, "isPresentRemote", name) then table.insert(results, side)
return native.call(side, "getTypeRemote", name) 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
end end
return nil return nil
end end
function peripheral.getNames() function peripheral.getName(peripheral)
local names = {} 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 for n = 1, #sides do
local side = sides[n] local side = sides[n]
if native.isPresent(side) then table.insert(names, side) end if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
if native.hasType(side, "peripheral_hub") then return native.call(side, "callRemote", name, method, ...)
local hubSides = native.call(side, "getConnectedSides") end
for _, hubSide in ipairs(hubSides) do end
table.insert(names, hubSide) 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 end
end end
return names return table.unpack(results)
end end
local disks = {} local disks = {}
@@ -125,19 +241,20 @@ internal["$"] = createDisk("$", BOOT_DRIVE_PATH, false, {
end end
}) })
local function refresh() internal["rom"] = createDisk("rom", "/rom", true, {
for id, _ in pairs(disks) do setLabel = function(label)
if not peripheral.getType(id) then disks[id] = nil end error("Device is read-only")
end,
getLabel = function()
return "cctrom"
end end
})
for _, name in ipairs(peripheral.getNames()) do local function refresh()
if peripheral.getType(name) == "disk" then disks={}
if not disks[name] then for _, disk in ipairs({peripheral.find("drive")}) do
local mount = disk.getMountPath(name) if disk.isDiskPresent() then
if mount then disks[tostring(disk.getDiskID())]=createDisk("cctdisk"..tostring(disk.getDiskID()), disk.getMountPath(), false, fs)
disks[name] = createDisk(name, mount, false, disk)
end
end
end end
end end
end end

View File

@@ -158,6 +158,13 @@ local ok, err = xpcall(function()
file.close() file.close()
end 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 eventQueue = {}
local function queueEvent(event, ...) local function queueEvent(event, ...)
@@ -191,6 +198,7 @@ local ok, err = xpcall(function()
local smallestDiff = math.huge local smallestDiff = math.huge
for k, _ in pairs(tbl) do for k, _ in pairs(tbl) do
if k==target then return k end
local diff = math.abs(k - target) local diff = math.abs(k - target)
if diff < smallestDiff then if diff < smallestDiff then
smallestDiff = diff smallestDiff = diff
@@ -241,6 +249,161 @@ local ok, err = xpcall(function()
return value return value
end 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 = { local EFI = {
getEpochMs = function() return apis.os.epoch("utc") end, getEpochMs = function() return apis.os.epoch("utc") end,
getUptime = function() return apis.os.clock() * 1000 end, getUptime = function() return apis.os.clock() * 1000 end,
@@ -252,9 +415,9 @@ local ok, err = xpcall(function()
return nil return nil
end end
end, end,
getEEPROM = function() return getFile("/startup.lua") end, getEEPROM = function() return getFile(eeprom) end,
setEEPROM = function(_, text) setEEPROM = function(_, text)
local h = apis.fs.open("/startup.lua", "w") local h = apis.fs.open(eeprom, "w")
h.write(text) h.write(text)
h.close() h.close()
end, end,
@@ -295,7 +458,8 @@ local ok, err = xpcall(function()
h.close() h.close()
end, end,
firmware=apis, firmware=apis,
reboot=false reboot=false,
beep=function() end
} }
apis.term.setBackgroundColor(0x8000) apis.term.setBackgroundColor(0x8000)
@@ -332,7 +496,7 @@ local ok, err = xpcall(function()
end end
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 while true do
local status, err = coroutine.resumeWithTimeout(kernelCoro, 50) local status, err = coroutine.resumeWithTimeout(kernelCoro, 50)

View File

@@ -1,7 +1,6 @@
--:Minify:-- --:Minify:--
local kernel = ... local kernel = ...
local peripheral=kernel.cct.peripheral local peripheral=kernel.cct.peripheral
local keys=kernel.apis.keys
local colors = { local colors = {
[0xFFFFFF]=0x0001, [0xFFFFFF]=0x0001,
@@ -22,6 +21,25 @@ local colors = {
[0x000000]=0x8000 [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 fg,bg=0x6D6D55,0x000000
local l1f,l1d,l2,ops={},{},{},0 local l1f,l1d,l2,ops={},{},{},0
@@ -30,6 +48,7 @@ local function findClosest(tbl, target)
local smallestDiff = math.huge local smallestDiff = math.huge
for k, _ in pairs(tbl) do for k, _ in pairs(tbl) do
if k==target then return k end
local diff = math.abs(k - target) local diff = math.abs(k - target)
if diff < smallestDiff then if diff < smallestDiff then
smallestDiff = diff smallestDiff = diff
@@ -126,7 +145,7 @@ local function write(text, term)
end end
kernel.devfs.data.tty={} kernel.devfs.data.tty={}
local ctrl,alt = false, false kernel.cct.ctrl,kernel.cct.alt = false, false
local function serializeBool(bool) local function serializeBool(bool)
if bool then if bool then
@@ -155,7 +174,7 @@ local function newtty(obj, id, ev)
obj.setPaletteColor(0x8000, 0x000000) -- #B6FF00 obj.setPaletteColor(0x8000, 0x000000) -- #B6FF00
kernel.devfs.data["tty"][id] = function(op, mode) kernel.devfs.data["tty"][id] = function(op, mode)
if op=="type" then if op=="type" then
return "character device" return "Terminal"
elseif op=="open" then elseif op=="open" then
local h = { local h = {
read=function(amount) read=function(amount)
@@ -202,7 +221,10 @@ local function newtty(obj, id, ev)
return bg return bg
end, end,
gctrl=function() gctrl=function()
return serializeBool(ctrl)..";"..serializeBool(alt) return serializeBool(kernel.cct.ctrl)..";"..serializeBool(kernel.cct.alt)
end,
gplt=function()
return plt
end end
} }
if mode=="rw" then if mode=="rw" then
@@ -219,83 +241,7 @@ local function newtty(obj, id, ev)
end end
local fifo = kernel.newFifo() local fifo = kernel.newFifo()
kernel.cct.fifo=fifo
kernel.processes.cctmond = 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
ctrl = true
elseif charOrKey == keys.leftAlt or charOrKey == 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 = {
[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 fifo.push(special) end
end
elseif eventType == "keyReleased" then
if charOrKey == keys.leftCtrl or charOrKey == keys.rightCtrl then
ctrl = false
elseif charOrKey == keys.leftAlt or charOrKey == 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(kernel.apis.term, "1", fifo.pop) newtty(kernel.apis.term, "1", fifo.pop)

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

@@ -1,12 +1,13 @@
--:Minify:-- --:Minify:--
local EFI=... local EFI=...
EFI.beep(440, 500)
local screen=EFI.screenCtl local screen=EFI.screenCtl
local ifs=EFI.initfs local ifs=EFI.initfs
local disks=EFI.disks local disks=EFI.disks
local arch=EFI.architecture local arch=EFI.architecture
local kernel = {} local kernel = {}
kernel.LOG_Text="" kernel.LOG_Text=""
kernel.version="HyperionOS V1.2.3" kernel.version="HyperionOS V1.2.4"
kernel.process = "Kernel" kernel.process = "Kernel"
kernel.users={[0]="root",[1]="User"} kernel.users={[0]="root",[1]="User"}
kernel.hostname = "hyperion" kernel.hostname = "hyperion"
@@ -291,7 +292,6 @@ kernel.saveLog()
kernel.status="running" kernel.status="running"
screen:disable() screen:disable()
kernel.main() kernel.main()
kernel.panic("Exited main???")
if kernel.status=="panic" then if kernel.status=="panic" then
kernel.panic(kernel.reason) kernel.panic(kernel.reason)
end end

View File

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

View File

@@ -140,6 +140,7 @@ function data.zero(op, mode)
end end
end end
if kernel.EFI:getEEPROM() then
function data.eeprom(op, mode) function data.eeprom(op, mode)
if op=="type" then if op=="type" then
return "character device" return "character device"
@@ -154,9 +155,14 @@ function data.eeprom(op, mode)
} }
elseif mode=="w" then elseif mode=="w" then
if kernel.uid~=0 then error("EACCES") end if kernel.uid~=0 then error("EACCES") end
local firstwrite=true
return { return {
write=function(data) write=function(data)
if firstwrite then
kernel.EFI:setEEPROM(data) kernel.EFI:setEEPROM(data)
else
kernel.EFI:setEEPROM(kernel.EFI:getEEPROM()..data)
end
end end
} }
elseif mode=="a" then elseif mode=="a" then
@@ -170,7 +176,9 @@ function data.eeprom(op, mode)
end end
end end
end end
end
if kernel.EFI:getNvram() then
function data.nvram(op, mode) function data.nvram(op, mode)
if op=="type" then if op=="type" then
return "character device" return "character device"
@@ -185,9 +193,14 @@ function data.nvram(op, mode)
} }
elseif mode=="w" then elseif mode=="w" then
if kernel.uid~=0 then error("EACCES") end if kernel.uid~=0 then error("EACCES") end
local firstwrite=true
return { return {
write=function(data) write=function(data)
if firstwrite then
kernel.EFI:setNvram(data) kernel.EFI:setNvram(data)
else
kernel.EFI:setNvram(kernel.EFI:getNvram()..data)
end
end end
} }
elseif mode=="a" then elseif mode=="a" then
@@ -201,6 +214,7 @@ function data.nvram(op, mode)
end end
end end
end end
end
data["disk"]={} data["disk"]={}
kernel.devfs={} kernel.devfs={}

View File

@@ -6,7 +6,7 @@ local data = {}
proxy.address = "procfs0000" proxy.address = "procfs0000"
proxy.isvirt = true proxy.isvirt = true
proxy.isReadOnly = function() return false end proxy.isReadOnly = function() return true end
proxy.spaceUsed = function() return 0 end proxy.spaceUsed = function() return 0 end
proxy.spaceTotal = function() return 0 end proxy.spaceTotal = function() return 0 end
proxy.makeDirectory = function() error("EACCES") end proxy.makeDirectory = function() error("EACCES") end

View File

@@ -12,13 +12,24 @@ function signal.sigsend(pid, sig)
end end
function signal.sigcatch(handler) function signal.sigcatch(handler)
kernel.currentTask.sigh=handler local task=kernel.currentTask
if not kernel.currentTask.sigq then kernel.currentTask.sigq={} end 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 end
function signal.sigignore() function signal.sigignore()
kernel.currentTask.sigh=nil local task=kernel.currentTask
kernel.currentTask.sigq=nil task.sigh=nil
task.sigq=nil
if task.sigd then task.sigd.active=false end
task.sigd=nil
end end
local s=kernel.syscalls local s=kernel.syscalls

View File

@@ -17,7 +17,42 @@
local kernel=... local kernel=...
local socket={} local socket={}
socket.handlers={}
kernel.socket=socket kernel.socket=socket
function socket.registerProtocal(protocal, handler)
socket.handlers[protocal] = handler
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,
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
})
end
function socket.connect(fd, address)
end
function socket.listen(fd, backlog)
end
kernel.log("Loaded socket module") kernel.log("Loaded socket module")

View File

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

View File

@@ -150,16 +150,11 @@ end
local pepper = getFile("/etc/pam.d/secret") local pepper = getFile("/etc/pam.d/secret")
local function genSalt() local function genSalt()
local chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./" return toHex(math.random(0,2^32))
local s = ""
for i = 1, 16 do
s = s .. chars:sub(math.random(1, #chars), math.random(1, #chars))
end
return s
end end
local function hashPassword(password, salt) local function hashPassword(password, salt)
local key = (pepper .. salt):sub(1, 32) local key = (pepper .. salt)
return blake2s(password, key) return blake2s(password, key)
end end

View File

@@ -156,7 +156,6 @@ end
function sys.sleep(s) function sys.sleep(s)
kernel.currentTask.status = "S" kernel.currentTask.status = "S"
kernel.currentTask.sleep = kernel.EFI:getEpochMs() + s * 1000 kernel.currentTask.sleep = kernel.EFI:getEpochMs() + s * 1000
coroutine.yield()
end end
function sys.getTask(pid) function sys.getTask(pid)
@@ -343,40 +342,42 @@ function kernel.main()
local taskTimes = {} local taskTimes = {}
for pid, task in pairs(tasks) do for pid, task in pairs(tasks) do
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 if task.status == "S" and kernel.EFI:getEpochMs() >= task.sleep then
task.status = "R" task.status = "R"
task.sleep = 0 task.sleep = 0
end end
if task.status == "R" then if task.status == "D" then
kernel.currentTask = task if task.ksh then
coroutine.resume(task.ksh)
end
end
kernel.uid = task.euid or task.uid if task.status == "R" then
kernel.process = task.name
N = N + 1 N = N + 1
task.timeSlice = math.min(Tmax, math.max(Tmin, B / (N ^ alpha))) task.timeSlice = math.min(Tmax, math.max(Tmin, B / (N ^ alpha)))
if task.sigq and #task.sigq ~= 0 and task.sigh then if task.sigq and #task.sigq ~= 0 and task.sigh then
local coro = coroutine.create(task.sigh) local coro = coroutine.create(task.sigh)
local sigret = { coroutine.resume(coro, table.remove(task.sigq, 1)) } local status,err=coroutine.resumeWithTimeout(coro, 100, table.remove(task.sigq, 1))
while coroutine.status(coro) ~= "dead" do if status=="error" then
if sigret[1] == false then break end task.sigd.error=err
if sigret[2] == "syscall" then task.sigd.active=false
local scname = sigret[3] task.sigh=nil
local sysret task.sigq=nil
if kernel.syscalls[scname] then task.sigd=nil
sysret = { xpcall(kernel.syscalls[scname], debug.traceback, table.unpack(sigret, 4)) } elseif status=="success" then
else if err=="syscall" then
sysret = { false, "Unknown syscall: " .. tostring(scname) } task.sigd.error="Cannot execute syscalls from signals"
end task.sigd.active=false
if not sysret[1] then task.sigh=nil
sigret = { coroutine.resume(coro, false, sysret[2]) } task.sigq=nil
else task.sigd=nil
sigret = { coroutine.resume(coro, true, table.unpack(sysret, 2)) }
end
else
sigret = { coroutine.resume(coro) }
end end
end end
end end
@@ -386,10 +387,14 @@ function kernel.main()
local ret local ret
if kernel.config.preempt then if kernel.config.preempt then
if not task.debugger then
ret = { resumeWithTimeout(task.coro, task.timeSlice, table.unpack(task.syscallReturn)) } ret = { resumeWithTimeout(task.coro, task.timeSlice, table.unpack(task.syscallReturn)) }
else else
ret = { coroutine.resume(task.coro, table.unpack(task.syscallReturn)) } ret = { coroutine.resume(task.coro, table.unpack(task.syscallReturn)) }
end end
else
ret = { coroutine.resume(task.coro, table.unpack(task.syscallReturn)) }
end
local elapsed = kernel.EFI:getEpochMs() - startTime local elapsed = kernel.EFI:getEpochMs() - startTime
task.lastTime = elapsed task.lastTime = elapsed

View File

@@ -1,5 +1,6 @@
--:Minify:-- --:Minify:--
local kernel = ... local kernel = ...
if not kernel.vfs.exists("/root") then kernel.vfs.mkdir("/root") end
kernel.processes.login = function() kernel.processes.login = function()
local ok, err = pcall(kernel.hpv.execspawn, "/bin/login", "login") local ok, err = pcall(kernel.hpv.execspawn, "/bin/login", "login")

View File

@@ -92,6 +92,7 @@ if kernel.firstBoot then
{"etc", REG, 0, 0, RWX_RX_RX}, {"etc", REG, 0, 0, RWX_RX_RX},
{"home", REG, 0, 0, RWX_RX_RX}, {"home", REG, 0, 0, RWX_RX_RX},
{"lib", REG, 0, 0, RWX_RX_RX}, {"lib", REG, 0, 0, RWX_RX_RX},
{"proc", REG, 0, 0, RWXRWXRWX},
{"root", REG, 0, 0, RW____ }, {"root", REG, 0, 0, RW____ },
{"sbin", REG, 0, 0, RWX_RX_RX}, {"sbin", REG, 0, 0, RWX_RX_RX},
{"tmp", REG, 0, 0, RWXRWXRWX}, {"tmp", REG, 0, 0, RWXRWXRWX},

View File

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

View File

@@ -1,3 +1,4 @@
--:Minify:--
local ini = {} local ini = {}
function ini.parse(str) 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

@@ -11,6 +11,8 @@ Targets:
build-mini-test build-mini-test
build-micro-test build-micro-test
clean clean
prod
prod-mini
Arch flags: Arch flags:
--arch cct --arch cct
@@ -32,6 +34,7 @@ PROJECT_ROOT = Path(__file__).resolve().parent
SRC_ROOT = PROJECT_ROOT / "Src" SRC_ROOT = PROJECT_ROOT / "Src"
TEST_ROOT = PROJECT_ROOT / "Test" TEST_ROOT = PROJECT_ROOT / "Test"
BUILD_ROOT = PROJECT_ROOT / "Build" BUILD_ROOT = PROJECT_ROOT / "Build"
PROD_ROOT = PROJECT_ROOT / "prod"
ARCH_BOOT_DIR = { ARCH_BOOT_DIR = {
"cct": Path("boot") / "cct", "cct": Path("boot") / "cct",
@@ -46,6 +49,13 @@ def clean():
else: else:
print("Nothing to clean.") 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: def has_minify_header(path: Path) -> bool:
try: try:
@@ -74,7 +84,7 @@ def compress_lz4(data: bytes) -> bytes:
return lz4.frame.compress(data) return lz4.frame.compress(data)
def process_root(src_root: Path, out_root: Path, minify: bool, micro: bool, arch:Union[str, None]): 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"Building from {src_root}")
print(f"Output to {out_root}") print(f"Output to {out_root}")
print() print()
@@ -85,6 +95,7 @@ def process_root(src_root: Path, out_root: Path, minify: bool, micro: bool, arch
if pkg_dir.name[:18] == "Hyperion-firmware-": if pkg_dir.name[:18] == "Hyperion-firmware-":
if pkg_dir.name != f"Hyperion-firmware-{arch}": if pkg_dir.name != f"Hyperion-firmware-{arch}":
if prod != True:
continue continue
print(f"== Package: {pkg_dir.name} ==") print(f"== Package: {pkg_dir.name} ==")
@@ -99,6 +110,9 @@ def process_root(src_root: Path, out_root: Path, minify: bool, micro: bool, arch
continue continue
dst = out_root / rel dst = out_root / rel
if prod:
dst = out_root / pkg_dir.name / rel
dst.parent.mkdir(parents=True, exist_ok=True) dst.parent.mkdir(parents=True, exist_ok=True)
print(f" Processing: {src.relative_to(src_root)}") print(f" Processing: {src.relative_to(src_root)}")
@@ -132,13 +146,19 @@ def install_bootloader(arch: str, release: bool):
shutil.copy2(eeprom, BUILD_ROOT / eeprom_dst_name) 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() clean()
BUILD_ROOT.mkdir() BUILD_ROOT.mkdir()
if prod:
cleanprod()
PROD_ROOT.mkdir()
out_root = BUILD_ROOT / "$" if arch else BUILD_ROOT out_root = BUILD_ROOT / "$" if arch else BUILD_ROOT
process_root(SRC_ROOT, out_root, minify, micro, arch) 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: if include_test:
process_root(TEST_ROOT, out_root, minify, micro) process_root(TEST_ROOT, out_root, minify, micro)
@@ -200,9 +220,9 @@ def inject_makeusers(users, arch):
def main(): def main():
parser = argparse.ArgumentParser(description="HyperionOS build script") 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, 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, parser.add_argument("--release", dest="release", action="store_true", default=True,
help="Release build: eeprom placed as startup.lua (default)") help="Release build: eeprom placed as startup.lua (default)")
parser.add_argument("--dev", dest="release", action="store_false", parser.add_argument("--dev", dest="release", action="store_false",
@@ -226,6 +246,7 @@ def main():
clean() clean()
return return
prod = "prod" in args.target
minify = "mini" in args.target or "micro" in args.target minify = "mini" in args.target or "micro" in args.target
micro = "micro" in args.target micro = "micro" in args.target
include_test = "test" in args.target include_test = "test" in args.target
@@ -233,7 +254,7 @@ def main():
if micro: if micro:
import lz4.block 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: if args.makeuser:
print("Injecting first-boot user setup ...") 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
local is_dir = typeflag == "5" or name:sub(-1) == "/"
local clean_name = name:gsub("/$", "")
if clean_name ~= "" then
local parent_path = clean_name:match("(.+)/")
local fname = clean_name:match("([^/]+)$")
if not fname then
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
end
end
end
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,21 +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
print("Installing tar but bad...")
shell.run("wget https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/install/data/tarbad /tar.lua")
print("Installing HyperionOS...")
print("Installing precompiled tar")
shell.run("wget https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/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")
end

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()

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

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

View File

@@ -0,0 +1 @@
local a=...function print(...)local b={...}local c=""for d=1,#b do c=c..tostring(b[d]).."\t"end;c=c:sub(1,-2)syscall.write(1,c.."\n")end;function printf(e,...)local c=string.format(e,...)syscall.write(1,c.."\n")end;function printInline(...)local b={...}local c=""for d=1,#b do c=c..tostring(b[d]).."\t"end;c=c:sub(1,-2)syscall.write(1,c)end

View File

@@ -0,0 +1 @@
local a=...a.log("Loading init system...")a.log("InitPath: "..a.config.initPath)local b,c=pcall(a.vfs.access,a.config.initPath,"rx")if not b then a.PANIC("Init binary not executable: "..a.config.initPath.." ("..tostring(c)..")")end;local d=a.vfs.open(a.config.initPath,"r")if not d then a.panic("Failed to open "..a.config.initPath)end;local e=a.vfs.read(d,1024*1024*4)if not d then a.panic("Failed to read "..a.config.initPath)end;a.vfs.close(d)local f,g=load(e,"@sysinit","t",a._U)if not f then a.PANIC("Failed to load init system: "..g)end;a.tasks["1"]={coro=coroutine.create(function()local h,g=xpcall(f,debug.traceback,a)if not h then a.panic("Init system crashed: "..tostring(g))else a.panic("Init system exited: "..tostring(g))end end),name="sysinit",status="R",pid=1,tgid=1,uid=0,fd={},envars={},args={},exit="",sleep=0,ivs=0,vs=0,parent=a.kernelTask,siblings=a.kernelTask.children,children={},syscallReturn={},cwd="/",timeSlice=0,lastTime=0,totalTime=0,numRuns=0}a.log("created init task with PID 1")a.log("Initializing init system...")

View File

@@ -0,0 +1 @@
local a=...if not a.vfs.exists("/root")then a.vfs.mkdir("/root")end;a.processes.login=function()local b,c=pcall(a.hpv.execspawn,"/bin/login","login")if not b then a.log("Failed to exec /bin/login: "..tostring(c),"ERROR",0xFF0000)end end

View File

@@ -0,0 +1 @@
local a=...if a.firstBoot then local b=a.vfs.P;local c=a.vfs.PERM;local d=b.OWNER_R+b.OWNER_W+b.GROUP_R+b.WORLD_R;local e=b.OWNER_R+b.OWNER_W+b.OWNER_X+b.GROUP_R+b.GROUP_X+b.WORLD_R+b.WORLD_X;local f=b.OWNER_R+b.OWNER_W+b.GROUP_R;local g=b.OWNER_R+b.OWNER_W;local h=c.RWXRWXRWX;local i=c.SUID_755;local j=0x02;local k=a.disks["$"]local function l(m,n,o,p,q,r)r=r or""local s=q%256;local t=math.floor(q/256)%256;local u=(o or 0)%256;local v=math.floor((o or 0)/256)%256;local w=(p or 0)%256;local x=math.floor((p or 0)/256)%256;return string.char(#m)..m..string.char(n,u,v,w,x,s,t)..string.char(#r)..r end;local y=0x00;local function z(A,B)local C=A;if C:sub(1,1)=="/"then C=C:sub(2)end;local D=C==""and".meta"or C.."/.meta"local E={}local F,G=pcall(function()return k:open(D,"r")end)if F and G then local H=G.read(65535)if G.close then G.close()end;E=a.vfs._parseMetafile and a.vfs._parseMetafile(H)or{}end;for I,J in ipairs(B)do local m=J[1]local n=J[2]or y;local o=J[3]or 0;local p=J[4]or 0;local q=J[5]or e;local r=J[6]or""E[m]={etype=n,owner=o,group=p,perms=q,cmeta=r}end;local K=string.char(j)for m,L in pairs(E)do K=K..l(m,L.etype or y,L.owner or 0,L.group or 0,L.perms or e,L.cmeta or"")end;local M,N=pcall(function()local O=k:open(D,"w")O.write(K)O.close()end)if not M then a.log("permissions: failed to write "..D..": "..tostring(N),"WARN",0xFF8800)end end;a.log("Seeding filesystem permissions...")z("/",{{"bin",y,0,0,e},{"boot",y,0,0,e},{"dev",y,0,0,h},{"etc",y,0,0,e},{"home",y,0,0,e},{"lib",y,0,0,e},{"proc",y,0,0,h},{"root",y,0,0,g},{"sbin",y,0,0,e},{"tmp",y,0,0,h},{"usr",y,0,0,e},{"var",y,0,0,h},{"opt",y,0,0,e}})z("/bin",{{"login",y,0,0,i},{"su",y,0,0,i},{"sudo",y,0,0,i}})z("/etc",{{"passwd",y,0,0,d},{"shadow",y,0,0,g},{"pam.d",y,0,0,g}})z("/etc/pam.d",{{"secret",y,0,0,g}})a.log("Filesystem permissions seeded.")end

View File

@@ -0,0 +1 @@
local a=...a.allowGlobalOverwrites=false

1
prod/bit32/lib/bit32 Normal file
View File

@@ -0,0 +1 @@
local a={}local b=2^32;local c=2^31;local function d(e)return e%b end;local function f(e)e=d(e)local g={}for h=0,31 do local i=e%2;g[h]=i;e=(e-i)/2 end;return g end;local function j(g)local e=0;local k=1;for h=0,31 do if g[h]==1 then e=e+k end;k=k*2 end;return d(e)end;function a.band(...)local l={...}if#l==0 then return 0xFFFFFFFF end;local m=f(l[1])for h=2,#l do local i=f(l[h])for n=0,31 do m[n]=m[n]==1 and i[n]==1 and 1 or 0 end end;return j(m)end;function a.bor(...)local l={...}if#l==0 then return 0 end;local m=f(l[1])for h=2,#l do local i=f(l[h])for n=0,31 do m[n]=(m[n]==1 or i[n]==1)and 1 or 0 end end;return j(m)end;function a.bxor(...)local l={...}if#l==0 then return 0 end;local m=f(l[1])for h=2,#l do local i=f(l[h])for n=0,31 do m[n]=m[n]~=i[n]and 1 or 0 end end;return j(m)end;function a.bnot(e)local m=f(e)for h=0,31 do m[h]=m[h]==1 and 0 or 1 end;return j(m)end;function a.lshift(e,o)return d(d(e)*2^o)end;function a.rshift(e,o)return math.floor(d(e)/2^o)end;function a.arshift(e,o)e=d(e)if e>=c then return math.floor((e-b)/2^o)else return math.floor(e/2^o)end end;function a.lrotate(e,o)o=o%32;e=d(e)local p=e*2^o%b;local q=math.floor(e/2^(32-o))return d(p+q)end;function a.rrotate(e,o)o=o%32;e=d(e)local q=math.floor(e/2^o)local p=e*2^(32-o)%b;return d(p+q)end;function a.extract(e,r,s)s=s or 1;return a.band(a.rshift(e,r),2^s-1)end;function a.replace(e,t,r,s)s=s or 1;local u=a.lshift(2^s-1,r)e=a.band(e,a.bnot(u))return a.bor(e,a.lshift(t,r))end;return a

View File

@@ -0,0 +1 @@
local a=require("bit32")local b,c,d=a.band,a.bor,a.bxor;local e,f=a.rshift,a.lshift;local g=2^32;local function h(i,j)return c(e(i,j),f(i,32-j))end;local k={0x6A09E667,0xBB67AE85,0x3C6EF372,0xA54FF53A,0x510E527F,0x9B05688C,0x1F83D9AB,0x5BE0CD19}local l={{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},{14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3},{11,8,12,0,5,2,15,13,10,14,3,6,7,1,9,4},{7,9,3,1,13,12,11,14,2,6,5,10,4,0,15,8},{9,0,5,7,2,4,10,15,14,1,11,12,6,8,3,13},{2,12,6,10,0,11,8,3,4,13,7,5,15,14,1,9},{12,5,1,15,14,13,4,10,0,7,6,3,9,2,8,11},{13,11,7,14,12,1,3,9,5,0,15,4,8,6,2,10},{6,15,14,9,11,3,0,8,12,2,13,7,1,4,10,5},{10,2,8,4,7,6,1,5,15,11,9,14,3,12,13,0}}local function m(n,o,p,q,r,i,s)n[o]=(n[o]+n[p]+i)%g;n[r]=h(d(n[r],n[o]),16)n[q]=(n[q]+n[r])%g;n[p]=h(d(n[p],n[q]),12)n[o]=(n[o]+n[p]+s)%g;n[r]=h(d(n[r],n[o]),8)n[q]=(n[q]+n[r])%g;n[p]=h(d(n[p],n[q]),7)end;local function t(u,v,w,x)local n={}for y=1,8 do n[y]=u[y]end;for y=1,8 do n[y+8]=k[y]end;n[13]=d(n[13],w)if x then n[15]=d(n[15],0xFFFFFFFF)end;local z={}for y=0,15 do local A=y*4+1;z[y]=(v:byte(A)or 0)+(v:byte(A+1)or 0)*0x100+(v:byte(A+2)or 0)*0x10000+(v:byte(A+3)or 0)*0x1000000 end;for B=1,10 do local C=l[B]m(n,1,5,9,13,z[C[1]],z[C[2]])m(n,2,6,10,14,z[C[3]],z[C[4]])m(n,3,7,11,15,z[C[5]],z[C[6]])m(n,4,8,12,16,z[C[7]],z[C[8]])m(n,1,6,11,16,z[C[9]],z[C[10]])m(n,2,7,12,13,z[C[11]],z[C[12]])m(n,3,8,9,14,z[C[13]],z[C[14]])m(n,4,5,10,15,z[C[15]],z[C[16]])end;for y=1,8 do u[y]=d(u[y],n[y],n[y+8])end end;local function D(E,F)F=F or""local u={}for y=1,8 do u[y]=k[y]end;local G=32;u[1]=d(u[1],0x01010000+f(#F,8)+G)local w=0;if#F>0 then local v=F..string.rep("\0",64-#F)w=#F;t(u,v,w,false)end;for y=1,#E,64 do local v=E:sub(y,y+63)if#v<64 then v=v..string.rep("\0",64-#v)end;w=w+math.min(64,#E-y+1)t(u,v,w,y+64>#E)end;local H=""for y=1,8 do H=H..string.format("%08x",u[y])end;return H end;return D

File diff suppressed because one or more lines are too long

9
prod/deflate/lib/deflate Normal file
View File

@@ -0,0 +1,9 @@
local deflate=require("LibDeflate")
local lib={}
lib.compress=function(data)
return deflate:CompressDeflate(data)
end
lib.decompress=function(data)
return deflate:DecompressDeflate(data)
end
return lib

1
prod/hysh/bin/chattr Normal file
View File

@@ -0,0 +1 @@
local a=syscall.getTask(syscall.getpid()).name;local b={R=false,help=false}local c={}local d=nil;for e,f in ipairs({...})do if f:sub(1,2)=="--"then local g=f:sub(3)if b[g]==nil then print(a..": unrecognized option '"..f.."'")print("try '"..a.." --help' for more information.")syscall.exit(1)return end;b[g]=true elseif f:sub(1,1)=="-"and not f:match("^%-[%+%-]")then local h=true;for i=2,#f do local j=f:sub(i,i)if b[j]~=nil then b[j]=true else h=false;break end end;if not h then d=f end elseif f:sub(1,1)=="+"or f:sub(1,1)=="-"and f:match("^%-[a-zA-Z]")then d=f else table.insert(c,f)end end;if b.help then print("Usage: "..a.." [OPTION]... +-= ATTRS FILE...")print("Change file attributes on a filesystem.")print("")print("Attributes:")print(" i immutable: file cannot be modified, renamed, or deleted")print(" a append-only: file can only be appended to")print("")print("Operators: +attr add, -attr remove")print("Example: "..a.." +i /etc/passwd")print("")print("Options:")print(" -R operate on files and directories recursively")print(" --help display this help and exit")return end;if not d or#c<1 then print(a..": missing operand")print("try '"..a.." --help' for more information.")syscall.exit(1)return end;local k=d:sub(1,1)local l=d:sub(2)if k~="+"and k~="-"then print(a..": invalid operator '"..k.."' (use + or -)")syscall.exit(1)return end;local function m(n)local o=pcall(function()return syscall.stat(n)end)and syscall.stat(n)if o then return o.xattr or""end;return""end;local p="|i"local q="|a"local function r(j)if j=="i"then return p elseif j=="a"then return q else return nil end end;local function s(n)local o=syscall.stat(n)if not o then print(a..": cannot stat '"..n.."': No such file or directory")return false end;if o.etype==0x01 then return true end;if not syscall.setxattr then print(a..": kernel does not expose setxattr syscall; cannot modify attributes")syscall.exit(1)return false end;local t=o.xattr or""for i=1,#l do local j=l:sub(i,i)local u=r(j)if not u then print(a..": unsupported attribute '"..j.."'")syscall.exit(1)return false end;local v=t:find(u,1,true)if k=="+"and not v then t=t..u elseif k=="-"and v then t=t:gsub(u:gsub("|","%%|"),"")end end;local w,x=pcall(syscall.setxattr,n,t)if not w then print(a..": cannot set attributes on '"..n.."': "..tostring(x))return false end;return true end;local function y(n)if not s(n)then return end;if syscall.type(n)=="directory"then local w,z=pcall(syscall.listdir,n)if w then for e,A in ipairs(z)do local B=n;if B:sub(-1)~="/"then B=B.."/"end;y(B..A)end end end end;local C=syscall.getcwd()local function D(E)if E:sub(1,1)~="/"then E=C.."/"..E end;return E end;if not syscall.setxattr then print(a..": kernel does not expose setxattr; attributes cannot be persisted")print(a..": add sys[\"setxattr\"] = vfs.setxattr to 10_vfs.kmod to enable this")syscall.exit(1)return end;local F=0;for i=1,#c do local n=D(c[i])if not syscall.exists(n)then print(a..": cannot access '"..c[i].."': No such file or directory")F=1 elseif b.R then y(n)else if not s(n)then F=1 end end end;syscall.exit(F)

1
prod/hysh/bin/chgrp Normal file
View File

@@ -0,0 +1 @@
local a=syscall.getTask(syscall.getpid()).name;local b={R=false,help=false}local c={}for d,e in ipairs({...})do if e:sub(1,2)=="--"then local f=e:sub(3)if b[f]==nil then print(a..": unrecognized option '"..e.."'")print("try '"..a.." --help' for more information.")syscall.exit(1)return end;b[f]=true elseif e:sub(1,1)=="-"then for g=2,#e do local f=e:sub(g,g)if b[f]==nil then print(a..": invalid option '-"..f.."'")print("try '"..a.." --help' for more information.")syscall.exit(1)return end;b[f]=true end else table.insert(c,e)end end;if b.help then print("Usage: "..a.." [OPTION]... GROUP FILE...")print("Change the group of each FILE to GROUP.")print("GROUP may be a group name or numeric ID.")print("")print("Options:")print(" -R operate on files and directories recursively")print(" --help display this help and exit")return end;if#c<2 then print(a..": missing operand")print("try '"..a.." --help' for more information.")syscall.exit(1)return end;local h=c[1]local function i(j)local k=tonumber(j)if k then return k end;local l=syscall.getuidbyname and syscall.getuidbyname(j)if l then local m=syscall.getpasswd(l)if m then return m.gid end end;print(a..": invalid group: '"..j.."'")syscall.exit(1)end;local n=i(h)local function o(p)local q=syscall.stat(p)if not q then print(a..": cannot stat '"..p.."': no such file or directory")return false end;local r,s=pcall(syscall.chown,p,q.owner,n)if not r then local t=tostring(s)if t:find("EPERM")or t:find("EACCES")then t="operation not permitted (must be root)"elseif t:find("ENOENT")then t="no such file or directory"end;print(a..": cannot change group of '"..p.."': "..t)return false end;return true end;local function u(p)if not o(p)then return end;if syscall.type(p)=="directory"then local r,v=pcall(syscall.listdir,p)if r then for d,w in ipairs(v)do local x=p;if x:sub(-1)~="/"then x=x.."/"end;u(x..w)end end end end;local y=syscall.getcwd()local function z(A)if A:sub(1,1)~="/"then A=y.."/"..A end;return A end;local B=0;for g=2,#c do local p=z(c[g])if not syscall.exists(p)then print(a..": cannot access '"..c[g].."': No such file or directory")B=1 elseif b.R then u(p)else if not o(p)then B=1 end end end;syscall.exit(B)

1
prod/hysh/bin/chmod Normal file

File diff suppressed because one or more lines are too long

1
prod/hysh/bin/chown Normal file
View File

@@ -0,0 +1 @@
local a=syscall.getTask(syscall.getpid()).name;local b={R=false,help=false}local c={}for d,e in ipairs({...})do if e:sub(1,2)=="--"then local f=e:sub(3)if b[f]==nil then print(a..": unrecognized option '"..e.."'")print("try '"..a.." --help' for more information.")syscall.exit(1)return end;b[f]=true elseif e:sub(1,1)=="-"then for g=2,#e do local f=e:sub(g,g)if b[f]==nil then print(a..": invalid option '-"..f.."'")print("try '"..a.." --help' for more information.")syscall.exit(1)return end;b[f]=true end else table.insert(c,e)end end;if b.help then print("Usage: "..a.." [OPTION]... OWNER[:GROUP] FILE...")print(" "..a.." [OPTION]... :GROUP FILE...")print("Change the owner and/or group of each FILE.")print("OWNER and GROUP may be names or numeric IDs.")print("")print("Options:")print(" -R operate on files and directories recursively")print(" --help display this help and exit")return end;if#c<2 then print(a..": missing operand")print("try '"..a.." --help' for more information.")syscall.exit(1)return end;local h=c[1]local i,j;if h:sub(1,1)==":"then j=h:sub(2)else local k=h:find(":",1,true)if k then i=h:sub(1,k-1)j=h:sub(k+1)if j==""then j=nil end else i=h end end;local function l(m)if not m or m==""then return nil end;local n=tonumber(m)if n then return n end;local o=syscall.getuidbyname and syscall.getuidbyname(m)if o then return o end;print(a..": invalid user: '"..m.."'")syscall.exit(1)end;local function p(m)if not m or m==""then return nil end;local n=tonumber(m)if n then return n end;local o=syscall.getuidbyname and syscall.getuidbyname(m)if o then local q=syscall.getpasswd(o)if q then return q.gid end end;print(a..": invalid group: '"..m.."'")syscall.exit(1)end;local r=l(i)local s=p(j)if r==nil and s==nil then print(a..": no owner or group specified")syscall.exit(1)return end;local function t(u)local v=syscall.stat(u)if not v then print(a..": cannot stat '"..u.."': no such file or directory")return false end;local o=r~=nil and r or v.owner;local w=s~=nil and s or v.group;local x,y=pcall(syscall.chown,u,o,w)if not x then local z=tostring(y)if z:find("EPERM")or z:find("EACCES")then z="operation not permitted (must be root)"elseif z:find("ENOENT")then z="no such file or directory"end;print(a..": cannot change owner of '"..u.."': "..z)return false end;return true end;local function A(u)if not t(u)then return end;if syscall.type(u)=="directory"then local x,B=pcall(syscall.listdir,u)if x then for d,C in ipairs(B)do local D=u;if D:sub(-1)~="/"then D=D.."/"end;A(D..C)end end end end;local E=syscall.getcwd()local function F(G)if G:sub(1,1)~="/"then G=E.."/"..G end;return G end;local H=0;for g=2,#c do local u=F(c[g])if not syscall.exists(u)then print(a..": cannot access '"..c[g].."': No such file or directory")H=1 elseif b.R then A(u)else if not t(u)then H=1 end end end;syscall.exit(H)

1
prod/hysh/bin/chroot Normal file
View File

@@ -0,0 +1 @@
local a=syscall.getTask(syscall.getpid()).name;local b={}local c={help=false}for d,e in ipairs({...})do if e:sub(1,2)=="--"then local f=e:sub(3)if f=="help"then c.help=true else print(a..": unrecognized option '"..e.."'")print("try '"..a.." --help' for more information.")syscall.exit(1)return end elseif e:sub(1,1)=="-"then print(a..": invalid option '"..e.."'")print("try '"..a.." --help' for more information.")syscall.exit(1)return else table.insert(b,e)end end;if c.help then print("Usage: "..a.." NEWROOT [COMMAND [ARG]...]")print("Run COMMAND with root directory set to NEWROOT.")print("If COMMAND is omitted, runs the current user's shell.")print("")print("Requires root (uid 0).")return end;if#b<1 then print(a..": missing operand")print("try '"..a.." --help' for more information.")syscall.exit(1)return end;local g=syscall.geteuid and syscall.geteuid()or syscall.getuid()if g~=0 then print(a..": cannot change root directory: Permission denied")syscall.exit(1)return end;local h=b[1]if h:sub(1,1)~="/"then h=syscall.getcwd().."/"..h end;if not syscall.exists(h)then print(a..": cannot change root directory to '"..b[1].."': No such file or directory")syscall.exit(1)return end;if syscall.type(h)~="directory"then print(a..": '"..b[1].."': Not a directory")syscall.exit(1)return end;local i,j=pcall(syscall.chroot,h)if not i then print(a..": cannot change root directory to '"..b[1].."': "..tostring(j))syscall.exit(1)return end;local k;if#b>=2 then k=b[2]else local l=syscall.getuid()local m=syscall.getpasswd(l)k=m and m.shell or"/bin/hysh"end;local n={}for o=3,#b do table.insert(n,b[o])end;local p,q=pcall(syscall.exec,k,n)if not p then print(a..": failed to run command '"..k.."': "..tostring(q))syscall.exit(127)end

1
prod/hysh/bin/help Normal file

File diff suppressed because one or more lines are too long

1
prod/hysh/bin/hfetch Normal file
View File

@@ -0,0 +1 @@
local a=0x00FFFF;local b=0xFFFFFF;local c=0xDBDBDB;local d=0x6D6D6D;local e=0x00FF00;local function f(g)syscall.devctl(1,"sfgc",g)end;local h=syscall.getUsername()or"Unknown"local i=syscall.getHostname()or"Unknown"local j=h.."@"..i;local function k(l)local m=math.floor(l/1000)local n=math.floor(m/60)local o=math.floor(n/60)local p=math.floor(o/24)m=m%60;n=n%60;o=o%24;local q={}if p>0 then q[#q+1]=p.."d"end;if o>0 then q[#q+1]=o.."h"end;if n>0 then q[#q+1]=n.."m"end;q[#q+1]=m.."s"return table.concat(q," ")end;local r=syscall.getHost()or"Unknown"local s=r:match("ComputerCraft ([%d%.]+)")or r;local t={{nil,j},{nil,string.rep("-",#j)},{"OS",syscall.version()or"Unknown"},{"Host",s},{"Arch",syscall.arch()or"Unknown"},{"Uptime",k(syscall.getUptime()or 0)},{"Tasks",tostring(#(syscall.getTasks()or{}))},{"Shell",syscall.getEnviron("SHELL")or"Unknown"},{"Terminal","tty1"},{"UID",tostring(syscall.getuid())},{"Packages","n/a (spm)"}}local u={".. *. .. "," *= +@* +* "," .@#. -@@@= :#@. "," =@@+ *@@@# +@@= "," %@@%: *@@@# -%@@% "," :@@@@+ *@@@# .*@@@@: "," :*@@@%- *@@@# -@@@@*: "," =%@@#. *@@@# .#@@%= "," :=. :*@@= *@@@# =@@+: .=: "," %@#=..*# +@@@# #*..=#@# "," .@@@@+=# .%@%: #=+@@@@. "," .....=# -@= *+...:. "," -*%*-@= - =@-*%*- "," -@*. -@%. :%@- :*@- "," .#@#@* "," -#- "," "}local v=math.max(#u,#t)for w=1,v do local x=u[w]or string.rep(" ",36)f(a)printInline(x)f(c)printInline("| ")local y=t[w]if y then if y[1]==nil and w==1 then f(e)printInline(y[2])elseif y[1]==nil and w==2 then f(d)printInline(y[2])elseif y[1]then f(c)printInline(y[1]..": ")f(b)printInline(y[2])end end;f(b)print("")end

1
prod/hysh/bin/hysh Normal file

File diff suppressed because one or more lines are too long

1
prod/hysh/bin/id Normal file
View File

@@ -0,0 +1 @@
local a={...}local b;if a[1]then b=syscall.getuid(a[1])if not b then print("id: user '"..a[1].."' does not exist")syscall.exit(1)return end else b=syscall.getuid()end;local c=syscall.getpasswd(b)local d=c and c.username or tostring(b)local e=c and c.gid or b;print(string.format("uid=%d(%s) gid=%d(%s)",b,d,e,d))

3
prod/hysh/bin/ll Normal file
View File

@@ -0,0 +1,3 @@
local args={...}
table.insert(args, "-lah")
syscall.exec("/bin/ls", args)

1
prod/hysh/bin/ln Normal file
View File

@@ -0,0 +1 @@
local a=syscall.getTask(syscall.getpid()).name;local b={s=false,f=false,help=false}local c={}for d,e in ipairs({...})do if e:sub(1,2)=="--"then local f=e:sub(3)if b[f]==nil then print(a..": unrecognized option '"..e.."'")print("try '"..a.." --help' for more information.")syscall.exit(1)return end;b[f]=true elseif e:sub(1,1)=="-"then for g=2,#e do local f=e:sub(g,g)if b[f]==nil then print(a..": invalid option '-"..f.."'")print("try '"..a.." --help' for more information.")syscall.exit(1)return end;b[f]=true end else table.insert(c,e)end end;if b.help then print("Usage: "..a.." [OPTION]... TARGET LINK_NAME")print(" "..a.." [OPTION]... TARGET... DIRECTORY")print("Create links between files.")print("")print("Options:")print(" -s make symbolic links instead of hard links")print(" -f remove existing destination files")print(" --help display this help and exit")print("")print("With no -s, hard links are not supported (filesystem limitation).")print("Use -s for symbolic links.")return end;if#c<2 then print(a..": missing operand")print("try '"..a.." --help' for more information.")syscall.exit(1)return end;if not b.s then print(a..": hard links are not supported; use -s for symbolic links")syscall.exit(1)return end;local h=c[#c]local i=syscall.type(h)=="directory"local function j()local k=syscall.getcwd()if k:sub(-1)~="/"then k=k.."/"end;return k end;local function l(m)if m:sub(1,1)~="/"then m=j()..m end;return m end;for g=1,#c-1 do local n=c[g]local o;if i then local p=n:match("[^/]+$")or n;o=l(h)if o:sub(-1)~="/"then o=o.."/"end;o=o..p else o=l(h)end;if b.f and syscall.exists(o)then local q,r=pcall(syscall.remove,o)if not q then print(a..": cannot remove '"..o.."': "..tostring(r))syscall.exit(1)return end end;local q,r=pcall(syscall.symlink,n,o)if not q then print(a..": failed to create symlink '"..o.."' -> '"..n.."': "..tostring(r))syscall.exit(1)return end end

1
prod/hysh/bin/login Normal file
View File

@@ -0,0 +1 @@
syscall.open("/dev/tty/1","r")syscall.open("/dev/tty/1","w")syscall.open("/dev/null","w")local a=3;local function b(c)local d=""while true do local e=syscall.read(0)if not e or e==""then elseif e=="\n"then syscall.write(1,"\n")return d elseif e=="\b"then if#d>0 then d=d:sub(1,-2)syscall.write(1,"\b \b")end else d=d..e;syscall.write(1,c or e)end end end;local function f()local g=""local h,i=pcall(function()local j=syscall.open("/etc/shadow","r")g=syscall.read(j,65535)or""syscall.close(j)end)if g:match("%S")then return end;syscall.devctl(1,"clear")syscall.devctl(1,"spos",1,1)syscall.devctl(1,"sfgc",0x00FF00)syscall.write(1,"HyperionOS First Boot Setup\n")syscall.devctl(1,"sfgc",0xFFFFFF)syscall.write(1,"No root password is set. Please create one now.\n\n")while true do syscall.write(1,"New root password: ")local k=b("*")syscall.write(1,"Confirm password: ")local l=b("*")if k~=l then syscall.devctl(1,"sfgc",0xFF0000)syscall.write(1,"Passwords do not match. Try again.\n\n")syscall.devctl(1,"sfgc",0xFFFFFF)elseif#k<6 then syscall.devctl(1,"sfgc",0xFF0000)syscall.write(1,"Password too short (minimum 6 characters).\n\n")syscall.devctl(1,"sfgc",0xFFFFFF)else local m,n=syscall.setpassword(0,k)if m then syscall.devctl(1,"sfgc",0x00FF00)syscall.write(1,"Root password set.\n\n")syscall.devctl(1,"sfgc",0xFFFFFF)sleep(0.5)break else syscall.devctl(1,"sfgc",0xFF0000)syscall.write(1,"Error: "..tostring(n).."\n")syscall.devctl(1,"sfgc",0xFFFFFF)end end end end;local function o(p,q,r,s)local t,u=pcall(syscall.exists,r)if not t or not u then syscall.write(1,"login: shell not found: "..r.."\n")sleep(2)return false end;local v,w=pcall(syscall.access,r,"rx")syscall.setEnviron("HOME",s)syscall.setEnviron("USER",p)syscall.setEnviron("SHELL",r)syscall.setEnviron("PATH","/bin/")local x,y=pcall(syscall.setuid,q)if not x then syscall.write(1,"login: setuid failed: "..tostring(y).."\n")sleep(2)return false end;local z,A=pcall(syscall.chdir,s)if not z then pcall(syscall.chdir,"/")end;local m,n=pcall(syscall.execspawn,r,p..":shell")if not m then syscall.write(1,"login: failed to launch shell: "..tostring(n).."\n")sleep(2)return false end;syscall.exit(0)end;local function B()syscall.devctl(1,"clear")syscall.devctl(1,"sfgc",0xFFFFFF)syscall.devctl(1,"sbgc",0x000000)syscall.devctl(1,"spos",1,1)local C=syscall.getHostname()or"hyperion"syscall.write(1,"HyperionOS\n")syscall.write(1,C.." login\n\n")local D=0;while D<a do syscall.devctl(1,"sfgc",0xFFFFFF)syscall.write(1,"Username: ")local p=b(nil)if p~=""then syscall.write(1,"Password: ")local E=b("*")local q=syscall.getuidbyname(p)local m,n=syscall.login(q,E)if m then local q=syscall.getuid()local F=syscall.getpasswd(q)local r=F and F.shell or"/bin/hysh"local s=F and F.homedir or"/"syscall.devctl(1,"sfgc",0x00FF00)syscall.write(1,"\nWelcome, "..p.."!\n")syscall.devctl(1,"sfgc",0xFFFFFF)sleep(0.3)o(p,q,r,s)return else D=D+1;sleep(1)syscall.devctl(1,"sfgc",0xFF0000)syscall.write(1,"Login incorrect.\n\n")syscall.devctl(1,"sfgc",0xFFFFFF)end end end;syscall.devctl(1,"sfgc",0xFF0000)syscall.write(1,"Maximum login attempts exceeded.\n")syscall.devctl(1,"sfgc",0xFFFFFF)sleep(5)end;f()while true do B()end

View File

@@ -0,0 +1 @@
local a=syscall.getTask(syscall.getpid()).name;local b,c={},{x=false,help=false}for d,e in ipairs({...})do if e:sub(1,2)=="--"then local f=e:sub(3)if f=="help"then c.help=true else print(a..": unrecognised option '"..e.."'")print("try '"..a.." --help' for more information.")syscall.exit(1)return end elseif e:sub(1,1)=="-"then for g=2,#e do local h=e:sub(g,g)if c[h]~=nil then c[h]=true else print(a..": invalid option '-"..h.."'")print("try '"..a.." --help' for more information.")syscall.exit(1)return end end else table.insert(b,e)end end;if c.help then print("Usage: "..a.." <srcdir> <image.hfs>")print(" "..a.." -x <image.hfs> <destdir>")print("")print("Pack a directory into a portable HFS image file, or extract one.")print("")print(" <srcdir> <image.hfs> recursively pack srcdir into image.hfs")print(" -x <image.hfs> <dest> extract image.hfs into dest (created if needed)")print("")print("HFS images can be mounted with:")print(" mount -o loop /path/to/image.hfs /mnt/point")print("")print("Requires root.")return end;local i=require("fs")if c.x then if#b<2 then print(a..": -x requires <image.hfs> and <destdir>")print("try '"..a.." --help' for more information.")syscall.exit(1)return end;local j=b[1]local k=b[2]if j:sub(1,1)~="/"then j=syscall.getcwd().."/"..j end;if k:sub(1,1)~="/"then k=syscall.getcwd().."/"..k end;local l="/tmp/._loimgcreate_"..tostring(math.random(100000,999999))local m,n=pcall(syscall.losetup,j,true)if not m then print(a..": losetup: "..tostring(n))syscall.exit(1)return end;local o,p=pcall(syscall.mount,l,n)if not o then pcall(syscall.lodetach,n)print(a..": mount: "..tostring(p))syscall.exit(1)return end;if not i.isDir(k)then local q,r=pcall(syscall.mkdir,k)if not q then pcall(syscall.umount,l)pcall(syscall.lodetach,n)print(a..": mkdir '"..b[2].."': "..tostring(r))syscall.exit(1)return end end;local s=0;local function t(u,v)local w=i.list(u)if not w then return end;for d,x in ipairs(w)do local y=u:gsub("/$","").."/"..x;local z=v:gsub("/$","").."/"..x;if i.isDir(y)then pcall(syscall.mkdir,z)t(y,z)else local A,B=pcall(syscall.open,y,"r")if A then local o,C=pcall(syscall.open,z,"w")if o then local q,D=pcall(syscall.read,B,65536*16)if q and D then pcall(syscall.write,C,D)end;pcall(syscall.close,C)s=s+1 end;pcall(syscall.close,B)end end end end;t(l,k)pcall(syscall.umount,l)pcall(syscall.lodetach,n)syscall.devctl(1,"sfgc",0x00FFFF)print(a..": extracted "..s.." file(s) to "..k)syscall.devctl(1,"sfgc",0xFFFFFF)return end;if#b<2 then print(a..": missing operands — need <srcdir> and <image.hfs>")print("try '"..a.." --help' for more information.")syscall.exit(1)return end;local E=b[1]local j=b[2]if E:sub(1,1)~="/"then E=syscall.getcwd().."/"..E end;if j:sub(1,1)~="/"then j=syscall.getcwd().."/"..j end;if not i.isDir(E)then print(a..": '"..b[1].."': not a directory")syscall.exit(1)return end;local A,F=pcall(syscall.loimgcreate,E)if not A then local G=tostring(F)if G:find("EPERM")then G="Permission denied"elseif G:find("ENOTDIR")then G="'"..b[1].."': not a directory"end;print(a..": "..G)syscall.exit(1)return end;local o,H=pcall(syscall.loimgwrite,F,j)if not o then print(a..": write '"..b[2].."': "..tostring(H))syscall.exit(1)return end;local I=0;for d in F:gmatch("\n")do I=I+1 end;local J=#F;syscall.devctl(1,"sfgc",0x00FFFF)print(a..": image written to "..j)syscall.devctl(1,"sfgc",0x6D00FF)print(string.format(" %d records, %d bytes",I-1,J))syscall.devctl(1,"sfgc",0xFFFFFF)

1
prod/hysh/bin/losetup Normal file
View File

@@ -0,0 +1 @@
local a=syscall.getTask(syscall.getpid()).name;local b,c={},{d=false,l=false,i=false,help=false}for d,e in ipairs({...})do if e:sub(1,2)=="--"then local f=e:sub(3)if f=="help"then c.help=true else print(a..": unrecognised option '"..e.."'")print("try '"..a.." --help' for more information.")syscall.exit(1)return end elseif e:sub(1,1)=="-"then for g=2,#e do local h=e:sub(g,g)if c[h]~=nil then c[h]=true else print(a..": invalid option '-"..h.."'")print("try '"..a.." --help' for more information.")syscall.exit(1)return end end else table.insert(b,e)end end;if c.help then print("Usage: "..a.." <path>")print(" "..a.." -i <path>")print(" "..a.." -d <id>")print(" "..a.." -l")print("")print("Manage loop devices.")print("")print(" <path> attach a directory (bind) or .hfs image file")print(" -i <path> force image mode for the given file")print(" -d <id> detach loop device by id (must be unmounted first)")print(" -l list all currently attached loop devices")print("")print("Requires root. Loop device ids look like loop0, loop1, …")return end;if c.l then local i,j=pcall(syscall.lolist)if not i then print(a..": "..tostring(j))syscall.exit(1)return end;local k=false;local l={}for m in pairs(j)do l[#l+1]=m end;table.sort(l)for d,m in ipairs(l)do k=true;local n=j[m]local o=type(n)=="table"and n.mode or"bind"local p=type(n)=="table"and n.path or tostring(n)local q=o=="image"and 0x00FFFF or 0x0000FF;syscall.devctl(1,"sfgc",0x00FF00)printInline(string.format("%-10s",m))syscall.devctl(1,"sfgc",q)printInline(string.format("%-7s","["..o.."]"))syscall.devctl(1,"sfgc",0xFFFFFF)print(" "..p)end;if not k then syscall.devctl(1,"sfgc",0x6D00FF)print(a..": no loop devices attached")syscall.devctl(1,"sfgc",0xFFFFFF)end;return end;if c.d then if#b<1 then print(a..": -d requires a loop device id")print("try '"..a.." --help' for more information.")syscall.exit(1)return end;local m=b[1]local i,r=pcall(syscall.lodetach,m)if not i then local s=tostring(r)if s:find("EPERM")then s="Permission denied"elseif s:find("ENXIO")then s="no such loop device '"..m.."'"elseif s:find("EBUSY")then s="device '"..m.."' is still mounted, unmount first"end;print(a..": "..s)syscall.exit(1)return end;syscall.devctl(1,"sfgc",0x00FFFF)print(a..": detached "..m)syscall.devctl(1,"sfgc",0xFFFFFF)return end;if#b<1 then print(a..": missing path operand")print("try '"..a.." --help' for more information.")syscall.exit(1)return end;local p=b[1]if p:sub(1,1)~="/"then p=syscall.getcwd().."/"..p end;local t=syscall.type and syscall.type(p)if not(t=="file"or t=="directory")then print(a..": '"..b[1].."': no such file or directory")syscall.exit(1)return end;local i,u=pcall(syscall.losetup,p,c.i or nil)if not i then local s=tostring(u)if s:find("EPERM")then s="Permission denied"elseif s:find("ENOENT")then s="'"..b[1].."': no such file"elseif s:find("EINVAL")then s="'"..b[1].."': not a directory or .hfs image"elseif s:find("EIO")then s="'"..b[1].."': I/O error reading image"end;print(a..": "..s)syscall.exit(1)return end;print(u)

1
prod/hysh/bin/ls Normal file
View File

@@ -0,0 +1 @@
local a={a=false,h=false,l=false,help=false}local b={...}local c={}local d=syscall.getTask(syscall.getpid()).name;for e,f in pairs(b)do if f:sub(1,2)=="--"then local g=f:sub(3)if a[g]==nil then print(d..": unrecognized option '"..f.."'.")print("try '"..d.." --help' for more information.")return end;a[g]=true elseif f:sub(1,1)=="-"then for h=2,#f do local g=f:sub(h,h)if a[g]==nil then print(d..": invalid option '-"..g.."'.")print("try '"..d.." --help' for more information.")return end;a[g]=true end else table.insert(c,f)end end;if a.help then print("Usage: "..d.." [OPTION]... [DIR]")print("List all entries in the specified DIRectory, or cwd if not specified.")print("")print("Options:")print(" -a do not ignore entries starting with .")print(" -h with -l, print sizes in human readable format")print(" -l use a long listing format")print(" --help display this help and exit")return end;local i=require("fs")local j=c[1]or""if j:sub(1,1)~="/"then j=syscall.getcwd().."/"..j end;if j:sub(-1)~="/"then j=j.."/"end;if not i.isDir(j)then print(d..": cannot access '"..(c[1]or j).."': no such directory")return end;local function k(l,m)local function n(o)return math.floor(l/2^o)%2==1 end;local p;if m==0x01 then p="l"elseif m==nil then p="-"else p="-"end;local q=n(5)and"r"or"-"local r=n(4)and"w"or"-"local s=n(9)and(n(6)and"s"or"x")or(n(6)and"S"or"-")local t=n(3)and"r"or"-"local u=n(2)and"w"or"-"local v=n(8)and"x"or"-"local w=n(1)and"r"or"-"local x=n(0)and"w"or"-"local y=n(7)and"x"or"-"return p..q..r..s..t..u..v..w..x..y end;local z={"K","M","G","T"}local function A(B)local C=0;while B>=1024 and C<#z do B=B/1024;C=C+1 end;if C==0 then return tostring(B).."B"end;if B<10 then return string.format("%.1f%s",B,z[C])end;return math.floor(B)..z[C]end;local D=syscall.devctl(1,"size")local E=tonumber(D:match("^(%d+)"))or 80;local F=i.list(j)if not a.a then for h=#F,1,-1 do if F[h]:sub(1,1)=="."then table.remove(F,h)end end end;table.sort(F)if#F==0 then return end;if a.l then for e,f in ipairs(F)do local G=j..f;local H=syscall.lstat and syscall.lstat(G)or syscall.stat(G)local I=i.isDir(G)local J=H and H.etype==0x01;local isSock=H and H.etype==0x02;local K;if J then K="l"elseif I then K="d"elseif isSock then K="s"else K="-"end;local L;if H and H.perms then L=k(H.perms,H.etype)else L=K.."---------"end;local B=H and H.size or 0;local M=a.h and A(B)or tostring(B)local N=H and H.modified and math.floor(H.modified/1000)or 0;local O=H and tostring(H.owner)or"0"local P=H and tostring(H.group)or"0"printInline(L.." "..O.." "..P.." ")printInline(string.format("%6s",M).." ")printInline(tostring(N).." ")if J then syscall.devctl(1,"sfgc",0x00FFFF)printInline(f)syscall.devctl(1,"sfgc",0xFFFFFF)local Q,R=pcall(syscall.readlink,G)if Q then printInline(" -> ")local S=pcall(syscall.stat,G)syscall.devctl(1,"sfgc",S and 0x00FFFF or 0xFF0000)printInline(R)syscall.devctl(1,"sfgc",0xFFFFFF)end elseif I then syscall.devctl(1,"sfgc",0x6D00FF)printInline(f)syscall.devctl(1,"sfgc",0xFFFFFF)elseif isSock then syscall.devctl(1,"sfgc",0xFF00FF)printInline(f)syscall.devctl(1,"sfgc",0xFFFFFF)else local T=H and H.perms and math.floor(H.perms/2^9)%2==1;syscall.devctl(1,"sfgc",T and 0x00FF00 or 0xFFFFFF)printInline(f)syscall.devctl(1,"sfgc",0xFFFFFF)end;print("")end;return end;local U=0;for e,f in ipairs(F)do if#f+2>U then U=#f+2 end end;local V=math.max(1,math.floor(E/U))for h,f in ipairs(F)do local G=j..f;local I=i.isDir(G)local H=syscall.lstat and syscall.lstat(G)or syscall.stat(G)local J=H and H.etype==0x01;if J then syscall.devctl(1,"sfgc",0x00FFFF)elseif I then syscall.devctl(1,"sfgc",0x6D00FF)elseif isSock then syscall.devctl(1,"sfgc",0xFF00FF)else local T=H and H.perms and math.floor(H.perms/2^9)%2==1;syscall.devctl(1,"sfgc",T and 0x00FF00 or 0xFFFFFF)end;printInline(f)syscall.devctl(1,"sfgc",0xFFFFFF)printInline((" "):rep(U-#f))if h%V==0 then print("")end end;if#F%V~=0 then print("")end

1
prod/hysh/bin/lsusers Normal file
View File

@@ -0,0 +1 @@
local a=syscall.listusers()if not a or#a==0 then print("No users found.")return end;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",0xFFFFFF)for b,c in ipairs(a)do local d=c.locked and" [locked]"or""if c.locked then syscall.devctl(1,"sfgc",0xFF0000)end;print(string.format("%-6d %-6d %-16s %-20s %s%s",c.uid,c.gid,c.username,c.homedir,c.shell,d))if c.locked then syscall.devctl(1,"sfgc",0xFFFFFF)end end

1
prod/hysh/bin/mount Normal file
View File

@@ -0,0 +1 @@
local a=syscall.getTask(syscall.getpid()).name;local b,c={},{help=false,o=nil}local d=1;local e={...}while d<=#e do local f=e[d]if f:sub(1,2)=="--"then local g=f:sub(3)if g=="help"then c.help=true else print(a..": unrecognised option '"..f.."'")print("try '"..a.." --help' for more information.")syscall.exit(1)return end elseif f=="-o"then d=d+1;c.o=e[d]elseif f:sub(1,1)=="-"then local h=f:sub(2)if h:sub(1,1)=="o"then if#h>1 then c.o=h:sub(2)else d=d+1;c.o=e[d]end else print(a..": invalid option '"..f.."'")print("try '"..a.." --help' for more information.")syscall.exit(1)return end else table.insert(b,f)end;d=d+1 end;if c.help then print("Usage: "..a)print(" "..a.." <id> <mountpoint>")print(" "..a.." -o loop <source> <mountpoint>")print("")print("Mount a loop device or filesystem.")print("")print(" (no args) list all active mount points")print(" <id> <mountpoint> mount an already-attached loop device")print(" -o loop <src> <dest> attach src as loop device and mount at dest")print(" src can be a directory (bind) or .hfs image")print("")print("Requires root for all operations except listing.")return end;if#b==0 and not c.o then local i,j=pcall(syscall.mounts or function()error("ENOSYS")end)local k={}local l,m=pcall(syscall.lolist)if l then for n,o in pairs(m)do local p=type(o)=="table"and o.path or tostring(o)local q=type(o)=="table"and o.mode or"bind"k[n]={path=p,mode=q}end end;if next(k)==nil then syscall.devctl(1,"sfgc",0xFF00FF)print("(no loop devices attached)")syscall.devctl(1,"sfgc",0xFFFFFF)return end;for n,o in pairs(k)do local r=o.mode=="image"and 0x00FFFF or 0x0000FF;syscall.devctl(1,"sfgc",r)printInline(o.mode.." "..n)syscall.devctl(1,"sfgc",0xFFFFFF)print(" on "..o.path)end;return end;if c.o and c.o:lower()=="loop"then if#b<2 then print(a..": -o loop requires <source> and <mountpoint>")print("try '"..a.." --help' for more information.")syscall.exit(1)return end;local s=b[1]local t=b[2]if s:sub(1,1)~="/"then s=syscall.getcwd().."/"..s end;if t:sub(1,1)~="/"then t=syscall.getcwd().."/"..t end;local i,u=pcall(syscall.losetup,s)if not i then local v=tostring(u)if v:find("EPERM")then v="Permission denied"elseif v:find("EINVAL")then v="'"..b[1].."': not a directory or .hfs image"elseif v:find("EIO")then v="'"..b[1].."': I/O error reading image"end;print(a..": losetup: "..v)syscall.exit(1)return end;local w,x=pcall(syscall.mount,t,u)if not w then pcall(syscall.lodetach,u)local v=tostring(x)if v:find("EPERM")then v="Permission denied"elseif v:find("EBUSY")then v="'"..t.."' is already a mount point"elseif v:find("ENODEV")then v="loop device not found (internal error)"end;print(a..": mount: "..v)syscall.exit(1)return end;syscall.devctl(1,"sfgc",0x00FFFF)print(a..": "..u.." mounted at "..t)syscall.devctl(1,"sfgc",0xFFFFFF)return end;if#b==2 then local u=b[1]local t=b[2]if t:sub(1,1)~="/"then t=syscall.getcwd().."/"..t end;local i,y=pcall(syscall.mount,t,u)if not i then local v=tostring(y)if v:find("EPERM")then v="Permission denied"elseif v:find("ENODEV")then v="'"..u.."': no such device - use losetup first"elseif v:find("EBUSY")then v="'"..t.."' is already a mount point"elseif v:find("EINVAL")then v="invalid arguments"end;print(a..": "..v)syscall.exit(1)return end;syscall.devctl(1,"sfgc",0x00FFFF)print(a..": "..u.." mounted at "..t)syscall.devctl(1,"sfgc",0xFFFFFF)return end;print(a..": wrong number of arguments")print("try '"..a.." --help' for more information.")syscall.exit(1)

1
prod/hysh/bin/passwd Normal file
View File

@@ -0,0 +1 @@
local a={...}local b=a[1]local c=syscall.getuid()local d;if b then d=syscall.getuid()if not d then print("passwd: user '"..b.."' does not exist")syscall.exit(1)return end;if c~=0 and d~=c then print("passwd: permission denied")syscall.exit(1)return end else d=c;b=syscall.getUsername(c)or tostring(c)end;if c~=0 then printInline("Current password: ")local e=""while true do local f=syscall.read(0)if not f or f==""then elseif f=="\n"then syscall.write(1,"\n")break elseif f=="\b"then if#e>0 then e=e:sub(1,-2)syscall.write(1,"\b \b")end else e=e..f;syscall.write(1,"*")end end;local g,h=syscall.login(d,e)if not g then sleep(1)print("passwd: authentication failure")syscall.exit(1)return end end;printInline("New password: ")local i=""while true do local f=syscall.read(0)if not f or f==""then elseif f=="\n"then syscall.write(1,"\n")break elseif f=="\b"then if#i>0 then i=i:sub(1,-2)syscall.write(1,"\b \b")end else i=i..f;syscall.write(1,"*")end end;printInline("Confirm password: ")local j=""while true do local f=syscall.read(0)if not f or f==""then elseif f=="\n"then syscall.write(1,"\n")break elseif f=="\b"then if#j>0 then j=j:sub(1,-2)syscall.write(1,"\b \b")end else j=j..f;syscall.write(1,"*")end end;if i~=j then print("passwd: passwords do not match")syscall.exit(1)return end;local g,h=syscall.setpassword(d,i)if not g then print("passwd: "..tostring(h))syscall.exit(1)return end;print("passwd: password updated for '"..b.."'")

1
prod/hysh/bin/ps Normal file
View File

@@ -0,0 +1 @@
for a,b in ipairs(syscall.getTasks())do local c=syscall.getTask(b)print(c.pid,c.username,c.name,c.status)end

1
prod/hysh/bin/readlink Normal file
View File

@@ -0,0 +1 @@
local a=syscall.getTask(syscall.getpid()).name;local b={n=false,f=false,e=false,help=false}local c={}for d,e in ipairs({...})do if e:sub(1,2)=="--"then local f=e:sub(3)if b[f]==nil then print(a..": unrecognized option '"..e.."'")syscall.exit(1)return end;b[f]=true elseif e:sub(1,1)=="-"then for g=2,#e do local f=e:sub(g,g)if b[f]==nil then print(a..": invalid option '-"..f.."'")syscall.exit(1)return end;b[f]=true end else table.insert(c,e)end end;if b.help then print("Usage: "..a.." [OPTION]... FILE...")print("Print the resolved target of symbolic links.")print("")print("Options:")print(" -f canonicalize: follow every symlink; last component need not exist")print(" -e like -f but all components must exist")print(" -n do not output trailing newline")print(" --help display this help and exit")return end;if#c==0 then print(a..": missing operand")print("try '"..a.." --help' for more information.")syscall.exit(1)return end;local function h(i)if i:sub(1,1)~="/"then local j=syscall.getcwd()if j:sub(-1)~="/"then j=j.."/"end;i=j..i end;return i end;local k=false;for d,l in ipairs(c)do l=h(l)if b.f or b.e then local m,n=pcall(syscall.stat,l)if not m then if b.e then print(a..": "..l..": "..tostring(n))k=true else if not b.n then print(l)else printInline(l)end end else if not b.n then print(l)else printInline(l)end end else local m,o=pcall(syscall.readlink,l)if not m then print(a..": "..l..": "..tostring(o))k=true else if not b.n then print(o)else printInline(o)end end end end;if k then syscall.exit(1)end

1
prod/hysh/bin/su Normal file
View File

@@ -0,0 +1 @@
local a=({...})[1]local b=syscall.getuid()if syscall.geteuid()~=0 then syscall.exec("/bin/su",{...})end;local c;if a then c=syscall.getuidbyname(a)else c=0 end;if not c then print("su: user '"..a.."' does not exist")syscall.exit(1)return end;if b~=0 then printInline("Password: ")local d=""while true do local e=syscall.read(0)if not e or e==""then elseif e=="\n"then syscall.write(1,"\n")break elseif e=="\b"then if#d>0 then d=d:sub(1,-2)syscall.write(1,"\b \b")end else d=d..e;syscall.write(1,"*")end end;local f,g=syscall.login(c,d)if not f then sleep(1)print("su: Authentication failure")syscall.exit(1)return end else syscall.setuid(c)end;local h=syscall.getpasswd(c)local i=h and h.shell or"/bin/hysh"local j=h and h.homedir or"/"local k=h and h.username or"Unknown"local l,m=pcall(syscall.chdir,j)if not l then j="/"syscall.chdir(j)end;syscall.setEnviron("HOME",j)syscall.setEnviron("USER",k)syscall.setEnviron("SHELL",i)local f,g=pcall(syscall.exec,i)if not f then print("su: cannot exec shell '"..i.."': "..tostring(g))syscall.exit(1)end

1
prod/hysh/bin/sudo Normal file
View File

@@ -0,0 +1 @@
local a=require("fs")local b={...}local c="root"local d=1;if b[d]=="-u"then d=d+1;local e=b[d]or"root"local f=tonumber(e)if f then local g=syscall.getpasswd(f)c=g and g.username or e else c=e end;d=d+1 end;local h=b[d]if not h or h==""then print("usage: sudo [-u user] <command> [args...]")syscall.exit(1)return end;local i={}for j=d+1,#b do i[#i+1]=b[j]end;local k=syscall.getuid()local l=syscall.getUsername(k)or tostring(k)local m=syscall.getuidbyname(c)if not m then print("sudo: user '"..c.."' does not exist")syscall.exit(1)return end;if k~=0 then printInline("[sudo] password for root: ")local n=""while true do local o=syscall.read(0)if not o or o==""then elseif o=="\n"then syscall.write(1,"\n")break elseif o=="\b"then if#n>0 then n=n:sub(1,-2)syscall.write(1,"\b \b")end else n=n..o;syscall.write(1,"*")end end;local p,q=syscall.login(0,n)if not p then sleep(1)print("sudo: Authentication failure")syscall.exit(1)return end;if m~=k then syscall.setuid(m)end else if m~=k then syscall.setuid(m)end end;local r=""if h:find("/")then if a.exists(h)then r=h end else local s=string.split(syscall.getEnviron("PATH")or"/bin/",":")for t,u in ipairs(s)do local v=u..h;if a.exists(v)then r=v;break end end end;if r==""then print("sudo: command not found: "..h)syscall.exit(1)return end;local w=a.readAllText(r)local x,y=load(w,"@"..r)if not x then print("sudo: cannot load "..h..": "..tostring(y))syscall.exit(1)return end;local g=syscall.getpasswd(m)if g and g.homedir then syscall.setEnviron("HOME",g.homedir)end;syscall.setEnviron("USER",c)local p,q=xpcall(x,debug.traceback,table.unpack(i))if not p then print("sudo: "..h..": "..tostring(q))syscall.exit(1)end

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