# This class action script copies the files being replaced
# into a package being constructed in $BUILD_DIR. This class
# action script is only appropriate for regular files that
# are installed by simply copying them into place.
#
# For special package objects such as edittable files, the patch
# producer must supply appropriate class action scripts.
#
# directory format options.
#
#       @(#)i.script 1.14 01/04/09 SMI
#
# Copyright (c) 1995 by Sun Microsystems, Inc.
# All rights reserved
#


make_chattr_list() {
cat > /tmp/chattr.$$ << EOF
audio:*				0666 root sys 0600 root sys	/dev/sound/*
dbri:sound,audio		0666 root sys 0600 root sys	/dev/sound/*
SUNW,DBRId:sound,audio		0666 root sys 0600 root sys	/dev/sound/*
SUNW,DBRIe:sound,audio		0666 root sys 0600 root sys	/dev/sound/*
SUNW,DBRIf:sound,audio		0666 root sys 0600 root sys	/dev/sound/*
dbri:sound,audioctl		0666 root sys 0600 root sys	/dev/sound/*
SUNW,DBRId:sound,audioctl	0666 root sys 0600 root sys	/dev/sound/*
SUNW,DBRIe:sound,audioctl	0666 root sys 0600 root sys	/dev/sound/*
SUNW,DBRIf:sound,audioctl	0666 root sys 0600 root sys	/dev/sound/*
dbri:aux,audio			0666 root sys 0600 root sys	/dev/sound/*
SUNW,DBRId:aux,audio		0666 root sys 0600 root sys	/dev/sound/*
SUNW,DBRIe:aux,audio		0666 root sys 0600 root sys	/dev/sound/*
SUNW,DBRIf:aux,audio		0666 root sys 0600 root sys	/dev/sound/*
dbri:aux,audioctl		0666 root sys 0600 root sys	/dev/sound/*
SUNW,DBRId:aux,audioctl		0666 root sys 0600 root sys	/dev/sound/*
SUNW,DBRIe:aux,audioctl		0666 root sys 0600 root sys	/dev/sound/*
SUNW,DBRIf:aux,audioctl		0666 root sys 0600 root sys	/dev/sound/*
vol:volctl			0600 root sys 0666 root sys	/dev/volctl
sad:user			0600 root sys 0666 root sys	/dev/sad/user
se:*				0666 root sys 0600 uucp uucp	/dev/cua/*
zs:*				0666 root sys 0600 uucp uucp	/dev/cua/*
su:*				0666 root sys 0600 uucp uucp	/dev/cua/*
ssd:*			0666 root sys 0640 root sys	/dev/dsk/* /dev/rdsk/*
dad:*			0600 root sys 0640 root sys	/dev/dsk/* /dev/rdsk/*
log:conslog			0622 root sys 0666 root sys	/dev/conslog
sy:tty				0666 root sys 0666 root tty	/dev/tty
cvc:*				0666 root sys 0600 root sys
cvcredir:*			0666 root sys 0600 root sys
EOF
}


#
#  If an entry in /etc/minor_perm needs to be deleted, identify
#  the entry in the list copied to /etc/delete.$$ by this function.
#  The fields are:
#
#  <device>:<minor>  <optional list of logical devices to be deleted>
#					

make_delete_list() {
cat > /tmp/delete.$$ << EOF
mm:mbio /dev/mbio /devices/pseudo/mm:mbio
mm:mbmem /dev/mbmem /devices/pseudo/mm:mbmem
clone:amd,0,aux,audio
clone:dbri,0,aux,audio
sw:drum
rip:rawip
zs:*
consfb:consfb
win:*
rtvc:*
gt:*
mic:*
cgeight-p4:*
cgfour:*
cgtwo:*
id:*
xd:*
xt:*
xy:*
ie:*
be:*
se:ucm
se:ucmctl
clone:arp
clone:icmp
clone:ip
clone:tcp
clone:udp
clone:rts
clone:ipsecah
clone:ipsecesp
clone:keysock
su:*
profile:profile
EOF
}

#
#  If an entry needs to be added to /etc/minor_perm, add the first
#  field of the entry to the list created by this function.  The
#  remainder of the entry will be extracted from the /etc/minor_perm
#  in the package being installed, so it is not necessary to supply
#  it here.
#

make_add_list() {
cat > /tmp/add.$$ << EOF
clone:le
clone:llc1
sx_cmem:*
SUNW,sx:*
cgfourteen:*
stc:*
clone:qe
mcpzsa:*
mcpp:*
vol:volctl
tl:*
tnf:tnfctl
tnf:tnfmap
zs:[a-z]
zs:[a-z],cu
sad:user
se:*
su:[a-z]
su:[a-z],cu
su:ssp
su:sspctl
fdthree:*
ssd:*
dad:*
pm:*
tod:*
SUNW,pmc:*
SUNW,mic:*
SUNW,fas:devctl
cvc:*
cvcredir:*
devinfo:devinfo
envctrltwo:*
se:[a-h]
se:[a-h],cu
se:[0-7],hdlc
se:ssp
se:sspctl
clone:hme
clone:eri
wc:*
arp:arp
icmp:icmp
icmp6:icmp6
ip:ip
ip6:ip6
tcp:tcp
tcp6:tcp6
udp:udp
udp6:udp6
rts:rts
poll:*
cpc:shared
sysmsg:msglog
sysmsg:sysmsg
ipsecah:ipsecah
ipsecesp:ipsecesp
keysock:keysock
devinfo:devinfo,ro
lofi:*
lofi:ctl
sgen:*
pcf8574:*
pcf8591:*
gpio_87317:*
fssnap:*
fssnap:ctl
rsm:*
mm:allkmem
bscv:*
EOF
}


# Internal routine to create a sed script which can be used to
# escape all shell globbing metacharacters in a path.

create_esc_sedscript()
{
cat > /tmp/esc.sed.$$ << EOF
s/\*/\\\\*/g
s/\?/\\\\?/g
s/\[/\\\\[/g
s/\]/\\\\]/g
EOF
}

