Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
e36f7356
Kaydet (Commit)
e36f7356
authored
Kas 01, 1993
tarafından
Guido van Rossum
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Major rewrite with new read_* interfaces
üst
0b26a19a
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
295 additions
and
155 deletions
+295
-155
telnetlib.py
Demo/cwilib/telnetlib.py
+295
-155
No files found.
Demo/cwilib/telnetlib.py
Dosyayı görüntüle @
e36f7356
# Telnet client library
# A TELNET client class. Based on RFC 854: TELNET Protocol
# Specification, by J. Postel and J. Reynolds
# Example:
#
# >>> from telnetlib import Telnet
# >>> tn = Telnet('voorn.cwi.nl', 79) # connect to finger port
# >>> tn.write('guido\r\n')
# >>> print tn.read_all()
# Login name: guido In real life: Guido van Rossum
# Office: M353, x4127 Home phone: 020-6225521
# Directory: /ufs/guido Shell: /usr/local/bin/esh
# On since Oct 28 11:02:16 on ttyq1
# Project: Multimedia Kernel Systems
# No Plan.
# >>>
#
# Note that read() won't read until eof -- it just reads some data
# (but it guarantees to read at least one byte unless EOF is hit).
#
# It is possible to pass a Telnet object to select.select() in order
# to wait until more data is available. Note that in this case,
# read_eager() may return '' even if there was data on the socket,
# because the protocol negotiation may have eaten the data.
# This is why EOFError is needed to distinguish between "no data"
# and "connection closed" (since the socket also appears ready for
# reading when it is closed).
#
# Bugs:
# - may hang when connection is slow in the middle of an IAC sequence
#
# To do:
# - option negotiation
# Imported modules
import
socket
import
socket
import
select
import
select
import
string
import
string
import
regsub
import
regsub
# Tunable parameters
# Tunable parameters
TIMEOUT
=
30.0
DEBUGLEVEL
=
0
DEBUGLEVEL
=
1
# Telnet protocol defaults
# Telnet protocol defaults
TELNET_PORT
=
23
TELNET_PORT
=
23
...
@@ -24,158 +58,264 @@ WILL = chr(251)
...
@@ -24,158 +58,264 @@ WILL = chr(251)
class
Telnet
:
class
Telnet
:
# Constructor
# Constructor
def
__init__
(
self
,
host
,
port
):
def
__init__
(
self
,
host
,
*
args
):
self
.
debuglevel
=
DEBUGLEVEL
if
not
args
:
self
.
host
=
host
port
=
TELNET_PORT
if
not
port
:
port
=
TELNET_PORT
else
:
self
.
port
=
port
if
len
(
args
)
>
1
:
raise
TypeError
,
'too many args'
self
.
timeout
=
TIMEOUT
port
=
args
[
0
]
self
.
sock
=
socket
.
socket
(
socket
.
AF_INET
,
socket
.
SOCK_STREAM
)
if
not
port
:
port
=
TELNET_PORT
self
.
sock
.
connect
((
self
.
host
,
self
.
port
))
self
.
debuglevel
=
DEBUGLEVEL
self
.
rawq
=
''
self
.
host
=
host
self
.
irawq
=
0
self
.
port
=
port
self
.
cookedq
=
''
self
.
sock
=
socket
.
socket
(
socket
.
AF_INET
,
socket
.
SOCK_STREAM
)
self
.
sock
.
connect
((
self
.
host
,
self
.
port
))
# Destructor
self
.
rawq
=
''
def
__del__
(
self
):
self
.
irawq
=
0
self
.
close
()
self
.
cookedq
=
''
self
.
eof
=
0
# Print debug message
def
msg
(
self
,
msg
,
*
args
):
# Destructor
if
self
.
debuglevel
>
0
:
def
__del__
(
self
):
print
'TELNET:'
,
msg
%
args
self
.
close
()
# Set debug level
# Debug message
def
set_debuglevel
(
self
,
debuglevel
):
def
msg
(
self
,
msg
,
*
args
):
self
.
debuglevel
=
debuglevel
if
self
.
debuglevel
>
0
:
print
'Telnet(
%
s,
%
d):'
%
(
self
.
host
,
self
.
port
),
msg
%
args
# Set time-out on certain reads
def
set_timeout
(
self
,
timeout
):
# Set debug level
self
.
timeout
=
float
(
timeout
)
def
set_debuglevel
(
self
,
debuglevel
):
self
.
debuglevel
=
debuglevel
# Explicit close
def
close
(
self
):
# Explicit close
if
self
.
sock
:
def
close
(
self
):
self
.
sock
.
close
()
if
self
.
sock
:
self
.
sock
=
None
self
.
sock
.
close
()
self
.
sock
=
None
# Return socket (e.g. for select)
self
.
eof
=
1
def
get_socket
(
self
):
return
self
.
sock
# Return socket (e.g. for select)
def
get_socket
(
self
):
# Return socket's fileno (e.g. for select)
return
self
.
sock
def
fileno
(
self
):
return
self
.
sock
.
fileno
()
# Return socket's fileno (e.g. for select)
def
fileno
(
self
):
# Write a string to the socket, doubling any IAC characters
return
self
.
sock
.
fileno
()
def
write
(
self
,
buffer
):
if
IAC
in
buffer
:
# Write a string to the socket, doubling any IAC characters
buffer
=
regsub
.
gsub
(
IAC
,
IAC
+
IAC
,
buffer
)
# Might block if the connection is blocked
self
.
sock
.
send
(
buffer
)
# May raise socket.error if the connection is closed
def
write
(
self
,
buffer
):
# Read until a given string is encountered or until timeout
if
IAC
in
buffer
:
def
read_until
(
self
,
match
):
buffer
=
regsub
.
gsub
(
IAC
,
IAC
+
IAC
,
buffer
)
## self.msg('read_until(%s)' % `match`)
self
.
sock
.
send
(
buffer
)
n
=
len
(
match
)
self
.
process_rawq
()
# The following read_* methods exist:
i
=
string
.
find
(
self
.
cookedq
,
match
)
# Special case:
if
i
<
0
:
# - read_until() reads until a string is encountered or a timeout is hit
i
=
max
(
0
,
len
(
self
.
cookedq
)
-
n
)
# These may block:
self
.
fill_cookedq
()
# - read_all() reads all data until EOF
i
=
string
.
find
(
self
.
cookedq
,
match
,
i
)
# - read_some() reads at least one byte until EOF
if
i
>=
0
:
# These may do I/O but won't block doing it:
i
=
i
+
n
# - read_very_eager() reads all data available on the socket
buf
=
self
.
cookedq
[:
i
]
# - read_eager() reads either data already queued or some data
self
.
cookedq
=
self
.
cookedq
[
i
:]
# available on the socket
## self.msg('read_until(%s) -> %s' % (`match`, `buf`))
# These don't do I/O:
return
buf
# - read_lazy() reads all data in the raw queue (processing it first)
while
select
.
select
([
self
],
[],
[],
self
.
timeout
)
==
\
# - read_very_lazy() reads all data in the cooked queue
([
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
# Read until a given string is encountered or until timeout
def
read_now
(
self
):
# Raise EOFError if connection closed and no cooked data available
self
.
fill_cookedq
()
# Return '' if no cooked data available otherwise
buf
=
self
.
cookedq
def
read_until
(
self
,
match
,
*
args
):
self
.
cookedq
=
''
if
not
args
:
## self.msg('read_now() --> %s' % `buf`)
timeout
=
None
else
:
if
len
(
args
)
>
1
:
raise
TypeError
,
'too many args'
timeout
=
args
[
0
]
n
=
len
(
match
)
self
.
process_rawq
()
i
=
string
.
find
(
self
.
cookedq
,
match
)
if
i
>=
0
:
i
=
i
+
n
buf
=
self
.
cookedq
[:
i
]
self
.
cookedq
=
self
.
cookedq
[
i
:]
return
buf
s_reply
=
([
self
],
[],
[])
s_args
=
s_reply
if
timeout
is
not
None
:
s_args
=
s_args
+
(
timeout
,)
while
not
self
.
eof
and
apply
(
select
.
select
,
s_args
)
==
s_reply
:
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
:]
return
buf
return
buf
return
self
.
read_very_lazy
()
# Read all data until EOF
# Block until connection closed
def
read_all
(
self
):
self
.
process_rawq
()
while
not
self
.
eof
:
self
.
fill_rawq
()
self
.
process_rawq
()
buf
=
self
.
cookedq
self
.
cookedq
=
''
return
buf
# Read at least one byte of cooked data unless EOF is hit
# Return '' if EOF is hit
# Block if no data is immediately available
def
read_some
(
self
):
self
.
process_rawq
()
while
not
self
.
cookedq
and
not
self
.
eof
:
self
.
fill_rawq
()
self
.
process_rawq
()
buf
=
self
.
cookedq
self
.
cookedq
=
''
return
buf
# Read everything that's possible without blocking in I/O (eager)
# Raise EOFError if connection closed and no cooked data available
# Return '' if no cooked data available otherwise
# Don't block unless in the midst of an IAC sequence
def
read_very_eager
(
self
):
self
.
process_rawq
()
while
not
self
.
eof
and
self
.
sock_avail
():
self
.
fill_rawq
()
self
.
process_rawq
()
return
self
.
read_very_lazy
()
# Read readily available data
# Raise EOFError if connection closed and no cooked data available
# Return '' if no cooked data available otherwise
# Don't block unless in the midst of an IAC sequence
def
read_eager
(
self
):
self
.
process_rawq
()
while
not
self
.
cookedq
and
not
self
.
eof
and
self
.
sock_avail
():
self
.
fill_rawq
()
self
.
process_rawq
()
return
self
.
read_very_lazy
()
# Process and return data that's already in the queues (lazy)
# Raise EOFError if connection closed and no data available
# Return '' if no cooked data available otherwise
# Don't block unless in the midst of an IAC sequence
def
read_lazy
(
self
):
self
.
process_rawq
()
return
self
.
read_very_lazy
()
# Return any data available in the cooked queue (very lazy)
# Raise EOFError if connection closed and no data available
# Return '' if no cooked data available otherwise
# Don't block
def
read_very_lazy
(
self
):
buf
=
self
.
cookedq
self
.
cookedq
=
''
if
not
buf
and
self
.
eof
and
not
self
.
rawq
:
raise
EOFError
,
'telnet connection closed'
return
buf
# Transfer from raw queue to cooked queue
# Set self.eof when connection is closed
# Don't block unless in the midst of an IAC sequence
def
process_rawq
(
self
):
buf
=
''
try
:
while
self
.
rawq
:
c
=
self
.
rawq_getchar
()
if
c
!=
IAC
:
buf
=
buf
+
c
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`
)
except
EOFError
:
# raised by self.rawq_getchar()
pass
self
.
cookedq
=
self
.
cookedq
+
buf
# Get next char from raw queue
# Block if no data is immediately available
# Raise EOFError when connection is closed
def
rawq_getchar
(
self
):
if
not
self
.
rawq
:
self
.
fill_rawq
()
if
self
.
eof
:
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 from exactly one recv() system call
# Block if no data is immediately available
# Set self.eof when connection is closed
def
fill_rawq
(
self
):
if
self
.
irawq
>=
len
(
self
.
rawq
):
self
.
rawq
=
''
self
.
irawq
=
0
# The buffer size should be fairly small so as to avoid quadratic
# behavior in process_rawq() above
buf
=
self
.
sock
.
recv
(
50
)
self
.
eof
=
(
not
buf
)
self
.
rawq
=
self
.
rawq
+
buf
# Test whether data is available on the socket
def
sock_avail
(
self
):
return
select
.
select
([
self
],
[],
[],
0
)
==
([
self
],
[],
[])
# Fill cooked queue without blocking
# Test program
def
fill_cookedq
(
self
):
# Usage: test [-d] ... [host [port]]
self
.
process_rawq
()
def
test
():
while
select
.
select
([
self
],
[],
[],
0
)
==
([
self
],
[],
[]):
import
sys
,
string
,
socket
,
select
self
.
fill_rawq
()
debuglevel
=
0
if
not
self
.
rawq
:
while
sys
.
argv
[
1
:]
and
sys
.
argv
[
1
]
==
'-d'
:
raise
EOFError
debuglevel
=
debuglevel
+
1
self
.
process_rawq
()
del
sys
.
argv
[
1
]
host
=
'localhost'
# Transfer from raw queue to cooked queue
if
sys
.
argv
[
1
:]:
def
process_rawq
(
self
):
host
=
sys
.
argv
[
1
]
# There is some silliness going on here in an attempt
port
=
0
# to avoid quadratic behavior with large inputs...
if
sys
.
argv
[
2
:]:
buf
=
''
portstr
=
sys
.
argv
[
2
]
while
self
.
rawq
:
try
:
c
=
self
.
rawq_getchar
()
port
=
string
.
atoi
(
portstr
)
if
c
!=
IAC
:
except
string
.
atoi_error
:
buf
=
buf
+
c
port
=
socket
.
getservbyname
(
portstr
,
'tcp'
)
if
len
(
buf
)
>=
44
:
tn
=
Telnet
(
host
,
port
)
## self.msg('transfer: %s' % `buf`)
tn
.
set_debuglevel
(
debuglevel
)
self
.
cookedq
=
self
.
cookedq
+
buf
while
1
:
buf
=
''
rfd
,
wfd
,
xfd
=
select
.
select
([
tn
,
sys
.
stdin
],
[],
[])
continue
if
sys
.
stdin
in
rfd
:
c
=
self
.
rawq_getchar
()
line
=
sys
.
stdin
.
readline
()
if
c
==
IAC
:
tn
.
write
(
line
)
buf
=
buf
+
c
if
tn
in
rfd
:
elif
c
in
(
DO
,
DONT
):
try
:
opt
=
self
.
rawq_getchar
()
text
=
tn
.
read_eager
()
self
.
msg
(
'IAC
%
s
%
d'
,
except
EOFError
:
c
==
DO
and
'DO'
or
'DONT'
,
print
'*** Connection closed by remote host ***'
ord
(
c
))
break
self
.
sock
.
send
(
IAC
+
WONT
+
opt
)
if
text
:
elif
c
in
(
WILL
,
WONT
):
sys
.
stdout
.
write
(
text
)
opt
=
self
.
rawq_getchar
()
sys
.
stdout
.
flush
()
self
.
msg
(
'IAC
%
s
%
d'
,
tn
.
close
()
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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment