View difference between Paste ID: ra2cAXFh and 2SQAzrWi
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()