Mercurial > illumos > onarm
comparison usr/src/cmd/lp/model/netstandard @ 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 # Copyright 2005 Sun Microsystems, Inc. All rights reserved. | |
3 # Use is subject to license terms. | |
4 # | |
5 # CDDL HEADER START | |
6 # | |
7 # The contents of this file are subject to the terms of the | |
8 # Common Development and Distribution License, Version 1.0 only | |
9 # (the "License"). You may not use this file except in compliance | |
10 # with the License. | |
11 # | |
12 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | |
13 # or http://www.opensolaris.org/os/licensing. | |
14 # See the License for the specific language governing permissions | |
15 # and limitations under the License. | |
16 # | |
17 # When distributing Covered Code, include this CDDL HEADER in each | |
18 # file and include the License file at usr/src/OPENSOLARIS.LICENSE. | |
19 # If applicable, add the following below this CDDL HEADER, with the | |
20 # fields enclosed by brackets "[]" replaced with your own identifying | |
21 # information: Portions Copyright [yyyy] [name of copyright owner] | |
22 # | |
23 # CDDL HEADER END | |
24 # | |
25 #pragma ident "@(#)netstandard 1.25 05/06/08 SMI" | |
26 ########### | |
27 ## | |
28 ## Network Standard printer interface program. | |
29 ## | |
30 ########### | |
31 | |
32 ##### | |
33 # We can't do much except exit if spooler/scheduler | |
34 # cancels us. | |
35 ##### | |
36 trap 'eval exit_clean 15' 15 | |
37 | |
38 #### | |
39 # | |
40 # Send standard error messages to /dev/null rather than to | |
41 # the spooler. Avoids "Terminated" messages that shell puts out | |
42 # when gets SIGTERM. Save standard error so it can be used | |
43 # when we need it | |
44 #### | |
45 exec 5>&2 2>/dev/null 3>&1 | |
46 | |
47 #### | |
48 # set some global variables | |
49 #### | |
50 | |
51 : ${LPTMPDIR:=/tmp} | |
52 : ${SPOOLDIR:=/usr/spool/lp} | |
53 : ${LOCALPATH:=${SPOOLDIR}/bin} | |
54 PATH="/bin:/usr/bin:${LOCALPATH}" | |
55 exit_code=0 | |
56 | |
57 | |
58 # ${LPTELL} is the name of a program that will send its | |
59 # standard input to the Spooler. It is used to forward | |
60 # the description of a printer fault to the Spooler, | |
61 # which uses it in an alert to the administrator. | |
62 ##### | |
63 if [ ! -x "${LPTELL:=${LOCALPATH}/lp.tell}" ] | |
64 then | |
65 fake_lptell () { | |
66 header="no" | |
67 while read line | |
68 do | |
69 if [ "no" = "${header}" ] | |
70 then | |
71 errmsg ERROR ${E_IP_UNKNOWN} \ | |
72 "unknown printer/interface failure" \ | |
73 "consult your system administrator; | |
74 reasons for failure (if any) follow:" | |
75 header=yes | |
76 fi | |
77 echo "${line}" >&2 | |
78 done | |
79 return 1 | |
80 } | |
81 LPTELL=fake_lptell | |
82 fi | |
83 | |
84 ##### | |
85 # Error message formatter: | |
86 # | |
87 # Invoke as | |
88 # | |
89 # errmsg severity message-number problem help | |
90 # | |
91 # where severity is "ERROR" or "WARNING", message-number is | |
92 # a unique identifier, problem is a short description of the | |
93 # problem, and help is a short suggestion for fixing the problem. | |
94 ##### | |
95 | |
96 LP_ERR_LABEL="UX:lp" | |
97 E_IP_ARGS=1 | |
98 E_IP_OPTS=2 | |
99 #E_IP_FILTER=3 | |
100 E_IP_UNKNOWN=5 | |
101 E_IP_BADFILE=6 | |
102 E_IP_ERRORS=12 # (in slow.filter) | |
103 | |
104 errmsg () { | |
105 | |
106 case $1 in | |
107 ERROR ) | |
108 sev=" ERROR"; | |
109 ;; | |
110 WARNING ) | |
111 sev="WARNING"; | |
112 ;; | |
113 esac | |
114 | |
115 echo "${LP_ERR_LABEL}:$2 ${sev}: $3 | |
116 TO FIX: $4" >&5 | |
117 } | |
118 | |
119 ########### | |
120 ## | |
121 ## Check arguments | |
122 ########### | |
123 | |
124 parse () { | |
125 echo "`expr \"$1\" : \"^[^=]*=\(.*\)\"`" | |
126 } | |
127 | |
128 ##### | |
129 ## | |
130 ## Error Cleanup and Exit | |
131 ## | |
132 ##### | |
133 | |
134 exit_clean() | |
135 { | |
136 | |
137 if [ -f "${LPTMPDIR}/pr_eexit_code.$$" ] | |
138 then | |
139 /bin/rm ${LPTMPDIR}/pr_eexit_code.$$ | |
140 fi | |
141 | |
142 if [ -f "${LPTMPDIR}/small_banner.$$" ] | |
143 then | |
144 /bin/rm ${LPTMPDIR}/small_banner.$$ | |
145 fi | |
146 | |
147 if [ -f "${tmpfile}" ] | |
148 then | |
149 /bin/rm "${tmpfile}" | |
150 fi | |
151 | |
152 exit $1 | |
153 } | |
154 | |
155 ##### | |
156 # | |
157 # This program is invoked as | |
158 # | |
159 # ${SPOOLDIR}/.../printer request-id user title copies options files... | |
160 # | |
161 # The first three arguments are simply reprinted on the banner page, | |
162 # the fourth (copies) is used to control the number of copies to print, | |
163 # the fifth (options) is a blank separated list (in a single argument) | |
164 # of user or Spooler supplied options (without the -o prefix), | |
165 # and the last arguments are the files to print. | |
166 ##### | |
167 | |
168 if [ $# -lt 5 ] | |
169 then | |
170 | |
171 errmsg ERROR ${E_IP_ARGS} \ | |
172 "wrong number of arguments to interface program" \ | |
173 "consult your system administrator" | |
174 exit 1 | |
175 fi | |
176 | |
177 printer=`basename $0` | |
178 request_id=$1 | |
179 user_name=$2 | |
180 title=$3 | |
181 copies=$4 | |
182 option_list=$5 | |
183 | |
184 shift 5 | |
185 files="$*" | |
186 | |
187 | |
188 # | |
189 # debug sent to file if defined in /etc/syslog.conf | |
190 # syslog.conf entry: | |
191 # lpr.debug /path/filename | |
192 # | |
193 logger -p lpr.debug -t "netstandard: ${request_id}" " " | |
194 logger -p lpr.debug -t "netstandard: ${request_id}" "INPUT" | |
195 logger -p lpr.debug -t "netstandard: ${request_id}" " printer : ${printer}" | |
196 logger -p lpr.debug -t "netstandard: ${request_id}" " request_id : ${request_id}" | |
197 logger -p lpr.debug -t "netstandard: ${request_id}" " user_name : ${user_name}" | |
198 logger -p lpr.debug -t "netstandard: ${request_id}" " title : ${title}" | |
199 logger -p lpr.debug -t "netstandard: ${request_id}" " copies : ${copies}" | |
200 logger -p lpr.debug -t "netstandard: ${request_id}" " option_list : ${option_list}" | |
201 logger -p lpr.debug -t "netstandard: ${request_id}" " files : ${files}" | |
202 logger -p lpr.debug -t "netstandard: ${request_id}" " spooler_key ${SPOOLER_KEY}" | |
203 | |
204 #### | |
205 # default: do print a banner | |
206 #### | |
207 nobanner=no | |
208 nofilebreak="no" | |
209 inlist= | |
210 data_file_flag= | |
211 | |
212 for i in ${option_list} | |
213 do | |
214 case "${inlist}${i}" in | |
215 | |
216 nobanner ) | |
217 nobanner="yes" | |
218 ;; | |
219 | |
220 nofilebreak ) | |
221 nofilebreak="yes" | |
222 ;; | |
223 | |
224 ##### | |
225 # | |
226 # If you want to add simple options (e.g. -o simple) | |
227 # identify them here. | |
228 ##### | |
229 # simple ) | |
230 # simple="yes" | |
231 # ;; | |
232 | |
233 cpi=pica ) | |
234 cpi=10 | |
235 ;; | |
236 cpi=elite ) | |
237 cpi=12 | |
238 ;; | |
239 cpi=* ) | |
240 cpi=`parse ${i}` | |
241 ;; | |
242 | |
243 lpi=* ) | |
244 lpi=`parse ${i}` | |
245 ;; | |
246 | |
247 length=* ) | |
248 length=`parse ${i}` | |
249 ;; | |
250 | |
251 width=* ) | |
252 width=`parse ${i}` | |
253 ;; | |
254 dest=* ) | |
255 dest="-d `parse ${i}`" | |
256 ;; | |
257 | |
258 protocol=* ) | |
259 protocol="-P `parse ${i}`" | |
260 ;; | |
261 bsdctrl=* ) | |
262 controlfile="-c `parse ${i}`" | |
263 ;; | |
264 timeout=* ) | |
265 timeout="-t `parse ${i}`" | |
266 ;; | |
267 | |
268 data-file-type=* ) | |
269 data_file_flag="-f `parse ${i}`" | |
270 ;; | |
271 | |
272 ##### | |
273 # | |
274 # If you want to add simple-value options (e.g. -o value=a) | |
275 # identify them here. | |
276 ##### | |
277 # value=* ) | |
278 # value=`parse ${i}` | |
279 # ;; | |
280 | |
281 ##### | |
282 # | |
283 # If you want to add options that, | |
284 # take a list (e.g. -o lopt='a b c'), identif | |
285 # them here and below (look for LOPT). | |
286 ##### | |
287 | |
288 # flist=* | lpd=* | options=* ) | |
289 flist=* | lpd=* ) | |
290 #LOPT stty=* | flist=* | lpd=* | lopt=* ) | |
291 | |
292 inlist=`expr "${inlist}${i}" : "^\([^=]*=\)"` | |
293 case "${i}" in | |
294 ${inlist}\'*\' ) | |
295 item=`expr "${i}" : "^[^=]*='*\(.*\)'\$"` | |
296 ;; | |
297 ${inlist}\' ) | |
298 continue | |
299 ;; | |
300 ${inlist}\'* ) | |
301 item=`expr "${i}" : "^[^=]*='*\(.*\)\$"` | |
302 ;; | |
303 ${inlist}* ) | |
304 item=`expr "${i}" : "^[^=]*=\(.*\)\$"` | |
305 ;; | |
306 *\' ) | |
307 item=`expr "${i}" : "^\(.*\)'\$"` | |
308 ;; | |
309 * ) | |
310 item="${i}" | |
311 ;; | |
312 esac | |
313 | |
314 ##### | |
315 # | |
316 # We don't dare use "eval" because a clever user could | |
317 # put something in an option value that we'd end up | |
318 # exec'ing. | |
319 ##### | |
320 case "${inlist}" in | |
321 flist= ) | |
322 flist="${flist} ${item}" | |
323 ;; | |
324 lpd= ) | |
325 lpd="${lpd} ${item}" | |
326 ;; | |
327 #LOPT lopt= ) | |
328 #LOPT lopt="${lopt} ${item}" | |
329 #LOPT ;; | |
330 # options= ) | |
331 # options="${options} ${item}" | |
332 # ;; | |
333 esac | |
334 | |
335 case "${i}" in | |
336 ${inlist}\'*\' ) | |
337 inlist= | |
338 ;; | |
339 ${inlist}\'* ) | |
340 ;; | |
341 *\' | ${inlist}* ) | |
342 inlist= | |
343 ;; | |
344 esac | |
345 ;; | |
346 | |
347 * ) | |
348 errmsg WARNING ${E_IP_OPTS} \ | |
349 "unrecognized \"-o ${i}\" option" \ | |
350 "check the option, resubmit if necessary | |
351 printing continues" | |
352 ;; | |
353 esac | |
354 done | |
355 | |
356 logger -p lpr.debug -t "netstandard: ${request_id}" "term : ${TERM}" | |
357 | |
358 if [ -z "${FILTER}" ] | |
359 then | |
360 ##### | |
361 # | |
362 # If no filter is being used, we use netpr to push the | |
363 # file to the printer. | |
364 # (QUOTES ARE IMPORTANT!) | |
365 ##### | |
366 | |
367 case "$TERM" in | |
368 PS ) | |
369 # make the "postscript" printers use netpr | |
370 FILTER= | |
371 ;; | |
372 PSR ) | |
373 # make the "reverse postscript" printers reverse the | |
374 # output and the use postio to talk to the printer | |
375 #FILTER="/usr/lib/lp/postscript/postreverse " | |
376 #FILTER= | |
377 FILTER="/usr/lib/lp/postscript/postreverse " | |
378 ;; | |
379 * ) | |
380 # We don't know the type, so just assume that the | |
381 # input and output are the same. Use netpr. | |
382 #FILTER=/bin/cat | |
383 FILTER= | |
384 ;; | |
385 esac | |
386 fi | |
387 | |
388 #### | |
389 # sets default value for ordering of data and control files with | |
390 # bsd protocol. Default: data files first. Administrator | |
391 # may set to control file first with lpadmin -o bsdctrl=first | |
392 #### | |
393 | |
394 banner_flag="" | |
395 case "${nobanner}" in | |
396 yes ) | |
397 banner_flag="-b" | |
398 ;; | |
399 esac | |
400 | |
401 NETPR="/usr/lib/lp/bin/netpr ${banner_flag} ${data_file_flag} \ | |
402 -I ${request_id} -U ${user_name} \ | |
403 -p ${printer} ${dest} -T \"${title}\" \ | |
404 ${timeout} ${protocol} ${controlfile} " | |
405 LPTELL_OPTS="-l" # netpr sends LaserWriter style messages back | |
406 | |
407 logger -p lpr.debug -t "netstandard: ${request_id}" "NETPR= ${NETPR}" | |
408 logger -p lpr.debug -t "netstandard: ${request_id}" "filter : ${FILTER}" | |
409 | |
410 node=`uname -n` | |
411 pid=$$ | |
412 tmpfile=${LPTMPDIR}/${node}.${pid} | |
413 | |
414 logger -p lpr.debug -t "netstandard: ${request_id}" "tmpfile : ${tmpfile}" | |
415 | |
416 ##### | |
417 # | |
418 # Set up filter for banner page | |
419 # | |
420 ##### | |
421 banner_filter= | |
422 case "${TERM}" in | |
423 PS | PSR ) | |
424 banner_filter=" | /usr/lib/lp/postscript/postprint " | |
425 LPTELL_OPTS="-l" | |
426 ;; | |
427 esac | |
428 | |
429 ##### | |
430 # | |
431 # Build temporary file that is the banner page | |
432 # | |
433 ##### | |
434 PAD="#####${NL}" | |
435 CR="\r" | |
436 NL="${CR}\n" | |
437 FF= | |
438 | |
439 small_banner() { | |
440 echo "${CR}\c" | |
441 echo "${PAD}\c" | |
442 echo "##### User: ${user_name}${NL}\c" | |
443 if [ -n "${title}" ] | |
444 then | |
445 echo "##### Title: ${title}${NL}\c" | |
446 fi | |
447 echo "##### Date: `LANG=C date '+%a %H:%M %h %d, %Y'`${NL}\c" | |
448 echo "##### Job: ${request_id}${NL}\c" | |
449 echo "${PAD}\c" | |
450 if [ -n "${FF}" ] | |
451 then | |
452 echo "${CR}${FF}\c" | |
453 fi | |
454 } | |
455 | |
456 ##### | |
457 # | |
458 # Doing small banner as we don't know what printer is out there | |
459 # | |
460 ##### | |
461 banner=small_banner | |
462 | |
463 if [ "no" = "${nobanner}" ] | |
464 then | |
465 eval "${banner} ${banner_filter}" 2>&1 1>${LPTMPDIR}/small_banner.$$ | |
466 fi | |
467 | |
468 ##### | |
469 # | |
470 # Print banner page before job unless PSR | |
471 # | |
472 ##### | |
473 | |
474 | |
475 if [ "no" = "${nobanner}" -a "${TERM}" != "PSR" ] | |
476 then | |
477 ( | |
478 eval ${NETPR} ${LPTMPDIR}/small_banner.$$ 2>&1 | |
479 echo $? > ${LPTMPDIR}/pr_eexit_code.$$ | |
480 ) | ${LPTELL} ${LPTELL_OPTS} ${printer} | |
481 | |
482 exit_code=`cat ${LPTMPDIR}/pr_eexit_code.$$` | |
483 logger -p lpr.debug -t "netstandard: ${request_id}" \ | |
484 "banner page exit code : ${exit_code}" | |
485 | |
486 fi | |
487 | |
488 i=1 | |
489 while [ $i -le $copies ] | |
490 do | |
491 for file in ${files} | |
492 do | |
493 if [ -r "${file}" ] | |
494 then | |
495 | |
496 if [ ! -z "${FILTER}" ] | |
497 then | |
498 ( | |
499 ##### | |
500 # There is a filter, use it | |
501 # | |
502 # Put 0<${file} before the "eval" to keep | |
503 # clever users from giving a file name that | |
504 # evaluates as something to execute. | |
505 # Redirect stderr to stdout so LPTELL will | |
506 # get error messages from pipe. | |
507 ##### | |
508 | |
509 0<${file} eval ${FILTER} 2>&1 1>${tmpfile} | |
510 echo $? > ${LPTMPDIR}/pr_eexit_code.$$ | |
511 ) | ${LPTELL} ${LPTELL_OPTS} ${printer} | |
512 | |
513 exit_code=`cat ${LPTMPDIR}/pr_eexit_code.$$` | |
514 logger -p lpr.debug -t "netstandard: ${request_id}" \ | |
515 "filter exit_code : ${exit_code}" | |
516 | |
517 if [ -n "${exit_code}" ] | |
518 then | |
519 if [ "${exit_code}" -eq 0 ] | |
520 then | |
521 printfile=${tmpfile} | |
522 else | |
523 #### | |
524 # The filter did not succeed, so don't try to print | |
525 #### | |
526 printfile= | |
527 fi | |
528 fi | |
529 | |
530 else | |
531 printfile=${file} | |
532 fi | |
533 | |
534 logger -p lpr.debug -t "netstandard: ${request_id}" \ | |
535 "printfile : ${printfile}" | |
536 | |
537 ##### | |
538 # Print the file | |
539 ##### | |
540 | |
541 if [ -r "${printfile}" ] | |
542 then | |
543 ( | |
544 eval ${NETPR} ${printfile} 2>&1 | |
545 echo $? > ${LPTMPDIR}/pr_eexit_code.$$ | |
546 ) | ${LPTELL} ${LPTELL_OPTS} ${printer} | |
547 | |
548 exit_code=`cat ${LPTMPDIR}/pr_eexit_code.$$` | |
549 logger -p lpr.debug -t "netstandard: ${request_id}" \ | |
550 "netpr exit_code : ${exit_code}" | |
551 | |
552 if [ -f "${tmpfile}" ] | |
553 then | |
554 /bin/rm "${tmpfile}" | |
555 fi | |
556 | |
557 if [ -n "${exit_code}" ] | |
558 then | |
559 if [ "${exit_code}" -eq 0 ] | |
560 then | |
561 printone=yes | |
562 else | |
563 if [ "${exit_code}" -lt 128 ] | |
564 then | |
565 noprint=yes | |
566 else | |
567 retry=yes | |
568 fi | |
569 fi | |
570 fi | |
571 | |
572 | |
573 else | |
574 | |
575 errmsg WARNING ${E_IP_BADFILE} \ | |
576 "cannot read temporary file \"${printfile}\""\ | |
577 "see if file still exists, | |
578 or consult your system administrator; | |
579 printing continues" | |
580 | |
581 fi | |
582 else | |
583 | |
584 ##### | |
585 # | |
586 # Don't complain about not being able to read | |
587 # a file on second and subsequent copies, unless | |
588 # we've not complained yet. This removes repeated | |
589 # messages about the same file yet reduces the | |
590 # chance that the user can remove a file and not | |
591 # know that we had trouble finding it. | |
592 ##### | |
593 | |
594 if [ "${i}" -le 1 -o -z "${badfileyet}" ] | |
595 then | |
596 errmsg WARNING ${E_IP_BADFILE} \ | |
597 "cannot read file \"${file}\"" \ | |
598 "see if the file still exists and is readable, | |
599 or consult your system administrator; | |
600 printing continues" | |
601 badfileyet=yes | |
602 fi | |
603 | |
604 fi | |
605 | |
606 # for file in ${files} | |
607 done | |
608 i=`expr $i + 1` | |
609 done | |
610 | |
611 ##### | |
612 # | |
613 # If printing in reverse order, print the banner page now | |
614 # | |
615 ##### | |
616 | |
617 if [ "no" = "${nobanner}" -a "${TERM}" = "PSR" ] | |
618 then | |
619 ( | |
620 eval ${NETPR} ${LPTMPDIR}/small_banner.$$ 2>&1 | |
621 echo $? > ${LPTMPDIR}/pr_eexit_code.$$ | |
622 ) | ${LPTELL} ${LPTELL_OPTS} ${printer} | |
623 fi | |
624 | |
625 exit_code=`cat ${LPTMPDIR}/pr_eexit_code.$$` | |
626 logger -p lpr.debug -t "netstandard: ${request_id}" \ | |
627 "banner page exit code : ${exit_code}" | |
628 | |
629 if [ -n "${printone}" -a -z "${retry}" -a -z "${noprint}" ] | |
630 then | |
631 exit_code=`expr 0` | |
632 else | |
633 if [ -n "${retry}" -a -z "${printone}" -a -z "${noprint}" ] | |
634 then | |
635 exit_code=`expr 129` | |
636 else | |
637 exit_code=`expr 1` | |
638 fi | |
639 fi | |
640 | |
641 logger -p lpr.debug -t "netstandard: ${request_id}" \ | |
642 "FINAL exit_code : ${exit_code}" | |
643 | |
644 exit_clean ${exit_code} |