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