python-2.5.2/win32/Lib/pty.py
changeset 0 ae805ac0140d
equal deleted inserted replaced
-1:000000000000 0:ae805ac0140d
       
     1 """Pseudo terminal utilities."""
       
     2 
       
     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.
       
     8 
       
     9 from select import select
       
    10 import os
       
    11 import tty
       
    12 
       
    13 __all__ = ["openpty","fork","spawn"]
       
    14 
       
    15 STDIN_FILENO = 0
       
    16 STDOUT_FILENO = 1
       
    17 STDERR_FILENO = 2
       
    18 
       
    19 CHILD = 0
       
    20 
       
    21 def openpty():
       
    22     """openpty() -> (master_fd, slave_fd)
       
    23     Open a pty master/slave pair, using os.openpty() if possible."""
       
    24 
       
    25     try:
       
    26         return os.openpty()
       
    27     except (AttributeError, OSError):
       
    28         pass
       
    29     master_fd, slave_name = _open_terminal()
       
    30     slave_fd = slave_open(slave_name)
       
    31     return master_fd, slave_fd
       
    32 
       
    33 def master_open():
       
    34     """master_open() -> (master_fd, slave_name)
       
    35     Open a pty master and return the fd, and the filename of the slave end.
       
    36     Deprecated, use openpty() instead."""
       
    37 
       
    38     try:
       
    39         master_fd, slave_fd = os.openpty()
       
    40     except (AttributeError, OSError):
       
    41         pass
       
    42     else:
       
    43         slave_name = os.ttyname(slave_fd)
       
    44         os.close(slave_fd)
       
    45         return master_fd, slave_name
       
    46 
       
    47     return _open_terminal()
       
    48 
       
    49 def _open_terminal():
       
    50     """Open pty master and return (master_fd, tty_name).
       
    51     SGI and generic BSD version, for when openpty() fails."""
       
    52     try:
       
    53         import sgi
       
    54     except ImportError:
       
    55         pass
       
    56     else:
       
    57         try:
       
    58             tty_name, master_fd = sgi._getpty(os.O_RDWR, 0666, 0)
       
    59         except IOError, msg:
       
    60             raise os.error, msg
       
    61         return master_fd, tty_name
       
    62     for x in 'pqrstuvwxyzPQRST':
       
    63         for y in '0123456789abcdef':
       
    64             pty_name = '/dev/pty' + x + y
       
    65             try:
       
    66                 fd = os.open(pty_name, os.O_RDWR)
       
    67             except os.error:
       
    68                 continue
       
    69             return (fd, '/dev/tty' + x + y)
       
    70     raise os.error, 'out of pty devices'
       
    71 
       
    72 def slave_open(tty_name):
       
    73     """slave_open(tty_name) -> slave_fd
       
    74     Open the pty slave and acquire the controlling terminal, returning
       
    75     opened filedescriptor.
       
    76     Deprecated, use openpty() instead."""
       
    77 
       
    78     result = os.open(tty_name, os.O_RDWR)
       
    79     try:
       
    80         from fcntl import ioctl, I_PUSH
       
    81     except ImportError:
       
    82         return result
       
    83     try:
       
    84         ioctl(result, I_PUSH, "ptem")
       
    85         ioctl(result, I_PUSH, "ldterm")
       
    86     except IOError:
       
    87         pass
       
    88     return result
       
    89 
       
    90 def fork():
       
    91     """fork() -> (pid, master_fd)
       
    92     Fork and make the child a session leader with a controlling terminal."""
       
    93 
       
    94     try:
       
    95         pid, fd = os.forkpty()
       
    96     except (AttributeError, OSError):
       
    97         pass
       
    98     else:
       
    99         if pid == CHILD:
       
   100             try:
       
   101                 os.setsid()
       
   102             except OSError:
       
   103                 # os.forkpty() already set us session leader
       
   104                 pass
       
   105         return pid, fd
       
   106 
       
   107     master_fd, slave_fd = openpty()
       
   108     pid = os.fork()
       
   109     if pid == CHILD:
       
   110         # Establish a new session.
       
   111         os.setsid()
       
   112         os.close(master_fd)
       
   113 
       
   114         # Slave becomes stdin/stdout/stderr of child.
       
   115         os.dup2(slave_fd, STDIN_FILENO)
       
   116         os.dup2(slave_fd, STDOUT_FILENO)
       
   117         os.dup2(slave_fd, STDERR_FILENO)
       
   118         if (slave_fd > STDERR_FILENO):
       
   119             os.close (slave_fd)
       
   120 
       
   121         # Explicitly open the tty to make it become a controlling tty.
       
   122         tmp_fd = os.open(os.ttyname(STDOUT_FILENO), os.O_RDWR)
       
   123         os.close(tmp_fd)
       
   124     else:
       
   125         os.close(slave_fd)
       
   126 
       
   127     # Parent and child process.
       
   128     return pid, master_fd
       
   129 
       
   130 def _writen(fd, data):
       
   131     """Write all the data to a descriptor."""
       
   132     while data != '':
       
   133         n = os.write(fd, data)
       
   134         data = data[n:]
       
   135 
       
   136 def _read(fd):
       
   137     """Default read function."""
       
   138     return os.read(fd, 1024)
       
   139 
       
   140 def _copy(master_fd, master_read=_read, stdin_read=_read):
       
   141     """Parent copy loop.
       
   142     Copies
       
   143             pty master -> standard output   (master_read)
       
   144             standard input -> pty master    (stdin_read)"""
       
   145     while 1:
       
   146         rfds, wfds, xfds = select(
       
   147                 [master_fd, STDIN_FILENO], [], [])
       
   148         if master_fd in rfds:
       
   149             data = master_read(master_fd)
       
   150             os.write(STDOUT_FILENO, data)
       
   151         if STDIN_FILENO in rfds:
       
   152             data = stdin_read(STDIN_FILENO)
       
   153             _writen(master_fd, data)
       
   154 
       
   155 def spawn(argv, master_read=_read, stdin_read=_read):
       
   156     """Create a spawned process."""
       
   157     if type(argv) == type(''):
       
   158         argv = (argv,)
       
   159     pid, master_fd = fork()
       
   160     if pid == CHILD:
       
   161         os.execlp(argv[0], *argv)
       
   162     try:
       
   163         mode = tty.tcgetattr(STDIN_FILENO)
       
   164         tty.setraw(STDIN_FILENO)
       
   165         restore = 1
       
   166     except tty.error:    # This is the same as termios.error
       
   167         restore = 0
       
   168     try:
       
   169         _copy(master_fd, master_read, stdin_read)
       
   170     except (IOError, OSError):
       
   171         if restore:
       
   172             tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode)
       
   173 
       
   174     os.close(master_fd)