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