Compare commits
3 commits
Author | SHA1 | Date | |
---|---|---|---|
c196c4a066 | |||
|
7df5b38ebb | ||
|
55bb9aef13 |
176 changed files with 12 additions and 10337 deletions
|
@ -1,5 +1 @@
|
||||||
# **FREAX**
|
This is the simple website for FREAX. Currently it redirects to the documentation.
|
||||||
**FREAX** is a operating system written in Lua and can only be ran in ComputerCraft, a Minecraft modification. It is designed to be as Linux-y as possible.
|
|
||||||
|
|
||||||
# **Install**
|
|
||||||
Just clone the repository and move everything into your computer's data folder. A advanced installation documentation will be added soon.
|
|
||||||
|
|
26
bin/alias
26
bin/alias
|
@ -1,26 +0,0 @@
|
||||||
local tArgs = { ... }
|
|
||||||
if #tArgs > 2 then
|
|
||||||
local programName = "alias"
|
|
||||||
print("Usage: " .. programName .. " <alias> <program>")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local sAlias = tArgs[1]
|
|
||||||
local sProgram = tArgs[2]
|
|
||||||
|
|
||||||
if sAlias and sProgram then
|
|
||||||
-- Set alias
|
|
||||||
shell.setAlias(sAlias, sProgram)
|
|
||||||
elseif sAlias then
|
|
||||||
-- Clear alias
|
|
||||||
shell.clearAlias(sAlias)
|
|
||||||
else
|
|
||||||
-- List aliases
|
|
||||||
local tAliases = shell.aliases()
|
|
||||||
local tList = {}
|
|
||||||
for sAlias, sCommand in pairs(tAliases) do
|
|
||||||
table.insert(tList, sAlias .. ":" .. sCommand)
|
|
||||||
end
|
|
||||||
table.sort(tList)
|
|
||||||
textutils.pagedTabulate(tList)
|
|
||||||
end
|
|
14
bin/apis
14
bin/apis
|
@ -1,14 +0,0 @@
|
||||||
local tApis = {}
|
|
||||||
for k, v in pairs(_G) do
|
|
||||||
if type(k) == "string" and type(v) == "table" and k ~= "_G" then
|
|
||||||
table.insert(tApis, k)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
table.insert(tApis, "shell")
|
|
||||||
table.insert(tApis, "package")
|
|
||||||
if multishell then
|
|
||||||
table.insert(tApis, "multishell")
|
|
||||||
end
|
|
||||||
table.sort(tApis)
|
|
||||||
|
|
||||||
textutils.pagedTabulate(tApis)
|
|
131
bin/archiver
131
bin/archiver
|
@ -1,131 +0,0 @@
|
||||||
print("Debian CC Archiver v0.1 by 1Ridav")
|
|
||||||
tArgs = {...}
|
|
||||||
local function getPath(input)
|
|
||||||
if string.sub(input, 1, 1)=="/" then path=input else
|
|
||||||
path=("/" .. shell.dir() .. "/" .. input) end
|
|
||||||
return path
|
|
||||||
end
|
|
||||||
if tArgs[2] then
|
|
||||||
tArgs[2]=getPath(tArgs[2])
|
|
||||||
end
|
|
||||||
|
|
||||||
local FFormat = ".arch"
|
|
||||||
local nFile, nDir, size = 0, 0
|
|
||||||
|
|
||||||
if #tArgs < 3 then
|
|
||||||
print("Usage:"
|
|
||||||
.."\narchiver zip <DIR> <ZIPname> [DIRtoSkip] [DIRtoSkip]"
|
|
||||||
.."\narchiver unzip <ZIPname> <DIR>")
|
|
||||||
end
|
|
||||||
|
|
||||||
local function fopen(path, mode)
|
|
||||||
local f = fs.open(path, mode)
|
|
||||||
if not f then
|
|
||||||
print("ERROR: Could not open "..path.." with mode \""..mode.."\"")
|
|
||||||
exit()
|
|
||||||
end
|
|
||||||
return f
|
|
||||||
end
|
|
||||||
|
|
||||||
local function skip(df)
|
|
||||||
for i = 3, #tArgs do
|
|
||||||
if tArgs[i] == fs.getName(df) then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for i = 4, #tArgs do
|
|
||||||
if tArgs[i] == fs.getName(df) then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local function zip(file)
|
|
||||||
print("zipping: ".. file)
|
|
||||||
local f = fopen(file, "r")
|
|
||||||
local z = textutils.serialize(f.readAll())
|
|
||||||
f.close()
|
|
||||||
return z
|
|
||||||
end
|
|
||||||
|
|
||||||
local function ZIP(path)
|
|
||||||
local list = fs.list(path)
|
|
||||||
local array = {}
|
|
||||||
local t, name, d = 0, "", 0
|
|
||||||
|
|
||||||
for i = 2, #list * 2, 2 do
|
|
||||||
t = i/2
|
|
||||||
local tpath = path.."/"..list[t]
|
|
||||||
if fs.isDir(tpath) then
|
|
||||||
if not skip(tpath) then
|
|
||||||
name = "D:"..list[t]
|
|
||||||
array[i] = ZIP(tpath)
|
|
||||||
nDir = nDir + 1
|
|
||||||
end
|
|
||||||
else
|
|
||||||
name = "F:"..list[t]
|
|
||||||
array[i] = zip(tpath)
|
|
||||||
nFile = nFile + 1
|
|
||||||
end
|
|
||||||
array[i - 1] = name
|
|
||||||
end
|
|
||||||
|
|
||||||
return textutils.serialize(array)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function unzip(text, path)
|
|
||||||
print("unzipping: "..path)
|
|
||||||
local f = fopen(path, "w")
|
|
||||||
f.write(textutils.unserialize(text))
|
|
||||||
f.close()
|
|
||||||
end
|
|
||||||
|
|
||||||
local function UNZIP(text, path)
|
|
||||||
local array = textutils.unserialize(text)
|
|
||||||
local unz, dp
|
|
||||||
local d = 0
|
|
||||||
for i = 2, #array, 2 do
|
|
||||||
if string.sub(array[i-1], 1, 1) == "D" then
|
|
||||||
dp = string.sub(array[i-1], 3, #array[i-1])
|
|
||||||
fs.makeDir(path.."/"..dp)
|
|
||||||
UNZIP(array[i], path.."/"..dp)
|
|
||||||
nDir = nDir + 1
|
|
||||||
elseif string.sub(array[i-1], 1, 1) == "F" then
|
|
||||||
local p = string.sub(array[i-1], 3, #array[i-1])
|
|
||||||
unzip(array[i], path.."/"..p)
|
|
||||||
nFile = nFile + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function result()
|
|
||||||
print("\nDone"
|
|
||||||
,"\n size: "
|
|
||||||
,size, " B "
|
|
||||||
,math.floor(size/1024), " KB"
|
|
||||||
,"\n Files: ", nFile
|
|
||||||
,"\n Folders: ", nDir
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
if tArgs[1] == "zip" then
|
|
||||||
if fs.exists(tArgs[2]) and fs.isDir(tArgs[2]) then
|
|
||||||
local zipped = ZIP(shell.resolve(tArgs[2]))
|
|
||||||
local f = fs.open(tArgs[3]..FFormat, "w")
|
|
||||||
f.write(zipped)
|
|
||||||
f.close()
|
|
||||||
zipped = nil
|
|
||||||
size = fs.getSize(tArgs[3]..FFormat)
|
|
||||||
result()
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif tArgs[1] == "unzip" then
|
|
||||||
local f = fopen(tArgs[2], "r")
|
|
||||||
if not fs.exists(tArgs[3]) then
|
|
||||||
fs.makeDir(tArgs[3])
|
|
||||||
end
|
|
||||||
UNZIP(f.readAll(), tArgs[3])
|
|
||||||
size = fs.getSize(tArgs[2])
|
|
||||||
result()
|
|
||||||
end
|
|
16
bin/attach
16
bin/attach
|
@ -1,16 +0,0 @@
|
||||||
if periphemu == nil then error("Attaching peripherals is not supported in vanilla mode.") end
|
|
||||||
local args = { ... }
|
|
||||||
if args[1] == "list" then
|
|
||||||
print("Available peripheral types:")
|
|
||||||
for _,p in ipairs(periphemu.names()) do print(p) end
|
|
||||||
elseif type(args[1]) ~= "string" or type(args[2]) ~= "string" then
|
|
||||||
print("Usage: attach <side> <type> [options...]\n attach list")
|
|
||||||
else
|
|
||||||
if peripheral.isPresent(args[1]) and peripheral.getType(args[1]) == args[2] then
|
|
||||||
print("Peripheral already attached")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if tonumber(args[3]) ~= nil then args[3] = tonumber(args[3]) end
|
|
||||||
local ok, err = periphemu.create(args[1], args[2], args[3])
|
|
||||||
if not ok then printError("Could not attach peripheral" .. (err and ": " .. err or "")) end
|
|
||||||
end
|
|
18
bin/cat
18
bin/cat
|
@ -1,18 +0,0 @@
|
||||||
local tArgs = {...}
|
|
||||||
|
|
||||||
if #tArgs >= 1 then
|
|
||||||
path = shell.resolve(tArgs[1])
|
|
||||||
if fs.isReadOnly(path) and not security.getSU() then
|
|
||||||
-- prevent users from seeing unauthorized code
|
|
||||||
-- they should only be able to see their own files and ones in /var/log
|
|
||||||
exception.throw("SecurityException", path)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if not fs.exists(path) or fs.isDir(path) then
|
|
||||||
kerneldraw.printAppInfo("cat", "File or directory not found")
|
|
||||||
else
|
|
||||||
textutils.pagedPrint(kernel.printFile(path))
|
|
||||||
end
|
|
||||||
else
|
|
||||||
kerneldraw.printAppInfo("cat", "No file specified")
|
|
||||||
end
|
|
14
bin/cd
14
bin/cd
|
@ -1,14 +0,0 @@
|
||||||
local tArgs = { ... }
|
|
||||||
if #tArgs < 1 then
|
|
||||||
local programName = arg[0] or fs.getName(shell.getRunningProgram())
|
|
||||||
print("Usage: " .. programName .. " <path>")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local sNewDir = shell.resolve(tArgs[1])
|
|
||||||
if fs.isDir(sNewDir) then
|
|
||||||
shell.setDir(sNewDir)
|
|
||||||
else
|
|
||||||
print("Not a directory")
|
|
||||||
return
|
|
||||||
end
|
|
44
bin/clear
44
bin/clear
|
@ -1,44 +0,0 @@
|
||||||
local tArgs = { ... }
|
|
||||||
|
|
||||||
local function printUsage()
|
|
||||||
local programName = "clear"
|
|
||||||
print("Usages:")
|
|
||||||
print(programName)
|
|
||||||
print(programName .. " screen")
|
|
||||||
print(programName .. " palette")
|
|
||||||
print(programName .. " all")
|
|
||||||
end
|
|
||||||
|
|
||||||
local function clear()
|
|
||||||
term.clear()
|
|
||||||
term.setCursorPos(1, 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function clearPixels()
|
|
||||||
if term.getGraphicsMode then
|
|
||||||
term.setGraphicsMode(1)
|
|
||||||
term.clear()
|
|
||||||
term.setGraphicsMode(0)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function resetPalette()
|
|
||||||
for i = 0, 15 do
|
|
||||||
term.setPaletteColour(2^i, term.nativePaletteColour(2^i))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local sCommand = tArgs[1] or "screen"
|
|
||||||
if sCommand == "screen" then
|
|
||||||
clear()
|
|
||||||
elseif sCommand == "palette" then
|
|
||||||
resetPalette()
|
|
||||||
elseif sCommand == "graphics" then
|
|
||||||
clearPixels()
|
|
||||||
elseif sCommand == "all" then
|
|
||||||
clear()
|
|
||||||
clearPixels()
|
|
||||||
resetPalette()
|
|
||||||
else
|
|
||||||
printUsage()
|
|
||||||
end
|
|
23
bin/convert
23
bin/convert
|
@ -1,23 +0,0 @@
|
||||||
local args = {...}
|
|
||||||
|
|
||||||
local function checksys(txt)
|
|
||||||
if txt == "kernel" or txt == "gui" or txt == "app" or txt == "log" or txt == "config" or txt == "manual" or txt == "search" or txt == "tpm" or txt == "exception" or string.find(txt, "boot/") or string.find(txt, "system/") or string.find(txt, ".freax/startup") then
|
|
||||||
kerneldraw.printAppWarning("kernel", "attempt to perform restricted operations")
|
|
||||||
--return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if #args < 1 or not fs.exists(shell.resolveProgram(args[1])) or fs.isDir(shell.resolve(args[1])) then
|
|
||||||
kerneldraw.printAppInfo("config", "No file specified")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if not checksys(shell.resolveProgram(args[1])) then
|
|
||||||
if os.loadAPI(shell.resolveProgram(args[1])) then
|
|
||||||
config.save(_G[args[1]], textutils.serialize(args[1]))
|
|
||||||
os.unloadAPI(args[1])
|
|
||||||
kerneldraw.printAppSuccess("config", "Done")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
exception.throw("RestrictedOpsException")
|
|
||||||
end
|
|
32
bin/cp
32
bin/cp
|
@ -1,32 +0,0 @@
|
||||||
local tArgs = { ... }
|
|
||||||
if #tArgs < 2 then
|
|
||||||
local programName = "cp"
|
|
||||||
print("Usage: " .. programName .. " <source> <destination>")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local sSource = shell.resolve(tArgs[1])
|
|
||||||
local sDest = shell.resolve(tArgs[2])
|
|
||||||
local tFiles = fs.find(sSource)
|
|
||||||
if #tFiles > 0 then
|
|
||||||
for _, sFile in ipairs(tFiles) do
|
|
||||||
if fs.isDir(sDest) then
|
|
||||||
fs.copy(sFile, fs.combine(sDest, fs.getName(sFile)))
|
|
||||||
elseif #tFiles == 1 then
|
|
||||||
if fs.exists(sDest) then
|
|
||||||
printError("Destination exists")
|
|
||||||
elseif fs.isReadOnly(sDest) then
|
|
||||||
printError("Destination is read-only")
|
|
||||||
elseif fs.getFreeSpace(sDest) < fs.getSize(sFile) then
|
|
||||||
printError("Not enough space")
|
|
||||||
else
|
|
||||||
fs.copy(sFile, sDest)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
printError("Cannot overwrite file multiple times")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
printError("No matching files")
|
|
||||||
end
|
|
|
@ -1 +0,0 @@
|
||||||
shell.run("/bin/man credits")
|
|
|
@ -1,2 +0,0 @@
|
||||||
if periphemu == nil then error("Attaching peripherals is not supported in vanilla mode.") end
|
|
||||||
if type(({...})[1]) ~= "string" then print("Usage: detach <side>") else if not periphemu.remove(({...})[1]) then printError("Could not detach peripheral") end end
|
|
12
bin/df
12
bin/df
|
@ -1,12 +0,0 @@
|
||||||
local tArgs = {...}
|
|
||||||
local sz = fs.getSize(shell.dir())
|
|
||||||
local fspc = fs.getFreeSpace(shell.dir())
|
|
||||||
|
|
||||||
kerneldraw.printAppInfo("type", fs.getDrive(shell.dir()))
|
|
||||||
if search.findValue(tArgs, "-sB") then
|
|
||||||
kerneldraw.printAppInfo("size", tostring(sz).." B")
|
|
||||||
kerneldraw.printAppInfo("free space", tostring(fspc).." B")
|
|
||||||
elseif search.findValue(tArgs, "-sKB") then
|
|
||||||
kerneldraw.printAppInfo("size", tostring(sz/1024).." KB")
|
|
||||||
kerneldraw.printAppInfo("free space", tostring(fspc/1024).." KB")
|
|
||||||
end
|
|
21
bin/drive
21
bin/drive
|
@ -1,21 +0,0 @@
|
||||||
local tArgs = { ... }
|
|
||||||
|
|
||||||
-- Get where a directory is mounted
|
|
||||||
local sPath = shell.dir()
|
|
||||||
if tArgs[1] ~= nil then
|
|
||||||
sPath = shell.resolve(tArgs[1])
|
|
||||||
end
|
|
||||||
|
|
||||||
if fs.exists(sPath) then
|
|
||||||
write(fs.getDrive(sPath) .. " (")
|
|
||||||
local nSpace = fs.getFreeSpace(sPath)
|
|
||||||
if nSpace >= 1000 * 1000 then
|
|
||||||
print(math.floor(nSpace / (100 * 1000)) / 10 .. "MB remaining)")
|
|
||||||
elseif nSpace >= 1000 then
|
|
||||||
print(math.floor(nSpace / 100) / 10 .. "KB remaining)")
|
|
||||||
else
|
|
||||||
print(nSpace .. "B remaining)")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
print("No such path")
|
|
||||||
end
|
|
18
bin/eject
18
bin/eject
|
@ -1,18 +0,0 @@
|
||||||
-- Get arguments
|
|
||||||
local tArgs = { ... }
|
|
||||||
if #tArgs == 0 then
|
|
||||||
local programName = "eject"
|
|
||||||
print("Usage: " .. programName .. " <drive>")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local sDrive = tArgs[1]
|
|
||||||
|
|
||||||
-- Check the disk exists
|
|
||||||
local bPresent = disk.isPresent(sDrive)
|
|
||||||
if not bPresent then
|
|
||||||
print("Nothing in " .. sDrive .. " drive")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
disk.eject(sDrive)
|
|
40
bin/env
40
bin/env
|
@ -1,40 +0,0 @@
|
||||||
if shell.environment == nil then error("Requires the cash shell.") end
|
|
||||||
local args = {...}
|
|
||||||
|
|
||||||
local env = setmetatable({}, {__index = _ENV})
|
|
||||||
local path = shell.path()
|
|
||||||
local unset = {}
|
|
||||||
local cmd = {}
|
|
||||||
local cmdargs = false
|
|
||||||
local nextarg
|
|
||||||
|
|
||||||
for k,v in ipairs(args) do
|
|
||||||
if nextarg then
|
|
||||||
if nextarg == 1 then path = v
|
|
||||||
elseif nextarg == 2 then table.insert(unset, v) end
|
|
||||||
nextarg = nil
|
|
||||||
elseif cmdargs then
|
|
||||||
table.insert(cmd, v)
|
|
||||||
else
|
|
||||||
if v == "-i" then setmetatable(env, {__index = _G})
|
|
||||||
elseif v == "-P" then nextarg = 1
|
|
||||||
elseif v == "-u" then nextarg = 2
|
|
||||||
elseif string.find(v, "=") then env[string.sub(v, 1, string.find(v, "=") - 1)] = string.sub(v, string.find(v, "=") + 1)
|
|
||||||
else table.insert(cmd, v); cmdargs = true end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if #unset > 0 then
|
|
||||||
local oldidx = getmetatable(env).__index
|
|
||||||
local u = {}
|
|
||||||
for k,v in ipairs(unset) do u[v] = true end
|
|
||||||
setmetatable(env, {__index = function(self, name) if u[name] then return nil else return oldidx[name] end end})
|
|
||||||
end
|
|
||||||
|
|
||||||
local oldPath = shell.path()
|
|
||||||
local oldEnv = shell.environment()
|
|
||||||
shell.setPath(path)
|
|
||||||
shell.setEnvironment(env)
|
|
||||||
shell.run(table.unpack(cmd))
|
|
||||||
shell.setPath(oldPath)
|
|
||||||
shell.setEnvironment(oldEnv)
|
|
5
bin/exit
5
bin/exit
|
@ -1,5 +0,0 @@
|
||||||
if security.getSU() then
|
|
||||||
shell.exit()
|
|
||||||
else
|
|
||||||
kernel.reboot(true)
|
|
||||||
end
|
|
|
@ -1 +0,0 @@
|
||||||
shell.run("/bin/man firststeps")
|
|
994
bin/gclone
994
bin/gclone
|
@ -1,994 +0,0 @@
|
||||||
local replaceLine = true -- Setting to false may result in corrupted output
|
|
||||||
local preload = type(package) == "table" and type(package.preload) == "table" and package.preload or {}
|
|
||||||
|
|
||||||
local require = require
|
|
||||||
if type(require) ~= "function" then
|
|
||||||
local loading = {}
|
|
||||||
local loaded = {}
|
|
||||||
require = function(name)
|
|
||||||
local result = loaded[name]
|
|
||||||
|
|
||||||
if result ~= nil then
|
|
||||||
if result == loading then
|
|
||||||
error("loop or previous error loading module '" .. name .. "'", 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
|
|
||||||
loaded[name] = loading
|
|
||||||
local contents = preload[name]
|
|
||||||
if contents then
|
|
||||||
result = contents(name)
|
|
||||||
else
|
|
||||||
error("cannot load '" .. name .. "'", 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
if result == nil then result = true end
|
|
||||||
loaded[name] = result
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
end
|
|
||||||
preload["objects"] = function(...)
|
|
||||||
local inflate_zlib = require "deflate".inflate_zlib
|
|
||||||
local sha = require "metis.crypto.sha1"
|
|
||||||
|
|
||||||
local band, bor, lshift, rshift = bit32.band, bit32.bor, bit32.lshift, bit32.rshift
|
|
||||||
local byte, format, sub = string.byte, string.format, string.sub
|
|
||||||
|
|
||||||
local types = { [0] = "none", "commit", "tree", "blob", "tag", nil, "ofs_delta", "ref_delta", "any", "max" }
|
|
||||||
|
|
||||||
--- Get the type of a specific object
|
|
||||||
-- @tparam Object x The object to get the type of
|
|
||||||
-- @treturn string The object's type.
|
|
||||||
local function get_type(x) return types[x.ty] or "?" end
|
|
||||||
|
|
||||||
local event = ("luagit-%08x"):format(math.random(0, 2^24))
|
|
||||||
local function check_in()
|
|
||||||
os.queueEvent(event)
|
|
||||||
os.pullEvent(event)
|
|
||||||
end
|
|
||||||
|
|
||||||
local sha_format = ("%02x"):rep(20)
|
|
||||||
|
|
||||||
local function reader(str)
|
|
||||||
local expected_checksum = format(sha_format, byte(str, -20, -1))
|
|
||||||
local actual_checksum = sha(str:sub(1, -21));
|
|
||||||
if expected_checksum ~= actual_checksum then
|
|
||||||
error(("checksum mismatch: expected %s, got %s"):format(expected_checksum, actual_checksum))
|
|
||||||
end
|
|
||||||
|
|
||||||
str = str:sub(1, -20)
|
|
||||||
|
|
||||||
local pos = 1
|
|
||||||
|
|
||||||
local function consume_read(len)
|
|
||||||
if len <= 0 then error("len < 0", 2) end
|
|
||||||
if pos > #str then error("end of stream") end
|
|
||||||
|
|
||||||
local cur_pos = pos
|
|
||||||
pos = pos + len
|
|
||||||
local res = sub(str, cur_pos, pos - 1)
|
|
||||||
if #res ~= len then error("expected " .. len .. " bytes, got" .. #res) end
|
|
||||||
return res
|
|
||||||
end
|
|
||||||
|
|
||||||
local function read8()
|
|
||||||
if pos > #str then error("end of stream") end
|
|
||||||
local cur_pos = pos
|
|
||||||
pos = pos + 1
|
|
||||||
return byte(str, cur_pos)
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
|
||||||
offset = function() return pos - 1 end,
|
|
||||||
read8 = read8,
|
|
||||||
read16 = function() return (read8() * (2^8)) + read8() end,
|
|
||||||
read32 = function() return (read8() * (2^24)) + (read8() * (2^16)) + (read8() * (2^8)) + read8() end,
|
|
||||||
read = consume_read,
|
|
||||||
|
|
||||||
close = function()
|
|
||||||
if pos ~= #str then error(("%d of %d bytes remaining"):format(#str - pos + 1, #str)) end
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Consume a string from the given input buffer
|
|
||||||
--
|
|
||||||
-- @tparam Reader handle The handle to read from
|
|
||||||
-- @tparam number size The number of decompressed bytes to read
|
|
||||||
-- @treturn string The decompressed data
|
|
||||||
local function get_data(handle, size)
|
|
||||||
local tbl, n = {}, 1
|
|
||||||
|
|
||||||
inflate_zlib {
|
|
||||||
input = handle.read8,
|
|
||||||
output = function(x) tbl[n], n = string.char(x), n + 1 end
|
|
||||||
}
|
|
||||||
|
|
||||||
local res = table.concat(tbl)
|
|
||||||
if #res ~= size then error(("expected %d decompressed bytes, got %d"):format(size, #res)) end
|
|
||||||
return res
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Decode a binary delta file, applying it to the original
|
|
||||||
--
|
|
||||||
-- The format is described in more detail in [the Git documentation][git_pack]
|
|
||||||
--
|
|
||||||
-- [git_pack]: https://git-scm.com/docs/pack-format#_deltified_representation
|
|
||||||
--
|
|
||||||
-- @tparam string original The original string
|
|
||||||
-- @tparam string delta The binary delta
|
|
||||||
-- @treturn string The patched string
|
|
||||||
local function apply_delta(original, delta)
|
|
||||||
local delta_offset = 1
|
|
||||||
local function read_size()
|
|
||||||
local c = byte(delta, delta_offset)
|
|
||||||
delta_offset = delta_offset + 1
|
|
||||||
|
|
||||||
local size = band(c, 0x7f)
|
|
||||||
local shift = 7
|
|
||||||
while band(c, 0x80) ~= 0 do
|
|
||||||
c, delta_offset = byte(delta, delta_offset), delta_offset + 1
|
|
||||||
size, shift = size + lshift(band(c, 0x7f), shift), shift + 7
|
|
||||||
end
|
|
||||||
|
|
||||||
return size
|
|
||||||
end
|
|
||||||
|
|
||||||
local original_length = read_size()
|
|
||||||
local patched_length = read_size()
|
|
||||||
if original_length ~= #original then
|
|
||||||
error(("expected original of size %d, got size %d"):format(original_length, #original))
|
|
||||||
end
|
|
||||||
|
|
||||||
local parts, n = {}, 1
|
|
||||||
while delta_offset <= #delta do
|
|
||||||
local b = byte(delta, delta_offset)
|
|
||||||
delta_offset = delta_offset + 1
|
|
||||||
|
|
||||||
if band(b, 0x80) ~= 0 then
|
|
||||||
-- Copy from the original file. Each bit represents which optional length/offset
|
|
||||||
-- bits are used.
|
|
||||||
local offset, length = 0, 0
|
|
||||||
|
|
||||||
if band(b, 0x01) ~= 0 then
|
|
||||||
offset, delta_offset = bor(offset, byte(delta, delta_offset)), delta_offset + 1
|
|
||||||
end
|
|
||||||
if band(b, 0x02) ~= 0 then
|
|
||||||
offset, delta_offset = bor(offset, lshift(byte(delta, delta_offset), 8)), delta_offset + 1
|
|
||||||
end
|
|
||||||
if band(b, 0x04) ~= 0 then
|
|
||||||
offset, delta_offset = bor(offset, lshift(byte(delta, delta_offset), 16)), delta_offset + 1
|
|
||||||
end
|
|
||||||
if band(b, 0x08) ~= 0 then
|
|
||||||
offset, delta_offset = bor(offset, lshift(byte(delta, delta_offset), 24)), delta_offset + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
if band(b, 0x10) ~= 0 then
|
|
||||||
length, delta_offset = bor(length, byte(delta, delta_offset)), delta_offset + 1
|
|
||||||
end
|
|
||||||
if band(b, 0x20) ~= 0 then
|
|
||||||
length, delta_offset = bor(length, lshift(byte(delta, delta_offset), 8)), delta_offset + 1
|
|
||||||
end
|
|
||||||
if band(b, 0x40) ~= 0 then
|
|
||||||
length, delta_offset = bor(length, lshift(byte(delta, delta_offset), 16)), delta_offset + 1
|
|
||||||
end
|
|
||||||
if length == 0 then length = 0x10000 end
|
|
||||||
|
|
||||||
parts[n], n = sub(original, offset + 1, offset + length), n + 1
|
|
||||||
elseif b > 0 then
|
|
||||||
-- Copy from the delta. The opcode encodes the length
|
|
||||||
parts[n], n = sub(delta, delta_offset, delta_offset + b - 1), n + 1
|
|
||||||
delta_offset = delta_offset + b
|
|
||||||
else
|
|
||||||
error(("unknown opcode '%02x'"):format(b))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local patched = table.concat(parts)
|
|
||||||
if patched_length ~= #patched then
|
|
||||||
error(("expected patched of size %d, got size %d"):format(patched_length, #patched))
|
|
||||||
end
|
|
||||||
|
|
||||||
return patched
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Unpack a single object, populating the output table
|
|
||||||
--
|
|
||||||
-- @tparam Reader handle The handle to read from
|
|
||||||
-- @tparam { [string] = Object } out The populated data
|
|
||||||
local function unpack_object(handle, out)
|
|
||||||
local c = handle.read8()
|
|
||||||
local ty = band(rshift(c, 4), 7)
|
|
||||||
local size = band(c, 15)
|
|
||||||
local shift = 4
|
|
||||||
while band(c, 0x80) ~= 0 do
|
|
||||||
c = handle.read8()
|
|
||||||
size = size + lshift(band(c, 0x7f), shift)
|
|
||||||
shift = shift + 7
|
|
||||||
end
|
|
||||||
|
|
||||||
local data
|
|
||||||
if ty >= 1 and ty <= 4 then
|
|
||||||
-- commit/tree/blob/tag
|
|
||||||
data = get_data(handle, size)
|
|
||||||
elseif ty == 6 then
|
|
||||||
-- ofs_delta
|
|
||||||
data = get_data(handle, size)
|
|
||||||
error("ofs_delta not yet implemented")
|
|
||||||
|
|
||||||
elseif ty == 7 then
|
|
||||||
-- ref_delta
|
|
||||||
local base_hash = sha_format:format(handle.read(20):byte(1, 20))
|
|
||||||
local delta = get_data(handle, size)
|
|
||||||
|
|
||||||
local original = out[base_hash]
|
|
||||||
if not original then error(("cannot find object %d to apply diff"):format(base_hash)) return end
|
|
||||||
ty = original.ty
|
|
||||||
data = apply_delta(original.data, delta)
|
|
||||||
else
|
|
||||||
error(("unknown object of type '%d'"):format(ty))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- We've got to do these separately. Format doesn't like null bytes
|
|
||||||
local whole = ("%s %d\0"):format(types[ty], #data) .. data
|
|
||||||
local sha = sha(whole)
|
|
||||||
out[sha] = { ty = ty, data = data, sha = sha }
|
|
||||||
end
|
|
||||||
|
|
||||||
local function unpack(handle, progress)
|
|
||||||
local header = handle.read(4)
|
|
||||||
if header ~= "PACK" then error("expected PACK, got " .. header, 0) end
|
|
||||||
|
|
||||||
local version = handle.read32()
|
|
||||||
local entries = handle.read32()
|
|
||||||
|
|
||||||
local out = {}
|
|
||||||
for i = 1, entries do
|
|
||||||
if progress then progress(i, entries) end
|
|
||||||
check_in()
|
|
||||||
|
|
||||||
unpack_object(handle, out)
|
|
||||||
end
|
|
||||||
|
|
||||||
return out
|
|
||||||
end
|
|
||||||
|
|
||||||
local function build_tree(objects, object, prefix, out)
|
|
||||||
if not prefix then prefix = "" end
|
|
||||||
if not out then out = {} end
|
|
||||||
|
|
||||||
local idx = 1
|
|
||||||
|
|
||||||
while idx <= #object do
|
|
||||||
-- dddddd NAME\0<SHA>
|
|
||||||
local _, endidx, mode, name = object:find("^(%x+) ([^%z]+)%z", idx)
|
|
||||||
if not endidx then break end
|
|
||||||
name = prefix .. name
|
|
||||||
|
|
||||||
local sha = object:sub(endidx + 1, endidx + 20):gsub(".", function(x) return ("%02x"):format(string.byte(x)) end)
|
|
||||||
|
|
||||||
local entry = objects[sha]
|
|
||||||
if not entry then error(("cannot find %s %s (%s)"):format(mode, name, sha)) end
|
|
||||||
|
|
||||||
if entry.ty == 3 then
|
|
||||||
out[name] = entry.data
|
|
||||||
elseif entry.ty == 2 then
|
|
||||||
build_tree(objects, entry.data, name .. "/", out)
|
|
||||||
else
|
|
||||||
error("unknown type for " .. name .. " (" .. sha .. "): " .. get_type(entry))
|
|
||||||
end
|
|
||||||
|
|
||||||
idx = endidx + 21
|
|
||||||
end
|
|
||||||
|
|
||||||
return out
|
|
||||||
end
|
|
||||||
|
|
||||||
local function build_commit(objects, sha)
|
|
||||||
local commit = objects[sha]
|
|
||||||
if not commit then error("cannot find commit " .. sha) end
|
|
||||||
if commit.ty ~= 1 then error("Expected commit, got " .. types[commit.ty]) end
|
|
||||||
|
|
||||||
local tree_sha = commit.data:match("tree (%x+)\n")
|
|
||||||
if not tree_sha then error("Cannot find tree from commit") end
|
|
||||||
|
|
||||||
local tree = objects[tree_sha]
|
|
||||||
if not tree then error("cannot find tree " .. tree_sha) end
|
|
||||||
if tree.ty ~= 2 then error("Expected tree, got " .. tree[tree.ty]) end
|
|
||||||
|
|
||||||
return build_tree(objects, tree.data)
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
|
||||||
reader = reader,
|
|
||||||
unpack = unpack,
|
|
||||||
build_tree = build_tree,
|
|
||||||
build_commit = build_commit,
|
|
||||||
type = get_type,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
preload["network"] = function(...)
|
|
||||||
local function pkt_line(msg)
|
|
||||||
return ("%04x%s\n"):format(5 + #msg, msg)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function pkt_linef(fmt, ...)
|
|
||||||
return pkt_line(fmt:format(...))
|
|
||||||
end
|
|
||||||
|
|
||||||
local flush_line = "0000"
|
|
||||||
|
|
||||||
local function read_pkt_line(handle)
|
|
||||||
local data = handle.read(4)
|
|
||||||
if data == nil or data == "" then return nil end
|
|
||||||
|
|
||||||
local len = tonumber(data, 16)
|
|
||||||
if len == nil then
|
|
||||||
error(("read_pkt_line: cannot convert %q to a number"):format(data))
|
|
||||||
elseif len == 0 then
|
|
||||||
return false, data
|
|
||||||
else
|
|
||||||
return handle.read(len - 4), data
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function fetch(url, lines, content_type)
|
|
||||||
if type(lines) == "table" then lines = table.concat(lines) end
|
|
||||||
|
|
||||||
local ok, err = http.request(url, lines, {
|
|
||||||
['User-Agent'] = 'CCGit/1.0',
|
|
||||||
['Content-Type'] = content_type,
|
|
||||||
}, true)
|
|
||||||
|
|
||||||
if ok then
|
|
||||||
while true do
|
|
||||||
local event, event_url, param1, param2 = os.pullEvent()
|
|
||||||
if event == "http_success" and event_url == url then
|
|
||||||
return true, param1
|
|
||||||
elseif event == "http_failure" and event_url == url then
|
|
||||||
printError("Cannot fetch " .. url .. ": " .. param1)
|
|
||||||
return false, param2
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
printError("Cannot fetch " .. url .. ": " .. err)
|
|
||||||
return false, nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function force_fetch(...)
|
|
||||||
local ok, handle, err_handle = fetch(...)
|
|
||||||
if not ok then
|
|
||||||
if err_handle then
|
|
||||||
print(err_handle.getStatusCode())
|
|
||||||
print(textutils.serialize(err_handle.getResponseHeaders()))
|
|
||||||
print(err_handle.readAll())
|
|
||||||
end
|
|
||||||
error("Cannot fetch", 0)
|
|
||||||
end
|
|
||||||
|
|
||||||
return handle
|
|
||||||
end
|
|
||||||
|
|
||||||
local function receive(handle)
|
|
||||||
local out = {}
|
|
||||||
while true do
|
|
||||||
local line = read_pkt_line(handle)
|
|
||||||
if line == nil then break end
|
|
||||||
out[#out + 1] = line
|
|
||||||
end
|
|
||||||
|
|
||||||
handle.close()
|
|
||||||
return out
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
|
||||||
read_pkt_line = read_pkt_line,
|
|
||||||
force_fetch = force_fetch,
|
|
||||||
receive = receive,
|
|
||||||
|
|
||||||
pkt_linef = pkt_linef,
|
|
||||||
flush_line = flush_line,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
preload["deflate"] = function(...)
|
|
||||||
--[[
|
|
||||||
(c) 2008-2011 David Manura. Licensed under the same terms as Lua (MIT).
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
(end license)
|
|
||||||
--]]
|
|
||||||
|
|
||||||
local assert, error, ipairs, pairs, tostring, type, setmetatable, io, math
|
|
||||||
= assert, error, ipairs, pairs, tostring, type, setmetatable, io, math
|
|
||||||
local table_sort, math_max, string_char = table.sort, math.max, string.char
|
|
||||||
local band, lshift, rshift = bit32.band, bit32.lshift, bit32.rshift
|
|
||||||
|
|
||||||
local function make_outstate(outbs)
|
|
||||||
local outstate = {}
|
|
||||||
outstate.outbs = outbs
|
|
||||||
outstate.len = 0
|
|
||||||
outstate.window = {}
|
|
||||||
outstate.window_pos = 1
|
|
||||||
return outstate
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function output(outstate, byte)
|
|
||||||
local window_pos = outstate.window_pos
|
|
||||||
outstate.outbs(byte)
|
|
||||||
outstate.len = outstate.len + 1
|
|
||||||
outstate.window[window_pos] = byte
|
|
||||||
outstate.window_pos = window_pos % 32768 + 1 -- 32K
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function noeof(val)
|
|
||||||
return assert(val, 'unexpected end of file')
|
|
||||||
end
|
|
||||||
|
|
||||||
local function memoize(f)
|
|
||||||
return setmetatable({}, {
|
|
||||||
__index = function(self, k)
|
|
||||||
local v = f(k)
|
|
||||||
self[k] = v
|
|
||||||
return v
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
-- small optimization (lookup table for powers of 2)
|
|
||||||
local pow2 = memoize(function(n) return 2^n end)
|
|
||||||
|
|
||||||
local function bitstream_from_bytestream(bys)
|
|
||||||
local buf_byte = 0
|
|
||||||
local buf_nbit = 0
|
|
||||||
local o = { type = "bitstream" }
|
|
||||||
|
|
||||||
function o:nbits_left_in_byte()
|
|
||||||
return buf_nbit
|
|
||||||
end
|
|
||||||
|
|
||||||
function o:read(nbits)
|
|
||||||
nbits = nbits or 1
|
|
||||||
while buf_nbit < nbits do
|
|
||||||
local byte = bys()
|
|
||||||
if not byte then return end -- note: more calls also return nil
|
|
||||||
buf_byte = buf_byte + lshift(byte, buf_nbit)
|
|
||||||
buf_nbit = buf_nbit + 8
|
|
||||||
end
|
|
||||||
local bits
|
|
||||||
if nbits == 0 then
|
|
||||||
bits = 0
|
|
||||||
elseif nbits == 32 then
|
|
||||||
bits = buf_byte
|
|
||||||
buf_byte = 0
|
|
||||||
else
|
|
||||||
bits = band(buf_byte, rshift(0xffffffff, 32 - nbits))
|
|
||||||
buf_byte = rshift(buf_byte, nbits)
|
|
||||||
end
|
|
||||||
buf_nbit = buf_nbit - nbits
|
|
||||||
return bits
|
|
||||||
end
|
|
||||||
|
|
||||||
return o
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get_bitstream(o)
|
|
||||||
if type(o) == "table" and o.type == "bitstream" then
|
|
||||||
return o
|
|
||||||
elseif io.type(o) == 'file' then
|
|
||||||
return bitstream_from_bytestream(function() local sb = o:read(1) if sb then return sb:byte() end end)
|
|
||||||
elseif type(o) == "function" then
|
|
||||||
return bitstream_from_bytestream(o)
|
|
||||||
else
|
|
||||||
error 'unrecognized type'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function get_obytestream(o)
|
|
||||||
local bs
|
|
||||||
if io.type(o) == 'file' then
|
|
||||||
bs = function(sbyte) o:write(string_char(sbyte)) end
|
|
||||||
elseif type(o) == 'function' then
|
|
||||||
bs = o
|
|
||||||
else
|
|
||||||
error('unrecognized type: ' .. tostring(o))
|
|
||||||
end
|
|
||||||
return bs
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function HuffmanTable(init, is_full)
|
|
||||||
local t = {}
|
|
||||||
if is_full then
|
|
||||||
for val,nbits in pairs(init) do
|
|
||||||
if nbits ~= 0 then
|
|
||||||
t[#t+1] = {val=val, nbits=nbits}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
for i=1,#init-2,2 do
|
|
||||||
local firstval, nbits, nextval = init[i], init[i+1], init[i+2]
|
|
||||||
if nbits ~= 0 then
|
|
||||||
for val=firstval,nextval-1 do
|
|
||||||
t[#t+1] = {val=val, nbits=nbits}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
table_sort(t, function(a,b)
|
|
||||||
return a.nbits == b.nbits and a.val < b.val or a.nbits < b.nbits
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- assign codes
|
|
||||||
local code = 1 -- leading 1 marker
|
|
||||||
local nbits = 0
|
|
||||||
for _, s in ipairs(t) do
|
|
||||||
if s.nbits ~= nbits then
|
|
||||||
code = code * pow2[s.nbits - nbits]
|
|
||||||
nbits = s.nbits
|
|
||||||
end
|
|
||||||
s.code = code
|
|
||||||
code = code + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
local minbits = math.huge
|
|
||||||
local look = {}
|
|
||||||
for _, s in ipairs(t) do
|
|
||||||
minbits = math.min(minbits, s.nbits)
|
|
||||||
look[s.code] = s.val
|
|
||||||
end
|
|
||||||
|
|
||||||
local msb = function(bits, nbits)
|
|
||||||
local res = 0
|
|
||||||
for _ = 1, nbits do
|
|
||||||
res = lshift(res, 1) + band(bits, 1)
|
|
||||||
bits = rshift(bits, 1)
|
|
||||||
end
|
|
||||||
return res
|
|
||||||
end
|
|
||||||
|
|
||||||
local tfirstcode = memoize(
|
|
||||||
function(bits) return pow2[minbits] + msb(bits, minbits) end)
|
|
||||||
|
|
||||||
function t:read(bs)
|
|
||||||
local code = 1 -- leading 1 marker
|
|
||||||
local nbits = 0
|
|
||||||
while 1 do
|
|
||||||
if nbits == 0 then -- small optimization (optional)
|
|
||||||
code = tfirstcode[noeof(bs:read(minbits))]
|
|
||||||
nbits = nbits + minbits
|
|
||||||
else
|
|
||||||
local b = noeof(bs:read())
|
|
||||||
nbits = nbits + 1
|
|
||||||
code = code * 2 + b -- MSB first
|
|
||||||
end
|
|
||||||
local val = look[code]
|
|
||||||
if val then
|
|
||||||
return val
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return t
|
|
||||||
end
|
|
||||||
|
|
||||||
local function parse_zlib_header(bs)
|
|
||||||
local cm = bs:read(4) -- Compression Method
|
|
||||||
local cinfo = bs:read(4) -- Compression info
|
|
||||||
local fcheck = bs:read(5) -- FLaGs: FCHECK (check bits for CMF and FLG)
|
|
||||||
local fdict = bs:read(1) -- FLaGs: FDICT (present dictionary)
|
|
||||||
local flevel = bs:read(2) -- FLaGs: FLEVEL (compression level)
|
|
||||||
local cmf = cinfo * 16 + cm -- CMF (Compresion Method and flags)
|
|
||||||
local flg = fcheck + fdict * 32 + flevel * 64 -- FLaGs
|
|
||||||
|
|
||||||
if cm ~= 8 then -- not "deflate"
|
|
||||||
error("unrecognized zlib compression method: " .. cm)
|
|
||||||
end
|
|
||||||
if cinfo > 7 then
|
|
||||||
error("invalid zlib window size: cinfo=" .. cinfo)
|
|
||||||
end
|
|
||||||
local window_size = 2^(cinfo + 8)
|
|
||||||
|
|
||||||
if (cmf*256 + flg) % 31 ~= 0 then
|
|
||||||
error("invalid zlib header (bad fcheck sum)")
|
|
||||||
end
|
|
||||||
|
|
||||||
if fdict == 1 then
|
|
||||||
error("FIX:TODO - FDICT not currently implemented")
|
|
||||||
local dictid_ = bs:read(32)
|
|
||||||
end
|
|
||||||
|
|
||||||
return window_size
|
|
||||||
end
|
|
||||||
|
|
||||||
local function parse_huffmantables(bs)
|
|
||||||
local hlit = bs:read(5) -- # of literal/length codes - 257
|
|
||||||
local hdist = bs:read(5) -- # of distance codes - 1
|
|
||||||
local hclen = noeof(bs:read(4)) -- # of code length codes - 4
|
|
||||||
|
|
||||||
local ncodelen_codes = hclen + 4
|
|
||||||
local codelen_init = {}
|
|
||||||
local codelen_vals = {
|
|
||||||
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}
|
|
||||||
for i=1,ncodelen_codes do
|
|
||||||
local nbits = bs:read(3)
|
|
||||||
local val = codelen_vals[i]
|
|
||||||
codelen_init[val] = nbits
|
|
||||||
end
|
|
||||||
local codelentable = HuffmanTable(codelen_init, true)
|
|
||||||
|
|
||||||
local function decode(ncodes)
|
|
||||||
local init = {}
|
|
||||||
local nbits
|
|
||||||
local val = 0
|
|
||||||
while val < ncodes do
|
|
||||||
local codelen = codelentable:read(bs)
|
|
||||||
--FIX:check nil?
|
|
||||||
local nrepeat
|
|
||||||
if codelen <= 15 then
|
|
||||||
nrepeat = 1
|
|
||||||
nbits = codelen
|
|
||||||
elseif codelen == 16 then
|
|
||||||
nrepeat = 3 + noeof(bs:read(2))
|
|
||||||
-- nbits unchanged
|
|
||||||
elseif codelen == 17 then
|
|
||||||
nrepeat = 3 + noeof(bs:read(3))
|
|
||||||
nbits = 0
|
|
||||||
elseif codelen == 18 then
|
|
||||||
nrepeat = 11 + noeof(bs:read(7))
|
|
||||||
nbits = 0
|
|
||||||
else
|
|
||||||
error 'ASSERT'
|
|
||||||
end
|
|
||||||
for _ = 1, nrepeat do
|
|
||||||
init[val] = nbits
|
|
||||||
val = val + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local huffmantable = HuffmanTable(init, true)
|
|
||||||
return huffmantable
|
|
||||||
end
|
|
||||||
|
|
||||||
local nlit_codes = hlit + 257
|
|
||||||
local ndist_codes = hdist + 1
|
|
||||||
|
|
||||||
local littable = decode(nlit_codes)
|
|
||||||
local disttable = decode(ndist_codes)
|
|
||||||
|
|
||||||
return littable, disttable
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local tdecode_len_base
|
|
||||||
local tdecode_len_nextrabits
|
|
||||||
local tdecode_dist_base
|
|
||||||
local tdecode_dist_nextrabits
|
|
||||||
local function parse_compressed_item(bs, outstate, littable, disttable)
|
|
||||||
local val = littable:read(bs)
|
|
||||||
if val < 256 then -- literal
|
|
||||||
output(outstate, val)
|
|
||||||
elseif val == 256 then -- end of block
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
if not tdecode_len_base then
|
|
||||||
local t = {[257]=3}
|
|
||||||
local skip = 1
|
|
||||||
for i=258,285,4 do
|
|
||||||
for j=i,i+3 do t[j] = t[j-1] + skip end
|
|
||||||
if i ~= 258 then skip = skip * 2 end
|
|
||||||
end
|
|
||||||
t[285] = 258
|
|
||||||
tdecode_len_base = t
|
|
||||||
end
|
|
||||||
if not tdecode_len_nextrabits then
|
|
||||||
local t = {}
|
|
||||||
for i=257,285 do
|
|
||||||
local j = math_max(i - 261, 0)
|
|
||||||
t[i] = rshift(j, 2)
|
|
||||||
end
|
|
||||||
t[285] = 0
|
|
||||||
tdecode_len_nextrabits = t
|
|
||||||
end
|
|
||||||
local len_base = tdecode_len_base[val]
|
|
||||||
local nextrabits = tdecode_len_nextrabits[val]
|
|
||||||
local extrabits = bs:read(nextrabits)
|
|
||||||
local len = len_base + extrabits
|
|
||||||
|
|
||||||
if not tdecode_dist_base then
|
|
||||||
local t = {[0]=1}
|
|
||||||
local skip = 1
|
|
||||||
for i=1,29,2 do
|
|
||||||
for j=i,i+1 do t[j] = t[j-1] + skip end
|
|
||||||
if i ~= 1 then skip = skip * 2 end
|
|
||||||
end
|
|
||||||
tdecode_dist_base = t
|
|
||||||
end
|
|
||||||
if not tdecode_dist_nextrabits then
|
|
||||||
local t = {}
|
|
||||||
for i=0,29 do
|
|
||||||
local j = math_max(i - 2, 0)
|
|
||||||
t[i] = rshift(j, 1)
|
|
||||||
end
|
|
||||||
tdecode_dist_nextrabits = t
|
|
||||||
end
|
|
||||||
local dist_val = disttable:read(bs)
|
|
||||||
local dist_base = tdecode_dist_base[dist_val]
|
|
||||||
local dist_nextrabits = tdecode_dist_nextrabits[dist_val]
|
|
||||||
local dist_extrabits = bs:read(dist_nextrabits)
|
|
||||||
local dist = dist_base + dist_extrabits
|
|
||||||
|
|
||||||
for _ = 1,len do
|
|
||||||
local pos = (outstate.window_pos - 1 - dist) % 32768 + 1 -- 32K
|
|
||||||
output(outstate, assert(outstate.window[pos], 'invalid distance'))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_block(bs, outstate)
|
|
||||||
local bfinal = bs:read(1)
|
|
||||||
local btype = bs:read(2)
|
|
||||||
|
|
||||||
local BTYPE_NO_COMPRESSION = 0
|
|
||||||
local BTYPE_FIXED_HUFFMAN = 1
|
|
||||||
local BTYPE_DYNAMIC_HUFFMAN = 2
|
|
||||||
local _BTYPE_RESERVED = 3
|
|
||||||
|
|
||||||
if btype == BTYPE_NO_COMPRESSION then
|
|
||||||
bs:read(bs:nbits_left_in_byte())
|
|
||||||
local len = bs:read(16)
|
|
||||||
local _nlen = noeof(bs:read(16))
|
|
||||||
|
|
||||||
for i=1,len do
|
|
||||||
local by = noeof(bs:read(8))
|
|
||||||
output(outstate, by)
|
|
||||||
end
|
|
||||||
elseif btype == BTYPE_FIXED_HUFFMAN or btype == BTYPE_DYNAMIC_HUFFMAN then
|
|
||||||
local littable, disttable
|
|
||||||
if btype == BTYPE_DYNAMIC_HUFFMAN then
|
|
||||||
littable, disttable = parse_huffmantables(bs)
|
|
||||||
else
|
|
||||||
littable = HuffmanTable {0,8, 144,9, 256,7, 280,8, 288,nil}
|
|
||||||
disttable = HuffmanTable {0,5, 32,nil}
|
|
||||||
end
|
|
||||||
|
|
||||||
repeat
|
|
||||||
local is_done = parse_compressed_item(
|
|
||||||
bs, outstate, littable, disttable)
|
|
||||||
until is_done
|
|
||||||
else
|
|
||||||
error('unrecognized compression type '..btype)
|
|
||||||
end
|
|
||||||
|
|
||||||
return bfinal ~= 0
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function inflate(t)
|
|
||||||
local bs = get_bitstream(t.input)
|
|
||||||
local outbs = get_obytestream(t.output)
|
|
||||||
local outstate = make_outstate(outbs)
|
|
||||||
|
|
||||||
repeat
|
|
||||||
local is_final = parse_block(bs, outstate)
|
|
||||||
until is_final
|
|
||||||
end
|
|
||||||
|
|
||||||
local function adler32(byte, crc)
|
|
||||||
local s1 = crc % 65536
|
|
||||||
local s2 = (crc - s1) / 65536
|
|
||||||
s1 = (s1 + byte) % 65521
|
|
||||||
s2 = (s2 + s1) % 65521
|
|
||||||
return s2*65536 + s1
|
|
||||||
end -- 65521 is the largest prime smaller than 2^16
|
|
||||||
|
|
||||||
local function inflate_zlib(t)
|
|
||||||
local bs = get_bitstream(t.input)
|
|
||||||
local outbs = get_obytestream(t.output)
|
|
||||||
local disable_crc = t.disable_crc
|
|
||||||
if disable_crc == nil then disable_crc = false end
|
|
||||||
|
|
||||||
local _window_size = parse_zlib_header(bs)
|
|
||||||
|
|
||||||
local data_adler32 = 1
|
|
||||||
|
|
||||||
inflate {
|
|
||||||
input=bs,
|
|
||||||
output = disable_crc and outbs or function(byte)
|
|
||||||
data_adler32 = adler32(byte, data_adler32)
|
|
||||||
outbs(byte)
|
|
||||||
end,
|
|
||||||
len = t.len,
|
|
||||||
}
|
|
||||||
|
|
||||||
bs:read(bs:nbits_left_in_byte())
|
|
||||||
|
|
||||||
local b3 = bs:read(8)
|
|
||||||
local b2 = bs:read(8)
|
|
||||||
local b1 = bs:read(8)
|
|
||||||
local b0 = bs:read(8)
|
|
||||||
local expected_adler32 = ((b3*256 + b2)*256 + b1)*256 + b0
|
|
||||||
|
|
||||||
if not disable_crc then
|
|
||||||
if data_adler32 ~= expected_adler32 then
|
|
||||||
error('invalid compressed data--crc error')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
|
||||||
inflate = inflate,
|
|
||||||
inflate_zlib = inflate_zlib,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
preload["clone"] = function(...)
|
|
||||||
--- Git clone in Lua, from the bottom up
|
|
||||||
--
|
|
||||||
-- http://stefan.saasen.me/articles/git-clone-in-haskell-from-the-bottom-up/#the_clone_process
|
|
||||||
-- https://github.com/creationix/lua-git
|
|
||||||
|
|
||||||
do -- metis loader
|
|
||||||
local modules = {
|
|
||||||
["metis.argparse"] = "src/metis/argparse.lua",
|
|
||||||
["metis.crypto.sha1"] = "src/metis/crypto/sha1.lua",
|
|
||||||
["metis.timer"] = "src/metis/timer.lua",
|
|
||||||
}
|
|
||||||
package.loaders[#package.loaders + 1] = function(name)
|
|
||||||
local path = modules[name]
|
|
||||||
if not path then return nil, "not a metis module" end
|
|
||||||
|
|
||||||
local local_path = "/.cache/metis/ae11085f261e5b506654162c80d21954c0d54e5e/" .. path
|
|
||||||
if not fs.exists(local_path) then
|
|
||||||
local url = "https://raw.githubusercontent.com/SquidDev-CC/metis/ae11085f261e5b506654162c80d21954c0d54e5e/" .. path
|
|
||||||
local request, err = http.get(url)
|
|
||||||
if not request then return nil, "Cannot download " .. url .. ": " .. err end
|
|
||||||
|
|
||||||
local out = fs.open(local_path, "w")
|
|
||||||
out.write(request.readAll())
|
|
||||||
out.close()
|
|
||||||
|
|
||||||
request.close()
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local fn, err = loadfile(local_path, nil, _ENV)
|
|
||||||
if fn then return fn, local_path else return nil, err end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local network = require "network"
|
|
||||||
local objects = require "objects"
|
|
||||||
|
|
||||||
local url, name = ...
|
|
||||||
if not url or url == "-h" or url == "--help" then error("clone.lua URL [name]", 0) end
|
|
||||||
|
|
||||||
if url:sub(-1) == "/" then url = url:sub(1, -2) end
|
|
||||||
name = name or fs.getName(url):gsub("%.git$", "")
|
|
||||||
|
|
||||||
local destination = shell.resolve(name)
|
|
||||||
if fs.exists(destination) then
|
|
||||||
error(("%q already exists"):format(name), 0)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function report(msg)
|
|
||||||
local last = ""
|
|
||||||
for line in msg:gmatch("[^\n]+") do last = line end
|
|
||||||
if replaceLine then
|
|
||||||
term.setCursorPos(1, select(2, term.getCursorPos()))
|
|
||||||
term.clearLine()
|
|
||||||
term.write(last)
|
|
||||||
else
|
|
||||||
print(last)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local head
|
|
||||||
do -- Request a list of all refs
|
|
||||||
report("Cloning from " .. url)
|
|
||||||
|
|
||||||
local handle = network.force_fetch(url .. "/info/refs?service=git-upload-pack")
|
|
||||||
local res = network.receive(handle)
|
|
||||||
|
|
||||||
local sha_ptrn = ("%x"):rep(40)
|
|
||||||
|
|
||||||
local caps = {}
|
|
||||||
local refs = {}
|
|
||||||
for i = 1, #res do
|
|
||||||
local line = res[i]
|
|
||||||
if line ~= false and line:sub(1, 1) ~= "#" then
|
|
||||||
local sha, name = line:match("(" .. sha_ptrn .. ") ([^%z\n]+)")
|
|
||||||
if sha and name then
|
|
||||||
refs[name] = sha
|
|
||||||
|
|
||||||
local capData = line:match("%z([^\n]+)\n")
|
|
||||||
if capData then
|
|
||||||
for cap in (capData .. " "):gmatch("%S+") do
|
|
||||||
local eq = cap:find("=")
|
|
||||||
if eq then
|
|
||||||
caps[cap:sub(1, eq - 1)] = cap:sub(eq + 1)
|
|
||||||
else
|
|
||||||
caps[cap] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
printError("Unexpected line: " .. line)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
head = refs['HEAD'] or refs['refs/heads/master'] or error("Cannot find master", 0)
|
|
||||||
|
|
||||||
if not caps['shallow'] then error("Server does not support shallow fetching", 0) end
|
|
||||||
|
|
||||||
-- TODO: Handle both. We don't even need the side-band really?
|
|
||||||
if not caps['side-band-64k'] then error("Server does not support side band", 0) end
|
|
||||||
end
|
|
||||||
|
|
||||||
do -- Now actually perform the clone
|
|
||||||
local handle = network.force_fetch(url .. "/git-upload-pack", {
|
|
||||||
network.pkt_linef("want %s side-band-64k shallow", head),
|
|
||||||
network.pkt_linef("deepen 1"),
|
|
||||||
network.flush_line,
|
|
||||||
network.pkt_linef("done"),
|
|
||||||
}, "application/x-git-upload-pack-request")
|
|
||||||
|
|
||||||
local pack, head = {}, nil
|
|
||||||
while true do
|
|
||||||
local line = network.read_pkt_line(handle)
|
|
||||||
if line == nil then break end
|
|
||||||
|
|
||||||
if line == false or line == "NAK\n" then
|
|
||||||
-- Skip
|
|
||||||
elseif line:byte(1) == 1 then
|
|
||||||
table.insert(pack, line:sub(2))
|
|
||||||
elseif line:byte(1) == 2 or line:byte(1) == 3 then
|
|
||||||
report(line:sub(2):gsub("\r", "\n"))
|
|
||||||
elseif line:find("^shallow ") then
|
|
||||||
head = line:sub(#("shallow ") + 1)
|
|
||||||
else
|
|
||||||
printError("Unknown line: " .. tostring(line))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
handle.close()
|
|
||||||
|
|
||||||
local stream = objects.reader(table.concat(pack))
|
|
||||||
local objs = objects.unpack(stream, function(x, n)
|
|
||||||
report(("Extracting %d/%d (%.2f%%)"):format(x, n, x/n*100))
|
|
||||||
end)
|
|
||||||
stream.close()
|
|
||||||
|
|
||||||
if not head then error("Cannot find HEAD commit", 0) end
|
|
||||||
|
|
||||||
for k, v in pairs(objects.build_commit(objs, head)) do
|
|
||||||
local out = fs.open(fs.combine(destination, fs.combine(k, "")), "wb")
|
|
||||||
out.write(v)
|
|
||||||
out.close()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
report(("Cloned to %q"):format(name))
|
|
||||||
print()
|
|
||||||
end
|
|
||||||
return preload["clone"](...)
|
|
109
bin/gist
109
bin/gist
|
@ -1,109 +0,0 @@
|
||||||
-- gist.lua - Gist client for ComputerCraft
|
|
||||||
-- Made by JackMacWindows for CraftOS-PC and CC: Tweaked
|
|
||||||
|
|
||||||
if not http then
|
|
||||||
printError("Gist requires http API")
|
|
||||||
if _G.config ~= nil then printError("Set http_enable to true in the CraftOS-PC configuration")
|
|
||||||
else printError("Set http_enable to true in ComputerCraft's configuration") end
|
|
||||||
return 2
|
|
||||||
end
|
|
||||||
|
|
||||||
local gist = require "cc.http.gist"
|
|
||||||
|
|
||||||
local args = { ... }
|
|
||||||
|
|
||||||
local function readFile(filename, files, isEditing)
|
|
||||||
if fs.isDir(shell.resolve(filename)) then
|
|
||||||
for _, v in ipairs(fs.list(shell.resolve(filename))) do if readFile(fs.combine(filename, v), files, isEditing) then return true end end
|
|
||||||
else
|
|
||||||
if files[fs.getName(filename)] then print("Cannot upload files with duplicate names.") return true end
|
|
||||||
local file = fs.open(shell.resolve(filename), "rb")
|
|
||||||
if file == nil then
|
|
||||||
if not isEditing then print("Could not read " .. filename .. ".") return true
|
|
||||||
else files[fs.getName(filename)] = textutils.json_null end
|
|
||||||
else
|
|
||||||
files[fs.getName(filename)] = file.readAll()
|
|
||||||
file.close()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function getFiles(isEditing)
|
|
||||||
local files = {}
|
|
||||||
local i = isEditing and 3 or 2
|
|
||||||
while args[i] ~= nil and args[i] ~= "--" do
|
|
||||||
if readFile(args[i], files, isEditing) then return nil end
|
|
||||||
i = i + 1
|
|
||||||
end
|
|
||||||
if args[i] == "--" then return files, table.concat({ table.unpack(args, i + 1) }, " ") end
|
|
||||||
return files
|
|
||||||
end
|
|
||||||
|
|
||||||
local function setTextColor(c) if term.isColor() then term.setTextColor(c) elseif c == colors.white or c == colors.yellow then term.setTextColor(colors.white) else term.setTextColor(colors.lightGray) end end
|
|
||||||
|
|
||||||
local helpstr = "Usages:\ngist put <files...> [-- description...]\ngist edit <id> <files...> [-- description]\ngist delete <id>\ngist get <id> <filename>\ngist run <id> [arguments...]\ngist info <id>"
|
|
||||||
|
|
||||||
if #args < 2 then
|
|
||||||
print(helpstr)
|
|
||||||
return 1
|
|
||||||
end
|
|
||||||
|
|
||||||
if args[1] == "get" then
|
|
||||||
if #args < 3 then print(helpstr) return 1 end
|
|
||||||
if args[3]:sub(#args[3]) == "/" or fs.isDir(shell.resolve(args[3])) then
|
|
||||||
fs.makeDir(shell.resolve(args[3]))
|
|
||||||
local files, err = gist.getAll(args[2], write)
|
|
||||||
if files == nil then printError(err) return 3 end
|
|
||||||
for k, v in pairs(files) do
|
|
||||||
local file = fs.open(shell.resolve(fs.combine(args[3], k)), "wb")
|
|
||||||
file.write(v)
|
|
||||||
file.close()
|
|
||||||
end
|
|
||||||
print("Downloaded all files to " .. shell.resolve(args[3]))
|
|
||||||
else
|
|
||||||
local data, err = gist.get(args[2], write)
|
|
||||||
if data == nil then printError(err) return 3 end
|
|
||||||
local file = fs.open(shell.resolve(args[3]), "wb")
|
|
||||||
file.write(data)
|
|
||||||
file.close()
|
|
||||||
print("Downloaded as " .. shell.resolve(args[3]))
|
|
||||||
end
|
|
||||||
elseif args[1] == "run" then
|
|
||||||
return gist.run(args[2], write, table.unpack(args, 3))
|
|
||||||
elseif args[1] == "put" then
|
|
||||||
local files, description = getFiles(false)
|
|
||||||
if files == nil then return end
|
|
||||||
local id, html_url = gist.put(files, description, nil, true)
|
|
||||||
if id ~= nil then print("Uploaded as " .. html_url .. "\nRun 'gist get " .. id .. "' to download anywhere")
|
|
||||||
else printError(html_url) return 3 end
|
|
||||||
elseif args[1] == "info" then
|
|
||||||
local tab, err = gist.info(args[2], write)
|
|
||||||
if tab == nil then printError(err) return 3 end
|
|
||||||
setTextColor(colors.yellow)
|
|
||||||
write("Description: ")
|
|
||||||
setTextColor(colors.white)
|
|
||||||
print(tab.description)
|
|
||||||
setTextColor(colors.yellow)
|
|
||||||
write("Author: ")
|
|
||||||
setTextColor(colors.white)
|
|
||||||
print(tab.author)
|
|
||||||
setTextColor(colors.yellow)
|
|
||||||
write("Revisions: ")
|
|
||||||
setTextColor(colors.white)
|
|
||||||
print(tab.revisionCount)
|
|
||||||
setTextColor(colors.yellow)
|
|
||||||
print("Files in this Gist:")
|
|
||||||
setTextColor(colors.white)
|
|
||||||
textutils.tabulate(tab.files)
|
|
||||||
elseif args[1] == "edit" then
|
|
||||||
if #args < 3 then print(helpstr) return 1 end
|
|
||||||
local files, description = getFiles(true)
|
|
||||||
if files == nil then return 2 end
|
|
||||||
if not description then description = gist.info(args[2], write).description end
|
|
||||||
local id, html_url = gist.put(files, description, args[2], true)
|
|
||||||
if id then print("Uploaded as " .. html_url .. "\nRun 'gist get " .. args[2] .. "' to download anywhere")
|
|
||||||
else printError(html_url) return 3 end
|
|
||||||
elseif args[1] == "delete" then
|
|
||||||
local ok, err = gist.delete(args[2], true)
|
|
||||||
if ok then print("The requested Gist has been deleted.") else printError(err) return 3 end
|
|
||||||
else print(helpstr) return 1 end
|
|
94
bin/gps
94
bin/gps
|
@ -1,94 +0,0 @@
|
||||||
local function printUsage()
|
|
||||||
local programName = "gps"
|
|
||||||
print("Usages:")
|
|
||||||
print(programName .. " host")
|
|
||||||
print(programName .. " host <x> <y> <z>")
|
|
||||||
print(programName .. " locate")
|
|
||||||
end
|
|
||||||
|
|
||||||
local tArgs = { ... }
|
|
||||||
if #tArgs < 1 then
|
|
||||||
printUsage()
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local sCommand = tArgs[1]
|
|
||||||
if sCommand == "locate" then
|
|
||||||
-- "gps locate"
|
|
||||||
-- Just locate this computer (this will print the results)
|
|
||||||
gps.locate(2, true)
|
|
||||||
|
|
||||||
elseif sCommand == "host" then
|
|
||||||
-- "gps host"
|
|
||||||
-- Act as a GPS host
|
|
||||||
if pocket then
|
|
||||||
print("GPS Hosts must be stationary")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Find a modem
|
|
||||||
local sModemSide = nil
|
|
||||||
for _, sSide in ipairs(rs.getSides()) do
|
|
||||||
if peripheral.getType(sSide) == "modem" and peripheral.call(sSide, "isWireless") then
|
|
||||||
sModemSide = sSide
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if sModemSide == nil then
|
|
||||||
print("No wireless modems found. 1 required.")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Determine position
|
|
||||||
local x, y, z
|
|
||||||
if #tArgs >= 4 then
|
|
||||||
-- Position is manually specified
|
|
||||||
x = tonumber(tArgs[2])
|
|
||||||
y = tonumber(tArgs[3])
|
|
||||||
z = tonumber(tArgs[4])
|
|
||||||
if x == nil or y == nil or z == nil then
|
|
||||||
printUsage()
|
|
||||||
return
|
|
||||||
end
|
|
||||||
print("Position is " .. x .. "," .. y .. "," .. z)
|
|
||||||
else
|
|
||||||
-- Position is to be determined using locate
|
|
||||||
x, y, z = gps.locate(2, true)
|
|
||||||
if x == nil then
|
|
||||||
print("Run \"gps host <x> <y> <z>\" to set position manually")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Open a channel
|
|
||||||
local modem = peripheral.wrap(sModemSide)
|
|
||||||
print("Opening channel on modem " .. sModemSide)
|
|
||||||
modem.open(gps.CHANNEL_GPS)
|
|
||||||
|
|
||||||
-- Serve requests indefinately
|
|
||||||
local nServed = 0
|
|
||||||
while true do
|
|
||||||
local e, p1, p2, p3, p4, p5 = os.pullEvent("modem_message")
|
|
||||||
if e == "modem_message" then
|
|
||||||
-- We received a message from a modem
|
|
||||||
local sSide, sChannel, sReplyChannel, sMessage, nDistance = p1, p2, p3, p4, p5
|
|
||||||
if sSide == sModemSide and sChannel == gps.CHANNEL_GPS and sMessage == "PING" and nDistance then
|
|
||||||
-- We received a ping message on the GPS channel, send a response
|
|
||||||
modem.transmit(sReplyChannel, gps.CHANNEL_GPS, { x, y, z })
|
|
||||||
|
|
||||||
-- Print the number of requests handled
|
|
||||||
nServed = nServed + 1
|
|
||||||
if nServed > 1 then
|
|
||||||
local _, y = term.getCursorPos()
|
|
||||||
term.setCursorPos(1, y - 1)
|
|
||||||
end
|
|
||||||
print(nServed .. " GPS requests served")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- "gps somethingelse"
|
|
||||||
-- Error
|
|
||||||
printUsage()
|
|
||||||
end
|
|
18
bin/hostname
18
bin/hostname
|
@ -1,18 +0,0 @@
|
||||||
local tArgs = { ... }
|
|
||||||
if #tArgs < 1 then
|
|
||||||
kerneldraw.printAppInfo("net", kernel.getHostname())
|
|
||||||
else
|
|
||||||
if tArgs[1] == "--set" then
|
|
||||||
if #tArgs >= 2 then
|
|
||||||
local hostname = tArgs[2]
|
|
||||||
for i,v in ipairs(tArgs) do
|
|
||||||
if not (i == 1 or i == 2) then
|
|
||||||
hostname = hostname .. tArgs[i]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
kernel.setHostname(hostname)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
kerneldraw.printAppInfo("hostname","Arguments not specified")
|
|
||||||
end
|
|
||||||
end
|
|
37
bin/list
37
bin/list
|
@ -1,37 +0,0 @@
|
||||||
local tArgs = { ... }
|
|
||||||
|
|
||||||
-- Get all the files in the directory
|
|
||||||
local sDir = shell.dir()
|
|
||||||
if tArgs[1] ~= nil then
|
|
||||||
sDir = shell.resolve(tArgs[1])
|
|
||||||
end
|
|
||||||
|
|
||||||
if not fs.isDir(sDir) then
|
|
||||||
printError("Not a directory")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Sort into dirs/files, and calculate column count
|
|
||||||
local tAll = fs.list(sDir)
|
|
||||||
local tFiles = {}
|
|
||||||
local tDirs = {}
|
|
||||||
|
|
||||||
local bShowHidden = settings.get("list.show_hidden")
|
|
||||||
for _, sItem in pairs(tAll) do
|
|
||||||
if bShowHidden or string.sub(sItem, 1, 1) ~= "." then
|
|
||||||
local sPath = fs.combine(sDir, sItem)
|
|
||||||
if fs.isDir(sPath) then
|
|
||||||
table.insert(tDirs, sItem)
|
|
||||||
else
|
|
||||||
table.insert(tFiles, sItem)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
table.sort(tDirs)
|
|
||||||
table.sort(tFiles)
|
|
||||||
|
|
||||||
if term.isColour() then
|
|
||||||
textutils.pagedTabulate(colors.green, tDirs, colors.white, tFiles)
|
|
||||||
else
|
|
||||||
textutils.pagedTabulate(colors.lightGray, tDirs, colors.white, tFiles)
|
|
||||||
end
|
|
102
bin/lsh
102
bin/lsh
|
@ -1,102 +0,0 @@
|
||||||
local bRunning = true
|
|
||||||
local tCommandHistory = {}
|
|
||||||
local tEnv = {
|
|
||||||
["exit"] = function()
|
|
||||||
bRunning = false
|
|
||||||
end,
|
|
||||||
["_echo"] = function( ... )
|
|
||||||
return ...
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
if not security.getSU() then
|
|
||||||
exception.throw("RestrictedOpsException")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
setmetatable( tEnv, { __index = _ENV } )
|
|
||||||
|
|
||||||
local label = os.getComputerLabel() or os.getComputerID()
|
|
||||||
|
|
||||||
print( "lsh - The Lua interpreter shell" )
|
|
||||||
print("Call exit() to quit.")
|
|
||||||
term.setTextColour( colours.white )
|
|
||||||
|
|
||||||
while bRunning do
|
|
||||||
if security.getActiveUserStatus() then
|
|
||||||
term.setTextColour( colours.lime )
|
|
||||||
else
|
|
||||||
term.setTextColour( colours.orange )
|
|
||||||
end
|
|
||||||
write( _activeUser )
|
|
||||||
term.setTextColour( colours.lightGrey )
|
|
||||||
write( "@" )
|
|
||||||
term.setTextColour( colours.lightBlue )
|
|
||||||
write( label )
|
|
||||||
term.setTextColour( colours.lightGrey )
|
|
||||||
write( "/" )
|
|
||||||
term.setTextColour( colours.lightBlue )
|
|
||||||
write( shell.dir() )
|
|
||||||
if security.getActiveUserStatus() then
|
|
||||||
term.setTextColour( colours.lime )
|
|
||||||
else
|
|
||||||
term.setTextColour( colours.orange )
|
|
||||||
end
|
|
||||||
write( " % " )
|
|
||||||
|
|
||||||
term.setTextColour( colours.white )
|
|
||||||
|
|
||||||
local s = read( nil, tCommandHistory, function( sLine )
|
|
||||||
local nStartPos = string.find( sLine, "[a-zA-Z0-9_%.]+$" )
|
|
||||||
if nStartPos then
|
|
||||||
sLine = string.sub( sLine, nStartPos )
|
|
||||||
end
|
|
||||||
if #sLine > 0 then
|
|
||||||
return textutils.complete( sLine, tEnv )
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end )
|
|
||||||
term.setTextColour( colours.lightGrey )
|
|
||||||
table.insert( tCommandHistory, s )
|
|
||||||
|
|
||||||
local nForcePrint = 0
|
|
||||||
local func, e = load( s, "lua", "t", tEnv )
|
|
||||||
local func2, e2 = load( "return _echo("..s..");", "lua", "t", tEnv )
|
|
||||||
if not func then
|
|
||||||
if func2 then
|
|
||||||
func = func2
|
|
||||||
e = nil
|
|
||||||
nForcePrint = 1
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if func2 then
|
|
||||||
func = func2
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if func then
|
|
||||||
local tResults = { pcall( func ) }
|
|
||||||
if tResults[1] then
|
|
||||||
local n = 1
|
|
||||||
while (tResults[n + 1] ~= nil) or (n <= nForcePrint) do
|
|
||||||
local value = tResults[ n + 1 ]
|
|
||||||
if type( value ) == "table" then
|
|
||||||
local ok, serialised = pcall( textutils.serialise, value )
|
|
||||||
if ok then
|
|
||||||
print( serialised )
|
|
||||||
else
|
|
||||||
print( tostring( value ) )
|
|
||||||
end
|
|
||||||
else
|
|
||||||
print( tostring( value ) )
|
|
||||||
end
|
|
||||||
n = n + 1
|
|
||||||
end
|
|
||||||
else
|
|
||||||
printError( tResults[2] )
|
|
||||||
end
|
|
||||||
else
|
|
||||||
printError( e )
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
7
bin/man
7
bin/man
|
@ -1,7 +0,0 @@
|
||||||
local tArgs = {...}
|
|
||||||
|
|
||||||
if #tArgs < 1 then
|
|
||||||
kerneldraw.printAppInfo("man", "type 'ls system/man-pages' or 'manpages'")
|
|
||||||
else
|
|
||||||
kerneldraw.printAppInfo("man", man.findManual(tArgs[1]))
|
|
||||||
end
|
|
13
bin/manedit
13
bin/manedit
|
@ -1,13 +0,0 @@
|
||||||
local tArgs = {...}
|
|
||||||
|
|
||||||
if not security.getSU() then
|
|
||||||
exception.throw("RestrictedOpsException")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if #tArgs < 1 then
|
|
||||||
kerneldraw.printAppInfo("manedit", "filename not specified")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
shell.run("/bin/nano /etc/manuals/"..tArgs[1])
|
|
|
@ -1 +0,0 @@
|
||||||
shell.run("/bin/nano /etc/manuals")
|
|
18
bin/mkdir
18
bin/mkdir
|
@ -1,18 +0,0 @@
|
||||||
local tArgs = { ... }
|
|
||||||
|
|
||||||
if #tArgs < 1 then
|
|
||||||
local programName = "mkdir"
|
|
||||||
print("Usage: " .. programName .. " <paths>")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, v in ipairs(tArgs) do
|
|
||||||
local sNewDir = shell.resolve(v)
|
|
||||||
if fs.exists(sNewDir) and not fs.isDir(sNewDir) then
|
|
||||||
printError(v .. ": Destination exists")
|
|
||||||
elseif fs.isReadOnly(sNewDir) then
|
|
||||||
printError(v .. ": Access denied")
|
|
||||||
else
|
|
||||||
fs.makeDir(sNewDir)
|
|
||||||
end
|
|
||||||
end
|
|
95
bin/monitor
95
bin/monitor
|
@ -1,95 +0,0 @@
|
||||||
local function printUsage()
|
|
||||||
local programName = "monitor"
|
|
||||||
print("Usage:")
|
|
||||||
print(" " .. programName .. " <name> <program> <arguments>")
|
|
||||||
print(" " .. programName .. " scale <name> <scale>")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local tArgs = { ... }
|
|
||||||
if #tArgs < 2 or tArgs[1] == "scale" and #tArgs < 3 then
|
|
||||||
printUsage()
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if tArgs[1] == "scale" then
|
|
||||||
local sName = tArgs[2]
|
|
||||||
if peripheral.getType(sName) ~= "monitor" then
|
|
||||||
print("No monitor named " .. sName)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local nRes = tonumber(tArgs[3])
|
|
||||||
if nRes == nil or nRes < 0.5 or nRes > 5 then
|
|
||||||
print("Invalid scale: " .. tArgs[3])
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
peripheral.call(sName, "setTextScale", nRes)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local sName = tArgs[1]
|
|
||||||
if peripheral.getType(sName) ~= "monitor" then
|
|
||||||
print("No monitor named " .. sName)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local sProgram = tArgs[2]
|
|
||||||
|
|
||||||
local sPath = shell.resolveProgram(sProgram)
|
|
||||||
if sPath == nil then
|
|
||||||
print("No such program: " .. sProgram)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
print("Running " .. sProgram .. " on monitor " .. sName)
|
|
||||||
|
|
||||||
local monitor = peripheral.wrap(sName)
|
|
||||||
local previousTerm = term.redirect(monitor)
|
|
||||||
|
|
||||||
local co = coroutine.create(function()
|
|
||||||
(shell.execute or shell.run)(sProgram, table.unpack(tArgs, 3))
|
|
||||||
end)
|
|
||||||
|
|
||||||
local function resume(...)
|
|
||||||
local ok, param = coroutine.resume(co, ...)
|
|
||||||
if not ok then
|
|
||||||
printError(param)
|
|
||||||
end
|
|
||||||
return param
|
|
||||||
end
|
|
||||||
|
|
||||||
local timers = {}
|
|
||||||
|
|
||||||
local ok, param = pcall(function()
|
|
||||||
local sFilter = resume()
|
|
||||||
while coroutine.status(co) ~= "dead" do
|
|
||||||
local tEvent = table.pack(os.pullEventRaw())
|
|
||||||
if sFilter == nil or tEvent[1] == sFilter or tEvent[1] == "terminate" then
|
|
||||||
sFilter = resume(table.unpack(tEvent, 1, tEvent.n))
|
|
||||||
end
|
|
||||||
if coroutine.status(co) ~= "dead" and (sFilter == nil or sFilter == "mouse_click") then
|
|
||||||
if tEvent[1] == "monitor_touch" and tEvent[2] == sName then
|
|
||||||
timers[os.startTimer(0.1)] = { tEvent[3], tEvent[4] }
|
|
||||||
sFilter = resume("mouse_click", 1, table.unpack(tEvent, 3, tEvent.n))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if coroutine.status(co) ~= "dead" and (sFilter == nil or sFilter == "term_resize") then
|
|
||||||
if tEvent[1] == "monitor_resize" and tEvent[2] == sName then
|
|
||||||
sFilter = resume("term_resize")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if coroutine.status(co) ~= "dead" and (sFilter == nil or sFilter == "mouse_up") then
|
|
||||||
if tEvent[1] == "timer" and timers[tEvent[2]] then
|
|
||||||
sFilter = resume("mouse_up", 1, table.unpack(timers[tEvent[2]], 1, 2))
|
|
||||||
timers[tEvent[2]] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
term.redirect(previousTerm)
|
|
||||||
if not ok then
|
|
||||||
printError(param)
|
|
||||||
end
|
|
23
bin/mount
23
bin/mount
|
@ -1,23 +0,0 @@
|
||||||
if mounter == nil then error("Mounting directories is not supported in vanilla mode.") end
|
|
||||||
local args = { ... }
|
|
||||||
|
|
||||||
if args[2] ~= nil then
|
|
||||||
local ro = nil
|
|
||||||
if args[3] == "readOnly" or args[3] == "true" then ro = true
|
|
||||||
elseif args[3] == "false" then ro = false end
|
|
||||||
if config.get("showMountPrompt") then print("A prompt will appear asking to confirm mounting. Press Allow to continue mounting.") end
|
|
||||||
if not mounter.mount(args[1], args[2], ro) then printError("Could not mount") end
|
|
||||||
elseif args[1] == "--help" then
|
|
||||||
term.setTextColor(colors.red)
|
|
||||||
print("Usage: mount <name> <path> [readOnly]")
|
|
||||||
print(" mount --help")
|
|
||||||
print(" mount")
|
|
||||||
term.setTextColor(colors.white)
|
|
||||||
else
|
|
||||||
local mounts = mounter.list()
|
|
||||||
print("/ on computer/" .. os.getComputerID())
|
|
||||||
for k,v in pairs(mounts) do
|
|
||||||
write("/" .. k .. " on " .. (#v == 1 and v[1] or "(\n " .. table.concat(v, ",\n ") .. "\n)"))
|
|
||||||
if mounter.isReadOnly(k) then print(" (read-only)") else print() end
|
|
||||||
end
|
|
||||||
end
|
|
47
bin/mv
47
bin/mv
|
@ -1,47 +0,0 @@
|
||||||
local tArgs = { ... }
|
|
||||||
if #tArgs < 2 then
|
|
||||||
local programName = "mv"
|
|
||||||
print("Usage: " .. programName .. " <source> <destination>")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local sSource = shell.resolve(tArgs[1])
|
|
||||||
local sDest = shell.resolve(tArgs[2])
|
|
||||||
local tFiles = fs.find(sSource)
|
|
||||||
|
|
||||||
local function sanity_checks(source, dest)
|
|
||||||
if fs.exists(dest) then
|
|
||||||
printError("Destination exists")
|
|
||||||
return false
|
|
||||||
elseif fs.isReadOnly(dest) then
|
|
||||||
printError("Destination is read-only")
|
|
||||||
return false
|
|
||||||
elseif fs.isDriveRoot(source) then
|
|
||||||
printError("Cannot move mount /" .. source)
|
|
||||||
return false
|
|
||||||
elseif fs.isReadOnly(source) then
|
|
||||||
printError("Cannot move read-only file /" .. source)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
if #tFiles > 0 then
|
|
||||||
for _, sFile in ipairs(tFiles) do
|
|
||||||
if fs.isDir(sDest) then
|
|
||||||
local dest = fs.combine(sDest, fs.getName(sFile))
|
|
||||||
if sanity_checks(sFile, dest) then
|
|
||||||
fs.move(sFile, dest)
|
|
||||||
end
|
|
||||||
elseif #tFiles == 1 then
|
|
||||||
if sanity_checks(sFile, sDest) then
|
|
||||||
fs.move(sFile, sDest)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
printError("Cannot overwrite file multiple times")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
printError("No matching files")
|
|
||||||
end
|
|
772
bin/nano
772
bin/nano
|
@ -1,772 +0,0 @@
|
||||||
-- Get file to edit
|
|
||||||
local tArgs = { ... }
|
|
||||||
if #tArgs == 0 then
|
|
||||||
print( "Usage: nano <path>" )
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Error checking
|
|
||||||
local sPath = shell.resolve( tArgs[1] )
|
|
||||||
local bReadOnly = fs.isReadOnly( sPath )
|
|
||||||
if fs.exists( sPath ) and fs.isDir( sPath ) then
|
|
||||||
print( "Cannot edit a directory." )
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if bReadOnly and not security.getSU() then
|
|
||||||
-- prevent users from seeing unauthorized code
|
|
||||||
-- they should only be able to see their own files and ones in /var/log
|
|
||||||
exception.throw("SecurityException", sPath)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local x,y = 1,1
|
|
||||||
local w,h = term.getSize()
|
|
||||||
local scrollX, scrollY = 0,0
|
|
||||||
|
|
||||||
local tLines = {}
|
|
||||||
local bRunning = true
|
|
||||||
|
|
||||||
-- Colours
|
|
||||||
local highlightColour, keywordColour, commentColour, textColour, bgColour
|
|
||||||
if term.isColour() then
|
|
||||||
bgColour = colours.black
|
|
||||||
textColour = colours.white
|
|
||||||
highlightColour = colours.yellow
|
|
||||||
keywordColour = colours.yellow
|
|
||||||
commentColour = colours.green
|
|
||||||
stringColour = colours.red
|
|
||||||
else
|
|
||||||
bgColour = colours.black
|
|
||||||
textColour = colours.white
|
|
||||||
highlightColour = colours.white
|
|
||||||
keywordColour = colours.white
|
|
||||||
commentColour = colours.white
|
|
||||||
stringColour = colours.white
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Menus
|
|
||||||
local bMenu = false
|
|
||||||
local nMenuItem = 1
|
|
||||||
local tMenuItems = {}
|
|
||||||
if not bReadOnly then
|
|
||||||
table.insert( tMenuItems, "Save" )
|
|
||||||
end
|
|
||||||
if shell.openTab then
|
|
||||||
table.insert( tMenuItems, "Run" )
|
|
||||||
end
|
|
||||||
if peripheral.find( "printer" ) then
|
|
||||||
table.insert( tMenuItems, "Print" )
|
|
||||||
end
|
|
||||||
table.insert( tMenuItems, "Exit" )
|
|
||||||
|
|
||||||
local sStatus = "Press Ctrl to access menu"
|
|
||||||
if string.len( sStatus ) > w - 5 then
|
|
||||||
sStatus = "Press Ctrl for menu"
|
|
||||||
end
|
|
||||||
|
|
||||||
local function load( _sPath )
|
|
||||||
tLines = {}
|
|
||||||
if fs.exists( _sPath ) then
|
|
||||||
local file = io.open( _sPath, "r" )
|
|
||||||
local sLine = file:read()
|
|
||||||
while sLine do
|
|
||||||
table.insert( tLines, sLine )
|
|
||||||
sLine = file:read()
|
|
||||||
end
|
|
||||||
file:close()
|
|
||||||
end
|
|
||||||
|
|
||||||
if #tLines == 0 then
|
|
||||||
table.insert( tLines, "" )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function save( _sPath )
|
|
||||||
-- Create intervening folder
|
|
||||||
local sDir = _sPath:sub(1, _sPath:len() - fs.getName(_sPath):len() )
|
|
||||||
if not fs.exists( sDir ) then
|
|
||||||
fs.makeDir( sDir )
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Save
|
|
||||||
local file = nil
|
|
||||||
local function innerSave()
|
|
||||||
file = fs.open( _sPath, "w" )
|
|
||||||
if file then
|
|
||||||
for n, sLine in ipairs( tLines ) do
|
|
||||||
file.write( sLine .. "\n" )
|
|
||||||
end
|
|
||||||
else
|
|
||||||
error( "Failed to open ".._sPath )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local ok, err = pcall( innerSave )
|
|
||||||
if file then
|
|
||||||
file.close()
|
|
||||||
end
|
|
||||||
return ok, err
|
|
||||||
end
|
|
||||||
|
|
||||||
local tKeywords = {
|
|
||||||
["and"] = true,
|
|
||||||
["break"] = true,
|
|
||||||
["do"] = true,
|
|
||||||
["else"] = true,
|
|
||||||
["elseif"] = true,
|
|
||||||
["end"] = true,
|
|
||||||
["false"] = true,
|
|
||||||
["for"] = true,
|
|
||||||
["function"] = true,
|
|
||||||
["if"] = true,
|
|
||||||
["in"] = true,
|
|
||||||
["local"] = true,
|
|
||||||
["nil"] = true,
|
|
||||||
["not"] = true,
|
|
||||||
["or"] = true,
|
|
||||||
["repeat"] = true,
|
|
||||||
["return"] = true,
|
|
||||||
["then"] = true,
|
|
||||||
["true"] = true,
|
|
||||||
["until"]= true,
|
|
||||||
["while"] = true,
|
|
||||||
}
|
|
||||||
|
|
||||||
local function tryWrite( sLine, regex, colour )
|
|
||||||
local match = string.match( sLine, regex )
|
|
||||||
if match then
|
|
||||||
if type(colour) == "number" then
|
|
||||||
term.setTextColour( colour )
|
|
||||||
else
|
|
||||||
term.setTextColour( colour(match) )
|
|
||||||
end
|
|
||||||
term.write( match )
|
|
||||||
term.setTextColour( textColour )
|
|
||||||
return string.sub( sLine, string.len(match) + 1 )
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local function writeHighlighted( sLine )
|
|
||||||
while string.len(sLine) > 0 do
|
|
||||||
sLine =
|
|
||||||
tryWrite( sLine, "^%-%-%[%[.-%]%]", commentColour ) or
|
|
||||||
tryWrite( sLine, "^%-%-.*", commentColour ) or
|
|
||||||
tryWrite( sLine, "^\".-[^\\]\"", stringColour ) or
|
|
||||||
tryWrite( sLine, "^\'.-[^\\]\'", stringColour ) or
|
|
||||||
tryWrite( sLine, "^%[%[.-%]%]", stringColour ) or
|
|
||||||
tryWrite( sLine, "^[%w_]+", function( match )
|
|
||||||
if tKeywords[ match ] then
|
|
||||||
return keywordColour
|
|
||||||
end
|
|
||||||
return textColour
|
|
||||||
end ) or
|
|
||||||
tryWrite( sLine, "^[^%w_]", textColour )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local tCompletions
|
|
||||||
local nCompletion
|
|
||||||
|
|
||||||
local tCompleteEnv = _ENV
|
|
||||||
local function complete( sLine )
|
|
||||||
local nStartPos = string.find( sLine, "[a-zA-Z0-9_%.]+$" )
|
|
||||||
if nStartPos then
|
|
||||||
sLine = string.sub( sLine, nStartPos )
|
|
||||||
end
|
|
||||||
if #sLine > 0 then
|
|
||||||
return textutils.complete( sLine, tCompleteEnv )
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local function recomplete()
|
|
||||||
local sLine = tLines[y]
|
|
||||||
if not bMenu and not bReadOnly and x == string.len(sLine) + 1 then
|
|
||||||
tCompletions = complete( sLine )
|
|
||||||
if tCompletions and #tCompletions > 0 then
|
|
||||||
nCompletion = 1
|
|
||||||
else
|
|
||||||
nCompletion = nil
|
|
||||||
end
|
|
||||||
else
|
|
||||||
tCompletions = nil
|
|
||||||
nCompletion = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function writeCompletion( sLine )
|
|
||||||
if nCompletion then
|
|
||||||
local sCompletion = tCompletions[ nCompletion ]
|
|
||||||
term.setTextColor( colours.white )
|
|
||||||
term.setBackgroundColor( colours.grey )
|
|
||||||
term.write( sCompletion )
|
|
||||||
term.setTextColor( textColour )
|
|
||||||
term.setBackgroundColor( bgColour )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function redrawText()
|
|
||||||
local cursorX, cursorY = x, y
|
|
||||||
for y=1,h-1 do
|
|
||||||
term.setCursorPos( 1 - scrollX, y )
|
|
||||||
term.clearLine()
|
|
||||||
|
|
||||||
local sLine = tLines[ y + scrollY ]
|
|
||||||
if sLine ~= nil then
|
|
||||||
writeHighlighted( sLine )
|
|
||||||
if cursorY == y and cursorX == #sLine + 1 then
|
|
||||||
writeCompletion()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
term.setCursorPos( x - scrollX, y - scrollY )
|
|
||||||
end
|
|
||||||
|
|
||||||
local function redrawLine(_nY)
|
|
||||||
local sLine = tLines[_nY]
|
|
||||||
if sLine then
|
|
||||||
term.setCursorPos( 1 - scrollX, _nY - scrollY )
|
|
||||||
term.clearLine()
|
|
||||||
writeHighlighted( sLine )
|
|
||||||
if _nY == y and x == #sLine + 1 then
|
|
||||||
writeCompletion()
|
|
||||||
end
|
|
||||||
term.setCursorPos( x - scrollX, _nY - scrollY )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function redrawMenu()
|
|
||||||
-- Clear line
|
|
||||||
term.setCursorPos( 1, h )
|
|
||||||
term.clearLine()
|
|
||||||
|
|
||||||
-- Draw line numbers
|
|
||||||
term.setCursorPos( w - string.len( "Ln "..y ) + 1, h )
|
|
||||||
term.setTextColour( highlightColour )
|
|
||||||
term.write( "Ln " )
|
|
||||||
term.setTextColour( textColour )
|
|
||||||
term.write( y )
|
|
||||||
|
|
||||||
term.setCursorPos( 1, h )
|
|
||||||
if bMenu then
|
|
||||||
-- Draw menu
|
|
||||||
term.setTextColour( textColour )
|
|
||||||
for nItem,sItem in pairs( tMenuItems ) do
|
|
||||||
if nItem == nMenuItem then
|
|
||||||
term.setTextColour( highlightColour )
|
|
||||||
term.write( "[" )
|
|
||||||
term.setTextColour( textColour )
|
|
||||||
term.write( sItem )
|
|
||||||
term.setTextColour( highlightColour )
|
|
||||||
term.write( "]" )
|
|
||||||
term.setTextColour( textColour )
|
|
||||||
else
|
|
||||||
term.write( " "..sItem.." " )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- Draw status
|
|
||||||
term.setTextColour( highlightColour )
|
|
||||||
term.write( sStatus )
|
|
||||||
term.setTextColour( textColour )
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Reset cursor
|
|
||||||
term.setCursorPos( x - scrollX, y - scrollY )
|
|
||||||
end
|
|
||||||
|
|
||||||
local tMenuFuncs = {
|
|
||||||
Save = function()
|
|
||||||
if bReadOnly then
|
|
||||||
sStatus = "Access denied"
|
|
||||||
else
|
|
||||||
local ok, err = save( sPath )
|
|
||||||
if ok then
|
|
||||||
sStatus="Saved to "..sPath
|
|
||||||
else
|
|
||||||
sStatus="Error saving to "..sPath
|
|
||||||
end
|
|
||||||
end
|
|
||||||
redrawMenu()
|
|
||||||
end,
|
|
||||||
Print = function()
|
|
||||||
local printer = peripheral.find( "printer" )
|
|
||||||
if not printer then
|
|
||||||
sStatus = "No printer attached"
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local nPage = 0
|
|
||||||
local sName = fs.getName( sPath )
|
|
||||||
if printer.getInkLevel() < 1 then
|
|
||||||
sStatus = "Printer out of ink"
|
|
||||||
return
|
|
||||||
elseif printer.getPaperLevel() < 1 then
|
|
||||||
sStatus = "Printer out of paper"
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local screenTerminal = term.current()
|
|
||||||
local printerTerminal = {
|
|
||||||
getCursorPos = printer.getCursorPos,
|
|
||||||
setCursorPos = printer.setCursorPos,
|
|
||||||
getSize = printer.getPageSize,
|
|
||||||
write = printer.write,
|
|
||||||
}
|
|
||||||
printerTerminal.scroll = function()
|
|
||||||
if nPage == 1 then
|
|
||||||
printer.setPageTitle( sName.." (page "..nPage..")" )
|
|
||||||
end
|
|
||||||
|
|
||||||
while not printer.newPage() do
|
|
||||||
if printer.getInkLevel() < 1 then
|
|
||||||
sStatus = "Printer out of ink, please refill"
|
|
||||||
elseif printer.getPaperLevel() < 1 then
|
|
||||||
sStatus = "Printer out of paper, please refill"
|
|
||||||
else
|
|
||||||
sStatus = "Printer output tray full, please empty"
|
|
||||||
end
|
|
||||||
|
|
||||||
term.redirect( screenTerminal )
|
|
||||||
redrawMenu()
|
|
||||||
term.redirect( printerTerminal )
|
|
||||||
|
|
||||||
local timer = os.startTimer(0.5)
|
|
||||||
sleep(0.5)
|
|
||||||
end
|
|
||||||
|
|
||||||
nPage = nPage + 1
|
|
||||||
if nPage == 1 then
|
|
||||||
printer.setPageTitle( sName )
|
|
||||||
else
|
|
||||||
printer.setPageTitle( sName.." (page "..nPage..")" )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
bMenu = false
|
|
||||||
term.redirect( printerTerminal )
|
|
||||||
local ok, error = pcall( function()
|
|
||||||
term.scroll()
|
|
||||||
for n, sLine in ipairs( tLines ) do
|
|
||||||
print( sLine )
|
|
||||||
end
|
|
||||||
end )
|
|
||||||
term.redirect( screenTerminal )
|
|
||||||
if not ok then
|
|
||||||
print( error )
|
|
||||||
end
|
|
||||||
|
|
||||||
while not printer.endPage() do
|
|
||||||
sStatus = "Printer output tray full, please empty"
|
|
||||||
redrawMenu()
|
|
||||||
sleep( 0.5 )
|
|
||||||
end
|
|
||||||
bMenu = true
|
|
||||||
|
|
||||||
if nPage > 1 then
|
|
||||||
sStatus = "Printed "..nPage.." Pages"
|
|
||||||
else
|
|
||||||
sStatus = "Printed 1 Page"
|
|
||||||
end
|
|
||||||
redrawMenu()
|
|
||||||
end,
|
|
||||||
Exit = function()
|
|
||||||
bRunning = false
|
|
||||||
end,
|
|
||||||
Run = function()
|
|
||||||
local sTempPath = "/.temp"
|
|
||||||
local ok, err = save( sTempPath )
|
|
||||||
if ok then
|
|
||||||
local nTask = shell.openTab( sTempPath )
|
|
||||||
if nTask then
|
|
||||||
shell.switchTab( nTask )
|
|
||||||
else
|
|
||||||
sStatus="Error starting Task"
|
|
||||||
end
|
|
||||||
fs.delete( sTempPath )
|
|
||||||
else
|
|
||||||
sStatus="Error saving to "..sTempPath
|
|
||||||
end
|
|
||||||
redrawMenu()
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
local function doMenuItem( _n )
|
|
||||||
tMenuFuncs[tMenuItems[_n]]()
|
|
||||||
if bMenu then
|
|
||||||
bMenu = false
|
|
||||||
term.setCursorBlink( true )
|
|
||||||
end
|
|
||||||
redrawMenu()
|
|
||||||
end
|
|
||||||
|
|
||||||
local function setCursor( newX, newY )
|
|
||||||
local oldX, oldY = x, y
|
|
||||||
x, y = newX, newY
|
|
||||||
local screenX = x - scrollX
|
|
||||||
local screenY = y - scrollY
|
|
||||||
|
|
||||||
local bRedraw = false
|
|
||||||
if screenX < 1 then
|
|
||||||
scrollX = x - 1
|
|
||||||
screenX = 1
|
|
||||||
bRedraw = true
|
|
||||||
elseif screenX > w then
|
|
||||||
scrollX = x - w
|
|
||||||
screenX = w
|
|
||||||
bRedraw = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if screenY < 1 then
|
|
||||||
scrollY = y - 1
|
|
||||||
screenY = 1
|
|
||||||
bRedraw = true
|
|
||||||
elseif screenY > h-1 then
|
|
||||||
scrollY = y - (h-1)
|
|
||||||
screenY = h-1
|
|
||||||
bRedraw = true
|
|
||||||
end
|
|
||||||
|
|
||||||
recomplete()
|
|
||||||
if bRedraw then
|
|
||||||
redrawText()
|
|
||||||
elseif y ~= oldY then
|
|
||||||
redrawLine( oldY )
|
|
||||||
redrawLine( y )
|
|
||||||
else
|
|
||||||
redrawLine( y )
|
|
||||||
end
|
|
||||||
term.setCursorPos( screenX, screenY )
|
|
||||||
|
|
||||||
redrawMenu()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Actual program functionality begins
|
|
||||||
load(sPath)
|
|
||||||
|
|
||||||
term.setBackgroundColour( bgColour )
|
|
||||||
term.clear()
|
|
||||||
term.setCursorPos(x,y)
|
|
||||||
term.setCursorBlink( true )
|
|
||||||
|
|
||||||
recomplete()
|
|
||||||
redrawText()
|
|
||||||
redrawMenu()
|
|
||||||
|
|
||||||
local function acceptCompletion()
|
|
||||||
if nCompletion then
|
|
||||||
-- Find the common prefix of all the other suggestions which start with the same letter as the current one
|
|
||||||
local sCompletion = tCompletions[ nCompletion ]
|
|
||||||
local sFirstLetter = string.sub( sCompletion, 1, 1 )
|
|
||||||
local sCommonPrefix = sCompletion
|
|
||||||
for n=1,#tCompletions do
|
|
||||||
local sResult = tCompletions[n]
|
|
||||||
if n ~= nCompletion and string.find( sResult, sFirstLetter, 1, true ) == 1 then
|
|
||||||
while #sCommonPrefix > 1 do
|
|
||||||
if string.find( sResult, sCommonPrefix, 1, true ) == 1 then
|
|
||||||
break
|
|
||||||
else
|
|
||||||
sCommonPrefix = string.sub( sCommonPrefix, 1, #sCommonPrefix - 1 )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Append this string
|
|
||||||
tLines[y] = tLines[y] .. sCommonPrefix
|
|
||||||
setCursor( x + string.len( sCommonPrefix ), y )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Handle input
|
|
||||||
while bRunning do
|
|
||||||
local sEvent, param, param2, param3 = os.pullEvent()
|
|
||||||
if sEvent == "key" then
|
|
||||||
local oldX, oldY = x, y
|
|
||||||
if param == keys.up then
|
|
||||||
-- Up
|
|
||||||
if not bMenu then
|
|
||||||
if nCompletion then
|
|
||||||
-- Cycle completions
|
|
||||||
nCompletion = nCompletion - 1
|
|
||||||
if nCompletion < 1 then
|
|
||||||
nCompletion = #tCompletions
|
|
||||||
end
|
|
||||||
redrawLine(y)
|
|
||||||
|
|
||||||
elseif y > 1 then
|
|
||||||
-- Move cursor up
|
|
||||||
setCursor(
|
|
||||||
math.min( x, string.len( tLines[y - 1] ) + 1 ),
|
|
||||||
y - 1
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif param == keys.down then
|
|
||||||
-- Down
|
|
||||||
if not bMenu then
|
|
||||||
-- Move cursor down
|
|
||||||
if nCompletion then
|
|
||||||
-- Cycle completions
|
|
||||||
nCompletion = nCompletion + 1
|
|
||||||
if nCompletion > #tCompletions then
|
|
||||||
nCompletion = 1
|
|
||||||
end
|
|
||||||
redrawLine(y)
|
|
||||||
|
|
||||||
elseif y < #tLines then
|
|
||||||
-- Move cursor down
|
|
||||||
setCursor(
|
|
||||||
math.min( x, string.len( tLines[y + 1] ) + 1 ),
|
|
||||||
y + 1
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif param == keys.tab then
|
|
||||||
-- Tab
|
|
||||||
if not bMenu and not bReadOnly then
|
|
||||||
if nCompletion and x == string.len(tLines[y]) + 1 then
|
|
||||||
-- Accept autocomplete
|
|
||||||
acceptCompletion()
|
|
||||||
else
|
|
||||||
-- Indent line
|
|
||||||
local sLine = tLines[y]
|
|
||||||
tLines[y] = string.sub(sLine,1,x-1) .. " " .. string.sub(sLine,x)
|
|
||||||
setCursor( x + 2, y )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif param == keys.pageUp then
|
|
||||||
-- Page Up
|
|
||||||
if not bMenu then
|
|
||||||
-- Move up a page
|
|
||||||
local newY
|
|
||||||
if y - (h - 1) >= 1 then
|
|
||||||
newY = y - (h - 1)
|
|
||||||
else
|
|
||||||
newY = 1
|
|
||||||
end
|
|
||||||
setCursor(
|
|
||||||
math.min( x, string.len( tLines[newY] ) + 1 ),
|
|
||||||
newY
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif param == keys.pageDown then
|
|
||||||
-- Page Down
|
|
||||||
if not bMenu then
|
|
||||||
-- Move down a page
|
|
||||||
local newY
|
|
||||||
if y + (h - 1) <= #tLines then
|
|
||||||
newY = y + (h - 1)
|
|
||||||
else
|
|
||||||
newY = #tLines
|
|
||||||
end
|
|
||||||
local newX = math.min( x, string.len( tLines[newY] ) + 1 )
|
|
||||||
setCursor( newX, newY )
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif param == keys.home then
|
|
||||||
-- Home
|
|
||||||
if not bMenu then
|
|
||||||
-- Move cursor to the beginning
|
|
||||||
if x > 1 then
|
|
||||||
setCursor(1,y)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif param == keys["end"] then
|
|
||||||
-- End
|
|
||||||
if not bMenu then
|
|
||||||
-- Move cursor to the end
|
|
||||||
local nLimit = string.len( tLines[y] ) + 1
|
|
||||||
if x < nLimit then
|
|
||||||
setCursor( nLimit, y )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif param == keys.left then
|
|
||||||
-- Left
|
|
||||||
if not bMenu then
|
|
||||||
if x > 1 then
|
|
||||||
-- Move cursor left
|
|
||||||
setCursor( x - 1, y )
|
|
||||||
elseif x==1 and y>1 then
|
|
||||||
setCursor( string.len( tLines[y-1] ) + 1, y - 1 )
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- Move menu left
|
|
||||||
nMenuItem = nMenuItem - 1
|
|
||||||
if nMenuItem < 1 then
|
|
||||||
nMenuItem = #tMenuItems
|
|
||||||
end
|
|
||||||
redrawMenu()
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif param == keys.right then
|
|
||||||
-- Right
|
|
||||||
if not bMenu then
|
|
||||||
local nLimit = string.len( tLines[y] ) + 1
|
|
||||||
if x < nLimit then
|
|
||||||
-- Move cursor right
|
|
||||||
setCursor( x + 1, y )
|
|
||||||
elseif nCompletion and x == string.len(tLines[y]) + 1 then
|
|
||||||
-- Accept autocomplete
|
|
||||||
acceptCompletion()
|
|
||||||
elseif x==nLimit and y<#tLines then
|
|
||||||
-- Go to next line
|
|
||||||
setCursor( 1, y + 1 )
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- Move menu right
|
|
||||||
nMenuItem = nMenuItem + 1
|
|
||||||
if nMenuItem > #tMenuItems then
|
|
||||||
nMenuItem = 1
|
|
||||||
end
|
|
||||||
redrawMenu()
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif param == keys.delete then
|
|
||||||
-- Delete
|
|
||||||
if not bMenu and not bReadOnly then
|
|
||||||
local nLimit = string.len( tLines[y] ) + 1
|
|
||||||
if x < nLimit then
|
|
||||||
local sLine = tLines[y]
|
|
||||||
tLines[y] = string.sub(sLine,1,x-1) .. string.sub(sLine,x+1)
|
|
||||||
recomplete()
|
|
||||||
redrawLine(y)
|
|
||||||
elseif y<#tLines then
|
|
||||||
tLines[y] = tLines[y] .. tLines[y+1]
|
|
||||||
table.remove( tLines, y+1 )
|
|
||||||
recomplete()
|
|
||||||
redrawText()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif param == keys.backspace then
|
|
||||||
-- Backspace
|
|
||||||
if not bMenu and not bReadOnly then
|
|
||||||
if x > 1 then
|
|
||||||
-- Remove character
|
|
||||||
local sLine = tLines[y]
|
|
||||||
tLines[y] = string.sub(sLine,1,x-2) .. string.sub(sLine,x)
|
|
||||||
setCursor( x - 1, y )
|
|
||||||
elseif y > 1 then
|
|
||||||
-- Remove newline
|
|
||||||
local sPrevLen = string.len( tLines[y-1] )
|
|
||||||
tLines[y-1] = tLines[y-1] .. tLines[y]
|
|
||||||
table.remove( tLines, y )
|
|
||||||
setCursor( sPrevLen + 1, y - 1 )
|
|
||||||
redrawText()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif param == keys.enter then
|
|
||||||
-- Enter
|
|
||||||
if not bMenu and not bReadOnly then
|
|
||||||
-- Newline
|
|
||||||
local sLine = tLines[y]
|
|
||||||
local _,spaces=string.find(sLine,"^[ ]+")
|
|
||||||
if not spaces then
|
|
||||||
spaces=0
|
|
||||||
end
|
|
||||||
tLines[y] = string.sub(sLine,1,x-1)
|
|
||||||
table.insert( tLines, y+1, string.rep(' ',spaces)..string.sub(sLine,x) )
|
|
||||||
setCursor( spaces + 1, y + 1 )
|
|
||||||
redrawText()
|
|
||||||
|
|
||||||
elseif bMenu then
|
|
||||||
-- Menu selection
|
|
||||||
doMenuItem( nMenuItem )
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif param == keys.leftCtrl or param == keys.rightCtrl or param == keys.rightAlt then
|
|
||||||
-- Menu toggle
|
|
||||||
bMenu = not bMenu
|
|
||||||
if bMenu then
|
|
||||||
term.setCursorBlink( false )
|
|
||||||
else
|
|
||||||
term.setCursorBlink( true )
|
|
||||||
end
|
|
||||||
redrawMenu()
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif sEvent == "char" then
|
|
||||||
if not bMenu and not bReadOnly then
|
|
||||||
-- Input text
|
|
||||||
local sLine = tLines[y]
|
|
||||||
tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)
|
|
||||||
setCursor( x + 1, y )
|
|
||||||
|
|
||||||
elseif bMenu then
|
|
||||||
-- Select menu items
|
|
||||||
for n,sMenuItem in ipairs( tMenuItems ) do
|
|
||||||
if string.lower(string.sub(sMenuItem,1,1)) == string.lower(param) then
|
|
||||||
doMenuItem( n )
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif sEvent == "paste" then
|
|
||||||
if not bMenu and not bReadOnly then
|
|
||||||
-- Input text
|
|
||||||
local sLine = tLines[y]
|
|
||||||
tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)
|
|
||||||
setCursor( x + string.len( param ), y )
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif sEvent == "mouse_click" then
|
|
||||||
if not bMenu then
|
|
||||||
if param == 1 then
|
|
||||||
-- Left click
|
|
||||||
local cx,cy = param2, param3
|
|
||||||
if cy < h then
|
|
||||||
local newY = math.min( math.max( scrollY + cy, 1 ), #tLines )
|
|
||||||
local newX = math.min( math.max( scrollX + cx, 1 ), string.len( tLines[newY] ) + 1 )
|
|
||||||
setCursor( newX, newY )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif sEvent == "mouse_scroll" then
|
|
||||||
if not bMenu then
|
|
||||||
if param == -1 then
|
|
||||||
-- Scroll up
|
|
||||||
if scrollY > 0 then
|
|
||||||
-- Move cursor up
|
|
||||||
scrollY = scrollY - 1
|
|
||||||
redrawText()
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif param == 1 then
|
|
||||||
-- Scroll down
|
|
||||||
local nMaxScroll = #tLines - (h-1)
|
|
||||||
if scrollY < nMaxScroll then
|
|
||||||
-- Move cursor down
|
|
||||||
scrollY = scrollY + 1
|
|
||||||
redrawText()
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif sEvent == "term_resize" then
|
|
||||||
w,h = term.getSize()
|
|
||||||
setCursor( x, y )
|
|
||||||
redrawMenu()
|
|
||||||
redrawText()
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Cleanup
|
|
||||||
term.clear()
|
|
||||||
term.setCursorBlink( false )
|
|
||||||
term.setCursorPos( 1, 1 )
|
|
|
@ -1,4 +0,0 @@
|
||||||
-- testing
|
|
||||||
net.openModems()
|
|
||||||
net.setWorkstationStatus(true)
|
|
||||||
print(tostring(net.getWorkstationStatus()))
|
|
50
bin/nmap
50
bin/nmap
|
@ -1,50 +0,0 @@
|
||||||
--Initializing IP address generator
|
|
||||||
|
|
||||||
local tArgs = {...}
|
|
||||||
if #tArgs < 4 then
|
|
||||||
kerneldraw.printAppInfo("nmap", "No IP address specified")
|
|
||||||
else
|
|
||||||
kerneldraw.printAppSuccess("nmap", "Scanning for specified IP")
|
|
||||||
end
|
|
||||||
|
|
||||||
if #tArgs == 5 then
|
|
||||||
kerneldraw.printAppSuccess("nmap", "Specified DNS record")
|
|
||||||
end
|
|
||||||
|
|
||||||
local ip, node
|
|
||||||
|
|
||||||
if #tArgs < 4 then
|
|
||||||
local x = tostring(math.random(0, 255))
|
|
||||||
local y = tostring(math.random(0, 255))
|
|
||||||
local z = tostring(math.random(0, 255))
|
|
||||||
local r = tostring(math.random(0, 255))
|
|
||||||
ip = x.."."..y.."."..z.."."..r
|
|
||||||
elseif #tArgs >= 4 then
|
|
||||||
ip = tArgs[1].."."..tArgs[2].."."..tArgs[3].."."..tArgs[4]
|
|
||||||
end
|
|
||||||
|
|
||||||
if not fs.exists("/network") or not fs.isDir("/network") then
|
|
||||||
fs.makeDir("/network")
|
|
||||||
end
|
|
||||||
|
|
||||||
--node = "/network/"..ip
|
|
||||||
|
|
||||||
kerneldraw.printAppInfo("nmap", "Found "..ip)
|
|
||||||
|
|
||||||
if #tArgs == 5 then
|
|
||||||
kerneldraw.printAppSuccess("nmap", "Assigned DNS record "..tArgs[5])
|
|
||||||
node = "/network/"..tArgs[5]
|
|
||||||
else
|
|
||||||
kerneldraw.printAppWarning("nmap", "No DNS record found, defaulting to IP")
|
|
||||||
node = "/network/"..ip
|
|
||||||
end
|
|
||||||
|
|
||||||
if fs.exists(node) and fs.isDir(node) then
|
|
||||||
kerneldraw.printAppInfo("nmap", ip.." already known")
|
|
||||||
else
|
|
||||||
fs.makeDir(node)
|
|
||||||
fs.makeDir(node.."/sys")
|
|
||||||
fs.makeDir(node.."/home")
|
|
||||||
fs.makeDir(node.."/bin")
|
|
||||||
kerneldraw.printAppSuccess("nmap", ip.." added to network")
|
|
||||||
end
|
|
50
bin/passwd
50
bin/passwd
|
@ -1,50 +0,0 @@
|
||||||
local tArgs = {...}
|
|
||||||
|
|
||||||
if #tArgs < 1 then
|
|
||||||
kerneldraw.printAppInfo("passwd", "Specify a user")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if not security.getSU() then
|
|
||||||
exception.throw("RestrictedOpsException")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if fs.exists("/etc/passwd/"..tArgs[1]..".dat") and not fs.isDir("/etc/passwd/"..tArgs[1]..".dat") then
|
|
||||||
local passwd = nil
|
|
||||||
local passwd_reenter = nil
|
|
||||||
passwd = kernel.secureInputReturn("New Password: ")
|
|
||||||
os.pullEvent = function()
|
|
||||||
local eventData = { os.pullEventRaw( _sFilter ) }
|
|
||||||
if eventData[1] == "terminate" then
|
|
||||||
error( "Terminated", 0 )
|
|
||||||
end
|
|
||||||
return unpack( eventData )
|
|
||||||
end
|
|
||||||
if passwd == "" or passwd == nil then
|
|
||||||
kerneldraw.printAppInfo("passwd","Invalid password")
|
|
||||||
return
|
|
||||||
else
|
|
||||||
passwd_reenter = kernel.secureInput("Reenter: ", passwd)
|
|
||||||
os.pullEvent = function()
|
|
||||||
local eventData = { os.pullEventRaw( _sFilter ) }
|
|
||||||
if eventData[1] == "terminate" then
|
|
||||||
error( "Terminated", 0 )
|
|
||||||
end
|
|
||||||
return unpack( eventData )
|
|
||||||
end
|
|
||||||
if not passwd == passwd_reenter then
|
|
||||||
kerneldraw.printAppInfo("passwd","Passwords don't match")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if security.passbyte(tArgs[1], passwd) then
|
|
||||||
kerneldraw.printAppSuccess("passwd", "Password of user "..tArgs[1].." changed")
|
|
||||||
log.writeSecurity("Password of user "..tArgs[1].." changed")
|
|
||||||
else
|
|
||||||
kerneldraw.printAppInfo("passwd", "Failed to change password")
|
|
||||||
log.writeSecurity("Failed to change password")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
kerneldraw.printAppInfo("security", "User " .. tArgs[1] .. " does not exist")
|
|
||||||
end
|
|
160
bin/pastebin
160
bin/pastebin
|
@ -1,160 +0,0 @@
|
||||||
local function printUsage()
|
|
||||||
local programName = "pastebin"
|
|
||||||
print("Usages:")
|
|
||||||
print(programName .. " put <filename>")
|
|
||||||
print(programName .. " get <code> <filename>")
|
|
||||||
print(programName .. " run <code> <arguments>")
|
|
||||||
end
|
|
||||||
|
|
||||||
local tArgs = { ... }
|
|
||||||
if #tArgs < 2 then
|
|
||||||
printUsage()
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if not http then
|
|
||||||
printError("Pastebin requires the http API")
|
|
||||||
printError("Set http.enabled to true in CC: Tweaked's config")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Attempts to guess the pastebin ID from the given code or URL
|
|
||||||
local function extractId(paste)
|
|
||||||
local patterns = {
|
|
||||||
"^([%a%d]+)$",
|
|
||||||
"^https?://pastebin.com/([%a%d]+)$",
|
|
||||||
"^pastebin.com/([%a%d]+)$",
|
|
||||||
"^https?://pastebin.com/raw/([%a%d]+)$",
|
|
||||||
"^pastebin.com/raw/([%a%d]+)$",
|
|
||||||
}
|
|
||||||
|
|
||||||
for i = 1, #patterns do
|
|
||||||
local code = paste:match(patterns[i])
|
|
||||||
if code then return code end
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get(url)
|
|
||||||
local paste = extractId(url)
|
|
||||||
if not paste then
|
|
||||||
io.stderr:write("Invalid pastebin code.\n")
|
|
||||||
io.write("The code is the ID at the end of the pastebin.com URL.\n")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
write("Connecting to pastebin.com... ")
|
|
||||||
-- Add a cache buster so that spam protection is re-checked
|
|
||||||
local cacheBuster = ("%x"):format(math.random(0, 2 ^ 30))
|
|
||||||
local response, err = http.get(
|
|
||||||
"https://pastebin.com/raw/" .. textutils.urlEncode(paste) .. "?cb=" .. cacheBuster
|
|
||||||
)
|
|
||||||
|
|
||||||
if response then
|
|
||||||
-- If spam protection is activated, we get redirected to /paste with Content-Type: text/html
|
|
||||||
local headers = response.getResponseHeaders()
|
|
||||||
if not headers["Content-Type"] or not headers["Content-Type"]:find("^text/plain") then
|
|
||||||
io.stderr:write("Failed.\n")
|
|
||||||
print("Pastebin blocked the download due to spam protection. Please complete the captcha in a web browser: https://pastebin.com/" .. textutils.urlEncode(paste))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
print("Success.")
|
|
||||||
|
|
||||||
local sResponse = response.readAll()
|
|
||||||
response.close()
|
|
||||||
return sResponse
|
|
||||||
else
|
|
||||||
io.stderr:write("Failed.\n")
|
|
||||||
print(err)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local sCommand = tArgs[1]
|
|
||||||
if sCommand == "put" then
|
|
||||||
-- Upload a file to pastebin.com
|
|
||||||
-- Determine file to upload
|
|
||||||
local sFile = tArgs[2]
|
|
||||||
local sPath = shell.resolve(sFile)
|
|
||||||
if not fs.exists(sPath) or fs.isDir(sPath) then
|
|
||||||
print("No such file")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Read in the file
|
|
||||||
local sName = fs.getName(sPath)
|
|
||||||
local file = fs.open(sPath, "r")
|
|
||||||
local sText = file.readAll()
|
|
||||||
file.close()
|
|
||||||
|
|
||||||
-- POST the contents to pastebin
|
|
||||||
write("Connecting to pastebin.com... ")
|
|
||||||
local key = "0ec2eb25b6166c0c27a394ae118ad829"
|
|
||||||
local response = http.post(
|
|
||||||
"https://pastebin.com/api/api_post.php",
|
|
||||||
"api_option=paste&" ..
|
|
||||||
"api_dev_key=" .. key .. "&" ..
|
|
||||||
"api_paste_format=lua&" ..
|
|
||||||
"api_paste_name=" .. textutils.urlEncode(sName) .. "&" ..
|
|
||||||
"api_paste_code=" .. textutils.urlEncode(sText)
|
|
||||||
)
|
|
||||||
|
|
||||||
if response then
|
|
||||||
print("Success.")
|
|
||||||
|
|
||||||
local sResponse = response.readAll()
|
|
||||||
response.close()
|
|
||||||
|
|
||||||
local sCode = string.match(sResponse, "[^/]+$")
|
|
||||||
print("Uploaded as " .. sResponse)
|
|
||||||
print("Run \"pastebin get " .. sCode .. "\" to download anywhere")
|
|
||||||
|
|
||||||
else
|
|
||||||
print("Failed.")
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif sCommand == "get" then
|
|
||||||
-- Download a file from pastebin.com
|
|
||||||
if #tArgs < 3 then
|
|
||||||
printUsage()
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Determine file to download
|
|
||||||
local sCode = tArgs[2]
|
|
||||||
local sFile = tArgs[3]
|
|
||||||
local sPath = shell.resolve(sFile)
|
|
||||||
if fs.exists(sPath) then
|
|
||||||
print("File already exists")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- GET the contents from pastebin
|
|
||||||
local res = get(sCode)
|
|
||||||
if res then
|
|
||||||
local file = fs.open(sPath, "w")
|
|
||||||
file.write(res)
|
|
||||||
file.close()
|
|
||||||
|
|
||||||
print("Downloaded as " .. sFile)
|
|
||||||
end
|
|
||||||
elseif sCommand == "run" then
|
|
||||||
local sCode = tArgs[2]
|
|
||||||
|
|
||||||
local res = get(sCode)
|
|
||||||
if res then
|
|
||||||
local func, err = load(res, sCode, "t", _ENV)
|
|
||||||
if not func then
|
|
||||||
printError(err)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local success, msg = pcall(func, select(3, ...))
|
|
||||||
if not success then
|
|
||||||
printError(msg)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
printUsage()
|
|
||||||
return
|
|
||||||
end
|
|
|
@ -1,10 +0,0 @@
|
||||||
local tPeripherals = peripheral.getNames()
|
|
||||||
print("Attached Peripherals:")
|
|
||||||
if #tPeripherals > 0 then
|
|
||||||
for n = 1, #tPeripherals do
|
|
||||||
local sPeripheral = tPeripherals[n]
|
|
||||||
print(sPeripheral .. " (" .. table.concat({ peripheral.getType(sPeripheral) }, ", ") .. ")")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
print("None")
|
|
||||||
end
|
|
118
bin/redstone
118
bin/redstone
|
@ -1,118 +0,0 @@
|
||||||
local tArgs = { ... }
|
|
||||||
|
|
||||||
local function printUsage()
|
|
||||||
local programName = "redstone"
|
|
||||||
print("Usages:")
|
|
||||||
print(programName .. " probe")
|
|
||||||
print(programName .. " set <side> <value>")
|
|
||||||
print(programName .. " set <side> <color> <value>")
|
|
||||||
print(programName .. " pulse <side> <count> <period>")
|
|
||||||
end
|
|
||||||
|
|
||||||
local sCommand = tArgs[1]
|
|
||||||
if sCommand == "probe" then
|
|
||||||
-- "redstone probe"
|
|
||||||
-- Regular input
|
|
||||||
print("Redstone inputs: ")
|
|
||||||
|
|
||||||
local count = 0
|
|
||||||
local bundledCount = 0
|
|
||||||
for _, sSide in ipairs(redstone.getSides()) do
|
|
||||||
if redstone.getBundledInput(sSide) > 0 then
|
|
||||||
bundledCount = bundledCount + 1
|
|
||||||
end
|
|
||||||
if redstone.getInput(sSide) then
|
|
||||||
if count > 0 then
|
|
||||||
io.write(", ")
|
|
||||||
end
|
|
||||||
io.write(sSide)
|
|
||||||
count = count + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if count > 0 then
|
|
||||||
print(".")
|
|
||||||
else
|
|
||||||
print("None.")
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Bundled input
|
|
||||||
if bundledCount > 0 then
|
|
||||||
print()
|
|
||||||
print("Bundled inputs:")
|
|
||||||
for _, sSide in ipairs(redstone.getSides()) do
|
|
||||||
local nInput = redstone.getBundledInput(sSide)
|
|
||||||
if nInput ~= 0 then
|
|
||||||
write(sSide .. ": ")
|
|
||||||
local count = 0
|
|
||||||
for sColour, nColour in pairs(colors) do
|
|
||||||
if type(nColour) == "number" and colors.test(nInput, nColour) then
|
|
||||||
if count > 0 then
|
|
||||||
write(", ")
|
|
||||||
end
|
|
||||||
if term.isColour() then
|
|
||||||
term.setTextColour(nColour)
|
|
||||||
end
|
|
||||||
write(sColour)
|
|
||||||
if term.isColour() then
|
|
||||||
term.setTextColour(colours.white)
|
|
||||||
end
|
|
||||||
count = count + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
print(".")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif sCommand == "pulse" then
|
|
||||||
-- "redstone pulse"
|
|
||||||
local sSide = tArgs[2]
|
|
||||||
local nCount = tonumber(tArgs[3]) or 1
|
|
||||||
local nPeriod = tonumber(tArgs[4]) or 0.5
|
|
||||||
for _ = 1, nCount do
|
|
||||||
redstone.setOutput(sSide, true)
|
|
||||||
sleep(nPeriod / 2)
|
|
||||||
redstone.setOutput(sSide, false)
|
|
||||||
sleep(nPeriod / 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif sCommand == "set" then
|
|
||||||
-- "redstone set"
|
|
||||||
local sSide = tArgs[2]
|
|
||||||
if #tArgs > 3 then
|
|
||||||
-- Bundled cable output
|
|
||||||
local sColour = tArgs[3]
|
|
||||||
local nColour = colors[sColour] or colours[sColour]
|
|
||||||
if type(nColour) ~= "number" then
|
|
||||||
printError("No such color")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local sValue = tArgs[4]
|
|
||||||
if sValue == "true" then
|
|
||||||
rs.setBundledOutput(sSide, colors.combine(rs.getBundledOutput(sSide), nColour))
|
|
||||||
elseif sValue == "false" then
|
|
||||||
rs.setBundledOutput(sSide, colors.subtract(rs.getBundledOutput(sSide), nColour))
|
|
||||||
else
|
|
||||||
print("Value must be boolean")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- Regular output
|
|
||||||
local sValue = tArgs[3]
|
|
||||||
local nValue = tonumber(sValue)
|
|
||||||
if sValue == "true" then
|
|
||||||
rs.setOutput(sSide, true)
|
|
||||||
elseif sValue == "false" then
|
|
||||||
rs.setOutput(sSide, false)
|
|
||||||
elseif nValue and nValue >= 0 and nValue <= 15 then
|
|
||||||
rs.setAnalogOutput(sSide, nValue)
|
|
||||||
else
|
|
||||||
print("Value must be boolean or 0-15")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
|
||||||
-- Something else
|
|
||||||
printUsage()
|
|
||||||
|
|
||||||
end
|
|
30
bin/rm
30
bin/rm
|
@ -1,30 +0,0 @@
|
||||||
local args = table.pack(...)
|
|
||||||
|
|
||||||
if args.n < 1 then
|
|
||||||
local programName = "rm"
|
|
||||||
print("Usage: " .. programName .. " <paths>")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
for i = 1, args.n do
|
|
||||||
local files = fs.find(shell.resolve(args[i]))
|
|
||||||
if #files > 0 then
|
|
||||||
for _, file in ipairs(files) do
|
|
||||||
if fs.isReadOnly(file) then
|
|
||||||
printError("Cannot delete read-only file /" .. file)
|
|
||||||
elseif fs.isDriveRoot(file) then
|
|
||||||
printError("Cannot delete mount /" .. file)
|
|
||||||
if fs.isDir(file) then
|
|
||||||
print("To delete its contents run rm /" .. fs.combine(file, "*"))
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local ok, err = pcall(fs.delete, file)
|
|
||||||
if not ok then
|
|
||||||
printError((err:gsub("^pcall: ", "")))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
printError(args[i] .. ": No matching files")
|
|
||||||
end
|
|
||||||
end
|
|
375
bin/screenfetch
375
bin/screenfetch
|
@ -1,375 +0,0 @@
|
||||||
if os.pullEvent ~= nil then
|
|
||||||
|
|
||||||
local ccart, ccart_fg, ccart_bg, ccart_adv_fg, ccart_adv_bg, ccart_width
|
|
||||||
|
|
||||||
if ... == "--small" then
|
|
||||||
|
|
||||||
ccart = ([[\159\143\143\143\143\143\143\143\144
|
|
||||||
\150\136\144 \150
|
|
||||||
\150\130 \131 \150
|
|
||||||
\150 \150
|
|
||||||
\150 \150
|
|
||||||
\150 \140\150
|
|
||||||
]]):gsub("\\130", "\130"):gsub("\\131", "\131"):gsub("\\136", "\136"):gsub("\\140", "\140"):gsub("\\143", "\143"):gsub("\\144", "\144"):gsub("\\150", "\149"):gsub("\\159", "\159")
|
|
||||||
|
|
||||||
ccart_fg = [[ffffffff7
|
|
||||||
f00fffff7
|
|
||||||
f0f0ffff7
|
|
||||||
ffffffff8
|
|
||||||
ffffffff8
|
|
||||||
f888888f8
|
|
||||||
fffffffff]]
|
|
||||||
|
|
||||||
ccart_bg = [[77777777f
|
|
||||||
7ffffffff
|
|
||||||
7ffffffff
|
|
||||||
8ffffffff
|
|
||||||
8ffffffff
|
|
||||||
88888888f
|
|
||||||
fffffffff]]
|
|
||||||
|
|
||||||
ccart_adv_fg = [[ffffffff4
|
|
||||||
f00fffff4
|
|
||||||
f0f0ffff4
|
|
||||||
ffffffff4
|
|
||||||
ffffffff4
|
|
||||||
f444444d4
|
|
||||||
fffffffff]]
|
|
||||||
|
|
||||||
ccart_adv_bg = [[44444444f
|
|
||||||
4ffffffff
|
|
||||||
4ffffffff
|
|
||||||
4ffffffff
|
|
||||||
4ffffffff
|
|
||||||
44444444f
|
|
||||||
fffffffff]]
|
|
||||||
|
|
||||||
ccart_width = 10
|
|
||||||
|
|
||||||
else
|
|
||||||
ccart = [[------------------------
|
|
||||||
| |
|
|
||||||
| -------------------- |
|
|
||||||
| | \ | |
|
|
||||||
| | / __ | |
|
|
||||||
| | | |
|
|
||||||
| | | |
|
|
||||||
| | | |
|
|
||||||
| | | |
|
|
||||||
| | | |
|
|
||||||
| | | |
|
|
||||||
| -------------------- |
|
|
||||||
| |
|
|
||||||
| [=] |
|
|
||||||
| |
|
|
||||||
------------------------]]
|
|
||||||
|
|
||||||
ccart_fg = [[ffffffffffffffffffffffff
|
|
||||||
f7777777777777777777777f
|
|
||||||
f7ffffffffffffffffffff7f
|
|
||||||
f7ff0fffffffffffffffff7f
|
|
||||||
f7ff0f00ffffffffffffff7f
|
|
||||||
f7ffffffffffffffffffff7f
|
|
||||||
f7ffffffffffffffffffff7f
|
|
||||||
f7ffffffffffffffffffff7f
|
|
||||||
f8ffffffffffffffffffff8f
|
|
||||||
f8ffffffffffffffffffff8f
|
|
||||||
f8ffffffffffffffffffff8f
|
|
||||||
f8ffffffffffffffffffff8f
|
|
||||||
f8888888888888888888888f
|
|
||||||
f888888888888888888fff8f
|
|
||||||
f8888888888888888888888f
|
|
||||||
ffffffffffffffffffffffff]]
|
|
||||||
|
|
||||||
ccart_bg = [[ffffffffffffffffffffffff
|
|
||||||
f7777777777777777777777f
|
|
||||||
f7ffffffffffffffffffff7f
|
|
||||||
f7ffffffffffffffffffff7f
|
|
||||||
f7ffffffffffffffffffff7f
|
|
||||||
f7ffffffffffffffffffff7f
|
|
||||||
f7ffffffffffffffffffff7f
|
|
||||||
f7ffffffffffffffffffff7f
|
|
||||||
f8ffffffffffffffffffff8f
|
|
||||||
f8ffffffffffffffffffff8f
|
|
||||||
f8ffffffffffffffffffff8f
|
|
||||||
f8ffffffffffffffffffff8f
|
|
||||||
f8888888888888888888888f
|
|
||||||
f888888888888888888fff8f
|
|
||||||
f8888888888888888888888f
|
|
||||||
ffffffffffffffffffffffff]]
|
|
||||||
|
|
||||||
ccart_adv_fg = [[ffffffffffffffffffffffff
|
|
||||||
f4444444444444444444444f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ff0fffffffffffffffff4f
|
|
||||||
f4ff0f00ffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4444444444444444444444f
|
|
||||||
f444444444444444444ddd4f
|
|
||||||
f4444444444444444444444f
|
|
||||||
ffffffffffffffffffffffff]]
|
|
||||||
|
|
||||||
ccart_adv_bg = [[ffffffffffffffffffffffff
|
|
||||||
f4444444444444444444444f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4444444444444444444444f
|
|
||||||
f444444444444444444ddd4f
|
|
||||||
f4444444444444444444444f
|
|
||||||
ffffffffffffffffffffffff]]
|
|
||||||
|
|
||||||
ccart_width = 25
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
local function fg(l) if term.isColor() then return string.rep("4", l) else return string.rep("8", l) end end
|
|
||||||
local function text(title, str) return {title .. str, fg(string.len(title)) .. string.rep("0", string.len(str)), string.rep("f", string.len(title .. str))} end
|
|
||||||
|
|
||||||
local function time(n)
|
|
||||||
local h = math.floor(n / 3600)
|
|
||||||
local m = math.floor(n / 60) % 60
|
|
||||||
local s = n % 60
|
|
||||||
local retval = s .. "s"
|
|
||||||
if m > 0 or h > 0 then retval = m .. "m " .. retval end
|
|
||||||
if h > 0 then retval = h .. "h " .. retval end
|
|
||||||
return retval
|
|
||||||
end
|
|
||||||
|
|
||||||
local function ext(retval)
|
|
||||||
if debug ~= nil then table.insert(retval, text(" ", "Debug enabled")) end
|
|
||||||
if http ~= nil then table.insert(retval, text(" ", "HTTP enabled"))
|
|
||||||
if http.websocket ~= nil then table.insert(retval, text(" ", "CC: Tweaked")) end end
|
|
||||||
if mounter ~= nil then table.insert(retval, text(" ", "CraftOS-PC")) end
|
|
||||||
if term.setGraphicsMode ~= nil then table.insert(retval, text(" ", "CraftOS-PC GFX")) end
|
|
||||||
if term.screenshot ~= nil then table.insert(retval, text(" ", "CraftOS-PC 2")) end
|
|
||||||
if ccemux ~= nil then table.insert(retval, text(" ", "CCEmuX")) end
|
|
||||||
if fs.exists(".mbs") or fs.exists("rom/.mbs") then table.insert(retval, text(" ", "MBS")) end
|
|
||||||
if type(kernel) == "table" then table.insert(retval, text(" ", "CCKernel2")) end
|
|
||||||
return retval
|
|
||||||
end
|
|
||||||
|
|
||||||
local function getRuntime()
|
|
||||||
if os.about ~= nil then return string.sub(os.about(), 1, string.find(os.about(), "\n"))
|
|
||||||
elseif ccemux ~= nil then return ccemux.getVersion()
|
|
||||||
elseif _MC_VERSION ~= nil then return _MC_VERSION
|
|
||||||
else return "Unknown" end
|
|
||||||
end
|
|
||||||
|
|
||||||
local sysinfo = {
|
|
||||||
text(os.getComputerLabel() or "Untitled Computer", ""),
|
|
||||||
text("Type: ", commands ~= nil and "Command Computer" or term.isColor() and "Advanced Computer" or "Standard Computer"),
|
|
||||||
text("OS: ", kernel.getOS()),
|
|
||||||
text("Kernel: ", kernel.getRelease()),
|
|
||||||
text("Runtime: ", getRuntime()),
|
|
||||||
text("Lua: ", _VERSION),
|
|
||||||
text("Host: ", _HOST),
|
|
||||||
text("Uptime: ", time(os.clock())),
|
|
||||||
text("Extensions: ", "")
|
|
||||||
}
|
|
||||||
ext(sysinfo)
|
|
||||||
local lines, sw, sh = 2, term.getSize()
|
|
||||||
term.clear()
|
|
||||||
term.setCursorPos(1, 2)
|
|
||||||
for i = 1, string.len(ccart), ccart_width do
|
|
||||||
term.blit(string.sub(ccart, i, i+ccart_width-2), string.sub(term.isColor() and ccart_adv_fg or ccart_fg, i, i+ccart_width-2), string.sub(term.isColor() and ccart_adv_bg or ccart_bg, i, i+ccart_width-2))
|
|
||||||
write(" ")
|
|
||||||
if sysinfo[((i-1)/ccart_width)+1] ~= nil then term.blit(table.unpack(sysinfo[((i-1)/ccart_width)+1])) end
|
|
||||||
print("")
|
|
||||||
lines = lines + 1
|
|
||||||
end
|
|
||||||
for i = lines - 1, #sysinfo do
|
|
||||||
write(string.rep(" ", ccart_width + 1))
|
|
||||||
term.blit(table.unpack(sysinfo[i]))
|
|
||||||
print("")
|
|
||||||
end
|
|
||||||
print("")
|
|
||||||
if term.screenshot ~= nil then term.screenshot() end
|
|
||||||
sleep(0.25)
|
|
||||||
|
|
||||||
elseif require("filesystem") ~= nil then
|
|
||||||
|
|
||||||
-- TODO: Find better art
|
|
||||||
local ccart = [[------------------------
|
|
||||||
| |
|
|
||||||
| -------------------- |
|
|
||||||
| | \ | |
|
|
||||||
| | / __ | |
|
|
||||||
| | | |
|
|
||||||
| | | |
|
|
||||||
| | | |
|
|
||||||
| | | |
|
|
||||||
| | | |
|
|
||||||
| | | |
|
|
||||||
| -------------------- |
|
|
||||||
| |
|
|
||||||
| [=] |
|
|
||||||
| |
|
|
||||||
------------------------]]
|
|
||||||
|
|
||||||
local ccart_fg = [[ffffffffffffffffffffffff
|
|
||||||
f0000000000000000000000f
|
|
||||||
f0ffffffffffffffffffff0f
|
|
||||||
f0ff0fffffffffffffffff0f
|
|
||||||
f0ff0f00ffffffffffffff0f
|
|
||||||
f0ffffffffffffffffffff0f
|
|
||||||
f0ffffffffffffffffffff0f
|
|
||||||
f0ffffffffffffffffffff0f
|
|
||||||
f0ffffffffffffffffffff0f
|
|
||||||
f0ffffffffffffffffffff0f
|
|
||||||
f0ffffffffffffffffffff0f
|
|
||||||
f0ffffffffffffffffffff0f
|
|
||||||
f0000000000000000000000f
|
|
||||||
f000000000000000000fff0f
|
|
||||||
f0000000000000000000000f
|
|
||||||
ffffffffffffffffffffffff]]
|
|
||||||
|
|
||||||
local ccart_bg = [[ffffffffffffffffffffffff
|
|
||||||
f0000000000000000000000f
|
|
||||||
f0ffffffffffffffffffff0f
|
|
||||||
f0ffffffffffffffffffff0f
|
|
||||||
f0ffffffffffffffffffff0f
|
|
||||||
f0ffffffffffffffffffff0f
|
|
||||||
f0ffffffffffffffffffff0f
|
|
||||||
f0ffffffffffffffffffff0f
|
|
||||||
f0ffffffffffffffffffff0f
|
|
||||||
f0ffffffffffffffffffff0f
|
|
||||||
f0ffffffffffffffffffff0f
|
|
||||||
f0ffffffffffffffffffff0f
|
|
||||||
f0000000000000000000000f
|
|
||||||
f000000000000000000fff0f
|
|
||||||
f0000000000000000000000f
|
|
||||||
ffffffffffffffffffffffff]]
|
|
||||||
|
|
||||||
local ccart_adv_fg = [[ffffffffffffffffffffffff
|
|
||||||
f4444444444444444444444f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ff0fffffffffffffffff4f
|
|
||||||
f4ff0f00ffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4444444444444444444444f
|
|
||||||
f444444444444444444ddd4f
|
|
||||||
f4444444444444444444444f
|
|
||||||
ffffffffffffffffffffffff]]
|
|
||||||
|
|
||||||
local ccart_adv_bg = [[ffffffffffffffffffffffff
|
|
||||||
f4444444444444444444444f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4ffffffffffffffffffff4f
|
|
||||||
f4444444444444444444444f
|
|
||||||
f444444444444444444ddd4f
|
|
||||||
f4444444444444444444444f
|
|
||||||
ffffffffffffffffffffffff]]
|
|
||||||
|
|
||||||
local component = require("component")
|
|
||||||
local computer = require("computer")
|
|
||||||
local term = require("term")
|
|
||||||
local gpu = term.gpu()
|
|
||||||
|
|
||||||
local function fg(l) if gpu.getDepth() > 1 then return string.rep("4", l) else return string.rep("0", l) end end
|
|
||||||
local function text(title, str) return {title .. str, fg(string.len(title)) .. string.rep("0", string.len(str)), string.rep("f", string.len(title .. str))} end
|
|
||||||
|
|
||||||
local function time(n)
|
|
||||||
local h = math.floor(n / 3600)
|
|
||||||
local m = math.floor(n / 60) % 60
|
|
||||||
local s = n % 60
|
|
||||||
local retval = s .. "s"
|
|
||||||
if m > 0 or h > 0 then retval = m .. "m " .. retval end
|
|
||||||
if h > 0 then retval = h .. "h " .. retval end
|
|
||||||
return retval
|
|
||||||
end
|
|
||||||
|
|
||||||
local function mem(bytes)
|
|
||||||
if bytes > 1048576 then return string.gsub(string.sub((math.floor((bytes / 1048576) * 1000) / 1000) .. "", 1, 4), "%.$", "") .. " MB"
|
|
||||||
elseif bytes > 1024 then return string.gsub(string.sub((math.floor((bytes / 1024) * 1000) / 1000) .. "", 1, 4), "%.$", "") .. " kB"
|
|
||||||
else return bytes .. " B" end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function ext(retval)
|
|
||||||
for address, type in component.list() do table.insert(retval, text(" " .. type .. " ", address)) end
|
|
||||||
return retval
|
|
||||||
end
|
|
||||||
|
|
||||||
local tier = "Unknown"
|
|
||||||
for k,v in pairs(component.computer.getDeviceInfo()) do if v.class == "processor" then tier = string.match(v.product, "FlexiArch (%d+) Processor") end end
|
|
||||||
|
|
||||||
local sysinfo = {
|
|
||||||
text("OpenComputers", ""),
|
|
||||||
text("Tier: ", tier),
|
|
||||||
text("OS: ", _OSVERSION),
|
|
||||||
text("Lua: ", _VERSION),
|
|
||||||
text("RAM: ", mem(computer.totalMemory() - computer.freeMemory()) .. " / " .. mem(computer.totalMemory())),
|
|
||||||
text("Uptime: ", time(computer.uptime())),
|
|
||||||
text("Components: ", "")
|
|
||||||
}
|
|
||||||
ext(sysinfo)
|
|
||||||
|
|
||||||
local ccColors = {
|
|
||||||
["0"] = 0xFFFFFF,
|
|
||||||
["4"] = 0xFFFF00,
|
|
||||||
["7"] = 0x404040,
|
|
||||||
["8"] = 0x7F7F7F,
|
|
||||||
d = 0x00FF00,
|
|
||||||
f = 0x000000
|
|
||||||
}
|
|
||||||
|
|
||||||
local function blit(text, fg, bg)
|
|
||||||
if text == "" then return end
|
|
||||||
if #text ~= #fg or #fg ~= #bg then error("Unbalanced string lengths in blit", 2) end
|
|
||||||
if #text > term.getViewport() - term.getCursor() then
|
|
||||||
text = string.sub(text, 1, term.getViewport() - term.getCursor(), nil)
|
|
||||||
fg = string.sub(fg, 1, term.getViewport() - term.getCursor(), nil)
|
|
||||||
bg = string.sub(bg, 1, term.getViewport() - term.getCursor(), nil)
|
|
||||||
end
|
|
||||||
for i = 1, #text do
|
|
||||||
if ccColors[string.sub(fg, i, i)] == nil then error("Unknown color " .. string.sub(fg, i, i)) end
|
|
||||||
if ccColors[string.sub(bg, i, i)] == nil then error("Unknown color " .. string.sub(bg, i, i)) end
|
|
||||||
gpu.setForeground(ccColors[string.sub(fg, i, i)])
|
|
||||||
gpu.setBackground(ccColors[string.sub(bg, i, i)])
|
|
||||||
term.write(string.sub(text, i, i))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
print("")
|
|
||||||
for i = 1, string.len(ccart), 25 do
|
|
||||||
blit(string.sub(ccart, i, i+23), string.sub(gpu.getDepth() > 1 and ccart_adv_fg or ccart_fg, i, i+23), string.sub(gpu.getDepth() > 1 and ccart_adv_bg or ccart_bg, i, i+23))
|
|
||||||
term.write(" ")
|
|
||||||
if sysinfo[((i-1)/25)+1] ~= nil then blit(table.unpack(sysinfo[((i-1)/25)+1])) end
|
|
||||||
print("")
|
|
||||||
end
|
|
||||||
if #sysinfo > 16 then for i = 16, #sysinfo do
|
|
||||||
term.write(string.rep(" ", 26))
|
|
||||||
blit(table.unpack(sysinfo[i]))
|
|
||||||
print("")
|
|
||||||
end end
|
|
||||||
print("")
|
|
||||||
os.sleep(0.25)
|
|
||||||
|
|
||||||
else print("Unknown computer type") end
|
|
|
@ -1,7 +0,0 @@
|
||||||
local tArgs = {...}
|
|
||||||
|
|
||||||
if #tArgs >= 1 then
|
|
||||||
shell.executeScript(shell.resolve(tArgs[1]))
|
|
||||||
else
|
|
||||||
kerneldraw.printAppInfo("script", "No file specified")
|
|
||||||
end
|
|
55
bin/set
55
bin/set
|
@ -1,55 +0,0 @@
|
||||||
local pp = require "cc.pretty"
|
|
||||||
|
|
||||||
local tArgs = { ... }
|
|
||||||
if #tArgs == 0 then
|
|
||||||
-- "set"
|
|
||||||
local _, y = term.getCursorPos()
|
|
||||||
local tSettings = {}
|
|
||||||
for n, sName in ipairs(settings.getNames()) do
|
|
||||||
tSettings[n] = textutils.serialize(sName) .. " is " .. textutils.serialize(settings.get(sName))
|
|
||||||
end
|
|
||||||
textutils.pagedPrint(table.concat(tSettings, "\n"), y - 3)
|
|
||||||
|
|
||||||
elseif #tArgs == 1 then
|
|
||||||
-- "set foo"
|
|
||||||
local sName = tArgs[1]
|
|
||||||
local deets = settings.getDetails(sName)
|
|
||||||
local msg = pp.text(sName, colors.cyan) .. " is " .. pp.pretty(deets.value)
|
|
||||||
if deets.default ~= nil and deets.value ~= deets.default then
|
|
||||||
msg = msg .. " (default is " .. pp.pretty(deets.default) .. ")"
|
|
||||||
end
|
|
||||||
pp.print(msg)
|
|
||||||
if deets.description then print(deets.description) end
|
|
||||||
|
|
||||||
else
|
|
||||||
-- "set foo bar"
|
|
||||||
local sName = tArgs[1]
|
|
||||||
local sValue = tArgs[2]
|
|
||||||
local value
|
|
||||||
if sValue == "true" then
|
|
||||||
value = true
|
|
||||||
elseif sValue == "false" then
|
|
||||||
value = false
|
|
||||||
elseif sValue == "nil" then
|
|
||||||
value = nil
|
|
||||||
elseif tonumber(sValue) then
|
|
||||||
value = tonumber(sValue)
|
|
||||||
else
|
|
||||||
value = sValue
|
|
||||||
end
|
|
||||||
|
|
||||||
local option = settings.getDetails(sName)
|
|
||||||
if value == nil then
|
|
||||||
settings.unset(sName)
|
|
||||||
print(textutils.serialize(sName) .. " unset")
|
|
||||||
elseif option.type and option.type ~= type(value) then
|
|
||||||
printError(("%s is not a valid %s."):format(textutils.serialize(sValue), option.type))
|
|
||||||
else
|
|
||||||
settings.set(sName, value)
|
|
||||||
print(textutils.serialize(sName) .. " set to " .. textutils.serialize(value))
|
|
||||||
end
|
|
||||||
|
|
||||||
if value ~= option.value then
|
|
||||||
settings.save()
|
|
||||||
end
|
|
||||||
end
|
|
256
bin/sh
256
bin/sh
|
@ -1,256 +0,0 @@
|
||||||
local tArgs = {...}
|
|
||||||
|
|
||||||
local parentShell = shell
|
|
||||||
|
|
||||||
local bExit = false
|
|
||||||
local sDir = (parentShell and parentShell.dir()) or ""
|
|
||||||
local sPath = (parentShell and parentShell.path()) or ".:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
|
|
||||||
local tAliases = (parentShell and parentShell.aliases()) or {}
|
|
||||||
local tProgramStack = {}
|
|
||||||
|
|
||||||
local shell = {}
|
|
||||||
local tEnv = {
|
|
||||||
["shell"] = shell,
|
|
||||||
}
|
|
||||||
|
|
||||||
local function findArg(arg)
|
|
||||||
for _,v in ipairs(tArgs) do
|
|
||||||
if v == arg then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Colours
|
|
||||||
local promptColour, textColour, bgColour
|
|
||||||
if term.isColour() then
|
|
||||||
promptColour = colours.yellow
|
|
||||||
textColour = colours.white
|
|
||||||
bgColour = colours.black
|
|
||||||
else
|
|
||||||
promptColour = colours.white
|
|
||||||
textColour = colours.white
|
|
||||||
bgColour = colours.black
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function run( _sCommand, ... )
|
|
||||||
local sPath = shell.resolveProgram( _sCommand )
|
|
||||||
if sPath ~= nil then
|
|
||||||
tProgramStack[#tProgramStack + 1] = sPath
|
|
||||||
local result = os.run( tEnv, sPath, ... )
|
|
||||||
tProgramStack[#tProgramStack] = nil
|
|
||||||
return result
|
|
||||||
else
|
|
||||||
printError( "No such program" )
|
|
||||||
printError( _sCommand .. ": Command not found" )
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function runLine( _sLine )
|
|
||||||
local tWords = {}
|
|
||||||
for match in string.gmatch( _sLine, "[^ \t]+" ) do
|
|
||||||
table.insert( tWords, match )
|
|
||||||
end
|
|
||||||
|
|
||||||
local sCommand = tWords[1]
|
|
||||||
if sCommand then
|
|
||||||
return run( sCommand, unpack( tWords, 2 ) )
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Install shell API
|
|
||||||
function shell.run( ... )
|
|
||||||
return runLine( table.concat( { ... }, " " ) )
|
|
||||||
end
|
|
||||||
|
|
||||||
function shell.exit()
|
|
||||||
bExit = true
|
|
||||||
end
|
|
||||||
|
|
||||||
function shell.dir()
|
|
||||||
return sDir
|
|
||||||
end
|
|
||||||
|
|
||||||
function shell.setDir( _sDir )
|
|
||||||
sDir = _sDir
|
|
||||||
end
|
|
||||||
|
|
||||||
function shell.path()
|
|
||||||
return sPath
|
|
||||||
end
|
|
||||||
|
|
||||||
function shell.setPath( _sPath )
|
|
||||||
sPath = _sPath
|
|
||||||
end
|
|
||||||
|
|
||||||
function shell.resolve( _sPath )
|
|
||||||
local sStartChar = string.sub( _sPath, 1, 1 )
|
|
||||||
if sStartChar == "/" or sStartChar == "\\" then
|
|
||||||
return fs.combine( "", _sPath )
|
|
||||||
else
|
|
||||||
return fs.combine( sDir, _sPath )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function shell.resolveProgram( _sCommand )
|
|
||||||
-- Substitute aliases firsts
|
|
||||||
if tAliases[ _sCommand ] ~= nil then
|
|
||||||
_sCommand = tAliases[ _sCommand ]
|
|
||||||
end
|
|
||||||
|
|
||||||
-- If the path is a global path, use it directly
|
|
||||||
local sStartChar = string.sub( _sCommand, 1, 1 )
|
|
||||||
if sStartChar == "/" or sStartChar == "\\" then
|
|
||||||
local sPath = fs.combine( "", _sCommand )
|
|
||||||
if fs.exists( sPath ) and not fs.isDir( sPath ) then
|
|
||||||
return sPath
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Otherwise, look on the path variable
|
|
||||||
for sPath in string.gmatch(sPath, "[^:]+") do
|
|
||||||
sPath = fs.combine( shell.resolve( sPath ), _sCommand )
|
|
||||||
if fs.exists( sPath ) and not fs.isDir( sPath ) then
|
|
||||||
return sPath
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Not found
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function shell.programs( _bIncludeHidden )
|
|
||||||
local tItems = {}
|
|
||||||
|
|
||||||
-- Add programs from the path
|
|
||||||
for sPath in string.gmatch(sPath, "[^:]+") do
|
|
||||||
sPath = shell.resolve( sPath )
|
|
||||||
if fs.isDir( sPath ) then
|
|
||||||
local tList = fs.list( sPath )
|
|
||||||
for n,sFile in pairs( tList ) do
|
|
||||||
if not fs.isDir( fs.combine( sPath, sFile ) ) and
|
|
||||||
(_bIncludeHidden or string.sub( sFile, 1, 1 ) ~= ".") then
|
|
||||||
tItems[ sFile ] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Sort and return
|
|
||||||
local tItemList = {}
|
|
||||||
for sItem, b in pairs( tItems ) do
|
|
||||||
table.insert( tItemList, sItem )
|
|
||||||
end
|
|
||||||
table.sort( tItemList )
|
|
||||||
return tItemList
|
|
||||||
end
|
|
||||||
|
|
||||||
function shell.getRunningProgram()
|
|
||||||
if #tProgramStack > 0 then
|
|
||||||
return tProgramStack[#tProgramStack]
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function shell.setAlias( _sCommand, _sProgram )
|
|
||||||
tAliases[ _sCommand ] = _sProgram
|
|
||||||
end
|
|
||||||
|
|
||||||
function shell.clearAlias( _sCommand )
|
|
||||||
tAliases[ _sCommand ] = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function shell.aliases()
|
|
||||||
-- Add aliases
|
|
||||||
local tCopy = {}
|
|
||||||
for sAlias, sCommand in pairs( tAliases ) do
|
|
||||||
tCopy[sAlias] = sCommand
|
|
||||||
end
|
|
||||||
return tCopy
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Custom shell API functions
|
|
||||||
|
|
||||||
function shell.executeScript(path)
|
|
||||||
if not fs.exists(path) or fs.isDir(path) then
|
|
||||||
return "File or directory not found"
|
|
||||||
else
|
|
||||||
local t = luaex.iterateFileLines(path)
|
|
||||||
if string.find(t[1], "@ @ !! FREAX SCRIPT HEADER") or t[1] == "@ @ !! FREAX SCRIPT HEADER" then
|
|
||||||
for _,cmd in pairs(t) do
|
|
||||||
shell.run(cmd)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
return "Couldn't find script header"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function shell.getActiveUserShell()
|
|
||||||
if fs.exists("/etc/passwd/.shadow/".._G["_activeUser"]..".usr") then
|
|
||||||
local ud = dofile("/etc/passwd/.shadow/".._G["_activeUser"]..".usr")
|
|
||||||
return ud.shell or "/bin/sh"
|
|
||||||
else
|
|
||||||
return "/bin/sh"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Run custom shells
|
|
||||||
if findArg("--force") or findArg("-f") then
|
|
||||||
kernel.writeMessage("Ignoring shell settings")
|
|
||||||
elseif shell.getActiveUserShell() ~= "/bin/sh" then
|
|
||||||
shell.run(shell.getActiveUserShell())
|
|
||||||
kernel.shutdown(false)
|
|
||||||
end
|
|
||||||
|
|
||||||
term.setBackgroundColor( bgColour )
|
|
||||||
term.setTextColour( textColour )
|
|
||||||
|
|
||||||
local label = os.getComputerLabel() or os.getComputerID()
|
|
||||||
|
|
||||||
-- Read commands and execute them
|
|
||||||
local tCommandHistory = {}
|
|
||||||
while not bExit do
|
|
||||||
term.setBackgroundColor( bgColour )
|
|
||||||
if security.getSU() then
|
|
||||||
if security.getActiveUserStatus() then
|
|
||||||
term.setTextColour( colours.lime )
|
|
||||||
else
|
|
||||||
term.setTextColour( colours.orange )
|
|
||||||
end
|
|
||||||
else
|
|
||||||
term.setTextColour( colours.cyan )
|
|
||||||
end
|
|
||||||
write( _activeUser )
|
|
||||||
term.setTextColour( colours.lightGrey )
|
|
||||||
write( "@" )
|
|
||||||
term.setTextColour( colours.lightBlue )
|
|
||||||
write( label )
|
|
||||||
term.setTextColour( colours.lightGrey )
|
|
||||||
write( "/" )
|
|
||||||
term.setTextColour( colours.lightBlue )
|
|
||||||
write( shell.dir() )
|
|
||||||
if security.getSU() then
|
|
||||||
if security.getActiveUserStatus() then
|
|
||||||
term.setTextColour( colours.lime )
|
|
||||||
else
|
|
||||||
term.setTextColour( colours.orange )
|
|
||||||
end
|
|
||||||
write( " # " )
|
|
||||||
else
|
|
||||||
term.setTextColour( colours.cyan )
|
|
||||||
write( " $ " )
|
|
||||||
end
|
|
||||||
term.setTextColour( textColour )
|
|
||||||
|
|
||||||
local sLine = read( nil, tCommandHistory )
|
|
||||||
table.insert( tCommandHistory, sLine )
|
|
||||||
runLine( sLine )
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Custom shutdown code goes here
|
|
3
bin/time
3
bin/time
|
@ -1,3 +0,0 @@
|
||||||
local nTime = os.time()
|
|
||||||
local nDay = os.day()
|
|
||||||
print("The time is " .. textutils.formatTime(nTime, false) .. " on Day " .. nDay)
|
|
|
@ -1,65 +0,0 @@
|
||||||
local tArgs = {...}
|
|
||||||
local packages = config.load("/etc/tpm/package.dat")
|
|
||||||
local temp = config.load("/etc/tpm/packageInstalled.dat")
|
|
||||||
local found, value
|
|
||||||
|
|
||||||
if not security.getSU() then
|
|
||||||
exception.throw("RestrictedOpsException")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if #tArgs < 1 then
|
|
||||||
kerneldraw.printAppInfo("tpm", "Package name not specified")
|
|
||||||
return
|
|
||||||
elseif not packages then
|
|
||||||
kerneldraw.printAppInfo("tpm", "package.dat is missing or corrupt")
|
|
||||||
log.writeMessage("package.dat unable to be traversed")
|
|
||||||
return
|
|
||||||
elseif not temp then
|
|
||||||
shell.executeScript("/etc/scripts/tpm-recache.tsf")
|
|
||||||
end
|
|
||||||
|
|
||||||
found, value = search.traverseKey(temp, tArgs[1])
|
|
||||||
if found and value then
|
|
||||||
kerneldraw.printAppInfo("tpm", "Package already installed")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
kerneldraw.printAppInfo("tpm", "Traversing package.dat")
|
|
||||||
local ok, pack = search.traverseValue(packages, tArgs[1])
|
|
||||||
if ok and pack then
|
|
||||||
kerneldraw.printAppInfo("tpm", "Found corresponding package")
|
|
||||||
kerneldraw.printAppInfo("tpm", "Downloading API files [1/2]")
|
|
||||||
local numapi = 1
|
|
||||||
local numbin = 1
|
|
||||||
local APIInstallFlag = false
|
|
||||||
for k,v in pairs(pack.apis) do
|
|
||||||
if tpm.downloadAPI(k, v) then
|
|
||||||
APIInstallFlag = true
|
|
||||||
kerneldraw.printAppInfo("tpm", "Downloaded API "..k.." ["..tostring(numapi).."]")
|
|
||||||
else
|
|
||||||
kerneldraw.printAppWarning("tpm", "Failed to download API "..k)
|
|
||||||
end
|
|
||||||
numapi = numapi + 1
|
|
||||||
end
|
|
||||||
kerneldraw.printAppInfo("tpm", "Downloading binaries [2/2]")
|
|
||||||
for k,v in pairs(pack.bins) do
|
|
||||||
if tpm.downloadBinary(k, v) then
|
|
||||||
kerneldraw.printAppInfo("tpm", "Downloaded binary "..k.." ["..tostring(numbin).."]")
|
|
||||||
else
|
|
||||||
kerneldraw.printAppWarning("tpm", "Failed to download binary "..k)
|
|
||||||
end
|
|
||||||
numbin = numbin + 1
|
|
||||||
end
|
|
||||||
table.insert(temp, pack.name)
|
|
||||||
log.writeMessage("New package downloaded and installed")
|
|
||||||
config.save(temp, "/etc/tpm/packageInstalled.dat")
|
|
||||||
kerneldraw.printAppSuccess("tpm", "package installed")
|
|
||||||
if APIInstallFlag then
|
|
||||||
if kerneldraw.request("Assemblies were installed, restart") then
|
|
||||||
kernel.reboot(false)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
kerneldraw.printAppInfo("tpm", "Unable to find id for "..tArgs[1])
|
|
||||||
end
|
|
30
bin/tpm-list
30
bin/tpm-list
|
@ -1,30 +0,0 @@
|
||||||
local tArgs = {...}
|
|
||||||
local packages = config.load("/etc/tpm/package.dat")
|
|
||||||
local packageInstalled = config.load("/etc/tpm/packageInstalled.dat")
|
|
||||||
|
|
||||||
if not security.getSU() then
|
|
||||||
exception.throw("RestrictedOpsException")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if not packages then
|
|
||||||
kerneldraw.printAppInfo("tpm", "package.dat is missing or corrupt")
|
|
||||||
log.writeMessage("package.dat unable to be traversed")
|
|
||||||
return
|
|
||||||
elseif not packageInstalled then
|
|
||||||
shell.executeScript("/etc/scripts/tpm-recache.tsf")
|
|
||||||
end
|
|
||||||
|
|
||||||
if search.findValue(tArgs, "available") then
|
|
||||||
kerneldraw.printAppInfo("tpm", "Traversing package.dat")
|
|
||||||
for k, v in pairs(packages) do
|
|
||||||
kerneldraw.printAppInfo("tpm", "Found package identifier "..v.name)
|
|
||||||
end
|
|
||||||
elseif search.findValue(tArgs, "installed") then
|
|
||||||
kerneldraw.printAppInfo("tpm", "Traversing packageInstalled.dat")
|
|
||||||
for k, v in pairs(packageInstalled) do
|
|
||||||
kerneldraw.printAppInfo("tpm", "Found package identifier "..v)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
kerneldraw.printAppInfo("tpm", "Specify listing type")
|
|
||||||
end
|
|
|
@ -1,13 +0,0 @@
|
||||||
if not security.getSU() then
|
|
||||||
exception.throw("RestrictedOpsException")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
kerneldraw.printAppInfo("tpm", "Redownloading package.dat")
|
|
||||||
if tpm.getPaste("/etc/tpm/package.dat", "0YScZtUc", true) then
|
|
||||||
kerneldraw.printAppSuccess("tpm", "Package cache updated")
|
|
||||||
log.writeMessage("Package cache updated")
|
|
||||||
else
|
|
||||||
kerneldraw.printAppInfo("tpm", "Failed to update package cache")
|
|
||||||
log.writeMessage("Failed to update package cache")
|
|
||||||
end
|
|
|
@ -1,68 +0,0 @@
|
||||||
local tArgs = {...}
|
|
||||||
local packages = config.load("/etc/tpm/package.dat")
|
|
||||||
local temp = config.load("/etc/tpm/packageInstalled.dat")
|
|
||||||
local found, value
|
|
||||||
|
|
||||||
if not security.getSU() then
|
|
||||||
exception.throw("RestrictedOpsException")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if #tArgs < 1 then
|
|
||||||
kerneldraw.printAppInfo("tpm", "Package name not specified")
|
|
||||||
return
|
|
||||||
elseif not packages then
|
|
||||||
kerneldraw.printAppInfo("tpm", "package.dat is missing or corrupt")
|
|
||||||
log.writeMessage("package.dat unable to be traversed")
|
|
||||||
return
|
|
||||||
elseif not temp then
|
|
||||||
shell.executeScript("/etc/scripts/tpm-recache.tsf")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
kerneldraw.printAppInfo("tpm", "Traversing package.dat")
|
|
||||||
local ok, pack = search.traverseValue(packages, tArgs[1])
|
|
||||||
if ok and pack then
|
|
||||||
found, value = search.traverseKey(temp, pack.name)
|
|
||||||
if found and value then
|
|
||||||
temp[value] = nil
|
|
||||||
else
|
|
||||||
kerneldraw.printAppInfo("tpm", "Package missing")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
kerneldraw.printAppInfo("tpm", "Found corresponding package")
|
|
||||||
kerneldraw.printAppInfo("tpm", "Removing API files [1/2]")
|
|
||||||
local numapi = 1
|
|
||||||
local numbin = 1
|
|
||||||
local APIRemovalFlag = false
|
|
||||||
for k,v in pairs(pack.apis) do
|
|
||||||
if fs.exists(tpm.toPackageAPI(k)) and not fs.isDir(tpm.toPackageAPI(k)) then
|
|
||||||
fs.delete(tpm.toPackageAPI(k))
|
|
||||||
APIRemovalFlag = true
|
|
||||||
kerneldraw.printAppInfo("tpm", "Removed API "..k.." ["..tostring(numapi).."]")
|
|
||||||
else
|
|
||||||
kerneldraw.printAppWarning("tpm", "Failed to remove API "..k)
|
|
||||||
end
|
|
||||||
numapi = numapi + 1
|
|
||||||
end
|
|
||||||
kerneldraw.printAppInfo("tpm", "Removing binaries [2/2]")
|
|
||||||
for k,v in pairs(pack.bins) do
|
|
||||||
if fs.exists(tpm.toPackageBinary(k)) and not fs.isDir(tpm.toPackageBinary(k)) then
|
|
||||||
fs.delete(tpm.toPackageBinary(k))
|
|
||||||
kerneldraw.printAppInfo("tpm", "Removed binary "..k.." ["..tostring(numbin).."]")
|
|
||||||
else
|
|
||||||
kerneldraw.printAppWarning("tpm", "Failed to remove binary "..k)
|
|
||||||
end
|
|
||||||
numbin = numbin + 1
|
|
||||||
end
|
|
||||||
if APIRemovalFlag then
|
|
||||||
if kerneldraw.request("Assemblies were removed, restart") then
|
|
||||||
kernel.reboot(false)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
config.save(temp, "/etc/tpm/packageInstalled.dat")
|
|
||||||
log.writeMessage("Removed package "..tArgs[1])
|
|
||||||
kerneldraw.printAppSuccess("tpm", "Package removed")
|
|
||||||
else
|
|
||||||
kerneldraw.printAppInfo("tpm", "Unable to find id for "..tArgs[1])
|
|
||||||
end
|
|
|
@ -1,14 +0,0 @@
|
||||||
if not security.getSU() then
|
|
||||||
exception.throw("RestrictedOpsException")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if not config.load("/etc/tpm/packageInstalled.dat") then
|
|
||||||
kerneldraw.printAppInfo("tpm", "packageInstalled.dat is missing or corrupt")
|
|
||||||
if kerneldraw.request("Repair TPM data files") then
|
|
||||||
config.save({}, "/etc/tpm/packageInstalled.dat")
|
|
||||||
kerneldraw.printAppInfo("tpm", "Package registry reconstructed")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
kerneldraw.printAppInfo("tpm", "packageInstalled.dat is correctly readable")
|
|
||||||
end
|
|
2
bin/tty
2
bin/tty
|
@ -1,2 +0,0 @@
|
||||||
local x, y = term.getSize()
|
|
||||||
kerneldraw.printAppInfo("tty", "Terminal object size is "..tostring(x).."x"..tostring(y))
|
|
17
bin/type
17
bin/type
|
@ -1,17 +0,0 @@
|
||||||
local tArgs = { ... }
|
|
||||||
if #tArgs < 1 then
|
|
||||||
local programName = "type"
|
|
||||||
print("Usage: " .. programName .. " <path>")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local sPath = shell.resolve(tArgs[1])
|
|
||||||
if fs.exists(sPath) then
|
|
||||||
if fs.isDir(sPath) then
|
|
||||||
print("directory")
|
|
||||||
else
|
|
||||||
print("file")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
print("No such path")
|
|
||||||
end
|
|
62
bin/uname
62
bin/uname
|
@ -1,62 +0,0 @@
|
||||||
local tArgs = {...}
|
|
||||||
local err = true
|
|
||||||
local function findArg(arg)
|
|
||||||
for _,v in ipairs(tArgs) do
|
|
||||||
if v == arg then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
if findArg("--help") or findArg("-h") then
|
|
||||||
err = false
|
|
||||||
shell.execute("/bin/man uname")
|
|
||||||
end
|
|
||||||
if findArg("--kernel-name") or findArg("-s") then
|
|
||||||
err = false
|
|
||||||
kerneldraw.printAppInfo("uname", kernel.getName())
|
|
||||||
end
|
|
||||||
if findArg("--nodename") or findArg("-n") then
|
|
||||||
err = false
|
|
||||||
kerneldraw.printAppInfo("uname", kernel.getHostname())
|
|
||||||
end
|
|
||||||
if findArg("--kernel-release") or findArg("-r") then
|
|
||||||
err = false
|
|
||||||
kerneldraw.printAppInfo("uname", kernel.getRelease())
|
|
||||||
end
|
|
||||||
if findArg("--kernel-version") or findArg("-v") then
|
|
||||||
err = false
|
|
||||||
kerneldraw.printAppInfo("uname", kernel.getVersion())
|
|
||||||
end
|
|
||||||
if findArg("--machine") or findArg("-m") then
|
|
||||||
err = false
|
|
||||||
kerneldraw.printAppInfo("uname", kernel.getMachine())
|
|
||||||
end
|
|
||||||
if findArg("--processor") or findArg("-p") then
|
|
||||||
err = false
|
|
||||||
kerneldraw.printAppInfo("uname", kernel.getProcessorArchitecture())
|
|
||||||
end
|
|
||||||
if findArg("--hardware-platform") or findArg("-i") then
|
|
||||||
err = false
|
|
||||||
kerneldraw.printAppInfo("uname", kernel.getHardwarePlatform())
|
|
||||||
end
|
|
||||||
if findArg("--operating-system") or findArg("-o") then
|
|
||||||
err = false
|
|
||||||
kerneldraw.printAppInfo("uname", kernel.getOS())
|
|
||||||
end
|
|
||||||
if findArg("--path") or findArg("-b") then
|
|
||||||
err = false
|
|
||||||
kerneldraw.printAppInfo("uname", shell.path())
|
|
||||||
end
|
|
||||||
if findArg("--id") or findArg("-c") then
|
|
||||||
err = false
|
|
||||||
kerneldraw.printAppInfo("uname", os.getComputerID())
|
|
||||||
end
|
|
||||||
if findArg("--user") or findArg("-u") then
|
|
||||||
err = false
|
|
||||||
kerneldraw.printAppInfo("uname", _G[_activeUser])
|
|
||||||
end
|
|
||||||
if #tArgs < 1 or err then
|
|
||||||
kerneldraw.printAppInfo("uname", "Arguments not specified")
|
|
||||||
end
|
|
|
@ -1,4 +0,0 @@
|
||||||
if mounter == nil then error("Mounting directories is not supported in vanilla mode.") end
|
|
||||||
local args = { ... }
|
|
||||||
if args[1] ~= nil then if not mounter.unmount(args[1]) then printError("Could not unmount") end
|
|
||||||
else print("Usage: unmount <name>") end
|
|
25
bin/useradd
25
bin/useradd
|
@ -1,25 +0,0 @@
|
||||||
local tArgs = {...}
|
|
||||||
|
|
||||||
if #tArgs < 2 then
|
|
||||||
kerneldraw.printAppInfo("useradd", "Specify a user")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if fs.exists("/etc/passwd/"..tArgs[1]..".dat") and not fs.isDir("/etc/passwd/"..tArgs[1]..".dat") then
|
|
||||||
kerneldraw.printAppInfo("useradd", "User already exists")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if not security.getSU() then
|
|
||||||
exception.throw("RestrictedOpsException")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if security.passbyte(tArgs[1], tArgs[2]) then
|
|
||||||
kerneldraw.printAppSuccess("useradd", "User "..tArgs[1].." added")
|
|
||||||
log.writeSecurity("User "..tArgs[1].." added")
|
|
||||||
fs.makeDir("/home/"..tArgs[1])
|
|
||||||
else
|
|
||||||
kerneldraw.printAppInfo("useradd", "Failed to add user " .. tArgs[1])
|
|
||||||
log.writeSecurity("Failed to add user " .. tArgs[1])
|
|
||||||
end
|
|
27
bin/userdel
27
bin/userdel
|
@ -1,27 +0,0 @@
|
||||||
local tArgs = { ... }
|
|
||||||
|
|
||||||
if #tArgs < 1 then
|
|
||||||
kerneldraw.printAppInfo( "userdel", "Specify a user" )
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if not security.getSU() or tArgs[1] == "root" then
|
|
||||||
exception.throw("RestrictedOpsException")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local pathA = "/etc/passwd/"..tArgs[1]..".dat"
|
|
||||||
local pathB = "/etc/passwd/.shadow/"..tArgs[1]..".usr"
|
|
||||||
local pathC = "/home/"..tArgs[1]
|
|
||||||
|
|
||||||
if fs.exists(pathA) then
|
|
||||||
if kerneldraw.request("remove user record") then
|
|
||||||
fs.delete( pathA )
|
|
||||||
if fs.exists(pathB) then
|
|
||||||
fs.delete( pathB )
|
|
||||||
end
|
|
||||||
fs.delete( pathC )
|
|
||||||
end
|
|
||||||
else
|
|
||||||
kerneldraw.printAppInfo("userdel", "User " .. tArgs[1] .. " does not exist")
|
|
||||||
end
|
|
92
bin/wget
92
bin/wget
|
@ -1,92 +0,0 @@
|
||||||
local function printUsage()
|
|
||||||
local programName = "wget"
|
|
||||||
print("Usage:")
|
|
||||||
print(programName .. " <url> [filename]")
|
|
||||||
print(programName .. " run <url>")
|
|
||||||
end
|
|
||||||
|
|
||||||
local tArgs = { ... }
|
|
||||||
|
|
||||||
local run = false
|
|
||||||
if tArgs[1] == "run" then
|
|
||||||
table.remove(tArgs, 1)
|
|
||||||
run = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if #tArgs < 1 then
|
|
||||||
printUsage()
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local url = table.remove(tArgs, 1)
|
|
||||||
|
|
||||||
if not http then
|
|
||||||
printError("wget requires the http API")
|
|
||||||
printError("Set http.enabled to true in CC: Tweaked's config")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local function getFilename(sUrl)
|
|
||||||
sUrl = sUrl:gsub("[#?].*" , ""):gsub("/+$" , "")
|
|
||||||
return sUrl:match("/([^/]+)$")
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get(sUrl)
|
|
||||||
-- Check if the URL is valid
|
|
||||||
local ok, err = http.checkURL(url)
|
|
||||||
if not ok then
|
|
||||||
printError(err or "Invalid URL.")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
write("Connecting to " .. sUrl .. "... ")
|
|
||||||
|
|
||||||
local response = http.get(sUrl , nil , true)
|
|
||||||
if not response then
|
|
||||||
print("Failed.")
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
print("Success.")
|
|
||||||
|
|
||||||
local sResponse = response.readAll()
|
|
||||||
response.close()
|
|
||||||
return sResponse or ""
|
|
||||||
end
|
|
||||||
|
|
||||||
if run then
|
|
||||||
local res = get(url)
|
|
||||||
if not res then return end
|
|
||||||
|
|
||||||
local func, err = load(res, getFilename(url), "t", _ENV)
|
|
||||||
if not func then
|
|
||||||
printError(err)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local ok, err = pcall(func, table.unpack(tArgs))
|
|
||||||
if not ok then
|
|
||||||
printError(err)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local sFile = tArgs[1] or getFilename(url) or url
|
|
||||||
local sPath = shell.resolve(sFile)
|
|
||||||
if fs.exists(sPath) then
|
|
||||||
print("File already exists")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local res = get(url)
|
|
||||||
if not res then return end
|
|
||||||
|
|
||||||
local file, err = fs.open(sPath, "wb")
|
|
||||||
if not file then
|
|
||||||
printError("Cannot save file: " .. err)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
file.write(res)
|
|
||||||
file.close()
|
|
||||||
|
|
||||||
print("Downloaded as " .. sFile)
|
|
||||||
end
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
[ "enableBootScreen" ] = "true",
|
|
||||||
[ "doSystemSetup" ] = "true",
|
|
||||||
[ "logo" ] = "/boot/freax/freax.img",
|
|
||||||
[ "logo_small" ] = "/boot/freax/freax-small.img",
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
aaaaaaaaaaaaaaaaaaa
|
|
||||||
aaa000aaaeeaaeeaaaa
|
|
||||||
aaa0aaaaaaa11aaaaaa
|
|
||||||
aaa000aaaaa44aaaaaa
|
|
||||||
aaa0aaaaaaa55aaaaaa
|
|
||||||
aaa0aaaaa33aa33aaaa
|
|
||||||
aaaaaaaaaaaaaaaaaaa
|
|
|
@ -1,7 +0,0 @@
|
||||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
|
||||||
aaa000aaa0000aaa000aaa0000aaaeeaaeeaa
|
|
||||||
aaa0aaaaa0aa0aaa0aaaaa0aa0aaaaa11aaaa
|
|
||||||
aaa000aaa0000aaa000aaa0000aaaaa44aaaa
|
|
||||||
aaa0aaaaa00aaaaa0aaaaa0aa0aaaaa55aaaa
|
|
||||||
aaa0aaaaa0a00aaa000aaa0aa0aaa33aa33aa
|
|
||||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
|
|
@ -1,169 +0,0 @@
|
||||||
kernel.isBooting = true
|
|
||||||
settings.load("/boot/freax/boot.conf")
|
|
||||||
if not fs.exists(settings.get("logo")) then
|
|
||||||
print("logo is not a valid image")
|
|
||||||
sleep(3)
|
|
||||||
os.reboot()
|
|
||||||
end
|
|
||||||
if not fs.exists(settings.get("logo_small")) then
|
|
||||||
print("logo_small is not a valid image")
|
|
||||||
sleep(3)
|
|
||||||
os.reboot()
|
|
||||||
end
|
|
||||||
local logo = paintutils.loadImage(settings.get("logo"))
|
|
||||||
local slogo = paintutils.loadImage(settings.get("logo_small"))
|
|
||||||
local enableBootScreen = settings.get("enableBootScreen")
|
|
||||||
local doSystemSetup = settings.get("doSystemSetup")
|
|
||||||
if enableBootScreen == "false" then
|
|
||||||
enableBootScreen = false
|
|
||||||
elseif enableBootScreen == "true" then
|
|
||||||
enableBootScreen = true
|
|
||||||
else
|
|
||||||
print("enableBootScreen is a boolean.")
|
|
||||||
sleep(3)
|
|
||||||
kernel.reboot(true)
|
|
||||||
end
|
|
||||||
if doSystemSetup == "false" then
|
|
||||||
doSystemSetup = false
|
|
||||||
elseif doSystemSetup == "true" then
|
|
||||||
doSystemSetup = true
|
|
||||||
else
|
|
||||||
print("doSystemSetup is a boolean.")
|
|
||||||
sleep(3)
|
|
||||||
kernel.reboot(true)
|
|
||||||
end
|
|
||||||
kernel.printLog = not enableBootScreen
|
|
||||||
kernel.writeBootLog("Initializing " .. kernel.getName())
|
|
||||||
kerneldraw.bootScreen(enableBootScreen,0,logo,slogo,"Initializing " .. kernel.getName())
|
|
||||||
kerneldraw.bootDelay(1)
|
|
||||||
kerneldraw.bootScreen(enableBootScreen,0,logo,slogo,"Loading system libraries")
|
|
||||||
kernel.loadSysLibs()
|
|
||||||
local oldReadOnly = _G["fs"]["isReadOnly"]
|
|
||||||
local oldMove = _G["fs"]["move"]
|
|
||||||
local oldDelete = _G["fs"]["delete"]
|
|
||||||
local oldHttpGet = _G["http"]["get"]
|
|
||||||
local oldError = _G["error"]
|
|
||||||
kerneldraw.bootDelay(1)
|
|
||||||
kerneldraw.bootScreen(enableBootScreen,10,logo,slogo,"Initializing logs")
|
|
||||||
kerneldraw.bootDelay(0.5)
|
|
||||||
kernel.writeBootLog("Initialized system boot log")
|
|
||||||
kernel.writeSyslog("Initialized primary system log")
|
|
||||||
kernel.writeMessage("Initialized secondary system log")
|
|
||||||
kerneldraw.bootScreen(enableBootScreen,13,logo,slogo,"Initializing logs")
|
|
||||||
kernel.writeSecurity("Initialized security/access log")
|
|
||||||
kernel.writeShutdown("Initialized shutdown log")
|
|
||||||
kernel.writeAuth("Initialized authorization log")
|
|
||||||
kerneldraw.bootDelay(0.25)
|
|
||||||
kerneldraw.bootScreen(enableBootScreen,15,logo,slogo,"Initializing HTTP")
|
|
||||||
if http then
|
|
||||||
kernel.writeBootLog("HTTP detection succeeded")
|
|
||||||
else
|
|
||||||
kernel.writeBootLog("HTTP detection failed")
|
|
||||||
end
|
|
||||||
kerneldraw.bootDelay(2.1)
|
|
||||||
kerneldraw.bootScreen(enableBootScreen,27,logo,slogo,"Executing autorun")
|
|
||||||
shell.run("/etc/autorun")
|
|
||||||
kerneldraw.bootScreen(enableBootScreen,36,logo,slogo,"Loading user libraries")
|
|
||||||
kernel.loadUsrLibs()
|
|
||||||
kerneldraw.bootDelay(0.25)
|
|
||||||
kerneldraw.bootScreen(enableBootScreen,44,logo,slogo,"Initializing security")
|
|
||||||
kernel.writeBootLog("Initializing security")
|
|
||||||
_G["fs"]["isReadOnly"] = function(path)
|
|
||||||
local find1 = shell.resolve(path)
|
|
||||||
if string.find(find1, "boot") or string.find(find1, "etc") or string.find(find1, "bin") or string.find(find1, "sbin") then
|
|
||||||
kernel.writeSecurity("Attempt to access system files!")
|
|
||||||
if security.getSU() or _IDENTIFIER then
|
|
||||||
kernel.writeSecurity("Superuser access verified.")
|
|
||||||
return false
|
|
||||||
else
|
|
||||||
kernel.writeSecurity("Attempt blocked.")
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
elseif find1 == "initrd" or find1 == "/boot/kernel" then
|
|
||||||
kernel.writeSecurity("Attempt to access bootloader!")
|
|
||||||
kernel.writeSecurity("Attempt blocked.")
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
return oldReadOnly(path)
|
|
||||||
end
|
|
||||||
_G["fs"]["move"] = function(path1, path2)
|
|
||||||
local find2 = shell.resolve(path1)
|
|
||||||
if string.find(find2, "boot") or string.find(find2, "etc") or string.find(find2, "bin") or string.find(find2, "sbin") then
|
|
||||||
kernel.writeSecurity("Attempt to access system files!")
|
|
||||||
if security.getSU() or _IDENTIFIER then
|
|
||||||
kernel.writeSecurity("Superuser access verified.")
|
|
||||||
else
|
|
||||||
kernel.writeSecurity("Attempt blocked.")
|
|
||||||
exception.throw("RestrictedOpsException")
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
elseif find2 == "initrd" or find2 == "/boot/kernel" then
|
|
||||||
kernel.writeSecurity("Attempt to access bootloader!")
|
|
||||||
kernel.writeSecurity("Attempt blocked.")
|
|
||||||
exception.throw("RestrictedOpsException")
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
return oldMove(path1, path2)
|
|
||||||
end
|
|
||||||
_G["fs"]["delete"] = function(path)
|
|
||||||
local find3 = shell.resolve(path)
|
|
||||||
if string.find(find3, "boot") or string.find(find3, "etc") or string.find(find3, "bin") or string.find(find3, "sbin") then
|
|
||||||
kernel.writeSecurity("Attempt to access system files!")
|
|
||||||
if security.getSU() or _IDENTIFIER then
|
|
||||||
kernel.writeSecurity("Superuser access verified.")
|
|
||||||
else
|
|
||||||
kernel.writeSecurity("Attempt blocked.")
|
|
||||||
exception.throw("RestrictedOpsException")
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
elseif find3 == "initrd" or find3 == "/boot/kernel" then
|
|
||||||
kernel.writeSecurity("Attempt to access bootloader!")
|
|
||||||
kernel.writeSecurity("Attempt blocked.")
|
|
||||||
exception.throw("RestrictedOpsException")
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
return oldDelete(path)
|
|
||||||
end
|
|
||||||
_G["http"]["get"] = function(url, headers)
|
|
||||||
kernel.writeSecurity("Downloaded contents of "..url)
|
|
||||||
return oldHttpGet(url, headers)
|
|
||||||
end
|
|
||||||
_G["error"] = function(text, lvl)
|
|
||||||
local x = lvl or 2
|
|
||||||
local logger = fs.open("/etc/errorLog", "a")
|
|
||||||
logger.writeLine(tostring(os.day()).."d:"..textutils.formatTime(os.time(), true).." | "..text)
|
|
||||||
logger.close()
|
|
||||||
oldError(text, x or 1)
|
|
||||||
end
|
|
||||||
rawset(fs, "_native", {})
|
|
||||||
rawset(fs, "_native.check", oldReadOnly)
|
|
||||||
rawset(fs, "_native.move", oldMove)
|
|
||||||
rawset(fs, "_native.delete", oldDelete)
|
|
||||||
rawset(http, "_synchronise", oldHttpGet)
|
|
||||||
rawset(os, "_exception", oldError)
|
|
||||||
kerneldraw.bootDelay(3.6)
|
|
||||||
kernel.writeBootLog("Boot sequence stage 2 complete")
|
|
||||||
kerneldraw.bootScreen(enableBootScreen,86,logo,slogo,"Finishing")
|
|
||||||
kerneldraw.bootDelay(3)
|
|
||||||
if doSystemSetup then
|
|
||||||
if enableBootScreen then
|
|
||||||
kerneldraw.clearScreen(colors.black)
|
|
||||||
end
|
|
||||||
local isLogsEnabled = kernel.printLog
|
|
||||||
kernel.printLog = true
|
|
||||||
if kernel.setupSystem() then
|
|
||||||
settings.set("doSystemSetup","false")
|
|
||||||
settings.save("/boot/freax/boot.conf")
|
|
||||||
else
|
|
||||||
kernel.printLog = isLogsEnabled
|
|
||||||
kernel.poweroff(true)
|
|
||||||
end
|
|
||||||
kernel.printLog = isLogsEnabled
|
|
||||||
end
|
|
||||||
kerneldraw.bootScreen(enableBootScreen,100,logo,slogo,"Starting login")
|
|
||||||
kerneldraw.bootDelay(0.5)
|
|
||||||
kernel.printLog = true
|
|
||||||
if enableBootScreen then
|
|
||||||
kerneldraw.clearScreen(colors.black)
|
|
||||||
end
|
|
||||||
shell.run("/sbin/login")
|
|
|
@ -1,376 +0,0 @@
|
||||||
print("freax: loading")
|
|
||||||
|
|
||||||
local printLog = false
|
|
||||||
local isBooting = false
|
|
||||||
|
|
||||||
function setupSystem()
|
|
||||||
kerneldraw.printKernelMessage("Starting system setup")
|
|
||||||
kerneldraw.printKernelMessage("Please enter a new root password")
|
|
||||||
kerneldraw.printKernelAsking("Password:")
|
|
||||||
local passwd = secureInputReturn("")
|
|
||||||
if security.passbyte("root", passwd) then
|
|
||||||
kerneldraw.printKernelMessage("Changed password of the root user")
|
|
||||||
while true do
|
|
||||||
kerneldraw.printKernelMessage("Do you want to add another user?")
|
|
||||||
kerneldraw.printKernelAsking("[y/n]: ")
|
|
||||||
local add_user = "n"
|
|
||||||
add_user = read()
|
|
||||||
if add_user == "y" or add_user == "Y" then
|
|
||||||
local username = nil
|
|
||||||
local password = nil
|
|
||||||
kerneldraw.printKernelAsking("Username: ")
|
|
||||||
username = read()
|
|
||||||
if username == nil or username == "" then
|
|
||||||
kerneldraw.printKernelMessage("Invalid username")
|
|
||||||
break
|
|
||||||
end
|
|
||||||
kerneldraw.printKernelAsking("Password:")
|
|
||||||
password = secureInputReturn("")
|
|
||||||
if password == nil or password == "" then
|
|
||||||
kerneldraw.printKernelMessage("Invalid password")
|
|
||||||
end
|
|
||||||
if security.passbyte(username,password) then
|
|
||||||
log.writeSecurity("User ".. username .." added")
|
|
||||||
fs.makeDir("/home/" .. username)
|
|
||||||
else
|
|
||||||
kerneldraw.printKernelMessage("Failed to add user " .. username)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
else
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
kerneldraw.printKernelMessage("System setup completed")
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
kerneldraw.printKernelMessage("Failed to change the password. Shutting down in 3 seconds")
|
|
||||||
sleep(3)
|
|
||||||
reboot(true)
|
|
||||||
return(false)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function initLogger(file)
|
|
||||||
if not fs.isDir("/var") and not fs.exists("/var/log") and not fs.isDir("/var/log") then
|
|
||||||
fs.makeDir("/var")
|
|
||||||
fs.makeDir("/var/log")
|
|
||||||
end
|
|
||||||
return "/var/log/" .. file
|
|
||||||
end
|
|
||||||
|
|
||||||
function halt()
|
|
||||||
writeKernelCall("halt()")
|
|
||||||
sleep(1)
|
|
||||||
writeShutdown("halting")
|
|
||||||
while true do
|
|
||||||
coroutine.create(function() while true do coroutine.yield() end end)
|
|
||||||
coroutine.yield()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function poweroff(varDelete)
|
|
||||||
if varDelete then
|
|
||||||
writeKernelCall("poweroff(true)")
|
|
||||||
else
|
|
||||||
writeKernelCall("poweroff(false)")
|
|
||||||
end
|
|
||||||
writeShutdown("Reaching system poweroff")
|
|
||||||
if varDelete then
|
|
||||||
writeShutdown("Removing temporary files")
|
|
||||||
if fs.exists("/var") and fs.isDir("/var") then
|
|
||||||
fs.delete("/var")
|
|
||||||
end
|
|
||||||
sleep(1)
|
|
||||||
end
|
|
||||||
writeShutdown("Reached system poweroff")
|
|
||||||
sleep(1)
|
|
||||||
os.shutdown()
|
|
||||||
halt()
|
|
||||||
end
|
|
||||||
|
|
||||||
function reboot(varDelete)
|
|
||||||
if varDelete then
|
|
||||||
writeKernelCall("reboot(true)")
|
|
||||||
else
|
|
||||||
writeKernelCall("reboot(false)")
|
|
||||||
end
|
|
||||||
writeShutdown("Reaching system reboot")
|
|
||||||
if varDelete then
|
|
||||||
sleep(0.5)
|
|
||||||
writeShutdown("Removing temporary files")
|
|
||||||
if fs.exists("/var") and fs.isDir("/var") then
|
|
||||||
fs.delete("/var")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
writeShutdown("Reached system reboot")
|
|
||||||
sleep(1.5)
|
|
||||||
os.reboot()
|
|
||||||
halt()
|
|
||||||
end
|
|
||||||
|
|
||||||
function panic(text)
|
|
||||||
writeKernelCall("panic(" .. text .. ")")
|
|
||||||
local logger = fs.open("/etc/errorLog", "a")
|
|
||||||
logger.writeLine(tostring(os.day()).. "d:" ..textutils.formatTime(os.time(), true).. " | panic! " ..text)
|
|
||||||
logger.close()
|
|
||||||
printError("freax: panic! " .. text)
|
|
||||||
halt()
|
|
||||||
end
|
|
||||||
|
|
||||||
function import(file)
|
|
||||||
writeKernelCall("import(" .. file .. ")")
|
|
||||||
if fs.exists(file) and not fs.isDir(file) then
|
|
||||||
return os.loadAPI(file)
|
|
||||||
else
|
|
||||||
writeSyslog("Failed to load API " .. file)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function require(file) -- A primitive require
|
|
||||||
writeKernelCall("require(" .. file .. ")")
|
|
||||||
if fs.exists(file) and not fs.isDir(file) then
|
|
||||||
return dofile(file)
|
|
||||||
else
|
|
||||||
writeSyslog("Failed to load module " .. file)
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function APIHook(t)
|
|
||||||
writeKernelCall("APIHook(" .. t .. ")")
|
|
||||||
if t then
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
-- Not loaded
|
|
||||||
if import("/system/api/" .. t) then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
function writeKernelCall(calledFunc)
|
|
||||||
--kerneldraw.printKernelMessage("Function called: " .. calledFunc)
|
|
||||||
local logger = fs.open(initLogger("calls"), "a")
|
|
||||||
logger.writeLine(tostring(os.day()) .. "d:" .. textutils.formatTime(os.time(),true) .. " | Function called: " .. calledFunc)
|
|
||||||
logger.close()
|
|
||||||
end
|
|
||||||
|
|
||||||
function writeSyslog(text)
|
|
||||||
writeKernelCall("writeSyslog(" .. text .. ")")
|
|
||||||
kerneldraw.printKernelMessage(text)
|
|
||||||
local logger = fs.open(initLogger("syslog"), "a")
|
|
||||||
logger.writeLine(tostring(os.day()).. "d:" ..textutils.formatTime(os.time(), true).. " | " ..text)
|
|
||||||
logger.close()
|
|
||||||
end
|
|
||||||
|
|
||||||
function writeMessage(text)
|
|
||||||
writeKernelCall("writeMessage(" .. text .. ")")
|
|
||||||
kerneldraw.printKernelMessage(text)
|
|
||||||
local logger = fs.open(initLogger("messages"), "a")
|
|
||||||
logger.writeLine(tostring(os.day()).. "d:" ..textutils.formatTime(os.time(), true).. " | " ..text)
|
|
||||||
logger.close()
|
|
||||||
end
|
|
||||||
|
|
||||||
function writeSecurity(text)
|
|
||||||
writeKernelCall("writeSecurity(" .. text .. ")")
|
|
||||||
kerneldraw.printKernelMessage(text)
|
|
||||||
local logger = fs.open(initLogger("security"), "a")
|
|
||||||
logger.writeLine(tostring(os.day()).. "d:" ..textutils.formatTime(os.time(), true).. " | " ..text)
|
|
||||||
logger.close()
|
|
||||||
end
|
|
||||||
|
|
||||||
function writeShutdown(text)
|
|
||||||
writeKernelCall("writeShutdown(" .. text .. ")")
|
|
||||||
kerneldraw.printKernelMessage(text)
|
|
||||||
local logger = fs.open(initLogger("shutdown"), "a")
|
|
||||||
logger.writeLine(tostring(os.day()).. "d:" ..textutils.formatTime(os.time(), true).. " | " ..text)
|
|
||||||
logger.close()
|
|
||||||
end
|
|
||||||
|
|
||||||
function writeAuth(text)
|
|
||||||
writeKernelCall("writeAuth(" .. text .. ")")
|
|
||||||
kerneldraw.printKernelMessage(text)
|
|
||||||
local logger = fs.open(initLogger("auth"), "a")
|
|
||||||
logger.writeLine(tostring(os.day()).. "d:" ..textutils.formatTime(os.time(), true).. " | " ..text)
|
|
||||||
logger.close()
|
|
||||||
end
|
|
||||||
|
|
||||||
function writeBootLog(text)
|
|
||||||
writeKernelCall("writeBootLog(" .. text .. ")")
|
|
||||||
kerneldraw.printKernelMessage(text)
|
|
||||||
local logger = fs.open(initLogger("boot"), "a")
|
|
||||||
logger.writeLine(tostring(os.day()).. "d:" ..textutils.formatTime(os.time(), true).. " | " ..text)
|
|
||||||
logger.close()
|
|
||||||
end
|
|
||||||
|
|
||||||
function loadSysLibs()
|
|
||||||
writeKernelCall("loadSysLibs()")
|
|
||||||
writeBootLog("Loading system libraries")
|
|
||||||
local flist = fs.list("/etc/lib")
|
|
||||||
for _, file in ipairs(flist) do
|
|
||||||
sleep(0.25)
|
|
||||||
local returnValue = import("/etc/lib/" ..file)
|
|
||||||
if returnValue then
|
|
||||||
writeSyslog("Library " .. file .. " loaded")
|
|
||||||
else
|
|
||||||
writeSysLog("Library " .. file .. " failed to load")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function loadUsrLibs()
|
|
||||||
writeKernelCall("loadUsrLibs()")
|
|
||||||
writeBootLog("Loading user libraries")
|
|
||||||
local flist = fs.list("/usr/local/lib")
|
|
||||||
for _, file in ipairs(flist) do
|
|
||||||
sleep(0.25)
|
|
||||||
local returnValue = import("/usr/local/lib/" ..file)
|
|
||||||
if returnValue then
|
|
||||||
writeSyslog("Library " .. file .. " loaded")
|
|
||||||
else
|
|
||||||
writeSysLog("Library " .. file .. " failed to load")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function printFile(file)
|
|
||||||
writeKernelCall("printFile(" .. file .. ")")
|
|
||||||
if fs.exists(file) and not fs.isDir(file) then
|
|
||||||
local handle = fs.open(file, "r")
|
|
||||||
local contents = handle.readAll()
|
|
||||||
handle.close()
|
|
||||||
return contents
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function getURLContents(url)
|
|
||||||
writeKernelCall("getURLContents(" .. url .. ")")
|
|
||||||
local handlex = http.get(url)
|
|
||||||
local contents = handlex.readAll()
|
|
||||||
handlex.close()
|
|
||||||
return contents
|
|
||||||
end
|
|
||||||
|
|
||||||
function getFile(file, url, overwrite)
|
|
||||||
writeKernelCall("getFile(" .. file .. "," .. url .. "," .. overwrite .. ")")
|
|
||||||
if not fs.exists(file) then
|
|
||||||
local handle = fs.open(file, "w")
|
|
||||||
handle.writeLine(getURLContents(url))
|
|
||||||
handle.close()
|
|
||||||
return true
|
|
||||||
elseif overwrite and not fs.isDir(file) then
|
|
||||||
local handle = fs.open(file, "w")
|
|
||||||
handle.writeLine(getURLContents(url))
|
|
||||||
handle.close()
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
function secureInput(invite, definition)
|
|
||||||
writeKernelCall("secureInput(" .. invite .. "," .. definition .. ")")
|
|
||||||
write(invite.. " ")
|
|
||||||
local input = read("*")
|
|
||||||
if input == definition then
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function secureInputReturn(invite)
|
|
||||||
writeKernelCall("secureInput(" .. invite .. ")")
|
|
||||||
write(invite.. " ")
|
|
||||||
local input = read("*")
|
|
||||||
return input
|
|
||||||
end
|
|
||||||
|
|
||||||
function getName()
|
|
||||||
writeKernelCall("getName()")
|
|
||||||
return "FREAX Kernel"
|
|
||||||
end
|
|
||||||
|
|
||||||
function getVersion()
|
|
||||||
writeKernelCall("getVersion()")
|
|
||||||
return "d0.0.1.0"
|
|
||||||
end
|
|
||||||
|
|
||||||
function getRelease()
|
|
||||||
writeKernelCall("getRelease()")
|
|
||||||
return getName() .. " " .. getVersion()
|
|
||||||
end
|
|
||||||
|
|
||||||
function getMachine()
|
|
||||||
writeKernelCall("getMachine()")
|
|
||||||
if turtle then
|
|
||||||
if commands then
|
|
||||||
return "Command Turtle"
|
|
||||||
elseif term.isColor() then
|
|
||||||
return "Advanced Turtle"
|
|
||||||
else
|
|
||||||
return "Turtle"
|
|
||||||
end
|
|
||||||
elseif pocket then
|
|
||||||
if commands then
|
|
||||||
return "Command Pocket Computer"
|
|
||||||
elseif term.isColor() then
|
|
||||||
return "Advanced Pocket Computer"
|
|
||||||
else
|
|
||||||
return "Pocket Computer"
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if commands then
|
|
||||||
return "Command Computer"
|
|
||||||
elseif term.isColor() then
|
|
||||||
return "Advanced Computer"
|
|
||||||
else
|
|
||||||
return "Computer"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function getProcessorArchitecture()
|
|
||||||
writeKernelCall("getProcessorArchitecture()")
|
|
||||||
return "lua"
|
|
||||||
end
|
|
||||||
|
|
||||||
function getHardwarePlatform()
|
|
||||||
writeKernelCall("getHardwarePlatform()")
|
|
||||||
return "ComputerCraft"
|
|
||||||
end
|
|
||||||
|
|
||||||
function getOS()
|
|
||||||
writeKernelCall("getOS()")
|
|
||||||
return "FREAX"
|
|
||||||
end
|
|
||||||
|
|
||||||
function getHostname()
|
|
||||||
writeKernelCall("getHostname()")
|
|
||||||
if os.getComputerLabel() == nil then
|
|
||||||
return getOS()
|
|
||||||
else
|
|
||||||
return os.getComputerLabel()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function setHostname(hostname)
|
|
||||||
writeKernelCall("setHostname()")
|
|
||||||
local returncode os.setComputerLabel(hostname)
|
|
||||||
kerneldraw.printAppInfo("net","Changed hostname to " .. hostname)
|
|
||||||
kernel.writeMessage("Changed hostname to " .. hostname)
|
|
||||||
return returncode
|
|
||||||
end
|
|
||||||
|
|
||||||
function numRound(num)
|
|
||||||
return num>=0 and math.floor(num+0.5) or math.ceil(num-0.5)
|
|
||||||
end
|
|
||||||
|
|
||||||
function string2table(string_convert)
|
|
||||||
local table = {}
|
|
||||||
string_convert:sub(".",function(c) table.insert(table,c) end)
|
|
||||||
return table
|
|
||||||
end
|
|
||||||
|
|
||||||
print("freax: loaded")
|
|
|
@ -1,286 +0,0 @@
|
||||||
termw,termh = term.getSize()
|
|
||||||
|
|
||||||
function clearScreen(color)
|
|
||||||
term.setBackgroundColor(color or colors.black)
|
|
||||||
term.setCursorPos(1,1)
|
|
||||||
term.clear()
|
|
||||||
end
|
|
||||||
|
|
||||||
function button(text, x1, x2, y)
|
|
||||||
term.setCursorPos(x1, y)
|
|
||||||
print(text)
|
|
||||||
local a, b, xx, yy = os.pullEvent("mouse_click")
|
|
||||||
if (xx >= x1 and xx <= x2 and yy == y) then
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function counter(text, y)
|
|
||||||
for i=1,100 do
|
|
||||||
sleep(0.1)
|
|
||||||
term.setCursorPos(1, y)
|
|
||||||
print(text.." ["..tostring(i).."%]")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function drawProgress(txt, y)
|
|
||||||
term.setCursorPos(4, 4)
|
|
||||||
print(txt)
|
|
||||||
term.setCursorPos(1, y)
|
|
||||||
print("[ ]")
|
|
||||||
term.setCursorPos(2, y)
|
|
||||||
textutils.slowPrint("==============================]", 10)
|
|
||||||
end
|
|
||||||
|
|
||||||
function drawProgressAlt(color)
|
|
||||||
term.setCursorPos(4, 10)
|
|
||||||
print("#-------------------------------------------#")
|
|
||||||
term.setCursorPos(4, 11)
|
|
||||||
print("| |")
|
|
||||||
term.setCursorPos(4, 12)
|
|
||||||
print("#-------------------------------------------#")
|
|
||||||
term.setBackgroundColor(color or colors.yellow)
|
|
||||||
term.setCursorPos(5, 11)
|
|
||||||
textutils.slowWrite(" ", 10)
|
|
||||||
term.setBackgroundColor(colors.black)
|
|
||||||
end
|
|
||||||
|
|
||||||
function printColoredTextLine(y, txt, centered,bg, fg)
|
|
||||||
term.setCursorPos(1, y)
|
|
||||||
term.setBackgroundColor(bg or colors.lightGray)
|
|
||||||
term.write(" ")
|
|
||||||
if centered then
|
|
||||||
term.setCursorPos(termw/2-(string.len(txt)/2-1),y)
|
|
||||||
else
|
|
||||||
term.setCursorPos(1, y)
|
|
||||||
end
|
|
||||||
term.setTextColor(fg or colors.black)
|
|
||||||
print(txt)
|
|
||||||
term.setBackgroundColor(colors.black)
|
|
||||||
term.setTextColor(colors.white)
|
|
||||||
end
|
|
||||||
|
|
||||||
function printColoredProgressTextLine(y, txt, progress, bgn, fgn, bgp, fgp)
|
|
||||||
if progress >= 101 then
|
|
||||||
kernel.panic("progress can't be over 100 (printColoredProgressTextLine in kerneldraw)")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local progress_max = termw
|
|
||||||
local progress_cur
|
|
||||||
if progress >= 2 then
|
|
||||||
if progress_max == 51 then
|
|
||||||
progress_cur = kernel.numRound(progress/1.96078431357)
|
|
||||||
else
|
|
||||||
kernel.panic("monitor has a invalid width that hasn't been programmed in (printColoredProgressTextLine in kerneldraw)")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
else
|
|
||||||
progress_cur = progress
|
|
||||||
end
|
|
||||||
local txt_progress = nil
|
|
||||||
local txt_normal = nil
|
|
||||||
local progresstxt_tmp = nil
|
|
||||||
if progress_cur >= 1 then
|
|
||||||
if progress_cur >= string.len(txt)+1 then
|
|
||||||
txt_progress = txt
|
|
||||||
progresstxttmp = progress_cur-string.len(txt)
|
|
||||||
repeat
|
|
||||||
txt_progress = txt_progress .. " "
|
|
||||||
until progresstxttmp <= 0
|
|
||||||
else
|
|
||||||
txt_progress = string.sub(txt,1,progress_cur)
|
|
||||||
txt_normal = string.sub(txt,progress_cur,string.len(txt))
|
|
||||||
end
|
|
||||||
else
|
|
||||||
txt_progress = ""
|
|
||||||
txt_normal = txt
|
|
||||||
end
|
|
||||||
term.setCursorPos(1,1)
|
|
||||||
term.setBackgroundColor(colors.gray)
|
|
||||||
term.setTextColor(colors.white)
|
|
||||||
print("progress:" .. progress)
|
|
||||||
print("progress_max:" .. progress_max)
|
|
||||||
print("progress_cur:" .. progress_cur)
|
|
||||||
print("txt_progress:" .. txt_progress)
|
|
||||||
print("txt_normal:" .. txt_normal)
|
|
||||||
term.setCursorPos(1, y)
|
|
||||||
term.setBackgroundColor(bgn or colors.purple)
|
|
||||||
term.write(" ")
|
|
||||||
term.setCursorPos(1, y)
|
|
||||||
term.setTextColor(fgp or colors.black)
|
|
||||||
term.setBackgroundColor(bgp or colors.white)
|
|
||||||
print(txt_progress)
|
|
||||||
if not txt_progress == "" then
|
|
||||||
term.setCursorPos(string.len(txt_progress)+1,y)
|
|
||||||
end
|
|
||||||
term.setTextColor(fgn or colors.white)
|
|
||||||
term.setBackgroundColor(bgn or colors.purple)
|
|
||||||
print(txt_normal)
|
|
||||||
term.setBackgroundColor(colors.black)
|
|
||||||
term.setTextColor(colors.white)
|
|
||||||
end
|
|
||||||
|
|
||||||
function printBootInfo(i)
|
|
||||||
term.setBackgroundColor(colors.black)
|
|
||||||
term.setTextColor(colors.lightGray)
|
|
||||||
write("")
|
|
||||||
term.setTextColor(colors.cyan)
|
|
||||||
write("*")
|
|
||||||
term.setTextColor(colors.lightGray)
|
|
||||||
write(" ")
|
|
||||||
print(" "..i)
|
|
||||||
term.setTextColor(colors.white)
|
|
||||||
if log then
|
|
||||||
log.writeBootLog(i)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function printBootWarning(w)
|
|
||||||
term.setBackgroundColor(colors.black)
|
|
||||||
term.setTextColor(colors.lightGray)
|
|
||||||
write("")
|
|
||||||
term.setTextColor(colors.orange)
|
|
||||||
write("!")
|
|
||||||
term.setTextColor(colors.lightGray)
|
|
||||||
write(" ")
|
|
||||||
print(" "..w)
|
|
||||||
term.setTextColor(colors.white)
|
|
||||||
if log then
|
|
||||||
log.writeBootLog(w)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function printBootSuccess(wa)
|
|
||||||
term.setBackgroundColor(colors.black)
|
|
||||||
term.setTextColor(colors.lightGray)
|
|
||||||
write("")
|
|
||||||
term.setTextColor(colors.lime)
|
|
||||||
write("v")
|
|
||||||
term.setTextColor(colors.lightGray)
|
|
||||||
write(" ")
|
|
||||||
print(" "..wa)
|
|
||||||
term.setTextColor(colors.white)
|
|
||||||
if log then
|
|
||||||
log.writeBootLog(wa)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function printAppInfo(header, msg)
|
|
||||||
term.setTextColor(colors.cyan)
|
|
||||||
write(header..": ")
|
|
||||||
term.setTextColor(colors.lightGray)
|
|
||||||
print(msg)
|
|
||||||
term.setTextColor(colors.white)
|
|
||||||
end
|
|
||||||
|
|
||||||
function printAppWarning(header, msg)
|
|
||||||
term.setTextColor(colors.red)
|
|
||||||
write(header..": ")
|
|
||||||
term.setTextColor(colors.orange)
|
|
||||||
print(msg)
|
|
||||||
term.setTextColor(colors.white)
|
|
||||||
end
|
|
||||||
|
|
||||||
function printAppSuccess(header, msg)
|
|
||||||
term.setTextColor(colors.lime)
|
|
||||||
write(header..": ")
|
|
||||||
term.setTextColor(colors.green)
|
|
||||||
print(msg)
|
|
||||||
term.setTextColor(colors.white)
|
|
||||||
end
|
|
||||||
|
|
||||||
function printKernelMessage(msg)
|
|
||||||
if kernel.printLog then
|
|
||||||
term.setTextColor(colors.blue)
|
|
||||||
write("freax: ")
|
|
||||||
term.setTextColor(colors.lightBlue)
|
|
||||||
print(msg)
|
|
||||||
term.setTextColor(colors.white)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function printKernelAsking(msg)
|
|
||||||
if kernel.printLog then
|
|
||||||
term.setTextColor(colors.blue)
|
|
||||||
write("freax: ")
|
|
||||||
term.setTextColor(colors.lightBlue)
|
|
||||||
write(msg)
|
|
||||||
term.setTextColor(colors.white)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function request(req)
|
|
||||||
while true do
|
|
||||||
term.setTextColor(colors.cyan)
|
|
||||||
write(req .. "? ")
|
|
||||||
term.setTextColor(colors.lightGray)
|
|
||||||
write("(")
|
|
||||||
term.setTextColor(colors.lime)
|
|
||||||
write("Y")
|
|
||||||
term.setTextColor(colors.lightGray)
|
|
||||||
write("/")
|
|
||||||
term.setTextColor(colors.red)
|
|
||||||
write("N")
|
|
||||||
term.setTextColor(colors.lightGray)
|
|
||||||
write(") ")
|
|
||||||
local presel=read()
|
|
||||||
if presel=="Y" or presel=="y" then
|
|
||||||
return true
|
|
||||||
elseif presel=="N" or presel=="n" then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function drawImg(path, x, y)
|
|
||||||
if fs.exists(path) and not fs.isDir(path) then
|
|
||||||
local img = paintutils.loadImage(path)
|
|
||||||
paintutils.drawImage(img, x, y)
|
|
||||||
else
|
|
||||||
printAppWarning("gui", "Image not found")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function drawImgArg(img, x, y)
|
|
||||||
paintutils.drawImage(img, x, y)
|
|
||||||
end
|
|
||||||
|
|
||||||
function printColored(text, color)
|
|
||||||
local tmp = term.getTextColor()
|
|
||||||
term.setTextColor(color)
|
|
||||||
print(text)
|
|
||||||
term.setTextColor(tmp)
|
|
||||||
end
|
|
||||||
|
|
||||||
function bootScreen(enable,progress,logo,logo_small,txt)
|
|
||||||
if enable then
|
|
||||||
clearScreen(colors.black)
|
|
||||||
local check_size = termw
|
|
||||||
local logo_size = 38
|
|
||||||
local logo_small_size = 20
|
|
||||||
if check_size == logo_size then
|
|
||||||
drawImgArg(logo, 1,5)
|
|
||||||
elseif check_size >= logo_size then
|
|
||||||
drawImgArg(logo, (termw/2)-(logo_size/2)+1, 5)
|
|
||||||
elseif check_size == logo_small_size then
|
|
||||||
drawImgArg(logo_small, 1,5)
|
|
||||||
elseif check_size >= logo_small_size then
|
|
||||||
drawImgArg(logo_small, (termw/2)-(logo_small_size/2)+1, 5)
|
|
||||||
end
|
|
||||||
printColoredTextLine(termh-1, txt, true, colors.black, colors.white)
|
|
||||||
--printColoredProgressTextLine(termh-1, txt, progress, colors.black, colors.white, colors.purple, colors.white)
|
|
||||||
--printColoredProgressTextLine(termh-1, txt, progress)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function bootDelay(delay)
|
|
||||||
local enableSleeps = true -- Disabled sleeps
|
|
||||||
local enableDisabledSleep = false -- Disables 0.1 sleep when disabled
|
|
||||||
if enableSleeps then
|
|
||||||
sleep(delay)
|
|
||||||
elseif enableDisabledSleep then
|
|
||||||
sleep(0.1)
|
|
||||||
end
|
|
||||||
end
|
|
83
boot/ofbl
83
boot/ofbl
|
@ -1,83 +0,0 @@
|
||||||
--rawset(_G, "nativepullevent", os.pullEvent)
|
|
||||||
os.pullEvent = os.pullEventRaw
|
|
||||||
|
|
||||||
enableSleeps = true
|
|
||||||
function string2table(string_convert)
|
|
||||||
local table = {}
|
|
||||||
string_convert:sub(".",function(c) table.insert(table,c) end)
|
|
||||||
return table
|
|
||||||
end
|
|
||||||
|
|
||||||
if not term.isColour() then
|
|
||||||
printError("ofbl: OFBL and FREAX only supports")
|
|
||||||
printError("ofbl: advanced (pocket) computers")
|
|
||||||
sleep(3)
|
|
||||||
os.shutdown()
|
|
||||||
end
|
|
||||||
print("ofbl: conf: Loading")
|
|
||||||
if enableSleeps then sleep(0.3) else sleep(0.1) end
|
|
||||||
local config = {}
|
|
||||||
local name = nil
|
|
||||||
local initrd = nil
|
|
||||||
local kernel = nil
|
|
||||||
local kerneldraw = nil
|
|
||||||
if fs.exists("/boot/ofbl.conf") then
|
|
||||||
settings.load("/boot/ofbl.conf")
|
|
||||||
--config.oslist = string2table(settings.get("oslist"))
|
|
||||||
name = settings.get("os0.name")
|
|
||||||
initrd = settings.get("os0.initrd")
|
|
||||||
kernel = settings.get("os0.kernel")
|
|
||||||
kerneldraw = settings.get("os0.kerneldraw")
|
|
||||||
if name == nil then
|
|
||||||
print("ofbl: conf: name is null")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if initrd == nil then
|
|
||||||
print("ofbl: conf: initrd is null")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if kernel == nil then
|
|
||||||
print("ofbl: conf: kernel is null")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if kerneldraw == nil then
|
|
||||||
print("ofbl: conf: kerneldraw is null")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
else
|
|
||||||
print("ofbl: conf: Not found")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
print("ofbl: Copying kernel and initrd.img into RAM")
|
|
||||||
if enableSleeps then sleep(0.1) else sleep(0.1) end
|
|
||||||
fs.delete("/var/boot")
|
|
||||||
if not fs.isDir("/var") and not fs.exists("/var/boot") and not fs.isDir("/var/boot") then
|
|
||||||
fs.makeDir("/var")
|
|
||||||
fs.makeDir("/var/boot")
|
|
||||||
end
|
|
||||||
if fs.exists(kernel) then
|
|
||||||
if fs.exists(kerneldraw) then
|
|
||||||
if fs.exists(initrd) then
|
|
||||||
fs.copy(initrd,"/var/boot/initrd")
|
|
||||||
fs.copy(kernel,"/var/boot/kernel")
|
|
||||||
fs.copy(kerneldraw,"/var/boot/kerneldraw")
|
|
||||||
else
|
|
||||||
print("ofbl: " .. initrd .. " not found")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
else
|
|
||||||
print("ofbl: " .. kerneldraw .. " not found")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
else
|
|
||||||
print("ofbl: " .. kernel .. " not found")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if enableSleeps then sleep(1.95) else sleep(0.1) end
|
|
||||||
print("ofbl: Loading kernel")
|
|
||||||
if enableSleeps then sleep(3.25) else sleep(0.1) end
|
|
||||||
os.loadAPI("/var/boot/kernel")
|
|
||||||
os.loadAPI("/var/boot/kerneldraw")
|
|
||||||
print("ofbl: Loading initrd.img")
|
|
||||||
if enableSleeps then sleep(2.65) else sleep(0.1) end
|
|
||||||
shell.execute(initrd)
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
[ "oslist"] = "0",
|
|
||||||
[ "os0.name" ] = "FREAX",
|
|
||||||
[ "os0.initrd" ] = "/boot/freax/initrd.img",
|
|
||||||
[ "os0.kernel" ] = "/boot/freax/kernel.boot",
|
|
||||||
[ "os0.kerneldraw" ] = "/boot/freax/kerneldraw.boot",
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
local oldPath = shell.path()
|
|
||||||
shell.setPath(":/bin:/sbin:/etc/script_util:/usr/bin:/usr/local/bin")
|
|
||||||
|
|
||||||
local link = config.load("/etc/link.dat")
|
|
||||||
|
|
||||||
for k,v in pairs(link) do
|
|
||||||
shell.setAlias(k, v)
|
|
||||||
end
|
|
|
@ -1,2 +0,0 @@
|
||||||
207d:19:39 | Cannot serialize type function
|
|
||||||
208d:6:38 | 1
|
|
|
@ -1,22 +0,0 @@
|
||||||
function load(path)
|
|
||||||
if fs.exists(path) and not fs.isDir(path) then
|
|
||||||
local lf = fs.open(path, "r")
|
|
||||||
local contents = lf.readAll()
|
|
||||||
lf.close()
|
|
||||||
return textutils.unserialize(contents)
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function save(cTable, path)
|
|
||||||
if fs.exists(path) then
|
|
||||||
if fs.isDir(path) then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local sf = fs.open(path, "w")
|
|
||||||
sf.write(textutils.serialize(cTable))
|
|
||||||
sf.close()
|
|
||||||
return true
|
|
||||||
end
|
|
|
@ -1,26 +0,0 @@
|
||||||
local instances = {}
|
|
||||||
|
|
||||||
instances.GenericException = function(text)
|
|
||||||
kerneldraw.printAppWarning(fs.getName(shell.getRunningProgram()), text)
|
|
||||||
log.writeSecurity(text)
|
|
||||||
end
|
|
||||||
|
|
||||||
instances.RestrictedOpsException = function(a)
|
|
||||||
b = a or " "
|
|
||||||
kerneldraw.printAppWarning("kernel", "Attempt to perform restricted operations")
|
|
||||||
log.writeSecurity("Attempt to perform restricted operations")
|
|
||||||
log.writeSecurity("Attempt blocked.")
|
|
||||||
end
|
|
||||||
|
|
||||||
instances.SecurityException = function(path)
|
|
||||||
kerneldraw.printAppWarning("kernel", "Attempt to perform restricted operations")
|
|
||||||
log.writeSecurity(_activeUser.." Attempted to open restricted file at "..path)
|
|
||||||
end
|
|
||||||
|
|
||||||
function throw(exception, arg)
|
|
||||||
if instances[exception] then
|
|
||||||
instances[exception](arg)
|
|
||||||
else
|
|
||||||
instances.GenericException("Exception not found")
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,8 +0,0 @@
|
||||||
-- this is a compatibility file for supporting kernel-mode logging
|
|
||||||
|
|
||||||
writeSyslog = kernel.writeSyslog
|
|
||||||
writeMessage = kernel.writeMessage
|
|
||||||
writeSecurity = kernel.writeSecurity
|
|
||||||
writeShutdown = kernel.writeShutdown
|
|
||||||
writeAuth = kernel.writeAuth
|
|
||||||
writeBootLog = kernel.writeBootLog
|
|
|
@ -1,31 +0,0 @@
|
||||||
function stringToByteArray(str)
|
|
||||||
return string.byte(str, 1, str:len())
|
|
||||||
end
|
|
||||||
|
|
||||||
function argsToTable(...)
|
|
||||||
return { ... }
|
|
||||||
end
|
|
||||||
|
|
||||||
function stringFromByteArray(...)
|
|
||||||
return string.char(...)
|
|
||||||
end
|
|
||||||
|
|
||||||
function iterateFileLines(path)
|
|
||||||
local handle = fs.open(path, "r")
|
|
||||||
local commands = {}
|
|
||||||
local line = handle.readLine()
|
|
||||||
while line do
|
|
||||||
commands[#commands + 1] = line
|
|
||||||
line = handle.readLine()
|
|
||||||
end
|
|
||||||
handle.close()
|
|
||||||
return commands
|
|
||||||
end
|
|
||||||
|
|
||||||
local function string_separate(str)
|
|
||||||
local t = {}
|
|
||||||
for i in string.gmatch(str, "[A-z]") do
|
|
||||||
table.insert(t, i)
|
|
||||||
end
|
|
||||||
return t
|
|
||||||
end
|
|
12
etc/lib/man
12
etc/lib/man
|
@ -1,12 +0,0 @@
|
||||||
function findManual(name)
|
|
||||||
local flist = fs.list("/etc/manuals")
|
|
||||||
for _, file in ipairs(flist) do
|
|
||||||
if not fs.isDir("/etc/manuals/"..file) and file == name then
|
|
||||||
local handle = fs.open("/etc/manuals/"..file, "r")
|
|
||||||
local contents = handle.readAll()
|
|
||||||
handle.close()
|
|
||||||
return contents
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return "No manual available"
|
|
||||||
end
|
|
70
etc/lib/net
70
etc/lib/net
|
@ -1,70 +0,0 @@
|
||||||
local isOnline = false
|
|
||||||
|
|
||||||
function getHTTP(url)
|
|
||||||
local handlex = http.get(url)
|
|
||||||
local contents = handlex.readAll()
|
|
||||||
handlex.close()
|
|
||||||
return contents
|
|
||||||
end
|
|
||||||
|
|
||||||
function openModems()
|
|
||||||
for n,sModem in ipairs( peripheral.getNames() ) do
|
|
||||||
if peripheral.getType( sModem ) == "modem" then
|
|
||||||
if not rednet.isOpen( sModem ) then
|
|
||||||
rednet.open( sModem )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function closeModems()
|
|
||||||
for n,sModem in ipairs( peripheral.getNames() ) do
|
|
||||||
if peripheral.getType( sModem ) == "modem" then
|
|
||||||
if rednet.isOpen( sModem ) then
|
|
||||||
rednet.close( sModem )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function getModemStatus(side)
|
|
||||||
kerneldraw.printAppInfo("net", side .. " modem status: " .. tostring(rednet.isOpen(side)))
|
|
||||||
return rednet.isOpen(side)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- DNS self-hosting functions
|
|
||||||
|
|
||||||
function setWorkstationStatus(state)
|
|
||||||
if state == true and isOnline == false then
|
|
||||||
local label = os.getComputerLabel() or kernel.getOS()
|
|
||||||
rednet.host("freax_dns", tostring(os.getComputerID()).."_"..label)
|
|
||||||
isOnline = true
|
|
||||||
log.writeSyslog("Now susceptible for DNS lookup")
|
|
||||||
log.writeMessage("Assigned DNS label "..tostring(os.getComputerID()).."_"..label)
|
|
||||||
elseif state == false and isOnline == true then
|
|
||||||
local label = os.getComputerLabel or kernel.getOS()
|
|
||||||
rednet.host("freax_dns", tostring(os.getComputerID()).."_"..label)
|
|
||||||
isOnline = false
|
|
||||||
log.writeSyslog("No longer susceptible for DNS lookup")
|
|
||||||
log.writeMessage("De-assigned DNS label "..tostring(os.getComputerID()).."_"..label)
|
|
||||||
elseif state == true and isOnline == true then
|
|
||||||
kerneldraw.printAppWarning("net", "workstation already online")
|
|
||||||
elseif state == false and isOnline == false then
|
|
||||||
kerneldraw.printAppWarning("net", "workstation already offline")
|
|
||||||
else
|
|
||||||
log.writeSyslog("RedNet interface error")
|
|
||||||
return nil, "Error in RNI, please consult developer"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function getWorkstationStatus()
|
|
||||||
return isOnline
|
|
||||||
end
|
|
||||||
|
|
||||||
function findWorkstation(query)
|
|
||||||
if rednet.lookup("freax_dns", query) ~= nil then
|
|
||||||
return true, rednet.lookup("freax_dns", query)
|
|
||||||
else
|
|
||||||
return false, nil
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,53 +0,0 @@
|
||||||
function traverseKey(array, text)
|
|
||||||
for k,v in pairs(array) do
|
|
||||||
if v == text then
|
|
||||||
return true, k
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false, nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function traverseValue(array, text)
|
|
||||||
for k,v in pairs(array) do
|
|
||||||
if k == text then
|
|
||||||
return true, v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false, nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function findKey(array, text)
|
|
||||||
for k,v in pairs(array) do
|
|
||||||
if k == text then
|
|
||||||
return true, k
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false, nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function findValue(array, text)
|
|
||||||
for k,v in pairs(array) do
|
|
||||||
if v == text then
|
|
||||||
return true, v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false, nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function queryForKey(array, text)
|
|
||||||
for k,v in pairs(array) do
|
|
||||||
if string.find(k, text) then
|
|
||||||
return true, k
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false, nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function queryForValue(array, text)
|
|
||||||
for k,v in pairs(array) do
|
|
||||||
if string.find(v, text) then
|
|
||||||
return true, v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false, nil
|
|
||||||
end
|
|
|
@ -1,42 +0,0 @@
|
||||||
local _IDENTIFIER = "ac30527de6170b7d545bdc152f76237276537f2cf8eb7fe5bdb2a7627f48cec1"
|
|
||||||
|
|
||||||
function getSU()
|
|
||||||
if fs.exists("/etc/passwd/.shadow/".._G["_activeUser"]..".usr") then
|
|
||||||
local ud = dofile("/etc/passwd/.shadow/".._G["_activeUser"]..".usr")
|
|
||||||
return ud.SU
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function getID()
|
|
||||||
return _IDENTIFIER
|
|
||||||
end
|
|
||||||
|
|
||||||
function getActiveUserStatus()
|
|
||||||
if fs.exists("/etc/passwd/.shadow/".._G["_activeUser"]..".usr") then
|
|
||||||
local ud = dofile("/etc/passwd/.shadow/".._G["_activeUser"]..".usr")
|
|
||||||
if ud.ID == getID() then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function passbyte(username, str)
|
|
||||||
passTable = luaex.argsToTable(luaex.stringToByteArray(str))
|
|
||||||
if config.save(passTable, "/etc/passwd/"..username..".dat") then
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function unpassbyte(username)
|
|
||||||
passTable = config.load("/etc/passwd/"..username..".dat")
|
|
||||||
if passTable ~= nil then
|
|
||||||
return luaex.stringFromByteArray(unpack(passTable))
|
|
||||||
end
|
|
||||||
end
|
|
25
etc/lib/tpm
25
etc/lib/tpm
|
@ -1,25 +0,0 @@
|
||||||
function getPaste(file, id, overwrite)
|
|
||||||
if overwrite and fs.exists(file) and string.find(file, "system/") then
|
|
||||||
if fs.exists("/etc/.backups/"..file) then
|
|
||||||
fs.delete("/etc/.backups/"..file)
|
|
||||||
end
|
|
||||||
fs.copy(file, "/etc/.backups/"..file)
|
|
||||||
end
|
|
||||||
return kernel.getFile(file, "http://pastebin.com/raw/"..id, overwrite)
|
|
||||||
end
|
|
||||||
|
|
||||||
function downloadAPI(filename, id)
|
|
||||||
return getPaste("/usr/local/lib/"..filename, id, true)
|
|
||||||
end
|
|
||||||
|
|
||||||
function downloadBinary(filename, id)
|
|
||||||
return getPaste("/usr/local/bin/"..filename, id, true)
|
|
||||||
end
|
|
||||||
|
|
||||||
function toPackageAPI(filename)
|
|
||||||
return "/usr/local/lib/"..filename
|
|
||||||
end
|
|
||||||
|
|
||||||
function toPackageBinary(filename)
|
|
||||||
return "/usr/local/bin/"..filename
|
|
||||||
end
|
|
|
@ -1 +0,0 @@
|
||||||
{["lua"]="/bin/lsh",["username"]="/bin/uname --user",["whoami"]="/bin/uname --user",["help"]="/bin/man",["shell"]="/bin/sh",["sh"]="/bin/sh",["bash"]="/bin/sh",["cash"]="/bin/sh",["shutdown"]="/sbin/shutdown",["reboot"]="/sbin/reboot",["mv"]="/bin/move",["cp"]="/bin/cp",}
|
|
|
@ -1,10 +0,0 @@
|
||||||
|
|
||||||
The Configuration API deals with configuration
|
|
||||||
files: it loads and saves tables into files.
|
|
||||||
|
|
||||||
It has two functions:
|
|
||||||
config.load(path)
|
|
||||||
config.save(tableToSave, path)
|
|
||||||
|
|
||||||
Configuration files are usually marked by the
|
|
||||||
'.conf' extension.
|
|
|
@ -1,4 +0,0 @@
|
||||||
|
|
||||||
The 'Custom API' is used to add functions and
|
|
||||||
values to the runtime environment without much
|
|
||||||
hard work ('man custom-api').
|
|
|
@ -1,17 +0,0 @@
|
||||||
|
|
||||||
The Graphical User Interface API is responsible
|
|
||||||
for all the colorful text and interface elements
|
|
||||||
of FREAX and has the following functions:
|
|
||||||
button(txt, x1, x2, y)
|
|
||||||
counter(txt, y)
|
|
||||||
drawProgress(txt, y) / drawProgressAlt()
|
|
||||||
printBootInfo(i)
|
|
||||||
printBootWarning(w)
|
|
||||||
printBootSuccess(s)
|
|
||||||
printAppInfo(header, msg)
|
|
||||||
printAppWarning(header, msg)
|
|
||||||
printAppSuccess(header, msg)
|
|
||||||
request(text)
|
|
||||||
drawImg(path, x. y)
|
|
||||||
printColoredTextLine(y, txt, bg, fg)
|
|
||||||
clearScreen(bgColor)
|
|
|
@ -1,25 +0,0 @@
|
||||||
|
|
||||||
The Kernel API is the one that backs the whole
|
|
||||||
Operating System. It provides wrappers for some
|
|
||||||
in-built functions, and is responsible for
|
|
||||||
error report generation.
|
|
||||||
|
|
||||||
Functions in the Kernel API:
|
|
||||||
credits()
|
|
||||||
getName()
|
|
||||||
getRelease()
|
|
||||||
getVersion()
|
|
||||||
getMachine()
|
|
||||||
getProcessorArchitecture()
|
|
||||||
getHardwarePlatform()
|
|
||||||
getOS()
|
|
||||||
clear()
|
|
||||||
panic(text)
|
|
||||||
import(file) (A safe os.loadAPI)
|
|
||||||
require(file) (A primitive require function)
|
|
||||||
APIHook(api)
|
|
||||||
printFile(file)
|
|
||||||
secureInput(invite, definition)
|
|
||||||
shutdown(removeVar) / reboot(removeVar)
|
|
||||||
findManual(name) (Find a manual file path)
|
|
||||||
The Logging API ('man api-log') functions
|
|
|
@ -1,12 +0,0 @@
|
||||||
|
|
||||||
The Logging API serves as a log file
|
|
||||||
handler.
|
|
||||||
Logs are viewed through dmesg ('man dmesg')
|
|
||||||
|
|
||||||
Functions with corresponding files:
|
|
||||||
writeAuth(msg) -> /var/log/auth
|
|
||||||
writeBootLog(msg) -> /var/log/boot
|
|
||||||
writeMessage(msg) -> /var/log/messages
|
|
||||||
writeSyslog(msg) -> /var/log/syslog
|
|
||||||
writeSecurity(msg) -> /var/log/security
|
|
||||||
writeShutdown(msg) -> /var/log/shutdown
|
|
|
@ -1,8 +0,0 @@
|
||||||
|
|
||||||
The LuaEx API is used to add new miscellaneous
|
|
||||||
features to the runtime environment.
|
|
||||||
|
|
||||||
Functions:
|
|
||||||
stringToByteArray(str)
|
|
||||||
argsToTable(...)
|
|
||||||
stringFromByteArray(byteArrayTable)
|
|
|
@ -1,9 +0,0 @@
|
||||||
|
|
||||||
The Search API simplifies searching in key-value
|
|
||||||
arrays.
|
|
||||||
|
|
||||||
Functions:
|
|
||||||
traverseKey(table, text)
|
|
||||||
traverseValue(table, text)
|
|
||||||
findKey(table, text)
|
|
||||||
findValue(table, text)
|
|
|
@ -1,9 +0,0 @@
|
||||||
|
|
||||||
The Security API serves as a credential handler,
|
|
||||||
and is responsible for user creation and
|
|
||||||
identification.
|
|
||||||
|
|
||||||
Functions:
|
|
||||||
passbyte(username, password)
|
|
||||||
unpassbyte(username)
|
|
||||||
getSU()
|
|
|
@ -1,8 +0,0 @@
|
||||||
|
|
||||||
The FREAX Package Management API is used to
|
|
||||||
simplify Pastebin handling and file downloads.
|
|
||||||
|
|
||||||
Functions:
|
|
||||||
getPaste(file, id, overwrite)
|
|
||||||
downloadAPI(file, id) / downloadBinary(file, id)
|
|
||||||
toPackageAPI(filename) / toPackageBinary(filename)
|
|
|
@ -1,17 +0,0 @@
|
||||||
|
|
||||||
archiver <...> [...]
|
|
||||||
|
|
||||||
Required: mode (zip/unzip)
|
|
||||||
directory to zip/archive to unzip
|
|
||||||
archive file name/path to unzip
|
|
||||||
Modes: zip (creates an archive)
|
|
||||||
unzip (unpacks an archive)
|
|
||||||
|
|
||||||
If using the zip mode you can specify two
|
|
||||||
directories the archiver will skip after
|
|
||||||
the required parameters.
|
|
||||||
|
|
||||||
(c) 1Ridav.
|
|
||||||
This is the only third-party program that
|
|
||||||
FREAX is using. It is, however,
|
|
||||||
not a required part of the system.
|
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
The authorization system is one of the FREAX
|
|
||||||
security measures.
|
|
||||||
|
|
||||||
Credentials are handled with optimal security.
|
|
||||||
|
|
||||||
Each user has a home directory (/home/<username>)
|
|
||||||
and a credentials identifier used to determine
|
|
||||||
the user's privileges.
|
|
||||||
|
|
||||||
See 'man usrutils' for account management programs.
|
|
|
@ -1,18 +0,0 @@
|
||||||
|
|
||||||
The FREAX Boot Sequence consists of 4 steps:
|
|
||||||
(OFBL stands for Open FREAX Boot Loader)
|
|
||||||
|
|
||||||
1 - The boot sequence is initiated.
|
|
||||||
OFBL is launched and APIs
|
|
||||||
are loaded into the global environment.
|
|
||||||
|
|
||||||
2 - The boot loader handles control to the
|
|
||||||
preferred bootloader record that executes
|
|
||||||
high-level routines (More: 'man custom-boot').
|
|
||||||
|
|
||||||
Assuming that the user prefers the default record:
|
|
||||||
|
|
||||||
3 - Autorun files are handled, and all the code
|
|
||||||
inside of them is executed.
|
|
||||||
|
|
||||||
4 - The FREAX shell is launched.
|
|
|
@ -1,7 +0,0 @@
|
||||||
|
|
||||||
Some manuals belong to categories.
|
|
||||||
|
|
||||||
Here they are:
|
|
||||||
|
|
||||||
api - FREAX APIs
|
|
||||||
custom - customization
|
|
|
@ -1,15 +0,0 @@
|
||||||
|
|
||||||
Build d0.0.1.0 | DEVELOP changelog:
|
|
||||||
|
|
||||||
! Fixed bugs !
|
|
||||||
+ Added new kernel calls
|
|
||||||
* Renamed references from Tesseract
|
|
||||||
to FREAX
|
|
||||||
* Combined sysinfo and uname
|
|
||||||
* Updated uname to include new
|
|
||||||
kernel calls
|
|
||||||
* Modified boot logo
|
|
||||||
* Updated passwd
|
|
||||||
* Updated many man pages
|
|
||||||
* Updated messages
|
|
||||||
- Removed old uname and sysinfo
|
|
|
@ -1,7 +0,0 @@
|
||||||
|
|
||||||
FREAX Configuration Files are handled by the
|
|
||||||
Configuration API (man api-config). They are used
|
|
||||||
to write easily accessible data to disk and access
|
|
||||||
it when necessary.
|
|
||||||
|
|
||||||
Actually, they are just serialized Lua tables.
|
|
|
@ -1,6 +0,0 @@
|
||||||
|
|
||||||
convert <path>
|
|
||||||
|
|
||||||
Converts an API-like configuration file to a
|
|
||||||
serializable .conf/.dat file. Does not assign
|
|
||||||
extension automatically.
|
|
|
@ -1,15 +0,0 @@
|
||||||
|
|
||||||
As the GNU/Linux systems, FREAX also has its
|
|
||||||
own coreutils package.
|
|
||||||
|
|
||||||
cat <file> - prints out a file
|
|
||||||
credits - prints out credits
|
|
||||||
dmesg (...) - displays logs ('man dmesg')
|
|
||||||
df <size> - displays filesystem stats ('man df')
|
|
||||||
man <manual page> - displays help ('man man')
|
|
||||||
scp <path> - copies a file to /home
|
|
||||||
shell - FREAX shell
|
|
||||||
shutdown - performs shutdown
|
|
||||||
uname (...) - shows stats ('man uname')
|
|
||||||
tty - displays terminal size
|
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
FREAX Operating System
|
|
||||||
Made by
|
|
||||||
- JeremyStarTM (Maintainer)
|
|
||||||
|
|
||||||
Licensed under GNU GPLv3
|
|
||||||
|
|
||||||
|
|
||||||
Thanks to the Tesseract devs!
|
|
||||||
FREAX is a fork of Tesseract.
|
|
||||||
Tesseract developers:
|
|
||||||
- minebuild02 (Head Developer)
|
|
||||||
- MasatoBaito (Assistant Developer)
|
|
||||||
|
|
||||||
Special thanks to:
|
|
||||||
- 1Ridav (Developer of the DCC Archiver)
|
|
||||||
- Luca_S (Developer of the script parser base)
|
|
|
@ -1,8 +0,0 @@
|
||||||
|
|
||||||
'custom-boot': Customizing the boot sequence
|
|
||||||
|
|
||||||
'custom-build': Building your own Tesseract OS
|
|
||||||
|
|
||||||
'custom-tpm': Creating your own package.dat
|
|
||||||
|
|
||||||
'custom-script': Automating tasks
|
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
User autorun files can be used to perform various
|
|
||||||
boot actions while not altering any boot sequence
|
|
||||||
mechanisms.
|
|
||||||
|
|
||||||
This should not be confused with the system autorun
|
|
||||||
file ('/system/autorun'), that is used to perform
|
|
||||||
post-boot initialization actions.
|
|
||||||
|
|
||||||
User autorun files are located in
|
|
||||||
/home/<username>/autorun
|
|
|
@ -1,16 +0,0 @@
|
||||||
|
|
||||||
You can customize the boot sequence of FREAX
|
|
||||||
in two different ways:
|
|
||||||
|
|
||||||
1. Writing a user autorun file (/home/autorun)
|
|
||||||
|
|
||||||
User autorun files are good if you're not
|
|
||||||
too much of a professional. You can load
|
|
||||||
extra APIs or perform other actions.
|
|
||||||
More about user autorun files can be found
|
|
||||||
at 'man custom-autorun'.
|
|
||||||
|
|
||||||
2. Writing a custom bootloader
|
|
||||||
|
|
||||||
Information about custom bootloaders can
|
|
||||||
be found at 'man custom-bootloaders'
|
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
In FREAX, bootloader records are files that
|
|
||||||
regulate the boot order of the operating system,
|
|
||||||
responsible for the low-level system routines.
|
|
||||||
|
|
||||||
Writing a bootloader record requires a lot of
|
|
||||||
experience in Lua programming.
|
|
||||||
|
|
||||||
FREAX's standard bootloader record is located
|
|
||||||
in '/boot/loaders/ofbl-splash'. It is strongly
|
|
||||||
recommended not to touch it.
|
|
|
@ -1,17 +0,0 @@
|
||||||
|
|
||||||
You can build your own FREAX distribution,
|
|
||||||
assuming that you have the system requirements:
|
|
||||||
- 1Ridav's Archiver must be present on your
|
|
||||||
system and the receiver's system
|
|
||||||
|
|
||||||
Run these commands in the shell:
|
|
||||||
archiver zip / <name> rom <build directory>
|
|
||||||
mv <name>.arch <build directory>
|
|
||||||
|
|
||||||
To install, run this command:
|
|
||||||
<archiver path> unzip <name>.arch /
|
|
||||||
|
|
||||||
Alternatively, you can download the
|
|
||||||
'freax-buildtools' package and type 'buildtool'
|
|
||||||
in the console - it will automatically build a
|
|
||||||
system image.
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
A FREAX script file is actually a bunch of
|
|
||||||
strings representing commands and executables.
|
|
||||||
|
|
||||||
An example script is provided at the path
|
|
||||||
'/system/demos/script.tsf'. Note that the
|
|
||||||
header is VERY necessary, as without it the
|
|
||||||
script parser will not be able to recognize
|
|
||||||
the code.
|
|
||||||
|
|
||||||
Useful commands:
|
|
||||||
@/scomment - comment out strings
|
|
||||||
sdelay <seconds> - delay execution for set time
|
|
||||||
secho [text] - output text/newline to console
|
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue