#!/usr/bin/perl -w

##############################################################################
#
# Print billing management system
#
# Version 4.0.6
#
# Copyright (C) 2000, 2001, 2002 Daniel Franklin
#
# This program is distributed under the terms of the GNU General Public
# License Version 2.
#
# This is a print accounting and billing filter.
#
# To use this, you need the following (or similar) lines in your printcap
# file:
#
#lp|default printer:\
#	 :lp=/dev/lp0
#	 :achk=true
#	 :as=|/usr/sbin/printbill --type [bill|lazybill|accountonly] [-printbill_secondary printer]
#        :if=/etc/magicfilter/psonly600-filter
#	 :sd=/var/spool/lpd/inkjet
#	 :mx#0
#	 :sh
#
# Refer to the man page to see the additional stuff required if you use
# --type bill
#
##############################################################################

use IO::Socket::UNIX;
use Getopt::Long;
use Sys::Syslog qw(:DEFAULT setlogsock);
use strict;

my $sversion;
my $cversion = "4.0.6";
my $JREMOVE = 3;
my $sockname = "/tmp/printbilld";
my $line = "";
my ($smajor, $sminor, $spointrel, $cmajor, $cminor, $cpointrel);
my ($sock, $msg);
my ($job, $remote_host, $secondary, $quoteprinter, $cf, $spooldir, $user, $printer, $type, $response);

setlogsock 'unix';
openlog $0, 'cons', 'lpr';

# Parse standard command-line options sent to us by lprng

if ($] >= 5.005) {
	Getopt::Long::Configure ("pass_through");
	Getopt::Long::Configure ("bundling");
} else {
	Getopt::Long::config ("pass_through");
	Getopt::Long::config ("bundling");
}

GetOptions ("type=s" => \$type, "j=n" => \$job, "H=s" => \$remote_host, "printbill_secondary=s" => \$secondary, "printbill_printer=s" => \$quoteprinter, "n=s" => \$user, "k=s" => \$cf, "P=s" => \$printer, "d=s" => \$spooldir);

&abortjob ("$0: must specify type via --type option (may be bill, lazybill, account or quote)")
	if (!defined $type || ($type ne "bill" && $type ne "lazybill" && $type ne "account" && $type ne "quote"));
	
&abortjob ("$0: must specify job number via -j option") unless (defined $job);

&abortjob ("$0: must specify remote host via -H option") unless (defined $remote_host);

&abortjob ("$0: must specify username via -n option") unless (defined $user);

&abortjob ("$0: must specify printer name via -P option") unless (defined $printer);

&abortjob ("$0: must specify control file via -k option") unless (defined $cf);

&abortjob ("$0: must specify spool directory via -d option") unless (defined $spooldir);

&abortjob ("$0: must specify secondary print queue name if using --type bill via --printbill_secondary option") if ($type eq "bill" && !defined $secondary);

&abortjob ("$0: must specify target printer name if using --type quote via --printbill_printer option") if ($type eq "quote" && !defined $quoteprinter);

$sock = IO::Socket::UNIX -> new (Peer => $sockname)
	or &abortjob ("$0: Unable to establish socket connection on $sockname: $!");

defined ($line = <$sock>)
	or &abortjob ("$0: Unable to read version string from socket connection on $sockname: $!");

chomp $line;

$sversion = (split (/\s?:\s?/, $line))[1];
($smajor, $sminor, $spointrel) = split (".", $sversion);
($cmajor, $cminor, $cpointrel) = split (".", $cversion);

if ($smajor ne $cmajor) {
	&abortjob ("$0: Incompatible version number (server is $sversion, client is $cversion)");
}

$msg = "type: $type;";
$msg .= "printer: $printer;";
$msg .= "user: $user;";
$msg .= "job: $job;";
$msg .= "control_file: $cf;";
$msg .= "spool_directory: $spooldir;";
$msg .= "remote_host: $remote_host;";

if ($type eq "bill") {
	$msg .= "secondary_queue: $secondary;";
}

if ($type eq "quote") {
	$msg .= "quote_printer: $quoteprinter;";
}

$msg .= "\n";

print $sock $msg
	or &abortjob ("$0: Unable to write to socket connection on $sockname: $!");

defined ($response = <$sock>)
	or &abortjob ("$0: Unable to read final response from socket connection on $sockname: $!");

close $sock;

exit $response;

sub abortjob {
	my ($text) = @_;
	print STDERR "$text\n";
	syslog 'err', $text;
	exit $JREMOVE;
}