# Internal routine to convert an entry in a /tmp/chwhatever.$$ file to
# an appropriately escaped pattern which can be used to grep into minor_perm.

entry2pattern()
{
	# the first argument is the 'key' field from the change file.
	# entries can contain shell globbing characters to match
	# several devices - hence all the palaver below.

	printf '%s' `echo "$1" | sed \
		-e 's/\*/\\\\*/g'	-e 's/\?/\\\\?/g'	\
		-e 's/\./\\\\./g'	-e 's/\[/\\\\[/g'	\
		-e 's/\]/\\\\]/g'`
	shift

	# the remaining optional arguments are tokens separated by white-space

	if [ $# = 0 ] ; then
		printf '[ \t]'
	else
		while [ -n "$1" ]
		do
			printf '[ \t][ \t]*%s' $1
			shift
		done
		printf '[ \t]*$'
	fi
}


PATH=/usr/sadm/bin:$PATH
PATH="/sbin:/usr/sbin:/usr/bin:/usr/sadm/install/bin"
PATH="/usr/bin:/usr/sbin:${PATH}"

ECHO="/usr/bin/echo"
SED="/usr/bin/sed"
PKGPROTO="/usr/bin/pkgproto"
EXPR="/usr/bin/expr"	# used by dirname
MKDIR="/usr/bin/mkdir"
CP="/usr/bin/cp"
RM="/usr/bin/rm"
MV="/usr/bin/mv"
KSH="/usr/bin/ksh"

recovery="no"
Pn=$$
procIdCtr=0

CMDS_USED="$KSH $ECHO $SED $PKGPROTO $EXPR $MKDIR $CP $RM $MV"
LIBS_USED=""

if [ "$PKG_INSTALL_ROOT" = "/" ]; then
	PKG_INSTALL_ROOT=""
fi

# Check to see if this is a patch installation retry.
if [ "$INTERRUPTION" = "yes" ]; then
	if [ -d "$PKG_INSTALL_ROOT/var/tmp/$SUNW_PATCHID.$PKGINST" ] || [ -d "$PATCH_BUILD_DIR/$SUNW_PATCHID.$PKGINST" ]; then
		recovery="yes"
	fi
fi

if [ -n "$PATCH_BUILD_DIR" -a -d "$PATCH_BUILD_DIR" ]; then
	BUILD_DIR="$PATCH_BUILD_DIR/$SUNW_PATCHID.$PKGINST"
else
	BUILD_DIR="$PKG_INSTALL_ROOT/var/tmp/$SUNW_PATCHID.$PKGINST"
fi

FILE_DIR=$BUILD_DIR/files
RELOC_DIR=$FILE_DIR/reloc
ROOT_DIR=$FILE_DIR/root
BO_Deletes=$FILE_DIR/deletes
PROGNAME=`basename $0`

if [ "$PATCH_PROGRESSIVE" = "true" ]; then
	PATCH_NO_UNDO="true"
fi

# Since this is generic, figure out the class.
Class=`echo $PROGNAME | nawk ' { print substr($0, 3)  }'`

# Since this is an update, $BASEDIR is guaranteed to be correct
BD=${BASEDIR:-/}

cd $BD

#
# First, figure out the dynamic libraries that can trip us up.
#
if [ -z "$PKG_INSTALL_ROOT" ]; then
	if [ -x /usr/bin/ldd ]; then
		LIB_LIST=`/usr/bin/ldd $CMDS_USED | sort -u | nawk '
			$1 ~ /\// { continue; }
			{ printf "%s ", $3 } '`
	else
		LIB_LIST="/usr/lib/libc.so.1 /usr/lib/libdl.so.1 /usr/lib/libw.so.1 /usr/lib/libintl.so.1 /usr/lib/libgen.so.1 /usr/lib/libadm.so.1 /usr/lib/libelf.so.1"
	fi
fi

#
# Now read the list of files in this class to be replaced. If the file
# is already in place, then this is a change and we need to copy it
# over to the build directory if undo is allowed. If it's a new entry
# (No $dst), then it goes in the deletes file for the backout package.
#

LD_LIB_DIR=$PKG_INSTALL_ROOT/var/tmp/LDLIB.$$

procIdCtr=0
while read src dst; do

	if [ "$PATCH_PROGRESSIVE" = "true" ]; then
		# If this is being used in an old-style patch, insert
		# the old-style script commands here.

		#XXXOld_CommandsXXX#
		echo >/dev/null	# dummy
	fi

	if [ "${PATCH_NO_UNDO}" != "true" ]; then
		#
		# Here we construct the path to the appropriate source
		# tree for the build. First we try to strip BASEDIR. If
		# there's no BASEDIR in the path, we presume that it is
		# absolute and construct the target as an absolute path
		# by stripping PKG_INSTALL_ROOT. FS_Path is the path to
		# the file on the file system (for deletion purposes).
		# Build_Path is the path to the object in the build
		# environment.
		#
		# The following rootPath variable accounts for a BASEDIR
		# that is used as a regular variable within the path and
		# not as a variable that a path needs to be relocated to.

		rootPath=`$ECHO $src | $SED s@"$INST_DATADIR/$PKGINST"@@ | \
			nawk -F/ '{print $2}'`
		if [ "$rootPath" = "root" ]; then
			FS_Path=$dst
		elif [ "$BD" = "/" ]; then
			FS_Path=`$ECHO $dst | $SED s@"$BD"@@`
		else
			FS_Path=`$ECHO $dst | $SED "s|$BD/||"`
		fi

		# If it's an absolute path the attempt to strip the
		# BASEDIR will have failed.
		if [ "$dst" = "$FS_Path" ]; then
			if [ -z "$PKG_INSTALL_ROOT" ]; then
				FS_Path=$dst
				Build_Path="$ROOT_DIR$dst"
			else
				Build_Path="$ROOT_DIR"`echo $dst | \
				    $SED "s|$PKG_INSTALL_ROOT||"`
				FS_Path=`echo $dst | \
				    $SED "s|$PKG_INSTALL_ROOT||"`
			fi
		else
			Build_Path="$RELOC_DIR/$FS_Path"
		fi

		if [ -f "$dst" ]; then	# If this is replacing something
			cd $FILE_DIR
			#
			# Construct the prototype file entry. We replace
			# the pointer to the filesystem object with the
			# build directory object.
			#
			
			echo "e minorperm $FS_Path=$Build_Path ? ? ?" >> \
				$BUILD_DIR/prototype

			# Now copy over the file
			if [ "$recovery" = "no" ]; then
				DirName=`dirname $Build_Path`
				$MKDIR -p $DirName
				$CP -p $dst $Build_Path
			else
				# If this file is already in the build area skip it
				if [ -f "$Build_Path" ]; then
					cd $BD
					continue
				else
					DirName=`dirname $Build_Path`
					if [ ! -d "$DirName" ]; then
						$MKDIR -p $DirName
					fi
					$CP -p $dst $Build_Path
				fi
			fi

			cd $BD
		else	# It's brand new
			$ECHO $FS_Path >> $BO_Deletes
		fi
	fi

	# If special processing is required for each src/dst pair,
	# add that here.
	#
	#XXXSpecial_CommandsXXX#
	#

	if [ ! -f $dst ] ; then
		cp $src $dst
	else
		rm -f /tmp/*.$$
		create_esc_sedscript
		make_chattr_list
		make_delete_list
		make_add_list

		#
		#  Process the list of devices whose attributes are to be
		#  changed.  Find those that actually need to be
		#  applied to the file.  For each change that needs
		#  to be applied, add an entry for it to the sed
		#  script that will eventually be applied to the
		#  currently-installed /etc/minor_perm file.  Also,
		#  add an entry to the /tmp/chdevs.$$ file, which
		#  contains the list of logical names of devices
		#  whose permissions need to be changed.
		#

		cat /tmp/chattr.$$ | \
		while read key oldp oldu oldg newp newu newg chdevs
		do
			do_chdevs=no

			#
			#  First determine whether the device entry
			#  is already in the file, but with the old
			#  permissions.  If so, the entry needs to be
			#  modified and the devices in the chdevs list
			#  need to have their permissions and ownerships
			#  changed.
			#
			grepstr=`entry2pattern "${key}" $oldp $oldu $oldg`
			if grep "$grepstr" $dst > /dev/null 2>&1; then
				echo "s/${grepstr}/$key $newp $newu $newg/" \
				    >> /tmp/sedscript.$$
				do_chdevs=yes
			fi

			#
			#  Now determine whether the device entry is
			#  in the file at all.  If not, it is a new
			#  entry, but there may already be devices
			#  on the system whose permissions need to
			#  be changed.
			#
			grepstr=`entry2pattern "${key}"`
			grep "${grepstr}" $dst > /dev/null 2>&1
			if [ $? != 0 ] ; then
				do_chdevs=yes
			fi

			if [ $do_chdevs = yes -a "$chdevs" != "" ] ; then
				xchdevs=`echo "$chdevs" | \
				    sed -f /tmp/esc.sed.$$`
				for m in $xchdevs ; do
					echo "$m" $oldp $oldu $oldg \
					    $newp $newu $newg >> /tmp/chdevs.$$
				done
			fi
		done

		#
		#  Make sure /dev/volctl gets its permissions corrected.
		#  (systems upgraded from 2.2 to 2.3 may have a correct
		#  entry for /dev/volctl in the /etc/minor_perm file
		#  but the actual /dev/volctl node may have the wrong
		#  permissions.)
		#

		echo /dev/volctl 0600 root sys 0666 root sys >> /tmp/chdevs.$$

		if [ -s /tmp/chdevs.$$ ] ; then
			sort -u /tmp/chdevs.$$ > /tmp/tmp.$$
			mv /tmp/tmp.$$ /tmp/chdevs.$$
		fi

		#
		#  Process the list of devices to be deleted.
		#  Find those that actually need to be deleted
		#  from the file.  For each entry to be deleted,
		#  add an entry for it to the sed script that will
		#  eventually be applied to the  currently-installed
		#  /etc/minor_perm file.  Also, add an entry to the
		#  /tmp/deldevs.$$ file, which contains the list of
		#  logical names of devices to be deleted.
		#

		cat /tmp/delete.$$ | while read key deldevs
		do
			grepstr=`entry2pattern "${key}"`
			if grep "$grepstr" $dst > /dev/null 2>&1; then
				echo "/${grepstr}/d" >> /tmp/sedscript.$$
				if [ "$deldevs" != "" ] ; then
					xdeldevs=`echo "$deldevs" | \
					    sed -f /tmp/esc.sed.$$`
					for m in $xdeldevs ; do
						echo "$m" >> /tmp/deldevs.$$
					done
				fi
			fi
		done
		if [ -s /tmp/deldevs.$$ ] ; then
			sort -u /tmp/deldevs.$$ > /tmp/tmp.$$
			mv /tmp/tmp.$$ /tmp/deldevs.$$
		fi

		#
		#  Apply the sed script built above to the
		#  currently-installed /etc/minor_perm file.
		#

		if [ -s /tmp/sedscript.$$ ] ; then
			sed -f /tmp/sedscript.$$ $dst > /tmp/tmp.$$
			cp /tmp/tmp.$$ $dst
		fi

		#
		#  Special case code to handle bug in 2.1, 2.2, and
		#  early 2.3 releases:  the link from /dev/sound/*
		#  has one extra set of "../"'s in the link.  This
		#  doesn't cause problems in normal operation 
		#  because ".."'s that would take the search path
		#  higher than the real root are ignored.  However,
		#  during upgrade, when the system being upgraded is
		#  mounted at /a, the extra ".." in the link causes
		#  the link to be unresolvable.  The link must be
		#  corrected so that the chmod of /dev/sound/*
		#  works.
		#

		if [ "$PKG_INSTALL_ROOT" != "" -a "$PKG_INSTALL_ROOT" != "/" ]
		then
			for i in $PKG_INSTALL_ROOT/dev/sound/* ; do
				if [ "$i" = "$PKG_INSTALL_ROOT/dev/sound/*" ]
				then
					break;
				fi

				# if it's not a symlink, continue
				if [ ! -h $i ] ; then
					continue
				fi

				ls -L $i >/dev/null 2>&1
				if [ $? = 0 ] ; then
					#  link is already OK
					continue
				fi

				# otherwise, link can't be followed

				# build the correct link
				link=`ls -l $i | sed 's,.* ,,'`
				link=`expr $link : '\.\.\/\(.*\)'`
				if [ "$link" = "" ] ; then
					continue;
				fi

				# build a test link
				rm -f $PKG_INSTALL_ROOT/dev/sound/test.$$
				ln -s $link $PKG_INSTALL_ROOT/dev/sound/test.$$

				# test the link
				ls -L $PKG_INSTALL_ROOT/dev/sound/test.$$ \
					>/dev/null 2>&1

				# it worked, so replace old link with new
				if [ $? = 0 ] ; then
					rm -f $i
					ln -s $link $i
				fi
				rm -f $PKG_INSTALL_ROOT/dev/sound/test.$$
			done
		fi

		#  For all entries in minor_perm whose attributes had
		#  to be corrected, correct the relevant attributes of the
		#  already-existing devices that correspond to those
		#  entries.
		#
		if [ -s /tmp/chdevs.$$ -a "$PKG_INSTALL_ROOT" != ""  -a \
		     "$PKG_INSTALL_ROOT" != "/" ] ; then
			cat /tmp/chdevs.$$ |\
			while read device oldp oldu oldg newp newu newg
			do
				#
				# Note that we take pains -only- to change
				# the permission/ownership of devices that
				# have kept their original permissions.
				#
				for dev in $PKG_INSTALL_ROOT/$device; do
					find $dev -follow -perm $oldp -exec \
					    chmod $newp $dev \; >/dev/null 2>&1
					find $dev -follow -user $oldu -exec \
					    chown $newu $dev \; >/dev/null 2>&1
					find $dev -follow -group $oldg -exec \
					    chgrp $newg $dev \; >/dev/null 2>&1
				done
			done
		fi

		#
		#  For all entries in minor_perm that were deleted,
		#  remove the /dev entries that point to device nodes
		#  that correspond to those entries.
		#
		if [ -s /tmp/deldevs.$$ -a "$PKG_INSTALL_ROOT" != ""  -a \
		     "$PKG_INSTALL_ROOT" != "/" ] ; then
			cat /tmp/deldevs.$$ | while read device
			do
				rm -f $PKG_INSTALL_ROOT/$device
			done
		fi


		cat /tmp/add.$$ | while read key
		do
			grepstr=`entry2pattern "${key}"`
			grep "$grepstr" $dst > /dev/null 2>&1
			if [ $? != 0 ] ; then
				grep "$grepstr" $src >> $dst
			fi
		done

		rm -f /tmp/*.$$
	fi
done

 
# If additional operations are required for this package, place
# those package-specific commands here.

#XXXSpecial_CommandsXXX#

exit 0

