[an error occurred while processing this directive] FreeBSD Handbook : Printing : Advanced Printer Setup : Accounting for Printer Usage
Previous: Restricting Printer Usage
Next: Alternatives to the Standard Spooler

7.6.5. Accounting for Printer Usage

So, you need to charge for printouts. And why not? Paper and ink cost money. And then there are maintenance costs---printers are loaded with moving parts and tend to break down. You've examined your printers, usage patterns, and maintenance fees and have come up with a per-page (or per-foot, per-meter, or per-whatever) cost. Now, how do you actually start accounting for printouts?

Well, the bad news is the LPD spooling system doesn't provide much help in this department. Accounting is highly dependent on the kind of printer in use, the formats being printed, and your requirements in charging for printer usage.

To implement accounting, you have to modify a printer's text filter (to charge for plain text jobs) and the conversion filters (to charge for other file formats), to count pages or query the printer for pages printed. You can't get away with using the simple output filter, since it cannot do accounting. See section Filters .

Generally, there are two ways to do accounting:

The LPD spooling system supports both methods easily: since you have to provide the filters (well, most of the time), you also have to provide the accounting code. But there is a bright side: you have enormous flexibility in your accounting methods. For example, you choose whether to use periodic or timely accounting. You choose what information to log: user names, host names, job types, pages printed, square footage of paper used, how long the job took to print, and so forth. And you do so by modifying the filters to save this information.

7.6.5.1. Quick and Dirty Printer Accounting

FreeBSD comes with two programs that can get you set up with simple periodic accounting right away. They are the text filter lpf, described in section lpf: a Text Filter , and pac, a program to gather and total entries from printer accounting files.

As mentioned in the section on filters ( Filters ), LPD starts the text and the conversion filters with the name of the accounting file to use on the filter command line. The filters can use this argument to know where to write an accounting file entry. The name of this file comes from the af capability in /etc/printcap, and if not specified as an absolute path, is relative to the spooling directory.

LPD starts lpf with page width and length arguments (from the pw and pl capabilities). lpf uses these arguments to determine how much paper will be used. After sending the file to the printer, it then writes an accounting entry in the accounting file. The entries look like this:

   2.00 rose:andy
   3.00 rose:kelly
   3.00 orchid:mary
   5.00 orchid:mary
   2.00 orchid:zhang
You should use a separate accounting file for each printer, as lpf has no file locking logic built into it, and two lpfs might corrupt each other's entries if they were to write to the same file at the same time. A easy way to insure a separate accounting file for each printer is to use af=acct in /etc/printcap. Then, each accounting file will be in the spooling directory for a printer, in a file named acct.

When you're ready to charge users for printouts, run the pac program. Just change to the spooling directory for the printer you want to collect on and type pac. You'll get a dollar-centric summary like the following:


  Login               pages/feet   runs    price
orchid:kelly                5.00    1   $  0.10
orchid:mary                31.00    3   $  0.62
orchid:zhang                9.00    1   $  0.18
rose:andy                   2.00    1   $  0.04
rose:kelly                177.00  104   $  3.54
rose:mary                  87.00   32   $  1.74
rose:root                  26.00   12   $  0.52

total                     337.00  154   $  6.74

These are the arguments pac expects:

-Pprinter

Which printer to summarize. This option works only if there's an absolute path in the af capability in /etc/printcap.

-c

Sort the output by cost instead of alphabetically by user name.

-m

Ignore host name in the accounting files. With this option, user smith on host alpha is the same user smith on host gamma. Without, they're different users.

-pprice

Compute charges with price dollars per page or per foot instead of the price from the pc capabilty in /etc/printcap, or two cents (the default). You can specify price as a floating point number.

-r

Reverse the sort order.

-s

Make an accounting summary file and truncate the accounting file.

names...

Print accounting information for the given user names only.

In the default summary that pac produces, you see the number of pages printed by each user from various hosts. If, at your site, host doesn't matter (because users can use any host), run pac -m, to produce the following summary:


  Login               pages/feet   runs    price
andy                        2.00    1   $  0.04
kelly                     182.00  105   $  3.64
mary                      118.00   35   $  2.36
root                       26.00   12   $  0.52
zhang                       9.00    1   $  0.18

total                     337.00  154   $  6.74

To compute the dollar amount due, pac uses the pc capability in the /etc/printcap file (default of 200, or 2 cents per page). Specify, in hundreths of cents, the price per page or per foot you want to charge for printouts in this capability. You can override this value when you run pac with the -p option. The units for the -p option are in dollars, though, not hundreths of cents. For example,
pac -p1.50
makes each page cost one dollar and fifty cents. You can really rake in the profits by using this option.

Finally, running pac -s will save the summary information in a summary accounting file, which is named the same as the printer's accounting file, but with _sum appended to the name. It then truncates the accounting file. When you run pac again, it rereads the summary file to get starting totals, then adds information from the regular accounting file.

7.6.5.2. How Can You Count Pages Printed?

In order to perform even remotely accurate accounting, you need to be able to determine how much paper a job uses. This is the essential problem of printer accounting.

For plain text jobs, the problem's not that hard to solve: you count how many lines are in a job and compare it to how many lines per page your printer supports. Don't forget to take into account backspaces in the file which overprint lines, or long logical lines that wrap onto one or more additional physical lines.

The text filter lpf (introduced in lpf: a Text Filter ) takes into account these things when it does accounting. If you're writing a text filter which needs to do accounting, you might want to examine lpf's source code.

How do you handle other file formats, though?

Well, for DVI-to-LaserJet or DVI-to-PostScript conversion, you can have your filter parse the diagnostic output of dvilj or dvips and look to see how many pages were converted. You might be able to do similar things with other file formats and conversion programs.

But these methods suffer from the fact that the printer may not actually print all those pages. For example, it could jam, run out of toner, or explode---and the user would still get charged.

So, what can you do?

There is only one sure way to do accurate accounting. Get a printer that can tell you how much paper it uses, and attach it via a serial line or a network connection. Nearly all PostScript printers support this notion. Other makes and models do as well (networked Imagen laser printers, for example). Modify the filters for these printers to get the page usage after they print each job and have them log accounting information based on that value only. There's no line counting nor error-prone file examination required.

Of course, you can always be generous and make all printouts free.


FreeBSD Handbook : Printing : Advanced Printer Setup : Accounting for Printer Usage
Previous: Restricting Printer Usage
Next: Alternatives to the Standard Spooler [an error occurred while processing this directive]