module Rex::Ui::Text::Shell
The shell class provides a command-prompt style interface in a generic fashion.
Attributes
Whether or not output has been disabled.
The input handle to read user input from.
The output handle to write output to.
Public Class Methods
Initializes a shell that has a prompt and can be interacted with.
# File lib/rex/ui/text/shell.rb, line 40 def initialize(prompt, prompt_char = '>', histfile = nil, framework = nil) # Set the stop flag to false self.stop_flag = false self.disable_output = false self.stop_count = 0 # Initialize the prompt self.init_prompt = prompt self.prompt_char = prompt_char self.histfile = histfile self.hist_last_saved = 0 self.framework = framework end
Public Instance Methods
# File lib/rex/ui/text/shell.rb, line 56 def init_tab_complete if (self.input and self.input.supports_readline) self.input = Input::Readline.new(lambda { |str| tab_complete(str) }) if Readline::HISTORY.length == 0 and histfile and File.exists?(histfile) File.readlines(histfile).each { |e| Readline::HISTORY << e.chomp } self.hist_last_saved = Readline::HISTORY.length end self.input.output = self.output update_prompt(input.prompt) end end
Initializes the user interface input/output classes.
# File lib/rex/ui/text/shell.rb, line 73 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) # 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
Prints a raw message to the output handle.
# File lib/rex/ui/text/shell.rb, line 318 def print(msg='') return if (disable_output == true) self.on_print_proc.call(msg) if self.on_print_proc log_output(output.print(msg)) end
Prints an error message to the output handle.
# File lib/rex/ui/text/shell.rb, line 267 def print_error(msg='') return if (output.nil?) self.on_print_proc.call(msg) if self.on_print_proc # Errors are not subject to disabled output log_output(output.print_error(msg)) end
Prints a good message to the output handle.
# File lib/rex/ui/text/shell.rb, line 288 def print_good(msg='') return if (disable_output == true) self.on_print_proc.call(msg) if self.on_print_proc log_output(output.print_good(msg)) end
Prints a line of text to the output handle.
# File lib/rex/ui/text/shell.rb, line 298 def print_line(msg='') return if (disable_output == true) self.on_print_proc.call(msg) if self.on_print_proc log_output(output.print_line(msg)) end
Prints a status message to the output handle.
# File lib/rex/ui/text/shell.rb, line 278 def print_status(msg='') return if (disable_output == true) self.on_print_proc.call(msg) if self.on_print_proc log_output(output.print_status(msg)) end
Prints a warning message to the output handle.
# File lib/rex/ui/text/shell.rb, line 308 def print_warning(msg='') return if (disable_output == true) self.on_print_proc.call(msg) if self.on_print_proc log_output(output.print_warning(msg)) end
Resets the user interface handles.
# File lib/rex/ui/text/shell.rb, line 93 def reset_ui init_ui end
Run the command processing loop.
# File lib/rex/ui/text/shell.rb, line 121 def run(&block) begin while true # If the stop flag was set or we've hit EOF, break out break if (self.stop_flag or self.stop_count > 1) init_tab_complete if framework if input.prompt.include?("%T") t = Time.now if framework.datastore['PromptTimeFormat'] t = t.strftime(framework.datastore['PromptTimeFormat']) end input.prompt.gsub!(/%T/, t.to_s) end if input.prompt.include?("%H") hostname = ENV['HOSTNAME'] if hostname.nil? hostname = `hostname`.split('.')[0] end # check if hostname is still nil if hostname.nil? hostname = ENV['COMPUTERNAME'] end if hostname.nil? hostname = 'unknown' end input.prompt.gsub!(/%H/, hostname.chomp) end if input.prompt.include?("%U") user = ENV['USER'] if user.nil? user = `whoami` end # check if username is still nil if user.nil? user = ENV['USERNAME'] end if user.nil? user = 'unknown' end input.prompt.gsub!(/%U/, user.chomp) end input.prompt.gsub!(/%S/, framework.sessions.length.to_s) input.prompt.gsub!(/%J/, framework.jobs.length.to_s) input.prompt.gsub!(/%L/, Rex::Socket.source_address("50.50.50.50")) input.prompt.gsub!(/%D/, ::Dir.getwd) self.init_prompt = input.prompt end line = input.pgets() log_output(input.prompt) # 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 (line == nil or block.call(line)) elsif(input.eof? or line == nil) # If you have sessions active, this will give you a shot to exit gravefully # If you really are ambitious, 2 eofs will kick this out self.stop_count += 1 next if(self.stop_count > 1) run_single("quit") else # Otherwise, call what should be an overriden instance method to # process the line. ret = run_single(line) # don't bother saving lines that couldn't be found as a # command, create the file if it doesn't exist if ret and self.histfile File.open(self.histfile, "a+") { |f| f.puts(line) } end self.stop_count = 0 end end # Prevent accidental console quits rescue ::Interrupt output.print("Interrupt: use the 'exit' command to quit\n") retry end end
Sets the log source that should be used for logging input and output.
# File lib/rex/ui/text/shell.rb, line 100 def set_log_source(log_source) self.log_source = log_source end
Stop processing user input.
# File lib/rex/ui/text/shell.rb, line 221 def stop self.stop_flag = true end
Checks to see if the shell has stopped.
# File lib/rex/ui/text/shell.rb, line 228 def stopped? self.stop_flag end
Performs tab completion on the supplied string.
# File lib/rex/ui/text/shell.rb, line 114 def tab_complete(str) return tab_complete_proc(str) if (tab_complete_proc) end
Unsets the log source so that logging becomes disabled.
# File lib/rex/ui/text/shell.rb, line 107 def unset_log_source set_log_source(nil) end
Change the input prompt.
prompt - the actual prompt new_prompt_char the char to append to the prompt mode - append or not to append - false = append true = make a new prompt
# File lib/rex/ui/text/shell.rb, line 238 def update_prompt(prompt = nil, new_prompt_char = nil, mode = false) if (self.input) if prompt new_prompt = self.init_prompt + ' ' + prompt + prompt_char + ' ' else new_prompt = self.prompt || '' end if mode new_prompt = prompt + (new_prompt_char || prompt_char) + ' ' end # Save the prompt before any substitutions self.prompt = new_prompt # Set the actual prompt to the saved prompt with any substitutions # or updates from our output driver, be they color or whatever self.input.prompt = self.output.update_prompt(new_prompt) self.prompt_char = new_prompt_char if (new_prompt_char) end end
Protected Instance Methods
Print the prompt, but do not log it.
# File lib/rex/ui/text/shell.rb, line 363 def _print_prompt(prompt) output.print(prompt) end
Writes the supplied input to the log source if one has been registered.
# File lib/rex/ui/text/shell.rb, line 370 def log_input(buf) rlog(buf, log_source) if (log_source) end
Writes the supplied output to the log source if one has been registered.
# File lib/rex/ui/text/shell.rb, line 377 def log_output(buf) rlog(buf, log_source) if (log_source) end
Parse a line into an array of arguments.
# File lib/rex/ui/text/shell.rb, line 346 def parse_line(line) log_input(line) line.gsub!(/(\r|\n)/, '') begin return args = Rex::Parser::Arguments.from_s(line) rescue ::ArgumentError print_error("Parse error: #{$!}") end return [] end