Simulating Telnet from a Program (Perl Cookbook, 2nd Edition)

## 18.6. Simulating Telnet from a Program

### 18.6.1. Problem

You want to simulate a telnet connection from your program by logging into a remote machine, issuing commands, and reacting to what is returned. This has many applications, from automating tasks on machines you can telnet to but which don't support scripting or rsh, to simply testing whether a machine's Telnet daemon is still running properly.

### 18.6.2. Solution

Use the CPAN module Net::Telnet:

>     use Net::Telnet;

>     $t = Net::Telnet->new( Timeout => 10,
>                            Prompt  => '/%/',
>                            Host    => $hostname );

>     $t->login($username, $password);
>     @files = $t->cmd("ls");
>     $t->print("top");
>     (undef, $process_string) = $t->waitfor('/\d+ processes/');
>     $t->close;

### 18.6.3. Discussion

Net::Telnet provides an object-oriented interface to the Telnet protocol. Create a connection with `Net::Telnet->new`, then interact with the remote machine using method calls on the resulting object.

Give the `new` method a list of named-parameter pairs, much like initializing a hash. We'll cover only a few possible parameters. The most important is `Host`, the machine you're telnetting to. The default host is `localhost`. To connect to a port other than the one Telnet normally uses, specify this in the `Port` option. Error handling is done through the function whose reference is specified in the `Errmode` parameter.

Another important option is `Prompt`. When you log in or run a command, Net::Telnet uses the `Prompt` pattern to determine when the login or command has completed. The default `Prompt` is:

>     /[\$%#>] $/

which matches the common Unix shell prompts. If the prompt on the remote machine doesn't match the default pattern, you have to specify your own. Remember to include slashes.

`Timeout` lets you control how long (in seconds) network operations wait before they give up. The default is 10 seconds.

An error or timeout in the Net::Telnet module raises an exception by default, which, if uncaught, prints a message to `STDERR` and exits. To change this, pass `new` a subroutine reference to the `Errmode` argument. If instead of a code subroutine you specify the string "`return`" as the `Errmode`, methods return `undef` (in scalar context) or an empty list (in list context) on error, with the error message available via the `errmsg` method:

>     $telnet = Net::Telnet->new( Errmode => sub { main::log(@_) }, ... );

The `login` method sends a username and password to the remote machine. It uses the `Prompt` to decide when the login is complete and times out if the machine doesn't reply with a prompt:

>     $telnet->login($username, $password)
>         or die "Login failed: @{[ $telnet->errmsg( ) ]}\n";

To run a program and gather its output, use the `cmd` method. Pass it the string to send; it returns the command output as one line per list element in list context, or as one long line in scalar context. It waits for the `Prompt` before returning.

Separate sending the command from reception of its output with the `print` and `waitfor` methods, as we do in the Solution. The `waitfor` method takes either a single string containing a Perl regular expression in slashes:

>     $telnet->waitfor('/--more--/')

or named arguments. `Timeout` specifies a timeout to override the default, `Match` is a string containing a match operator as shown earlier, and `String` is a literal string to find:

>     $telnet->waitfor(String => 'greasy smoke', Timeout => 30)

In scalar context, `waitfor` returns true if the pattern or string was found. Otherwise, the `Errmode` action is performed. In list context, it returns two strings: any text before the match and the matching text itself.

### 18.6.4. See Also

The documentation for the Net::Telnet module from CPAN; RFCs 854-856, as amended by later RFCs

Copyright © 2003 O'Reilly & Associates. All rights reserved.