#!/usr/local/bin/perl

# edit this to the printer hostname
$them = 'printer';
# lpt1, 2 or 3
$printer = 'lpt1';
# change only for testing
$port = 'printer';
#$port = 1515;

$login = getlogin || (getpwuid($<))[0] || "?";

$file = "stdin";
&errexit("Stdin is not a file\n") unless (-f STDIN && ($dsize = -s STDIN));

require 'sys/socket.ph';

$sockaddr = 'S n a4 x8';
chop($hostname = `hostname`);
$num = sprintf("%03d", $$ % 1000);

($name, $aliases, $proto) = getprotobyname('tcp');
($name, $aliases, $port) = getservbyname($port, 'tcp')
	unless $port =~ /^\d+$/;
($name, $aliases, $type, $len, $thisaddr) = gethostbyname($hostname);
($name, $aliases, $type, $len, $thataddr) = gethostbyname($them);

socket(S, &PF_INET, &SOCK_STREAM, $proto) || &errexit("socket: $!\n");

$srcport = 0;
foreach $p (721..731)
{
	$this = pack($sockaddr, &AF_INET, $p, $thisaddr);
	last if bind(S, $this) && ($srcport = $p);
}
# otherwise use any old port
if ($srcport == 0)
{
	$this = pack($sockaddr, &AF_INET, 0, $thisaddr);
	bind(S, $this) || &errexit("bind: $!\n");
}

$that = pack($sockaddr, &AF_INET, $port, $thataddr);
connect(S, $that) || &errexit("connect: $!\n");

select(S); $| = 1; select(stdout);

print(S "\002$printer\n");
&errexit("Broken data connection\n") unless defined($r = read(S, $ans, 1));
&errexit("$printer: not available\n") if $ans ne "\0";

$cfile = "cfA$num$hostname";
$dfile = "dfA$num$hostname";
&controlfile();
&datafile();

exit 0;

sub controlfile
{
	$ctlstring = "H$hostname\nP$login\nJ$file\nC$hostname\nL$login\nN$file\nl$dfile\n";
	$csize = length($ctlstring);
	$ctlstring .= "\0";

	print(S "\002$csize $cfile\n");
	&errexit("Broken data connection\n") unless defined($r = read(S, $ans, 1));
	&errexit("Control file error\n") if $ans ne "\0";

	print(S $ctlstring);
	&errexit("Broken data connection\n") unless defined($r = read(S, $ans, 1));
	&errexit("Control data rejected\n") if $ans ne "\0";
}

sub datafile
{
	print(S "\003$dsize $dfile\n");
	&errexit("Broken data connection\n") unless defined($r = read(S, $ans, 1));
	&errexit("Printer error\n") if $ans ne "\0";

	# we append the ending '\0' on the last buffer to increase the
	# chance that it will be sent off in the same packet, reducing
	# the number of packets flowing
	while ($dsize > 0)
	{
		$nread = read(STDIN, $buffer, 1024);
		if (($dsize -= $nread) <= 0)
		{
			$buffer .= "\0";
			++$nread;
		}
		&errexit("write: $!\n") unless syswrite(S, $buffer, $nread);
	}
	&errexit("Broken data connection\n") unless defined($r = read(S, $ans, 1));
	&errexit("Data rejected\n") if $ans ne "\0";
}

sub errexit
{
	print STDERR @_;
	exit 2;
}
