def spawn(argv, master_read=pty._read, stdin_read=pty._read, handle_window_size=False): # copied from pty.py, with modifications # note that it references a few private functions - would be nice to not # do that, but you know if type(argv) == type(''): argv = (argv,) pid, master_fd, slave_name = fork(handle_window_size) if pid == CHILD: os.execlp(argv[0], *argv) try: mode = tty.tcgetattr(STDIN_FILENO) tty.setraw(STDIN_FILENO) restore = 1 except tty.error: # This is the same as termios.error restore = 0 if handle_window_size: signal.signal( signal.SIGWINCH, lambda signum, frame: _winch(slave_name, pid) ) while True: try: pty._copy(master_fd, master_read, stdin_read) except OSError as e: if e.errno == errno.EINTR: continue if restore: tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode) break os.close(master_fd) return os.waitpid(pid, 0)[1]
def _connectSSHLocal(self, hostname, username, passwd): sshcmd = [self.ssh_bin, '%s@%s' % (username, hostname)] if self.ssh_extraopt: sshcmd += self.ssh_extraopt.split() self.addStringToClipboard(passwd) pid, self.remote_fd = pty.fork() if pid == pty.CHILD: os.execlp(sshcmd[0], *sshcmd) try: mode = tty.tcgetattr(pty.STDIN_FILENO) tty.setraw(pty.STDIN_FILENO) restore = True except tty.error: restore = False signal.signal(signal.SIGWINCH, self._winchHandler) self._setRemoteTTYSize(self.remote_fd) self._setTerminalTitle('%s@%s' % (username, hostname)) try: self._copySSHData(self.remote_fd, passwd) except (IOError, OSError): pass except: if restore: tty.tcsetattr(pty.STDIN_FILENO, tty.TCSAFLUSH, mode) raise if restore: tty.tcsetattr(pty.STDIN_FILENO, tty.TCSAFLUSH, mode) signal.signal(signal.SIGWINCH, signal.SIG_DFL) os.close(self.remote_fd)
def ez_spawn(argv, master_read=_read, stdin_read=_read): """ To spawn the process. """ if type(argv) == str: argv = (argv, ) pid, master_fd = pty.fork() if pid == CHILD: # Fork worked, run the program os.execlp(argv[0], *argv) try: mode = tty.tcgetattr(STDIN_FILENO) tty.setraw(STDIN_FILENO) # disable line buffering # interrupt signals are no longer interpreted restore = 1 except tty.error: # Did not work, no need to restore. restore = 0 try: ez_copy(master_fd, "toto", master_read, stdin_read) except OSError: if restore: # Discard queued data and change mode to original tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode) os.close(master_fd) # wait for completion and return exit status return os.waitpid(pid, 0)[1]
def __init__(self): self.fd = sys.stdin.fileno() self.old_settings = termios.tcgetattr(self.fd) tty.setraw(self.fd) mode = tty.tcgetattr(self.fd) mode[tty.OFLAG] = mode[tty.OFLAG] | tty.OPOST tty.tcsetattr(self.fd, tty.TCSAFLUSH, mode)
def read_chr(): old_settings = tty.tcgetattr(sys.stdin.fileno()) tty.setraw(sys.stdin, tty.TCSANOW) chr = sys.stdin.read(1) tty.tcsetattr(sys.stdin.fileno(), tty.TCSADRAIN, old_settings) return chr
def fork(mode=None, winsz=None): """fork() -> (pid, master_fd) Fork and make the child a session leader with a controlling terminal.""" try: pid, master_fd = os.forkpty() except AttributeError: master_fd, slave_fd = openpty(mode, winsz) pid = os.fork() if pid == CHILD: os.close(master_fd) os.login_tty(slave_fd) else: os.close(slave_fd) else: # re-introduce the os.setsid() call here? # # os.forkpty() makes sure that the slave end of # the pty becomes the stdin of the child; this # is usually done via a dup2() call if pid == CHILD: if mode: tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode) if tty.HAVE_WINSZ and winsz: tty.tcsetwinsize(STDIN_FILENO, winsz) return pid, master_fd
def _detach(self): """Dettach the controlling terminal to aptdaemon.""" for wid in self._watchers: GLib.source_remove(wid) if self._old_tty_mode: tty.tcsetattr(pty.STDIN_FILENO, tty.TCSAFLUSH, self._old_tty_mode)
def enter(self): if self.in_raw_mode: return fd = sys.stdin.fileno() try: old = tty.tcgetattr(fd) new = old[:] self.saved_mode = old except: log.msg('not a typewriter!') self.saved_mode = None return # iflage new[0] = new[0] | tty.IGNPAR new[0] = new[0] & ~(tty.ISTRIP | tty.INLCR | tty.IGNCR | tty.ICRNL | tty.IXON | tty.IXANY | tty.IXOFF) if hasattr(tty, 'IUCLC'): new[0] = new[0] & ~tty.IUCLC # lflag new[3] = new[3] & ~(tty.ISIG | tty.ICANON | tty.ECHO | tty.ECHO | tty.ECHOE | tty.ECHOK | tty.ECHONL) if hasattr(tty, 'IEXTEN'): new[3] = new[3] & ~tty.IEXTEN #oflag new[1] = new[1] & ~tty.OPOST new[6][tty.VMIN] = 1 new[6][tty.VTIME] = 0 tty.tcsetattr(fd, tty.TCSANOW, new) self.in_raw_mode = True
def _pty_setup(slave_echo): """Opens a pty pair. If current stdin is a tty, then applies current stdin's termios and winsize to the slave, sets current stdin to raw mode. Returns (master, slave, original stdin mode/None, stdin winsize/None).""" mode = None winsz = None try: mode = tty.tcgetattr(STDIN_FILENO) except tty.error: master_fd, slave_fd = openpty() _mode = tty.tcgetattr(slave_fd) tty.mode_echo(_mode, slave_echo) tty.tcsetattr(slave_fd, tty.TCSAFLUSH, _mode) else: if tty.HAVE_WINSZ: winsz = tty.getwinsize(STDIN_FILENO) _mode = list(mode) tty.mode_echo(_mode, slave_echo) master_fd, slave_fd = openpty(_mode, winsz) tty.mode_raw(_mode) tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, _mode) return master_fd, slave_fd, mode, winsz
def enter(self): if self.in_raw_mode: return fd = sys.stdin.fileno() try: old = tty.tcgetattr(fd) new = old[:] self.saved_mode = old except: log.msg('not a typewriter!') self.saved_mode = None return # iflage new[0] = new[0] | tty.IGNPAR new[0] = new[0] & ~(tty.ISTRIP|tty.INLCR|tty.IGNCR|tty.ICRNL | tty.IXON | tty.IXANY | tty.IXOFF) if hasattr(tty, 'IUCLC'): new[0] = new[0] & ~tty.IUCLC # lflag new[3] = new[3] & ~(tty.ISIG | tty.ICANON | tty.ECHO | tty.ECHO | tty.ECHOE | tty.ECHOK | tty.ECHONL) if hasattr(tty, 'IEXTEN'): new[3] = new[3] & ~tty.IEXTEN #oflag new[1] = new[1] & ~tty.OPOST new[6][tty.VMIN] = 1 new[6][tty.VTIME] = 0 tty.tcsetattr(fd, tty.TCSANOW, new) self.in_raw_mode = True
def menu(self, title, names, top_info=(), cmds=None): attr = tty.tcgetattr(sys.stdin) try: self.cprint(TITLE, '==>', title) items = {} for i in top_info: self.cprint(b'34', ' ', i) for c, (n, t) in letterify(names): print(' ', c, t) items[c] = n if cmds: mlen = max(len(mv) + len(k) for k, mv, name in cmds) + 1 for k, mv, name in cmds: print(' :{0:{1}} {2}'.format(k + ' ' + mv, mlen, name)) tty.setcbreak(sys.stdin) ch = sys.stdin.read(1) if ch == ':': tty.tcsetattr(sys.stdin, tty.TCSADRAIN, attr) cmd = input(':') parts = cmd.strip().split(None, 1) if not parts: return None raise CommandExecute(*parts) elif ch in items: return items[ch] finally: tty.tcsetattr(sys.stdin, tty.TCSADRAIN, attr)
def menu(self, title, names, top_info=(), cmds=None): attr = tty.tcgetattr(sys.stdin) try: self.cprint(TITLE, "==>", title) items = {} for i in top_info: self.cprint(b"34", " ", i) for c, (n, t) in letterify(names): print(" ", c, t) items[c] = n if cmds: mlen = max(len(mv) + len(k) for k, mv, name in cmds) + 1 for k, mv, name in cmds: print(" :{0:{1}} {2}".format(k + " " + mv, mlen, name)) tty.setcbreak(sys.stdin) ch = sys.stdin.read(1) if ch == ":": tty.tcsetattr(sys.stdin, tty.TCSADRAIN, attr) cmd = input(":") parts = cmd.strip().split(None, 1) if not parts: return None raise CommandExecute(*parts) elif ch in items: return items[ch] finally: tty.tcsetattr(sys.stdin, tty.TCSADRAIN, attr)
def pty_attached(cmd: str = "/bin/sh") -> int: """ Run a command in a pseudo terminal, while being attached to this terminal. """ exec_bin = "/bin/sh" exec_args = [exec_bin, "-c", cmd] master_read = pty._read stdin_read = pty._read pid, master_fd = pty.fork() if pid == pty.CHILD: log.d(f"os.execv({exec_bin}, {exec_args})") os.execv(exec_bin, exec_args) tty_mode = None try: tty_mode = tty.tcgetattr(pty.STDIN_FILENO) tty.setraw(pty.STDIN_FILENO) except tty.error: pass try: pty._copy(master_fd, master_read, stdin_read) except OSError: pass finally: if tty_mode: tty.tcsetattr(pty.STDIN_FILENO, tty.TCSAFLUSH, tty_mode) os.close(master_fd) (pid, retcode) = os.waitpid(pid, 0) return retcode
def _spawn(self): '''Create a spawned process. Based on pty.spawn() from standard library. ''' assert self.master_fd is None pid, self.master_fd = pty.fork() if pid == pty.CHILD: os.execlp(self.command[0], *self.command) old_handler = signal.signal(signal.SIGWINCH, self._signal_winch) try: mode = tty.tcgetattr(pty.STDIN_FILENO) tty.setraw(pty.STDIN_FILENO) restore = 1 except tty.error: # This is the same as termios.error restore = 0 self._set_pty_size() try: self._copy() except (IOError, OSError): if restore: tty.tcsetattr(pty.STDIN_FILENO, tty.TCSAFLUSH, mode) os.close(self.master_fd) self.master_fd = None signal.signal(signal.SIGWINCH, old_handler) return True
def __init__(self, filename): SerialIO.__init__(self, filename) self.fd = os.open(filename, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK) tty.setraw(self.fd) attr = tty.tcgetattr(self.fd) attr[tty.ISPEED] = attr[tty.OSPEED] = tty.B57600 tty.tcsetattr(self.fd, tty.TCSAFLUSH, attr)
def spawn(argv, master_read=_read, stdin_read=_read, timeout=None, env=None): """Create a spawned process.""" if env is None: env = os.environ if isinstance(argv, str): argv = (argv, ) pid, master_fd = fork() if pid == CHILD: os.execvpe(argv[0], argv, env) if timeout is not None: timer = threading.Timer(timeout, _kill, args=(pid, signal.SIGKILL, master_fd)) timer.start() try: mode = tty.tcgetattr(STDIN_FILENO) tty.setraw(STDIN_FILENO) restore = 1 except tty.error: # This is the same as termios.error restore = 0 try: _copy(pid, master_fd, master_read, stdin_read) # print('copied!') except OSError: if restore: tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode) os.close(master_fd) if timeout is not None: timer.cancel() return os.waitpid(pid, 0)[1]
def spawn(argv, master_read=pty._read, stdin_read=pty._read, handle_window_size=False): # copied from pty.py, with modifications # note that it references a few private functions - would be nice to not # do that, but you know if type(argv) == type(''): argv = (argv, ) pid, master_fd, slave_name = fork(handle_window_size) if pid == CHILD: os.execlp(argv[0], *argv) try: mode = tty.tcgetattr(STDIN_FILENO) tty.setraw(STDIN_FILENO) restore = 1 except tty.error: # This is the same as termios.error restore = 0 if handle_window_size: signal.signal(signal.SIGWINCH, lambda signum, frame: _winch(slave_name, pid)) while True: try: pty._copy(master_fd, master_read, stdin_read) except OSError as e: if e.errno == errno.EINTR: continue if restore: tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode) break os.close(master_fd) return os.waitpid(pid, 0)[1]
def _enterRawMode(): global _inRawMode, _savedRawMode if _inRawMode: return fd = sys.stdin.fileno() try: old = tty.tcgetattr(fd) new = old[:] except: log.msg('not a typewriter!') else: # iflage new[0] = new[0] | tty.IGNPAR new[0] = new[0] & ~(tty.ISTRIP | tty.INLCR | tty.IGNCR | tty.ICRNL | tty.IXON | tty.IXANY | tty.IXOFF) if hasattr(tty, 'IUCLC'): new[0] = new[0] & ~tty.IUCLC # lflag new[3] = new[3] & ~(tty.ISIG | tty.ICANON | tty.ECHO | tty.ECHO | tty.ECHOE | tty.ECHOK | tty.ECHONL) if hasattr(tty, 'IEXTEN'): new[3] = new[3] & ~tty.IEXTEN #oflag new[1] = new[1] & ~tty.OPOST new[6][tty.VMIN] = 1 new[6][tty.VTIME] = 0 _savedRawMode = old tty.tcsetattr(fd, tty.TCSANOW, new) #tty.setraw(fd) _inRawMode = 1
def spawn(argv, master_read=_read, stdin_read=_read): """Create a spawned process.""" if type(argv) == type(''): argv = (argv, ) sys.audit('pty.spawn', argv) pid, master_fd = fork() if pid == CHILD: os.execlp(argv[0], *argv) try: mode = tcgetattr(STDIN_FILENO) setraw(STDIN_FILENO) restore = True except tty.error: # This is the same as termios.error restore = False try: _copy(master_fd, master_read, stdin_read) finally: if restore: tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode) close(master_fd) return waitpid(pid, 0)[1]
def spawn(argv, master_read=_read, stdin_read=_read): """Create a spawned process.""" if type(argv) == type(''): argv = (argv, ) pid, master_fd = fork() if pid == CHILD: try: os.execlp(argv[0], *argv) except: # If we wanted to be really clever, we would use # the same method as subprocess() to pass the error # back to the parent. For now just dump stack trace. traceback.print_exc() finally: os._exit(1) try: mode = tty.tcgetattr(STDIN_FILENO) tty.setraw(STDIN_FILENO) restore = 1 except tty.error: # This is the same as termios.error restore = 0 try: _copy(master_fd, master_read, stdin_read) except OSError: # Some OSes never return an EOF on pty, just raise # an error instead. pass finally: if restore: tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode) os.close(master_fd) return os.waitpid(pid, 0)[1]
def _spawn(shell, master_read): """Create a spawned process. Modified version of pty.spawn with terminal size support. """ pid, master_fd = pty.fork() if pid == pty.CHILD: os.execlp(shell, shell) try: mode = tty.tcgetattr(pty.STDIN_FILENO) tty.setraw(pty.STDIN_FILENO) restore = True except tty.error: # This is the same as termios.error restore = False _set_pty_size(master_fd) signal.signal(signal.SIGWINCH, lambda *_: _set_pty_size(master_fd)) try: pty._copy(master_fd, master_read, pty._read) except OSError: if restore: tty.tcsetattr(pty.STDIN_FILENO, tty.TCSAFLUSH, mode) os.close(master_fd) return os.waitpid(pid, 0)[1]
def spawn(argv, master_read=pty_read, stdin_read=pty_read): """Create a spawned process. Based on pty.spawn code.""" # TODO(larsbutler): This type check won't work with python3 # See http://packages.python.org/six/#six.string_types # for a possible solution. if isinstance(argv, (basestring)): argv = (argv, ) pid, master_fd = pty.fork() if pid == pty.CHILD: os.execlp(argv[0], *argv) try: mode = tty.tcgetattr(pty.STDIN_FILENO) tty.setraw(pty.STDIN_FILENO) restore = 1 except tty.error: # This is the same as termios.error restore = 0 # get pseudo-terminal window size buf = array.array('h', [0, 0, 0, 0]) fcntl.ioctl(pty.STDOUT_FILENO, termios.TIOCGWINSZ, buf, True) # pass window size settings to forked one fcntl.ioctl(master_fd, termios.TIOCSWINSZ, buf) try: pty_copy(master_fd, master_read, stdin_read) except (IOError, OSError): if restore: tty.tcsetattr(pty.STDIN_FILENO, tty.TCSAFLUSH, mode) os.close(master_fd)
def setup_tty_for_pty(func): """ Sets up tty for raw mode while retaining original tty settings and then starts the reactor to connect to the pty. Upon exiting pty, restores original tty settings. :param func: The callable to run after the tty is ready, such as ``reactor.run`` """ # Preserve original tty settings stdin_fileno = sys.stdin.fileno() old_ttyattr = tty.tcgetattr(stdin_fileno) try: # Enter raw mode on the local tty. tty.setraw(stdin_fileno) raw_ta = tty.tcgetattr(stdin_fileno) raw_ta[tty.LFLAG] |= tty.ISIG raw_ta[tty.OFLAG] |= tty.OPOST | tty.ONLCR # Pass ^C through so we can abort traceroute, etc. raw_ta[tty.CC][tty.VINTR] = '\x18' # ^X is the new ^C # Ctrl-Z is used by a lot of vendors to exit config mode raw_ta[tty.CC][tty.VSUSP] = 0 # disable ^Z tty.tcsetattr(stdin_fileno, tty.TCSANOW, raw_ta) # Execute our callable here func() finally: # Restore original tty settings tty.tcsetattr(stdin_fileno, tty.TCSANOW, old_ttyattr)
def _copy(master_fd, master_read=_read, stdin_read=_read, stdin_fd=STDIN_FILENO, stdout_fd=STDOUT_FILENO): """Parent copy loop. Copies pty master -> stdout_fd (master_read) stdin_fd -> pty master (stdin_read)""" try: mode = tty.tcgetattr(stdin_fd) tty.setraw(stdin_fd) restore = 1 except tty.error: # This is the same as termios.error restore = 0 try: while 1: rfds, wfds, xfds = select([master_fd, stdin_fd], [], []) if master_fd in rfds: data = master_read(master_fd) os.write(stdout_fd, data) if stdin_fd in rfds: data = stdin_read(stdin_fd) _writen(master_fd, data) except (IOError, OSError, error): # The last entry is select.error if restore: tty.tcsetattr(stdin_fd, tty.TCSAFLUSH, mode) if stdin_fd > STDERR_FILENO: os.close(stdin_fd) if stdout_fd > STDERR_FILENO: os.close(stdout_fd)
def _leaveRawMode(): global _inRawMode if not _inRawMode: return fd = sys.stdin.fileno() tty.tcsetattr(fd, tty.TCSANOW, _savedRawMode) _inRawMode = 0
def pty_spawn(argv): """Version of pty.spawn() for PY2, that returns the exit code. This works around https://bugs.python.org/issue2489. """ logger.info("Using builtin pty.spawn()") import pty import tty if isinstance(argv, bytes): argv = (argv, ) pid, master_fd = pty.fork() if pid == pty.CHILD: os.execlp(argv[0], *argv) try: mode = tty.tcgetattr(pty.STDIN_FILENO) tty.setraw(pty.STDIN_FILENO) restore = 1 except tty.error: # This is the same as termios.error restore = 0 try: pty._copy(master_fd, pty._read, pty._read) except (IOError, OSError): if restore: tty.tcsetattr(pty.STDIN_FILENO, tty.TCSAFLUSH, mode) os.close(master_fd) return os.waitpid(pid, 0)[1]
def spawn(argv, master_read=pty_read, stdin_read=pty_read): """Create a spawned process. Based on pty.spawn code.""" # TODO(larsbutler): This type check won't work with python3 # See http://packages.python.org/six/#six.string_types # for a possible solution. if isinstance(argv, (basestring)): argv = (argv,) pid, master_fd = pty.fork() if pid == pty.CHILD: os.execlp(argv[0], *argv) try: mode = tty.tcgetattr(pty.STDIN_FILENO) tty.setraw(pty.STDIN_FILENO) restore = 1 except tty.error: # This is the same as termios.error restore = 0 # get pseudo-terminal window size buf = array.array('h', [0, 0, 0, 0]) fcntl.ioctl(pty.STDOUT_FILENO, termios.TIOCGWINSZ, buf, True) # pass window size settings to forked one fcntl.ioctl(master_fd, termios.TIOCSWINSZ, buf) try: pty_copy(master_fd, master_read, stdin_read) except (IOError, OSError): if restore: tty.tcsetattr(pty.STDIN_FILENO, tty.TCSAFLUSH, mode) os.close(master_fd)
def setup(self): if tty: self.tcattr = tty.tcgetattr(sys.stdin.fileno()) tcattr = tty.tcgetattr(sys.stdin.fileno()) tcattr[0] = tcattr[0] & ~(tty.IXON) tty.tcsetattr(sys.stdin.fileno(), tty.TCSANOW, tcattr) self.w = curses.initscr() curses.cbreak() curses.noecho() try: curses.meta(1) except: pass self.cursor(0) signal.signal(signal.SIGCHLD, signal.SIG_IGN) signal.signal(signal.SIGHUP, self.handler_quit) signal.signal(signal.SIGINT, self.handler_quit) signal.signal(signal.SIGTERM, self.handler_quit) signal.signal(signal.SIGWINCH, self.handler_resize) self.win_root = RootWindow(None) self.win_root.update() self.win_status = self.win_root.win_status self.status = self.win_status.status self.win_podlist = self.win_root.win_tab.win_podlist self.timeout = Timeout()
def setModes(self): pty = self.pty attr = tty.tcgetattr(pty.fileno()) for mode, modeValue in self.modes: if mode not in ttymodes.TTYMODES: continue ttyMode = ttymodes.TTYMODES[mode] if len(ttyMode) == 2: # Flag. flag, ttyAttr = ttyMode if not hasattr(tty, ttyAttr): continue ttyval = getattr(tty, ttyAttr) if modeValue: attr[flag] = attr[flag] | ttyval else: attr[flag] = attr[flag] & ~ttyval elif ttyMode == "OSPEED": attr[tty.OSPEED] = getattr(tty, "B%s" % (modeValue, )) elif ttyMode == "ISPEED": attr[tty.ISPEED] = getattr(tty, "B%s" % (modeValue, )) else: if not hasattr(tty, ttyMode): continue ttyval = getattr(tty, ttyMode) attr[tty.CC][ttyval] = bytes((modeValue, )) tty.tcsetattr(pty.fileno(), tty.TCSANOW, attr)
def spawn(self, argv=None): ''' Create a spawned process. Based on the code for pty.spawn(). ''' assert self.master_fd is None if not argv: argv = [os.environ['SHELL']] pid, master_fd = pty.fork() self.master_fd = master_fd if pid == pty.CHILD: os.execlp(argv[0], *argv) old_handler = signal.signal(signal.SIGWINCH, self._signal_winch) try: mode = tty.tcgetattr(pty.STDIN_FILENO) tty.setraw(pty.STDIN_FILENO) restore = 1 except tty.error: # This is the same as termios.error restore = 0 self._init_fd() try: self._copy() except (IOError, OSError): if restore: tty.tcsetattr(pty.STDIN_FILENO, tty.TCSAFLUSH, mode) os.close(master_fd) self.master_fd = None signal.signal(signal.SIGWINCH, old_handler) self._set_pty_size()
def _copy(master_fd, master_read=_read, stdin_read=_read, stdin_fd=STDIN_FILENO, stdout_fd=STDOUT_FILENO): """Parent copy loop. Copies pty master -> stdout_fd (master_read) stdin_fd -> pty master (stdin_read)""" try: mode = tty.tcgetattr(stdin_fd) tty.setraw(stdin_fd) restore = 1 except tty.error: # This is the same as termios.error restore = 0 try: while 1: rfds, wfds, xfds = select( [master_fd, stdin_fd], [], []) if master_fd in rfds: data = master_read(master_fd) os.write(stdout_fd, data) if stdin_fd in rfds: data = stdin_read(stdin_fd) _writen(master_fd, data) except (IOError, OSError, error): # The last entry is select.error if restore: tty.tcsetattr(stdin_fd, tty.TCSAFLUSH, mode) if stdin_fd > STDERR_FILENO: os.close(stdin_fd) if stdout_fd > STDERR_FILENO: os.close(stdout_fd)
def run(self): pid, self.master_fd = pty.fork() if pid == pty.CHILD: os.execlp(self.argv[0], *self.argv) old_handler = signal.signal(signal.SIGWINCH, lambda signum, frame: self._set_pty_size()) mode = tty.tcgetattr(pty.STDIN_FILENO) tty.setraw(pty.STDIN_FILENO) self._set_pty_size() try: self._process() except Exception: pass tty.tcsetattr(pty.STDIN_FILENO, tty.TCSAFLUSH, mode) os.close(self.master_fd) self.master_fd = None signal.signal(signal.SIGWINCH, old_handler) if self.server_address: # Make sure the socket does not already exist try: os.unlink(self.server_address) except OSError: pass
def pty_spawn(argv): """Version of pty.spawn() for PY2, that returns the exit code. This works around https://bugs.python.org/issue2489. """ logger.info("Using builtin pty.spawn()") import pty import tty if isinstance(argv, bytes): argv = (argv,) pid, master_fd = pty.fork() if pid == pty.CHILD: os.execlp(argv[0], *argv) try: mode = tty.tcgetattr(pty.STDIN_FILENO) tty.setraw(pty.STDIN_FILENO) restore = 1 except tty.error: # This is the same as termios.error restore = 0 try: pty._copy(master_fd, pty._read, pty._read) except (IOError, OSError): if restore: tty.tcsetattr(pty.STDIN_FILENO, tty.TCSAFLUSH, mode) os.close(master_fd) return os.waitpid(pid, 0)[1]
def run(self): """Run the proxy, the entry point.""" old_handler = signal.signal(signal.SIGWINCH, lambda signum, frame: self._set_pty_size()) mode = tty.tcgetattr(pty.STDIN_FILENO) tty.setraw(pty.STDIN_FILENO) self._set_pty_size() try: self._process() except OSError as os_err: self.logger.exception("Exception") # Avoid printing I/O Error that happens on every GDB quit if os_err.errno != errno.EIO: raise except Exception: self.logger.exception("Exception") raise finally: tty.tcsetattr(pty.STDIN_FILENO, tty.TCSAFLUSH, mode) os.close(self.master_fd) self.master_fd = None signal.signal(signal.SIGWINCH, old_handler) if self.server_address: # Make sure the socket does not already exist try: os.unlink(self.server_address) except OSError: pass
def spawn(self, argv=None): ''' Create a spawned process. Based on the code for pty.spawn(). ''' assert self.master_fd is None if not argv: argv = [os.environ['SHELL']] pid, master_fd = pty.fork() self.master_fd = master_fd if pid == pty.CHILD: os.execlp(argv[0], *argv) old_handler = signal.signal(signal.SIGWINCH, self._signal_winch) try: mode = tty.tcgetattr(pty.STDIN_FILENO) tty.setraw(pty.STDIN_FILENO) restore = 1 except tty.error: # This is the same as termios.error restore = 0 self._init_fd() try: self._copy() except (IOError, OSError): if restore: tty.tcsetattr(pty.STDIN_FILENO, tty.TCSAFLUSH, mode) os.close(master_fd) self.master_fd = None signal.signal(signal.SIGWINCH, old_handler)
def setModes(self): pty = self.pty attr = tty.tcgetattr(pty.fileno()) for mode, modeValue in self.modes: if mode not in ttymodes.TTYMODES: continue ttyMode = ttymodes.TTYMODES[mode] if len(ttyMode) == 2: # Flag. flag, ttyAttr = ttyMode if not hasattr(tty, ttyAttr): continue ttyval = getattr(tty, ttyAttr) if modeValue: attr[flag] = attr[flag] | ttyval else: attr[flag] = attr[flag] & ~ttyval elif ttyMode == 'OSPEED': attr[tty.OSPEED] = getattr(tty, 'B%s' % (modeValue,)) elif ttyMode == 'ISPEED': attr[tty.ISPEED] = getattr(tty, 'B%s' % (modeValue,)) else: if not hasattr(tty, ttyMode): continue ttyval = getattr(tty, ttyMode) attr[tty.CC][ttyval] = chr(modeValue) tty.tcsetattr(pty.fileno(), tty.TCSANOW, attr)
def spawn(argv, master_read=_read, stdin_read=_read): """Create a spawned process.""" if type(argv) == type(''): argv = (argv,) pid, master_fd = fork() if pid == CHILD: try: os.execlp(argv[0], *argv) except: # If we wanted to be really clever, we would use # the same method as subprocess() to pass the error # back to the parent. For now just dump stack trace. traceback.print_exc() finally: os._exit(1) try: mode = tty.tcgetattr(STDIN_FILENO) tty.setraw(STDIN_FILENO) restore = 1 except tty.error: # This is the same as termios.error restore = 0 try: _copy(master_fd, master_read, stdin_read) except OSError: # Some OSes never return an EOF on pty, just raise # an error instead. pass finally: if restore: tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode) os.close(master_fd) return os.waitpid(pid, 0)[1]
def interact(fd, stderr=None): """Interact with pty""" ## window size change handler debug("started") def change_winsz(signum, frame): winsz_arg = struct.pack("HHHH", 0, 0, 0, 0) fcntl.ioctl(fd, termios.TIOCSWINSZ, fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ, winsz_arg)) old_handler = signal.signal(signal.SIGWINCH, change_winsz) try: mode = termios.tcgetattr(sys.stdin) tty.setraw(sys.stdin, termios.TCSANOW) restore = 1 except tty.error: restore = 0 debug("stdin: %s" % sys.stdin.fileno()) debug("child tty: %s" % fd) fds = [fd, sys.stdin.fileno()] if stderr: fds.append(stderr) debug("child stderr: %s" % stderr) debug("before loop") try: try: while True: if not fds: break try: rfds, wfds, xfds = select.select(fds, [], []) except select.error, se: if se[0] == errno.EINTR: continue # Interrupted system call else: raise se for i, o in [[fd, sys.stdout.fileno()], [stderr, sys.stderr.fileno()], [sys.stdin.fileno(), fd]]: if i in rfds: debug("about to read from %s" % i) data = os.read(i, 1024) if not data: # Reached EOF. fds.remove(i) debug('EOF %s' % i) else: debug('read from %s: %s' % (i, repr(data))) write(o, data) except (IOError, OSError), e: exc_type, exc_obj, exc_tb = sys.exc_info() debug("IOError/OSError %s: %s" % (traceback.format_exception_only(exc_type, exc_obj)[0], traceback.format_tb(exc_tb))) pass finally: debug("finished") if restore: tty.tcsetattr(sys.stdin, tty.TCSAFLUSH, mode) signal.signal(signal.SIGWINCH, old_handler) os.close(fd) if stderr: os.close(stderr)
def clean_shutdown(self,orig_tty_mode): DEBUG("clean_shutdown") sys.stdout.write("QUIT\n") # let sstream.py know we quit # everything received from sys.stdin before "FIN\n" has been sent before # sstream.py received QUIT - discard that self.ignore_until_fin() tty.tcsetattr(0, tty.TCSAFLUSH, orig_tty_mode) #STDIN sys.stderr.write("sstream-server stopped at "+time.strftime("%x %X %Z", time.localtime())+"\n" )
def interact(self, escape_character=chr(29), input_filter=None, output_filter=None): '''This gives control of the child process to the interactive user (the human at the keyboard). Keystrokes are sent to the child process, and the stdout and stderr output of the child process is printed. This simply echos the child stdout and child stderr to the real stdout and it echos the real stdin to the child stdin. When the user types the escape_character this method will return None. The escape_character will not be transmitted. The default for escape_character is entered as ``Ctrl - ]``, the very same as BSD telnet. To prevent escaping, escape_character may be set to None. If a logfile is specified, then the data sent and received from the child process in interact mode is duplicated to the given log. You may pass in optional input and output filter functions. These functions should take bytes array and return bytes array too. Even with ``encoding='utf-8'`` support, meth:`interact` will always pass input_filter and output_filter bytes. You may need to wrap your function to decode and encode back to UTF-8. The output_filter will be passed all the output from the child process. The input_filter will be passed all the keyboard input from the user. The input_filter is run BEFORE the check for the escape_character. Note that if you change the window size of the parent the SIGWINCH signal will not be passed through to the child. If you want the child window size to change when the parent's window size changes then do something like the following example:: import pipenv.vendor.pexpect as pexpect, struct, fcntl, termios, signal, sys def sigwinch_passthrough (sig, data): s = struct.pack("HHHH", 0, 0, 0, 0) a = struct.unpack('hhhh', fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ , s)) if not p.closed: p.setwinsize(a[0],a[1]) # Note this 'p' is global and used in sigwinch_passthrough. p = pexpect.spawn('/bin/bash') signal.signal(signal.SIGWINCH, sigwinch_passthrough) p.interact() ''' # Flush the buffer. self.write_to_stdout(self.buffer) self.stdout.flush() self._buffer = self.buffer_type() mode = tty.tcgetattr(self.STDIN_FILENO) tty.setraw(self.STDIN_FILENO) if escape_character is not None and PY3: escape_character = escape_character.encode('latin-1') try: self.__interact_copy(escape_character, input_filter, output_filter) finally: tty.tcsetattr(self.STDIN_FILENO, tty.TCSAFLUSH, mode)
def run(): global options, old args = sys.argv[1:] if "-l" in args: # CVS is an idiot i = args.index("-l") args = args[i:i + 2] + args del args[i + 2:i + 4] for arg in args[:]: try: i = args.index(arg) if arg[:2] == "-o" and args[i + 1][0] != "-": args[i:i + 2] = [] # Suck on it scp except ValueError: pass options = ClientOptions() try: options.parseOptions(args) except usage.UsageError as u: print(f"ERROR: {u}") options.opt_help() sys.exit(1) if options["log"]: if options["logfile"]: if options["logfile"] == "-": f = sys.stdout else: f = open(options["logfile"], "a+") else: f = sys.stderr realout = sys.stdout log.startLogging(f) sys.stdout = realout else: log.discardLogs() doConnect() fd = sys.stdin.fileno() try: old = tty.tcgetattr(fd) except BaseException: old = None try: oldUSR1 = signal.signal(signal.SIGUSR1, lambda *a: reactor.callLater(0, reConnect)) except BaseException: oldUSR1 = None try: reactor.run() finally: if old: tty.tcsetattr(fd, tty.TCSANOW, old) if oldUSR1: signal.signal(signal.SIGUSR1, oldUSR1) if (options["command"] and options["tty"]) or not options["notty"]: signal.signal(signal.SIGWINCH, signal.SIG_DFL) if sys.stdout.isatty() and not options["command"]: print("Connection to {} closed.".format(options["host"])) sys.exit(exitStatus)
def interact(self, escape_character=chr(29), input_filter=None, output_filter=None): '''This gives control of the child process to the interactive user (the human at the keyboard). Keystrokes are sent to the child process, and the stdout and stderr output of the child process is printed. This simply echos the child stdout and child stderr to the real stdout and it echos the real stdin to the child stdin. When the user types the escape_character this method will return None. The escape_character will not be transmitted. The default for escape_character is entered as ``Ctrl - ]``, the very same as BSD telnet. To prevent escaping, escape_character may be set to None. If a logfile is specified, then the data sent and received from the child process in interact mode is duplicated to the given log. You may pass in optional input and output filter functions. These functions should take bytes array and return bytes array too. Even with ``encoding='utf-8'`` support, meth:`interact` will always pass input_filter and output_filter bytes. You may need to wrap your function to decode and encode back to UTF-8. The output_filter will be passed all the output from the child process. The input_filter will be passed all the keyboard input from the user. The input_filter is run BEFORE the check for the escape_character. Note that if you change the window size of the parent the SIGWINCH signal will not be passed through to the child. If you want the child window size to change when the parent's window size changes then do something like the following example:: import pexpect, struct, fcntl, termios, signal, sys def sigwinch_passthrough (sig, data): s = struct.pack("HHHH", 0, 0, 0, 0) a = struct.unpack('hhhh', fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ , s)) if not p.closed: p.setwinsize(a[0],a[1]) # Note this 'p' is global and used in sigwinch_passthrough. p = pexpect.spawn('/bin/bash') signal.signal(signal.SIGWINCH, sigwinch_passthrough) p.interact() ''' # Flush the buffer. self.write_to_stdout(self.buffer) self.stdout.flush() self._buffer = self.buffer_type() mode = tty.tcgetattr(self.STDIN_FILENO) tty.setraw(self.STDIN_FILENO) if escape_character is not None and PY3: escape_character = escape_character.encode('latin-1') try: self.__interact_copy(escape_character, input_filter, output_filter) finally: tty.tcsetattr(self.STDIN_FILENO, tty.TCSAFLUSH, mode)
def run(): global options, old args = sys.argv[1:] if '-l' in args: # CVS is an idiot i = args.index('-l') args = args[i:i + 2] + args del args[i + 2:i + 4] for arg in args[:]: try: i = args.index(arg) if arg[:2] == '-o' and args[i + 1][0] != '-': args[i:i + 2] = [] # Suck on it scp except ValueError: pass options = ClientOptions() try: options.parseOptions(args) except usage.UsageError as u: print('ERROR: {}'.format(u)) options.opt_help() sys.exit(1) if options['log']: if options['logfile']: if options['logfile'] == '-': f = sys.stdout else: f = open(options['logfile'], 'a+') else: f = sys.stderr realout = sys.stdout log.startLogging(f) sys.stdout = realout else: log.discardLogs() doConnect() fd = sys.stdin.fileno() try: old = tty.tcgetattr(fd) except: old = None try: oldUSR1 = signal.signal(signal.SIGUSR1, lambda *a: reactor.callLater(0, reConnect)) except: oldUSR1 = None try: reactor.run() finally: if old: tty.tcsetattr(fd, tty.TCSANOW, old) if oldUSR1: signal.signal(signal.SIGUSR1, oldUSR1) if (options['command'] and options['tty']) or not options['notty']: signal.signal(signal.SIGWINCH, signal.SIG_DFL) if sys.stdout.isatty() and not options['command']: print('Connection to {} closed.'.format(options['host'])) sys.exit(exitStatus)
def run(): global options, old args = sys.argv[1:] if '-l' in args: # cvs is an idiot i = args.index('-l') args = args[i:i+2]+args del args[i+2:i+4] for arg in args[:]: try: i = args.index(arg) if arg[:2] == '-o' and args[i+1][0]!='-': args[i:i+2] = [] # suck on it scp except ValueError: pass options = ClientOptions() try: options.parseOptions(args) except usage.UsageError as u: print('ERROR: %s' % u) options.opt_help() sys.exit(1) if options['log']: if options['logfile']: if options['logfile'] == '-': f = sys.stdout else: f = file(options['logfile'], 'a+') else: f = sys.stderr realout = sys.stdout log.startLogging(f) sys.stdout = realout else: log.discardLogs() doConnect() fd = sys.stdin.fileno() try: old = tty.tcgetattr(fd) except: old = None try: oldUSR1 = signal.signal(signal.SIGUSR1, lambda *a: reactor.callLater(0, reConnect)) except: oldUSR1 = None try: reactor.run() finally: if old: tty.tcsetattr(fd, tty.TCSANOW, old) if oldUSR1: signal.signal(signal.SIGUSR1, oldUSR1) if (options['command'] and options['tty']) or not options['notty']: signal.signal(signal.SIGWINCH, signal.SIG_DFL) if sys.stdout.isatty() and not options['command']: print('Connection to %s closed.' % options['host']) sys.exit(exitStatus)
def mergePipeAndInteract(self, pipe): self.stdout.write (self.buffer) self.stdout.flush() self.buffer = '' mode = tty.tcgetattr(self.STDIN_FILENO) tty.setraw(self.STDIN_FILENO) try: self.__merge_copy(pipe) finally: tty.tcsetattr(self.STDIN_FILENO, tty.TCSAFLUSH, mode)
def __call__(self): tty, sys, select = self.mods fd = sys.stdin.fileno() old = tty.tcgetattr(fd) tty.setcbreak(fd, tty.TCSANOW) try: return sys.stdin.read(1) finally: tty.tcsetattr(fd, tty.TCSAFLUSH, old)
def __init__(self,infile): if not infile.isatty(): raise NotTTYException() self.file=infile #prepare for getch self.save_attr=tty.tcgetattr(self.file) newattr=self.save_attr[:] newattr[3] &= ~tty.ECHO & ~tty.ICANON tty.tcsetattr(self.file, tty.TCSANOW, newattr)
def open(self, command, env={}): """ Create subprocess using forkpty() """ # parse command command_arr = shlex.split(command) executable = command_arr[0] args = command_arr # try to fork a new pty try: self.pid, self.fd = pty.fork() except: return False # child proc, replace with command after altering terminal attributes if self.pid == 0: # Set signals to default values in child try: signal.signal(signal.SIGCHLD, signal.SIG_DFL) except: pass try: signal.signal(signal.SIGHUP, signal.SIG_DFL) except: pass # set requested environment variables for k in env.keys(): os.environ[k] = env[k] # set tty attributes try: attrs = tty.tcgetattr(1) attrs[0] = attrs[0] ^ tty.IGNBRK attrs[0] = attrs[0] | tty.BRKINT | tty.IXANY | tty.IMAXBEL attrs[2] = attrs[2] | tty.HUPCL attrs[3] = attrs[3] | tty.ICANON | tty.ECHO | tty.ISIG | tty.ECHOKE attrs[6][tty.VMIN] = 1 attrs[6][tty.VTIME] = 0 tty.tcsetattr(1, tty.TCSANOW, attrs) except: pass # replace this process with the subprocess os.execvp(executable, args) # else master, do nothing else: pass
def __init__(self, filename, speed=tty.B57600): try: self.filename = filename logger.info('opening %r' % filename) self.fd = os.open(filename, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK) tty.setraw(self.fd) attr = tty.tcgetattr(self.fd) attr[tty.ISPEED] = attr[tty.OSPEED] = speed tty.tcsetattr(self.fd, tty.TCSAFLUSH, attr) except termios.error: raise IOError
def spawn(argv, master_read=read, stdin_read=read): if type(argv) == type(''): argv = (argv,) pid, master_fd = fork() if pid == CHILD: apply(os.execlp, (argv[0],) + argv) mode = tty.tcgetattr(STDIN_FILENO) tty.setraw(STDIN_FILENO) try: copy(master_fd, master_read, stdin_read) except: tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode)
def listener_sig_handler(signum, frame): """ listener signal handler """ global g_listener_old_ttyattr global g_listener_win_changed if signum in [signal.SIGINT, signal.SIGTERM]: print '[II] listener terminated forcefully, restore terminal attributes' tty.tcsetattr(sys.stdin, tty.TCSAFLUSH, g_listener_old_ttyattr) os.abort() elif signum is signal.SIGWINCH: g_listener_win_changed = True