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