Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

$ENV{TERM} and Net::Telnet

by bbutler (Initiate)
on Jun 11, 2002 at 22:44 UTC ( [id://173684]=perlquestion: print w/replies, xml ) Need Help??

bbutler has asked for the wisdom of the Perl Monks concerning the following question:

i'm having some trouble with Net::Telnet. the remote machine queries the TERM shell variable in order to see if a 'resize' command should be issued. if TERM is 'no-resize-vt100', it does no resize, otherwise, 'resize' is executed. of course, 'resize' hangs on a non-interactive session, and the script gets no further. so, i try to set TERM via $ENV{TERM}, but it doesn't seem to work. in detail, here is the full script:
#!/usr/local/bin/perl use Env qw(TERM); $ENV{TERM} = 'no-resize-vt100'; use Net::Telnet; $connection = new Net::Telnet ( Host=>'ssd.jpl.nasa.gov', Port=>6775); $connection->open(); $connection->waitfor('/Horizons> /'); $connection->print('load vla-1'); $connection->waitfor('/Horizons> /'); $connection->print('page'); $connection->waitfor('/Horizons> /'); $connection->print('799'); $connection->waitfor('/.*Select.*: $/'); $connection->print('e'); $connection->waitfor('/.*Observe.*: $/'); $connection->print('o'); $connection->waitfor('/.*Coordinate.*: $/'); $connection->print('500@399'); $connection->waitfor('/.*Starting.*: $/'); $connection->print('1981-Mar-07 08:00'); $connection->waitfor('/.*Ending.*: $/'); $connection->print('1981-Mar-07 17:00'); $connection->waitfor('/.*interval.*: $/'); $connection->print('10m'); $connection->waitfor('/.*Accept.*: $/'); $connection->print('y'); $connection->waitfor('/.*Select.*: $/'); $connection->print('y'); $connection->print('q'); $connection->close; exit 0;
which hangs at the $connection->open() command, because the session tries to do a 'resize' (i can see this by putting in a $connection->input_log(...) statement). so, for some reason, the TERM variable doesn't seem to be getting set/reset correctly. the equivalent expect script, which looks like this:
#!/usr/bin/expect set env(TERM) no-resize-vt100 spawn telnet ssd.jpl.nasa.gov 6775 expect "Horizons> " { send "load vla-1\r" } expect "Horizons> " { send page\r } expect "Horizons> " { send 799\r } expect -re ".*Select.*: $" { send e\r } expect -re ".*Observe.*: $" { send o\r } expect -re ".*Coordinate.*: $" { send 500@399\r } expect -re ".*Starting.*: $" { send "1981-Mar-07 08:00\r" } expect -re ".*Ending.*: $" { send "1981-Mar-07 17:00\r" } expect -re ".*interval.*: $" { send 10m\r } expect -re ".*Accept.*: $" { send y\r } expect -re ".*Select.*: $" { send q\r } exit 0
works perfectly, i.e., the TERM variable seems to get set correctly, and the remote machine never attempts to do the 'resize'.

what am i doing wrong in the Perl version?

Replies are listed 'Best First'.
Re: $ENV{TERM} and Net::Telnet
by Mr. Muskrat (Canon) on Jun 12, 2002 at 01:43 UTC

    I was drawn to this post because of where you are trying to retrieve data from and because I too have had problems with Net::Telnet scripts not working as expected... After much trial and error, I have arrived at a solution... not the best solution but it works. Most of your code is still there.

    #!/usr/local/bin/perl use strict; use warnings; #use Env qw(TERM); #$ENV{TERM} = 'no-resize-vt100'; # doesn't work even if it is defined +... at least on win2k with ActiveState Perl use Net::Telnet; my $connection = new Net::Telnet ( Host =>' ssd.jpl.nasa.gov', Port => 6775, Dump_Log => './telnet.log', Input_log => './telnet.txt', timeout => 10, ); $connection->open(); $connection->print(''); # couldn't get the tty command to work either +but this forces it to continue $connection->waitfor('/Press return to continue -->/'); # Is it waitin +g for user input? $connection->print(''); # what are you waiting for? press return! $connection->waitfor('/Horizons>\s+$/'); $connection->print('load vla-1'); $connection->waitfor('/Horizons>\s+$/'); $connection->print('page'); $connection->waitfor('/Horizons>\s+$/'); $connection->print('799'); $connection->waitfor('/.*Select.*: $/'); $connection->print('e'); $connection->waitfor('/.*Observe.*: $/'); $connection->print('o'); $connection->waitfor('/.*Coordinate.*: $/'); $connection->print('500@399'); $connection->waitfor('/.*Starting.*: $/'); $connection->print('1981-Mar-07 08:00'); $connection->waitfor('/.*Ending.*: $/'); $connection->print('1981-Mar-07 17:00'); $connection->waitfor('/.*interval.*: $/'); $connection->print('10m'); $connection->waitfor('/.*Accept.*: $/'); $connection->print('y'); $connection->waitfor('/.*Select.*: $/'); $connection->print('y'); $connection->print('q'); $connection->close; exit 0;

    Who says that programmers can't work in the Marketing Department?
    Or is that who says that Marketing people can't program?
Re: $ENV{TERM} and Net::Telnet
by Mr. Muskrat (Canon) on Jun 12, 2002 at 00:49 UTC

    You might want to consider using this connection method:

    $connection = new Net::Telnet ( Host => 'ssd.jpl.nasa.gov', Port => 6775, Dump_Log => './telnet.log', );
    It will output everything received to a log file.
    Who says that programmers can't work in the Marketing Department?
    Or is that who says that Marketing people can't program?
Re: $ENV{TERM} and Net::Telnet
by Fastolfe (Vicar) on Jun 12, 2002 at 02:57 UTC
    I don't believe Net::Telnet does terminal type option negotiation. As a result, setting this environment variable probably isn't having any effect.

    To see the types of option negotiation performed with your stock 'telnet' application, use the "toggle options" command:

    $ telnet telnet> toggle options Will show option processing. telnet> open shell.example.com ...
    You should then get a bunch of diagnostic output showing the telnet options being passed back and forth, and among those should be options specifying a willingness to negotiate terminal type and the request and reply with the actual information.

    Your job, should you choose to really need it, would be to get your Net::Telnet object to send these options when you make your connection, probably through callbacks and the like. Looking at documentation for the module, the 'option_send' function should start you on the track, but it doesn't look like it's implemented. You've gotta let the other end know you're willing to do terminal type negotiation, and presumably then you could use the option_callback function to respond to a request for the terminal type. :/

      this was the key. thanks much, fastolfe!

      the solution by mr. muskrat was interesting, but really not the right way to go about this. thanks to him also though.

      the reply by abigail is not right - Net::Telnet *does* correctly implement the telnet protocol, and establishes the connection in the proper way.

      i was under the impression that the terminal type was always negotiated in a telnet session, but this is not the case. it turns out in my particular application, the remote client asks for the terminal type, but that particular negotiation is *not* enabled by default, so the local side was rejecting the request. i figured this out by doing a $connection->option_log('option.log'); statement (equivalently, i could have included the option in the object creation, but i like to keep them separate - makes it easier to comment them out as i go). so, i had to figure out how to make the local side not only accept a request for the terminal type, but then to send it back to the remote client. this is not trivial. fortunately, i found some help on the web at: http://dbforums.com/archive/96/2002/02/1/256002 which shows how to do it.

      note that this takes advantage of a completely undocumented part of Net::Telnet (suboption_callback), and if i had not found this example on the web, i would have been pulling my hair out for days trying to figure it out. so, here is the modified code, which works perfectly:

      #!/usr/local/bin/perl use Net::Telnet qw (TELOPT_TTYPE); $termtype = 'no-resize-vt100'; $telopt_ttype_ok = ''; $connection = new Net::Telnet ( Host=>'ssd.jpl.nasa.gov', Port=>6775 ); $connection->option_callback(\&opt_callback); $connection->option_accept(Do=>TELOPT_TTYPE); $connection->suboption_callback(\&subopt_callback); $connection->open(); $connection->waitfor('/Horizons> /'); $connection->print('load vla-1'); $connection->waitfor('/Horizons> /'); $connection->print('page'); $connection->waitfor('/Horizons> /'); $connection->print('799'); $connection->waitfor('/.*Select.*: $/'); $connection->print('e'); $connection->waitfor('/.*Observe.*: $/'); $connection->print('o'); $connection->waitfor('/.*Coordinate.*: $/'); $connection->print('-5@399'); $connection->waitfor('/.*Starting.*: $/'); $connection->print('1981-Mar-07 08:00'); $connection->waitfor('/.*Ending.*: $/'); $connection->print('1981-Mar-07 17:00'); $connection->waitfor('/.*interval.*: $/'); $connection->print('10m'); $connection->waitfor('/.*Accept.*: $/'); $connection->print('y'); $connection->input_log('horizons.ephem.log'); $connection->waitfor('/.*Select.*: $/'); $connection->input_log(''); $connection->print('q'); $connection->close; exit 0; sub opt_callback { my ($obj, $option, $is_remote, $is_enabled, $was_enabled, $buf_positi +on) = @_; if ($option == TELOPT_TTYPE and $is_enabled and !$is_remote) { $telopt_ttype_ok = 1; } 1; } sub subopt_callback { my ($obj, $option, $parameters) = @_; my $ors_old; if ($option == TELOPT_TTYPE) { $ors_old = $obj->output_record_separator(""); $obj->print("\xff\xfa", pack("CC", $option, 0), $termtype, "\xff\xf0 +"); $obj->output_record_separator($ors_old); } 1; }
      thanks again to fastolfe for pointing me in the right direction!

      bbutler
Re: $ENV{TERM} and Net::Telnet
by Abigail-II (Bishop) on Jun 12, 2002 at 11:02 UTC
    As far as I know, Net::Telnet doesn't actually talk the telnet protocol. Note that you are connecting to a non-standard prot (23 is the telnet port), and many telnet clients don't use the telnet protocol if you use them to connect to a non-standard port. (Luckely I must say, I wouldn't want my telnet client to try to negotiate to a webserver if I do telnet host 80).

    I haven't heard of an available module out there that does implement the telnet protocol, but that doesn't mean there isn't one.

    Abigail

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://173684]
Approved by rob_au
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (3)
As of 2024-04-20 05:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found