#!/usr/bin/perl -w
# test_server

use strict;
use IO::Socket;

my ($MSG_EOL, $kidpid, $listen_handle, $handle, $line);

if (($ARGV[0]||'') eq '-crlf') {
    shift;
    $MSG_EOL = "\015\012";
} else {
    $MSG_EOL = "\012";
}

if (@ARGV == 1 && $ARGV[0] =~ /^\d{1,5}$/) {
    my $port = shift;
    # serve tcp on the specified host and port
    $listen_handle = IO::Socket::INET->new(Proto     => "tcp",
				    LocalPort => $port,
				    Listen    => 1,
				    Reuse     => 1)
	or die "can't serve on TCP port $port: $!";
    print STDERR "[Serving on TCP port $port]\n";
} elsif (@ARGV == 1) {
    my $socket = shift;
    # serve unix domain on the specified named socket
    unlink $socket;
    $listen_handle = IO::Socket::UNIX->new( Local     => $socket,
					     Listen    => 1 )
	or die "cannot serve on UNIX socket $socket: $!";
    chmod 0777, $socket;
    print STDERR "[Serving on UNIX socket $socket]\n";
} else {
    print "usage: $0 [-crlf] (UNIX-socket-name|TCP-port)\n";
    exit 1;
}

SERVER: {
    print STDERR "[waiting for connection]\n";

$handle = $listen_handle->accept()
    or die "accept failed";

print "[connected]\n";

$handle->autoflush(1);              # so output gets there right away

# split the program into two processes, identical twins
die "can't fork: $!" unless defined($kidpid = fork());

# the if{} block runs only in the parent process
if ($kidpid) {
    # copy standard input to the socket
    while (defined ($line = <STDIN>)) {
	chomp $line;
	print $handle "$line$MSG_EOL";
    }
    kill("TERM", $kidpid);                  # send SIGTERM to child
    close $handle;
    redo SERVER;
}
# the else{} block runs only in the child process
else {
    # copy the socket to standard output
    while (defined ($line = <$handle>)) {
	print $line;
    }
}

}
