1
0
Fork 0
zmodemjs/tools/talk_to_sz.pl

228 lines
4.4 KiB
Perl
Raw Permalink Normal View History

#!/usr/bin/env perl
use strict;
use warnings;
use autodie;
use constant CANCEL_BYTES => (
((24) x 5),
((8) x 5),
#0,
);
use constant ZCAN_BYTES => (
42, 42, 24, 66, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 52, 53, 97, 13, 10, 17
);
use constant VERBOSE => '-vvvvvvvvvvvv';
use feature 'say';
use IO::Poll ();
use File::Temp ();
use File::Which ();
use Text::Control ();
my $COMMAND = 'sz';
#my @verbose_flags = ( VERBOSE() );
my @verbose_flags = ();
my $size = 2**24;
my $file_content = ('x' x $size) . '=THE END';
my $cmd_path = File::Which::which($COMMAND) or die "Need “$COMMAND”!";
#$cmd_path = '/Users/felipe/code/lrzsz/src/lsz';
my ($tfh, $tpath) = File::Temp::tempfile( CLEANUP => 1 );
print "temp file path: $tpath\n";
syswrite $tfh, $file_content;
close $tfh;
pipe( my $pr, my $cw );
pipe( my $cr, my $pw );
my $pid = fork or do {
close $_ for ($pr, $pw);
open \*STDIN, '<&=', $cr;
open \*STDOUT, '>>&=', $cw;
exec $cmd_path, @verbose_flags, $tpath or die $!;
};
close $_ for ($cr, $cw);
$pr->blocking(0);
my $poll = IO::Poll->new();
$poll->mask( $pr, IO::Poll::POLLIN() );
sub _poll_in {
return $poll->poll(30) || die 'Timed out on read!';
}
sub _read {
_poll_in();
my $buf = q<>;
sysread( $pr, $buf, 4096, length $buf ); #itll never be that big
return $buf;
}
sub _read_and_report {
my $input = _read();
_report_from_child($input);
}
sub _report_from_child {
my $bytes = $_[0];
my $truncated_yn;
my $orig_len = length $bytes;
if ($orig_len > 70) {
substr($bytes, 25) = q<>;
$truncated_yn = 1;
}
$bytes = Text::Control::to_hex($bytes);
if ($truncated_yn) {
$bytes .= ' … ' . Text::Control::to_hex( substr($_[0], -45) );
$bytes .= " ($orig_len bytes)";
}
say "$COMMAND says: $bytes";
}
sub _write { syswrite $pw, $_[0]; }
sub _write_octets {
my $bytes = join( q<>, map { chr } @_ );
_write( $bytes );
say "to $COMMAND: " . Text::Control::to_hex($bytes);
}
sub _write_and_wait_to_finish {
_write_octets(@_);
_wait_to_finish();
}
sub _wait_to_finish {
close $pw;
$pr->blocking(1);
my $buf = q<>;
while (my $read = sysread $pr, $buf, 65536) {
if ($buf =~ m<=THE END>) {
print STDERR "\x07XXXXX FAILED TO STOP THE ONSLAUGHT!!\n";
sleep 2;
}
print "=========== FINAL ($read) ===========\n";
_report_from_child($buf);
}
close $pr;
waitpid $pid, 0;
my $exit = $? >> 8;
print "$COMMAND exit: $exit\n";
exit;
}
sub _send_cancel {
print "======= SENDING CANCEL\n";
_write_and_wait_to_finish( CANCEL_BYTES() );
}
sub _read_until_packet_end {
my $buf = q<>;
my $next_header;
while (1) {
if ($buf =~ m<\x18h..(.*)>) {
$next_header = $1;
last;
}
_poll_in();
sysread $pr, $buf, 65536, length $buf;
}
print "\nEnd of packet\n";
_report_from_child($next_header) if length $next_header;
return;
}
sub _send_ZCAN {
print "======= SENDING ZCAN\n";
_write_and_wait_to_finish( ZCAN_BYTES() );
}
#----------------------------------------------------------------------
#Shows ZRQINIT
_read_and_report();
#_send_cancel(); #works
#_send_ZCAN(); #doesnt work
use constant ZRINIT_BYTES => (
#CANOVIO, CANFDX
#42, 42, 24, 66, 48, 49, 48, 48, 48, 48, 48, 48, 48, 48, 97, 97, 53, 49, 13, 10, 17,
#CANOVIO, CANFDX, CANFC32
qw( 42 42 24 66 48 49 48 48 48 48 48 48 50 51 98 101 53 48 13 10 17 ),
);
use constant ZSKIP_BYTES => (
42, 42, 24, 66, 48, 53, 48, 48, 48, 48, 48, 48, 48, 48, 50, 51, 53, 55, 13, 10, 17,
);
#ZRINIT
_write_octets( ZRINIT_BYTES() );
#Shows ZFILE and offer subpacket
_read_and_report();
#_send_cancel(); #works
#_send_ZCAN(); #works
#ZRPOS
_write_octets(
42, 42, 24, 66, 48, 57, 48, 48, 48, 48, 48, 48, 48, 48, 97, 56, 55, 99, 13, 10, 17
);
#Shows initial batch of file data
#_read_and_report();
#
#_send_ZCAN(); #works - BUFFER OVERFLOW
_send_cancel(); #works - BUFFER OVERFLOW
_read_and_report();
#_write_octets( ZSKIP_BYTES() );
#_read_until_packet_end();
#_send_cancel(); #works
#ZRINIT
_write_octets( ZRINIT_BYTES() );
#_send_cancel(); #works
_read_and_report();
_send_cancel(); #works - but by this point the transfer is done
#ZFIN
_write_octets(
42, 42, 24, 66, 48, 56, 48, 48, 48, 48, 48, 48, 48, 48, 48, 50, 50, 100, 13, 10
);
_wait_to_finish();