View difference between Paste ID: xhM6zwPq and ZJxyBnui
SHOW: | | - or go back to the newest paste.
1
-- Shell
2
local parentShell = shell
3
4
local bExit = false
5
local sDir = (parentShell and parentShell.dir()) or ""
6
local sPath = (parentShell and parentShell.path()) or ".:/rom/programs"
7
local tAliases = (parentShell and parentShell.aliases()) or {}
8
local tProgramStack = {}
9
10
local shell = {}
11
local tEnv = {
12
	["shell"] = shell,
13
}
14
15
-- Install shell API
16
function shell.run( _sCommand, ... )
17
	local sPath = shell.resolveProgram( _sCommand )
18
	if sPath ~= nil then
19
		tProgramStack[#tProgramStack + 1] = sPath
20
   		local result = os.run( tEnv, sPath, ... )
21
		tProgramStack[#tProgramStack] = nil
22
		return result
23
   	else
24
    	print( "No such program" )
25
    	return false
26
    end
27
end
28
29
function shell.exit()
30
    bExit = true
31
end
32
33
function shell.dir()
34
	return sDir
35
end
36
37
function shell.setDir( _sDir )
38
	sDir = _sDir
39
end
40
41
function shell.path()
42
	return sPath
43
end
44
45
function shell.setPath( _sPath )
46
	sPath = _sPath
47
end
48
49
function shell.resolve( _sPath )
50
	local sStartChar = string.sub( _sPath, 1, 1 )
51
	if sStartChar == "/" or sStartChar == "\\" then
52
		return fs.combine( "", _sPath )
53
	else
54
		return fs.combine( sDir, _sPath )
55
	end
56
end
57
58
function shell.resolveProgram( _sCommand )
59
	-- Substitute aliases firsts
60
	if tAliases[ _sCommand ] ~= nil then
61
		_sCommand = tAliases[ _sCommand ]
62
	end
63
64
    -- If the path is a global path, use it directly
65
    local sStartChar = string.sub( _sCommand, 1, 1 )
66
    if sStartChar == "/" or sStartChar == "\\" then
67
    	local sPath = fs.combine( "", _sCommand )
68
    	if fs.exists( sPath ) and not fs.isDir( sPath ) then
69
			return sPath
70
    	end
71
		return nil
72
    end
73
    
74
 	-- Otherwise, look on the path variable
75-
    for sPath in string.gmatch(sPath, "[^:] ") do
75+
    for sPath in string.gmatch(sPath, "[^:]+") do
76
    	sPath = fs.combine( shell.resolve( sPath ), _sCommand )
77
    	if fs.exists( sPath ) and not fs.isDir( sPath ) then
78
			return sPath
79
    	end
80
    end
81
	
82
	-- Not found
83
	return nil
84
end
85
86
function shell.programs( _bIncludeHidden )
87
	local tItems = {}
88
	
89
	-- Add programs from the path
90-
    for sPath in string.gmatch(sPath, "[^:] ") do
90+
    for sPath in string.gmatch(sPath, "[^:]+") do
91
    	sPath = shell.resolve( sPath )
92
		if fs.isDir( sPath ) then
93
			local tList = fs.list( sPath )
94
			for n,sFile in pairs( tList ) do
95
				if not fs.isDir( fs.combine( sPath, sFile ) ) and
96
				   (_bIncludeHidden or string.sub( sFile, 1, 1 ) ~= ".") then
97
					tItems[ sFile ] = true
98
				end
99
			end
100
		end
101
    end	
102
103
	-- Sort and return
104
	local tItemList = {}
105
	for sItem, b in pairs( tItems ) do
106
		table.insert( tItemList, sItem )
107
	end
108
	table.sort( tItemList )
109
	return tItemList
110
end
111
112
function shell.getRunningProgram()
113
	if #tProgramStack > 0 then
114
		return tProgramStack[#tProgramStack]
115
	end
116
	return nil
117
end
118
119
function shell.setAlias( _sCommand, _sProgram )
120
	tAliases[ _sCommand ] = _sProgram
121
end
122
123
function shell.clearAlias( _sCommand )
124
	tAliases[ _sCommand ] = nil
125
end
126
127
function shell.aliases()
128
	-- Add aliases
129
	local tCopy = {}
130
	for sAlias, sCommand in pairs( tAliases ) do
131
		tCopy[sAlias] = sCommand
132
	end
133
	return tCopy
134
end
135
	
136
print( os.version() )
137
138
-- If this is the toplevel shell, run the startup programs
139
if parentShell == nil then
140
	-- Run the startup from the ROM first
141
	local sRomStartup = shell.resolveProgram( "/rom/startup" )
142
	if sRomStartup then
143
		shell.run( sRomStartup )
144
	end
145
	
146
	-- Then run the user created startup, from the disks or the root
147
	local sUserStartup = shell.resolveProgram( "/startup" )
148
	for n,sSide in pairs( redstone.getSides() ) do
149
		if disk.isPresent( sSide ) and disk.hasData( sSide ) then
150
			local sDiskStartup = shell.resolveProgram( fs.combine(disk.getMountPath( sSide ), "startup") )
151
			if sDiskStartup then
152
				sUserStartup = sDiskStartup
153
				break
154
			end
155
		end
156
	end
157
	
158
	if sUserStartup then
159
		shell.run( sUserStartup )
160
	end
161
end
162
163
-- Run any programs passed in as arguments
164
local tArgs = { ... }
165
if #tArgs > 0 then
166
	shell.run( ... )
167
end
168
169
-- Variables
170
oldshellrun = shell.run
171
oldfsopen = fs.open
172
canmove = fs.move
173
rof = fs.isReadOnly
174
del = fs.delete
175
iopen = io.open
176
-----------------------------
177
178
function antiFsOpen( path, mode )
179
	if path == "/disk/bios.lua" or path == "disk/bios.lua" or path == "/disk/pwd" or path == "disk/pwd" or path == "/disk/echo" or path == "disk/echo" then
180
		return false
181
	else
182
		return oldfsopen( path, mode )
183
	end
184
end
185
186
function movedeny( path, to )
187
	if path == "/disk/bios.lua" or path == "disk/bios.lua" or path == "/disk/pwd" or path == "disk/pwd" or path == "/disk/echo" or path == "disk/echo" then
188
		return false
189
	else
190
		return canmove( path, to )
191
	end
192
end
193
194
function isReadOnly( path )
195
	if path == "/disk/bios.lua" or path == "disk/bios.lua" or path == "/disk/pwd" or path == "disk/pwd" or path == "/disk/echo" or path == "disk/echo" then
196
		return true
197
	else
198
		return rof( path )
199
	end
200
end
201
202
function newdelete( path )
203
	if path == "/disk/bios.lua" or path == "disk/bios.lua" or path == "/disk/pwd" or path == "disk/pwd" or path == "/disk/echo" or path == "disk/echo" then
204
		return false
205
	else
206
		return del( path )
207
	end
208
end
209
210
function newiopen( path, mode )
211
	if path == "/disk/bios.lua" or path == "disk/bios.lua" or path == "/disk/pwd" or path == "disk/pwd" or path == "/disk/echo" or path == "disk/echo" then
212
		return false
213
	else
214
		return iopen( path, mode )
215
	end
216
end
217
218
219
fs.delete = newdelete
220
fs.isReadOnly = isReadOnly
221
fs.move = movedeny
222
fs.open = antiFsOpen
223
shell.run = shellrun
224
io.open = newiopen
225
226
id = os.getComputerID()
227
-- Read commands and execute them
228
local tCommandHistory = {}
229
while not bExit do
230
	if shell.dir() == "" then
231
		write( "[root@".. id .." /]# " )
232
	else
233
		write( "[root@".. id .." ".. shell.dir() .."]# " )
234
	end
235
236
	local sLine = read( nil, tCommandHistory )
237
	table.insert( tCommandHistory, sLine )
238
	
239
	local tWords = {}
240
	for match in string.gmatch(sLine, "[^ \t]+") do
241
		table.insert( tWords, match )
242
	end
243
244
	local sCommand = tWords[1]
245
	if sCommand then
246
		shell.run( sCommand, unpack( tWords, 2 ) )
247
	end
248
end
249
250
-- If this is the toplevel shell, run the shutdown program
251
if parentShell == nil then
252
	if shell.resolveProgram( "shutdown" ) then
253
		shell.run( "shutdown" )
254
	end
255
	os.shutdown() -- just in case
256
end