xref: /onnv-gate/usr/src/cmd/lp/model/tsol_standard_foomatic (revision 4746:0bc0c48f4304)
1*4746Srica#
2*4746Srica# CDDL HEADER START
3*4746Srica#
4*4746Srica# The contents of this file are subject to the terms of the
5*4746Srica# Common Development and Distribution License (the "License").
6*4746Srica# You may not use this file except in compliance with the License.
7*4746Srica#
8*4746Srica# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*4746Srica# or http://www.opensolaris.org/os/licensing.
10*4746Srica# See the License for the specific language governing permissions
11*4746Srica# and limitations under the License.
12*4746Srica#
13*4746Srica# When distributing Covered Code, include this CDDL HEADER in each
14*4746Srica# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*4746Srica# If applicable, add the following below this CDDL HEADER, with the
16*4746Srica# fields enclosed by brackets "[]" replaced with your own identifying
17*4746Srica# information: Portions Copyright [yyyy] [name of copyright owner]
18*4746Srica#
19*4746Srica# CDDL HEADER END
20*4746Srica#
21*4746Srica#
22*4746Srica#ident	"%Z%%M%	%I%	%E% SMI"
23*4746Srica#
24*4746Srica# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
25*4746Srica# Use is subject to license terms.
26*4746Srica#
27*4746Srica
28*4746Srica###########
29*4746Srica##
30*4746Srica## Standard printer interface program.
31*4746Srica##
32*4746Srica###########
33*4746Srica
34*4746Srica#####
35*4746Srica#
36*4746Srica# Until we get to the point below where the printer port
37*4746Srica# and physical printer are initialized, we can't do much
38*4746Srica# except exit if the Spooler/Scheduler cancels us.
39*4746Srica#####
40*4746Sricatrap 'exit' 15
41*4746Srica
42*4746Srica#####
43*4746Srica#
44*4746Srica# We can be clever about getting a hangup or interrupt, though, at least
45*4746Srica# until the filter runs. Do this early, even though $LPTELL
46*4746Srica# isn't defined, so that we're covered.
47*4746Srica#####
48*4746Sricacatch_hangup () {
49*4746Srica	if [ -n "${LPTELL}" ]
50*4746Srica	then
51*4746Srica		echo \
52*4746Srica"The connection to the printer dropped; perhaps the printer went off-line?" \
53*4746Srica		| ${LPTELL} ${printer}
54*4746Srica	fi
55*4746Srica	return 0
56*4746Srica}
57*4746Sricacatch_interrupt () {
58*4746Srica	if [ -n "${LPTELL}" ]
59*4746Srica	then
60*4746Srica		echo \
61*4746Srica"Received an interrupt from the printer.  The reason is unknown,
62*4746Sricaalthough a common cause is that the baud rate is too high." \
63*4746Srica		| ${LPTELL} ${printer}
64*4746Srica	fi
65*4746Srica	return 0
66*4746Srica}
67*4746Sricatrap 'catch_hangup; exit_code=129 exit 129' 1
68*4746Sricatrap 'catch_interrupt; exit_code=129 exit 129' 2 3
69*4746Srica
70*4746Srica#####
71*4746Srica#
72*4746Srica# Most of the time we don't want the standard error to be captured
73*4746Srica# by the Spooler, mainly to avoid "Terminated" messages that the
74*4746Srica# shell puts out when we get a SIGTERM. We'll save the standard
75*4746Srica# error channel under another number, so we can use it when it
76*4746Srica# should be captured.
77*4746Srica#
78*4746Srica# Open another channel to the printer port, for use when the
79*4746Srica# regular standard output won't be directed there, such as in
80*4746Srica# command substitution (`cmd`).
81*4746Srica#####
82*4746Sricaexec 5>&2 2>/dev/null 3>&1
83*4746Srica
84*4746Srica#####
85*4746Srica#
86*4746Srica# Set some globally used variables and functions.
87*4746Srica#####
88*4746Srica
89*4746Srica: ${TMPDIR:=/tmp}
90*4746Srica: ${SPOOLDIR:=/usr/spool/lp}
91*4746Srica: ${TERMINFO:=/usr/lib/terminfo}
92*4746Srica: ${CHARSETDIR:=/usr/lib/charsets}
93*4746Srica
94*4746Srica: ${LOCALPATH:=${SPOOLDIR}/bin}
95*4746SricaPATH="/bin:/usr/bin:${LOCALPATH}"
96*4746Srica
97*4746SricaMAX_COLS_SMALL_BANNER=40
98*4746Srica
99*4746Srica#####
100*4746Srica#
101*4746Srica# On the 3.2 release of the 386unix product, the parallel port does
102*4746Srica# not support any ioctl calls.  As a result, we cannot set the opost
103*4746Srica# and onlcr attributes to have <NL>'s expanded to <CR><NL>.  This
104*4746Srica# "filter" gets the job done for us.
105*4746Srica#####
106*4746Srica: ${FIX386BD:=${LOCALPATH}/386parallel}
107*4746Sricaif [ -n "${FIX386BD}" -a -x "${FIX386BD}" ]
108*4746Sricathen
109*4746Srica	FIX386BD="| ${FIX386BD}"
110*4746Sricaelse
111*4746Srica	FIX386BD=""
112*4746Sricafi
113*4746Srica
114*4746Srica#####
115*4746Srica# Use ${TMPPREFIX} as the prefix for all temporary files, so
116*4746Srica# that cleanup is easy. The prefix may be up to 13 characters
117*4746Srica# long, so you only have space for one more character to make
118*4746Srica# a file name. If necessary, make a directory using this prefix
119*4746Srica# for better management of unique temporary file names.
120*4746Srica#####
121*4746SricaTMPPREFIX=${TMPDIR}/`uname -n`$$
122*4746Srica
123*4746Srica#####
124*4746Srica# Before exiting, set ${exit_code} to the value with which to exit.
125*4746Srica# Otherwise, the exit from this script will be 0.
126*4746Srica#####
127*4746Sricatrap 'rm -fr ${TMPPREFIX}*; exit ${exit_code}' 0
128*4746Srica
129*4746Srica#####
130*4746Srica# ${LPTELL} is the name of a program that will send its
131*4746Srica# standard input to the Spooler. It is used to forward
132*4746Srica# the description of a printer fault to the Spooler,
133*4746Srica# which uses it in an alert to the administrator.
134*4746Srica#####
135*4746Sricaif [ ! -x "${LPTELL:=${LOCALPATH}/lp.tell}" ]
136*4746Sricathen
137*4746Srica	fake_lptell () {
138*4746Srica		header="no"
139*4746Srica		while read line
140*4746Srica		do
141*4746Srica			if [ "no" = "${header}" ]
142*4746Srica			then
143*4746Srica				errmsg ERROR ${E_IP_UNKNOWN} \
144*4746Srica		"unknown printer/interface failure" \
145*4746Srica		"consult your system administrator;
146*4746Srica		reasons for failure (if any) follow:"
147*4746Srica				header=yes
148*4746Srica			fi
149*4746Srica			echo "${line}" >&2
150*4746Srica		done
151*4746Srica		return 1
152*4746Srica	}
153*4746Srica	LPTELL=fake_lptell
154*4746Sricafi
155*4746Srica
156*4746Srica#####
157*4746Srica# ${DRAIN} is the name of a program that will wait
158*4746Srica# long enough for data sent to the printer to print.
159*4746Srica#####
160*4746Sricaif [ -x "${LOCALPATH}/drain.output" ]
161*4746Sricathen
162*4746Srica	DRAIN="${LOCALPATH}/drain.output 5"	# wait only five seconds
163*4746Sricaelse
164*4746Srica	DRAIN=
165*4746Sricafi
166*4746Srica
167*4746Srica#####
168*4746Srica# ${LPTSOLSEPARATOR} is the name of a program to put banner and trailer
169*4746Srica# pages around the job.
170*4746Srica#####
171*4746Sricaif [ -x ${LOCALPATH}/lp.tsol_separator ]
172*4746Sricathen
173*4746Srica	LPTSOLSEPARATOR=${LOCALPATH}/lp.tsol_separator
174*4746Sricaelse
175*4746Srica	echo "${LOCALPATH}/lp.tsol_separator not found." >&2
176*4746Srica	exit 1
177*4746Sricafi
178*4746Srica
179*4746Srica#####
180*4746Srica# ${LPCAT} is the name of a program to use as a default
181*4746Srica# filter. Minimally it should copy its standard input to
182*4746Srica# the standard output, but it should also trap printer
183*4746Srica# faults. The current LPCAT traps hangups (DCD dropping, SIGHUP),
184*4746Srica# interrupts (SIGINT, SIGQUIT), broken pipe (SIGPIPE), and
185*4746Srica# excess delays in sending data to the printer, interpreting all
186*4746Srica# as printer faults.
187*4746Srica#####
188*4746Sricaif [ ! -x "${LPCAT:=${LOCALPATH}/lp.cat}" ]
189*4746Sricathen
190*4746Srica	LPCAT="cat"
191*4746Sricafi
192*4746Srica
193*4746Srica#####
194*4746Srica# ${LPSET} is the name of a program that will set the
195*4746Srica# character pitch, line pitch, page width, page length,
196*4746Srica# and character set. It helps to have this in a single
197*4746Srica# binary program so that (1) it's faster than calls
198*4746Srica# to "tput"; and (2) it can access the new Terminfo
199*4746Srica# capabilities for printers (on pre SVR3.2 machines, tput can't).
200*4746Srica#####
201*4746Sricaif [ ! -x "${LPSET:=${LOCALPATH}/lp.set}" ]
202*4746Sricathen
203*4746Srica	fake_lpset () {
204*4746Srica		echo H V W L S >&2
205*4746Srica		false
206*4746Srica	}
207*4746Srica	LPSET=fake_lpset
208*4746Sricafi
209*4746Srica
210*4746Sricainternal_lpset () {
211*4746Srica	#####
212*4746Srica	#
213*4746Srica	# The funny business with the "2>&1 1>&3" is to let us capture
214*4746Srica	# the standard ERROR, not the standard OUTPUT as is the usual case
215*4746Srica	# with foo=`cmd`. The standard output will go to the printer.
216*4746Srica	#####
217*4746Srica	[ -n "${stty1}" ] && stty ${stty1} 0<&1
218*4746Srica	chk=`${LPSET} "$1" "$2" "$3" "$4" "$5" 2>&1 1>&3`
219*4746Srica	[ -n "${stty2}" ] && stty ${stty2} 0<&1
220*4746Srica
221*4746Srica	#####
222*4746Srica	#
223*4746Srica	# The standard error of the delivered ${LPSET} program
224*4746Srica	# is a string of letters, H, V, W, L, S, which correspond
225*4746Srica	# to cpi, lpi, width, length, and character set. A letter
226*4746Srica	# is present only if the corresponding attribute could not
227*4746Srica	# be set.
228*4746Srica	#####
229*4746Srica	for err in ${chk}
230*4746Srica	do
231*4746Srica		case ${err} in
232*4746Srica		H )
233*4746Srica			errmsg WARNING ${E_IP_BADCPI} \
234*4746Srica		"can't select the character pitch \"${cpi}\"" \
235*4746Srica		"check the valid pitches for the printer,
236*4746Srica		or consult your system administrator;
237*4746Srica		printing continues"
238*4746Srica			;;
239*4746Srica		V )
240*4746Srica			errmsg WARNING ${E_IP_BADLPI} \
241*4746Srica		"can't select the line pitch \"${lpi}\"" \
242*4746Srica		"check the valid pitches for the printer,
243*4746Srica		or consult your system administrator;
244*4746Srica		printing continues"
245*4746Srica			;;
246*4746Srica		W )
247*4746Srica			width=${cols}
248*4746Srica			errmsg WARNING ${E_IP_BADWIDTH} \
249*4746Srica		"can't select the page width \"${width}\"" \
250*4746Srica		"check the valid widths for the printer,
251*4746Srica		or consult your system administrator;
252*4746Srica		printing continues"
253*4746Srica			;;
254*4746Srica		L )
255*4746Srica			length=${lines}
256*4746Srica			errmsg WARNING ${E_IP_BADLENGTH} \
257*4746Srica		"can't select the page length \"${length}\"" \
258*4746Srica		"check the valid lengths for the printer,
259*4746Srica		or consult your system administrator;
260*4746Srica		printing continues"
261*4746Srica			;;
262*4746Srica		S )
263*4746Srica			errmsg WARNING ${E_IP_BADCHARSET} \
264*4746Srica		"can't select the character set \"${CHARSET}\"" \
265*4746Srica		"check the name given in the -S option,
266*4746Srica		or consult your system administrator;
267*4746Srica		printing continues"
268*4746Srica			;;
269*4746Srica		esac
270*4746Srica	done
271*4746Srica}
272*4746Srica
273*4746Srica
274*4746Srica#####
275*4746Srica# ${TPUT} is "tput" IF it works. We'll disable it if we get an
276*4746Srica# ugly error message the first time we use it. See the TERM variable
277*4746Srica# later in the script.
278*4746Srica#
279*4746Srica# NOTE: The check we use to see if "tput" works is to use an OLD
280*4746Srica# Terminfo capability, like "lines". If it works with that it may
281*4746Srica# still fail with some of the newer capabilities like "init" (SVR3.0)
282*4746Srica# or "swidm" (SVR3.2), because the version of "tput" we have on your
283*4746Srica# machine is older. Thus, on some of the code where ${TPUT} is used
284*4746Srica# you'll see "2>/dev/null" being used to avoid ugly error messages.
285*4746Srica#####
286*4746SricaTPUT=tput
287*4746Srica
288*4746Srica#####
289*4746Srica# Error message formatter:
290*4746Srica#
291*4746Srica# Invoke as
292*4746Srica#
293*4746Srica#	errmsg severity message-number problem help
294*4746Srica#
295*4746Srica# where severity is "ERROR" or "WARNING", message-number is
296*4746Srica# a unique identifier, problem is a short description of the
297*4746Srica# problem, and help is a short suggestion for fixing the problem.
298*4746Srica#####
299*4746Srica
300*4746SricaLP_ERR_LABEL="UX:lp"
301*4746Srica
302*4746SricaE_IP_ARGS=1
303*4746SricaE_IP_OPTS=2
304*4746Srica#E_IP_FILTER=3
305*4746SricaE_IP_STTY=4
306*4746SricaE_IP_UNKNOWN=5
307*4746SricaE_IP_BADFILE=6
308*4746SricaE_IP_BADCHARSET=7
309*4746SricaE_IP_BADCPI=8
310*4746SricaE_IP_BADLPI=9
311*4746SricaE_IP_BADWIDTH=10
312*4746SricaE_IP_BADLENGTH=11
313*4746SricaE_IP_ERRORS=12		# (in slow.filter)
314*4746Srica
315*4746Sricaerrmsg () {
316*4746Srica	case $1 in
317*4746Srica	ERROR )
318*4746Srica		sev="  ERROR";
319*4746Srica		;;
320*4746Srica	WARNING )
321*4746Srica		sev="WARNING";
322*4746Srica		;;
323*4746Srica	esac
324*4746Srica#	tag=`expr "${LP_ERR_LABEL}" : "\(.*\):"``expr "${LP_ERR_LABEL}" : ".*:\(.*\)"`
325*4746Srica	echo "${LP_ERR_LABEL}: ${sev}: $3
326*4746Srica        TO FIX: $4" >&5
327*4746Srica}
328*4746Srica
329*4746Srica
330*4746Srica###########
331*4746Srica##
332*4746Srica## Check arguments
333*4746Srica###########
334*4746Srica
335*4746Sricaparse () {
336*4746Srica	echo "`expr \"$1\" : \"^[^=]*=\(.*\)\"`"
337*4746Srica}
338*4746Srica
339*4746Srica#####
340*4746Srica#
341*4746Srica# This program is invoked as
342*4746Srica#
343*4746Srica# ${SPOOLDIR}/.../printer request-id user title copies options files...
344*4746Srica#
345*4746Srica# The first three arguments are simply reprinted on the banner page,
346*4746Srica# the fourth (copies) is used to control the number of copies to print,
347*4746Srica# the fifth (options) is a blank separated list (in a single argument)
348*4746Srica# of user or Spooler supplied options (without the -o prefix),
349*4746Srica# and the last arguments are the files to print.
350*4746Srica#####
351*4746Srica
352*4746Sricaif [ $# -lt 5 ]
353*4746Sricathen
354*4746Srica	errmsg ERROR ${E_IP_ARGS} \
355*4746Srica		"wrong number of arguments to interface program" \
356*4746Srica		"consult your system administrator"
357*4746Srica	exit 1
358*4746Sricafi
359*4746Srica
360*4746Sricaprinter=`basename $0`
361*4746Sricarequest_id=$1
362*4746Sricauser_name=$2
363*4746Sricatitle=$3
364*4746Sricacopies=$4
365*4746Sricaoption_list=$5
366*4746Srica
367*4746Sricashift 5
368*4746Sricafiles="$*"
369*4746Srica
370*4746Sricanobanner="no"
371*4746Sricanofilebreak="no"
372*4746Sricanolabels="no"
373*4746Sricastty=
374*4746Srica
375*4746Sricainlist=
376*4746Sricafor i in ${option_list}
377*4746Sricado
378*4746Srica	case "${inlist}${i}" in
379*4746Srica
380*4746Srica
381*4746Srica	nobanner )
382*4746Srica		nobanner="yes"
383*4746Srica		;;
384*4746Srica
385*4746Srica	nofilebreak )
386*4746Srica		nofilebreak="yes"
387*4746Srica		;;
388*4746Srica
389*4746Srica	nolabels )
390*4746Srica		nolabels="yes"
391*4746Srica		;;
392*4746Srica
393*4746Srica	#
394*4746Srica	# The IPP/PAPI attributes are handled by the foomatic-rip filter so
395*4746Srica	# all we need to do here is ignore them so that they don't invoke the
396*4746Srica	# "unrecognized option" message.
397*4746Srica	#
398*4746Srica
399*4746Srica	finishing=* | page-ranges=* | sides=* )
400*4746Srica		;;
401*4746Srica	number-up=* | orientation-requested=* | media=* )
402*4746Srica		;;
403*4746Srica	printer-resolution=* | print-quality=* )
404*4746Srica		;;
405*4746Srica
406*4746Srica	#####
407*4746Srica	#
408*4746Srica	# If you want to add simple options (e.g. -o simple)
409*4746Srica	# identify them here.
410*4746Srica	#####
411*4746Srica#	simple )
412*4746Srica#		simple="yes"
413*4746Srica#		;;
414*4746Srica
415*4746Srica
416*4746Srica	cpi=pica )
417*4746Srica		cpi=10
418*4746Srica		;;
419*4746Srica	cpi=elite )
420*4746Srica		cpi=12
421*4746Srica		;;
422*4746Srica	cpi=* )
423*4746Srica		cpi=`parse ${i}`
424*4746Srica		;;
425*4746Srica
426*4746Srica	lpi=* )
427*4746Srica		lpi=`parse ${i}`
428*4746Srica		;;
429*4746Srica
430*4746Srica	length=* )
431*4746Srica		length=`parse ${i}`
432*4746Srica		;;
433*4746Srica
434*4746Srica	width=* )
435*4746Srica		width=`parse ${i}`
436*4746Srica		;;
437*4746Srica
438*4746Srica	#####
439*4746Srica	#
440*4746Srica	# If you want to add simple-value options (e.g. -o value=a)
441*4746Srica	# identify them here.
442*4746Srica	#####
443*4746Srica#	value=* )
444*4746Srica#		value=`parse ${i}`
445*4746Srica#		;;
446*4746Srica
447*4746Srica
448*4746Srica	#####
449*4746Srica	#
450*4746Srica	# If you want to add options that, like "stty",
451*4746Srica	# take a list (e.g. -o lopt='a b c'), identify
452*4746Srica	# them here and below (look for LOPT).
453*4746Srica	#####
454*4746Srica	stty=* | flist=* | lpd=* )
455*4746Srica#LOPT	stty=* | flist=* | lpd=* | lopt=* )
456*4746Srica
457*4746Srica		inlist=`expr "${inlist}${i}" : "^\([^=]*=\)"`
458*4746Srica		case "${i}" in
459*4746Srica		${inlist}\'*\' )
460*4746Srica			item=`expr "${i}" : "^[^=]*='*\(.*\)'\$"`
461*4746Srica			;;
462*4746Srica		${inlist}\' )
463*4746Srica			continue
464*4746Srica			;;
465*4746Srica		${inlist}\'* )
466*4746Srica			item=`expr "${i}" : "^[^=]*='*\(.*\)\$"`
467*4746Srica			;;
468*4746Srica		${inlist}* )
469*4746Srica			item=`expr "${i}" : "^[^=]*=\(.*\)\$"`
470*4746Srica			;;
471*4746Srica		*\' )
472*4746Srica			item=`expr "${i}" : "^\(.*\)'\$"`
473*4746Srica			;;
474*4746Srica		* )
475*4746Srica			item="${i}"
476*4746Srica			;;
477*4746Srica		esac
478*4746Srica
479*4746Srica		#####
480*4746Srica		#
481*4746Srica		# We don't dare use "eval" because a clever user could
482*4746Srica		# put something in an option value that we'd end up
483*4746Srica		# exec'ing.
484*4746Srica		#####
485*4746Srica		case "${inlist}" in
486*4746Srica		stty= )
487*4746Srica			stty="${stty} ${item}"
488*4746Srica			;;
489*4746Srica		flist= )
490*4746Srica			flist="${flist} ${item}"
491*4746Srica			;;
492*4746Srica		lpd= )
493*4746Srica			lpd="${lpd} ${item}"
494*4746Srica			;;
495*4746Srica#LOPT		lopt= )
496*4746Srica#LOPT			lopt="${lopt} ${item}"
497*4746Srica#LOPT			;;
498*4746Srica		esac
499*4746Srica
500*4746Srica		case "${i}" in
501*4746Srica		${inlist}\'*\' )
502*4746Srica			inlist=
503*4746Srica			;;
504*4746Srica		${inlist}\'* )
505*4746Srica			;;
506*4746Srica		*\' | ${inlist}* )
507*4746Srica			inlist=
508*4746Srica			;;
509*4746Srica		esac
510*4746Srica		;;
511*4746Srica
512*4746Srica	* )
513*4746Srica		errmsg WARNING ${E_IP_OPTS} \
514*4746Srica			"unrecognized \"-o ${i}\" option" \
515*4746Srica			"check the option, resubmit if necessary
516*4746Srica		printing continues"
517*4746Srica		;;
518*4746Srica	esac
519*4746Sricadone
520*4746Srica
521*4746Srica#####
522*4746Srica#
523*4746Srica# Additional ``parameters'' are passed via Shell environment
524*4746Srica# variables:
525*4746Srica#
526*4746Srica#	TERM	The printer type (used for Terminfo access)
527*4746Srica#	CHARSET	The character set to choose
528*4746Srica#	FILTER	The filter to run
529*4746Srica#####
530*4746Srica
531*4746Srica#####
532*4746Srica# Set defaults for unset variables.
533*4746Srica#####
534*4746Srica
535*4746Srica: ${TERM:=unknown}
536*4746Sricatput lines 1>/dev/null 2>&1 || TPUT=:
537*4746Srica
538*4746Srica: ${CHARSET:=cs0}
539*4746Srica
540*4746SricaPPDFILTER=/usr/lib/lp/bin/foomatic-rip
541*4746SricaPPDFILTERA="${PPDFILTER} ${request_id} ${user_name} \"${title}\" ${copies} \"${option_list}\""
542*4746Srica
543*4746Sricaif [ -z "${FILTER}" ]
544*4746Sricathen
545*4746Srica	#####
546*4746Srica	#
547*4746Srica	# If no filter is being used, we have a little routine that
548*4746Srica	# will push the data to the printer. It traps hangups (loss
549*4746Srica	# of carrier) and checks for excessive delays in sending the
550*4746Srica	# data to the printer. The lesser of the print rate of the printer
551*4746Srica	# (obtained from Terminfo) or the baud rate is used to compute
552*4746Srica	# the expected delay. If neither of these is correct, you
553*4746Srica	# may be experiencing false alarms. If so, give the correct
554*4746Srica	# rate, in characters per second, as a single argument.
555*4746Srica	# An argument of 0 means don't check for delays.
556*4746Srica	# Give an -r option to get a printout of actual delays.
557*4746Srica	# (QUOTES ARE IMPORTANT!)
558*4746Srica	#####
559*4746Srica	case "$TERM" in
560*4746Srica		PS )
561*4746Srica			# make the "postscript" printers use postio to
562*4746Srica			# talk to the printer and periodically get a
563*4746Srica			# status from them
564*4746Srica			FILTER="/usr/lib/lp/postscript/postio"
565*4746Srica		;;
566*4746Srica		PSR )
567*4746Srica			# make the "reverse postscript" printers reverse the
568*4746Srica			# output and the use postio to talk to the printer
569*4746Srica			FILTER="/usr/lib/lp/postscript/postreverse | \
570*4746Srica				/usr/lib/lp/postscript/postio"
571*4746Srica		;;
572*4746Srica		* )
573*4746Srica			# we don't know the type, so just assume that the
574*4746Srica			# input and output are the same
575*4746Srica			if [ `basename "${LPCAT}"` = "lp.cat" ] ; then
576*4746Srica				FILTER="${LPCAT} 0"	# infinite delays
577*4746Srica				# FILTER="${LPCAT} 120"	# e.g. 120 CPS
578*4746Srica				# FILTER="${LPCAT} -r 0 2>/tmp/delays"
579*4746Srica				# FILTER=${LPCAT}
580*4746Srica			fi
581*4746Srica		;;
582*4746Srica	esac
583*4746Sricafi
584*4746Srica
585*4746Sricalogger -p lpr.debug -t "tsol_standard_foomatic: ${request_id}" "filter : ${FILTER}"
586*4746Sricalogger -p lpr.debug -t "tsol_standard_foomatic: ${request_id}" "ppdfilter : ${PPDFILTERA}"
587*4746Srica
588*4746Srica#
589*4746Srica# Append the PPD foomatic-rip filter
590*4746Srica#
591*4746SricaFILTER="${FILTER} | ${PPDFILTERA}"
592*4746Srica
593*4746Srica###########
594*4746Srica##
595*4746Srica## Initialize the printer port
596*4746Srica###########
597*4746Srica
598*4746Srica#####
599*4746Srica#
600*4746Srica# SERIAL PORTS:
601*4746Srica# Initialize everything.
602*4746Srica#
603*4746Srica# PARALLEL PORTS:
604*4746Srica# Don't initialize baud rate.
605*4746Srica#
606*4746Srica# It's not obvious how to tell if a port is parallel or serial.
607*4746Srica# However, by splitting the initialization into two steps and letting
608*4746Srica# the serial-only part fail nicely, it'll work.
609*4746Srica#
610*4746Srica# Another point: The output must be a ``tty'' device. If not, don't
611*4746Srica# bother with any of this.
612*4746Srica#####
613*4746Sricastty1= stty2=
614*4746Sricatty 0<&1 1>/dev/null 2>&1 && {
615*4746Srica
616*4746Srica	#####
617*4746Srica	#
618*4746Srica	# First set the default parameters,
619*4746Srica	# then the requested parameters.
620*4746Srica	#####
621*4746Srica
622*4746Srica	stty \
623*4746Srica		9600 \
624*4746Srica			0<&1 2>/dev/null 1>&2
625*4746Srica	stty \
626*4746Srica		cs8 -cstopb -parenb -parodd \
627*4746Srica		ixon -ixany \
628*4746Srica		opost -olcuc onlcr -ocrnl -onocr -onlret -ofill \
629*4746Srica		nl0 cr0 tab0 bs0 vt0 ff0 \
630*4746Srica			0<&1 2>/dev/null 1>&2
631*4746Srica
632*4746Srica	if [ -n "${stty}" ]
633*4746Srica	then
634*4746Srica		if stty ${stty} 0<&1 1>/dev/null 2>&5
635*4746Srica		then
636*4746Srica			:
637*4746Srica		else
638*4746Srica			errmsg ERROR ${E_IP_STTY} \
639*4746Srica				"stty option list failed" \
640*4746Srica				"check the \"-o stty\" option you used,
641*4746Srica		or consult your system administrator"
642*4746Srica			exit 1
643*4746Srica		fi
644*4746Srica	fi
645*4746Srica
646*4746Srica	#####
647*4746Srica	#
648*4746Srica	# Here you may want to add other port initialization code.
649*4746Srica	# Some examples:
650*4746Srica	#
651*4746Srica	# estty	# for printer needing hardware flow control (3B2/EPORTS)
652*4746Srica	# fctty	# for printer needing hardware flow control (3B15,3B20)
653*4746Srica	#####
654*4746Srica	#estty 0<&1
655*4746Srica	#fctty 0<&1
656*4746Srica
657*4746Srica
658*4746Srica	##########
659*4746Srica	#
660*4746Srica	# Find out if we have to turn off opost before initializing the
661*4746Srica	# printer and on after. Likewise, check clocal.
662*4746Srica	#
663*4746Srica	# Turning OFF opost (output postprocessing) keeps the UNIX system
664*4746Srica	# from changing what we try to send to the printer. Turning ON
665*4746Srica	# clocal keeps the UNIX system from dropping what we are trying to
666*4746Srica	# send if the printer drops DTR. An example of the former is the
667*4746Srica	# AT&T 479, which wants to send a linefeed (ASCII 10) when a page
668*4746Srica	# width of 10 is set; with opost on, this COULD BE turned into a
669*4746Srica	# carriage-return/linefeed pair. An example of the latter is the
670*4746Srica	# AT&T 455, which momentarily drops DTR when it gets the
671*4746Srica	# initialization string, is2; with clocal off, the UNIX system
672*4746Srica	# stops sending the rest of the initialization sequence at that
673*4746Srica	# point.
674*4746Srica	#
675*4746Srica	# THIS CODE MUST FOLLOW THE REST OF THE PORT INITIALIZATION CODE.
676*4746Srica	##########
677*4746Srica	cur_stty=`stty -a 0<&3`
678*4746Srica	expr "${cur_stty}" : '.*-opost' 1>/dev/null 2>&1 \
679*4746Srica		|| stty1="${stty1} -opost" stty2="${stty2} opost"
680*4746Srica	expr "${cur_stty}" : '.*-clocal' 1>/dev/null 2>&1 \
681*4746Srica		&& stty1="${stty1} clocal" stty2="${stty2} -clocal"
682*4746Srica	expr "${cur_stty}" : '.* opost.*' 1>/dev/null 2>&1 \
683*4746Srica		|| banner_filter=${FIX386BD}
684*4746Srica
685*4746Srica}
686*4746Srica
687*4746Srica
688*4746Srica###########
689*4746Srica##
690*4746Srica## Initialize the physical printer (Part I).
691*4746Srica## Here we bring the printer to a sane state and set the page size.
692*4746Srica###########
693*4746Srica
694*4746Srica##########
695*4746Srica#
696*4746Srica# WARNING! The "echo" command will catch backslashes (\) and
697*4746Srica# try to interpret the characters following it. Thus, using
698*4746Srica# "echo" to print string values obtained from "tput" is dangerous.
699*4746Srica##########
700*4746Srica
701*4746Srica#####
702*4746Srica# We're confident that most printers don't have backslashes
703*4746Srica# in the control sequences for carriage return and form-feed.
704*4746Srica# We're also confident that these don't contain newlines.
705*4746Srica# We're also confident that most printers have a linefeed
706*4746Srica# in the control sequence for doing a newline (move to beginning
707*4746Srica# of next line), but we can't capture it like we do the
708*4746Srica# carriage return or form-feed. Thus we set it unconditionally.
709*4746Srica# We don't set form-feed if it isn't defined, however, because
710*4746Srica# maybe the printer doesn't have a formfeed. If not set, we're
711*4746Srica# out of luck.
712*4746Srica#####
713*4746Srica
714*4746SricaCR=`${TPUT} cr`
715*4746Srica[ -z "${CR}" ] && CR="\r"
716*4746Srica
717*4746SricaFF=`${TPUT} ff`
718*4746SricaBFF=$FF
719*4746Srica[ -z "${BFF}" ] && BFF="\f"
720*4746Srica
721*4746SricaNL="${CR}\n"
722*4746Srica
723*4746Sricalines=`${TPUT} lines`
724*4746Srica[ -z "${lines}" -o 0 -ge "${lines}" ] && lines=66
725*4746Srica
726*4746Sricacols=`${TPUT} cols`
727*4746Srica[ -z "${cols}" -o 0 -ge "${cols}" ] && cols=132
728*4746Srica
729*4746Srica#####
730*4746Srica#
731*4746Srica# Basic initialization. The ``else'' clause is equivalent,
732*4746Srica# but covers cases where old Terminal Information Utilities are present.
733*4746Srica#####
734*4746Srica[ -n "${stty1}" ] && stty ${stty1} 0<&1
735*4746Srica
736*4746Srica#
737*4746Srica# "tput init" will return an "^M" in many cases to "stdout", i.e., printer!
738*4746Srica# This creates problems for some PS printers
739*4746Srica#
740*4746Sricaif [ "${TERM}" = "PS" -o "${TERM}" = "PSR" ]
741*4746Sricathen
742*4746Srica	:
743*4746Sricaelif ${TPUT} init 2>/dev/null
744*4746Sricathen
745*4746Srica	:
746*4746Sricaelse
747*4746Srica	pgm=`${TPUT} iprog`
748*4746Srica	if [ -x "${pgm}" ]
749*4746Srica	then
750*4746Srica		eval ${pgm}
751*4746Srica	fi
752*4746Srica
753*4746Srica	${TPUT} is1
754*4746Srica	${TPUT} is2
755*4746Srica
756*4746Srica	tabset=
757*4746Srica	if [ "8" != "`${TPUT} it`" ]
758*4746Srica	then
759*4746Srica		stty tab3 0<&1 1>/dev/null 2>&1
760*4746Srica
761*4746Srica	elif `${TPUT} ht >/dev/null`
762*4746Srica	then
763*4746Srica		tabset="/usr/lib/tabset/${TERM}"
764*4746Srica		if [ -r ${tabset} ]
765*4746Srica		then
766*4746Srica			cat -s ${tabset}
767*4746Srica		fi
768*4746Srica		stty tab3 0<&1 1>/dev/null 2>&1
769*4746Srica	fi
770*4746Srica
771*4746Srica	file=`${TPUT} if`
772*4746Srica	if [ "${tabset}" != "${file}" -a -r "${file}" ]
773*4746Srica	then
774*4746Srica		cat -s "${file}"
775*4746Srica	fi
776*4746Srica
777*4746Srica	${TPUT} is3
778*4746Srica	echo "${CR}\c"
779*4746Sricafi
780*4746Srica[ -n "${stty2}" ] && stty ${stty2} 0<&1
781*4746Srica
782*4746Srica#####
783*4746Srica#
784*4746Srica# Set the page size and print spacing, but not the character set.
785*4746Srica# We will be doing the character set later (after the header).
786*4746Srica#####
787*4746Sricainternal_lpset "${cpi}" "${lpi}" "${width}" "${length}" ""
788*4746Srica
789*4746Srica#####
790*4746Srica#
791*4746Srica# The banner page (and cancellation page) will
792*4746Srica# use double width characters if they're available.
793*4746Srica#####
794*4746SricaWIDE_CS=`${TPUT} swidm 2>/dev/null` && NORM_CS=`${TPUT} rwidm 2>/dev/null`
795*4746SricaPAD="#####${NL}"
796*4746Srica
797*4746Srica#####
798*4746Srica#
799*4746Srica# Some printers need to have the banner page filtered.
800*4746Srica#####
801*4746Sricacase "${TERM}" in
802*4746Srica
803*4746SricaPS | PSR )
804*4746Srica	banner_filter="/usr/lib/lp/postscript/postprint | /usr/lib/lp/postscript/postio"
805*4746Srica	LPTELL_OPTS="-l"
806*4746Srica	;;
807*4746Srica
808*4746Sricaesac
809*4746Sricaif [ -n "${banner_filter}" ]
810*4746Sricathen
811*4746Srica	banner_filter="| ${banner_filter}"
812*4746Sricafi
813*4746Srica
814*4746Srica#####
815*4746Srica#
816*4746Srica# Now that the printer is ready for printing, we're able
817*4746Srica# to record on paper a cancellation.
818*4746Srica#####
819*4746Srica
820*4746Sricacancel_banner () {
821*4746Srica	echo "${PAD}${PAD}\c"
822*4746Srica	echo "#####${WIDE_CS} Job ${request_id}${NORM_CS}${NL}\c"
823*4746Srica	echo "#####${WIDE_CS} suspended or canceled${NORM_CS}${NL}\c"
824*4746Srica	echo "${PAD}${PAD}\c"
825*4746Srica}
826*4746Srica
827*4746Sricacanceled () {
828*4746Srica	${TPUT} scs 0 2>/dev/null
829*4746Srica	echo "${CR}\c"
830*4746Srica	if [ "${width:-${cols}}" -lt "${MAX_COLS_SMALL_BANNER}" ]
831*4746Srica	then
832*4746Srica		WIDE_CS= NORM_CS=
833*4746Srica	fi
834*4746Srica	cancel_banner
835*4746Srica	if [ -n "${BFF}" ]
836*4746Srica	then
837*4746Srica		echo "${CR}${BFF}\c"
838*4746Srica	fi
839*4746Srica}
840*4746Srica
841*4746Sricatrap 'eval canceled ${banner_filter}; exit_code=0 exit' 15
842*4746Srica
843*4746Srica
844*4746Srica###########
845*4746Srica##
846*4746Srica## Print the banner page
847*4746Srica###########
848*4746Srica
849*4746Srica#####
850*4746Srica#
851*4746Srica# You may want to change the following code to get a custom banner.
852*4746Srica#####
853*4746Srica
854*4746Sricaregular_banner () {
855*4746Srica	echo "${CR}\c"
856*4746Srica	echo "${PAD}${PAD}${PAD}${PAD}${PAD}\c"
857*4746Srica	echo "#####${WIDE_CS}       User: ${user_name}${NORM_CS}${NL}\c"
858*4746Srica	if [ -n "$ALIAS_USERNAME" ]
859*4746Srica	then
860*4746Srica		echo "${PAD}\c"
861*4746Srica		echo "#####${WIDE_CS}      Alias: ${ALIAS_USERNAME}${NORM_CS}${NL}\c"
862*4746Srica	fi
863*4746Srica	if [ -n "${title}" ]
864*4746Srica	then
865*4746Srica		echo "${PAD}\c"
866*4746Srica		echo "#####${WIDE_CS}      Title: ${title}${NORM_CS}${NL}\c"
867*4746Srica	fi
868*4746Srica	echo "${PAD}\c"
869*4746Srica	echo "#####${WIDE_CS}    Printed: `LANG=C date '+%a %H:%M %h %d, %Y'`${NORM_CS}${NL}\c"
870*4746Srica	echo "${PAD}\c"
871*4746Srica	echo "#####${WIDE_CS} Job number: ${request_id}${NORM_CS}${NL}\c"
872*4746Srica	echo "${PAD}${PAD}${PAD}${PAD}${PAD}\c"
873*4746Srica	if [ -n "${BFF}" ]
874*4746Srica	then
875*4746Srica		echo "${CR}${BFF}\c"
876*4746Srica	fi
877*4746Srica}
878*4746Srica
879*4746Sricasmall_banner () {
880*4746Srica	echo "${CR}\c"
881*4746Srica	echo "${PAD}\c"
882*4746Srica	echo "#####  User: ${user_name}${NL}\c"
883*4746Srica	if [ -n "${title}" ]
884*4746Srica	then
885*4746Srica		echo "##### Title: ${title}${NL}\c"
886*4746Srica	fi
887*4746Srica	echo "#####  Date: `LANG=C date '+%a %H:%M %h %d, %Y'`${NL}\c"
888*4746Srica	echo "#####   Job: ${request_id}${NL}\c"
889*4746Srica	echo "${PAD}\c"
890*4746Srica	if [ -n "${BFF}" ]
891*4746Srica	then
892*4746Srica		echo "${CR}${BFF}\c"
893*4746Srica	fi
894*4746Srica}
895*4746Srica
896*4746Sricaif [ "${width:-${cols}}" -lt "${MAX_COLS_SMALL_BANNER}" ]
897*4746Sricathen
898*4746Srica	banner=small_banner
899*4746Sricaelse
900*4746Srica	banner=regular_banner
901*4746Sricafi
902*4746Srica
903*4746Srica## Skip this for PS/PSR in TSOL, since lp.tsol_separator handles the banners
904*4746Sricaif [ "no" = "${nobanner}" -a "${TERM}" != "PSR" -a "${TERM}" != "PS" ]
905*4746Sricathen
906*4746Srica	( eval "${banner} ${banner_filter}" 2>&1 1>&3 ) \
907*4746Srica		| ${LPTELL} ${LPTELL_OPTS} ${printer}
908*4746Sricafi
909*4746Srica
910*4746Srica###########
911*4746Srica##
912*4746Srica## Surround the job by PostScript code to produce banner
913*4746Srica## and trailerpages and page headers and footers.
914*4746Srica##
915*4746Srica###########
916*4746Srica
917*4746SricaBANNER_EXIT_CODE=${TMPPREFIX}.banner.exit_code
918*4746Sricaecho 0 > ${BANNER_EXIT_CODE}
919*4746SricaTSOLSEPARATOR_LOG=${TMPPREFIX}.banner.errmsg
920*4746Srica
921*4746Sricatsol_bannerize () {
922*4746Srica	TSOLSEPARATOR_OPTS="-e ${TSOLSEPARATOR_LOG}"
923*4746Srica
924*4746Srica	if [ "yes" = "${nolabels}" ]
925*4746Srica	then
926*4746Srica		TSOLSEPARATOR_OPTS="${TSOLSEPARATOR_OPTS} -l"
927*4746Srica	fi
928*4746Srica
929*4746Srica	if [ "yes" = "${nobanner}" ]
930*4746Srica	then
931*4746Srica		TSOLSEPARATOR_OPTS="${TSOLSEPARATOR_OPTS} -t /dev/null -b /dev/null"
932*4746Srica	fi
933*4746Srica
934*4746Srica	if [ "${TERM}" = "PSR" ]
935*4746Srica	then
936*4746Srica		TSOLSEPARATOR_OPTS="${TSOLSEPARATOR_OPTS} -r"
937*4746Srica	fi
938*4746Srica
939*4746Srica	# Get rid of the #, TAB and NL characters in the title
940*4746Srica	tsol_title=`echo $title`
941*4746Srica	tsol_title=`echo $tsol_title | sed 's/#//g'`
942*4746Srica
943*4746Srica	LC_TIME=C ${LPTSOLSEPARATOR} ${TSOLSEPARATOR_OPTS} "${printer}" \
944*4746Srica	    "${request_id}" "${user_name}" "${tsol_title}" "${file}"
945*4746Srica	echo $? > ${BANNER_EXIT_CODE}
946*4746Srica	true
947*4746Srica}
948*4746Srica
949*4746Sricabannerize=tsol_bannerize
950*4746Srica
951*4746Sricaif [ "yes" = "${nobanner}" -a  "yes" = "${nolabels}" ]
952*4746Sricathen
953*4746Srica	bannerize=cat
954*4746Sricafi
955*4746Srica
956*4746Sricaif [ "${TERM}" != "PSR" -a "${TERM}" != "PS" ]
957*4746Sricathen
958*4746Srica	bannerize=cat
959*4746Sricafi
960*4746Srica
961*4746Srica
962*4746Srica###########
963*4746Srica##
964*4746Srica## Initialize the physical printer (Part II)
965*4746Srica## Here we select the character set.
966*4746Srica## One could argue that this should be done before the banner is printed,
967*4746Srica## but we don't, to keep the banner page looking consistent for the
968*4746Srica## operator. You can move this code before the banner code if you
969*4746Srica## disagree. If you do, combine it with the other call to "internal_lpset"
970*4746Srica## to do everything in one shot.
971*4746Srica###########
972*4746Sricainternal_lpset "" "" "" "" "${CHARSET}"
973*4746Srica
974*4746Srica###########
975*4746Srica##
976*4746Srica## Print some copies of the file(s)
977*4746Srica###########
978*4746Srica
979*4746Srica#####
980*4746Srica#
981*4746Srica# The protocol between the interface program and the Spooler
982*4746Srica# is fairly simple:
983*4746Srica#
984*4746Srica#	All standard error output is assumed to indicate a
985*4746Srica#	fault WITH THE REQUEST. The output is mailed to the
986*4746Srica#	user who submitted the print request and the print
987*4746Srica#	request is finished.
988*4746Srica#
989*4746Srica#	If the interface program sets a zero exit code,
990*4746Srica#	it is assumed that the file printed correctly.
991*4746Srica#	If the interface program sets a non-zero exit code
992*4746Srica#	less than 128, it is assumed that the file did not
993*4746Srica#	print correctly, and the user will be notified.
994*4746Srica#	In either case the print request is finished.
995*4746Srica#
996*4746Srica#	If the interface program sets an exit code greater
997*4746Srica#	than 128, it is assumed that the file did not print
998*4746Srica#	because of a printer fault. If an alert isn't already
999*4746Srica#	active (see below) one will be activated. (Exit code
1000*4746Srica#	128 should not be used at all. The shell, which executes
1001*4746Srica#	this program, turns SIGTERM, used to kill this program
1002*4746Srica#	for a cancellation or disabling, into exit 128. The
1003*4746Srica#	Spooler thus interpretes 128 as SIGTERM.)
1004*4746Srica#
1005*4746Srica#	A message sent to the standard input of the ${LPTELL}
1006*4746Srica#	program is assumed to describe a fault WITH THE PRINTER.
1007*4746Srica#	The output is used in an alert (if alerts are defined).
1008*4746Srica#	If the fault recovery is "wait" or "begin", the printer
1009*4746Srica#	is disabled (killing the interface program if need be),
1010*4746Srica#	and the print request is left on the queue.
1011*4746Srica#	If the fault recovery is "continue", the interface program
1012*4746Srica#	is allowed to wait for the printer fault to be cleared so
1013*4746Srica#	it can resume printing.
1014*4746Srica#
1015*4746Srica# This interface program relies on filters to detect printer faults.
1016*4746Srica# In absence of a filter provided by the customer, it uses a simple
1017*4746Srica# filter (${LPCAT}) to detect the class of faults that cause DCD
1018*4746Srica# (``carrier'') drop. The protocol between the interface program and
1019*4746Srica# the filter:
1020*4746Srica#
1021*4746Srica#	The filter should exit with zero if printing was
1022*4746Srica#	successful and non-zero if printing failed because
1023*4746Srica#	of a printer fault. This interface program turns a
1024*4746Srica#	non-zero exit of the filter into an "exit 129" from
1025*4746Srica#	itself, thus telling the Spooler that a printer fault
1026*4746Srica#	(still) exists.
1027*4746Srica#
1028*4746Srica#	The filter should report printer faults via a message
1029*4746Srica#	to its standard error. This interface program takes all
1030*4746Srica#	standard error output from the filter and feeds it as
1031*4746Srica#	standard input to the ${LPTELL} program.
1032*4746Srica#
1033*4746Srica#	The filter should wait for a printer fault to clear,
1034*4746Srica#	and should resume printing when the fault clears.
1035*4746Srica#	Preferably it should resume at the top of the page
1036*4746Srica#	that was being printed when the fault occurred.
1037*4746Srica#	If it waits and finishes printing, it should exit
1038*4746Srica#	with a 0 exit code. If it can't wait, it should exit
1039*4746Srica#	with a non-zero exit code.
1040*4746Srica#
1041*4746Srica#	The interface program expects that ANY message on the
1042*4746Srica#	standard error from the filter indicates a printer fault.
1043*4746Srica#	Therefore, a filter should not put user (input) error
1044*4746Srica#	messages on the standard error, but on the standard output
1045*4746Srica#	(where the user can read them when he or she examines
1046*4746Srica#	the print-out).
1047*4746Srica#
1048*4746Srica#####
1049*4746Srica
1050*4746Sricabadfileyet=
1051*4746Sricai=1
1052*4746Sricawhile [ $i -le $copies ]
1053*4746Sricado
1054*4746Srica	for file in ${files}
1055*4746Srica	do
1056*4746Srica		if [ -r "${file}" ]
1057*4746Srica		then
1058*4746Srica			#####
1059*4746Srica			#
1060*4746Srica			# Here's where we set up the $LPTELL program to
1061*4746Srica			# capture fault messages, and...
1062*4746Srica			#
1063*4746Srica			# Here's where we print the file.
1064*4746Srica			#
1065*4746Srica			# We set up a pipeline to $LPTELL, but play a trick
1066*4746Srica			# to get the filter's standard ERROR piped instead of
1067*4746Srica			# its standard OUTPUT: Divert the standard error (#2) to
1068*4746Srica			# the standard output (#1) IN THE PIPELINE. The shell
1069*4746Srica			# will have changed #1 to be the pipe, not the
1070*4746Srica			# printer, so diverting #2 connects it to the pipe.
1071*4746Srica			# We then change the filter's #1 to a copy of the real
1072*4746Srica			# standard output (the printer port) made earlier,
1073*4746Srica			# so that is connected back to the printer again.
1074*4746Srica			#
1075*4746Srica			# We do all this inside a parenthesized expression
1076*4746Srica			# so that we can get the exit code; this is necessary
1077*4746Srica			# because the exit code of a pipeline is the exit
1078*4746Srica			# code of the right-most command, which isn't the
1079*4746Srica			# filter.
1080*4746Srica			#
1081*4746Srica			# These two tricks could be avoided by using a named
1082*4746Srica			# pipe to connect the standard error to $LPTELL. In
1083*4746Srica			# fact an early prototype of this script did just
1084*4746Srica			# that; however, the named pipe introduced a timing
1085*4746Srica			# problem. The processes that open a named pipe hang
1086*4746Srica			# until both ends of the pipe are opened. Cancelling
1087*4746Srica			# a request or disabling the printer often killed one
1088*4746Srica			# of the processes, causing the other process to hang
1089*4746Srica			# forever waiting for the other end of the pipe to
1090*4746Srica			# be opened.
1091*4746Srica			#####
1092*4746Srica			EXIT_CODE=${TMPPREFIX}e
1093*4746Srica			trap '' 1	# Let the filter handle a hangup
1094*4746Srica			trap '' 2 3	# and interrupts
1095*4746Srica			(
1096*4746Srica				#####
1097*4746Srica				# Put the 0<${file} before the "eval" to keep
1098*4746Srica				# clever users from giving a file name that
1099*4746Srica				# evaluates as something to execute.
1100*4746Srica				#####
1101*4746Srica				0<${file} $bannerize | eval ${FILTER} 2>&1 1>&3
1102*4746Srica				echo $? >${EXIT_CODE}
1103*4746Srica			) | ${LPTELL} ${LPTELL_OPTS} ${printer}
1104*4746Srica
1105*4746Srica			# if lp.tsol_separator had an error, send its logged
1106*4746Srica			# error message to LPTELL.
1107*4746Srica			banner_exit_code=`cat ${BANNER_EXIT_CODE}`
1108*4746Srica			if [ -n "${banner_exit_code}" -a \
1109*4746Srica				0 -ne "${banner_exit_code}" -a \
1110*4746Srica				 -n "${LPTELL}" -a \
1111*4746Srica				-r "${TSOLSEPARATOR_LOG}" ]
1112*4746Srica			then
1113*4746Srica				cat ${TSOLSEPARATOR_LOG} | ${LPTELL} ${printer}
1114*4746Srica				echo 77 > ${EXIT_CODE}
1115*4746Srica			fi
1116*4746Srica
1117*4746Srica			trap 'catch_hangup; exit_code=129 exit 129' 1
1118*4746Srica			trap 'catch_interrupt; exit_code=129 exit 129' 2 3
1119*4746Srica			exit_code=`cat ${EXIT_CODE}`
1120*4746Srica
1121*4746Srica			if [ -n "${exit_code}" -a 0 -ne "${exit_code}" ]
1122*4746Srica			then
1123*4746Srica				trap '' 15  # Avoid dying from disable
1124*4746Srica				sleep 4	    # Give $LPTELL a chance to tell
1125*4746Srica				exit ${exit_code}
1126*4746Srica			fi
1127*4746Srica
1128*4746Srica			if [ -n "${FF}" -a "no" = "${nofilebreak}" ]
1129*4746Srica			then
1130*4746Srica				echo "${CR}${FF}\c"
1131*4746Srica			fi
1132*4746Srica
1133*4746Srica		else
1134*4746Srica
1135*4746Srica			#####
1136*4746Srica			#
1137*4746Srica			# Don't complain about not being able to read
1138*4746Srica			# a file on second and subsequent copies, unless
1139*4746Srica			# we've not complained yet. This removes repeated
1140*4746Srica			# messages about the same file yet reduces the
1141*4746Srica			# chance that the user can remove a file and not
1142*4746Srica			# know that we had trouble finding it.
1143*4746Srica			#####
1144*4746Srica			if [ "${i}" -le 1 -o -z "${badfileyet}" ]
1145*4746Srica			then
1146*4746Srica				errmsg WARNING ${E_IP_BADFILE} \
1147*4746Srica					"cannot read file \"${file}\"" \
1148*4746Srica					"see if the file still exists and is readable,
1149*4746Srica		or consult your system administrator;
1150*4746Srica		printing continues"
1151*4746Srica				badfileyet=yes
1152*4746Srica			fi
1153*4746Srica
1154*4746Srica		fi
1155*4746Srica
1156*4746Srica	done
1157*4746Srica	i=`expr $i + 1`
1158*4746Srica
1159*4746Sricadone
1160*4746Srica
1161*4746Srica# Skip this for TSOL, since lp.tsol_separator handles the banners
1162*4746Srica#
1163*4746Srica# if [ "no" = "${nobanner}" -a "${TERM}" = "PSR" ]
1164*4746Srica# then
1165*4746Srica# 	( eval "${banner} ${banner_filter}" 2>&1 1>&3 ) \
1166*4746Srica# 		| ${LPTELL} ${LPTELL_OPTS} ${printer}
1167*4746Srica# fi
1168*4746Srica
1169*4746Sricaif [ -n "${exit_code}" -a 0 -ne "${exit_code}" ]
1170*4746Sricathen
1171*4746Srica	exit ${exit_code}
1172*4746Sricafi
1173*4746Srica
1174*4746Srica#####
1175*4746Srica#
1176*4746Srica# Always ensure the complete job ends with a ``formfeed'', to
1177*4746Srica# let the next job start on a new page. (If someone wants to
1178*4746Srica# concatenate files, they can give them in one job.)
1179*4746Srica# So, if we haven't been putting out a ``formfeed'' between files,
1180*4746Srica# it means we haven't followed the last file with a formfeed,
1181*4746Srica# so we do it here.
1182*4746Srica#####
1183*4746Sricaif [ -n "${FF}" -a "yes" = "${nofilebreak}" ]
1184*4746Sricathen
1185*4746Srica	echo "${CR}${FF}\c"
1186*4746Sricafi
1187*4746Srica
1188*4746Srica${DRAIN}
1189*4746Srica
1190*4746Sricaexit_code=0 exit 0
1191