Advertisement
An_random_user

bios.lua

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