16
16
17
17
CHILD = 0
18
18
19
+ def openpty ():
20
+ """openpty() -> (master_fd, slave_fd)
21
+ Open a pty master/slave pair, using os.openpty() if possible."""
22
+
23
+ try :
24
+ return os .openpty ()
25
+ except (AttributeError , OSError ):
26
+ pass
27
+ master_fd , slave_name = _open_terminal ()
28
+ slave_fd = _slave_open (slave_name )
29
+ return master_fd , slave_fd
30
+
19
31
def master_open ():
32
+ """master_open() -> (master_fd, slave_name)
33
+ Open a pty master and return the fd, and the filename of the slave end.
34
+ Deprecated, use openpty() instead."""
35
+
36
+ try :
37
+ master_fd , slave_fd = os .openpty ()
38
+ except (AttributeError , OSError ):
39
+ pass
40
+ else :
41
+ slave_name = os .ttyname (slave_fd )
42
+ os .close (slave_fd )
43
+ return master_fd , slave_name
44
+
45
+ return _open_terminal ()
46
+
47
+ def _open_terminal ():
20
48
"""Open pty master and return (master_fd, tty_name).
21
- SGI and Linux/ BSD version."""
49
+ SGI and generic BSD version, for when openpty() fails ."""
22
50
try :
23
51
import sgi
24
52
except ImportError :
@@ -40,22 +68,35 @@ def master_open():
40
68
raise os .error , 'out of pty devices'
41
69
42
70
def slave_open (tty_name ):
43
- """Open the pty slave and acquire the controlling terminal.
44
- Return the file descriptor. Linux version."""
45
- # (Should be universal? --Guido)
71
+ """slave_open(tty_name) -> slave_fd
72
+ Open the pty slave and acquire the controlling terminal, returning
73
+ opened filedescriptor.
74
+ Deprecated, use openpty() instead."""
75
+
46
76
return os .open (tty_name , FCNTL .O_RDWR )
47
77
48
78
def fork ():
49
- """Fork and make the child a session leader with a controlling terminal.
50
- Return (pid, master_fd)."""
51
- master_fd , tty_name = master_open ()
79
+ """fork() -> (pid, master_fd)
80
+ Fork and make the child a session leader with a controlling terminal."""
81
+
82
+ try :
83
+ pid , fd = os .forkpty ()
84
+ except (AttributeError , OSError ):
85
+ pass
86
+ else :
87
+ if pid == CHILD :
88
+ try :
89
+ os .setsid ()
90
+ except OSError :
91
+ # os.forkpty() already set us session leader
92
+ pass
93
+ return pid , fd
94
+
95
+ master_fd , slave_fd = openpty ()
52
96
pid = os .fork ()
53
97
if pid == CHILD :
54
98
# Establish a new session.
55
99
os .setsid ()
56
-
57
- # Acquire controlling terminal.
58
- slave_fd = slave_open (tty_name )
59
100
os .close (master_fd )
60
101
61
102
# Slave becomes stdin/stdout/stderr of child.
@@ -68,17 +109,17 @@ def fork():
68
109
# Parent and child process.
69
110
return pid , master_fd
70
111
71
- def writen (fd , data ):
112
+ def _writen (fd , data ):
72
113
"""Write all the data to a descriptor."""
73
114
while data != '' :
74
115
n = os .write (fd , data )
75
116
data = data [n :]
76
117
77
- def read (fd ):
118
+ def _read (fd ):
78
119
"""Default read function."""
79
120
return os .read (fd , 1024 )
80
121
81
- def copy (master_fd , master_read = read , stdin_read = read ):
122
+ def _copy (master_fd , master_read = _read , stdin_read = _read ):
82
123
"""Parent copy loop.
83
124
Copies
84
125
pty master -> standard output (master_read)
@@ -91,9 +132,9 @@ def copy(master_fd, master_read=read, stdin_read=read):
91
132
os .write (STDOUT_FILENO , data )
92
133
if STDIN_FILENO in rfds :
93
134
data = stdin_read (STDIN_FILENO )
94
- writen (master_fd , data )
135
+ _writen (master_fd , data )
95
136
96
- def spawn (argv , master_read = read , stdin_read = read ):
137
+ def spawn (argv , master_read = _read , stdin_read = _read ):
97
138
"""Create a spawned process."""
98
139
if type (argv ) == type ('' ):
99
140
argv = (argv ,)
@@ -103,6 +144,6 @@ def spawn(argv, master_read=read, stdin_read=read):
103
144
mode = tty .tcgetattr (STDIN_FILENO )
104
145
tty .setraw (STDIN_FILENO )
105
146
try :
106
- copy (master_fd , master_read , stdin_read )
147
+ _copy (master_fd , master_read , stdin_read )
107
148
except :
108
149
tty .tcsetattr (STDIN_FILENO , tty .TCSAFLUSH , mode )
0 commit comments