--- cpython/Lib/pty.py 2020-08-13 12:12:37.350048897 -0500 +++ pty.py 2020-08-14 16:23:16.339054106 -0500 @@ -10,6 +10,9 @@ import os import sys import tty +from termios import TIOCGWINSZ, TIOCSWINSZ +from struct import pack +from fcntl import ioctl __all__ = ["openpty","fork","spawn"] @@ -67,7 +70,7 @@ result = os.open(tty_name, os.O_RDWR) try: - from fcntl import ioctl, I_PUSH + from fcntl import I_PUSH except ImportError: return result try: @@ -77,6 +80,25 @@ pass return result +def _login_pty(master_fd, slave_fd): + """Given a pty, makes the calling process a session leader, + makes the pty slave its stdin/stdout/stderr, and makes the + stdout its controlling tty.""" + # Establish a new session. + os.setsid() + os.close(master_fd) + + # Slave becomes stdin/stdout/stderr of child. + os.dup2(slave_fd, STDIN_FILENO) + os.dup2(slave_fd, STDOUT_FILENO) + os.dup2(slave_fd, STDERR_FILENO) + if (slave_fd > STDERR_FILENO): + os.close(slave_fd) + + # Explicitly open the tty to make it become a controlling tty. + tmp_fd = os.open(os.ttyname(STDOUT_FILENO), os.O_RDWR) + os.close(tmp_fd) + def fork(): """fork() -> (pid, master_fd) Fork and make the child a session leader with a controlling terminal.""" @@ -97,20 +119,7 @@ master_fd, slave_fd = openpty() pid = os.fork() if pid == CHILD: - # Establish a new session. - os.setsid() - os.close(master_fd) - - # Slave becomes stdin/stdout/stderr of child. - os.dup2(slave_fd, STDIN_FILENO) - os.dup2(slave_fd, STDOUT_FILENO) - os.dup2(slave_fd, STDERR_FILENO) - if (slave_fd > STDERR_FILENO): - os.close (slave_fd) - - # Explicitly open the tty to make it become a controlling tty. - tmp_fd = os.open(os.ttyname(STDOUT_FILENO), os.O_RDWR) - os.close(tmp_fd) + _login_pty(master_fd, slave_fd) else: os.close(slave_fd) @@ -127,6 +136,12 @@ """Default read function.""" return os.read(fd, 1024) +def _setwinsz(slave_fd): + """Sets window size.""" + w = pack('HHHH', 0, 0, 0, 0) + s = ioctl(STDIN_FILENO, TIOCGWINSZ, w) + ioctl(slave_fd, TIOCSWINSZ, s) + def _copy(master_fd, master_read=_read, stdin_read=_read): """Parent copy loop. Copies @@ -153,10 +168,17 @@ if type(argv) == type(''): argv = (argv,) sys.audit('pty.spawn', argv) - pid, master_fd = fork() + master_fd, slave_fd = openpty() + pid = os.fork() if pid == CHILD: + _login_pty(master_fd, slave_fd) os.execlp(argv[0], *argv) try: + _setwinsz(slave_fd) + except: + pass + os.close(slave_fd) + try: mode = tty.tcgetattr(STDIN_FILENO) tty.setraw(STDIN_FILENO) restore = 1