home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyos2bin.zip / Lib / pty.py < prev    next >
Text File  |  1994-09-12  |  3KB  |  107 lines

  1. # pty.py -- 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, sys, FCNTL
  11. import tty
  12.  
  13. STDIN_FILENO = 0
  14. STDOUT_FILENO = 1
  15. STDERR_FILENO = 2
  16.  
  17. CHILD = 0
  18.  
  19. # Open pty master.  Returns (master_fd, tty_name).  SGI and Linux/BSD version.
  20. def master_open():
  21.     try:
  22.         import sgi
  23.     except ImportError:
  24.         pass
  25.     else:
  26.         try:
  27.             tty_name, master_fd = sgi._getpty(FCNTL.O_RDWR, 0666, 0)
  28.         except IOError, msg:
  29.             raise os.error, msg
  30.         return master_fd, tty_name
  31.     for x in 'pqrstuvwxyzPQRST':
  32.         for y in '0123456789abcdef':
  33.             pty_name = '/dev/pty' + x + y
  34.             try:
  35.                 fd = os.open(pty_name, FCNTL.O_RDWR)
  36.             except os.error:
  37.                 continue
  38.             return (fd, '/dev/tty' + x + y)
  39.     raise os.error, 'out of pty devices'
  40.  
  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)
  45.  
  46. # Fork and make the child a session leader with a controlling terminal.
  47. # Returns (pid, master_fd)
  48. def fork():
  49.     master_fd, tty_name = master_open() 
  50.     pid = os.fork()
  51.     if pid == CHILD:
  52.         # Establish a new session.
  53.         os.setsid()
  54.  
  55.         # Acquire controlling terminal.
  56.         slave_fd = slave_open(tty_name)
  57.         os.close(master_fd)
  58.  
  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):
  64.             os.close (slave_fd)
  65.  
  66.     # Parent and child process.
  67.     return pid, master_fd
  68.  
  69. # Write all the data to a descriptor.
  70. def writen(fd, data):
  71.     while data != '':
  72.         n = os.write(fd, data)
  73.         data = data[n:]
  74.  
  75. # Default read function.
  76. def read(fd):
  77.     return os.read(fd, 1024)
  78.  
  79. # Parent copy loop.
  80. # Copies  
  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):
  84.     while 1:
  85.         rfds, wfds, xfds = select(
  86.             [master_fd, STDIN_FILENO], [], [])
  87.         if master_fd in rfds:
  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)
  93.  
  94. # Create a spawned process.
  95. def spawn(argv, master_read=read, stdin_read=read):
  96.     if type(argv) == type(''):
  97.         argv = (argv,)
  98.     pid, master_fd = fork()
  99.     if pid == CHILD:
  100.         apply(os.execlp, (argv[0],) + argv)
  101.     mode = tty.tcgetattr(STDIN_FILENO)
  102.     tty.setraw(STDIN_FILENO)
  103.     try:
  104.         copy(master_fd, master_read, stdin_read)
  105.     except:
  106.         tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode)
  107.