This class implements the stubs that are needed to provide an interactive user interface that is backed against something arbitrary.
Stops the current interaction
# File lib/rex/ui/interactive.rb, line 92 def detach if (self.interacting) self.interacting = false while(not self.completed) ::IO.select(nil, nil, nil, 0.25) end end end
Starts interacting with the session at the most raw level, simply forwarding input from user_input to rstream and forwarding input from rstream to user_output.
# File lib/rex/ui/interactive.rb, line 23 def interact(user_input, user_output) # Detach from any existing console if(self.interacting) detach() end init_ui(user_input, user_output) self.interacting = true self.completed = false eof = false # Start the readline stdin monitor # XXX disabled # user_input.readline_start() if user_input.supports_readline # Handle suspend notifications handle_suspend # As long as we're interacting... while (self.interacting == true) begin _interact rescue Interrupt # If we get an interrupt exception, ask the user if they want to # abort the interaction. If they do, then we return out of # the interact function and call it a day. eof = true if (_interrupt) rescue EOFError, Errno::ECONNRESET, IOError # If we reach EOF or the connection is reset... eof = true end break if eof end begin # Restore the suspend handler restore_suspend # If we've hit eof, call the interact complete handler _interact_complete if (eof == true) # Shutdown the readline thread # XXX disabled # user_input.readline_stop() if user_input.supports_readline # Detach from the input/output handles reset_ui() ensure # Mark this as completed self.completed = true end # Return whether or not EOF was reached return eof end
Stub method that is meant to handler interaction
# File lib/rex/ui/interactive.rb, line 124 def _interact end
Called when interaction has completed and one of the sides has closed.
# File lib/rex/ui/interactive.rb, line 144 def _interact_complete true end
Called when an interrupt is sent.
# File lib/rex/ui/interactive.rb, line 130 def _interrupt true end
The local file descriptor handle.
# File lib/rex/ui/interactive.rb, line 171 def _local_fd user_input.fd end
The remote file descriptor handle.
# File lib/rex/ui/interactive.rb, line 178 def _remote_fd(stream) stream.fd end
Read from local and write to remote.
# File lib/rex/ui/interactive.rb, line 161 def _stream_read_local_write_remote(stream) data = user_input.gets self.on_command_proc.call(data) if self.on_command_proc stream.put(data) end
Read from remote and write to local.
# File lib/rex/ui/interactive.rb, line 151 def _stream_read_remote_write_local(stream) data = stream.get self.on_print_proc.call(data) if self.on_print_proc user_output.print(data) end
Called when a suspend is sent.
# File lib/rex/ui/interactive.rb, line 137 def _suspend false end
Installs a signal handler to monitor suspend signal notifications.
# File lib/rex/ui/interactive.rb, line 254 def handle_suspend if (orig_suspend == nil) begin self.orig_suspend = Signal.trap("TSTP") { _suspend } rescue end end end
Interacts between a local stream and a remote ring buffer. This has to use a secondary thread to prevent the select on the local stream from blocking
# File lib/rex/ui/interactive.rb, line 212 def interact_ring(ring) begin rdr = Rex::ThreadFactory.spawn("RingMonitor", false) do seq = nil while self.interacting # Look for any pending data from the remote ring nseq,data = ring.read_data(seq) # Update the sequence number if necessary seq = nseq || seq # Write output to the local stream if successful user_output.print(data) if data # Wait for new data to arrive on this session ring.wait(seq) end end while self.interacting # Look for any pending input from the local stream sd = Rex::ThreadSafe.select([ _local_fd ], nil, [_local_fd], 5.0) # Write input to the ring's input mechanism if sd data = user_input.gets ring.put(data) end end ensure rdr.kill end end
Interacts with two streaming connections, reading data from one and writing it to the other. Both are expected to implement Rex::IO::Stream.
# File lib/rex/ui/interactive.rb, line 186 def interact_stream(stream) while self.interacting # Select input and rstream sd = Rex::ThreadSafe.select([ _local_fd, _remote_fd(stream) ], nil, nil, 0.25) # Cycle through the items that have data # From the stream? Write to user_output. sd[0].each { |s| if (s == _remote_fd(stream)) _stream_read_remote_write_local(stream) # From user_input? Write to stream. elsif (s == _local_fd) _stream_read_local_write_remote(stream) end } if (sd) Thread.pass end end
Prompt the user for input if possible. XXX: This is not thread-safe on Windows
# File lib/rex/ui/interactive.rb, line 285 def prompt(query) if (user_output and user_input) user_output.print("\n" + query) user_input.sysread(2) end end
Check the return value of a yes/no prompt
# File lib/rex/ui/interactive.rb, line 295 def prompt_yesno(query) (prompt(query + " [y/N] ") =~ /^y/) ? true : false end
Restores the previously installed signal handler for suspend notifications.
# File lib/rex/ui/interactive.rb, line 269 def restore_suspend begin if (orig_suspend) Signal.trap("TSTP", orig_suspend) else Signal.trap("TSTP", "DEFAULT") end self.orig_suspend = nil rescue end end
Generated with the Darkfish Rdoc Generator 2.