mirror of
https://github.com/python/cpython.git
synced 2024-11-27 03:45:08 +08:00
54f22ed30b
who writes: Here is batch 2, as a big collection of CVS context diffs. Along with moving comments into docstrings, i've added a couple of missing docstrings and attempted to make sure more module docstrings begin with a one-line summary. I did not add docstrings to the methods in profile.py for fear of upsetting any careful optimizations there, though i did move class documentation into class docstrings. The convention i'm using is to leave credits/version/copyright type of stuff in # comments, and move the rest of the descriptive stuff about module usage into module docstrings. Hope this is okay.
109 lines
2.7 KiB
Python
109 lines
2.7 KiB
Python
"""Pseudo terminal utilities."""
|
|
|
|
# Bugs: No signal handling. Doesn't set slave termios and window size.
|
|
# Only tested on Linux.
|
|
# See: W. Richard Stevens. 1992. Advanced Programming in the
|
|
# UNIX Environment. Chapter 19.
|
|
# Author: Steen Lumholt -- with additions by Guido.
|
|
|
|
from select import select
|
|
import os, FCNTL
|
|
import tty
|
|
|
|
STDIN_FILENO = 0
|
|
STDOUT_FILENO = 1
|
|
STDERR_FILENO = 2
|
|
|
|
CHILD = 0
|
|
|
|
def master_open():
|
|
"""Open pty master and return (master_fd, tty_name).
|
|
SGI and Linux/BSD version."""
|
|
try:
|
|
import sgi
|
|
except ImportError:
|
|
pass
|
|
else:
|
|
try:
|
|
tty_name, master_fd = sgi._getpty(FCNTL.O_RDWR, 0666, 0)
|
|
except IOError, msg:
|
|
raise os.error, msg
|
|
return master_fd, tty_name
|
|
for x in 'pqrstuvwxyzPQRST':
|
|
for y in '0123456789abcdef':
|
|
pty_name = '/dev/pty' + x + y
|
|
try:
|
|
fd = os.open(pty_name, FCNTL.O_RDWR)
|
|
except os.error:
|
|
continue
|
|
return (fd, '/dev/tty' + x + y)
|
|
raise os.error, 'out of pty devices'
|
|
|
|
def slave_open(tty_name):
|
|
"""Open the pty slave and acquire the controlling terminal.
|
|
Return the file descriptor. Linux version."""
|
|
# (Should be universal? --Guido)
|
|
return os.open(tty_name, FCNTL.O_RDWR)
|
|
|
|
def fork():
|
|
"""Fork and make the child a session leader with a controlling terminal.
|
|
Return (pid, master_fd)."""
|
|
master_fd, tty_name = master_open()
|
|
pid = os.fork()
|
|
if pid == CHILD:
|
|
# Establish a new session.
|
|
os.setsid()
|
|
|
|
# Acquire controlling terminal.
|
|
slave_fd = slave_open(tty_name)
|
|
os.close(master_fd)
|
|
|
|
# Slave becomes stdin/stdout/stderr of child.
|
|
os.dup2(slave_fd, STDIN_FILENO)
|
|
os.dup2(slave_fd, STDOUT_FILENO)
|
|
os.dup2(slave_fd, STDERR_FILENO)
|
|
if (slave_fd > STDERR_FILENO):
|
|
os.close (slave_fd)
|
|
|
|
# Parent and child process.
|
|
return pid, master_fd
|
|
|
|
def writen(fd, data):
|
|
"""Write all the data to a descriptor."""
|
|
while data != '':
|
|
n = os.write(fd, data)
|
|
data = data[n:]
|
|
|
|
def read(fd):
|
|
"""Default read function."""
|
|
return os.read(fd, 1024)
|
|
|
|
def copy(master_fd, master_read=read, stdin_read=read):
|
|
"""Parent copy loop.
|
|
Copies
|
|
pty master -> standard output (master_read)
|
|
standard input -> pty master (stdin_read)"""
|
|
while 1:
|
|
rfds, wfds, xfds = select(
|
|
[master_fd, STDIN_FILENO], [], [])
|
|
if master_fd in rfds:
|
|
data = master_read(master_fd)
|
|
os.write(STDOUT_FILENO, data)
|
|
if STDIN_FILENO in rfds:
|
|
data = stdin_read(STDIN_FILENO)
|
|
writen(master_fd, data)
|
|
|
|
def spawn(argv, master_read=read, stdin_read=read):
|
|
"""Create a spawned process."""
|
|
if type(argv) == type(''):
|
|
argv = (argv,)
|
|
pid, master_fd = fork()
|
|
if pid == CHILD:
|
|
apply(os.execlp, (argv[0],) + argv)
|
|
mode = tty.tcgetattr(STDIN_FILENO)
|
|
tty.setraw(STDIN_FILENO)
|
|
try:
|
|
copy(master_fd, master_read, stdin_read)
|
|
except:
|
|
tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode)
|