Compare commits

...

8 Commits

Author SHA1 Message Date
20kdc fab88f137c svc-virtudev: virtual devices for KittenOS NEO 2020-03-28 00:32:16 +00:00
20kdc 7680aa7579 Apparently I missed a few details of the packaging stuff for setup 2020-03-27 22:35:00 +00:00
20kdc 429de87a61 Add missing secpolicy version bump (oops) 2019-01-02 15:28:59 +00:00
20kdc 7307eb30a4 Consider 'tablet' component & tablet_use safe in secpolicy, fix incorrect documentation on k.computer 2019-01-02 15:28:01 +00:00
20kdc 0d9583fcff r8: Yet another release for a single feature request
This isn't getting pushed until AmandaC's tested it.
I'm not sure this is such a good idea, anyway ; if it's for load/save
 workflow improvements, wouldn't it be better to have a file access method
 that allows for file re-opening?
That said, there's a limit to *that* before you just have to say,
 "Just use /data/".
2018-12-24 21:11:59 +00:00
20kdc 375995c2d3 r7: Fix the read-only-FS filemanager bug AmandaC found
This should fix everything
2018-12-11 16:40:30 +00:00
20kdc efae7716da Merge branch 'repository' (for rwhateverwe'reon) 2018-12-11 15:26:23 +00:00
20kdc 27bd71f9e4 (Probably) fix sys-init self-destructing if no monitors around 2018-11-09 23:19:27 +00:00
21 changed files with 344 additions and 93 deletions

View File

@ -3,7 +3,7 @@
return {
["neo"] = {
desc = "KittenOS NEO Kernel & Base Libs",
v = 5,
v = 8,
deps = {
},
dirs = {
@ -26,7 +26,7 @@ return {
},
["neo-init"] = {
desc = "KittenOS NEO / sys-init (startup)",
v = 6,
v = 7,
deps = {
"neo",
"neo-icecap",
@ -67,7 +67,7 @@ return {
},
["neo-icecap"] = {
desc = "KittenOS NEO / Icecap",
v = 3,
v = 8,
deps = {
"neo"
},
@ -84,7 +84,7 @@ return {
},
["neo-secpolicy"] = {
desc = "KittenOS NEO / Secpolicy",
v = 2,
v = 8,
deps = {
},
dirs = {
@ -125,7 +125,7 @@ return {
},
["neo-logo"] = {
desc = "KittenOS NEO Logo (data)",
v = 6,
v = 8,
deps = {
},
dirs = {

View File

@ -24,7 +24,7 @@ return {
},
["neo-docs"] = {
desc = "KittenOS NEO system documentation",
v = 5,
v = 8,
deps = {
"zzz-license-pd"
},
@ -251,6 +251,24 @@ return {
"docs/repoauthors/app-slaunch"
},
},
["svc-virtudev"] = {
desc = "a clone of vcomponent",
v = 0,
deps = {
"neo",
"zzz-license-pd"
},
dirs = {
"apps",
"docs",
"docs/repoauthors"
},
files = {
"apps/svc-virtudev.lua",
"apps/app-vdrslamp.lua",
"docs/repoauthors/svc-virtudev"
},
},
-- libraries
["lib-knbs"] = {
desc = "NBS reader/writer library",

View File

@ -109,17 +109,20 @@ donkonitDFProvider(function (pkg, pid, sendSig)
end
end
return {
showFileDialogAsync = function (forWrite)
showFileDialogAsync = function (forWrite, defName)
if not rawequal(forWrite, nil) then
require("sys-filewrap").ensureMode(forWrite)
end
if not rawequal(defName, nil) then
defName = tostring(defName)
end
-- Not hooked into the event API, so can't safely interfere
-- Thus, this is async and uses a return event.
local tag = {}
neo.scheduleTimer(0)
table.insert(todo, function ()
-- sys-filedialog is yet another "library to control memory usage".
local closer = require("sys-filedialog")(event, nexus, function (res) openHandles[tag] = nil sendSig("filedialog", tag, res) end, neo.requireAccess("c.filesystem", "file managers"), pkg, forWrite)
local closer = require("sys-filedialog")(event, nexus, function (res) openHandles[tag] = nil sendSig("filedialog", tag, res) end, neo.requireAccess("c.filesystem", "file managers"), pkg, forWrite, defName)
openHandles[tag] = closer
end)
return tag

View File

@ -65,6 +65,17 @@ local function basicDraw(bg)
return gpu
end
local function consoleEventHandler(ev)
if ev[1] == "h._kosneo_syslog" then
local text = ""
for i = 3, #ev do
if i ~= 3 then text = text .. " " end
text = text .. tostring(ev[i])
end
table.insert(console, text)
end
end
-- Attempts to get an NSS monitor with a priority list of screens
local function retrieveNssMonitor(...)
local spc = {...}
@ -133,17 +144,6 @@ local function retrieveNssMonitor(...)
end
end
local function consoleEventHandler(ev)
if ev[1] == "h._kosneo_syslog" then
local text = ""
for i = 3, #ev do
if i ~= 3 then text = text .. " " end
text = text .. tostring(ev[i])
end
table.insert(console, text)
end
end
local function sleep(t)
neo.scheduleTimer(os.uptime() + t)
while true do

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -25,7 +25,7 @@ newNeoux = function (event, neo)
end
end)
local neoux = {}
neoux.fileDialog = function (forWrite, callback)
neoux.fileDialog = function (forWrite, callback, dfn)
local sync = false
local rtt = nil
if not callback then
@ -35,7 +35,7 @@ newNeoux = function (event, neo)
rtt = rt
end
end
local tag = neo.requireAccess("x.neo.pub.base", "filedialog").showFileDialogAsync(forWrite)
local tag = neo.requireAccess("x.neo.pub.base", "filedialog").showFileDialogAsync(forWrite, dfn)
local f
f = function (_, fd, tg, re)
if fd == "filedialog" then

View File

@ -2,7 +2,7 @@
-- No warranty is provided, implied or otherwise.
-- just don't bother with proper indent here
return function (event, nexus, retFunc, fs, pkg, mode)
return function (event, nexus, retFunc, fs, pkg, mode, defName)
local fmt = require("fmttext")
local class = "manage"
@ -141,7 +141,7 @@ end
nexus.create(w, h, class .. " " .. pkg, function (w, ev, a, b, c)
if not wnd then
wnd = w
prepareNode(require("sys-filevfs")(fs, mode))
prepareNode(require("sys-filevfs")(fs, mode, defName))
end
if ev == "key" then
key2(a, b, c)

View File

@ -16,12 +16,12 @@ end
local getFsNode, getRoot
local setupCopyNode
function setupCopyNode(parent, myRoot, op, complete, impliedName)
function setupCopyNode(parent, myRoot, op, complete)
local function handleResult(aRes, res)
if aRes then
return complete(res, true)
else
return nil, setupCopyNode(parent, res, op, complete, impliedName)
return nil, setupCopyNode(parent, res, op, complete)
end
end
return {
@ -32,11 +32,6 @@ function setupCopyNode(parent, myRoot, op, complete, impliedName)
complete(nil, false)
return false, parent
end})
if impliedName and myRoot.unknownAvailable then
table.insert(l, {"Implied: " .. impliedName, function ()
return handleResult(myRoot.selectUnknown(impliedName))
end})
end
for _, v in ipairs(myRoot.list()) do
table.insert(l, {v[1], function ()
return handleResult(v[2]())
@ -54,7 +49,7 @@ local function setupCopyVirtualEnvironment(fs, parent, fwrap, impliedName)
if not fwrap then
return false, dialog("Could not open source", parent)
end
local myRoot = getRoot(fs, true)
local myRoot = getRoot(fs, true, impliedName)
-- Setup wrapping node
return setupCopyNode(parent, myRoot, "Copy", function (fwrap2, intent)
if not fwrap2 then
@ -72,14 +67,22 @@ local function setupCopyVirtualEnvironment(fs, parent, fwrap, impliedName)
fwrap.close()
fwrap2.close()
return false, dialog("Completed copy.", parent)
end, impliedName)
end)
end
function getFsNode(fs, parent, fsc, path, mode)
function getFsNode(fs, parent, fsc, path, mode, impliedName)
local va = fsc.address:sub(1, 4)
local fscrw = not fsc.isReadOnly()
local dir = path:sub(#path, #path) == "/"
local confirmedDel = false
local t
local function selectUnknown(text)
-- Relies on text being nil if used in leaf node
local rt, re = require("sys-filewrap").create(fsc, path .. (text or ""), mode)
if not rt then
return false, dialog("Open Error: " .. tostring(re), parent)
end
return true, rt
end
t = {
name = ((dir and "DIR: ") or "FILE: ") .. va .. path,
list = function ()
@ -94,7 +97,7 @@ function getFsNode(fs, parent, fsc, path, mode)
if fsc.isDirectory(fp) then
nm = "D: " .. v
end
n[k + 1] = {nm, function () return nil, getFsNode(fs, t, fsc, fp, mode) end}
n[k + 1] = {nm, function () return nil, getFsNode(fs, t, fsc, fp, mode, impliedName) end}
end
end
if fscrw then
@ -114,31 +117,6 @@ function getFsNode(fs, parent, fsc, path, mode)
end
}
end})
else
if mode ~= nil then
local tx = "Open"
if mode == true then
tx = "Save"
elseif mode == "append" then
tx = "Append"
end
if fscrw or mode == false then
table.insert(n, {tx, function ()
local rt, re = require("sys-filewrap").create(fsc, path, mode)
if not rt then
return false, dialog("Open Error: " .. tostring(re), parent)
end
return true, rt
end})
end
end
table.insert(n, {"Copy", function ()
local rt, re = require("sys-filewrap").create(fsc, path, false)
if not rt then
return false, dialog("Open Error: " .. tostring(re), parent)
end
return nil, setupCopyVirtualEnvironment(fs, parent, rt, path:match("[^/]*$") or "")
end})
end
if path ~= "/" then
local delText = "Delete"
@ -172,20 +150,38 @@ function getFsNode(fs, parent, fsc, path, mode)
end})
end
end
if not dir then
table.insert(n, {"Copy", function ()
local rt, re = require("sys-filewrap").create(fsc, path, false)
if not rt then
return false, dialog("Open Error: " .. tostring(re), parent)
end
return nil, setupCopyVirtualEnvironment(fs, parent, rt, path:match("[^/]*$") or "")
end})
if (fscrw or mode == false) and (mode ~= nil) then
local tx = "Open"
if mode == true then
tx = "Save (Overwrite)"
elseif mode == "append" then
tx = "Append"
end
if fscrw or mode == false then
table.insert(n, {tx, selectUnknown})
end
end
elseif impliedName then
table.insert(n, {"Implied: " .. impliedName, function ()
return selectUnknown(impliedName)
end})
end
return n
end,
unknownAvailable = dir and (mode ~= nil) and ((mode == false) or fscrw),
selectUnknown = function (text)
local rt, re = require("sys-filewrap").create(fsc, path .. text, mode)
if not rt then
return false, dialog("Open Error: " .. tostring(re), parent)
end
return true, rt
end
selectUnknown = selectUnknown
}
return t
end
function getRoot(fs, mode)
function getRoot(fs, mode, defName)
local t
t = {
name = "DRVS:",
@ -209,7 +205,7 @@ function getRoot(fs, mode)
id = "RW " .. amount .. "% " .. mb .. "M " .. id
end
table.insert(l, {fsi.address:sub(1, 4) .. " " .. id, function ()
return nil, getFsNode(fs, t, fsi, "/", mode)
return nil, getFsNode(fs, t, fsi, "/", mode, defName)
end})
end
return l

View File

@ -22,7 +22,7 @@ local function actualPolicy(pkg, pid, perm, matchesSvc)
return "allow"
end
-- These signals are harmless, though they identify HW (as does everything in OC...)
if perm == "s.h.component_added" or perm == "s.h.component_removed" then
if perm == "s.h.component_added" or perm == "s.h.component_removed" or perm == "s.h.tablet_use" or perm == "c.tablet" then
return "allow"
end
if matchesSvc("r.", pkg, perm) then

View File

@ -34,8 +34,12 @@ while blk ~= "" do
break
end
local pm = p - 1
bestData = string.char(128 + lm, math.floor(pm / 256), pm % 256)
bestRes = pfx
local thirdByte = pm % 256
-- anti ']'-corruption helper
if thirdByte ~= 93 then
bestData = string.char(128 + lm, math.floor(pm / 256), thirdByte)
bestRes = pfx
end
end
-- ok, encode!
io.write(bestData)

View File

@ -6,9 +6,5 @@
cp ocemu.cfg.default ocemu.cfg && rm -rf c1-sda c1-sdb
mkdir c1-sda c1-sdb
echo -n c1-sda > c1-eeprom/data.bin
cd ..
cp -r code/* laboratory/c1-sdb/
cp -r repository/* laboratory/c1-sdb/
lua claw/clawconv.lua laboratory/c1-sdb/data/app-claw/ < claw/code-claw.lua > /dev/null
lua claw/clawconv.lua laboratory/c1-sdb/data/app-claw/ < claw/repo-claw.lua >> /dev/null
cp -r laboratory/c1-sdb/* laboratory/c1-sda/
./update.sh

11
laboratory/update.sh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/sh
# This is released into the public domain.
# No warranty is provided, implied or otherwise.
cd ..
cp -r code/* laboratory/c1-sdb/
cp -r repository/* laboratory/c1-sdb/
lua claw/clawconv.lua laboratory/c1-sdb/data/app-claw/ < claw/code-claw.lua > /dev/null
lua claw/clawconv.lua laboratory/c1-sdb/data/app-claw/ < claw/repo-claw.lua >> /dev/null
cp -r laboratory/c1-sdb/* laboratory/c1-sda/

View File

@ -5,8 +5,11 @@
# Package repository using supplied inst.lua (use inst-gold.lua for repository branch)
stat repobuild/data/app-claw && rm -rf repobuild
mkdir repobuild
# this is a guard check to avoid removing repobuild if it's blatantly
# not the actual repobuild directory (this is an rm -rf after all)
stat repobuild/data/app-claw 1>/dev/null 2>/dev/null && rm -rf repobuild
mkdir -p repobuild
cp -r code/* repobuild/
cp -r repository/* repobuild/
cp $1 repobuild/

View File

@ -4,6 +4,7 @@
# No warranty is provided, implied or otherwise.
rm code/data/app-claw/*
mkdir -p code/data/app-claw
lua claw/clawconv.lua code/data/app-claw/ < claw/code-claw.lua > /dev/null
rm code.tar
# Hey, look behind you, there's nothing to see here.

View File

@ -0,0 +1,49 @@
-- This is released into the public domain.
-- No warranty is provided, implied or otherwise.
-- svc-vdrslamp.lua : Virtual Redstone Lamp
-- Authors: 20kdc
local vdev = neo.requireAccess("x.svc.virtudev", "lamp dev")
local evr = neo.requireAccess("x.neo.pub.window", "the lamp")
local wnd = evr(12, 6)
local bLine = (" "):rep(12)
local function blank()
return 0
end
local total = 0
vdev.install({
type = "redstone",
address = "vdrslamp-" .. neo.pid,
slot = 0,
getWakeThreshold = blank,
setWakeThreshold = blank,
getInput = blank,
getOutput = function (i)
return total
end,
setOutput = function (i, v)
total = v
wnd.setSize(12, 6)
end
})
while true do
local e = {coroutine.yield()}
if e[1] == "x.neo.pub.window" then
if e[3] == "close" then
-- the ignorance of unregistration is deliberate
-- a working impl. will properly recover
return
elseif e[3] == "line" then
local bg = 0xFFFFFF
if total == 0 then bg = 0 end
wnd.span(1, e[4], bLine, bg, bg)
end
end
end

View File

@ -0,0 +1,156 @@
-- This is released into the public domain.
-- No warranty is provided, implied or otherwise.
-- svc-virtudev.lua : Virtual Device interface
-- Authors: 20kdc
local ic = neo.requireAccess("x.neo.pub.base", "to lock x.svc.virtudev")
-- this is a pretty powerful permission, and PROBABLY EXPLOITABLE
ic.lockPerm("x.svc.virtudev")
local r = neo.requireAccess("r.svc.virtudev", "api endpoint")
local root = neo.requireAccess("k.root", "the ability to modify the component API")
local proxies = {}
local types = {}
local function uninstall(k)
proxies[k] = nil
types[k] = nil
root.computer.pushSignal("component_removed", k, types[k])
end
local users = {}
local userCount = 0
r(function (pkg, pid, sendSig)
local userAddresses = {}
users[pid] = userAddresses
userCount = userCount + 1
return {
install = function (proxy)
local proxyAddress = proxy.address
local proxyType = proxy.type
assert(type(proxyAddress) == "string")
assert(type(proxyType) == "string")
assert(not proxies[proxyAddress], "proxy address in use: " .. proxyAddress)
proxies[proxyAddress] = proxy
types[proxyAddress] = proxyType
userAddresses[proxyAddress] = true
root.computer.pushSignal("component_added", proxyAddress, proxyType)
return function (a, ...)
root.computer.pushSignal(a, proxyAddress, ...)
end
end,
uninstall = function (k)
if userAddresses[k] then
uninstall(k)
userAddresses[k] = nil
end
end
}
end)
local componentProxyRaw = root.component.proxy
local componentTypeRaw = root.component.type
local componentMethodsRaw = root.component.methods
local componentFieldsRaw = root.component.fields
local componentDocRaw = root.component.doc
local componentInvokeRaw = root.component.invoke
local componentListRaw = root.component.list
root.component.proxy = function (address)
if proxies[address] then
return proxies[address]
end
return componentProxyRaw(address)
end
root.component.type = function (address)
if types[address] then
return types[address]
end
return componentTypeRaw(address)
end
local function methodsFieldsHandler(address, methods)
if proxies[address] then
local mt = {}
for k, v in pairs(proxies[address]) do
if (type(v) == "function") == methods then
mt[k] = true
end
end
return mt
end
if methods then
return componentMethodsRaw(address)
else
return componentFieldsRaw(address)
end
end
root.component.methods = function (address) return methodsFieldsHandler(address, true) end
root.component.fields = function (address) return methodsFieldsHandler(address, false) end
root.component.doc = function (address, method)
if proxies[address] then
return tostring(proxies[address][method])
end
return componentDocRaw(address, method)
end
root.component.invoke = function (address, method, ...)
if proxies[address] then
return proxies[address][method](...)
end
return componentInvokeRaw(address, method, ...)
end
root.component.list = function (f, e)
local iter = componentListRaw(f, e)
local ended = false
local others = {}
for k, v in pairs(types) do
if (f == v) or ((not e) and v:find(f, 1, true)) then
table.insert(others, {k, v})
end
end
return function ()
if not ended then
local a, t = iter()
if not a then
ended = true
else
return a, t
end
end
-- at end of that, so what about others
local ent = table.remove(others, 1)
if ent then
return table.unpack(ent)
end
end
end
while true do
local e1, e2, e3 = coroutine.yield()
if e1 == "k.procdie" then
if users[e3] then
for k, _ in pairs(users[e3]) do
uninstall(k)
end
users[e3] = nil
userCount = userCount - 1
if userCount == 0 then
break
end
end
end
end
root.component.proxy = componentProxyRaw
root.component.type = componentTypeRaw
root.component.methods = componentMethodsRaw
root.component.fields = componentFieldsRaw
root.component.doc = componentDocRaw
root.component.invoke = componentInvokeRaw
root.component.list = componentListRaw

View File

@ -53,9 +53,9 @@ Here, "*" means that everything after
program to start up.
"k.computer": The "computer" table,
with wrapMeta applied,
pullSignal removed,
and also pushSignal.
with wrapMeta applied.
The security check may be aliased to
the "k.root" permission in future.
"k.kill": function (pid) to kill any
process on the system.

View File

@ -0,0 +1,3 @@
repository/apps/svc-virtudev.lua: 20kdc, Public Domain
repository/apps/app-vdrslamp.lua: 20kdc, Public Domain

View File

@ -15,10 +15,12 @@ The mode you give to it can be one of
true: Write "wb"
"append": Append "ab"
May have some readability
propertiues - just in
properties - just in
case, I've added 'read',
but don't get your hopes
up...
"access": Like read, but can be
re-opened for write.
It returns two things - a table, that
being the file object, and the
@ -37,7 +39,9 @@ The possible functions are:
[aw] write(data): Writes to the
file.
[arw] read(data): Reads from the
file.
file. data is the byte count.
However, "*a" is valid here.
Other string-based options are not.
NOTE: Some of these may not actually
work. They're just there as more or

View File

@ -33,16 +33,19 @@ The most reliable reference on the
Main functions:
fileDialog(mode[, callback]):
neoux.fileDialog(mode, [callback],
[dfn]):
Creates a file dialog, returning a
file wrapper (see ul-fwrap) on
success, or nil on failure.
If a callback is given, then nil is
If callback isn't nil, then nil is
always returned immediately, and
the callback is called when the
dialog has shown.
the callback is called with the
result when the dialog is closed.
mode is the mode used for the file,
so see ul-fwrap for values.
dfn is, if not nil, the default
'implied' filename (as with Copy).
neoux.create(w, h, title, callback):
Creates a window,

View File

@ -57,11 +57,15 @@ Paths for the IO parts of this API
the standard KittenOS NEO path
safety rules in the kernel.
showFileDialogAsync(mode): Shows a
filedialog with a given filemode,
or nil for "none". Returns a new,
empty table as a "tag", and emits a
"filedialog" event on completion.
showFileDialogAsync(mode, dfn):
Shows a filedialog with a given
filemode, or nil for "none".
Returns a new, empty table as a
"tag", and emits a "filedialog"
event on completion.
dfn meanwhile adds an 'Implied'
button for reasonable default file
names.
myApi: A string such as "svc.abc"
for the program svc-abc, used for