xref: /titanic_52/usr/src/cmd/print/scripts/lpadmin (revision 0209230bf1261579beab4f55226bb509e6b850cb)
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 2006 Sun Microsystems, Inc.  All rights reserved.
24# Use is subject to license terms.
25#
26# ident	"%Z%%M%	%I%	%E% SMI"
27#
28PATH=/bin:/usr/bin:/usr/sbin export PATH
29
30TEXTDOMAIN="SUNW_OST_OSCMD"
31export TEXTDOMAIN
32
33LPSET=/usr/bin/lpset
34LPGET=/usr/bin/lpget
35LPSTAT=/usr/bin/lpstat
36LPADMIN=/usr/lib/lp/local/lpadmin
37
38HOST=$(/bin/uname -n)
39exit_code=0
40
41usage() {
42	gettext "Usage:\n" 1>&2
43	gettext "	lpadmin -p (printer) (options)\n" 1>&2
44	gettext "	lpadmin -x (dest)\n" 1>&2
45	gettext "	lpadmin -d (dest)\n" 1>&2
46	gettext "	lpadmin -S print-wheel -A alert-type [ -W minutes ]\n" 1>&2
47	gettext "		[ -Q requests ]\n" 1>&2
48	gettext "	lpadmin -M -f form-name [ -a [ -o filebreak ]\n" 1>&2
49	gettext "		[ -t tray-number ]]\n" 1>&2
50	exit 1
51}
52
53# echo names in ${1} that are not in ${2}
54missing() {
55	for i in ${1} ; do
56		MATCHED=0
57		for j in ${2} ; do
58			if [[ $i = $j ]] ; then
59				MATCHED=1
60			fi
61		done
62		if [[ $MATCHED == 0 ]] ; then
63			echo $i
64		fi
65	done
66}
67
68# create a filter table for LP service
69lp_config_filters() {
70	if [[ ! -f /etc/lp/filter.table ]] ; then
71		cd /etc/lp/fd ; for filter in *.fd ; do
72			/usr/sbin/lpfilter \
73				-f $(/usr/bin/basename $filter .fd) \
74				-F $filter
75		done
76	fi
77}
78
79# enable/disable LP related service(s)
80lp_config_service() {	# (enable | disable)
81	svcadm ${1} -s svc:/application/print/server:default
82	# svcadm ${1} -s svc:/application/print/rfc1179:default
83	# svcadm ${1} -s svc:/application/print/ipp-listener:default
84}
85
86# synchronize printers.conf with LP configuration changes
87lp_config_sync_pconf() {	# (pre) (post)
88	if [[ "${1}" != "${2}" ]] ; then
89		ADDED=$(missing "${2}" "${1}")
90		REMOVED=$(missing "${1}" "${2}")
91
92		lp_server=${server:-${HOST}}
93		for DEST in ${ADDED} ; do
94			lp_uri="ipp://${lp_server}/printers/${DEST}"
95			lp_bsdaddr="${lp_server},${DEST},Solaris"
96			${LPSET} -n system \
97				-a "printer-uri-supported=${lp_uri}" \
98				-a "bsdaddr=${lp_bsdaddr}" \
99			 	${DEST} 2>/dev/null
100		done
101
102		for DEST in ${REMOVED} ; do
103			${LPSET} -n system -x ${DEST} 2>/dev/null
104		done
105	fi
106}
107
108# Delete all destinations in printers.conf
109delete_all() {
110	for DEST in $(lpget -n system list | egrep -e '.+:$' | sed -e 's/://')
111	do
112		${LPSET} -n system -x ${DEST}
113		status=$?
114	done
115}
116
117#
118# Execution begins here
119#
120
121# be sure that we can run lpset and lpget
122if [[ ! -x ${LPSET} || ! -x ${LPGET} ]] ; then
123	gettext "lpadmin: System error; cannot set default printer\n" 1>&2
124	exit 2
125fi
126
127if [[ $# -lt 1 ]] ; then
128	usage
129	exit 1
130fi
131
132# Deal with the -d option independently since getopts does not handle
133# options that may or may not have arguments
134#
135if [[ ${1} = "-d" ]] ; then
136	if [[ $# -eq 1 ]] ; then	# remove the "default"
137		${LPGET} -n system _default >/dev/null 2>&1
138		exit_code=$?
139
140		if [[ ${exit_code} -eq 0 ]] ; then
141			${LPSET} -n system -x _default
142			exit_code=$?
143		else	# no default, nothing to do
144			exit_code=0
145		fi
146	elif [[ $# -eq 2 ]] ; then	# add/change the "default"
147		${LPGET} -k bsdaddr ${2} >/dev/null 2>&1
148		exit_code=$?
149
150		if [[ $exit_code -eq 0 ]] ; then
151			${LPSET} -n system -a "use=${2}" _default
152			exit_code=$?
153		else	# can't set default to an unconfigured printer
154			gettext "${2}: undefined printer\n" 1>&1
155		fi
156	else				# invalid usage
157		usage
158		exit 1
159	fi
160
161	exit ${exit_code}
162fi
163
164#		Strip off legal options
165while getopts "A:ac:D:e:f:F:H:hi:I:lm:Mn:o:p:Q:r:S:s:T:u:U:v:W:x:t:P:" arg
166do
167	case $arg in
168	D)
169		description="${OPTARG}"
170	;;
171	p)
172		if [[ -n "${delete}" ]] ; then
173			usage
174		fi
175		printer=${OPTARG}
176	;;
177	s)
178		server=${OPTARG}
179	;;
180	v|U)
181		device=${OPTARG}
182		if [[ ! -n "${server}" ]] ; then
183			server=${HOST}
184		fi
185		local="true"
186	;;
187	x)
188		if [[ -n "${printer}" || -n "${server}" || \
189		     -n "${device}" || -n "${description}" ]] ; then
190			usage
191		fi
192		delete=${OPTARG}
193		printer=${OPTARG}
194		if [[ ${printer} = "all" ]] ; then
195			local="true"
196		fi
197	;;
198	S|M|A)
199		local="true"
200	;;
201	c)
202		class=${OPTARG}
203		local="true"
204		if [[ ! -f ${LPGET} ]] ; then
205			gettext "lpadmin: System error; cannot set class\n " 1>&2
206			exit 2
207		fi
208
209		${LPGET} "${class}" > /dev/null 2>&1
210		lpget_class=$?
211		if [[ ${lpget_class} -eq 0 && ! -r /etc/lp/classes/"${class}" ]] ; then
212			gettext "lpadmin: ERROR: Can't create class ${class}.\n" 1>&2
213			gettext "           TO FIX: This is an existing printer name;\n" 1>&2
214			gettext "                   choose another name.\n" 1>&2
215			exit 1
216		fi
217	;;
218	r)
219		local="true"
220	;;
221	esac
222done
223
224#
225# We don't have anything to do; let user know and bail
226#
227if [[ ! -n "${printer}" && ! -n "${delete}" && ! -n "${local}" ]] ; then
228	gettext "lpadmin: ERROR: Nothing to do.\n" 1>&2
229	gettext "        TO FIX: You must give one of these options:\n" 1>&2
230	gettext "		      -p, -d, -x -S\n" 1>&2
231	exit 1
232fi
233
234#
235#       Printer does not exist
236#       To be consistent with 2.5, assume adding local printer
237#
238if [[ ! -n "${device}" && ! -n "${server}" && ! -n "${delete}" && \
239	  ! -n "${local}" ]] ; then
240	${LPGET} "${printer}" > /dev/null 2>&1
241	lpget_stat=$?
242	if [[ ${lpget_stat} -ne 0 ]] ; then
243		gettext "lpadmin: ERROR: Missing -U or -v option.\n" 1>&2
244		gettext "           TO FIX: Local printers must have\n" 1>&2
245		gettext "                   a port defined (-v option) or\n" 1>&2
246		gettext "                   have dial-out instructions (-U option).\n" 1>&2
247		exit 1
248	fi
249fi
250
251#	process the "server" value
252#	It can be a hostname, UUCP form (server!queue), RCMD form(queue@server),
253#	or in URI form ({scheme}://{endpoint})
254#
255case "${server}" in
256	*://*)	# URI form
257		uri=${server}
258		rem_printer=$(expr "${server}" : ".*://.*/\([^/]*\)")
259		server=$(expr "${server}" : ".*://\([^/]*\)/.*")
260		;;
261	*@*)	# RCMD form
262		rem_printer=$(expr "${server}" : "\(.*\)@.*")
263		server=$(expr "${server}" : ".*@\(.*\)")
264		;;
265	*!*)	# UUCP form
266		rem_printer=$(expr "${server}" : ".*!\(.*\)")
267		server=$(expr "${server}" : "\(.*\)!.*")
268		;;
269	*)	# hostname
270		rem_printer=${printer}
271		;;
272esac
273
274if [[ -n "${server}" ]] ; then
275	# if we need a uri, find the "best" one.
276	if [[ -z "${uri}" ]] ; then
277		uri="ipp://${server}/printers/${rem_printer}"
278		${LPSTAT} -p ${uri} >/dev/null 2>&1
279		if [[ $? -ne 0 ]] ; then
280			uri="lpd://${server}/printers/${rem_printer}#Solaris"
281		fi
282	fi
283	# set the bsdaddr
284	bsdaddr="${server},${rem_printer},Solaris"
285fi
286
287# if there is a "device" or LP configuration, it's local
288if [[ -n "${device}" || -f /etc/lp/printers/${printer}/configuration || \
289      -f /etc/lp/classes/${printer} ]] ; then
290	local="true"
291fi
292
293# Do the LP configuration for a local printer served by lpsched
294if [[ -x ${LPADMIN} && -n "${local}" ]] ; then
295	# enumerate LP configured printers before modification
296	PRE=$(/bin/ls /etc/lp/printers 2>/dev/null ; /bin/ls /etc/lp/classes \
297		2>/dev/null)
298
299	# if there are no printers configured, enable LP service(s)
300	[[ -z "${PRE}" ]] && lp_config_service enable
301
302	# add filters to LP service
303	lp_config_filters
304
305	# modify LP destination(s)
306	CMD=${LPADMIN}
307	while [[ -n "$*" ]] ; do	# to deal with multi-word arguments
308		CMD="$CMD \"$1\""
309		shift
310	done
311	case "$CMD" in
312		*\"-D\")
313			CMD="$CMD \"\""
314		;;
315	esac
316
317	# execute the LP lpadmin command
318	eval $CMD
319	exit_code=$?
320
321	# enumerate LP configured printers after modification
322	POST=$(/bin/ls /etc/lp/printers 2>/dev/null ; /bin/ls /etc/lp/classes \
323                    2>/dev/null)
324
325	# if there are no destinations, disable the service(s)
326	[[ -z "${POST}" ]] && lp_config_service disable
327
328	# sync printers.conf with LP configuration
329	lp_config_sync_pconf "${PRE}" "${POST}"
330fi
331
332# Do any printers.conf configuration that is required
333if [[ -n "${delete}" ]] ; then
334	if [[ "${delete}" = "all" ]] ; then
335		[[ $exit_code -eq 0 ]] && delete_all
336   	elif [[ -z "${local}" ]] ; then
337   		${LPSET} -n system -x ${delete}
338   		exit_code=$?
339   	fi
340elif [[ -z "${local}" ]] ; then
341	if [[ -n "${printer}" ]] ; then
342		${LPSET} -n system \
343			-a "printer-uri-supported=${uri}" \
344			-a "bsdaddr=${bsdaddr}" ${printer}
345		exit_code=$?
346	fi
347
348	if [[ -n "${printer}" && -n "${description}" ]] ; then
349		${LPSET} -n system \
350			-a "description=${description}" ${printer}
351		exit_code=$?
352	fi
353fi
354
355# if the "default" doesn't resolve a "bsdaddr", the printer is gone, remove it
356${LPGET} -n system -k bsdaddr _default >/dev/null 2>&1 ||
357	${LPSET} -n system -x _default >/dev/null 2>&1
358
359exit $exit_code
360