Derek1017

Kernel

Jun 19th, 2015
366
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 15.33 KB | None | 0 0
  1. -- (c) 2014 RDashINC
  2. --
  3. -- Linux kernel, in computercraft.
  4. -- Will at one point adheed to Linux Kernel standards.
  5. -- Open Source, and object oriented.
  6. --
  7. -- License: MIT
  8. -- Author: RainbowDashDC
  9. -- Contributors: see CREDITS
  10. -- URL: http://github.com/ccLinux/kernel
  11. --
  12. -- Specifications & Planning moved to: http://bit.ly/11Fx45o
  13.  
  14. -- Main Functions of the kernel --
  15.  
  16. -- Using Globals, so incase we're in a developer env (no reboot to clear _G),
  17. -- we clear it ourselves
  18. -- os.pullEvent = os.pullEventRaw
  19. _G['debug_flag']=false
  20. _G['quiet_flag']=false
  21. _G['root_flag']=false
  22. _G['shell_flag']=false
  23. _G['log_flag']=false
  24.  
  25. local Args={...}
  26.  
  27. -- Helper Functions --
  28. _G['Set'] = function(list)
  29.   local set = {}
  30.   for _, l in ipairs(list) do set[l] = true end
  31.   return set
  32. end
  33.  
  34. -- @see http://bit.ly/1FI4PSn
  35. _G['copytable'] = function(source)
  36.     local function copyTableInternal(source, seen)
  37.         if type(source) ~= 'table' then return source end
  38.         if seen[source] then return seen[source] end
  39.  
  40.         local rv = {}
  41.         seen[source] = rv
  42.         for k,v in pairs(source) do
  43.             rv[copyTableInternal(k, seen)] = copyTableInternal(v, seen)
  44.         end
  45.         return rv
  46.     end
  47.  
  48.     return copyTableInternal(source, {})
  49. end
  50.  
  51. -- @see https://gist.github.com/jrus/3197011
  52. local random = math.random
  53. _G['getRandomString'] = function(template)
  54.     return string.gsub(template, '[xy]', function (c)
  55.     local v = (c == 'x') and random(0, 0xf) or random(8, 0xb)
  56.         return string.format('%x', v)
  57.     end)
  58. end
  59. --[[
  60.   Split has been deprecated in favor of <string>:split.
  61.  
  62.   This will be removed in 0.1.0.3
  63. ]]--
  64. _G['split'] = function(s,re)
  65.   kernel.output("_G[\"split\"] is deprecated.")
  66.     local i1 = 1
  67.     local ls = {}
  68.     local append = table.insert
  69.     if not re then re = '%s+' end
  70.         if re == '' then return {s} end
  71.         while true do
  72.             local i2,i3 = s:find(re,i1)
  73.             if not i2 then
  74.                 local last = s:sub(i1)
  75.                 if last ~= '' then append(ls,last) end
  76.                 if #ls == 1 and ls[1] == '' then
  77.                     return {}
  78.                 else
  79.                     return ls
  80.                 end
  81.             end
  82.             append(ls,s:sub(i1,i2-1))
  83.             i1 = i3+1
  84.         end
  85. end
  86.  
  87. --[[
  88.   <string>:split
  89.  
  90.   @desc seperate a string by delimiter
  91.   @param delimiter - delimiter to split with
  92.   @returns class
  93. ]]--
  94. function string:split( delimiter )
  95.     if type( delimiter ) == "string" then
  96.         local result = { }
  97.         local from = 1
  98.         local delim_from, delim_to = string.find( self, delimiter, from )
  99.         while delim_from do
  100.             table.insert( result, string.sub( self, from , delim_from-1 ) )
  101.             from = delim_to + 1
  102.             delim_from, delim_to = string.find( self, delimiter, from )
  103.         end
  104.         table.insert( result, string.sub( self, from ) )
  105.         return result
  106.     elseif type( delimiter ) == "number" then
  107.         return self:gmatch( (".?"):rep( delimiter ) )
  108.     end
  109. end
  110.  
  111. _G['getRandomNumber'] = function(min, max)
  112.     return math.random(min, max)
  113. end
  114.  
  115. _G['readonlytable'] = function(table)
  116.    return setmetatable({}, {
  117.      __index = table,
  118.      __newindex = function(table, key, value)
  119.                     kernel.panic('Attempt to modify a readonlytable', 12,
  120.                      debug.traceback())
  121.                   end,
  122.      __metatable = false
  123.    });
  124. end
  125.  
  126. --[[
  127.     The main method in the new class system.
  128.     (please consult /doc/classes.md for a more in-depth explanation)
  129.  
  130.     Creates a class out of an optional subclass and a constructor method.
  131.     This returns a table that can be modified normally.
  132.     The constructor does not provide the self variable by itself:
  133.     You'll need to add in a parameter.
  134.     For example, if you need to pass a name and age to a constructor
  135.     the params will be instance, name and age.
  136.  
  137.     The markdown documentation contains more information about this specific
  138.     method.
  139. ]]--
  140. function _G.class(base, init)
  141.     local c = {}    -- a new class instance
  142.     if not init and type(base) == 'function' then
  143.         init = base
  144.         base = nil
  145.         elseif type(base) == 'table' then
  146.             -- our new class is a shallow copy of the base class!
  147.             for i,v in pairs(base) do
  148.                 c[i] = v
  149.             end
  150.             c._base = base
  151.         end
  152.         -- the class will be the metatable for all its objects,
  153.         -- and they will look up their methods in it.
  154.         c.__index = c
  155.  
  156.     -- expose a constructor which can be called by <classname>(<args>)
  157.     local mt = {}
  158.  
  159.         mt.__call = function(class_tbl, ...)
  160.         local obj = {}
  161.         setmetatable(obj,c)
  162.         if init then
  163.             init(obj,...)
  164.         else
  165.             -- make sure that any stuff from the base class is initialized!
  166.             if base and base.init then
  167.                 base.init(obj, ...)
  168.             end
  169.         end
  170.         return obj
  171.     end
  172.  
  173.     c.init = init
  174.     c.isSubclassOf = function(self, klass)
  175.         local m = getmetatable(self)
  176.         while m do
  177.             if m == klass then return true end
  178.             m = m._base
  179.         end
  180.         return false
  181.     end
  182.  
  183.     function c:equals (otherObject)
  184.         if not otherObject:isSubclassOf(self) then
  185.             return false
  186.         else
  187.             for i = 1, #otherObject do
  188.                 if not otherObject[i] == self[i] then
  189.                     return false
  190.                 end
  191.             end
  192.         end
  193.  
  194.         return true
  195.     end
  196.  
  197.     function c:clone ()
  198.         return c
  199.     end
  200.  
  201.     function c:toString ()
  202.         local mt = getmetatable(self)
  203.         if mt.__tostring then
  204.             return mt.__tostring()
  205.         end
  206.  
  207.         return tostring(self)
  208.     end
  209.  
  210.     function c:include ( mixin )
  211.         for k,v in pairs(mixin) do
  212.             c[k] = mixin[k]
  213.         end
  214.     end
  215.  
  216.     setmetatable(c, mt)
  217.     return c
  218. end
  219.  
  220. function printf (fmt, ...)
  221.     print(string.format(fmt, ...))
  222. end
  223.  
  224.  
  225. -- End --
  226.  
  227. -- Kernel --
  228. kernel         = {}
  229. computer       = {}
  230. kernel.apis    = {}
  231. kernel.DIR     = '/kernel' -- blank for root directory. (no trailing slashes)
  232. kernel.dir     = kernel.DIR
  233. kernel.version ='0.1.0.2-rc2'
  234.  
  235. function kernel.output(msg, debug)
  236.   -- Log the output no matter what flags.
  237.   kernel.log(msg)
  238.  
  239.     if not (_G['quiet_flag']) then
  240.     if not (debug_flag) then
  241.       if(debug) then
  242.         return false
  243.       end
  244.     end
  245.  
  246.         term.write('['..tostring(timer.getTime())..']: '..tostring(msg))
  247.         kernel.newline()
  248.  
  249.     -- We were outputed.
  250.     return true
  251.   else
  252.     return false
  253.   end
  254. end
  255.  
  256. function kernel.log(msg)
  257.   msg='['..timer.getTime()..']: '..tostring(msg).."\n"
  258.  
  259.   local log = fs.open(kernel.DIR..'/kernel.log', 'a')
  260.   log.write(msg)
  261.   log.close()
  262.  
  263.   return true;
  264. end
  265.  
  266. function kernel.newline()
  267.     print('')
  268. end
  269.  
  270. function kernel.cleanup()
  271.   -- Reset Term
  272.   pcall(term.clear)
  273.   term.setCursorPos(1,1)
  274.  
  275.     -- Unload Devices, de-register them, etc --
  276.     pcall(devices.unload)
  277.  
  278.     -- Flush vRAM --
  279.   pcall(ram.flush)
  280.  
  281.     -- Write stopped to STDIN --
  282.     kernel.output('Will now halt')
  283.  
  284.     -- End --
  285.     if not (_G['shell_flag']) then
  286.         os.shutdown()
  287.     end
  288. end
  289.  
  290. function kernel.getType()
  291.     if not (term.isColour()) then
  292.     if (pocket) then
  293.       computer.type='pc'
  294.           return 'pocket computer'
  295.     else
  296.       computer.type='c'
  297.       return 'standard computer'
  298.     end
  299.  
  300.     -- Set color
  301.     computer.isColor=false
  302.   else
  303.     if (pocket) then
  304.       computer.type='advpc'
  305.       return 'advanced pocket computer'
  306.         else
  307.       computer.type='advc'
  308.       return 'advanced computer'
  309.         end
  310.  
  311.         -- Set color
  312.         computer.isColor=true
  313.     end
  314. end
  315.  
  316.  
  317. function kernel.loadAPI(api, t)
  318.     -- Core or ext
  319.     local path = '/etc/kernel/'..(t == 'core' and 'core' or 'ext/'..api )
  320.  
  321.   if(t=='class') then
  322.     kernel.output('kernel: API is using class wrapper', true)
  323.     path = '/etc/kernel/core/classes'
  324.   end
  325.  
  326.     if not (fs.exists(kernel.DIR..path..'/'..api..'.lua')) then
  327.     -- Return false because file doesn't exist, or isn't setup correctly.
  328.  
  329.     kernel.output('kernel: Failed to load api \''..api..'\'')
  330.     kernel.output('kernel: path='..kernel.DIR..path..'/'..api..'.lua', true)
  331.         return false
  332.     else
  333.         if(t=='core') then
  334.  
  335.             kernel.output('Loading core api \''..api..'\'', true)
  336.  
  337.             local i,err = loadfile(kernel.DIR..path..'/'..api..'.lua')
  338.             -- print(kernel.DIR..path..'/'..api..'.lua')
  339.             if(i==nil) then
  340.                 kernel.panic(
  341.          string.format('kernel: Couldn\'t load API, i is \'%s\'.Syntax error?',
  342.          type(i)),27,err)
  343.             end
  344.  
  345.       local coi=copytable(_G)
  346.       coi.kernel        = kernel
  347.       coi.timer         = timer
  348.       coi.devices       = devices
  349.       coi.thread        = thread
  350.       coi.threads       = threads
  351.       coi.base64        = base64
  352.             setfenv(i, coi)
  353.  
  354.             -- Readonly by default, because core.
  355.             local t=i()
  356.  
  357.       -- Add too loaded APIs List
  358.       table.insert(kernel.apis, api)
  359.  
  360.       if (type(t)=='table') then
  361.         if not (t[api]==nil) then
  362.           kernel.output("Returned multiple objects.", true)
  363.  
  364.           for i, k in pairs(t) do
  365.             kernel.output('Adding object \''..tostring(i)..'\'', true)
  366.  
  367.             if not (kernel.apis[i]==nil) then
  368.               kernel.panic('API confliction, '..tostring(i)..' is SET', 22, 'kernel->loadApi('..api..')')
  369.             end
  370.  
  371.             -- Add to loaded APIs
  372.             table.insert(kernel.apis, i)
  373.  
  374.             -- Return object
  375.             _G[i]=k
  376.           end
  377.         else
  378.           _G[api]=readonlytable(t)
  379.         end
  380.       else
  381.         _G[api]=readonlytable(t)
  382.       end
  383.         else
  384.             if(t=='ext') then
  385.                 kernel.output('Loading external api \''..api..'\'', true)
  386.  
  387.                 local i,err = loadfile(kernel.DIR..path..'/'..api..'.lua')
  388.  
  389.                 -- Check if we had some sort of load issue.
  390.                 if(i==nil) then
  391.                         kernel.panic(
  392.              string.format('Couldn\'t load API, i is  \'%s\'. Syntax error?',
  393.              type(i)),27,err)
  394.                 end
  395.  
  396.                 setfenv(i, _G)
  397.  
  398.                 _G[api]=i()
  399.  
  400.         -- Add too loaded APIs List
  401.         table.insert(kernel.apis, api)
  402.             else
  403.           kernel.output('Loading class api \''..api..'\'', true)
  404.  
  405.           -- Load API
  406.           local i,err = loadfile(kernel.DIR..path..'/'..api..'.lua')
  407.  
  408.           -- Check if an error occured.
  409.           if(i==nil) then
  410.             kernel.panic(
  411.             string.format('Couldn\'t load API, i is  \'%s\'. Syntax error?',
  412.             type(i)),27,err)
  413.           end
  414.  
  415.           -- Set enviroment
  416.           setfenv(i, _G)
  417.  
  418.           -- Execute
  419.           local t=i()
  420.  
  421.           if (type(t)=='table') then
  422.             if not (t[api]==nil) then
  423.               kernel.output("Returned multiple objects.", true)
  424.  
  425.               for i, k in pairs(t) do
  426.                 kernel.output('Adding object \''..tostring(i)..'\'', true)
  427.  
  428.                 if not (kernel.apis[i]==nil) then
  429.                   kernel.panic('API confliction, '..tostring(i)..' is SET', 22, 'kernel->loadApi('..api..')')
  430.                 end
  431.  
  432.                 -- Add to loaded APIs
  433.                 table.insert(kernel.apis, i)
  434.  
  435.                 -- Return object
  436.                 _G[i]=k
  437.               end
  438.           else
  439.             kernel.output('t is not table, t=type('..type(t)..')')
  440.             _G[api]=readonlytable(t)
  441.           end
  442.  
  443.           -- Add too loaded APIs List
  444.           table.insert(kernel.apis, api)
  445.         end
  446.       end
  447.         end
  448.  
  449.         -- No error
  450.         return true
  451.     end
  452. end
  453.  
  454.  
  455.  
  456. function kernel.panic(msg, code, traceback)
  457.   -- Reset Term
  458.   pcall(term.clear)
  459.   term.setCursorPos(1,1)
  460.  
  461.     -- Kernel Panic Info
  462.     local kpt=timer.getTime()
  463.  
  464.     -- Error exit
  465.     -- pcall must have name of function not function()
  466.   -- (Otherwise you run it beforehand!)
  467.     if not (devices==nil) then
  468.         pcall(devices.unload)
  469.     end
  470.     if not (ram==nil) then
  471.         pcall(ram.flush)
  472.     end
  473.     pcall(timer.stop)
  474.  
  475.   -- Display panic
  476.     print('('..code..') Kernel panic - at time ' .. kpt)
  477.     kernel.newline()
  478.     print('('..code..') Kernel panic - not syncing: '..tostring(msg))
  479.     kernel.newline()
  480.     if(debug_flag) then
  481.         print('('..code..') Trace: ')
  482.         print(traceback)
  483.     else
  484.         print('('..code..')',  'Stack trace witheld, run with \'debug\' for one')
  485.     end
  486.     kernel.newline()
  487.     term.write('('..code..') Invoked: ')
  488.     for i, v in ipairs(Args) do
  489.         term.write(v)
  490.         term.write(' ')
  491.     end
  492.     kernel.newline()
  493.     print('('..code..') kernel.DIR: '..kernel.DIR)
  494.     print('('..code..') Version: '..kernel.version)
  495.  
  496.     -- The linux kernel doesn't exit, nor does it return
  497.     -- Thus we make a loop that can only be terminated via reboot.
  498.     while true do sleep(0) end
  499. end
  500. -- End --
  501.  
  502. -- Timer --
  503. timer = {}
  504. function timer.start()
  505.     timer.startTime=os.clock()
  506. end
  507.  
  508. function timer.getTime()
  509.     if not (timer.startTime==nil) then
  510.         return tostring(os.clock()-timer.startTime)
  511.     else
  512.         return nil
  513.     end
  514. end
  515. -- End --
  516.  
  517. -------------------------------------------------------------------------
  518. -- ccLinux
  519. -------------------------------------------------------------------------
  520.  
  521. if not fs.exists(kernel.dir .. '/vram') then
  522.     fs.makeDir(kernel.dir .. '/vram')
  523. end
  524.  
  525. -- Start Execution --
  526. timer.start()
  527. for i, v in ipairs(Args) do
  528.   -- fixes split bug/
  529.   v=v..'='
  530.  
  531.   -- Singluar no argument args
  532.     if(v=='quiet=') then
  533.         _G['quiet_flag']=true
  534.     else
  535.         if(v=='debug=') then
  536.             _G['debug_flag']=true
  537.             _G['shell_flag']=true
  538.         else
  539.             if(v=='shell_dump=') then
  540.                 _G['shell_flag']=true
  541.             else
  542.         if(v=='log=') then
  543.           _G['log_flag']=true
  544.         end
  545.       end
  546.         end
  547.  
  548.     -- Use arguments ones
  549.     local a = v:split('=')
  550.     if not (a==nil) then
  551.       -- Change device root
  552.       if(a[1]=="root") then
  553.         kernel.DIR=a[2]
  554.         kernel.dir=kernel.DIR
  555.       end
  556.     end
  557.     end
  558. end
  559.  
  560. -- Remove old logs if they exists
  561. -- should be in var at one point
  562. if (fs.exists(kernel.DIR..'/kernel.log')==true) then
  563.   fs.delete(kernel.DIR..'/kernel.log')
  564. end
  565.  
  566. -- Create a new log.
  567. local l = fs.open(kernel.DIR..'/kernel.log', 'w')
  568. l.write('')
  569. l.close()
  570.  
  571. kernel.output('ccLinux v'..kernel.version);
  572.  
  573. -- Where are we? --
  574. kernel.output('Base: '..kernel.DIR)
  575.  
  576. -- What are we? --
  577. kernel.output('Got '..kernel.getType())
  578.  
  579. -- Set globals, yes they are apparently different!
  580. -- Helps with scopes. APIs and threads will have access to only _G functions.
  581. _G['kernel'] = readonlytable(kernel)
  582. _G['timer'] = readonlytable(timer)
  583. _G['shell'] = shell
  584. _G['os'] = os
  585. _G['fs'] = fs
  586.  
  587. -- Load Core APIs
  588. -- Notice the 2nd parameter 'core', it's different than ext.
  589. kernel.loadAPI('ram', 'core')
  590. kernel.loadAPI('devices', 'core')
  591. kernel.loadAPI('thread', 'core')
  592. kernel.loadAPI('links', 'core')
  593. kernel.loadAPI('debug', 'core')
  594. kernel.loadAPI('vfs', 'core')
  595. kernel.loadAPI('rc', 'core')
  596.  
  597. -- Load external APIs
  598. kernel.loadAPI('aeslua', 'ext')
  599. kernel.loadAPI('JSON', 'ext')
  600. kernel.loadAPI('luajit', 'ext')
  601. kernel.loadAPI('base64', 'ext')
  602. kernel.loadAPI('sha', 'ext')
  603. kernel.loadAPI('libcomp', 'ext')
  604.  
  605. -- Load MatAlcDev class APIs
  606. kernel.loadAPI("utils", "class")
  607.  
  608. -- Initalize RAM --
  609. kernel.output('Initializing RAM', true)
  610. ram.init()
  611.  
  612.  
  613. -- Running INIT --
  614. -- Run 0 before anything for updates and etc --
  615. rc.doRunLevel(0)
  616.  
  617. -- Initialize devices, and objects --
  618. devices.getAll();
  619.  
  620. -- Thread Test --
  621. thread.start(function()
  622.   local tid=thread.getThreadID()
  623.   thread.listener(kernel.DIR..'/etc/kernel/main.lua', tid)
  624. end)
  625.  
  626. -- Return to shell, we must've not shutdown
  627. return true
Add Comment
Please, Sign In to add comment