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# Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23# Use is subject to license terms. 24# 25 26# 27# Description: Script to generate the Solaris printmgr 'ppdcache' file from the 28# ppd files installed in the given ppd database directory 29# 30# ppdmgr -a <ppd_filename_path> [ -L <label> ] [-w] 31# ppdmgr -g <ppd_filename_path> [ -L <label> ] [ -R <ppd_repository> ] 32# ppdmgr -r [ -L <label> ] [ -R <ppd_repository> ] 33# ppdmgr -u [ -L <label> ] [ -R <ppd_repository> ] 34# 35# Options: 36# -a <ppd_filename_path> - Add a new PPD file to the specified 37# label in the "user" repository, and 38# updates to the "user" repository 39# in the ppdcache. 40# -g <ppd_filename_path> - Generate a cache file entry 41# for the specified PPD file 42# on standard out. 43# -L <label> - Label name. <label> 44# can be any characters from the 45# portable character set, however 46# may not contain a semi-colon (':'). 47# The following are the defaults 48# for <label> for each option: 49# OPTION DEFAULT LABEL 50# ------ ------------- 51# -a <label> from <ppd_filename_path> 52# if <ppd_filename_path> 53# is from a known repository, 54# otherwise defaults to "user". 55# -g <label> from <ppd_filename_path> 56# if <ppd_filename_path> 57# is from a known repository, 58# otherwise defaults to "user". 59# -r all 60# -u all 61# The following are reserved labels: 62# caches - may never be specified 63# ppdcache - may never be specified 64# manufaliases - may never be specified 65# all - applies specified 66# action to all labels 67# in a repository. 68# Can only be specified 69# with -r or -u. 70# SUNW* - anything starting with 71# SUNW is reserved for 72# use by Sun, but not 73# prohibited. 74# -r - Rebuild the cache information for the 75# specified label in the specified 76# repository. Similar to -u, however, 77# the cache file is removed to force an 78# update to the ppdcache. 79# -R <ppd_repository> - PPD repository name. 80# Defaults to "user". 81# The following are the possible 82# values for <ppd_repository> and 83# location in the system: 84# REP LOCATION 85# --- -------- 86# user /var/lp/ppd 87# admin /usr/local/share/ppd 88# vendor /opt/share/ppd 89# system /usr/share/ppd 90# all all repositories 91# 92# Note: When specified with the -a option 93# only "user" and "admin" are valid. 94# "vendor", "system", and "all" will be 95# considered reserved. 96# -u - Update the PPD cache information 97# for the specified label in the specified 98# repository if needed. If the cache 99# update was required, then the updated 100# cache information is reflected in 101# the ppdcache. 102# -w - Display full path of where the 103# ppd file is located on the system. 104# Only valid with -a, otherwise the 105# option is ignored. 106# 107# If -a, -g, -r, or -u are specified on the command line, only the last action 108# specified will be performed. 109# 110# Cache file entry format: 111# <ModifiedManufacturerName>:<Model>:<NickName>:<1284DeviceIDManufacturer>:<1284DeviceIDModel>:<FullPPDFilePath> 112# HP:HP DeskJet 450:Foomatic/hpijs (recommended):dj450:hp:/usr/share/ppd/HP/HP-DeskJet_450-hpijs.ppd.gz 113# 114 115PATH=/bin:/usr/bin:/usr/sbin export PATH 116set -o noclobber 117 118TEXTDOMAIN="SUNW_OST_OSCMD" 119export TEXTDOMAIN 120 121# 122# Generates debug output for calling routine. 123# If calling routine's name is passed in, then 124# will also generate the name of the calling routine. 125# 126# $1 - Name of calling routine 127debugger() 128{ 129 [[ ${debug} -eq 1 ]] || return 1 130 if [[ -n "${1}" ]] ; then 131 echo "In ${1}..." 1>&2 132 fi 133 return 0 134} 135 136# 137# Set the ownership and permissions on a file. 138# 139# $1 - Mode 140# $2 - Owner:Group 141# $3 - Full path to file 142# 143set_perms() 144{ 145 /bin/chmod -f ${1} "${3}" >/dev/null 2>&1 146 /bin/chown -f ${2} "${3}" >/dev/null 2>&1 147} 148 149# 150# Create administrator repository directories, /usr/local/share/ppd, 151# if needed. This is a special case a Solaris doesn't deliver 152# /usr/local/share and it has different permissions than the 153# user repository. 154# 155# $1 - destination repository name 156# 157create_adminrep_dirs() 158{ 159 if debugger "check_adminrep_dirs" ; then 160 set -x 161 fi 162 163 # Only create administrator repository directories, if needed. 164 [[ "${1}" = "${ADMIN}" ]] || return 0 165 166 # Check /usr/local/share/ppd 167 [[ ! -d "${ADMINREP}" ]] || return 0 168 169 # Check /usr/local/share 170 admpar=$(/bin/dirname "${ADMINREP}") 171 if [[ ! -d "${admpar}" ]] ; then 172 173 # Check /usr/local 174 admppar=$(/bin/dirname "${admpar}") 175 if [[ ! -d "${admppar}" ]] ; then 176 make_dir ${DIRMODE} ${ADMINOWNER} "${admppar}" || \ 177 return 1 178 fi 179 make_dir ${DIRMODE} ${ADMINOWNER} "${admpar}" || return 1 180 fi 181 make_dir ${DIRMODE} ${ADMINOWNER} ${ADMINREP} || return 1 182 return 0 183} 184 185# 186# Returns full path to PPD file that was added to the system. 187# 188# $1 - Full path to source PPD file 189# $2 - PPD file name 190# $3 - Full path to repository 191# $4 - Repository name 192# $5 - Label name 193# 194# Return codes: 195# 0 - File successfully added 196# 1 - Error 197# 2 - Duplicate file already exists 198# 199add_ppd() 200{ 201 if debugger ; then 202 set -x 203 fi 204 205 verify_ppd_file "${1}" 206 if [[ $? -ne 0 ]] ; then 207 gettext "invalid PPD file: ${1}" 2>/dev/null 208 return 3 209 fi 210 211 # The destination path can now be set 212 dstlabelpath="${3}/${5}" 213 dstmanufpath="${dstlabelpath}/${modmanuf}" 214 dstpath="${dstmanufpath}/${2}" 215 216 # 217 # If a version (either compressed or not compressed) of the PPD 218 # file exists in the destination in the label/repository, 219 # then just return as there no work to be done. 220 dst_copy_path=$(variant_copy "${1}" "${dstpath}" "${6}" "${ppdfname}") 221 ap_rc=$? 222 if [[ ${ap_rc} -ne 0 ]] ; then 223 echo "${dst_copy_path}" 224 return ${ap_rc} 225 fi 226 227 # 228 # Can only add a PPD file to the "user" or "admin" repository. 229 # Note: this check is here instead of at the top of this 230 # function as we don't want to cause an error if a user 231 # specifies the same repository and label as a the specified 232 # ppd file and the repository of the specified ppd file 233 # exists in a known repository. 234 # 235 if [[ "${4}" != "${USER}" && "${4}" != "${ADMIN}" ]] ; then 236 gettext "invalid PPD file repository name: ${4}" 2>/dev/null 237 return 3 238 fi 239 240 # Ensure destination directories exist 241 if ! create_adminrep_dirs ${4} ${DIRMODE} ${ADMINOWNER} || \ 242 ! make_dir ${DIRMODE} ${DIROWNER} "${3}" || \ 243 ! make_dir ${DIRMODE} ${DIROWNER} "${dstlabelpath}" || \ 244 ! make_dir ${DIRMODE} ${DIROWNER} "${dstmanufpath}" ; then 245 gettext "unable to create destination directories" 2>/dev/null 246 return 3 247 fi 248 249 # Copy source PPD file, and compress if needed, to destination 250 if [[ "${ppdfileext}" = "${PEXT}" ]] ; then 251 ${GZIP} "${1}" >"${dst_copy_path}" 2>/dev/null 252 if [[ $? -eq 1 ]] ; then 253 gettext "unable to copy PPD file " 2>/dev/null 254 gettext "to destination" 2>/dev/null 255 return 3 256 fi 257 else 258 /bin/cp -f "${1}" "${dst_copy_path}" >/dev/null 2>&1 259 if [[ $? -ne 0 ]] ; then 260 gettext "unable to copy PPD file " 2>/dev/null 261 gettext "to destination" 2>/dev/null 262 return 3 263 fi 264 fi 265 set_perms ${FILEMODE} ${FILEOWNER} "${dst_copy_path}" 266 267 echo "${dst_copy_path}" 268 269 return 0 270} 271 272# 273# Returns 0 if the cache needs to be modified, otherwise 274# returns 1. 275# 276# $1 - Full path to cache 277# $2 - Full path to cache replacement candidate 278# 279changes_in_cache() 280{ 281 if debugger "changes_in_cache" ; then 282 set -x 283 fi 284 285 if [[ "${action}" = "${REBUILD}" ]] ; then 286 return 0 287 fi 288 [[ "${2}" -nt "${1}" ]] || return 1 289 if $(${CMP} "${1}" "${2}" >/dev/null 2>&1) ; then 290 # No differences. Just update timestamp 291 /bin/touch -r "${2}" "${1}" >/dev/null 2>&1 292 return 1 293 else 294 return 0 295 fi 296} 297 298# 299# Generate a new golden cache file (/var/lp/ppd/ppdcache), by 300# concatenating and sorting all existing cache files in /var/lp/ppd/caches. 301# 302# If there are difference between the newly generated golden cache file and 303# the existing one (if it exists) then the newly generated one replaces the 304# existing one at /var/lp/ppd/ppdcache. 305# 306update_golden_cache() 307{ 308 309 if debugger "update_golden_cache" ; then 310 set -x 311 fi 312 313 # 314 # Remove any cache files that don't have an associated 315 # label. 316 # 317 for cname in $(/bin/ls ${VARCACHES} 2>/dev/null) ; do 318 repname="${cname%%:*}" 319 cfile="${cname#*:}" 320 checkdir="$(get_rep_path ${repname})/${cfile}" 321 remove_unassociated_cache "${checkdir}" "${cname}" 322 done 323 324 # 325 # Combine the contents of all cache files into a 326 # temporary golden cache file. 327 # 328 tmpgoldencache=$(/bin/mktemp -p "${ppdmgrtmpdir}" \ 329 tmpgoldencache.XXXXXX 2>/dev/null) 330 /bin/sort "${VARCACHES}"/* >>"${tmpgoldencache}" 2>/dev/null 331 332 if [[ ! -s "${tmpgoldencache}" ]] ; then 333 # No cache files. Remove golden cache. 334 /bin/rm -f "${GOLDCACHE}" >/dev/null 2>&1 335 /bin/rm -f "${tmpgoldencache}" >/dev/null 2>&1 336 elif [[ -e "${GOLDCACHE}" ]] ; then 337 # 338 # Use the newly generated "temporary" golden cache file if there 339 # differences between the current and newly generated ppdcache 340 # or if a rebuild is being performed. 341 # 342 if [[ "${VARCACHES}" -nt "${GOLDCACHE}" ]] || \ 343 changes_in_cache "${GOLDCACHE}" "${tmpgoldencache}" ; then 344 set_perms ${FILEMODE} ${FILEOWNER} "${tmpgoldencache}" 345 /bin/mv -f "${tmpgoldencache}" \ 346 "${GOLDCACHE}" >/dev/null 2>&1 347 else 348 /bin/rm -f "${tmpgoldencache}" >/dev/null 2>&1 349 fi 350 else 351 # There wasn't an existing ppdcache. Install the newly 352 # generated ppdcache file to the golden ppdcache. 353 set_perms ${FILEMODE} ${FILEOWNER} "${tmpgoldencache}" 354 /bin/mv -f "${tmpgoldencache}" "${GOLDCACHE}" >/dev/null 2>&1 355 fi 356} 357 358# 359# Returns a list of PPD files that exist. 360# 361# $1 - Full path to cache file 362# 363remove_invalid_cache_entries() 364{ 365 if debugger ; then 366 set -x 367 fi 368 369 [[ -s "${1}" ]] || return 370 371 IFS="$NoSpaceTabIFS" 372 for centry in $(/bin/cat "${1}" 2>/dev/null) ; do 373 IFS="$SaveIFS" 374 # 375 # Keep the entry from the ppd cache if it still 376 # exists and there haven't been any modifications 377 # since the last update to the cache. 378 # 379 if [[ -n "${centry}" ]] ; then 380 ppdfile="${centry##*:}" 381 if [[ -n "${ppdfile}" && -e "${ppdfile}" && 382 "${1}" -nt "${ppdfile}" ]] ; then 383 echo "${centry}" 384 fi 385 fi 386 IFS="$NoSpaceTabIFS" 387 done 388 IFS="$SaveIFS" 389} 390 391# 392# Returns 0 if the path to the PPD is as follows: 393# <PPD file repository>/<label>/<manufacturer>/<PPD file> 394# otherwise, returns 1 395# 396# $1 Full path to PPD file 397# 398verify_ppd_location() 399{ 400 if debugger ; then 401 set -x 402 fi 403 404 # 405 # Strip off what should be <label>/<manufacturer>/<PPD file> 406 # and verify the PPD file repository matches one of the 407 # known PPD file repositories. 408 # 409 ppd_file_repository=${1%/*/*/*} 410 found=1 411 for repository in ${REPOSITORIES} ; do 412 if [[ "${repository}" = "${ppd_file_repository}" ]] ; then 413 found=0 414 break 415 fi 416 done 417 return ${found} 418} 419 420# 421# Generate, and sort, cache entries for each PPD files in the specified 422# list to the specified file. 423# 424# $1 - List of full paths to PPD files 425# $2 - Full path to current cache file 426# $3 - Full path to label 427# $4 - Full path to new cache file to generate 428# 429# Return code: 430# 0 success 431# 1 unsuccessful 432# 433generate_label_cache_file() 434{ 435 if debugger ; then 436 set -x 437 fi 438 439 # 440 # Generate a cache file containing cache entries for 441 # all files in the label. 442 # 443 ucfile=$(/bin/mktemp -p "${ppdmgrtmpdir}" \ 444 unsortedcache.XXXXXX 2>/dev/null) 445 446 # 447 # Before processing new files, remove any cache entries 448 # which may be invalid. 449 # 450 valid_files= 451 if [[ -e "${2}" && "${action}" != "${REBUILD}" ]] ; then 452 valid_files=$(remove_invalid_cache_entries "${2}") 453 if [[ -n "${valid_files}" ]] ; then 454 echo "${valid_files}" >>${ucfile} 455 fi 456 fi 457 458 # 459 # If there are no valid PPD files in the current cache file, 460 # and there are no new PPD files to process, the only thing 461 # left to do is to remove the current cache file. 462 # 463 if [[ -z "${valid_files}" && -z "${1}" ]] ; then 464 /bin/rm -f "${2}" >/dev/null 2>&1 465 /bin/rm -f "${ucfile}" >/dev/null 2>&1 466 return 0 467 fi 468 469 # 470 # For each of the label's PPD files, generate 471 # a cache file entry and add it to the cache file. 472 # 473 vpl_rc=0 474 vpf_rc=0 475 vpl_msg= 476 vpf_msg= 477 IFS="$NoSpaceTabIFS" 478 for fname in ${1} ; do 479 IFS="$SaveIFS" 480 if [[ -n "${fname}" ]] ; then 481 verify_ppd_location "${fname}" 482 vpl_rc=$? 483 if [[ ${vpl_rc} -ne 0 ]] ; then 484 vpl_msg="${vpl_msg}\t${fname}\n" 485 fi 486 487 verify_ppd_file "${fname}" 488 vpf_rc=$? 489 if [[ ${vpf_rc} -ne 0 ]] ; then 490 vpf_msg="${vpf_msg}\t${fname}\n" 491 fi 492 493 if [[ ${vpl_rc} -eq 0 && ${vpf_rc} -eq 0 ]] ; then 494 echo "$(generate_cache_file_entry \ 495 "${modmanuf}" "${model}" "${nickn}" \ 496 "${devidmfg}" "${devidmdl}" "${fname}")" 497 fi 498 fi 499 IFS="$NoSpaceTabIFS" 500 done >>"${ucfile}" 501 IFS="$SaveIFS" 502 /bin/sort -u "${ucfile}" >>"${4}" 2>/dev/null 503 /bin/rm -f "${ucfile}" >/dev/null 2>&1 504 505 [[ -n "${vpl_msg}" || -n "${vpf_msg}" ]] || return 0 506 if [[ -n ${vpl_msg} ]] ; then 507 gettext " PPD file(s) not in valid location\n" 2>/dev/null 508 gettext \ 509 " (<repository>/<label>/<manufacturer>/<PPD file>):\n" 2>/dev/null 510 echo "${vpl_msg}" 511 fi 512 if [[ -n ${vpf_msg} ]] ; then 513 gettext " invalid PPD file(s):\n" 2>/dev/null 514 echo "${vpf_msg}" 515 fi 516 return 1 517} 518 519# 520# Update current cache file with candidate cache file if there are 521# differences. 522# 523# $1 - Current cache file 524# $2 - Candidate cache file to update 525# $3 - Repository name 526# 527update_current_cache_file() 528{ 529 if debugger "update_current_cache_file" ; then 530 set -x 531 fi 532 533 if [[ ! -s "${2}" ]] ; then 534 # 535 # Candidate cache has zero size (label 536 # directory with no PPD files under it). 537 # Delete the empty candidate cache 538 # file and delete the current cache 539 # file. 540 # 541 /bin/rm -f "${1}" >/dev/null 2>&1 542 /bin/rm -f "${2}" >/dev/null 2>&1 543 elif [[ -e "${1}" ]] ; then 544 # 545 # If there are differences between the current 546 # cache file and the newly generated one, then 547 # replace the current one with the new one, and 548 # set the flag to update the golden ppdcache 549 # file. 550 # 551 if changes_in_cache "${1}" "${2}" ; then 552 set_perms ${FILEMODE} ${FILEOWNER} "${2}" 553 /bin/mv -f "${2}" "${1}" >/dev/null 2>&1 554 else 555 /bin/rm -f "${2}" >/dev/null 2>&1 556 fi 557 else 558 559 # 560 # There is no current cache file. Move the candidate 561 # to the caches directory. 562 # 563 set_perms ${FILEMODE} ${FILEOWNER} "${2}" 564 /bin/mv -f "${2}" "${1}" >/dev/null 2>&1 565 fi 566} 567 568# 569# Returns 0 if there are files in $1 with newer timestamp 570# than $2 or if deletions have occurred under $1, 571# otherwise returns 1. 572# 573# $1 - Full path to the destination label 574# $2 - Full path to label cache file 575# 576changes_under_label() 577{ 578 if debugger ; then 579 set -x 580 fi 581 582 # First check for newer files in the directory 583 if [[ -e "${2}" && "${action}" != "${REBUILD}" ]] ; then 584 newfiles=$(/bin/find "${1}" -type f -newer "${2}") 585 else 586 newfiles=$(/bin/find "${1}" -type f) 587 fi 588 echo "${newfiles}" 589 [[ -z "${newfiles}" ]] || return 0 590 591 # 592 # Need to detect if PPD files have been deleted by checking 593 # timestamps on label and manufacturer directories. 594 # 595 [[ ! "${1}" -nt "${2}" ]] || return 0 596 /bin/find "${1}" -type d -newer "${2}" >/dev/null 2>&1 || return 1 597 return 0 598} 599 600# 601# If -R was specified, or the timestamp on the specified label's 602# directory or any of the PPD files under the specified label in 603# the specified PPD file respository is newer than the cache file 604# associated with the label, then generate a new sorted cache file. 605# 606# The new cache will replace the existing one (if any) only if there 607# are differences. Note: if -r was specified, then a new cache file 608# file will always be installed at 609# /var/lp/ppd/caches/<PPD file repository name>-<label name> 610# 611# $1 - Full path of the destination PPD file repository 612# $2 - Destination PPD file repository name 613# $3 - Destination label name 614# 615update_label_cache() 616{ 617 if debugger ; then 618 set -x 619 fi 620 621 dstlabelpath="${1}/${3}" 622 replabelcachepath="${1}/${CACHES}/${3}" 623 varlabelcachepath="${VARCACHES}/${2}${SEP}${3}" 624 625 ulc_rc=0 626 if [[ -d "${dstlabelpath}" ]] ; then 627 628 # 629 # If the cache doesn't exist for a label, 630 # or if there were any changes under a label 631 # (i.e., the timestamp on the label directory or any 632 # of the PPD files under it is newer than the 633 # existing cache file), then generate a new cache file. 634 # 635 tmpcachepath=$(/bin/mktemp -p "${ppdmgrtmpdir}" \ 636 tmpcachepath.XXXXXX 2>/dev/null) 637 638 # if this is a system repository, check for a prepopulated cache 639 if [[ "${2}" = "${SYSTEM}" && -e ${FOOCACHEDIR}/${3}.cache ]] ; then 640 # copy prepopulated cache 641 /bin/cp -f ${FOOCACHEDIR}/${3}.cache ${tmpcachepath} 642 643 else 644 newfileslist=$(changes_under_label "${dstlabelpath}" \ 645 "${varlabelcachepath}") 646 if [[ $? -eq 0 ]] ; then 647 err_files=$(generate_label_cache_file \ 648 "${newfileslist}" "${varlabelcachepath}" \ 649 "${dstlabelpath}" "${tmpcachepath}") 650 if [[ $? -ne 0 ]] ; then 651 # 652 # At least one PPD file was invalid. 653 # Don't return yet, as the cache info 654 # for the valid PPD files can still be 655 # used to generate a cache file. 656 # 657 echo "${err_files}" 658 ulc_rc=1 659 fi 660 fi 661 fi 662 663 if [[ -e "${tmpcachepath}" ]] ; then 664 update_current_cache_file \ 665 "${varlabelcachepath}" "${tmpcachepath}" "${2}" 666 /bin/rm -f "${tmpcachepath}" >/dev/null 2>&1 667 fi 668 else 669 # 670 # If there is a cache file in /var/lp/ppd/caches associated 671 # with the label which no longer exists, remove it. 672 # 673 /bin/rm -f "${varlabelcachepath}" >/dev/null 2>&1 674 fi 675 return ${ulc_rc} 676} 677 678# 679# Returns the alias for the specified real manufacturer's name. 680# 681# $1 - Real manufacturer's name 682# $2 - File containing list of files that have manufacturers aliases 683# 684manuf_name_alias() 685{ 686 if debugger ; then 687 set -x 688 fi 689 690 # 691 # Found a couple of PPD files which had special characters 692 # in the Manufacturer name (i.e, the following is the Manufacturer 693 # entry: 694 # *Manufacturer: "Canon Inc. (Kosugi Offic" 695 # We'll only search the alias file for "Canon Inc." 696 # 697 tmpmanuf="${1% *\(*}" 698 699 # Search alias files for a match on the real manufacturer name 700 if [[ -s "${2}" ]] ; then 701 # 702 # Check the manufacturer aliases file for case 703 # insensitive match of the Manufacturer entry 704 # from the PPD file. If a match is found, 705 # then modify the manufacturer entry to 706 # be that of the specified alias. 707 # 708 manufaliases=$(/bin/egrep -i \ 709 "^${tmpmanuf}:|:${tmpmanuf}:|:${tmpmanuf}$" "${2}") 710 if [[ -n "${manufaliases}" ]] ; then 711 echo "${manufaliases%%:*}" 712 break 713 else 714 echo "${tmpmanuf}" 715 fi 716 else 717 echo "${tmpmanuf}" 718 fi 719} 720 721# 722# Returns 0 if the extension to the specified PPD file is a known 723# extension, otherwise returns 1. 724# 725# $1 - Full path to PPD file 726# 727# Set upon return: 728# ppdfileext - PPD file ext (.ppd or .ppd.gz) 729# 730verify_file_ext() 731{ 732 if debugger ; then 733 set -x 734 fi 735 736 if [[ "${1%.gz}".gz = "${1}" ]] ; then 737 ppdfileext=${GEXT} 738 elif [[ "${1%.ppd}".ppd = "${1}" ]] ; then 739 ppdfileext=${PEXT} 740 else 741 # invalid PPD file name extension 742 return 1 743 fi 744 745 return 0 746} 747 748# 749# Return the lines from the specified PPD file matching the specified 750# spec items. 751# 752# $1 - spec entries from PPD file 753# $2 - spec item 754# 755# $1 example - 1 string with substrings separated by newline: 756# *PPD-Adobe: "4.3" 757# *Manufacturer: "HP" 758# *Product: "(officejet 4200 series)" 759# *ModelName: "HP OfficeJet 4200" 760# *NickName: "HP OfficeJet 4200 Foomatic/hpijs (recommended)" 761# $2 example: 762# ^\*Manufacturer 763# 764spec_entry() 765{ 766 if debugger ; then 767 set -x 768 fi 769 770 item=$(echo "${1}" | /bin/grep ${2}) 771 # Remove everything up to and including the first quote 772 item=${item#*\"} 773 # Remove the end quote 774 echo "${item%\"}" 775} 776 777# 778# Return the lines from the specified PPD file matching the specified 779# spec items. 780# 781# Note: this is similar to spec_entry() except the tokens in the 782# spec entry are different. 783# 784# $1 - spec entries from PPD file 785# $2 - spec item 786# 787devid_spec_entry() 788{ 789 if debugger ; then 790 set -x 791 fi 792 793 item=$(echo "${1}" | /bin/grep ${2}) 794 # Remove everything up to and including the first semi-colon 795 item=${item#*\:} 796 # Remove the end quote 797 echo ${item%\;} 798 799} 800 801# 802# Verifies that the specified PPD file 803# - has a valid extension 804# - has the following required spec file entries: 805# *PPD-Adobe: "4.3" 806# Manufacturer 807# Product 808# ModelName 809# NickName 810# 811# In addition, the manufacture and model from the IEEE1284 device id 812# information will be gathered here, although it's not an error that 813# it isn't in the PPD file as many don't contain the IEEE1284 info. 814# 815# $1 - Full path to PPD file 816# 817# Return codes: 818# 0 success 819# 1 invalid PPD file 820# 821verify_ppd_file() 822{ 823 if debugger ; then 824 set -x 825 fi 826 827 ADOBESPEC="PPD-Adobe" 828 MANUF="Manufacturer" 829 PRODUCT="Product" 830 MODEL="ModelName" 831 NICKNAME="NickName" 832 DEVID="1284DeviceID" 833 834 # Verify the PPD file extension 835 verify_file_ext "${1}" || return 1 836 837 # Query for the required spec items 838 searchentries="^\*${ADOBESPEC}:|^\*${MANUF}:|^\*${PRODUCT}:" 839 searchentries="${searchentries}|^\*${MODEL}:|^\*${NICKNAME}:" 840 searchentries="${searchentries}|^\*${DEVID}:" 841 ppd_info="$(/bin/gzgrep -e "${searchentries}" "${1}")" 842 843 # 844 # Process the query results to verify each of the required spec 845 # file items appears in the PPD file. 846 # 847 for spec_item in ${ADOBESPEC} ${MANUF} ${PRODUCT} ${MODEL} \ 848 ${NICKNAME} ; do 849 entry=$(spec_entry "${ppd_info}" "^\*${spec_item}:") 850 [[ ! -z "${entry}" ]] || return 1 851 case ${spec_item} in 852 ${MANUF}) 853 realmanuf="${entry}" 854 ;; 855 ${PRODUCT}) 856 product="${entry}" 857 ;; 858 ${MODEL}) 859 model="${entry}" 860 ;; 861 ${NICKNAME}) 862 # 863 # Remove the model and any commas and spaces 864 # which appear before the driver 865 # 866 nickn="${entry#$model[, ]*}" 867 ;; 868 esac 869 870 done 871 872 # Save IEEE1284 device id information 873 if $(echo "${ppd_info}" | grep "${DEVID}" >/dev/null 2>&1) ; then 874 DMDL="MDL" 875 DMFG="MFG" 876 devid="$(/bin/gzgrep -e "^[ ]*${DMDL}:|^[ ]*${DMFG}:" "${1}")" 877 devidmdl="$(devid_spec_entry "${devid}" "${DMDL}")" 878 devidmfg="$(devid_spec_entry "${devid}" "${DMFG}")" 879 else 880 devidmdl= 881 devidmfg= 882 fi 883 modmanuf=$(manuf_name_alias "${realmanuf}" ${aliasfile}) 884 885 return 0 886} 887 888# 889# generate_cache_file_entry() 890# 891# Returns a cache file entry for the specified PPD file. 892# 893# $1 - modmanuf 894# $2 - model 895# $3 - nickn 896# $4 - devidmfg 897# $5 - devidmdl 898# $6 - Full path to the specified PPD file 899# 900generate_cache_file_entry() 901{ 902 if debugger "generate_cache_file_entry" ; then 903 set -x 904 fi 905 906 echo "${1}":"${2}":"${3}":"${4}":"${5}":"${6}" 907} 908 909# 910# Expand specified file to the full path. 911# 912# $1 - File path to expand 913# 914# Return code set to 0 if expanded successfully, otherwise set to 1. 915# 916ppd_pathname() 917{ 918 if debugger ; then 919 set -x 920 fi 921 922 if [[ -f "${1}" && -s "${1}" ]] ; then 923 (cd "$(/bin/dirname "${1}")" ; \ 924 echo "$(/bin/pwd)/$(/bin/basename "${1}")") || return 1 925 return 0 926 else 927 return 1 928 fi 929} 930 931# 932# Returns the PPD repsitory path associated with the specified 933# PPD repository name. 934# 935# $1 - Repository name 936# 937get_rep_path() 938{ 939 if debugger ; then 940 set -x 941 fi 942 943 case ${1} in 944 ${SYSTEM}) 945 echo "${SYSTEMREP}" 946 ;; 947 ${VENDOR}) 948 echo "${VENDORREP}" 949 ;; 950 ${ADMIN}) 951 echo "${ADMINREP}" 952 ;; 953 ${USER}) 954 echo "${USERREP}" 955 ;; 956 *) 957 echo "${UNSET}" 958 ;; 959 esac 960} 961 962# 963# Returns the PPD respository name from the repository path 964# 965# $1 - PPD repository path 966# 967get_rep_name() 968{ 969 if debugger ; then 970 set -x 971 fi 972 973 case ${1} in 974 ${SYSTEMREP}) 975 echo "${SYSTEM}" 976 ;; 977 ${VENDORREP}) 978 echo "${VENDOR}" 979 ;; 980 ${ADMINREP}) 981 echo "${ADMIN}" 982 ;; 983 ${USERREP}) 984 echo "${USER}" 985 ;; 986 "all") 987 echo "all" 988 ;; 989 *) 990 echo "${UNSET}" 991 ;; 992 esac 993} 994 995# 996# Returns 0 if a matching label name is found in the specified repository, 997# otherwise returns 1. 998# 999# $1 - repository path 1000# $2 - label name 1001# 1002label_path_in_repository() 1003{ 1004 if debugger "label_path_in_repository" ; then 1005 set -x 1006 fi 1007 1008 [[ "${1}" != "" && "${2}" != "" ]] || return 1 1009 lpir_rc=1 1010 for repository in ${REPOSITORIES} ; do 1011 if [[ "${repository}" = "${1}" && -d "${1}/${2}" ]] ; then 1012 lpir_rc=0 1013 break 1014 fi 1015 done 1016 return ${lpir_rc} 1017} 1018 1019# 1020# Returns 0 if the source label path is the same 1021# as the destination label path, otherwise returns 1. 1022# 1023# $1 - full path to source PPD file (source label path) 1024# $2 - destination repository path 1025# $3 - destination label name 1026# 1027label_path_match() 1028{ 1029 if debugger "label_path_match" ; then 1030 set -x 1031 fi 1032 1033 # dest repository not specified 1034 if [[ "${2}" = "${UNSET}" ]] ; then 1035 # dest label not specified 1036 if [[ "${3}" = "${UNSET}" ]] ; then 1037 # 1038 # We've found a match if the label path is in a known 1039 # repository. 1040 # 1041 lpath="${1%/*/*}" 1042 label_path_in_repository \ 1043 "${1%/*/*/*}" "${lpath##*/}" || return 1 1044 else 1045 # 1046 # If the source label path exists in the 1047 # in a known repository, and the destination 1048 # label is the same as the source label, 1049 # then we'll assume the default destination 1050 # repository is the same as the source 1051 # destination repository. 1052 # 1053 [[ "${1%/*/*}" = "${1%/*/*/*}/${3}" ]] || return 1 1054 label_path_in_repository "${1%/*/*/*}" "${3}" || \ 1055 return 1 1056 fi 1057 1058 # dest repository specified, dest label not specified 1059 elif [[ "${3}" = "${UNSET}" ]] ; then 1060 # 1061 # If the destination repository path is the same as the 1062 # source repository, and if the source label exists in the 1063 # destination repository path, then we'll assume the default 1064 # destination label is the same as the source label. 1065 # 1066 [[ "${2}" = "${1%/*/*/*}" ]] || return 1 1067 lpath="${1%/*/*}" 1068 label_path_in_repository "${2}" "${lpath##*/}" || return 1 1069 1070 # dest repository and dest label specified. 1071 else 1072 # 1073 # We've found a match if the destination and label 1074 # match those of the source label path, and the source 1075 # label path is in a known repository. 1076 # 1077 [[ "${1%/*/*}" = "${2}/${3}" ]] || return 1 1078 label_path_in_repository "${2}" "${3}" || return 1 1079 fi 1080 return 0 1081} 1082 1083# 1084# Returns 0 if specified label name is a reserved label, otherwise 1085# returns 1. 1086# 1087# $1 - label name 1088# 1089reserved_label() 1090{ 1091 if debugger ; then 1092 set -x 1093 fi 1094 1095 rl_rc=1 1096 for labelname in ${RESERVEDLABELS} ; do 1097 if [[ "${1}" = "${labelname}" ]] ; then 1098 rl_rc=0 1099 break 1100 fi 1101 done 1102 return ${rl_rc} 1103} 1104 1105# 1106# Returns a list of all labels that exist in a repository that are 1107# not reserved labels. 1108# 1109# $1 - Full path of repository 1110# $2 - Repository name 1111# 1112get_rep_label_list() 1113{ 1114 if debugger ; then 1115 set -x 1116 fi 1117 1118 # 1119 # Get a list of all labels that exist in all of the 1120 # PPD file repository. 1121 # 1122 for lname in $(/bin/ls "${1}" 2>/dev/null) ; do 1123 if [[ -d "${1}/${lname}" ]] ; then 1124 if ! reserved_label "${lname}" ; then 1125 echo "${lname} " 1126 fi 1127 fi 1128 done 1129} 1130 1131# 1132# Returns a valid PPD label. 1133# 1134# Verifies the specified PPD label is a valid label. If the 1135# label is not set, then it is set to a default value. 1136# 1137# Return code set to 0 if the specified PPD label is valid, otherwise 1. 1138# 1139# $1 - PPD label 1140# 1141valid_specified_label() 1142{ 1143 if debugger ; then 1144 set -x 1145 fi 1146 1147 # Verify the specified label 1148 vsl_rc=0 1149 case "${1}" in 1150 "all") 1151 # Reserved label name with -a or -g options 1152 if [[ "${action}" = "${ADD}" || \ 1153 "${action}" = "${GENERATEENTRY}" ]] ; then 1154 print -n "$myprog: " 1>&2 1155 gettext "reserved PPD label name: ${1}\n" 1>&2 1156 vsl_rc=1 1157 else 1158 echo "${1}" 1159 fi 1160 ;; 1161 1162 "ppdcache" | "caches" | "manufaliases") 1163 # Reserved label names with any option 1164 print -n "$myprog: " 1>&2 1165 gettext "reserved PPD label name: ${1}\n" 1>&2 1166 vsl_rc=1 1167 ;; 1168 1169 "" | "${UNSET}") 1170 # Label name not specified. Set the default label name. 1171 # For -g and -a, default is "user", otherwise, default 1172 # is "all". 1173 if [[ "${action}" = "${ADD}" || \ 1174 "${action}" = "${GENERATEENTRY}" ]] ; then 1175 echo "${USER}" 1176 else 1177 echo "all" 1178 fi 1179 ;; 1180 1181 *) 1182 # label cannot be "." or ".." 1183 if [[ "${1}" = "." || "${1}" = ".." ]] ; then 1184 print -n "$myprog: " 1>&2 1185 gettext "PPD label name cannot be " 1>&2 1186 gettext "\".\" or \"..\"\n" 1>&2 1187 vsl_rc=1 1188 fi 1189 1190 # Label name cannot contain special characters 1191 echo "${1}" | /bin/egrep "${SPECIALCHARS}" >/dev/null 1192 if [[ $? -eq 0 ]] ; then 1193 print -n "$myprog: " 1>&2 1194 gettext "PPD label name contains " 1>&2 1195 gettext "an invalid character: ${1}\n" 1>&2 1196 vsl_rc=1 1197 else 1198 echo "${1}" 1199 fi 1200 ;; 1201 esac 1202 return ${vsl_rc} 1203} 1204 1205# 1206# Returns the full path of any variant copy of the source file in 1207# the destination label/repository. 1208# 1209# $1 - Full path to source PPD file 1210# $2 - Full path to destination PPD file 1211# 1212# Return code set to 1213# 0 - Copy doesn't exist 1214# 1 - Duplicate copy exists 1215# 2 - Variant copy exists 1216# 1217variant_copy() 1218{ 1219 if debugger ; then 1220 set -x 1221 fi 1222 1223 # 1224 # First make sure there is not a .ppd and a .ppd.gz version 1225 # of the destination file; users should know not to do this. 1226 # 1227 if [[ -e "${2%.gz}" && -e "${2%.gz}.gz" ]] ; then 1228 /bin/rm -f "${2%.gz}" >/dev/null 2>&1 1229 fi 1230 1231 # Use gzcmp to compare PPD files as it can deal with 1232 # gzipped or regular files. 1233 if $(${GZCMP} "${1}" "${2}"* >/dev/null 2>&1) ; then 1234 echo "${2}"* 1235 return 1 1236 elif [[ -e "${2%.gz}" ]] ; then 1237 echo "${2%.gz}" 1238 return 2 1239 elif [[ -e "${2%.gz}.gz" ]] ; then 1240 echo "${2%.gz}.gz" 1241 return 2 1242 else 1243 # 1244 # A PPD file doesn't exist in the destination 1245 # repository under the destination label. 1246 # Just display the source PPD file, ensuring 1247 # it has a gzip extension as we will always 1248 # try to gzip the copy in the destination. 1249 # 1250 if [[ "${1#*.ppd}" = ".gz" ]] ; then 1251 echo "${2}" 1252 else 1253 echo "${2}.gz" 1254 fi 1255 return 0 1256 fi 1257} 1258 1259# 1260# $1 - Directory mode 1261# $2 - Directory owner (i.e., root:lp) 1262# $3 - Directory to create 1263# 1264make_dir() 1265{ 1266 if debugger "make_dir" ; then 1267 set -x 1268 fi 1269 1270 [[ ! -d "${3}" ]] || return 0 1271 /bin/mkdir "${3}" >/dev/null 2>&1 || return 1 1272 set_perms ${1} ${2} "${3}" 1273 return 0 1274} 1275 1276# 1277# Remove a ppdmgr generated cache (in /var/lp/ppd/cache) 1278# if it doesn't have an associated label in the repository. 1279# 1280# $1 - Full path to label 1281# $2 - Cache name 1282# 1283remove_unassociated_cache() 1284{ 1285 if debugger "remove_unassociated_cache" ; then 1286 set -x 1287 fi 1288 1289 if [[ "${1}" != "${UNSET}" ]] ; then 1290 if [[ -n "${1}" && ! -d "${1}" ]] ; then 1291 # 1292 # The label doesn't exist, so delete 1293 # the associated cache file. 1294 # 1295 /bin/rm -f "${VARCACHES}/${2}" >/dev/null 2>&1 1296 fi 1297 fi 1298} 1299 1300# 1301# Sorted copies of cache files for each label in each PPD repository 1302# are maintained in /var/lp/ppd/caches/<PPD respository>-<label>. 1303# This is done so that changes in delivered cache files can be 1304# detected. If a difference in cache files is detected, or a 1305# cache file is either added or removed, then we know that 1306# the ppdcache file needs to be updated. 1307# 1308# Get a list of all cache files and compare against the list 1309# of labels in all of the PPD file repositories. They should 1310# be the same. If there is a label in one of the PPD file 1311# repositories that doesn't have an associated cache file, then 1312# we don't worry about it now, as that will be resolved when 1313# we update the cache for that label. However, if there is 1314# a cache file associated with a label that no longer exists, then 1315# remove the cache file. 1316# 1317# $1 - Full path to repository (or "all") 1318# $2 - Label name 1319# 1320update_cache() 1321{ 1322 if debugger ; then 1323 set -x 1324 fi 1325 1326 # 1327 # Determine which labels in which PPD repository the 1328 # cache file will be updated for. 1329 # 1330 if [[ "${1}" = "all" ]] ; then 1331 rname="${REPOSITORIES}" 1332 else 1333 rname="${1}" 1334 fi 1335 1336 uc_rc=0 1337 for dstreppath in ${rname} ; do 1338 labellist= 1339 if [[ "${2}" = "all" ]] ; then 1340 dstrepname=$(get_rep_name "${dstreppath}") 1341 labellist=$(get_rep_label_list "${dstreppath}" \ 1342 "${dstrepname}") 1343 else 1344 1345 # Ensure the label exists in the PPD file repository. 1346 if [[ -d "${dstreppath}/${2}" ]] ; then 1347 labellist="${2}" 1348 fi 1349 fi 1350 1351 # 1352 # Update the cache for each label in the PPD repository 1353 # 1354 for dstlabel in ${labellist} ; do 1355 ulc_msg=$(update_label_cache "${dstreppath}" \ 1356 "${dstrepname}" "${dstlabel}") 1357 if [[ $? -ne 0 ]] ; then 1358 echo "${ulc_msg}" 1359 uc_rc=1 1360 fi 1361 done 1362 done 1363 1364 # Update the golden cache file. 1365 update_golden_cache 1366 return ${uc_rc} 1367} 1368 1369# $1 - exit status 1370ppdmgr_exit() 1371{ 1372 if debugger "ppdmgr_exit" ; then 1373 set -x 1374 fi 1375 1376 /bin/rm -rf "${ppdmgrtmpdir}" >/dev/null 2>&1 1377 exit ${1} 1378} 1379 1380 1381usage() 1382{ 1383 gettext "usage:\n" 1>&2 1384 print -n "\t$myprog: " 1>&2 1385 gettext "-a <ppd_filename_path> [ -L <label> ]\n" 1>&2 1386 gettext "\t\t[ -R <ppd_repository> ] [-w]\n" 1>&2 1387 print -n "\t$myprog: " 1>&2 1388 gettext "-r [ -L <label> ] [ -R <ppd_repository> ]\n" 1>&2 1389 print -n "\t$myprog: " 1>&2 1390 gettext "-u [ -L <label> ] [ -R <ppd_repository> ]\n" 1>&2 1391 1392 ppdmgr_exit ${FAIL} 1393} 1394 1395########################################################################## 1396# main 1397########################################################################## 1398 1399myprog=$(/bin/basename $0) 1400 1401SaveIFS="$IFS" 1402NoSpaceTabIFS=' 1403' 1404 1405# Updatable PPD repository 1406VARDIR=/var/lp/ppd 1407 1408# Delivered PPD respository 1409SYSTEMREP=/usr/share/ppd 1410ADMINREP=/usr/local/share/ppd 1411VENDORREP=/opt/share/ppd 1412USERREP=${VARDIR} 1413 1414RESERVEDREPS="${SYSTEMREP} ${ADMINREP} ${VENDORREP}" 1415REPOSITORIES="${USERREP} ${RESERVEDREPS}" 1416RESERVEDLABELS="all caches ppdcache manufaliases" 1417 1418# Directory where system:SUNWfoomatic is delivered 1419FOOCACHEDIR=/usr/lib/lp/caches 1420 1421# Deliveries 1422SYSTEM=system 1423VENDOR=vendor 1424ADMIN=admin 1425USER=user 1426 1427# Sytem PPD cache name used by printmgr 1428GOLDCACHE=${USERREP}/ppdcache 1429 1430# Delivered caches directory 1431CACHES=caches 1432MANUFALIASES=manufaliases 1433 1434# Updated caches directory 1435VARCACHES=${VARDIR}/${CACHES} 1436 1437# valid PPD file name extensions 1438PEXT=ppd 1439GEXT=gz 1440FILEEXTS=".${PEXT} .${PEXT}.${GEXT}" 1441 1442# Default modes and owners 1443DIRMODE=755 1444DIROWNER=root:lp 1445ADMINOWNER=root:root 1446FILEMODE=444 1447FILEOWNER=root:lp 1448 1449# ppdmgr actions 1450ADD=add 1451GENERATEENTRY=generateentry 1452UPDATE=update 1453REBUILD=rebuild 1454 1455SUCCESS=0 1456FAIL=1 1457WARN=2 1458 1459MAXLABELNAME=256 1460GZIP="/bin/gzip -c" 1461GZCMP="/bin/gzcmp -s" 1462CMP="/bin/cmp -s" 1463SPECIALCHARS=":" 1464SEP=":" 1465 1466debug=0 1467wflag=0 1468status=${SUCCESS} 1469 1470UNSET="" 1471ppdlabel=${UNSET} 1472ppdrepname=${UNSET} 1473ppdreppath=${UNSET} 1474modmanuf= 1475model= 1476nickn= 1477devidmdl= 1478devidmfg= 1479 1480ppdmgrtmpdir=/tmp/ppdmgr.$$ 1481/bin/mkdir "${ppdmgrtmpdir}" >/dev/null 2>&1 1482set_perms ${DIRMODE} ${DIROWNER} "${ppdmgrtmpdir}" 1483 1484aliasfile=${USERREP}/manufaliases 1485tmpfilepath= 1486 1487 1488OPTS=a:g:L:rR:uwZ 1489while getopts "$OPTS" arg ; do 1490 case ${arg} in 1491 a) # add PPD file 1492 action=${ADD} 1493 origsrcppdpath=${OPTARG} 1494 ;; 1495 1496 g) # create cache entry 1497 action=${GENERATEENTRY} 1498 origsrcppdpath=${OPTARG} 1499 ;; 1500 1501 L) # PPD label name 1502 ppdlabel=${OPTARG} 1503 ;; 1504 1505 r) # rebuild cache 1506 action=${REBUILD} 1507 ;; 1508 1509 R) # PPD file repository to use 1510 ppdrepname=${OPTARG} 1511 ;; 1512 1513 u) # update cache 1514 action=${UPDATE} 1515 ;; 1516 1517 w) # display PPD file path 1518 wflag=1 1519 ;; 1520 1521 Z) # debug 1522 debug=1 1523 ;; 1524 1525 ?) 1526 usage 1527 ;; 1528 esac 1529done 1530 1531if debugger "Main" ; then 1532 set -x 1533fi 1534 1535if [[ $# -lt 1 || -z "${action}" ]] ; then 1536 usage 1537fi 1538 1539# ignore wflag unless specified with -a 1540if [[ ${wflag} -eq 1 && "${action}" != ${ADD} ]] ; then 1541 wflag=0 1542fi 1543 1544# 1545# Ensure the destination PPD repository directory is set 1546# to match the specified repository. If the 1547# destination PPD file repository was specified, then 1548# it must be one of the following: 1549# "user" 1550# "admin" 1551# "vendor" 1552# "system" 1553# "all" 1554# 1555case "${ppdrepname}" in 1556"${SYSTEM}") 1557 ppdreppath="${SYSTEMREP}" 1558 ;; 1559"${ADMIN}") 1560 ppdreppath="${ADMINREP}" 1561 ;; 1562"${VENDOR}") 1563 ppdreppath="${VENDORREP}" 1564 ;; 1565"${USER}") 1566 ppdreppath="${USERREP}" 1567 ;; 1568"all") 1569 if [[ "${action}" = "${ADD}" || \ 1570 "${action}" = "${GENERATEENTRY}" ]] ; then 1571 print -n "$myprog: " 1>&2 1572 gettext "reserved PPD repository name: " 1>&2 1573 gettext "${ppdrepname}\n" 1>&2 1574 ppdmgr_exit ${FAIL} 1575 fi 1576 ppdreppath="all" 1577 ;; 1578"${UNSET}"|"") 1579 ppdreppath="${UNSET}" 1580 ;; 1581 1582*) 1583 print -n "$myprog: " 1>&2 1584 gettext "invalid PPD repository name: ${ppdrepname}\n" 1>&2 1585 ppdmgr_exit ${FAIL} 1586 ;; 1587esac 1588 1589# 1590# When a source PPD file's path is from a known repository, the 1591# destination repository and desination label are assumed to be the 1592# same as the source PPD file's unless a differing repository or label 1593# was specified. 1594# 1595if [[ "${action}" = "${ADD}" || "${action}" = "${GENERATEENTRY}" ]] ; then 1596 1597 srcppdpath=$(ppd_pathname "${origsrcppdpath}") 1598 ppd_pathname_rc=$? 1599 if [[ ${ppd_pathname_rc} -ne 0 ]] ; then 1600 print -n "$myprog: " 1>&2 1601 gettext "invalid PPD file: ${origsrcppdpath}\n" 1>&2 1602 ppdmgr_exit ${ppd_pathname_rc} 1603 fi 1604 1605 # Path cannot contain special characters 1606 echo "${srcppdpath}" | /bin/egrep "${SPECIALCHARS}" >/dev/null 1607 if [[ $? -eq 0 ]] ; then 1608 print -n "$myprog: " 1>&2 1609 gettext "PPD path contains " 1>&2 1610 gettext "an invalid character: ${ppd_pathname}\n" 1>&2 1611 ppdmgr_exit ${FAIL} 1612 fi 1613 ppdfname=$(/bin/basename "${origsrcppdpath}") 1614 1615 # 1616 # Check to see if there's any work to be done. If the source file 1617 # is already in the destination repository under the destination 1618 # label, then there's nothing left to do. We exit rather than 1619 # going on to do an update on the label in the repository as 1620 # it could possible take a long time to update. If an add was 1621 # requested, it could have come from an application, so we want 1622 # to return quickly. 1623 # 1624 if label_path_match "${srcppdpath}" "${ppdreppath}" "${ppdlabel}" ; then 1625 if [[ ${wflag} -eq 1 || \ 1626 "${action}" = "${GENERATEENTRY}" ]] ; then 1627 echo "${srcppdpath}" 1628 fi 1629 ppdmgr_exit ${SUCCESS} 1630 fi 1631fi 1632 1633ppdlabel=$(valid_specified_label "${ppdlabel}") 1634if [[ $? -ne 0 ]] ; then 1635 ppdmgr_exit ${FAIL} 1636fi 1637 1638if [[ "${ppdreppath}" = "${UNSET}" ]] ; then 1639 ppdreppath="${USERREP}" 1640fi 1641 1642dstrepname=$(get_rep_name "${ppdreppath}") 1643 1644case "${action}" in 1645"${ADD}") 1646 # 1647 # Attempt to add the PPD file to the repository under the 1648 # specified label. If any errors occur, final_dst_ppd_path 1649 # will contain the error message rather than the path to the 1650 # PPD file. 1651 # 1652 final_dst_ppd_path=$(add_ppd "${srcppdpath}" "${ppdfname}" \ 1653 "${ppdreppath}" "${dstrepname}" "${ppdlabel}") 1654 add_ppd_rc=$? 1655 case ${add_ppd_rc} in 1656 0) # 1657 # The PPD file was added. Update the specified 1658 # cache associated with the label if the PPD file 1659 # was added successfully and was not a duplicate. 1660 # Ensure any changes are also reflected in the 1661 # golden cache. 1662 # 1663 add_ppd_msg=$(update_label_cache "${ppdreppath}" \ 1664 "${dstrepname}" "${ppdlabel}") 1665 apm_rc=$? 1666 1667 echo "${add_ppd_msg}" | /bin/grep "${final_dst_ppd_path}" 1668 path_in_msg=$? 1669 1670 # 1671 # Only report cache update errors if the file that was 1672 # added was one that was reported as not being added 1673 # to the cache. This really should happen as the file 1674 # was verified during the add. 1675 # 1676 if [[ ${apm_rc} -ne 0 && ${path_in_msg} -eq 0 ]] ; then 1677 print -n "$myprog: " 1>&2 1678 gettext "printer information does not reflect " 1>&2 1679 gettext "the\nfollowing PPD file(s):\n" 1>&2 1680 print "${add_ppd_msg}" 1>&2 1681 status=${FAIL} 1682 else 1683 update_golden_cache 1684 1685 # 1686 # Display the full path to the added PPD file, 1687 # if requested (-w). 1688 # 1689 if [[ ${wflag} -eq 1 ]] ; then 1690 print "${final_dst_ppd_path}" 1691 fi 1692 fi 1693 ;; 1694 1695 1) # Duplicate copy exists 1696 if [[ ${wflag} -eq 1 ]] ; then 1697 print "${final_dst_ppd_path}" 1698 fi 1699 ;; 1700 1701 2) # Varying copy exists 1702 print -n "$myprog: " 1>&2 1703 gettext "differing variant of source PPD file " 1>&2 1704 gettext "already exists at\n" 1>&2 1705 gettext "${final_dst_ppd_path}\n" 1>&2 1706 status=${FAIL} 1707 ;; 1708 *) # The PPD file was not added as a problem occurred. 1709 # Display the error message. 1710 print -n "$myprog: " 1>&2 1711 print "${final_dst_ppd_path}" 1>&2 1712 status=${FAIL} 1713 ;; 1714 1715 esac 1716 ;; 1717 1718"${GENERATEENTRY}") 1719 # 1720 # Create a cache file entry for the specified PPD file and 1721 # display it on standard out. 1722 # 1723 verify_ppd_file "${srcppdpath}" 1724 if [[ $? -eq 0 ]] ; then 1725 dstdir="${ppdreppath}/${ppdlabel}/${modmanuf}" 1726 final_dst_path="${dstdir}/$(/bin/basename ${srcppdpath})" 1727 verify_ppd_location "${final_dst_path}" 1728 if [[ $? -eq 0 ]] ; then 1729 # Generate the cache file entry 1730 print "$(generate_cache_file_entry "${modmanuf}" \ 1731 "${model}" "${nickn}" "${devidmfg}" "${devidmdl}" \ 1732 "${final_dst_path}")" 1733 else 1734 print -n "$myprog: " 1>&2 1735 gettext "PPD file not in valid location\n" 1>&2 1736 gettext \ 1737 "(<repository>/<label>/<manufacturer>/<PPD file>):\n\t${1}\n" 1>&2 1738 status=${FAIL} 1739 fi 1740 1741 else 1742 print -n "$myprog: " 1>&2 1743 gettext "invalid PPD file: ${1}\n" 1>&2 1744 status=${FAIL} 1745 fi 1746 ;; 1747 1748"${REBUILD}" | "${UPDATE}") 1749 update_msg=$(update_cache "${ppdreppath}" "${ppdlabel}") 1750 if [[ $? -ne 0 ]] ; then 1751 print -n "$myprog: " 1>&2 1752 gettext "printer information does not reflect " 1>&2 1753 gettext "the\nfollowing PPD file(s):\n" 1>&2 1754 print "${update_msg}" 1>&2 1755 status=${WARN} 1756 fi 1757 ;; 1758 1759*) 1760 usage 1761 ;; 1762esac 1763 1764ppdmgr_exit ${status} 1765