@@ -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+
80101def 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+
151174def 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