finished http implementation working on spm and liveboot env
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
Hyperion
|
||||
Astronand
|
||||
@@ -0,0 +1,7 @@
|
||||
local http=require("http")
|
||||
local ok,err = xpcall(http.get, debug.traceback, "http://localhost:8000/spm.json")
|
||||
if not ok then
|
||||
print(err)
|
||||
else
|
||||
print(err.body)
|
||||
end
|
||||
@@ -26,8 +26,7 @@ local function parseUrl(url)
|
||||
end
|
||||
|
||||
local function buildRequest(req)
|
||||
local host, path =
|
||||
parseUrl(req.url)
|
||||
local host, path = parseUrl(req.url)
|
||||
|
||||
if not host then
|
||||
return nil, path
|
||||
@@ -75,73 +74,39 @@ local function buildRequest(req)
|
||||
return table.concat(out, "\r\n")
|
||||
end
|
||||
|
||||
local function parseResponse(raw)
|
||||
local headerEnd =
|
||||
raw:find(
|
||||
"\r\n\r\n",
|
||||
1,
|
||||
true
|
||||
)
|
||||
|
||||
if not headerEnd then
|
||||
return nil, "EBADMSG"
|
||||
local function parseResponse(response)
|
||||
local headerBlock, body = response:match("^(.-)\r\n\r\n(.*)$")
|
||||
if not headerBlock then
|
||||
return nil, "invalid HTTP response"
|
||||
end
|
||||
|
||||
local headerPart =
|
||||
raw:sub(1, headerEnd - 1)
|
||||
|
||||
local body =
|
||||
raw:sub(headerEnd + 4)
|
||||
|
||||
local lines = {}
|
||||
|
||||
for line in headerPart:gmatch("[^\r\n]+") do
|
||||
lines[#lines + 1] = line
|
||||
end
|
||||
|
||||
local _, code, msg =
|
||||
lines[1]:match(
|
||||
"^(HTTP/%S+)%s+(%d+)%s*(.*)$"
|
||||
)
|
||||
|
||||
local headers = {}
|
||||
|
||||
for i = 2, #lines do
|
||||
local k, v =
|
||||
lines[i]:match(
|
||||
"^([^:]+):%s*(.*)$"
|
||||
)
|
||||
-- Parse status line
|
||||
local statusLine, rest = headerBlock:match("^(.-)\r\n(.*)$")
|
||||
if not statusLine then
|
||||
statusLine = headerBlock
|
||||
rest = ""
|
||||
end
|
||||
|
||||
if k then
|
||||
headers[k:lower()] = v
|
||||
local version, code, message = statusLine:match("^(HTTP/%d+%.%d+)%s+(%d+)%s+(.*)$")
|
||||
|
||||
-- Parse headers
|
||||
for line in (rest .. "\r\n"):gmatch("(.-)\r\n") do
|
||||
local key, value = line:match("^([^:]+):%s*(.*)$")
|
||||
if key then
|
||||
headers[key:lower()] = value
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
code = tonumber(code),
|
||||
message = msg,
|
||||
headers = headers,
|
||||
body = body
|
||||
code=tonumber(code),
|
||||
message=message,
|
||||
headers=headers,
|
||||
body=body
|
||||
}
|
||||
end
|
||||
|
||||
local function readAll(fd)
|
||||
local out = ""
|
||||
|
||||
while true do
|
||||
local chunk =
|
||||
syscall.read(fd, 4096)
|
||||
|
||||
if not chunk or chunk == "" then
|
||||
break
|
||||
end
|
||||
|
||||
out = out .. chunk
|
||||
end
|
||||
|
||||
return out
|
||||
end
|
||||
|
||||
function http.request(req)
|
||||
local raw, err =
|
||||
buildRequest(req)
|
||||
@@ -151,34 +116,50 @@ function http.request(req)
|
||||
end
|
||||
|
||||
local fd =
|
||||
syscall.socket(0, 0)
|
||||
syscall.socket()
|
||||
|
||||
if not fd then
|
||||
return nil, "ESOCKET"
|
||||
end
|
||||
|
||||
local ok, err =
|
||||
syscall.connect(fd, req.url)
|
||||
local host, path = parseUrl(req.url)
|
||||
|
||||
if not host then
|
||||
syscall.close(fd)
|
||||
return nil, path
|
||||
end
|
||||
|
||||
local proto = req.url:match("^(https?://)")
|
||||
|
||||
local base = proto .. host
|
||||
|
||||
local ok, err = syscall.connect(fd, base)
|
||||
|
||||
if not ok then
|
||||
syscall.close(fd)
|
||||
return nil, err
|
||||
end
|
||||
|
||||
local ok2, err2 =
|
||||
syscall.write(fd, raw)
|
||||
local ok2, err2 = syscall.write(fd, raw)
|
||||
|
||||
if not ok2 then
|
||||
syscall.close(fd)
|
||||
return nil, err2
|
||||
end
|
||||
|
||||
local resp =
|
||||
readAll(fd)
|
||||
local out = {}
|
||||
|
||||
while true do
|
||||
local chunk = syscall.read(fd, 4096)
|
||||
if chunk == "" then
|
||||
break
|
||||
end
|
||||
|
||||
out[#out+1] = chunk
|
||||
end
|
||||
|
||||
syscall.close(fd)
|
||||
|
||||
return parseResponse(resp)
|
||||
return parseResponse(table.concat(out))
|
||||
end
|
||||
|
||||
function http.get(url, headers)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Core library for Hyperion
|
||||
@@ -0,0 +1 @@
|
||||
1.0.0
|
||||
@@ -0,0 +1,3 @@
|
||||
Hyperion
|
||||
Astronand
|
||||
GHXX (Advanced Computers)
|
||||
@@ -0,0 +1 @@
|
||||
firmware for Advanced Computers
|
||||
@@ -0,0 +1 @@
|
||||
1.0.0
|
||||
@@ -0,0 +1,2 @@
|
||||
Hyperion
|
||||
Astronand
|
||||
@@ -0,0 +1 @@
|
||||
firmware for CraftOS PC
|
||||
@@ -0,0 +1 @@
|
||||
1.0.0
|
||||
@@ -0,0 +1,2 @@
|
||||
Hyperion
|
||||
Astronand
|
||||
@@ -9,25 +9,15 @@ kernel.cct.httpqueue = kernel.cct.httpqueue or {}
|
||||
kernel.cct.httpresponse = kernel.cct.httpresponse or {}
|
||||
kernel.cct.httperror = kernel.cct.httperror or {}
|
||||
|
||||
local function parseRawRequest(raw)
|
||||
local sepLen = 4
|
||||
|
||||
local headerEnd =
|
||||
raw:find("\r\n\r\n", 1, true)
|
||||
|
||||
if not headerEnd then
|
||||
headerEnd =
|
||||
raw:find("\n\n", 1, true)
|
||||
|
||||
sepLen = 2
|
||||
end
|
||||
local function parseRawRequest(raw, address)
|
||||
local headerEnd = raw:find("\r\n\r\n", 1, true)
|
||||
|
||||
local headerPart
|
||||
local body = ""
|
||||
|
||||
if headerEnd then
|
||||
headerPart = raw:sub(1, headerEnd - 1)
|
||||
body = raw:sub(headerEnd + sepLen)
|
||||
body = raw:sub(headerEnd + 4)
|
||||
else
|
||||
headerPart = raw
|
||||
end
|
||||
@@ -42,37 +32,25 @@ local function parseRawRequest(raw)
|
||||
return nil, "EINVAL"
|
||||
end
|
||||
|
||||
local method, path =
|
||||
lines[1]:match("^(%S+)%s+(%S+)")
|
||||
|
||||
if not method or not path then
|
||||
return nil, "EBADMSG"
|
||||
local split=string.split(lines[1], " ")
|
||||
if #split~=3 then
|
||||
return nil, "EINVAL"
|
||||
end
|
||||
local method, path, ver = table.unpack(split)
|
||||
|
||||
local headers = {}
|
||||
|
||||
for i = 2, #lines do
|
||||
local k, v =
|
||||
lines[i]:match("^([^:]+):%s*(.*)$")
|
||||
|
||||
local k, v = lines[i]:match("^([^:]+):%s*(.*)$")
|
||||
if k then
|
||||
headers[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
local host = headers.Host or headers.host
|
||||
|
||||
if not host and not path:match("^https?://") then
|
||||
return nil, "EHOSTUNREACH"
|
||||
end
|
||||
|
||||
local url
|
||||
|
||||
if path:match("^https?://") then
|
||||
url = path
|
||||
else
|
||||
url = "http://" .. host .. path
|
||||
if path:sub(1,1)~="/" then
|
||||
return nil, "EINVAL"
|
||||
end
|
||||
local url = address..path
|
||||
|
||||
local req = {
|
||||
url = url,
|
||||
@@ -84,7 +62,7 @@ local function parseRawRequest(raw)
|
||||
req.body = body
|
||||
end
|
||||
|
||||
return req
|
||||
return req, url
|
||||
end
|
||||
|
||||
local function buildResponse(resp)
|
||||
@@ -93,37 +71,19 @@ local function buildResponse(resp)
|
||||
end
|
||||
|
||||
local code, msg = resp.getResponseCode()
|
||||
|
||||
local headers =
|
||||
resp:getResponseHeaders()
|
||||
|
||||
local body =
|
||||
resp:readAll() or ""
|
||||
local headers = resp.getResponseHeaders()
|
||||
local body = resp.readAll() or ""
|
||||
resp.close()
|
||||
|
||||
local out = {
|
||||
"HTTP/1.1 " ..
|
||||
tostring(code) ..
|
||||
" " ..
|
||||
tostring(msg)
|
||||
tostring(msg or "")
|
||||
}
|
||||
|
||||
local hasLength = false
|
||||
|
||||
for k, v in pairs(headers or {}) do
|
||||
if k:lower() == "content-length" then
|
||||
hasLength = true
|
||||
end
|
||||
|
||||
out[#out + 1] =
|
||||
tostring(k) ..
|
||||
": " ..
|
||||
tostring(v)
|
||||
end
|
||||
|
||||
if not hasLength then
|
||||
out[#out + 1] =
|
||||
"Content-Length: " ..
|
||||
tostring(#body)
|
||||
for i,v in pairs(headers) do
|
||||
out[#out+1] = i..": "..v
|
||||
end
|
||||
|
||||
out[#out + 1] = ""
|
||||
@@ -139,155 +99,91 @@ function handler.connect(fd, address)
|
||||
return nil, "EBADF"
|
||||
end
|
||||
|
||||
fdo.socket.rbuf = ""
|
||||
fdo.socket.closed = false
|
||||
fdo.socket.httpid = nil
|
||||
|
||||
fdo.handle.write = function(raw)
|
||||
local req, err =
|
||||
parseRawRequest(raw)
|
||||
local req, url = parseRawRequest(raw, address)
|
||||
|
||||
if not req then
|
||||
return nil, err
|
||||
return nil, url
|
||||
end
|
||||
|
||||
local id =
|
||||
tostring(kernel.uuid())
|
||||
|
||||
fdo.socket.httpid = id
|
||||
|
||||
kernel.cct.httpqueue[id] = true
|
||||
|
||||
local ok, err =
|
||||
http.request(req, id)
|
||||
kernel.cct.httpqueue[url] = true
|
||||
local ok, err = http.request(req)
|
||||
|
||||
if not ok then
|
||||
kernel.cct.httpqueue[id] = nil
|
||||
kernel.cct.httpqueue[url] = nil
|
||||
return nil, err
|
||||
end
|
||||
if fdo.socket.active then
|
||||
fdo.socket.content=nil
|
||||
fdo.socket.file.close()
|
||||
fdo.socket.file=nil
|
||||
end
|
||||
fdo.socket.active=true
|
||||
fdo.socket.url=url
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
fdo.handle.read = function(count)
|
||||
count = count or 4096
|
||||
|
||||
local sock = fdo.socket
|
||||
|
||||
if #sock.rbuf > 0 then
|
||||
local out =
|
||||
sock.rbuf:sub(1, count)
|
||||
|
||||
sock.rbuf =
|
||||
sock.rbuf:sub(count + 1)
|
||||
|
||||
return out
|
||||
if not fdo.socket.active then
|
||||
return
|
||||
end
|
||||
|
||||
local id = sock.httpid
|
||||
|
||||
if not id then
|
||||
return ""
|
||||
if not kernel.cct.httpqueue[fdo.socket.url] then
|
||||
fdo.socket.file=kernel.sfile(buildResponse(kernel.cct.httpresponse[fdo.socket.url]))
|
||||
kernel.cct.httpqueue[fdo.socket.url]=nil
|
||||
kernel.cct.httpresponse[fdo.socket.url]=nil
|
||||
end
|
||||
|
||||
local function finish(resp)
|
||||
sock.rbuf =
|
||||
buildResponse(resp) or ""
|
||||
|
||||
local out =
|
||||
sock.rbuf:sub(1, count)
|
||||
|
||||
sock.rbuf =
|
||||
sock.rbuf:sub(count + 1)
|
||||
|
||||
return out
|
||||
end
|
||||
|
||||
if kernel.cct.httpresponse[id] then
|
||||
local resp =
|
||||
kernel.cct.httpresponse[id]
|
||||
|
||||
kernel.cct.httpresponse[id] = nil
|
||||
kernel.cct.httpqueue[id] = nil
|
||||
|
||||
return finish(resp)
|
||||
end
|
||||
|
||||
if kernel.cct.httperror[id] then
|
||||
local err =
|
||||
kernel.cct.httperror[id]
|
||||
|
||||
kernel.cct.httperror[id] = nil
|
||||
kernel.cct.httpqueue[id] = nil
|
||||
|
||||
return nil, err
|
||||
end
|
||||
|
||||
kernel.currentTask.status = "D"
|
||||
|
||||
local coro
|
||||
|
||||
coro = function()
|
||||
if kernel.cct.httpresponse[id] then
|
||||
local resp =
|
||||
kernel.cct.httpresponse[id]
|
||||
|
||||
kernel.cct.httpresponse[id] = nil
|
||||
kernel.cct.httpqueue[id] = nil
|
||||
|
||||
kernel.asyncReturn(
|
||||
finish(resp)
|
||||
)
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
if kernel.cct.httperror[id] then
|
||||
local err =
|
||||
kernel.cct.httperror[id]
|
||||
|
||||
kernel.cct.httperror[id] = nil
|
||||
kernel.cct.httpqueue[id] = nil
|
||||
|
||||
kernel.asyncReturn(
|
||||
nil,
|
||||
err
|
||||
)
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
coroutine.yield()
|
||||
end
|
||||
|
||||
kernel.currentTask.ksh =
|
||||
coroutine.create(function()
|
||||
local ok, err =
|
||||
xpcall(
|
||||
coro,
|
||||
debug.traceback
|
||||
)
|
||||
|
||||
if not ok then
|
||||
kernel.asyncReturn(
|
||||
nil,
|
||||
err
|
||||
)
|
||||
if not fdo.socket.file then
|
||||
kernel.currentTask.io=function()
|
||||
if not kernel.cct.httpqueue[fdo.socket.url] then
|
||||
fdo.socket.file=kernel.sfile(buildResponse(kernel.cct.httpresponse[fdo.socket.url]))
|
||||
kernel.cct.httpqueue[fdo.socket.url]=nil
|
||||
kernel.cct.httpresponse[fdo.socket.url]=nil
|
||||
return fdo.socket.file.read(count)
|
||||
end
|
||||
end)
|
||||
end
|
||||
kernel.currentTask.status="D"
|
||||
return
|
||||
else
|
||||
return fdo.socket.file.read(count)
|
||||
end
|
||||
end
|
||||
|
||||
fdo.handle.seek = function(whence, offset)
|
||||
if not fdo.socket.active then
|
||||
return
|
||||
end
|
||||
|
||||
if not kernel.cct.httpqueue[fdo.socket.url] then
|
||||
fdo.socket.file=kernel.sfile(buildResponse(kernel.cct.httpresponse[fdo.socket.url]))
|
||||
kernel.cct.httpqueue[fdo.socket.url]=nil
|
||||
kernel.cct.httpresponse[fdo.socket.url]=nil
|
||||
end
|
||||
|
||||
if not fdo.socket.file then
|
||||
kernel.currentTask.io=function()
|
||||
if not kernel.cct.httpqueue[fdo.socket.url] then
|
||||
fdo.socket.file=kernel.sfile(buildResponse(kernel.cct.httpresponse[fdo.socket.url]))
|
||||
kernel.cct.httpqueue[fdo.socket.url]=nil
|
||||
kernel.cct.httpresponse[fdo.socket.url]=nil
|
||||
return fdo.socket.file.seek(whence, offset)
|
||||
end
|
||||
end
|
||||
kernel.currentTask.status="D"
|
||||
return
|
||||
else
|
||||
return fdo.socket.file.seek(whence, offset)
|
||||
end
|
||||
end
|
||||
|
||||
fdo.handle.close = function()
|
||||
fdo.socket.closed = true
|
||||
|
||||
local id =
|
||||
fdo.socket.httpid
|
||||
|
||||
if id then
|
||||
kernel.cct.httpqueue[id] = nil
|
||||
kernel.cct.httpresponse[id] = nil
|
||||
kernel.cct.httperror[id] = nil
|
||||
end
|
||||
fdo.socket.file.close()
|
||||
fdo.socket.active=false
|
||||
kernel.cct.httpqueue[fdo.socket.url] = nil
|
||||
kernel.cct.httpresponse[fdo.socket.url] = nil
|
||||
kernel.cct.httperror[fdo.socket.url] = nil
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
@@ -74,11 +74,16 @@ kernel.processes.cctdeamon = function()
|
||||
kernel.cct.fifo.push("[nT")
|
||||
end
|
||||
elseif eventType == "http_success" then
|
||||
kernel.cct.httpqueue[event[2]]=nil
|
||||
kernel.cct.httpresponse[event[2]]=event[3]
|
||||
if kernel.cct.httpqueue[event[2]] then
|
||||
kernel.cct.httpqueue[event[2]]=nil
|
||||
kernel.cct.httpresponse[event[2]]=event[3]
|
||||
end
|
||||
elseif eventType == "http_failure" then
|
||||
kernel.cct.httpqueue[event[2]]=nil
|
||||
kernel.cct.httperror[event[2]]=event[3]
|
||||
if kernel.cct.httpqueue[event[2]] then
|
||||
kernel.cct.httpqueue[event[2]]=nil
|
||||
kernel.cct.httperror[event[2]]=event[3]
|
||||
kernel.cct.httpresponse[event[2]]=event[4]
|
||||
end
|
||||
end
|
||||
|
||||
timeout = false
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
firmware for ComputerCraft Tweaked
|
||||
@@ -0,0 +1 @@
|
||||
1.3.0
|
||||
@@ -0,0 +1 @@
|
||||
Hyperion
|
||||
@@ -0,0 +1 @@
|
||||
firmware for Opencomputers
|
||||
@@ -0,0 +1 @@
|
||||
0.1.0
|
||||
@@ -0,0 +1,3 @@
|
||||
Hyperion
|
||||
Astronand
|
||||
Spsf
|
||||
@@ -193,6 +193,100 @@ function kernel.newUUID()
|
||||
return uuid
|
||||
end
|
||||
|
||||
function kernel.sfile(str, writeable)
|
||||
local buf = {str or ""}
|
||||
local pos = 1
|
||||
local closed = false
|
||||
|
||||
local function content()
|
||||
return table.concat(buf)
|
||||
end
|
||||
|
||||
local function set_content(s)
|
||||
buf = {s}
|
||||
end
|
||||
|
||||
local function flush()
|
||||
str=content()
|
||||
end
|
||||
|
||||
local file = {}
|
||||
|
||||
function file.read(n)
|
||||
assert(not closed, "file is closed")
|
||||
|
||||
local s = content()
|
||||
local len = #s
|
||||
|
||||
if not n then
|
||||
local out = s:sub(pos)
|
||||
pos = len + 1
|
||||
return out
|
||||
end
|
||||
|
||||
local out = s:sub(pos, pos + n - 1)
|
||||
pos = pos + #out
|
||||
return out
|
||||
end
|
||||
|
||||
if writeable then
|
||||
function file.write(data)
|
||||
assert(not closed, "file is closed")
|
||||
|
||||
local s = content()
|
||||
local before = s:sub(1, pos - 1)
|
||||
local after = s:sub(pos + #data)
|
||||
|
||||
set_content(before .. data .. after)
|
||||
pos = pos + #data
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function file.seek(whence, offset)
|
||||
assert(not closed, "file is closed")
|
||||
|
||||
local s = content()
|
||||
local len = #s
|
||||
|
||||
whence = whence or "cur"
|
||||
offset = offset or 0
|
||||
|
||||
if whence == "set" then
|
||||
pos = offset + 1
|
||||
elseif whence == "cur" then
|
||||
pos = pos + offset
|
||||
elseif whence == "end" then
|
||||
pos = len + offset + 1
|
||||
else
|
||||
error("invalid whence")
|
||||
end
|
||||
|
||||
if pos < 1 then pos = 1 end
|
||||
if pos > len + 1 then pos = len + 1 end
|
||||
|
||||
return pos - 1
|
||||
end
|
||||
|
||||
function file.close()
|
||||
assert(not closed, "file is closed")
|
||||
flush()
|
||||
closed = true
|
||||
end
|
||||
|
||||
function file.flush()
|
||||
assert(not closed, "file is closed")
|
||||
flush()
|
||||
end
|
||||
|
||||
function file.content()
|
||||
return str
|
||||
end
|
||||
|
||||
return file
|
||||
end
|
||||
|
||||
kernel.syscalls={}
|
||||
local modules={[0]={}}
|
||||
for i=0, 100 do
|
||||
@@ -297,6 +391,7 @@ kernel.syscalls["halt"]=function()
|
||||
end
|
||||
end
|
||||
|
||||
kernel.saveLog()
|
||||
kernel.log("Running modules")
|
||||
for _,p in ipairs(modules) do
|
||||
for _,v in ipairs(p) do
|
||||
@@ -310,6 +405,7 @@ for _,p in ipairs(modules) do
|
||||
local status, err = xpcall(func,debug.traceback, kernel)
|
||||
if not status then kernel.panic("ModuRunErr: "..tostring(err)) end
|
||||
if kernel.config.showModLoad then kernel.log("Loaded module "..v, "DBUG", 0x00FFFF) end
|
||||
if kernel.config.moreLogsaves then kernel.saveLog() end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -9,55 +9,39 @@ kernel.reqcache = cache
|
||||
|
||||
local function require(module, ...)
|
||||
if cache[module] then return cache[module].ret end
|
||||
kernel.currentTask.status = "D"
|
||||
local args = {...}
|
||||
kernel.currentTask.ksh = coroutine.create(function()
|
||||
local coro = function()
|
||||
for _, path in ipairs(kernel.searchpaths) do
|
||||
local filepath = path:gsub("?", module)
|
||||
if kernel.vfs.exists(filepath) then
|
||||
if kernel.vfs.type(filepath) == "directory" then
|
||||
filepath = filepath .. "/init.lua"
|
||||
if kernel.vfs.type(filepath) == "directory" then
|
||||
kernel.asyncReturn(false, "Module not found: "..module)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local fd = kernel.vfs.open(filepath, "r")
|
||||
local chunks = {}
|
||||
while true do
|
||||
local chunk = kernel.vfs.read(fd, 4096)
|
||||
if not chunk or chunk == "" then break end
|
||||
chunks[#chunks + 1] = chunk
|
||||
coroutine.yield()
|
||||
end
|
||||
kernel.vfs.close(fd)
|
||||
local data = table.concat(chunks)
|
||||
local func, err = load(data, "@"..module, "t", kernel._U)
|
||||
if not func then
|
||||
kernel.asyncReturn(false, "Error loading module "..module..": "..tostring(err))
|
||||
return
|
||||
end
|
||||
local ok, ret = xpcall(func, debug.traceback, table.unpack(args))
|
||||
if not ok then
|
||||
kernel.asyncReturn(false, "Error running module "..module..": "..tostring(ret))
|
||||
return
|
||||
end
|
||||
cache[module] = {ret = ret, expires = kernel.EFI:getEpochMs() + 120000}
|
||||
kernel.asyncReturn(true, ret)
|
||||
return
|
||||
for _, path in ipairs(kernel.searchpaths) do
|
||||
local filepath = path:gsub("?", module)
|
||||
if kernel.vfs.exists(filepath) then
|
||||
if kernel.vfs.type(filepath) == "directory" then
|
||||
filepath = filepath .. "/init.lua"
|
||||
if kernel.vfs.type(filepath) == "directory" then
|
||||
error("Module not found: "..module)
|
||||
end
|
||||
coroutine.yield()
|
||||
end
|
||||
kernel.asyncReturn(false, "Module not found: "..module)
|
||||
local fd = kernel.vfs.open(filepath, "r")
|
||||
local chunks = {}
|
||||
while true do
|
||||
local chunk = kernel.vfs.read(fd, 4096)
|
||||
if not chunk or chunk == "" then break end
|
||||
chunks[#chunks + 1] = chunk
|
||||
end
|
||||
kernel.vfs.close(fd)
|
||||
local data = table.concat(chunks)
|
||||
local func, err = load(data, "@"..module, "t", kernel._U)
|
||||
if not func then
|
||||
error("Error loading module "..module..": "..tostring(err))
|
||||
end
|
||||
local ok, ret = xpcall(func, debug.traceback, table.unpack(args))
|
||||
if not ok then
|
||||
error("Error running module "..module..": "..tostring(ret))
|
||||
end
|
||||
cache[module] = {ret = ret, expires = kernel.EFI:getEpochMs() + 120000}
|
||||
return ret
|
||||
end
|
||||
local status, err = xpcall(coro, debug.traceback)
|
||||
if not status then
|
||||
kernel.asyncReturn(false, "Error in require coroutine for module "..module..": "..tostring(err))
|
||||
end
|
||||
end)
|
||||
coroutine.yield()
|
||||
end
|
||||
error("Module not found: "..module)
|
||||
end
|
||||
|
||||
kernel.syscalls["require"] = require
|
||||
_G.require = function(...) return syscall.require(...) end
|
||||
_G.require = function(...) return require(...) end
|
||||
@@ -217,7 +217,7 @@ data[".meta"]=strFile(buildMeta({
|
||||
log="/var/log/syslog.log"
|
||||
}))
|
||||
|
||||
if kernel.EFI:getEEPROM() then
|
||||
if kernel.EFI.getEEPROM then
|
||||
function data.eeprom(op, mode)
|
||||
if op=="type" then
|
||||
return "character device"
|
||||
@@ -255,7 +255,7 @@ if kernel.EFI:getEEPROM() then
|
||||
end
|
||||
end
|
||||
|
||||
if kernel.EFI:getNvram() then
|
||||
if kernel.EFI.getNvram then
|
||||
function data.nvram(op, mode)
|
||||
if op=="type" then
|
||||
return "character device"
|
||||
|
||||
@@ -22,7 +22,7 @@ local function getHandler(address)
|
||||
end
|
||||
end
|
||||
|
||||
function socket.socket(domain, socktype)
|
||||
function socket.socket()
|
||||
local fd = kernel.vfs.newfd({
|
||||
handle = {},
|
||||
|
||||
@@ -54,7 +54,7 @@ function socket.socket(domain, socktype)
|
||||
local fdo = kernel.currentTask.fd[fd]
|
||||
|
||||
fdo.handle.read = function()
|
||||
return ""
|
||||
return nil, "ENOTCONN"
|
||||
end
|
||||
|
||||
fdo.handle.write = function()
|
||||
|
||||
@@ -396,22 +396,16 @@ function kernel.main()
|
||||
end
|
||||
|
||||
if task.status == "D" then
|
||||
if task.ksh then
|
||||
coroutine.resume(task.ksh)
|
||||
if coroutine.status(task.ksh) == "dead" then
|
||||
task.ksh = nil
|
||||
if task.status == "D" then
|
||||
task.status = "R"
|
||||
end
|
||||
|
||||
if kernel.config.debugSyscalls then
|
||||
kernel.log("Task " .. task.pid .. " IO wait completed", "DBUG", 0x00FFFF)
|
||||
local sysret = task.syscallReturn
|
||||
for i = 2, #sysret do
|
||||
local v = type(sysret[i]) == "table" and table.serialize(sysret[i]) or tostring(sysret[i])
|
||||
kernel.log(" retval[" .. (i-1) .. "] = " .. v, "DBUG", 0x00FFFF)
|
||||
end
|
||||
end
|
||||
if task.io then
|
||||
local ret = {xpcall(task.io, debug.traceback)}
|
||||
if not ret[1] then
|
||||
task.syscallReturn = {false, table.unpack(ret, 2)}
|
||||
task.status = "R"
|
||||
task.io=nil
|
||||
elseif #ret>1 then
|
||||
task.syscallReturn = {true, table.unpack(ret, 2)}
|
||||
task.status = "R"
|
||||
task.io=nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -25,6 +25,7 @@ kernel.tasks["1"] = {
|
||||
else
|
||||
kernel.panic("Init system exited: " .. tostring(err))
|
||||
end
|
||||
kernel.saveLog()
|
||||
end),
|
||||
|
||||
name = "sysinit",
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
--:Minify:--
|
||||
local kernel = ...
|
||||
if not kernel.vfs.exists("/root") then kernel.vfs.mkdir("/root") end
|
||||
|
||||
kernel.processes.login = function()
|
||||
local ok, err = pcall(kernel.hpv.execspawn, "/bin/login", "login")
|
||||
if not ok then
|
||||
kernel.log("Failed to exec /bin/login: " .. tostring(err), "ERROR", 0xFF0000)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1 @@
|
||||
Hyperion kernel package
|
||||
@@ -0,0 +1 @@
|
||||
1.5.0
|
||||
@@ -0,0 +1,2 @@
|
||||
Hyperion
|
||||
Lua
|
||||
@@ -0,0 +1 @@
|
||||
Bit32 package for Hyperion
|
||||
@@ -0,0 +1 @@
|
||||
1.0.0
|
||||
@@ -0,0 +1,2 @@
|
||||
Hyperion
|
||||
Astronand
|
||||
@@ -0,0 +1 @@
|
||||
blake2s package for Hyperion
|
||||
@@ -0,0 +1 @@
|
||||
1.0.0
|
||||
@@ -0,0 +1,3 @@
|
||||
Hyperion
|
||||
Astronand
|
||||
Spsf
|
||||
@@ -0,0 +1,169 @@
|
||||
--:Minify:--
|
||||
syscall.open("/dev/input/keyboard1", "r") --stdin (fd 0)
|
||||
syscall.open("/dev/tty/1", "w") --stdout (fd 1)
|
||||
syscall.open("/dev/null", "w") --stderr (fd 2)
|
||||
|
||||
|
||||
local MAX_ATTEMPTS = 3
|
||||
|
||||
local function readLine(mask)
|
||||
local input = ""
|
||||
while true do
|
||||
local ch = syscall.read(0)
|
||||
if not ch or ch == "" then
|
||||
elseif ch == "\n" then
|
||||
syscall.write(1, "\n")
|
||||
return input
|
||||
elseif ch == "\b" then
|
||||
if #input > 0 then
|
||||
input = input:sub(1, -2)
|
||||
syscall.write(1, "\b \b")
|
||||
end
|
||||
else
|
||||
input = input .. ch
|
||||
syscall.write(1, mask or ch)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function firstBoot()
|
||||
local shadow = ""
|
||||
local _fd, _fderr = pcall(function()
|
||||
local fd = syscall.open("/etc/shadow", "r")
|
||||
shadow = syscall.read(fd, 65535) or ""
|
||||
syscall.close(fd)
|
||||
end)
|
||||
if shadow: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 pw1 = readLine("*")
|
||||
syscall.write(1, "Confirm password: ")
|
||||
local pw2 = readLine("*")
|
||||
|
||||
if pw1 ~= pw2 then
|
||||
syscall.devctl(1, "sfgc", 0xFF0000)
|
||||
syscall.write(1, "Passwords do not match. Try again.\n\n")
|
||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
||||
elseif #pw1 < 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 ok, err = syscall.setpassword(0, pw1)
|
||||
if ok 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(err) .. "\n")
|
||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function spawnShell(username, uid, shell, homedir)
|
||||
local existsOk, existsErr = pcall(syscall.exists, shell)
|
||||
if not existsOk or not existsErr then
|
||||
syscall.write(1, "login: shell not found: " .. shell .. "\n")
|
||||
sleep(2)
|
||||
return false
|
||||
end
|
||||
|
||||
local accessOk, accessErr = pcall(syscall.access, shell, "rx")
|
||||
|
||||
syscall.setEnviron("HOME", homedir)
|
||||
syscall.setEnviron("USER", username)
|
||||
syscall.setEnviron("SHELL", shell)
|
||||
syscall.setEnviron("PATH", "/bin/")
|
||||
|
||||
local setuidOk, setuidErr = pcall(syscall.setuid, uid)
|
||||
if not setuidOk then
|
||||
syscall.write(1, "login: setuid failed: " .. tostring(setuidErr) .. "\n")
|
||||
sleep(2)
|
||||
return false
|
||||
end
|
||||
|
||||
local chdirOk, chdirErr = pcall(syscall.chdir, homedir)
|
||||
if not chdirOk then
|
||||
pcall(syscall.chdir, "/")
|
||||
end
|
||||
|
||||
local ok, err = pcall(syscall.execspawn, shell, username .. ":shell")
|
||||
if not ok then
|
||||
syscall.write(1, "login: failed to launch shell: " .. tostring(err) .. "\n")
|
||||
sleep(2)
|
||||
return false
|
||||
end
|
||||
|
||||
syscall.exit(0)
|
||||
end
|
||||
|
||||
local function doLogin()
|
||||
syscall.devctl(1, "clear")
|
||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
||||
syscall.devctl(1, "sbgc", 0x000000)
|
||||
syscall.devctl(1, "spos", 1, 1)
|
||||
|
||||
local hostname = syscall.getHostname() or "hyperion"
|
||||
syscall.write(1, "HyperionOS\n")
|
||||
syscall.write(1, hostname .. " login\n\n")
|
||||
|
||||
local attempts = 0
|
||||
while attempts < MAX_ATTEMPTS do
|
||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
||||
syscall.write(1, "Username: ")
|
||||
local username = readLine(nil)
|
||||
|
||||
if username ~= "" then
|
||||
|
||||
syscall.write(1, "Password: ")
|
||||
local password = readLine("*")
|
||||
local uid = syscall.getuidbyname(username)
|
||||
|
||||
local ok, err = syscall.login(uid, password)
|
||||
if ok then
|
||||
local uid = syscall.getuid()
|
||||
local pwent = syscall.getpasswd(uid)
|
||||
|
||||
local shell = (pwent and pwent.shell) or "/bin/hysh"
|
||||
local homedir = (pwent and pwent.homedir) or "/"
|
||||
|
||||
syscall.devctl(1, "sfgc", 0x00FF00)
|
||||
syscall.write(1, "\nWelcome, " .. username .. "!\n")
|
||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
||||
sleep(0.3)
|
||||
|
||||
spawnShell(username, uid, shell, homedir)
|
||||
return -- back to login prompt
|
||||
else
|
||||
attempts = attempts + 1
|
||||
sleep(1)
|
||||
syscall.devctl(1, "sfgc", 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
|
||||
|
||||
firstBoot()
|
||||
while true do
|
||||
doLogin()
|
||||
end
|
||||
@@ -0,0 +1 @@
|
||||
core utilities for user management
|
||||
@@ -0,0 +1 @@
|
||||
1.0.0
|
||||
@@ -0,0 +1,2 @@
|
||||
Hyperion
|
||||
Haoqian He
|
||||
@@ -0,0 +1 @@
|
||||
Libdeflate for Hyperion
|
||||
@@ -0,0 +1 @@
|
||||
1.0.0-release
|
||||
@@ -0,0 +1,2 @@
|
||||
Hyperion
|
||||
Astronand
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
package providing kernel support for framebuffers and graphics
|
||||
@@ -0,0 +1 @@
|
||||
1.0.0
|
||||
@@ -0,0 +1,2 @@
|
||||
Hyperion
|
||||
Spsf
|
||||
@@ -0,0 +1 @@
|
||||
Official Hyperion shell package
|
||||
@@ -0,0 +1 @@
|
||||
1.3.0
|
||||
@@ -0,0 +1,2 @@
|
||||
Hyperion
|
||||
Astronand
|
||||
@@ -0,0 +1 @@
|
||||
ini parser
|
||||
@@ -0,0 +1 @@
|
||||
1.0.0
|
||||
@@ -1,12 +0,0 @@
|
||||
[
|
||||
"Hyperion-kernel",
|
||||
"Hyperion-core",
|
||||
"hysh",
|
||||
"lua",
|
||||
"micro",
|
||||
"sysinit",
|
||||
"bit32",
|
||||
"json",
|
||||
"muxzcat",
|
||||
"spm"
|
||||
]
|
||||
@@ -0,0 +1,2 @@
|
||||
Hyperion
|
||||
Astronand
|
||||
@@ -0,0 +1 @@
|
||||
Hyperion os live installer
|
||||
@@ -0,0 +1 @@
|
||||
1.0.0
|
||||
@@ -0,0 +1,2 @@
|
||||
Hyperion
|
||||
rxi
|
||||
@@ -0,0 +1 @@
|
||||
JSON library for Hyperion
|
||||
@@ -0,0 +1 @@
|
||||
1.0.0
|
||||
@@ -0,0 +1,2 @@
|
||||
Hyperion
|
||||
Spsf
|
||||
@@ -0,0 +1 @@
|
||||
Interactive lua shell
|
||||
@@ -0,0 +1 @@
|
||||
1.2.0
|
||||
@@ -0,0 +1,2 @@
|
||||
Hyperion
|
||||
Spsf
|
||||
@@ -0,0 +1 @@
|
||||
micro text editor
|
||||
@@ -0,0 +1 @@
|
||||
1.0.0
|
||||
@@ -0,0 +1,3 @@
|
||||
Hyperion
|
||||
Mark Langen
|
||||
Astronand (added goto support)
|
||||
@@ -0,0 +1 @@
|
||||
lua minifier
|
||||
@@ -0,0 +1 @@
|
||||
1.0.0
|
||||
@@ -0,0 +1,2 @@
|
||||
Hyperion
|
||||
Astronand
|
||||
@@ -0,0 +1 @@
|
||||
Proportional Integral Derivative library
|
||||
@@ -0,0 +1 @@
|
||||
1.0.0
|
||||
@@ -0,0 +1,2 @@
|
||||
Hyperion
|
||||
Astronand
|
||||
+65
-3
@@ -1,6 +1,68 @@
|
||||
local args={...}
|
||||
|
||||
local json=require("json")
|
||||
local http=require("http")
|
||||
local rootRepo="https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/spm/spm.src"
|
||||
-- local test repo
|
||||
local rootRepo="http://localhost:8000/spm.json"
|
||||
--local rootRepo="https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/spm.json"
|
||||
|
||||
local json = require("json")
|
||||
local http = require("http")
|
||||
local deflate = require("deflate")
|
||||
|
||||
local function checkRepo(repo)
|
||||
local resp = http.get(repo)
|
||||
if resp.code ~= 200 then
|
||||
return false
|
||||
end
|
||||
local repojson = json.decode(resp.body)
|
||||
if not repojson then
|
||||
return false
|
||||
end
|
||||
return true, repojson
|
||||
end
|
||||
|
||||
local function getRepos(root)
|
||||
local repos = {}
|
||||
local visited = {}
|
||||
|
||||
local queue = {root}
|
||||
local head = 1
|
||||
|
||||
while head <= #queue do
|
||||
local url = queue[head]
|
||||
head = head + 1
|
||||
|
||||
if not visited[url] then
|
||||
visited[url] = true
|
||||
|
||||
local ok, repo = checkRepo(url)
|
||||
if ok then
|
||||
table.insert(repos, {
|
||||
url = url,
|
||||
data = repo
|
||||
})
|
||||
|
||||
if repo.refs then
|
||||
for _, ref in ipairs(repo.refs) do
|
||||
if not visited[ref] then
|
||||
queue[#queue + 1] = ref
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return repos
|
||||
end
|
||||
|
||||
local function getPkg(name)
|
||||
|
||||
end
|
||||
|
||||
if args[1] == "install" then
|
||||
local pkg=getPkg(args[2])
|
||||
elseif args[1] == "sync" then
|
||||
error("not implemented")
|
||||
elseif args[1] == "remove" then
|
||||
error("not implemented")
|
||||
end
|
||||
@@ -0,0 +1 @@
|
||||
Simple Package Manager
|
||||
@@ -0,0 +1 @@
|
||||
1.0.0
|
||||
@@ -0,0 +1,2 @@
|
||||
Hyperion
|
||||
Astronand
|
||||
@@ -1,8 +1,9 @@
|
||||
--:Minify:--
|
||||
local kernel=...
|
||||
local fs=require("fs")
|
||||
kernel.log("Sysinit started...")
|
||||
kernel.saveLog()
|
||||
local fs=require("fs")
|
||||
kernel.log("Loaded fs")
|
||||
|
||||
for i,v in pairs(kernel.processes) do
|
||||
kernel.log("Spawning kernel task "..i)
|
||||
@@ -16,30 +17,32 @@ for i,v in pairs(kernel.processes) do
|
||||
end, i)
|
||||
end
|
||||
|
||||
if not fs.exists("/bin/startup") then
|
||||
fs.mkdir("/bin/startup")
|
||||
-- config file path setup
|
||||
if not fs.exists("/etc/sysinit/") then
|
||||
kernel.log("Creating conf path")
|
||||
fs.mkdir("/etc/sysinit/")
|
||||
fs.mkdir("/etc/sysinit/autorun/")
|
||||
fs.mkdir("/etc/sysinit/system/")
|
||||
fs.mkdir("/etc/sysinit/user/")
|
||||
end
|
||||
|
||||
local files = fs.list("/bin/startup")
|
||||
if not files then error("Failed to list /bin/startup") end
|
||||
local files = fs.list("/etc/sysinit/autorun/")
|
||||
if not files then error("Failed to list autorun") end
|
||||
for i,v in ipairs(files) do
|
||||
if v:sub(-4) == ".lua" then
|
||||
local filepath = "/bin/startup/" .. v
|
||||
kernel.log("Executing startup script: " .. filepath)
|
||||
local startupFunc, err = load(fs.readAllText(filepath), "@" .. filepath)
|
||||
if not startupFunc then
|
||||
kernel.log("Error loading startup script '" .. filepath .. "': " .. err, "ERROR", 0xFF0000)
|
||||
else
|
||||
syscall.spawn(function()
|
||||
syscall.setuid(1)
|
||||
local status, err = pcall(startupFunc)
|
||||
if not status then
|
||||
kernel.log("Error executing startup script '" .. filepath .. "': " .. err, "ERROR", 0xFF0000)
|
||||
else
|
||||
kernel.log("Successfully executed startup script: " .. filepath)
|
||||
end
|
||||
end, "startup:" .. v)
|
||||
end
|
||||
local filepath = "/etc/sysinit/autorun/" .. v
|
||||
kernel.log("Executing startup script: " .. filepath)
|
||||
local startupFunc, err = load(fs.readAllText(filepath), "@" .. filepath)
|
||||
if not startupFunc then
|
||||
kernel.log("Error loading startup script '" .. filepath .. "': " .. err, "ERROR", 0xFF0000)
|
||||
else
|
||||
syscall.spawn(function()
|
||||
local status, err = pcall(startupFunc)
|
||||
if not status then
|
||||
kernel.log("Error executing startup script '" .. filepath .. "': " .. err, "ERROR", 0xFF0000)
|
||||
else
|
||||
kernel.log("Successfully executed startup script: " .. filepath)
|
||||
end
|
||||
end, "startup:" .. v)
|
||||
end
|
||||
end
|
||||
kernel.saveLog()
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
System init package
|
||||
@@ -0,0 +1 @@
|
||||
1.1.0
|
||||
@@ -0,0 +1,5 @@
|
||||
Hyperion
|
||||
Astronand
|
||||
pts@fazekas.hu
|
||||
JackMacWindows
|
||||
hanzhao
|
||||
@@ -0,0 +1 @@
|
||||
XZ compression library
|
||||
@@ -0,0 +1 @@
|
||||
1.0.0
|
||||
Reference in New Issue
Block a user