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