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