Vega strike Python Modules doc  0.5.1
Documentation of the " Modules " folder of Vega strike
 All Data Structures Namespaces Files Functions Variables
telnetlib.py
Go to the documentation of this file.
1 """TELNET client class.
2 
3 Based on RFC 854: TELNET Protocol Specification, by J. Postel and
4 J. Reynolds
5 
6 Example:
7 
8 >>> from telnetlib import Telnet
9 >>> tn = Telnet('www.python.org', 79) # connect to finger port
10 >>> tn.write('guido\r\n')
11 >>> print tn.read_all()
12 Login Name TTY Idle When Where
13 guido Guido van Rossum pts/2 <Dec 2 11:10> snag.cnri.reston..
14 
15 >>>
16 
17 Note that read_all() won't read until eof -- it just reads some data
18 -- but it guarantees to read at least one byte unless EOF is hit.
19 
20 It is possible to pass a Telnet object to select.select() in order to
21 wait until more data is available. Note that in this case,
22 read_eager() may return '' even if there was data on the socket,
23 because the protocol negotiation may have eaten the data. This is why
24 EOFError is needed in some cases to distinguish between "no data" and
25 "connection closed" (since the socket also appears ready for reading
26 when it is closed).
27 
28 Bugs:
29 - may hang when connection is slow in the middle of an IAC sequence
30 
31 To do:
32 - option negotiation
33 - timeout should be intrinsic to the connection object instead of an
34  option on one of the read calls only
35 
36 """
37 
38 
39 # Imported modules
40 import sys
41 import socket
42 import select
43 
44 __all__ = ["Telnet"]
45 
46 # Tunable parameters
47 DEBUGLEVEL = 0
48 
49 # Telnet protocol defaults
50 TELNET_PORT = 23
51 
52 # Telnet protocol characters (don't change)
53 IAC = chr(255) # "Interpret As Command"
54 DONT = chr(254)
55 DO = chr(253)
56 WONT = chr(252)
57 WILL = chr(251)
58 theNULL = chr(0)
59 
60 # Telnet protocol options code (don't change)
61 # These ones all come from arpa/telnet.h
62 BINARY = chr(0) # 8-bit data path
63 ECHO = chr(1) # echo
64 RCP = chr(2) # prepare to reconnect
65 SGA = chr(3) # suppress go ahead
66 NAMS = chr(4) # approximate message size
67 STATUS = chr(5) # give status
68 TM = chr(6) # timing mark
69 RCTE = chr(7) # remote controlled transmission and echo
70 NAOL = chr(8) # negotiate about output line width
71 NAOP = chr(9) # negotiate about output page size
72 NAOCRD = chr(10) # negotiate about CR disposition
73 NAOHTS = chr(11) # negotiate about horizontal tabstops
74 NAOHTD = chr(12) # negotiate about horizontal tab disposition
75 NAOFFD = chr(13) # negotiate about formfeed disposition
76 NAOVTS = chr(14) # negotiate about vertical tab stops
77 NAOVTD = chr(15) # negotiate about vertical tab disposition
78 NAOLFD = chr(16) # negotiate about output LF disposition
79 XASCII = chr(17) # extended ascii character set
80 LOGOUT = chr(18) # force logout
81 BM = chr(19) # byte macro
82 DET = chr(20) # data entry terminal
83 SUPDUP = chr(21) # supdup protocol
84 SUPDUPOUTPUT = chr(22) # supdup output
85 SNDLOC = chr(23) # send location
86 TTYPE = chr(24) # terminal type
87 EOR = chr(25) # end or record
88 TUID = chr(26) # TACACS user identification
89 OUTMRK = chr(27) # output marking
90 TTYLOC = chr(28) # terminal location number
91 VT3270REGIME = chr(29) # 3270 regime
92 X3PAD = chr(30) # X.3 PAD
93 NAWS = chr(31) # window size
94 TSPEED = chr(32) # terminal speed
95 LFLOW = chr(33) # remote flow control
96 LINEMODE = chr(34) # Linemode option
97 XDISPLOC = chr(35) # X Display Location
98 OLD_ENVIRON = chr(36) # Old - Environment variables
99 AUTHENTICATION = chr(37) # Authenticate
100 ENCRYPT = chr(38) # Encryption option
101 NEW_ENVIRON = chr(39) # New - Environment variables
102 # the following ones come from
103 # http://www.iana.org/assignments/telnet-options
104 # Unfortunately, that document does not assign identifiers
105 # to all of them, so we are making them up
106 TN3270E = chr(40) # TN3270E
107 XAUTH = chr(41) # XAUTH
108 CHARSET = chr(42) # CHARSET
109 RSP = chr(43) # Telnet Remote Serial Port
110 COM_PORT_OPTION = chr(44) # Com Port Control Option
111 SUPPRESS_LOCAL_ECHO = chr(45) # Telnet Suppress Local Echo
112 TLS = chr(46) # Telnet Start TLS
113 KERMIT = chr(47) # KERMIT
114 SEND_URL = chr(48) # SEND-URL
115 FORWARD_X = chr(49) # FORWARD_X
116 PRAGMA_LOGON = chr(138) # TELOPT PRAGMA LOGON
117 SSPI_LOGON = chr(139) # TELOPT SSPI LOGON
118 PRAGMA_HEARTBEAT = chr(140) # TELOPT PRAGMA HEARTBEAT
119 EXOPL = chr(255) # Extended-Options-List
120 
121 class Telnet:
122 
123  """Telnet interface class.
124 
125  An instance of this class represents a connection to a telnet
126  server. The instance is initially not connected; the open()
127  method must be used to establish a connection. Alternatively, the
128  host name and optional port number can be passed to the
129  constructor, too.
130 
131  Don't try to reopen an already connected instance.
132 
133  This class has many read_*() methods. Note that some of them
134  raise EOFError when the end of the connection is read, because
135  they can return an empty string for other reasons. See the
136  individual doc strings.
137 
138  read_until(expected, [timeout])
139  Read until the expected string has been seen, or a timeout is
140  hit (default is no timeout); may block.
141 
142  read_all()
143  Read all data until EOF; may block.
144 
145  read_some()
146  Read at least one byte or EOF; may block.
147 
148  read_very_eager()
149  Read all data available already queued or on the socket,
150  without blocking.
151 
152  read_eager()
153  Read either data already queued or some data available on the
154  socket, without blocking.
155 
156  read_lazy()
157  Read all data in the raw queue (processing it first), without
158  doing any socket I/O.
159 
160  read_very_lazy()
161  Reads all data in the cooked queue, without doing any socket
162  I/O.
163 
164  set_option_negotiation_callback(callback)
165  Each time a telnet option is read on the input flow, this callback
166  (if set) is called with the following parameters :
167  callback(telnet socket, command (DO/DONT/WILL/WONT), option)
168  No other action is done afterwards by telnetlib.
169 
170  """
171 
172  def __init__(self, host=None, port=0):
173  """Constructor.
174 
175  When called without arguments, create an unconnected instance.
176  With a hostname argument, it connects the instance; a port
177  number is optional.
178 
179  """
180  self.debuglevel = DEBUGLEVEL
181  self.host = host
182  self.port = port
183  self.sock = None
184  self.rawq = ''
185  self.irawq = 0
186  self.cookedq = ''
187  self.eof = 0
188  self.option_callback = None
189  if host:
190  self.open(host, port)
191 
192  def open(self, host, port=0):
193  """Connect to a host.
194 
195  The optional second argument is the port number, which
196  defaults to the standard telnet port (23).
197 
198  Don't try to reopen an already connected instance.
199 
200  """
201  self.eof = 0
202  if not port:
203  port = TELNET_PORT
204  self.host = host
205  self.port = port
206  msg = "getaddrinfo returns an empty list"
207  for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM):
208  af, socktype, proto, canonname, sa = res
209  try:
210  self.sock = socket.socket(af, socktype, proto)
211  self.sock.connect(sa)
212  except socket.error, msg:
213  if self.sock:
214  self.sock.close()
215  self.sock = None
216  continue
217  break
218  if not self.sock:
219  raise socket.error, msg
220 
221  def __del__(self):
222  """Destructor -- close the connection."""
223  self.close()
224 
225  def msg(self, msg, *args):
226  """Print a debug message, when the debug level is > 0.
227 
228  If extra arguments are present, they are substituted in the
229  message using the standard string formatting operator.
230 
231  """
232  if self.debuglevel > 0:
233  print 'Telnet(%s,%d):' % (self.host, self.port),
234  if args:
235  print msg % args
236  else:
237  print msg
238 
239  def set_debuglevel(self, debuglevel):
240  """Set the debug level.
241 
242  The higher it is, the more debug output you get (on sys.stdout).
243 
244  """
245  self.debuglevel = debuglevel
246 
247  def close(self):
248  """Close the connection."""
249  if self.sock:
250  self.sock.close()
251  self.sock = 0
252  self.eof = 1
253 
254  def get_socket(self):
255  """Return the socket object used internally."""
256  return self.sock
257 
258  def fileno(self):
259  """Return the fileno() of the socket object used internally."""
260  return self.sock.fileno()
261 
262  def write(self, buffer):
263  """Write a string to the socket, doubling any IAC characters.
264 
265  Can block if the connection is blocked. May raise
266  socket.error if the connection is closed.
267 
268  """
269  if IAC in buffer:
270  buffer = buffer.replace(IAC, IAC+IAC)
271  self.msg("send %s", `buffer`)
272  self.sock.sendall(buffer)
273 
274  def read_until(self, match, timeout=None):
275  """Read until a given string is encountered or until timeout.
276 
277  When no match is found, return whatever is available instead,
278  possibly the empty string. Raise EOFError if the connection
279  is closed and no cooked data is available.
280 
281  """
282  n = len(match)
283  self.process_rawq()
284  i = self.cookedq.find(match)
285  if i >= 0:
286  i = i+n
287  buf = self.cookedq[:i]
288  self.cookedq = self.cookedq[i:]
289  return buf
290  s_reply = ([self], [], [])
291  s_args = s_reply
292  if timeout is not None:
293  s_args = s_args + (timeout,)
294  while not self.eof and apply(select.select, s_args) == s_reply:
295  i = max(0, len(self.cookedq)-n)
296  self.fill_rawq()
297  self.process_rawq()
298  i = self.cookedq.find(match, i)
299  if i >= 0:
300  i = i+n
301  buf = self.cookedq[:i]
302  self.cookedq = self.cookedq[i:]
303  return buf
304  return self.read_very_lazy()
305 
306  def read_all(self):
307  """Read all data until EOF; block until connection closed."""
308  self.process_rawq()
309  while not self.eof:
310  self.fill_rawq()
311  self.process_rawq()
312  buf = self.cookedq
313  self.cookedq = ''
314  return buf
315 
316  def read_some(self):
317  """Read at least one byte of cooked data unless EOF is hit.
318 
319  Return '' if EOF is hit. Block if no data is immediately
320  available.
321 
322  """
323  self.process_rawq()
324  while not self.cookedq and not self.eof:
325  self.fill_rawq()
326  self.process_rawq()
327  buf = self.cookedq
328  self.cookedq = ''
329  return buf
330 
331  def read_very_eager(self):
332  """Read everything that's possible without blocking in I/O (eager).
333 
334  Raise EOFError if connection closed and no cooked data
335  available. Return '' if no cooked data available otherwise.
336  Don't block unless in the midst of an IAC sequence.
337 
338  """
339  self.process_rawq()
340  while not self.eof and self.sock_avail():
341  self.fill_rawq()
342  self.process_rawq()
343  return self.read_very_lazy()
344 
345  def read_eager(self):
346  """Read readily available data.
347 
348  Raise EOFError if connection closed and no cooked data
349  available. Return '' if no cooked data available otherwise.
350  Don't block unless in the midst of an IAC sequence.
351 
352  """
353  self.process_rawq()
354  while not self.cookedq and not self.eof and self.sock_avail():
355  self.fill_rawq()
356  self.process_rawq()
357  return self.read_very_lazy()
358 
359  def read_lazy(self):
360  """Process and return data that's already in the queues (lazy).
361 
362  Raise EOFError if connection closed and no data available.
363  Return '' if no cooked data available otherwise. Don't block
364  unless in the midst of an IAC sequence.
365 
366  """
367  self.process_rawq()
368  return self.read_very_lazy()
369 
370  def read_very_lazy(self):
371  """Return any data available in the cooked queue (very lazy).
372 
373  Raise EOFError if connection closed and no data available.
374  Return '' if no cooked data available otherwise. Don't block.
375 
376  """
377  buf = self.cookedq
378  self.cookedq = ''
379  if not buf and self.eof and not self.rawq:
380  raise EOFError, 'telnet connection closed'
381  return buf
382 
383  def set_option_negotiation_callback(self, callback):
384  """Provide a callback function called after each receipt of a telnet option."""
385  self.option_callback = callback
386 
387  def process_rawq(self):
388  """Transfer from raw queue to cooked queue.
389 
390  Set self.eof when connection is closed. Don't block unless in
391  the midst of an IAC sequence.
392 
393  """
394  buf = ''
395  try:
396  while self.rawq:
397  c = self.rawq_getchar()
398  if c == theNULL:
399  continue
400  if c == "\021":
401  continue
402  if c != IAC:
403  buf = buf + c
404  continue
405  c = self.rawq_getchar()
406  if c == IAC:
407  buf = buf + c
408  elif c in (DO, DONT):
409  opt = self.rawq_getchar()
410  self.msg('IAC %s %d', c == DO and 'DO' or 'DONT', ord(opt))
411  if self.option_callback:
412  self.option_callback(self.sock, c, opt)
413  else:
414  self.sock.sendall(IAC + WONT + opt)
415  elif c in (WILL, WONT):
416  opt = self.rawq_getchar()
417  self.msg('IAC %s %d',
418  c == WILL and 'WILL' or 'WONT', ord(opt))
419  if self.option_callback:
420  self.option_callback(self.sock, c, opt)
421  else:
422  self.sock.sendall(IAC + DONT + opt)
423  else:
424  self.msg('IAC %d not recognized' % ord(opt))
425  except EOFError: # raised by self.rawq_getchar()
426  pass
427  self.cookedq = self.cookedq + buf
428 
429  def rawq_getchar(self):
430  """Get next char from raw queue.
431 
432  Block if no data is immediately available. Raise EOFError
433  when connection is closed.
434 
435  """
436  if not self.rawq:
437  self.fill_rawq()
438  if self.eof:
439  raise EOFError
440  c = self.rawq[self.irawq]
441  self.irawq = self.irawq + 1
442  if self.irawq >= len(self.rawq):
443  self.rawq = ''
444  self.irawq = 0
445  return c
446 
447  def fill_rawq(self):
448  """Fill raw queue from exactly one recv() system call.
449 
450  Block if no data is immediately available. Set self.eof when
451  connection is closed.
452 
453  """
454  if self.irawq >= len(self.rawq):
455  self.rawq = ''
456  self.irawq = 0
457  # The buffer size should be fairly small so as to avoid quadratic
458  # behavior in process_rawq() above
459  buf = self.sock.recv(50)
460  self.msg("recv %s", `buf`)
461  self.eof = (not buf)
462  self.rawq = self.rawq + buf
463 
464  def sock_avail(self):
465  """Test whether data is available on the socket."""
466  return select.select([self], [], [], 0) == ([self], [], [])
467 
468  def interact(self):
469  """Interaction function, emulates a very dumb telnet client."""
470  if sys.platform == "win32":
471  self.mt_interact()
472  return
473  while 1:
474  rfd, wfd, xfd = select.select([self, sys.stdin], [], [])
475  if self in rfd:
476  try:
477  text = self.read_eager()
478  except EOFError:
479  print '*** Connection closed by remote host ***'
480  break
481  if text:
482  sys.stdout.write(text)
483  sys.stdout.flush()
484  if sys.stdin in rfd:
485  line = sys.stdin.readline()
486  if not line:
487  break
488  self.write(line)
489 
490  def mt_interact(self):
491  """Multithreaded version of interact()."""
492  import thread
493  thread.start_new_thread(self.listener, ())
494  while 1:
495  line = sys.stdin.readline()
496  if not line:
497  break
498  self.write(line)
499 
500  def listener(self):
501  """Helper for mt_interact() -- this executes in the other thread."""
502  while 1:
503  try:
504  data = self.read_eager()
505  except EOFError:
506  print '*** Connection closed by remote host ***'
507  return
508  if data:
509  sys.stdout.write(data)
510  else:
511  sys.stdout.flush()
512 
513  def expect(self, list, timeout=None):
514  """Read until one from a list of a regular expressions matches.
515 
516  The first argument is a list of regular expressions, either
517  compiled (re.RegexObject instances) or uncompiled (strings).
518  The optional second argument is a timeout, in seconds; default
519  is no timeout.
520 
521  Return a tuple of three items: the index in the list of the
522  first regular expression that matches; the match object
523  returned; and the text read up till and including the match.
524 
525  If EOF is read and no text was read, raise EOFError.
526  Otherwise, when nothing matches, return (-1, None, text) where
527  text is the text received so far (may be the empty string if a
528  timeout happened).
529 
530  If a regular expression ends with a greedy match (e.g. '.*')
531  or if more than one expression can match the same input, the
532  results are undeterministic, and may depend on the I/O timing.
533 
534  """
535  re = None
536  list = list[:]
537  indices = range(len(list))
538  for i in indices:
539  if not hasattr(list[i], "search"):
540  if not re: import re
541  list[i] = re.compile(list[i])
542  while 1:
543  self.process_rawq()
544  for i in indices:
545  m = list[i].search(self.cookedq)
546  if m:
547  e = m.end()
548  text = self.cookedq[:e]
549  self.cookedq = self.cookedq[e:]
550  return (i, m, text)
551  if self.eof:
552  break
553  if timeout is not None:
554  r, w, x = select.select([self.fileno()], [], [], timeout)
555  if not r:
556  break
557  self.fill_rawq()
558  text = self.read_very_lazy()
559  if not text and self.eof:
560  raise EOFError
561  return (-1, None, text)
562 
563 
564 def test():
565  """Test program for telnetlib.
566 
567  Usage: python telnetlib.py [-d] ... [host [port]]
568 
569  Default host is localhost; default port is 23.
570 
571  """
572  debuglevel = 0
573  while sys.argv[1:] and sys.argv[1] == '-d':
574  debuglevel = debuglevel+1
575  del sys.argv[1]
576  host = 'localhost'
577  if sys.argv[1:]:
578  host = sys.argv[1]
579  port = 0
580  if sys.argv[2:]:
581  portstr = sys.argv[2]
582  try:
583  port = int(portstr)
584  except ValueError:
585  port = socket.getservbyname(portstr, 'tcp')
586  tn = Telnet()
587  tn.set_debuglevel(debuglevel)
588  tn.open(host, port)
589  tn.interact()
590  tn.close()
591 
592 if __name__ == '__main__':
593  test()