Advertisement
LoganDark

TLCO

Jan 2nd, 2021 (edited)
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.37 KB | None | 0 0
  1. local program, args = (select(1, ...)), table.pack(select(2, ...))
  2. if select('#', ...) < 1 then program = 'shell' end
  3.  
  4. if shell then
  5.     local resolved = shell.resolveProgram(program)
  6.  
  7.     if not resolved then
  8.         printError('Couldn\'t find program: ' .. program)
  9.         return 1
  10.     end
  11.  
  12.     program = resolved
  13. end
  14.  
  15. -- else hope the user knows what they are doing
  16. -- it probably won't even work unless some parent env has shell
  17.  
  18. local function pullEventAbsolute(filter)
  19.     local data
  20.  
  21.     while true do
  22.         data = table.pack(coroutine.yield(filter))
  23.  
  24.         if data[1] == filter then
  25.             return table.unpack(data, 1, data.n)
  26.         end
  27.     end
  28. end
  29.  
  30. local originalQueueEvent = os.queueEvent
  31. local function onError(err)
  32.     printError(err)
  33.     print('Press any key to continue')
  34.     originalQueueEvent('fast-forward')
  35.     pullEventAbsolute('fast-forward')
  36.     pullEventAbsolute('key')
  37.     os.shutdown()
  38.     os.shutdown()
  39. end
  40.  
  41. local eventName = 'tlco_' .. tostring(math.random(-20000, 20000))
  42.  
  43. local originalPrint = print
  44. local originalShutdown = os.shutdown
  45. local originalPullEvent = os.pullEvent
  46.  
  47. local function restore()
  48.     _G.print = originalPrint
  49.     os.shutdown = originalShutdown
  50.     os.pullEvent = originalPullEvent
  51. end
  52.  
  53. function _G.print() end -- prevent error text, and "press any key to continue"
  54.  
  55. local methodUsed = 'Unknown'
  56.  
  57. function os.shutdown() -- called at end of bios
  58.     pullEventAbsolute(eventName)
  59.  
  60.     restore()
  61.  
  62.     -- We have now achieved top-level coroutine override
  63.  
  64.     term.setTextColor(colors.cyan)
  65.     print('TLCO Activated, ' .. methodUsed .. ' method')
  66.     term.setTextColor(colors.white)
  67.  
  68.     local preShutdown = os.shutdown
  69.  
  70.     -- run directly in _G
  71.     local func, err = loadfile(program, nil, _G)
  72.     if not func then return onError(err) end
  73.  
  74.     local ok, err = pcall(func, table.unpack(args, 1, args.n))
  75.     if not ok then return onError(err) end
  76.  
  77.     -- Only run os.shutdown if it has changed, for nested TLCOs
  78.     if os.shutdown ~= preShutdown then
  79.         -- Run os.shutdown twice. Why? Because regular bios does it. Sane TLCOs hook the second shutdown after shell exit.
  80.         -- There is no rednet to crash, so TLCO will try to exit the shell. Give them something to hook if they so please.
  81.         -- I don't know why people would nest TLCOs, but maybe they do
  82.         os.shutdown()
  83.         os.shutdown()
  84.     end
  85. end
  86.  
  87. function os.pullEvent(filter) -- called in middle of bios
  88.     if filter == 'key' then
  89.         -- haha lol
  90.     else
  91.         return originalPullEvent(filter)
  92.     end
  93. end
  94.  
  95. methodUsed = 'Rednet'
  96.  
  97. os.queueEvent('modem_message', 0) -- crash rednet
  98. os.queueEvent(eventName)
  99. pullEventAbsolute(eventName) -- wait for the crash
  100.  
  101. -- If we are still running, try a different method
  102.  
  103. methodUsed = 'Shell'
  104.  
  105. do -- Expect two shutdowns
  106.     local hookedShutdown = os.shutdown
  107.     function os.shutdown()
  108.         os.shutdown = hookedShutdown
  109.     end
  110. end
  111.  
  112. do -- Prevent one second delay caused by rom/programs/shutdown.lua
  113.     local originalSleep = _G.sleep
  114.     function _G.sleep() end
  115.  
  116.     -- Restore os.sleep once TLCO executes
  117.  
  118.     local originalRestore = restore
  119.     restore = function()
  120.         originalRestore()
  121.         _G.sleep = originalSleep
  122.     end
  123. end
  124.  
  125. do -- Exit all shells
  126.     local exited = false
  127.  
  128.     for i = 1, 100 do
  129.         local ok, fenv = pcall(getfenv, i)
  130.         if ok and fenv.shell then
  131.             fenv.shell.exit()
  132.             exited = true
  133.         end
  134.     end
  135.  
  136.     if not exited then
  137.         restore()
  138.         printError('TLCO failed: not running under CraftOS')
  139.         return 1
  140.     end
  141. end
  142.  
  143. os.queueEvent(eventName)
  144.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement