Skip to content

Commit 5ebf0f3

Browse files
committed
Make pty.spawn set window size
1 parent 0244838 commit 5ebf0f3

File tree

1 file changed

+42
-14
lines changed

1 file changed

+42
-14
lines changed

Lib/pty.py

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,27 @@ def slave_open(tty_name):
7777
pass
7878
return result
7979

80+
def login_tty(fd):
81+
"""Makes the calling process a session leader, makes fd its
82+
controlling terminal, stdin, stdout, and stderr. Closes fd."""
83+
# Establish a new session.
84+
os.setsid()
85+
86+
# Make fd the controlling terminal.
87+
try:
88+
from fcntl import ioctl
89+
ioctl(fd, tty.TIOCSCTTY)
90+
except (ImportError, AttributeError, OSError):
91+
tmp_fd = os.open(os.ttyname(fd), os.O_RDWR)
92+
os.close(tmp_fd)
93+
94+
# fd becomes stdin/stdout/stderr.
95+
os.dup2(fd, STDIN_FILENO)
96+
os.dup2(fd, STDOUT_FILENO)
97+
os.dup2(fd, STDERR_FILENO)
98+
if (fd > STDERR_FILENO):
99+
os.close(fd)
100+
80101
def fork():
81102
"""fork() -> (pid, master_fd)
82103
Fork and make the child a session leader with a controlling terminal."""
@@ -97,20 +118,8 @@ def fork():
97118
master_fd, slave_fd = openpty()
98119
pid = os.fork()
99120
if pid == CHILD:
100-
# Establish a new session.
101-
os.setsid()
102121
os.close(master_fd)
103-
104-
# Slave becomes stdin/stdout/stderr of child.
105-
os.dup2(slave_fd, STDIN_FILENO)
106-
os.dup2(slave_fd, STDOUT_FILENO)
107-
os.dup2(slave_fd, STDERR_FILENO)
108-
if (slave_fd > STDERR_FILENO):
109-
os.close (slave_fd)
110-
111-
# Explicitly open the tty to make it become a controlling tty.
112-
tmp_fd = os.open(os.ttyname(STDOUT_FILENO), os.O_RDWR)
113-
os.close(tmp_fd)
122+
login_tty(slave_fd)
114123
else:
115124
os.close(slave_fd)
116125

@@ -148,14 +157,33 @@ def _copy(master_fd, master_read=_read, stdin_read=_read):
148157
else:
149158
_writen(master_fd, data)
150159

160+
def _setwinsz(fd):
161+
"""Sets window size.
162+
If both stdin and fd are terminals,
163+
then set fd's window size to be the
164+
same as that of stdin's."""
165+
try:
166+
from struct import pack
167+
from fcntl import ioctl
168+
strct = pack('HHHH', 0, 0, 0, 0)
169+
winsz = ioctl(STDIN_FILENO, tty.TIOCGWINSZ, strct)
170+
ioctl(fd, tty.TIOCSWINSZ, winsz)
171+
except (ImportError, AttributeError, OSError):
172+
pass
173+
151174
def spawn(argv, master_read=_read, stdin_read=_read):
152175
"""Create a spawned process."""
153176
if type(argv) == type(''):
154177
argv = (argv,)
155178
sys.audit('pty.spawn', argv)
156-
pid, master_fd = fork()
179+
master_fd, slave_fd = openpty()
180+
_setwinsz(slave_fd)
181+
pid = os.fork()
157182
if pid == CHILD:
183+
os.close(master_fd)
184+
login_tty(slave_fd)
158185
os.execlp(argv[0], *argv)
186+
os.close(slave_fd)
159187
try:
160188
mode = tty.tcgetattr(STDIN_FILENO)
161189
tty.setraw(STDIN_FILENO)

0 commit comments

Comments
 (0)