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