1 | r"""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 | To do: |
---|
29 | - option negotiation |
---|
30 | - timeout should be intrinsic to the connection object instead of an |
---|
31 | option on one of the read calls only |
---|
32 | |
---|
33 | """ |
---|
34 | |
---|
35 | |
---|
36 | # Imported modules |
---|
37 | import errno |
---|
38 | import sys |
---|
39 | import socket |
---|
40 | import select |
---|
41 | |
---|
42 | __all__ = ["Telnet"] |
---|
43 | |
---|
44 | # Tunable parameters |
---|
45 | DEBUGLEVEL = 0 |
---|
46 | |
---|
47 | # Telnet protocol defaults |
---|
48 | TELNET_PORT = 23 |
---|
49 | |
---|
50 | # Telnet protocol characters (don't change) |
---|
51 | IAC = chr(255) # "Interpret As Command" |
---|
52 | DONT = chr(254) |
---|
53 | DO = chr(253) |
---|
54 | WONT = chr(252) |
---|
55 | WILL = chr(251) |
---|
56 | theNULL = chr(0) |
---|
57 | |
---|
58 | SE = chr(240) # Subnegotiation End |
---|
59 | NOP = chr(241) # No Operation |
---|
60 | DM = chr(242) # Data Mark |
---|
61 | BRK = chr(243) # Break |
---|
62 | IP = chr(244) # Interrupt process |
---|
63 | AO = chr(245) # Abort output |
---|
64 | AYT = chr(246) # Are You There |
---|
65 | EC = chr(247) # Erase Character |
---|
66 | EL = chr(248) # Erase Line |
---|
67 | GA = chr(249) # Go Ahead |
---|
68 | SB = chr(250) # Subnegotiation Begin |
---|
69 | |
---|
70 | |
---|
71 | # Telnet protocol options code (don't change) |
---|
72 | # These ones all come from arpa/telnet.h |
---|
73 | BINARY = chr(0) # 8-bit data path |
---|
74 | ECHO = chr(1) # echo |
---|
75 | RCP = chr(2) # prepare to reconnect |
---|
76 | SGA = chr(3) # suppress go ahead |
---|
77 | NAMS = chr(4) # approximate message size |
---|
78 | STATUS = chr(5) # give status |
---|
79 | TM = chr(6) # timing mark |
---|
80 | RCTE = chr(7) # remote controlled transmission and echo |
---|
81 | NAOL = chr(8) # negotiate about output line width |
---|
82 | NAOP = chr(9) # negotiate about output page size |
---|
83 | NAOCRD = chr(10) # negotiate about CR disposition |
---|
84 | NAOHTS = chr(11) # negotiate about horizontal tabstops |
---|
85 | NAOHTD = chr(12) # negotiate about horizontal tab disposition |
---|
86 | NAOFFD = chr(13) # negotiate about formfeed disposition |
---|
87 | NAOVTS = chr(14) # negotiate about vertical tab stops |
---|
88 | NAOVTD = chr(15) # negotiate about vertical tab disposition |
---|
89 | NAOLFD = chr(16) # negotiate about output LF disposition |
---|
90 | XASCII = chr(17) # extended ascii character set |
---|
91 | LOGOUT = chr(18) # force logout |
---|
92 | BM = chr(19) # byte macro |
---|
93 | DET = chr(20) # data entry terminal |
---|
94 | SUPDUP = chr(21) # supdup protocol |
---|
95 | SUPDUPOUTPUT = chr(22) # supdup output |
---|
96 | SNDLOC = chr(23) # send location |
---|
97 | TTYPE = chr(24) # terminal type |
---|
98 | EOR = chr(25) # end or record |
---|
99 | TUID = chr(26) # TACACS user identification |
---|
100 | OUTMRK = chr(27) # output marking |
---|
101 | TTYLOC = chr(28) # terminal location number |
---|
102 | VT3270REGIME = chr(29) # 3270 regime |
---|
103 | X3PAD = chr(30) # X.3 PAD |
---|
104 | NAWS = chr(31) # window size |
---|
105 | TSPEED = chr(32) # terminal speed |
---|
106 | LFLOW = chr(33) # remote flow control |
---|
107 | LINEMODE = chr(34) # Linemode option |
---|
108 | XDISPLOC = chr(35) # X Display Location |
---|
109 | OLD_ENVIRON = chr(36) # Old - Environment variables |
---|
110 | AUTHENTICATION = chr(37) # Authenticate |
---|
111 | ENCRYPT = chr(38) # Encryption option |
---|
112 | NEW_ENVIRON = chr(39) # New - Environment variables |
---|
113 | # the following ones come from |
---|
114 | # http://www.iana.org/assignments/telnet-options |
---|
115 | # Unfortunately, that document does not assign identifiers |
---|
116 | # to all of them, so we are making them up |
---|
117 | TN3270E = chr(40) # TN3270E |
---|
118 | XAUTH = chr(41) # XAUTH |
---|
119 | CHARSET = chr(42) # CHARSET |
---|
120 | RSP = chr(43) # Telnet Remote Serial Port |
---|
121 | COM_PORT_OPTION = chr(44) # Com Port Control Option |
---|
122 | SUPPRESS_LOCAL_ECHO = chr(45) # Telnet Suppress Local Echo |
---|
123 | TLS = chr(46) # Telnet Start TLS |
---|
124 | KERMIT = chr(47) # KERMIT |
---|
125 | SEND_URL = chr(48) # SEND-URL |
---|
126 | FORWARD_X = chr(49) # FORWARD_X |
---|
127 | PRAGMA_LOGON = chr(138) # TELOPT PRAGMA LOGON |
---|
128 | SSPI_LOGON = chr(139) # TELOPT SSPI LOGON |
---|
129 | PRAGMA_HEARTBEAT = chr(140) # TELOPT PRAGMA HEARTBEAT |
---|
130 | EXOPL = chr(255) # Extended-Options-List |
---|
131 | NOOPT = chr(0) |
---|
132 | |
---|
133 | class Telnet: |
---|
134 | |
---|
135 | """Telnet interface class. |
---|
136 | |
---|
137 | An instance of this class represents a connection to a telnet |
---|
138 | server. The instance is initially not connected; the open() |
---|
139 | method must be used to establish a connection. Alternatively, the |
---|
140 | host name and optional port number can be passed to the |
---|
141 | constructor, too. |
---|
142 | |
---|
143 | Don't try to reopen an already connected instance. |
---|
144 | |
---|
145 | This class has many read_*() methods. Note that some of them |
---|
146 | raise EOFError when the end of the connection is read, because |
---|
147 | they can return an empty string for other reasons. See the |
---|
148 | individual doc strings. |
---|
149 | |
---|
150 | read_until(expected, [timeout]) |
---|
151 | Read until the expected string has been seen, or a timeout is |
---|
152 | hit (default is no timeout); may block. |
---|
153 | |
---|
154 | read_all() |
---|
155 | Read all data until EOF; may block. |
---|
156 | |
---|
157 | read_some() |
---|
158 | Read at least one byte or EOF; may block. |
---|
159 | |
---|
160 | read_very_eager() |
---|
161 | Read all data available already queued or on the socket, |
---|
162 | without blocking. |
---|
163 | |
---|
164 | read_eager() |
---|
165 | Read either data already queued or some data available on the |
---|
166 | socket, without blocking. |
---|
167 | |
---|
168 | read_lazy() |
---|
169 | Read all data in the raw queue (processing it first), without |
---|
170 | doing any socket I/O. |
---|
171 | |
---|
172 | read_very_lazy() |
---|
173 | Reads all data in the cooked queue, without doing any socket |
---|
174 | I/O. |
---|
175 | |
---|
176 | read_sb_data() |
---|
177 | Reads available data between SB ... SE sequence. Don't block. |
---|
178 | |
---|
179 | set_option_negotiation_callback(callback) |
---|
180 | Each time a telnet option is read on the input flow, this callback |
---|
181 | (if set) is called with the following parameters : |
---|
182 | callback(telnet socket, command, option) |
---|
183 | option will be chr(0) when there is no option. |
---|
184 | No other action is done afterwards by telnetlib. |
---|
185 | |
---|
186 | """ |
---|
187 | |
---|
188 | def __init__(self, host=None, port=0, |
---|
189 | timeout=socket._GLOBAL_DEFAULT_TIMEOUT): |
---|
190 | """Constructor. |
---|
191 | |
---|
192 | When called without arguments, create an unconnected instance. |
---|
193 | With a hostname argument, it connects the instance; port number |
---|
194 | and timeout are optional. |
---|
195 | """ |
---|
196 | self.debuglevel = DEBUGLEVEL |
---|
197 | self.host = host |
---|
198 | self.port = port |
---|
199 | self.timeout = timeout |
---|
200 | self.sock = None |
---|
201 | self.rawq = '' |
---|
202 | self.irawq = 0 |
---|
203 | self.cookedq = '' |
---|
204 | self.eof = 0 |
---|
205 | self.iacseq = '' # Buffer for IAC sequence. |
---|
206 | self.sb = 0 # flag for SB and SE sequence. |
---|
207 | self.sbdataq = '' |
---|
208 | self.option_callback = None |
---|
209 | self._has_poll = hasattr(select, 'poll') |
---|
210 | if host is not None: |
---|
211 | self.open(host, port, timeout) |
---|
212 | |
---|
213 | def open(self, host, port=0, timeout=socket._GLOBAL_DEFAULT_TIMEOUT): |
---|
214 | """Connect to a host. |
---|
215 | |
---|
216 | The optional second argument is the port number, which |
---|
217 | defaults to the standard telnet port (23). |
---|
218 | |
---|
219 | Don't try to reopen an already connected instance. |
---|
220 | """ |
---|
221 | self.eof = 0 |
---|
222 | if not port: |
---|
223 | port = TELNET_PORT |
---|
224 | self.host = host |
---|
225 | self.port = port |
---|
226 | self.timeout = timeout |
---|
227 | self.sock = socket.create_connection((host, port), timeout) |
---|
228 | |
---|
229 | def __del__(self): |
---|
230 | """Destructor -- close the connection.""" |
---|
231 | self.close() |
---|
232 | |
---|
233 | def msg(self, msg, *args): |
---|
234 | """Print a debug message, when the debug level is > 0. |
---|
235 | |
---|
236 | If extra arguments are present, they are substituted in the |
---|
237 | message using the standard string formatting operator. |
---|
238 | |
---|
239 | """ |
---|
240 | if self.debuglevel > 0: |
---|
241 | print 'Telnet(%s,%s):' % (self.host, self.port), |
---|
242 | if args: |
---|
243 | print msg % args |
---|
244 | else: |
---|
245 | print msg |
---|
246 | |
---|
247 | def set_debuglevel(self, debuglevel): |
---|
248 | """Set the debug level. |
---|
249 | |
---|
250 | The higher it is, the more debug output you get (on sys.stdout). |
---|
251 | |
---|
252 | """ |
---|
253 | self.debuglevel = debuglevel |
---|
254 | |
---|
255 | def close(self): |
---|
256 | """Close the connection.""" |
---|
257 | sock = self.sock |
---|
258 | self.sock = 0 |
---|
259 | self.eof = 1 |
---|
260 | self.iacseq = '' |
---|
261 | self.sb = 0 |
---|
262 | if sock: |
---|
263 | sock.close() |
---|
264 | |
---|
265 | def get_socket(self): |
---|
266 | """Return the socket object used internally.""" |
---|
267 | return self.sock |
---|
268 | |
---|
269 | def fileno(self): |
---|
270 | """Return the fileno() of the socket object used internally.""" |
---|
271 | return self.sock.fileno() |
---|
272 | |
---|
273 | def write(self, buffer): |
---|
274 | """Write a string to the socket, doubling any IAC characters. |
---|
275 | |
---|
276 | Can block if the connection is blocked. May raise |
---|
277 | socket.error if the connection is closed. |
---|
278 | |
---|
279 | """ |
---|
280 | if IAC in buffer: |
---|
281 | buffer = buffer.replace(IAC, IAC+IAC) |
---|
282 | self.msg("send %r", buffer) |
---|
283 | self.sock.sendall(buffer) |
---|
284 | |
---|
285 | def read_until(self, match, timeout=None): |
---|
286 | """Read until a given string is encountered or until timeout. |
---|
287 | |
---|
288 | When no match is found, return whatever is available instead, |
---|
289 | possibly the empty string. Raise EOFError if the connection |
---|
290 | is closed and no cooked data is available. |
---|
291 | |
---|
292 | """ |
---|
293 | if self._has_poll: |
---|
294 | return self._read_until_with_poll(match, timeout) |
---|
295 | else: |
---|
296 | return self._read_until_with_select(match, timeout) |
---|
297 | |
---|
298 | def _read_until_with_poll(self, match, timeout): |
---|
299 | """Read until a given string is encountered or until timeout. |
---|
300 | |
---|
301 | This method uses select.poll() to implement the timeout. |
---|
302 | """ |
---|
303 | n = len(match) |
---|
304 | call_timeout = timeout |
---|
305 | if timeout is not None: |
---|
306 | from time import time |
---|
307 | time_start = time() |
---|
308 | self.process_rawq() |
---|
309 | i = self.cookedq.find(match) |
---|
310 | if i < 0: |
---|
311 | poller = select.poll() |
---|
312 | poll_in_or_priority_flags = select.POLLIN | select.POLLPRI |
---|
313 | poller.register(self, poll_in_or_priority_flags) |
---|
314 | while i < 0 and not self.eof: |
---|
315 | try: |
---|
316 | # Poll takes its timeout in milliseconds. |
---|
317 | ready = poller.poll(None if timeout is None |
---|
318 | else 1000 * call_timeout) |
---|
319 | except select.error as e: |
---|
320 | if e.errno == errno.EINTR: |
---|
321 | if timeout is not None: |
---|
322 | elapsed = time() - time_start |
---|
323 | call_timeout = timeout-elapsed |
---|
324 | continue |
---|
325 | raise |
---|
326 | for fd, mode in ready: |
---|
327 | if mode & poll_in_or_priority_flags: |
---|
328 | i = max(0, len(self.cookedq)-n) |
---|
329 | self.fill_rawq() |
---|
330 | self.process_rawq() |
---|
331 | i = self.cookedq.find(match, i) |
---|
332 | if timeout is not None: |
---|
333 | elapsed = time() - time_start |
---|
334 | if elapsed >= timeout: |
---|
335 | break |
---|
336 | call_timeout = timeout-elapsed |
---|
337 | poller.unregister(self) |
---|
338 | if i >= 0: |
---|
339 | i = i + n |
---|
340 | buf = self.cookedq[:i] |
---|
341 | self.cookedq = self.cookedq[i:] |
---|
342 | return buf |
---|
343 | return self.read_very_lazy() |
---|
344 | |
---|
345 | def _read_until_with_select(self, match, timeout=None): |
---|
346 | """Read until a given string is encountered or until timeout. |
---|
347 | |
---|
348 | The timeout is implemented using select.select(). |
---|
349 | """ |
---|
350 | n = len(match) |
---|
351 | self.process_rawq() |
---|
352 | i = self.cookedq.find(match) |
---|
353 | if i >= 0: |
---|
354 | i = i+n |
---|
355 | buf = self.cookedq[:i] |
---|
356 | self.cookedq = self.cookedq[i:] |
---|
357 | return buf |
---|
358 | s_reply = ([self], [], []) |
---|
359 | s_args = s_reply |
---|
360 | if timeout is not None: |
---|
361 | s_args = s_args + (timeout,) |
---|
362 | from time import time |
---|
363 | time_start = time() |
---|
364 | while not self.eof and select.select(*s_args) == s_reply: |
---|
365 | i = max(0, len(self.cookedq)-n) |
---|
366 | self.fill_rawq() |
---|
367 | self.process_rawq() |
---|
368 | i = self.cookedq.find(match, i) |
---|
369 | if i >= 0: |
---|
370 | i = i+n |
---|
371 | buf = self.cookedq[:i] |
---|
372 | self.cookedq = self.cookedq[i:] |
---|
373 | return buf |
---|
374 | if timeout is not None: |
---|
375 | elapsed = time() - time_start |
---|
376 | if elapsed >= timeout: |
---|
377 | break |
---|
378 | s_args = s_reply + (timeout-elapsed,) |
---|
379 | return self.read_very_lazy() |
---|
380 | |
---|
381 | def read_all(self): |
---|
382 | """Read all data until EOF; block until connection closed.""" |
---|
383 | self.process_rawq() |
---|
384 | while not self.eof: |
---|
385 | self.fill_rawq() |
---|
386 | self.process_rawq() |
---|
387 | buf = self.cookedq |
---|
388 | self.cookedq = '' |
---|
389 | return buf |
---|
390 | |
---|
391 | def read_some(self): |
---|
392 | """Read at least one byte of cooked data unless EOF is hit. |
---|
393 | |
---|
394 | Return '' if EOF is hit. Block if no data is immediately |
---|
395 | available. |
---|
396 | |
---|
397 | """ |
---|
398 | self.process_rawq() |
---|
399 | while not self.cookedq and not self.eof: |
---|
400 | self.fill_rawq() |
---|
401 | self.process_rawq() |
---|
402 | buf = self.cookedq |
---|
403 | self.cookedq = '' |
---|
404 | return buf |
---|
405 | |
---|
406 | def read_very_eager(self): |
---|
407 | """Read everything that's possible without blocking in I/O (eager). |
---|
408 | |
---|
409 | Raise EOFError if connection closed and no cooked data |
---|
410 | available. Return '' if no cooked data available otherwise. |
---|
411 | Don't block unless in the midst of an IAC sequence. |
---|
412 | |
---|
413 | """ |
---|
414 | self.process_rawq() |
---|
415 | while not self.eof and self.sock_avail(): |
---|
416 | self.fill_rawq() |
---|
417 | self.process_rawq() |
---|
418 | return self.read_very_lazy() |
---|
419 | |
---|
420 | def read_eager(self): |
---|
421 | """Read readily available data. |
---|
422 | |
---|
423 | Raise EOFError if connection closed and no cooked data |
---|
424 | available. Return '' if no cooked data available otherwise. |
---|
425 | Don't block unless in the midst of an IAC sequence. |
---|
426 | |
---|
427 | """ |
---|
428 | self.process_rawq() |
---|
429 | while not self.cookedq and not self.eof and self.sock_avail(): |
---|
430 | self.fill_rawq() |
---|
431 | self.process_rawq() |
---|
432 | return self.read_very_lazy() |
---|
433 | |
---|
434 | def read_lazy(self): |
---|
435 | """Process and return data that's already in the queues (lazy). |
---|
436 | |
---|
437 | Raise EOFError if connection closed and no data available. |
---|
438 | Return '' if no cooked data available otherwise. Don't block |
---|
439 | unless in the midst of an IAC sequence. |
---|
440 | |
---|
441 | """ |
---|
442 | self.process_rawq() |
---|
443 | return self.read_very_lazy() |
---|
444 | |
---|
445 | def read_very_lazy(self): |
---|
446 | """Return any data available in the cooked queue (very lazy). |
---|
447 | |
---|
448 | Raise EOFError if connection closed and no data available. |
---|
449 | Return '' if no cooked data available otherwise. Don't block. |
---|
450 | |
---|
451 | """ |
---|
452 | buf = self.cookedq |
---|
453 | self.cookedq = '' |
---|
454 | if not buf and self.eof and not self.rawq: |
---|
455 | raise EOFError, 'telnet connection closed' |
---|
456 | return buf |
---|
457 | |
---|
458 | def read_sb_data(self): |
---|
459 | """Return any data available in the SB ... SE queue. |
---|
460 | |
---|
461 | Return '' if no SB ... SE available. Should only be called |
---|
462 | after seeing a SB or SE command. When a new SB command is |
---|
463 | found, old unread SB data will be discarded. Don't block. |
---|
464 | |
---|
465 | """ |
---|
466 | buf = self.sbdataq |
---|
467 | self.sbdataq = '' |
---|
468 | return buf |
---|
469 | |
---|
470 | def set_option_negotiation_callback(self, callback): |
---|
471 | """Provide a callback function called after each receipt of a telnet option.""" |
---|
472 | self.option_callback = callback |
---|
473 | |
---|
474 | def process_rawq(self): |
---|
475 | """Transfer from raw queue to cooked queue. |
---|
476 | |
---|
477 | Set self.eof when connection is closed. Don't block unless in |
---|
478 | the midst of an IAC sequence. |
---|
479 | |
---|
480 | """ |
---|
481 | buf = ['', ''] |
---|
482 | try: |
---|
483 | while self.rawq: |
---|
484 | c = self.rawq_getchar() |
---|
485 | if not self.iacseq: |
---|
486 | if c == theNULL: |
---|
487 | continue |
---|
488 | if c == "\021": |
---|
489 | continue |
---|
490 | if c != IAC: |
---|
491 | buf[self.sb] = buf[self.sb] + c |
---|
492 | continue |
---|
493 | else: |
---|
494 | self.iacseq += c |
---|
495 | elif len(self.iacseq) == 1: |
---|
496 | # 'IAC: IAC CMD [OPTION only for WILL/WONT/DO/DONT]' |
---|
497 | if c in (DO, DONT, WILL, WONT): |
---|
498 | self.iacseq += c |
---|
499 | continue |
---|
500 | |
---|
501 | self.iacseq = '' |
---|
502 | if c == IAC: |
---|
503 | buf[self.sb] = buf[self.sb] + c |
---|
504 | else: |
---|
505 | if c == SB: # SB ... SE start. |
---|
506 | self.sb = 1 |
---|
507 | self.sbdataq = '' |
---|
508 | elif c == SE: |
---|
509 | self.sb = 0 |
---|
510 | self.sbdataq = self.sbdataq + buf[1] |
---|
511 | buf[1] = '' |
---|
512 | if self.option_callback: |
---|
513 | # Callback is supposed to look into |
---|
514 | # the sbdataq |
---|
515 | self.option_callback(self.sock, c, NOOPT) |
---|
516 | else: |
---|
517 | # We can't offer automatic processing of |
---|
518 | # suboptions. Alas, we should not get any |
---|
519 | # unless we did a WILL/DO before. |
---|
520 | self.msg('IAC %d not recognized' % ord(c)) |
---|
521 | elif len(self.iacseq) == 2: |
---|
522 | cmd = self.iacseq[1] |
---|
523 | self.iacseq = '' |
---|
524 | opt = c |
---|
525 | if cmd in (DO, DONT): |
---|
526 | self.msg('IAC %s %d', |
---|
527 | cmd == DO and 'DO' or 'DONT', ord(opt)) |
---|
528 | if self.option_callback: |
---|
529 | self.option_callback(self.sock, cmd, opt) |
---|
530 | else: |
---|
531 | self.sock.sendall(IAC + WONT + opt) |
---|
532 | elif cmd in (WILL, WONT): |
---|
533 | self.msg('IAC %s %d', |
---|
534 | cmd == WILL and 'WILL' or 'WONT', ord(opt)) |
---|
535 | if self.option_callback: |
---|
536 | self.option_callback(self.sock, cmd, opt) |
---|
537 | else: |
---|
538 | self.sock.sendall(IAC + DONT + opt) |
---|
539 | except EOFError: # raised by self.rawq_getchar() |
---|
540 | self.iacseq = '' # Reset on EOF |
---|
541 | self.sb = 0 |
---|
542 | pass |
---|
543 | self.cookedq = self.cookedq + buf[0] |
---|
544 | self.sbdataq = self.sbdataq + buf[1] |
---|
545 | |
---|
546 | def rawq_getchar(self): |
---|
547 | """Get next char from raw queue. |
---|
548 | |
---|
549 | Block if no data is immediately available. Raise EOFError |
---|
550 | when connection is closed. |
---|
551 | |
---|
552 | """ |
---|
553 | if not self.rawq: |
---|
554 | self.fill_rawq() |
---|
555 | if self.eof: |
---|
556 | raise EOFError |
---|
557 | c = self.rawq[self.irawq] |
---|
558 | self.irawq = self.irawq + 1 |
---|
559 | if self.irawq >= len(self.rawq): |
---|
560 | self.rawq = '' |
---|
561 | self.irawq = 0 |
---|
562 | return c |
---|
563 | |
---|
564 | def fill_rawq(self): |
---|
565 | """Fill raw queue from exactly one recv() system call. |
---|
566 | |
---|
567 | Block if no data is immediately available. Set self.eof when |
---|
568 | connection is closed. |
---|
569 | |
---|
570 | """ |
---|
571 | if self.irawq >= len(self.rawq): |
---|
572 | self.rawq = '' |
---|
573 | self.irawq = 0 |
---|
574 | # The buffer size should be fairly small so as to avoid quadratic |
---|
575 | # behavior in process_rawq() above |
---|
576 | buf = self.sock.recv(50) |
---|
577 | self.msg("recv %r", buf) |
---|
578 | self.eof = (not buf) |
---|
579 | self.rawq = self.rawq + buf |
---|
580 | |
---|
581 | def sock_avail(self): |
---|
582 | """Test whether data is available on the socket.""" |
---|
583 | return select.select([self], [], [], 0) == ([self], [], []) |
---|
584 | |
---|
585 | def interact(self): |
---|
586 | """Interaction function, emulates a very dumb telnet client.""" |
---|
587 | if sys.platform == "win32": |
---|
588 | self.mt_interact() |
---|
589 | return |
---|
590 | while 1: |
---|
591 | rfd, wfd, xfd = select.select([self, sys.stdin], [], []) |
---|
592 | if self in rfd: |
---|
593 | try: |
---|
594 | text = self.read_eager() |
---|
595 | except EOFError: |
---|
596 | print '*** Connection closed by remote host ***' |
---|
597 | break |
---|
598 | if text: |
---|
599 | sys.stdout.write(text) |
---|
600 | sys.stdout.flush() |
---|
601 | if sys.stdin in rfd: |
---|
602 | line = sys.stdin.readline() |
---|
603 | if not line: |
---|
604 | break |
---|
605 | self.write(line) |
---|
606 | |
---|
607 | def mt_interact(self): |
---|
608 | """Multithreaded version of interact().""" |
---|
609 | import thread |
---|
610 | thread.start_new_thread(self.listener, ()) |
---|
611 | while 1: |
---|
612 | line = sys.stdin.readline() |
---|
613 | if not line: |
---|
614 | break |
---|
615 | self.write(line) |
---|
616 | |
---|
617 | def listener(self): |
---|
618 | """Helper for mt_interact() -- this executes in the other thread.""" |
---|
619 | while 1: |
---|
620 | try: |
---|
621 | data = self.read_eager() |
---|
622 | except EOFError: |
---|
623 | print '*** Connection closed by remote host ***' |
---|
624 | return |
---|
625 | if data: |
---|
626 | sys.stdout.write(data) |
---|
627 | else: |
---|
628 | sys.stdout.flush() |
---|
629 | |
---|
630 | def expect(self, list, timeout=None): |
---|
631 | """Read until one from a list of a regular expressions matches. |
---|
632 | |
---|
633 | The first argument is a list of regular expressions, either |
---|
634 | compiled (re.RegexObject instances) or uncompiled (strings). |
---|
635 | The optional second argument is a timeout, in seconds; default |
---|
636 | is no timeout. |
---|
637 | |
---|
638 | Return a tuple of three items: the index in the list of the |
---|
639 | first regular expression that matches; the match object |
---|
640 | returned; and the text read up till and including the match. |
---|
641 | |
---|
642 | If EOF is read and no text was read, raise EOFError. |
---|
643 | Otherwise, when nothing matches, return (-1, None, text) where |
---|
644 | text is the text received so far (may be the empty string if a |
---|
645 | timeout happened). |
---|
646 | |
---|
647 | If a regular expression ends with a greedy match (e.g. '.*') |
---|
648 | or if more than one expression can match the same input, the |
---|
649 | results are undeterministic, and may depend on the I/O timing. |
---|
650 | |
---|
651 | """ |
---|
652 | if self._has_poll: |
---|
653 | return self._expect_with_poll(list, timeout) |
---|
654 | else: |
---|
655 | return self._expect_with_select(list, timeout) |
---|
656 | |
---|
657 | def _expect_with_poll(self, expect_list, timeout=None): |
---|
658 | """Read until one from a list of a regular expressions matches. |
---|
659 | |
---|
660 | This method uses select.poll() to implement the timeout. |
---|
661 | """ |
---|
662 | re = None |
---|
663 | expect_list = expect_list[:] |
---|
664 | indices = range(len(expect_list)) |
---|
665 | for i in indices: |
---|
666 | if not hasattr(expect_list[i], "search"): |
---|
667 | if not re: import re |
---|
668 | expect_list[i] = re.compile(expect_list[i]) |
---|
669 | call_timeout = timeout |
---|
670 | if timeout is not None: |
---|
671 | from time import time |
---|
672 | time_start = time() |
---|
673 | self.process_rawq() |
---|
674 | m = None |
---|
675 | for i in indices: |
---|
676 | m = expect_list[i].search(self.cookedq) |
---|
677 | if m: |
---|
678 | e = m.end() |
---|
679 | text = self.cookedq[:e] |
---|
680 | self.cookedq = self.cookedq[e:] |
---|
681 | break |
---|
682 | if not m: |
---|
683 | poller = select.poll() |
---|
684 | poll_in_or_priority_flags = select.POLLIN | select.POLLPRI |
---|
685 | poller.register(self, poll_in_or_priority_flags) |
---|
686 | while not m and not self.eof: |
---|
687 | try: |
---|
688 | ready = poller.poll(None if timeout is None |
---|
689 | else 1000 * call_timeout) |
---|
690 | except select.error as e: |
---|
691 | if e.errno == errno.EINTR: |
---|
692 | if timeout is not None: |
---|
693 | elapsed = time() - time_start |
---|
694 | call_timeout = timeout-elapsed |
---|
695 | continue |
---|
696 | raise |
---|
697 | for fd, mode in ready: |
---|
698 | if mode & poll_in_or_priority_flags: |
---|
699 | self.fill_rawq() |
---|
700 | self.process_rawq() |
---|
701 | for i in indices: |
---|
702 | m = expect_list[i].search(self.cookedq) |
---|
703 | if m: |
---|
704 | e = m.end() |
---|
705 | text = self.cookedq[:e] |
---|
706 | self.cookedq = self.cookedq[e:] |
---|
707 | break |
---|
708 | if timeout is not None: |
---|
709 | elapsed = time() - time_start |
---|
710 | if elapsed >= timeout: |
---|
711 | break |
---|
712 | call_timeout = timeout-elapsed |
---|
713 | poller.unregister(self) |
---|
714 | if m: |
---|
715 | return (i, m, text) |
---|
716 | text = self.read_very_lazy() |
---|
717 | if not text and self.eof: |
---|
718 | raise EOFError |
---|
719 | return (-1, None, text) |
---|
720 | |
---|
721 | def _expect_with_select(self, list, timeout=None): |
---|
722 | """Read until one from a list of a regular expressions matches. |
---|
723 | |
---|
724 | The timeout is implemented using select.select(). |
---|
725 | """ |
---|
726 | re = None |
---|
727 | list = list[:] |
---|
728 | indices = range(len(list)) |
---|
729 | for i in indices: |
---|
730 | if not hasattr(list[i], "search"): |
---|
731 | if not re: import re |
---|
732 | list[i] = re.compile(list[i]) |
---|
733 | if timeout is not None: |
---|
734 | from time import time |
---|
735 | time_start = time() |
---|
736 | while 1: |
---|
737 | self.process_rawq() |
---|
738 | for i in indices: |
---|
739 | m = list[i].search(self.cookedq) |
---|
740 | if m: |
---|
741 | e = m.end() |
---|
742 | text = self.cookedq[:e] |
---|
743 | self.cookedq = self.cookedq[e:] |
---|
744 | return (i, m, text) |
---|
745 | if self.eof: |
---|
746 | break |
---|
747 | if timeout is not None: |
---|
748 | elapsed = time() - time_start |
---|
749 | if elapsed >= timeout: |
---|
750 | break |
---|
751 | s_args = ([self.fileno()], [], [], timeout-elapsed) |
---|
752 | r, w, x = select.select(*s_args) |
---|
753 | if not r: |
---|
754 | break |
---|
755 | self.fill_rawq() |
---|
756 | text = self.read_very_lazy() |
---|
757 | if not text and self.eof: |
---|
758 | raise EOFError |
---|
759 | return (-1, None, text) |
---|
760 | |
---|
761 | |
---|
762 | def test(): |
---|
763 | """Test program for telnetlib. |
---|
764 | |
---|
765 | Usage: python telnetlib.py [-d] ... [host [port]] |
---|
766 | |
---|
767 | Default host is localhost; default port is 23. |
---|
768 | |
---|
769 | """ |
---|
770 | debuglevel = 0 |
---|
771 | while sys.argv[1:] and sys.argv[1] == '-d': |
---|
772 | debuglevel = debuglevel+1 |
---|
773 | del sys.argv[1] |
---|
774 | host = 'localhost' |
---|
775 | if sys.argv[1:]: |
---|
776 | host = sys.argv[1] |
---|
777 | port = 0 |
---|
778 | if sys.argv[2:]: |
---|
779 | portstr = sys.argv[2] |
---|
780 | try: |
---|
781 | port = int(portstr) |
---|
782 | except ValueError: |
---|
783 | port = socket.getservbyname(portstr, 'tcp') |
---|
784 | tn = Telnet() |
---|
785 | tn.set_debuglevel(debuglevel) |
---|
786 | tn.open(host, port, timeout=0.5) |
---|
787 | tn.interact() |
---|
788 | tn.close() |
---|
789 | |
---|
790 | if __name__ == '__main__': |
---|
791 | test() |
---|