diff options
Diffstat (limited to 'Demo/cwilib/telnetlib.py')
-rwxr-xr-x | Demo/cwilib/telnetlib.py | 321 |
1 files changed, 0 insertions, 321 deletions
diff --git a/Demo/cwilib/telnetlib.py b/Demo/cwilib/telnetlib.py deleted file mode 100755 index 3a48a79..0000000 --- a/Demo/cwilib/telnetlib.py +++ /dev/null @@ -1,321 +0,0 @@ -# A TELNET client class. Based on RFC 854: TELNET Protocol -# Specification, by J. Postel and J. Reynolds - - -# Example: -# -# >>> from telnetlib import Telnet -# >>> tn = Telnet('voorn.cwi.nl', 79) # connect to finger port -# >>> tn.write('guido\r\n') -# >>> print tn.read_all() -# Login name: guido In real life: Guido van Rossum -# Office: M353, x4127 Home phone: 020-6225521 -# Directory: /ufs/guido Shell: /usr/local/bin/esh -# On since Oct 28 11:02:16 on ttyq1 -# Project: Multimedia Kernel Systems -# No Plan. -# >>> -# -# Note that read() won't read until eof -- it just reads some data -# (but it guarantees to read at least one byte unless EOF is hit). -# -# It is possible to pass a Telnet object to select.select() in order -# to wait until more data is available. Note that in this case, -# read_eager() may return '' even if there was data on the socket, -# because the protocol negotiation may have eaten the data. -# This is why EOFError is needed to distinguish between "no data" -# and "connection closed" (since the socket also appears ready for -# reading when it is closed). -# -# Bugs: -# - may hang when connection is slow in the middle of an IAC sequence -# -# To do: -# - option negotiation - - -# Imported modules -import socket -import select -import string -import regsub - -# Tunable parameters -DEBUGLEVEL = 0 - -# Telnet protocol defaults -TELNET_PORT = 23 - -# Telnet protocol characters (don't change) -IAC = chr(255) # "Interpret As Command" -DONT = chr(254) -DO = chr(253) -WONT = chr(252) -WILL = chr(251) - - -# Telnet interface class - -class Telnet: - - # Constructor - def __init__(self, host, *args): - if not args: - port = TELNET_PORT - else: - if len(args) > 1: raise TypeError, 'too many args' - port = args[0] - if not port: port = TELNET_PORT - self.debuglevel = DEBUGLEVEL - self.host = host - self.port = port - self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.sock.connect((self.host, self.port)) - self.rawq = '' - self.irawq = 0 - self.cookedq = '' - self.eof = 0 - - # Destructor - def __del__(self): - self.close() - - # Debug message - def msg(self, msg, *args): - if self.debuglevel > 0: - print 'Telnet(%s,%d):' % (self.host, self.port), msg % args - - # Set debug level - def set_debuglevel(self, debuglevel): - self.debuglevel = debuglevel - - # Explicit close - def close(self): - if self.sock: - self.sock.close() - self.sock = None - self.eof = 1 - - # Return socket (e.g. for select) - def get_socket(self): - return self.sock - - # Return socket's fileno (e.g. for select) - def fileno(self): - return self.sock.fileno() - - # Write a string to the socket, doubling any IAC characters - # Might block if the connection is blocked - # May raise socket.error if the connection is closed - def write(self, buffer): - if IAC in buffer: - buffer = regsub.gsub(IAC, IAC+IAC, buffer) - self.sock.send(buffer) - - # The following read_* methods exist: - # Special case: - # - read_until() reads until a string is encountered or a timeout is hit - # These may block: - # - read_all() reads all data until EOF - # - read_some() reads at least one byte until EOF - # These may do I/O but won't block doing it: - # - read_very_eager() reads all data available on the socket - # - read_eager() reads either data already queued or some data - # available on the socket - # These don't do I/O: - # - read_lazy() reads all data in the raw queue (processing it first) - # - read_very_lazy() reads all data in the cooked queue - - # Read until a given string is encountered or until timeout - # Raise EOFError if connection closed and no cooked data available - # Return '' if no cooked data available otherwise - def read_until(self, match, *args): - if not args: - timeout = None - else: - if len(args) > 1: raise TypeError, 'too many args' - timeout = args[0] - n = len(match) - self.process_rawq() - i = string.find(self.cookedq, match) - if i >= 0: - i = i+n - buf = self.cookedq[:i] - self.cookedq = self.cookedq[i:] - return buf - s_reply = ([self], [], []) - s_args = s_reply - if timeout is not None: - s_args = s_args + (timeout,) - while not self.eof and apply(select.select, s_args) == s_reply: - i = max(0, len(self.cookedq)-n) - self.fill_rawq() - self.process_rawq() - i = string.find(self.cookedq, match, i) - if i >= 0: - i = i+n - buf = self.cookedq[:i] - self.cookedq = self.cookedq[i:] - return buf - return self.read_very_lazy() - - # Read all data until EOF - # Block until connection closed - def read_all(self): - self.process_rawq() - while not self.eof: - self.fill_rawq() - self.process_rawq() - buf = self.cookedq - self.cookedq = '' - return buf - - # Read at least one byte of cooked data unless EOF is hit - # Return '' if EOF is hit - # Block if no data is immediately available - def read_some(self): - self.process_rawq() - while not self.cookedq and not self.eof: - self.fill_rawq() - self.process_rawq() - buf = self.cookedq - self.cookedq = '' - return buf - - # Read everything that's possible without blocking in I/O (eager) - # Raise EOFError if connection closed and no cooked data available - # Return '' if no cooked data available otherwise - # Don't block unless in the midst of an IAC sequence - def read_very_eager(self): - self.process_rawq() - while not self.eof and self.sock_avail(): - self.fill_rawq() - self.process_rawq() - return self.read_very_lazy() - - # Read readily available data - # Raise EOFError if connection closed and no cooked data available - # Return '' if no cooked data available otherwise - # Don't block unless in the midst of an IAC sequence - def read_eager(self): - self.process_rawq() - while not self.cookedq and not self.eof and self.sock_avail(): - self.fill_rawq() - self.process_rawq() - return self.read_very_lazy() - - # Process and return data that's already in the queues (lazy) - # Raise EOFError if connection closed and no data available - # Return '' if no cooked data available otherwise - # Don't block unless in the midst of an IAC sequence - def read_lazy(self): - self.process_rawq() - return self.read_very_lazy() - - # Return any data available in the cooked queue (very lazy) - # Raise EOFError if connection closed and no data available - # Return '' if no cooked data available otherwise - # Don't block - def read_very_lazy(self): - buf = self.cookedq - self.cookedq = '' - if not buf and self.eof and not self.rawq: - raise EOFError, 'telnet connection closed' - return buf - - # Transfer from raw queue to cooked queue - # Set self.eof when connection is closed - # Don't block unless in the midst of an IAC sequence - def process_rawq(self): - buf = '' - try: - while self.rawq: - c = self.rawq_getchar() - if c != IAC: - buf = buf + c - continue - c = self.rawq_getchar() - if c == IAC: - buf = buf + c - elif c in (DO, DONT): - opt = self.rawq_getchar() - self.msg('IAC %s %d', c == DO and 'DO' or 'DONT', ord(c)) - self.sock.send(IAC + WONT + opt) - elif c in (WILL, WONT): - opt = self.rawq_getchar() - self.msg('IAC %s %d', - c == WILL and 'WILL' or 'WONT', ord(c)) - else: - self.msg('IAC %s not recognized' % `c`) - except EOFError: # raised by self.rawq_getchar() - pass - self.cookedq = self.cookedq + buf - - # Get next char from raw queue - # Block if no data is immediately available - # Raise EOFError when connection is closed - def rawq_getchar(self): - if not self.rawq: - self.fill_rawq() - if self.eof: - raise EOFError - c = self.rawq[self.irawq] - self.irawq = self.irawq + 1 - if self.irawq >= len(self.rawq): - self.rawq = '' - self.irawq = 0 - return c - - # Fill raw queue from exactly one recv() system call - # Block if no data is immediately available - # Set self.eof when connection is closed - def fill_rawq(self): - if self.irawq >= len(self.rawq): - self.rawq = '' - self.irawq = 0 - # The buffer size should be fairly small so as to avoid quadratic - # behavior in process_rawq() above - buf = self.sock.recv(50) - self.eof = (not buf) - self.rawq = self.rawq + buf - - # Test whether data is available on the socket - def sock_avail(self): - return select.select([self], [], [], 0) == ([self], [], []) - - -# Test program -# Usage: test [-d] ... [host [port]] -def test(): - import sys, string, socket, select - debuglevel = 0 - while sys.argv[1:] and sys.argv[1] == '-d': - debuglevel = debuglevel+1 - del sys.argv[1] - host = 'localhost' - if sys.argv[1:]: - host = sys.argv[1] - port = 0 - if sys.argv[2:]: - portstr = sys.argv[2] - try: - port = string.atoi(portstr) - except string.atoi_error: - port = socket.getservbyname(portstr, 'tcp') - tn = Telnet(host, port) - tn.set_debuglevel(debuglevel) - while 1: - rfd, wfd, xfd = select.select([tn, sys.stdin], [], []) - if sys.stdin in rfd: - line = sys.stdin.readline() - tn.write(line) - if tn in rfd: - try: - text = tn.read_eager() - except EOFError: - print '*** Connection closed by remote host ***' - break - if text: - sys.stdout.write(text) - sys.stdout.flush() - tn.close() |