#!/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