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.
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.
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]
22 # Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 # Use is subject to license terms.
25 #pragma ident "%Z%%M% %I% %E% SMI"
29 ## Network Standard printer interface program.
34 # We can't do much except exit if spooler/scheduler
37 trap 'eval exit_clean 15' 15
41 # Send standard error messages to /dev/null rather than to
42 # the spooler. Avoids "Terminated" messages that shell puts out
43 # when gets SIGTERM. Save standard error so it can be used
46 exec 5>&2 2>/dev/null 3>&1
49 # set some global variables
53 : ${SPOOLDIR:=/usr/spool/lp}
54 : ${LOCALPATH:=${SPOOLDIR}/bin}
55 PATH="/bin:/usr/bin:${LOCALPATH}"
59 # ${LPTELL} is the name of a program that will send its
60 # standard input to the Spooler. It is used to forward
61 # the description of a printer fault to the Spooler,
62 # which uses it in an alert to the administrator.
64 if [ ! -x "${LPTELL:=${LOCALPATH}/lp.tell}" ]
70 if [ "no" = "${header}" ]
72 errmsg ERROR ${E_IP_UNKNOWN} \
73 "unknown printer/interface failure" \
74 "consult your system administrator;
75 reasons for failure (if any) follow:"
86 # ${LPTSOLSEPARATOR} is the name of a program to put banner and trailer
87 # pages around the job.
89 if [ -x ${LOCALPATH}/lp.tsol_separator ]
91 LPTSOLSEPARATOR=${LOCALPATH}/lp.tsol_separator
93 echo "${LOCALPATH}/lp.tsol_separator not found." >&2
98 # Error message formatter:
102 # errmsg severity message-number problem help
104 # where severity is "ERROR" or "WARNING", message-number is
105 # a unique identifier, problem is a short description of the
106 # problem, and help is a short suggestion for fixing the problem.
115 E_IP_ERRORS=12 # (in slow.filter)
128 echo "${LP_ERR_LABEL}:$2 ${sev}: $3
138 echo "`expr \"$1\" : \"^[^=]*=\(.*\)\"`"
143 ## Error Cleanup and Exit
150 if [ -f "${LPTMPDIR}/pr_eexit_code.$$" ]
152 /bin/rm ${LPTMPDIR}/pr_eexit_code.$$
155 if [ -f "${LPTMPDIR}/small_banner.$$" ]
157 /bin/rm ${LPTMPDIR}/small_banner.$$
160 if [ -f "${LPTMPDIR}/banner.exit_code.$$" ]
162 /bin/rm ${LPTMPDIR}/banner.exit_code.$$
165 if [ -f "${LPTMPDIR}/banner.errmsg.$$" ]
167 /bin/rm ${LPTMPDIR}/banner.errmsg.$$
170 if [ -f "${tmpfile}" ]
180 # This program is invoked as
182 # ${SPOOLDIR}/.../printer request-id user title copies options files...
184 # The first three arguments are simply reprinted on the banner page,
185 # the fourth (copies) is used to control the number of copies to print,
186 # the fifth (options) is a blank separated list (in a single argument)
187 # of user or Spooler supplied options (without the -o prefix),
188 # and the last arguments are the files to print.
194 errmsg ERROR ${E_IP_ARGS} \
195 "wrong number of arguments to interface program" \
196 "consult your system administrator"
200 printer=`basename $0`
212 # debug sent to file if defined in /etc/syslog.conf
214 # lpr.debug /path/filename
216 logger -p lpr.debug -t "tsol_netstandard: ${request_id}" " "
217 logger -p lpr.debug -t "tsol_netstandard: ${request_id}" "INPUT"
218 logger -p lpr.debug -t "tsol_netstandard: ${request_id}" " \
219 printer : ${printer}"
220 logger -p lpr.debug -t "tsol_netstandard: ${request_id}" " \
221 request_id : ${request_id}"
222 logger -p lpr.debug -t "tsol_netstandard: ${request_id}" " \
223 user_name : ${user_name}"
224 logger -p lpr.debug -t "tsol_netstandard: ${request_id}" " title : ${title}"
225 logger -p lpr.debug -t "tsol_netstandard: ${request_id}" " \
227 logger -p lpr.debug -t "tsol_netstandard: ${request_id}" " \
228 option_list : ${option_list}"
229 logger -p lpr.debug -t "tsol_netstandard: ${request_id}" " files : ${files}"
230 logger -p lpr.debug -t "tsol_netstandard: ${request_id}" " \
231 spooler_key ${SPOOLER_KEY}"
234 # default: do print a banner
242 for i in ${option_list}
244 case "${inlist}${i}" in
260 # If you want to add simple options (e.g. -o simple)
261 # identify them here.
289 dest="-d `parse ${i}`"
293 protocol="-P `parse ${i}`"
296 controlfile="-c `parse ${i}`"
299 timeout="-t `parse ${i}`"
303 data_file_flag="-f `parse ${i}`"
308 # If you want to add simple-value options (e.g. -o value=a)
309 # identify them here.
317 # If you want to add options that,
318 # take a list (e.g. -o lopt='a b c'), identif
319 # them here and below (look for LOPT).
322 # flist=* | lpd=* | options=* )
324 #LOPT stty=* | flist=* | lpd=* | lopt=* )
326 inlist=`expr "${inlist}${i}" : "^\([^=]*=\)"`
329 item=`expr "${i}" : "^[^=]*='*\(.*\)'\$"`
335 item=`expr "${i}" : "^[^=]*='*\(.*\)\$"`
338 item=`expr "${i}" : "^[^=]*=\(.*\)\$"`
341 item=`expr "${i}" : "^\(.*\)'\$"`
350 # We don't dare use "eval" because a clever user could
351 # put something in an option value that we'd end up
356 flist="${flist} ${item}"
362 #LOPT lopt="${lopt} ${item}"
365 # options="${options} ${item}"
382 errmsg WARNING ${E_IP_OPTS} \
383 "unrecognized \"-o ${i}\" option" \
384 "check the option, resubmit if necessary
390 logger -p lpr.debug -t "tsol_netstandard: ${request_id}" "term : ${TERM}"
392 if [ -z "${FILTER}" ]
396 # If no filter is being used, we use netpr to push the
397 # file to the printer.
398 # (QUOTES ARE IMPORTANT!)
403 # make the "postscript" printers use cat
404 # (TSOL banners are added during filtering, so we have
405 # to use some filter.)
409 # make the "reverse postscript" printers reverse the
410 # output and the use postio to talk to the printer
411 #FILTER="/usr/lib/lp/postscript/postreverse "
413 FILTER="/usr/lib/lp/postscript/postreverse "
416 # We don't know the type, so just assume that the
417 # input and output are the same. Use netpr.
425 # sets default value for ordering of data and control files with
426 # bsd protocol. Default: data files first. Administrator
427 # may set to control file first with lpadmin -o bsdctrl=first
431 case "${nobanner}" in
437 NETPR="/usr/lib/lp/bin/netpr ${banner_flag} ${data_file_flag} \
438 -I ${request_id} -U ${user_name} \
439 -p ${printer} ${dest} -T \"${title}\" \
440 ${timeout} ${protocol} ${controlfile} "
441 LPTELL_OPTS="-l" # netpr sends LaserWriter style messages back
443 logger -p lpr.debug -t "tsol_netstandard: ${request_id}" "NETPR= ${NETPR}"
444 logger -p lpr.debug -t "tsol_netstandard: ${request_id}" "filter : ${FILTER}"
448 tmpfile=${LPTMPDIR}/${node}.${pid}
450 logger -p lpr.debug -t "tsol_netstandard: ${request_id}" "tmpfile : ${tmpfile}"
454 # Set up filter for banner page
460 banner_filter=" | /usr/lib/lp/postscript/postprint "
467 # Build temporary file that is the banner page
478 echo "##### User: ${user_name}${NL}\c"
481 echo "##### Title: ${title}${NL}\c"
483 echo "##### Date: `LANG=C date '+%a %H:%M %h %d, %Y'`${NL}\c"
484 echo "##### Job: ${request_id}${NL}\c"
494 # Doing small banner as we don't know what printer is out there
499 ## Skip this for PS/PSR printers, since lp.tsol_separator handles the banners
500 if [ "no" = "${nobanner}" -a "${TERM}" != "PSR" -a "${TERM}" != "PS" ]
502 eval "${banner} ${banner_filter}" 2>&1 1>${LPTMPDIR}/small_banner.$$
507 ## Surround the job by PostScript code to produce banner
508 ## and trailerpages and page headers and footers.
512 BANNER_EXIT_CODE=${LPTMPDIR}/banner.exit_code.$$
513 echo 0 > ${BANNER_EXIT_CODE}
514 TSOLSEPARATOR_LOG=${LPTMPDIR}/banner.errmsg.$$
517 TSOLSEPARATOR_OPTS="-e ${TSOLSEPARATOR_LOG}"
519 if [ "yes" = "${nolabels}" ]
521 TSOLSEPARATOR_OPTS="${TSOLSEPARATOR_OPTS} -l"
524 if [ "yes" = "${nobanner}" ]
526 TSOLSEPARATOR_OPTS="${TSOLSEPARATOR_OPTS} -t /dev/null -b /dev/null"
529 if [ "${TERM}" = "PSR" ]
531 TSOLSEPARATOR_OPTS="${TSOLSEPARATOR_OPTS} -r"
534 # Get rid of the #, TAB and NL characters in the title
535 tsol_title=`echo $title`
536 tsol_title=`echo $tsol_title | sed 's/#//g'`
538 logger -p lpr.debug -t "tsol_netstandard: ${request_id}" \
539 "banner command: ${LPTSOLSEPARATOR} ${TSOLSEPARATOR_OPTS} \
540 ${printer} ${request_id} ${user_name} \"${tsol_title}\" ${file}"
541 ${LPTSOLSEPARATOR} ${TSOLSEPARATOR_OPTS} ${printer} \
542 ${request_id} ${user_name} "${tsol_title}" ${file}
544 echo $? > ${BANNER_EXIT_CODE}
548 bannerize=tsol_bannerize
550 if [ "yes" = "${nobanner}" -a "yes" = "${nolabels}" ]
555 if [ "${TERM}" != "PSR" -a "${TERM}" != "PS" ]
562 # Print banner page before job unless PS or PSR.
566 if [ "no" = "${nobanner}" -a "${TERM}" != "PSR" -a "${TERM}" != "PS" ]
569 eval ${NETPR} ${LPTMPDIR}/small_banner.$$ 2>&1
570 echo $? > ${LPTMPDIR}/pr_eexit_code.$$
571 ) | ${LPTELL} ${LPTELL_OPTS} ${printer}
573 exit_code=`cat ${LPTMPDIR}/pr_eexit_code.$$`
574 logger -p lpr.debug -t "tsol_netstandard: ${request_id}" \
575 "banner page exit code : ${exit_code}"
580 while [ $i -le $copies ]
587 if [ ! -z "${FILTER}" ]
591 # There is a filter, use it
593 # Put 0<${file} before the "eval" to keep
594 # clever users from giving a file name that
595 # evaluates as something to execute.
596 # Redirect stderr to stdout so LPTELL will
597 # get error messages from pipe.
599 0<${file} $bannerize | eval ${FILTER} 2>&1 1>${tmpfile}
600 echo $? > ${LPTMPDIR}/pr_eexit_code.$$
601 ) | ${LPTELL} ${LPTELL_OPTS} ${printer}
603 # if lp.tsol_separator had an error, send its logged
604 # error message to LPTELL.
605 banner_exit_code=`cat ${BANNER_EXIT_CODE}`
606 if [ -n "${banner_exit_code}" -a \
607 0 -ne "${banner_exit_code}" -a \
609 -r "${TSOLSEPARATOR_LOG}" ]
611 cat ${TSOLSEPARATOR_LOG} | ${LPTELL} ${printer}
612 echo 77 > ${LPTMPDIR}/pr_eexit_code
615 exit_code=`cat ${LPTMPDIR}/pr_eexit_code.$$`
616 logger -p lpr.debug \
617 -t "tsol_netstandard: ${request_id}" \
618 "filter exit_code : ${exit_code}"
620 if [ -n "${exit_code}" ]
622 if [ "${exit_code}" -eq 0 ]
627 # The filter did not succeed, so don't try to print
637 logger -p lpr.debug \
638 -t "tsol_netstandard: ${request_id}" \
639 "printfile : ${printfile}"
645 if [ -r "${printfile}" ]
648 eval ${NETPR} ${printfile} 2>&1
649 echo $? > ${LPTMPDIR}/pr_eexit_code.$$
650 ) | ${LPTELL} ${LPTELL_OPTS} ${printer}
652 exit_code=`cat ${LPTMPDIR}/pr_eexit_code.$$`
653 logger -p lpr.debug \
654 -t "tsol_netstandard: ${request_id}" \
655 "netpr exit_code : ${exit_code}"
657 # if [ -f "${tmpfile}" ]
659 # /bin/rm "${tmpfile}"
662 if [ -n "${exit_code}" ]
664 if [ "${exit_code}" -eq 0 ]
668 if [ "${exit_code}" -lt 128 ]
680 errmsg WARNING ${E_IP_BADFILE} \
681 "cannot read temporary file \"${printfile}\""\
682 "see if file still exists,
683 or consult your system administrator;
691 # Don't complain about not being able to read
692 # a file on second and subsequent copies, unless
693 # we've not complained yet. This removes repeated
694 # messages about the same file yet reduces the
695 # chance that the user can remove a file and not
696 # know that we had trouble finding it.
699 if [ "${i}" -le 1 -o -z "${badfileyet}" ]
701 errmsg WARNING ${E_IP_BADFILE} \
702 "cannot read file \"${file}\"" \
703 "see if the file still exists and is readable,
704 or consult your system administrator;
711 # for file in ${files}
718 # If printing in reverse order, print the banner page now
719 # Skip this for TSOL, since lp.tsol_separator handles the banners
724 # if [ "no" = "${nobanner}" -a "${TERM}" = "PSR" ]
727 # eval ${NETPR} ${LPTMPDIR}/small_banner.$$ 2>&1
728 # echo $? > ${LPTMPDIR}/pr_eexit_code.$$
729 # ) | ${LPTELL} ${LPTELL_OPTS} ${printer}
732 exit_code=`cat ${LPTMPDIR}/pr_eexit_code.$$`
733 logger -p lpr.debug -t "tsol_netstandard: ${request_id}" \
734 "banner page exit code : ${exit_code}"
736 if [ -n "${printone}" -a -z "${retry}" -a -z "${noprint}" ]
740 if [ -n "${retry}" -a -z "${printone}" -a -z "${noprint}" ]
748 logger -p lpr.debug -t "tsol_netstandard: ${request_id}" \
749 "FINAL exit_code : ${exit_code}"
751 exit_clean ${exit_code}