1*f875b4ebSrica# 2*f875b4ebSrica# CDDL HEADER START 3*f875b4ebSrica# 4*f875b4ebSrica# The contents of this file are subject to the terms of the 5*f875b4ebSrica# Common Development and Distribution License (the "License"). 6*f875b4ebSrica# You may not use this file except in compliance with the License. 7*f875b4ebSrica# 8*f875b4ebSrica# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*f875b4ebSrica# or http://www.opensolaris.org/os/licensing. 10*f875b4ebSrica# See the License for the specific language governing permissions 11*f875b4ebSrica# and limitations under the License. 12*f875b4ebSrica# 13*f875b4ebSrica# When distributing Covered Code, include this CDDL HEADER in each 14*f875b4ebSrica# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*f875b4ebSrica# If applicable, add the following below this CDDL HEADER, with the 16*f875b4ebSrica# fields enclosed by brackets "[]" replaced with your own identifying 17*f875b4ebSrica# information: Portions Copyright [yyyy] [name of copyright owner] 18*f875b4ebSrica# 19*f875b4ebSrica# CDDL HEADER END 20*f875b4ebSrica# 21*f875b4ebSrica# 22*f875b4ebSrica#ident "%Z%%M% %I% %E% SMI" 23*f875b4ebSrica# 24*f875b4ebSrica# Copyright 2007 Sun Microsystems, Inc. All rights reserved. 25*f875b4ebSrica# Use is subject to license terms. 26*f875b4ebSrica# 27*f875b4ebSrica 28*f875b4ebSrica########### 29*f875b4ebSrica## 30*f875b4ebSrica## Standard printer interface program. 31*f875b4ebSrica## 32*f875b4ebSrica########### 33*f875b4ebSrica 34*f875b4ebSrica##### 35*f875b4ebSrica# 36*f875b4ebSrica# Until we get to the point below where the printer port 37*f875b4ebSrica# and physical printer are initialized, we can't do much 38*f875b4ebSrica# except exit if the Spooler/Scheduler cancels us. 39*f875b4ebSrica##### 40*f875b4ebSricatrap 'exit' 15 41*f875b4ebSrica 42*f875b4ebSrica##### 43*f875b4ebSrica# 44*f875b4ebSrica# We can be clever about getting a hangup or interrupt, though, at least 45*f875b4ebSrica# until the filter runs. Do this early, even though $LPTELL 46*f875b4ebSrica# isn't defined, so that we're covered. 47*f875b4ebSrica##### 48*f875b4ebSricacatch_hangup () { 49*f875b4ebSrica if [ -n "${LPTELL}" ] 50*f875b4ebSrica then 51*f875b4ebSrica echo \ 52*f875b4ebSrica"The connection to the printer dropped; perhaps the printer went off-line?" \ 53*f875b4ebSrica | ${LPTELL} ${printer} 54*f875b4ebSrica fi 55*f875b4ebSrica return 0 56*f875b4ebSrica} 57*f875b4ebSricacatch_interrupt () { 58*f875b4ebSrica if [ -n "${LPTELL}" ] 59*f875b4ebSrica then 60*f875b4ebSrica echo \ 61*f875b4ebSrica"Received an interrupt from the printer. The reason is unknown, 62*f875b4ebSricaalthough a common cause is that the baud rate is too high." \ 63*f875b4ebSrica | ${LPTELL} ${printer} 64*f875b4ebSrica fi 65*f875b4ebSrica return 0 66*f875b4ebSrica} 67*f875b4ebSricatrap 'catch_hangup; exit_code=129 exit 129' 1 68*f875b4ebSricatrap 'catch_interrupt; exit_code=129 exit 129' 2 3 69*f875b4ebSrica 70*f875b4ebSrica##### 71*f875b4ebSrica# 72*f875b4ebSrica# Most of the time we don't want the standard error to be captured 73*f875b4ebSrica# by the Spooler, mainly to avoid "Terminated" messages that the 74*f875b4ebSrica# shell puts out when we get a SIGTERM. We'll save the standard 75*f875b4ebSrica# error channel under another number, so we can use it when it 76*f875b4ebSrica# should be captured. 77*f875b4ebSrica# 78*f875b4ebSrica# Open another channel to the printer port, for use when the 79*f875b4ebSrica# regular standard output won't be directed there, such as in 80*f875b4ebSrica# command substitution (`cmd`). 81*f875b4ebSrica##### 82*f875b4ebSricaexec 5>&2 2>/dev/null 3>&1 83*f875b4ebSrica 84*f875b4ebSrica##### 85*f875b4ebSrica# 86*f875b4ebSrica# Set some globally used variables and functions. 87*f875b4ebSrica##### 88*f875b4ebSrica 89*f875b4ebSrica: ${TMPDIR:=/tmp} 90*f875b4ebSrica: ${SPOOLDIR:=/usr/spool/lp} 91*f875b4ebSrica: ${TERMINFO:=/usr/lib/terminfo} 92*f875b4ebSrica: ${CHARSETDIR:=/usr/lib/charsets} 93*f875b4ebSrica 94*f875b4ebSrica: ${LOCALPATH:=${SPOOLDIR}/bin} 95*f875b4ebSricaPATH="/bin:/usr/bin:${LOCALPATH}" 96*f875b4ebSrica 97*f875b4ebSricaMAX_COLS_SMALL_BANNER=40 98*f875b4ebSrica 99*f875b4ebSrica##### 100*f875b4ebSrica# 101*f875b4ebSrica# On the 3.2 release of the 386unix product, the parallel port does 102*f875b4ebSrica# not support any ioctl calls. As a result, we cannot set the opost 103*f875b4ebSrica# and onlcr attributes to have <NL>'s expanded to <CR><NL>. This 104*f875b4ebSrica# "filter" gets the job done for us. 105*f875b4ebSrica##### 106*f875b4ebSrica: ${FIX386BD:=${LOCALPATH}/386parallel} 107*f875b4ebSricaif [ -n "${FIX386BD}" -a -x "${FIX386BD}" ] 108*f875b4ebSricathen 109*f875b4ebSrica FIX386BD="| ${FIX386BD}" 110*f875b4ebSricaelse 111*f875b4ebSrica FIX386BD="" 112*f875b4ebSricafi 113*f875b4ebSrica 114*f875b4ebSrica##### 115*f875b4ebSrica# Use ${TMPPREFIX} as the prefix for all temporary files, so 116*f875b4ebSrica# that cleanup is easy. The prefix may be up to 13 characters 117*f875b4ebSrica# long, so you only have space for one more character to make 118*f875b4ebSrica# a file name. If necessary, make a directory using this prefix 119*f875b4ebSrica# for better management of unique temporary file names. 120*f875b4ebSrica##### 121*f875b4ebSricaTMPPREFIX=${TMPDIR}/`uname -n`$$ 122*f875b4ebSrica 123*f875b4ebSrica##### 124*f875b4ebSrica# Before exiting, set ${exit_code} to the value with which to exit. 125*f875b4ebSrica# Otherwise, the exit from this script will be 0. 126*f875b4ebSrica##### 127*f875b4ebSricatrap 'rm -fr ${TMPPREFIX}*; exit ${exit_code}' 0 128*f875b4ebSrica 129*f875b4ebSrica##### 130*f875b4ebSrica# ${LPTELL} is the name of a program that will send its 131*f875b4ebSrica# standard input to the Spooler. It is used to forward 132*f875b4ebSrica# the description of a printer fault to the Spooler, 133*f875b4ebSrica# which uses it in an alert to the administrator. 134*f875b4ebSrica##### 135*f875b4ebSricaif [ ! -x "${LPTELL:=${LOCALPATH}/lp.tell}" ] 136*f875b4ebSricathen 137*f875b4ebSrica fake_lptell () { 138*f875b4ebSrica header="no" 139*f875b4ebSrica while read line 140*f875b4ebSrica do 141*f875b4ebSrica if [ "no" = "${header}" ] 142*f875b4ebSrica then 143*f875b4ebSrica errmsg ERROR ${E_IP_UNKNOWN} \ 144*f875b4ebSrica "unknown printer/interface failure" \ 145*f875b4ebSrica "consult your system administrator; 146*f875b4ebSrica reasons for failure (if any) follow:" 147*f875b4ebSrica header=yes 148*f875b4ebSrica fi 149*f875b4ebSrica echo "${line}" >&2 150*f875b4ebSrica done 151*f875b4ebSrica return 1 152*f875b4ebSrica } 153*f875b4ebSrica LPTELL=fake_lptell 154*f875b4ebSricafi 155*f875b4ebSrica 156*f875b4ebSrica##### 157*f875b4ebSrica# ${DRAIN} is the name of a program that will wait 158*f875b4ebSrica# long enough for data sent to the printer to print. 159*f875b4ebSrica##### 160*f875b4ebSricaif [ -x "${LOCALPATH}/drain.output" ] 161*f875b4ebSricathen 162*f875b4ebSrica DRAIN="${LOCALPATH}/drain.output 5" # wait only five seconds 163*f875b4ebSricaelse 164*f875b4ebSrica DRAIN= 165*f875b4ebSricafi 166*f875b4ebSrica 167*f875b4ebSrica##### 168*f875b4ebSrica# ${LPTSOLSEPARATOR} is the name of a program to put banner and trailer 169*f875b4ebSrica# pages around the job. 170*f875b4ebSrica##### 171*f875b4ebSricaif [ -x ${LOCALPATH}/lp.tsol_separator ] 172*f875b4ebSricathen 173*f875b4ebSrica LPTSOLSEPARATOR=${LOCALPATH}/lp.tsol_separator 174*f875b4ebSricaelse 175*f875b4ebSrica echo "${LOCALPATH}/lp.tsol_separator not found." >&2 176*f875b4ebSrica exit 1 177*f875b4ebSricafi 178*f875b4ebSrica 179*f875b4ebSrica##### 180*f875b4ebSrica# ${LPCAT} is the name of a program to use as a default 181*f875b4ebSrica# filter. Minimally it should copy its standard input to 182*f875b4ebSrica# the standard output, but it should also trap printer 183*f875b4ebSrica# faults. The current LPCAT traps hangups (DCD dropping, SIGHUP), 184*f875b4ebSrica# interrupts (SIGINT, SIGQUIT), broken pipe (SIGPIPE), and 185*f875b4ebSrica# excess delays in sending data to the printer, interpreting all 186*f875b4ebSrica# as printer faults. 187*f875b4ebSrica##### 188*f875b4ebSricaif [ ! -x "${LPCAT:=${LOCALPATH}/lp.cat}" ] 189*f875b4ebSricathen 190*f875b4ebSrica LPCAT="cat" 191*f875b4ebSricafi 192*f875b4ebSrica 193*f875b4ebSrica##### 194*f875b4ebSrica# ${LPSET} is the name of a program that will set the 195*f875b4ebSrica# character pitch, line pitch, page width, page length, 196*f875b4ebSrica# and character set. It helps to have this in a single 197*f875b4ebSrica# binary program so that (1) it's faster than calls 198*f875b4ebSrica# to "tput"; and (2) it can access the new Terminfo 199*f875b4ebSrica# capabilities for printers (on pre SVR3.2 machines, tput can't). 200*f875b4ebSrica##### 201*f875b4ebSricaif [ ! -x "${LPSET:=${LOCALPATH}/lp.set}" ] 202*f875b4ebSricathen 203*f875b4ebSrica fake_lpset () { 204*f875b4ebSrica echo H V W L S >&2 205*f875b4ebSrica false 206*f875b4ebSrica } 207*f875b4ebSrica LPSET=fake_lpset 208*f875b4ebSricafi 209*f875b4ebSrica 210*f875b4ebSricainternal_lpset () { 211*f875b4ebSrica ##### 212*f875b4ebSrica # 213*f875b4ebSrica # The funny business with the "2>&1 1>&3" is to let us capture 214*f875b4ebSrica # the standard ERROR, not the standard OUTPUT as is the usual case 215*f875b4ebSrica # with foo=`cmd`. The standard output will go to the printer. 216*f875b4ebSrica ##### 217*f875b4ebSrica [ -n "${stty1}" ] && stty ${stty1} 0<&1 218*f875b4ebSrica chk=`${LPSET} "$1" "$2" "$3" "$4" "$5" 2>&1 1>&3` 219*f875b4ebSrica [ -n "${stty2}" ] && stty ${stty2} 0<&1 220*f875b4ebSrica 221*f875b4ebSrica ##### 222*f875b4ebSrica # 223*f875b4ebSrica # The standard error of the delivered ${LPSET} program 224*f875b4ebSrica # is a string of letters, H, V, W, L, S, which correspond 225*f875b4ebSrica # to cpi, lpi, width, length, and character set. A letter 226*f875b4ebSrica # is present only if the corresponding attribute could not 227*f875b4ebSrica # be set. 228*f875b4ebSrica ##### 229*f875b4ebSrica for err in ${chk} 230*f875b4ebSrica do 231*f875b4ebSrica case ${err} in 232*f875b4ebSrica H ) 233*f875b4ebSrica errmsg WARNING ${E_IP_BADCPI} \ 234*f875b4ebSrica "can't select the character pitch \"${cpi}\"" \ 235*f875b4ebSrica "check the valid pitches for the printer, 236*f875b4ebSrica or consult your system administrator; 237*f875b4ebSrica printing continues" 238*f875b4ebSrica ;; 239*f875b4ebSrica V ) 240*f875b4ebSrica errmsg WARNING ${E_IP_BADLPI} \ 241*f875b4ebSrica "can't select the line pitch \"${lpi}\"" \ 242*f875b4ebSrica "check the valid pitches for the printer, 243*f875b4ebSrica or consult your system administrator; 244*f875b4ebSrica printing continues" 245*f875b4ebSrica ;; 246*f875b4ebSrica W ) 247*f875b4ebSrica width=${cols} 248*f875b4ebSrica errmsg WARNING ${E_IP_BADWIDTH} \ 249*f875b4ebSrica "can't select the page width \"${width}\"" \ 250*f875b4ebSrica "check the valid widths for the printer, 251*f875b4ebSrica or consult your system administrator; 252*f875b4ebSrica printing continues" 253*f875b4ebSrica ;; 254*f875b4ebSrica L ) 255*f875b4ebSrica length=${lines} 256*f875b4ebSrica errmsg WARNING ${E_IP_BADLENGTH} \ 257*f875b4ebSrica "can't select the page length \"${length}\"" \ 258*f875b4ebSrica "check the valid lengths for the printer, 259*f875b4ebSrica or consult your system administrator; 260*f875b4ebSrica printing continues" 261*f875b4ebSrica ;; 262*f875b4ebSrica S ) 263*f875b4ebSrica errmsg WARNING ${E_IP_BADCHARSET} \ 264*f875b4ebSrica "can't select the character set \"${CHARSET}\"" \ 265*f875b4ebSrica "check the name given in the -S option, 266*f875b4ebSrica or consult your system administrator; 267*f875b4ebSrica printing continues" 268*f875b4ebSrica ;; 269*f875b4ebSrica esac 270*f875b4ebSrica done 271*f875b4ebSrica} 272*f875b4ebSrica 273*f875b4ebSrica 274*f875b4ebSrica##### 275*f875b4ebSrica# ${TPUT} is "tput" IF it works. We'll disable it if we get an 276*f875b4ebSrica# ugly error message the first time we use it. See the TERM variable 277*f875b4ebSrica# later in the script. 278*f875b4ebSrica# 279*f875b4ebSrica# NOTE: The check we use to see if "tput" works is to use an OLD 280*f875b4ebSrica# Terminfo capability, like "lines". If it works with that it may 281*f875b4ebSrica# still fail with some of the newer capabilities like "init" (SVR3.0) 282*f875b4ebSrica# or "swidm" (SVR3.2), because the version of "tput" we have on your 283*f875b4ebSrica# machine is older. Thus, on some of the code where ${TPUT} is used 284*f875b4ebSrica# you'll see "2>/dev/null" being used to avoid ugly error messages. 285*f875b4ebSrica##### 286*f875b4ebSricaTPUT=tput 287*f875b4ebSrica 288*f875b4ebSrica##### 289*f875b4ebSrica# Error message formatter: 290*f875b4ebSrica# 291*f875b4ebSrica# Invoke as 292*f875b4ebSrica# 293*f875b4ebSrica# errmsg severity message-number problem help 294*f875b4ebSrica# 295*f875b4ebSrica# where severity is "ERROR" or "WARNING", message-number is 296*f875b4ebSrica# a unique identifier, problem is a short description of the 297*f875b4ebSrica# problem, and help is a short suggestion for fixing the problem. 298*f875b4ebSrica##### 299*f875b4ebSrica 300*f875b4ebSricaLP_ERR_LABEL="UX:lp" 301*f875b4ebSrica 302*f875b4ebSricaE_IP_ARGS=1 303*f875b4ebSricaE_IP_OPTS=2 304*f875b4ebSrica#E_IP_FILTER=3 305*f875b4ebSricaE_IP_STTY=4 306*f875b4ebSricaE_IP_UNKNOWN=5 307*f875b4ebSricaE_IP_BADFILE=6 308*f875b4ebSricaE_IP_BADCHARSET=7 309*f875b4ebSricaE_IP_BADCPI=8 310*f875b4ebSricaE_IP_BADLPI=9 311*f875b4ebSricaE_IP_BADWIDTH=10 312*f875b4ebSricaE_IP_BADLENGTH=11 313*f875b4ebSricaE_IP_ERRORS=12 # (in slow.filter) 314*f875b4ebSrica 315*f875b4ebSricaerrmsg () { 316*f875b4ebSrica case $1 in 317*f875b4ebSrica ERROR ) 318*f875b4ebSrica sev=" ERROR"; 319*f875b4ebSrica ;; 320*f875b4ebSrica WARNING ) 321*f875b4ebSrica sev="WARNING"; 322*f875b4ebSrica ;; 323*f875b4ebSrica esac 324*f875b4ebSrica# tag=`expr "${LP_ERR_LABEL}" : "\(.*\):"``expr "${LP_ERR_LABEL}" : ".*:\(.*\)"` 325*f875b4ebSrica echo "${LP_ERR_LABEL}: ${sev}: $3 326*f875b4ebSrica TO FIX: $4" >&5 327*f875b4ebSrica} 328*f875b4ebSrica 329*f875b4ebSrica 330*f875b4ebSrica########### 331*f875b4ebSrica## 332*f875b4ebSrica## Check arguments 333*f875b4ebSrica########### 334*f875b4ebSrica 335*f875b4ebSricaparse () { 336*f875b4ebSrica echo "`expr \"$1\" : \"^[^=]*=\(.*\)\"`" 337*f875b4ebSrica} 338*f875b4ebSrica 339*f875b4ebSrica##### 340*f875b4ebSrica# 341*f875b4ebSrica# This program is invoked as 342*f875b4ebSrica# 343*f875b4ebSrica# ${SPOOLDIR}/.../printer request-id user title copies options files... 344*f875b4ebSrica# 345*f875b4ebSrica# The first three arguments are simply reprinted on the banner page, 346*f875b4ebSrica# the fourth (copies) is used to control the number of copies to print, 347*f875b4ebSrica# the fifth (options) is a blank separated list (in a single argument) 348*f875b4ebSrica# of user or Spooler supplied options (without the -o prefix), 349*f875b4ebSrica# and the last arguments are the files to print. 350*f875b4ebSrica##### 351*f875b4ebSrica 352*f875b4ebSricaif [ $# -lt 5 ] 353*f875b4ebSricathen 354*f875b4ebSrica errmsg ERROR ${E_IP_ARGS} \ 355*f875b4ebSrica "wrong number of arguments to interface program" \ 356*f875b4ebSrica "consult your system administrator" 357*f875b4ebSrica exit 1 358*f875b4ebSricafi 359*f875b4ebSrica 360*f875b4ebSricaprinter=`basename $0` 361*f875b4ebSricarequest_id=$1 362*f875b4ebSricauser_name=$2 363*f875b4ebSricatitle=$3 364*f875b4ebSricacopies=$4 365*f875b4ebSricaoption_list=$5 366*f875b4ebSrica 367*f875b4ebSricashift 5 368*f875b4ebSricafiles="$*" 369*f875b4ebSrica 370*f875b4ebSricanobanner="no" 371*f875b4ebSricanofilebreak="no" 372*f875b4ebSricanolabels="no" 373*f875b4ebSricastty= 374*f875b4ebSrica 375*f875b4ebSricainlist= 376*f875b4ebSricafor i in ${option_list} 377*f875b4ebSricado 378*f875b4ebSrica case "${inlist}${i}" in 379*f875b4ebSrica 380*f875b4ebSrica 381*f875b4ebSrica nobanner ) 382*f875b4ebSrica nobanner="yes" 383*f875b4ebSrica ;; 384*f875b4ebSrica 385*f875b4ebSrica nofilebreak ) 386*f875b4ebSrica nofilebreak="yes" 387*f875b4ebSrica ;; 388*f875b4ebSrica 389*f875b4ebSrica nolabels ) 390*f875b4ebSrica nolabels="yes" 391*f875b4ebSrica ;; 392*f875b4ebSrica 393*f875b4ebSrica # 394*f875b4ebSrica # The IPP/PAPI attributes are handled by the foomatic-rip filter so 395*f875b4ebSrica # all we need to do here is ignore them so that they don't invoke the 396*f875b4ebSrica # "unrecognized option" message. 397*f875b4ebSrica # 398*f875b4ebSrica 399*f875b4ebSrica finishing=* | page-ranges=* | sides=* ) 400*f875b4ebSrica ;; 401*f875b4ebSrica number-up=* | orientation-requested=* | media=* ) 402*f875b4ebSrica ;; 403*f875b4ebSrica printer-resolution=* | print-quality=* ) 404*f875b4ebSrica ;; 405*f875b4ebSrica 406*f875b4ebSrica ##### 407*f875b4ebSrica # 408*f875b4ebSrica # If you want to add simple options (e.g. -o simple) 409*f875b4ebSrica # identify them here. 410*f875b4ebSrica ##### 411*f875b4ebSrica# simple ) 412*f875b4ebSrica# simple="yes" 413*f875b4ebSrica# ;; 414*f875b4ebSrica 415*f875b4ebSrica 416*f875b4ebSrica cpi=pica ) 417*f875b4ebSrica cpi=10 418*f875b4ebSrica ;; 419*f875b4ebSrica cpi=elite ) 420*f875b4ebSrica cpi=12 421*f875b4ebSrica ;; 422*f875b4ebSrica cpi=* ) 423*f875b4ebSrica cpi=`parse ${i}` 424*f875b4ebSrica ;; 425*f875b4ebSrica 426*f875b4ebSrica lpi=* ) 427*f875b4ebSrica lpi=`parse ${i}` 428*f875b4ebSrica ;; 429*f875b4ebSrica 430*f875b4ebSrica length=* ) 431*f875b4ebSrica length=`parse ${i}` 432*f875b4ebSrica ;; 433*f875b4ebSrica 434*f875b4ebSrica width=* ) 435*f875b4ebSrica width=`parse ${i}` 436*f875b4ebSrica ;; 437*f875b4ebSrica 438*f875b4ebSrica ##### 439*f875b4ebSrica # 440*f875b4ebSrica # If you want to add simple-value options (e.g. -o value=a) 441*f875b4ebSrica # identify them here. 442*f875b4ebSrica ##### 443*f875b4ebSrica# value=* ) 444*f875b4ebSrica# value=`parse ${i}` 445*f875b4ebSrica# ;; 446*f875b4ebSrica 447*f875b4ebSrica 448*f875b4ebSrica ##### 449*f875b4ebSrica # 450*f875b4ebSrica # If you want to add options that, like "stty", 451*f875b4ebSrica # take a list (e.g. -o lopt='a b c'), identify 452*f875b4ebSrica # them here and below (look for LOPT). 453*f875b4ebSrica ##### 454*f875b4ebSrica stty=* | flist=* | lpd=* ) 455*f875b4ebSrica#LOPT stty=* | flist=* | lpd=* | lopt=* ) 456*f875b4ebSrica 457*f875b4ebSrica inlist=`expr "${inlist}${i}" : "^\([^=]*=\)"` 458*f875b4ebSrica case "${i}" in 459*f875b4ebSrica ${inlist}\'*\' ) 460*f875b4ebSrica item=`expr "${i}" : "^[^=]*='*\(.*\)'\$"` 461*f875b4ebSrica ;; 462*f875b4ebSrica ${inlist}\' ) 463*f875b4ebSrica continue 464*f875b4ebSrica ;; 465*f875b4ebSrica ${inlist}\'* ) 466*f875b4ebSrica item=`expr "${i}" : "^[^=]*='*\(.*\)\$"` 467*f875b4ebSrica ;; 468*f875b4ebSrica ${inlist}* ) 469*f875b4ebSrica item=`expr "${i}" : "^[^=]*=\(.*\)\$"` 470*f875b4ebSrica ;; 471*f875b4ebSrica *\' ) 472*f875b4ebSrica item=`expr "${i}" : "^\(.*\)'\$"` 473*f875b4ebSrica ;; 474*f875b4ebSrica * ) 475*f875b4ebSrica item="${i}" 476*f875b4ebSrica ;; 477*f875b4ebSrica esac 478*f875b4ebSrica 479*f875b4ebSrica ##### 480*f875b4ebSrica # 481*f875b4ebSrica # We don't dare use "eval" because a clever user could 482*f875b4ebSrica # put something in an option value that we'd end up 483*f875b4ebSrica # exec'ing. 484*f875b4ebSrica ##### 485*f875b4ebSrica case "${inlist}" in 486*f875b4ebSrica stty= ) 487*f875b4ebSrica stty="${stty} ${item}" 488*f875b4ebSrica ;; 489*f875b4ebSrica flist= ) 490*f875b4ebSrica flist="${flist} ${item}" 491*f875b4ebSrica ;; 492*f875b4ebSrica lpd= ) 493*f875b4ebSrica lpd="${lpd} ${item}" 494*f875b4ebSrica ;; 495*f875b4ebSrica#LOPT lopt= ) 496*f875b4ebSrica#LOPT lopt="${lopt} ${item}" 497*f875b4ebSrica#LOPT ;; 498*f875b4ebSrica esac 499*f875b4ebSrica 500*f875b4ebSrica case "${i}" in 501*f875b4ebSrica ${inlist}\'*\' ) 502*f875b4ebSrica inlist= 503*f875b4ebSrica ;; 504*f875b4ebSrica ${inlist}\'* ) 505*f875b4ebSrica ;; 506*f875b4ebSrica *\' | ${inlist}* ) 507*f875b4ebSrica inlist= 508*f875b4ebSrica ;; 509*f875b4ebSrica esac 510*f875b4ebSrica ;; 511*f875b4ebSrica 512*f875b4ebSrica * ) 513*f875b4ebSrica errmsg WARNING ${E_IP_OPTS} \ 514*f875b4ebSrica "unrecognized \"-o ${i}\" option" \ 515*f875b4ebSrica "check the option, resubmit if necessary 516*f875b4ebSrica printing continues" 517*f875b4ebSrica ;; 518*f875b4ebSrica esac 519*f875b4ebSricadone 520*f875b4ebSrica 521*f875b4ebSrica##### 522*f875b4ebSrica# 523*f875b4ebSrica# Additional ``parameters'' are passed via Shell environment 524*f875b4ebSrica# variables: 525*f875b4ebSrica# 526*f875b4ebSrica# TERM The printer type (used for Terminfo access) 527*f875b4ebSrica# CHARSET The character set to choose 528*f875b4ebSrica# FILTER The filter to run 529*f875b4ebSrica##### 530*f875b4ebSrica 531*f875b4ebSrica##### 532*f875b4ebSrica# Set defaults for unset variables. 533*f875b4ebSrica##### 534*f875b4ebSrica 535*f875b4ebSrica: ${TERM:=unknown} 536*f875b4ebSricatput lines 1>/dev/null 2>&1 || TPUT=: 537*f875b4ebSrica 538*f875b4ebSrica: ${CHARSET:=cs0} 539*f875b4ebSrica 540*f875b4ebSricaPPDFILTER=/usr/lib/lp/bin/foomatic-rip 541*f875b4ebSricaPPDFILTERA="${PPDFILTER} ${request_id} ${user_name} \"${title}\" ${copies} \"${option_list}\"" 542*f875b4ebSrica 543*f875b4ebSricaif [ -z "${FILTER}" ] 544*f875b4ebSricathen 545*f875b4ebSrica ##### 546*f875b4ebSrica # 547*f875b4ebSrica # If no filter is being used, we have a little routine that 548*f875b4ebSrica # will push the data to the printer. It traps hangups (loss 549*f875b4ebSrica # of carrier) and checks for excessive delays in sending the 550*f875b4ebSrica # data to the printer. The lesser of the print rate of the printer 551*f875b4ebSrica # (obtained from Terminfo) or the baud rate is used to compute 552*f875b4ebSrica # the expected delay. If neither of these is correct, you 553*f875b4ebSrica # may be experiencing false alarms. If so, give the correct 554*f875b4ebSrica # rate, in characters per second, as a single argument. 555*f875b4ebSrica # An argument of 0 means don't check for delays. 556*f875b4ebSrica # Give an -r option to get a printout of actual delays. 557*f875b4ebSrica # (QUOTES ARE IMPORTANT!) 558*f875b4ebSrica ##### 559*f875b4ebSrica case "$TERM" in 560*f875b4ebSrica PS ) 561*f875b4ebSrica # make the "postscript" printers use postio to 562*f875b4ebSrica # talk to the printer and periodically get a 563*f875b4ebSrica # status from them 564*f875b4ebSrica FILTER="/usr/lib/lp/postscript/postio" 565*f875b4ebSrica ;; 566*f875b4ebSrica PSR ) 567*f875b4ebSrica # make the "reverse postscript" printers reverse the 568*f875b4ebSrica # output and the use postio to talk to the printer 569*f875b4ebSrica FILTER="/usr/lib/lp/postscript/postreverse | \ 570*f875b4ebSrica /usr/lib/lp/postscript/postio" 571*f875b4ebSrica ;; 572*f875b4ebSrica * ) 573*f875b4ebSrica # we don't know the type, so just assume that the 574*f875b4ebSrica # input and output are the same 575*f875b4ebSrica if [ `basename "${LPCAT}"` = "lp.cat" ] ; then 576*f875b4ebSrica FILTER="${LPCAT} 0" # infinite delays 577*f875b4ebSrica # FILTER="${LPCAT} 120" # e.g. 120 CPS 578*f875b4ebSrica # FILTER="${LPCAT} -r 0 2>/tmp/delays" 579*f875b4ebSrica # FILTER=${LPCAT} 580*f875b4ebSrica fi 581*f875b4ebSrica ;; 582*f875b4ebSrica esac 583*f875b4ebSricafi 584*f875b4ebSrica 585*f875b4ebSricalogger -p lpr.debug -t "tsol_standard_foomatic: ${request_id}" "filter : ${FILTER}" 586*f875b4ebSricalogger -p lpr.debug -t "tsol_standard_foomatic: ${request_id}" "ppdfilter : ${PPDFILTERA}" 587*f875b4ebSrica 588*f875b4ebSrica# 589*f875b4ebSrica# Append the PPD foomatic-rip filter 590*f875b4ebSrica# 591*f875b4ebSricaFILTER="${FILTER} | ${PPDFILTERA}" 592*f875b4ebSrica 593*f875b4ebSrica########### 594*f875b4ebSrica## 595*f875b4ebSrica## Initialize the printer port 596*f875b4ebSrica########### 597*f875b4ebSrica 598*f875b4ebSrica##### 599*f875b4ebSrica# 600*f875b4ebSrica# SERIAL PORTS: 601*f875b4ebSrica# Initialize everything. 602*f875b4ebSrica# 603*f875b4ebSrica# PARALLEL PORTS: 604*f875b4ebSrica# Don't initialize baud rate. 605*f875b4ebSrica# 606*f875b4ebSrica# It's not obvious how to tell if a port is parallel or serial. 607*f875b4ebSrica# However, by splitting the initialization into two steps and letting 608*f875b4ebSrica# the serial-only part fail nicely, it'll work. 609*f875b4ebSrica# 610*f875b4ebSrica# Another point: The output must be a ``tty'' device. If not, don't 611*f875b4ebSrica# bother with any of this. 612*f875b4ebSrica##### 613*f875b4ebSricastty1= stty2= 614*f875b4ebSricatty 0<&1 1>/dev/null 2>&1 && { 615*f875b4ebSrica 616*f875b4ebSrica ##### 617*f875b4ebSrica # 618*f875b4ebSrica # First set the default parameters, 619*f875b4ebSrica # then the requested parameters. 620*f875b4ebSrica ##### 621*f875b4ebSrica 622*f875b4ebSrica stty \ 623*f875b4ebSrica 9600 \ 624*f875b4ebSrica 0<&1 2>/dev/null 1>&2 625*f875b4ebSrica stty \ 626*f875b4ebSrica cs8 -cstopb -parenb -parodd \ 627*f875b4ebSrica ixon -ixany \ 628*f875b4ebSrica opost -olcuc onlcr -ocrnl -onocr -onlret -ofill \ 629*f875b4ebSrica nl0 cr0 tab0 bs0 vt0 ff0 \ 630*f875b4ebSrica 0<&1 2>/dev/null 1>&2 631*f875b4ebSrica 632*f875b4ebSrica if [ -n "${stty}" ] 633*f875b4ebSrica then 634*f875b4ebSrica if stty ${stty} 0<&1 1>/dev/null 2>&5 635*f875b4ebSrica then 636*f875b4ebSrica : 637*f875b4ebSrica else 638*f875b4ebSrica errmsg ERROR ${E_IP_STTY} \ 639*f875b4ebSrica "stty option list failed" \ 640*f875b4ebSrica "check the \"-o stty\" option you used, 641*f875b4ebSrica or consult your system administrator" 642*f875b4ebSrica exit 1 643*f875b4ebSrica fi 644*f875b4ebSrica fi 645*f875b4ebSrica 646*f875b4ebSrica ##### 647*f875b4ebSrica # 648*f875b4ebSrica # Here you may want to add other port initialization code. 649*f875b4ebSrica # Some examples: 650*f875b4ebSrica # 651*f875b4ebSrica # estty # for printer needing hardware flow control (3B2/EPORTS) 652*f875b4ebSrica # fctty # for printer needing hardware flow control (3B15,3B20) 653*f875b4ebSrica ##### 654*f875b4ebSrica #estty 0<&1 655*f875b4ebSrica #fctty 0<&1 656*f875b4ebSrica 657*f875b4ebSrica 658*f875b4ebSrica ########## 659*f875b4ebSrica # 660*f875b4ebSrica # Find out if we have to turn off opost before initializing the 661*f875b4ebSrica # printer and on after. Likewise, check clocal. 662*f875b4ebSrica # 663*f875b4ebSrica # Turning OFF opost (output postprocessing) keeps the UNIX system 664*f875b4ebSrica # from changing what we try to send to the printer. Turning ON 665*f875b4ebSrica # clocal keeps the UNIX system from dropping what we are trying to 666*f875b4ebSrica # send if the printer drops DTR. An example of the former is the 667*f875b4ebSrica # AT&T 479, which wants to send a linefeed (ASCII 10) when a page 668*f875b4ebSrica # width of 10 is set; with opost on, this COULD BE turned into a 669*f875b4ebSrica # carriage-return/linefeed pair. An example of the latter is the 670*f875b4ebSrica # AT&T 455, which momentarily drops DTR when it gets the 671*f875b4ebSrica # initialization string, is2; with clocal off, the UNIX system 672*f875b4ebSrica # stops sending the rest of the initialization sequence at that 673*f875b4ebSrica # point. 674*f875b4ebSrica # 675*f875b4ebSrica # THIS CODE MUST FOLLOW THE REST OF THE PORT INITIALIZATION CODE. 676*f875b4ebSrica ########## 677*f875b4ebSrica cur_stty=`stty -a 0<&3` 678*f875b4ebSrica expr "${cur_stty}" : '.*-opost' 1>/dev/null 2>&1 \ 679*f875b4ebSrica || stty1="${stty1} -opost" stty2="${stty2} opost" 680*f875b4ebSrica expr "${cur_stty}" : '.*-clocal' 1>/dev/null 2>&1 \ 681*f875b4ebSrica && stty1="${stty1} clocal" stty2="${stty2} -clocal" 682*f875b4ebSrica expr "${cur_stty}" : '.* opost.*' 1>/dev/null 2>&1 \ 683*f875b4ebSrica || banner_filter=${FIX386BD} 684*f875b4ebSrica 685*f875b4ebSrica} 686*f875b4ebSrica 687*f875b4ebSrica 688*f875b4ebSrica########### 689*f875b4ebSrica## 690*f875b4ebSrica## Initialize the physical printer (Part I). 691*f875b4ebSrica## Here we bring the printer to a sane state and set the page size. 692*f875b4ebSrica########### 693*f875b4ebSrica 694*f875b4ebSrica########## 695*f875b4ebSrica# 696*f875b4ebSrica# WARNING! The "echo" command will catch backslashes (\) and 697*f875b4ebSrica# try to interpret the characters following it. Thus, using 698*f875b4ebSrica# "echo" to print string values obtained from "tput" is dangerous. 699*f875b4ebSrica########## 700*f875b4ebSrica 701*f875b4ebSrica##### 702*f875b4ebSrica# We're confident that most printers don't have backslashes 703*f875b4ebSrica# in the control sequences for carriage return and form-feed. 704*f875b4ebSrica# We're also confident that these don't contain newlines. 705*f875b4ebSrica# We're also confident that most printers have a linefeed 706*f875b4ebSrica# in the control sequence for doing a newline (move to beginning 707*f875b4ebSrica# of next line), but we can't capture it like we do the 708*f875b4ebSrica# carriage return or form-feed. Thus we set it unconditionally. 709*f875b4ebSrica# We don't set form-feed if it isn't defined, however, because 710*f875b4ebSrica# maybe the printer doesn't have a formfeed. If not set, we're 711*f875b4ebSrica# out of luck. 712*f875b4ebSrica##### 713*f875b4ebSrica 714*f875b4ebSricaCR=`${TPUT} cr` 715*f875b4ebSrica[ -z "${CR}" ] && CR="\r" 716*f875b4ebSrica 717*f875b4ebSricaFF=`${TPUT} ff` 718*f875b4ebSricaBFF=$FF 719*f875b4ebSrica[ -z "${BFF}" ] && BFF="\f" 720*f875b4ebSrica 721*f875b4ebSricaNL="${CR}\n" 722*f875b4ebSrica 723*f875b4ebSricalines=`${TPUT} lines` 724*f875b4ebSrica[ -z "${lines}" -o 0 -ge "${lines}" ] && lines=66 725*f875b4ebSrica 726*f875b4ebSricacols=`${TPUT} cols` 727*f875b4ebSrica[ -z "${cols}" -o 0 -ge "${cols}" ] && cols=132 728*f875b4ebSrica 729*f875b4ebSrica##### 730*f875b4ebSrica# 731*f875b4ebSrica# Basic initialization. The ``else'' clause is equivalent, 732*f875b4ebSrica# but covers cases where old Terminal Information Utilities are present. 733*f875b4ebSrica##### 734*f875b4ebSrica[ -n "${stty1}" ] && stty ${stty1} 0<&1 735*f875b4ebSrica 736*f875b4ebSrica# 737*f875b4ebSrica# "tput init" will return an "^M" in many cases to "stdout", i.e., printer! 738*f875b4ebSrica# This creates problems for some PS printers 739*f875b4ebSrica# 740*f875b4ebSricaif [ "${TERM}" = "PS" -o "${TERM}" = "PSR" ] 741*f875b4ebSricathen 742*f875b4ebSrica : 743*f875b4ebSricaelif ${TPUT} init 2>/dev/null 744*f875b4ebSricathen 745*f875b4ebSrica : 746*f875b4ebSricaelse 747*f875b4ebSrica pgm=`${TPUT} iprog` 748*f875b4ebSrica if [ -x "${pgm}" ] 749*f875b4ebSrica then 750*f875b4ebSrica eval ${pgm} 751*f875b4ebSrica fi 752*f875b4ebSrica 753*f875b4ebSrica ${TPUT} is1 754*f875b4ebSrica ${TPUT} is2 755*f875b4ebSrica 756*f875b4ebSrica tabset= 757*f875b4ebSrica if [ "8" != "`${TPUT} it`" ] 758*f875b4ebSrica then 759*f875b4ebSrica stty tab3 0<&1 1>/dev/null 2>&1 760*f875b4ebSrica 761*f875b4ebSrica elif `${TPUT} ht >/dev/null` 762*f875b4ebSrica then 763*f875b4ebSrica tabset="/usr/lib/tabset/${TERM}" 764*f875b4ebSrica if [ -r ${tabset} ] 765*f875b4ebSrica then 766*f875b4ebSrica cat -s ${tabset} 767*f875b4ebSrica fi 768*f875b4ebSrica stty tab3 0<&1 1>/dev/null 2>&1 769*f875b4ebSrica fi 770*f875b4ebSrica 771*f875b4ebSrica file=`${TPUT} if` 772*f875b4ebSrica if [ "${tabset}" != "${file}" -a -r "${file}" ] 773*f875b4ebSrica then 774*f875b4ebSrica cat -s "${file}" 775*f875b4ebSrica fi 776*f875b4ebSrica 777*f875b4ebSrica ${TPUT} is3 778*f875b4ebSrica echo "${CR}\c" 779*f875b4ebSricafi 780*f875b4ebSrica[ -n "${stty2}" ] && stty ${stty2} 0<&1 781*f875b4ebSrica 782*f875b4ebSrica##### 783*f875b4ebSrica# 784*f875b4ebSrica# Set the page size and print spacing, but not the character set. 785*f875b4ebSrica# We will be doing the character set later (after the header). 786*f875b4ebSrica##### 787*f875b4ebSricainternal_lpset "${cpi}" "${lpi}" "${width}" "${length}" "" 788*f875b4ebSrica 789*f875b4ebSrica##### 790*f875b4ebSrica# 791*f875b4ebSrica# The banner page (and cancellation page) will 792*f875b4ebSrica# use double width characters if they're available. 793*f875b4ebSrica##### 794*f875b4ebSricaWIDE_CS=`${TPUT} swidm 2>/dev/null` && NORM_CS=`${TPUT} rwidm 2>/dev/null` 795*f875b4ebSricaPAD="#####${NL}" 796*f875b4ebSrica 797*f875b4ebSrica##### 798*f875b4ebSrica# 799*f875b4ebSrica# Some printers need to have the banner page filtered. 800*f875b4ebSrica##### 801*f875b4ebSricacase "${TERM}" in 802*f875b4ebSrica 803*f875b4ebSricaPS | PSR ) 804*f875b4ebSrica banner_filter="/usr/lib/lp/postscript/postprint | /usr/lib/lp/postscript/postio" 805*f875b4ebSrica LPTELL_OPTS="-l" 806*f875b4ebSrica ;; 807*f875b4ebSrica 808*f875b4ebSricaesac 809*f875b4ebSricaif [ -n "${banner_filter}" ] 810*f875b4ebSricathen 811*f875b4ebSrica banner_filter="| ${banner_filter}" 812*f875b4ebSricafi 813*f875b4ebSrica 814*f875b4ebSrica##### 815*f875b4ebSrica# 816*f875b4ebSrica# Now that the printer is ready for printing, we're able 817*f875b4ebSrica# to record on paper a cancellation. 818*f875b4ebSrica##### 819*f875b4ebSrica 820*f875b4ebSricacancel_banner () { 821*f875b4ebSrica echo "${PAD}${PAD}\c" 822*f875b4ebSrica echo "#####${WIDE_CS} Job ${request_id}${NORM_CS}${NL}\c" 823*f875b4ebSrica echo "#####${WIDE_CS} suspended or canceled${NORM_CS}${NL}\c" 824*f875b4ebSrica echo "${PAD}${PAD}\c" 825*f875b4ebSrica} 826*f875b4ebSrica 827*f875b4ebSricacanceled () { 828*f875b4ebSrica ${TPUT} scs 0 2>/dev/null 829*f875b4ebSrica echo "${CR}\c" 830*f875b4ebSrica if [ "${width:-${cols}}" -lt "${MAX_COLS_SMALL_BANNER}" ] 831*f875b4ebSrica then 832*f875b4ebSrica WIDE_CS= NORM_CS= 833*f875b4ebSrica fi 834*f875b4ebSrica cancel_banner 835*f875b4ebSrica if [ -n "${BFF}" ] 836*f875b4ebSrica then 837*f875b4ebSrica echo "${CR}${BFF}\c" 838*f875b4ebSrica fi 839*f875b4ebSrica} 840*f875b4ebSrica 841*f875b4ebSricatrap 'eval canceled ${banner_filter}; exit_code=0 exit' 15 842*f875b4ebSrica 843*f875b4ebSrica 844*f875b4ebSrica########### 845*f875b4ebSrica## 846*f875b4ebSrica## Print the banner page 847*f875b4ebSrica########### 848*f875b4ebSrica 849*f875b4ebSrica##### 850*f875b4ebSrica# 851*f875b4ebSrica# You may want to change the following code to get a custom banner. 852*f875b4ebSrica##### 853*f875b4ebSrica 854*f875b4ebSricaregular_banner () { 855*f875b4ebSrica echo "${CR}\c" 856*f875b4ebSrica echo "${PAD}${PAD}${PAD}${PAD}${PAD}\c" 857*f875b4ebSrica echo "#####${WIDE_CS} User: ${user_name}${NORM_CS}${NL}\c" 858*f875b4ebSrica if [ -n "$ALIAS_USERNAME" ] 859*f875b4ebSrica then 860*f875b4ebSrica echo "${PAD}\c" 861*f875b4ebSrica echo "#####${WIDE_CS} Alias: ${ALIAS_USERNAME}${NORM_CS}${NL}\c" 862*f875b4ebSrica fi 863*f875b4ebSrica if [ -n "${title}" ] 864*f875b4ebSrica then 865*f875b4ebSrica echo "${PAD}\c" 866*f875b4ebSrica echo "#####${WIDE_CS} Title: ${title}${NORM_CS}${NL}\c" 867*f875b4ebSrica fi 868*f875b4ebSrica echo "${PAD}\c" 869*f875b4ebSrica echo "#####${WIDE_CS} Printed: `LANG=C date '+%a %H:%M %h %d, %Y'`${NORM_CS}${NL}\c" 870*f875b4ebSrica echo "${PAD}\c" 871*f875b4ebSrica echo "#####${WIDE_CS} Job number: ${request_id}${NORM_CS}${NL}\c" 872*f875b4ebSrica echo "${PAD}${PAD}${PAD}${PAD}${PAD}\c" 873*f875b4ebSrica if [ -n "${BFF}" ] 874*f875b4ebSrica then 875*f875b4ebSrica echo "${CR}${BFF}\c" 876*f875b4ebSrica fi 877*f875b4ebSrica} 878*f875b4ebSrica 879*f875b4ebSricasmall_banner () { 880*f875b4ebSrica echo "${CR}\c" 881*f875b4ebSrica echo "${PAD}\c" 882*f875b4ebSrica echo "##### User: ${user_name}${NL}\c" 883*f875b4ebSrica if [ -n "${title}" ] 884*f875b4ebSrica then 885*f875b4ebSrica echo "##### Title: ${title}${NL}\c" 886*f875b4ebSrica fi 887*f875b4ebSrica echo "##### Date: `LANG=C date '+%a %H:%M %h %d, %Y'`${NL}\c" 888*f875b4ebSrica echo "##### Job: ${request_id}${NL}\c" 889*f875b4ebSrica echo "${PAD}\c" 890*f875b4ebSrica if [ -n "${BFF}" ] 891*f875b4ebSrica then 892*f875b4ebSrica echo "${CR}${BFF}\c" 893*f875b4ebSrica fi 894*f875b4ebSrica} 895*f875b4ebSrica 896*f875b4ebSricaif [ "${width:-${cols}}" -lt "${MAX_COLS_SMALL_BANNER}" ] 897*f875b4ebSricathen 898*f875b4ebSrica banner=small_banner 899*f875b4ebSricaelse 900*f875b4ebSrica banner=regular_banner 901*f875b4ebSricafi 902*f875b4ebSrica 903*f875b4ebSrica## Skip this for PS/PSR in TSOL, since lp.tsol_separator handles the banners 904*f875b4ebSricaif [ "no" = "${nobanner}" -a "${TERM}" != "PSR" -a "${TERM}" != "PS" ] 905*f875b4ebSricathen 906*f875b4ebSrica ( eval "${banner} ${banner_filter}" 2>&1 1>&3 ) \ 907*f875b4ebSrica | ${LPTELL} ${LPTELL_OPTS} ${printer} 908*f875b4ebSricafi 909*f875b4ebSrica 910*f875b4ebSrica########### 911*f875b4ebSrica## 912*f875b4ebSrica## Surround the job by PostScript code to produce banner 913*f875b4ebSrica## and trailerpages and page headers and footers. 914*f875b4ebSrica## 915*f875b4ebSrica########### 916*f875b4ebSrica 917*f875b4ebSricaBANNER_EXIT_CODE=${TMPPREFIX}.banner.exit_code 918*f875b4ebSricaecho 0 > ${BANNER_EXIT_CODE} 919*f875b4ebSricaTSOLSEPARATOR_LOG=${TMPPREFIX}.banner.errmsg 920*f875b4ebSrica 921*f875b4ebSricatsol_bannerize () { 922*f875b4ebSrica TSOLSEPARATOR_OPTS="-e ${TSOLSEPARATOR_LOG}" 923*f875b4ebSrica 924*f875b4ebSrica if [ "yes" = "${nolabels}" ] 925*f875b4ebSrica then 926*f875b4ebSrica TSOLSEPARATOR_OPTS="${TSOLSEPARATOR_OPTS} -l" 927*f875b4ebSrica fi 928*f875b4ebSrica 929*f875b4ebSrica if [ "yes" = "${nobanner}" ] 930*f875b4ebSrica then 931*f875b4ebSrica TSOLSEPARATOR_OPTS="${TSOLSEPARATOR_OPTS} -t /dev/null -b /dev/null" 932*f875b4ebSrica fi 933*f875b4ebSrica 934*f875b4ebSrica if [ "${TERM}" = "PSR" ] 935*f875b4ebSrica then 936*f875b4ebSrica TSOLSEPARATOR_OPTS="${TSOLSEPARATOR_OPTS} -r" 937*f875b4ebSrica fi 938*f875b4ebSrica 939*f875b4ebSrica # Get rid of the #, TAB and NL characters in the title 940*f875b4ebSrica tsol_title=`echo $title` 941*f875b4ebSrica tsol_title=`echo $tsol_title | sed 's/#//g'` 942*f875b4ebSrica 943*f875b4ebSrica LC_TIME=C ${LPTSOLSEPARATOR} ${TSOLSEPARATOR_OPTS} "${printer}" \ 944*f875b4ebSrica "${request_id}" "${user_name}" "${tsol_title}" "${file}" 945*f875b4ebSrica echo $? > ${BANNER_EXIT_CODE} 946*f875b4ebSrica true 947*f875b4ebSrica} 948*f875b4ebSrica 949*f875b4ebSricabannerize=tsol_bannerize 950*f875b4ebSrica 951*f875b4ebSricaif [ "yes" = "${nobanner}" -a "yes" = "${nolabels}" ] 952*f875b4ebSricathen 953*f875b4ebSrica bannerize=cat 954*f875b4ebSricafi 955*f875b4ebSrica 956*f875b4ebSricaif [ "${TERM}" != "PSR" -a "${TERM}" != "PS" ] 957*f875b4ebSricathen 958*f875b4ebSrica bannerize=cat 959*f875b4ebSricafi 960*f875b4ebSrica 961*f875b4ebSrica 962*f875b4ebSrica########### 963*f875b4ebSrica## 964*f875b4ebSrica## Initialize the physical printer (Part II) 965*f875b4ebSrica## Here we select the character set. 966*f875b4ebSrica## One could argue that this should be done before the banner is printed, 967*f875b4ebSrica## but we don't, to keep the banner page looking consistent for the 968*f875b4ebSrica## operator. You can move this code before the banner code if you 969*f875b4ebSrica## disagree. If you do, combine it with the other call to "internal_lpset" 970*f875b4ebSrica## to do everything in one shot. 971*f875b4ebSrica########### 972*f875b4ebSricainternal_lpset "" "" "" "" "${CHARSET}" 973*f875b4ebSrica 974*f875b4ebSrica########### 975*f875b4ebSrica## 976*f875b4ebSrica## Print some copies of the file(s) 977*f875b4ebSrica########### 978*f875b4ebSrica 979*f875b4ebSrica##### 980*f875b4ebSrica# 981*f875b4ebSrica# The protocol between the interface program and the Spooler 982*f875b4ebSrica# is fairly simple: 983*f875b4ebSrica# 984*f875b4ebSrica# All standard error output is assumed to indicate a 985*f875b4ebSrica# fault WITH THE REQUEST. The output is mailed to the 986*f875b4ebSrica# user who submitted the print request and the print 987*f875b4ebSrica# request is finished. 988*f875b4ebSrica# 989*f875b4ebSrica# If the interface program sets a zero exit code, 990*f875b4ebSrica# it is assumed that the file printed correctly. 991*f875b4ebSrica# If the interface program sets a non-zero exit code 992*f875b4ebSrica# less than 128, it is assumed that the file did not 993*f875b4ebSrica# print correctly, and the user will be notified. 994*f875b4ebSrica# In either case the print request is finished. 995*f875b4ebSrica# 996*f875b4ebSrica# If the interface program sets an exit code greater 997*f875b4ebSrica# than 128, it is assumed that the file did not print 998*f875b4ebSrica# because of a printer fault. If an alert isn't already 999*f875b4ebSrica# active (see below) one will be activated. (Exit code 1000*f875b4ebSrica# 128 should not be used at all. The shell, which executes 1001*f875b4ebSrica# this program, turns SIGTERM, used to kill this program 1002*f875b4ebSrica# for a cancellation or disabling, into exit 128. The 1003*f875b4ebSrica# Spooler thus interpretes 128 as SIGTERM.) 1004*f875b4ebSrica# 1005*f875b4ebSrica# A message sent to the standard input of the ${LPTELL} 1006*f875b4ebSrica# program is assumed to describe a fault WITH THE PRINTER. 1007*f875b4ebSrica# The output is used in an alert (if alerts are defined). 1008*f875b4ebSrica# If the fault recovery is "wait" or "begin", the printer 1009*f875b4ebSrica# is disabled (killing the interface program if need be), 1010*f875b4ebSrica# and the print request is left on the queue. 1011*f875b4ebSrica# If the fault recovery is "continue", the interface program 1012*f875b4ebSrica# is allowed to wait for the printer fault to be cleared so 1013*f875b4ebSrica# it can resume printing. 1014*f875b4ebSrica# 1015*f875b4ebSrica# This interface program relies on filters to detect printer faults. 1016*f875b4ebSrica# In absence of a filter provided by the customer, it uses a simple 1017*f875b4ebSrica# filter (${LPCAT}) to detect the class of faults that cause DCD 1018*f875b4ebSrica# (``carrier'') drop. The protocol between the interface program and 1019*f875b4ebSrica# the filter: 1020*f875b4ebSrica# 1021*f875b4ebSrica# The filter should exit with zero if printing was 1022*f875b4ebSrica# successful and non-zero if printing failed because 1023*f875b4ebSrica# of a printer fault. This interface program turns a 1024*f875b4ebSrica# non-zero exit of the filter into an "exit 129" from 1025*f875b4ebSrica# itself, thus telling the Spooler that a printer fault 1026*f875b4ebSrica# (still) exists. 1027*f875b4ebSrica# 1028*f875b4ebSrica# The filter should report printer faults via a message 1029*f875b4ebSrica# to its standard error. This interface program takes all 1030*f875b4ebSrica# standard error output from the filter and feeds it as 1031*f875b4ebSrica# standard input to the ${LPTELL} program. 1032*f875b4ebSrica# 1033*f875b4ebSrica# The filter should wait for a printer fault to clear, 1034*f875b4ebSrica# and should resume printing when the fault clears. 1035*f875b4ebSrica# Preferably it should resume at the top of the page 1036*f875b4ebSrica# that was being printed when the fault occurred. 1037*f875b4ebSrica# If it waits and finishes printing, it should exit 1038*f875b4ebSrica# with a 0 exit code. If it can't wait, it should exit 1039*f875b4ebSrica# with a non-zero exit code. 1040*f875b4ebSrica# 1041*f875b4ebSrica# The interface program expects that ANY message on the 1042*f875b4ebSrica# standard error from the filter indicates a printer fault. 1043*f875b4ebSrica# Therefore, a filter should not put user (input) error 1044*f875b4ebSrica# messages on the standard error, but on the standard output 1045*f875b4ebSrica# (where the user can read them when he or she examines 1046*f875b4ebSrica# the print-out). 1047*f875b4ebSrica# 1048*f875b4ebSrica##### 1049*f875b4ebSrica 1050*f875b4ebSricabadfileyet= 1051*f875b4ebSricai=1 1052*f875b4ebSricawhile [ $i -le $copies ] 1053*f875b4ebSricado 1054*f875b4ebSrica for file in ${files} 1055*f875b4ebSrica do 1056*f875b4ebSrica if [ -r "${file}" ] 1057*f875b4ebSrica then 1058*f875b4ebSrica ##### 1059*f875b4ebSrica # 1060*f875b4ebSrica # Here's where we set up the $LPTELL program to 1061*f875b4ebSrica # capture fault messages, and... 1062*f875b4ebSrica # 1063*f875b4ebSrica # Here's where we print the file. 1064*f875b4ebSrica # 1065*f875b4ebSrica # We set up a pipeline to $LPTELL, but play a trick 1066*f875b4ebSrica # to get the filter's standard ERROR piped instead of 1067*f875b4ebSrica # its standard OUTPUT: Divert the standard error (#2) to 1068*f875b4ebSrica # the standard output (#1) IN THE PIPELINE. The shell 1069*f875b4ebSrica # will have changed #1 to be the pipe, not the 1070*f875b4ebSrica # printer, so diverting #2 connects it to the pipe. 1071*f875b4ebSrica # We then change the filter's #1 to a copy of the real 1072*f875b4ebSrica # standard output (the printer port) made earlier, 1073*f875b4ebSrica # so that is connected back to the printer again. 1074*f875b4ebSrica # 1075*f875b4ebSrica # We do all this inside a parenthesized expression 1076*f875b4ebSrica # so that we can get the exit code; this is necessary 1077*f875b4ebSrica # because the exit code of a pipeline is the exit 1078*f875b4ebSrica # code of the right-most command, which isn't the 1079*f875b4ebSrica # filter. 1080*f875b4ebSrica # 1081*f875b4ebSrica # These two tricks could be avoided by using a named 1082*f875b4ebSrica # pipe to connect the standard error to $LPTELL. In 1083*f875b4ebSrica # fact an early prototype of this script did just 1084*f875b4ebSrica # that; however, the named pipe introduced a timing 1085*f875b4ebSrica # problem. The processes that open a named pipe hang 1086*f875b4ebSrica # until both ends of the pipe are opened. Cancelling 1087*f875b4ebSrica # a request or disabling the printer often killed one 1088*f875b4ebSrica # of the processes, causing the other process to hang 1089*f875b4ebSrica # forever waiting for the other end of the pipe to 1090*f875b4ebSrica # be opened. 1091*f875b4ebSrica ##### 1092*f875b4ebSrica EXIT_CODE=${TMPPREFIX}e 1093*f875b4ebSrica trap '' 1 # Let the filter handle a hangup 1094*f875b4ebSrica trap '' 2 3 # and interrupts 1095*f875b4ebSrica ( 1096*f875b4ebSrica ##### 1097*f875b4ebSrica # Put the 0<${file} before the "eval" to keep 1098*f875b4ebSrica # clever users from giving a file name that 1099*f875b4ebSrica # evaluates as something to execute. 1100*f875b4ebSrica ##### 1101*f875b4ebSrica 0<${file} $bannerize | eval ${FILTER} 2>&1 1>&3 1102*f875b4ebSrica echo $? >${EXIT_CODE} 1103*f875b4ebSrica ) | ${LPTELL} ${LPTELL_OPTS} ${printer} 1104*f875b4ebSrica 1105*f875b4ebSrica # if lp.tsol_separator had an error, send its logged 1106*f875b4ebSrica # error message to LPTELL. 1107*f875b4ebSrica banner_exit_code=`cat ${BANNER_EXIT_CODE}` 1108*f875b4ebSrica if [ -n "${banner_exit_code}" -a \ 1109*f875b4ebSrica 0 -ne "${banner_exit_code}" -a \ 1110*f875b4ebSrica -n "${LPTELL}" -a \ 1111*f875b4ebSrica -r "${TSOLSEPARATOR_LOG}" ] 1112*f875b4ebSrica then 1113*f875b4ebSrica cat ${TSOLSEPARATOR_LOG} | ${LPTELL} ${printer} 1114*f875b4ebSrica echo 77 > ${EXIT_CODE} 1115*f875b4ebSrica fi 1116*f875b4ebSrica 1117*f875b4ebSrica trap 'catch_hangup; exit_code=129 exit 129' 1 1118*f875b4ebSrica trap 'catch_interrupt; exit_code=129 exit 129' 2 3 1119*f875b4ebSrica exit_code=`cat ${EXIT_CODE}` 1120*f875b4ebSrica 1121*f875b4ebSrica if [ -n "${exit_code}" -a 0 -ne "${exit_code}" ] 1122*f875b4ebSrica then 1123*f875b4ebSrica trap '' 15 # Avoid dying from disable 1124*f875b4ebSrica sleep 4 # Give $LPTELL a chance to tell 1125*f875b4ebSrica exit ${exit_code} 1126*f875b4ebSrica fi 1127*f875b4ebSrica 1128*f875b4ebSrica if [ -n "${FF}" -a "no" = "${nofilebreak}" ] 1129*f875b4ebSrica then 1130*f875b4ebSrica echo "${CR}${FF}\c" 1131*f875b4ebSrica fi 1132*f875b4ebSrica 1133*f875b4ebSrica else 1134*f875b4ebSrica 1135*f875b4ebSrica ##### 1136*f875b4ebSrica # 1137*f875b4ebSrica # Don't complain about not being able to read 1138*f875b4ebSrica # a file on second and subsequent copies, unless 1139*f875b4ebSrica # we've not complained yet. This removes repeated 1140*f875b4ebSrica # messages about the same file yet reduces the 1141*f875b4ebSrica # chance that the user can remove a file and not 1142*f875b4ebSrica # know that we had trouble finding it. 1143*f875b4ebSrica ##### 1144*f875b4ebSrica if [ "${i}" -le 1 -o -z "${badfileyet}" ] 1145*f875b4ebSrica then 1146*f875b4ebSrica errmsg WARNING ${E_IP_BADFILE} \ 1147*f875b4ebSrica "cannot read file \"${file}\"" \ 1148*f875b4ebSrica "see if the file still exists and is readable, 1149*f875b4ebSrica or consult your system administrator; 1150*f875b4ebSrica printing continues" 1151*f875b4ebSrica badfileyet=yes 1152*f875b4ebSrica fi 1153*f875b4ebSrica 1154*f875b4ebSrica fi 1155*f875b4ebSrica 1156*f875b4ebSrica done 1157*f875b4ebSrica i=`expr $i + 1` 1158*f875b4ebSrica 1159*f875b4ebSricadone 1160*f875b4ebSrica 1161*f875b4ebSrica# Skip this for TSOL, since lp.tsol_separator handles the banners 1162*f875b4ebSrica# 1163*f875b4ebSrica# if [ "no" = "${nobanner}" -a "${TERM}" = "PSR" ] 1164*f875b4ebSrica# then 1165*f875b4ebSrica# ( eval "${banner} ${banner_filter}" 2>&1 1>&3 ) \ 1166*f875b4ebSrica# | ${LPTELL} ${LPTELL_OPTS} ${printer} 1167*f875b4ebSrica# fi 1168*f875b4ebSrica 1169*f875b4ebSricaif [ -n "${exit_code}" -a 0 -ne "${exit_code}" ] 1170*f875b4ebSricathen 1171*f875b4ebSrica exit ${exit_code} 1172*f875b4ebSricafi 1173*f875b4ebSrica 1174*f875b4ebSrica##### 1175*f875b4ebSrica# 1176*f875b4ebSrica# Always ensure the complete job ends with a ``formfeed'', to 1177*f875b4ebSrica# let the next job start on a new page. (If someone wants to 1178*f875b4ebSrica# concatenate files, they can give them in one job.) 1179*f875b4ebSrica# So, if we haven't been putting out a ``formfeed'' between files, 1180*f875b4ebSrica# it means we haven't followed the last file with a formfeed, 1181*f875b4ebSrica# so we do it here. 1182*f875b4ebSrica##### 1183*f875b4ebSricaif [ -n "${FF}" -a "yes" = "${nofilebreak}" ] 1184*f875b4ebSricathen 1185*f875b4ebSrica echo "${CR}${FF}\c" 1186*f875b4ebSricafi 1187*f875b4ebSrica 1188*f875b4ebSrica${DRAIN} 1189*f875b4ebSrica 1190*f875b4ebSricaexit_code=0 exit 0 1191