ppdmgr revision 70fa9386ff0a83ccf99d2d3ac2198d2ed51bf748
1345N/A# The contents of this file are subject to the terms of the 70N/A# Common Development and Distribution License (the "License"). 70N/A# You may not use this file except in compliance with the License. 919N/A# See the License for the specific language governing permissions 919N/A# and limitations under the License. 919N/A# When distributing Covered Code, include this CDDL HEADER in each 919N/A# If applicable, add the following below this CDDL HEADER, with the 919N/A# fields enclosed by brackets "[]" replaced with your own identifying 919N/A# information: Portions Copyright [yyyy] [name of copyright owner] 919N/A# Copyright 2008 Sun Microsystems, Inc. All rights reserved. 919N/A# Use is subject to license terms. 70N/A# Description: Script to generate the Solaris printmgr 'ppdcache' file from the 70N/A# ppd files installed in the given ppd database directory 70N/A# ppdmgr -a <ppd_filename_path> [ -L <label> ] [-w] 70N/A# ppdmgr -g <ppd_filename_path> [ -L <label> ] [ -R <ppd_repository> ] 1370N/A# ppdmgr -r [ -L <label> ] [ -R <ppd_repository> ] 70N/A# ppdmgr -u [ -L <label> ] [ -R <ppd_repository> ] 1370N/A# -a <ppd_filename_path> - Add a new PPD file to the specified 1370N/A# label in the "user" repository, and 911N/A# updates to the "user" repository 1370N/A# -g <ppd_filename_path> - Generate a cache file entry 70N/A# for the specified PPD file 70N/A# -L <label> - Label name. <label> 70N/A# can be any characters from the 970N/A# portable character set, however 970N/A# may not contain a semi-colon (':'). 970N/A# The following are the defaults 970N/A# for <label> for each option: 70N/A# OPTION DEFAULT LABEL 70N/A# ------ ------------- 493N/A# -a <label> from <ppd_filename_path> 969N/A# if <ppd_filename_path> 70N/A# is from a known repository, 70N/A# otherwise defaults to "user". 70N/A# -g <label> from <ppd_filename_path> 70N/A# if <ppd_filename_path> 970N/A# is from a known repository, 970N/A# otherwise defaults to "user". # The following are reserved labels: # caches - may never be specified # ppdcache - may never be specified # manufaliases - may never be specified # all - applies specified # SUNW* - anything starting with # -r - Rebuild the cache information for the # specified label in the specified # repository. Similar to -u, however, # the cache file is removed to force an # update to the ppdcache. # -R <ppd_repository> - PPD repository name. # The following are the possible # values for <ppd_repository> and # location in the system: # Note: When specified with the -a option # only "user" and "admin" are valid. # "vendor", "system", and "all" will be # -u - Update the PPD cache information # for the specified label in the specified # repository if needed. If the cache # update was required, then the updated # cache information is reflected in # -w - Display full path of where the # ppd file is located on the system. # Only valid with -a, otherwise the # If -a, -g, -r, or -u are specified on the command line, only the last action # specified will be performed. # Cache file entry format: # <ModifiedManufacturerName>:<Model>:<NickName>:<1284DeviceIDManufacturer>:<1284DeviceIDModel>:<FullPPDFilePath> # Generates debug output for calling routine. # If calling routine's name is passed in, then # will also generate the name of the calling routine. # $1 - Name of calling routine if [[ -n "${1}" ]] ; then # Set the ownership and permissions on a file. # if needed. This is a special case a Solaris doesn't deliver # $1 - destination repository name if debugger "check_adminrep_dirs" ; then # Only create administrator repository directories, if needed. [[ "${1}" = "${ADMIN}" ]] || return 0 [[ ! -d "${ADMINREP}" ]] || return 0 if [[ ! -d "${admpar}" ]] ; then if [[ ! -d "${admppar}" ]] ; then # Returns full path to PPD file that was added to the system. # $1 - Full path to source PPD file # $3 - Full path to repository # 0 - File successfully added # 2 - Duplicate file already exists # The destination path can now be set # If a version (either compressed or not compressed) of the PPD # then just return as there no work to be done. # Can only add a PPD file to the "user" or "admin" repository. # Note: this check is here instead of at the top of this # function as we don't want to cause an error if a user # specifies the same repository and label as a the specified # ppd file and the repository of the specified ppd file # exists in a known repository. if [[ "${4}" != "${USER}" && "${4}" != "${ADMIN}" ]] ; then # Ensure destination directories exist # Copy source PPD file, and compress if needed, to destination if [[ "${ppdfileext}" = "${PEXT}" ]] ; then # Returns 0 if the cache needs to be modified, otherwise # $1 - Full path to cache # $2 - Full path to cache replacement candidate if [[ "${action}" = "${REBUILD}" ]] ; then [[ "${2}" -nt "${1}" ]] || return 1 # No differences. Just update timestamp # concatenating and sorting all existing cache files in /var/lp/ppd/caches. # If there are difference between the newly generated golden cache file and # the existing one (if it exists) then the newly generated one replaces the if debugger "update_golden_cache" ; then # Remove any cache files that don't have an associated # Combine the contents of all cache files into a # temporary golden cache file. if [[ ! -s "${tmpgoldencache}" ]] ; then # No cache files. Remove golden cache. elif [[ -e "${GOLDCACHE}" ]] ; then # Use the newly generated "temporary" golden cache file if there # differences between the current and newly generated ppdcache # or if a rebuild is being performed. if [[ "${VARCACHES}" -nt "${GOLDCACHE}" ]] || \ /bin/mv -f "${tmpgoldencache}" \ # There wasn't an existing ppdcache. Install the newly # generated ppdcache file to the golden ppdcache. /bin/mv -f "${tmpgoldencache}" "${GOLDCACHE}" >/dev/null 2>&1 # Returns a list of PPD files that exist. # $1 - Full path to cache file [[ -s "${1}" ]] || return # Keep the entry from the ppd cache if it still # exists and there haven't been any modifications # since the last update to the cache. if [[ -n "${centry}" ]] ; then if [[ -n "${ppdfile}" && -e "${ppdfile}" && "${1}" -nt "${ppdfile}" ]] ; then # Returns 0 if the path to the PPD is as follows: # <PPD file repository>/<label>/<manufacturer>/<PPD file> # $1 Full path to PPD file # Strip off what should be <label>/<manufacturer>/<PPD file> # and verify the PPD file repository matches one of the # known PPD file repositories. if [[ "${repository}" = "${ppd_file_repository}" ]] ; then # Generate, and sort, cache entries for each PPD files in the specified # list to the specified file. # $1 - List of full paths to PPD files # $2 - Full path to current cache file # $3 - Full path to label # $4 - Full path to new cache file to generate # Generate a cache file containing cache entries for # all files in the label. # Before processing new files, remove any cache entries if [[ -e "${2}" && "${action}" != "${REBUILD}" ]] ; then if [[ -n "${valid_files}" ]] ; then echo "${valid_files}" >>${ucfile} # If there are no valid PPD files in the current cache file, # and there are no new PPD files to process, the only thing # left to do is to remove the current cache file. if [[ -z "${valid_files}" && -z "${1}" ]] ; then # For each of the label's PPD files, generate # a cache file entry and add it to the cache file. if [[ -n "${fname}" ]] ; then "${modmanuf}" "${model}" "${nickn}" \ "${devidmfg}" "${devidmdl}" "${fname}")" [[ -n "${vpl_msg}" || -n "${vpf_msg}" ]] || return 0 " (<repository>/<label>/<manufacturer>/<PPD file>):\n" 2>/dev/null # Update current cache file with candidate cache file if there are # $1 - Current cache file # $2 - Candidate cache file to update if debugger "update_current_cache_file" ; then if [[ ! -s "${2}" ]] ; then # Candidate cache has zero size (label # directory with no PPD files under it). # Delete the empty candidate cache # file and delete the current cache elif [[ -e "${1}" ]] ; then # If there are differences between the current # cache file and the newly generated one, then # replace the current one with the new one, and # set the flag to update the golden ppdcache # There is no current cache file. Move the candidate # to the caches directory. # Returns 0 if there are files in $1 with newer timestamp # than $2 or if deletions have occurred under $1, # $1 - Full path to the destination label # $2 - Full path to label cache file # First check for newer files in the directory if [[ -e "${2}" && "${action}" != "${REBUILD}" ]] ; then [[ -z "${newfiles}" ]] || return 0 # Need to detect if PPD files have been deleted by checking # timestamps on label and manufacturer directories. [[ ! "${1}" -nt "${2}" ]] || return 0 # If -R was specified, or the timestamp on the specified label's # directory or any of the PPD files under the specified label in # the specified PPD file respository is newer than the cache file # associated with the label, then generate a new sorted cache file. # The new cache will replace the existing one (if any) only if there # are differences. Note: if -r was specified, then a new cache file # file will always be installed at # $1 - Full path of the destination PPD file repository # $2 - Destination PPD file repository name # $3 - Destination label name if [[ -d "${dstlabelpath}" ]] ; then # If the cache doesn't exist for a label, # or if there were any changes under a label # (i.e., the timestamp on the label directory or any # of the PPD files under it is newer than the # existing cache file), then generate a new cache file. # if this is a system repository, check for a prepopulated cache # copy prepopulated cache "${newfileslist}" "${varlabelcachepath}" \ "${dstlabelpath}" "${tmpcachepath}") # At least one PPD file was invalid. # Don't return yet, as the cache info # for the valid PPD files can still be # used to generate a cache file. if [[ -e "${tmpcachepath}" ]] ; then "${varlabelcachepath}" "${tmpcachepath}" "${2}" # with the label which no longer exists, remove it. # Returns the alias for the specified real manufacturer's name. # $1 - Real manufacturer's name # $2 - File containing list of files that have manufacturers aliases # Found a couple of PPD files which had special characters # in the Manufacturer name (i.e, the following is the Manufacturer # *Manufacturer: "Canon Inc. (Kosugi Offic" # We'll only search the alias file for "Canon Inc." # Search alias files for a match on the real manufacturer name if [[ -s "${2}" ]] ; then # Check the manufacturer aliases file for case # insensitive match of the Manufacturer entry # from the PPD file. If a match is found, # then modify the manufacturer entry to # be that of the specified alias. "^${tmpmanuf}:|:${tmpmanuf}:|:${tmpmanuf}$" "${2}") if [[ -n "${manufaliases}" ]] ; then echo "${manufaliases%%:*}" # Returns 0 if the extension to the specified PPD file is a known # extension, otherwise returns 1. # $1 - Full path to PPD file # ppdfileext - PPD file ext (.ppd or .ppd.gz) if [[ "${1%.gz}".gz = "${1}" ]] ; then elif [[ "${1%.ppd}".ppd = "${1}" ]] ; then # invalid PPD file name extension # Return the lines from the specified PPD file matching the specified # $1 - spec entries from PPD file # $1 example - 1 string with substrings separated by newline: # *Product: "(officejet 4200 series)" # *ModelName: "HP OfficeJet 4200" # Remove everything up to and including the first quote # Return the lines from the specified PPD file matching the specified # Note: this is similar to spec_entry() except the tokens in the # spec entry are different. # $1 - spec entries from PPD file # Remove everything up to and including the first semi-colon # Verifies that the specified PPD file # - has a valid extension # - has the following required spec file entries: # In addition, the manufacture and model from the IEEE1284 device id # information will be gathered here, although it's not an error that # it isn't in the PPD file as many don't contain the IEEE1284 info. # $1 - Full path to PPD file # Verify the PPD file extension # Query for the required spec items # Process the query results to verify each of the required spec # file items appears in the PPD file. [[ ! -z "${entry}" ]] || return 1 # Remove the model and any commas and spaces # which appear before the driver # Save IEEE1284 device id information if $(echo "${ppd_info}" | grep "${DEVID}" >/dev/null 2>&1) ; then # generate_cache_file_entry() # Returns a cache file entry for the specified PPD file. # $6 - Full path to the specified PPD file if debugger "generate_cache_file_entry" ; then echo "${1}":"${2}":"${3}":"${4}":"${5}":"${6}" # Expand specified file to the full path. # $1 - File path to expand # Return code set to 0 if expanded successfully, otherwise set to 1. if [[ -f "${1}" && -s "${1}" ]] ; then # Returns the PPD repsitory path associated with the specified # Returns the PPD respository name from the repository path # $1 - PPD repository path # Returns 0 if a matching label name is found in the specified repository, if debugger "label_path_in_repository" ; then [[ "${1}" != "" && "${2}" != "" ]] || return 1 if [[ "${repository}" = "${1}" && -d "${1}/${2}" ]] ; then # Returns 0 if the source label path is the same # as the destination label path, otherwise returns 1. # $1 - full path to source PPD file (source label path) # $2 - destination repository path # $3 - destination label name # dest repository not specified if [[ "${2}" = "${UNSET}" ]] ; then # dest label not specified if [[ "${3}" = "${UNSET}" ]] ; then # We've found a match if the label path is in a known "${1%/*/*/*}" "${lpath##*/}" || return 1 # If the source label path exists in the # in a known repository, and the destination # label is the same as the source label, # then we'll assume the default destination # repository is the same as the source # destination repository. [[ "${1%/*/*}" = "${1%/*/*/*}/${3}" ]] || return 1 # dest repository specified, dest label not specified elif [[ "${3}" = "${UNSET}" ]] ; then # If the destination repository path is the same as the # source repository, and if the source label exists in the # destination repository path, then we'll assume the default # destination label is the same as the source label. [[ "${2}" = "${1%/*/*/*}" ]] || return 1 # dest repository and dest label specified. # We've found a match if the destination and label # match those of the source label path, and the source # label path is in a known repository. [[ "${1%/*/*}" = "${2}/${3}" ]] || return 1 # Returns 0 if specified label name is a reserved label, otherwise if [[ "${1}" = "${labelname}" ]] ; then # Returns a list of all labels that exist in a repository that are # $1 - Full path of repository # Get a list of all labels that exist in all of the if [[ -d "${1}/${lname}" ]] ; then # Returns a valid PPD label. # Verifies the specified PPD label is a valid label. If the # label is not set, then it is set to a default value. # Return code set to 0 if the specified PPD label is valid, otherwise 1. # Verify the specified label # Reserved label name with -a or -g options if [[ "${action}" = "${ADD}" || \ "${action}" = "${GENERATEENTRY}" ]] ; then gettext "reserved PPD label name: ${1}\n" 1>&2 "ppdcache" | "caches" | "manufaliases") # Reserved label names with any option gettext "reserved PPD label name: ${1}\n" 1>&2 # Label name not specified. Set the default label name. # For -g and -a, default is "user", otherwise, default if [[ "${action}" = "${ADD}" || \ "${action}" = "${GENERATEENTRY}" ]] ; then # label cannot be "." or ".." if [[ "${1}" = "." || "${1}" = ".." ]] ; then gettext "PPD label name cannot be " 1>&2 # Label name cannot contain special characters gettext "PPD label name contains " 1>&2 gettext "an invalid character: ${1}\n" 1>&2 # Returns the full path of any variant copy of the source file in # $1 - Full path to source PPD file # $2 - Full path to destination PPD file # 1 - Duplicate copy exists # 2 - Variant copy exists # First make sure there is not a .ppd and a .ppd.gz version # of the destination file; users should know not to do this. if [[ -e "${2%.gz}" && -e "${2%.gz}.gz" ]] ; then # Use gzcmp to compare PPD files as it can deal with # gzipped or regular files. elif [[ -e "${2%.gz}" ]] ; then elif [[ -e "${2%.gz}.gz" ]] ; then # A PPD file doesn't exist in the destination # repository under the destination label. # Just display the source PPD file, ensuring # it has a gzip extension as we will always # try to gzip the copy in the destination. if [[ "${1#*.ppd}" = ".gz" ]] ; then # $2 - Directory owner (i.e., root:lp) # $3 - Directory to create [[ ! -d "${3}" ]] || return 0 # if it doesn't have an associated label in the repository. # $1 - Full path to label if debugger "remove_unassociated_cache" ; then if [[ "${1}" != "${UNSET}" ]] ; then if [[ -n "${1}" && ! -d "${1}" ]] ; then # The label doesn't exist, so delete # the associated cache file. # Sorted copies of cache files for each label in each PPD repository # This is done so that changes in delivered cache files can be # detected. If a difference in cache files is detected, or a # cache file is either added or removed, then we know that # the ppdcache file needs to be updated. # Get a list of all cache files and compare against the list # of labels in all of the PPD file repositories. They should # be the same. If there is a label in one of the PPD file # repositories that doesn't have an associated cache file, then # we don't worry about it now, as that will be resolved when # we update the cache for that label. However, if there is # a cache file associated with a label that no longer exists, then # $1 - Full path to repository (or "all") # Determine which labels in which PPD repository the # cache file will be updated for. if [[ "${1}" = "all" ]] ; then if [[ "${2}" = "all" ]] ; then # Ensure the label exists in the PPD file repository. if [[ -d "${dstreppath}/${2}" ]] ; then # Update the cache for each label in the PPD repository "${dstrepname}" "${dstlabel}") # Update the golden cache file. gettext "-a <ppd_filename_path> [ -L <label> ]\n" 1>&2 gettext "\t\t[ -R <ppd_repository> ] [-w]\n" 1>&2 gettext "-r [ -L <label> ] [ -R <ppd_repository> ]\n" 1>&2 gettext "-u [ -L <label> ] [ -R <ppd_repository> ]\n" 1>&2 ########################################################################## ########################################################################## # Updatable PPD repository # Delivered PPD respository # Directory where system:SUNWfoomatic is delivered # Sytem PPD cache name used by printmgr # Delivered caches directory # Updated caches directory # valid PPD file name extensions # Default modes and owners R)
# PPD file repository to use w)
# display PPD file pathif [[ $# -
lt 1 || -z
"${action}" ]] ;
then # ignore wflag unless specified with -a if [[ ${
wflag} -
eq 1 &&
"${action}" != ${
ADD} ]] ;
then # Ensure the destination PPD repository directory is set # to match the specified repository. If the # destination PPD file repository was specified, then # it must be one of the following: if [[
"${action}" =
"${ADD}" || \
"${action}" =
"${GENERATEENTRY}" ]] ;
then gettext "reserved PPD repository name: " 1>&
2 gettext "invalid PPD repository name: ${ppdrepname}\n" 1>&
2 # When a source PPD file's path is from a known repository, the # destination repository and desination label are assumed to be the # same as the source PPD file's unless a differing repository or label if [[
"${action}" =
"${ADD}" ||
"${action}" =
"${GENERATEENTRY}" ]] ;
then gettext "invalid PPD file: ${origsrcppdpath}\n" 1>&
2 # Path cannot contain special characters gettext "an invalid character: ${ppd_pathname}\n" 1>&
2 # Check to see if there's any work to be done. If the source file # is already in the destination repository under the destination # label, then there's nothing left to do. We exit rather than # going on to do an update on the label in the repository as # it could possible take a long time to update. If an add was # requested, it could have come from an application, so we want "${action}" =
"${GENERATEENTRY}" ]] ;
then if [[
"${ppdreppath}" =
"${UNSET}" ]] ;
then # Attempt to add the PPD file to the repository under the # specified label. If any errors occur, final_dst_ppd_path # will contain the error message rather than the path to the "${ppdreppath}" "${dstrepname}" "${ppdlabel}") # The PPD file was added. Update the specified # cache associated with the label if the PPD file # was added successfully and was not a duplicate. # Ensure any changes are also reflected in the "${dstrepname}" "${ppdlabel}") echo "${add_ppd_msg}" | /
bin/
grep "${final_dst_ppd_path}" # Only report cache update errors if the file that was # added was one that was reported as not being added # to the cache. This really should happen as the file # was verified during the add. gettext "printer information does not reflect " 1>&
2 gettext "the\nfollowing PPD file(s):\n" 1>&
2 print "${add_ppd_msg}" 1>&
2 # Display the full path to the added PPD file, print "${final_dst_ppd_path}" 1)
# Duplicate copy exists print "${final_dst_ppd_path}" gettext "differing variant of source PPD file " 1>&
2 gettext "${final_dst_ppd_path}\n" 1>&
2 *)
# The PPD file was not added as a problem occurred. # Display the error message. print "${final_dst_ppd_path}" 1>&
2 # Create a cache file entry for the specified PPD file and # display it on standard out. dstdir=
"${ppdreppath}/${ppdlabel}/${modmanuf}" # Generate the cache file entry "${model}" "${nickn}" "${devidmfg}" "${devidmdl}" \ gettext "PPD file not in valid location\n" 1>&
2 "(<repository>/<label>/<manufacturer>/<PPD file>):\n\t${1}\n" 1>&
2 gettext "invalid PPD file: ${1}\n" 1>&
2 "${REBUILD}" |
"${UPDATE}")
gettext "printer information does not reflect " 1>&
2 gettext "the\nfollowing PPD file(s):\n" 1>&
2 print "${update_msg}" 1>&
2