1*2792Sjacobs#!/bin/ksh
20Sstevel@tonic-gate#
30Sstevel@tonic-gate# CDDL HEADER START
40Sstevel@tonic-gate#
50Sstevel@tonic-gate# The contents of this file are subject to the terms of the
62264Sjacobs# Common Development and Distribution License (the "License").
72264Sjacobs# You may not use this file except in compliance with the License.
80Sstevel@tonic-gate#
90Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate# See the License for the specific language governing permissions
120Sstevel@tonic-gate# and limitations under the License.
130Sstevel@tonic-gate#
140Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate#
200Sstevel@tonic-gate# CDDL HEADER END
210Sstevel@tonic-gate#
220Sstevel@tonic-gate#
232264Sjacobs# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate# Use is subject to license terms.
250Sstevel@tonic-gate#
260Sstevel@tonic-gate# ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate#
280Sstevel@tonic-gatePATH=/bin:/usr/bin:/usr/sbin export PATH
290Sstevel@tonic-gate
300Sstevel@tonic-gateTEXTDOMAIN="SUNW_OST_OSCMD"
310Sstevel@tonic-gateexport TEXTDOMAIN
320Sstevel@tonic-gate
330Sstevel@tonic-gateLPSET=/usr/bin/lpset
340Sstevel@tonic-gateLPGET=/usr/bin/lpget
35*2792SjacobsLPADMIN=/usr/lib/lp/local/lpadmin
360Sstevel@tonic-gate
37*2792SjacobsHOST=$(/bin/uname -n)
380Sstevel@tonic-gateexit_code=0
390Sstevel@tonic-gate
400Sstevel@tonic-gateusage() {
410Sstevel@tonic-gate	gettext "Usage:\n" 1>&2
420Sstevel@tonic-gate	gettext "	lpadmin -p (printer) (options)\n" 1>&2
430Sstevel@tonic-gate	gettext "	lpadmin -x (dest)\n" 1>&2
440Sstevel@tonic-gate	gettext "	lpadmin -d (dest)\n" 1>&2
450Sstevel@tonic-gate	gettext "	lpadmin -S print-wheel -A alert-type [ -W minutes ]\n" 1>&2
460Sstevel@tonic-gate	gettext "		[ -Q requests ]\n" 1>&2
470Sstevel@tonic-gate	gettext "	lpadmin -M -f form-name [ -a [ -o filebreak ]\n" 1>&2
480Sstevel@tonic-gate	gettext "		[ -t tray-number ]]\n" 1>&2
490Sstevel@tonic-gate	exit 1
500Sstevel@tonic-gate}
510Sstevel@tonic-gate
52*2792Sjacobs# echo names in ${1} that are not in ${2}
53*2792Sjacobsmissing() {
54*2792Sjacobs	for i in ${1} ; do
55*2792Sjacobs		MATCHED=0
56*2792Sjacobs		for j in ${2} ; do
57*2792Sjacobs			if [[ $i = $j ]] ; then
58*2792Sjacobs				MATCHED=1
59*2792Sjacobs			fi
60*2792Sjacobs		done
61*2792Sjacobs		if [[ $MATCHED == 0 ]] ; then
62*2792Sjacobs			echo $i
63*2792Sjacobs		fi
64*2792Sjacobs	done
65*2792Sjacobs}
660Sstevel@tonic-gate
67*2792Sjacobs# create a filter table for LP service
68*2792Sjacobslp_config_filters() {
69*2792Sjacobs	if [[ ! -f /etc/lp/filter.table ]] ; then
70*2792Sjacobs		cd /etc/lp/fd ; for filter in *.fd ; do
71*2792Sjacobs			/usr/sbin/lpfilter \
72*2792Sjacobs				-f $(/usr/bin/basename $filter .fd) \
73*2792Sjacobs				-F $filter
74*2792Sjacobs		done
75*2792Sjacobs	fi
76*2792Sjacobs}
770Sstevel@tonic-gate
78*2792Sjacobs# enable/disable LP related service(s)
79*2792Sjacobslp_config_service() {	# (enable | disable)
80*2792Sjacobs	svcadm ${1} -s svc:/application/print/server:default
81*2792Sjacobs	# svcadm ${1} -s svc:/application/print/rfc1179:default
82*2792Sjacobs	# svcadm ${1} -s svc:/application/print/ipp-listener:default
83*2792Sjacobs}
84*2792Sjacobs
85*2792Sjacobs# synchronize printers.conf with LP configuration changes
86*2792Sjacobslp_config_sync_pconf() {	# (pre) (post)
87*2792Sjacobs	if [[ "${1}" != "${2}" ]] ; then
88*2792Sjacobs		ADDED=$(missing "${2}" "${1}")
89*2792Sjacobs		REMOVED=$(missing "${1}" "${2}")
900Sstevel@tonic-gate
91*2792Sjacobs		lp_server=${server:-${HOST}}
92*2792Sjacobs		for DEST in ${ADDED} ; do
93*2792Sjacobs			lp_uri="ipp://${lp_server}/printers/${DEST}"
94*2792Sjacobs			lp_bsdaddr="${lp_server},${DEST},Solaris"
95*2792Sjacobs			${LPSET} -n system \
96*2792Sjacobs				-a "printer-uri-supported=${lp_uri}" \
97*2792Sjacobs				-a "bsdaddr=${lp_bsdaddr}" \
98*2792Sjacobs			 	${DEST} 2>/dev/null
99*2792Sjacobs		done
1000Sstevel@tonic-gate
101*2792Sjacobs		for DEST in ${REMOVED} ; do
102*2792Sjacobs			${LPSET} -n system -x ${DEST} 2>/dev/null
103*2792Sjacobs		done
104*2792Sjacobs	fi
105*2792Sjacobs}
106*2792Sjacobs
107*2792Sjacobs# Delete all destinations in printers.conf
108*2792Sjacobsdelete_all() {
109*2792Sjacobs	for DEST in $(lpget -n system list | egrep -e '.+:$' | sed -e 's/://')
110*2792Sjacobs	do
111*2792Sjacobs		${LPSET} -n system -x ${DEST}
112*2792Sjacobs		status=$?
113*2792Sjacobs	done
114*2792Sjacobs}
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate#
117*2792Sjacobs# Execution begins here
1180Sstevel@tonic-gate#
1190Sstevel@tonic-gate
120*2792Sjacobs# be sure that we can run lpset and lpget
121*2792Sjacobsif [[ ! -x ${LPSET} || ! -x ${LPGET} ]] ; then
122*2792Sjacobs	gettext "lpadmin: System error; cannot set default printer\n" 1>&2
123*2792Sjacobs	exit 2
1240Sstevel@tonic-gatefi
1250Sstevel@tonic-gate
126*2792Sjacobsif [[ $# -lt 1 ]] ; then
1270Sstevel@tonic-gate	usage
1280Sstevel@tonic-gate	exit 1
1290Sstevel@tonic-gatefi
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate# Deal with the -d option independently since getopts does not handle
1320Sstevel@tonic-gate# options that may or may not have arguments
1330Sstevel@tonic-gate#
134*2792Sjacobsif [[ ${1} = "-d" ]] ; then
135*2792Sjacobs	if [[ $# -eq 1 ]] ; then	# remove the "default"
136*2792Sjacobs		${LPGET} -n system _default >/dev/null 2>&1
137*2792Sjacobs		exit_code=$?
1380Sstevel@tonic-gate
139*2792Sjacobs		if [[ ${exit_code} -eq 0 ]] ; then
140*2792Sjacobs			${LPSET} -n system -x _default
141*2792Sjacobs			exit_code=$?
142*2792Sjacobs		else	# no default, nothing to do
143*2792Sjacobs			exit_code=0
144*2792Sjacobs		fi
145*2792Sjacobs	elif [[ $# -eq 2 ]] ; then	# add/change the "default"
146*2792Sjacobs		${LPGET} -k bsdaddr ${2} >/dev/null 2>&1
147*2792Sjacobs		exit_code=$?
148*2792Sjacobs
149*2792Sjacobs		if [[ $exit_code -eq 0 ]] ; then
150*2792Sjacobs			${LPSET} -n system -a "use=${2}" _default
151*2792Sjacobs			exit_code=$?
152*2792Sjacobs		else	# can't set default to an unconfigured printer
153*2792Sjacobs			gettext "${2}: undefined printer\n" 1>&1
154*2792Sjacobs		fi
155*2792Sjacobs	else				# invalid usage
1560Sstevel@tonic-gate		usage
1570Sstevel@tonic-gate		exit 1
1580Sstevel@tonic-gate	fi
1590Sstevel@tonic-gate
1600Sstevel@tonic-gate	exit ${exit_code}
1610Sstevel@tonic-gatefi
1620Sstevel@tonic-gate
1630Sstevel@tonic-gate#		Strip off legal options
1640Sstevel@tonic-gatewhile 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
1650Sstevel@tonic-gatedo
1660Sstevel@tonic-gate	case $arg in
1670Sstevel@tonic-gate	D)
1680Sstevel@tonic-gate		description="${OPTARG}"
1690Sstevel@tonic-gate	;;
1700Sstevel@tonic-gate	p)
171*2792Sjacobs		if [[ -n "${delete}" ]] ; then
1720Sstevel@tonic-gate			usage
1730Sstevel@tonic-gate		fi
1740Sstevel@tonic-gate		printer=${OPTARG}
1750Sstevel@tonic-gate	;;
1760Sstevel@tonic-gate	s)
1770Sstevel@tonic-gate		server=${OPTARG}
1780Sstevel@tonic-gate	;;
1790Sstevel@tonic-gate	v|U)
1800Sstevel@tonic-gate		device=${OPTARG}
181*2792Sjacobs		if [[ ! -n "${server}" ]] ; then
182831Swendyp			server=${HOST}
183831Swendyp		fi
1840Sstevel@tonic-gate	;;
1850Sstevel@tonic-gate	x)
186*2792Sjacobs		if [[ -n "${printer}" || -n "${server}" || \
187*2792Sjacobs		     -n "${device}" || -n "${description}" ]] ; then
1880Sstevel@tonic-gate			usage
1890Sstevel@tonic-gate		fi
1900Sstevel@tonic-gate		delete=${OPTARG}
1910Sstevel@tonic-gate		printer=${OPTARG}
192*2792Sjacobs		if [[ ${printer} = "all" ]] ; then
1930Sstevel@tonic-gate			local="true"
1940Sstevel@tonic-gate		fi
1950Sstevel@tonic-gate	;;
1960Sstevel@tonic-gate	S|M|A)
1970Sstevel@tonic-gate		local="true"
1980Sstevel@tonic-gate	;;
1990Sstevel@tonic-gate	c)
2000Sstevel@tonic-gate		class=${OPTARG}
2010Sstevel@tonic-gate		local="true"
202*2792Sjacobs		if [[ ! -f ${LPGET} ]] ; then
2030Sstevel@tonic-gate			gettext "lpadmin: System error; cannot set class\n " 1>&2
2040Sstevel@tonic-gate			exit 2
2050Sstevel@tonic-gate		fi
2060Sstevel@tonic-gate
2070Sstevel@tonic-gate		${LPGET} "${class}" > /dev/null 2>&1
2080Sstevel@tonic-gate		lpget_class=$?
209*2792Sjacobs		if [[ ${lpget_class} -eq 0 && ! -r /etc/lp/classes/"${class}" ]] ; then
2100Sstevel@tonic-gate			gettext "lpadmin: ERROR: Can't create class ${class}.\n" 1>&2
2110Sstevel@tonic-gate			gettext "           TO FIX: This is an existing printer name;\n" 1>&2
2120Sstevel@tonic-gate			gettext "                   choose another name.\n" 1>&2
2130Sstevel@tonic-gate			exit 1
2140Sstevel@tonic-gate		fi
2150Sstevel@tonic-gate	;;
2160Sstevel@tonic-gate	r)
2170Sstevel@tonic-gate		local="true"
2180Sstevel@tonic-gate	;;
2190Sstevel@tonic-gate	esac
2200Sstevel@tonic-gatedone
2210Sstevel@tonic-gate
2220Sstevel@tonic-gate#
2230Sstevel@tonic-gate# We don't have anything to do; let user know and bail
2240Sstevel@tonic-gate#
225*2792Sjacobsif [[ ! -n "${printer}" && ! -n "${delete}" && ! -n "${local}" ]] ; then
2260Sstevel@tonic-gate	gettext "lpadmin: ERROR: Nothing to do.\n" 1>&2
2270Sstevel@tonic-gate	gettext "        TO FIX: You must give one of these options:\n" 1>&2
2280Sstevel@tonic-gate	gettext "		      -p, -d, -x -S\n" 1>&2
2290Sstevel@tonic-gate	exit 1
2300Sstevel@tonic-gatefi
2310Sstevel@tonic-gate
2320Sstevel@tonic-gate#
2330Sstevel@tonic-gate#       Printer does not exist
2340Sstevel@tonic-gate#       To be consistent with 2.5, assume adding local printer
2350Sstevel@tonic-gate#
236*2792Sjacobsif [[ ! -n "${device}" && ! -n "${server}" && ! -n "${delete}" && \
237*2792Sjacobs	  ! -n "${local}" ]] ; then
2380Sstevel@tonic-gate	${LPGET} "${printer}" > /dev/null 2>&1
2390Sstevel@tonic-gate	lpget_stat=$?
240*2792Sjacobs	if [[ ${lpget_stat} -ne 0 ]] ; then
2410Sstevel@tonic-gate		gettext "lpadmin: ERROR: Missing -U or -v option.\n" 1>&2
2420Sstevel@tonic-gate		gettext "           TO FIX: Local printers must have\n" 1>&2
2430Sstevel@tonic-gate		gettext "                   a port defined (-v option) or\n" 1>&2
2440Sstevel@tonic-gate		gettext "                   have dial-out instructions (-U option).\n" 1>&2
2450Sstevel@tonic-gate		exit 1
2460Sstevel@tonic-gate	fi
2470Sstevel@tonic-gatefi
2480Sstevel@tonic-gate
2492264Sjacobs#	process the "server" value
2502264Sjacobs#	It can be a hostname, UUCP form (server!queue), RCMD form(queue@server),
2512264Sjacobs#	or in URI form ({scheme}://{endpoint})
2522264Sjacobs#
2532264Sjacobscase "${server}" in
2542264Sjacobs	*://*)	# URI form
2552264Sjacobs		uri=${server}
256*2792Sjacobs		rem_printer=$(expr "${server}" : ".*://.*/\([^/]*\)")
257*2792Sjacobs		server=$(expr "${server}" : ".*://\([^/]*\)/.*")
2582264Sjacobs		;;
2592264Sjacobs	*@*)	# RCMD form
260*2792Sjacobs		rem_printer=$(expr "${server}" : "\(.*\)@.*")
261*2792Sjacobs		server=$(expr "${server}" : ".*@\(.*\)")
2622264Sjacobs		;;
2632264Sjacobs	*!*)	# UUCP form
264*2792Sjacobs		rem_printer=$(expr "${server}" : ".*!\(.*\)")
265*2792Sjacobs		server=$(expr "${server}" : "\(.*\)!.*")
2662264Sjacobs		;;
2672264Sjacobs	*)	# hostname
2682264Sjacobs		rem_printer=${printer}
2692264Sjacobs		;;
2702264Sjacobsesac
271*2792Sjacobs
2722264Sjacobs# default URI form is "lpd" form
273*2792Sjacobsif [[ -n "${server}" ]] ; then
2742264Sjacobs	uri=${uri:-"lpd://${server}/printers/${rem_printer}#Solaris"}
2752264Sjacobs	bsdaddr="${server},${rem_printer},Solaris"
2760Sstevel@tonic-gatefi
2770Sstevel@tonic-gate
278*2792Sjacobs
279*2792Sjacobs# Do the LP configuration for a local printer served by lpsched
280*2792Sjacobsif [[ -x ${LPADMIN} && ( -n "${local}" || -n "${device}" || \
281*2792Sjacobs                          -f /etc/lp/printers/${printer}/configuration || \
282*2792Sjacobs      			          -f /etc/lp/classes/${printer} ) ]] ; then
283*2792Sjacobs	# enumerate LP configured printers before modification
284*2792Sjacobs	PRE=$(/bin/ls /etc/lp/printers 2>/dev/null ; /bin/ls /etc/lp/classes \
285*2792Sjacobs		2>/dev/null)
286*2792Sjacobs
287*2792Sjacobs	# if there are no printers configured, enable LP service(s)
288*2792Sjacobs	[[ -z "${PRE}" ]] && lp_config_service enable
289*2792Sjacobs
290*2792Sjacobs	# add filters to LP service
291*2792Sjacobs	lp_config_filters
292*2792Sjacobs
293*2792Sjacobs	# modify LP destination(s)
294*2792Sjacobs	CMD=${LPADMIN}
295*2792Sjacobs	while [[ -n "$*" ]] ; do	# to deal with multi-word arguments
296*2792Sjacobs		CMD="$CMD \"$1\""
297*2792Sjacobs		shift
298*2792Sjacobs	done
299*2792Sjacobs	case "$CMD" in
300*2792Sjacobs		*\"-D\")
301*2792Sjacobs			CMD="$CMD \"\""
302*2792Sjacobs		;;
303*2792Sjacobs	esac
3040Sstevel@tonic-gate
305*2792Sjacobs	# execute the LP lpadmin command
306*2792Sjacobs	eval $CMD
307*2792Sjacobs	exit_code=$?
308*2792Sjacobs
309*2792Sjacobs	# enumerate LP configured printers after modification
310*2792Sjacobs	POST=$(/bin/ls /etc/lp/printers 2>/dev/null ; /bin/ls /etc/lp/classes \
311*2792Sjacobs                    2>/dev/null)
312*2792Sjacobs
313*2792Sjacobs	# if there are no destinations, disable the service(s)
314*2792Sjacobs	[[ -z "${POST}" ]] && lp_config_service disable
315*2792Sjacobs
316*2792Sjacobs	# sync printers.conf with LP configuration
317*2792Sjacobs	lp_config_sync_pconf "${PRE}" "${POST}"
318*2792Sjacobsfi
319*2792Sjacobs
320*2792Sjacobs# Do any printers.conf configuration that is required
321*2792Sjacobsif [[ -n "${delete}" ]] ; then
322*2792Sjacobs	if [[ "${delete}" = "all" ]] ; then
323*2792Sjacobs		[[ $exit_code -eq 0 ]] && delete_all
324*2792Sjacobs   	elif [[ -n "${local}" ]] ; then
325*2792Sjacobs   		${LPSET} -n system -x ${delete}
326*2792Sjacobs   		exit_code=$?
327*2792Sjacobs   	fi
328*2792Sjacobselif [[ -n "${local}" ]] ; then
329*2792Sjacobs	if [[ -n "${printer}" ]] ; then
330*2792Sjacobs		${LPSET} -n system \
331*2792Sjacobs			-a "printer-uri-supported=${uri}" \
332*2792Sjacobs			-a "bsdaddr=${bsdaddr}" ${printer}
3330Sstevel@tonic-gate		exit_code=$?
3340Sstevel@tonic-gate	fi
3350Sstevel@tonic-gate
336*2792Sjacobs	if [[ -n "${printer}" && -n "${description}" ]] ; then
337*2792Sjacobs		${LPSET} -n system \
338*2792Sjacobs			-a "description=${description}" ${printer}
339*2792Sjacobs		exit_code=$?
3400Sstevel@tonic-gate	fi
3410Sstevel@tonic-gatefi
3420Sstevel@tonic-gate
343*2792Sjacobs# if the "default" doesn't resolve a "bsdaddr", the printer is gone, remove it
344*2792Sjacobs${LPGET} -n system -k bsdaddr _default >/dev/null 2>&1 ||
345*2792Sjacobs	${LPSET} -n system -x _default >/dev/null 2>&1
3460Sstevel@tonic-gate
3470Sstevel@tonic-gateexit $exit_code
348