├── .gitignore ├── kernel ├── copper.lua ├── devices.lua ├── eventdebug.lua ├── events.lua ├── filesys.lua ├── json.lua ├── lib │ ├── AES │ ├── Base64 │ └── json ├── library.lua ├── mounts.lua ├── path.lua ├── registry.lua ├── sandbox.lua ├── security.lua ├── shellmgr.lua ├── socket.lua ├── start.lua ├── tasks.lua └── tlc.lua ├── startup ├── system ├── default │ ├── cdrv │ ├── copper │ ├── copperserver │ ├── coservice.lua │ ├── devices │ ├── devservice.lua │ ├── drives │ ├── echo │ ├── findtid │ ├── kill │ ├── mount │ ├── mounts │ ├── origin │ ├── pinvoke │ ├── registry │ ├── sshost.lua │ ├── start │ ├── taft │ ├── tasks │ └── unmount ├── errordebug.lua ├── shell.lua └── sysinit.lua └── user └── start.ss /.gitignore: -------------------------------------------------------------------------------- 1 | system/boot_log.txt 2 | registry.dat 3 | /copper 4 | -------------------------------------------------------------------------------- /kernel/copper.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | COPPER - The networking library 3 | 4 | CheetOS Protocol Protection and Encryption Rsomething 5 | ]] 6 | 7 | local COPPER = { 8 | PACKET_CONNECT = 0x01; 9 | PACKET_BROADCAST_SERVER = 0x02; 10 | PACKET_REQUEST_SALT = 0x03; 11 | PACKET_ACCESS_DENIED = 0x04; 12 | PACKET_ACCESS_GRANTED = 0x05; 13 | PACKET_SALT = 0x06; 14 | PACKET_LOGOUT = 0x07; 15 | 16 | DENY_REASON_ALREADY_LOGGED_IN = 0x01; 17 | DENY_REASON_INVALID_CREDENTIALS = 0x02; 18 | } 19 | 20 | local Packet = {} 21 | Packet.__index = Packet 22 | 23 | setmetatable(Packet, { 24 | __call = function(cls, data) 25 | local self = setmetatable({}, Packet) 26 | self.__data = data or {} 27 | self.__readPtr = 1 28 | return self 29 | end 30 | }) 31 | 32 | function Packet:WriteNumber(num) 33 | self.__data[#self.__data + 1] = num 34 | end 35 | 36 | function Packet:WriteString(str) 37 | if type(str) ~= "string" then 38 | return error("WriteString(): argument #1 must be a string!", 2) 39 | end 40 | 41 | self:WriteNumber(#str) 42 | self:WriteChars(str) 43 | end 44 | 45 | function Packet:WriteChars(str) 46 | for i=1,#str do 47 | self:WriteNumber(string.byte(str:sub(i, i))) 48 | end 49 | end 50 | 51 | function Packet:ReadNumber() 52 | local i = self.__readPtr 53 | self.__readPtr = self.__readPtr + 1 54 | local num = self.__data[i] 55 | if num == nil then 56 | error("end of stream", 2) 57 | end 58 | return num 59 | end 60 | 61 | function Packet:ReadString() 62 | return self:ReadChars(self:ReadNumber()) 63 | end 64 | 65 | function Packet:ReadChars(count) 66 | local str = "" 67 | for i=1,count do 68 | local num = self:ReadNumber() 69 | str = str .. string.char(num) 70 | end 71 | return str 72 | end 73 | 74 | function Packet:GetBytes() 75 | return self.__data 76 | end 77 | 78 | function Packet:GetReadPosition() 79 | return self.__readPtr -- subtract the magic bytes 80 | end 81 | 82 | function Packet:GetSize() 83 | return #self.__data 84 | end 85 | 86 | COPPER.Packet = Packet 87 | 88 | local Socket = {} 89 | Socket.__index = Socket 90 | 91 | setmetatable(Socket, { 92 | __call = function(cls, localhost, serverName, device, frequency, replyFreq) 93 | local self = setmetatable({}, Socket) 94 | self.__serverName = serverName 95 | self.__localhost = localhost 96 | 97 | if serverName == nil and device == nil and frequency == nil then 98 | self.__sysSock = localhost -- A socket was supplied 99 | else 100 | self.__sysSock = System.Socket.RequestNetSocket(device, frequency, replyFreq) 101 | end 102 | return self 103 | end 104 | }) 105 | 106 | function Socket:SendPacket(packet) 107 | if type(packet) ~= "table" then 108 | return error("SendPacket(): argument #1 must be a packet!", 2) 109 | end 110 | self.__sysSock:Transmit(packet.__data) 111 | end 112 | 113 | local function convertToTable(data) 114 | local tbl = {} 115 | 116 | if type(data) == "string" then 117 | for i=1,#data do 118 | local c = data:sub(i, i) 119 | tbl[#tbl + 1] = c:byte() 120 | end 121 | elseif type(data) == "number" then 122 | tbl[#tbl + 1] = data 123 | else 124 | return nil 125 | end 126 | 127 | return tbl 128 | end 129 | 130 | local function makePacketFromData(data) 131 | if type(data) ~= "table" then 132 | data = convertToTable(data) 133 | end 134 | 135 | if data ~= nil then 136 | return Packet(data) 137 | end 138 | end 139 | 140 | COPPER.MakePacketFromData = makePacketFromData 141 | 142 | function Socket:ReceivePacket(timeout) 143 | while true do 144 | local data = self.__sysSock:Receive(timeout) 145 | return makePacketFromData(data) 146 | end 147 | end 148 | 149 | function Socket:RequestSalt() 150 | local packet = Packet() 151 | packet:WriteString(self.__localhost) 152 | packet:WriteNumber(COPPER.PACKET_REQUEST_SALT) 153 | packet:WriteString(self.__serverName) 154 | return self:SendPacket(packet) 155 | end 156 | 157 | function Socket:Connect(password, salt) 158 | local packet = Packet() 159 | packet:WriteString(self.__localhost) 160 | packet:WriteNumber(COPPER.PACKET_CONNECT) 161 | packet:WriteString(self.__serverName) 162 | 163 | local hashedPass = System.Security.Hash(password, salt) 164 | local encrypted = System.Security.Encrypt(password, hashedPass) 165 | 166 | if encrypted == nil then 167 | return error("Failed to encrypt.") 168 | end 169 | 170 | packet:WriteString(encrypted) 171 | return self:SendPacket(packet) 172 | end 173 | 174 | function Socket:Disconnect(key) 175 | local packet = Packet() 176 | packet:WriteString(self.__localhost) 177 | packet:WriteNumber(COPPER.PACKET_LOGOUT) 178 | packet:WriteString(self.__serverName) 179 | packet:WriteString(key) 180 | return self:SendPacket(packet) 181 | end 182 | 183 | function Socket:Close() 184 | return self.__sysSock:Close() 185 | end 186 | 187 | COPPER.Socket = Socket 188 | return COPPER 189 | -------------------------------------------------------------------------------- /kernel/devices.lua: -------------------------------------------------------------------------------- 1 | local Devices = {} 2 | local __devices = {} 3 | 4 | function Devices.Register(netName, handle) 5 | __devices[netName] = setmetatable({}, { __index = handle }) 6 | 7 | local dev = __devices[netName] 8 | local type = peripheral.getType(netName) 9 | 10 | dev.GetType = function() 11 | return type 12 | end 13 | 14 | dev.GetName = function() 15 | return netName 16 | end 17 | 18 | dev.IsValid = function() 19 | return peripheral.isPresent(netName) 20 | end 21 | end 22 | 23 | function Devices.Unregister(netName) 24 | __devices[netName] = nil 25 | end 26 | 27 | function Devices.GetAnyOfType(_type, predicate) 28 | for k,v in pairs(__devices) do 29 | if Devices.GetDevType(k) == _type then 30 | if type(predicate) == "function" then 31 | if predicate(v) then 32 | return v 33 | end 34 | else 35 | return v 36 | end 37 | end 38 | end 39 | 40 | return nil 41 | end 42 | 43 | function Devices.GetHandle(netName) 44 | return __devices[netName] 45 | end 46 | 47 | function Devices.GetDevType(netName) 48 | return peripheral.getType(netName) 49 | end 50 | 51 | function Devices.List() 52 | return __devices 53 | end 54 | 55 | function Devices.Scan() 56 | for _,v in pairs(peripheral.getNames()) do 57 | Devices.Register(v, peripheral.wrap(v)) 58 | end 59 | end 60 | 61 | Devices.Scan() 62 | 63 | setmetatable(Devices, { __index = __devices }) 64 | return Devices 65 | -------------------------------------------------------------------------------- /kernel/eventdebug.lua: -------------------------------------------------------------------------------- 1 | print("Hello from eventdebug.lua!!") 2 | print("Polling mouse_click, char, key and mouse_scroll") 3 | 4 | while true do 5 | local evt = { os.pullEvent("mouse_click", "char", "key", "mouse_scroll") } 6 | print(table.concat(evt, ", ")) 7 | end -------------------------------------------------------------------------------- /kernel/events.lua: -------------------------------------------------------------------------------- 1 | local Events = {} 2 | local translators = {} 3 | local queue = {} 4 | 5 | function Events.RegisterTranslator(event, translator) 6 | local tbl = nil 7 | 8 | if translators[event] == nil then 9 | translators[event] = {} 10 | tbl = translators[event] 11 | else 12 | tbl = translators[event] 13 | end 14 | 15 | local index = #tbl + 1 16 | tbl[index] = translator 17 | end 18 | 19 | function Events.Translate(event, ...) 20 | for k,v in pairs(translators) do 21 | if k == event then 22 | for _,t in pairs(v) do 23 | t(...) 24 | end 25 | end 26 | end 27 | 28 | return event, ... 29 | end 30 | 31 | os.pullEventRaw = function(...) 32 | return coroutine.yield(...) 33 | end 34 | 35 | return Events 36 | -------------------------------------------------------------------------------- /kernel/filesys.lua: -------------------------------------------------------------------------------- 1 | local _fs = {} 2 | 3 | local mounts = {} 4 | 5 | local function GetFSAPI() 6 | return setmetatable({}, { __index = fs }) 7 | end 8 | 9 | local function GetRealFSAPI() 10 | return setmetatable({}, { __index = _fs }) 11 | end 12 | 13 | local assert = function(cond, err) 14 | if not cond then 15 | error(err, 4) 16 | end 17 | end 18 | 19 | do 20 | for k,v in pairs(_G.fs) do 21 | if type(k) == "string" then 22 | _fs[k] = v 23 | end 24 | end 25 | end 26 | 27 | local function RealToVirtual(path) 28 | path = System.Path.Normalise(path) 29 | 30 | for _,v in pairs(mounts) do 31 | local real = v.__realPath 32 | if path:sub(1, #real) == real then 33 | return System.Path.Normalise(v.__letter .. ":" .. path:sub(#real + 1, #path)) 34 | end 35 | end 36 | 37 | return nil 38 | end 39 | 40 | local FS_ARG_PATH = 1 41 | local FS_ARG_OTHER = 2 42 | local FS_ARG_WILDCARD = 4 43 | 44 | local fsFunctions = { 45 | list = { FS_ARG_PATH }; 46 | exists = { FS_ARG_PATH }; 47 | isDir = { FS_ARG_PATH }; 48 | isReadOnly = { FS_ARG_PATH }; 49 | getName = { FS_ARG_PATH }; 50 | getDrive = { FS_ARG_PATH }; 51 | getSize = { FS_ARG_PATH }; 52 | getFreeSpace = { FS_ARG_PATH }; 53 | makeDir = { FS_ARG_PATH }; 54 | move = { FS_ARG_PATH, FS_ARG_OTHER }; 55 | copy = { FS_ARG_PATH, FS_ARG_OTHER }; 56 | delete = { FS_ARG_PATH }; 57 | combine = { FS_ARG_PATH, FS_ARG_PATH }; 58 | open = { FS_ARG_PATH, FS_ARG_OTHER }; 59 | find = { FS_ARG_PATH }; 60 | getDir = { FS_ARG_PATH }; 61 | complete = { FS_ARG_OTHER, FS_ARG_PATH, FS_ARG_OTHER, FS_ARG_OTHER }; 62 | } 63 | 64 | _G.fs = {} 65 | 66 | local Mount = {} 67 | Mount.__index = Mount 68 | Mount.__type = "unknown" 69 | 70 | setmetatable(Mount, { 71 | __call = function(cls) 72 | local self = setmetatable({}, Mount) 73 | return self 74 | end, 75 | }) 76 | 77 | -- Mount events: 78 | function Mount:OnMount() end 79 | function Mount:OnUnmount() end 80 | 81 | function Mount:GetLetter() 82 | return self.__letter 83 | end 84 | 85 | local DirMount = {} 86 | DirMount.__index = DirMount 87 | DirMount.__type = "DirMount" 88 | 89 | setmetatable(DirMount, { 90 | __index = Mount, 91 | 92 | __call = function(cls, realPath) 93 | local self = setmetatable({}, DirMount) 94 | assert(type(realPath == "string"), "DirMount(): arg #1 must be a string") 95 | self.__realPath = System.Path.Normalise(realPath) 96 | 97 | return self 98 | end 99 | }) 100 | 101 | function DirMount:Resolve(path) 102 | local _, driveless = System.Path.GetDriveAndPath(path) 103 | return System.Path.Combine(self.__realPath, driveless) 104 | end 105 | 106 | function DirMount:list(path) 107 | if System.Path.Normalise(path) == "S:/default" then 108 | local files = _fs.list(self:Resolve(path)) 109 | local idxToRemove = -1 110 | for i,v in pairs(files) do 111 | if v == "taft" then 112 | -- necessary for locking the buffer 113 | idxToRemove = i 114 | break 115 | end 116 | end 117 | 118 | if idxToRemove ~= -1 then 119 | table.remove(files, idxToRemove) 120 | end 121 | 122 | return files 123 | else 124 | return _fs.list(self:Resolve(path)) 125 | end 126 | end 127 | 128 | function DirMount:IsInDrive(path) 129 | local resolved = self:Resolve(path) 130 | local normalised = System.Path.Normalise(resolved) 131 | return normalised:sub(1, #self.__realPath) == self.__realPath 132 | end 133 | 134 | function DirMount:exists(path) 135 | return _fs.exists(self:Resolve(path)) 136 | end 137 | 138 | function DirMount:isDir(path) 139 | return _fs.isDir(self:Resolve(path)) 140 | end 141 | 142 | function DirMount:isReadOnly(path) 143 | return _fs.isReadOnly(self:Resolve(path)) 144 | end 145 | 146 | function DirMount:getName(path) 147 | return _fs.getName(self:Resolve(path)) 148 | end 149 | 150 | function DirMount:getDrive(path) 151 | return _fs.getDrive(self:Resolve(path)) 152 | end 153 | 154 | function DirMount:getSize(path) 155 | return _fs.getSize(self:Resolve(path)) 156 | end 157 | 158 | function DirMount:getFreeSpace(path) 159 | return _fs.getFreeSpace(self:Resolve(path)) 160 | end 161 | 162 | function DirMount:makeDir(path) 163 | return _fs.makeDir(self:Resolve(path)) 164 | end 165 | 166 | function DirMount:move(from, to) 167 | local drive = System.Path.GetDriveAndPath(to) 168 | local mount = mounts[drive] 169 | return _fs.move(self:Resolve(from), mount:Resolve(to)) 170 | end 171 | 172 | function DirMount:copy(from, to) 173 | local drive = System.Path.GetDriveAndPath(to) 174 | local mount = mounts[drive] 175 | return _fs.copy(self:Resolve(from), mount:Resolve(to)) 176 | end 177 | 178 | function DirMount:delete(path) 179 | return _fs.delete(self:Resolve(path)) 180 | end 181 | 182 | function DirMount:combine(base, localPath) 183 | return System.Path.Combine(base, localPath) 184 | end 185 | 186 | function DirMount:open(path, mode) 187 | return _fs.open(self:Resolve(path), mode) 188 | end 189 | 190 | function DirMount:getDir(path) 191 | return RealToVirtual(_fs.getDir(self:Resolve(path))) 192 | end 193 | 194 | function DirMount:find(wildcard) 195 | local results = _fs.find(self:Resolve(wildcard)) 196 | 197 | for k,v in pairs(results) do 198 | local virtual = RealToVirtual(v) 199 | results[k] = virtual 200 | end 201 | 202 | return results 203 | end 204 | 205 | function DirMount:complete(file, parent, inclFiles, inclSlashes) 206 | return _fs.complete(file, parent, inclFiles, inclSlashes) 207 | end 208 | 209 | function DirMount:OnMount() 210 | if not _fs.exists(self.__realPath) then 211 | _fs.makeDir(self.__realPath) 212 | end 213 | end 214 | 215 | local function RegisterMount(letter, mount) 216 | assert(type(letter == "string"), "RegisterMount(): arg #1 must be a string") 217 | letter = letter:sub(1, 1) 218 | 219 | assert(type(letter == "table"), "RegisterMount(): arg #2 must be a mount") 220 | 221 | mount.__letter = letter 222 | mounts[letter] = mount 223 | mounts[letter]:OnMount() 224 | end 225 | 226 | local function Unmount(letter) 227 | assert(type(letter == "string"), "Unmount(): arg #1 must be a string") 228 | letter = letter:sub(1, 1) 229 | mounts[letter]:OnUnmount() 230 | mounts[letter] = nil 231 | end 232 | 233 | local function GetMountFromDrive(letter) 234 | assert(type(letter == "string"), "GetMountFromDrive(): arg #1 must be a string") 235 | letter = letter:sub(1, 1) 236 | return mounts[letter] 237 | end 238 | 239 | local theAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 240 | 241 | local function GetNextFreeLetter() 242 | for i=1,#theAlphabet do 243 | local c = theAlphabet:sub(i, i) 244 | if mounts[c] == nil then 245 | return c 246 | end 247 | end 248 | end 249 | 250 | local function IsDrive(letter) 251 | return mounts[letter] ~= nil 252 | end 253 | 254 | local function GetMounts() 255 | return mounts 256 | end 257 | 258 | do 259 | --RegisterMount("U", DirMount("/user")) 260 | RegisterMount("R", DirMount("/rom")) 261 | RegisterMount("S", DirMount("/system")) 262 | RegisterMount("K", DirMount("/kernel")) 263 | 264 | for k,v in pairs(fsFunctions) do 265 | _G.fs[k] = function(...) 266 | local args = { ... } 267 | local pathCount = 0 268 | local mount = nil 269 | 270 | local function GetArg(i, expected) 271 | local arg = args[i] 272 | 273 | if expected ~= nil then 274 | assert(type(arg) == expected, k .. "(): arg #" .. i .. " must be a " .. expected .. ", got " .. type(arg)) 275 | end 276 | 277 | return arg 278 | end 279 | 280 | local newArgs = {} 281 | 282 | for i,t in pairs(v) do 283 | if t == FS_ARG_PATH then 284 | if pathCount == 0 then 285 | local primaryPath = GetArg(i, "string") 286 | local drive, path = System.Path.GetDriveAndPath(primaryPath) 287 | drive = drive or System.Path.GetDefaultDrive() 288 | mount = GetMountFromDrive(drive) 289 | 290 | if mount and not mount:IsInDrive(System.Path.Combine(drive .. ":/", path)) then 291 | error("invalid path", 2) 292 | end 293 | end 294 | 295 | pathCount = pathCount + 1 296 | end 297 | 298 | newArgs[#newArgs + 1] = GetArg(i) 299 | end 300 | 301 | if mount ~= nil then 302 | local func = mount[k] 303 | if func == nil then 304 | error(k .. "(): function unsupported on this drive", 2) 305 | else 306 | return func(mount, unpack(newArgs)) 307 | end 308 | else 309 | error("couldn't find a drive to call this on", 2) 310 | end 311 | end 312 | end 313 | end 314 | 315 | return { 316 | Mount = Mount, 317 | DirMount = DirMount, 318 | 319 | RealToVirtual = RealToVirtual, 320 | 321 | GetMountFromDrive = GetMountFromDrive, 322 | RegisterMount = RegisterMount, 323 | Unmount = Unmount, 324 | GetMounts = GetMounts, 325 | IsDrive = IsDrive, 326 | GetNextFreeLetter = GetNextFreeLetter, 327 | 328 | GetFSAPI = GetFSAPI, 329 | GetRealFSAPI = GetRealFSAPI 330 | } 331 | -------------------------------------------------------------------------------- /kernel/json.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Uses ElvishJerricco's JSON Library (http://www.computercraft.info/forums2/index.php?/topic/5854-json-api-v201-for-computercraft/) 3 | to implement textutils.unserialiseJSON (and textutils.serialiseJSON if necessary). 4 | 5 | As well as that, System.JSON is ElvishJerricco's API itself. 6 | ]] 7 | 8 | local _json = System.Library.Load("K:/lib/json") 9 | 10 | if textutils.serialiseJSON == nil then 11 | textutils.serialiseJSON = function(input) 12 | return _json.encode(input) 13 | end 14 | 15 | textutils.serializeJSON = textutils.serialiseJSON 16 | end 17 | 18 | textutils.unserialiseJSON = function(input) 19 | return _json.decode(input) 20 | end 21 | 22 | textutils.unserializeJSON = textutils.unserialiseJSON 23 | 24 | return _json 25 | -------------------------------------------------------------------------------- /kernel/lib/AES: -------------------------------------------------------------------------------- 1 | local function e(a)local o=setmetatable({},{__index=getfenv()})return 2 | setfenv(a,o)()or o end 3 | bit=e(function() 4 | local a=math.floor;local o,i=bit.band,bit.bxor 5 | local function n(d,l)if d>2147483647 then d=d-4294967296 end;if l> 6 | 2147483647 then l=l-4294967296 end;return o(d,l)end 7 | local function s(d,l)if d>2147483647 then d=d-4294967296 end;if l>2147483647 then 8 | l=l-4294967296 end;return i(d,l)end;local h,r 9 | r=function(d,l)return a(d%4294967296/2^l)end 10 | h=function(d,l)return(d*2^l)%4294967296 end;return{bnot=bit.bnot,band=n,bor=bit.bor,bxor=s,rshift=r,lshift=h}end) 11 | gf=e(function()local a=bit.bxor;local o=bit.lshift;local i=0x100;local n=0xff;local s=0x11b;local h={}local r={}local function d(p,v) 12 | return a(p,v)end;local function l(p,v)return a(p,v)end;local function u(p)if(p==1)then return 1 end 13 | local v=n-r[p]return h[v]end 14 | local function c(p,v) 15 | if(p==0 or v==0)then return 0 end;local b=r[p]+r[v]if(b>=n)then b=b-n end;return h[b]end 16 | local function m(p,v)if(p==0)then return 0 end;local b=r[p]-r[v]if(b<0)then b=b+n end;return h[b]end 17 | local function f()for p=1,i do print("log(",p-1,")=",r[p-1])end end 18 | local function w()for p=1,i do print("exp(",p-1,")=",h[p-1])end end;local function y()local p=1 19 | for v=0,n-1 do h[v]=p;r[p]=v;p=a(o(p,1),p)if p>n then p=l(p,s)end end end;y()return 20 | {add=d,sub=l,invert=u,mul=c,div=dib,printLog=f,printExp=w}end) 21 | util=e(function()local a=bit.bxor;local o=bit.rshift;local i=bit.band;local n=bit.lshift;local s 22 | local function h(x) 23 | x=a(x,o(x,4))x=a(x,o(x,2))x=a(x,o(x,1))return i(x,1)end;local function r(x,z) 24 | if(z==0)then return i(x,0xff)else return i(o(x,z*8),0xff)end end 25 | local function d(x,z)if(z==0)then return i(x,0xff)else return 26 | n(i(x,0xff),z*8)end end 27 | local function l(x,z,_)local E={} 28 | for T=0,_-1 do 29 | E[T]= 30 | d(x[z+ (T*4)],3)+d(x[z+ (T*4)+1],2)+d(x[z+ (T*4)+2],1)+ 31 | d(x[z+ (T*4)+3],0)if _%10000 ==0 then s()end end;return E end;local function u(x,z,_,E)E=E or#x;for T=0,E do 32 | for A=0,3 do z[_+T*4+ (3-A)]=r(x[T],A)end;if E%10000 ==0 then s()end end 33 | return z end;local function c(x)local z="" 34 | for _,E in 35 | ipairs(x)do z=z..string.format("%02x ",E)end;return z end 36 | local function m(x)local z=type(x) 37 | if 38 | (z=="number")then return string.format("%08x",x)elseif(z=="table")then return c(x)elseif 39 | (z=="string")then local _={string.byte(x,1,#x)}return c(_)else return x end end 40 | local function f(x)local z=#x;local _=math.random(0,255)local E=math.random(0,255) 41 | local T=string.char(_,E,_,E,r(z,3),r(z,2),r(z,1),r(z,0))x=T..x;local A=math.ceil(#x/16)*16-#x;local O=""for I=1,A do O=O.. 42 | string.char(math.random(0,255))end;return x..O end 43 | local function w(x)local z={string.byte(x,1,4)}if 44 | (z[1]==z[3]and z[2]==z[4])then return true end;return false end 45 | local function y(x)if(not w(x))then return nil end 46 | local z= 47 | d(string.byte(x,5),3)+ 48 | d(string.byte(x,6),2)+d(string.byte(x,7),1)+d(string.byte(x,8),0)return string.sub(x,9,8+z)end;local function p(x,z)for _=1,16 do x[_]=a(x[_],z[_])end end 49 | local v,b,g=os.queueEvent,coroutine.yield,os.time;local k=g()local function s()local x=g() 50 | if x-k>=0.03 then k=x;v("sleep")b("sleep")end end 51 | local function q(x) 52 | local z,_,E,T=string.char,math.random,s,table.insert;local A={} 53 | for O=1,x do T(A,_(0,255))if O%10240 ==0 then E()end end;return A end 54 | local function j(x)local z,_,E,T=string.char,math.random,s,table.insert;local A={}for O=1,x do 55 | T(A,z(_(0,255)))if O%10240 ==0 then E()end end 56 | return table.concat(A)end 57 | return 58 | {byteParity=h,getByte=r,putByte=d,bytesToInts=l,intsToBytes=u,bytesToHex=c,toHexString=m,padByteString=f,properlyDecrypted=w,unpadByteString=y,xorIV=p,sleepCheckIn=s,getRandomData=q,getRandomString=j}end) 59 | aes=e(function()local a=util.putByte;local o=util.getByte;local i='rounds'local n="type"local s=1;local h=2 60 | local r={}local d={}local l={}local u={}local c={}local m={}local f={}local w={}local y={}local p={} 61 | local v={0x01000000,0x02000000,0x04000000,0x08000000,0x10000000,0x20000000,0x40000000,0x80000000,0x1b000000,0x36000000,0x6c000000,0xd8000000,0xab000000,0x4d000000,0x9a000000,0x2f000000} 62 | local function b(D)mask=0xf8;result=0 63 | for L=1,8 do result=bit.lshift(result,1) 64 | parity=util.byteParity(bit.band(D,mask))result=result+parity;lastbit=bit.band(mask,1) 65 | mask=bit.band(bit.rshift(mask,1),0xff)if(lastbit~=0)then mask=bit.bor(mask,0x80)else 66 | mask=bit.band(mask,0x7f)end end;return bit.bxor(result,0x63)end;local function g() 67 | for D=0,255 do if(D~=0)then inverse=gf.invert(D)else inverse=D end 68 | mapped=b(inverse)r[D]=mapped;d[mapped]=D end end 69 | local function k() 70 | for D=0,255 do 71 | byte=r[D] 72 | l[D]= 73 | a(gf.mul(0x03,byte),0)+a(byte,1)+a(byte,2)+a(gf.mul(0x02,byte),3) 74 | u[D]= 75 | a(byte,0)+a(byte,1)+a(gf.mul(0x02,byte),2)+a(gf.mul(0x03,byte),3) 76 | c[D]=a(byte,0)+a(gf.mul(0x02,byte),1)+ 77 | a(gf.mul(0x03,byte),2)+a(byte,3) 78 | m[D]= 79 | a(gf.mul(0x02,byte),0)+a(gf.mul(0x03,byte),1)+a(byte,2)+a(byte,3)end end 80 | local function q() 81 | for D=0,255 do byte=d[D] 82 | f[D]= 83 | a(gf.mul(0x0b,byte),0)+a(gf.mul(0x0d,byte),1)+a(gf.mul(0x09,byte),2)+ 84 | a(gf.mul(0x0e,byte),3) 85 | w[D]= 86 | a(gf.mul(0x0d,byte),0)+a(gf.mul(0x09,byte),1)+a(gf.mul(0x0e,byte),2)+ 87 | a(gf.mul(0x0b,byte),3) 88 | y[D]= 89 | a(gf.mul(0x09,byte),0)+a(gf.mul(0x0e,byte),1)+a(gf.mul(0x0b,byte),2)+ 90 | a(gf.mul(0x0d,byte),3) 91 | p[D]= 92 | a(gf.mul(0x0e,byte),0)+a(gf.mul(0x0b,byte),1)+a(gf.mul(0x0d,byte),2)+ 93 | a(gf.mul(0x09,byte),3)end end;local function j(D)local L=bit.band(D,0xff000000)return 94 | (bit.lshift(D,8)+bit.rshift(L,24))end 95 | local function x(D)return 96 | a(r[o(D,0)],0)+a(r[o(D,1)],1)+a(r[o(D,2)],2)+ 97 | a(r[o(D,3)],3)end 98 | local function z(D)local L={}local U=math.floor(#D/4)if( 99 | (U~=4 and U~=6 and U~=8)or(U*4 ~=#D))then 100 | print("Invalid key size: ",U)return nil end;L[i]=U+6;L[n]=s;for C=0,U-1 do 101 | L[C]= 102 | a(D[ 103 | C*4+1],3)+a(D[C*4+2],2)+a(D[C*4+3],1)+a(D[C*4+4],0)end 104 | for C=U,(L[i]+1)*4-1 do 105 | local M=L[C-1] 106 | if(C%U==0)then M=j(M)M=x(M)local F=math.floor(C/U) 107 | M=bit.bxor(M,v[F])elseif(U>6 and C%U==4)then M=x(M)end;L[C]=bit.bxor(L[(C-U)],M)end;return L end 108 | local function _(D)local L=o(D,3)local U=o(D,2)local C=o(D,1)local M=o(D,0) 109 | return 110 | 111 | 112 | 113 | a(gf.add(gf.add(gf.add(gf.mul(0x0b,U),gf.mul(0x0d,C)),gf.mul(0x09,M)),gf.mul(0x0e,L)),3)+ 114 | a(gf.add(gf.add(gf.add(gf.mul(0x0b,C),gf.mul(0x0d,M)),gf.mul(0x09,L)),gf.mul(0x0e,U)),2)+ 115 | a(gf.add(gf.add(gf.add(gf.mul(0x0b,M),gf.mul(0x0d,L)),gf.mul(0x09,U)),gf.mul(0x0e,C)),1)+ 116 | a(gf.add(gf.add(gf.add(gf.mul(0x0b,L),gf.mul(0x0d,U)),gf.mul(0x09,C)),gf.mul(0x0e,M)),0)end 117 | local function E(D)local L=o(D,3)local U=o(D,2)local C=o(D,1)local M=o(D,0)local F=bit.bxor(M,C) 118 | local W=bit.bxor(U,L)local Y=bit.bxor(F,W)Y=bit.bxor(Y,gf.mul(0x08,Y)) 119 | w=bit.bxor(Y,gf.mul(0x04,bit.bxor(C,L))) 120 | Y=bit.bxor(Y,gf.mul(0x04,bit.bxor(M,U))) 121 | return 122 | 123 | 124 | 125 | a(bit.bxor(bit.bxor(M,Y),gf.mul(0x02,bit.bxor(L,M))),0)+a(bit.bxor(bit.bxor(C,w),gf.mul(0x02,F)),1)+ 126 | a(bit.bxor(bit.bxor(U,Y),gf.mul(0x02,bit.bxor(L,M))),2)+a(bit.bxor(bit.bxor(L,w),gf.mul(0x02,W)),3)end 127 | local function T(D)local L=z(D)if(L==nil)then return nil end;L[n]=h;for U=4,(L[i]+1)*4-5 do 128 | L[U]=_(L[U])end;return L end 129 | local function A(D,L,U)for C=0,3 do D[C]=bit.bxor(D[C],L[U*4+C])end end 130 | local function O(D,L) 131 | L[0]=bit.bxor(bit.bxor(bit.bxor(l[o(D[0],3)],u[o(D[1],2)]),c[o(D[2],1)]),m[o(D[3],0)]) 132 | L[1]=bit.bxor(bit.bxor(bit.bxor(l[o(D[1],3)],u[o(D[2],2)]),c[o(D[3],1)]),m[o(D[0],0)]) 133 | L[2]=bit.bxor(bit.bxor(bit.bxor(l[o(D[2],3)],u[o(D[3],2)]),c[o(D[0],1)]),m[o(D[1],0)]) 134 | L[3]=bit.bxor(bit.bxor(bit.bxor(l[o(D[3],3)],u[o(D[0],2)]),c[o(D[1],1)]),m[o(D[2],0)])end 135 | local function I(D,L) 136 | L[0]=a(r[o(D[0],3)],3)+a(r[o(D[1],2)],2)+ 137 | a(r[o(D[2],1)],1)+a(r[o(D[3],0)],0) 138 | L[1]=a(r[o(D[1],3)],3)+a(r[o(D[2],2)],2)+ 139 | a(r[o(D[3],1)],1)+a(r[o(D[0],0)],0) 140 | L[2]=a(r[o(D[2],3)],3)+a(r[o(D[3],2)],2)+ 141 | a(r[o(D[0],1)],1)+a(r[o(D[1],0)],0) 142 | L[3]=a(r[o(D[3],3)],3)+a(r[o(D[0],2)],2)+ 143 | a(r[o(D[1],1)],1)+a(r[o(D[2],0)],0)end 144 | local function N(D,L) 145 | L[0]=bit.bxor(bit.bxor(bit.bxor(f[o(D[0],3)],w[o(D[3],2)]),y[o(D[2],1)]),p[o(D[1],0)]) 146 | L[1]=bit.bxor(bit.bxor(bit.bxor(f[o(D[1],3)],w[o(D[0],2)]),y[o(D[3],1)]),p[o(D[2],0)]) 147 | L[2]=bit.bxor(bit.bxor(bit.bxor(f[o(D[2],3)],w[o(D[1],2)]),y[o(D[0],1)]),p[o(D[3],0)]) 148 | L[3]=bit.bxor(bit.bxor(bit.bxor(f[o(D[3],3)],w[o(D[2],2)]),y[o(D[1],1)]),p[o(D[0],0)])end 149 | local function S(D,L) 150 | L[0]=a(d[o(D[0],3)],3)+a(d[o(D[3],2)],2)+ 151 | a(d[o(D[2],1)],1)+a(d[o(D[1],0)],0) 152 | L[1]=a(d[o(D[1],3)],3)+a(d[o(D[0],2)],2)+ 153 | a(d[o(D[3],1)],1)+a(d[o(D[2],0)],0) 154 | L[2]=a(d[o(D[2],3)],3)+a(d[o(D[1],2)],2)+ 155 | a(d[o(D[0],1)],1)+a(d[o(D[3],0)],0) 156 | L[3]=a(d[o(D[3],3)],3)+a(d[o(D[2],2)],2)+ 157 | a(d[o(D[1],1)],1)+a(d[o(D[0],0)],0)end 158 | local function H(D,L,U,C,M)U=U or 1;C=C or{}M=M or 1;local F={}local W={}if(D[n]~=s)then 159 | print("No encryption key: ",D[n])return end;F=util.bytesToInts(L,U,4) 160 | A(F,D,0)local Y=util.sleepCheckIn;local P=1;while(P2)do N(F,W)A(W,D,P)P=P-1;N(W,F) 166 | A(F,D,P)P=P-1;if P%32 ==0 then Y()end end;Y() 167 | N(F,W)A(W,D,P)P=P-1;S(W,F)A(F,D,P)return util.intsToBytes(F,C,M)end;g()k()q() 168 | return{ROUNDS=i,KEY_TYPE=n,ENCRYPTION_KEY=s,DECRYPTION_KEY=h,expandEncryptionKey=z,expandDecryptionKey=T,encrypt=H,decrypt=R}end) 169 | buffer=e(function()local function a()return{}end;local function o(n,h)table.insert(n,h) 170 | for s=#n-1,1,-1 do if 171 | #n[s]>#n[s+1]then break end;n[s]=n[s]..table.remove(n)end end 172 | local function i(n)for s=#n-1,1,-1 do n[s]=n[s].. 173 | table.remove(n)end;return n[1]end;return{new=a,addString=o,toString=i}end) 174 | ciphermode=e(function()local a={} 175 | function a.encryptString(o,i,n) 176 | local s=iv or{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}local h=aes.expandEncryptionKey(o)local r=buffer.new()for d=1,#i/16 do local l= 177 | (d-1)*16+1;local u={string.byte(i,l,l+15)} 178 | n(h,u,s) 179 | buffer.addString(r,string.char(unpack(u)))end;return 180 | buffer.toString(r)end;function a.encryptECB(o,i,n)aes.encrypt(o,i,1,i,1)end 181 | function a.encryptCBC(o,i,n) 182 | util.xorIV(i,n)aes.encrypt(o,i,1,i,1)for s=1,16 do n[s]=i[s]end end 183 | function a.encryptOFB(o,i,n)aes.encrypt(o,n,1,n,1)util.xorIV(i,n)end;function a.encryptCFB(o,i,n)aes.encrypt(o,n,1,n,1)util.xorIV(i,n) 184 | for s=1,16 do n[s]=i[s]end end 185 | function a.decryptString(o,i,n)local s=iv or 186 | {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}local h 187 | if(n==a.decryptOFB or 188 | n==a.decryptCFB)then 189 | h=aes.expandEncryptionKey(o)else h=aes.expandDecryptionKey(o)end;local r=buffer.new()for d=1,#i/16 do local l=(d-1)*16+1 190 | local u={string.byte(i,l,l+15)}s=n(h,u,s) 191 | buffer.addString(r,string.char(unpack(u)))end;return 192 | buffer.toString(r)end;function a.decryptECB(o,i,n)aes.decrypt(o,i,1,i,1)return n end;function a.decryptCBC(o,i,n) 193 | local s={}for h=1,16 do s[h]=i[h]end;aes.decrypt(o,i,1,i,1) 194 | util.xorIV(i,n)return s end;function a.decryptOFB(o,i,n) 195 | aes.encrypt(o,n,1,n,1)util.xorIV(i,n)return n end;function a.decryptCFB(o,i,n) 196 | local s={}for h=1,16 do s[h]=i[h]end;aes.encrypt(o,n,1,n,1) 197 | util.xorIV(i,n)return s end;return a end)AES128=16;AES192=24;AES256=32;ECBMODE=1;CBCMODE=2;OFBMODE=3;CFBMODE=4 198 | local function t(a,o)local i=o;if 199 | (o==AES192)then i=32 end 200 | if(i>#a)then local s="" 201 | for h=1,i-#a do s=s..string.char(0)end;a=a..s else a=string.sub(a,1,i)end;local n={string.byte(a,1,#a)} 202 | a=ciphermode.encryptString(n,a,ciphermode.encryptCBC)a=string.sub(a,1,o)return{string.byte(a,1,#a)}end 203 | function encrypt(a,o,i,n)assert(a~=nil,"Empty password.") 204 | assert(a~=nil,"Empty data.")local n=n or CBCMODE;local i=i or AES128;local s=t(a,i) 205 | local h=util.padByteString(o) 206 | if(n==ECBMODE)then 207 | return ciphermode.encryptString(s,h,ciphermode.encryptECB)elseif(n==CBCMODE)then 208 | return ciphermode.encryptString(s,h,ciphermode.encryptCBC)elseif(n==OFBMODE)then 209 | return ciphermode.encryptString(s,h,ciphermode.encryptOFB)elseif(n==CFBMODE)then 210 | return ciphermode.encryptString(s,h,ciphermode.encryptCFB)else return nil end end 211 | function decrypt(a,o,i,n)local n=n or CBCMODE;local i=i or AES128;local s=t(a,i)local h 212 | if(n==ECBMODE)then 213 | h=ciphermode.decryptString(s,o,ciphermode.decryptECB)elseif(n==CBCMODE)then 214 | h=ciphermode.decryptString(s,o,ciphermode.decryptCBC)elseif(n==OFBMODE)then 215 | h=ciphermode.decryptString(s,o,ciphermode.decryptOFB)elseif(n==CFBMODE)then 216 | h=ciphermode.decryptString(s,o,ciphermode.decryptCFB)end;result=util.unpadByteString(h) 217 | if(result==nil)then return nil end;return result end;return{} -------------------------------------------------------------------------------- /kernel/lib/Base64: -------------------------------------------------------------------------------- 1 | -- Base64 2 | 3 | -- Characters 4 | local b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" 5 | 6 | -- Encoding 7 | function encode(data) 8 | return ((data:gsub('.', function(x) 9 | local r,b='',x:byte() 10 | for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end 11 | return r; 12 | end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x) 13 | if (#x < 6) then return '' end 14 | local c=0 15 | for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end 16 | return b:sub(c+1,c+1) 17 | end)..({ '', '==', '=' })[#data%3+1]) 18 | end 19 | 20 | -- Decoding 21 | function decode(data) 22 | data = string.gsub(data, '[^'..b..'=]', '') 23 | return (data:gsub('.', function(x) 24 | if (x == '=') then return '' end 25 | local r,f='',(b:find(x)-1) 26 | for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end 27 | return r; 28 | end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x) 29 | if (#x ~= 8) then return '' end 30 | local c=0 31 | for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end 32 | return string.char(c) 33 | end)) 34 | end -------------------------------------------------------------------------------- /kernel/lib/json: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------ utils 2 | local controls = {["\n"]="\\n", ["\r"]="\\r", ["\t"]="\\t", ["\b"]="\\b", ["\f"]="\\f", ["\""]="\\\"", ["\\"]="\\\\"} 3 | 4 | local function isArray(t) 5 | local max = 0 6 | for k,v in pairs(t) do 7 | if type(k) ~= "number" then 8 | return false 9 | elseif k > max then 10 | max = k 11 | end 12 | end 13 | return max == #t 14 | end 15 | 16 | local whites = {['\n']=true; ['r']=true; ['\t']=true; [' ']=true; [',']=true; [':']=true} 17 | function removeWhite(str) 18 | while whites[str:sub(1, 1)] do 19 | str = str:sub(2) 20 | end 21 | return str 22 | end 23 | 24 | ------------------------------------------------------------------ encoding 25 | 26 | local function encodeCommon(val, pretty, tabLevel, tTracking) 27 | local str = "" 28 | 29 | -- Tabbing util 30 | local function tab(s) 31 | str = str .. ("\t"):rep(tabLevel) .. s 32 | end 33 | 34 | local function arrEncoding(val, bracket, closeBracket, iterator, loopFunc) 35 | str = str .. bracket 36 | if pretty then 37 | str = str .. "\n" 38 | tabLevel = tabLevel + 1 39 | end 40 | for k,v in iterator(val) do 41 | tab("") 42 | loopFunc(k,v) 43 | str = str .. "," 44 | if pretty then str = str .. "\n" end 45 | end 46 | if pretty then 47 | tabLevel = tabLevel - 1 48 | end 49 | if str:sub(-2) == ",\n" then 50 | str = str:sub(1, -3) .. "\n" 51 | elseif str:sub(-1) == "," then 52 | str = str:sub(1, -2) 53 | end 54 | tab(closeBracket) 55 | end 56 | 57 | -- Table encoding 58 | if type(val) == "table" then 59 | assert(not tTracking[val], "Cannot encode a table holding itself recursively") 60 | tTracking[val] = true 61 | if isArray(val) then 62 | arrEncoding(val, "[", "]", ipairs, function(k,v) 63 | str = str .. encodeCommon(v, pretty, tabLevel, tTracking) 64 | end) 65 | else 66 | arrEncoding(val, "{", "}", pairs, function(k,v) 67 | assert(type(k) == "string", "JSON object keys must be strings", 2) 68 | str = str .. encodeCommon(k, pretty, tabLevel, tTracking) 69 | str = str .. (pretty and ": " or ":") .. encodeCommon(v, pretty, tabLevel, tTracking) 70 | end) 71 | end 72 | -- String encoding 73 | elseif type(val) == "string" then 74 | str = '"' .. val:gsub("[%c\"\\]", controls) .. '"' 75 | -- Number encoding 76 | elseif type(val) == "number" or type(val) == "boolean" then 77 | str = tostring(val) 78 | else 79 | error("JSON only supports arrays, objects, numbers, booleans, and strings", 2) 80 | end 81 | return str 82 | end 83 | 84 | function encode(val) 85 | return encodeCommon(val, false, 0, {}) 86 | end 87 | 88 | function encodePretty(val) 89 | return encodeCommon(val, true, 0, {}) 90 | end 91 | 92 | ------------------------------------------------------------------ decoding 93 | 94 | function parseBoolean(str) 95 | if str:sub(1, 4) == "true" then 96 | return true, removeWhite(str:sub(5)) 97 | else 98 | return false, removeWhite(str:sub(6)) 99 | end 100 | end 101 | 102 | function parseNull(str) 103 | return nil, removeWhite(str:sub(5)) 104 | end 105 | 106 | local numChars = {['e']=true; ['E']=true; ['+']=true; ['-']=true; ['.']=true} 107 | function parseNumber(str) 108 | local i = 1 109 | while numChars[str:sub(i, i)] or tonumber(str:sub(i, i)) do 110 | i = i + 1 111 | end 112 | local val = tonumber(str:sub(1, i - 1)) 113 | str = removeWhite(str:sub(i)) 114 | return val, str 115 | end 116 | 117 | function parseString(str) 118 | local i,j = str:find('[^\\]"') 119 | local s = str:sub(2, j - 1) 120 | 121 | for k,v in pairs(controls) do 122 | s = s:gsub(v, k) 123 | end 124 | str = removeWhite(str:sub(j + 1)) 125 | return s, str 126 | end 127 | 128 | function parseArray(str) 129 | str = removeWhite(str:sub(2)) 130 | 131 | local val = {} 132 | local i = 1 133 | while str:sub(1, 1) ~= "]" do 134 | local v = nil 135 | v, str = parseValue(str) 136 | val[i] = v 137 | i = i + 1 138 | str = removeWhite(str) 139 | end 140 | str = removeWhite(str:sub(2)) 141 | return val, str 142 | end 143 | 144 | function parseObject(str) 145 | str = removeWhite(str:sub(2)) 146 | 147 | local val = {} 148 | while str:sub(1, 1) ~= "}" do 149 | local k, v = nil, nil 150 | k, v, str = parseMember(str) 151 | val[k] = v 152 | str = removeWhite(str) 153 | end 154 | str = removeWhite(str:sub(2)) 155 | return val, str 156 | end 157 | 158 | function parseMember(str) 159 | local k = nil 160 | k, str = parseValue(str) 161 | local val = nil 162 | val, str = parseValue(str) 163 | return k, val, str 164 | end 165 | 166 | function parseValue(str) 167 | local fchar = str:sub(1, 1) 168 | if fchar == "{" then 169 | return parseObject(str) 170 | elseif fchar == "[" then 171 | return parseArray(str) 172 | elseif tonumber(fchar) ~= nil or numChars[fchar] then 173 | return parseNumber(str) 174 | elseif str:sub(1, 4) == "true" or str:sub(1, 5) == "false" then 175 | return parseBoolean(str) 176 | elseif fchar == "\"" then 177 | return parseString(str) 178 | elseif str:sub(1, 4) == "null" then 179 | return parseNull(str) 180 | end 181 | return nil 182 | end 183 | 184 | function decode(str) 185 | str = removeWhite(str) 186 | t = parseValue(str) 187 | return t 188 | end 189 | 190 | function decodeFromFile(path) 191 | local file = assert(fs.open(path, "r")) 192 | return decode(file.readAll()) 193 | end -------------------------------------------------------------------------------- /kernel/library.lua: -------------------------------------------------------------------------------- 1 | local Library = {} 2 | 3 | function Library.Load(file, ...) 4 | local task = System.Tasks.NewTask(file, false) 5 | task:Start(...) 6 | 7 | local env = setmetatable({ function() end }, { 8 | __index = task:GetSandbox():GetEnv(), 9 | __tostring = function() 10 | return "Library (" .. System.Path.Normalise(file) .. ")" 11 | end 12 | }) 13 | 14 | return env 15 | end 16 | 17 | function Library.LoadIntoTask(file, task, ...) 18 | local lib = Library.Load(file, ...) 19 | task:AddLibrary(lib, fs.getName(file), file) 20 | end 21 | 22 | System.Tasks.__replaceNative("os", "loadAPI", function(task, file, ...) 23 | local ok, err = pcall(Library.LoadIntoTask, file, task, ...) 24 | printError(err) 25 | return ok 26 | end) 27 | 28 | return Library 29 | -------------------------------------------------------------------------------- /kernel/mounts.lua: -------------------------------------------------------------------------------- 1 | do 2 | local mounts = System.Registry.Get("FileSystem/Mounts") 3 | for k,v in pairs(mounts) do 4 | if k == "K" then 5 | print("Drive K:/ can't be mounted at boot!! You must mount it yourself later.") 6 | else 7 | print("Mounting " .. k .. " -> " .. v) 8 | System.File.RegisterMount(k, System.File.DirMount(v)) 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /kernel/path.lua: -------------------------------------------------------------------------------- 1 | local fscombine = fs.combine 2 | 3 | local function GetDriveAndPath(path) 4 | if path == "" then return nil, "/" end 5 | if path == "/" or path == "\\" then return nil, "/" end 6 | 7 | if path == nil then error("path can't be nil", 2) end 8 | 9 | local drive = path:match("([A-Z])[%:%%]") 10 | if drive == "" then drive = nil end 11 | 12 | local filePattern = "[A-Z][%:%%](.*)" 13 | if drive == nil then filePattern = "(.*)" end 14 | 15 | local filePath = path:match(filePattern) 16 | return drive, filePath 17 | end 18 | 19 | local function GetPathWithoutDrive(path) 20 | return path:match("[A-Z][%:%%](.*)") or "/" 21 | end 22 | 23 | local function GetDefaultDrive() 24 | return "U" 25 | end 26 | 27 | local function GetRootElement(path) 28 | local name = "" 29 | local drive, filePath = GetDriveAndPath(path) 30 | 31 | if drive ~= nil then 32 | path = filePath 33 | end 34 | 35 | for i=1,#path do 36 | local c = path:sub(i, i) 37 | 38 | if i > 1 and (c == "/" or c == "\\") then 39 | break 40 | end 41 | 42 | name = name .. c 43 | end 44 | 45 | return name, drive 46 | end 47 | 48 | local function GetRootElementWithDrive(path) 49 | local name, drive = GetRootElement(path) 50 | return drive .. name 51 | end 52 | 53 | local function Normalise(path, driveSep) 54 | driveSep = driveSep or ":" 55 | 56 | if path == nil then error("path can't be nil", 2) end 57 | local drive, fullPath = GetDriveAndPath(path) 58 | 59 | if fullPath ~= nil then 60 | local continue = true 61 | 62 | if fullPath == "" then fullPath = "/"; continue = false end 63 | if fullPath == "/" or fullPath == "\\" then fullPath = "/"; continue = false end 64 | 65 | if continue then 66 | fullPath = fullPath:gsub("\\", "/") 67 | if fullPath:sub(1, 1) ~= "/" then 68 | fullPath = "/" .. fullPath 69 | end 70 | 71 | if fullPath:sub(#fullPath, #fullPath) == "/" then 72 | fullPath = fullPath:sub(1, #fullPath - 1) 73 | end 74 | end 75 | end 76 | 77 | if drive ~= nil then 78 | fullPath = drive .. driveSep .. (fullPath or "/") 79 | end 80 | 81 | return fullPath 82 | end 83 | 84 | local function Combine(path1, path2, driveSep) 85 | driveSep = driveSep or ":" 86 | 87 | local d1, p1 = GetDriveAndPath(path1) 88 | local d2, p2 = GetDriveAndPath(path2) 89 | 90 | local combined = Normalise(fscombine(p1, p2)) 91 | if d1 ~= nil and d2 ~= nil then 92 | if d1 ~= d2 then 93 | error("paths have differing drives!", 2) 94 | end 95 | 96 | return d1 .. driveSep .. combined 97 | elseif (d1 ~= nil and d2 == nil) or (d1 == nil and d2 ~= nil) then 98 | return (d1 or d2) .. driveSep .. combined 99 | elseif d1 == nil and d2 == nil then 100 | return combined 101 | end 102 | end 103 | 104 | return { 105 | GetDrive = GetDrive, 106 | GetRootElement = GetRootElement, 107 | GetRootElementWithDrive = GetRootElementWithDrive, 108 | GetPathWithoutDrive = GetPathWithoutDrive, 109 | GetDriveAndPath = GetDriveAndPath, 110 | GetDefaultDrive = GetDefaultDrive, 111 | 112 | Combine = Combine, 113 | Normalise = Normalise, 114 | Normalize = Normalise 115 | } 116 | -------------------------------------------------------------------------------- /kernel/registry.lua: -------------------------------------------------------------------------------- 1 | local Registry = {} 2 | 3 | local REGISTRY_FILE = "S:/registry.dat" 4 | local REGENTRY_KEY = 0xFF 5 | local REGENTRY_DIR = 0xFE 6 | 7 | local __registry = { 8 | FileSystem = { 9 | Mounts = { 10 | U = "/user" 11 | } 12 | }, 13 | 14 | COPPER = { 15 | Name = "Computer-" .. os.getComputerID() 16 | } 17 | } 18 | 19 | local function explodeKey(key) 20 | local elements = {} 21 | for elem in key:gmatch("[^/\\]+") do 22 | elements[#elements + 1] = elem 23 | end 24 | return elements 25 | end 26 | 27 | function Registry.Set(key, value) 28 | local elems = explodeKey(key) 29 | 30 | if #elems == 0 then 31 | error("can't set the root dir", 2) 32 | end 33 | 34 | local dir = nil 35 | local last = __registry 36 | 37 | local _key = nil 38 | 39 | for i,v in ipairs(elems) do 40 | dir = last[v] 41 | if i == #elems then 42 | _key = v 43 | break 44 | end 45 | 46 | last = dir 47 | end 48 | 49 | last[_key] = value 50 | end 51 | 52 | function Registry.Get(key) 53 | local elems = explodeKey(key) 54 | 55 | if #elems == 0 then 56 | return __registry 57 | end 58 | 59 | local dir = nil 60 | local last = __registry 61 | 62 | for _,v in pairs(elems) do 63 | dir = last[v] 64 | if dir == nil then 65 | return nil, v 66 | end 67 | 68 | last = dir 69 | end 70 | 71 | return dir 72 | end 73 | 74 | function Registry.ValidateKey(key, tbl, doSave) 75 | if doSave == nil then doSave = true end 76 | 77 | local changes = 0 78 | local dir = System.Registry.Get(key) 79 | if dir ~= nil and type(dir) ~= "table" then 80 | error("can't validate non-table key", 2) 81 | end 82 | 83 | if dir == nil then 84 | dir = {} 85 | System.Registry.Set(key, dir) 86 | end 87 | 88 | for k,v in pairs(tbl) do 89 | if dir[k] == nil then 90 | dir[k] = v 91 | changes = changes + 1 92 | else 93 | if type(v) == "table" then 94 | local _changes = Registry.ValidateKey(key .. "/" .. k, v, false) 95 | changes = changes + _changes 96 | end 97 | end 98 | end 99 | 100 | if doSave and changes > 0 then 101 | Registry.Save() 102 | end 103 | 104 | return changes 105 | end 106 | 107 | function Registry.Delete(key) 108 | Registry.Set(key, nil) 109 | end 110 | 111 | function Registry.Save() 112 | local file = fs.open(REGISTRY_FILE, "w") 113 | file.write(textutils.serialiseJSON(__registry)) 114 | file.close() 115 | end 116 | 117 | function Registry.Load() 118 | local file = fs.open(REGISTRY_FILE, "r") 119 | if file then 120 | __registry = textutils.unserialiseJSON(file.readAll()) 121 | file.close() 122 | else 123 | Registry.Save() 124 | end 125 | end 126 | 127 | Registry.Load() 128 | 129 | return Registry 130 | -------------------------------------------------------------------------------- /kernel/sandbox.lua: -------------------------------------------------------------------------------- 1 | local SandboxLib = {} 2 | 3 | local Sandbox = {} 4 | Sandbox.__index = Sandbox 5 | 6 | setmetatable(Sandbox, { 7 | __call = function(self, file, _env) 8 | local self = setmetatable({}, Sandbox) 9 | 10 | local env = setmetatable({}, { __index = _env }) 11 | 12 | self.__env = env 13 | 14 | if load then 15 | -- Lua 5.2 (CC1.74+) 16 | local chunk, msg = loadfile(file, env) 17 | if chunk == nil then 18 | self.__func = nil 19 | error("Failed to create sandbox: " .. msg, 0) 20 | end 21 | 22 | self.__func = chunk 23 | else 24 | -- Lua 5.1 25 | local chunk, msg = loadfile(file) 26 | if chunk == nil then 27 | self.__func = nil 28 | error("Failed to create sandbox: " .. msg, 0) 29 | end 30 | 31 | setfenv(chunk, env) 32 | self.__func = chunk 33 | end 34 | 35 | return self 36 | end 37 | }) 38 | 39 | function Sandbox:GetFunction() 40 | return self.__func 41 | end 42 | 43 | function Sandbox:GetEnv() 44 | return self.__env 45 | end 46 | 47 | function SandboxLib.NewSandbox(...) 48 | return Sandbox(...) 49 | end 50 | 51 | return SandboxLib 52 | -------------------------------------------------------------------------------- /kernel/security.lua: -------------------------------------------------------------------------------- 1 | -- Minified SHA256 lib by GravityScore found here: http://www.computercraft.info/forums2/index.php?/topic/8169-sha-256-in-pure-lua/ 2 | local a=2^32;local b=a-1;local function c(d)local mt={}local e=setmetatable({},mt)function mt:__index(f)local g=d(f)e[f]=g;return g end;return e end;local function h(e,i)local function j(k,l)local m,o=0,1;while k~=0 and l~=0 do local p,q=k%i,l%i;m=m+e[p][q]*o;k=(k-p)/i;l=(l-q)/i;o=o*i end;m=m+(k+l)*o;return m end;return j end;local function r(e)local s=h(e,2^1)local t=c(function(k)return c(function(l)return s(k,l)end)end)return h(t,2^e.n or 1)end;local u=r({[0]={[0]=0,[1]=1},[1]={[0]=1,[1]=0},n=4})local function v(k,l,w,...)local x=nil;if l then k=k%a;l=l%a;x=u(k,l)if w then x=v(x,w,...)end;return x elseif k then return k%a else return 0 end end;local function y(k,l,w,...)local x;if l then k=k%a;l=l%a;x=(k+l-u(k,l))/2;if w then x=bit32_band(x,w,...)end;return x elseif k then return k%a else return b end end;local function z(A)return(-1-A)%a end;local function B(k,C)if C<0 then return lshift(k,-C)end;return math.floor(k%2^32/2^C)end;local function D(A,C)if C>31 or C<-31 then return 0 end;return B(A%a,C)end;local function lshift(k,C)if C<0 then return D(k,-C)end;return k*2^C%2^32 end;local function E(A,C)A=A%a;C=C%32;local F=y(A,2^C-1)return D(A,C)+lshift(F,32-C)end;local f={0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2}local function G(H)return string.gsub(H,".",function(w)return string.format("%02x",string.byte(w))end)end;local function I(J,n)local H=""for K=1,n do local L=J%256;H=string.char(L)..H;J=(J-L)/256 end;return H end;local function M(H,K)local n=0;for K=K,K+3 do n=n*256+string.byte(H,K)end;return n end;local function N(O,P)local Q=64-(P+9)%64;P=I(8*P,8)O=O.."\128"..string.rep("\0",Q)..P;assert(#O%64==0)return O end;local function R(S)S[1]=0x6a09e667;S[2]=0xbb67ae85;S[3]=0x3c6ef372;S[4]=0xa54ff53a;S[5]=0x510e527f;S[6]=0x9b05688c;S[7]=0x1f83d9ab;S[8]=0x5be0cd19;return S end;local function T(O,K,S)local U={}for V=1,16 do U[V]=M(O,K+(V-1)*4)end;for V=17,64 do local g=U[V-15]local W=v(E(g,7),E(g,18),D(g,3))g=U[V-2]U[V]=U[V-16]+W+U[V-7]+v(E(g,17),E(g,19),D(g,10))end;local k,l,w,X,Y,d,Z,_=S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[8]for K=1,64 do local W=v(E(k,2),E(k,13),E(k,22))local a0=v(y(k,l),y(k,w),y(l,w))local a1=W+a0;local a2=v(E(Y,6),E(Y,11),E(Y,25))local a3=v(y(Y,d),y(z(Y),Z))local a4=_+a2+a3+f[K]+U[K]_,Z,d,Y,X,w,l,k=Z,d,Y,X+a4,w,l,k,a4+a1 end;S[1]=y(S[1]+k)S[2]=y(S[2]+l)S[3]=y(S[3]+w)S[4]=y(S[4]+X)S[5]=y(S[5]+Y)S[6]=y(S[6]+d)S[7]=y(S[7]+Z)S[8]=y(S[8]+_)end;local function sha256(O)O=N(O,#O)local S=R({})for K=1,#O,64 do T(O,K,S)end;return G(I(S[1],4)..I(S[2],4)..I(S[3],4)..I(S[4],4)..I(S[5],4)..I(S[6],4)..I(S[7],4)..I(S[8],4))end 3 | 4 | local Security = {} 5 | 6 | function Security.GenerateSalt(length) 7 | local salt = "" 8 | for i=1,(length or 8) do 9 | salt = salt .. string.char(math.random(33, 127)) 10 | end 11 | return salt 12 | end 13 | 14 | function Security.Hash(input, salt) 15 | return sha256(input .. (salt or "")) 16 | end 17 | 18 | local AES = System.Library.Load("K:/lib/AES") 19 | local Base64 = System.Library.Load("K:/lib/Base64") 20 | 21 | function Security.Encrypt(input, key) 22 | return Base64.encode(AES.encrypt(key, input)) 23 | end 24 | 25 | function Security.Decrypt(input, key) 26 | return AES.decrypt(key, Base64.decode(input)) 27 | end 28 | 29 | function Security.Encode(input) 30 | return Base64.encode(input) 31 | end 32 | 33 | function Security.Decode(input) 34 | return Base64.decode(input) 35 | end 36 | 37 | return Security 38 | -------------------------------------------------------------------------------- /kernel/shellmgr.lua: -------------------------------------------------------------------------------- 1 | local ShellMgr = {} 2 | local currentShell = nil 3 | 4 | local required = { 5 | "exit"; 6 | "dir", "setDir"; 7 | "path", "setPath"; 8 | "resolve", "resolveProgram"; 9 | "aliases", "setAlias", "clearAlias"; 10 | "programs", "run"; 11 | } 12 | 13 | local function isRequired(func) 14 | for _,v in pairs(required) do 15 | if v == func then 16 | return true 17 | end 18 | end 19 | 20 | return false 21 | end 22 | 23 | local function verifyShell(sh) 24 | local valid = {} 25 | 26 | local function isValid(func) 27 | for _,v in pairs(valid) do 28 | if v == func then 29 | return true 30 | end 31 | end 32 | 33 | return false 34 | end 35 | 36 | for k,v in pairs(sh) do 37 | if isRequired(k) and type(v) == "function" then 38 | valid[#valid + 1] = k 39 | end 40 | end 41 | 42 | local invalid = {} 43 | 44 | for _,v in pairs(required) do 45 | if not isValid(v) then 46 | invalid[#invalid + 1] = v 47 | end 48 | end 49 | 50 | return invalid 51 | end 52 | 53 | function ShellMgr.SetShell(sh) 54 | local invalids = verifyShell(sh) 55 | if #invalids > 0 then 56 | error("Invalid or missing shell functions: " .. table.concat(invalids, ", "), 2) 57 | return 58 | end 59 | 60 | currentShell = sh 61 | end 62 | 63 | function ShellMgr.GetShell() 64 | return currentShell 65 | end 66 | 67 | local shellTID = nil 68 | 69 | function ShellMgr.SetShellTID(tid) 70 | shellTID = tid 71 | end 72 | 73 | function ShellMgr.GetShellTID() 74 | return shellTID 75 | end 76 | 77 | System.Tasks.__replaceNative("shell", "getRunningProgram", function(task) 78 | return task.Name 79 | end) 80 | 81 | return ShellMgr 82 | -------------------------------------------------------------------------------- /kernel/socket.lua: -------------------------------------------------------------------------------- 1 | local SocketLib = { 2 | SocketType = { 3 | Net = 0x1; 4 | Task = 0x2; 5 | } 6 | } 7 | 8 | local socketCache = {} 9 | 10 | local function makeCacheID(device, freq, replyFreq) 11 | return device.GetName() .. ":" .. freq .. ":" .. (replyFreq or freq) 12 | end 13 | 14 | local Socket = {} 15 | Socket.__index = Socket 16 | 17 | setmetatable(Socket, { 18 | __call = function(cls) 19 | error("can't instantiate a socket this way", 2) 20 | end 21 | }) 22 | 23 | function Socket:GetSocketType() end 24 | function Socket:Transmit(data) end 25 | function Socket:Receive(timeout) end 26 | function Socket:Close() end 27 | 28 | local NetSocket = {} 29 | NetSocket.__index = NetSocket 30 | 31 | setmetatable(NetSocket, { 32 | __index = Socket, 33 | __call = function(cls, device, freq, replyFreq) 34 | local self = setmetatable({}, NetSocket) 35 | self.__frequency = freq 36 | self.__replyFreq = replyFreq or freq 37 | 38 | if device.GetType() ~= "modem" then 39 | error("NetSocket(): arg #1 must be a modem!!", 2) 40 | return 41 | end 42 | 43 | self.__device = device 44 | self.__distance = -1 45 | 46 | self:EnsureOpen() 47 | return self 48 | end 49 | }) 50 | 51 | function NetSocket:GetSocketType() 52 | return SocketLib.SocketType.Net 53 | end 54 | 55 | function NetSocket:GetReplyFrequency() 56 | return self.__replyFreq or self.__frequency 57 | end 58 | 59 | function NetSocket:GetFrequency() 60 | return self.__frequency 61 | end 62 | 63 | function NetSocket:IsWireless() 64 | return self.__device.isWireless() 65 | end 66 | 67 | function NetSocket:EnsureOpen() 68 | if not self.__device.isOpen(self.__frequency) then 69 | self.__device.open(self.__frequency) 70 | end 71 | 72 | if not self.__device.isOpen(self.__replyFreq) then 73 | self.__device.open(self.__replyFreq) 74 | end 75 | end 76 | 77 | function NetSocket:Transmit(data) 78 | self:EnsureOpen() 79 | self.__device.transmit(self.__frequency, self.__replyFreq, data) 80 | end 81 | 82 | function NetSocket:Receive(timeout) 83 | self:EnsureOpen() 84 | 85 | local timerID = nil 86 | if timeout then 87 | timerID = os.startTimer(timeout) 88 | end 89 | 90 | local _data = nil 91 | 92 | while true do 93 | local e, side, _, _, data, dist = os.pullEvent() 94 | 95 | if e == "modem_message" and side == self.__device.GetName() then 96 | self.__distance = dist 97 | _data = data 98 | break 99 | elseif e == "timer" and side == timerID then 100 | _data = nil 101 | break 102 | end 103 | end 104 | 105 | return _data 106 | end 107 | 108 | function NetSocket:GetDistance() 109 | return self.__distance 110 | end 111 | 112 | function NetSocket:GetCacheID() 113 | return makeCacheID(self.__device, self.__frequency, self.__replyFreq) 114 | end 115 | 116 | function NetSocket:Close() 117 | self.__device.close(self.__replyFreq) 118 | self.__device.close(self.__frequency) 119 | 120 | local cacheID = self:GetCacheID() 121 | if socketCache[cacheID] ~= nil then 122 | socketCache[cacheID] = nil 123 | end 124 | end 125 | 126 | function SocketLib.RequestNetSocket(device, freq, replyFreq) 127 | local socketID = makeCacheID(device, freq, replyFreq) 128 | local socket = socketCache[socketID] 129 | 130 | if socket == nil then 131 | socket = NetSocket(device, freq, replyFreq) 132 | socketCache[socketID] = socket 133 | return socketCache[socketID], socketID 134 | end 135 | 136 | return socket, socketID 137 | end 138 | 139 | --[[function SocketLib.GetSocketCache() 140 | return socketCache 141 | end]] 142 | 143 | function SocketLib.GetFromCacheID(cid) 144 | return socketCache[cid] 145 | end 146 | 147 | System.Events.RegisterTranslator("modem_message", function(side, freq, replyFreq, msg, dist) 148 | if side ~= nil then 149 | local device = System.Network[side] 150 | local sock = System.Socket.RequestNetSocket(device, freq, replyFreq) 151 | sock.__distance = dist 152 | os.queueEvent("socket_message", makeCacheID(device, freq, replyFreq), msg) 153 | return "modem_message", side, freq, replyFreq, msg, dist 154 | end 155 | end) 156 | 157 | return SocketLib 158 | -------------------------------------------------------------------------------- /kernel/start.lua: -------------------------------------------------------------------------------- 1 | term.clear() 2 | term.setCursorPos(1, 1) 3 | 4 | local _fs = _G.fs 5 | 6 | if unpack == nil then 7 | unpack = table.unpack 8 | end 9 | 10 | System = { 11 | Version = "1.0"; 12 | } 13 | 14 | local modules = { 15 | { "Path", "kernel/path.lua" }; 16 | { "File", "kernel/filesys.lua" }; 17 | 18 | { "Events", "K:/events.lua" }; 19 | { "Sandbox", "K:/sandbox.lua" }; 20 | { "Tasks", "K:/tasks.lua"}; 21 | { "Library", "K:/library.lua" }; 22 | { "Security", "K:/security.lua" }; 23 | { "JSON", "K:/json.lua" }; 24 | { "Registry", "K:/registry.lua" }; 25 | { "Mounts", "K:/mounts.lua" }; 26 | { "ShellMgr", "K:/shellmgr.lua" }; 27 | { "Network", "K:/devices.lua" }; 28 | { "Socket", "K:/socket.lua" }; 29 | { "COPPER", "K:/copper.lua" }; 30 | } 31 | 32 | local function loadModules(loadCallback) 33 | for i=1,#modules do 34 | local v = modules[i] 35 | local chunk, msg = loadfile(v[2], env) 36 | 37 | loadCallback(v[1], v[2]) 38 | 39 | if chunk == nil then 40 | printError("Syntax error: " .. msg) 41 | end 42 | 43 | local ok, err = pcall(function() 44 | local module = chunk() 45 | if module ~= nil then 46 | module[1] = function() end -- Make sure the table can't be serialised 47 | 48 | local mt = getmetatable(module) 49 | if mt == nil then 50 | mt = setmetatable(module, {}) 51 | end 52 | 53 | mt.__tostring = function() 54 | return "Kernel Module (" .. v[1] .. ")" 55 | end 56 | 57 | setmetatable(module, mt) 58 | 59 | System[v[1]] = module 60 | end 61 | end) 62 | 63 | if not ok then 64 | printError("Failed! Error: " .. err) 65 | end 66 | end 67 | end 68 | 69 | local function mainLoop(...) 70 | local e, p1, p2, p3, p4, p5 = System.Events.Translate(...) 71 | System.Tasks.KeepAlive({ e, p1, p2, p3, p4, p5 }) 72 | end 73 | 74 | local log = nil 75 | 76 | local oldPrint = print 77 | print = function(...) 78 | local str = table.concat({ ... }) 79 | if log ~= nil then 80 | log.writeLine(str) 81 | end 82 | return oldPrint(str) 83 | end 84 | 85 | do 86 | log = _fs.open("system/boot_log.txt", "w") 87 | 88 | print("Running cheetOS v" .. System.Version) 89 | print("Loading modules...") 90 | loadModules(function(k, v) 91 | print(" -> " .. k .. " (" .. v .. ")...") 92 | end) 93 | 94 | if System.Tasks.__replaceNative then 95 | System.Tasks.__replaceNative = nil 96 | end 97 | 98 | System.File.Unmount("K") 99 | 100 | log.close() 101 | log = nil 102 | 103 | print = oldPrint 104 | 105 | local sysinit = System.Tasks.NewTask("S:/sysinit.lua") 106 | sysinit:Start() 107 | 108 | while true do 109 | mainLoop(os.pullEventRaw()) 110 | end 111 | end 112 | -------------------------------------------------------------------------------- /kernel/tasks.lua: -------------------------------------------------------------------------------- 1 | local __replacements = {} 2 | local __customQueue = {} 3 | 4 | local Tasks = { 5 | Signal = { 6 | Terminate = 1; -- 00000001 7 | Kill = 2; -- 00000010 8 | Suspend = 4; -- 00000100 9 | Resume = 8; -- 00001000 10 | RequestExit = 16; -- 00010000 11 | }, 12 | 13 | TaskState = { 14 | Alive = 1; -- 00000001 15 | Dead = 2; -- 00000010 16 | Error = 4; -- 00000100 17 | Idle = 8; -- 00001000 18 | } 19 | } 20 | 21 | local signalHandlers = { 22 | [Tasks.Signal.Terminate] = function(self) 23 | self:QueueEvent("terminate") 24 | end, 25 | 26 | [Tasks.Signal.RequestExit] = function(self) 27 | self:QueueEvent("please_exit") 28 | end, 29 | 30 | [Tasks.Signal.Kill] = function(self) 31 | self.__state = Tasks.TaskState.Dead 32 | self.__coro = nil 33 | end, 34 | 35 | [Tasks.Signal.Resume] = function(self) 36 | self.__state = Tasks.TaskState.Alive 37 | end, 38 | 39 | [Tasks.Signal.Suspend] = function(self) 40 | self.__state = Tasks.TaskState.Idle 41 | end 42 | } 43 | 44 | local Task = {} 45 | Task.__index = Task 46 | 47 | setmetatable(Task, { 48 | __call = function(cls, file, allowYield) 49 | local self = setmetatable({}, Task) 50 | self.TID = 0 51 | 52 | if allowYield == nil then allowYield = true end 53 | 54 | self.__coro = nil 55 | self.__lastError = "" 56 | self.__state = Tasks.TaskState.Idle 57 | self.__reqEvents = nil 58 | self.__file = file 59 | self.__sandbox = nil 60 | self.__allowYield = allowYield 61 | self.__libs = {} 62 | 63 | self.__libTbl = {} 64 | setmetatable(self.__libTbl, { __index = _G }) 65 | 66 | self.Name = fs.getName(self.__file) 67 | 68 | return self 69 | end 70 | }) 71 | 72 | function Task:__processYield(yieldData) 73 | local success = yieldData[1] 74 | 75 | if not success then 76 | local message = yieldData[2] 77 | printError(message) 78 | self.__lastError = message 79 | else 80 | local requestedEvents = { select( 2, unpack(yieldData) ) } 81 | 82 | if #requestedEvents == 0 then 83 | requestedEvents = nil 84 | end 85 | 86 | self.__reqEvents = requestedEvents 87 | end 88 | 89 | self:__handleDeath() 90 | end 91 | 92 | function Task:__handleDeath() 93 | if self.__coro == nil or coroutine.status(self.__coro) == "dead" then 94 | self.__state = Tasks.TaskState.Dead 95 | self.__coro = nil 96 | os.queueEvent("task_dead", self.TID) 97 | return 98 | end 99 | end 100 | 101 | function Task:AddLibrary(lib, name, file) 102 | self.__libs[name] = { 103 | File = file, 104 | Lib = lib 105 | } 106 | 107 | self.__libTbl[name] = lib 108 | end 109 | 110 | function Task:GetLibrary(name) 111 | return self.__libs[name] 112 | end 113 | 114 | function Task:GetSandbox() 115 | return self.__sandbox 116 | end 117 | 118 | function Task:Start(...) 119 | local env = {} 120 | 121 | env.__TASK__ = self 122 | env.__TID__ = self.TID 123 | env.__FILE__ = System.Path.Normalise(self.__file) 124 | env.__NAME__ = self.Name 125 | 126 | if System.ShellMgr then 127 | env.shell = System.ShellMgr.GetShell() 128 | end 129 | 130 | env.fs = System.File.GetFSAPI() 131 | 132 | for k,v in pairs(__replacements) do 133 | local target = nil 134 | if k == "" then 135 | target = env 136 | else 137 | if env[k] == nil then 138 | env[k] = {} 139 | setmetatable(env[k], { __index = _G[k] }) 140 | end 141 | 142 | target = env[k] 143 | end 144 | 145 | for fn,f in pairs(v) do 146 | target[fn] = function(...) 147 | return f(self, ...) 148 | end 149 | end 150 | end 151 | 152 | setmetatable(env, { __index = self.__libTbl }) 153 | 154 | local ok, err = pcall(function() 155 | self.__sandbox = System.Sandbox.NewSandbox(self.__file, env) 156 | end) 157 | 158 | if not ok then 159 | self.__coro = nil 160 | self:__handleDeath() 161 | error(err, 0) 162 | return 163 | end 164 | 165 | self.__func = self.__sandbox:GetFunction() 166 | self.__coro = coroutine.create(self.__func) 167 | self.__state = Tasks.TaskState.Alive 168 | 169 | if not self.__allowYield then 170 | self:__handleDeath() 171 | end 172 | 173 | local yieldData = { coroutine.resume(self.__coro, ...) } 174 | self:__processYield(yieldData) 175 | end 176 | 177 | function Task:HasRequested(event) 178 | if event == "terminate" then -- always allow terminate to pass through 179 | return true 180 | end 181 | 182 | if self.__reqEvents == nil then -- nil = any event 183 | return true 184 | end 185 | 186 | for _,v in pairs(self.__reqEvents) do 187 | if v == event then 188 | return true 189 | end 190 | end 191 | 192 | return false 193 | end 194 | 195 | function Task:KeepAlive(evtData) 196 | if self.__allowYield then 197 | if self.__state == Tasks.TaskState.Alive then 198 | local evtName = evtData[1] 199 | if not self:HasRequested(evtName) then 200 | return 201 | end 202 | 203 | local yieldData = { coroutine.resume( self.__coro, unpack(evtData) ) } 204 | self:__processYield(yieldData) 205 | end 206 | end 207 | end 208 | 209 | function Task:GetError() 210 | return self.__lastError 211 | end 212 | 213 | function Task:GetState() 214 | return self.__state 215 | end 216 | 217 | function Task:GetFile() 218 | return self.__file 219 | end 220 | 221 | function Task:SendSignal(signal) 222 | signalHandlers[signal](self) 223 | end 224 | 225 | local taskList = {} 226 | local newTaskQueue = {} 227 | 228 | local nextTaskID = 0 229 | 230 | function Tasks.NewTask(...) 231 | local task = Task(...) 232 | nextTaskID = nextTaskID + 1 233 | 234 | local index = nextTaskID 235 | task.TID = index 236 | newTaskQueue[index] = task 237 | return task, index 238 | end 239 | 240 | function Tasks.GetTaskByTID(tid) 241 | return taskList[tid] 242 | end 243 | 244 | function Tasks.KeepAlive(evtData) 245 | local toRemove = {} 246 | 247 | for k,v in pairs(newTaskQueue) do 248 | taskList[k] = v 249 | end 250 | 251 | newTaskQueue = {} 252 | 253 | for i,v in pairs(taskList) do 254 | v:KeepAlive(evtData) 255 | 256 | if v:GetState() == Tasks.TaskState.Dead then 257 | toRemove[#toRemove + 1] = i 258 | end 259 | end 260 | 261 | for i=1,#toRemove do 262 | local v = toRemove[i] 263 | taskList[v] = nil 264 | end 265 | end 266 | 267 | function Tasks.List() 268 | return taskList 269 | end 270 | 271 | function Tasks.WaitForTask(task) 272 | if type(task) == "number" then 273 | task = Tasks.GetTaskByTID(task) 274 | end 275 | 276 | assert(type(task) == "table") 277 | 278 | while task:GetState() ~= System.Tasks.TaskState.Dead do 279 | os.pullEvent("task_dead") 280 | end 281 | end 282 | 283 | function Tasks.__replaceNative(api, name, handler) 284 | if not __replacements[api] then 285 | __replacements[api] = {} 286 | end 287 | 288 | __replacements[api][name] = handler 289 | end 290 | 291 | local function customPullEvent(task, ...) 292 | local evtData = { os.pullEventRaw(...) } 293 | if evtData[1] == "terminate" then 294 | task:SendSignal(Tasks.Signal.Kill) 295 | end 296 | 297 | return unpack(evtData) 298 | end 299 | 300 | Tasks.__replaceNative("os", "pullEvent", customPullEvent) 301 | 302 | return Tasks 303 | -------------------------------------------------------------------------------- /kernel/tlc.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Top level coroutine override taken from http://www.computercraft.info/forums2/index.php?/topic/14785-a-smaller-top-level-coroutine-override/ 3 | ]] 4 | 5 | os.queueEvent("modem_message") 6 | local r = rednet.run 7 | function rednet.run() 8 | error("", 0) 9 | end 10 | 11 | local p = printError 12 | function _G.printError() 13 | _G.printError = p 14 | rednet.run = r 15 | local ok, err = pcall(function() assert(loadfile("kernel/start.lua"))() end) 16 | if not ok then printError(err) end 17 | end -------------------------------------------------------------------------------- /startup: -------------------------------------------------------------------------------- 1 | local useTLCO = true 2 | 3 | if fs.exists("notlco") then 4 | useTLCO = false 5 | end 6 | 7 | if useTLCO then 8 | dofile("kernel/tlc.lua") 9 | else 10 | shell.exit() 11 | shell = nil 12 | dofile("kernel/start.lua") 13 | end -------------------------------------------------------------------------------- /system/default/cdrv: -------------------------------------------------------------------------------- 1 | local newDrive = ... 2 | local drive = System.Path.GetDriveAndPath(newDrive or "") or newDrive 3 | 4 | if drive == nil then 5 | printError("Usage: " .. shell.getRunningProgram() .. " ") 6 | return 7 | end 8 | 9 | if not System.File.IsDrive(drive) then 10 | printError(tostring(drive) .. " is not a valid drive!") 11 | return 12 | end 13 | 14 | shell.setDir(drive .. ":/") 15 | -------------------------------------------------------------------------------- /system/default/copper: -------------------------------------------------------------------------------- 1 | local Config = { 2 | Name = "Computer-" .. os.getComputerID(), 3 | ModemName = "any", 4 | Frequency = 65000, 5 | CommandTimeout = 10, 6 | 7 | Session = { 8 | Server = nil, 9 | Key = nil, 10 | } 11 | } 12 | 13 | System.Registry.ValidateKey("COPPER", Config) 14 | Config = System.Registry.Get("COPPER") 15 | 16 | local function printSuccess(...) 17 | term.setTextColour(term.isColour() and colours.green or colours.white) 18 | _G.print(...) 19 | return term.setTextColour(colours.white) 20 | end 21 | 22 | local cmd = ... 23 | local args = { select(2, ...) } 24 | 25 | local function getModem(name) 26 | if name == "any" then 27 | return System.Network.GetAnyOfType("modem", function(m) 28 | return not m.isWireless() 29 | end) or 30 | System.Network.GetAnyOfType("modem") 31 | else 32 | local device = System.Network[name] 33 | return device.GetType() ~= "modem" and nil or device 34 | end 35 | end 36 | 37 | local function receivePacket(sock, serverName, timeout, ...) 38 | local pids = { ... } 39 | 40 | while true do 41 | local pack = sock:ReceivePacket(timeout) 42 | if pack == nil then 43 | -- timeout 44 | break 45 | end 46 | 47 | local rpid = pack:ReadNumber() 48 | local server = pack:ReadString() 49 | 50 | if server == serverName then 51 | for _,v in pairs(pids) do 52 | if v == rpid then 53 | return pack, rpid 54 | end 55 | end 56 | end 57 | end 58 | end 59 | 60 | local commands = { 61 | ["login"] = function(server) 62 | if not server then 63 | printError("Usage: login ") 64 | return 65 | end 66 | 67 | local modem = getModem(Config.ModemName) 68 | local sock = System.COPPER.Socket(Config.Name, server, modem, Config.Frequency) 69 | sock:RequestSalt() 70 | 71 | local pack = receivePacket(sock, server, Config.CommandTimeout, 72 | System.COPPER.PACKET_SALT) 73 | local salt = pack:ReadString() 74 | 75 | write("Enter Password: ") 76 | sock:Connect(read("*"), salt) 77 | 78 | local pid 79 | pack, pid = receivePacket(sock, server, Config.CommandTimeout, 80 | System.COPPER.PACKET_ACCESS_DENIED, 81 | System.COPPER.PACKET_ACCESS_GRANTED) 82 | 83 | if pid == System.COPPER.PACKET_ACCESS_GRANTED then 84 | local key = pack:ReadString() 85 | Config.Session.Server = server 86 | Config.Session.Key = key 87 | System.Registry.Save() 88 | 89 | printSuccess("Access granted.") 90 | print("Got key " .. key) 91 | elseif pid == System.COPPER.PACKET_ACCESS_DENIED then 92 | printError("Access denied. (Reason code ".. pack:ReadNumber() .. ")") 93 | end 94 | 95 | sock:Close() 96 | end, 97 | 98 | ["logout"] = function() 99 | local sock = System.COPPER.Socket(Config.Name, Config.Session.Server, 100 | getModem(Config.ModemName), Config.Frequency) 101 | 102 | local key = Config.Session.Key 103 | if key == nil then 104 | printError("You are not logged in.") 105 | return 106 | end 107 | 108 | sock:Disconnect(Config.Session.Key) 109 | sock:Close() 110 | 111 | Config.Session.Key = nil 112 | Config.Session.Server = nil 113 | System.Registry.Save() 114 | printSuccess("Successfully logged out.") 115 | end 116 | } 117 | 118 | do 119 | if Config.Name:match("^%s-$") then 120 | printError("Please name your computer by setting COPPER/Name in the registry.") 121 | return 122 | end 123 | 124 | if not commands[cmd] then 125 | printError("Type '" .. shell.getRunningProgram() .. " help' for a list of commands.") 126 | return 127 | end 128 | 129 | commands[cmd](unpack(args)) 130 | end 131 | -------------------------------------------------------------------------------- /system/default/copperserver: -------------------------------------------------------------------------------- 1 | local ServerConfig = { 2 | User = { 3 | Frequency = 65000; 4 | ModemName = "any"; 5 | Name = ""; 6 | MaxAcceptedDistance = 128; 7 | ServerDir = ""; 8 | }, 9 | 10 | Internal = { 11 | Password = nil, 12 | Salt = nil, 13 | }, 14 | } 15 | 16 | System.Registry.ValidateKey("COPPERServer", ServerConfig) 17 | ServerConfig = System.Registry.Get("COPPERServer") 18 | 19 | local logFile = nil 20 | 21 | local function print(...) 22 | term.setTextColour(colours.white) 23 | logFile.writeLine(table.concat({ ... })) 24 | return _G.print(...) 25 | end 26 | 27 | local function printWarning(...) 28 | term.setTextColour(term.isColour() and colours.yellow or colours.white) 29 | if logFile then 30 | logFile.writeLine(table.concat({ "Warning: ", ... })) 31 | end 32 | return _G.print(...) 33 | end 34 | 35 | local function printError(...) 36 | term.setTextColour(term.isColour() and colours.red or colours.white) 37 | if logFile then 38 | logFile.writeLine(table.concat({ "Error: ", ... })) 39 | end 40 | return _G.print(...) 41 | end 42 | 43 | local serverName = ServerConfig.User.Name 44 | if serverName:match("^%s-$") then 45 | printError("Please name your server by setting COPPERServer/User/Name in the registry.") 46 | return 47 | end 48 | 49 | local serverDir = ServerConfig.User.ServerDir 50 | if serverDir:match("^%s-$") then 51 | printError("Please set a directory for your server to run in by setting COPPERServer/User/ServerDir in the registry.") 52 | return 53 | end 54 | 55 | do 56 | local drive = System.Path.GetDriveAndPath(serverDir) 57 | if not System.File.IsDrive(drive) then 58 | printError("Server directory is not inside a valid drive.") 59 | return 60 | end 61 | 62 | if not fs.exists(serverDir) then 63 | fs.makeDir(serverDir) 64 | end 65 | end 66 | 67 | logFile = fs.open(System.Path.Combine(serverDir, "logs.txt"), "w") 68 | 69 | local password = ServerConfig.Internal.Password 70 | 71 | local modemName = ServerConfig.User.ModemName 72 | local modem 73 | 74 | do 75 | local wiredLambda = function(m) return not m.isWireless() end 76 | 77 | if modemName:lower() == "any" then 78 | modem = System.Network.GetAnyOfType("modem", wiredLambda) -- prefer wired 79 | or System.Network.GetAnyOfType("modem") -- fall back to wireless 80 | modemName = modem.GetName() 81 | else 82 | modem = System.Network[modemName] 83 | end 84 | 85 | 86 | if modem == nil then 87 | printError("No suitable modem found.") 88 | return 89 | end 90 | 91 | if modem.isWireless() then 92 | printWarning("Consider switching to a wired network!") 93 | end 94 | end 95 | 96 | local frequency = ServerConfig.User.Frequency 97 | local maxDist = ServerConfig.User.MaxAcceptedDistance 98 | 99 | local running = false 100 | 101 | local serverSocket = System.COPPER.Socket(serverName, serverName, modem, frequency) 102 | 103 | local function closeServer() 104 | logFile.close() 105 | running = false 106 | serverSocket:Close() 107 | end 108 | 109 | local function denyConnection(reason) 110 | local packet = System.COPPER.Packet() 111 | packet:WriteNumber(System.COPPER.PACKET_ACCESS_DENIED) 112 | packet:WriteString(serverName) 113 | packet:WriteNumber(reason) 114 | return packet 115 | end 116 | 117 | local function grantConnection(key) 118 | local packet = System.COPPER.Packet() 119 | packet:WriteNumber(System.COPPER.PACKET_ACCESS_GRANTED) 120 | packet:WriteString(serverName) 121 | packet:WriteString(key) 122 | return packet 123 | end 124 | 125 | local sessions = {} 126 | 127 | local function getSessionFromKey(key) 128 | for k,v in pairs(sessions) do 129 | if v.Key == key then 130 | return v, k 131 | end 132 | end 133 | end 134 | 135 | local packetHandlers = { 136 | [System.COPPER.PACKET_CONNECT] = function(name, pack) 137 | local encrypted = pack:ReadString() 138 | local hashed = ServerConfig.Internal.Password 139 | local salt = ServerConfig.Internal.Salt 140 | local password = System.Security.Decrypt(encrypted, hashed) 141 | 142 | if password == nil then 143 | return denyConnection(System.COPPER.DENY_REASON_INVALID_CREDENTIALS) 144 | end 145 | 146 | local incomingHashed = System.Security.Hash(password, salt) 147 | 148 | if hashed == incomingHashed then 149 | if sessions[name] ~= nil then 150 | return denyConnection(System.COPPER.DENY_REASON_ALREADY_LOGGED_IN) 151 | end 152 | 153 | local key = System.Security.Hash(password .. name, System.Security.GenerateSalt(32)) 154 | sessions[name] = { 155 | Key = key 156 | } 157 | 158 | return grantConnection(key) 159 | else 160 | return denyConnection(System.COPPER.DENY_REASON_INVALID_CREDENTIALS) 161 | end 162 | end, 163 | 164 | [System.COPPER.PACKET_REQUEST_SALT] = function(name, pack) 165 | local response = System.COPPER.Packet() 166 | response:WriteNumber(System.COPPER.PACKET_SALT) 167 | response:WriteString(serverName) 168 | response:WriteString(ServerConfig.Internal.Salt) 169 | print("Sending salt " .. ServerConfig.Internal.Salt) 170 | return response 171 | end, 172 | 173 | [System.COPPER.PACKET_LOGOUT] = function(name, pack) 174 | local key = pack:ReadString() 175 | local session, sessionName = getSessionFromKey(key) 176 | sessions[sessionName] = nil 177 | end 178 | } 179 | 180 | local function processMessage(sock, msg, dist) 181 | if maxDist >= 0 then 182 | if dist > maxDist then 183 | return -- ignore 184 | end 185 | end 186 | 187 | local packet = System.COPPER.MakePacketFromData(msg) 188 | if packet ~= nil then -- Non-COPPER packets will be nil 189 | local clientName = packet:ReadString() 190 | local pid = packet:ReadNumber() 191 | local name = packet:ReadString() 192 | 193 | if name ~= serverName then 194 | return 195 | end 196 | 197 | local handler = packetHandlers[pid] 198 | 199 | if handler then 200 | local response = handler(clientName, packet) 201 | if response then 202 | serverSocket:SendPacket(response) 203 | end 204 | end 205 | end 206 | end 207 | 208 | local function serverLoop() 209 | while running do 210 | local e, p1, p2, p3, p4, p5 = os.pullEvent("socket_message", "char") 211 | if e == "socket_message" then 212 | local sock = System.Socket.GetFromCacheID(p1) 213 | processMessage(sock, p2, sock:GetDistance()) 214 | elseif e == "char" then 215 | if p1 == "q" then 216 | return closeServer() 217 | end 218 | end 219 | end 220 | end 221 | 222 | local function setPassword(input) 223 | local salt = System.Security.GenerateSalt() 224 | local pswd = System.Security.Hash(input, salt) 225 | ServerConfig.Internal.Password = pswd 226 | ServerConfig.Internal.Salt = salt 227 | System.Registry.Save() 228 | end 229 | 230 | do 231 | print("Starting server on frequency " .. frequency) 232 | print("Name: " .. serverName) 233 | print("Modem: " .. modemName) 234 | print("Directory: " .. System.Path.Normalise(serverDir)) 235 | 236 | if password == nil then 237 | write("Please enter a password: ") 238 | setPassword(read("*")) 239 | end 240 | 241 | print("Press Q to end the server...") 242 | 243 | running = true 244 | serverLoop() 245 | 246 | return closeServer() 247 | end 248 | -------------------------------------------------------------------------------- /system/default/coservice.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | while true do 3 | local e, sockID, msg = os.pullEvent("socket_message") 4 | local sock = System.Socket.GetFromCacheID(sockID) 5 | 6 | end 7 | ]] 8 | -------------------------------------------------------------------------------- /system/default/devices: -------------------------------------------------------------------------------- 1 | do 2 | for k,v in pairs(System.Network.List()) do 3 | print("-> " .. tostring(System.Network.GetDevType(k) or "N/A") .. " (" .. tostring(k) .. ")") 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /system/default/devservice.lua: -------------------------------------------------------------------------------- 1 | while true do 2 | local e, side = os.pullEvent("peripheral", "peripheral_detach") 3 | if e == "peripheral" then 4 | System.Network.Register(side, peripheral.wrap(side)) 5 | elseif e == "peripheral_detach" then 6 | local device = System.Network[side] 7 | local removalList = { side } 8 | 9 | if device.GetType() == "modem" then 10 | -- check if any other devices were detached consequently 11 | 12 | for k,v in pairs(System.Network.List()) do 13 | if not v.IsValid() then 14 | removalList[#removalList + 1] = k 15 | end 16 | end 17 | end 18 | 19 | for i=1,#removalList do 20 | local item = removalList[i] 21 | System.Network.Unregister(item) 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /system/default/drives: -------------------------------------------------------------------------------- 1 | do 2 | local _fs = System.File.GetRealFSAPI() 3 | local rootFiles = _fs.list("/") 4 | 5 | for i=1,#rootFiles do 6 | local file = rootFiles[i] 7 | if _fs.isDir(file) then 8 | local drive = _fs.getDrive(file) 9 | if drive ~= "hdd" and drive ~= "rom" then 10 | print("-> " .. _fs.getName(file) .. " (" .. drive .. ")") 11 | end 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /system/default/echo: -------------------------------------------------------------------------------- 1 | local args = { ... } 2 | local cmdLine = table.concat(args, " ") 3 | print(cmdLine) 4 | -------------------------------------------------------------------------------- /system/default/findtid: -------------------------------------------------------------------------------- 1 | local name = ... 2 | 3 | if name == nil then 4 | printError("Usage: " .. shell.getRunningProgram() .. " ") 5 | return 6 | end 7 | 8 | do 9 | local found = false 10 | for _,v in pairs(System.Tasks.List()) do 11 | if v.Name == name then 12 | print("-> " .. v.Name .. " has TID " .. v.TID) 13 | found = true 14 | end 15 | end 16 | 17 | if not found then 18 | printError("No results.") 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /system/default/kill: -------------------------------------------------------------------------------- 1 | local task = ... 2 | 3 | local function printUsage() 4 | printError("Usage: " .. shell.getRunningProgram() .. " ") 5 | end 6 | 7 | if task == nil then 8 | printUsage() 9 | return 10 | end 11 | 12 | task = tonumber(task) or task 13 | 14 | do 15 | if type(task) == "number" then 16 | local t = System.Tasks.GetTaskByTID(task) 17 | if t == nil then 18 | printError("No such task") 19 | else 20 | print("Killing task " .. t.TID) 21 | t:SendSignal(System.Tasks.Signal.Kill) 22 | end 23 | elseif type(task) == "string" then 24 | local found = false 25 | for _,v in pairs(System.Tasks.List()) do 26 | if v.Name == task then 27 | print("Killing task " .. v.TID) 28 | v:SendSignal(System.Tasks.Signal.Kill) 29 | found = true 30 | end 31 | end 32 | 33 | if not found then 34 | printError("No such task") 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /system/default/mount: -------------------------------------------------------------------------------- 1 | local drive, dir = ... 2 | 3 | local function printUsage() 4 | printError("Usage: " .. shell.getRunningProgram() .. " ") 5 | end 6 | 7 | do 8 | if drive == nil or dir == nil then 9 | printUsage() 10 | return 11 | end 12 | 13 | drive = System.Path.GetDriveAndPath(drive) or drive 14 | 15 | if System.File.IsDrive(drive) then 16 | printError("The drive " .. drive .. " already exists") 17 | return 18 | end 19 | 20 | print("Mounting " .. dir .. " as " .. drive .. ":/") 21 | System.File.RegisterMount(drive, System.File.DirMount(dir)) 22 | 23 | if drive == "K" then 24 | if term.isColour() then 25 | term.setTextColour(colours.yellow) 26 | end 27 | 28 | print("Warning: Drive K:/ will not persist! You must re-mount it on reboot. Use a different drive letter to prevent this.") 29 | else 30 | System.Registry.Set("FileSystem/Mounts/" .. drive, dir) 31 | System.Registry.Save() 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /system/default/mounts: -------------------------------------------------------------------------------- 1 | do 2 | for _,v in pairs(System.File.GetMounts()) do 3 | local type = getmetatable(v).__type 4 | write("-> " .. v:GetLetter() .. " (" .. type) 5 | 6 | if type == "DirMount" then 7 | write(": " .. v:Resolve("")) 8 | end 9 | 10 | print(")") 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /system/default/origin: -------------------------------------------------------------------------------- 1 | local input = ... 2 | 3 | if input == nil then 4 | printError("Usage: " .. shell.getRunningProgram() .. " ") 5 | return 6 | end 7 | 8 | do 9 | local result = nil 10 | local asNum = tonumber(input) 11 | if asNum == nil then 12 | -- Command 13 | result = shell.resolveProgram(input) 14 | else 15 | -- Task 16 | local task = System.Tasks.GetTaskByTID(asNum) 17 | if task then 18 | result = task:GetFile() 19 | end 20 | end 21 | 22 | if result == nil then 23 | printError("Couldn't find origin of " .. tostring(input)) 24 | return 25 | end 26 | 27 | print("-> " .. tostring(result)) 28 | end 29 | -------------------------------------------------------------------------------- /system/default/pinvoke: -------------------------------------------------------------------------------- 1 | local netname, func = ... 2 | local argsStr = table.concat({ select(3, ...) }, " ") or "" 3 | 4 | local function printUsage() 5 | return printError("Usage: " .. shell.getRunningProgram() .. " [args]") 6 | end 7 | 8 | if netname == nil or func == nil then 9 | printUsage() 10 | return 11 | end 12 | 13 | local args = {} 14 | for arg in argsStr:gmatch("[^,]+") do 15 | args[#args + 1] = arg 16 | end 17 | 18 | local device = System.Network[netname] 19 | if device == nil then 20 | printError("Device not found.") 21 | return 22 | end 23 | 24 | local fargs = {} 25 | 26 | for i=1,#args do 27 | local arg = args[i] 28 | local strMatch = arg:match("\"(.-)\"") 29 | 30 | if strMatch then 31 | fargs[#fargs + 1] = strMatch 32 | else 33 | local asNum = tonumber(arg) 34 | if asNum ~= nil then 35 | fargs[#fargs + 1] = asNum 36 | else 37 | printError("Invalid argument. Did you put quotes around your strings?") 38 | return 39 | end 40 | end 41 | end 42 | 43 | return device[func](unpack(fargs)) 44 | -------------------------------------------------------------------------------- /system/default/registry: -------------------------------------------------------------------------------- 1 | local cmd = ... 2 | local args = { select(2, ...) } 3 | 4 | local function printUsage() 5 | printError("Type '" .. shell.getRunningProgram() .. " help' to show a list of available commands") 6 | end 7 | 8 | do 9 | local commands = { 10 | set = function(key, ...) 11 | if key == nil then 12 | return false, "No key was specified" 13 | end 14 | 15 | local values = { ... } 16 | if #values == 0 then 17 | return false, "No value was specified" 18 | end 19 | 20 | local value = table.concat(values, " ") 21 | 22 | print("Setting " .. key .. " to " .. value) 23 | System.Registry.Set(key, value) 24 | System.Registry.Save() 25 | return true 26 | end, 27 | 28 | get = function(key) 29 | if key == nil then 30 | return false, "No key was specified" 31 | end 32 | 33 | local value = System.Registry.Get(key) 34 | write("=> ") 35 | 36 | if type(value) == "table" then 37 | print() 38 | 39 | local encoded = System.JSON.encodePretty(value):gsub("\t", " ") 40 | print(encoded) 41 | else 42 | print(tostring(value)) 43 | end 44 | 45 | return true 46 | end, 47 | 48 | del = function(key) 49 | if key == nil then 50 | return false, "No key was specified" 51 | end 52 | 53 | print("Deleting " .. key) 54 | System.Registry.Delete(key) 55 | System.Registry.Save() 56 | return true 57 | end, 58 | 59 | help = function() 60 | print("List of commands:") 61 | print("set - Sets a registry key to a value") 62 | print("get - Outputs the value of a key") 63 | print("del - Deletes the specified key") 64 | print("help - Displays help") 65 | return true 66 | end 67 | } 68 | 69 | local command = commands[cmd] 70 | if command == nil then 71 | printUsage() 72 | return 73 | else 74 | local ok, err = command(unpack(args)) 75 | if not ok then 76 | printError(err) 77 | return 78 | end 79 | end 80 | end 81 | -------------------------------------------------------------------------------- /system/default/sshost.lua: -------------------------------------------------------------------------------- 1 | local EXIT_SUCCESS = 0 2 | local EXIT_FAILURE = 1 3 | 4 | local function runShellScript(file) 5 | local fhandle = fs.open(file, "r") 6 | 7 | local lineNum = 0 8 | for line in fhandle.readLine do 9 | lineNum = lineNum + 1 10 | if line:match("^%s-$") == nil and line:match("^[/%-][/%-].-$") == nil then 11 | shell.run(line) 12 | end 13 | end 14 | end 15 | 16 | local file = ... 17 | if not file then 18 | printError("No file specified.") 19 | return EXIT_FAILURE 20 | else 21 | if not fs.exists(file) then 22 | printError("The specified file doesn't exist!") 23 | return EXIT_FAILURE 24 | end 25 | 26 | runShellScript(file) 27 | return EXIT_SUCCESS 28 | end 29 | -------------------------------------------------------------------------------- /system/default/start: -------------------------------------------------------------------------------- 1 | local command = ... 2 | local args = { select(2, ...) } 3 | 4 | if command == nil then 5 | printError("Usage: " .. shell.getRunningProgram() .. " ") 6 | return 7 | end 8 | 9 | do 10 | local path = shell.resolveProgram(command) 11 | if not fs.exists(path) then 12 | printError("No such command") 13 | return 14 | end 15 | 16 | local task = System.Tasks.NewTask(path) 17 | task:Start(unpack(args or {})) 18 | end 19 | -------------------------------------------------------------------------------- /system/default/taft: -------------------------------------------------------------------------------- 1 | print("enry oward aft") -------------------------------------------------------------------------------- /system/default/tasks: -------------------------------------------------------------------------------- 1 | local w,h = term.getSize() 2 | 3 | local columns = { 4 | ["State"] = function(task) 5 | return task:GetState() 6 | end, 7 | 8 | ["Name"] = function(task) 9 | return task.Name 10 | end, 11 | 12 | ["TID"] = function(task) 13 | return task.TID 14 | end, 15 | } 16 | 17 | local function makeProcTable() 18 | local tbl = {} 19 | local cols = {} 20 | 21 | for k,_ in pairs(columns) do 22 | table.insert(cols, k) 23 | end 24 | 25 | table.insert(tbl, cols) 26 | 27 | for _,v in pairs(System.Tasks.List()) do 28 | local entry = {} 29 | 30 | for _,c in pairs(columns) do 31 | table.insert(entry, tostring(c(v))) 32 | end 33 | 34 | table.insert(tbl, entry) 35 | end 36 | 37 | return tbl 38 | end 39 | 40 | textutils.pagedTabulate(unpack(makeProcTable())) 41 | -------------------------------------------------------------------------------- /system/default/unmount: -------------------------------------------------------------------------------- 1 | local drive = ... 2 | 3 | local function printUsage() 4 | printError("Usage: " .. shell.getRunningProgram() .. " ") 5 | end 6 | 7 | do 8 | if drive == nil then 9 | printUsage() 10 | return 11 | end 12 | 13 | drive = System.Path.GetDriveAndPath(drive) or drive 14 | 15 | if not System.File.IsDrive(drive) then 16 | printError("No such drive '" .. drive .. "'") 17 | return 18 | end 19 | 20 | print("Unmounting " .. drive .. ":/") 21 | System.File.Unmount(drive) 22 | System.Registry.Delete("FileSystem/Mounts/" .. drive) 23 | System.Registry.Save() 24 | end 25 | -------------------------------------------------------------------------------- /system/errordebug.lua: -------------------------------------------------------------------------------- 1 | error("Hello World!") 2 | sleep(1) 3 | error("Hello World #2!") -------------------------------------------------------------------------------- /system/shell.lua: -------------------------------------------------------------------------------- 1 | local registryEntry = { 2 | StartupFile = "U:/start.ss", 3 | StartWorkingDir = "U:/", 4 | 5 | TextColour = "cyan", 6 | BackgroundColour = "black", 7 | 8 | ActiveTextColour = "white", 9 | ActiveBackgroundColour = "grey", 10 | 11 | InputChar = "$" 12 | } 13 | 14 | -- Make sure the shell keys exist 15 | System.Registry.ValidateKey("Shell", registryEntry) 16 | 17 | local function setColours(fg, bg) 18 | if fg ~= nil then 19 | term.setTextColour(term.isColour() and fg or colours.white) 20 | end 21 | 22 | if bg ~= nil then 23 | term.setBackgroundColour(term.isColour() and bg or colours.black) 24 | end 25 | end 26 | 27 | local function processInput(input) 28 | return shell.run(input) 29 | end 30 | 31 | local function getColourFromRegistry(key) 32 | local colour = System.Registry.Get(key) 33 | if type(colour) == "number" then 34 | return colour 35 | elseif type(colour) == "string" then 36 | return colours[colour] 37 | end 38 | end 39 | 40 | local textColour = getColourFromRegistry("Shell/TextColour") 41 | local backgroundColour = getColourFromRegistry("Shell/BackgroundColour") 42 | local activeTextColour = getColourFromRegistry("Shell/ActiveTextColour") 43 | local activeBackgroundColour = getColourFromRegistry("Shell/ActiveBackgroundColour") 44 | 45 | local function runShell() 46 | setColours(textColour, backgroundColour) 47 | term.clear() 48 | term.setCursorPos(1, 1) 49 | 50 | local startupFile = System.Registry.Get("Shell/StartupFile") 51 | if type(startupFile) == "string" then 52 | shell.run(startupFile) 53 | end 54 | 55 | local workingDir = System.Registry.Get("Shell/StartWorkingDir") 56 | if type(workingDir) == "string" then 57 | shell.setDir(workingDir) 58 | end 59 | 60 | local inputChar = System.Registry.Get("Shell/InputChar") 61 | 62 | local history = {} 63 | 64 | while true do 65 | local ok, err = pcall(function() 66 | setColours(textColour, activeBackgroundColour) 67 | term.clearLine() 68 | write(shell.dir() .. inputChar .. " ") 69 | 70 | setColours(activeTextColour, activeBackgroundColour) 71 | local input = read(nil, history) 72 | history[#history + 1] = input 73 | 74 | setColours(colours.white, backgroundColour) 75 | term.clearLine() 76 | processInput(input) 77 | end) 78 | 79 | if not ok then 80 | printError(err) 81 | end 82 | end 83 | end 84 | 85 | runShell() 86 | -------------------------------------------------------------------------------- /system/sysinit.lua: -------------------------------------------------------------------------------- 1 | local ok, err = pcall(function() 2 | local cdir = "S:/" 3 | local path = ".:S%/default:U%/global:R%/programs:R%/programs/rednet:R%/programs/fun:R%/programs/fun/advanced:R%/programs/http:R%/programs/advanced:R%/programs/pocket:R%/programs/command" 4 | 5 | local aliases = {} 6 | 7 | local associations = { 8 | ["ss"] = "sshost.lua" 9 | } 10 | 11 | local shell = {} -- Shell API 12 | 13 | shell.dir = function() 14 | return cdir 15 | end 16 | 17 | shell.setDir = function(path) 18 | if not fs.exists(path) then 19 | error("invalid path!", 2) 20 | end 21 | 22 | cdir = path 23 | end 24 | 25 | shell.run = function(file, ...) 26 | local args = {} 27 | for arg in file:gmatch("[^%s]+") do 28 | args[#args + 1] = arg 29 | end 30 | 31 | local varargs = { ... } 32 | for _,v in pairs(varargs) do 33 | args[#args + 1] = v 34 | end 35 | 36 | if args[1] == nil then 37 | return false 38 | end 39 | 40 | file = shell.resolveProgram(args[1]) 41 | 42 | if not fs.exists(file) then 43 | printError("No such program '" .. file .. "'") 44 | return false 45 | end 46 | 47 | local ext = fs.getName(file):match(".+%.(.+)") 48 | if ext ~= nil then 49 | local association = shell.__getAssociatedProgram(ext) 50 | if association ~= nil then 51 | association = shell.resolveProgram(association) 52 | local prog = System.Tasks.NewTask(association) 53 | prog:Start(file) 54 | 55 | System.Tasks.WaitForTask(prog) 56 | return true 57 | end 58 | end 59 | 60 | local prog = System.Tasks.NewTask(file) 61 | prog:Start(select(2, unpack(args))) 62 | 63 | System.Tasks.WaitForTask(prog) 64 | return true 65 | end 66 | 67 | shell.path = function() 68 | return path 69 | end 70 | 71 | shell.setPath = function(newPath) 72 | path = newPath 73 | end 74 | 75 | shell.__addToPath = function(dir) 76 | path[#path + 1] = dir 77 | end 78 | 79 | shell.__removeFromPath = function(dir) 80 | local index = 0 81 | 82 | for i,v in pairs(path) do 83 | if System.Path.Normalise(v) == System.Path.Normalise(dir) then 84 | index = i 85 | break 86 | end 87 | end 88 | 89 | table.remove(path, index) 90 | end 91 | 92 | shell.setAlias = function(alias, prog) 93 | aliases[alias] = prog 94 | end 95 | 96 | shell.aliases = function() 97 | return aliases 98 | end 99 | 100 | shell.clearAlias = function(alias) 101 | aliases[alias] = nil 102 | end 103 | 104 | shell.__resolveAlias = function(alias) 105 | return aliases[alias] 106 | end 107 | 108 | shell.programs = function() 109 | return {} 110 | end 111 | 112 | shell.__drive = function() 113 | return System.Path.GetDriveAndPath(cdir) 114 | end 115 | 116 | shell.resolve = function(file, driveSep) 117 | driveSep = driveSep or ":" 118 | 119 | local drive,_ = System.Path.GetDriveAndPath(file) 120 | local cdrive = shell.__drive() 121 | local _cdir = cdir 122 | 123 | if drive ~= nil and cdrive ~= drive then 124 | _cdir = drive .. ":/" 125 | end 126 | 127 | local firstChar = file:sub(1, 1) 128 | if firstChar == "/" or firstChar == "\\" then -- root! 129 | return System.Path.Combine(cdrive .. driveSep .. "/", file, driveSep) 130 | else 131 | return System.Path.Combine(_cdir, file, driveSep) 132 | end 133 | end 134 | 135 | shell.resolveProgram = function(name) 136 | if aliases[name] ~= nil then 137 | name = aliases[name] 138 | end 139 | 140 | for entry in path:gmatch("[^%:]+") do 141 | if fs.exists(entry) and fs.isDir(entry) then 142 | for _, file in pairs(fs.list(entry)) do 143 | if fs.getName(name) == fs.getName(file) then 144 | return System.Path.Normalise(System.Path.Combine(entry, file)) 145 | end 146 | end 147 | end 148 | end 149 | 150 | return System.Path.Normalise(shell.resolve(name)) 151 | end 152 | 153 | --[[shell.getRunningProgram = function() 154 | if getfenv then 155 | return getfenv(2).__FILE__ or "N/A" 156 | else 157 | error("shell.getRunningProgram not available in Lua 5.2!", 2) 158 | end 159 | end]] 160 | 161 | shell.__associate = function(ext, program) 162 | associations[ext] = program 163 | end 164 | 165 | shell.__clearAssociation = function(ext) 166 | associations[ext] = nil 167 | end 168 | 169 | shell.__getAssociatedProgram = function(ext) 170 | return associations[ext] 171 | end 172 | 173 | shell.exit = function() 174 | local shtid = System.ShellMgr.GetShellTID() 175 | local task = System.Tasks.GetTaskByTID(shtid) 176 | task:SendSignal(System.Tasks.Signal.Kill) 177 | end 178 | 179 | System.ShellMgr.SetShell(shell) 180 | 181 | local sh = System.Tasks.NewTask("S:/shell.lua") 182 | System.ShellMgr.SetShellTID(sh.TID) 183 | sh:Start() 184 | end) 185 | 186 | if not ok then 187 | printError(err) 188 | end 189 | -------------------------------------------------------------------------------- /user/start.ss: -------------------------------------------------------------------------------- 1 | // 2 | // Safe to change 3 | // 4 | alias ls list 5 | alias dir list 6 | 7 | alias fucking sudo 8 | 9 | alias rm delete 10 | alias del delete 11 | 12 | alias cp copy 13 | alias mv move 14 | alias taft S:/default/taft 15 | alias mov move 16 | 17 | alias clr clear 18 | alias cls clear 19 | 20 | alias rs redstone 21 | 22 | alias reg registry 23 | 24 | alias tasklist tasks 25 | alias ps tasks 26 | alias procs tasks 27 | 28 | alias devs devices 29 | alias devcs devices 30 | alias devlist devices 31 | 32 | // 33 | // You might break things here 34 | // 35 | start devservice.lua 36 | 37 | // 38 | // Safe 39 | // 40 | echo Basic Shell for cheetOS 41 | --------------------------------------------------------------------------------