From 024483879bffa61bd64d91f82174cdab22cedad5 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Thu, 13 Aug 2020 17:48:59 +0000 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/Library/2020-08-13-17-48-58.bpo-41541.vKJSeV.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2020-08-13-17-48-58.bpo-41541.vKJSeV.rst diff --git a/Misc/NEWS.d/next/Library/2020-08-13-17-48-58.bpo-41541.vKJSeV.rst b/Misc/NEWS.d/next/Library/2020-08-13-17-48-58.bpo-41541.vKJSeV.rst new file mode 100644 index 00000000000000..5e49a7c836989c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-08-13-17-48-58.bpo-41541.vKJSeV.rst @@ -0,0 +1 @@ +Make pty.spawn set window size. \ No newline at end of file From 5ebf0f31044081d88b428e55b2f39b1f2acb7cc1 Mon Sep 17 00:00:00 2001 From: Soumendra Ganguly Date: Tue, 18 Aug 2020 21:40:07 -0500 Subject: [PATCH 2/3] Make pty.spawn set window size --- Lib/pty.py | 56 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/Lib/pty.py b/Lib/pty.py index a32432041fa1db..3032a3e260e893 100644 --- a/Lib/pty.py +++ b/Lib/pty.py @@ -77,6 +77,27 @@ def slave_open(tty_name): pass return result +def login_tty(fd): + """Makes the calling process a session leader, makes fd its + controlling terminal, stdin, stdout, and stderr. Closes fd.""" + # Establish a new session. + os.setsid() + + # Make fd the controlling terminal. + try: + from fcntl import ioctl + ioctl(fd, tty.TIOCSCTTY) + except (ImportError, AttributeError, OSError): + tmp_fd = os.open(os.ttyname(fd), os.O_RDWR) + os.close(tmp_fd) + + # fd becomes stdin/stdout/stderr. + os.dup2(fd, STDIN_FILENO) + os.dup2(fd, STDOUT_FILENO) + os.dup2(fd, STDERR_FILENO) + if (fd > STDERR_FILENO): + os.close(fd) + def fork(): """fork() -> (pid, master_fd) Fork and make the child a session leader with a controlling terminal.""" @@ -97,20 +118,8 @@ def fork(): 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_tty(slave_fd) else: os.close(slave_fd) @@ -148,14 +157,33 @@ def _copy(master_fd, master_read=_read, stdin_read=_read): else: _writen(master_fd, data) +def _setwinsz(fd): + """Sets window size. + If both stdin and fd are terminals, + then set fd's window size to be the + same as that of stdin's.""" + try: + from struct import pack + from fcntl import ioctl + strct = pack('HHHH', 0, 0, 0, 0) + winsz = ioctl(STDIN_FILENO, tty.TIOCGWINSZ, strct) + ioctl(fd, tty.TIOCSWINSZ, winsz) + except (ImportError, AttributeError, OSError): + pass + 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() + master_fd, slave_fd = openpty() + _setwinsz(slave_fd) + pid = os.fork() if pid == CHILD: + os.close(master_fd) + login_tty(slave_fd) os.execlp(argv[0], *argv) + os.close(slave_fd) try: mode = tty.tcgetattr(STDIN_FILENO) tty.setraw(STDIN_FILENO) From efca4a109cb9d6621a4dea97c6602d2a7a1d2cec Mon Sep 17 00:00:00 2001 From: Soumendra Ganguly <67527439+8vasu@users.noreply.github.com> Date: Sat, 19 Sep 2020 17:00:44 -0500 Subject: [PATCH 3/3] Minor modification to _setwinsz() --- Lib/pty.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Lib/pty.py b/Lib/pty.py index 3032a3e260e893..16a4cdd71ef67c 100644 --- a/Lib/pty.py +++ b/Lib/pty.py @@ -165,10 +165,14 @@ def _setwinsz(fd): try: from struct import pack from fcntl import ioctl - strct = pack('HHHH', 0, 0, 0, 0) + except ImportError: + return + + strct = pack('HHHH', 0, 0, 0, 0) + try: winsz = ioctl(STDIN_FILENO, tty.TIOCGWINSZ, strct) ioctl(fd, tty.TIOCSWINSZ, winsz) - except (ImportError, AttributeError, OSError): + except (AttributeError, OSError): pass def spawn(argv, master_read=_read, stdin_read=_read):