Mercurial > illumos > onarm
comparison usr/src/cmd/lp/model/tsol_standard_foomatic @ 0:c9caec207d52 b86
Initial porting based on b86
author | Koji Uno <koji.uno@sun.com> |
---|---|
date | Tue, 02 Jun 2009 18:56:50 +0900 |
parents | |
children | 1a15d5aaf794 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c9caec207d52 |
---|---|
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 |