Home | History | Annotate | Download | only in common_files
      1 #!/bin/sh
      2 #
      3 # CDDL HEADER START
      4 #
      5 # The contents of this file are subject to the terms of the
      6 # Common Development and Distribution License, Version 1.0 only
      7 # (the "License").  You may not use this file except in compliance
      8 # with the License.
      9 #
     10 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     11 # or http://www.opensolaris.org/os/licensing.
     12 # See the License for the specific language governing permissions
     13 # and limitations under the License.
     14 #
     15 # When distributing Covered Code, include this CDDL HEADER in each
     16 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     17 # If applicable, add the following below this CDDL HEADER, with the
     18 # fields enclosed by brackets "[]" replaced with your own identifying
     19 # information: Portions Copyright [yyyy] [name of copyright owner]
     20 #
     21 # CDDL HEADER END
     22 #
     23 #
     24 # Copyright 1997-1998, 2003 Sun Microsystems, Inc.  All rights reserved.
     25 # Use is subject to license terms.
     26 #
     27 #ident	"%Z%%M%	%I%	%E% SMI"
     28 #
     29 # i.initd - Class action script for /etc/init.d script files.
     30 # 
     31 # This class action script handles the issue of delivering a new version of
     32 # an /etc/init.d script with a new set of [SK][0-9][0-9] links (or in non-glob
     33 # terms, a new set of start and/or kill number links).  It assumes that
     34 # the package prototype file has been set up so that we have a set of
     35 # entries similar to the following:
     36 # 
     37 #	e initd etc/init.d/syslog 744 root sys
     38 #	l initd etc/rc0.d/K40syslog=../../etc/init.d/syslog
     39 #	l initd etc/rc1.d/K40syslog=../../etc/init.d/syslog
     40 #	l initd etc/rc2.d/S74syslog=../../etc/init.d/syslog
     41 #	l initd etc/rcS.d/K40syslog=../../etc/init.d/syslog
     42 #
     43 # Note that the script file (/etc/init.d/syslog) is marked as type 'e' for
     44 # editable so that this script is invoked during both install and upgrade.
     45 # The S and K scripts are installed as hard links to the /etc/init.d/ file.
     46 # Since all the files are specified as class 'initd', we know that this
     47 # script will first be invoked for all the 'e' files, and then for the links.
     48 # We are responsible for copying over the 'e' files, and installf creates
     49 # the hard links for us.
     50 #
     51 # Since we know that pkgadd will call installf to add the 'l' links last,
     52 # our goal is to remove all existing or likely links to each /etc/init.d/ file
     53 # we are asked to install.  In order to locate existing S and K links, we use
     54 # two algorithms: (1) If the destination file exists and has a > 1 link count,
     55 # we scan the /etc directory (relative to the destination file) for files with
     56 # the same inode number whose names begin with [SK][0-9][0-9] and remove them.
     57 # (2) If the the destination file exists, we remove all files in /etc/rc?.d
     58 # whose names are [SK][0-9][0-9] followed by the basename of the destination
     59 # file.  Step (2) is needed because we may have mistakenly delivered the file
     60 # earlier as a symbolic link, or because a system administrator may have
     61 # mistakenly unlinked the /etc/init.d script from its S or K counterpart.
     62 #
     63 # For each file we wish to remove, we need to first ask removef if it's ok
     64 # to remove, and then remove it, and finally call removef -f to update the
     65 # software database.  With that complete, we then invoke installf to
     66 # install all of the 'l' links in the 'initd' class specified in the pkgmap
     67 # file.  This step is necessary because during upgrade, pkgadd will not
     68 # invoke this script for 'l' links, since it has no concept of an 'editable'
     69 # link which is changing during an upgrade.
     70 #
     71 # Execution of the checkinstall script will have determined, which, if any of
     72 # the scripts were modified by a system administrator.  This list of scripts
     73 # was preserved in the MODIFIED_AFTER_INSTALLED variable.  We iterate through
     74 # the modified scripts, saving the system administrator's old version and
     75 # echoing a magic token out to the /tmp/CLEANUP file.  This will result in an
     76 # internationalized message being written to the upgrade log
     77 # /var/sadm/install_data/upgrade_cleanup.  For more on the details of
     78 # /tmp/CLEANUP, refer back to PSARC 1992/118.
     79 
     80 REMOVEF=removef
     81 INSTALLF=installf
     82 CLEANUP=/tmp/CLEANUP
     83 
     84 case "$ARCH" in
     85 	sparc.sun4m)	EXT=.m;;
     86 	sparc.sun4u)	EXT=.u;;
     87 	i386.i86pc)	EXT=.i;;
     88 	*)		EXT="";;
     89 esac
     90 PKGMAP=$INST_DATADIR/$PKG$EXT/pkgmap
     91 
     92 if [ "x$UPDATE" = xyes ]; then
     93 	for ofile in $MODIFIED_AFTER_INSTALLED; do
     94 		case "`basename $ofile`" in
     95 		[SK][0-9]*)
     96 			nfile="`dirname $ofile`/_`basename $ofile`.old" ;;
     97 		*)
     98 			nfile="${ofile}.old" ;;
     99 		esac
    100 		if [ -f $ofile ]; then
    101 			cp -p $ofile $nfile
    102 			echo "EXISTING_FILE_RENAMED: $ofile $nfile" >>$CLEANUP
    103 		fi
    104 	done
    105 fi
    106 
    107 # Now read the standard input to the class-action script (this will be
    108 # the list of 'e' editable files corresponding to the /etc/init.d/scripts),
    109 # remove the corresponding hard links in the /etc/rc?.d directories, and
    110 # install the new version of each init.d script.
    111 
    112 while read src dst; do
    113 	dstname=`basename $dst`
    114 	case "$dstname" in
    115 
    116 	[SK][0-9]*)
    117 		# If this item is the link, the additional hard link to the
    118 		# /etc/init.d file will be created by installf so we do not
    119 		# need to do anything here.
    120 		;;
    121 
    122 	acct)
    123 		# By default (the '*' case below) we're going to remove all
    124 		# links to each /etc/init.d script.  There is one exception
    125 		# to this rule: links to /etc/init.d/acct. We don't ship any
    126 		# links to this script; if links are present, the administrator
    127 		# has created them in order to enable accounting, and we want
    128 		# to leave them enabled.
    129 
    130 		cp -p $src $dst
    131 		;;
    132 
    133 	*)
    134 		# If this item is the script, then remove any existing links
    135 		# and then copy the contents from $src to $dst
    136 
    137 		if [ -f $dst ]; then
    138 			shift $#
    139 			set -- `ls -li $dst 2>/dev/null`
    140 			inode=${1:-0}; nlink=${3:-0}
    141 
    142 			(
    143 
    144 			if [ $nlink -gt 1 ]; then
    145 				find $PKG_INSTALL_ROOT/etc/rc?.d -mount \
    146 				    -type f -inum $inode \
    147 				    -name '[SK][0-9][0-9]*' -print
    148 			fi
    149 			echo $PKG_INSTALL_ROOT/etc/rc?.d/[SK][0-9][0-9]$dstname
    150 
    151 			) | xargs $REMOVEF $PKGINST 2>/dev/null | xargs rm -f
    152 		fi
    153 
    154 		cp -p $src $dst
    155 		;;
    156 	esac
    157 done
    158 
    159 # Complete the removal operations specified in the loop above
    160 
    161 $REMOVEF -f $PKGINST || exit 2
    162 
    163 # Now find all the hard links for the initd class in the package map
    164 # and make sure they get recreated.  In the case of hard links, installf
    165 # takes care of updating the database *and* creating the links.  We need
    166 # to tweak the source and destination of the link to be absolute paths.
    167 # Installf will convert these to be relative to $PKG_INSTALL_ROOT, which
    168 # it inherits through the environment.
    169 
    170 awk '$2 == "l" && $3 =="initd" {print $4, $2}' $PKGMAP | \
    171   sed -e 's:^etc/:/etc/:' | \
    172   $INSTALLF -c initd $PKGINST - && exit 0 || exit 2
    173