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