def run(self): """ Pass data between stdin -> channel, channel -> stdout Returns True if channel is still up, False if channel is broken. """ if term.has_resized(): term_size = term.get_size() self.__ichan.resize_pty(term_size[1], term_size[0]) try: ready = select.select([self.__ichan, sys.stdin], [], [], 0.2)[0] if self.__ichan in ready: from_chan = self.__ichan.recv(512) sys.stdout.write(from_chan) sys.stdout.flush() if sys.stdin in ready: # use raw read for nonblock. # see http://bugs.python.org/issue1175#msg56041 from_console = os.read(sys.stdin.fileno(), 512) # catch command escape if from_console == '\r': self.__prev_char = '\n' self.__ichan.send(from_console) elif from_console == '~': if self.__prev_char == '\n': self.__prev_char = '~' else: self.__prev_char = None self.__ichan.send(from_console) elif self.__prev_char == '~': self.__prev_char = None if from_console == '.': from reach import commands commands.execute_interactive() else: self.__ichan.send('~'+from_console) else: self.__prev_char = None self.__ichan.send(from_console) except select.error: # Occurs when signal is received while select (E.G. term resize). # This is ok. Just continue as if nothing appened. # We'll resume select on next run(). pass # Check if remote interactive channel has closed (shell exited). if self.__ichan.exit_status_ready(): return False return True
def get_interactive_chan(self): """ Returns an interactive (shell) channel. A new channel is established if none exists. """ if self.__ichan: return self.__ichan # else establish and create interactive channel term_size = term.get_size() self.__ichan = self.__chan.open_session() self.__ichan.get_pty(os.environ.get('TERM', 'vt100'), height=term_size[0], width=term_size[1]) self.__ichan.invoke_shell()