home *** CD-ROM | disk | FTP | other *** search
/ Freelog 125 / Freelog_MarsAvril2015_No125.iso / Bureautique / OpenOffice / Apache_OpenOffice_4.1.1_Win_x86_install_fr.exe / openoffice1.cab / pty.py < prev    next >
Text File  |  2014-07-29  |  5KB  |  181 lines

  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.     fds = [master_fd, STDIN_FILENO]
  146.     while True:
  147.         rfds, wfds, xfds = select(fds, [], [])
  148.         if master_fd in rfds:
  149.             data = master_read(master_fd)
  150.             if not data:  # Reached EOF.
  151.                 fds.remove(master_fd)
  152.             else:
  153.                 os.write(STDOUT_FILENO, data)
  154.         if STDIN_FILENO in rfds:
  155.             data = stdin_read(STDIN_FILENO)
  156.             if not data:
  157.                 fds.remove(STDIN_FILENO)
  158.             else:
  159.                 _writen(master_fd, data)
  160.  
  161. def spawn(argv, master_read=_read, stdin_read=_read):
  162.     """Create a spawned process."""
  163.     if type(argv) == type(''):
  164.         argv = (argv,)
  165.     pid, master_fd = fork()
  166.     if pid == CHILD:
  167.         os.execlp(argv[0], *argv)
  168.     try:
  169.         mode = tty.tcgetattr(STDIN_FILENO)
  170.         tty.setraw(STDIN_FILENO)
  171.         restore = 1
  172.     except tty.error:    # This is the same as termios.error
  173.         restore = 0
  174.     try:
  175.         _copy(master_fd, master_read, stdin_read)
  176.     except (IOError, OSError):
  177.         if restore:
  178.             tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode)
  179.  
  180.     os.close(master_fd)
  181.