#!/usr/contrib/bin/perl5

use English;
use Socket;
use Sys::Hostname;
require "getopts.pl";

$opt_P = "";
&Getopts('P:');

if( !(@files = @ARGV) ){
	$f = "/tmp/lpr$$";
	@files = $f;
	open( TEMP, $f ) or die "cannot open $f - $!\n";
	while( <> ){
		print TEMP $f;
	}
	close TEMP or die "cannot close $f - $!\n";
}

print "files " . join(",",@files) . "\n";

$printer = $opt_P;
$printer = $ENV{PRINTER} unless $printer;
$printer = 'pr@localhost' unless $printer;
$remote = "";

if( $printer =~ /@/ ){
	($printer,$remote) = $printer =~ m/(.*)@(.*)/;
}
$remote="localhost" unless $remote;
if( $remote =~ /%/ ){
	($remote,$port) = $remote =~ m/(.*)%(.*)/;
}
$port = 515 unless $port;
print "remote='$remote', port='$port', pr='$printer'\n";

$hostname = hostname();
$username = getpwuid($UID);

$cf = "H$hostname\n"
 . "P$printer\n"
 . "L$username\n" ;

$idn = $$ % 100;
$cfn = sprintf( "cfA%03d%s", $idn, $hostname );
print "cfn='$cfn'\n";
$fn = "A";
$filecount = 0;
for( $i = 0; $i < @files; ++$i ){
	$file = $files[$i];
	if( ! -f $file || ! -r _ || ! -s _ ){
		print "not a readable, nonzero length file - $file\n";
	} else {
		$df = sprintf( "df%s%03d%s", $fn, $idn, $hostname );
		$dfn[$i] = $df;
		$cf .= "N$file\n" . "f$df\n" . "U$df\n";
		++$filecount;
	}
}

if( $filecount == 0 ){
	print "nothing to print\n";
	exit( 1 );
}

print "cf contents = '$cf'\n";
print "cf len " . length( $cf ) . "\n";


$SOCK = getconnection( $remote, $port );
sendit( $SOCK, sprintf( "\002%s\n", $printer ));;

$sendcf = "\002" . length( $cf ) . " $cfn\n"; 
sendbuffer( $SOCK, $sendcf, $cf );

print "sending files '@files'\n";
for( $i = 0; $i < @files; ++$i ){
	if( $dfn[$i] ){
		sendfile( $SOCK, $dfn[$i], $files[$i] );
	}
}

close ($SOCK) or die "close: $!"; 
exit;

sub getconnection {
	my ($remote,$port) = @_;
	my ($iaddr,$paddr,$proto);
	$iaddr = inet_aton($remote) or die "no host: $remote";
	$paddr = sockaddr_in($port,$iaddr);
	$proto = getprotobyname('tcp');
	print "$remote is $remote and port is $port and iaddr is $iaddr and paddr is $paddr\n";
	socket(SOCK,PF_INET,SOCK_STREAM,$proto) or die "socket: $!";
	connect(SOCK,$paddr) or die "connect: $!";
	print "connection made\n";
	# unbufferred IO
	select(SOCK); $| = 1; select(STDOUT);
	SOCK;
}

sub sendit {
	my( $SOCK, $line ) = @_;
	my( $count );
	print $SOCK $line or die "print to socket failed - $!\n";
	$line = "";
	$count = read $SOCK, $line, 1;
	print "sendit read $count\n";
	if( !defined($count) ){
		die "read error on socket - $!\n";
	}
	if( !$count ){
		die "EOF on socket\n";
	}
	$count = unpack( "C", $line );
	if( $count ){
		print "error: ";
		while( $line = <> ){
			print $line;
		}
		print "\n";
		exit 1;
	}
	print "sendit no error\n";
}

sub sendbuffer {
	my($SOCK, $line, $buffer ) = @_;
	my( $count );
	print "sendbuffer line '$line'\n";
	sendit( $SOCK, $line );
	print "sendbuffer buffer '$buffer'\n";
	print $SOCK $buffer;
	print $SOCK "\000";
	$line = "";
	$count = read $SOCK, $line, 1;
	print "sendbuffer read $count\n";
	if( !defined($count) ){
		die "read error on socket - $!\n";
	}
	if( !$count ){
		die "EOF on socket\n";
	}
	$count = unpack( "C", $line );
	if( $count ){
		print "error code: $count\n";
		while( <> ){
			print $_;
		}
		print "\n";
		exit 1;
	}
	print "sendbuffer no error\n";
}

sub sendfile {
	my( $SOCK, $name, $filename ) = @_;
	my( $size, $line );
	open( FILE, "<$filename") or die "cannot open file '$filename'\n";
	$size = -s FILE;
	print "sendfile: '$name' size $size\n";
	sendit( $SOCK, "\003$size $name\n" );
	print "sendfile: sending file\n";
	while( $size = read FILE, $line, 1024 ){
		print "read $size bytes\n";
		print $SOCK $line;
	}
	print "sendfile: finished\n";
	if( !defined( $size ) ){
		die "bad read from '$name' - $!\n";
	}
	print $SOCK "\000";
	$line = "";
	$count = read $SOCK, $line, 1;
	print "sendfile read $count\n";
	if( !defined($count) ){
		die "read error on socket - $!\n";
	}
	if( !$count ){
		die "EOF on socket\n";
	}
	$count = unpack( "C", $line );
	if( $count ){
		print "error code: $count\n";
		while( <> ){
			print $_;
		}
		print "\n";
		exit 1;
	}
	print "sendfile no error\n";
}
