10Sstevel@tonic-gate#!/bin/ksh 20Sstevel@tonic-gate# 30Sstevel@tonic-gate# CDDL HEADER START 40Sstevel@tonic-gate# 50Sstevel@tonic-gate# The contents of this file are subject to the terms of the 6*3999Sjacobs# Common Development and Distribution License (the "License"). 7*3999Sjacobs# You may not use this file except in compliance with the License. 80Sstevel@tonic-gate# 90Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate# See the License for the specific language governing permissions 120Sstevel@tonic-gate# and limitations under the License. 130Sstevel@tonic-gate# 140Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate# 200Sstevel@tonic-gate# CDDL HEADER END 210Sstevel@tonic-gate# 220Sstevel@tonic-gate# 23*3999Sjacobs# Copyright 2007 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate# Use is subject to license terms. 250Sstevel@tonic-gate# 260Sstevel@tonic-gate# ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate# 280Sstevel@tonic-gate# printer interface script for printers with a URI instead of 290Sstevel@tonic-gate# device name. 300Sstevel@tonic-gate# 310Sstevel@tonic-gate# The existence of a "PPD" environment variable in the calling environment 320Sstevel@tonic-gate# indicates that Foomatic is to be used for filtering all job data as it is 330Sstevel@tonic-gate# streamed to the output device (printer). 340Sstevel@tonic-gate# 350Sstevel@tonic-gate# The contents of a "DEVICE_URI" environment variable in the calling 360Sstevel@tonic-gate# environment indicates the method and endpoint used in communicating with 370Sstevel@tonic-gate# the output device (printer). If no DEVICE_URI is present or the value 380Sstevel@tonic-gate# contains a missing or unknown scheme, the URI scheme is assumed to be 390Sstevel@tonic-gate# "file" and output streaming will be handled accordingly. 400Sstevel@tonic-gate 410Sstevel@tonic-gateexport PATH=/bin:/usr/bin:/usr/lib/lp/bin:/usr/sfw/bin 420Sstevel@tonic-gate 430Sstevel@tonic-gateTAG="uri-interface" 440Sstevel@tonic-gate 450Sstevel@tonic-gate 460Sstevel@tonic-gate# Re-arrange fds for later use 470Sstevel@tonic-gateexec 5>&2 2>/dev/null 3>&1 480Sstevel@tonic-gate 490Sstevel@tonic-gate# 500Sstevel@tonic-gate# Exit Codes: 510Sstevel@tonic-gate# 520Sstevel@tonic-gateEXIT_OK=0 530Sstevel@tonic-gateEXIT_FATAL=1 540Sstevel@tonic-gateEXIT_TERM=128 550Sstevel@tonic-gateEXIT_RETRY=129 560Sstevel@tonic-gate 570Sstevel@tonic-gatefail() { # exit-code "message" 58*3999Sjacobs logger -p lpr.error -t ${TAG} "${2}" 590Sstevel@tonic-gate echo ${2} >&5 600Sstevel@tonic-gate exit ${1} 610Sstevel@tonic-gate} 620Sstevel@tonic-gate 630Sstevel@tonic-gate# signal handling 640Sstevel@tonic-gate# EXIT 0 - normal exit 650Sstevel@tonic-gate# HUP 1 - the output stream disconnected 660Sstevel@tonic-gate# INT 2 - the output stream interupted us 670Sstevel@tonic-gate# QUIT 3 - the output stream interupted us 680Sstevel@tonic-gate# TERM 15 - we have been cancelled or shutdown 690Sstevel@tonic-gate 700Sstevel@tonic-gatecatch_exit() { 710Sstevel@tonic-gate exit $exit_code 720Sstevel@tonic-gate} 730Sstevel@tonic-gate 740Sstevel@tonic-gatecatch_disconnect() { 750Sstevel@tonic-gate fail ${EXIT_RETRY} "connection to the printer dropped; off-line?" 760Sstevel@tonic-gate} 770Sstevel@tonic-gate 780Sstevel@tonic-gatecatch_interrupt() { 790Sstevel@tonic-gate fail ${EXIT_RETRY} "interrupt from the printer; baud-rate issues?" 800Sstevel@tonic-gate} 810Sstevel@tonic-gate 820Sstevel@tonic-gatecatch_cancellation() { 830Sstevel@tonic-gate fail ${EXIT_RETRY} "job cancelled" 840Sstevel@tonic-gate} 850Sstevel@tonic-gate 860Sstevel@tonic-gatetrap 'catch_disconnect()' HUP 870Sstevel@tonic-gatetrap 'catch_interrupt()' INT QUIT 880Sstevel@tonic-gatetrap 'catch_cancellation()' TERM 890Sstevel@tonic-gate 900Sstevel@tonic-gateparse_uri() { # scheme://[[user[:password]@]host[:port]]/path 910Sstevel@tonic-gate URI_SCHEME=$(expr "$1" : "\(.*\)://.*") 920Sstevel@tonic-gate} 930Sstevel@tonic-gate 940Sstevel@tonic-gateparse() { 950Sstevel@tonic-gate echo "$(expr \"$1\" : \"^[^=]*=\(.*\)\")" 960Sstevel@tonic-gate} 970Sstevel@tonic-gate 980Sstevel@tonic-gate# 990Sstevel@tonic-gate# Generate an ASCII burst page and pass it to the printer 1000Sstevel@tonic-gate# This may be much faster than the PostScript(TM) burst page 1010Sstevel@tonic-gate# 1020Sstevel@tonic-gateascii_burst_page() { 1030Sstevel@tonic-gate cat <<EOF 1040Sstevel@tonic-gate ${title} 1050Sstevel@tonic-gate Request: ${request_id} 1060Sstevel@tonic-gate User: ${user} 1070Sstevel@tonic-gate Printer: ${printer} 1080Sstevel@tonic-gate Time: $(date) 1090Sstevel@tonic-gate Copies: ${copies} 1100Sstevel@tonic-gateEOF 1110Sstevel@tonic-gate tput ff 1120Sstevel@tonic-gate} 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate# 1150Sstevel@tonic-gate# Generate a PostScript(TM) burst page (this assumes an 8.5x11 page size) 1160Sstevel@tonic-gate# 1170Sstevel@tonic-gatepostscript_burst_page() { 1180Sstevel@tonic-gate cat <<-EOF 1190Sstevel@tonic-gate %!ps 1200Sstevel@tonic-gate /PrintLine { exch findfont exch scalefont setfont moveto show } def 1210Sstevel@tonic-gate newpath 4 setlinewidth 1 setlinejoin 1220Sstevel@tonic-gate 15 760 moveto 595 760 lineto 595 585 lineto 15 585 lineto closepath 1230Sstevel@tonic-gate gsave .75 setgray fill grestore 1240Sstevel@tonic-gate 0 setgray stroke 1250Sstevel@tonic-gate (${user}) 30 730 /Times-Bold 24 PrintLine 1260Sstevel@tonic-gate (${request_id}) 415 730 /Times-Bold 24 PrintLine 1270Sstevel@tonic-gate (${printer}) 30 600 /Times-Bold 16 PrintLine 1280Sstevel@tonic-gate ($(date)) 350 600 /Times-Roman 16 PrintLine 1290Sstevel@tonic-gate (${title}) 100 660 /Times-Bold 36 PrintLine 1300Sstevel@tonic-gate (Copies: ${copies}) 30 25 /Times-Roman 16 PrintLine 1310Sstevel@tonic-gate showpage 1320Sstevel@tonic-gate EOF 1330Sstevel@tonic-gate} 1340Sstevel@tonic-gate 1350Sstevel@tonic-gatelogger -p lpr.debug -t ${TAG} "$0 $*" 1360Sstevel@tonic-gate 1370Sstevel@tonic-gate# 1380Sstevel@tonic-gate# Detemine if we were called correctly 1390Sstevel@tonic-gate# 1400Sstevel@tonic-gateif [[ $# -lt 5 ]] ; then 1410Sstevel@tonic-gate fail ${EXIT_FATAL} "wrong number of arguments to interface script" 1420Sstevel@tonic-gatefi 1430Sstevel@tonic-gate 1440Sstevel@tonic-gate 1450Sstevel@tonic-gateprinter=$(basename $0) 1460Sstevel@tonic-gaterequest_id=$1 1470Sstevel@tonic-gateuser=$2 1480Sstevel@tonic-gatetitle=$3 1490Sstevel@tonic-gatecopies=$4 1500Sstevel@tonic-gateoptions=$5 1510Sstevel@tonic-gate 1520Sstevel@tonic-gateshift 5 1530Sstevel@tonic-gatefiles="$*" 1540Sstevel@tonic-gate 1550Sstevel@tonic-gateburst_page="postscript_burst_page" 1560Sstevel@tonic-gate 1570Sstevel@tonic-gatefor i in ${options} 1580Sstevel@tonic-gatedo 1590Sstevel@tonic-gate case "${i}" in 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate nobanner ) 1620Sstevel@tonic-gate burst_page="" 1630Sstevel@tonic-gate ;; 1640Sstevel@tonic-gate 1650Sstevel@tonic-gate nofilebreak ) 1660Sstevel@tonic-gate nofilebreak="yes" 1670Sstevel@tonic-gate ;; 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate burst-page-type=* ) 1700Sstevel@tonic-gate burst_page="$(parse ${i})_burst_page" 1710Sstevel@tonic-gate ;; 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate * ) 1740Sstevel@tonic-gate logger -p lpr.error -t ${TAG} \ 1750Sstevel@tonic-gate "unrecognized \"-o ${i}\" option, ignored" 1>&2 1760Sstevel@tonic-gate ;; 1770Sstevel@tonic-gate esac 1780Sstevel@tonic-gatedone 1790Sstevel@tonic-gate 1800Sstevel@tonic-gate 1810Sstevel@tonic-gate# 1820Sstevel@tonic-gate# Procss the DEVICE_URI if we have one 1830Sstevel@tonic-gate# 1840Sstevel@tonic-gateif [[ -n "${DEVICE_URI}" ]] ; then 1850Sstevel@tonic-gate parse_uri ${DEVICE_URI} # split up the URI 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate URI_SCHEME=${URI_SCHEME:-file} # if there is no scheme, assume "file" 1880Sstevel@tonic-gate 1890Sstevel@tonic-gate case "${URI_SCHEME}" in 1900Sstevel@tonic-gate file|usb|ecpp|serial|parallel) 1910Sstevel@tonic-gate IO_HANDLER="lp.cat" 1920Sstevel@tonic-gate IO_HANDLER_ARGS="" 1930Sstevel@tonic-gate ;; 1940Sstevel@tonic-gate smb) 1950Sstevel@tonic-gate IO_HANDLER="smbspool" 1960Sstevel@tonic-gate IO_HANDLER_ARGS="${request_id} ${user} \"${title}\" 1 1970Sstevel@tonic-gate \"${options}\"" 1980Sstevel@tonic-gate ;; 199*3999Sjacobs tcp|socket) 200*3999Sjacobs URI_HOST=$(expr "${DEVICE_URI}" : ".*://\([^:/]*\)") 201*3999Sjacobs URI_PORT=$(expr "${DEVICE_URI}" : ".*://.*:\([^/]*\)") 202*3999Sjacobs if [[ -z "${URI_HOST}" ]] ; then 203*3999Sjacobs fail ${EXIT_FATAL} "invalid device-uri: ${DEVICE_URI}, reset with lpadmin -v" 204*3999Sjacobs fi 205*3999Sjacobs URI_PORT=${URI_PORT:-"9100"} 206*3999Sjacobs IO_HANDLER="telnet" 207*3999Sjacobs IO_HANDLER_ARGS="-c -E ${URI_HOST} ${URI_PORT}" 208*3999Sjacobs ;; 209*3999Sjacobs lpd|ipp) 210*3999Sjacobs IO_HANDLER="lp" 211*3999Sjacobs IO_HANDLER_ARGS="-s -d ${DEVICE_URI}" 212*3999Sjacobs ;; 2130Sstevel@tonic-gate *) 2140Sstevel@tonic-gate IO_HANDLER=${URI_SCHEME} 2150Sstevel@tonic-gate IO_HANDLER_ARGS="" 2160Sstevel@tonic-gate ;; 2170Sstevel@tonic-gate esac 2180Sstevel@tonic-gatefi 2190Sstevel@tonic-gateIO_HANDLER=${IO_HANDLER:-"lp.cat"} # if IO_HANDLER is still unset, use lp.cat 2200Sstevel@tonic-gate 2210Sstevel@tonic-gate# determine if the IO handler is available for us to use when communicating with 2220Sstevel@tonic-gate# the output device (printer.) 2230Sstevel@tonic-gatewhence ${IO_HANDLER} >/dev/null 2240Sstevel@tonic-gateif [[ $? -ne 0 ]] ; then 2250Sstevel@tonic-gate fail ${ERR_FATAL} \ 2260Sstevel@tonic-gate "Interface script unable to locate IO handler: ${IO_HANDLER}" 2270Sstevel@tonic-gatefi 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate# There is a PPD file specified, so use foomatic 2300Sstevel@tonic-gateif [[ -n "${PPD}" ]] ; then 2310Sstevel@tonic-gate FILTER_CHAIN="| foomatic-rip" 2320Sstevel@tonic-gatefi 2330Sstevel@tonic-gate 2340Sstevel@tonic-gate# 2350Sstevel@tonic-gate# Start processing the job here 2360Sstevel@tonic-gate# 2370Sstevel@tonic-gateset | logger -p lpr.debug -t "${TAG}" 2380Sstevel@tonic-gate 2390Sstevel@tonic-gate( 2400Sstevel@tonic-gate if [[ -n "${burst_page}" ]] ; then 2410Sstevel@tonic-gate eval "${burst_page} ${FILTER_CHAIN}" 2420Sstevel@tonic-gate fi 2430Sstevel@tonic-gate while [[ $copies -gt 0 ]] ; do 2440Sstevel@tonic-gate for file in ${files} ; do 2450Sstevel@tonic-gate if [[ -r "${file}" ]] ; then 2460Sstevel@tonic-gate eval "cat ${file} ${FILTER_CHAIN}" 2470Sstevel@tonic-gate fi 2480Sstevel@tonic-gate done 2490Sstevel@tonic-gate copies=$(( copies - 1 )) 2500Sstevel@tonic-gate done 2510Sstevel@tonic-gate) | ${IO_HANDLER} ${IO_HANDLER_ARGS} 2520Sstevel@tonic-gate 2530Sstevel@tonic-gateexit ${EXIT_OK} 254