#!/bin/perl
#Telnet client.

use Socket;
use FileHandle;   #for autoflush
use POSIX;        #for WIFEXITED and WEXITSTATUS

if (@ARGV == 1) {   #This @ARGV is in a scalar context
	$port = getservbyname('telnet', 'tcp') #look up telnet in /etc/services
		or die "$0: couldn't find port number for telnet";
} elsif (@ARGV == 2) {
	$port = $ARGV[1];
} else {
	die "$0: requires 1 or 2 command line arguments";
}

socket(S, AF_INET, SOCK_STREAM, 0) or die "$0: $!";
S->autoflush();      #pp. 130, 444 in O'Reilly Perl book

$ip = inet_aton($ARGV[0])          or die "$0: inet_aton failed";
$address = sockaddr_in($port, $ip) or die "$0: sockaddr_in failed";

$dotted = inet_ntoa($ip);
print "Trying $dotted...\n";
connect(S, $address)               or die "$0: $!";
$name = gethostbyaddr($ip, AF_INET) or $name = $dotted;
print "Connected to $name.\n";

$SIG{CHLD} = 'death_of_child';   #Must be before the fork.
$pid = fork();
defined $pid or die "$0: $!";

if ($pid == 0) {
	#Arrive here if I am the child.
	#Copy from the server to the stdout.

	while (<S>) {            #Read one line from the socket
		print STDOUT $_;     #and write it to the stdout.
	}

	exit 0;
}

#Arrive here if I am the parent.
#Copy from the stdin to the server.
while (<STDIN>) {                #Read one line from the stdin
	print S $_;                  #and write it to the server.
}

shutdown(S, SHUT_RDWR) or die "$0: $!";
print "Connection closed.\n";
exit 0;

sub death_of_child {
	$pid = wait();
	if (!WIFEXITED($?) || WEXITSTATUS($?) != 0) {
		print STDERR "Child did not return exit status 0.\n";
	}

	shutdown(S, SHUT_RDWR) or die "$0: $!";
	print "Connection closed by foreign host.\n";
	exit 0;
}
