Simple accounting filter/backend (With Perl or another script language)
Nayco
anonymous at easysw.com
Tue Jun 15 08:59:39 PDT 2004
If someone wishes to help, here is my current full script... Thanks for suggestions !
Oh, I forgot: This is GPLed ;-) (Hell, I stolen this code from other backends, just translated it to Perl !)
#!/usr/bin/perl -w
use strict;
#use Data::Dumper;
use POSIX qw(strftime);
use File::Basename;
# Variables
my $logfile="/tmp/quota_backend.log";
my $backends_dir = dirname($0);
my $me = basename($0);
my $lockfile = $backends_dir."/".$me.".lock";
# We'll use a logfile for developpement, may no need it after...
open (LOG,">>".$logfile) or die "$me: Unable to create logfile $logfile, exiting !";
# Cups backends work this way that when called without argument, they must output
# which devices they manage. As we don't manage anything but just call other backends
# to process the printing, we've got to call them one by one, modifying parts of the
# output. This way, Cups believes that we manage all printers (I stolen this idea
# from Pykota, free software rocks!) ;-)
# NOTE: Cups only calls backends without arguments during its initialisation
# procedure (Or when reloaded), to see what printers are managed. This should never occur
# during normal operation.
if (@ARGV == 0){
# Search for a lockfile, and exit if it exists.
# This is mainly to avoid calling ourselves when scanning the backend directory
# if the corresponding test (see below) fails. Mind you, a P4 XEON 2GHz managed to stay
# up during 20 second when this script started calling itself in an infinite loop !
# The Kernel, however, is so altruistic that it kept killing processes to free up
# memory so this script could bring down the system... ;-)
# Remember that we don't need any lockfile when called to process a print job (ie
# with 6 or 7 arguments, see below), and using it would prevent multiple print jobs at a time,
# somewhat strange for a print server....
if (-e $backends_dir."/".$me.".lock"){
print STDERR "Another instance is already running... Bye !\n";
exit 1;
}
# So, if we managed to get here, it's time to create this lockfile...
open (LOCKFILE, ">".$lockfile) or die "$me: Unable to create lockfile in $backends_dir, exiting !";
# Feed the logfile...
print LOG "---> Started at ".strftime ("%a %b %e %H:%M:%S %Y", localtime)."\n";
print LOG " Command line: $0\n";
print LOG " Arguments: ".join("|", @ARGV)."\n\n";
print LOG " I was called with 0 arguments, let's fool Cups !\n";
# Get the list of all backends from the Cups backends directory:
my @backends_list = glob($backends_dir.'/*');
# We gonna echo this list in the logfile, so:
print LOG " Backends list:\n";
# Let's call each backend, filter output, and echo all on STDIN:
foreach my $backend (@backends_list){
# Avoid calling ourselves, we are not in need of a brutal reset, are we ?
next if ($backend =~ /$0/); # /!\ TODO: Doublecheck this line so that it ALWAYS work !
# Echo the name of the backend to the logfile...
print LOG " - $backend\n";
# ...And execute the backend, feeding a list with its output.
my @sortie = `$backend`;
# This is the pattern that'll check the output of the backends,
# and extract the four fields:
my $motif = "^(\\S+)\\s(\\S+)\\s\"([^\"]+)\"\\s\"([^\"]+)\"\$";
# A given backend may managed many devices, thus outputing many lines:
# we process each line.
foreach my $ligne (@sortie){
# Check the line against the pattern, and extract the fields
# in the special variables $1, $2, $3 and $4
if ($ligne =~ $motif){
# Then we output what Cups expects, lightly modified so we appear
# in the device list when configuring a new printer: For example,
# a "socket" printer will appear as "quota:socket://hostname:port"
print "$1 $me:$2 \"$3\" \"$4 (Quota Managed)\"\n";
# Don't forget the logfile: He's so hungry !
print LOG " $1 $me:$2 \"$3\" \"$4 (Quota Managed)\"\n";
}
# If the backend spited a line that doesn't fit our needs, ignore it,
# but mention it in the logs.
else {
print STDERR "Cette ligne est invalide: \"$ligne\"";
print LOG "Cette ligne est invalide: \"$ligne\"";
}
}
}
# Remove the lock file...
close LOCKFILE;
unlink $lockfile;
}
# OK, back to the main part of the script; We saw what needed to be done when
# called without argument. Now, when Cups has finished its init, it only calls
# us with 6 or 7 arguments. If there are 7, we gotta read the file to print
# ourselves from the given path. If only 6 are given, the file is sent by STDIN.
else {
print LOG "---> Print job started at ".strftime ("%a %b %e %H:%M:%S %Y", localtime)."\n";
print LOG " Command line: $0\n";
print LOG " Arguments: ".join("|", @ARGV)."\n\n";
print LOG " \$ENV{DEVICE_URI}= ".$ENV{DEVICE_URI}."\n\n";
print LOG " Content:\n";
# If we were called with the wrong number of arguments, exit.
if ( (@ARGV < 6) || (@ARGV > 7) ){
print LOG " Wrong parameter count.\n";
print LOG "---> Ended at: ".strftime ("%a %b %e %H:%M:%S %Y", localtime)."\n\n\n";
close LOG;
die "$me: Too few or too many parameters, exiting!";
}
### From this point, this is testing only code..... OK, so is the above ;-)
# If we were called with 6 arguments, read from STDIN to a tempfile:
#if (@ARGV == 6){
my $tmpfile= `mktemp </dev/null /tmp/print.XXXXXX`;
`cat > $tmpfile`;
#}
my $cmd='cat $tmpfile|/usr/lib/cups/backend/socket '.join(" ", @ARGV);
$ENV{DEVICE_URI} =~ s/^comptage:(.*)/$1/;
print LOG "Commande éxecutée: $cmd\n\n;";
`$cmd`;
`cat $tmpfile >> /tmp/comptage/mac_print.log`;
unlink $tmpfile;
}
print LOG "---> Ended at: ".strftime ("%a %b %e %H:%M:%S %Y", localtime)."\n\n\n";
close LOG;
exit 0;
More information about the cups-devel
mailing list