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