Foundations of Python Network Programming 978-1-4302-3004-5
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
CHAPTER 16 ■ TELNET AND SSH<br />
• The more powerful and sophisticated expect() method takes a list <strong>of</strong> <strong>Python</strong><br />
regular expressions. Once the text arriving from the remote end finally adds up to<br />
something that matches one <strong>of</strong> the regular expressions, expect() returns three<br />
items: the index in your list <strong>of</strong> the pattern that matched, the regular expression<br />
SRE_Match object itself, and the text that was received leading up to the matching<br />
text. For more information on what you can do with a SRE_Match, including finding<br />
the values <strong>of</strong> any sub-expressions in your pattern, read the Standard Library<br />
documentation for the re module.<br />
Regular expressions, as always, have to be written carefully. When I first wrote this script, I used '$'<br />
as the expect() pattern that watched for the shell prompt to appear—which, <strong>of</strong> course, is a special<br />
character in a regular expression! So the corrected script shown in the listing escapes the $ so that<br />
expect() actually waits until it sees a dollar sign arrive from the remote end.<br />
If the script sees an error message because <strong>of</strong> an incorrect password—and does not get stuck waiting<br />
forever for a login or password prompt that never arrives or that looks different than it was expecting—<br />
then it exits:<br />
$ python telnet_login.py<br />
Username and password failed - giving up<br />
If you wind up writing a <strong>Python</strong> script that has to use Telnet, it will simply be a larger or more<br />
complicated version <strong>of</strong> the same simple pattern shown here.<br />
Both read_until() and expect() take an optional second argument named timeout that places a<br />
maximum limit on how long the call will watch for the text pattern before giving up and returning<br />
control to your <strong>Python</strong> script. If they quit and give up because <strong>of</strong> the timeout, they do not raise an error;<br />
instead—awkwardly enough—they just return the text they have seen so far, and leave it to you to figure<br />
out whether that text contains the pattern!<br />
There are a few odds and ends in the Telnet object that we need not cover here. You will find them<br />
in the telnetlib Standard Library documentation—including an interact() method that lets the user<br />
“talk” directly over your Telnet connection using the terminal! This kind <strong>of</strong> call was very popular back in<br />
the old days, when you wanted to automate login but then take control and issue normal commands<br />
yourself.<br />
The Telnet protocol does have a convention for embedding control information, and telnetlib<br />
follows these protocol rules carefully to keep your data separate from any control codes that appear. So<br />
you can use a Telnet object to send and receive all <strong>of</strong> the binary data you want, and ignore the fact that<br />
control codes might be arriving as well. But if you are doing a sophisticated Telnet-based project, then<br />
you might need to process options.<br />
Normally, each time a Telnet server sends an option request, telnetlib flatly refuses to send or<br />
receive that option. But you can provide a Telnet object with your own callback function for processing<br />
options; a modest example is shown in Listing 16–4. For most options, it simply re-implements the<br />
default telnetlib behavior and refuses to handle any options (and always remember to respond to each<br />
option one way or another; failing to do so will <strong>of</strong>ten hang the Telnet session as the server waits forever<br />
for your reply). But if the server expresses interest in the “terminal type” option, then this client sends<br />
back a reply <strong>of</strong> “mypython,” which the shell command it runs after logging in then sees as its $TERM<br />
environment variable.<br />
Listing 16–4. How to Process Telnet Option Codes<br />
#!/usr/bin/env python<br />
# <strong>Foundations</strong> <strong>of</strong> <strong>Python</strong> <strong>Network</strong> <strong>Programming</strong> - Chapter 16 - telnet_codes.py<br />
# How your code might look if you intercept Telnet options yourself<br />
from telnetlib import Telnet, IAC, DO, DONT, WILL, WONT, SB, SE, TTYPE<br />
277