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