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