#!/usr/local/bin/perl # Currently we only support ASCII use Getopt::Std; use IO::Socket; use IO::Select; $BUFFSIZE = 1024; %options = (); $x = getopts( 's:d:h', \%options ); usage() if ( ( ! $options{ 's' } && ! $options{ 'd' } ) || $options{ 'h' } ); # Putting the data out the destination is just a print whether file, STDOUT, # or a socket. $DST = setdestination( $options{ 'd' } ); ( $SRC, $LMODE ) = setsource( $options{ 's' } ); # Depending on the source, we need different loop styles. if ( $LMODE eq 'file' ) { # source data is a file or STDIN while ( sysread( $SRC, $buffer, $BUFFSIZE ) ) { syswrite( $DST, $buffer, $BUFFSIZE ); } close( $DST ); close( $SRC ); exit; } # If source is not file or STDIN, must be a socket. But I # only know of different ways to handle tcp and udp. if ( $LMODE eq 'tcp' ) { while ( $new_socket = $SRC -> accept() ) { while ( sysread( $new_socket, $buffer, $BUFFSIZE ) ) { syswrite( $DST, $buffer, $BUFFSIZE ); } } close( $DST ); close( $SRC ); } else { $selects = new IO::Select(); $selects -> add( $SRC ); while ( 1 ) { foreach $server ( $selects -> can_read( 60 ) ) { $server -> recv( $buffer, $BUFFSIZE ); syswrite( $DST, $buffer, $BUFFSIZE ); } } close( $DST ); close( $SRC ); } sub setsource { my ( $source ) = $_[0]; my ( $ip, $port, $proto ); my $result, $lmode; $lmode = 'file'; if ( ! $source ) { $result = STDIN; } elsif ( $source =~ /\:[0-9]+\// ) { ( $ip, $port, $proto ) = $source =~ /^([^:]+):([0-9]+)\/(.+)$/; $lmode = $proto; if ( $proto =~ /tcp/ ) { $result = new IO::Socket::INET( LocalHost => $ip, LocalPort => $port, Reuse => 1, Listen => 5 ); if ( ! $result ) { print "Unable to create socket: $!\n...Terminating.\n\n"; exit; } } else { $result = new IO::Socket::INET( LocalHost => $ip, LocalPort => $port, Proto => $proto ); if ( ! $result ) { print "Unable to create socket: $!\n...Terminating.\n\n"; exit; } } } else { open( F, $source ) or do { print "Unable to read $source...terminating.\n"; exit; }; $result = F; } return ( $result, $lmode ); } sub setdestination { my ( $destination ) = $_[0]; my ( $ip, $port, $proto, $filename ); my $result; if ( ! $destination ) { $result = STDOUT; } elsif ( $destination =~ /\:[0-9]+\// ) { ( $ip, $port, $proto ) = $destination =~ /^([^:]+):([0-9]+)\/(.+)$/; $result = new IO::Socket::INET( PeerAddr => $ip, PeerPort => $port, Proto => $proto ); if ( ! $result ) { print "Socket could not be created: $!\n...Terminating.\n\n"; exit; } } else { open( F, ">$destination" ) or do { print "Unable to write $destination...terminating\n"; exit; }; $result = F; } return $result; } sub usage { print qq{ Usage: $0 {options} -s [host:port/proto|filename] : Set source (STDIN) -d [host:port/proto|filename] : Set destination (STDOUT) }; exit; }