#!/bin/ksh # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # # printer interface script for printers with a URI instead of # device name. # # The existence of a "PPD" environment variable in the calling environment # indicates that Foomatic is to be used for filtering all job data as it is # streamed to the output device (printer). # # The contents of a "DEVICE_URI" environment variable in the calling # environment indicates the method and endpoint used in communicating with # the output device (printer). If no DEVICE_URI is present or the value # contains a missing or unknown scheme, the URI scheme is assumed to be # "file" and output streaming will be handled accordingly. export PATH=/bin:/usr/bin:/usr/lib/lp/bin:/usr/sfw/bin TAG="uri-interface" # Re-arrange fds for later use exec 5>&2 2>/dev/null 3>&1 # # Exit Codes: # EXIT_OK=0 EXIT_FATAL=1 EXIT_TERM=128 EXIT_RETRY=129 fail() { # exit-code "message" logger -p lpr.error -t ${TAG} "${2}" echo ${2} >&5 exit ${1} } # signal handling # EXIT 0 - normal exit # HUP 1 - the output stream disconnected # INT 2 - the output stream interupted us # QUIT 3 - the output stream interupted us # TERM 15 - we have been cancelled or shutdown catch_exit() { exit $exit_code } catch_disconnect() { fail ${EXIT_RETRY} "connection to the printer dropped; off-line?" } catch_interrupt() { fail ${EXIT_RETRY} "interrupt from the printer; baud-rate issues?" } catch_cancellation() { fail ${EXIT_RETRY} "job cancelled" } trap 'catch_disconnect()' HUP trap 'catch_interrupt()' INT QUIT trap 'catch_cancellation()' TERM parse_uri() { # scheme://[[user[:password]@]host[:port]]/path URI_SCHEME=$(expr "$1" : "\(.*\)://.*") } parse() { echo "$(expr \"$1\" : \"^[^=]*=\(.*\)\")" } # # Generate an ASCII burst page and pass it to the printer # This may be much faster than the PostScript(TM) burst page # ascii_burst_page() { cat <<EOF ${title} Request: ${request_id} User: ${user} Printer: ${printer} Time: $(date) Copies: ${copies} EOF tput ff } # # Generate a PostScript(TM) burst page (this assumes an 8.5x11 page size) # postscript_burst_page() { cat <<-EOF %!ps /PrintLine { exch findfont exch scalefont setfont moveto show } def newpath 4 setlinewidth 1 setlinejoin 15 760 moveto 595 760 lineto 595 585 lineto 15 585 lineto closepath gsave .75 setgray fill grestore 0 setgray stroke (${user}) 30 730 /Times-Bold 24 PrintLine (${request_id}) 415 730 /Times-Bold 24 PrintLine (${printer}) 30 600 /Times-Bold 16 PrintLine ($(date)) 350 600 /Times-Roman 16 PrintLine (${title}) 100 660 /Times-Bold 36 PrintLine (Copies: ${copies}) 30 25 /Times-Roman 16 PrintLine showpage EOF } logger -p lpr.debug -t ${TAG} "$0 $*" # # Detemine if we were called correctly # if [[ $# -lt 5 ]] ; then fail ${EXIT_FATAL} "wrong number of arguments to interface script" fi printer=$(basename $0) request_id=$1 user=$2 title=$3 copies=$4 options=$5 shift 5 files="$*" burst_page="postscript_burst_page" for i in ${options} do case "${i}" in nobanner ) burst_page="" ;; nofilebreak ) nofilebreak="yes" ;; burst-page-type=* ) burst_page="$(parse ${i})_burst_page" ;; * ) logger -p lpr.error -t ${TAG} \ "unrecognized \"-o ${i}\" option, ignored" 1>&2 ;; esac done # # Procss the DEVICE_URI if we have one # if [[ -n "${DEVICE_URI}" ]] ; then parse_uri ${DEVICE_URI} # split up the URI URI_SCHEME=${URI_SCHEME:-file} # if there is no scheme, assume "file" case "${URI_SCHEME}" in file|usb|ecpp|serial|parallel) IO_HANDLER="lp.cat" IO_HANDLER_ARGS="" ;; smb) IO_HANDLER="smbspool" IO_HANDLER_ARGS="${request_id} ${user} \"${title}\" 1 \"${options}\"" ;; tcp|socket) URI_HOST=$(expr "${DEVICE_URI}" : ".*://\([^:/]*\)") URI_PORT=$(expr "${DEVICE_URI}" : ".*://.*:\([^/]*\)") if [[ -z "${URI_HOST}" ]] ; then fail ${EXIT_FATAL} "invalid device-uri: ${DEVICE_URI}, reset with lpadmin -v" fi URI_PORT=${URI_PORT:-"9100"} IO_HANDLER="telnet" IO_HANDLER_ARGS="-c -E ${URI_HOST} ${URI_PORT}" ;; lpd|ipp) IO_HANDLER="lp" IO_HANDLER_ARGS="-s -d ${DEVICE_URI}" ;; *) IO_HANDLER=${URI_SCHEME} IO_HANDLER_ARGS="" ;; esac fi IO_HANDLER=${IO_HANDLER:-"lp.cat"} # if IO_HANDLER is still unset, use lp.cat # determine if the IO handler is available for us to use when communicating with # the output device (printer.) whence ${IO_HANDLER} >/dev/null if [[ $? -ne 0 ]] ; then fail ${ERR_FATAL} \ "Interface script unable to locate IO handler: ${IO_HANDLER}" fi # There is a PPD file specified, so use foomatic if [[ -n "${PPD}" ]] ; then FILTER_CHAIN="| foomatic-rip" fi # # Start processing the job here # set | logger -p lpr.debug -t "${TAG}" ( if [[ -n "${burst_page}" ]] ; then eval "${burst_page} ${FILTER_CHAIN}" fi while [[ $copies -gt 0 ]] ; do for file in ${files} ; do if [[ -r "${file}" ]] ; then eval "cat ${file} ${FILTER_CHAIN}" fi done copies=$(( copies - 1 )) done ) | ${IO_HANDLER} ${IO_HANDLER_ARGS} exit ${EXIT_OK}