]> arthur.barton.de Git - netatalk.git/blob - contrib/printing/netatalk.template
Big configure.in cleanup
[netatalk.git] / contrib / printing / netatalk.template
1 #ident  "@(#)netatalk   0.7     99/06/22 job@uchicago.edu"  /* Netatalk 1.4*/
2
3 #####
4 # User configuration:
5 #
6 # Set timeout for pap($time) and papstatus($time2).  both are in seconds.
7 # extraneous if you do not have NETATALKHOME/bin/timeout
8 # set how many times to loop before we just abort entirely ($attempts)
9 # what flags pap is run w/. -c makes pap claim to have been waiting forever
10 #####
11
12 time=1800
13 time2=60
14 attempts=3
15 pap_flags="-c"
16
17 #####
18 # this should get "fixed" to something like
19 # NETATALKHOME=/opt ; export NETATALKHOME
20 # by the add_netatalk_printer script
21 #
22 # DO NOT use the user's env for this or the PATH above.
23 #####
24
25 NETATALKHOME=DEFAULT_NETATALK_HOME ; export NETATALKHOME
26 #NETATALKHOME=/opt ; export NETATALKHOME
27
28 if [ "${NETATALKHOME}" = "DEFAULT_NETATALK_HOME" ]; then
29    echo "bleah, NETATALKHOME not set, exiting..." ; exit 5
30 fi
31
32 #####
33 # BUGS/TODO:
34 # move all TMP stuff to use a directory for security reasons
35 # run nbplkup to check if the reason we cannot print, is that it's not on 
36 #       the net
37 # move to "${foo}" from $foo and ${foo}
38 # add debuging info that gets sent to "logger lpd.debug"
39 # if we timeout while printing the banner page, we do not keep trying to print.
40 # perhaps filter_timeout should only complain once per job; like badfile.
41 # check if the timeout messages are duplicated by the lp system
42 # psa will not drop in for pap to use accting.  perhaps lp does not need it?
43 # make pap print all the files at once; kill for file in ($files)
44 # move badfile error to printfile function
45 #####
46
47 # This File is released under the Perl Artistic Licence.  
48 # See http://www.perl.org for details
49 #
50 # Or you can use it under the licence that accompanies Netatalk 1.3 =)
51
52 ###########
53 ## Netatalk printer interface.  Heavily modified from 
54 ## /usr/lib/lp/model/standard on Sparc Solaris 2.5.1 (May 97)
55 ##
56 ## Meant to be used w/ add_netatalk_printer
57 ###########
58
59 #####
60 # This program is invoked as
61 #
62 # ${SPOOLDIR}/.../printer request-id user title copies options files...
63 #
64 # The first three arguments are simply reprinted on the banner page,
65 # the fourth (copies) is used to control the number of copies to print,
66 # the fifth (options) is a blank separated list (in a single argument)
67 # of user or Spooler supplied options (without the -o prefix),
68 # and the last argument(s) is/are the file(s) to print.
69 #####
70
71 #####
72 #
73 # The protocol between the interface program and the Spooler
74 # is fairly simple:
75 #
76 #       All standard error output is assumed to indicate a
77 #       fault WITH THE REQUEST. The output is mailed to the
78 #       user who submitted the print request and the print
79 #       request is finished.
80 #
81 #       If the interface program sets a zero exit code,
82 #       it is assumed that the file printed correctly.
83 #       If the interface program sets a non-zero exit code
84 #       less than 128, it is assumed that the file did not
85 #       print correctly, and the user will be notified.
86 #       In either case the print request is finished.
87 #
88 #       If the interface program sets an exit code greater
89 #       than 128, it is assumed that the file did not print
90 #       because of a printer fault. If an alert isn't already
91 #       active (see below) one will be activated. (Exit code
92 #       128 should not be used at all. The shell, which executes
93 #       this program, turns SIGTERM, used to kill this program
94 #       for a cancellation or disabling, into exit 128. The
95 #       Spooler thus interpretes 128 as SIGTERM.)
96 #
97 #       A message sent to the standard input of the ${LPTELL}
98 #       program is assumed to describe a fault WITH THE PRINTER.
99 #       The output is used in an alert (if alerts are defined).
100 #       If the fault recovery is "wait" or "begin", the printer
101 #       is disabled (killing the interface program if need be),
102 #       and the print request is left on the queue.
103 #       If the fault recovery is "continue", the interface program
104 #       is allowed to wait for the printer fault to be cleared so
105 #       it can resume printing.
106 #
107 #####
108
109 ###########################################################################
110 #
111 # Set up the basic traps. and other important things
112 #
113 ###########################################################################
114
115 #####
116 # For the time being, just exit if we are poked.
117 #####
118
119 # SIGTERM handler
120
121 trap 'exit' 15
122
123 #####
124 # We can be clever about getting a hangup or interrupt, though, at least
125 # until the filter runs. Do this early, even though $LPTELL
126 # isn't defined, so that we're covered.
127 #####
128
129 trap 'catch_hangup; exit_code=129 exit 129' 1
130 trap 'catch_interrupt; exit_code=129 exit 129' 2 3
131
132 #####
133 # VARIBLE DECLARED - put here so we don't ever run the trap below w/o
134 # TMPPREFIX defined.  We hard code /tmp for the moment, but fix that later
135 #
136 # Use ${TMPPREFIX} as the prefix for all temporary files, so
137 # that cleanup is easy. The prefix may be up to 13 characters
138 # long, so you only have space for one more character to make
139 # a file name. If necessary, make a directory using this prefix
140 # for better management of unique temporary file names.
141 #####
142
143 TMPPREFIX=/tmp/`uname -n`$$
144
145 #####
146 # Before exiting, set ${exit_code} to the value with which to exit.
147 # Otherwise, the exit from this script will be 0.
148 #####
149
150 trap 'rm -fr ${TMPPREFIX}*; exit ${exit_code}' 0
151
152 catch_hangup () {
153         if [ -n "${LPTELL}" ]
154         then
155                 echo \
156     "Humm, we got a SIGHUP.  Not sure what it means, but... we'll keep going anyway" \
157           | ${LPTELL} "${printer}"
158         fi
159         return 0
160 }
161
162 catch_interrupt () {
163         if [ -n "${LPTELL}" ]
164         then
165             echo \
166         "Received an interrupt from the printer.  The reason is unknown." \
167             | ${LPTELL} "${printer}"
168         fi
169         return 0
170 }
171
172 #####
173 # Most of the time we don't want the standard error to be captured
174 # by the Spooler, mainly to avoid "Terminated" messages that the
175 # shell puts out when we get a SIGTERM. We'll save the standard
176 # error channel under another number, so we can use it when it
177 # should be captured.
178 #
179 # Open another channel to the printer port, for use when the
180 # regular standard output won't be directed there, such as in
181 # command substitution (`cmd`).
182 #####
183
184 exec 5>&2 2>/dev/null 3>&1
185
186 ###########################################################################
187 #
188 # Define local varibles and such
189 #
190 ###########################################################################
191
192 #####
193 # There is one more varible set by the shell that execs us.
194 # FILTER        The filter to run ; we ignore this directive
195 #####
196
197 #####
198 # Use the user set env, or else default to standard values.
199 #####
200
201 : ${SPOOLDIR:=/usr/spool/lp}
202 : ${TMPDIR:=/tmp} ; export TMPDIR
203 : ${LOCALPATH:=${SPOOLDIR}/bin} ; export LOCALPATH
204
205 PATH="/bin:/usr/bin:${LOCALPATH}:${NETATALKHOME}/bin:${NETATALKHOME}/etc"
206 export PATH
207
208 TMPPREFIX=${TMPDIR}/`uname -n`$$
209
210 #####
211 # Error levels for the errmsg() func.
212 #####
213
214 LP_ERR_LABEL="UX:lp" ; export LP_ERR_LABEL
215
216 E_IP_ARGS=1
217 E_IP_OPTS=2
218 E_IP_UNKNOWN=5
219 E_IP_BADFILE=6
220
221 #####
222 # Error message formatter:
223 #
224 # Invoke as
225 #
226 #       errmsg severity message-number problem help
227 #
228 # where severity is "ERROR" or "WARNING", message-number is
229 # a unique identifier, problem is a short description of the
230 # problem, and help is a short suggestion for fixing the problem.
231 #####
232
233 errmsg () {
234         case $1 in
235         ERROR )
236                 sev="  ERROR";
237                 ;;
238         WARNING )
239                 sev="WARNING";
240                 ;;
241         esac
242         echo "${LP_ERR_LABEL}: ${sev}: $3
243         TO FIX: $4" >&5
244 }
245
246 parse () {
247         echo "`expr \"$1\" : \"^[^=]*=\(.*\)\"`"
248 }
249
250 #####
251 # die quickly if we do not have the right number of arguments.
252 #####
253
254 if [ $# -lt 5 ]
255 then
256         errmsg ERROR ${E_IP_ARGS} \
257                 "wrong number of arguments to interface program" \
258                 "consult your system administrator"
259         exit 1
260 fi
261
262 printer=`basename $0`
263 request_id=$1
264
265 # this will formated be machine!username, so we want to split that up...
266
267 user_name=$2
268 machine=`echo $user_name | cut -d! -f1`
269 user_name=`echo $user_name | cut -d! -f2`
270
271 title=$3
272 copies=$4
273 option_list=$5
274
275 shift 5
276 files="$*"
277
278 nobanner="yes"
279
280 inlist=
281
282 for i in ${option_list}
283 do
284 case "${inlist}${i}" in
285     nobanner )
286         nobanner="yes" ;;
287     banner )
288         nobanner="no" ;;
289 #####
290 #
291 # If you want to add simple options (e.g. -o simple)
292 # identify them here.
293 #####
294 #    simple )
295 #       simple="yes" ;;
296
297 #####
298 # These get ignored, but would matter little anyway since all we see 
299 # here is PS anyway.
300 #####
301         cpi=* )
302 #           cpi=`parse ${i}` ;;
303             true ;;
304         lpi=* )
305 #           lpi=`parse ${i}` ;;
306             true ;;
307         length=* )
308 #           length=`parse ${i}` ;;
309             true ;;
310         width=* )
311 #           width=`parse ${i}` ;;
312             true ;;
313
314         #####
315         # If you want to add simple-value options (e.g. -o value=a)
316         # identify them here.
317         #####
318         #value=* )
319         #    value=`parse ${i}` ;;
320
321         flist=* )
322             flist=`parse ${i}` ;;
323         input* )
324             true ;;
325         * )
326             errmsg WARNING ${E_IP_OPTS} \
327             "unrecognized \"-o ${i}\" option" \
328             "check the option, resubmit if necessary
329             printing continues" ;;
330
331         esac
332 done
333
334 #####
335 # A bit ugly, but grabs the appletalk printer name from the lp system printer
336 # description, so it's right up there in admintool.  the appletalk name must 
337 # be delimited by [ and ].
338 #
339 # eg - 'this is the printer [hp-mrsec-l114:lasershared@Research Insitutes] that i use.'
340 #####
341
342 PAPDEST="`lpstat -D -p "${printer}" | grep -i descrip | sed 's/.*Description:.*\[//g' | sed 's/\].*//g'`"
343
344 export PAPDEST
345
346 ###########################################################################
347 #
348 # Define our local functions  (parse is declared above option parsing)
349 #
350 ###########################################################################
351
352 banner () {
353     echo "#####    User: ${user_name}"
354     echo ""
355     echo "##### Machine: ${user_name}"
356     echo ""
357
358    if [ -n "${title}" ]
359    then
360     echo "#####   Title: ${title}"
361     echo ""
362    fi
363
364     echo "#####   Files: ${flist}"
365     echo ""
366
367 #####
368 # this should deal w/ the year 2000 ok.  But will die in 2038. =)
369 #####
370
371     YEAR=`date '+%y'`
372     YEAR=`expr 1900 + ${YEAR}`
373
374     echo "#####    Date: `date '+%a %H:%M %h %d,'` ${YEAR}"
375     echo ""
376     echo "#####     Job: ${request_id}"
377     echo ""
378
379 }
380
381 print_banner() {
382     if [ -x ${NETATALKHOME}/bin/timeout ]
383     then
384         banner | ${NETATALKHOME}/etc/psf \
385             | ${NETATALKHOME}/bin/timeout "${time}" ${NETATALKHOME}/bin/pap -c -p "${PAPDEST}"
386     else
387         banner | ${NETATALKHOME}/etc/psf \
388             | ${NETATALKHOME}/bin/pap -c -p "{PAPDEST}"
389     fi
390
391     if [ ${?} -ne 0 ]
392     then
393         filter_timeout
394     fi  
395 }
396
397 #####
398 # ${LPTELL} is the name of a program that will send its
399 # standard input to the Spooler. It is used to forward
400 # the description of a printer fault to the Spooler,
401 # which uses it in an alert to the administrator.
402 #####
403 if [ ! -x "${LPTELL:=${LOCALPATH}/lp.tell}" ]
404 then
405     fake_lptell(){
406         header="no"
407         while read line
408         do
409             if [ "no" = "${header}" ]
410             then
411                 errmsg ERROR ${E_IP_UNKNOWN} \
412                 "unknown printer/interface failure" \
413                 "consult your system administrator; \
414                 reasons for failure (if any) follow:"
415                 header=yes
416             fi
417             echo "${line}" >&2
418         done
419     return 1
420     }
421     LPTELL=fake_lptell
422 fi
423
424
425 #####
426 # timeout catcher for the printing filter
427 #####
428
429 filter_timeout() {
430
431         cat > ${TMPPREFIX}D <<EOF
432
433 The printer ${printer} either timed out at ${time} seconds or pap exited
434 abnormally.  As well, we may have exceeded ${print_tries} print attempts.
435 The job ${request_id} from ${user_name} on ${machine} was
436 printing when this happened.
437
438 It may be that the only problem is the size of the job and the speed
439 of the printer.
440
441 Here is what $NETATALKHOME/bin/papstatus reports as the current 
442 state of the printer:
443
444 EOF
445 #####
446 # We don't need to test for timeout, since we cannot get here w/o it.
447 #####
448
449     ${NETATALKHOME}/bin/timeout ${time2} ${NETATALKHOME}/bin/papstatus -p "${PAPDEST}" 2>&1 >> ${TMPPREFIX}D 
450     paperr=${?}
451
452     errmsg WARNING ${E_IP_UNKNOWN} "`cat ${TMPPREFIX}D`" "printing continues"
453 #####
454 # This ought to deal w/ the problem of nonexistent appletalk names, but...
455 # for the moment, it calls filter_death.  But it sends the  papstatus 
456 # info to LPTELL anyhow, so you should be able to see the error.
457 #####
458
459     if [ ${paperr} -ne 0 -o ${too_many} = "1" ]; then
460         paperr=
461         filter_death
462     fi
463     paperr=
464     echo "serverdict begin 0 exitserver systemdict /quit get exec" | \
465                  ${NETATALKHOME}/bin/pap -c -p "${PAPDEST}"
466     return 0
467 }
468
469 #####
470 # Death catcher for filter_timeout
471 #####
472
473 filter_death() {
474
475     cat > ${TMPPREFIX}Z <<EOF
476 Excessive delays w/ the printer ${printer}!
477
478 While processing on printer ${printer} the job ${request_id} 
479 from ${user_name} on ${machine} timed out at ${time} seconds.  
480
481 Then while cleaning that timeout, the cleanup operation failed as
482 well.
483
484 EOF
485     errmsg ERROR ${E_IP_UNKNOWN} "`cat ${TMPPREFIX}Z`"
486     exit 129
487 #####
488 # Exit and fault the printer.
489 #####
490 }
491
492 #####
493 # Print the job
494 #####
495 printfile() {
496     trap '' 1   # Let the filter handle a hangup
497     trap '' 2 3 # and interrupts
498 #####
499 # We use timeout so as to not hang the print queue indefinately.  (pap does not
500 # timeout on it's own.)
501 #
502 # Put the 0<${files} before the "eval" to keep clever users from giving 
503 # a file name that evaluates as something to execute.
504 #####
505     if [ "${TERM}" == "Netatalk-R" ]; then
506         if [ -x ${NETATALKHOME}/bin/timeout ]; then
507             0<${file} /usr/lib/lp/postscript/postreverse | ${NETATALKHOME}/bin/timeout ${time} ${NETATALKHOME}/bin/pap -c -p "${PAPDEST}"
508         else
509             0<${file} /usr/lib/lp/postscript/postreverse | ${NETATALKHOME}/bin/pap -c -p "${PAPDEST}"
510         fi
511     else
512         if [ -x ${NETATALKHOME}/bin/timeout ]; then
513             0<${file} ${NETATALKHOME}/bin/timeout ${time} ${NETATALKHOME}/bin/pap -c -p "${PAPDEST}"
514         else
515             0<${file} ${NETATALKHOME}/bin/pap -c -p "${PAPDEST}"
516         fi
517     fi
518     paperr=${?}
519     print_tries=`expr "${print_tries}" + 1`
520     if [ "${paperr}" != "0" -a "${print_tries}" -gt "${attempts}" ]; then
521         too_many=1
522     fi
523     trap 'catch_hangup; exit_code=129 exit 129' 1
524     trap 'catch_interrupt; exit_code=129 exit 129' 2 3
525     return ${paperr}
526 }
527
528 #####
529 # Some basic sanity checking:
530 #####
531
532 if [ ! -x $NETATALKHOME/bin/pap ]
533 then
534     echo "Opps, cannot find $NETATALKHOME/bin/pap, so I don't know how to"
535     echo "print things"
536     # exit w/ less than 128 to mark an error w/ the job, and call it done
537     exit 1 
538 fi
539
540 ###########################################################################
541 #
542 # Start the main section of the program.
543 #
544 ###########################################################################
545
546 #####
547 # Here i should have a "job canceled" page ready in a trap in case of getting killed
548 # but, alas, that would most likely muck up the PS.  So we just drop the job on the 
549 # floor.
550 #####
551
552 #####
553 # If you want a custom banner, change the code up in the functions section.
554 #####
555
556 if [ "no" = "${nobanner}" -a "${TERM}" != "Netatalk-R" ]
557 then
558     print_banner
559 fi
560
561 #####
562 # Print some copies of the file(s)
563 #####
564
565 badfileyet=
566 i=1
567 while [ $i -le $copies ]
568 do
569     for file in ${files}
570     do
571         if [ -r "${file}" ]
572         then
573             print_tries=0
574             until printfile
575             do
576                 filter_timeout;
577             done
578         else
579 #####
580 # Don't complain about not being able to read a file on second and
581 # subsequent copies, unless we've not complained yet. This removes
582 # repeated messages about the same file yet reduces the chance that the
583 # user can remove a file and not know that we had trouble finding it.
584 #####
585             if [ "${i}" -le 1 -o -z "${badfileyet}" ]
586             then
587                 errmsg WARNING ${E_IP_BADFILE} \
588                     "cannot read file \"${file}\" " \
589                     "see if the file still exists and is readable by the user\
590                     lp (or world), or consult your system administrator; \
591                     We will keep trying to print the other files or copies"
592                 badfileyet=yes
593             fi
594         fi
595     done
596     i=`expr $i + 1`
597 done
598
599 #####
600 # print the banner page if we are a reversed queue
601 #####
602 if [ "no" = "${nobanner}" -a "${TERM}" == "Netatalk-R" ]
603 then
604     print_banner
605 fi
606
607 echo "serverdict begin 0 exitserver systemdict /quit get exec" | \
608                  ${NETATALKHOME}/bin/pap -c -p "${PAPDEST}"
609
610 Exit_code=0 exit 0