blob: 4595426055fddfc7930bc76f92711e8737eb0f36 [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..
14
15>>>
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
33
34"""
35
36
37# Imported modules
38import socket
39import select
40import string
41import regsub
42
43# Tunable parameters
44DEBUGLEVEL = 0
45
46# Telnet protocol defaults
47TELNET_PORT = 23
48
49# Telnet protocol characters (don't change)
50IAC = chr(255) # "Interpret As Command"
51DONT = chr(254)
52DO = chr(253)
53WONT = chr(252)
54WILL = chr(251)
55theNULL = chr(0)
56
57
58class Telnet:
59
60 """Telnet interface class.
61
62 An instance of this class represents a connection to a telnet
63 server. The instance is initially not connected; the open()
64 method must be used to establish a connection. Alternatively, the
65 host name and optional port number can be passed to the
66 constructor, too.
67
68 Don't try to reopen an already connected instance.
69
70 This class has many read_*() methods. Note that some of them
71 raise EOFError when the end of the connection is read, because
72 they can return an empty string for other reasons. See the
73 individual doc strings.
74
75 read_until(expected, [timeout])
76 Read until the expected string has been seen, or a timeout is
77 hit (default is no timeout); may block.
78
79 read_all()
80 Read all data until EOF; may block.
81
82 read_some()
83 Read at least one byte or EOF; may block.
84
85 read_very_eager()
86 Read all data available already queued or on the socket,
87 without blocking.
88
89 read_eager()
90 Read either data already queued or some data available on the
91 socket, without blocking.
92
93 read_lazy()
94 Read all data in the raw queue (processing it first), without
95 doing any socket I/O.
96
97 read_very_lazy()
98 Reads all data in the cooked queue, without doing any socket
99 I/O.
100
101 """
102
103 def __init__(self, host=None, port=0):
104 """Constructor.
105
106 When called without arguments, create an unconnected instance.
107 With a hostname argument, it connects the instance; a port
108 number is optional.
109
110 """
111 self.debuglevel = DEBUGLEVEL
112 self.host = host
113 self.port = port
114 self.sock = None
115 self.rawq = ''
116 self.irawq = 0
117 self.cookedq = ''
118 self.eof = 0
119 if host:
120 self.open(host, port)
121
122 def open(self, host, port=0):
123 """Connect to a host.
124
125 The optional second argument is the port number, which
126 defaults to the standard telnet port (23).
127
128 Don't try to reopen an already connected instance.
129
130 """
131 self.eof = 0
132 if not port:
133 port = TELNET_PORT
134 self.host = host
135 self.port = port
136 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
137 self.sock.connect((self.host, self.port))
138
139 def __del__(self):
140 """Destructor -- close the connection."""
141 self.close()
142
143 def msg(self, msg, *args):
144 """Print a debug message, when the debug level is > 0.
145
146 If extra arguments are present, they are substituted in the
147 message using the standard string formatting operator.
148
149 """
150 if self.debuglevel > 0:
151 print 'Telnet(%s,%d):' % (self.host, self.port),
152 if args:
153 print msg % args
154 else:
155 print msg
156
157 def set_debuglevel(self, debuglevel):
158 """Set the debug level.
159
160 The higher it is, the more debug output you get (on sys.stdout).
161
162 """
163 self.debuglevel = debuglevel
164
165 def close(self):
166 """Close the connection."""
167 if self.sock:
168 self.sock.close()
169 self.sock = 0
170 self.eof = 1
171
172 def get_socket(self):
173 """Return the socket object used internally."""
174 return self.sock
175
176 def fileno(self):
177 """Return the fileno() of the socket object used internally."""
178 return self.sock.fileno()
179
180 def write(self, buffer):
181 """Write a string to the socket, doubling any IAC characters.
182
183 Can block if the connection is blocked. May raise
184 socket.error if the connection is closed.
185
186 """
187 if IAC in buffer:
188 buffer = regsub.gsub(IAC, IAC+IAC, buffer)
189 self.sock.send(buffer)
190
191 def read_until(self, match, timeout=None):
192 """Read until a given string is encountered or until timeout.
193
194 When no match is found, return whatever is available instead,
195 possibly the empty string. Raise EOFError if the connection
196 is closed and no cooked data is available.
197
198 """
199 n = len(match)
200 self.process_rawq()
201 i = string.find(self.cookedq, match)
202 if i >= 0:
203 i = i+n
204 buf = self.cookedq[:i]
205 self.cookedq = self.cookedq[i:]
206 return buf
207 s_reply = ([self], [], [])
208 s_args = s_reply
209 if timeout is not None:
210 s_args = s_args + (timeout,)
211 while not self.eof and apply(select.select, s_args) == s_reply:
212 i = max(0, len(self.cookedq)-n)
213 self.fill_rawq()
214 self.process_rawq()
215 i = string.find(self.cookedq, match, i)
216 if i >= 0:
217 i = i+n
218 buf = self.cookedq[:i]
219 self.cookedq = self.cookedq[i:]
220 return buf
221 return self.read_very_lazy()
222
223 def read_all(self):
224 """Read all data until EOF; block until connection closed."""
225 self.process_rawq()
226 while not self.eof:
227 self.fill_rawq()
228 self.process_rawq()
229 buf = self.cookedq
230 self.cookedq = ''
231 return buf
232
233 def read_some(self):
234 """Read at least one byte of cooked data unless EOF is hit.
235
236 Return '' if EOF is hit. Block if no data is immediately
237 available.
238
239 """
240 self.process_rawq()
241 while not self.cookedq and not self.eof:
242 self.fill_rawq()
243 self.process_rawq()
244 buf = self.cookedq
245 self.cookedq = ''
246 return buf
247
248 def read_very_eager(self):
249 """Read everything that's possible without blocking in I/O (eager).
250
251 Raise EOFError if connection closed and no cooked data
252 available. Return '' if no cooked data available otherwise.
253 Don't block unless in the midst of an IAC sequence.
254
255 """
256 self.process_rawq()
257 while not self.eof and self.sock_avail():
258 self.fill_rawq()
259 self.process_rawq()
260 return self.read_very_lazy()
261
262 def read_eager(self):
263 """Read readily available data.
264
265 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.
268
269 """
270 self.process_rawq()
271 while not self.cookedq and not self.eof and self.sock_avail():
272 self.fill_rawq()
273 self.process_rawq()
274 return self.read_very_lazy()
275
276 def read_lazy(self):
277 """Process and return data that's already in the queues (lazy).
278
279 Raise EOFError if connection closed and no data available.
280 Return '' if no cooked data available otherwise. Don't block
281 unless in the midst of an IAC sequence.
282
283 """
284 self.process_rawq()
285 return self.read_very_lazy()
286
287 def read_very_lazy(self):
288 """Return any data available in the cooked queue (very lazy).
289
290 Raise EOFError if connection closed and no data available.
291 Return '' if no cooked data available otherwise. Don't block.
292
293 """
294 buf = self.cookedq
295 self.cookedq = ''
296 if not buf and self.eof and not self.rawq:
297 raise EOFError, 'telnet connection closed'
298 return buf
299
300 def process_rawq(self):
301 """Transfer from raw queue to cooked queue.
302
303 Set self.eof when connection is closed. Don't block unless in
304 the midst of an IAC sequence.
305
306 """
307 buf = ''
308 try:
309 while self.rawq:
310 c = self.rawq_getchar()
311 if c == theNULL:
312 continue
313 if c == "\021":
314 continue
315 if c != IAC:
316 buf = buf + c
317 continue
318 c = self.rawq_getchar()
319 if c == IAC:
320 buf = buf + c
321 elif c in (DO, DONT):
322 opt = self.rawq_getchar()
323 self.msg('IAC %s %d', c == DO and 'DO' or 'DONT', ord(c))
324 self.sock.send(IAC + WONT + opt)
325 elif c in (WILL, WONT):
326 opt = self.rawq_getchar()
327 self.msg('IAC %s %d',
328 c == WILL and 'WILL' or 'WONT', ord(c))
329 else:
330 self.msg('IAC %s not recognized' % `c`)
331 except EOFError: # raised by self.rawq_getchar()
332 pass
333 self.cookedq = self.cookedq + buf
334
335 def rawq_getchar(self):
336 """Get next char from raw queue.
337
338 Block if no data is immediately available. Raise EOFError
339 when connection is closed.
340
341 """
342 if not self.rawq:
343 self.fill_rawq()
344 if self.eof:
345 raise EOFError
346 c = self.rawq[self.irawq]
347 self.irawq = self.irawq + 1
348 if self.irawq >= len(self.rawq):
349 self.rawq = ''
350 self.irawq = 0
351 return c
352
353 def fill_rawq(self):
354 """Fill raw queue from exactly one recv() system call.
355
356 Block if no data is immediately available. Set self.eof when
357 connection is closed.
358
359 """
360 if self.irawq >= len(self.rawq):
361 self.rawq = ''
362 self.irawq = 0
363 # The buffer size should be fairly small so as to avoid quadratic
364 # behavior in process_rawq() above
365 buf = self.sock.recv(50)
366 self.eof = (not buf)
367 self.rawq = self.rawq + buf
368
369 def sock_avail(self):
370 """Test whether data is available on the socket."""
371 return select.select([self], [], [], 0) == ([self], [], [])
372
373 def interact(self):
374 """Interaction function, emulates a very dumb telnet client."""
375 import sys, select
376 while 1:
377 rfd, wfd, xfd = select.select([self, sys.stdin], [], [])
378 if sys.stdin in rfd:
379 line = sys.stdin.readline()
380 self.write(line)
381 if self in rfd:
382 try:
383 text = self.read_eager()
384 except EOFError:
385 print '*** Connection closed by remote host ***'
386 break
387 if text:
388 sys.stdout.write(text)
389 sys.stdout.flush()
390 self.close()
391
392
393
394def test():
395 """Test program for telnetlib.
396
397 Usage: python telnetlib.py [-d] ... [host [port]]
398
399 Default host is localhost; default port is 23.
400
401 """
402 import sys
403 debuglevel = 0
404 while sys.argv[1:] and sys.argv[1] == '-d':
405 debuglevel = debuglevel+1
406 del sys.argv[1]
407 host = 'localhost'
408 if sys.argv[1:]:
409 host = sys.argv[1]
410 port = 0
411 if sys.argv[2:]:
412 portstr = sys.argv[2]
413 try:
414 port = int(portstr)
415 except ValueError:
416 port = socket.getservbyname(portstr, 'tcp')
417 tn = Telnet()
418 tn.set_debuglevel(debuglevel)
419 tn.open(host, port)
420 tn.interact()
421 tn.close()
422
423if __name__ == '__main__':
424 test()