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