@@ -77,6 +77,27 @@ def slave_open(tty_name):
77
77
pass
78
78
return result
79
79
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
+
80
101
def fork ():
81
102
"""fork() -> (pid, master_fd)
82
103
Fork and make the child a session leader with a controlling terminal."""
@@ -97,20 +118,8 @@ def fork():
97
118
master_fd , slave_fd = openpty ()
98
119
pid = os .fork ()
99
120
if pid == CHILD :
100
- # Establish a new session.
101
- os .setsid ()
102
121
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 )
114
123
else :
115
124
os .close (slave_fd )
116
125
@@ -148,14 +157,33 @@ def _copy(master_fd, master_read=_read, stdin_read=_read):
148
157
else :
149
158
_writen (master_fd , data )
150
159
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
+
151
174
def spawn (argv , master_read = _read , stdin_read = _read ):
152
175
"""Create a spawned process."""
153
176
if type (argv ) == type ('' ):
154
177
argv = (argv ,)
155
178
sys .audit ('pty.spawn' , argv )
156
- pid , master_fd = fork ()
179
+ master_fd , slave_fd = openpty ()
180
+ _setwinsz (slave_fd )
181
+ pid = os .fork ()
157
182
if pid == CHILD :
183
+ os .close (master_fd )
184
+ login_tty (slave_fd )
158
185
os .execlp (argv [0 ], * argv )
186
+ os .close (slave_fd )
159
187
try :
160
188
mode = tty .tcgetattr (STDIN_FILENO )
161
189
tty .setraw (STDIN_FILENO )
0 commit comments