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 2009 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=$ppdmgrtmpdir/tmpgoldencache 329 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=$ppdmgrtmpdir/unsortedcache 444 445 # 446 # Before processing new files, remove any cache entries 447 # which may be invalid. 448 # 449 valid_files= 450 if [[ -e "${2}" && "${action}" != "${REBUILD}" ]] ; then 451 valid_files=$(remove_invalid_cache_entries "${2}") 452 if [[ -n "${valid_files}" ]] ; then 453 echo "${valid_files}" >>${ucfile} 454 fi 455 fi 456 457 # 458 # If there are no valid PPD files in the current cache file, 459 # and there are no new PPD files to process, the only thing 460 # left to do is to remove the current cache file. 461 # 462 if [[ -z "${valid_files}" && -z "${1}" ]] ; then 463 /bin/rm -f "${2}" >/dev/null 2>&1 464 /bin/rm -f "${ucfile}" >/dev/null 2>&1 465 return 0 466 fi 467 468 # 469 # For each of the label's PPD files, generate 470 # a cache file entry and add it to the cache file. 471 # 472 vpl_rc=0 473 vpf_rc=0 474 vpl_msg= 475 vpf_msg= 476 IFS="$NoSpaceTabIFS" 477 for fname in ${1} ; do 478 IFS="$SaveIFS" 479 if [[ -n "${fname}" ]] ; then 480 verify_ppd_location "${fname}" 481 vpl_rc=$? 482 if [[ ${vpl_rc} -ne 0 ]] ; then 483 vpl_msg="${vpl_msg}\t${fname}\n" 484 fi 485 486 verify_ppd_file "${fname}" 487 vpf_rc=$? 488 if [[ ${vpf_rc} -ne 0 ]] ; then 489 vpf_msg="${vpf_msg}\t${fname}\n" 490 fi 491 492 if [[ ${vpl_rc} -eq 0 && ${vpf_rc} -eq 0 ]] ; then 493 echo "$(generate_cache_file_entry \ 494 "${modmanuf}" "${model}" "${nickn}" \ 495 "${devidmfg}" "${devidmdl}" "${fname}")" 496 fi 497 fi 498 IFS="$NoSpaceTabIFS" 499 done >>"${ucfile}" 500 IFS="$SaveIFS" 501 /bin/sort -u "${ucfile}" >>"${4}" 2>/dev/null 502 /bin/rm -f "${ucfile}" >/dev/null 2>&1 503 504 [[ -n "${vpl_msg}" || -n "${vpf_msg}" ]] || return 0 505 if [[ -n ${vpl_msg} ]] ; then 506 gettext " PPD file(s) not in valid location\n" 2>/dev/null 507 gettext \ 508 " (<repository>/<label>/<manufacturer>/<PPD file>):\n" 2>/dev/null 509 echo "${vpl_msg}" 510 fi 511 if [[ -n ${vpf_msg} ]] ; then 512 gettext " invalid PPD file(s):\n" 2>/dev/null 513 echo "${vpf_msg}" 514 fi 515 return 1 516} 517 518# 519# Update current cache file with candidate cache file if there are 520# differences. 521# 522# $1 - Current cache file 523# $2 - Candidate cache file to update 524# $3 - Repository name 525# 526update_current_cache_file() 527{ 528 if debugger "update_current_cache_file" ; then 529 set -x 530 fi 531 532 if [[ ! -s "${2}" ]] ; then 533 # 534 # Candidate cache has zero size (label 535 # directory with no PPD files under it). 536 # Delete the empty candidate cache 537 # file and delete the current cache 538 # file. 539 # 540 /bin/rm -f "${1}" >/dev/null 2>&1 541 /bin/rm -f "${2}" >/dev/null 2>&1 542 elif [[ -e "${1}" ]] ; then 543 # 544 # If there are differences between the current 545 # cache file and the newly generated one, then 546 # replace the current one with the new one, and 547 # set the flag to update the golden ppdcache 548 # file. 549 # 550 if changes_in_cache "${1}" "${2}" ; then 551 set_perms ${FILEMODE} ${FILEOWNER} "${2}" 552 /bin/mv -f "${2}" "${1}" >/dev/null 2>&1 553 else 554 /bin/rm -f "${2}" >/dev/null 2>&1 555 fi 556 else 557 558 # 559 # There is no current cache file. Move the candidate 560 # to the caches directory. 561 # 562 set_perms ${FILEMODE} ${FILEOWNER} "${2}" 563 /bin/mv -f "${2}" "${1}" >/dev/null 2>&1 564 fi 565} 566 567# 568# Returns 0 if there are files in $1 with newer timestamp 569# than $2 or if deletions have occurred under $1, 570# otherwise returns 1. 571# 572# $1 - Full path to the destination label 573# $2 - Full path to label cache file 574# 575changes_under_label() 576{ 577 if debugger ; then 578 set -x 579 fi 580 581 # First check for newer files in the directory 582 if [[ -e "${2}" && "${action}" != "${REBUILD}" ]] ; then 583 newfiles=$(/bin/find "${1}" -type f -newer "${2}") 584 else 585 newfiles=$(/bin/find "${1}" -type f) 586 fi 587 echo "${newfiles}" 588 [[ -z "${newfiles}" ]] || return 0 589 590 # 591 # Need to detect if PPD files have been deleted by checking 592 # timestamps on label and manufacturer directories. 593 # 594 [[ ! "${1}" -nt "${2}" ]] || return 0 595 /bin/find "${1}" -type d -newer "${2}" >/dev/null 2>&1 || return 1 596 return 0 597} 598 599# 600# If -R was specified, or the timestamp on the specified label's 601# directory or any of the PPD files under the specified label in 602# the specified PPD file respository is newer than the cache file 603# associated with the label, then generate a new sorted cache file. 604# 605# The new cache will replace the existing one (if any) only if there 606# are differences. Note: if -r was specified, then a new cache file 607# file will always be installed at 608# /var/lp/ppd/caches/<PPD file repository name>-<label name> 609# 610# $1 - Full path of the destination PPD file repository 611# $2 - Destination PPD file repository name 612# $3 - Destination label name 613# 614update_label_cache() 615{ 616 if debugger ; then 617 set -x 618 fi 619 620 dstlabelpath="${1}/${3}" 621 replabelcachepath="${1}/${CACHES}/${3}" 622 varlabelcachepath="${VARCACHES}/${2}${SEP}${3}" 623 624 ulc_rc=0 625 if [[ -d "${dstlabelpath}" ]] ; then 626 627 # 628 # If the cache doesn't exist for a label, 629 # or if there were any changes under a label 630 # (i.e., the timestamp on the label directory or any 631 # of the PPD files under it is newer than the 632 # existing cache file), then generate a new cache file. 633 # 634 tmpcachepath=$ppdmgrtmpdir/tmpcachepath 635 636 # if this is a system repository, check for a prepopulated cache 637 if [[ "${2}" = "${SYSTEM}" && -e ${FOOCACHEDIR}/${3}.cache ]] ; then 638 # copy prepopulated cache 639 /bin/cp -f ${FOOCACHEDIR}/${3}.cache ${tmpcachepath} 640 641 else 642 newfileslist=$(changes_under_label "${dstlabelpath}" \ 643 "${varlabelcachepath}") 644 if [[ $? -eq 0 ]] ; then 645 err_files=$(generate_label_cache_file \ 646 "${newfileslist}" "${varlabelcachepath}" \ 647 "${dstlabelpath}" "${tmpcachepath}") 648 if [[ $? -ne 0 ]] ; then 649 # 650 # At least one PPD file was invalid. 651 # Don't return yet, as the cache info 652 # for the valid PPD files can still be 653 # used to generate a cache file. 654 # 655 echo "${err_files}" 656 ulc_rc=1 657 fi 658 fi 659 fi 660 661 if [[ -e "${tmpcachepath}" ]] ; then 662 update_current_cache_file \ 663 "${varlabelcachepath}" "${tmpcachepath}" "${2}" 664 /bin/rm -f "${tmpcachepath}" >/dev/null 2>&1 665 fi 666 else 667 # 668 # If there is a cache file in /var/lp/ppd/caches associated 669 # with the label which no longer exists, remove it. 670 # 671 /bin/rm -f "${varlabelcachepath}" >/dev/null 2>&1 672 fi 673 return ${ulc_rc} 674} 675 676# 677# Returns the alias for the specified real manufacturer's name. 678# 679# $1 - Real manufacturer's name 680# $2 - File containing list of files that have manufacturers aliases 681# 682manuf_name_alias() 683{ 684 if debugger ; then 685 set -x 686 fi 687 688 # 689 # Found a couple of PPD files which had special characters 690 # in the Manufacturer name (i.e, the following is the Manufacturer 691 # entry: 692 # *Manufacturer: "Canon Inc. (Kosugi Offic" 693 # We'll only search the alias file for "Canon Inc." 694 # 695 tmpmanuf="${1% *\(*}" 696 697 # Search alias files for a match on the real manufacturer name 698 if [[ -s "${2}" ]] ; then 699 # 700 # Check the manufacturer aliases file for case 701 # insensitive match of the Manufacturer entry 702 # from the PPD file. If a match is found, 703 # then modify the manufacturer entry to 704 # be that of the specified alias. 705 # 706 manufaliases=$(/bin/egrep -i \ 707 "^${tmpmanuf}:|:${tmpmanuf}:|:${tmpmanuf}$" "${2}") 708 if [[ -n "${manufaliases}" ]] ; then 709 echo "${manufaliases%%:*}" 710 break 711 else 712 echo "${tmpmanuf}" 713 fi 714 else 715 echo "${tmpmanuf}" 716 fi 717} 718 719# 720# Returns 0 if the extension to the specified PPD file is a known 721# extension, otherwise returns 1. 722# 723# $1 - Full path to PPD file 724# 725# Set upon return: 726# ppdfileext - PPD file ext (.ppd or .ppd.gz) 727# 728verify_file_ext() 729{ 730 if debugger ; then 731 set -x 732 fi 733 734 if [[ "${1%.gz}".gz = "${1}" ]] ; then 735 ppdfileext=${GEXT} 736 elif [[ "${1%.ppd}".ppd = "${1}" ]] ; then 737 ppdfileext=${PEXT} 738 else 739 # invalid PPD file name extension 740 return 1 741 fi 742 743 return 0 744} 745 746# 747# Return the lines from the specified PPD file matching the specified 748# spec items. 749# 750# $1 - spec entries from PPD file 751# $2 - spec item 752# 753# $1 example - 1 string with substrings separated by newline: 754# *PPD-Adobe: "4.3" 755# *Manufacturer: "HP" 756# *Product: "(officejet 4200 series)" 757# *ModelName: "HP OfficeJet 4200" 758# *NickName: "HP OfficeJet 4200 Foomatic/hpijs (recommended)" 759# $2 example: 760# ^\*Manufacturer 761# 762spec_entry() 763{ 764 if debugger ; then 765 set -x 766 fi 767 768 item=$(echo "${1}" | /bin/grep ${2}) 769 # Remove everything up to and including the first quote 770 item=${item#*\"} 771 # Remove the end quote 772 echo "${item%\"}" 773} 774 775# 776# Return the lines from the specified PPD file matching the specified 777# spec items. 778# 779# Note: this is similar to spec_entry() except the tokens in the 780# spec entry are different. 781# 782# $1 - spec entries from PPD file 783# $2 - spec item 784# 785devid_spec_entry() 786{ 787 if debugger ; then 788 set -x 789 fi 790 791 item=$(echo "${1}" | /bin/grep ${2}) 792 # Remove everything up to and including the first semi-colon 793 item=${item#*\:} 794 # Remove the end quote 795 echo ${item%\;} 796 797} 798 799# 800# Verifies that the specified PPD file 801# - has a valid extension 802# - has the following required spec file entries: 803# *PPD-Adobe: "4.3" 804# Manufacturer 805# Product 806# ModelName 807# NickName 808# 809# In addition, the manufacture and model from the IEEE1284 device id 810# information will be gathered here, although it's not an error that 811# it isn't in the PPD file as many don't contain the IEEE1284 info. 812# 813# $1 - Full path to PPD file 814# 815# Return codes: 816# 0 success 817# 1 invalid PPD file 818# 819verify_ppd_file() 820{ 821 if debugger ; then 822 set -x 823 fi 824 825 ADOBESPEC="PPD-Adobe" 826 MANUF="Manufacturer" 827 PRODUCT="Product" 828 MODEL="ModelName" 829 NICKNAME="NickName" 830 DEVID="1284DeviceID" 831 832 # Verify the PPD file extension 833 verify_file_ext "${1}" || return 1 834 835 # Query for the required spec items 836 searchentries="^\*${ADOBESPEC}:|^\*${MANUF}:|^\*${PRODUCT}:" 837 searchentries="${searchentries}|^\*${MODEL}:|^\*${NICKNAME}:" 838 searchentries="${searchentries}|^\*${DEVID}:" 839 ppd_info="$(/bin/gzgrep -e "${searchentries}" "${1}")" 840 841 # 842 # Process the query results to verify each of the required spec 843 # file items appears in the PPD file. 844 # 845 for spec_item in ${ADOBESPEC} ${MANUF} ${PRODUCT} ${MODEL} \ 846 ${NICKNAME} ; do 847 entry=$(spec_entry "${ppd_info}" "^\*${spec_item}:") 848 [[ ! -z "${entry}" ]] || return 1 849 case ${spec_item} in 850 ${MANUF}) 851 realmanuf="${entry}" 852 ;; 853 ${PRODUCT}) 854 product="${entry}" 855 ;; 856 ${MODEL}) 857 model="${entry}" 858 ;; 859 ${NICKNAME}) 860 # 861 # Remove the model and any commas and spaces 862 # which appear before the driver 863 # 864 nickn="${entry#$model[, ]*}" 865 ;; 866 esac 867 868 done 869 870 # Save IEEE1284 device id information 871 if $(echo "${ppd_info}" | grep "${DEVID}" >/dev/null 2>&1) ; then 872 DMDL="MDL" 873 DMFG="MFG" 874 devid="$(/bin/gzgrep -e "^[ ]*${DMDL}:|^[ ]*${DMFG}:" "${1}")" 875 devidmdl="$(devid_spec_entry "${devid}" "${DMDL}")" 876 devidmfg="$(devid_spec_entry "${devid}" "${DMFG}")" 877 else 878 devidmdl= 879 devidmfg= 880 fi 881 modmanuf=$(manuf_name_alias "${realmanuf}" ${aliasfile}) 882 883 return 0 884} 885 886# 887# generate_cache_file_entry() 888# 889# Returns a cache file entry for the specified PPD file. 890# 891# $1 - modmanuf 892# $2 - model 893# $3 - nickn 894# $4 - devidmfg 895# $5 - devidmdl 896# $6 - Full path to the specified PPD file 897# 898generate_cache_file_entry() 899{ 900 if debugger "generate_cache_file_entry" ; then 901 set -x 902 fi 903 904 echo "${1}":"${2}":"${3}":"${4}":"${5}":"${6}" 905} 906 907# 908# Expand specified file to the full path. 909# 910# $1 - File path to expand 911# 912# Return code set to 0 if expanded successfully, otherwise set to 1. 913# 914ppd_pathname() 915{ 916 if debugger ; then 917 set -x 918 fi 919 920 if [[ -f "${1}" && -s "${1}" ]] ; then 921 (cd "$(/bin/dirname "${1}")" ; \ 922 echo "$(/bin/pwd)/$(/bin/basename "${1}")") || return 1 923 return 0 924 else 925 return 1 926 fi 927} 928 929# 930# Returns the PPD repsitory path associated with the specified 931# PPD repository name. 932# 933# $1 - Repository name 934# 935get_rep_path() 936{ 937 if debugger ; then 938 set -x 939 fi 940 941 case ${1} in 942 ${SYSTEM}) 943 echo "${SYSTEMREP}" 944 ;; 945 ${VENDOR}) 946 echo "${VENDORREP}" 947 ;; 948 ${ADMIN}) 949 echo "${ADMINREP}" 950 ;; 951 ${USER}) 952 echo "${USERREP}" 953 ;; 954 *) 955 echo "${UNSET}" 956 ;; 957 esac 958} 959 960# 961# Returns the PPD respository name from the repository path 962# 963# $1 - PPD repository path 964# 965get_rep_name() 966{ 967 if debugger ; then 968 set -x 969 fi 970 971 case ${1} in 972 ${SYSTEMREP}) 973 echo "${SYSTEM}" 974 ;; 975 ${VENDORREP}) 976 echo "${VENDOR}" 977 ;; 978 ${ADMINREP}) 979 echo "${ADMIN}" 980 ;; 981 ${USERREP}) 982 echo "${USER}" 983 ;; 984 "all") 985 echo "all" 986 ;; 987 *) 988 echo "${UNSET}" 989 ;; 990 esac 991} 992 993# 994# Returns 0 if a matching label name is found in the specified repository, 995# otherwise returns 1. 996# 997# $1 - repository path 998# $2 - label name 999# 1000label_path_in_repository() 1001{ 1002 if debugger "label_path_in_repository" ; then 1003 set -x 1004 fi 1005 1006 [[ "${1}" != "" && "${2}" != "" ]] || return 1 1007 lpir_rc=1 1008 for repository in ${REPOSITORIES} ; do 1009 if [[ "${repository}" = "${1}" && -d "${1}/${2}" ]] ; then 1010 lpir_rc=0 1011 break 1012 fi 1013 done 1014 return ${lpir_rc} 1015} 1016 1017# 1018# Returns 0 if the source label path is the same 1019# as the destination label path, otherwise returns 1. 1020# 1021# $1 - full path to source PPD file (source label path) 1022# $2 - destination repository path 1023# $3 - destination label name 1024# 1025label_path_match() 1026{ 1027 if debugger "label_path_match" ; then 1028 set -x 1029 fi 1030 1031 # dest repository not specified 1032 if [[ "${2}" = "${UNSET}" ]] ; then 1033 # dest label not specified 1034 if [[ "${3}" = "${UNSET}" ]] ; then 1035 # 1036 # We've found a match if the label path is in a known 1037 # repository. 1038 # 1039 lpath="${1%/*/*}" 1040 label_path_in_repository \ 1041 "${1%/*/*/*}" "${lpath##*/}" || return 1 1042 else 1043 # 1044 # If the source label path exists in the 1045 # in a known repository, and the destination 1046 # label is the same as the source label, 1047 # then we'll assume the default destination 1048 # repository is the same as the source 1049 # destination repository. 1050 # 1051 [[ "${1%/*/*}" = "${1%/*/*/*}/${3}" ]] || return 1 1052 label_path_in_repository "${1%/*/*/*}" "${3}" || \ 1053 return 1 1054 fi 1055 1056 # dest repository specified, dest label not specified 1057 elif [[ "${3}" = "${UNSET}" ]] ; then 1058 # 1059 # If the destination repository path is the same as the 1060 # source repository, and if the source label exists in the 1061 # destination repository path, then we'll assume the default 1062 # destination label is the same as the source label. 1063 # 1064 [[ "${2}" = "${1%/*/*/*}" ]] || return 1 1065 lpath="${1%/*/*}" 1066 label_path_in_repository "${2}" "${lpath##*/}" || return 1 1067 1068 # dest repository and dest label specified. 1069 else 1070 # 1071 # We've found a match if the destination and label 1072 # match those of the source label path, and the source 1073 # label path is in a known repository. 1074 # 1075 [[ "${1%/*/*}" = "${2}/${3}" ]] || return 1 1076 label_path_in_repository "${2}" "${3}" || return 1 1077 fi 1078 return 0 1079} 1080 1081# 1082# Returns 0 if specified label name is a reserved label, otherwise 1083# returns 1. 1084# 1085# $1 - label name 1086# 1087reserved_label() 1088{ 1089 if debugger ; then 1090 set -x 1091 fi 1092 1093 rl_rc=1 1094 for labelname in ${RESERVEDLABELS} ; do 1095 if [[ "${1}" = "${labelname}" ]] ; then 1096 rl_rc=0 1097 break 1098 fi 1099 done 1100 return ${rl_rc} 1101} 1102 1103# 1104# Returns a list of all labels that exist in a repository that are 1105# not reserved labels. 1106# 1107# $1 - Full path of repository 1108# $2 - Repository name 1109# 1110get_rep_label_list() 1111{ 1112 if debugger ; then 1113 set -x 1114 fi 1115 1116 # 1117 # Get a list of all labels that exist in all of the 1118 # PPD file repository. 1119 # 1120 for lname in $(/bin/ls "${1}" 2>/dev/null) ; do 1121 if [[ -d "${1}/${lname}" ]] ; then 1122 if ! reserved_label "${lname}" ; then 1123 echo "${lname} " 1124 fi 1125 fi 1126 done 1127} 1128 1129# 1130# Returns a valid PPD label. 1131# 1132# Verifies the specified PPD label is a valid label. If the 1133# label is not set, then it is set to a default value. 1134# 1135# Return code set to 0 if the specified PPD label is valid, otherwise 1. 1136# 1137# $1 - PPD label 1138# 1139valid_specified_label() 1140{ 1141 if debugger ; then 1142 set -x 1143 fi 1144 1145 # Verify the specified label 1146 vsl_rc=0 1147 case "${1}" in 1148 "all") 1149 # Reserved label name with -a or -g options 1150 if [[ "${action}" = "${ADD}" || \ 1151 "${action}" = "${GENERATEENTRY}" ]] ; then 1152 print -n "$myprog: " 1>&2 1153 gettext "reserved PPD label name: ${1}\n" 1>&2 1154 vsl_rc=1 1155 else 1156 echo "${1}" 1157 fi 1158 ;; 1159 1160 "ppdcache" | "caches" | "manufaliases") 1161 # Reserved label names with any option 1162 print -n "$myprog: " 1>&2 1163 gettext "reserved PPD label name: ${1}\n" 1>&2 1164 vsl_rc=1 1165 ;; 1166 1167 "" | "${UNSET}") 1168 # Label name not specified. Set the default label name. 1169 # For -g and -a, default is "user", otherwise, default 1170 # is "all". 1171 if [[ "${action}" = "${ADD}" || \ 1172 "${action}" = "${GENERATEENTRY}" ]] ; then 1173 echo "${USER}" 1174 else 1175 echo "all" 1176 fi 1177 ;; 1178 1179 *) 1180 # label cannot be "." or ".." 1181 if [[ "${1}" = "." || "${1}" = ".." ]] ; then 1182 print -n "$myprog: " 1>&2 1183 gettext "PPD label name cannot be " 1>&2 1184 gettext "\".\" or \"..\"\n" 1>&2 1185 vsl_rc=1 1186 fi 1187 1188 # Label name cannot contain special characters 1189 echo "${1}" | /bin/egrep "${SPECIALCHARS}" >/dev/null 1190 if [[ $? -eq 0 ]] ; then 1191 print -n "$myprog: " 1>&2 1192 gettext "PPD label name contains " 1>&2 1193 gettext "an invalid character: ${1}\n" 1>&2 1194 vsl_rc=1 1195 else 1196 echo "${1}" 1197 fi 1198 ;; 1199 esac 1200 return ${vsl_rc} 1201} 1202 1203# 1204# Returns the full path of any variant copy of the source file in 1205# the destination label/repository. 1206# 1207# $1 - Full path to source PPD file 1208# $2 - Full path to destination PPD file 1209# 1210# Return code set to 1211# 0 - Copy doesn't exist 1212# 1 - Duplicate copy exists 1213# 2 - Variant copy exists 1214# 1215variant_copy() 1216{ 1217 if debugger ; then 1218 set -x 1219 fi 1220 1221 # 1222 # First make sure there is not a .ppd and a .ppd.gz version 1223 # of the destination file; users should know not to do this. 1224 # 1225 if [[ -e "${2%.gz}" && -e "${2%.gz}.gz" ]] ; then 1226 /bin/rm -f "${2%.gz}" >/dev/null 2>&1 1227 fi 1228 1229 # Use gzcmp to compare PPD files as it can deal with 1230 # gzipped or regular files. 1231 if $(${GZCMP} "${1}" "${2}"* >/dev/null 2>&1) ; then 1232 echo "${2}"* 1233 return 1 1234 elif [[ -e "${2%.gz}" ]] ; then 1235 echo "${2%.gz}" 1236 return 2 1237 elif [[ -e "${2%.gz}.gz" ]] ; then 1238 echo "${2%.gz}.gz" 1239 return 2 1240 else 1241 # 1242 # A PPD file doesn't exist in the destination 1243 # repository under the destination label. 1244 # Just display the source PPD file, ensuring 1245 # it has a gzip extension as we will always 1246 # try to gzip the copy in the destination. 1247 # 1248 if [[ "${1#*.ppd}" = ".gz" ]] ; then 1249 echo "${2}" 1250 else 1251 echo "${2}.gz" 1252 fi 1253 return 0 1254 fi 1255} 1256 1257# 1258# $1 - Directory mode 1259# $2 - Directory owner (i.e., root:lp) 1260# $3 - Directory to create 1261# 1262make_dir() 1263{ 1264 if debugger "make_dir" ; then 1265 set -x 1266 fi 1267 1268 [[ ! -d "${3}" ]] || return 0 1269 /bin/mkdir "${3}" >/dev/null 2>&1 || return 1 1270 set_perms ${1} ${2} "${3}" 1271 return 0 1272} 1273 1274# 1275# Remove a ppdmgr generated cache (in /var/lp/ppd/cache) 1276# if it doesn't have an associated label in the repository. 1277# 1278# $1 - Full path to label 1279# $2 - Cache name 1280# 1281remove_unassociated_cache() 1282{ 1283 if debugger "remove_unassociated_cache" ; then 1284 set -x 1285 fi 1286 1287 if [[ "${1}" != "${UNSET}" ]] ; then 1288 if [[ -n "${1}" && ! -d "${1}" ]] ; then 1289 # 1290 # The label doesn't exist, so delete 1291 # the associated cache file. 1292 # 1293 /bin/rm -f "${VARCACHES}/${2}" >/dev/null 2>&1 1294 fi 1295 fi 1296} 1297 1298# 1299# Sorted copies of cache files for each label in each PPD repository 1300# are maintained in /var/lp/ppd/caches/<PPD respository>-<label>. 1301# This is done so that changes in delivered cache files can be 1302# detected. If a difference in cache files is detected, or a 1303# cache file is either added or removed, then we know that 1304# the ppdcache file needs to be updated. 1305# 1306# Get a list of all cache files and compare against the list 1307# of labels in all of the PPD file repositories. They should 1308# be the same. If there is a label in one of the PPD file 1309# repositories that doesn't have an associated cache file, then 1310# we don't worry about it now, as that will be resolved when 1311# we update the cache for that label. However, if there is 1312# a cache file associated with a label that no longer exists, then 1313# remove the cache file. 1314# 1315# $1 - Full path to repository (or "all") 1316# $2 - Label name 1317# 1318update_cache() 1319{ 1320 if debugger ; then 1321 set -x 1322 fi 1323 1324 # 1325 # Determine which labels in which PPD repository the 1326 # cache file will be updated for. 1327 # 1328 if [[ "${1}" = "all" ]] ; then 1329 rname="${REPOSITORIES}" 1330 else 1331 rname="${1}" 1332 fi 1333 1334 uc_rc=0 1335 for dstreppath in ${rname} ; do 1336 labellist= 1337 if [[ "${2}" = "all" ]] ; then 1338 dstrepname=$(get_rep_name "${dstreppath}") 1339 labellist=$(get_rep_label_list "${dstreppath}" \ 1340 "${dstrepname}") 1341 else 1342 1343 # Ensure the label exists in the PPD file repository. 1344 if [[ -d "${dstreppath}/${2}" ]] ; then 1345 labellist="${2}" 1346 fi 1347 fi 1348 1349 # 1350 # Update the cache for each label in the PPD repository 1351 # 1352 for dstlabel in ${labellist} ; do 1353 ulc_msg=$(update_label_cache "${dstreppath}" \ 1354 "${dstrepname}" "${dstlabel}") 1355 if [[ $? -ne 0 ]] ; then 1356 echo "${ulc_msg}" 1357 uc_rc=1 1358 fi 1359 done 1360 done 1361 1362 # Update the golden cache file. 1363 update_golden_cache 1364 return ${uc_rc} 1365} 1366 1367# $1 - exit status 1368ppdmgr_exit() 1369{ 1370 if debugger "ppdmgr_exit" ; then 1371 set -x 1372 fi 1373 1374 /bin/rm -rf "${ppdmgrtmpdir}" >/dev/null 2>&1 1375 exit ${1} 1376} 1377 1378 1379usage() 1380{ 1381 gettext "usage:\n" 1>&2 1382 print -n "\t$myprog: " 1>&2 1383 gettext "-a <ppd_filename_path> [ -L <label> ]\n" 1>&2 1384 gettext "\t\t[ -R <ppd_repository> ] [-w]\n" 1>&2 1385 print -n "\t$myprog: " 1>&2 1386 gettext "-r [ -L <label> ] [ -R <ppd_repository> ]\n" 1>&2 1387 print -n "\t$myprog: " 1>&2 1388 gettext "-u [ -L <label> ] [ -R <ppd_repository> ]\n" 1>&2 1389 1390 ppdmgr_exit ${FAIL} 1391} 1392 1393########################################################################## 1394# main 1395########################################################################## 1396 1397myprog=$(/bin/basename $0) 1398 1399SaveIFS="$IFS" 1400NoSpaceTabIFS=' 1401' 1402 1403# Updatable PPD repository 1404VARDIR=/var/lp/ppd 1405 1406# Delivered PPD respository 1407SYSTEMREP=/usr/share/ppd 1408ADMINREP=/usr/local/share/ppd 1409VENDORREP=/opt/share/ppd 1410USERREP=${VARDIR} 1411 1412RESERVEDREPS="${SYSTEMREP} ${ADMINREP} ${VENDORREP}" 1413REPOSITORIES="${USERREP} ${RESERVEDREPS}" 1414RESERVEDLABELS="all caches ppdcache manufaliases" 1415 1416# Directory where system:SUNWfoomatic is delivered 1417FOOCACHEDIR=/usr/lib/lp/caches 1418 1419# Deliveries 1420SYSTEM=system 1421VENDOR=vendor 1422ADMIN=admin 1423USER=user 1424 1425# Sytem PPD cache name used by printmgr 1426GOLDCACHE=${USERREP}/ppdcache 1427 1428# Delivered caches directory 1429CACHES=caches 1430MANUFALIASES=manufaliases 1431 1432# Updated caches directory 1433VARCACHES=${VARDIR}/${CACHES} 1434 1435# valid PPD file name extensions 1436PEXT=ppd 1437GEXT=gz 1438FILEEXTS=".${PEXT} .${PEXT}.${GEXT}" 1439 1440# Default modes and owners 1441DIRMODE=755 1442DIROWNER=root:lp 1443ADMINOWNER=root:root 1444FILEMODE=444 1445FILEOWNER=root:lp 1446 1447# ppdmgr actions 1448ADD=add 1449GENERATEENTRY=generateentry 1450UPDATE=update 1451REBUILD=rebuild 1452 1453SUCCESS=0 1454FAIL=1 1455WARN=2 1456 1457MAXLABELNAME=256 1458GZIP="/bin/gzip -c" 1459GZCMP="/bin/gzcmp -s" 1460CMP="/bin/cmp -s" 1461SPECIALCHARS=":" 1462SEP=":" 1463 1464debug=0 1465wflag=0 1466status=${SUCCESS} 1467 1468UNSET="" 1469ppdlabel=${UNSET} 1470ppdrepname=${UNSET} 1471ppdreppath=${UNSET} 1472modmanuf= 1473model= 1474nickn= 1475devidmdl= 1476devidmfg= 1477 1478ppdmgrtmpdir=$(/usr/bin/mktemp -t -d ppdmgr.XXXXXX) 1479if [ -z "$ppdmgrtmpdir" ] ; then 1480 print -n "$myprog: " 1>&2 1481 gettext "Fatal error: could not create temporary directory\n" 1>&2 1482 exit 1 1483fi 1484 1485aliasfile=${USERREP}/manufaliases 1486tmpfilepath= 1487 1488 1489OPTS=a:g:L:rR:uwZ 1490while getopts "$OPTS" arg ; do 1491 case ${arg} in 1492 a) # add PPD file 1493 action=${ADD} 1494 origsrcppdpath=${OPTARG} 1495 ;; 1496 1497 g) # create cache entry 1498 action=${GENERATEENTRY} 1499 origsrcppdpath=${OPTARG} 1500 ;; 1501 1502 L) # PPD label name 1503 ppdlabel=${OPTARG} 1504 ;; 1505 1506 r) # rebuild cache 1507 action=${REBUILD} 1508 ;; 1509 1510 R) # PPD file repository to use 1511 ppdrepname=${OPTARG} 1512 ;; 1513 1514 u) # update cache 1515 action=${UPDATE} 1516 ;; 1517 1518 w) # display PPD file path 1519 wflag=1 1520 ;; 1521 1522 Z) # debug 1523 debug=1 1524 ;; 1525 1526 ?) 1527 usage 1528 ;; 1529 esac 1530done 1531 1532if debugger "Main" ; then 1533 set -x 1534fi 1535 1536if [[ $# -lt 1 || -z "${action}" ]] ; then 1537 usage 1538fi 1539 1540# ignore wflag unless specified with -a 1541if [[ ${wflag} -eq 1 && "${action}" != ${ADD} ]] ; then 1542 wflag=0 1543fi 1544 1545# 1546# Ensure the destination PPD repository directory is set 1547# to match the specified repository. If the 1548# destination PPD file repository was specified, then 1549# it must be one of the following: 1550# "user" 1551# "admin" 1552# "vendor" 1553# "system" 1554# "all" 1555# 1556case "${ppdrepname}" in 1557"${SYSTEM}") 1558 ppdreppath="${SYSTEMREP}" 1559 ;; 1560"${ADMIN}") 1561 ppdreppath="${ADMINREP}" 1562 ;; 1563"${VENDOR}") 1564 ppdreppath="${VENDORREP}" 1565 ;; 1566"${USER}") 1567 ppdreppath="${USERREP}" 1568 ;; 1569"all") 1570 if [[ "${action}" = "${ADD}" || \ 1571 "${action}" = "${GENERATEENTRY}" ]] ; then 1572 print -n "$myprog: " 1>&2 1573 gettext "reserved PPD repository name: " 1>&2 1574 gettext "${ppdrepname}\n" 1>&2 1575 ppdmgr_exit ${FAIL} 1576 fi 1577 ppdreppath="all" 1578 ;; 1579"${UNSET}"|"") 1580 ppdreppath="${UNSET}" 1581 ;; 1582 1583*) 1584 print -n "$myprog: " 1>&2 1585 gettext "invalid PPD repository name: ${ppdrepname}\n" 1>&2 1586 ppdmgr_exit ${FAIL} 1587 ;; 1588esac 1589 1590# 1591# When a source PPD file's path is from a known repository, the 1592# destination repository and desination label are assumed to be the 1593# same as the source PPD file's unless a differing repository or label 1594# was specified. 1595# 1596if [[ "${action}" = "${ADD}" || "${action}" = "${GENERATEENTRY}" ]] ; then 1597 1598 srcppdpath=$(ppd_pathname "${origsrcppdpath}") 1599 ppd_pathname_rc=$? 1600 if [[ ${ppd_pathname_rc} -ne 0 ]] ; then 1601 print -n "$myprog: " 1>&2 1602 gettext "invalid PPD file: ${origsrcppdpath}\n" 1>&2 1603 ppdmgr_exit ${ppd_pathname_rc} 1604 fi 1605 1606 # Path cannot contain special characters 1607 echo "${srcppdpath}" | /bin/egrep "${SPECIALCHARS}" >/dev/null 1608 if [[ $? -eq 0 ]] ; then 1609 print -n "$myprog: " 1>&2 1610 gettext "PPD path contains " 1>&2 1611 gettext "an invalid character: ${ppd_pathname}\n" 1>&2 1612 ppdmgr_exit ${FAIL} 1613 fi 1614 ppdfname=$(/bin/basename "${origsrcppdpath}") 1615 1616 # 1617 # Check to see if there's any work to be done. If the source file 1618 # is already in the destination repository under the destination 1619 # label, then there's nothing left to do. We exit rather than 1620 # going on to do an update on the label in the repository as 1621 # it could possible take a long time to update. If an add was 1622 # requested, it could have come from an application, so we want 1623 # to return quickly. 1624 # 1625 if label_path_match "${srcppdpath}" "${ppdreppath}" "${ppdlabel}" ; then 1626 if [[ ${wflag} -eq 1 || \ 1627 "${action}" = "${GENERATEENTRY}" ]] ; then 1628 echo "${srcppdpath}" 1629 fi 1630 ppdmgr_exit ${SUCCESS} 1631 fi 1632fi 1633 1634ppdlabel=$(valid_specified_label "${ppdlabel}") 1635if [[ $? -ne 0 ]] ; then 1636 ppdmgr_exit ${FAIL} 1637fi 1638 1639if [[ "${ppdreppath}" = "${UNSET}" ]] ; then 1640 ppdreppath="${USERREP}" 1641fi 1642 1643dstrepname=$(get_rep_name "${ppdreppath}") 1644 1645case "${action}" in 1646"${ADD}") 1647 # 1648 # Attempt to add the PPD file to the repository under the 1649 # specified label. If any errors occur, final_dst_ppd_path 1650 # will contain the error message rather than the path to the 1651 # PPD file. 1652 # 1653 final_dst_ppd_path=$(add_ppd "${srcppdpath}" "${ppdfname}" \ 1654 "${ppdreppath}" "${dstrepname}" "${ppdlabel}") 1655 add_ppd_rc=$? 1656 case ${add_ppd_rc} in 1657 0) # 1658 # The PPD file was added. Update the specified 1659 # cache associated with the label if the PPD file 1660 # was added successfully and was not a duplicate. 1661 # Ensure any changes are also reflected in the 1662 # golden cache. 1663 # 1664 add_ppd_msg=$(update_label_cache "${ppdreppath}" \ 1665 "${dstrepname}" "${ppdlabel}") 1666 apm_rc=$? 1667 1668 echo "${add_ppd_msg}" | /bin/grep "${final_dst_ppd_path}" 1669 path_in_msg=$? 1670 1671 # 1672 # Only report cache update errors if the file that was 1673 # added was one that was reported as not being added 1674 # to the cache. This really should happen as the file 1675 # was verified during the add. 1676 # 1677 if [[ ${apm_rc} -ne 0 && ${path_in_msg} -eq 0 ]] ; then 1678 print -n "$myprog: " 1>&2 1679 gettext "printer information does not reflect " 1>&2 1680 gettext "the\nfollowing PPD file(s):\n" 1>&2 1681 print "${add_ppd_msg}" 1>&2 1682 status=${FAIL} 1683 else 1684 update_golden_cache 1685 1686 # 1687 # Display the full path to the added PPD file, 1688 # if requested (-w). 1689 # 1690 if [[ ${wflag} -eq 1 ]] ; then 1691 print "${final_dst_ppd_path}" 1692 fi 1693 fi 1694 ;; 1695 1696 1) # Duplicate copy exists 1697 if [[ ${wflag} -eq 1 ]] ; then 1698 print "${final_dst_ppd_path}" 1699 fi 1700 ;; 1701 1702 2) # Varying copy exists 1703 print -n "$myprog: " 1>&2 1704 gettext "differing variant of source PPD file " 1>&2 1705 gettext "already exists at\n" 1>&2 1706 gettext "${final_dst_ppd_path}\n" 1>&2 1707 status=${FAIL} 1708 ;; 1709 *) # The PPD file was not added as a problem occurred. 1710 # Display the error message. 1711 print -n "$myprog: " 1>&2 1712 print "${final_dst_ppd_path}" 1>&2 1713 status=${FAIL} 1714 ;; 1715 1716 esac 1717 ;; 1718 1719"${GENERATEENTRY}") 1720 # 1721 # Create a cache file entry for the specified PPD file and 1722 # display it on standard out. 1723 # 1724 verify_ppd_file "${srcppdpath}" 1725 if [[ $? -eq 0 ]] ; then 1726 dstdir="${ppdreppath}/${ppdlabel}/${modmanuf}" 1727 final_dst_path="${dstdir}/$(/bin/basename ${srcppdpath})" 1728 verify_ppd_location "${final_dst_path}" 1729 if [[ $? -eq 0 ]] ; then 1730 # Generate the cache file entry 1731 print "$(generate_cache_file_entry "${modmanuf}" \ 1732 "${model}" "${nickn}" "${devidmfg}" "${devidmdl}" \ 1733 "${final_dst_path}")" 1734 else 1735 print -n "$myprog: " 1>&2 1736 gettext "PPD file not in valid location\n" 1>&2 1737 gettext \ 1738 "(<repository>/<label>/<manufacturer>/<PPD file>):\n\t${1}\n" 1>&2 1739 status=${FAIL} 1740 fi 1741 1742 else 1743 print -n "$myprog: " 1>&2 1744 gettext "invalid PPD file: ${1}\n" 1>&2 1745 status=${FAIL} 1746 fi 1747 ;; 1748 1749"${REBUILD}" | "${UPDATE}") 1750 update_msg=$(update_cache "${ppdreppath}" "${ppdlabel}") 1751 if [[ $? -ne 0 ]] ; then 1752 print -n "$myprog: " 1>&2 1753 gettext "printer information does not reflect " 1>&2 1754 gettext "the\nfollowing PPD file(s):\n" 1>&2 1755 print "${update_msg}" 1>&2 1756 status=${WARN} 1757 fi 1758 ;; 1759 1760*) 1761 usage 1762 ;; 1763esac 1764 1765ppdmgr_exit ${status} 1766