8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / lp / model / tsol_netstandard_foomatic
blobb23d06a1ba282b525faad68b5670273cef505950
2 # CDDL HEADER START
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]
19 # CDDL HEADER END
22 #ident  "%Z%%M% %I%     %E% SMI"
24 # Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
25 # Use is subject to license terms.
28 ###########
30 ## Network Standard printer interface program for foomatic.
32 ###########
34 #####
35 # We can't do much except exit if spooler/scheduler
36 # cancels us.
37 #####
38 trap 'eval exit_clean 15' 15
40 ####
42 # Send standard error messages to /dev/null rather than to
43 # the spooler. Avoids "Terminated" messages that shell puts out
44 # when gets SIGTERM. Save standard error so it can be used
45 # when we need it
46 ####
47 exec 5>&2 2>/dev/null 3>&1
49 ####
50 # set some global variables
51 ####
53 : ${LPTMPDIR:=/tmp}
54 : ${SPOOLDIR:=/usr/spool/lp}
55 : ${LOCALPATH:=${SPOOLDIR}/bin}
56 PATH="/bin:/usr/bin:${LOCALPATH}"
57 exit_code=0
60 # ${LPTELL} is the name of a program that will send its
61 # standard input to the Spooler. It is used to forward
62 # the description of a printer fault to the Spooler,
63 # which uses it in an alert to the administrator.
64 #####
65 if [ ! -x "${LPTELL:=${LOCALPATH}/lp.tell}" ]
66 then
67         fake_lptell () {
68                 header="no"
69                 while read line
70                 do
71                         if [ "no" = "${header}" ]
72                         then
73                                 errmsg ERROR ${E_IP_UNKNOWN} \
74                 "unknown printer/interface failure" \
75                 "consult your system administrator;
76                 reasons for failure (if any) follow:"
77                                 header=yes
78                         fi
79                         echo "${line}" >&2
80                 done
81                 return 1
82         }
83         LPTELL=fake_lptell
84 fi       
86 #####
87 # ${LPTSOLSEPARATOR} is the name of a program to put banner and trailer
88 # pages around the job.
89 #####
90 if [ -x ${LOCALPATH}/lp.tsol_separator ]
91 then
92         LPTSOLSEPARATOR=${LOCALPATH}/lp.tsol_separator
93 else
94         echo "${LOCALPATH}/lp.tsol_separator not found." >&2
95         exit 1
98 #####
99 # Error message formatter:
101 # Invoke as
103 #       errmsg severity message-number problem help
104 #                                                   
105 # where severity is "ERROR" or "WARNING", message-number is
106 # a unique identifier, problem is a short description of the
107 # problem, and help is a short suggestion for fixing the problem.
108 #####
110 LP_ERR_LABEL="UX:lp"
111 E_IP_ARGS=1
112 E_IP_OPTS=2
113 #E_IP_FILTER=3
114 E_IP_UNKNOWN=5
115 E_IP_BADFILE=6
116 E_IP_ERRORS=12  # (in slow.filter)
118 errmsg () {
120         case $1 in
121         ERROR )
122                 sev="  ERROR";
123                 ;;
124         WARNING )
125                 sev="WARNING";
126                 ;;
127         esac
129         echo "${LP_ERR_LABEL}:$2 ${sev}: $3
130         TO FIX: $4" >&5
131 }                       
133 ###########
135 ## Check arguments
136 ###########
138 parse () {
139         echo "`expr \"$1\" : \"^[^=]*=\(.*\)\"`"
140 }         
142 #####
144 ## Error Cleanup and Exit
146 #####
148 exit_clean()
151         if [ -f "${LPTMPDIR}/pr_eexit_code.$$" ]
152         then
153                 /bin/rm ${LPTMPDIR}/pr_eexit_code.$$
154         fi
156         if [ -f "${LPTMPDIR}/small_banner.$$" ]
157         then
158                 /bin/rm ${LPTMPDIR}/small_banner.$$
159         fi
161         if [ -f "${LPTMPDIR}/banner.exit_code.$$" ]
162         then
163                 /bin/rm ${LPTMPDIR}/banner.exit_code.$$
164         fi
166         if [ -f "${LPTMPDIR}/banner.errmsg.$$" ]
167         then
168                 /bin/rm ${LPTMPDIR}/banner.errmsg.$$
169         fi
171         if [ -f "${tmpfile}" ]
172         then
173                 /bin/rm "${tmpfile}"
174         fi
176         exit $1
179 #####
181 # This program is invoked as
183 # ${SPOOLDIR}/.../printer request-id user title copies options files...
185 # The first three arguments are simply reprinted on the banner page,
186 # the fourth (copies) is used to control the number of copies to print,
187 # the fifth (options) is a blank separated list (in a single argument)
188 # of user or Spooler supplied options (without the -o prefix),
189 # and the last arguments are the files to print.
190 #####
192 if [ $# -lt 5 ]
193 then
195         errmsg ERROR ${E_IP_ARGS} \
196                 "wrong number of arguments to interface program" \
197                 "consult your system administrator"
198         exit 1
199 fi      
201 printer=`basename $0`
202 request_id=$1
203 user_name=$2
204 title=$3
205 copies=$4
206 option_list=$5
208 shift 5
209 files="$*"
213 # debug sent to file if defined in /etc/syslog.conf
214 # syslog.conf entry: 
215 #       lpr.debug       /path/filename
217 logger -p lpr.debug -t "tsol_netstandard_foomatic: ${request_id}" " "
218 logger -p lpr.debug -t "tsol_netstandard_foomatic: ${request_id}" "INPUT"
219 logger -p lpr.debug -t "tsol_netstandard_foomatic: ${request_id}" \
220     "    printer : ${printer}"
221 logger -p lpr.debug -t "tsol_netstandard_foomatic: ${request_id}" \
222     "    request_id : ${request_id}"
223 logger -p lpr.debug -t "tsol_netstandard_foomatic: ${request_id}" \
224     "    user_name : ${user_name}"
225 logger -p lpr.debug -t "tsol_netstandard_foomatic: ${request_id}" \
226     "    title : ${title}"
227 logger -p lpr.debug -t "tsol_netstandard_foomatic: ${request_id}" \
228     "    copies : ${copies}"
229 logger -p lpr.debug -t "tsol_netstandard_foomatic: ${request_id}" \
230     "    option_list : ${option_list}"
231 logger -p lpr.debug -t "tsol_netstandard_foomatic: ${request_id}" \
232     "    files : ${files}"
233 logger -p lpr.debug -t "tsol_netstandard_foomatic: ${request_id}" \
234     "    spooler_key ${SPOOLER_KEY}"
236 ####
237 # default: do print a banner
238 ####
239 nobanner=no
240 nolabels="no"
241 nofilebreak="no"
242 inlist=
243 data_file_flag=
245 for i in ${option_list}
247         case "${inlist}${i}" in
249         nobanner )
250                 nobanner="yes"
251                 ;;
253         nofilebreak )
254                 nofilebreak="yes"
255                 ;;
257         nolabels )
258                 nolabels="yes"
259                 ;;
261         #####
262         #
263         # If you want to add simple options (e.g. -o simple)
264         # identify them here.
265         #####
266 #       simple )
267 #               simple="yes"
268 #               ;;
269                    
270         cpi=pica )
271                 cpi=10
272                 ;;
273         cpi=elite )
274                 cpi=12
275                 ;; 
276         cpi=* )
277                 cpi=`parse ${i}`
278                 ;;
280         lpi=* )
281                 lpi=`parse ${i}`
282                 ;;
284         length=* )
285                 length=`parse ${i}`
286                 ;;
288         width=* )
289                 width=`parse ${i}`
290                 ;;
291         dest=* )
292                 dest="-d `parse ${i}`"
293                 ;;
295         protocol=* )
296                 protocol="-P `parse ${i}`"
297                 ;;
298         bsdctrl=* )
299                 controlfile="-c `parse ${i}`"
300                 ;;
301         timeout=* )
302                 timeout="-t `parse ${i}`"
303                 ;;
305         data-file-type=* )
306                 data_file_flag="-f `parse ${i}`"
307                 ;;
309         #
310         # The IPP/PAPI attributes are handled by the foomatic-rip filter so
311         # all we need to do here is ignore them so that they don't invoke the
312         # "unrecognized option" message.
313         #
315         finishing=* | page-ranges=* | sides=* )
316                 ;;
317         number-up=* | orientation-requested=* | media=* )
318                 ;;
319         printer-resolution=* | print-quality=* )
320                 ;;
322         #####
323         #
324         # If you want to add simple-value options (e.g. -o value=a)
325         # identify them here.
326         #####
327 #       value=* )
328 #               value=`parse ${i}`
329 #               ;;
331         #####
332         #
333         # If you want to add options that, 
334         # take a list (e.g. -o lopt='a b c'), identif
335         # them here and below (look for LOPT).
336         #####
337                                    
338 #       flist=* | lpd=* | options=* )
339         flist=* | lpd=* )
340 #LOPT   stty=* | flist=* | lpd=* | lopt=* )    
342                 inlist=`expr "${inlist}${i}" : "^\([^=]*=\)"`
343                 case "${i}" in
344                 ${inlist}\'*\' )
345                         item=`expr "${i}" : "^[^=]*='*\(.*\)'\$"`
346                         ;;
347                 ${inlist}\' )
348                         continue
349                         ;;
350                 ${inlist}\'* )
351                         item=`expr "${i}" : "^[^=]*='*\(.*\)\$"`
352                         ;;
353                 ${inlist}* )
354                         item=`expr "${i}" : "^[^=]*=\(.*\)\$"`
355                         ;;
356                 *\' )
357                         item=`expr "${i}" : "^\(.*\)'\$"`
358                         ;;
359                 * )
360                         item="${i}"
361                         ;;
362                 esac
364                 #####
365                 #
366                 # We don't dare use "eval" because a clever user could
367                 # put something in an option value that we'd end up
368                 # exec'ing.
369                 #####
370                 case "${inlist}" in
371                 flist= )
372                         flist="${flist} ${item}"
373                         ;;
374                 lpd= )
375                         lpd="${lpd} ${item}"
376                         ;;
377 #LOPT           lopt= )
378 #LOPT                   lopt="${lopt} ${item}"
379 #LOPT                   ;;
380 #               options= )
381 #                       options="${options} ${item}"
382 #                       ;;
383                 esac
384                      
385                 case "${i}" in
386                 ${inlist}\'*\' )
387                         inlist=
388                         ;;
389                 ${inlist}\'* )
390                         ;;
391                 *\' | ${inlist}* )
392                         inlist=
393                         ;;
394                 esac
395                 ;;
397         * )
398                 errmsg WARNING ${E_IP_OPTS} \
399                         "unrecognized \"-o ${i}\" option" \
400                         "check the option, resubmit if necessary
401                 printing continues"
402                 ;;
403         esac
404 done         
406 logger -p lpr.debug -t "tsol_netstandard_foomatic: ${request_id}"  \
407     "term : ${TERM}"
409 if [ -z "${FILTER}" ]
410 then
411         #####
412         #
413         # If no filter is being used, we use netpr to push the
414         # file to the printer.
415         # (QUOTES ARE IMPORTANT!)
416         #####
418         case "$TERM" in
419                 PS )
420                         # make the "postscript" printers use cat
421                         # (TSOL banners are added during filtering, so we have
422                         # to use some filter.)
423                         FILTER=/bin/cat
424                 ;;
425                 PSR )
426                         # make the "reverse postscript" printers reverse the
427                         # output and the use postio to talk to the printer
428                         #FILTER="/usr/lib/lp/postscript/postreverse "
429                         #FILTER=
430                         FILTER="/usr/lib/lp/postscript/postreverse "
431                 ;;
432                 * )
433                         # We don't know the type, so just assume that the
434                         # input and output are the same. Use netpr.
435                         #FILTER=/bin/cat
436                         FILTER=
437                 ;;
438         esac
441 ####
442 # sets default value for ordering of data and control files with
443 # bsd protocol. Default: data files first. Administrator
444 # may set to control file first with lpadmin -o bsdctrl=first
445 ####
447 banner_flag=""
448 case "${nobanner}" in
449         yes )
450                 banner_flag="-b"
451         ;;
452 esac
454 NETPR="/usr/lib/lp/bin/netpr ${banner_flag} ${data_file_flag} \
455         -I ${request_id} -U ${user_name} \
456         -p ${printer} ${dest} -T \"${title}\"  \
457         ${timeout}  ${protocol} ${controlfile} "
458 LPTELL_OPTS="-l"        # netpr sends LaserWriter style messages back
459 PPDFILTER=/usr/lib/lp/bin/foomatic-rip
460 PPDFILTERA="${PPDFILTER} ${request_id} ${user_name} \"${title}\" ${copies} \"${option_list}\""
462 logger -p lpr.debug -t "tsol_netstandard_foomatic: ${request_id}" \
463     "NETPR= ${NETPR}"
464 logger -p lpr.debug -t "tsol_netstandard_foomatic: ${request_id}" \
465     "filter : ${FILTER}"
466 logger -p lpr.debug -t "tsol_netstandard_foomatic: ${request_id}" \
467     "ppdfilter : ${PPDFILTERA}"
469 node=`uname -n`
470 pid=$$
471 tmpfile=${LPTMPDIR}/${node}.${pid}
472 tmpfilefoo=${LPTMPDIR}/${node}.${pid}.1
474 logger -p lpr.debug -t "tsol_netstandard_foomatic: ${request_id}" \
475     "tmpfile : ${tmpfile}"
477 #####
479 # Set up filter for banner page
481 #####
482 banner_filter=
483 case "${TERM}" in
484 PS | PSR )
485         banner_filter=" | /usr/lib/lp/postscript/postprint "
486         LPTELL_OPTS="-l"
487         ;;
488 esac 
490 #####
492 # Build temporary file that is the banner page
494 #####
495 PAD="#####${NL}"
496 CR="\r"
497 NL="${CR}\n"
500 small_banner() {
501         echo "${CR}\c"
502         echo "${PAD}\c"
503         echo "#####  User: ${user_name}${NL}\c"
504         if [ -n "${title}" ]
505         then
506                 echo "##### Title: ${title}${NL}\c"
507         fi
508         echo "#####  Date: `LANG=C date '+%a %H:%M %h %d, %Y'`${NL}\c"
509         echo "#####   Job: ${request_id}${NL}\c"
510         echo "${PAD}\c"
511         if [ -n "${FF}" ]
512         then
513                 echo "${CR}${FF}\c"
514         fi
517 #####
519 # Doing small banner as we don't know what printer is out there
521 #####
522 banner=small_banner
524 ## Skip this for PS/PSR printers, since lp.tsol_separator handles the banners
525 if [ "no" = "${nobanner}" -a "${TERM}" != "PSR" -a "${TERM}" != "PS" ]
526 then
527         eval "${banner} ${banner_filter}" 2>&1 1>${LPTMPDIR}/small_banner.$$ 
530 ###########
532 ## Surround the job by PostScript code to produce banner 
533 ## and trailerpages and page headers and footers.
535 ###########
537 BANNER_EXIT_CODE=${LPTMPDIR}/banner.exit_code.$$
538 echo 0 > ${BANNER_EXIT_CODE}
539 TSOLSEPARATOR_LOG=${LPTMPDIR}/banner.errmsg.$$
541 tsol_bannerize () {
542         TSOLSEPARATOR_OPTS="-e ${TSOLSEPARATOR_LOG}"
544         if [ "yes" = "${nolabels}" ]
545         then
546                 TSOLSEPARATOR_OPTS="${TSOLSEPARATOR_OPTS} -l"
547         fi
549         if [ "yes" = "${nobanner}" ]
550         then
551                 TSOLSEPARATOR_OPTS="${TSOLSEPARATOR_OPTS} -t /dev/null -b /dev/null"
552         fi
554         if [ "${TERM}" = "PSR" ]
555         then
556                 TSOLSEPARATOR_OPTS="${TSOLSEPARATOR_OPTS} -r"
557         fi
559         # Get rid of the #, TAB and NL characters in the title
560         tsol_title=`echo $title`
561         tsol_title=`echo $tsol_title | sed 's/#//g'`
563         logger -p lpr.debug -t "tsol_netstandard: ${request_id}" \
564             "banner command: ${LPTSOLSEPARATOR} ${TSOLSEPARATOR_OPTS} \
565             ${printer} ${request_id} ${user_name} \"${tsol_title}\" ${file}"
566         ${LPTSOLSEPARATOR} ${TSOLSEPARATOR_OPTS} ${printer} \
567             ${request_id} ${user_name} "${tsol_title}" ${file}
569         echo $? > ${BANNER_EXIT_CODE}
570         true
573 bannerize=tsol_bannerize
575 if [ "yes" = "${nobanner}" -a  "yes" = "${nolabels}" ]
576 then
577         bannerize=cat
580 if [ "${TERM}" != "PSR" -a "${TERM}" != "PS" ]
581 then
582         bannerize=cat
585 #####
587 # Print banner page before job unless PSR or PS
589 #####
592 ## Skip this for PS/PSR printers, since lp.tsol_separator handles the banners
593 if [ "no" = "${nobanner}" -a "${TERM}" != "PSR" -a "${TERM}" != "PS" ]
594 then
595         (
596                 eval ${NETPR} ${LPTMPDIR}/small_banner.$$ 2>&1
597                 echo $? > ${LPTMPDIR}/pr_eexit_code.$$
598         ) | ${LPTELL} ${LPTELL_OPTS} ${printer}
600         exit_code=`cat ${LPTMPDIR}/pr_eexit_code.$$`
601         logger -p lpr.debug -t \
602             "tsol_netstandard_foomatic: ${request_id}" \
603             "banner page exit code : ${exit_code}"
608 while [ $i -le $copies ]
610         for file in ${files}
611         do
612                 if [ -r "${file}" ]
613                 then
615                         if [ ! -z "${FILTER}" ]
616                         then
617                                 (
618                                         #####
619                                         # There is a filter, use it
620                                         #
621                                         # Put 0<${file} before the "eval" to keep
622                                         # clever users from giving a file name that
623                                         # evaluates as something to execute.
624                                         # Redirect stderr to stdout so LPTELL will
625                                         # get error messages from pipe. 
626                                         #####
628                                         0<${file} $bannerize | eval ${FILTER} 2>&1 1>${tmpfile}
629                                         echo $? > ${LPTMPDIR}/pr_eexit_code.$$
630                                 ) | ${LPTELL} ${LPTELL_OPTS} ${printer}
632                                 # if lp.tsol_separator had an error,
633                                 # send its logged error message to LPTELL.
634                                 banner_exit_code=`cat ${BANNER_EXIT_CODE}`
635                                 if [ -n "${banner_exit_code}" -a \
636                                         0 -ne "${banner_exit_code}" -a \
637                                          -n "${LPTELL}" -a \
638                                         -r "${TSOLSEPARATOR_LOG}" ]
639                                 then
640                                         cat ${TSOLSEPARATOR_LOG} | ${LPTELL} ${printer}
641                                         echo 77 > ${LPTMPDIR}/pr_eexit_code
642                                 fi
644                                 exit_code=`cat ${LPTMPDIR}/pr_eexit_code.$$`
645                                 logger -p lpr.debug -t \
646                                     "tsol_netstandard_foomatic: ${request_id}" \
647                                     "filter exit_code : ${exit_code}"
649                                 if [ -n "${exit_code}" ]
650                                 then
651                                         if [ "${exit_code}" -eq 0 ]
652                                         then
653                                                 printfile=${tmpfile}
654                                         else
655                                                 ####
656                                                 # The filter did not succeed, so don't try to print
657                                                 ####
658                                                         printfile=
659                                         fi
660                                 fi
662                         else
663                                 printfile=${file}
664                         fi
666                         logger -p lpr.debug -t \
667                             "tsol_netstandard_foomatic: ${request_id}" \
668                             "printfile : ${printfile}"
669                         
670                         #####
671                         # Print the file
672                         #####
674                         if [ -r "${printfile}" ]
675                         then
676                                 (
677 logger -p lpr.debug -t \
678     "@1 tsol_netstandard_foomatic: printfile = ${printfile}" ""
679 logger -p lpr.debug -t \
680     "tsol_netstandard_foomatic: ${NETPR} ${printfile}" ""
681                                         #eval ${NETPR} ${printfile} 2>&1
682                                         cat ${printfile} | ${PPDFILTER} \
683               ${request_id} ${user_name} "${title}" ${copies} "${option_list}" \
684                                                 > ${tmpfilefoo} 2> /dev/null
685                                         eval ${NETPR} ${tmpfilefoo} 2>&1
686                                         echo $? > ${LPTMPDIR}/pr_eexit_code.$$
687                                         /bin/rm -f ${tmpfilefoo}
688                                 ) | ${LPTELL} ${LPTELL_OPTS} ${printer}
690                                 exit_code=`cat ${LPTMPDIR}/pr_eexit_code.$$`
691                                 logger -p lpr.debug -t \
692                                     "@2 netstandard_foomatic: ${request_id}" \
693                                     "netpr exit_code : ${exit_code}"
695 #                               if [ -f "${tmpfile}" ]
696 #                               then
697 #                                       /bin/rm "${tmpfile}"
698 #                               fi
700                                 if [ -n "${exit_code}" ]
701                                 then
702                                         if [ "${exit_code}" -eq 0 ]
703                                         then
704                                                 printone=yes
705                                         else
706                                                 if [ "${exit_code}" -lt 128 ]
707                                                 then
708                                                         noprint=yes
709                                                 else
710                                                         retry=yes
711                                                 fi
712                                         fi
713                                 fi
714                                 
716                         else    
718                                 errmsg WARNING ${E_IP_BADFILE} \
719                                 "cannot read temporary file \"${printfile}\""\
720                                         "see if file still exists,
721                         or consult your system administrator;
722                         printing continues"
724                         fi
725                 else
727                         #####
728                         #
729                         # Don't complain about not being able to read
730                         # a file on second and subsequent copies, unless
731                         # we've not complained yet. This removes repeated
732                         # messages about the same file yet reduces the
733                         # chance that the user can remove a file and not
734                         # know that we had trouble finding it.
735                         #####
737                         if [ "${i}" -le 1 -o -z "${badfileyet}" ]
738                         then
739                                 errmsg WARNING ${E_IP_BADFILE} \
740                                         "cannot read file \"${file}\"" \
741                                         "see if the file still exists and is readable,
742                 or consult your system administrator;
743                 printing continues"
744                                 badfileyet=yes
745                         fi
747                 fi
749 # for file in ${files}
750         done
751         i=`expr $i + 1`
752 done
754 #####
756 # If printing in reverse order, print the banner page now
757 # Skip this for TSOL, since lp.tsol_separator handles the banners
759 #####
761 #if [ "no" = "${nobanner}" -a "${TERM}" = "PSR" ]
762 #then
764 #       eval ${NETPR} ${LPTMPDIR}/small_banner.$$ 2>&1
765 #       echo $? > ${LPTMPDIR}/pr_eexit_code.$$
766 #) | ${LPTELL} ${LPTELL_OPTS} ${printer}
769 exit_code=`cat ${LPTMPDIR}/pr_eexit_code.$$`
770 logger -p lpr.debug -t "tsol_netstandard_foomatic: ${request_id}" \
771     "banner page exit code : ${exit_code}"
773 if [ -n "${printone}" -a -z "${retry}" -a -z "${noprint}" ]
774 then
775         exit_code=`expr 0`
776 else
777         if [ -n "${retry}" -a -z "${printone}" -a -z "${noprint}" ]
778         then
779                 exit_code=`expr 129`
780         else
781                 exit_code=`expr 1`
782         fi
785 logger -p lpr.debug -t "tsol_netstandard_foomatic: ${request_id}" \
786     "FINAL exit_code : ${exit_code}"
788 exit_clean ${exit_code}