Initial revision
diff --git a/Demo/cwilib/telnetlib.py b/Demo/cwilib/telnetlib.py
new file mode 100755
index 0000000..5c862e7
--- /dev/null
+++ b/Demo/cwilib/telnetlib.py
@@ -0,0 +1,181 @@
+# Telnet client library
+
+import socket
+import select
+import string
+import regsub
+
+# Tunable parameters
+TIMEOUT = 30.0
+DEBUGLEVEL = 1
+
+# 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, port):
+		self.debuglevel = DEBUGLEVEL
+		self.host = host
+		if not port: port = TELNET_PORT
+		self.port = port
+		self.timeout = TIMEOUT
+		self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+		self.sock.connect((self.host, self.port))
+		self.rawq = ''
+		self.irawq = 0
+		self.cookedq = ''
+
+	# Destructor
+	def __del__(self):
+		self.close()
+
+	# Print debug message
+	def msg(self, msg, *args):
+		if self.debuglevel > 0:
+			print 'TELNET:', msg%args
+
+	# Set debug level
+	def set_debuglevel(self, debuglevel):
+		self.debuglevel = debuglevel
+
+	# Set time-out on certain reads
+	def set_timeout(self, timeout):
+		self.timeout = float(timeout)
+
+	# Explicit close
+	def close(self):
+		if self.sock:
+			self.sock.close()
+		self.sock = None
+
+	# 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
+	def write(self, buffer):
+		if IAC in buffer:
+			buffer = regsub.gsub(IAC, IAC+IAC, buffer)
+		self.sock.send(buffer)
+
+	# Read until a given string is encountered or until timeout
+	def read_until(self, match):
+##		self.msg('read_until(%s)' % `match`)
+		n = len(match)
+		self.process_rawq()
+		i = string.find(self.cookedq, match)
+		if i < 0:
+			i = max(0, len(self.cookedq)-n)
+			self.fill_cookedq()
+			i = string.find(self.cookedq, match, i)
+		if i >= 0:
+			i = i+n
+			buf = self.cookedq[:i]
+			self.cookedq = self.cookedq[i:]
+##			self.msg('read_until(%s) -> %s' % (`match`, `buf`))
+			return buf
+		while select.select([self], [], [], self.timeout) == \
+			  ([self], [], []):
+			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:]
+##				self.msg('read_until(%s) -> %s' %
+##					  (`match`, `buf`))
+				return buf
+		buf = self.cookedq
+		self.cookedq = ''
+##		self.msg('read_until(%s) -> %s' % (`match`, `buf`))
+		return buf
+
+	# Read everything that's possible without really blocking
+	def read_now(self):
+		self.fill_cookedq()
+		buf = self.cookedq
+		self.cookedq = ''
+##		self.msg('read_now() --> %s' % `buf`)
+		return buf
+
+	# Fill cooked queue without blocking
+	def fill_cookedq(self):
+		self.process_rawq()
+		while select.select([self], [], [], 0) == ([self], [], []):
+			self.fill_rawq()
+			if not self.rawq:
+				raise EOFError
+			self.process_rawq()
+
+	# Transfer from raw queue to cooked queue
+	def process_rawq(self):
+		# There is some silliness going on here in an attempt
+		# to avoid quadratic behavior with large inputs...
+		buf = ''
+		while self.rawq:
+			c = self.rawq_getchar()
+			if c != IAC:
+				buf = buf + c
+				if len(buf) >= 44:
+##					self.msg('transfer: %s' % `buf`)
+					self.cookedq = self.cookedq + buf
+					buf = ''
+				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`)
+##		self.msg('transfer: %s' % `buf`)
+		self.cookedq = self.cookedq + buf
+
+	# Get next char from raw queue, blocking if necessary
+	def rawq_getchar(self):
+		if not self.rawq:
+			self.fill_rawq()
+		if self.irawq >= len(self.rawq):
+			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
+	def fill_rawq(self):
+		if self.irawq >= len(self.rawq):
+			self.rawq = ''
+			self.irawq = 0
+		buf = self.sock.recv(50)
+##		self.msg('fill_rawq(): %s' % `buf`)
+		self.rawq = self.rawq + buf