Compare commits
2 Commits
776e19df41
...
78f637d8e9
Author | SHA1 | Date | |
---|---|---|---|
78f637d8e9 | |||
fa612224d6 |
238
bbs/OpenOS/bin/bbs.lua
Normal file
238
bbs/OpenOS/bin/bbs.lua
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
local serial = require "serialization"
|
||||||
|
local event = require "event"
|
||||||
|
local rpc = require "rpc"
|
||||||
|
local _, unicode = pcall(require, "unicode")
|
||||||
|
|
||||||
|
local cfg = {}
|
||||||
|
local status = ""
|
||||||
|
local bboard
|
||||||
|
local ssub = (unicode or {}).sub or string.sub
|
||||||
|
|
||||||
|
local function loadConfig()
|
||||||
|
local f = io.open("/etc/bbs.cfg","rb")
|
||||||
|
if not f then return false end
|
||||||
|
cfg = serial.unserialize(f:read("*a"))
|
||||||
|
f:close()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
local function saveConfig()
|
||||||
|
local f = io.open("/etc/bbs.cfg","wb")
|
||||||
|
if not f then return false end
|
||||||
|
f:write(serial.serialize(cfg))
|
||||||
|
f:close()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- figure out terminal geometry
|
||||||
|
|
||||||
|
local function getCursor()
|
||||||
|
io.write("\27[6n")
|
||||||
|
local b = ""
|
||||||
|
repeat
|
||||||
|
b = b .. io.read(1)
|
||||||
|
until b:match("\27%[%d+;%d+R")
|
||||||
|
local y,x = b:match("\27%[(%d+);(%d+)R")
|
||||||
|
return tonumber(x), tonumber(y)
|
||||||
|
end
|
||||||
|
io.write("\27[999;999H")
|
||||||
|
local mx, my = getCursor()
|
||||||
|
print(mx, my)
|
||||||
|
|
||||||
|
local function setStatus(str)
|
||||||
|
local ox, oy = getCursor()
|
||||||
|
status = str
|
||||||
|
io.write(string.format("\27[%d;1H\27[0m\27[7m\27[2K%s\27[0m\27[%i;%iH", my, status, oy, ox))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function menu(items, state)
|
||||||
|
local state = state or {1,1}
|
||||||
|
local i, si = state[1], state[2]
|
||||||
|
while true do
|
||||||
|
if si > i - 3 then
|
||||||
|
si = math.max(1, i-5)
|
||||||
|
elseif i > (si+my) - 6 then
|
||||||
|
si = math.min(i - (my-3) + 5, #items - (my - 3))
|
||||||
|
end
|
||||||
|
i = math.max(1,math.min(#items, i))
|
||||||
|
print(string.format("\27[H\27[0m\27[7m\27[2K%s\27[0m", items.header or ""))
|
||||||
|
for j = si, (si+my)-3 do
|
||||||
|
print((i==j and "\27[7m" or "\27[0m") .. "\27[2K" .. (items[j] or ""):sub(1,mx))
|
||||||
|
end
|
||||||
|
setStatus(status)
|
||||||
|
local _,_,ch,co = event.pull(60,"key_down")
|
||||||
|
ch=string.char(ch or 0)
|
||||||
|
if co == 208 then -- down
|
||||||
|
i = i + 1
|
||||||
|
elseif co == 200 then -- up
|
||||||
|
i = i - 1
|
||||||
|
elseif co == 201 then -- pgdn
|
||||||
|
i = i - (my - 2)
|
||||||
|
elseif co == 209 then -- pgdn
|
||||||
|
i = i + my - 2
|
||||||
|
else
|
||||||
|
return i, ch, co, {i, si}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function popup(str,title)
|
||||||
|
local len = (unicode or {}).len or string.len
|
||||||
|
if title then
|
||||||
|
title=string.format("[%s]",title or "")
|
||||||
|
else
|
||||||
|
title = ""
|
||||||
|
end
|
||||||
|
local width, height, content = 0, 0, {}
|
||||||
|
for line in str:gmatch("[^\n]*") do
|
||||||
|
height = height + 1
|
||||||
|
width = math.max(width,len(line))
|
||||||
|
content[#content+1] = line
|
||||||
|
end
|
||||||
|
if width < 1 or height < 1 then return false end
|
||||||
|
local startx,starty = ((mx//2)-(width//2))-2, ((my//2)-(height//2))-2
|
||||||
|
io.write(string.format("\27[%d;%dH╒═%s%s╕",starty,startx,title,("═"):rep((width+1)-len(title))))
|
||||||
|
for k,v in pairs(content) do
|
||||||
|
io.write(string.format("\27[%d;%dH│ %s%s │",starty+k,startx,v,(" "):rep(width-len(v))))
|
||||||
|
end
|
||||||
|
io.write(string.format("\27[%d;%dH┕%s┙",starty+1+#content,startx,("━"):rep(width+2)))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function query(str, default)
|
||||||
|
local rv
|
||||||
|
io.write(string.format(str, default or "no default"))
|
||||||
|
repeat
|
||||||
|
rv = io.read()
|
||||||
|
rv = #rv > 0 and rv or default or ""
|
||||||
|
until #rv > 0
|
||||||
|
return rv
|
||||||
|
end
|
||||||
|
|
||||||
|
local function help()
|
||||||
|
popup([[
|
||||||
|
[↑][↓] Move 1 entry
|
||||||
|
[PgUp][PgDn] Move 1 page
|
||||||
|
[Enter] Select item
|
||||||
|
|
||||||
|
[c] Compose new post
|
||||||
|
[r] Reply to post
|
||||||
|
[t] Thread view
|
||||||
|
|
||||||
|
[q] Exit
|
||||||
|
|
||||||
|
Press any key to continue...]],"Usage")
|
||||||
|
event.pull("key_down")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function compose(board, post)
|
||||||
|
local post = post or {}
|
||||||
|
io.write("\27[2J\27[H")
|
||||||
|
post.author = cfg.handle
|
||||||
|
post.subject = query("Subject [%s]? ", post.subject)
|
||||||
|
fn = os.tmpname()
|
||||||
|
os.execute(string.format("edit '%s'",fn))
|
||||||
|
f = io.open(fn, "rb")
|
||||||
|
if f then
|
||||||
|
post.content = f:read("*a")
|
||||||
|
f:close()
|
||||||
|
os.execute(string.format("rm '%s'", fn))
|
||||||
|
print("Posting...")
|
||||||
|
bboard.post(board,post)
|
||||||
|
else
|
||||||
|
print("Post empty, cancelled.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function viewPost(board,id)
|
||||||
|
io.write("\27[2J\27[H")
|
||||||
|
post = bboard.getPost(board, id)
|
||||||
|
fn = os.tmpname()
|
||||||
|
f = io.open(fn, "wb")
|
||||||
|
f:write(string.format("Author: %s\nSubject: %s\n", post.author, post.subject))
|
||||||
|
f:write(post.content)
|
||||||
|
f:close()
|
||||||
|
os.execute(string.format("less '%s'", fn))
|
||||||
|
os.execute(string.format("rm '%s'", fn))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function threadView(board,id)
|
||||||
|
local run = true
|
||||||
|
local i, ch, co, st
|
||||||
|
local list = bboard.getThread(board, id)
|
||||||
|
while run do
|
||||||
|
local vl = {header=string.format("%4s %15s %s", "ID", "Author", "Subject")}
|
||||||
|
status = string.format("[%s] Thread: %s - %i items", cfg.handle, list[1].subject, #list)
|
||||||
|
for k,v in pairs(list) do
|
||||||
|
vl[k] = string.format("%4d %15s %s", v.id, v.author:sub(1,15), v.subject):sub(1,mx)
|
||||||
|
end
|
||||||
|
i, ch, co, st = menu(vl, st)
|
||||||
|
if ch == "q" then -- quit
|
||||||
|
run = false
|
||||||
|
elseif co == 28 then -- enter, view
|
||||||
|
viewPost(board, list[i].id)
|
||||||
|
elseif ch == "r" then -- reply
|
||||||
|
local prev = list[i]
|
||||||
|
compose(board, {replyTo=prev.id, subject="Re:"..prev.subject})
|
||||||
|
list = bboard.list(board)
|
||||||
|
elseif ch == "h" or ch == "?" then
|
||||||
|
help()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function boardView(name)
|
||||||
|
local run = true
|
||||||
|
local i, ch, co, st, fn, f, post
|
||||||
|
local list = bboard.list(name)
|
||||||
|
while run do
|
||||||
|
status = string.format("[%s] %s/%s - %i items", cfg.handle, cfg.server, name, #list)
|
||||||
|
local vl = {header=string.format("%4s %15s %s", "ID", "Author", "Subject")}
|
||||||
|
for k,v in pairs(list) do
|
||||||
|
vl[k] = string.format("%4d %15s %s", v.id, v.author:sub(1,15), v.subject):sub(1,mx)
|
||||||
|
end
|
||||||
|
i, ch, co, st = menu(vl, st)
|
||||||
|
if ch == "q" then -- quit
|
||||||
|
run = false
|
||||||
|
elseif co == 28 then -- enter, view
|
||||||
|
viewPost(name, list[i].id)
|
||||||
|
elseif ch == "c" then -- compose
|
||||||
|
compose(name)
|
||||||
|
list = bboard.list(name)
|
||||||
|
elseif ch == "r" then -- reply
|
||||||
|
local prev = list[i]
|
||||||
|
compose(name, {replyTo=prev.id, subject="Re:"..prev.subject})
|
||||||
|
list = bboard.list(name)
|
||||||
|
elseif ch == "t" then -- thread view
|
||||||
|
threadView(name,list[i].id)
|
||||||
|
elseif ch == "h" or ch == "?" then
|
||||||
|
help()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
io.write("\27[2J\27[H")
|
||||||
|
setStatus("Loading config")
|
||||||
|
loadConfig()
|
||||||
|
setStatus("Basic setup...")
|
||||||
|
cfg.server = query("Server [%s]?", cfg.server)
|
||||||
|
cfg.handle = query("Username? [%s]?", cfg.handle)
|
||||||
|
setStatus("Saving config")
|
||||||
|
saveConfig()
|
||||||
|
|
||||||
|
setStatus("Connecting...")
|
||||||
|
bboard = rpc.proxy(cfg.server, "bbs_")
|
||||||
|
|
||||||
|
local run = true
|
||||||
|
local i, ch, co, st
|
||||||
|
while run do
|
||||||
|
local list = bboard.boards()
|
||||||
|
setStatus(string.format("Connected to %s - %i boards",cfg.server,#list))
|
||||||
|
list.header = "Choose a board..."
|
||||||
|
i, ch, co, st = menu(list, st)
|
||||||
|
if ch == "q" then
|
||||||
|
run = false
|
||||||
|
elseif co == 28 then
|
||||||
|
boardView(list[i])
|
||||||
|
elseif ch == "h" or ch == "?" then
|
||||||
|
help()
|
||||||
|
end
|
||||||
|
end
|
17
bbs/OpenOS/etc/rc.d/bbsd.lua
Normal file
17
bbs/OpenOS/etc/rc.d/bbsd.lua
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
local bboard = require "bboard"
|
||||||
|
local rpc = require "rpc"
|
||||||
|
function start()
|
||||||
|
for k,v in pairs(bboard) do
|
||||||
|
if type(v) == "function" then
|
||||||
|
rpc.register("bbs_"..k, v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function stop()
|
||||||
|
if not rpc.unregister then return false end
|
||||||
|
for k,v in pairs(bboard) do
|
||||||
|
rpc.unregister("bbs_"..k)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return {start=start, stop=stop}
|
140
bbs/OpenOS/lib/bboard.lua
Normal file
140
bbs/OpenOS/lib/bboard.lua
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
local serial = require "serialization"
|
||||||
|
local fs = require "filesystem"
|
||||||
|
local bboard = {}
|
||||||
|
|
||||||
|
local PSYCHOS = _OSVERSION:sub(1,8)=="PsychOS"
|
||||||
|
|
||||||
|
local f = io.open(PSYCHOS and "/boot/cfg/bboard.cfg" or "/etc/bboard.cfg", "rb")
|
||||||
|
if f then
|
||||||
|
bboard.cfg = serial.unserialize(f:read("*a"))
|
||||||
|
f:close()
|
||||||
|
else
|
||||||
|
bboard.cfg = {
|
||||||
|
path = PSYCHOS and "/boot/bboard" or "/var/spool/bboard",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local BOARDPATH = string.format("%s/%%s", bboard.cfg.path)
|
||||||
|
local POSTPATH = string.format("%s/%%i", BOARDPATH)
|
||||||
|
|
||||||
|
local function sanitise(str)
|
||||||
|
return str:gsub("/","")
|
||||||
|
end
|
||||||
|
|
||||||
|
local flist = PSYCHOS and fs.list or function(path)
|
||||||
|
local rt = {}
|
||||||
|
for file in fs.list(path) do
|
||||||
|
rt[#rt+1] = file
|
||||||
|
end
|
||||||
|
return rt
|
||||||
|
end
|
||||||
|
|
||||||
|
function bboard.boards()
|
||||||
|
local rt = {}
|
||||||
|
for _, file in ipairs(flist(bboard.cfg.path)) do
|
||||||
|
if fs.isDirectory(string.format(BOARDPATH, file)) then
|
||||||
|
rt[#rt+1] = sanitise(file)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return rt
|
||||||
|
end
|
||||||
|
|
||||||
|
function bboard.list(board, start, limit, trunc)
|
||||||
|
assert(type(board) == "string", "invalid board")
|
||||||
|
local rt = {}
|
||||||
|
local ft = flist(string.format(BOARDPATH, board))
|
||||||
|
local limit, start = math.max(limit or math.huge, 50), #ft
|
||||||
|
table.sort(ft, function(a,b) return a>b end)
|
||||||
|
for k,v in ipairs(ft) do
|
||||||
|
if tonumber(v) and tonumber(v) <= start then
|
||||||
|
rt[#rt+1] = bboard.getPostMeta(board, v, trunc)
|
||||||
|
rt[#rt].id = tonumber(v)
|
||||||
|
end
|
||||||
|
if #rt >= limit then break end
|
||||||
|
end
|
||||||
|
return rt
|
||||||
|
end
|
||||||
|
|
||||||
|
function bboard.getReplies(board, id, max, skip, trunc)
|
||||||
|
assert(type(board) == "string", "invalid board")
|
||||||
|
assert(type(id) == "number", "invalid post ID")
|
||||||
|
skip=skip or 0
|
||||||
|
local max = tonumber((bboard.list(board, nil, 1)[1] or {}).id or 0)
|
||||||
|
local rt = {}
|
||||||
|
for i = id, max do
|
||||||
|
if skip < 1 then
|
||||||
|
local post = bboard.getPost(board, i)
|
||||||
|
if post.replyTo == id then
|
||||||
|
rt[#rt+1] = bboard.getPostMeta(board,i,trunc)
|
||||||
|
end
|
||||||
|
if #rt >= math.max(trunc or math.huge, 50) then break end
|
||||||
|
end
|
||||||
|
skip = skip - 1
|
||||||
|
end
|
||||||
|
return rt
|
||||||
|
end
|
||||||
|
|
||||||
|
function bboard.getAllReplies(board, id, max, skip, trunc)
|
||||||
|
assert(type(board) == "string", "invalid board")
|
||||||
|
assert(type(id) == "number", "invalid post ID")
|
||||||
|
skip=skip or 0
|
||||||
|
local max = tonumber((bboard.list(board, nil, 1)[1] or {}).id or 0)
|
||||||
|
local ids,rt = {[id]=true}, {}
|
||||||
|
for i = id, max do
|
||||||
|
if skip < 1 then
|
||||||
|
local post = bboard.getPost(board, i)
|
||||||
|
if ids[post.replyTo] then
|
||||||
|
ids[i], rt[#rt+1] = true, bboard.getPostMeta(board,i,trunc)
|
||||||
|
end
|
||||||
|
if #rt >= math.max(trunc or math.huge, 50) then break end
|
||||||
|
end
|
||||||
|
skip = skip - 1
|
||||||
|
end
|
||||||
|
return rt
|
||||||
|
end
|
||||||
|
|
||||||
|
function bboard.getThread(board,id,max,skip,trunc)
|
||||||
|
assert(type(board) == "string", "invalid board")
|
||||||
|
assert(type(id) == "number", "invalid post ID")
|
||||||
|
skip=skip or 0
|
||||||
|
local op
|
||||||
|
repeat
|
||||||
|
op = bboard.getPostMeta(board, id)
|
||||||
|
id = op.replyTo or id
|
||||||
|
until not op.replyTo
|
||||||
|
return {op, table.unpack(bboard.getAllReplies(board,id,max,skip,trunc))}
|
||||||
|
end
|
||||||
|
|
||||||
|
function bboard.getPost(board,id)
|
||||||
|
board, id = sanitise(board), tonumber(id)
|
||||||
|
assert(type(board) == "string", "invalid board")
|
||||||
|
assert(type(id) == "number", "invalid post ID")
|
||||||
|
local f, e = io.open(string.format(POSTPATH, board, id), "rb")
|
||||||
|
assert(f, e)
|
||||||
|
local rt = serial.unserialize(f:read("*a"))
|
||||||
|
f:close()
|
||||||
|
rt.date = fs.lastModified(string.format(POSTPATH, board, id))
|
||||||
|
rt.id = id
|
||||||
|
return rt
|
||||||
|
end
|
||||||
|
function bboard.getPostMeta(board,id,trunc)
|
||||||
|
local rt = bboard.getPost(board,id)
|
||||||
|
rt.content = rt.content:match("^[^\n]+"):sub(1,math.min(trunc or 80, 160))
|
||||||
|
return rt
|
||||||
|
end
|
||||||
|
|
||||||
|
function bboard.post(board,post)
|
||||||
|
assert(type(board) == "string", "invalid board")
|
||||||
|
assert(type(post.author) == "string", "invalid author")
|
||||||
|
assert(type(post.subject) == "string" and #post.subject <= 40, "invalid subject")
|
||||||
|
assert(type(post.content) == "string", "no content")
|
||||||
|
post.author = string.format("%s@%s", post.author, os.getenv("RPC_CLIENT") or "localhost")
|
||||||
|
post.id = tonumber((bboard.list(board, nil, 1)[1] or {}).id or 0)+1
|
||||||
|
local f, e = io.open(string.format(POSTPATH, board, post.id), "wb")
|
||||||
|
assert(f, e)
|
||||||
|
f:write(serial.serialize(post))
|
||||||
|
f:close()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return bboard
|
111
livefdd/bin/livefdc.lua
Normal file
111
livefdd/bin/livefdc.lua
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
local serial = require "serialization"
|
||||||
|
local fs = require "filesystem"
|
||||||
|
|
||||||
|
local tA = {...}
|
||||||
|
|
||||||
|
if #tA < 8 then
|
||||||
|
print([[livefdc requires 8 arguments, in this order:
|
||||||
|
- path to clean OpenOS installer
|
||||||
|
- path to repoinstaller-compatible disk
|
||||||
|
- comma-separated list of packages to install in the base system
|
||||||
|
- comma-separated list of packages to archive for live use
|
||||||
|
- comma-separated list of packages to archive for constrained use
|
||||||
|
- comma-separated list of extra packages to be unpacked when there is space
|
||||||
|
- comma-separated list of paths to move into the extra archive
|
||||||
|
- output path
|
||||||
|
]])
|
||||||
|
os.exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function parsecs(str)
|
||||||
|
local rt = {}
|
||||||
|
for w in str:gmatch("[^,]+") do
|
||||||
|
rt[#rt+1] = w
|
||||||
|
end
|
||||||
|
return rt
|
||||||
|
end
|
||||||
|
|
||||||
|
local oospath = fs.canonical(tA[1])
|
||||||
|
local pkgpath = fs.canonical(tA[2])
|
||||||
|
local basepkg, livepkg, instpkg, extpkg = parsecs(tA[3]), parsecs(tA[4]), parsecs(tA[5]), parsecs(tA[6])
|
||||||
|
local archivepaths = parsecs(tA[7])
|
||||||
|
local outpath = fs.canonical(tA[8])
|
||||||
|
|
||||||
|
local f = io.open(pkgpath .. "/master/programs.cfg", "rb")
|
||||||
|
local pkgs = serial.unserialize(f:read("*a"))
|
||||||
|
f:close()
|
||||||
|
local ipkgs,opkgs = {}, {}
|
||||||
|
|
||||||
|
local function run(cmd)
|
||||||
|
print(cmd)
|
||||||
|
os.execute(cmd)
|
||||||
|
end
|
||||||
|
local function mkdir(path)
|
||||||
|
print("mkdir",path)
|
||||||
|
fs.makeDirectory(path)
|
||||||
|
end
|
||||||
|
local function copy(from,to)
|
||||||
|
print("copy",from,to)
|
||||||
|
fs.copy(from,to)
|
||||||
|
end
|
||||||
|
local function move(from,to)
|
||||||
|
print("move",from,to)
|
||||||
|
fs.rename(from,to)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function installPkg(pkgname, dest)
|
||||||
|
local pkg, opkg = pkgs[pkgname], {}
|
||||||
|
assert(pkg, "package not available")
|
||||||
|
print(string.format("Installing %s to %s", pkgname, dest))
|
||||||
|
for k,v in pairs(pkg.files or {}) do
|
||||||
|
v = v:match("^//") and v:sub(2) or fs.concat("/usr", v)
|
||||||
|
mkdir(fs.concat(dest,v))
|
||||||
|
copy(pkgpath .. "/" .. k,fs.concat(dest,v,fs.name(k)))
|
||||||
|
opkg[k] = fs.concat(v,fs.name(k))
|
||||||
|
end
|
||||||
|
for k,v in pairs(pkg.dependencies or {}) do
|
||||||
|
if k:match("^https?://") then
|
||||||
|
v = v:match("^//") and v:sub(2) or fs.concat("/usr", v)
|
||||||
|
mkdir(fs.concat(dest,v))
|
||||||
|
copy(fs.concat(pkgpath, "external", k:match("^https://(.+)$")), fs.concat(dest,v,fs.name(k)))
|
||||||
|
opkg[k] = fs.concat(v,fs.name(k))
|
||||||
|
elseif not ipkgs[k] then
|
||||||
|
installPkg(k,dest)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
ipkgs[pkgname] = pkg
|
||||||
|
opkgs[pkgname] = opkg
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
mkdir(outpath)
|
||||||
|
run(string.format("cp -rv '%s' '%s/img'",oospath,outpath))
|
||||||
|
|
||||||
|
for k,v in ipairs(basepkg) do
|
||||||
|
installPkg(v, fs.concat(outpath, "img"))
|
||||||
|
end
|
||||||
|
for k,v in ipairs(livepkg) do
|
||||||
|
installPkg(v, fs.concat(outpath, "live"))
|
||||||
|
end
|
||||||
|
for k,v in ipairs(instpkg) do
|
||||||
|
installPkg(v, fs.concat(outpath, "inst"))
|
||||||
|
end
|
||||||
|
for k,v in ipairs(extpkg) do
|
||||||
|
installPkg(v, fs.concat(outpath, "extra"))
|
||||||
|
end
|
||||||
|
|
||||||
|
for k,v in ipairs(archivepaths) do
|
||||||
|
mkdir(fs.concat(outpath, "extra", fs.path(v)))
|
||||||
|
move(fs.concat(outpath, "img", v), fs.concat(outpath, "extra", v))
|
||||||
|
end
|
||||||
|
|
||||||
|
local f = io.open(fs.concat(outpath, "img", "/etc/opdata.svd"), "wb")
|
||||||
|
f:write(serial.serialize(opkgs))
|
||||||
|
f:close()
|
||||||
|
|
||||||
|
local opwd = os.getenv("PWD")
|
||||||
|
for k,v in ipairs({"live","inst","extra"}) do
|
||||||
|
os.setenv("PWD", fs.concat(outpath, v))
|
||||||
|
run(string.format("mtar -czv '%s/img/.%s.mtar.lss' *", outpath, v))
|
||||||
|
end
|
||||||
|
os.setenv("PWD",opwd)
|
52
livefdd/etc/rc.d/livefdd.lua
Normal file
52
livefdd/etc/rc.d/livefdd.lua
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
function start()
|
||||||
|
|
||||||
|
local fs = require "filesystem"
|
||||||
|
local rootfs = fs.get("/")
|
||||||
|
local free = rootfs.spaceTotal() - rootfs.spaceUsed()
|
||||||
|
local function unpack(from,to)
|
||||||
|
if not fs.exists(from) then return false end
|
||||||
|
io.write(string.format("Unpacking %s to %s... ", from, to))
|
||||||
|
local opwd = os.getenv("PWD")
|
||||||
|
os.setenv("PWD", to)
|
||||||
|
os.execute(string.format("mtar -xz '%s'",from))
|
||||||
|
os.setenv("PWD", opwd)
|
||||||
|
print("Done!")
|
||||||
|
end
|
||||||
|
local function link(from)
|
||||||
|
from=fs.canonical(from)
|
||||||
|
local dt = {from}
|
||||||
|
for _, dir in ipairs(dt) do
|
||||||
|
for file in fs.list(dir) do
|
||||||
|
local fp = fs.concat(dir,file)
|
||||||
|
if file:match("/$") then
|
||||||
|
dt[#dt+1] = fp
|
||||||
|
else
|
||||||
|
local lt = fp:sub(#from+1)
|
||||||
|
while not fs.isDirectory(fs.path(lt)) and not fs.isLink(fs.path(lt)) do
|
||||||
|
lt = fs.path(lt)
|
||||||
|
end
|
||||||
|
fs.link(fs.concat(from,lt), lt)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if rootfs.isReadOnly() then -- live floppy
|
||||||
|
print("\27[2J\27[HPreparing live environment...")
|
||||||
|
fs.makeDirectory("/tmp/live")
|
||||||
|
unpack("/.live.mtar.lss","/tmp/live")
|
||||||
|
link("/tmp/live")
|
||||||
|
elseif not rootfs.isReadOnly() and free < 2^17 then -- installed on small media
|
||||||
|
print("\27[2J\27[HPreparing constrained environment...")
|
||||||
|
fs.makeDirectory("/tmp/live")
|
||||||
|
unpack("/.live.mtar.lss","/tmp/live")
|
||||||
|
unpack("/.inst.mtar.lss","/tmp/live")
|
||||||
|
link("/tmp/live")
|
||||||
|
else -- extract and deactivate
|
||||||
|
print("\27[2J\27[HFinalising installation...")
|
||||||
|
unpack("/.live.mtar.lss","/")
|
||||||
|
unpack("/.inst.mtar.lss","/")
|
||||||
|
unpack("/.extra.mtar.lss","/")
|
||||||
|
os.execute("rc livefdd disable")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@ -69,6 +69,12 @@ wget(src,pcfgname)
|
|||||||
local programs = parsecfg(pcfgname)
|
local programs = parsecfg(pcfgname)
|
||||||
os.execute("rm '"..pcfgname.."'")
|
os.execute("rm '"..pcfgname.."'")
|
||||||
|
|
||||||
|
if tArgs[3] then
|
||||||
|
for k,v in pairs(programs) do
|
||||||
|
if not filter[k] then programs[k] = nil end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local dlfiles = {}
|
local dlfiles = {}
|
||||||
for k,v in pairs(programs) do
|
for k,v in pairs(programs) do
|
||||||
for l,m in pairs(v.files or {}) do
|
for l,m in pairs(v.files or {}) do
|
||||||
|
Loading…
Reference in New Issue
Block a user