1
r"""TELNET client class.
3
Based on RFC 854: TELNET Protocol Specification, by J. Postel and
8
>>> from telnetlib import Telnet
9
>>> tn = Telnet('www.python.org', 79) # connect to finger port
10
>>> tn.write(b'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..
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.
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 b'' 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
30
- timeout should be intrinsic to the connection object instead of an
31
option on one of the read calls only
46
# Telnet protocol defaults
49
# Telnet protocol characters (don't change)
50
IAC = 255 # "Interpret As Command"
57
SE = 240 # Subnegotiation End
58
NOP = 241 # No Operation
61
IP = 244 # Interrupt process
62
AO = 245 # Abort output
63
AYT = 246 # Are You There
64
EC = 247 # Erase Character
67
SB = 250 # Subnegotiation Begin
70
# Telnet protocol options code (don't change)
71
# These ones all come from arpa/telnet.h
72
BINARY = 0 # 8-bit data path
74
RCP = 2 # prepare to reconnect
75
SGA = 3 # suppress go ahead
76
NAMS = 4 # approximate message size
77
STATUS = 5 # give status
79
RCTE = 7 # remote controlled transmission and echo
80
NAOL = 8 # negotiate about output line width
81
NAOP = 9 # negotiate about output page size
82
NAOCRD = 10 # negotiate about CR disposition
83
NAOHTS = 11 # negotiate about horizontal tabstops
84
NAOHTD = 12 # negotiate about horizontal tab disposition
85
NAOFFD = 13 # negotiate about formfeed disposition
86
NAOVTS = 14 # negotiate about vertical tab stops
87
NAOVTD = 15 # negotiate about vertical tab disposition
88
NAOLFD = 16 # negotiate about output LF disposition
89
XASCII = 17 # extended ascii character set
90
LOGOUT = 18 # force logout
92
DET = 20 # data entry terminal
93
SUPDUP = 21 # supdup protocol
94
SUPDUPOUTPUT = 22 # supdup output
95
SNDLOC = 23 # send location
96
TTYPE = 24 # terminal type
97
EOR = 25 # end or record
98
TUID = 26 # TACACS user identification
99
OUTMRK = 27 # output marking
100
TTYLOC = 28 # terminal location number
101
VT3270REGIME = 29 # 3270 regime
103
NAWS = 31 # window size
104
TSPEED = 32 # terminal speed
105
LFLOW = 33 # remote flow control
106
LINEMODE = 34 # Linemode option
107
XDISPLOC = 35 # X Display Location
108
OLD_ENVIRON = 36 # Old - Environment variables
109
AUTHENTICATION = 37 # Authenticate
110
ENCRYPT = 38 # Encryption option
111
NEW_ENVIRON = 39 # New - Environment variables
112
# the following ones come from
113
# http://www.iana.org/assignments/telnet-options
114
# Unfortunately, that document does not assign identifiers
115
# to all of them, so we are making them up
116
TN3270E = 40 # TN3270E
118
CHARSET = 42 # CHARSET
119
RSP = 43 # Telnet Remote Serial Port
120
COM_PORT_OPTION = 44 # Com Port Control Option
121
SUPPRESS_LOCAL_ECHO = 45 # Telnet Suppress Local Echo
122
TLS = 46 # Telnet Start TLS
124
SEND_URL = 48 # SEND-URL
125
FORWARD_X = 49 # FORWARD_X
126
PRAGMA_LOGON = 138 # TELOPT PRAGMA LOGON
127
SSPI_LOGON = 139 # TELOPT SSPI LOGON
128
PRAGMA_HEARTBEAT = 140 # TELOPT PRAGMA HEARTBEAT
129
EXOPL = 255 # Extended-Options-List
134
"""Telnet interface class.
136
An instance of this class represents a connection to a telnet
137
server. The instance is initially not connected; the open()
138
method must be used to establish a connection. Alternatively, the
139
host name and optional port number can be passed to the
142
Don't try to reopen an already connected instance.
144
This class has many read_*() methods. Note that some of them
145
raise EOFError when the end of the connection is read, because
146
they can return an empty string for other reasons. See the
147
individual doc strings.
149
read_until(expected, [timeout])
150
Read until the expected string has been seen, or a timeout is
151
hit (default is no timeout); may block.
154
Read all data until EOF; may block.
157
Read at least one byte or EOF; may block.
160
Read all data available already queued or on the socket,
164
Read either data already queued or some data available on the
165
socket, without blocking.
168
Read all data in the raw queue (processing it first), without
169
doing any socket I/O.
172
Reads all data in the cooked queue, without doing any socket
176
Reads available data between SB ... SE sequence. Don't block.
178
set_option_negotiation_callback(callback)
179
Each time a telnet option is read on the input flow, this callback
180
(if set) is called with the following parameters :
181
callback(telnet socket, command, option)
182
option will be chr(0) when there is no option.
183
No other action is done afterwards by telnetlib.
187
def __init__(self, host=None, port=0,
188
timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
191
When called without arguments, create an unconnected instance.
192
With a hostname argument, it connects the instance; port number
193
and timeout are optional.
195
self.debuglevel = DEBUGLEVEL
198
self.timeout = timeout
204
self.iacseq = b'' # Buffer for IAC sequence.
205
self.sb = 0 # flag for SB and SE sequence.
207
self.option_callback = None
209
self.open(host, port, timeout)
211
def open(self, host, port=0, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
212
"""Connect to a host.
214
The optional second argument is the port number, which
215
defaults to the standard telnet port (23).
217
Don't try to reopen an already connected instance.
224
self.timeout = timeout
225
self.sock = socket.create_connection((host, port), timeout)
228
"""Destructor -- close the connection."""
231
def msg(self, msg, *args):
232
"""Print a debug message, when the debug level is > 0.
234
If extra arguments are present, they are substituted in the
235
message using the standard string formatting operator.
238
if self.debuglevel > 0:
239
print('Telnet(%s,%d):' % (self.host, self.port), end=' ')
245
def set_debuglevel(self, debuglevel):
246
"""Set the debug level.
248
The higher it is, the more debug output you get (on sys.stdout).
251
self.debuglevel = debuglevel
254
"""Close the connection."""
262
def get_socket(self):
263
"""Return the socket object used internally."""
267
"""Return the fileno() of the socket object used internally."""
268
return self.sock.fileno()
270
def write(self, buffer):
271
"""Write a string to the socket, doubling any IAC characters.
273
Can block if the connection is blocked. May raise
274
socket.error if the connection is closed.
278
buffer = buffer.replace(IAC, IAC+IAC)
279
self.msg("send %r", buffer)
280
self.sock.sendall(buffer)
282
def read_until(self, match, timeout=None):
283
"""Read until a given string is encountered or until timeout.
285
When no match is found, return whatever is available instead,
286
possibly the empty string. Raise EOFError if the connection
287
is closed and no cooked data is available.
292
i = self.cookedq.find(match)
295
buf = self.cookedq[:i]
296
self.cookedq = self.cookedq[i:]
298
s_reply = ([self], [], [])
300
if timeout is not None:
301
s_args = s_args + (timeout,)
302
from time import time
304
while not self.eof and select.select(*s_args) == s_reply:
305
i = max(0, len(self.cookedq)-n)
308
i = self.cookedq.find(match, i)
311
buf = self.cookedq[:i]
312
self.cookedq = self.cookedq[i:]
314
if timeout is not None:
315
elapsed = time() - time_start
316
if elapsed >= timeout:
318
s_args = s_reply + (timeout-elapsed,)
319
return self.read_very_lazy()
322
"""Read all data until EOF; block until connection closed."""
332
"""Read at least one byte of cooked data unless EOF is hit.
334
Return b'' if EOF is hit. Block if no data is immediately
339
while not self.cookedq and not self.eof:
346
def read_very_eager(self):
347
"""Read everything that's possible without blocking in I/O (eager).
349
Raise EOFError if connection closed and no cooked data
350
available. Return b'' if no cooked data available otherwise.
351
Don't block unless in the midst of an IAC sequence.
355
while not self.eof and self.sock_avail():
358
return self.read_very_lazy()
360
def read_eager(self):
361
"""Read readily available data.
363
Raise EOFError if connection closed and no cooked data
364
available. Return b'' if no cooked data available otherwise.
365
Don't block unless in the midst of an IAC sequence.
369
while not self.cookedq and not self.eof and self.sock_avail():
372
return self.read_very_lazy()
375
"""Process and return data that's already in the queues (lazy).
377
Raise EOFError if connection closed and no data available.
378
Return b'' if no cooked data available otherwise. Don't block
379
unless in the midst of an IAC sequence.
383
return self.read_very_lazy()
385
def read_very_lazy(self):
386
"""Return any data available in the cooked queue (very lazy).
388
Raise EOFError if connection closed and no data available.
389
Return b'' if no cooked data available otherwise. Don't block.
394
if not buf and self.eof and not self.rawq:
395
raise EOFError('telnet connection closed')
398
def read_sb_data(self):
399
"""Return any data available in the SB ... SE queue.
401
Return b'' if no SB ... SE available. Should only be called
402
after seeing a SB or SE command. When a new SB command is
403
found, old unread SB data will be discarded. Don't block.
410
def set_option_negotiation_callback(self, callback):
411
"""Provide a callback function called after each receipt of a telnet option."""
412
self.option_callback = callback
414
def process_rawq(self):
415
"""Transfer from raw queue to cooked queue.
417
Set self.eof when connection is closed. Don't block unless in
418
the midst of an IAC sequence.
424
c = self.rawq_getchar()
431
buf[self.sb] = buf[self.sb] + c
435
elif len(self.iacseq) == 1:
436
# 'IAC: IAC CMD [OPTION only for WILL/WONT/DO/DONT]'
437
if c in (DO, DONT, WILL, WONT):
443
buf[self.sb] = buf[self.sb] + c
445
if c == SB: # SB ... SE start.
450
self.sbdataq = self.sbdataq + buf[1]
452
if self.option_callback:
453
# Callback is supposed to look into
455
self.option_callback(self.sock, c, NOOPT)
457
# We can't offer automatic processing of
458
# suboptions. Alas, we should not get any
459
# unless we did a WILL/DO before.
460
self.msg('IAC %d not recognized' % ord(c))
461
elif len(self.iacseq) == 2:
465
if cmd in (DO, DONT):
466
self.msg('IAC %s %d',
467
cmd == DO and 'DO' or 'DONT', ord(opt))
468
if self.option_callback:
469
self.option_callback(self.sock, cmd, opt)
471
self.sock.sendall(IAC + WONT + opt)
472
elif cmd in (WILL, WONT):
473
self.msg('IAC %s %d',
474
cmd == WILL and 'WILL' or 'WONT', ord(opt))
475
if self.option_callback:
476
self.option_callback(self.sock, cmd, opt)
478
self.sock.sendall(IAC + DONT + opt)
479
except EOFError: # raised by self.rawq_getchar()
480
self.iacseq = b'' # Reset on EOF
483
self.cookedq = self.cookedq + buf[0]
484
self.sbdataq = self.sbdataq + buf[1]
486
def rawq_getchar(self):
487
"""Get next char from raw queue.
489
Block if no data is immediately available. Raise EOFError
490
when connection is closed.
497
c = self.rawq[self.irawq:self.irawq+1]
498
self.irawq = self.irawq + 1
499
if self.irawq >= len(self.rawq):
505
"""Fill raw queue from exactly one recv() system call.
507
Block if no data is immediately available. Set self.eof when
508
connection is closed.
511
if self.irawq >= len(self.rawq):
514
# The buffer size should be fairly small so as to avoid quadratic
515
# behavior in process_rawq() above
516
buf = self.sock.recv(50)
517
self.msg("recv %r", buf)
519
self.rawq = self.rawq + buf
521
def sock_avail(self):
522
"""Test whether data is available on the socket."""
523
return select.select([self], [], [], 0) == ([self], [], [])
526
"""Interaction function, emulates a very dumb telnet client."""
527
if sys.platform == "win32":
531
rfd, wfd, xfd = select.select([self, sys.stdin], [], [])
534
text = self.read_eager()
536
print('*** Connection closed by remote host ***')
539
sys.stdout.write(text.decode('ascii'))
542
line = sys.stdin.readline().encode('ascii')
547
def mt_interact(self):
548
"""Multithreaded version of interact()."""
550
_thread.start_new_thread(self.listener, ())
552
line = sys.stdin.readline()
558
"""Helper for mt_interact() -- this executes in the other thread."""
561
data = self.read_eager()
563
print('*** Connection closed by remote host ***')
566
sys.stdout.write(data)
570
def expect(self, list, timeout=None):
571
"""Read until one from a list of a regular expressions matches.
573
The first argument is a list of regular expressions, either
574
compiled (re.RegexObject instances) or uncompiled (strings).
575
The optional second argument is a timeout, in seconds; default
578
Return a tuple of three items: the index in the list of the
579
first regular expression that matches; the match object
580
returned; and the text read up till and including the match.
582
If EOF is read and no text was read, raise EOFError.
583
Otherwise, when nothing matches, return (-1, None, text) where
584
text is the text received so far (may be the empty string if a
587
If a regular expression ends with a greedy match (e.g. '.*')
588
or if more than one expression can match the same input, the
589
results are undeterministic, and may depend on the I/O timing.
594
indices = range(len(list))
596
if not hasattr(list[i], "search"):
598
list[i] = re.compile(list[i])
599
if timeout is not None:
600
from time import time
605
m = list[i].search(self.cookedq)
608
text = self.cookedq[:e]
609
self.cookedq = self.cookedq[e:]
613
if timeout is not None:
614
elapsed = time() - time_start
615
if elapsed >= timeout:
617
s_args = ([self.fileno()], [], [], timeout-elapsed)
618
r, w, x = select.select(*s_args)
622
text = self.read_very_lazy()
623
if not text and self.eof:
625
return (-1, None, text)
629
"""Test program for telnetlib.
631
Usage: python telnetlib.py [-d] ... [host [port]]
633
Default host is localhost; default port is 23.
637
while sys.argv[1:] and sys.argv[1] == '-d':
638
debuglevel = debuglevel+1
645
portstr = sys.argv[2]
649
port = socket.getservbyname(portstr, 'tcp')
651
tn.set_debuglevel(debuglevel)
652
tn.open(host, port, timeout=0.5)
656
if __name__ == '__main__':