-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcupspracc.html
375 lines (316 loc) · 15.1 KB
/
cupspracc.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
<html>
<head>
<title>The pracc CUPS backend</title>
<style type="text/css">
body { margin:2pc }
h1,h2,h3 { font-family:sans-serif }
pre { background-color:#ccc; border:1px solid #444; padding:4px }
td { background-color:#ccc }
th { background-color:#888; text-align:left }
</style>
</head>
<body>
<h1>Pracc for CUPS</h1>
<p>Pracc for CUPS is a backend for CUPS, the new Unix printing system,<br>
is part of the <a href="pracc-about.html">pracc system</a>, and has these
features:</p>
<ul>
<li>count the number of pages printed by each print job,</li>
<li>record who printed how much, and</li>
<li>control if printing shall be allowed or denied.</li>
</ul>
<p><b>Contents:</b><br>
<a href="#usage">Usage</a>,
<a href="#config">Configuration</a>,
<a href="#logic">Accounting Logic</a>,
<a href="#accts">Account Types</a>,
<a href="#misc">Miscellaneous</a>,
<a href="#author">Author</a>.</p>
<a name="usage"></a>
<h2>Usage</h2>
<p>CUPS uses "backends" to communicate with printers.
Backends are ordinary applications but must adhere to the interface
described in the backend(7) manual page that comes with CUPS.
Depending on how a CUPS backend is invoked, it must operate in
device discovery mode or in normal mode.</p>
<h4>Device Discovery</h4>
<p>If no command line arguments are specified, CUPS expects backends
to list supported devices to standard output. This is called <i>device
discovery</i>. The pracc backends writes one line of this form:</p>
<pre>network <i>pracc</i> "Unknown" "AppSocket/JetDirect w/Acct"</pre>
<p>This informs CUPS about the supported device class (network) and
the URI scheme (which is the backend's file name, "pracc" by
default).</p>
<p><b>Note:</b>
The filename of a backend must correspond with the URI scheme
used in device discovery, otherwise CUPS will not use the backend.
The pracc for CUPS backend uses its own file name when advertising
its services and can therefore be named arbitrarily.
It is recommended to name it <i>pracc</i>, yielding device URIs
of the form pracc://...</p>
<h4>Normal Operation</h4>
<p>For normal printing, the backend is invoked with 6 or 7
command line arguments:</p>
<pre><i>printer-uri</i><sub>0</sub> <i>job-id</i><sub>1</sub> <i>user</i><sub>2</sub> <i>title</i><sub>3</sub> <i>copies</i><sub>4</sub> <i>options</i><sub>5</sub></i> [<i>file</i><sub>6</sub>]</pre>
<p>The <i>printer-uri</i> is used for connecting to the printer.
The <i>user</i> is taken as the name of the account to charge,
unless the <i>job-billing</i> attribute is set to a valid account
name (see <a href="#accts">Account Types</a> below).
The <i>title</i> is copied to the accounting record to help the
user identify jobs.</p>
<p>Note that <i>printer-uri</i> is the zeroth argument, that is,
the program name. With current CUPS versions, the printer-uri
can also be communicated to the backend using the <tt>DEVICE_URI</tt>
environment variable. The pracc backend uses the environment
variable, if defined, otherwise its zeroth argument.</p>
<p>The pracc backend performs these steps in order:</p>
<ol>
<li>If accounting: check if access to the claimed account
can be granted; if there is no account, use the default
account.</li>
<li>If accounting: check if the account has enough credit
and quit if there are insufficient funds.</li>
<li>Connect to the printer device.</li>
<li>Send the print job, either from standard input (if there
are 6 arguments) or from the named <i>file</i> (if there are
7 arguments). If accounting is enabled, the print job will
be preceded and succeeded by special codes to elicit the
printer's page count. While and after sending the job, read
and parse potential answers from the printer until there is
reason to assume the job has finished printing.</li>
<li>Close connection to printer device.</li>
<li>If accounting: append a record to the selected account.</li>
<li>Optionally, append a record to the pagecount log.</li>
</ol>
<p>The pracc backend appends a <i>debit record</i> to the account
if the number of pages printed could be determined, otherwise,
an <i>error record</i> is appended.</p>
<h4>Job Scanning (aka pre-counting)</h4>
<p>Optionally, the pracc backend can send the printjob through
a program that tries to figure out how many pages the printjob
would produce when printed. A typical program for that job would
be Pykota's pkpgcounter. The job scanning program must read a print
job from its standard input and write the number of pages to its
standard output. Error messages may be sent to standard error,
which is inherited from the backend, so they should end up
in the CUPS error log. The job scanning program must return
a status of 0 if (and only if) it was successful.</p>
<h4>Queue Stopping</h4>
<p>Backends can stop the queue by using a special exit value.
The pracc backend does this in the following cases to alert
the administrator of a serious problem:</p>
<ul>
<li>No DEVICE_URI specified (is CUPS broken?)</li>
<li>Printer name cannot be resolved.</li>
<li>Pracc API function praccAppend failed (check permissions).</li>
<li>Function fdnonblock() on <i>jobfd</i> or <i>devfd</i> failed
(check the source).</li>
</ul>
<p>In all other error situations, the pracc backend returns
the value CUPS_BACKEND_FAILED, which causes the CUPS scheduler
to react according to the printer's error policy.</p>
<h4>Pagecount Logging</h4>
<p>If the file <tt>PRACCPCLOG</tt> (as defined in <i>pracc.h</i>
at compile-time) exists, then a pagecount record will be appended
after printing the job. The pagecount record is a line of the form</p>
<pre>@<i>timestamp</i> <i>pagecount</i> <i>printername</i></pre>
<p>where <i>timestamp</i> is in TAI64 format and <i>pagecount</i>
is the value of the printer's pagecount register or <b>-1</b> if
unknown. The information accumulated in the pagecount logfile
is useful for statistical purposes.</p>
<h4>Debug Logging</h4>
<p>It seems the CUPS scheduler does not route all messages from
backends to its <i>error_log</i> file; in particular, INFO lines
are dropped. More recent versions of CUPS may behave differently.</p>
<p>The pracc backend writes to its own private log file,
<i>/var/log/cups/pracc</i>, provided that it exists and is writable
to the pracc backend. At present, the path of the debugging log
file is hard-coded. The file is silently truncated to zero bytes
if its size exceeds 1000000 bytes.</p>
<h4>Permissions</h4>
<p>In order to get access to the pracc files, the backend must
be run as root or with an appropriate group. According to the
backend(7) man page, the CUPS scheduler executes backends as root
if they are not world-writable, and as an unprivileged user
(typically <i>lp</i>) otherwise.</p>
<p>Tests showed that the non-world-executable-means-root thing
did not work. A look at the source of CUPS 1.2.9 showed that
group <em>and</em> other must <em>no</em> permissions at all
on the backend file for CUPS to execute it as root.</p>
<p>By default, the pracc for CUPS backend is installed as
root:<tt>PRACCGROUP</tt> with mode 700, where <tt>PRACCGROUP</tt>
is a compile-time configuration setting.</p>
<a name="config"></a>
<h2>Configuration</h2>
<p>The pracc backend is configured through parameters in the
device URI. By default, that is, without any parameters,
the pracc backend behaves like the <i>socket</i> backend
that comes with CUPS.</p>
<table border="0" cellpadding="3" cellspacing="2"><tbody>
<tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr>
<tr><td>acct</td>
<td><tt>off</tt> | <tt>PS</tt> | <tt>PJL</tt> | <tt>job</tt></td>
<td><b>off</b></td>
<td>Accounting method</td></tr>
<tr><td>wait0</td>
<td>positive integer</td>
<td><b>20</b> (PS) or <b>300</b> (PJL)</td>
<td>Initial timeout (see text)</td></tr>
<tr><td>wait1</td>
<td>positive integer</td>
<td><b>10</b> (PS) or <b>120</b> (PJL)</td>
<td>Subsequent timeout (see text)</td></tr>
<tr><td>jobscan</td>
<td>program</td>
<td><i>none</i></td>
<td>Precounting program</td></tr>
<tr><td>pagecost</td>
<td>integer</td>
<td><b>0</b></td>
<td>Cost per page, 0 = free printing</td></tr>
</tbody></table>
<p>The <i>acct</i> parameter specifies the method to be used for
counting the number of pages effectively printed: <b>off</b> means
no counting (the default), <b>PS</b> uses PostScript commands,
<b>PJL</b> uses PJL commands, <b>SNMP</b> uses SNMP datagrams
to get the pagecount, and <b>job</b> just uses the page number
from the job scanner. Note: SNMP is not yet implemented.</p>
<p>The parameters <i>wait0</i> and <i>wait1</i> specify timeouts
and/or delays in seconds, depending on the accounting method.
With <i>acct</i>=<b>PS</b>, <i>wait0</i> is the time to pause
after sending the job but before reading the pagecount for the
first time, and <i>wait1</i> is the time to pause between subsequent
pagecount readings.
With <i>acct</i>=<b>PJL</b>, <i>wait0</i> is used as the first
select(2) timeout and <i>wait1</i> is used as the timeout for
subsequent select(2) calls (the select calls wait till the
printer sends some information back but no longer than the
specified timeout). Depending on the printer and the job,
some tuning may be necessary.</p>
<p>The <i>jobscan</i> parameter names a program that counts
pages in the print job. The result of this job scanning will
be used to determine if the user has enough printing credits
for printing the job. If the printer does not return any
information on the number of pages printed, then this is
also so only information for accounting. Note that some
people use the term <i>precounting</i> for this job scanning.</p>
<p>The number of pages printed is multiplied with the value
of the <i>pagecost</i> parameter and the resulting figure is
used for accounting. The default value of <b>0</b> implies
free printing.</p>
<p><b>Disclaimer:</b> page counting is a delicate matter!
Be sure to read <a href="counting.html">counting.html</a>,
which contains background information on page counting,
including a description of the PS and PJL methods.</p>
<a name="logic"></a>
<h2>Accounting Logic</h2>
<p>These variables are involved in accounting:</p>
<table border="0" cellpadding="3" cellspacing="2"><tbody>
<tr><th>Var</th><th>Source</th><th>Description</th><th>Default</th></tr>
<tr><td align="center"><i>c</i></td>
<td>device URI</td>
<td>cost per page</td>
<td><b>0</b> = free printing</td></tr>
<tr><td align="center"><i>m</i></td>
<td>jobscan</td>
<td>#pages in print job</td>
<td><b>-1</b> = unknown</td></tr>
<tr><td align="center"><i>n</i></td>
<td>printer</td>
<td>#pages actually printed</td>
<td><b>-1</b> = unknown</td></tr>
<tr><td align="center"><i>b</i></td>
<td>account</td>
<td>account's balance</td>
<td><i>always known</i></td></tr>
<tr><td align="center"><i>l</i></td>
<td>account</td>
<td>account's limit (keep <i>b</i>><i>l</i>)</td>
<td><i>always known</i></td></tr>
</tbody></table>
<p>The accounting procedure is as follows:</p>
<p><b>Init:</b>
Read the account file and set <i>d</i> and <i>l</i> accordingly.</p>
<p><b>Check:</b>
if (<i>m</i>>0) subtract <i>m</i>×<i>c</i> from <i>b</i>.<br>
If (<i>b</i><<i>l</i>) report "insufficient funds" and quit.</p>
<p><b>Send:</b>
If the <i>jobscan</i> parameter specifies a job scanning program,
feed the print job through this program and read the value <i>m</i>.
Send the print job to the printer.</li>
<p><b>Sync:</b>
Wait for the "true-end-of-job" and try determining <i>n</i>.</p>
<p><b>Accounting:</b>
Set <i>d</i>=<i>c</i>×f(<i>m</i>,<i>n</i>), the amount to debit;<br>
set <i>type</i>=(<i>d</i>≥0) ? debit : error, the record type;<br>
append an accounting record with type=<i>type</i> and amount=<i>d</i>.</p>
<p>Both <i>m</i> and <i>n</i> are determined by heuristics
and may be wrong or unknown. Pracc estimates the pages actually printed
based on <i>m</i> and <i>n</i>:</p>
<pre>
<b>if</b> (<i>m</i> < 0 && <i>n</i> < 0) <b>return</b> -1; // unknown
<b>if</b> (<i>m</i> < 0) <b>return</b> <i>n</i>;
<b>if</b> (<i>n</i> < 0) <b>return</b> <i>m</i>;
<b>if</b> (<i>m</i> < <i>n</i>) <b>return</b> <i>n</i>;
<b>return</b> (<i>m</i>+<i>n</i>)/2;
</pre>
<a name="accts"></a>
<h2>Account Types</h2>
<p>Pracc supports personal accounts and group accounts.</p>
<p><b>Personal accounts</b> are named after Unix user names.<br>
They are accessible only to the user whose name equals the account's name.</p>
<p><b>Group accounts</b> are named after Unix groups.<br>
They are accessible only to users in the named Unix group.</p>
<p>If the <i>job-billing</i> attribute is set and names a valid group
account, the named group accont will be billed. Otherwise, the user's
personal account will be billed.</p>
<p>Personal and group accounts share the same account name space!
It is the administrator's responsibility to avoid name clashes
between personal and group accounts! Failure to do so makes this
scenario possible: If there are users <i>x</i> and <i>y</i>, and
also a group <i>x</i> of which <i>y</i> is a member, then if user
<i>y</i> asks to charge a print job to group account <i>x</i>,
it will be charged to the personal account of <i>x</i>.</p>
<p>The <b>default account</b> is used whenever a user tries
to bill an account that does not exist; in particular, it is
used for all users that do not have an account.</p>
<a name="misc"></a>
<h2>Miscellaneous</h2>
<h4>Why doesn't the backend create missing pracc files?</h4>
<p>Because the backend does not have easy access to the required
information, namely, the initial balance and the initial limit
of the account to be created.</p>
<h4>What is the default account useful for?</h4>
<p>Use it to determine if printing shall be allowed or denied
by default.</p>
<h4>What are the rules to access pracc files?</h4>
<p>Tools that run with real or effective uid <i>PRACCOWNER</i> or
real or effective gid <i>PRACCGROUP</i> must enforce these rules:<p>
<ol>
<li>each user can access only his/her own personal account</li>
<li>each user can access group account x only if he/she belongs to group x</li>
<li>users must not be able to tamper with their pracc files</li>
</ol>
<p>The pracc backend implements these rules in the checkaccess()
function that invokes the praccGrant() function in the pracc API.
It relies on the CUPS scheduler to properly authenticate the
<i>user</i> parameter that is passed to backends as <i>argv</i>[2].</p>
<h4>What are the backend's exit codes?</h4>
<p>The CUPS scheduler interprets backend exit codes as follows:</p>
<table>
<tr><td>0</td><td>CUPS_BACKEND_OK</td><td>print job successfully transmitted</td></tr>
<tr><td>1</td><td>CUPS_BACKEND_FAILED</td><td>scheduler reacts according to error-policy</td></tr>
<tr><td>2</td><td>CUPS_BACKEND_AUTH_REQUIRED</td><td>no or invalid authentication</td></tr>
<tr><td>3</td><td>CUPS_BACKEND_HOLD</td><td>scheduler will hold the job</td></tr>
<tr><td>4</td><td>CUPS_BACKEND_STOP</td><td>scheduler will stop the queue</td></tr>
<tr><td>5</td><td>CUPS_BACKENd_CANCEL</td><td>scheduler will cancel the job</td></tr>
</table>
<p>The pracc backend makes use of most of these codes.</p>
<a name="author"></a>
<h2>Author</h2>
<p>Pracc was written by Urs-Jakob Rüetschi
while working at PZM and PHZ Luzern.</p>
<p>Pracc is free software under the terms of the GNU General
Public License.</p>
</body>
</html>