OpenSolaris_b135/pkgdefs/common_files/i.initd

#!/bin/sh
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License, Version 1.0 only
# (the "License").  You may not use this file except in compliance
# with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# Copyright 1997-1998, 2003 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
#ident	"%Z%%M%	%I%	%E% SMI"
#
# i.initd - Class action script for /etc/init.d script files.
# 
# This class action script handles the issue of delivering a new version of
# an /etc/init.d script with a new set of [SK][0-9][0-9] links (or in non-glob
# terms, a new set of start and/or kill number links).  It assumes that
# the package prototype file has been set up so that we have a set of
# entries similar to the following:
# 
#	e initd etc/init.d/syslog 744 root sys
#	l initd etc/rc0.d/K40syslog=../../etc/init.d/syslog
#	l initd etc/rc1.d/K40syslog=../../etc/init.d/syslog
#	l initd etc/rc2.d/S74syslog=../../etc/init.d/syslog
#	l initd etc/rcS.d/K40syslog=../../etc/init.d/syslog
#
# Note that the script file (/etc/init.d/syslog) is marked as type 'e' for
# editable so that this script is invoked during both install and upgrade.
# The S and K scripts are installed as hard links to the /etc/init.d/ file.
# Since all the files are specified as class 'initd', we know that this
# script will first be invoked for all the 'e' files, and then for the links.
# We are responsible for copying over the 'e' files, and installf creates
# the hard links for us.
#
# Since we know that pkgadd will call installf to add the 'l' links last,
# our goal is to remove all existing or likely links to each /etc/init.d/ file
# we are asked to install.  In order to locate existing S and K links, we use
# two algorithms: (1) If the destination file exists and has a > 1 link count,
# we scan the /etc directory (relative to the destination file) for files with
# the same inode number whose names begin with [SK][0-9][0-9] and remove them.
# (2) If the the destination file exists, we remove all files in /etc/rc?.d
# whose names are [SK][0-9][0-9] followed by the basename of the destination
# file.  Step (2) is needed because we may have mistakenly delivered the file
# earlier as a symbolic link, or because a system administrator may have
# mistakenly unlinked the /etc/init.d script from its S or K counterpart.
#
# For each file we wish to remove, we need to first ask removef if it's ok
# to remove, and then remove it, and finally call removef -f to update the
# software database.  With that complete, we then invoke installf to
# install all of the 'l' links in the 'initd' class specified in the pkgmap
# file.  This step is necessary because during upgrade, pkgadd will not
# invoke this script for 'l' links, since it has no concept of an 'editable'
# link which is changing during an upgrade.
#
# Execution of the checkinstall script will have determined, which, if any of
# the scripts were modified by a system administrator.  This list of scripts
# was preserved in the MODIFIED_AFTER_INSTALLED variable.  We iterate through
# the modified scripts, saving the system administrator's old version and
# echoing a magic token out to the /tmp/CLEANUP file.  This will result in an
# internationalized message being written to the upgrade log
# /var/sadm/install_data/upgrade_cleanup.  For more on the details of
# /tmp/CLEANUP, refer back to PSARC 1992/118.

REMOVEF=removef
INSTALLF=installf
CLEANUP=/tmp/CLEANUP

case "$ARCH" in
	sparc.sun4m)	EXT=.m;;
	sparc.sun4u)	EXT=.u;;
	i386.i86pc)	EXT=.i;;
	*)		EXT="";;
esac
PKGMAP=$INST_DATADIR/$PKG$EXT/pkgmap

if [ "x$UPDATE" = xyes ]; then
	for ofile in $MODIFIED_AFTER_INSTALLED; do
		case "`basename $ofile`" in
		[SK][0-9]*)
			nfile="`dirname $ofile`/_`basename $ofile`.old" ;;
		*)
			nfile="${ofile}.old" ;;
		esac
		if [ -f $ofile ]; then
			cp -p $ofile $nfile
			echo "EXISTING_FILE_RENAMED: $ofile $nfile" >>$CLEANUP
		fi
	done
fi

# Now read the standard input to the class-action script (this will be
# the list of 'e' editable files corresponding to the /etc/init.d/scripts),
# remove the corresponding hard links in the /etc/rc?.d directories, and
# install the new version of each init.d script.

while read src dst; do
	dstname=`basename $dst`
	case "$dstname" in

	[SK][0-9]*)
		# If this item is the link, the additional hard link to the
		# /etc/init.d file will be created by installf so we do not
		# need to do anything here.
		;;

	acct)
		# By default (the '*' case below) we're going to remove all
		# links to each /etc/init.d script.  There is one exception
		# to this rule: links to /etc/init.d/acct. We don't ship any
		# links to this script; if links are present, the administrator
		# has created them in order to enable accounting, and we want
		# to leave them enabled.

		cp -p $src $dst
		;;

	*)
		# If this item is the script, then remove any existing links
		# and then copy the contents from $src to $dst

		if [ -f $dst ]; then
			shift $#
			set -- `ls -li $dst 2>/dev/null`
			inode=${1:-0}; nlink=${3:-0}

			(

			if [ $nlink -gt 1 ]; then
				find $PKG_INSTALL_ROOT/etc/rc?.d -mount \
				    -type f -inum $inode \
				    -name '[SK][0-9][0-9]*' -print
			fi
			echo $PKG_INSTALL_ROOT/etc/rc?.d/[SK][0-9][0-9]$dstname

			) | xargs $REMOVEF $PKGINST 2>/dev/null | xargs rm -f
		fi

		cp -p $src $dst
		;;
	esac
done

# Complete the removal operations specified in the loop above

$REMOVEF -f $PKGINST || exit 2

# Now find all the hard links for the initd class in the package map
# and make sure they get recreated.  In the case of hard links, installf
# takes care of updating the database *and* creating the links.  We need
# to tweak the source and destination of the link to be absolute paths.
# Installf will convert these to be relative to $PKG_INSTALL_ROOT, which
# it inherits through the environment.

awk '$2 == "l" && $3 =="initd" {print $4, $2}' $PKGMAP | \
  sed -e 's:^etc/:/etc/:' | \
  $INSTALLF -c initd $PKGINST - && exit 0 || exit 2