mirror of
https://github.com/20kdc/OC-KittenOS.git
synced 2025-02-17 12:06:01 +11:00
Just make everything *better*.
This commit is contained in:
parent
36afa760c4
commit
c2b373f261
@ -3,59 +3,48 @@
|
|||||||
|
|
||||||
-- app-claw: Package manager.
|
-- app-claw: Package manager.
|
||||||
|
|
||||||
-- HTTP-only because OCEmu SUCKS
|
-- libs & such
|
||||||
local source = "http://20kdc.duckdns.org/neo/"
|
|
||||||
|
|
||||||
local primaryINet = neo.requestAccess("c.internet")
|
|
||||||
if primaryINet then primaryINet = primaryINet.list()() end
|
|
||||||
|
|
||||||
local function pkgExists(pkg, isApp)
|
|
||||||
local b = {}
|
|
||||||
if isApp then
|
|
||||||
b = neo.listApps()
|
|
||||||
else
|
|
||||||
b = neo.listLibs()
|
|
||||||
end
|
|
||||||
for _, v in ipairs(b) do
|
|
||||||
if v == pkg then return true end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- global app variables
|
|
||||||
-- elements:
|
|
||||||
-- {
|
|
||||||
-- description,
|
|
||||||
-- dlURL/nil,
|
|
||||||
-- localPath,
|
|
||||||
-- isApp,
|
|
||||||
-- }
|
|
||||||
local packages = {}
|
|
||||||
local packageList = {}
|
|
||||||
local libList = {} -- removed after scan
|
|
||||||
local windows = 1
|
|
||||||
local searchTx = ""
|
|
||||||
local primaryWindowRegen
|
|
||||||
--
|
|
||||||
|
|
||||||
local event = require("event")(neo)
|
local event = require("event")(neo)
|
||||||
local neoux, err = require("neoux")
|
local neoux, err = require("neoux")
|
||||||
if not neoux then error(err) end
|
if not neoux then error(err) end
|
||||||
neoux = neoux(event, neo)
|
neoux = neoux(event, neo)
|
||||||
|
local claw = require("claw")()
|
||||||
|
|
||||||
local function download(url)
|
-- HTTP-only because OCEmu SUCKS
|
||||||
|
local source = "http://20kdc.duckdns.org/neo/"
|
||||||
|
local disks = neo.requireAccess("c.filesystem", "searching disks for packages")
|
||||||
|
local primaryDisk = disks.primary
|
||||||
|
local primaryINet = neo.requestAccess("c.internet")
|
||||||
|
if primaryINet then primaryINet = primaryINet.list()() end
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
local function yielder()
|
||||||
|
-- slightly dangerous, but what can we do?
|
||||||
|
event.sleepTo(os.uptime() + 0.05)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function download(url, cb)
|
||||||
if not primaryINet then return nil, "no internet" end
|
if not primaryINet then return nil, "no internet" end
|
||||||
local req, err = primaryINet.request(url)
|
local req, err = primaryINet.request(source .. url)
|
||||||
if not req then
|
if not req then
|
||||||
|
cb(nil)
|
||||||
return nil, tostring(err)
|
return nil, tostring(err)
|
||||||
end
|
end
|
||||||
local ok, err = req.finishConnect()
|
local ok, err = req.finishConnect()
|
||||||
if not req.finishConnect() then
|
if not req.finishConnect() then
|
||||||
req.close()
|
req.close()
|
||||||
|
cb(nil)
|
||||||
return nil, tostring(err)
|
return nil, tostring(err)
|
||||||
end
|
end
|
||||||
local dt = ""
|
local dt = ""
|
||||||
while true do
|
while true do
|
||||||
local n, n2 = req.read()
|
local n, n2 = req.read()
|
||||||
|
local o, r = cb(n)
|
||||||
|
if not o then
|
||||||
|
req.close()
|
||||||
|
return nil, r
|
||||||
|
end
|
||||||
if not n then
|
if not n then
|
||||||
req.close()
|
req.close()
|
||||||
if n2 then
|
if n2 then
|
||||||
@ -65,274 +54,280 @@ local function download(url)
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
if n == "" then
|
if n == "" then
|
||||||
-- slightly dangerous, but what can we do?
|
yielder()
|
||||||
event.sleepTo(os.uptime() + 0.05)
|
|
||||||
end
|
end
|
||||||
dt = dt .. n
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
req.close()
|
req.close()
|
||||||
return dt
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local function readLocal()
|
local function fsSrc(disk)
|
||||||
-- Read apps & libs
|
return function (url, cb)
|
||||||
local function isLua(v)
|
local h, e = disk.open(url, "rb")
|
||||||
if v:sub(#v - 3) == ".lua" then
|
if not h then cb(nil) return nil, tostring(e) end
|
||||||
return v:sub(1, #v - 4)
|
local c = ""
|
||||||
|
while c do
|
||||||
|
c = disk.read(h, neo.readBufSize)
|
||||||
|
local o, r = cb(c)
|
||||||
|
if not o then return nil, r end
|
||||||
end
|
end
|
||||||
end
|
disk.close(h)
|
||||||
for _, pkg in ipairs(neo.listApps()) do
|
return true
|
||||||
table.insert(packageList, pkg)
|
|
||||||
packages[pkg] = {
|
|
||||||
"A pre-installed or self-written process.",
|
|
||||||
nil,
|
|
||||||
"apps/" .. pkg .. ".lua",
|
|
||||||
true
|
|
||||||
}
|
|
||||||
end
|
|
||||||
for _, pkg in ipairs(neo.listLibs()) do
|
|
||||||
table.insert(libList, pkg)
|
|
||||||
packages[pkg] = {
|
|
||||||
"A pre-installed or self-written library.",
|
|
||||||
nil,
|
|
||||||
"libs/" .. pkg .. ".lua",
|
|
||||||
false
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function getEntry(name, isApp)
|
local function fsDst(disk)
|
||||||
if packages[name] then
|
return {function (url)
|
||||||
if packages[name][4] ~= isApp then
|
local h, e = disk.open(url, "wb")
|
||||||
return
|
if not h then return nil, tostring(e) end
|
||||||
end
|
return function (d)
|
||||||
else
|
local ok, r = true
|
||||||
local path = "libs/" .. name .. ".lua"
|
if d then
|
||||||
if isApp then
|
ok, r = disk.write(h, d)
|
||||||
path = "apps/" .. name .. ".lua"
|
|
||||||
end
|
|
||||||
packages[name] = {"An unknown entry, lost to time.", nil, path, isApp}
|
|
||||||
if isApp then
|
|
||||||
table.insert(packageList, name)
|
|
||||||
else
|
|
||||||
table.insert(libList, name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return packages[name]
|
|
||||||
end
|
|
||||||
|
|
||||||
local function readWeb()
|
|
||||||
local listData, err = download(source .. "list")
|
|
||||||
if not listData then
|
|
||||||
neoux.startDialog("Couldn't get web index: " .. err, "web", true)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
--neoux.startDialog(listData, "web", false)
|
|
||||||
listData = (listData .. "\n"):gmatch(".-\n")
|
|
||||||
local function listDataStrip()
|
|
||||||
local l = listData()
|
|
||||||
if not l then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
l = l:sub(1, #l - 1)
|
|
||||||
return l
|
|
||||||
end
|
|
||||||
while true do
|
|
||||||
local l = listDataStrip()
|
|
||||||
if not l then return end
|
|
||||||
if l == "end" then return end
|
|
||||||
local ent = getEntry(l:sub(5), l:sub(1, 4) == "app ")
|
|
||||||
if ent then
|
|
||||||
ent[1] = listDataStrip() or "PARSE ERROR"
|
|
||||||
ent[2] = source .. l:sub(5) .. ".lua"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
readLocal()
|
|
||||||
if source then
|
|
||||||
readWeb()
|
|
||||||
end
|
|
||||||
|
|
||||||
table.sort(packageList)
|
|
||||||
table.sort(libList)
|
|
||||||
for _, v in ipairs(libList) do
|
|
||||||
table.insert(packageList, v)
|
|
||||||
end
|
|
||||||
libList = nil
|
|
||||||
|
|
||||||
local function startPackageWindow(pkg)
|
|
||||||
windows = windows + 1
|
|
||||||
local downloading = false
|
|
||||||
local desc = packages[pkg][1]
|
|
||||||
local isApp = packages[pkg][4]
|
|
||||||
local isSysSvc = isApp and (pkg:sub(1, 4) == "sys-")
|
|
||||||
local isSvc = isSysSvc or (isApp and (pkg:sub(1, 4) == "svc-"))
|
|
||||||
local settings
|
|
||||||
if isSvc then
|
|
||||||
settings = neo.requestAccess("x.neo.sys.manage")
|
|
||||||
end
|
|
||||||
local function update(w)
|
|
||||||
if downloading then return end
|
|
||||||
downloading = true
|
|
||||||
local fd = download(packages[pkg][2])
|
|
||||||
local msg = "Success!"
|
|
||||||
if fd then
|
|
||||||
local primaryDisk = neo.requestAccess("c.filesystem").primary
|
|
||||||
local f = primaryDisk.open(packages[pkg][3], "wb")
|
|
||||||
primaryDisk.write(f, fd)
|
|
||||||
primaryDisk.close(f)
|
|
||||||
else
|
|
||||||
msg = "Couldn't download."
|
|
||||||
end
|
|
||||||
w.close()
|
|
||||||
windows = windows - 1
|
|
||||||
primaryWindowRegen()
|
|
||||||
-- Another event loop so the program won't exit too early.
|
|
||||||
neoux.startDialog(msg, pkg, true)
|
|
||||||
downloading = false
|
|
||||||
end
|
|
||||||
|
|
||||||
local elems = {
|
|
||||||
neoux.tcrawview(1, 1, neoux.fmtText(unicode.safeTextFormat(desc), 30)),
|
|
||||||
}
|
|
||||||
-- {txt, run}
|
|
||||||
local buttonbar = {}
|
|
||||||
if pkgExists(pkg, isApp) then
|
|
||||||
if isApp then
|
|
||||||
if not isSvc then
|
|
||||||
table.insert(buttonbar, {"Start", function (w)
|
|
||||||
neo.executeAsync(pkg)
|
|
||||||
w.close()
|
|
||||||
windows = windows - 1
|
|
||||||
end})
|
|
||||||
else
|
else
|
||||||
if not isSysSvc then
|
disk.close(h)
|
||||||
table.insert(buttonbar, {"Start", function (w)
|
|
||||||
neo.executeAsync(pkg)
|
|
||||||
w.close()
|
|
||||||
windows = windows - 1
|
|
||||||
end})
|
|
||||||
end
|
|
||||||
if settings.getSetting("run." .. pkg) == "yes" then
|
|
||||||
table.insert(buttonbar, {"Disable", function (w)
|
|
||||||
settings.setSetting("run." .. pkg, "no")
|
|
||||||
w.close()
|
|
||||||
windows = windows - 1
|
|
||||||
end})
|
|
||||||
else
|
|
||||||
table.insert(buttonbar, {"Enable", function (w)
|
|
||||||
settings.setSetting("run." .. pkg, "yes")
|
|
||||||
w.close()
|
|
||||||
windows = windows - 1
|
|
||||||
end})
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
if not ok then return nil, tostring(r) end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
if packages[pkg][2] then
|
end, disk.makeDirectory, disk.exists, disk.isDirectory, disk.remove, disk.rename}
|
||||||
table.insert(buttonbar, {"Update", update})
|
end
|
||||||
|
|
||||||
|
local function checked(...)
|
||||||
|
local res, res2, err = pcall(...)
|
||||||
|
if not res then
|
||||||
|
neoux.startDialog(tostring(res2), "error!", true)
|
||||||
|
elseif not res2 then
|
||||||
|
neoux.startDialog(tostring(err), "failed!", true)
|
||||||
|
else
|
||||||
|
return res2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Beginning Of The App (well, the actual one)
|
||||||
|
|
||||||
|
local genCurrent, genPrimary, genPackage, primaryWindow
|
||||||
|
local windows = 1
|
||||||
|
|
||||||
|
-- primary
|
||||||
|
local primarySearchTx = ""
|
||||||
|
local primaryPage = 1
|
||||||
|
local primaryList = {}
|
||||||
|
-- package
|
||||||
|
local packageLock = nil
|
||||||
|
local packageId = "FIXME"
|
||||||
|
|
||||||
|
local function describe(pkg)
|
||||||
|
local weHave = claw.getInfo(pkg, "local")
|
||||||
|
local theyHave = claw.getInfo(pkg, "local")
|
||||||
|
local someoneHas = claw.getInfo(pkg, nil, true)
|
||||||
|
if weHave then
|
||||||
|
if theyHave.v > weHave.v then
|
||||||
|
return pkg .. " [v" .. weHave.v .. "!]"
|
||||||
end
|
end
|
||||||
table.insert(buttonbar, {"Delete", function (w)
|
if someoneHas.v < weHave.v then
|
||||||
local primaryDisk = neo.requestAccess("c.filesystem").primary
|
return pkg .. " (v" .. weHave.v .. ") R<"
|
||||||
primaryDisk.remove(packages[pkg][3])
|
end
|
||||||
|
return pkg .. " (v" .. weHave.v .. ")"
|
||||||
|
end
|
||||||
|
return pkg
|
||||||
|
end
|
||||||
|
|
||||||
|
local function primaryWindowRegenCore()
|
||||||
|
return neoux.tcwindow(25, 12, genCurrent(), function (w)
|
||||||
w.close()
|
w.close()
|
||||||
windows = windows - 1
|
windows = windows - 1
|
||||||
primaryWindowRegen()
|
end, 0xFF8F00, 0)
|
||||||
end})
|
end
|
||||||
else
|
local function primaryWindowRegen()
|
||||||
if packages[pkg][2] then
|
primaryWindow.reset(25, 12, primaryWindowRegenCore())
|
||||||
table.insert(buttonbar, {"Install", update})
|
end
|
||||||
|
|
||||||
|
-- Use all non-primary filesystems
|
||||||
|
for pass = 1, 3 do
|
||||||
|
for v in disks.list() do
|
||||||
|
local nam = nil
|
||||||
|
if v == primaryDisk then
|
||||||
|
nam = (pass == 1) and "local"
|
||||||
|
elseif v == disks.temporary then
|
||||||
|
nam = (pass == 2) and "ramfs"
|
||||||
|
elseif pass == 3 then
|
||||||
|
nam = v.address
|
||||||
|
end
|
||||||
|
if nam then
|
||||||
|
local ok, r = claw.addSource(nam, fsSrc(v), (not v.isReadOnly()) and fsDst(v))
|
||||||
|
if not ok and nam == "local" then
|
||||||
|
claw.unlock()
|
||||||
|
error(r)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local x = 1
|
|
||||||
for _, v in ipairs(buttonbar) do
|
|
||||||
local b = neoux.tcbutton(x, 10, v[1], v[2])
|
|
||||||
x = x + (#v[1]) + 2
|
|
||||||
table.insert(elems, b)
|
|
||||||
end
|
|
||||||
neoux.create(30, 10, pkg, neoux.tcwindow(30, 10, elems, function (w)
|
|
||||||
w.close()
|
|
||||||
windows = windows - 1
|
|
||||||
end, 0xFFFFFF, 0))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local genwin, primaryWindow
|
if primaryINet then
|
||||||
local primaryWindowPage = 1
|
checked(claw.addSource, "inet", download)
|
||||||
local primaryWindowList = packageList
|
|
||||||
|
|
||||||
function primaryWindowRegen()
|
|
||||||
primaryWindow.reset(20, 8, genwin(primaryWindowPage, primaryWindowList))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
genwin = function (page, efList)
|
primaryList = claw.getList()
|
||||||
local pages = math.ceil(#efList / 6)
|
|
||||||
|
-- Sections
|
||||||
|
|
||||||
|
function genPrimary()
|
||||||
|
local pgs = 10
|
||||||
|
local pages = math.ceil(#primaryList / pgs)
|
||||||
local elems = {
|
local elems = {
|
||||||
neoux.tcbutton(18, 1, "+", function (w)
|
neoux.tcbutton(23, 1, "+", function (w)
|
||||||
if page < pages then
|
if primaryPage < pages then
|
||||||
primaryWindowPage = page + 1
|
primaryPage = primaryPage + 1
|
||||||
primaryWindowRegen()
|
primaryWindowRegen()
|
||||||
end
|
end
|
||||||
end),
|
end),
|
||||||
neoux.tcrawview(4, 1, {neoux.pad(page .. " / " .. pages, 14, true, true)}),
|
neoux.tcrawview(4, 1, {neoux.pad(primaryPage .. " / " .. pages, 19, true, true)}),
|
||||||
neoux.tcbutton(1, 1, "-", function (w)
|
neoux.tcbutton(1, 1, "-", function (w)
|
||||||
if page > 1 then
|
if primaryPage > 1 then
|
||||||
primaryWindowPage = page - 1
|
primaryPage = primaryPage - 1
|
||||||
primaryWindowRegen()
|
primaryWindowRegen()
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
}
|
}
|
||||||
local base = (page - 1) * 6
|
local base = (primaryPage - 1) * pgs
|
||||||
for i = 1, 6 do
|
for i = 1, pgs do
|
||||||
local ent = efList[base + i]
|
local ent = primaryList[base + i]
|
||||||
if ent then
|
if ent then
|
||||||
local enttx = ent
|
local enttx = describe(ent)
|
||||||
if packages[ent][4] then
|
|
||||||
enttx = "A " .. enttx
|
|
||||||
else
|
|
||||||
enttx = "L " .. enttx
|
|
||||||
end
|
|
||||||
if pkgExists(ent, packages[ent][4]) then
|
|
||||||
if packages[ent][2] then
|
|
||||||
enttx = "I" .. enttx
|
|
||||||
else
|
|
||||||
enttx = "i" .. enttx
|
|
||||||
end
|
|
||||||
else
|
|
||||||
enttx = " " .. enttx
|
|
||||||
end
|
|
||||||
table.insert(elems, neoux.tcbutton(1, i + 1, unicode.safeTextFormat(enttx), function (w)
|
table.insert(elems, neoux.tcbutton(1, i + 1, unicode.safeTextFormat(enttx), function (w)
|
||||||
-- Start a dialog
|
packageId = ent
|
||||||
startPackageWindow(ent)
|
genCurrent = genPackage
|
||||||
|
primaryWindowRegen()
|
||||||
end))
|
end))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
table.insert(elems, neoux.tcfield(1, 8, 11, function (s)
|
table.insert(elems, neoux.tcfield(1, 12, 16, function (s)
|
||||||
if s then searchTx = s end
|
if s then primarySearchTx = s end
|
||||||
return searchTx
|
return primarySearchTx
|
||||||
end))
|
end))
|
||||||
table.insert(elems, neoux.tcbutton(12, 8, "Search!", function (w)
|
table.insert(elems, neoux.tcbutton(17, 12, "Search!", function (w)
|
||||||
local n = {}
|
local n = {}
|
||||||
for _, v in ipairs(packageList) do
|
for _, v in ipairs(claw.getList()) do
|
||||||
for i = 1, #v do
|
for i = 1, #v do
|
||||||
if v:sub(i, i + #searchTx - 1) == searchTx then
|
if v:sub(i, i + #primarySearchTx - 1) == primarySearchTx then
|
||||||
table.insert(n, v)
|
table.insert(n, v)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
primaryWindowPage = 1
|
primaryPage = 1
|
||||||
primaryWindowList = n
|
primaryList = n
|
||||||
primaryWindowRegen()
|
primaryWindowRegen()
|
||||||
end))
|
end))
|
||||||
return neoux.tcwindow(20, 8, elems, function (w)
|
return elems
|
||||||
w.close()
|
|
||||||
windows = windows - 1
|
|
||||||
end, 0xFFFFFF, 0)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
primaryWindow = neoux.create(20, 8, "claw", genwin(1, packageList))
|
--
|
||||||
|
|
||||||
|
local function packageGetBB(src, lclI, srcI, srcW)
|
||||||
|
local buttons = {}
|
||||||
|
if srcI and srcW then
|
||||||
|
table.insert(buttons, {
|
||||||
|
"Del",
|
||||||
|
function ()
|
||||||
|
if packageLock then return end
|
||||||
|
packageLock = ""
|
||||||
|
checked(claw.remove, src, packageId, true)
|
||||||
|
packageLock = nil
|
||||||
|
primaryWindowRegen()
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
if srcI and ((not lclI) or (lclI.v < srcI.v)) then
|
||||||
|
table.insert(buttons, {
|
||||||
|
"Get",
|
||||||
|
function ()
|
||||||
|
if packageLock then return end
|
||||||
|
packageLock = "installing from " .. src
|
||||||
|
primaryWindowRegen()
|
||||||
|
checked(claw.installTo, "local", packageId, src, true, yielder)
|
||||||
|
packageLock = nil
|
||||||
|
primaryWindowRegen()
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
if srcW and lclI and not srcI then
|
||||||
|
table.insert(buttons, {
|
||||||
|
"All",
|
||||||
|
function ()
|
||||||
|
if packageLock then return end
|
||||||
|
packageLock = "storing w/ dependencies at " .. src
|
||||||
|
primaryWindowRegen()
|
||||||
|
checked(claw.installTo, src, packageId, "local", true, yielder)
|
||||||
|
packageLock = nil
|
||||||
|
primaryWindowRegen()
|
||||||
|
end
|
||||||
|
})
|
||||||
|
table.insert(buttons, {
|
||||||
|
"Put",
|
||||||
|
function ()
|
||||||
|
if packageLock then return end
|
||||||
|
packageLock = "storing at " .. src
|
||||||
|
primaryWindowRegen()
|
||||||
|
checked(claw.installTo, src, packageId, "local", false, yielder)
|
||||||
|
packageLock = nil
|
||||||
|
primaryWindowRegen()
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
return buttons
|
||||||
|
end
|
||||||
|
|
||||||
|
function genPackage()
|
||||||
|
if packageLock then
|
||||||
|
return {neoux.tcrawview(1, 1, neoux.fmtText(unicode.safeTextFormat(packageId .. "\n" .. packageLock), 25))}
|
||||||
|
end
|
||||||
|
-- concept:
|
||||||
|
-- mtd <back>
|
||||||
|
-- Multi-Track Drifting
|
||||||
|
--
|
||||||
|
-- local v20 <del> <run>
|
||||||
|
-- inet v21 <pull>
|
||||||
|
-- dir v22 <pull> <push>
|
||||||
|
-- crockett <push>
|
||||||
|
local info = claw.getInfo(packageId)
|
||||||
|
local infoL = claw.getInfo(packageId, "local")
|
||||||
|
local elems = {
|
||||||
|
neoux.tcrawview(1, 1, neoux.fmtText(unicode.safeTextFormat(packageId .. "\n" .. info.desc .. "\nv" .. info.v .. " deps " .. table.concat(info.deps, ", ")), 25)),
|
||||||
|
neoux.tcbutton(20, 1, "Back", function ()
|
||||||
|
if packageLock then return end
|
||||||
|
genCurrent = genPrimary
|
||||||
|
primaryWindowRegen()
|
||||||
|
end)
|
||||||
|
}
|
||||||
|
local srcs = claw.getSources()
|
||||||
|
for k, v in ipairs(srcs) do
|
||||||
|
local lI = claw.getInfo(packageId, v[1])
|
||||||
|
local row = 12 + k - #srcs
|
||||||
|
local pfx = " "
|
||||||
|
if lI then
|
||||||
|
pfx = "v" .. string.format("%04i", lI.v) .. " "
|
||||||
|
end
|
||||||
|
table.insert(elems, neoux.tcrawview(1, row, {neoux.pad(pfx .. v[1], 14, false, true)}))
|
||||||
|
local col = 26
|
||||||
|
for _, bv in ipairs(packageGetBB(v[1], infoL, lI, v[2])) do
|
||||||
|
local b = neoux.tcbutton(col, row, bv[1], bv[2])
|
||||||
|
col = col - b.w
|
||||||
|
b.x = col
|
||||||
|
table.insert(elems, b)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return elems
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
genCurrent = genPrimary
|
||||||
|
primaryWindow = neoux.create(25, 12, "claw", primaryWindowRegenCore())
|
||||||
|
|
||||||
while windows > 0 do
|
while windows > 0 do
|
||||||
event.pull()
|
event.pull()
|
||||||
end
|
end
|
||||||
|
claw.unlock()
|
||||||
|
@ -36,7 +36,8 @@ local ctrlFlag = false
|
|||||||
local dialogLock = false
|
local dialogLock = false
|
||||||
local appendFlag = false
|
local appendFlag = false
|
||||||
local sW, sH = 37, #lines + 2
|
local sW, sH = 37, #lines + 2
|
||||||
local window = neo.requestAccess("x.neo.pub.window")(sW, sH)
|
local windows = neo.requestAccess("x.neo.pub.window")
|
||||||
|
local window = windows(sW, sH)
|
||||||
local flush
|
local flush
|
||||||
|
|
||||||
local function splitCur()
|
local function splitCur()
|
||||||
@ -55,13 +56,24 @@ local function clampCursorX()
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local cbs = {}
|
||||||
|
|
||||||
local function fileDialog(writing, callback)
|
local function fileDialog(writing, callback)
|
||||||
local tag = neo.requestAccess("x.neo.pub.base").showFileDialogAsync(writing)
|
local tag = neo.requestAccess("x.neo.pub.base").showFileDialogAsync(writing)
|
||||||
local f
|
local f
|
||||||
function f(_, evt, tag2, res)
|
function f(_, evt, tag2, res)
|
||||||
if evt == "filedialog" then
|
if evt == "filedialog" then
|
||||||
if tag == tag2 then
|
if tag == tag2 then
|
||||||
callback(res)
|
local ok, e = pcall(callback, res)
|
||||||
|
if not ok then
|
||||||
|
e = unicode.safeTextFormat(tostring(e))
|
||||||
|
local wnd = windows(unicode.len(e), 1, "ERROR")
|
||||||
|
cbs[wnd.id] = {
|
||||||
|
wnd.close,
|
||||||
|
wnd.span,
|
||||||
|
e
|
||||||
|
}
|
||||||
|
end
|
||||||
event.ignore(f)
|
event.ignore(f)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -410,6 +422,14 @@ while true do
|
|||||||
ev_clipboard(e[4])
|
ev_clipboard(e[4])
|
||||||
flush()
|
flush()
|
||||||
end
|
end
|
||||||
|
elseif cbs[e[2]] then
|
||||||
|
if e[3] == "line" then
|
||||||
|
cbs[e[2]][2](1, 1, cbs[e[2]][3], 0, 0xFFFFFF)
|
||||||
|
end
|
||||||
|
if e[3] == "close" then
|
||||||
|
cbs[e[2]][1]()
|
||||||
|
cbs[e[2]] = nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -26,9 +26,7 @@
|
|||||||
-- or this is a screensaver host, and has a saving-throw to start Bristol if it dies unexpectedly.
|
-- or this is a screensaver host, and has a saving-throw to start Bristol if it dies unexpectedly.
|
||||||
-- In any case, this eventually returns to 2 or 4.
|
-- In any case, this eventually returns to 2 or 4.
|
||||||
|
|
||||||
local everestProvider = neo.requestAccess("r.neo.pub.window", "registering npw")
|
local everestProvider = neo.requireAccess("r.neo.pub.window", "registering npw")
|
||||||
if not everestProvider then return end
|
|
||||||
|
|
||||||
local everestSessionProvider = neo.requireAccess("r.neo.sys.session", "registering nsse")
|
local everestSessionProvider = neo.requireAccess("r.neo.sys.session", "registering nsse")
|
||||||
|
|
||||||
-- Got mutexes. Now setup saving throw and shutdown callback
|
-- Got mutexes. Now setup saving throw and shutdown callback
|
||||||
@ -57,6 +55,9 @@ monitors[0] = {nil, nil, 160, 50}
|
|||||||
-- line y
|
-- line y
|
||||||
local surfaces = {}
|
local surfaces = {}
|
||||||
|
|
||||||
|
-- Last Interact Monitor
|
||||||
|
local lIM = 1
|
||||||
|
|
||||||
-- Stops the main loop
|
-- Stops the main loop
|
||||||
local shuttingDown = false
|
local shuttingDown = false
|
||||||
|
|
||||||
@ -98,7 +99,7 @@ local function surfaceAt(monitor, x, y)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Always use the first sometime before the second
|
-- Always use the first if the GPU has been rebound
|
||||||
local function monitorResetBF(m)
|
local function monitorResetBF(m)
|
||||||
m[5] = -1
|
m[5] = -1
|
||||||
m[6] = -1
|
m[6] = -1
|
||||||
@ -136,9 +137,11 @@ end
|
|||||||
local function updateRegion(monitorId, x, y, w, h, surfaceSpanCache)
|
local function updateRegion(monitorId, x, y, w, h, surfaceSpanCache)
|
||||||
if not renderingAllowed() then return end
|
if not renderingAllowed() then return end
|
||||||
local m = monitors[monitorId]
|
local m = monitors[monitorId]
|
||||||
local mg = m[1]()
|
local mg, rb = m[1]()
|
||||||
if not mg then return end
|
if not mg then return end
|
||||||
monitorResetBF(m)
|
if rb then
|
||||||
|
monitorResetBF(m)
|
||||||
|
end
|
||||||
-- The input region is the one that makes SENSE.
|
-- The input region is the one that makes SENSE.
|
||||||
-- Considering WC handling, that's not an option.
|
-- Considering WC handling, that's not an option.
|
||||||
-- WCHAX: start
|
-- WCHAX: start
|
||||||
@ -198,7 +201,7 @@ local function ensureOnscreen(monitor, x, y, w, h)
|
|||||||
-- Failing anything else, revert to monitor 0
|
-- Failing anything else, revert to monitor 0
|
||||||
if #monitors == 0 then monitor = 0 end
|
if #monitors == 0 then monitor = 0 end
|
||||||
x = math.min(math.max(1, x), monitors[monitor][3] - (w - 1))
|
x = math.min(math.max(1, x), monitors[monitor][3] - (w - 1))
|
||||||
y = math.min(math.max(1, y), monitors[monitor][4] - (h - 1))
|
y = math.max(1, math.min(monitors[monitor][4] - (h - 1), y))
|
||||||
return monitor, x, y
|
return monitor, x, y
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -209,7 +212,10 @@ local function reconcileAll()
|
|||||||
v[1], v[2], v[3] = ensureOnscreen(v[1], v[2], v[3], v[4], v[5])
|
v[1], v[2], v[3] = ensureOnscreen(v[1], v[2], v[3], v[4], v[5])
|
||||||
end
|
end
|
||||||
for k, v in ipairs(monitors) do
|
for k, v in ipairs(monitors) do
|
||||||
local mon = v[1]()
|
local mon, rb = v[1]()
|
||||||
|
if rb then
|
||||||
|
monitorResetBF(v)
|
||||||
|
end
|
||||||
if mon then
|
if mon then
|
||||||
v[3], v[4] = mon.getResolution()
|
v[3], v[4] = mon.getResolution()
|
||||||
end
|
end
|
||||||
@ -218,7 +224,8 @@ local function reconcileAll()
|
|||||||
updateStatus()
|
updateStatus()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function moveSurface(surface, m, x, y, w, h)
|
-- NOTE: If the M, X, Y, W and H are the same, this function ignores you, unless you put , true on the end.
|
||||||
|
local function moveSurface(surface, m, x, y, w, h, force)
|
||||||
local om, ox, oy, ow, oh = table.unpack(surface, 1, 5)
|
local om, ox, oy, ow, oh = table.unpack(surface, 1, 5)
|
||||||
m = m or om
|
m = m or om
|
||||||
x = x or ox
|
x = x or ox
|
||||||
@ -227,24 +234,18 @@ local function moveSurface(surface, m, x, y, w, h)
|
|||||||
h = h or oh
|
h = h or oh
|
||||||
surface[1], surface[2], surface[3], surface[4], surface[5] = m, x, y, w, h
|
surface[1], surface[2], surface[3], surface[4], surface[5] = m, x, y, w, h
|
||||||
local cache = {}
|
local cache = {}
|
||||||
if om == m then
|
if om == m and ow == w and oh == h then
|
||||||
if ow == w then
|
if ox == x and oy == y and not force then
|
||||||
if oh == h then
|
return
|
||||||
-- Cheat - perform a GPU copy
|
end
|
||||||
-- this increases "apparent" performance while we're inevitably waiting for the app to catch up,
|
-- note: this doesn't always work due to WC support
|
||||||
-- CANNOT glitch since we're going to draw over this later,
|
if renderingAllowed() then
|
||||||
-- and will usually work since the user can only move focused surfaces
|
local cb, b = monitors[m][1]()
|
||||||
if renderingAllowed() then
|
if b then
|
||||||
local cb = monitors[m][1]()
|
monitorResetBF(b)
|
||||||
if cb then
|
end
|
||||||
cb.copy(ox, oy, w, h, x - ox, y - oy)
|
if cb then
|
||||||
end
|
cb.copy(ox, oy, w, h, x - ox, y - oy)
|
||||||
end
|
|
||||||
--because OC's widechar support sucks, comment out this perf. opt.
|
|
||||||
--if surfaces[1] == surface then
|
|
||||||
-- updateRegion(om, ox, oy, ow, oh, cache)
|
|
||||||
-- return
|
|
||||||
--end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -266,9 +267,11 @@ end
|
|||||||
local function handleSpan(target, x, y, text, bg, fg)
|
local function handleSpan(target, x, y, text, bg, fg)
|
||||||
if not renderingAllowed() then return end
|
if not renderingAllowed() then return end
|
||||||
local m = monitors[target[1]]
|
local m = monitors[target[1]]
|
||||||
local cb = m[1]()
|
local cb, rb = m[1]()
|
||||||
if not cb then return end
|
if not cb then return end
|
||||||
monitorResetBF(m)
|
if rb then
|
||||||
|
monitorResetBF(m)
|
||||||
|
end
|
||||||
-- It is assumed basic type checks were handled earlier.
|
-- It is assumed basic type checks were handled earlier.
|
||||||
if y < 1 then return end
|
if y < 1 then return end
|
||||||
if y > target[5] then return end
|
if y > target[5] then return end
|
||||||
@ -366,8 +369,7 @@ everestProvider(function (pkg, pid, sendSig)
|
|||||||
end
|
end
|
||||||
local m = 0
|
local m = 0
|
||||||
if renderingAllowed() then m = 1 end
|
if renderingAllowed() then m = 1 end
|
||||||
if surfaces[1] then m = surfaces[1][1] end
|
local surf = {math.min(#monitors, math.max(1, lIM)), 1, 2, w, h}
|
||||||
local surf = {m, 1, 2, w, h}
|
|
||||||
local focusState = false
|
local focusState = false
|
||||||
local llid = lid
|
local llid = lid
|
||||||
lid = lid + 1
|
lid = lid + 1
|
||||||
@ -380,6 +382,10 @@ everestProvider(function (pkg, pid, sendSig)
|
|||||||
if ev == "touch" then
|
if ev == "touch" then
|
||||||
specialDragHandler = nil
|
specialDragHandler = nil
|
||||||
if math.floor(b) == 1 then
|
if math.floor(b) == 1 then
|
||||||
|
if e == 1 then
|
||||||
|
sendSig(llid, "close")
|
||||||
|
return
|
||||||
|
end
|
||||||
specialDragHandler = function (x, y)
|
specialDragHandler = function (x, y)
|
||||||
local ofsX, ofsY = math.floor(x) - math.floor(a), math.floor(y) - math.floor(b)
|
local ofsX, ofsY = math.floor(x) - math.floor(a), math.floor(y) - math.floor(b)
|
||||||
if (ofsX == 0) and (ofsY == 0) then return end
|
if (ofsX == 0) and (ofsY == 0) then return end
|
||||||
@ -397,6 +403,7 @@ everestProvider(function (pkg, pid, sendSig)
|
|||||||
b = b - 1
|
b = b - 1
|
||||||
end
|
end
|
||||||
if ev == "scroll" or ev == "drop" then
|
if ev == "scroll" or ev == "drop" then
|
||||||
|
specialDragHandler = nil
|
||||||
b = b - 1
|
b = b - 1
|
||||||
end
|
end
|
||||||
if ev == "line" then
|
if ev == "line" then
|
||||||
@ -435,7 +442,7 @@ everestProvider(function (pkg, pid, sendSig)
|
|||||||
w = math.floor(math.max(w, 8))
|
w = math.floor(math.max(w, 8))
|
||||||
h = math.floor(math.max(h, 1)) + 1
|
h = math.floor(math.max(h, 1)) + 1
|
||||||
local _, x, y = ensureOnscreen(surf[1], surf[2], surf[3], w, h)
|
local _, x, y = ensureOnscreen(surf[1], surf[2], surf[3], w, h)
|
||||||
moveSurface(surf, nil, x, y, w, h)
|
moveSurface(surf, nil, x, y, w, h, true)
|
||||||
return w, (h - 1)
|
return w, (h - 1)
|
||||||
end,
|
end,
|
||||||
span = function (x, y, text, bg, fg)
|
span = function (x, y, text, bg, fg)
|
||||||
@ -538,6 +545,7 @@ local function key(ka, kc, down)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if focus then
|
if focus then
|
||||||
|
lIM = focus[1]
|
||||||
focus[6]("key", ka, kc, down)
|
focus[6]("key", ka, kc, down)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -577,6 +585,7 @@ while not shuttingDown do
|
|||||||
if s[1] == "h.touch" then
|
if s[1] == "h.touch" then
|
||||||
for k, v in ipairs(monitors) do
|
for k, v in ipairs(monitors) do
|
||||||
if v[2] == s[2] then
|
if v[2] == s[2] then
|
||||||
|
lIM = k
|
||||||
local x, y = math.floor(s[3]), math.floor(s[4])
|
local x, y = math.floor(s[3]), math.floor(s[4])
|
||||||
local ix, iy = s[3] - x, s[4] - y
|
local ix, iy = s[3] - x, s[4] - y
|
||||||
local sid, lx, ly = surfaceAt(k, x, y)
|
local sid, lx, ly = surfaceAt(k, x, y)
|
||||||
@ -586,6 +595,8 @@ while not shuttingDown do
|
|||||||
table.insert(surfaces, 1, ns)
|
table.insert(surfaces, 1, ns)
|
||||||
changeFocus(os)
|
changeFocus(os)
|
||||||
ns[6]("touch", lx, ly, ix, iy, s[5])
|
ns[6]("touch", lx, ly, ix, iy, s[5])
|
||||||
|
else
|
||||||
|
if s[5] == 1 and not waitingShutdownCallback then neo.executeAsync("app-launcher") end
|
||||||
end
|
end
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
@ -263,11 +263,13 @@ donkonitRDProvider(function (pkg, pid, sendSig)
|
|||||||
return function ()
|
return function ()
|
||||||
for v in gpus.list() do
|
for v in gpus.list() do
|
||||||
if v.address == gpu then
|
if v.address == gpu then
|
||||||
|
local didBind = false
|
||||||
if currentGPUBinding[gpu] ~= address then
|
if currentGPUBinding[gpu] ~= address then
|
||||||
v.bind(address, false)
|
v.bind(address, false)
|
||||||
|
didBind = true
|
||||||
end
|
end
|
||||||
currentGPUBinding[gpu] = address
|
currentGPUBinding[gpu] = address
|
||||||
return v
|
return v, didBind
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -110,27 +110,24 @@ end)
|
|||||||
local rootAccess = neo.requireAccess("k.root", "installing GUI integration")
|
local rootAccess = neo.requireAccess("k.root", "installing GUI integration")
|
||||||
local backup = rootAccess.securityPolicyINIT or rootAccess.securityPolicy
|
local backup = rootAccess.securityPolicyINIT or rootAccess.securityPolicy
|
||||||
rootAccess.securityPolicyINIT = backup
|
rootAccess.securityPolicyINIT = backup
|
||||||
rootAccess.securityPolicy = function (pid, proc, req)
|
rootAccess.securityPolicy = function (pid, proc, perm, req)
|
||||||
if neo.dead then
|
if neo.dead then
|
||||||
return backup(pid, proc, req)
|
return backup(pid, proc, perm, req)
|
||||||
end
|
end
|
||||||
req.result = proc.pkg:sub(1, 4) == "sys-"
|
local def = proc.pkg:sub(1, 4) == "sys-"
|
||||||
local secpol, err = require("sys-secpolicy")
|
local secpol, err = require("sys-secpolicy")
|
||||||
if not secpol then
|
if not secpol then
|
||||||
-- Failsafe.
|
-- Failsafe.
|
||||||
neo.emergency("Used fallback policy because of load-err: " .. err)
|
neo.emergency("Used fallback policy because of load-err: " .. err)
|
||||||
req.service()
|
req(def)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
-- Push to ICECAP thread to avoid deadlock on neoux b/c wrong event-pull context
|
-- Push to ICECAP thread to avoid deadlock on neoux b/c wrong event-pull context
|
||||||
event.runAt(0, function ()
|
event.runAt(0, function ()
|
||||||
local ok, err = pcall(secpol, neoux, settings, proc.pkg, pid, req.perm, function (r)
|
local ok, err = pcall(secpol, neoux, settings, proc.pkg, pid, perm, req)
|
||||||
req.result = r
|
|
||||||
req.service()
|
|
||||||
end)
|
|
||||||
if not ok then
|
if not ok then
|
||||||
neo.emergency("Used fallback policy because of run-err: " .. err)
|
neo.emergency("Used fallback policy because of run-err: " .. err)
|
||||||
req.service()
|
req(def)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
@ -153,6 +153,9 @@ local function finalPrompt()
|
|||||||
local password = ""
|
local password = ""
|
||||||
if nsm then
|
if nsm then
|
||||||
password = nsm.getSetting("password")
|
password = nsm.getSetting("password")
|
||||||
|
if nsm.getSetting("sys-init.nologin") == "yes" then
|
||||||
|
return false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
warnings[1] = "TAB to change option,"
|
warnings[1] = "TAB to change option,"
|
||||||
warnings[2] = "ENTER to select..."
|
warnings[2] = "ENTER to select..."
|
||||||
|
@ -2,7 +2,6 @@ return {
|
|||||||
["neo"] = {
|
["neo"] = {
|
||||||
desc = "KittenOS NEO Kernel & Base Libs",
|
desc = "KittenOS NEO Kernel & Base Libs",
|
||||||
v = 0,
|
v = 0,
|
||||||
app = false,
|
|
||||||
deps = {
|
deps = {
|
||||||
},
|
},
|
||||||
dirs = {
|
dirs = {
|
||||||
@ -12,6 +11,7 @@ return {
|
|||||||
},
|
},
|
||||||
files = {
|
files = {
|
||||||
"init.lua",
|
"init.lua",
|
||||||
|
"apps/sys-glacier.lua",
|
||||||
"libs/event.lua",
|
"libs/event.lua",
|
||||||
"libs/serial.lua",
|
"libs/serial.lua",
|
||||||
"libs/neoux.lua",
|
"libs/neoux.lua",
|
||||||
@ -21,10 +21,8 @@ return {
|
|||||||
["neo-init"] = {
|
["neo-init"] = {
|
||||||
desc = "KittenOS NEO / sys-init (startup)",
|
desc = "KittenOS NEO / sys-init (startup)",
|
||||||
v = 0,
|
v = 0,
|
||||||
app = "app-launcher",
|
|
||||||
deps = {
|
deps = {
|
||||||
"neo",
|
"neo",
|
||||||
"neo-glacier",
|
|
||||||
"neo-icecap",
|
"neo-icecap",
|
||||||
"neo-everest"
|
"neo-everest"
|
||||||
},
|
},
|
||||||
@ -38,7 +36,6 @@ return {
|
|||||||
["neo-launcher"] = {
|
["neo-launcher"] = {
|
||||||
desc = "KittenOS NEO / Default app-launcher",
|
desc = "KittenOS NEO / Default app-launcher",
|
||||||
v = 0,
|
v = 0,
|
||||||
app = "app-launcher",
|
|
||||||
deps = {
|
deps = {
|
||||||
"neo"
|
"neo"
|
||||||
},
|
},
|
||||||
@ -50,9 +47,8 @@ return {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
["neo-everest"] = {
|
["neo-everest"] = {
|
||||||
desc = "KittenOS NEO / Everest (settings & monitor management)",
|
desc = "KittenOS NEO / Everest (windowing)",
|
||||||
v = 0,
|
v = 0,
|
||||||
app = "sys-everest",
|
|
||||||
deps = {
|
deps = {
|
||||||
"neo"
|
"neo"
|
||||||
},
|
},
|
||||||
@ -66,7 +62,6 @@ return {
|
|||||||
["neo-icecap"] = {
|
["neo-icecap"] = {
|
||||||
desc = "KittenOS NEO / Icecap",
|
desc = "KittenOS NEO / Icecap",
|
||||||
v = 0,
|
v = 0,
|
||||||
app = "sys-icecap",
|
|
||||||
deps = {
|
deps = {
|
||||||
"neo"
|
"neo"
|
||||||
},
|
},
|
||||||
@ -81,24 +76,21 @@ return {
|
|||||||
"apps/app-fm.lua"
|
"apps/app-fm.lua"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
["neo-glacier"] = {
|
["neo-secpolicy"] = {
|
||||||
desc = "KittenOS NEO / Glacier (settings & monitor management)",
|
desc = "KittenOS NEO / Secpolicy",
|
||||||
v = 0,
|
v = 0,
|
||||||
app = "sys-glacier",
|
|
||||||
deps = {
|
deps = {
|
||||||
"neo"
|
|
||||||
},
|
},
|
||||||
dirs = {
|
dirs = {
|
||||||
"apps"
|
"libs"
|
||||||
},
|
},
|
||||||
files = {
|
files = {
|
||||||
"apps/sys-glacier.lua"
|
"libs/sys-secpolicy.lua"
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
["app-textedit"] = {
|
["neo-coreapps"] = {
|
||||||
desc = "KittenOS NEO Text Editor (Neolithic)",
|
desc = "KittenOS NEO Core Apps",
|
||||||
v = 0,
|
v = 0,
|
||||||
app = "app-textedit",
|
|
||||||
deps = {
|
deps = {
|
||||||
"neo"
|
"neo"
|
||||||
},
|
},
|
||||||
@ -106,13 +98,14 @@ return {
|
|||||||
"apps"
|
"apps"
|
||||||
},
|
},
|
||||||
files = {
|
files = {
|
||||||
"apps/app-textedit.lua"
|
"apps/app-textedit.lua",
|
||||||
},
|
"apps/app-pass.lua",
|
||||||
|
"apps/app-taskmgr.lua"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
["app-flash"] = {
|
["app-flash"] = {
|
||||||
desc = "KittenOS NEO EEPROM Flasher",
|
desc = "KittenOS NEO EEPROM Flasher",
|
||||||
v = 0,
|
v = 0,
|
||||||
app = "app-flash",
|
|
||||||
deps = {
|
deps = {
|
||||||
"neo"
|
"neo"
|
||||||
},
|
},
|
||||||
@ -123,38 +116,9 @@ return {
|
|||||||
"apps/app-flash.lua"
|
"apps/app-flash.lua"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
["app-pass"] = {
|
|
||||||
desc = "KittenOS NEO Password Setter & Logout",
|
|
||||||
v = 0,
|
|
||||||
app = "app-pass",
|
|
||||||
deps = {
|
|
||||||
"neo"
|
|
||||||
},
|
|
||||||
dirs = {
|
|
||||||
"apps"
|
|
||||||
},
|
|
||||||
files = {
|
|
||||||
"apps/app-pass.lua"
|
|
||||||
},
|
|
||||||
},
|
|
||||||
["app-taskmgr"] = {
|
|
||||||
desc = "KittenOS NEO Task Manager",
|
|
||||||
v = 0,
|
|
||||||
app = "app-taskmgr",
|
|
||||||
deps = {
|
|
||||||
"neo"
|
|
||||||
},
|
|
||||||
dirs = {
|
|
||||||
"apps"
|
|
||||||
},
|
|
||||||
files = {
|
|
||||||
"apps/app-taskmgr.lua"
|
|
||||||
},
|
|
||||||
},
|
|
||||||
["app-claw"] = {
|
["app-claw"] = {
|
||||||
desc = "KittenOS NEO Package Manager",
|
desc = "KittenOS NEO Package Manager",
|
||||||
v = 0,
|
v = 0,
|
||||||
app = "app-claw",
|
|
||||||
deps = {
|
deps = {
|
||||||
"neo"
|
"neo"
|
||||||
},
|
},
|
||||||
@ -166,5 +130,24 @@ return {
|
|||||||
"apps/app-claw.lua",
|
"apps/app-claw.lua",
|
||||||
"libs/claw.lua"
|
"libs/claw.lua"
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
["neo-meta"] = {
|
||||||
|
desc = "KittenOS NEO: Use 'All' to install to other disks",
|
||||||
|
v = 0,
|
||||||
|
deps = {
|
||||||
|
"neo",
|
||||||
|
"neo-init",
|
||||||
|
"neo-launcher",
|
||||||
|
"neo-everest",
|
||||||
|
"neo-icecap",
|
||||||
|
"neo-secpolicy",
|
||||||
|
"neo-coreapps",
|
||||||
|
"app-flash",
|
||||||
|
"app-claw"
|
||||||
|
},
|
||||||
|
dirs = {
|
||||||
|
},
|
||||||
|
files = {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,7 @@ primaryDisk = component.proxy(computer.getBootAddress())
|
|||||||
timers = {}
|
timers = {}
|
||||||
|
|
||||||
libraries = {}
|
libraries = {}
|
||||||
setmetatable(libraries, {
|
setmetatable(libraries, {__mode = "v"})
|
||||||
__mode = "v"
|
|
||||||
})
|
|
||||||
|
|
||||||
-- proc.co = coroutine.create(appfunc)
|
-- proc.co = coroutine.create(appfunc)
|
||||||
-- proc.pkg = "pkg"
|
-- proc.pkg = "pkg"
|
||||||
@ -89,7 +87,7 @@ function unicode.undoSafeTextFormat(s)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function loadfile(s, e)
|
local function loadfile(s, e)
|
||||||
local h = primaryDisk.open(s)
|
local h, er = primaryDisk.open(s)
|
||||||
if h then
|
if h then
|
||||||
local ch = ""
|
local ch = ""
|
||||||
local c = primaryDisk.read(h, readBufSize)
|
local c = primaryDisk.read(h, readBufSize)
|
||||||
@ -100,7 +98,7 @@ local function loadfile(s, e)
|
|||||||
primaryDisk.close(h)
|
primaryDisk.close(h)
|
||||||
return load(ch, "=" .. s, "t", e)
|
return load(ch, "=" .. s, "t", e)
|
||||||
end
|
end
|
||||||
return nil, "File Unreadable"
|
return nil, tostring(er)
|
||||||
end
|
end
|
||||||
|
|
||||||
local wrapMeta = nil
|
local wrapMeta = nil
|
||||||
@ -320,6 +318,7 @@ function loadLibraryInner(library)
|
|||||||
library = "libs/" .. library .. ".lua"
|
library = "libs/" .. library .. ".lua"
|
||||||
ensurePath(library, "libs/")
|
ensurePath(library, "libs/")
|
||||||
if libraries[library] then return libraries[library] end
|
if libraries[library] then return libraries[library] end
|
||||||
|
emergencyFunction("loading " .. library)
|
||||||
local l, r = loadfile(library, baseProcEnv())
|
local l, r = loadfile(library, baseProcEnv())
|
||||||
if l then
|
if l then
|
||||||
local ok, al = pcall(l)
|
local ok, al = pcall(l)
|
||||||
@ -335,10 +334,9 @@ end
|
|||||||
|
|
||||||
-- These two are hooks for k.root level applications to change policy.
|
-- These two are hooks for k.root level applications to change policy.
|
||||||
-- Only a k.root application is allowed to do this for obvious reasons.
|
-- Only a k.root application is allowed to do this for obvious reasons.
|
||||||
function securityPolicy(pid, proc, req)
|
function securityPolicy(pid, proc, perm, req)
|
||||||
-- Important safety measure : only sys-* gets anything at first
|
-- Important safety measure : only sys-* gets anything at first
|
||||||
req.result = proc.pkg:sub(1, 4) == "sys-"
|
req(proc.pkg:sub(1, 4) == "sys-")
|
||||||
req.service()
|
|
||||||
end
|
end
|
||||||
function runProgramPolicy(ipkg, pkg, pid, ...)
|
function runProgramPolicy(ipkg, pkg, pid, ...)
|
||||||
-- VERY specific injunction here:
|
-- VERY specific injunction here:
|
||||||
@ -489,13 +487,11 @@ function start(pkg, ...)
|
|||||||
local requestAccessAsync = function (perm)
|
local requestAccessAsync = function (perm)
|
||||||
ensureType(perm, "string")
|
ensureType(perm, "string")
|
||||||
-- Safety-checked, prepare security event.
|
-- Safety-checked, prepare security event.
|
||||||
local req = {}
|
local req = function (res)
|
||||||
req.perm = perm
|
|
||||||
req.service = function ()
|
|
||||||
if processes[pid] then
|
if processes[pid] then
|
||||||
local n = nil
|
local n = nil
|
||||||
local n2 = nil
|
local n2 = nil
|
||||||
if req.result then
|
if res then
|
||||||
proc.access[perm] = true
|
proc.access[perm] = true
|
||||||
proc.denied[perm] = nil
|
proc.denied[perm] = nil
|
||||||
n, n2 = retrieveAccess(perm, pkg, pid)
|
n, n2 = retrieveAccess(perm, pkg, pid)
|
||||||
@ -509,16 +505,14 @@ function start(pkg, ...)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- outer security policy:
|
-- outer security policy:
|
||||||
req.result = proc.access["k.root"] or not proc.denied[perm]
|
|
||||||
|
|
||||||
if proc.access["k.root"] or proc.access[perm] or proc.denied[perm] then
|
if proc.access["k.root"] or proc.access[perm] or proc.denied[perm] then
|
||||||
-- Use cached result to prevent possible unintentional security service spam
|
-- Use cached result to prevent possible unintentional security service spam
|
||||||
req.service()
|
req(proc.access["k.root"] or not proc.denied[perm])
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
-- Denied goes to on to prevent spam
|
-- Denied goes to on to prevent spam
|
||||||
proc.denied[perm] = true
|
proc.denied[perm] = true
|
||||||
securityPolicy(pid, proc, req)
|
securityPolicy(pid, proc, perm, req)
|
||||||
end
|
end
|
||||||
local env = baseProcEnv()
|
local env = baseProcEnv()
|
||||||
env.neo.pid = pid
|
env.neo.pid = pid
|
||||||
@ -558,7 +552,7 @@ function start(pkg, ...)
|
|||||||
if not appfunc then
|
if not appfunc then
|
||||||
return nil, r
|
return nil, r
|
||||||
end
|
end
|
||||||
proc.co = coroutine.create(appfunc)
|
proc.co = coroutine.create(function (...) local r = {xpcall(appfunc, debug.traceback)} if not r[1] then error(table.unpack(r, 2)) end return table.unpack(r, 2) end)
|
||||||
proc.pkg = pkg
|
proc.pkg = pkg
|
||||||
proc.access = {
|
proc.access = {
|
||||||
-- These permissions are the "critical set".
|
-- These permissions are the "critical set".
|
||||||
|
@ -2,3 +2,182 @@
|
|||||||
-- No warranty is provided, implied or otherwise.
|
-- No warranty is provided, implied or otherwise.
|
||||||
|
|
||||||
-- claw: assistant to app-claw
|
-- claw: assistant to app-claw
|
||||||
|
-- should only ever be one app-claw at a time
|
||||||
|
local lock = false
|
||||||
|
return function ()
|
||||||
|
if lock then
|
||||||
|
error("libclaw safety lock in use")
|
||||||
|
end
|
||||||
|
lock = true
|
||||||
|
local sourceList = {}
|
||||||
|
local sources = {}
|
||||||
|
-- 1 2 3 4 5 6
|
||||||
|
-- dst entries: writeFile(fn), mkdir(fn), exists(fn), isDirectory(fn), remove(fn), rename(fna, fnb)
|
||||||
|
-- writeFile(fn) -> function (data/nil to close)
|
||||||
|
local function saveInfo(dn)
|
||||||
|
sources[dn][2][2]("data")
|
||||||
|
sources[dn][2][2]("data/app-claw")
|
||||||
|
local cb, _, r = sources[dn][2][1]("data/app-claw/local.lua")
|
||||||
|
if not cb then return false, r end
|
||||||
|
_, r = cb(require("serial").serialize(sources[dn][3]))
|
||||||
|
if not _ then return false, r end
|
||||||
|
_, r = cb(nil)
|
||||||
|
if not _ then return false, r end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
local remove, installTo
|
||||||
|
-- NOTE: Functions in this must return something due to the checked-call wrapper,
|
||||||
|
-- but should all use error() for consistency.
|
||||||
|
-- Operations
|
||||||
|
installTo = function (dstName, pkg, srcName, checked, yielder)
|
||||||
|
local installed = {pkg}
|
||||||
|
local errs = {}
|
||||||
|
if srcName == dstName then
|
||||||
|
error("Invalid API use")
|
||||||
|
end
|
||||||
|
-- preliminary checks
|
||||||
|
if checked then
|
||||||
|
for _, v in ipairs(sources[srcName][3][pkg].deps) do
|
||||||
|
if not sources[dstName][3][v] then
|
||||||
|
if not sources[srcName][3][v] then
|
||||||
|
table.insert(errs, pkg .. " depends on " .. v .. "\n")
|
||||||
|
elseif #errs == 0 then
|
||||||
|
installTo(dstName, v, srcName, checked, yielder)
|
||||||
|
else
|
||||||
|
table.insert(errs, pkg .. " depends on " .. v .. " (can autoinstall)\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Files from previous versions to get rid of
|
||||||
|
local ignFiles = {}
|
||||||
|
if sources[dstName][3][pkg] then
|
||||||
|
for _, v in ipairs(sources[dstName][3][pkg].files) do
|
||||||
|
ignFiles[v] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _, v in ipairs(sources[srcName][3][pkg].files) do
|
||||||
|
if not ignFiles[v] then
|
||||||
|
if sources[dstName][2][3](v) then
|
||||||
|
table.insert(errs, v .. " already exists (corrupt system?)")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #errs > 0 then
|
||||||
|
error(table.concat(errs))
|
||||||
|
end
|
||||||
|
for _, v in ipairs(sources[srcName][3][pkg].dirs) do
|
||||||
|
sources[dstName][2][2](v)
|
||||||
|
if not sources[dstName][2][4](v) then
|
||||||
|
error("Unable to create directory " .. v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _, v in ipairs(sources[srcName][3][pkg].files) do
|
||||||
|
local ok, r = sources[srcName][1](v, sources[dstName][2][1](v .. ".claw-tmp"))
|
||||||
|
if ok then
|
||||||
|
yielder()
|
||||||
|
else
|
||||||
|
-- Cleanup...
|
||||||
|
for _, v in ipairs(sources[srcName][3][pkg].files) do
|
||||||
|
sources[dstName][2][5](v .. ".claw-tmp")
|
||||||
|
end
|
||||||
|
error(r)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- PAST THIS POINT, ERRORS CORRUPT!
|
||||||
|
sources[dstName][3][pkg] = nil
|
||||||
|
saveInfo(dstName)
|
||||||
|
for k, _ in pairs(ignFiles) do
|
||||||
|
yielder()
|
||||||
|
sources[dstName][2][5](k)
|
||||||
|
end
|
||||||
|
for _, v in ipairs(sources[srcName][3][pkg].files) do
|
||||||
|
yielder()
|
||||||
|
sources[dstName][2][6](v .. ".claw-tmp", v)
|
||||||
|
end
|
||||||
|
sources[dstName][3][pkg] = sources[srcName][3][pkg]
|
||||||
|
saveInfo(dstName)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
remove = function (dstName, pkg, checked)
|
||||||
|
if checked then
|
||||||
|
local errs = {}
|
||||||
|
for dpsName, dpsV in pairs(sources[dstName][3]) do
|
||||||
|
for _, v in ipairs(dpsV.deps) do
|
||||||
|
if v == pkg then
|
||||||
|
table.insert(errs, dpsName .. " depends on " .. pkg .. "\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #errs > 0 then
|
||||||
|
return nil, table.concat(errs)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _, v in ipairs(sources[dstName][3][pkg].files) do
|
||||||
|
sources[dstName][2][5](v)
|
||||||
|
end
|
||||||
|
sources[dstName][3][pkg] = nil
|
||||||
|
saveInfo(dstName)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return {
|
||||||
|
-- Gets the latest info, or if given a source just gives that source's info.
|
||||||
|
-- Do not modify output.
|
||||||
|
getInfo = function (pkg, source, oldest)
|
||||||
|
if source then return sources[source][3][pkg] end
|
||||||
|
local bestI = {
|
||||||
|
v = -1,
|
||||||
|
desc = "An unknown package.",
|
||||||
|
deps = {}
|
||||||
|
}
|
||||||
|
if oldest then bestI.v = 10000 end
|
||||||
|
for _, v in pairs(sources) do
|
||||||
|
if v[3][pkg] then
|
||||||
|
if ((not oldest) and (v[3][pkg].v > bestI.v)) or (oldest and (v[3][pkg].v > bestI.v)) then
|
||||||
|
bestI = v[3][pkg]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return bestI
|
||||||
|
end,
|
||||||
|
-- Provides an ordered list of sources, with writable.
|
||||||
|
-- Do not modify output.
|
||||||
|
getSources = function ()
|
||||||
|
return sourceList
|
||||||
|
end,
|
||||||
|
-- NOTE: If a source is writable, it's added anyway despite any problems.
|
||||||
|
addSource = function (name, src, dst)
|
||||||
|
local ifo = ""
|
||||||
|
local ifok, e = src("data/app-claw/local.lua", function (t)
|
||||||
|
ifo = ifo .. (t or "")
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
ifo = ifok and require("serial").deserialize(ifo)
|
||||||
|
if not (dst or ifo) then return false, e end
|
||||||
|
table.insert(sourceList, {name, not not dst})
|
||||||
|
sources[name] = {src, dst, ifo or {}}
|
||||||
|
return not not ifo, e or "local.lua parse error"
|
||||||
|
end,
|
||||||
|
remove = remove,
|
||||||
|
installTo = installTo,
|
||||||
|
|
||||||
|
-- Gets a total list of packages, as a table of strings. You can modify output.
|
||||||
|
getList = function ()
|
||||||
|
local n = {}
|
||||||
|
local seen = {}
|
||||||
|
for k, v in pairs(sources) do
|
||||||
|
for kb, vb in pairs(v[3]) do
|
||||||
|
if not seen[kb] then
|
||||||
|
seen[kb] = true
|
||||||
|
table.insert(n, kb)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.sort(n)
|
||||||
|
return n
|
||||||
|
end,
|
||||||
|
unlock = function ()
|
||||||
|
lock = false
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
@ -7,7 +7,8 @@
|
|||||||
-- This function needs access to the caller's NEO in order to ensure that NEO system functions are covered.
|
-- This function needs access to the caller's NEO in order to ensure that NEO system functions are covered.
|
||||||
-- This can do less checks than usual as it only affects the caller.
|
-- This can do less checks than usual as it only affects the caller.
|
||||||
|
|
||||||
return function (neo)
|
-- Global forces reference to prevent duplication
|
||||||
|
newEvent = function (neo)
|
||||||
local listeners = {}
|
local listeners = {}
|
||||||
local translations = {}
|
local translations = {}
|
||||||
local timers = {}
|
local timers = {}
|
||||||
@ -102,3 +103,4 @@ return function (neo)
|
|||||||
end
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
return newEvent
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
|
|
||||||
-- neoux: Implements utilities on top of Everest & event:
|
-- neoux: Implements utilities on top of Everest & event:
|
||||||
-- Everest crash protection
|
-- Everest crash protection
|
||||||
return function (event, neo)
|
|
||||||
|
-- Global forces reference. Otherwise, nasty duplication happens.
|
||||||
|
newNeoux = function (event, neo)
|
||||||
-- this is why neo access is 'needed'
|
-- this is why neo access is 'needed'
|
||||||
local function retrieveIcecap()
|
local function retrieveIcecap()
|
||||||
return neo.requestAccess("x.neo.pub.base")
|
return neo.requestAccess("x.neo.pub.base")
|
||||||
@ -448,8 +450,8 @@ return function (event, neo)
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
neoux.startDialog = function (fmt, title, wait)
|
neoux.startDialog = function (fmt, title, wait)
|
||||||
fmt = neoux.fmtText(unicode.safeTextFormat(fmt), 20)
|
fmt = neoux.fmtText(unicode.safeTextFormat(fmt), 40)
|
||||||
neoux.create(20, #fmt, title, function (window, ev, a, b, c)
|
neoux.create(40, #fmt, title, function (window, ev, a, b, c)
|
||||||
if ev == "line" then
|
if ev == "line" then
|
||||||
window.span(1, a, fmt[a], 0xFFFFFF, 0)
|
window.span(1, a, fmt[a], 0xFFFFFF, 0)
|
||||||
end
|
end
|
||||||
@ -464,3 +466,4 @@ return function (event, neo)
|
|||||||
end
|
end
|
||||||
return neoux
|
return neoux
|
||||||
end
|
end
|
||||||
|
return newNeoux
|
||||||
|
@ -4,17 +4,26 @@ local doSerialize = nil
|
|||||||
function doSerialize(s)
|
function doSerialize(s)
|
||||||
if type(s) == "table" then
|
if type(s) == "table" then
|
||||||
local str = "{\n"
|
local str = "{\n"
|
||||||
|
local p = 1
|
||||||
for k, v in pairs(s) do
|
for k, v in pairs(s) do
|
||||||
str = str .. "[" .. doSerialize(k) .. "]=" .. doSerialize(v) .. ",\n"
|
if k == p then
|
||||||
|
str = str .. doSerialize(v) .. ",\n"
|
||||||
|
p = p + 1
|
||||||
|
else
|
||||||
|
str = str .. "[" .. doSerialize(k) .. "]=" .. doSerialize(v) .. ",\n"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return str .. "}"
|
return str .. "}"
|
||||||
end
|
end
|
||||||
if type(s) == "string" then
|
if type(s) == "string" then
|
||||||
return string.format("%q", s)
|
return string.format("%q", s)
|
||||||
end
|
end
|
||||||
if type(s) == "number" then
|
if type(s) == "number" or type(s) == "boolean" then
|
||||||
return tostring(s)
|
return tostring(s)
|
||||||
end
|
end
|
||||||
|
if s == nil then
|
||||||
|
return "nil"
|
||||||
|
end
|
||||||
error("Cannot serialize " .. type(s))
|
error("Cannot serialize " .. type(s))
|
||||||
end
|
end
|
||||||
return neo.wrapMeta({
|
return neo.wrapMeta({
|
||||||
|
@ -130,6 +130,19 @@ local function prepareNodeI(node)
|
|||||||
if evt == "key" then
|
if evt == "key" then
|
||||||
key(wnd, a, b, c)
|
key(wnd, a, b, c)
|
||||||
end
|
end
|
||||||
|
if evt == "touch" then
|
||||||
|
local ns = b + math.max(1, selection - 4) - 2
|
||||||
|
local max = #l
|
||||||
|
if node.unknownAvailable then
|
||||||
|
max = max + 1
|
||||||
|
end
|
||||||
|
if ns == selection and selection ~= #l + 1 then
|
||||||
|
key(wnd, 13, 0, true)
|
||||||
|
else
|
||||||
|
selection = math.min(math.max(1, ns), max)
|
||||||
|
flush(wnd)
|
||||||
|
end
|
||||||
|
end
|
||||||
if evt == "line" then
|
if evt == "line" then
|
||||||
updateLine(wnd, a)
|
updateLine(wnd, a)
|
||||||
end
|
end
|
||||||
|
@ -113,7 +113,11 @@ getFsNode = function (fs, parent, fsc, path, mode)
|
|||||||
end,
|
end,
|
||||||
unknownAvailable = mode ~= nil,
|
unknownAvailable = mode ~= nil,
|
||||||
selectUnknown = function (text)
|
selectUnknown = function (text)
|
||||||
return true, require("sys-filewrap")(fsc, path .. text, mode)
|
local rt, re = require("sys-filewrap")(fsc, path .. text, mode)
|
||||||
|
if not rt then
|
||||||
|
return false, dialog("Open Error: " .. tostring(re), parent)
|
||||||
|
end
|
||||||
|
return true, rt
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
@ -127,11 +131,19 @@ getFsNode = function (fs, parent, fsc, path, mode)
|
|||||||
end})
|
end})
|
||||||
if mode ~= nil then
|
if mode ~= nil then
|
||||||
table.insert(n, {"Open", function ()
|
table.insert(n, {"Open", function ()
|
||||||
return true, require("sys-filewrap")(fsc, path, mode)
|
local rt, re = require("sys-filewrap")(fsc, path, mode)
|
||||||
|
if not rt then
|
||||||
|
return false, dialog("Open Error: " .. tostring(re), parent)
|
||||||
|
end
|
||||||
|
return true, rt
|
||||||
end})
|
end})
|
||||||
end
|
end
|
||||||
table.insert(n, {"Copy", function ()
|
table.insert(n, {"Copy", function ()
|
||||||
return nil, setupCopyVirtualEnvironment(fs, parent, require("sys-filewrap")(fsc, path, false))
|
local rt, re = require("sys-filewrap")(fsc, path, false)
|
||||||
|
if not rt then
|
||||||
|
return false, dialog("Open Error: " .. tostring(re), parent)
|
||||||
|
end
|
||||||
|
return nil, setupCopyVirtualEnvironment(fs, parent, rt)
|
||||||
end})
|
end})
|
||||||
table.insert(n, {"Delete", function ()
|
table.insert(n, {"Delete", function ()
|
||||||
fsc.remove(path)
|
fsc.remove(path)
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
return function(dev, file, mode)
|
return function(dev, file, mode)
|
||||||
local n = "rb"
|
local n = "rb"
|
||||||
if mode then n = "wb" end
|
if mode then n = "wb" end
|
||||||
local handle = dev.open(file, n)
|
local handle, r = dev.open(file, n)
|
||||||
|
if not handle then return nil, r end
|
||||||
local open = true
|
local open = true
|
||||||
local function closer()
|
local function closer()
|
||||||
if not open then return end
|
if not open then return end
|
||||||
@ -35,7 +36,8 @@ return function(dev, file, mode)
|
|||||||
close = closer,
|
close = closer,
|
||||||
write = function (txt)
|
write = function (txt)
|
||||||
if type(txt) ~= "string" then error("Write data must be string-bytearray") end
|
if type(txt) ~= "string" then error("Write data must be string-bytearray") end
|
||||||
return dev.write(handle, txt)
|
local ok, b = dev.write(handle, txt)
|
||||||
|
if not ok then error(tostring(b)) end
|
||||||
end
|
end
|
||||||
}, closer
|
}, closer
|
||||||
end
|
end
|
||||||
|
@ -28,7 +28,6 @@ for k, v in pairs(f) do
|
|||||||
end
|
end
|
||||||
os.execute("mkdir -p work/data/app-claw")
|
os.execute("mkdir -p work/data/app-claw")
|
||||||
os.execute("cp code/data/app-claw/local.lua work/data/app-claw/local.lua")
|
os.execute("cp code/data/app-claw/local.lua work/data/app-claw/local.lua")
|
||||||
os.execute("cp code/libs/sys-secpolicy.lua work/libs/sys-secpolicy.lua")
|
|
||||||
os.execute("cd code ; find . > ../imitclaw.treecode")
|
os.execute("cd code ; find . > ../imitclaw.treecode")
|
||||||
os.execute("cd work ; find . > ../imitclaw.treework")
|
os.execute("cd work ; find . > ../imitclaw.treework")
|
||||||
os.execute("diff -u imitclaw.treecode imitclaw.treework")
|
os.execute("diff -u imitclaw.treecode imitclaw.treework")
|
||||||
|
@ -11,13 +11,8 @@
|
|||||||
local event = require("event")(neo)
|
local event = require("event")(neo)
|
||||||
local neoux = require("neoux")(event, neo)
|
local neoux = require("neoux")(event, neo)
|
||||||
|
|
||||||
local eeprom = neo.requestAccess("c.eeprom")
|
local eeprom = neo.requireAccess("c.eeprom", "EEPROM access")
|
||||||
if eeprom then
|
eeprom = eeprom.list()()
|
||||||
eeprom = eeprom.list()()
|
|
||||||
end
|
|
||||||
if not eeprom then
|
|
||||||
error("No EEPROM access")
|
|
||||||
end
|
|
||||||
|
|
||||||
neoux.startDialog("NOTE: If this program is used improperly, it can require EEPROM replacement.\nOnly use trusted EEPROMs.", "eeprom-flash", true)
|
neoux.startDialog("NOTE: If this program is used improperly, it can require EEPROM replacement.\nOnly use trusted EEPROMs.", "eeprom-flash", true)
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ return {
|
|||||||
["app-eeprog"] = {
|
["app-eeprog"] = {
|
||||||
desc = "EEPROM programmer / copier",
|
desc = "EEPROM programmer / copier",
|
||||||
v = 0,
|
v = 0,
|
||||||
app = "app-eeprog",
|
|
||||||
deps = {
|
deps = {
|
||||||
"neo"
|
"neo"
|
||||||
},
|
},
|
||||||
@ -12,5 +11,17 @@ return {
|
|||||||
files = {
|
files = {
|
||||||
"apps/app-eeprog.lua"
|
"apps/app-eeprog.lua"
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
["mtd"] = {
|
||||||
|
desc = "Multi-Track Drifting",
|
||||||
|
v = 1337,
|
||||||
|
deps = {
|
||||||
|
"app-eeprog"
|
||||||
|
},
|
||||||
|
dirs = {
|
||||||
|
},
|
||||||
|
files = {
|
||||||
|
"oreproc.txt"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
1
repository/oreproc.txt
Normal file
1
repository/oreproc.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
Hello new world
|
Loading…
Reference in New Issue
Block a user