256 lines
5.6 KiB
Text
256 lines
5.6 KiB
Text
|
local tArgs = {...}
|
||
|
|
||
|
local parentShell = shell
|
||
|
|
||
|
local bExit = false
|
||
|
local sDir = (parentShell and parentShell.dir()) or ""
|
||
|
local sPath = (parentShell and parentShell.path()) or ".:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
|
||
|
local tAliases = (parentShell and parentShell.aliases()) or {}
|
||
|
local tProgramStack = {}
|
||
|
|
||
|
local shell = {}
|
||
|
local tEnv = {
|
||
|
["shell"] = shell,
|
||
|
}
|
||
|
|
||
|
local function findArg(arg)
|
||
|
for _,v in ipairs(tArgs) do
|
||
|
if v == arg then
|
||
|
return true
|
||
|
end
|
||
|
end
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
-- Colours
|
||
|
local promptColour, textColour, bgColour
|
||
|
if term.isColour() then
|
||
|
promptColour = colours.yellow
|
||
|
textColour = colours.white
|
||
|
bgColour = colours.black
|
||
|
else
|
||
|
promptColour = colours.white
|
||
|
textColour = colours.white
|
||
|
bgColour = colours.black
|
||
|
end
|
||
|
|
||
|
|
||
|
local function run( _sCommand, ... )
|
||
|
local sPath = shell.resolveProgram( _sCommand )
|
||
|
if sPath ~= nil then
|
||
|
tProgramStack[#tProgramStack + 1] = sPath
|
||
|
local result = os.run( tEnv, sPath, ... )
|
||
|
tProgramStack[#tProgramStack] = nil
|
||
|
return result
|
||
|
else
|
||
|
printError( "No such program" )
|
||
|
printError( _sCommand .. ": Command not found" )
|
||
|
return false
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function runLine( _sLine )
|
||
|
local tWords = {}
|
||
|
for match in string.gmatch( _sLine, "[^ \t]+" ) do
|
||
|
table.insert( tWords, match )
|
||
|
end
|
||
|
|
||
|
local sCommand = tWords[1]
|
||
|
if sCommand then
|
||
|
return run( sCommand, unpack( tWords, 2 ) )
|
||
|
end
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
-- Install shell API
|
||
|
function shell.run( ... )
|
||
|
return runLine( table.concat( { ... }, " " ) )
|
||
|
end
|
||
|
|
||
|
function shell.exit()
|
||
|
bExit = true
|
||
|
end
|
||
|
|
||
|
function shell.dir()
|
||
|
return sDir
|
||
|
end
|
||
|
|
||
|
function shell.setDir( _sDir )
|
||
|
sDir = _sDir
|
||
|
end
|
||
|
|
||
|
function shell.path()
|
||
|
return sPath
|
||
|
end
|
||
|
|
||
|
function shell.setPath( _sPath )
|
||
|
sPath = _sPath
|
||
|
end
|
||
|
|
||
|
function shell.resolve( _sPath )
|
||
|
local sStartChar = string.sub( _sPath, 1, 1 )
|
||
|
if sStartChar == "/" or sStartChar == "\\" then
|
||
|
return fs.combine( "", _sPath )
|
||
|
else
|
||
|
return fs.combine( sDir, _sPath )
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function shell.resolveProgram( _sCommand )
|
||
|
-- Substitute aliases firsts
|
||
|
if tAliases[ _sCommand ] ~= nil then
|
||
|
_sCommand = tAliases[ _sCommand ]
|
||
|
end
|
||
|
|
||
|
-- If the path is a global path, use it directly
|
||
|
local sStartChar = string.sub( _sCommand, 1, 1 )
|
||
|
if sStartChar == "/" or sStartChar == "\\" then
|
||
|
local sPath = fs.combine( "", _sCommand )
|
||
|
if fs.exists( sPath ) and not fs.isDir( sPath ) then
|
||
|
return sPath
|
||
|
end
|
||
|
return nil
|
||
|
end
|
||
|
|
||
|
-- Otherwise, look on the path variable
|
||
|
for sPath in string.gmatch(sPath, "[^:]+") do
|
||
|
sPath = fs.combine( shell.resolve( sPath ), _sCommand )
|
||
|
if fs.exists( sPath ) and not fs.isDir( sPath ) then
|
||
|
return sPath
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Not found
|
||
|
return nil
|
||
|
end
|
||
|
|
||
|
function shell.programs( _bIncludeHidden )
|
||
|
local tItems = {}
|
||
|
|
||
|
-- Add programs from the path
|
||
|
for sPath in string.gmatch(sPath, "[^:]+") do
|
||
|
sPath = shell.resolve( sPath )
|
||
|
if fs.isDir( sPath ) then
|
||
|
local tList = fs.list( sPath )
|
||
|
for n,sFile in pairs( tList ) do
|
||
|
if not fs.isDir( fs.combine( sPath, sFile ) ) and
|
||
|
(_bIncludeHidden or string.sub( sFile, 1, 1 ) ~= ".") then
|
||
|
tItems[ sFile ] = true
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Sort and return
|
||
|
local tItemList = {}
|
||
|
for sItem, b in pairs( tItems ) do
|
||
|
table.insert( tItemList, sItem )
|
||
|
end
|
||
|
table.sort( tItemList )
|
||
|
return tItemList
|
||
|
end
|
||
|
|
||
|
function shell.getRunningProgram()
|
||
|
if #tProgramStack > 0 then
|
||
|
return tProgramStack[#tProgramStack]
|
||
|
end
|
||
|
return nil
|
||
|
end
|
||
|
|
||
|
function shell.setAlias( _sCommand, _sProgram )
|
||
|
tAliases[ _sCommand ] = _sProgram
|
||
|
end
|
||
|
|
||
|
function shell.clearAlias( _sCommand )
|
||
|
tAliases[ _sCommand ] = nil
|
||
|
end
|
||
|
|
||
|
function shell.aliases()
|
||
|
-- Add aliases
|
||
|
local tCopy = {}
|
||
|
for sAlias, sCommand in pairs( tAliases ) do
|
||
|
tCopy[sAlias] = sCommand
|
||
|
end
|
||
|
return tCopy
|
||
|
end
|
||
|
|
||
|
-- Custom shell API functions
|
||
|
|
||
|
function shell.executeScript(path)
|
||
|
if not fs.exists(path) or fs.isDir(path) then
|
||
|
return "File or directory not found"
|
||
|
else
|
||
|
local t = luaex.iterateFileLines(path)
|
||
|
if string.find(t[1], "@ @ !! FREAX SCRIPT HEADER") or t[1] == "@ @ !! FREAX SCRIPT HEADER" then
|
||
|
for _,cmd in pairs(t) do
|
||
|
shell.run(cmd)
|
||
|
end
|
||
|
else
|
||
|
return "Couldn't find script header"
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function shell.getActiveUserShell()
|
||
|
if fs.exists("/etc/passwd/.shadow/".._G["_activeUser"]..".usr") then
|
||
|
local ud = dofile("/etc/passwd/.shadow/".._G["_activeUser"]..".usr")
|
||
|
return ud.shell or "/bin/sh"
|
||
|
else
|
||
|
return "/bin/sh"
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Run custom shells
|
||
|
if findArg("--force") or findArg("-f") then
|
||
|
kernel.writeMessage("Ignoring shell settings")
|
||
|
elseif shell.getActiveUserShell() ~= "/bin/sh" then
|
||
|
shell.run(shell.getActiveUserShell())
|
||
|
kernel.shutdown(false)
|
||
|
end
|
||
|
|
||
|
term.setBackgroundColor( bgColour )
|
||
|
term.setTextColour( textColour )
|
||
|
|
||
|
local label = os.getComputerLabel() or os.getComputerID()
|
||
|
|
||
|
-- Read commands and execute them
|
||
|
local tCommandHistory = {}
|
||
|
while not bExit do
|
||
|
term.setBackgroundColor( bgColour )
|
||
|
if security.getSU() then
|
||
|
if security.getActiveUserStatus() then
|
||
|
term.setTextColour( colours.lime )
|
||
|
else
|
||
|
term.setTextColour( colours.orange )
|
||
|
end
|
||
|
else
|
||
|
term.setTextColour( colours.cyan )
|
||
|
end
|
||
|
write( _activeUser )
|
||
|
term.setTextColour( colours.lightGrey )
|
||
|
write( "@" )
|
||
|
term.setTextColour( colours.lightBlue )
|
||
|
write( label )
|
||
|
term.setTextColour( colours.lightGrey )
|
||
|
write( "/" )
|
||
|
term.setTextColour( colours.lightBlue )
|
||
|
write( shell.dir() )
|
||
|
if security.getSU() then
|
||
|
if security.getActiveUserStatus() then
|
||
|
term.setTextColour( colours.lime )
|
||
|
else
|
||
|
term.setTextColour( colours.orange )
|
||
|
end
|
||
|
write( " # " )
|
||
|
else
|
||
|
term.setTextColour( colours.cyan )
|
||
|
write( " $ " )
|
||
|
end
|
||
|
term.setTextColour( textColour )
|
||
|
|
||
|
local sLine = read( nil, tCommandHistory )
|
||
|
table.insert( tCommandHistory, sLine )
|
||
|
runLine( sLine )
|
||
|
end
|
||
|
|
||
|
-- Custom shutdown code goes here
|