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