metasploit-framework/lib/rex/ui/text/shell.rb

238 lines
4.7 KiB
Ruby

require 'rex/ui'
module Rex
module Ui
module Text
###
#
# Shell
# -----
#
# The shell class provides a command-prompt style interface in a
# generic fashion.
#
###
module Shell
###
#
# InputShell
# ----------
#
# This module is meant to be mixed into an input medium class instance as a
# means of extending it to display a prompt before each call to gets.
#
###
module InputShell
attr_accessor :prompt, :output
def pgets
output.print(prompt)
gets
end
end
def initialize(prompt, prompt_char = '>')
# Set the stop flag to false
self.stop_flag = false
self.disable_output = false
# Initialize the prompt
self.init_prompt = prompt
self.prompt_char = prompt_char
# Initialize the user interface handles
init_ui(Input::Stdio.new, Output::Stdio.new)
end
#
# Initializes the user interface input/output classes.
#
def init_ui(in_input = nil, in_output = nil)
# Initialize the input and output methods
self.input = in_input
self.output = in_output
if (self.input)
begin
self.input = Input::Readline.new(lambda { |str| tab_complete(str) })
rescue
end
# Extend the input medium as an input shell if the input medium
# isn't intrinsicly a shell.
if (self.input.intrinsic_shell? == false)
self.input.extend(InputShell)
end
self.input.output = self.output
end
update_prompt
end
#
# Resets the user interface
#
def reset_ui
init_ui
end
#
# Performs tab completion on the supplied string
#
def tab_complete(str)
return tab_complete_proc(str) if (tab_complete_proc)
end
#
# Run the command processing loop
#
def run(&block)
stop_flag = false
while ((line = input.pgets))
# If a block was passed in, pass the line to it. If it returns true,
# break out of the shell loop.
if (block)
break if (block.call(line))
# Otherwise, call what should be an overriden instance method to
# process the line.
else
run_single(line)
end
# If the stop flag was set or we've hit EOF, break out
break if (input.eof? or self.stop_flag)
end
end
#
# Stop processing user input
#
def stop
self.stop_flag = true
end
#
# Checks to see if the shell has stopped
#
def stopped?
self.stop_flag
end
#
# Change the input prompt
#
def update_prompt(prompt = '', new_prompt_char = nil)
new_prompt = self.init_prompt + ' ' + prompt + prompt_char + ' '
# Substitute colors
new_prompt.gsub!(/%u/, colorize('underline'))
new_prompt.gsub!(/%b/, colorize('bold'))
new_prompt.gsub!(/%c/, colorize('clear'))
new_prompt.gsub!(/%red/, colorize('red'))
new_prompt.gsub!(/%grn/, colorize('green'))
new_prompt.gsub!(/%blu/, colorize('blue'))
new_prompt.gsub!(/%yel/, colorize('yellow'))
new_prompt.gsub!(/%cya/, colorize('cyan'))
new_prompt.gsub!(/%whi/, colorize('white'))
new_prompt.gsub!(/%mag/, colorize('magenta'))
new_prompt.gsub!(/%blk/, colorize('black'))
new_prompt.gsub!(/%dred/, colorize('dark', 'red'))
new_prompt.gsub!(/%dgrn/, colorize('dark', 'green'))
new_prompt.gsub!(/%dblu/, colorize('dark', 'blue'))
new_prompt.gsub!(/%dyel/, colorize('dark', 'yellow'))
new_prompt.gsub!(/%dcya/, colorize('dark', 'cyan'))
new_prompt.gsub!(/%dwhi/, colorize('dark', 'white'))
new_prompt.gsub!(/%dmag/, colorize('dark', 'magenta'))
self.input.prompt = new_prompt if (self.input)
self.prompt_char = new_prompt_char if (new_prompt_char)
end
#
# Color checks
#
#
# Checks to see whether or not colors are supported on this shell
# console
#
def supports_color?
return (ENV['TERM'].match(/(?:vt10[03]|xterm(?:-color)?|linux|screen)/i) != nil)
end
#
# Resets coloring so that it's back to normal
#
def reset_color
print(colorize('clear'))
end
#
# Returns colorized text if it's supported, otherwise an empty string
#
def colorize(*color)
# This check is busted atm...
#return (supports_color? == false) ? '' : Rex::Ui::Text::Color.ansi(color)
return Rex::Ui::Text::Color.ansi(*color)
end
#
# Output shortcuts
#
def print_error(msg)
# Errors are not subject to disabled output
output.print_error(msg)
end
def print_status(msg)
return if (disable_output == true)
output.print_status(msg)
end
def print_line(msg)
return if (disable_output == true)
output.print_line(msg)
end
def print(msg)
return if (disable_output == true)
output.print(msg)
end
attr_accessor :disable_output
attr_reader :input, :output
protected
#
# Parse a line into an array of arguments
#
def parse_line(line)
line.gsub!(/(\r|\n)/, '')
begin
return args = Rex::Parser::Arguments.from_s(line)
rescue ArgumentError
print_error("Parse error: #{$!}")
end
return []
end
attr_writer :input, :output
attr_accessor :stop_flag, :init_prompt
attr_accessor :prompt_char, :tab_complete_proc
end
end end end