SUN Packaging Guide -
Class Action Scripts

Writing class action scripts

For writing class action scripts we first have to know how they interact within the package installation/removal procedure. And of course we have to know how classes can be defined and where they are defined. With classes you are able to group certain files within a package. For instance, you will be able to group certain files together and choose only these files for installation.

Defining classes

Classes can be only defined in two files: the CLASSES variable in the pkginfo file and by assigning certain files to this predefined class in the prototype file. Then pkgadd/pkgrm will create a file list containing all these files during an installation/removal and invoke the class action scripts with the file list as 1st parameter. Class names can be freely defined except for the following exceptions:

sed Provides a method for using sed instructions to edit files upon package installation and removal.
awk Provides a method for using awk instructions to edit files upon package installation and removal.
build Provied a method to dynamically construct or modify files using Bourne shell commands.
preserve Provides a method to preserve files that should not be overwritten by future package installations.

There are two possibilities class action scripts can come into action:

The easiest way is using a default class, so we start off with this. Let's do this by choosing the awk system class.

Using a default system class (sed/awk)

To explain how this works out it is best to show you first the entry for the prototype file you have to make:

e awk tmp/dummy.conf 0755 root other

What does this mean? The "e" tells us we have a editable file. The "awk" tells us we have a file which belongs to the class "awk". The third entry tells us it is a file located in /tmp which contains the awk commands. Irritating, isn't it? We want to _modify_ an existing file and not placing a new file with awk commands there! As the /tmp/dummy.conf can't contain any awk commands, we place a awk command file _over_ it. The commands in this file will be then applied to the file it covers. It's like a hat you put on your head.

A _very important_ information I gave to you when explaining the prototype file syntax will now be useful for us. Of course we can't overwrite an existing configuration file for creating a package (imagine it would be a vital system file like /etc/syslog.conf). If you remember the link syntax <destination>=<source>, you can set the path to the final awk script to modify our configuration file like this:

e awk tmp/dummy.conf=/var/tmp/build-root/modify_config.awk 0755 root other

When you create the package then, the file modify_config.awk will be put in the package as tmp/dummy.conf and during installation/removal the script will be then applied to the dummy.conf file. Now we are half on our way to Chicago, folks :). The next part is the syntax of the script. This is quite simple and looks like this:

!install
# awk program to install changes
BEGIN {
}

END {
        print "Installing...";
}

!remove
# awk program to remove changes
BEGIN {
}

{
        print "Removing...";
}

As you can clearly see the script is divided into two parts: the "install" and the "remove" part. When our package is installed/removed, pkgadd/pkgrm creates a list of files which belong to this class and invokes the class action script with the file list. Here we only have one file so the script will be applied only to one file.
There is no difference between creating scripts for the sed class or the awk class except that in the first case any command is a sed command and in the second case we have awk commands only AND that the sed/awk classes _modify_ existing files only.

The "build" class

The "build" class is used to create _and_ modify a package object file by executing Bourne shell instructions. The prototype entry would look like this:

e build tmp/dummy=/var/tmp/build-root/modify_dummy.sh ? ? ?

The package object tmp/dummy would then look like this:

!install
# dummy file creator
if [ -r ${PKG_INSTALL_ROOT}/tmp/dummy ]
then
	echo "/tmp/dummy already in place"
else
	echo "# /tmp/dummy" > ${PKG_INSTALL_ROOT}/tmp/dummy
	echo "123456 # first random number" >> ${PKG_INSTALL_ROOT}/tmp/dummy
fi

!remove
# dummy file deconstructor
if [ -f ${PKG_INSTALL_ROOT}/tmp/dummy ]
then
	# The file can be removed if unchanged
	if [ egrep "first random number" ${PKG_INSTALL_ROOT}/tmp/dummy ]
	then
		rm ${PKG_INSTALL_ROOT}/tmp/dummy
	fi
fi

The "preserve" class

The preserve class preserves a package object file by determinig whether or not an existing file should be overwritten when the package is installed. Two possible scenarios when using a preserve class script are:

An example of a preserve class action script would be:

error=no
echo "## checking common configuration files"
while read src dest
do
      [ "$src" = /dev/null ] && continue

      if [ -f "$dest" ]
      then
              echo $dest preserve
      else
              echo $dest
              cp $src $dest || error=yes
      fi

done
[ "$error" = yes ] &&
        exit 2
exit 0

You may ask, what "$src" and "$dest" mean here. Very easy: The default behaviour of pkgadd is to copy the packaged file from the installation medium (e.g. a package) to its final destination. In this example we just want to know whether the file already exists ($src set to /dev/null).

Creating class action scripts with own classes

You already know the basics for this from the paragraphs above, so we will summarize it in a list:

  1. Assign the package objects in the prototype file the desired class names. For instance,
    f manpage usr/share/man/man1/myapp.1
  2. Modify the CLASSES variable in the pkginfo file to contain the newly defined class name, e.g.
    CLASSES=manpage application none
  3. Create the class scripts. An installation script for a certain class must be named i.<class>, e.g.
    i.manpage
    A removal class action script for a certain class must be named r.<class>, e.g.
    r.manpage
  4. Add the required class scripts separately to the prototype file, e.g.
    i i.manpage
    i r.manpage
  5. Create your package using pkgmk.

NOTE: Remember, when a file is part of a class that has a class action script, the script must install the file. The pkgadd command does not install files for which a class action script exists, although it does verify the installation. And, if you define a class but do not deliver a class action script, the only action taken for that class is to copy components from the installation medium (a package) to the target system (the default pkgadd behaviour).