09.11.2016 Views

Foundations of Python Network Programming 978-1-4302-3004-5

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

CHAPTER 16 ■ TELNET AND SSH<br />

tabify2.py<br />

test.py<br />

So what does all <strong>of</strong> this have to do with network programming?<br />

Well, these two behaviors that we have seen—the fact that programs tend to display prompts if<br />

connected to a terminal, but omit them and run silently if they are reading from a file or from the output<br />

<strong>of</strong> another command—also occur at the remote end <strong>of</strong> the shell protocols that we are considering in this<br />

chapter.<br />

A program running behind Telnet, for example, always thinks it is talking to a terminal; so your<br />

scripts or programs must always expect to see a prompt each time the shell is ready for input, and so<br />

forth. But when you make a connection over the more sophisticated SSH protocol, you will actually have<br />

your choice <strong>of</strong> whether the program thinks that its input is a terminal or just a plain pipe or file. You can<br />

test this easily from the command line if there is another computer you can connect to:<br />

$ ssh -t asaph<br />

asaph$ echo "Here we are, at a prompt."<br />

Here we are, at a prompt.<br />

asaph$ exit<br />

$ ssh -T asaph<br />

echo "The shell here on asaph sees no terminal; so, no prompt."<br />

The shell here on asaph sees no terminal; so, no prompt.<br />

exit<br />

$<br />

So when you spawn a command through a modern protocol like SSH, you need to consider whether<br />

you want the program on the remote end thinking that you are a person typing at it through a terminal,<br />

or whether it had best think it is talking to raw data coming in through a file or pipe.<br />

Programs are not actually required to act any differently when talking to a terminal; it is just for our<br />

convenience that they vary their behavior. They do so by calling the equivalent <strong>of</strong> the <strong>Python</strong> isatty()<br />

call (“is this a teletype?”) that you saw in the foregoing example session, and then having “if” statements<br />

everywhere that vary their behavior depending on what this call returns. Here are some common ways<br />

that they behave differently:<br />

• Programs that are <strong>of</strong>ten used interactively will present a human-readable prompt<br />

when they are talking to a terminal. But when they think input is coming from a<br />

file, they avoid printing a prompt, because otherwise your screen would become<br />

littered with hundreds <strong>of</strong> successive prompts as you ran a long shell script or<br />

<strong>Python</strong> program!<br />

• Sophisticated interactive programs, these days, usually turn on command-line<br />

editing when their input is a TTY. This makes many control characters special,<br />

because they are used to access the command-line history and perform editing<br />

commands. When they are not under the control <strong>of</strong> a terminal, these same<br />

programs turn command-line editing <strong>of</strong>f and absorb control characters as normal<br />

parts <strong>of</strong> their input stream.<br />

• Many programs read only one line <strong>of</strong> input at a time when listening to a terminal,<br />

because humans like to get an immediate response to every command they type.<br />

But when reading from a pipe or file, these same programs will wait until<br />

thousands <strong>of</strong> characters have arrived before they try to interpret their first batch <strong>of</strong><br />

input. As we just saw, bash stays in line-at-a-time mode even if its input is a file,<br />

but <strong>Python</strong> decided it wanted to read a whole <strong>Python</strong> script from its input before<br />

trying to execute even its first line.<br />

272

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

Saved successfully!

Ooh no, something went wrong!