1#!/bin/ksh 2# 3# CDDL HEADER START 4# 5# The contents of this file are subject to the terms of the 6# Common Development and Distribution License (the "License"). 7# You may not use this file except in compliance with the License. 8# 9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10# or http://www.opensolaris.org/os/licensing. 11# See the License for the specific language governing permissions 12# and limitations under the License. 13# 14# When distributing Covered Code, include this CDDL HEADER in each 15# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16# If applicable, add the following below this CDDL HEADER, with the 17# fields enclosed by brackets "[]" replaced with your own identifying 18# information: Portions Copyright [yyyy] [name of copyright owner] 19# 20# CDDL HEADER END 21# 22# 23# Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24# Use is subject to license terms. 25# 26# ident "%Z%%M% %I% %E% SMI" 27# 28# printer interface script for printers with a URI instead of 29# device name. 30# 31# The existence of a "PPD" environment variable in the calling environment 32# indicates that Foomatic is to be used for filtering all job data as it is 33# streamed to the output device (printer). 34# 35# The contents of a "DEVICE_URI" environment variable in the calling 36# environment indicates the method and endpoint used in communicating with 37# the output device (printer). If no DEVICE_URI is present or the value 38# contains a missing or unknown scheme, the URI scheme is assumed to be 39# "file" and output streaming will be handled accordingly. 40 41export PATH=/bin:/usr/bin:/usr/lib/lp/bin:/usr/sfw/bin 42 43TAG="uri-interface" 44 45 46# Re-arrange fds for later use 47exec 5>&2 2>/dev/null 3>&1 48 49# 50# Exit Codes: 51# 52EXIT_OK=0 53EXIT_FATAL=1 54EXIT_TERM=128 55EXIT_RETRY=129 56 57fail() { # exit-code "message" 58 logger -p lpr.error -t ${TAG} "${2}" 59 echo ${2} >&5 60 exit ${1} 61} 62 63# signal handling 64# EXIT 0 - normal exit 65# HUP 1 - the output stream disconnected 66# INT 2 - the output stream interupted us 67# QUIT 3 - the output stream interupted us 68# TERM 15 - we have been cancelled or shutdown 69 70catch_exit() { 71 exit $exit_code 72} 73 74catch_disconnect() { 75 fail ${EXIT_RETRY} "connection to the printer dropped; off-line?" 76} 77 78catch_interrupt() { 79 fail ${EXIT_RETRY} "interrupt from the printer; baud-rate issues?" 80} 81 82catch_cancellation() { 83 fail ${EXIT_RETRY} "job cancelled" 84} 85 86trap 'catch_disconnect()' HUP 87trap 'catch_interrupt()' INT QUIT 88trap 'catch_cancellation()' TERM 89 90parse_uri() { # scheme://[[user[:password]@]host[:port]]/path 91 URI_SCHEME=$(expr "$1" : "\(.*\)://.*") 92} 93 94parse() { 95 echo "$(expr \"$1\" : \"^[^=]*=\(.*\)\")" 96} 97 98# 99# Generate an ASCII burst page and pass it to the printer 100# This may be much faster than the PostScript(TM) burst page 101# 102ascii_burst_page() { 103 cat <<EOF 104 ${title} 105 Request: ${request_id} 106 User: ${user} 107 Printer: ${printer} 108 Time: $(date) 109 Copies: ${copies} 110EOF 111 tput ff 112} 113 114# 115# Generate a PostScript(TM) burst page (this assumes an 8.5x11 page size) 116# 117postscript_burst_page() { 118 cat <<-EOF 119 %!ps 120 /PrintLine { exch findfont exch scalefont setfont moveto show } def 121 newpath 4 setlinewidth 1 setlinejoin 122 15 760 moveto 595 760 lineto 595 585 lineto 15 585 lineto closepath 123 gsave .75 setgray fill grestore 124 0 setgray stroke 125 (${user}) 30 730 /Times-Bold 24 PrintLine 126 (${request_id}) 415 730 /Times-Bold 24 PrintLine 127 (${printer}) 30 600 /Times-Bold 16 PrintLine 128 ($(date)) 350 600 /Times-Roman 16 PrintLine 129 (${title}) 100 660 /Times-Bold 36 PrintLine 130 (Copies: ${copies}) 30 25 /Times-Roman 16 PrintLine 131 showpage 132 EOF 133} 134 135logger -p lpr.debug -t ${TAG} "$0 $*" 136 137# 138# Detemine if we were called correctly 139# 140if [[ $# -lt 5 ]] ; then 141 fail ${EXIT_FATAL} "wrong number of arguments to interface script" 142fi 143 144 145printer=$(basename $0) 146request_id=$1 147user=$2 148title=$3 149copies=$4 150options=$5 151 152shift 5 153files="$*" 154 155burst_page="postscript_burst_page" 156 157for i in ${options} 158do 159 case "${i}" in 160 161 nobanner ) 162 burst_page="" 163 ;; 164 165 nofilebreak ) 166 nofilebreak="yes" 167 ;; 168 169 burst-page-type=* ) 170 burst_page="$(parse ${i})_burst_page" 171 ;; 172 173 * ) 174 logger -p lpr.error -t ${TAG} \ 175 "unrecognized \"-o ${i}\" option, ignored" 1>&2 176 ;; 177 esac 178done 179 180 181# 182# Procss the DEVICE_URI if we have one 183# 184if [[ -n "${DEVICE_URI}" ]] ; then 185 parse_uri ${DEVICE_URI} # split up the URI 186 187 URI_SCHEME=${URI_SCHEME:-file} # if there is no scheme, assume "file" 188 189 case "${URI_SCHEME}" in 190 file|usb|ecpp|serial|parallel) 191 IO_HANDLER="lp.cat" 192 IO_HANDLER_ARGS="" 193 ;; 194 smb) 195 IO_HANDLER="smbspool" 196 IO_HANDLER_ARGS="${request_id} ${user} \"${title}\" 1 197 \"${options}\"" 198 ;; 199 tcp|socket) 200 URI_HOST=$(expr "${DEVICE_URI}" : ".*://\([^:/]*\)") 201 URI_PORT=$(expr "${DEVICE_URI}" : ".*://.*:\([^/]*\)") 202 if [[ -z "${URI_HOST}" ]] ; then 203 fail ${EXIT_FATAL} "invalid device-uri: ${DEVICE_URI}, reset with lpadmin -v" 204 fi 205 URI_PORT=${URI_PORT:-"9100"} 206 IO_HANDLER="telnet" 207 IO_HANDLER_ARGS="-c -E ${URI_HOST} ${URI_PORT}" 208 ;; 209 lpd|ipp) 210 IO_HANDLER="lp" 211 IO_HANDLER_ARGS="-s -d ${DEVICE_URI}" 212 ;; 213 *) 214 IO_HANDLER=${URI_SCHEME} 215 IO_HANDLER_ARGS="" 216 ;; 217 esac 218fi 219IO_HANDLER=${IO_HANDLER:-"lp.cat"} # if IO_HANDLER is still unset, use lp.cat 220 221# determine if the IO handler is available for us to use when communicating with 222# the output device (printer.) 223whence ${IO_HANDLER} >/dev/null 224if [[ $? -ne 0 ]] ; then 225 fail ${ERR_FATAL} \ 226 "Interface script unable to locate IO handler: ${IO_HANDLER}" 227fi 228 229# There is a PPD file specified, so use foomatic 230if [[ -n "${PPD}" ]] ; then 231 FILTER_CHAIN="| foomatic-rip" 232fi 233 234# 235# Start processing the job here 236# 237set | logger -p lpr.debug -t "${TAG}" 238 239( 240 if [[ -n "${burst_page}" ]] ; then 241 eval "${burst_page} ${FILTER_CHAIN}" 242 fi 243 while [[ $copies -gt 0 ]] ; do 244 for file in ${files} ; do 245 if [[ -r "${file}" ]] ; then 246 eval "cat ${file} ${FILTER_CHAIN}" 247 fi 248 done 249 copies=$(( copies - 1 )) 250 done 251) | ${IO_HANDLER} ${IO_HANDLER_ARGS} 252 253exit ${EXIT_OK} 254