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}