1 #ident "@(#)netatalk 0.7 99/06/22 job@uchicago.edu" /* Netatalk 1.4*/
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
18 # this should get "fixed" to something like
19 # NETATALKHOME=/opt ; export NETATALKHOME
20 # by the add_netatalk_printer script
22 # DO NOT use the user's env for this or the PATH above.
25 NETATALKHOME=DEFAULT_NETATALK_HOME ; export NETATALKHOME
26 #NETATALKHOME=/opt ; export NETATALKHOME
28 if [ "${NETATALKHOME}" = "DEFAULT_NETATALK_HOME" ]; then
29 echo "bleah, NETATALKHOME not set, exiting..." ; exit 5
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
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
47 # This File is released under the Perl Artistic Licence.
48 # See http://www.perl.org for details
50 # Or you can use it under the licence that accompanies Netatalk 1.3 =)
53 ## Netatalk printer interface. Heavily modified from
54 ## /usr/lib/lp/model/standard on Sparc Solaris 2.5.1 (May 97)
56 ## Meant to be used w/ add_netatalk_printer
60 # This program is invoked as
62 # ${SPOOLDIR}/.../printer request-id user title copies options files...
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.
73 # The protocol between the interface program and the Spooler
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.
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.
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.)
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.
109 ###########################################################################
111 # Set up the basic traps. and other important things
113 ###########################################################################
116 # For the time being, just exit if we are poked.
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.
129 trap 'catch_hangup; exit_code=129 exit 129' 1
130 trap 'catch_interrupt; exit_code=129 exit 129' 2 3
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
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.
143 TMPPREFIX=/tmp/`uname -n`$$
146 # Before exiting, set ${exit_code} to the value with which to exit.
147 # Otherwise, the exit from this script will be 0.
150 trap 'rm -fr ${TMPPREFIX}*; exit ${exit_code}' 0
153 if [ -n "${LPTELL}" ]
156 "Humm, we got a SIGHUP. Not sure what it means, but... we'll keep going anyway" \
157 | ${LPTELL} "${printer}"
163 if [ -n "${LPTELL}" ]
166 "Received an interrupt from the printer. The reason is unknown." \
167 | ${LPTELL} "${printer}"
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.
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`).
184 exec 5>&2 2>/dev/null 3>&1
186 ###########################################################################
188 # Define local varibles and such
190 ###########################################################################
193 # There is one more varible set by the shell that execs us.
194 # FILTER The filter to run ; we ignore this directive
198 # Use the user set env, or else default to standard values.
201 : ${SPOOLDIR:=/usr/spool/lp}
202 : ${TMPDIR:=/tmp} ; export TMPDIR
203 : ${LOCALPATH:=${SPOOLDIR}/bin} ; export LOCALPATH
205 PATH="/bin:/usr/bin:${LOCALPATH}:${NETATALKHOME}/bin:${NETATALKHOME}/etc"
208 TMPPREFIX=${TMPDIR}/`uname -n`$$
211 # Error levels for the errmsg() func.
214 LP_ERR_LABEL="UX:lp" ; export LP_ERR_LABEL
222 # Error message formatter:
226 # errmsg severity message-number problem help
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.
242 echo "${LP_ERR_LABEL}: ${sev}: $3
247 echo "`expr \"$1\" : \"^[^=]*=\(.*\)\"`"
251 # die quickly if we do not have the right number of arguments.
256 errmsg ERROR ${E_IP_ARGS} \
257 "wrong number of arguments to interface program" \
258 "consult your system administrator"
262 printer=`basename $0`
265 # this will formated be machine!username, so we want to split that up...
268 machine=`echo $user_name | cut -d! -f1`
269 user_name=`echo $user_name | cut -d! -f2`
282 for i in ${option_list}
284 case "${inlist}${i}" in
291 # If you want to add simple options (e.g. -o simple)
292 # identify them here.
298 # These get ignored, but would matter little anyway since all we see
302 # cpi=`parse ${i}` ;;
305 # lpi=`parse ${i}` ;;
308 # length=`parse ${i}` ;;
311 # width=`parse ${i}` ;;
315 # If you want to add simple-value options (e.g. -o value=a)
316 # identify them here.
319 # value=`parse ${i}` ;;
322 flist=`parse ${i}` ;;
326 errmsg WARNING ${E_IP_OPTS} \
327 "unrecognized \"-o ${i}\" option" \
328 "check the option, resubmit if necessary
329 printing continues" ;;
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 ].
339 # eg - 'this is the printer [hp-mrsec-l114:lasershared@Research Insitutes] that i use.'
342 PAPDEST="`lpstat -D -p "${printer}" | grep -i descrip | sed 's/.*Description:.*\[//g' | sed 's/\].*//g'`"
346 ###########################################################################
348 # Define our local functions (parse is declared above option parsing)
350 ###########################################################################
353 echo "##### User: ${user_name}"
355 echo "##### Machine: ${user_name}"
360 echo "##### Title: ${title}"
364 echo "##### Files: ${flist}"
368 # this should deal w/ the year 2000 ok. But will die in 2038. =)
372 YEAR=`expr 1900 + ${YEAR}`
374 echo "##### Date: `date '+%a %H:%M %h %d,'` ${YEAR}"
376 echo "##### Job: ${request_id}"
382 if [ -x ${NETATALKHOME}/bin/timeout ]
384 banner | ${NETATALKHOME}/etc/psf \
385 | ${NETATALKHOME}/bin/timeout "${time}" ${NETATALKHOME}/bin/pap -c -p "${PAPDEST}"
387 banner | ${NETATALKHOME}/etc/psf \
388 | ${NETATALKHOME}/bin/pap -c -p "{PAPDEST}"
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.
403 if [ ! -x "${LPTELL:=${LOCALPATH}/lp.tell}" ]
409 if [ "no" = "${header}" ]
411 errmsg ERROR ${E_IP_UNKNOWN} \
412 "unknown printer/interface failure" \
413 "consult your system administrator; \
414 reasons for failure (if any) follow:"
426 # timeout catcher for the printing filter
431 cat > ${TMPPREFIX}D <<EOF
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.
438 It may be that the only problem is the size of the job and the speed
441 Here is what $NETATALKHOME/bin/papstatus reports as the current
442 state of the printer:
446 # We don't need to test for timeout, since we cannot get here w/o it.
449 ${NETATALKHOME}/bin/timeout ${time2} ${NETATALKHOME}/bin/papstatus -p "${PAPDEST}" 2>&1 >> ${TMPPREFIX}D
452 errmsg WARNING ${E_IP_UNKNOWN} "`cat ${TMPPREFIX}D`" "printing continues"
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.
459 if [ ${paperr} -ne 0 -o ${too_many} = "1" ]; then
464 echo "serverdict begin 0 exitserver systemdict /quit get exec" | \
465 ${NETATALKHOME}/bin/pap -c -p "${PAPDEST}"
470 # Death catcher for filter_timeout
475 cat > ${TMPPREFIX}Z <<EOF
476 Excessive delays w/ the printer ${printer}!
478 While processing on printer ${printer} the job ${request_id}
479 from ${user_name} on ${machine} timed out at ${time} seconds.
481 Then while cleaning that timeout, the cleanup operation failed as
485 errmsg ERROR ${E_IP_UNKNOWN} "`cat ${TMPPREFIX}Z`"
488 # Exit and fault the printer.
496 trap '' 1 # Let the filter handle a hangup
497 trap '' 2 3 # and interrupts
499 # We use timeout so as to not hang the print queue indefinately. (pap does not
500 # timeout on it's own.)
502 # Put the 0<${files} before the "eval" to keep clever users from giving
503 # a file name that evaluates as something to execute.
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}"
509 0<${file} /usr/lib/lp/postscript/postreverse | ${NETATALKHOME}/bin/pap -c -p "${PAPDEST}"
512 if [ -x ${NETATALKHOME}/bin/timeout ]; then
513 0<${file} ${NETATALKHOME}/bin/timeout ${time} ${NETATALKHOME}/bin/pap -c -p "${PAPDEST}"
515 0<${file} ${NETATALKHOME}/bin/pap -c -p "${PAPDEST}"
519 print_tries=`expr "${print_tries}" + 1`
520 if [ "${paperr}" != "0" -a "${print_tries}" -gt "${attempts}" ]; then
523 trap 'catch_hangup; exit_code=129 exit 129' 1
524 trap 'catch_interrupt; exit_code=129 exit 129' 2 3
529 # Some basic sanity checking:
532 if [ ! -x $NETATALKHOME/bin/pap ]
534 echo "Opps, cannot find $NETATALKHOME/bin/pap, so I don't know how to"
536 # exit w/ less than 128 to mark an error w/ the job, and call it done
540 ###########################################################################
542 # Start the main section of the program.
544 ###########################################################################
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
553 # If you want a custom banner, change the code up in the functions section.
556 if [ "no" = "${nobanner}" -a "${TERM}" != "Netatalk-R" ]
562 # Print some copies of the file(s)
567 while [ $i -le $copies ]
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.
585 if [ "${i}" -le 1 -o -z "${badfileyet}" ]
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"
600 # print the banner page if we are a reversed queue
602 if [ "no" = "${nobanner}" -a "${TERM}" == "Netatalk-R" ]
607 echo "serverdict begin 0 exitserver systemdict /quit get exec" | \
608 ${NETATALKHOME}/bin/pap -c -p "${PAPDEST}"