• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/netatalk-2.2.0/contrib/printing/
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
12time=1800
13time2=60
14attempts=3
15pap_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
25NETATALKHOME=DEFAULT_NETATALK_HOME ; export NETATALKHOME
26#NETATALKHOME=/opt ; export NETATALKHOME
27
28if [ "${NETATALKHOME}" = "DEFAULT_NETATALK_HOME" ]; then
29   echo "bleah, NETATALKHOME not set, exiting..." ; exit 5
30fi
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
121trap '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
129trap 'catch_hangup; exit_code=129 exit 129' 1
130trap '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
143TMPPREFIX=/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
150trap 'rm -fr ${TMPPREFIX}*; exit ${exit_code}' 0
151
152catch_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
162catch_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
184exec 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
205PATH="/bin:/usr/bin:${LOCALPATH}:${NETATALKHOME}/bin:${NETATALKHOME}/etc"
206export PATH
207
208TMPPREFIX=${TMPDIR}/`uname -n`$$
209
210#####
211# Error levels for the errmsg() func.
212#####
213
214LP_ERR_LABEL="UX:lp" ; export LP_ERR_LABEL
215
216E_IP_ARGS=1
217E_IP_OPTS=2
218E_IP_UNKNOWN=5
219E_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
233errmsg () {
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
246parse () {
247        echo "`expr \"$1\" : \"^[^=]*=\(.*\)\"`"
248}
249
250#####
251# die quickly if we do not have the right number of arguments.
252#####
253
254if [ $# -lt 5 ]
255then
256	errmsg ERROR ${E_IP_ARGS} \
257		"wrong number of arguments to interface program" \
258		"consult your system administrator"
259	exit 1
260fi
261
262printer=`basename $0`
263request_id=$1
264
265# this will formated be machine!username, so we want to split that up...
266
267user_name=$2
268machine=`echo $user_name | cut -d! -f1`
269user_name=`echo $user_name | cut -d! -f2`
270
271title=$3
272copies=$4
273option_list=$5
274
275shift 5
276files="$*"
277
278nobanner="yes"
279
280inlist=
281
282for i in ${option_list}
283do
284case "${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
332done
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
342PAPDEST="`lpstat -D -p "${printer}" | grep -i descrip | sed 's/.*Description:.*\[//g' | sed 's/\].*//g'`"
343
344export PAPDEST
345
346###########################################################################
347#
348# Define our local functions  (parse is declared above option parsing)
349#
350###########################################################################
351
352banner () {
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
381print_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#####
403if [ ! -x "${LPTELL:=${LOCALPATH}/lp.tell}" ]
404then
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
422fi
423
424
425#####
426# timeout catcher for the printing filter
427#####
428
429filter_timeout() {
430
431	cat > ${TMPPREFIX}D <<EOF
432
433The printer ${printer} either timed out at ${time} seconds or pap exited
434abnormally.  As well, we may have exceeded ${print_tries} print attempts.
435The job ${request_id} from ${user_name} on ${machine} was
436printing when this happened.
437
438It may be that the only problem is the size of the job and the speed
439of the printer.
440
441Here is what $NETATALKHOME/bin/papstatus reports as the current 
442state of the printer:
443
444EOF
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
473filter_death() {
474
475    cat > ${TMPPREFIX}Z <<EOF
476Excessive delays w/ the printer ${printer}!
477
478While processing on printer ${printer} the job ${request_id} 
479from ${user_name} on ${machine} timed out at ${time} seconds.  
480
481Then while cleaning that timeout, the cleanup operation failed as
482well.
483
484EOF
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#####
495printfile() {
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
532if [ ! -x $NETATALKHOME/bin/pap ]
533then
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 
538fi
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
556if [ "no" = "${nobanner}" -a "${TERM}" != "Netatalk-R" ]
557then
558    print_banner
559fi
560
561#####
562# Print some copies of the file(s)
563#####
564
565badfileyet=
566i=1
567while [ $i -le $copies ]
568do
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`
597done
598
599#####
600# print the banner page if we are a reversed queue
601#####
602if [ "no" = "${nobanner}" -a "${TERM}" == "Netatalk-R" ]
603then
604    print_banner
605fi
606
607echo "serverdict begin 0 exitserver systemdict /quit get exec" | \
608		 ${NETATALKHOME}/bin/pap -c -p "${PAPDEST}"
609
610Exit_code=0 exit 0
611