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.
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.
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]
22 # Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 # Use is subject to license terms.
27 # Description: Script to generate the Solaris printmgr 'ppdcache' file from the
28 # ppd files installed in the given ppd database directory
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> ]
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
40 # -g <ppd_filename_path> - Generate a cache file entry
41 # for the specified PPD file
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".
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
68 # Can only be specified
70 # SUNW* - anything starting with
71 # SUNW is reserved for
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.
81 # The following are the possible
82 # values for <ppd_repository> and
83 # location in the system:
87 # admin /usr/local/share/ppd
88 # vendor /opt/share/ppd
89 # system /usr/share/ppd
90 # all all repositories
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
102 # -w - Display full path of where the
103 # ppd file is located on the system.
104 # Only valid with -a, otherwise the
107 # If -a, -g, -r, or -u are specified on the command line, only the last action
108 # specified will be performed.
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
115 PATH
=/bin
:/usr
/bin
:/usr
/sbin
export PATH
118 TEXTDOMAIN
="SUNW_OST_OSCMD"
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.
126 # $1 - Name of calling routine
129 [[ ${debug} -eq 1 ]] ||
return 1
130 if [[ -n "${1}" ]] ; then
131 echo "In ${1}..." 1>&2
137 # Set the ownership and permissions on a file.
141 # $3 - Full path to file
145 /bin
/chmod -f ${1} "${3}" >/dev
/null
2>&1
146 /bin
/chown
-f ${2} "${3}" >/dev
/null
2>&1
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
155 # $1 - destination repository name
157 create_adminrep_dirs
()
159 if debugger
"check_adminrep_dirs" ; then
163 # Only create administrator repository directories, if needed.
164 [[ "${1}" = "${ADMIN}" ]] ||
return 0
166 # Check /usr/local/share/ppd
167 [[ ! -d "${ADMINREP}" ]] ||
return 0
169 # Check /usr/local/share
170 admpar
=$
(/bin
/dirname "${ADMINREP}")
171 if [[ ! -d "${admpar}" ]] ; then
174 admppar
=$
(/bin
/dirname "${admpar}")
175 if [[ ! -d "${admppar}" ]] ; then
176 make_dir
${DIRMODE} ${ADMINOWNER} "${admppar}" || \
179 make_dir ${DIRMODE} ${ADMINOWNER} "${admpar}" ||
return 1
181 make_dir
${DIRMODE} ${ADMINOWNER} ${ADMINREP} ||
return 1
186 # Returns full path to PPD file that was added to the system.
188 # $1 - Full path to source PPD file
190 # $3 - Full path to repository
191 # $4 - Repository name
195 # 0 - File successfully added
197 # 2 - Duplicate file already exists
205 verify_ppd_file
"${1}"
206 if [[ $?
-ne 0 ]] ; then
207 gettext "invalid PPD file: ${1}" 2>/dev
/null
211 # The destination path can now be set
212 dstlabelpath
="${3}/${5}"
213 dstmanufpath
="${dstlabelpath}/${modmanuf}"
214 dstpath
="${dstmanufpath}/${2}"
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}")
222 if [[ ${ap_rc} -ne 0 ]] ; then
223 echo "${dst_copy_path}"
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.
235 if [[ "${4}" != "${USER}" && "${4}" != "${ADMIN}" ]] ; then
236 gettext "invalid PPD file repository name: ${4}" 2>/dev
/null
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
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
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
265 set_perms
${FILEMODE} ${FILEOWNER} "${dst_copy_path}"
267 echo "${dst_copy_path}"
273 # Returns 0 if the cache needs to be modified, otherwise
276 # $1 - Full path to cache
277 # $2 - Full path to cache replacement candidate
281 if debugger "changes_in_cache
" ; then
285 if [[ "${action}" = "${REBUILD}" ]] ; then
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
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.
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.
306 update_golden_cache
()
309 if debugger
"update_golden_cache" ; then
314 # Remove any cache files that don't have an associated
317 for cname
in $
(/bin
/ls ${VARCACHES} 2>/dev
/null
) ; do
318 repname
="${cname%%:*}"
320 checkdir
="$(get_rep_path ${repname})/${cfile}"
321 remove_unassociated_cache
"${checkdir}" "${cname}"
325 # Combine the contents of all cache files into a
326 # temporary golden cache file.
328 tmpgoldencache
=$ppdmgrtmpdir/tmpgoldencache
330 /bin
/sort "${VARCACHES}"/* >>"${tmpgoldencache}" 2>/dev
/null
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
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.
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
348 /bin/rm -f "${tmpgoldencache}" >/dev/null 2>&1
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
359 # Returns a list of PPD files that exist.
361 # $1 - Full path to cache file
363 remove_invalid_cache_entries
()
369 [[ -s "${1}" ]] ||
return
372 for centry
in $
(/bin
/cat "${1}" 2>/dev
/null
) ; do
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.
379 if [[ -n "${centry}" ]] ; then
380 ppdfile
="${centry##*:}"
381 if [[ -n "${ppdfile}" && -e "${ppdfile}" &&
382 "${1}" -nt "${ppdfile}" ]] ; then
392 # Returns 0 if the path to the PPD is as follows:
393 # <PPD file repository>/<label>/<manufacturer>/<PPD file>
394 # otherwise, returns 1
396 # $1 Full path to PPD file
398 verify_ppd_location
()
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.
409 ppd_file_repository
=${1%/*/*/*}
411 for repository
in ${REPOSITORIES} ; do
412 if [[ "${repository}" = "${ppd_file_repository}" ]] ; then
421 # Generate, and sort, cache entries for each PPD files in the specified
422 # list to the specified file.
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
433 generate_label_cache_file
()
440 # Generate a cache file containing cache entries for
441 # all files in the label.
443 ucfile
=$ppdmgrtmpdir/unsortedcache
446 # Before processing new files, remove any cache entries
447 # which may be invalid.
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}
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.
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
469 # For each of the label's PPD files, generate
470 # a cache file entry and add it to the cache file.
477 for fname
in ${1} ; do
479 if [[ -n "${fname}" ]] ; then
480 verify_ppd_location
"${fname}"
482 if [[ ${vpl_rc} -ne 0 ]] ; then
483 vpl_msg
="${vpl_msg}\t${fname}\n"
486 verify_ppd_file
"${fname}"
488 if [[ ${vpf_rc} -ne 0 ]] ; then
489 vpf_msg
="${vpf_msg}\t${fname}\n"
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}")"
501 /bin
/sort -u "${ucfile}" >>"${4}" 2>/dev
/null
502 /bin
/rm -f "${ucfile}" >/dev
/null
2>&1
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
508 " (<repository>/<label>/<manufacturer>/<PPD file>):\n" 2>/dev
/null
511 if [[ -n ${vpf_msg} ]] ; then
512 gettext " invalid PPD file(s):\n" 2>/dev
/null
519 # Update current cache file with candidate cache file if there are
522 # $1 - Current cache file
523 # $2 - Candidate cache file to update
524 # $3 - Repository name
526 update_current_cache_file
()
528 if debugger
"update_current_cache_file" ; then
532 if [[ ! -s "${2}" ]] ; then
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
540 /bin
/rm -f "${1}" >/dev
/null
2>&1
541 /bin
/rm -f "${2}" >/dev
/null
2>&1
542 elif [[ -e "${1}" ]] ; then
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
550 if changes_in_cache
"${1}" "${2}" ; then
551 set_perms
${FILEMODE} ${FILEOWNER} "${2}"
552 /bin/mv -f "${2}" "${1}" >/dev/null 2>&1
554 /bin/rm -f "${2}" >/dev/null 2>&1
559 # There is no current cache file. Move the candidate
560 # to the caches directory.
562 set_perms ${FILEMODE} ${FILEOWNER} "${2}"
563 /bin
/mv -f "${2}" "${1}" >/dev
/null
2>&1
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.
572 # $1 - Full path to the destination label
573 # $2 - Full path to label cache file
575 changes_under_label
()
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}")
585 newfiles
=$
(/bin
/find "${1}" -type f
)
588 [[ -z "${newfiles}" ]] ||
return 0
591 # Need to detect if PPD files have been deleted by checking
592 # timestamps on label and manufacturer directories.
594 [[ ! "${1}" -nt "${2}" ]] ||
return 0
595 /bin
/find "${1}" -type d
-newer "${2}" >/dev
/null
2>&1 ||
return 1
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.
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>
610 # $1 - Full path of the destination PPD file repository
611 # $2 - Destination PPD file repository name
612 # $3 - Destination label name
620 dstlabelpath
="${1}/${3}"
621 replabelcachepath
="${1}/${CACHES}/${3}"
622 varlabelcachepath
="${VARCACHES}/${2}${SEP}${3}"
625 if [[ -d "${dstlabelpath}" ]] ; then
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.
634 tmpcachepath
=$ppdmgrtmpdir/tmpcachepath
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}
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
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.
661 if [[ -e "${tmpcachepath}" ]] ; then
662 update_current_cache_file \
663 "${varlabelcachepath}" "${tmpcachepath}" "${2}"
664 /bin/rm -f "${tmpcachepath}" >/dev/null 2>&1
668 # If there is a cache file in /var/lp/ppd/caches associated
669 # with the label which no longer exists, remove it.
671 /bin/rm -f "${varlabelcachepath}" >/dev/null 2>&1
677 # Returns the alias for the specified real manufacturer's name.
679 # $1 - Real manufacturer's name
680 # $2 - File containing list of files that have manufacturers aliases
689 # Found a couple of PPD files which had special characters
690 # in the Manufacturer name (i.e, the following is the Manufacturer
692 # *Manufacturer: "Canon Inc.
(Kosugi Offic
"
693 # We'll only search the alias file for "Canon Inc.
"
695 tmpmanuf="${1% *\(*}"
697 # Search alias files for a match on the real manufacturer name
698 if [[ -s "${2}" ]] ; then
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.
706 manufaliases=$(/bin/egrep -i \
707 "^
${tmpmanuf}:|:${tmpmanuf}:|:${tmpmanuf}$" "${2}")
708 if [[ -n "${manufaliases}" ]] ; then
709 echo "${manufaliases%%:*}"
720 # Returns 0 if the extension to the specified PPD file is a known
721 # extension, otherwise returns 1.
723 # $1 - Full path to PPD file
726 # ppdfileext - PPD file ext (.ppd or .ppd.gz)
734 if [[ "${1%.gz}".gz = "${1}" ]] ; then
736 elif [[ "${1%.ppd}".ppd = "${1}" ]] ; then
739 # invalid PPD file name extension
747 # Return the lines from the specified PPD file matching the specified
750 # $1 - spec entries from PPD file
753 # $1 example - 1 string with substrings separated by newline:
755 # *Manufacturer: "HP
"
756 # *Product: "(officejet
4200 series
)"
757 # *ModelName: "HP OfficeJet
4200"
758 # *NickName: "HP OfficeJet
4200 Foomatic
/hpijs
(recommended
)"
768 item=$(echo "${1}" | /bin/grep ${2})
769 # Remove everything up to and including the first quote
771 # Remove the end quote
776 # Return the lines from the specified PPD file matching the specified
779 # Note: this is similar to spec_entry() except the tokens in the
780 # spec entry are different.
782 # $1 - spec entries from PPD file
791 item=$(echo "${1}" | /bin/grep ${2})
792 # Remove everything up to and including the first semi-colon
794 # Remove the end quote
800 # Verifies that the specified PPD file
801 # - has a valid extension
802 # - has the following required spec file entries:
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.
813 # $1 - Full path to PPD file
825 ADOBESPEC="PPD-Adobe
"
832 # Verify the PPD file extension
833 verify_file_ext "${1}" || return 1
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}")"
842 # Process the query results to verify each of the required spec
843 # file items appears in the PPD file.
845 for spec_item in ${ADOBESPEC} ${MANUF} ${PRODUCT} ${MODEL} \
847 entry=$(spec_entry "${ppd_info}" "^\
*${spec_item}:")
848 [[ ! -z "${entry}" ]] || return 1
861 # Remove the model and any commas and spaces
862 # which appear before the driver
864 nickn="${entry#$model[, ]*}"
870 # Save IEEE1284 device id information
871 if $(echo "${ppd_info}" | grep "${DEVID}" >/dev/null 2>&1) ; then
874 devid="$
(/bin
/gzgrep
-e "^[ ]*${DMDL}:|^[ ]*${DMFG}:" "${1}")"
875 devidmdl="$
(devid_spec_entry
"${devid}" "${DMDL}")"
876 devidmfg="$
(devid_spec_entry
"${devid}" "${DMFG}")"
881 modmanuf=$(manuf_name_alias "${realmanuf}" ${aliasfile})
887 # generate_cache_file_entry()
889 # Returns a cache file entry for the specified PPD file.
896 # $6 - Full path to the specified PPD file
898 generate_cache_file_entry()
900 if debugger "generate_cache_file_entry
" ; then
904 echo "${1}":"${2}":"${3}":"${4}":"${5}":"${6}"
908 # Expand specified file to the full path.
910 # $1 - File path to expand
912 # Return code set to 0 if expanded successfully, otherwise set to 1.
920 if [[ -f "${1}" && -s "${1}" ]] ; then
921 (cd "$
(/bin
/dirname "${1}")" ; \
922 echo "$
(/bin
/pwd)/$
(/bin
/basename "${1}")") || return 1
930 # Returns the PPD repsitory path associated with the specified
931 # PPD repository name.
933 # $1 - Repository name
961 # Returns the PPD respository name from the repository path
963 # $1 - PPD repository path
994 # Returns 0 if a matching label name is found in the specified repository,
995 # otherwise returns 1.
997 # $1 - repository path
1000 label_path_in_repository()
1002 if debugger "label_path_in_repository
" ; then
1006 [[ "${1}" != "" && "${2}" != "" ]] || return 1
1008 for repository in ${REPOSITORIES} ; do
1009 if [[ "${repository}" = "${1}" && -d "${1}/${2}" ]] ; then
1018 # Returns 0 if the source label path is the same
1019 # as the destination label path, otherwise returns 1.
1021 # $1 - full path to source PPD file (source label path)
1022 # $2 - destination repository path
1023 # $3 - destination label name
1027 if debugger "label_path_match
" ; then
1031 # dest repository not specified
1032 if [[ "${2}" = "${UNSET}" ]] ; then
1033 # dest label not specified
1034 if [[ "${3}" = "${UNSET}" ]] ; then
1036 # We've found a match if the label path is in a known
1040 label_path_in_repository \
1041 "${1%/*/*/*}" "${lpath##*/}" || return 1
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.
1051 [[ "${1%/*/*}" = "${1%/*/*/*}/${3}" ]] || return 1
1052 label_path_in_repository "${1%/*/*/*}" "${3}" || \
1056 # dest repository specified, dest label not specified
1057 elif [[ "${3}" = "${UNSET}" ]] ; then
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.
1064 [[ "${2}" = "${1%/*/*/*}" ]] || return 1
1066 label_path_in_repository "${2}" "${lpath##*/}" || return 1
1068 # dest repository and dest label specified.
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.
1075 [[ "${1%/*/*}" = "${2}/${3}" ]] || return 1
1076 label_path_in_repository "${2}" "${3}" || return 1
1082 # Returns 0 if specified label name is a reserved label, otherwise
1094 for labelname in ${RESERVEDLABELS} ; do
1095 if [[ "${1}" = "${labelname}" ]] ; then
1104 # Returns a list of all labels that exist in a repository that are
1105 # not reserved labels.
1107 # $1 - Full path of repository
1108 # $2 - Repository name
1110 get_rep_label_list()
1117 # Get a list of all labels that exist in all of the
1118 # PPD file repository.
1120 for lname in $(/bin/ls "${1}" 2>/dev/null) ; do
1121 if [[ -d "${1}/${lname}" ]] ; then
1122 if ! reserved_label "${lname}" ; then
1130 # Returns a valid PPD label.
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.
1135 # Return code set to 0 if the specified PPD label is valid, otherwise 1.
1139 valid_specified_label()
1145 # Verify the specified label
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
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
1168 # Label name not specified. Set the default label name.
1169 # For -g and -a, default is "user
", otherwise, default
1171 if [[ "${action}" = "${ADD}" || \
1172 "${action}" = "${GENERATEENTRY}" ]] ; then
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
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
1204 # Returns the full path of any variant copy of the source file in
1205 # the destination label/repository.
1207 # $1 - Full path to source PPD file
1208 # $2 - Full path to destination PPD file
1210 # Return code set to
1211 # 0 - Copy doesn't exist
1212 # 1 - Duplicate copy exists
1213 # 2 - Variant copy exists
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.
1225 if [[ -e "${2%.gz}" && -e "${2%.gz}.gz
" ]] ; then
1226 /bin/rm -f "${2%.gz}" >/dev/null 2>&1
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
1234 elif [[ -e "${2%.gz}" ]] ; then
1237 elif [[ -e "${2%.gz}.gz" ]] ; then
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.
1248 if [[ "${1#*.ppd}" = ".gz" ]] ; then
1258 # $1 - Directory mode
1259 # $2 - Directory owner (i.e., root:lp)
1260 # $3 - Directory to create
1264 if debugger
"make_dir" ; then
1268 [[ ! -d "${3}" ]] ||
return 0
1269 /bin
/mkdir
"${3}" >/dev
/null
2>&1 ||
return 1
1270 set_perms
${1} ${2} "${3}"
1275 # Remove a ppdmgr generated cache (in /var/lp/ppd/cache)
1276 # if it doesn't have an associated label in the repository.
1278 # $1 - Full path to label
1281 remove_unassociated_cache()
1283 if debugger "remove_unassociated_cache
" ; then
1287 if [[ "${1}" != "${UNSET}" ]] ; then
1288 if [[ -n "${1}" && ! -d "${1}" ]] ; then
1290 # The label doesn't exist, so delete
1291 # the associated cache file.
1293 /bin/rm -f "${VARCACHES}/${2}" >/dev/null 2>&1
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.
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.
1315 # $1 - Full path to repository (or "all
")
1325 # Determine which labels in which PPD repository the
1326 # cache file will be updated for.
1328 if [[ "${1}" = "all
" ]] ; then
1329 rname="${REPOSITORIES}"
1335 for dstreppath in ${rname} ; do
1337 if [[ "${2}" = "all
" ]] ; then
1338 dstrepname=$(get_rep_name "${dstreppath}")
1339 labellist=$(get_rep_label_list "${dstreppath}" \
1343 # Ensure the label exists in the PPD file repository.
1344 if [[ -d "${dstreppath}/${2}" ]] ; then
1350 # Update the cache for each label in the PPD repository
1352 for dstlabel in ${labellist} ; do
1353 ulc_msg=$(update_label_cache "${dstreppath}" \
1354 "${dstrepname}" "${dstlabel}")
1355 if [[ $? -ne 0 ]] ; then
1362 # Update the golden cache file.
1370 if debugger "ppdmgr_exit
" ; then
1374 /bin/rm -rf "${ppdmgrtmpdir}" >/dev/null 2>&1
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
1393 ##########################################################################
1395 ##########################################################################
1397 myprog=$(/bin/basename $0)
1403 # Updatable PPD repository
1406 # Delivered PPD respository
1407 SYSTEMREP=/usr/share/ppd
1408 ADMINREP=/usr/local/share/ppd
1409 VENDORREP=/opt/share/ppd
1412 RESERVEDREPS="${SYSTEMREP} ${ADMINREP} ${VENDORREP}"
1413 REPOSITORIES="${USERREP} ${RESERVEDREPS}"
1414 RESERVEDLABELS="all caches ppdcache manufaliases
"
1416 # Directory where system:SUNWfoomatic is delivered
1417 FOOCACHEDIR=/usr/lib/lp/caches
1425 # Sytem PPD cache name used by printmgr
1426 GOLDCACHE=${USERREP}/ppdcache
1428 # Delivered caches directory
1430 MANUFALIASES=manufaliases
1432 # Updated caches directory
1433 VARCACHES=${VARDIR}/${CACHES}
1435 # valid PPD file name extensions
1438 FILEEXTS=".
${PEXT} .${PEXT}.${GEXT}"
1440 # Default modes and owners
1443 ADMINOWNER=root:root
1449 GENERATEENTRY=generateentry
1459 GZCMP="/bin
/gzcmp
-s"
1478 ppdmgrtmpdir=$(/usr/bin/mktemp -t -d ppdmgr.XXXXXX)
1479 if [ -z "$ppdmgrtmpdir" ] ; then
1480 print -n "$myprog: " 1>&2
1481 gettext "Fatal error
: could not create temporary directory
\n" 1>&2
1485 aliasfile=${USERREP}/manufaliases
1490 while getopts "$OPTS" arg ; do
1494 origsrcppdpath=${OPTARG}
1497 g) # create cache entry
1498 action=${GENERATEENTRY}
1499 origsrcppdpath=${OPTARG}
1510 R) # PPD file repository to use
1511 ppdrepname=${OPTARG}
1518 w) # display PPD file path
1532 if debugger "Main
" ; then
1536 if [[ $# -lt 1 || -z "${action}" ]] ; then
1540 # ignore wflag unless specified with -a
1541 if [[ ${wflag} -eq 1 && "${action}" != ${ADD} ]] ; then
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:
1556 case "${ppdrepname}" in
1558 ppdreppath="${SYSTEMREP}"
1561 ppdreppath="${ADMINREP}"
1564 ppdreppath="${VENDORREP}"
1567 ppdreppath="${USERREP}"
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
1580 ppdreppath="${UNSET}"
1584 print -n "$myprog: " 1>&2
1585 gettext "invalid PPD repository name
: ${ppdrepname}\n" 1>&2
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
1596 if [[ "${action}" = "${ADD}" || "${action}" = "${GENERATEENTRY}" ]] ; then
1598 srcppdpath=$(ppd_pathname "${origsrcppdpath}")
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}
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
1614 ppdfname=$(/bin/basename "${origsrcppdpath}")
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.
1625 if label_path_match "${srcppdpath}" "${ppdreppath}" "${ppdlabel}" ; then
1626 if [[ ${wflag} -eq 1 || \
1627 "${action}" = "${GENERATEENTRY}" ]] ; then
1628 echo "${srcppdpath}"
1630 ppdmgr_exit ${SUCCESS}
1634 ppdlabel=$(valid_specified_label "${ppdlabel}")
1635 if [[ $? -ne 0 ]] ; then
1639 if [[ "${ppdreppath}" = "${UNSET}" ]] ; then
1640 ppdreppath="${USERREP}"
1643 dstrepname=$(get_rep_name "${ppdreppath}")
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
1653 final_dst_ppd_path=$(add_ppd "${srcppdpath}" "${ppdfname}" \
1654 "${ppdreppath}" "${dstrepname}" "${ppdlabel}")
1656 case ${add_ppd_rc} in
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
1664 add_ppd_msg=$(update_label_cache "${ppdreppath}" \
1665 "${dstrepname}" "${ppdlabel}")
1668 echo "${add_ppd_msg}" | /bin/grep "${final_dst_ppd_path}"
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.
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
1687 # Display the full path to the added PPD file,
1688 # if requested (-w).
1690 if [[ ${wflag} -eq 1 ]] ; then
1691 print "${final_dst_ppd_path}"
1696 1) # Duplicate copy exists
1697 if [[ ${wflag} -eq 1 ]] ; then
1698 print "${final_dst_ppd_path}"
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
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
1721 # Create a cache file entry for the specified PPD file and
1722 # display it on standard out.
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}")"
1735 print -n "$myprog: " 1>&2
1736 gettext "PPD
file not
in valid location
\n" 1>&2
1738 "(<repository
>/<label
>/<manufacturer
>/<PPD
file>):\n\t${1}\n" 1>&2
1743 print -n "$myprog: " 1>&2
1744 gettext "invalid PPD
file: ${1}\n" 1>&2
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
1765 ppdmgr_exit ${status}