/usr/share/doc/libterm-vt102-perl/examples/telnet-usage.pl is in libterm-vt102-perl 0.91-1.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | #!/usr/bin/perl
#
# Example script showing how to use Term::VT102 with Net::Telnet. Telnets to
# localhost and dumps what Term::VT102 thinks should be on the screen. Or
# you can pass it a host and a port and it will telnet there instead.
#
# Note that this script doesn't pass the terminal size through to the remote
# end, so you might have to do "stty rows 24 cols 80" to make things work
# (the default is generally 80x24 anyway though).
#
# Logs all terminal output to STDERR if STDERR is redirected to a file.
#
use Net::Telnet qw(TELOPT_TTYPE);
use Term::VT102;
use IO::Handle;
use strict;
$| = 1;
my ($host, $port) = @ARGV;
$host = 'localhost' if (not defined $host);
$port = 23 if (not defined $port);
my $t = new Net::Telnet (
'Host' => $host,
'Port' => $port,
'Errmode' => 'return',
'Timeout' => 1,
'Output_record_separator' => '',
);
die "failed to connect to $host:$port" if (not defined $t);
$t->option_callback (\&opt_callback);
$t->option_accept ('Do' => TELOPT_TTYPE);
$t->suboption_callback (\&subopt_callback);
my $vt = Term::VT102->new (
'cols' => 80,
'rows' => 24,
);
# Convert linefeeds to linefeed + carriage return.
#
$vt->option_set ('LFTOCRLF', 1);
# Make sure line wrapping is switched on.
#
$vt->option_set ('LINEWRAP', 1);
# Set up the callback for OUTPUT; this callback function simply sends
# whatever the Term::VT102 module wants to send back to the terminal and
# sends it to Net::Telnet - see its definition below.
#
$vt->callback_set ('OUTPUT', \&vt_output, $t);
# Set up a callback for row changes, so we can process updates and display
# them without having to redraw the whole screen every time. We catch CLEAR,
# SCROLL_UP, and SCROLL_DOWN with another function that triggers a
# whole-screen repaint. You could process SCROLL_UP and SCROLL_DOWN more
# elegantly, but this is just an example.
#
my $changedrows = {};
$vt->callback_set ('ROWCHANGE', \&vt_rowchange, $changedrows);
$vt->callback_set ('CLEAR', \&vt_changeall, $changedrows);
$vt->callback_set ('SCROLL_UP', \&vt_changeall, $changedrows);
$vt->callback_set ('SCROLL_DOWN', \&vt_changeall, $changedrows);
my ($telnetbuf, $io, $stdinbuf, $prevxy);
$io = new IO::Handle;
$io->fdopen (fileno(STDIN), 'r');
$io->blocking (0);
system 'stty raw -echo';
$prevxy = '';
while (1) {
last if ($t->eof ());
my ($rin, $win, $ein, $rout, $wout, $eout, $nr, $delay, $didout);
($rin, $win, $ein) = ('', '', '');
vec ($rin, fileno ($t), 1) = 1;
vec ($rin, fileno ($io), 1) = 1;
# If we have any changed rows on the screen still waiting to be
# output, we only wait a short time for activity, otherwise we wait
# a full second. This is so that batched-up screen updates get
# processed in a timely fashion.
#
$delay = 1;
$delay = 0.05 if ((scalar keys %$changedrows) > 0);
select ($rout=$rin, $wout=$win, $eout=$ein, $delay);
$telnetbuf = undef;
if (vec ($rout, fileno ($t), 1)) {
$telnetbuf = $t->get ('Timeout' => 1);
if (defined $telnetbuf) {
$vt->process ($telnetbuf);
print STDERR $telnetbuf if (! -t STDERR);
}
}
$telnetbuf = '' if (not defined $telnetbuf);
# Do your stuff here - use $vt->row_plaintext() to see what's on various
# rows of the screen, for instance, or before this main loop you could set
# up a ROWCHANGE callback which checks the changed row, or whatever.
#
# In this example, we just pass standard input to the telnet stream, we take
# the data coming back from Net::Telnet and pass it to the Term::VT102
# object, any changed rows of which we dump to the screen.
# Read key presses from standard input and pass them to Net::Telnet.
#
$stdinbuf = '';
if (vec ($rout, fileno ($io), 1)) {
if (defined $io->sysread ($stdinbuf, 16)) {
$t->print ($stdinbuf);
}
}
# Dump what Term::VT102 thinks is on the screen. We only output rows
# we know have changed, to avoid generating too much output.
#
$didout = 0;
foreach my $row (sort keys %$changedrows) {
printf "\e[%dH%s\r", $row, $vt->row_sgrtext ($row);
delete $changedrows->{$row};
$didout ++;
}
if (($didout > 0) || ($prevxy != ''.$vt->x.','.$vt->y)) {
printf "\e[%d;%dH", $vt->y, ($vt->x > $vt->cols ? $vt->cols : $vt->x);
}
}
$t->close ();
print "\e[24H\r\n";
system 'stty sane';
# Callback for "DO" handling - for Net::Telnet.
#
sub opt_callback {
my ($obj,$opt,$is_remote,$is_enabled,$was_enabled,$buf_position) = @_;
if ($opt == TELOPT_TTYPE and $is_enabled and !$is_remote) {
#
# Perhaps do something if we get TELOPT_TTYPE switched on?
#
}
return 1;
}
# Callback for sub-option handling - for Net::Telnet.
#
sub subopt_callback {
my ($obj, $opt, $parameters) = @_;
my ($ors_old, $otm_old);
# Respond to TELOPT_TTYPE with "I'm a VT100".
#
if ($opt == TELOPT_TTYPE) {
$ors_old = $obj->output_record_separator ('');
$otm_old = $obj->telnetmode (0);
$obj->print (
"\xff\xfa",
pack ('CC', $opt, 0),
'vt100',
"\xff\xf0"
);
$obj->telnetmode ($otm_old);
$obj->output_record_separator ($ors_old);
}
return 1;
}
# Callback for OUTPUT events - for Term::VT102.
#
sub vt_output {
my ($vtobject, $type, $arg1, $arg2, $private) = @_;
if ($type eq 'OUTPUT') {
$private->print ($arg1);
}
}
# Callback for ROWCHANGE events. This just sets a time value for the changed
# row using the private data as a hash reference - the time represents the
# earliest that row was changed since the last screen update.
#
sub vt_rowchange {
my ($vtobject, $type, $arg1, $arg2, $private) = @_;
$private->{$arg1} = time if (not exists $private->{$arg1});
}
# Callback to trigger a full-screen repaint.
#
sub vt_changeall {
my ($vtobject, $type, $arg1, $arg2, $private) = @_;
for (my $row = 1; $row <= $vtobject->rows; $row++) {
$private->{$row} = 0;
}
}
# EOF
|