SHOW:
|
|
- or go back to the newest paste.
| 1 | - | --[[ |
| 1 | + | |
| 2 | - | Author: NeverCast |
| 2 | + | |
| 3 | - | Last Edited: 22/07/13 |
| 3 | + | os.run( {}, "rom/programs/lua" )
|
| 4 | - | Published: 2/11/12 |
| 4 | + | |
| 5 | - | You're welcome to use this code however you like, but please leave my credit at the top. Thanks |
| 5 | + | |
| 6 | - | --]] |
| 6 | + | |
| 7 | -- Feel free to set this to false if you don't want the text printed | |
| 8 | - | --[[ |
| 8 | + | |
| 9 | - | Changes: |
| 9 | + | |
| 10 | ||
| 11 | - | 1.Replacing the for-loop with a while-loop to not limit the iterations required in finding the parent shell |
| 11 | + | |
| 12 | - | 2.Removing Rednet and reloading it to fix the already running issue. |
| 12 | + | |
| 13 | - | 3.Now clears the myEnv global variable once injection is complete. |
| 13 | + | |
| 14 | end | |
| 15 | - | Thanks KaoS and TheOriginalBit for code fixes and bug reports. |
| 15 | + | |
| 16 | - | --]] |
| 16 | + | |
| 17 | return | |
| 18 | - | -- Prior code writing hypothosis: |
| 18 | + | |
| 19 | - | -- How to become top level, |
| 19 | + | |
| 20 | local prevState = {}
| |
| 21 | - | -- Climb stack, Find single shell instance |
| 21 | + | |
| 22 | - | -- Kill shell instance, override pullEvent |
| 22 | + | |
| 23 | - | -- Override os.shutdown |
| 23 | + | |
| 24 | - | -- Exit code |
| 24 | + | |
| 25 | - | -- Wait for Bios to quit and hook that to fire up your own functions |
| 25 | + | |
| 26 | end | |
| 27 | - | -- Add the functions here that you want to run once the environment has been overridden |
| 27 | + | |
| 28 | - | -- In this bios this was shell and rednet.run, I've removed rednet.run as an example |
| 28 | + | |
| 29 | - | -- Any functions here will be top level and recieve all the events! |
| 29 | + | |
| 30 | local function getParentShell() | |
| 31 | local at=0 | |
| 32 | - | os.run( {}, "rom/programs/shell" )
|
| 32 | + | |
| 33 | at=at+1 | |
| 34 | local ok,env = pcall(function() return getfenv(at) end) | |
| 35 | if not ok then break end | |
| 36 | if table.size(env) == 1 then | |
| 37 | local i,v = next(env) -- Grab first | |
| 38 | if i == "shell" then | |
| 39 | return v | |
| 40 | end | |
| 41 | end | |
| 42 | end | |
| 43 | return nil | |
| 44 | end | |
| 45 | ||
| 46 | local function recover() | |
| 47 | -- Set flag | |
| 48 | os.myEnv = true | |
| 49 | -- Put back the trampled environment | |
| 50 | os.startTimer = prevState.startTimer | |
| 51 | os.shutdown = prevState.shutdown | |
| 52 | os.pullEvent = prevState.pullEvent | |
| 53 | -- Launch shell like nothing happened | |
| 54 | ||
| 55 | prevState = nil | |
| 56 | ||
| 57 | term.setCursorPos(1,1) | |
| 58 | term.clear() | |
| 59 | ||
| 60 | if showMessages then | |
| 61 | -- Feel free to remove this line, It's just a proof thing | |
| 62 | print"Look at me, I load before shell does" | |
| 63 | end | |
| 64 | ||
| 65 | -- Because we killed rednet, we have to remove it and then reload it | |
| 66 | _G['rednet'] = nil | |
| 67 | os.loadAPI('/rom/apis/rednet')
| |
| 68 | ||
| 69 | local ok, err = pcall( function() | |
| 70 | parallel.waitForAny( | |
| 71 | unpack(loadPool) | |
| 72 | ) | |
| 73 | end ) | |
| 74 | end | |
| 75 | ||
| 76 | os.stage = {}
| |
| 77 | ||
| 78 | -- Stages: | |
| 79 | -- injected: Overriding os functions | |
| 80 | -- shutdown: Shutdown program has been called | |
| 81 | -- jstincse: Shell is doing it's just-in-case | |
| 82 | -- bioswait: Bios is waiting for a key press | |
| 83 | -- biosexit: Bios has quit | |
| 84 | -- complete: fully injected | |
| 85 | ||
| 86 | ||
| 87 | local function setStage(stage) | |
| 88 | os.stage.currentStage = stage | |
| 89 | end | |
| 90 | ||
| 91 | local function getStage() | |
| 92 | return os.stage.currentStage | |
| 93 | end | |
| 94 | ||
| 95 | local function _os_pullEvent(_filter) | |
| 96 | _filter = _filter or "" | |
| 97 | if _filter == "key" then | |
| 98 | setStage("bioswait")
| |
| 99 | return "key", 0 | |
| 100 | elseif _filter == "timer" then | |
| 101 | setStage("shutdown")
| |
| 102 | return "timer", 0 | |
| 103 | end | |
| 104 | end | |
| 105 | ||
| 106 | local function _replSleep(dur) | |
| 107 | local timer = prevState.startTimer( dur ) | |
| 108 | repeat | |
| 109 | local sEvent, param = prevState.pullEvent( "timer" ) | |
| 110 | until param == timer | |
| 111 | end | |
| 112 | ||
| 113 | local function _os_shutdown() | |
| 114 | if getStage() == "shutdown" then | |
| 115 | setStage("jstincse")
| |
| 116 | elseif getStage() == "bioswait" then | |
| 117 | setStage("biosexit")
| |
| 118 | end | |
| 119 | if getStage() == "biosexit" then | |
| 120 | recover() | |
| 121 | end | |
| 122 | end | |
| 123 | ||
| 124 | local function _os_startTimer(seconds) | |
| 125 | return 0 | |
| 126 | end | |
| 127 | ||
| 128 | local function inject() | |
| 129 | prevState.startTimer = os.startTimer | |
| 130 | prevState.shutdown = os.shutdown | |
| 131 | prevState.pullEvent = os.pullEvent | |
| 132 | os.shutdown = _os_shutdown | |
| 133 | os.pullEvent = _os_pullEvent | |
| 134 | os.startTimer = _os_startTimer | |
| 135 | setStage("injected")
| |
| 136 | local shellImpl = getParentShell() | |
| 137 | shellImpl.exit() | |
| 138 | end | |
| 139 | ||
| 140 | -- Start everything | |
| 141 | inject() |