blob: 5bac9e770cb73697878e08ab1d7b189d887eea4a [file] [log] [blame]
Guido van Rossumb9b50eb1997-12-24 21:07:04 +00001"""TELNET client class.
2
3Based on RFC 854: TELNET Protocol Specification, by J. Postel and
4J. Reynolds
5
6Example:
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()
12Login Name TTY Idle When Where
13guido Guido van Rossum pts/2 <Dec 2 11:10> snag.cnri.reston..
Tim Petersb90f89a2001-01-15 03:26:36 +000014
Guido van Rossumb9b50eb1997-12-24 21:07:04 +000015>>>
16
17Note 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
20It is possible to pass a Telnet object to select.select() in order to
21wait until more data is available. Note that in this case,
22read_eager() may return '' even if there was data on the socket,
23because the protocol negotiation may have eaten the data. This is why
24EOFError is needed in some cases to distinguish between "no data" and
25"connection closed" (since the socket also appears ready for reading
26when it is closed).
27
28Bugs:
29- may hang when connection is slow in the middle of an IAC sequence
30
31To do:
32- option negotiation
Guido van Rossumccb5ec61997-12-24 22:24:19 +000033- timeout should be intrinsic to the connection object instead of an
34 option on one of the read calls only
Guido van Rossumb9b50eb1997-12-24 21:07:04 +000035
36"""
37
38
39# Imported modules
Guido van Rossumccb5ec61997-12-24 22:24:19 +000040import sys
Guido van Rossumb9b50eb1997-12-24 21:07:04 +000041import socket
42import select
Guido van Rossumb9b50eb1997-12-24 21:07:04 +000043
Skip Montanaro40fc1602001-03-01 04:27:19 +000044__all__ = ["Telnet"]
45
Guido van Rossumb9b50eb1997-12-24 21:07:04 +000046# Tunable parameters
47DEBUGLEVEL = 0
48
49# Telnet protocol defaults
50TELNET_PORT = 23
51
52# Telnet protocol characters (don't change)
53IAC = chr(255) # "Interpret As Command"
54DONT = chr(254)
55DO = chr(253)
56WONT = chr(252)
57WILL = chr(251)
58theNULL = chr(0)
59
60
61class Telnet:
62
63 """Telnet interface class.
64
65 An instance of this class represents a connection to a telnet
66 server. The instance is initially not connected; the open()
67 method must be used to establish a connection. Alternatively, the
68 host name and optional port number can be passed to the
69 constructor, too.
70
71 Don't try to reopen an already connected instance.
72
73 This class has many read_*() methods. Note that some of them
74 raise EOFError when the end of the connection is read, because
75 they can return an empty string for other reasons. See the
76 individual doc strings.
77
78 read_until(expected, [timeout])
79 Read until the expected string has been seen, or a timeout is
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000080 hit (default is no timeout); may block.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +000081
82 read_all()
83 Read all data until EOF; may block.
84
85 read_some()
86 Read at least one byte or EOF; may block.
87
88 read_very_eager()
89 Read all data available already queued or on the socket,
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000090 without blocking.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +000091
92 read_eager()
93 Read either data already queued or some data available on the
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000094 socket, without blocking.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +000095
96 read_lazy()
97 Read all data in the raw queue (processing it first), without
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000098 doing any socket I/O.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +000099
100 read_very_lazy()
101 Reads all data in the cooked queue, without doing any socket
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000102 I/O.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000103
104 """
105
106 def __init__(self, host=None, port=0):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000107 """Constructor.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000108
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000109 When called without arguments, create an unconnected instance.
110 With a hostname argument, it connects the instance; a port
111 number is optional.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000112
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000113 """
114 self.debuglevel = DEBUGLEVEL
115 self.host = host
116 self.port = port
117 self.sock = None
118 self.rawq = ''
119 self.irawq = 0
120 self.cookedq = ''
121 self.eof = 0
122 if host:
123 self.open(host, port)
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000124
125 def open(self, host, port=0):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000126 """Connect to a host.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000127
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000128 The optional second argument is the port number, which
129 defaults to the standard telnet port (23).
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000130
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000131 Don't try to reopen an already connected instance.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000132
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000133 """
134 self.eof = 0
135 if not port:
136 port = TELNET_PORT
137 self.host = host
138 self.port = port
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000139 for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM):
140 af, socktype, proto, canonname, sa = res
141 try:
142 self.sock = socket.socket(af, socktype, proto)
143 self.sock.connect(sa)
144 except socket.error, msg:
145 self.sock.close()
146 self.sock = None
147 continue
148 break
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000149 if not self.sock:
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000150 raise socket.error, msg
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000151
152 def __del__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000153 """Destructor -- close the connection."""
154 self.close()
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000155
156 def msg(self, msg, *args):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000157 """Print a debug message, when the debug level is > 0.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000158
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000159 If extra arguments are present, they are substituted in the
160 message using the standard string formatting operator.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000161
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000162 """
163 if self.debuglevel > 0:
164 print 'Telnet(%s,%d):' % (self.host, self.port),
165 if args:
166 print msg % args
167 else:
168 print msg
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000169
170 def set_debuglevel(self, debuglevel):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000171 """Set the debug level.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000172
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000173 The higher it is, the more debug output you get (on sys.stdout).
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000174
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000175 """
176 self.debuglevel = debuglevel
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000177
178 def close(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000179 """Close the connection."""
180 if self.sock:
181 self.sock.close()
182 self.sock = 0
183 self.eof = 1
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000184
185 def get_socket(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000186 """Return the socket object used internally."""
187 return self.sock
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000188
189 def fileno(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000190 """Return the fileno() of the socket object used internally."""
191 return self.sock.fileno()
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000192
193 def write(self, buffer):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000194 """Write a string to the socket, doubling any IAC characters.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000195
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000196 Can block if the connection is blocked. May raise
197 socket.error if the connection is closed.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000198
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000199 """
200 if IAC in buffer:
Eric S. Raymond6b8c5282001-02-09 07:10:12 +0000201 buffer = buffer.replace(IAC, IAC+IAC)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000202 self.msg("send %s", `buffer`)
203 self.sock.send(buffer)
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000204
205 def read_until(self, match, timeout=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000206 """Read until a given string is encountered or until timeout.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000207
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000208 When no match is found, return whatever is available instead,
209 possibly the empty string. Raise EOFError if the connection
210 is closed and no cooked data is available.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000211
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000212 """
213 n = len(match)
214 self.process_rawq()
Eric S. Raymond6b8c5282001-02-09 07:10:12 +0000215 i = self.cookedq.find(match)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000216 if i >= 0:
217 i = i+n
218 buf = self.cookedq[:i]
219 self.cookedq = self.cookedq[i:]
220 return buf
221 s_reply = ([self], [], [])
222 s_args = s_reply
223 if timeout is not None:
224 s_args = s_args + (timeout,)
225 while not self.eof and apply(select.select, s_args) == s_reply:
226 i = max(0, len(self.cookedq)-n)
227 self.fill_rawq()
228 self.process_rawq()
Eric S. Raymond6b8c5282001-02-09 07:10:12 +0000229 i = self.cookedq.find(match, i)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000230 if i >= 0:
231 i = i+n
232 buf = self.cookedq[:i]
233 self.cookedq = self.cookedq[i:]
234 return buf
235 return self.read_very_lazy()
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000236
237 def read_all(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000238 """Read all data until EOF; block until connection closed."""
239 self.process_rawq()
240 while not self.eof:
241 self.fill_rawq()
242 self.process_rawq()
243 buf = self.cookedq
244 self.cookedq = ''
245 return buf
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000246
247 def read_some(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000248 """Read at least one byte of cooked data unless EOF is hit.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000249
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000250 Return '' if EOF is hit. Block if no data is immediately
251 available.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000252
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000253 """
254 self.process_rawq()
255 while not self.cookedq and not self.eof:
256 self.fill_rawq()
257 self.process_rawq()
258 buf = self.cookedq
259 self.cookedq = ''
260 return buf
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000261
262 def read_very_eager(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000263 """Read everything that's possible without blocking in I/O (eager).
Tim Petersb90f89a2001-01-15 03:26:36 +0000264
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000265 Raise EOFError if connection closed and no cooked data
266 available. Return '' if no cooked data available otherwise.
267 Don't block unless in the midst of an IAC sequence.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000268
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000269 """
270 self.process_rawq()
271 while not self.eof and self.sock_avail():
272 self.fill_rawq()
273 self.process_rawq()
274 return self.read_very_lazy()
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000275
276 def read_eager(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000277 """Read readily available data.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000278
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000279 Raise EOFError if connection closed and no cooked data
280 available. Return '' if no cooked data available otherwise.
281 Don't block unless in the midst of an IAC sequence.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000282
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000283 """
284 self.process_rawq()
285 while not self.cookedq and not self.eof and self.sock_avail():
286 self.fill_rawq()
287 self.process_rawq()
288 return self.read_very_lazy()
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000289
290 def read_lazy(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000291 """Process and return data that's already in the queues (lazy).
Tim Petersb90f89a2001-01-15 03:26:36 +0000292
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000293 Raise EOFError if connection closed and no data available.
294 Return '' if no cooked data available otherwise. Don't block
295 unless in the midst of an IAC sequence.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000296
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000297 """
298 self.process_rawq()
299 return self.read_very_lazy()
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000300
301 def read_very_lazy(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000302 """Return any data available in the cooked queue (very lazy).
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000303
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000304 Raise EOFError if connection closed and no data available.
305 Return '' if no cooked data available otherwise. Don't block.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000306
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000307 """
308 buf = self.cookedq
309 self.cookedq = ''
310 if not buf and self.eof and not self.rawq:
311 raise EOFError, 'telnet connection closed'
312 return buf
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000313
314 def process_rawq(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000315 """Transfer from raw queue to cooked queue.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000316
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000317 Set self.eof when connection is closed. Don't block unless in
318 the midst of an IAC sequence.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000319
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000320 """
321 buf = ''
322 try:
323 while self.rawq:
324 c = self.rawq_getchar()
325 if c == theNULL:
326 continue
327 if c == "\021":
328 continue
329 if c != IAC:
330 buf = buf + c
331 continue
332 c = self.rawq_getchar()
333 if c == IAC:
334 buf = buf + c
335 elif c in (DO, DONT):
336 opt = self.rawq_getchar()
337 self.msg('IAC %s %d', c == DO and 'DO' or 'DONT', ord(c))
338 self.sock.send(IAC + WONT + opt)
339 elif c in (WILL, WONT):
340 opt = self.rawq_getchar()
341 self.msg('IAC %s %d',
342 c == WILL and 'WILL' or 'WONT', ord(c))
Guido van Rossum823eb4b2000-05-02 14:32:11 +0000343 self.sock.send(IAC + DONT + opt)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000344 else:
345 self.msg('IAC %s not recognized' % `c`)
346 except EOFError: # raised by self.rawq_getchar()
347 pass
348 self.cookedq = self.cookedq + buf
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000349
350 def rawq_getchar(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000351 """Get next char from raw queue.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000352
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000353 Block if no data is immediately available. Raise EOFError
354 when connection is closed.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000355
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000356 """
357 if not self.rawq:
358 self.fill_rawq()
359 if self.eof:
360 raise EOFError
361 c = self.rawq[self.irawq]
362 self.irawq = self.irawq + 1
363 if self.irawq >= len(self.rawq):
364 self.rawq = ''
365 self.irawq = 0
366 return c
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000367
368 def fill_rawq(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000369 """Fill raw queue from exactly one recv() system call.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000370
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000371 Block if no data is immediately available. Set self.eof when
372 connection is closed.
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000373
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000374 """
375 if self.irawq >= len(self.rawq):
376 self.rawq = ''
377 self.irawq = 0
378 # The buffer size should be fairly small so as to avoid quadratic
379 # behavior in process_rawq() above
380 buf = self.sock.recv(50)
381 self.msg("recv %s", `buf`)
382 self.eof = (not buf)
383 self.rawq = self.rawq + buf
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000384
385 def sock_avail(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000386 """Test whether data is available on the socket."""
387 return select.select([self], [], [], 0) == ([self], [], [])
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000388
389 def interact(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000390 """Interaction function, emulates a very dumb telnet client."""
Guido van Rossum82eae9e1998-12-23 23:04:17 +0000391 if sys.platform == "win32":
392 self.mt_interact()
393 return
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000394 while 1:
395 rfd, wfd, xfd = select.select([self, sys.stdin], [], [])
396 if self in rfd:
397 try:
398 text = self.read_eager()
399 except EOFError:
400 print '*** Connection closed by remote host ***'
401 break
402 if text:
403 sys.stdout.write(text)
404 sys.stdout.flush()
405 if sys.stdin in rfd:
406 line = sys.stdin.readline()
407 if not line:
408 break
409 self.write(line)
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000410
Guido van Rossum82eae9e1998-12-23 23:04:17 +0000411 def mt_interact(self):
412 """Multithreaded version of interact()."""
413 import thread
414 thread.start_new_thread(self.listener, ())
415 while 1:
416 line = sys.stdin.readline()
417 if not line:
418 break
419 self.write(line)
420
421 def listener(self):
422 """Helper for mt_interact() -- this executes in the other thread."""
423 while 1:
424 try:
425 data = self.read_eager()
426 except EOFError:
427 print '*** Connection closed by remote host ***'
428 return
429 if data:
430 sys.stdout.write(data)
431 else:
432 sys.stdout.flush()
433
Guido van Rossumccb5ec61997-12-24 22:24:19 +0000434 def expect(self, list, timeout=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000435 """Read until one from a list of a regular expressions matches.
Guido van Rossumccb5ec61997-12-24 22:24:19 +0000436
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000437 The first argument is a list of regular expressions, either
438 compiled (re.RegexObject instances) or uncompiled (strings).
439 The optional second argument is a timeout, in seconds; default
440 is no timeout.
Guido van Rossumccb5ec61997-12-24 22:24:19 +0000441
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000442 Return a tuple of three items: the index in the list of the
443 first regular expression that matches; the match object
444 returned; and the text read up till and including the match.
Guido van Rossumccb5ec61997-12-24 22:24:19 +0000445
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000446 If EOF is read and no text was read, raise EOFError.
447 Otherwise, when nothing matches, return (-1, None, text) where
448 text is the text received so far (may be the empty string if a
449 timeout happened).
Guido van Rossumccb5ec61997-12-24 22:24:19 +0000450
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000451 If a regular expression ends with a greedy match (e.g. '.*')
452 or if more than one expression can match the same input, the
453 results are undeterministic, and may depend on the I/O timing.
Guido van Rossumccb5ec61997-12-24 22:24:19 +0000454
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000455 """
456 re = None
457 list = list[:]
458 indices = range(len(list))
459 for i in indices:
460 if not hasattr(list[i], "search"):
461 if not re: import re
462 list[i] = re.compile(list[i])
463 while 1:
464 self.process_rawq()
465 for i in indices:
466 m = list[i].search(self.cookedq)
467 if m:
468 e = m.end()
469 text = self.cookedq[:e]
470 self.cookedq = self.cookedq[e:]
471 return (i, m, text)
472 if self.eof:
473 break
474 if timeout is not None:
475 r, w, x = select.select([self.fileno()], [], [], timeout)
476 if not r:
477 break
478 self.fill_rawq()
479 text = self.read_very_lazy()
480 if not text and self.eof:
481 raise EOFError
482 return (-1, None, text)
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000483
484
485def test():
486 """Test program for telnetlib.
487
488 Usage: python telnetlib.py [-d] ... [host [port]]
489
490 Default host is localhost; default port is 23.
491
492 """
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000493 debuglevel = 0
494 while sys.argv[1:] and sys.argv[1] == '-d':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000495 debuglevel = debuglevel+1
496 del sys.argv[1]
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000497 host = 'localhost'
498 if sys.argv[1:]:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000499 host = sys.argv[1]
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000500 port = 0
501 if sys.argv[2:]:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000502 portstr = sys.argv[2]
503 try:
504 port = int(portstr)
505 except ValueError:
506 port = socket.getservbyname(portstr, 'tcp')
Guido van Rossumb9b50eb1997-12-24 21:07:04 +0000507 tn = Telnet()
508 tn.set_debuglevel(debuglevel)
509 tn.open(host, port)
510 tn.interact()
511 tn.close()
512
513if __name__ == '__main__':
514 test()