xref: /illumos-gate/usr/src/cmd/lp/model/uri (revision 16d8656330ae5622ec32e5007f62145ebafdc50f)
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