09.11.2016 Views

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!