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