Exemple #1
0
    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')
Exemple #2
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]
Exemple #3
0
    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]
Exemple #7
0
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]
Exemple #8
0
    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])
Exemple #9
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
Exemple #10
0
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]
Exemple #11
0
    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])
Exemple #12
0
 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)
Exemple #13
0
 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])
Exemple #15
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')
Exemple #17
0
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)
Exemple #18
0
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]
Exemple #19
0
    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]
Exemple #20
0
    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)
Exemple #21
0
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:
Exemple #22
0
#
# 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