def test__copy_to_each(self): """Test the normal data case on both master_fd and stdin.""" read_from_stdout_fd, mock_stdout_fd = self._pipe() pty.STDOUT_FILENO = mock_stdout_fd mock_stdin_fd, write_to_stdin_fd = self._pipe() pty.STDIN_FILENO = mock_stdin_fd socketpair = self._socketpair() masters = [s.fileno() for s in socketpair] # Feed data. Smaller than PIPEBUF. These writes will not block. os.write(masters[1], b'from master') os.write(write_to_stdin_fd, b'from stdin') # Expect two select calls, the last one will cause IndexError pty.select = self._mock_select self.select_rfds_lengths.append(2) self.select_rfds_results.append([mock_stdin_fd, masters[0]]) self.select_rfds_lengths.append(2) with self.assertRaises(IndexError): pty._copy(masters[0]) # Test that the right data went to the right places. rfds = select.select([read_from_stdout_fd, masters[1]], [], [], 0)[0] self.assertEqual([read_from_stdout_fd, masters[1]], rfds) self.assertEqual(os.read(read_from_stdout_fd, 20), b'from master') self.assertEqual(os.read(masters[1], 20), b'from stdin')
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 test__copy_to_each(self): """Test the normal data case on both master_fd and stdin.""" read_from_stdout_fd, mock_stdout_fd = self._pipe() pty.STDOUT_FILENO = mock_stdout_fd mock_stdin_fd, write_to_stdin_fd = self._pipe() pty.STDIN_FILENO = mock_stdin_fd socketpair = self._socketpair() masters = [s.fileno() for s in socketpair] # Feed data. Smaller than PIPEBUF. These writes will not block. os.write(masters[1], b"from master") os.write(write_to_stdin_fd, b"from stdin") # Expect two select calls, the last one will cause IndexError pty.select = self._mock_select self.select_rfds_lengths.append(2) self.select_rfds_results.append([mock_stdin_fd, masters[0]]) self.select_rfds_lengths.append(2) with self.assertRaises(IndexError): pty._copy(masters[0]) # Test that the right data went to the right places. rfds = select.select([read_from_stdout_fd, masters[1]], [], [], 0)[0] self.assertEqual([read_from_stdout_fd, masters[1]], rfds) self.assertEqual(os.read(read_from_stdout_fd, 20), b"from master") self.assertEqual(os.read(masters[1], 20), b"from stdin")
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 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 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(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 test__copy_eof_on_all(self): """Test the empty read EOF case on both master_fd and stdin.""" read_from_stdout_fd, mock_stdout_fd = self._pipe() pty.STDOUT_FILENO = mock_stdout_fd mock_stdin_fd, write_to_stdin_fd = self._pipe() pty.STDIN_FILENO = mock_stdin_fd socketpair = socket.socketpair() for s in socketpair: self.addCleanup(s.close) masters = [s.fileno() for s in socketpair] os.close(masters[1]) socketpair[1].close() os.close(write_to_stdin_fd) # Expect two select calls, the last one will cause IndexError pty.select = self._mock_select self.select_rfds_lengths.append(2) self.select_rfds_results.append([mock_stdin_fd, masters[0]]) # We expect that both fds were removed from the fds list as they # both encountered an EOF before the second select call. self.select_rfds_lengths.append(0) with self.assertRaises(IndexError): pty._copy(masters[0])
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 interactive(self): print('Switching to interactive mode') mode = tty.tcgetattr(sys.stdin) tty.setraw(sys.stdin) try: pty._copy(self.child_fd, pty._read, pty._read) except Exception as e: print(e)
def communicate(self): import tty import pty try: mode = tty.tcgetattr(pty.STDIN_FILENO) tty.setraw(pty.STDIN_FILENO) restore = True except tty.error: restore = False try: pty._copy(self.master_fd) finally: if restore: tty.tcsetattr(pty.STDIN_FILENO, tty.TCSAFLUSH, mode) os.close(self.master_fd)
def test__copy_eof_on_all(self): """Test the empty read EOF case on both master_fd and stdin.""" read_from_stdout_fd, mock_stdout_fd = self._pipe() pty.STDOUT_FILENO = mock_stdout_fd mock_stdin_fd, write_to_stdin_fd = self._pipe() pty.STDIN_FILENO = mock_stdin_fd socketpair = self._socketpair() masters = [s.fileno() for s in socketpair] socketpair[1].close() os.close(write_to_stdin_fd) pty.select = self._mock_select self.select_rfds_lengths.append(2) self.select_rfds_results.append([mock_stdin_fd, masters[0]]) self.select_rfds_lengths.append(0) with self.assertRaises(IndexError): pty._copy(masters[0])
def communicate(self): import tty import pty try: mode = tty.tcgetattr(pty.STDIN_FILENO) setraw_but_sigint(pty.STDIN_FILENO) restore = True except tty.error: restore = False try: pty._copy(self.master_fd) except KeyboardInterrupt: print('^C\r') # we need the \r because we are still in raw mode finally: if restore: tty.tcsetattr(pty.STDIN_FILENO, tty.TCSAFLUSH, mode) os.close(self.master_fd)
def test__copy_to_each(self): """Test the normal data case on both master_fd and stdin.""" read_from_stdout_fd, mock_stdout_fd = self._pipe() pty.STDOUT_FILENO = mock_stdout_fd mock_stdin_fd, write_to_stdin_fd = self._pipe() pty.STDIN_FILENO = mock_stdin_fd socketpair = self._socketpair() masters = [s.fileno() for s in socketpair] os.write(masters[1], b'from master') os.write(write_to_stdin_fd, b'from stdin') pty.select = self._mock_select self.select_rfds_lengths.append(2) self.select_rfds_results.append([mock_stdin_fd, masters[0]]) self.select_rfds_lengths.append(2) with self.assertRaises(IndexError): pty._copy(masters[0]) rfds = select.select([read_from_stdout_fd, masters[1]], [], [], 0)[0] self.assertEqual([read_from_stdout_fd, masters[1]], rfds) self.assertEqual(os.read(read_from_stdout_fd, 20), b'from master') self.assertEqual(os.read(masters[1], 20), b'from stdin')
def main(path): s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) s.connect(path) master, slave = os.openpty() fds = [slave] s.sendmsg( [b'\x00'], [(socket.SOL_SOCKET, socket.SCM_RIGHTS, array.array("i", fds))]) os.close(slave) s.close() def setwinsz(): win = array.array('h', [0, 0, 0, 0]) fcntl.ioctl(STDOUT_FILENO, termios.TIOCGWINSZ, win) fcntl.ioctl(master, termios.TIOCSWINSZ, win) setwinsz() try: mode = tty.tcgetattr(STDIN_FILENO) tty.setraw(STDIN_FILENO) restore = 1 except tty.error: restore = 0 def sigwinch(signum, frame): setwinsz() signal.signal(signal.SIGWINCH, sigwinch) try: pty._copy(master) except (IOError, OSError): if restore: tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode) os.close(master)
def spawn(argv, master_read=_read, stdin_read=_read, initialize=None): """Create a spawned process.""" if isinstance(argv, str): argv = (argv, ) pid, master_fd = fork() 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 try: if initialize is not None: initialize(master_fd) _copy(master_fd, master_read, stdin_read) except OSError: if restore: tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode) os.close(master_fd) return os.waitpid(pid, 0)[1]
def _spawn(self, argv): import pty import tty self.argv = (argv, ) if type(argv) == type('') else argv self.pid, self.master_fd = pty.fork() if self.pid == CHILD: os.execlp(self.argv[0], *self.argv) # Never return 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: pty._copy(self.master_fd, self.master_read, self.stdin_read) except OSError: if restore: tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode) os.close(self.master_fd) return os.waitpid(self.pid, 0)[1]
def test__copy_eof_on_all(self): """Test the empty read EOF case on both master_fd and stdin.""" read_from_stdout_fd, mock_stdout_fd = self._pipe() pty.STDOUT_FILENO = mock_stdout_fd mock_stdin_fd, write_to_stdin_fd = self._pipe() pty.STDIN_FILENO = mock_stdin_fd socketpair = self._socketpair() masters = [s.fileno() for s in socketpair] socketpair[1].close() os.close(write_to_stdin_fd) pty.select = self._mock_select self.select_rfds_lengths.append(2) self.select_rfds_results.append([mock_stdin_fd, masters[0]]) # We expect that both fds were removed from the fds list as they # both encountered an EOF before the second select call. self.select_rfds_lengths.append(0) # We expect the function to return without error. self.assertEqual(pty._copy(masters[0]), None)
master, slave, os.ttyname(slave) pid = os.fork() if pid > 0: # parent os.close(slave) try: mode = tty.tcgetattr(STDIN_FILENO) tty.setraw(STDIN_FILENO) restore = 1 except tty.error: restore = 0 try: pty._copy(master) except (IOError, OSError): if restore: tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode) os.close(master) else: # child os.close(master) try: fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY) except OSError: pass else: try:
# # Revision 1.3 2001/06/14 20:56:14 mjk # More IA64 changes # import sys import pty import os # # this code is a slimmed down version of the 'spawn' function in # 'pty.py' found in the python distribution. # # this file has the the termio functions removed (e.g., tcgetattr) # because they fail when we use them with csp. # pid, master_fd = pty.fork() if pid == 0: # # child process # apply(os.execle, (sys.argv[1], ) + tuple(sys.argv[1:]) + (os.environ, )) else: # # parent # try: pty._copy(master_fd) except: pass
# # Revision 1.3 2001/06/14 20:56:14 mjk # More IA64 changes # import sys import pty import os # # this code is a slimmed down version of the 'spawn' function in # 'pty.py' found in the python distribution. # # this file has the the termio functions removed (e.g., tcgetattr) # because they fail when we use them with csp. # pid, master_fd = pty.fork() if pid == 0: # # child process # apply(os.execle, (sys.argv[1],) + tuple(sys.argv[1:]) + (os.environ,)) else: # # parent # try: pty._copy(master_fd) except: pass