Simple accounting filter/backend (With Perl or another script language)

alex at j2anywhere.com alex at j2anywhere.com
Fri Oct 22 12:43:54 PDT 2004


I'll take it this is the filter. Could you please explain exactly how to install a filter so that it works for all printers on the system without interfering too much with the configuration files.

Thanks
Alex

Nayco wrote:
> 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