diff options
author | Fred Drake <fdrake@acm.org> | 2000-06-28 16:40:38 (GMT) |
---|---|---|
committer | Fred Drake <fdrake@acm.org> | 2000-06-28 16:40:38 (GMT) |
commit | 8cef4cf737878bd8eec648426eebe9b9019b18be (patch) | |
tree | 2fe93f0a2d3c9e22ad836a45bc7a526416c11c61 /Lib | |
parent | 57823862683db7a463a134dbdf259d2e027619f6 (diff) | |
download | cpython-8cef4cf737878bd8eec648426eebe9b9019b18be.zip cpython-8cef4cf737878bd8eec648426eebe9b9019b18be.tar.gz cpython-8cef4cf737878bd8eec648426eebe9b9019b18be.tar.bz2 |
Thomas Wouters <thomas@xs4all.net>:
This patch adds the openpty() and forkpty() library calls to posixmodule.c,
when they are available on the target
system. (glibc-2.1-based Linux systems, FreeBSD and BSDI at least, probably
the other BSD-based systems as well.)
Lib/pty.py is also rewritten to use openpty when available, but falls
back to the old SGI method or the "manual" BSD open-a-pty
code. Openpty() is necessary to use the Unix98 ptys under Linux 2.2,
or when using non-standard tty names under (at least) BSDI, which is
why I needed it, myself ;-) forkpty() is included for symmetry.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/pty.py | 73 |
1 files changed, 57 insertions, 16 deletions
@@ -16,9 +16,37 @@ STDERR_FILENO = 2 CHILD = 0 +def openpty(): + """openpty() -> (master_fd, slave_fd) + Open a pty master/slave pair, using os.openpty() if possible.""" + + try: + return os.openpty() + except (AttributeError, OSError): + pass + master_fd, slave_name = _open_terminal() + slave_fd = _slave_open(slave_name) + return master_fd, slave_fd + def master_open(): + """master_open() -> (master_fd, slave_name) + Open a pty master and return the fd, and the filename of the slave end. + Deprecated, use openpty() instead.""" + + try: + master_fd, slave_fd = os.openpty() + except (AttributeError, OSError): + pass + else: + slave_name = os.ttyname(slave_fd) + os.close(slave_fd) + return master_fd, slave_name + + return _open_terminal() + +def _open_terminal(): """Open pty master and return (master_fd, tty_name). - SGI and Linux/BSD version.""" + SGI and generic BSD version, for when openpty() fails.""" try: import sgi except ImportError: @@ -40,22 +68,35 @@ def master_open(): 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) + """slave_open(tty_name) -> slave_fd + Open the pty slave and acquire the controlling terminal, returning + opened filedescriptor. + Deprecated, use openpty() instead.""" + 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() + """fork() -> (pid, master_fd) + Fork and make the child a session leader with a controlling terminal.""" + + try: + pid, fd = os.forkpty() + except (AttributeError, OSError): + pass + else: + if pid == CHILD: + try: + os.setsid() + except OSError: + # os.forkpty() already set us session leader + pass + return pid, fd + + master_fd, slave_fd = openpty() 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. @@ -68,17 +109,17 @@ def fork(): # Parent and child process. return pid, master_fd -def writen(fd, data): +def _writen(fd, data): """Write all the data to a descriptor.""" while data != '': n = os.write(fd, data) data = data[n:] -def read(fd): +def _read(fd): """Default read function.""" return os.read(fd, 1024) -def copy(master_fd, master_read=read, stdin_read=read): +def _copy(master_fd, master_read=_read, stdin_read=_read): """Parent copy loop. Copies pty master -> standard output (master_read) @@ -91,9 +132,9 @@ def copy(master_fd, master_read=read, stdin_read=read): os.write(STDOUT_FILENO, data) if STDIN_FILENO in rfds: data = stdin_read(STDIN_FILENO) - writen(master_fd, data) + _writen(master_fd, data) -def spawn(argv, master_read=read, stdin_read=read): +def spawn(argv, master_read=_read, stdin_read=_read): """Create a spawned process.""" if type(argv) == type(''): argv = (argv,) @@ -103,6 +144,6 @@ def spawn(argv, master_read=read, stdin_read=read): mode = tty.tcgetattr(STDIN_FILENO) tty.setraw(STDIN_FILENO) try: - copy(master_fd, master_read, stdin_read) + _copy(master_fd, master_read, stdin_read) except: tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode) |