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