Advertisement
osmarks

CC-VBIOS

Sep 29th, 2018
753
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 33.13 KB | None | 0 0
  1. function loadstring(code, env)
  2.     local e = _G
  3.     local name = "@code"
  4.     if type(env) == "table" then e = env
  5.     elseif type(env) == "string" then name = env end
  6.     return load(code, name, "t", e)
  7. end
  8.  
  9. -- Load in expect from the module path.
  10. --
  11. -- Ideally we'd use require, but that is part of the shell, and so is not
  12. -- available to the BIOS or any APIs. All APIs load this using dofile, but that
  13. -- has not been defined at this point.
  14. local expect
  15.  
  16. do
  17.     local h = fs.open("rom/modules/main/cc/expect.lua", "r")
  18.     local f, err = loadstring(h.readAll(), "@expect.lua")
  19.     h.close()
  20.  
  21.     if not f then error(err) end
  22.     expect = f().expect
  23. end
  24.  
  25. if _VERSION == "Lua 5.1" then
  26.     -- If we're on Lua 5.1, install parts of the Lua 5.2/5.3 API so that programs can be written against it
  27.     local type = type
  28.     local nativeload = load
  29.     local nativeloadstring = loadstring
  30.     local nativesetfenv = setfenv
  31.  
  32.     --- Historically load/loadstring would handle the chunk name as if it has
  33.     -- been prefixed with "=". We emulate that behaviour here.
  34.     local function prefix(chunkname)
  35.         if type(chunkname) ~= "string" then return chunkname end
  36.         local head = chunkname:sub(1, 1)
  37.         if head == "=" or head == "@" then
  38.             return chunkname
  39.         else
  40.             return "=" .. chunkname
  41.         end
  42.     end
  43.  
  44.     function load( x, name, mode, env )
  45.         expect(1, x, "function", "string")
  46.         expect(2, name, "string", "nil")
  47.         expect(3, mode, "string", "nil")
  48.         expect(4, env, "table", "nil")
  49.  
  50.         local ok, p1, p2 = pcall( function()
  51.             if type(x) == "string" then
  52.                 local result, err = nativeloadstring( x, name )
  53.                 if result then
  54.                     if env then
  55.                         env._ENV = env
  56.                         nativesetfenv( result, env )
  57.                     end
  58.                     return result
  59.                 else
  60.                     return nil, err
  61.                 end
  62.             else
  63.                 local result, err = nativeload( x, name )
  64.                 if result then
  65.                     if env then
  66.                         env._ENV = env
  67.                         nativesetfenv( result, env )
  68.                     end
  69.                     return result
  70.                 else
  71.                     return nil, err
  72.                 end
  73.             end
  74.         end )
  75.         if ok then
  76.             return p1, p2
  77.         else
  78.             error( p1, 2 )
  79.         end
  80.     end
  81.     table.unpack = unpack
  82.     table.pack = function( ... ) return { n = select( "#", ... ), ... } end
  83.  
  84.     if _CC_DISABLE_LUA51_FEATURES then
  85.         -- Remove the Lua 5.1 features that will be removed when we update to Lua 5.2, for compatibility testing.
  86.         -- See "disable_lua51_functions" in ComputerCraft.cfg
  87.         setfenv = nil
  88.         getfenv = nil
  89.         loadstring = nil
  90.         unpack = nil
  91.         math.log10 = nil
  92.         table.maxn = nil
  93.     else
  94.         loadstring = function(string, chunkname) return nativeloadstring(string, prefix( chunkname )) end
  95.  
  96.         -- Inject a stub for the old bit library
  97.         _G.bit = {
  98.             bnot = bit32.bnot,
  99.             band = bit32.band,
  100.             bor = bit32.bor,
  101.             bxor = bit32.bxor,
  102.             brshift = bit32.arshift,
  103.             blshift = bit32.lshift,
  104.             blogic_rshift = bit32.rshift,
  105.         }
  106.     end
  107. end
  108.  
  109. if _VERSION == "Lua 5.3" and not bit32 then
  110.     -- If we're on Lua 5.3, install the bit32 api from Lua 5.2
  111.     -- (Loaded from a string so this file will still parse on <5.3 lua)
  112.     load( [[
  113.         bit32 = {}
  114.  
  115.         function bit32.arshift( n, bits )
  116.             if type(n) ~= "number" or type(bits) ~= "number" then
  117.                 error( "Expected number, number", 2 )
  118.             end
  119.             return n >> bits
  120.         end
  121.  
  122.         function bit32.band( m, n )
  123.             if type(m) ~= "number" or type(n) ~= "number" then
  124.                 error( "Expected number, number", 2 )
  125.             end
  126.             return m & n
  127.         end
  128.  
  129.         function bit32.bnot( n )
  130.             if type(n) ~= "number" then
  131.                 error( "Expected number", 2 )
  132.             end
  133.             return ~n
  134.         end
  135.  
  136.         function bit32.bor( m, n )
  137.             if type(m) ~= "number" or type(n) ~= "number" then
  138.                 error( "Expected number, number", 2 )
  139.             end
  140.             return m | n
  141.         end
  142.  
  143.         function bit32.btest( m, n )
  144.             if type(m) ~= "number" or type(n) ~= "number" then
  145.                 error( "Expected number, number", 2 )
  146.             end
  147.             return (m & n) ~= 0
  148.         end
  149.  
  150.         function bit32.bxor( m, n )
  151.             if type(m) ~= "number" or type(n) ~= "number" then
  152.                 error( "Expected number, number", 2 )
  153.             end
  154.             return m ~ n
  155.         end
  156.  
  157.         function bit32.lshift( n, bits )
  158.             if type(n) ~= "number" or type(bits) ~= "number" then
  159.                 error( "Expected number, number", 2 )
  160.             end
  161.             return n << bits
  162.         end
  163.  
  164.         function bit32.rshift( n, bits )
  165.             if type(n) ~= "number" or type(bits) ~= "number" then
  166.                 error( "Expected number, number", 2 )
  167.             end
  168.             return n >> bits
  169.         end
  170.     ]] )()
  171. end
  172.  
  173. -- Install lua parts of the os api
  174. function os.version()
  175.     return "CraftOS 1.8"
  176. end
  177.  
  178. function os.pullEventRaw( sFilter )
  179.     return coroutine.yield( sFilter )
  180. end
  181.  
  182. function os.pullEvent( sFilter )
  183.     local eventData = table.pack( os.pullEventRaw( sFilter ) )
  184.     if eventData[1] == "terminate" then
  185.         error( "Terminated", 0 )
  186.     end
  187.     return table.unpack( eventData, 1, eventData.n )
  188. end
  189.  
  190. -- Install globals
  191. function sleep( nTime )
  192.     expect(1, nTime, "number", "nil")
  193.     local timer = os.startTimer( nTime or 0 )
  194.     repeat
  195.         local _, param = os.pullEvent( "timer" )
  196.     until param == timer
  197. end
  198.  
  199. function write( sText )
  200.     expect(1, sText, "string", "number")
  201.  
  202.     local w, h = term.getSize()
  203.     local x, y = term.getCursorPos()
  204.  
  205.     local nLinesPrinted = 0
  206.     local function newLine()
  207.         if y + 1 <= h then
  208.             term.setCursorPos(1, y + 1)
  209.         else
  210.             term.setCursorPos(1, h)
  211.             term.scroll(1)
  212.         end
  213.         x, y = term.getCursorPos()
  214.         nLinesPrinted = nLinesPrinted + 1
  215.     end
  216.  
  217.     -- Print the line with proper word wrapping
  218.     while #sText > 0 do
  219.         local whitespace = string.match( sText, "^[ \t]+" )
  220.         if whitespace then
  221.             -- Print whitespace
  222.             term.write( whitespace )
  223.             x, y = term.getCursorPos()
  224.             sText = string.sub( sText, #whitespace + 1 )
  225.         end
  226.  
  227.         local newline = string.match( sText, "^\n" )
  228.         if newline then
  229.             -- Print newlines
  230.             newLine()
  231.             sText = string.sub( sText, 2 )
  232.         end
  233.  
  234.         local text = string.match( sText, "^[^ \t\n]+" )
  235.         if text then
  236.             sText = string.sub( sText, #text + 1 )
  237.             if #text > w then
  238.                 -- Print a multiline word
  239.                 while #text > 0 do
  240.                     if x > w then
  241.                         newLine()
  242.                     end
  243.                     term.write( text )
  244.                     text = string.sub( text, w - x + 2 )
  245.                     x, y = term.getCursorPos()
  246.                 end
  247.             else
  248.                 -- Print a word normally
  249.                 if x + #text - 1 > w then
  250.                     newLine()
  251.                 end
  252.                 term.write( text )
  253.                 x, y = term.getCursorPos()
  254.             end
  255.         end
  256.     end
  257.  
  258.     return nLinesPrinted
  259. end
  260.  
  261. function print( ... )
  262.     local nLinesPrinted = 0
  263.     local nLimit = select("#", ... )
  264.     for n = 1, nLimit do
  265.         local s = tostring( select( n, ... ) )
  266.         if n < nLimit then
  267.             s = s .. "\t"
  268.         end
  269.         nLinesPrinted = nLinesPrinted + write( s )
  270.     end
  271.     nLinesPrinted = nLinesPrinted + write( "\n" )
  272.     return nLinesPrinted
  273. end
  274.  
  275. function printError( ... )
  276.     local oldColour
  277.     if term.isColour() then
  278.         oldColour = term.getTextColour()
  279.         term.setTextColour( colors.red )
  280.     end
  281.     print( ... )
  282.     if term.isColour() then
  283.         term.setTextColour( oldColour )
  284.     end
  285. end
  286.  
  287. function read( _sReplaceChar, _tHistory, _fnComplete, _sDefault )
  288.     expect(1, _sReplaceChar, "string", "nil")
  289.     expect(2, _tHistory, "table", "nil")
  290.     expect(3, _fnComplete, "function", "nil")
  291.     expect(4, _sDefault, "string", "nil")
  292.  
  293.     term.setCursorBlink( true )
  294.  
  295.     local sLine
  296.     if type( _sDefault ) == "string" then
  297.         sLine = _sDefault
  298.     else
  299.         sLine = ""
  300.     end
  301.     local nHistoryPos
  302.     local nPos, nScroll = #sLine, 0
  303.     if _sReplaceChar then
  304.         _sReplaceChar = string.sub( _sReplaceChar, 1, 1 )
  305.     end
  306.  
  307.     local tCompletions
  308.     local nCompletion
  309.     local function recomplete()
  310.         if _fnComplete and nPos == #sLine then
  311.             tCompletions = _fnComplete( sLine )
  312.             if tCompletions and #tCompletions > 0 then
  313.                 nCompletion = 1
  314.             else
  315.                 nCompletion = nil
  316.             end
  317.         else
  318.             tCompletions = nil
  319.             nCompletion = nil
  320.         end
  321.     end
  322.  
  323.     local function uncomplete()
  324.         tCompletions = nil
  325.         nCompletion = nil
  326.     end
  327.  
  328.     local w = term.getSize()
  329.     local sx = term.getCursorPos()
  330.  
  331.     local function redraw( _bClear )
  332.         local cursor_pos = nPos - nScroll
  333.         if sx + cursor_pos >= w then
  334.             -- We've moved beyond the RHS, ensure we're on the edge.
  335.             nScroll = sx + nPos - w
  336.         elseif cursor_pos < 0 then
  337.             -- We've moved beyond the LHS, ensure we're on the edge.
  338.             nScroll = nPos
  339.         end
  340.  
  341.         local _, cy = term.getCursorPos()
  342.         term.setCursorPos( sx, cy )
  343.         local sReplace = _bClear and " " or _sReplaceChar
  344.         if sReplace then
  345.             term.write( string.rep( sReplace, math.max( #sLine - nScroll, 0 ) ) )
  346.         else
  347.             term.write( string.sub( sLine, nScroll + 1 ) )
  348.         end
  349.  
  350.         if nCompletion then
  351.             local sCompletion = tCompletions[ nCompletion ]
  352.             local oldText, oldBg
  353.             if not _bClear then
  354.                 oldText = term.getTextColor()
  355.                 oldBg = term.getBackgroundColor()
  356.                 term.setTextColor( colors.white )
  357.                 term.setBackgroundColor( colors.gray )
  358.             end
  359.             if sReplace then
  360.                 term.write( string.rep( sReplace, #sCompletion ) )
  361.             else
  362.                 term.write( sCompletion )
  363.             end
  364.             if not _bClear then
  365.                 term.setTextColor( oldText )
  366.                 term.setBackgroundColor( oldBg )
  367.             end
  368.         end
  369.  
  370.         term.setCursorPos( sx + nPos - nScroll, cy )
  371.     end
  372.  
  373.     local function clear()
  374.         redraw( true )
  375.     end
  376.  
  377.     recomplete()
  378.     redraw()
  379.  
  380.     local function acceptCompletion()
  381.         if nCompletion then
  382.             -- Clear
  383.             clear()
  384.  
  385.             -- Find the common prefix of all the other suggestions which start with the same letter as the current one
  386.             local sCompletion = tCompletions[ nCompletion ]
  387.             sLine = sLine .. sCompletion
  388.             nPos = #sLine
  389.  
  390.             -- Redraw
  391.             recomplete()
  392.             redraw()
  393.         end
  394.     end
  395.     while true do
  396.         local sEvent, param, param1, param2 = os.pullEvent()
  397.         if sEvent == "char" then
  398.             -- Typed key
  399.             clear()
  400.             sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )
  401.             nPos = nPos + 1
  402.             recomplete()
  403.             redraw()
  404.  
  405.         elseif sEvent == "paste" then
  406.             -- Pasted text
  407.             clear()
  408.             sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )
  409.             nPos = nPos + #param
  410.             recomplete()
  411.             redraw()
  412.  
  413.         elseif sEvent == "key" then
  414.             if param == keys.enter then
  415.                 -- Enter
  416.                 if nCompletion then
  417.                     clear()
  418.                     uncomplete()
  419.                     redraw()
  420.                 end
  421.                 break
  422.  
  423.             elseif param == keys.left then
  424.                 -- Left
  425.                 if nPos > 0 then
  426.                     clear()
  427.                     nPos = nPos - 1
  428.                     recomplete()
  429.                     redraw()
  430.                 end
  431.  
  432.             elseif param == keys.right then
  433.                 -- Right
  434.                 if nPos < #sLine then
  435.                     -- Move right
  436.                     clear()
  437.                     nPos = nPos + 1
  438.                     recomplete()
  439.                     redraw()
  440.                 else
  441.                     -- Accept autocomplete
  442.                     acceptCompletion()
  443.                 end
  444.  
  445.             elseif param == keys.up or param == keys.down then
  446.                 -- Up or down
  447.                 if nCompletion then
  448.                     -- Cycle completions
  449.                     clear()
  450.                     if param == keys.up then
  451.                         nCompletion = nCompletion - 1
  452.                         if nCompletion < 1 then
  453.                             nCompletion = #tCompletions
  454.                         end
  455.                     elseif param == keys.down then
  456.                         nCompletion = nCompletion + 1
  457.                         if nCompletion > #tCompletions then
  458.                             nCompletion = 1
  459.                         end
  460.                     end
  461.                     redraw()
  462.  
  463.                 elseif _tHistory then
  464.                     -- Cycle history
  465.                     clear()
  466.                     if param == keys.up then
  467.                         -- Up
  468.                         if nHistoryPos == nil then
  469.                             if #_tHistory > 0 then
  470.                                 nHistoryPos = #_tHistory
  471.                             end
  472.                         elseif nHistoryPos > 1 then
  473.                             nHistoryPos = nHistoryPos - 1
  474.                         end
  475.                     else
  476.                         -- Down
  477.                         if nHistoryPos == #_tHistory then
  478.                             nHistoryPos = nil
  479.                         elseif nHistoryPos ~= nil then
  480.                             nHistoryPos = nHistoryPos + 1
  481.                         end
  482.                     end
  483.                     if nHistoryPos then
  484.                         sLine = _tHistory[nHistoryPos]
  485.                         nPos, nScroll = #sLine, 0
  486.                     else
  487.                         sLine = ""
  488.                         nPos, nScroll = 0, 0
  489.                     end
  490.                     uncomplete()
  491.                     redraw()
  492.  
  493.                 end
  494.  
  495.             elseif param == keys.backspace then
  496.                 -- Backspace
  497.                 if nPos > 0 then
  498.                     clear()
  499.                     sLine = string.sub( sLine, 1, nPos - 1 ) .. string.sub( sLine, nPos + 1 )
  500.                     nPos = nPos - 1
  501.                     if nScroll > 0 then nScroll = nScroll - 1 end
  502.                     recomplete()
  503.                     redraw()
  504.                 end
  505.  
  506.             elseif param == keys.home then
  507.                 -- Home
  508.                 if nPos > 0 then
  509.                     clear()
  510.                     nPos = 0
  511.                     recomplete()
  512.                     redraw()
  513.                 end
  514.  
  515.             elseif param == keys.delete then
  516.                 -- Delete
  517.                 if nPos < #sLine then
  518.                     clear()
  519.                     sLine = string.sub( sLine, 1, nPos ) .. string.sub( sLine, nPos + 2 )
  520.                     recomplete()
  521.                     redraw()
  522.                 end
  523.  
  524.             elseif param == keys["end"] then
  525.                 -- End
  526.                 if nPos < #sLine then
  527.                     clear()
  528.                     nPos = #sLine
  529.                     recomplete()
  530.                     redraw()
  531.                 end
  532.  
  533.             elseif param == keys.tab then
  534.                 -- Tab (accept autocomplete)
  535.                 acceptCompletion()
  536.  
  537.             end
  538.  
  539.         elseif sEvent == "mouse_click" or sEvent == "mouse_drag" and param == 1 then
  540.             local _, cy = term.getCursorPos()
  541.             if param1 >= sx and param1 <= w and param2 == cy then
  542.                 -- Ensure we don't scroll beyond the current line
  543.                 nPos = math.min(math.max(nScroll + param1 - sx, 0), #sLine)
  544.                 redraw()
  545.             end
  546.  
  547.         elseif sEvent == "term_resize" then
  548.             -- Terminal resized
  549.             w = term.getSize()
  550.             redraw()
  551.  
  552.         end
  553.     end
  554.  
  555.     local _, cy = term.getCursorPos()
  556.     term.setCursorBlink( false )
  557.     term.setCursorPos( w + 1, cy )
  558.     print()
  559.  
  560.     return sLine
  561. end
  562.  
  563. function loadfile( filename, mode, env )
  564.     -- Support the previous `loadfile(filename, env)` form instead.
  565.     if type(mode) == "table" and env == nil then
  566.         mode, env = nil, mode
  567.     end
  568.  
  569.     expect(1, filename, "string")
  570.     expect(2, mode, "string", "nil")
  571.     expect(3, env, "table", "nil")
  572.  
  573.     local file = fs.open( filename, "r" )
  574.     if not file then return nil, "File not found" end
  575.  
  576.     local func, err = load( file.readAll(), "@" .. fs.getName( filename ), mode, env )
  577.     file.close()
  578.     return func, err
  579. end
  580.  
  581. function dofile( _sFile )
  582.     expect(1, _sFile, "string")
  583.  
  584.     local fnFile, e = loadfile( _sFile, nil, _G )
  585.     if fnFile then
  586.         return fnFile()
  587.     else
  588.         error( e, 2 )
  589.     end
  590. end
  591.  
  592. -- Install the rest of the OS api
  593. function os.run( _tEnv, _sPath, ... )
  594.     expect(1, _tEnv, "table")
  595.     expect(2, _sPath, "string")
  596.  
  597.     local tArgs = table.pack( ... )
  598.     local tEnv = _tEnv
  599.     setmetatable( tEnv, { __index = _G } )
  600.     local fnFile, err = loadfile( _sPath, nil, tEnv )
  601.     if fnFile then
  602.         local ok, err = pcall( function()
  603.             fnFile( table.unpack( tArgs, 1, tArgs.n ) )
  604.         end )
  605.         if not ok then
  606.             if err and err ~= "" then
  607.                 printError( err )
  608.             end
  609.             return false
  610.         end
  611.         return true
  612.     end
  613.     if err and err ~= "" then
  614.         printError( err )
  615.     end
  616.     return false
  617. end
  618.  
  619. local tAPIsLoading = {}
  620. function os.loadAPI( _sPath )
  621.     expect(1, _sPath, "string")
  622.     local sName = fs.getName( _sPath )
  623.     if sName:sub(-4) == ".lua" then
  624.         sName = sName:sub(1, -5)
  625.     end
  626.     if tAPIsLoading[sName] == true then
  627.         printError( "API " .. sName .. " is already being loaded" )
  628.         return false
  629.     end
  630.     tAPIsLoading[sName] = true
  631.  
  632.     local tEnv = {}
  633.     setmetatable( tEnv, { __index = _G } )
  634.     local fnAPI, err = loadfile( _sPath, nil, tEnv )
  635.     if fnAPI then
  636.         local ok, err = pcall( fnAPI )
  637.         if not ok then
  638.             tAPIsLoading[sName] = nil
  639.             return error( "Failed to load API " .. sName .. " due to " .. err, 1 )
  640.         end
  641.     else
  642.         tAPIsLoading[sName] = nil
  643.         return error( "Failed to load API " .. sName .. " due to " .. err, 1 )
  644.     end
  645.  
  646.     local tAPI = {}
  647.     for k, v in pairs( tEnv ) do
  648.         if k ~= "_ENV" then
  649.             tAPI[k] =  v
  650.         end
  651.     end
  652.  
  653.     _G[sName] = tAPI
  654.     tAPIsLoading[sName] = nil
  655.     return true
  656. end
  657.  
  658. function os.unloadAPI( _sName )
  659.     expect(1, _sName, "string")
  660.     if _sName ~= "_G" and type(_G[_sName]) == "table" then
  661.         _G[_sName] = nil
  662.     end
  663. end
  664.  
  665. function os.sleep( nTime )
  666.     sleep( nTime )
  667. end
  668.  
  669. local nativeShutdown = os.shutdown
  670. function os.shutdown()
  671.     nativeShutdown()
  672.     while true do
  673.         coroutine.yield()
  674.     end
  675. end
  676.  
  677. local nativeReboot = os.reboot
  678. function os.reboot()
  679.     nativeReboot()
  680.     while true do
  681.         coroutine.yield()
  682.     end
  683. end
  684.  
  685. -- Install the lua part of the HTTP api (if enabled)
  686. if http then
  687.     local nativeHTTPRequest = http.request
  688.  
  689.     local methods = {
  690.         GET = true, POST = true, HEAD = true,
  691.         OPTIONS = true, PUT = true, DELETE = true,
  692.         PATCH = true, TRACE = true,
  693.     }
  694.  
  695.     local function checkKey( options, key, ty, opt )
  696.         local value = options[key]
  697.         local valueTy = type(value)
  698.  
  699.         if (value ~= nil or not opt) and valueTy ~= ty then
  700.             error(("bad field '%s' (expected %s, got %s"):format(key, ty, valueTy), 4)
  701.         end
  702.     end
  703.  
  704.     local function checkOptions( options, body )
  705.         checkKey( options, "url", "string")
  706.         if body == false then
  707.           checkKey( options, "body", "nil" )
  708.         else
  709.           checkKey( options, "body", "string", not body )
  710.         end
  711.         checkKey( options, "headers", "table", true )
  712.         checkKey( options, "method", "string", true )
  713.         checkKey( options, "redirect", "boolean", true )
  714.  
  715.         if options.method and not methods[options.method] then
  716.             error( "Unsupported HTTP method", 3 )
  717.         end
  718.     end
  719.  
  720.     local function wrapRequest( _url, ... )
  721.         local ok, err = nativeHTTPRequest( ... )
  722.         if ok then
  723.             while true do
  724.                 local event, param1, param2, param3 = os.pullEvent()
  725.                 if event == "http_success" and param1 == _url then
  726.                     return param2
  727.                 elseif event == "http_failure" and param1 == _url then
  728.                     return nil, param2, param3
  729.                 end
  730.             end
  731.         end
  732.         return nil, err
  733.     end
  734.  
  735.     http.get = function( _url, _headers, _binary)
  736.         if type( _url ) == "table" then
  737.             checkOptions( _url, false )
  738.             return wrapRequest( _url.url, _url )
  739.         end
  740.  
  741.         expect(1, _url, "string")
  742.         expect(2, _headers, "table", "nil")
  743.         expect(3, _binary, "boolean", "nil")
  744.         return wrapRequest( _url, _url, nil, _headers, _binary )
  745.     end
  746.  
  747.     http.post = function( _url, _post, _headers, _binary)
  748.         if type( _url ) == "table" then
  749.             checkOptions( _url, true )
  750.             return wrapRequest( _url.url, _url )
  751.         end
  752.  
  753.         expect(1, _url, "string")
  754.         expect(2, _post, "string")
  755.         expect(3, _headers, "table", "nil")
  756.         expect(4, _binary, "boolean", "nil")
  757.         return wrapRequest( _url, _url, _post, _headers, _binary )
  758.     end
  759.  
  760.     http.request = function( _url, _post, _headers, _binary )
  761.         local url
  762.         if type( _url ) == "table" then
  763.             checkOptions( _url )
  764.             url = _url.url
  765.         else
  766.             expect(1, _url, "string")
  767.             expect(2, _post, "string", "nil")
  768.             expect(3, _headers, "table", "nil")
  769.             expect(4, _binary, "boolean", "nil")
  770.             url = _url.url
  771.         end
  772.  
  773.         local ok, err = nativeHTTPRequest( _url, _post, _headers, _binary )
  774.         if not ok then
  775.             os.queueEvent( "http_failure", url, err )
  776.         end
  777.         return ok, err
  778.     end
  779.  
  780.     local nativeCheckURL = http.checkURL
  781.     http.checkURLAsync = nativeCheckURL
  782.     http.checkURL = function( _url )
  783.         local ok, err = nativeCheckURL( _url )
  784.         if not ok then return ok, err end
  785.  
  786.         while true do
  787.             local _, url, ok, err = os.pullEvent( "http_check" )
  788.             if url == _url then return ok, err end
  789.         end
  790.     end
  791.  
  792.     local nativeWebsocket = http.websocket
  793.     http.websocketAsync = nativeWebsocket
  794.     http.websocket = function( _url, _headers )
  795.         expect(1, _url, "string")
  796.         expect(2, _headers, "table", "nil")
  797.  
  798.         local ok, err = nativeWebsocket( _url, _headers )
  799.         if not ok then return ok, err end
  800.  
  801.         while true do
  802.             local event, url, param = os.pullEvent( )
  803.             if event == "websocket_success" and url == _url then
  804.                 return param
  805.             elseif event == "websocket_failure" and url == _url then
  806.                 return false, param
  807.             end
  808.         end
  809.     end
  810. end
  811.  
  812. -- Install the lua part of the FS api
  813. local tEmpty = {}
  814. function fs.complete( sPath, sLocation, bIncludeFiles, bIncludeDirs )
  815.     expect(1, sPath, "string")
  816.     expect(2, sLocation, "string")
  817.     expect(3, bIncludeFiles, "boolean", "nil")
  818.     expect(4, bIncludeDirs, "boolean", "nil")
  819.  
  820.     bIncludeFiles = bIncludeFiles ~= false
  821.     bIncludeDirs = bIncludeDirs ~= false
  822.     local sDir = sLocation
  823.     local nStart = 1
  824.     local nSlash = string.find( sPath, "[/\\]", nStart )
  825.     if nSlash == 1 then
  826.         sDir = ""
  827.         nStart = 2
  828.     end
  829.     local sName
  830.     while not sName do
  831.         local nSlash = string.find( sPath, "[/\\]", nStart )
  832.         if nSlash then
  833.             local sPart = string.sub( sPath, nStart, nSlash - 1 )
  834.             sDir = fs.combine( sDir, sPart )
  835.             nStart = nSlash + 1
  836.         else
  837.             sName = string.sub( sPath, nStart )
  838.         end
  839.     end
  840.  
  841.     if fs.isDir( sDir ) then
  842.         local tResults = {}
  843.         if bIncludeDirs and sPath == "" then
  844.             table.insert( tResults, "." )
  845.         end
  846.         if sDir ~= "" then
  847.             if sPath == "" then
  848.                 table.insert( tResults, bIncludeDirs and ".." or "../" )
  849.             elseif sPath == "." then
  850.                 table.insert( tResults, bIncludeDirs and "." or "./" )
  851.             end
  852.         end
  853.         local tFiles = fs.list( sDir )
  854.         for n = 1, #tFiles do
  855.             local sFile = tFiles[n]
  856.             if #sFile >= #sName and string.sub( sFile, 1, #sName ) == sName then
  857.                 local bIsDir = fs.isDir( fs.combine( sDir, sFile ) )
  858.                 local sResult = string.sub( sFile, #sName + 1 )
  859.                 if bIsDir then
  860.                     table.insert( tResults, sResult .. "/" )
  861.                     if bIncludeDirs and #sResult > 0 then
  862.                         table.insert( tResults, sResult )
  863.                     end
  864.                 else
  865.                     if bIncludeFiles and #sResult > 0 then
  866.                         table.insert( tResults, sResult )
  867.                     end
  868.                 end
  869.             end
  870.         end
  871.         return tResults
  872.     end
  873.     return tEmpty
  874. end
  875.  
  876. -- Load APIs
  877. local bAPIError = false
  878. local tApis = fs.list( "rom/apis" )
  879. for _, sFile in ipairs( tApis ) do
  880.     if string.sub( sFile, 1, 1 ) ~= "." then
  881.         local sPath = fs.combine( "rom/apis", sFile )
  882.         if not fs.isDir( sPath ) then
  883.             if not os.loadAPI( sPath ) then
  884.                 bAPIError = true
  885.             end
  886.         end
  887.     end
  888. end
  889.  
  890. if turtle and fs.isDir( "rom/apis/turtle" ) then
  891.     -- Load turtle APIs
  892.     local tApis = fs.list( "rom/apis/turtle" )
  893.     for _, sFile in ipairs( tApis ) do
  894.         if string.sub( sFile, 1, 1 ) ~= "." then
  895.             local sPath = fs.combine( "rom/apis/turtle", sFile )
  896.             if not fs.isDir( sPath ) then
  897.                 if not os.loadAPI( sPath ) then
  898.                     bAPIError = true
  899.                 end
  900.             end
  901.         end
  902.     end
  903. end
  904.  
  905. if pocket and fs.isDir( "rom/apis/pocket" ) then
  906.     -- Load pocket APIs
  907.     local tApis = fs.list( "rom/apis/pocket" )
  908.     for _, sFile in ipairs( tApis ) do
  909.         if string.sub( sFile, 1, 1 ) ~= "." then
  910.             local sPath = fs.combine( "rom/apis/pocket", sFile )
  911.             if not fs.isDir( sPath ) then
  912.                 if not os.loadAPI( sPath ) then
  913.                     bAPIError = true
  914.                 end
  915.             end
  916.         end
  917.     end
  918. end
  919.  
  920. if commands and fs.isDir( "rom/apis/command" ) then
  921.     -- Load command APIs
  922.     if os.loadAPI( "rom/apis/command/commands.lua" ) then
  923.         -- Add a special case-insensitive metatable to the commands api
  924.         local tCaseInsensitiveMetatable = {
  925.             __index = function( table, key )
  926.                 local value = rawget( table, key )
  927.                 if value ~= nil then
  928.                     return value
  929.                 end
  930.                 if type(key) == "string" then
  931.                     local value = rawget( table, string.lower(key) )
  932.                     if value ~= nil then
  933.                         return value
  934.                     end
  935.                 end
  936.                 return nil
  937.             end,
  938.         }
  939.         setmetatable( commands, tCaseInsensitiveMetatable )
  940.         setmetatable( commands.async, tCaseInsensitiveMetatable )
  941.  
  942.         -- Add global "exec" function
  943.         exec = commands.exec
  944.     else
  945.         bAPIError = true
  946.     end
  947. end
  948.  
  949. if bAPIError then
  950.     print( "Press any key to continue" )
  951.     os.pullEvent( "key" )
  952.     term.clear()
  953.     term.setCursorPos( 1, 1 )
  954. end
  955.  
  956. -- Set default settings
  957. settings.set( "shell.allow_startup", true )
  958. settings.set( "shell.allow_disk_startup", commands == nil )
  959. settings.set( "shell.autocomplete", true )
  960. settings.set( "edit.autocomplete", true )
  961. settings.set( "edit.default_extension", "lua" )
  962. settings.set( "paint.default_extension", "nfp" )
  963. settings.set( "lua.autocomplete", true )
  964. settings.set( "list.show_hidden", false )
  965. settings.set( "motd.enable", false )
  966. settings.set( "motd.path", "/rom/motd.txt:/motd.txt" )
  967. if term.isColour() then
  968.     settings.set( "bios.use_multishell", true )
  969. end
  970. if _CC_DEFAULT_SETTINGS then
  971.     for sPair in string.gmatch( _CC_DEFAULT_SETTINGS, "[^,]+" ) do
  972.         local sName, sValue = string.match( sPair, "([^=]*)=(.*)" )
  973.         if sName and sValue then
  974.             local value
  975.             if sValue == "true" then
  976.                 value = true
  977.             elseif sValue == "false" then
  978.                 value = false
  979.             elseif sValue == "nil" then
  980.                 value = nil
  981.             elseif tonumber(sValue) then
  982.                 value = tonumber(sValue)
  983.             else
  984.                 value = sValue
  985.             end
  986.             if value ~= nil then
  987.                 settings.set( sName, value )
  988.             else
  989.                 settings.unset( sName )
  990.             end
  991.         end
  992.     end
  993. end
  994.  
  995. -- Load user settings
  996. if fs.exists( ".settings" ) then
  997.     settings.load( ".settings" )
  998. end
  999.  
  1000. -- Run the shell
  1001. local ok, err = pcall( function()
  1002.     parallel.waitForAny(
  1003.         function()
  1004.             local sShell
  1005.             if term.isColour() and settings.get( "bios.use_multishell" ) then
  1006.                 sShell = "rom/programs/advanced/multishell.lua"
  1007.             else
  1008.                 sShell = "rom/programs/shell.lua"
  1009.             end
  1010.             os.run( {}, sShell )
  1011.             os.run( {}, "rom/programs/shutdown.lua" )
  1012.         end,
  1013.         function()
  1014.             rednet.run()
  1015.         end )
  1016. end )
  1017.  
  1018. -- If the shell errored, let the user read it.
  1019. term.redirect( term.native() )
  1020. if not ok then
  1021.     printError( err )
  1022.     pcall( function()
  1023.         term.setCursorBlink( false )
  1024.         print( "Press any key to continue" )
  1025.         os.pullEvent( "key" )
  1026.     end )
  1027. end
  1028.  
  1029. -- End
  1030. os.shutdown()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement