Vega strike Python Modules doc  0.5.1
Documentation of the " Modules " folder of Vega strike
 All Data Structures Namespaces Files Functions Variables
pty.py
Go to the documentation of this file.
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 
12 # Absurd: import termios and then delete it. This is to force an attempt
13 # to import pty to raise an ImportError on platforms that lack termios.
14 # Without this explicit import of termios here, some other module may
15 # import tty first, which in turn imports termios and dies with an
16 # ImportError then. But since tty *does* exist across platforms, that
17 # leaves a damaged module object for tty in sys.modules, and the import
18 # of tty here then appears to work despite that the tty imported is junk.
19 import termios
20 del termios
21 
22 import tty
23 
24 __all__ = ["openpty","fork","spawn"]
25 
26 STDIN_FILENO = 0
27 STDOUT_FILENO = 1
28 STDERR_FILENO = 2
29 
30 CHILD = 0
31 
32 def openpty():
33  """openpty() -> (master_fd, slave_fd)
34  Open a pty master/slave pair, using os.openpty() if possible."""
35 
36  try:
37  return os.openpty()
38  except (AttributeError, OSError):
39  pass
40  master_fd, slave_name = _open_terminal()
41  slave_fd = slave_open(slave_name)
42  return master_fd, slave_fd
43 
45  """master_open() -> (master_fd, slave_name)
46  Open a pty master and return the fd, and the filename of the slave end.
47  Deprecated, use openpty() instead."""
48 
49  try:
50  master_fd, slave_fd = os.openpty()
51  except (AttributeError, OSError):
52  pass
53  else:
54  slave_name = os.ttyname(slave_fd)
55  os.close(slave_fd)
56  return master_fd, slave_name
57 
58  return _open_terminal()
59 
60 def _open_terminal():
61  """Open pty master and return (master_fd, tty_name).
62  SGI and generic BSD version, for when openpty() fails."""
63  try:
64  import sgi
65  except ImportError:
66  pass
67  else:
68  try:
69  tty_name, master_fd = sgi._getpty(os.O_RDWR, 0666, 0)
70  except IOError, msg:
71  raise os.error, msg
72  return master_fd, tty_name
73  for x in 'pqrstuvwxyzPQRST':
74  for y in '0123456789abcdef':
75  pty_name = '/dev/pty' + x + y
76  try:
77  fd = os.open(pty_name, os.O_RDWR)
78  except os.error:
79  continue
80  return (fd, '/dev/tty' + x + y)
81  raise os.error, 'out of pty devices'
82 
83 def slave_open(tty_name):
84  """slave_open(tty_name) -> slave_fd
85  Open the pty slave and acquire the controlling terminal, returning
86  opened filedescriptor.
87  Deprecated, use openpty() instead."""
88 
89  return os.open(tty_name, os.O_RDWR)
90 
91 def fork():
92  """fork() -> (pid, master_fd)
93  Fork and make the child a session leader with a controlling terminal."""
94 
95  try:
96  pid, fd = os.forkpty()
97  except (AttributeError, OSError):
98  pass
99  else:
100  if pid == CHILD:
101  try:
102  os.setsid()
103  except OSError:
104  # os.forkpty() already set us session leader
105  pass
106  return pid, fd
107 
108  master_fd, slave_fd = openpty()
109  pid = os.fork()
110  if pid == CHILD:
111  # Establish a new session.
112  os.setsid()
113  os.close(master_fd)
114 
115  # Slave becomes stdin/stdout/stderr of child.
116  os.dup2(slave_fd, STDIN_FILENO)
117  os.dup2(slave_fd, STDOUT_FILENO)
118  os.dup2(slave_fd, STDERR_FILENO)
119  if (slave_fd > STDERR_FILENO):
120  os.close (slave_fd)
121 
122  # Parent and child process.
123  return pid, master_fd
124 
125 def _writen(fd, data):
126  """Write all the data to a descriptor."""
127  while data != '':
128  n = os.write(fd, data)
129  data = data[n:]
130 
131 def _read(fd):
132  """Default read function."""
133  return os.read(fd, 1024)
134 
135 def _copy(master_fd, master_read=_read, stdin_read=_read):
136  """Parent copy loop.
137  Copies
138  pty master -> standard output (master_read)
139  standard input -> pty master (stdin_read)"""
140  while 1:
141  rfds, wfds, xfds = select(
142  [master_fd, STDIN_FILENO], [], [])
143  if master_fd in rfds:
144  data = master_read(master_fd)
145  os.write(STDOUT_FILENO, data)
146  if STDIN_FILENO in rfds:
147  data = stdin_read(STDIN_FILENO)
148  _writen(master_fd, data)
149 
150 def spawn(argv, master_read=_read, stdin_read=_read):
151  """Create a spawned process."""
152  if type(argv) == type(''):
153  argv = (argv,)
154  pid, master_fd = fork()
155  if pid == CHILD:
156  apply(os.execlp, (argv[0],) + argv)
157  mode = tty.tcgetattr(STDIN_FILENO)
158  tty.setraw(STDIN_FILENO)
159  try:
160  _copy(master_fd, master_read, stdin_read)
161  except IOError:
162  tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode)