1 # pty.py -- Pseudo terminal utilities.
3 # Bugs: No signal handling. Doesn't set slave termios and window size.
4 # Only tested on Linux.
5 # See: W. Richard Stevens. 1992. Advanced Programming in the
6 # UNIX Environment. Chapter 19.
7 # Author: Steen Lumholt -- with additions by Guido.
9 from select
import select
19 # Open pty master. Returns (master_fd, tty_name). SGI and Linux/BSD version.
27 tty_name
, master_fd
= sgi
._getpty
(FCNTL
.O_RDWR
, 0666, 0)
30 return master_fd
, tty_name
31 for x
in 'pqrstuvwxyzPQRST':
32 for y
in '0123456789abcdef':
33 pty_name
= '/dev/pty' + x
+ y
35 fd
= os
.open(pty_name
, FCNTL
.O_RDWR
)
38 return (fd
, '/dev/tty' + x
+ y
)
39 raise os
.error
, 'out of pty devices'
41 # Open the pty slave. Acquire the controlling terminal.
42 # Returns file descriptor. Linux version. (Should be universal? --Guido)
43 def slave_open(tty_name
):
44 return os
.open(tty_name
, FCNTL
.O_RDWR
)
46 # Fork and make the child a session leader with a controlling terminal.
47 # Returns (pid, master_fd)
49 master_fd
, tty_name
= master_open()
52 # Establish a new session.
55 # Acquire controlling terminal.
56 slave_fd
= slave_open(tty_name
)
59 # Slave becomes stdin/stdout/stderr of child.
60 os
.dup2(slave_fd
, STDIN_FILENO
)
61 os
.dup2(slave_fd
, STDOUT_FILENO
)
62 os
.dup2(slave_fd
, STDERR_FILENO
)
63 if (slave_fd
> STDERR_FILENO
):
66 # Parent and child process.
69 # Write all the data to a descriptor.
72 n
= os
.write(fd
, data
)
75 # Default read function.
77 return os
.read(fd
, 1024)
81 # pty master -> standard output (master_read)
82 # standard input -> pty master (stdin_read)
83 def copy(master_fd
, master_read
=read
, stdin_read
=read
):
85 rfds
, wfds
, xfds
= select(
86 [master_fd
, STDIN_FILENO
], [], [])
88 data
= master_read(master_fd
)
89 os
.write(STDOUT_FILENO
, data
)
90 if STDIN_FILENO
in rfds
:
91 data
= stdin_read(STDIN_FILENO
)
92 writen(master_fd
, data
)
94 # Create a spawned process.
95 def spawn(argv
, master_read
=read
, stdin_read
=read
):
96 if type(argv
) == type(''):
98 pid
, master_fd
= fork()
100 apply(os
.execlp
, (argv
[0],) + argv
)
101 mode
= tty
.tcgetattr(STDIN_FILENO
)
102 tty
.setraw(STDIN_FILENO
)
104 copy(master_fd
, master_read
, stdin_read
)
106 tty
.tcsetattr(STDIN_FILENO
, tty
.TCSAFLUSH
, mode
)