This chapter provides case studies to show packaging scenarios such as installing objects conditionally, determining at run time how many files to create, and modifying an existing data file during package installation and removal.
Each case study begins with a description, followed by a list of the packaging techniques used, a narrative description of the approach taken when using those techniques, and sample files and scripts associated with the case study.
This is a list of the case studies in this chapter:
Creating a File at Installation and Saving It During Removal
Modifying a File by Using Standard Classes and Class Action Scripts
Modifying a File by Using the sed Class and a postinstall Script
Installing a Driver by Using the sed Class and Procedure Scripts
The package in this case study has three types of objects. The administrator may choose which of the three types to install and where to locate the objects on the installation machine.
This case study demonstrates the following techniques:
Using parametric path names (variables in object path names) that are used to establish multiple base directories
For information on parametric path names, see Parametric Path Names.
Using a request script to solicit input from the administrator
For information on request scripts, see Writing a request Script.
Setting conditional values for an installation parameter.
To set up the selective installation in this case study, you must complete the following tasks:
Define a class for each type of object that can be installed.
In this case study, the three object types are the package executables, the man pages, and the emacs executables. Each type has its own class: bin, man, and emacs, respectively. Notice that in the prototype file all the object files belong to one of these three classes.
Initialize the CLASSES parameter in the pkginfo file to null.
Normally when you define a class, you should list that class in the CLASSES parameter in the pkginfo file. Otherwise, no objects in that class are installed. For this case study, the parameter is initially set to null, which means no objects will get installed. The CLASSES parameter will be changed by the request script, based on the choices of the administrator. This way, the CLASSES parameter is set to only those object types that the administrator wants installed.
Usually it is a good idea to set parameters to a default value. If this package had components common to all three object types, you could assign them to the none class, and then set the CLASSES parameter equal to none.
Insert parametric path names into the prototype file.
The request script sets these environment variables to the value that the administrator provides. Then, the pkgadd command resolves these environment variables at installation time and knows where to install the package.
The three environment variables used in this example are set to their default in the pkginfo file and serve the following purposes:
$NCMPBIN defines the location for object executables
$NCMPMAN defines the location for man pages
$EMACS defines the location for emacs executables
The example prototype file shows how to define the object path names with variables.
Create a request script to ask the administrator which parts of the package should be installed and where they should be placed.
The request script for this package asks the administrator two questions:
Should this part of the package be installed?
When the answer is yes, the appropriate class name is added to the CLASSES parameter. For example, when the administrator chooses to install the man pages associated with this package, the class man is added to the CLASSES parameter.
If so, where should this part of the package be placed?
The appropriate environment variable is set to the response to this question. In the man page example, the variable $NCMPMAN is set to the response value.
These two questions are repeated for each of the three object types.
At the end of the request script, the parameters are made available to the installation environment for the pkgadd command and any other packaging scripts. The request script does this by writing these definitions to the file provided by the calling utility. For this case study, no other scripts are provided.
When looking at the request script for this case study, notice that the questions are generated by the data validation tools ckyorn and ckpath. For more information on these tools, see ckyorn(1) and ckpath(1).
PKG=ncmp NAME=NCMP Utilities CATEGORY=application, tools BASEDIR=/ ARCH=SPARC VERSION=RELEASE 1.0, Issue 1.0 CLASSES="" NCMPBIN=/bin NCMPMAN=/usr/man EMACS=/usr/emacs |
i pkginfo i request x bin $NCMPBIN 0755 root other f bin $NCMPBIN/dired=/usr/ncmp/bin/dired 0755 root other f bin $NCMPBIN/less=/usr/ncmp/bin/less 0755 root other f bin $NCMPBIN/ttype=/usr/ncmp/bin/ttype 0755 root other f emacs $NCMPBIN/emacs=/usr/ncmp/bin/emacs 0755 root other x emacs $EMACS 0755 root other f emacs $EMACS/ansii=/usr/ncmp/lib/emacs/macros/ansii 0644 root other f emacs $EMACS/box=/usr/ncmp/lib/emacs/macros/box 0644 root other f emacs $EMACS/crypt=/usr/ncmp/lib/emacs/macros/crypt 0644 root other f emacs $EMACS/draw=/usr/ncmp/lib/emacs/macros/draw 0644 root other f emacs $EMACS/mail=/usr/ncmp/lib/emacs/macros/mail 0644 root other f emacs $NCMPMAN/man1/emacs.1=/usr/ncmp/man/man1/emacs.1 0644 root other d man $NCMPMAN 0755 root other d man $NCMPMAN/man1 0755 root other f man $NCMPMAN/man1/dired.1=/usr/ncmp/man/man1/dired.1 0644 root other f man $NCMPMAN/man1/ttype.1=/usr/ncmp/man/man1/ttype.1 0644 root other f man $NCMPMAN/man1/less.1=/usr/ncmp/man/man1/less.1 0644 inixmr other |
trap 'exit 3' 15 # determine if and where general executables should be placed ans=`ckyorn -d y \ -p "Should executables included in this package be installed" ` || exit $? if [ "$ans" = y ] then CLASSES="$CLASSES bin" NCMPBIN=`ckpath -d /usr/ncmp/bin -aoy \ -p "Where should executables be installed" ` || exit $? fi # determine if emacs editor should be installed, and if it should # where should the associated macros be placed ans=`ckyorn -d y \ -p "Should emacs editor included in this package be installed" ` || exit $? if [ "$ans" = y ] then CLASSES="$CLASSES emacs" EMACS=`ckpath -d /usr/ncmp/lib/emacs -aoy \ -p "Where should emacs macros be installed" ` || exit $? fi |
Note that a request script can exit without leaving any files on the file system. For installations on Solaris versions prior to 2.5 and compatible versions (where no checkinstall script may be used) the request script is the correct place to test the file system in any manner necessary to ensure that the installation will succeed. When the request script exits with code 1, the installation will quit cleanly.
These example files show the use of parametric paths to establish multiple base directories. However, the preferred method involves use of the BASEDIR parameter which is managed and validated by the pkgadd command. Whenever multiple base directories are used, take special care to provide for installation of multiple versions and architectures on the same platform.
This case study creates a database file at installation time and saves a copy of the database when the package is removed.
This case study demonstrates the following techniques:
Using classes and class action scripts to perform special actions on different sets of objects
For more information, see Writing Class Action Scripts.
Using the space file to inform the pkgadd command that extra space is required to install this package properly
For more information on the space file, see Reserving Additional Space on a Target System.
Using the installf command to install a file not defined in the prototype and pkgmap files.
To create a database file at installation and save a copy on removal for this case study, you must complete the following tasks:
Define three classes.
The package in this case study requires the following three classes be defined in the CLASSES parameter:
The standard class of none, which contains a set of processes belonging in the subdirectory bin.
The admin class, which contains an executable file config and a directory containing data files.
The cfgdata class, which contains a directory.
Make the package collectively relocatable.
Notice in the prototype file that none of the path names begins with a slash or an environment variable. This indicates that they are collectively relocatable.
Calculate the amount of space the database file requires and create a space file to deliver with the package. This file notifies the pkgadd command that the package requires extra space and specifies how much.
Create a class action script for the admin class (i.admin).
The sample script initializes a database using the data files belonging to the admin class. To perform this task, it does the following:
Copies the source data file to its proper destination
Creates an empty file named config.data and assigns it to a class of cfgdata
Executes the bin/config command (delivered with the package and already installed) to populate the database file config.data using the data files belonging to the admin class
Executes the installf -f command to finalize installation of config.data
No special action is required for the admin class at removal time so no removal class action script is created. This means that all files and directories in the admin class are removed from the system.
Create a removal class action script for the cfgdata class (r.cfgdata).
The removal script makes a copy of the database file before it is deleted. No special action is required for this class at installation time, so no installation class action script is needed.
Remember that the input to a removal script is a list of path names to remove. Path names always appear in reverse alphabetical order. This removal script copies files to the directory named $PKGSAV. When all the path names have been processed, the script then goes back and removes all directories and files associated with the cfgdata class.
The outcome of this removal script is to copy config.data to $PKGSAV and then remove the config.data file and the data directory.
PKG=krazy NAME=KrAzY Applications CATEGORY=applications BASEDIR=/opt ARCH=SPARC VERSION=Version 1 CLASSES=none cfgdata admin |
i pkginfo i request i i.admin i r.cfgdata d none bin 555 root sys f none bin/process1 555 root other f none bin/process2 555 root other f none bin/process3 555 root other f admin bin/config 500 root sys d admin cfg 555 root sys f admin cfg/datafile1 444 root sys f admin cfg/datafile2 444 root sys f admin cfg/datafile3 444 root sys f admin cfg/datafile4 444 root sys d cfgdata data 555 root sys |
# extra space required by config data which is # dynamically loaded onto the system data 500 1 |
# PKGINST parameter provided by installation service # BASEDIR parameter provided by installation service while read src dest do cp $src $dest || exit 2 done # if this is the last time this script will be executed # during the installation, do additional processing here. if [ "$1" = ENDOFCLASS ] then # our config process will create a data file based on any changes # made by installing files in this class; make sure the data file # is in class `cfgdata' so special rules can apply to it during # package removal. installf -c cfgdata $PKGINST $BASEDIR/data/config.data f 444 root sys || exit 2 $BASEDIR/bin/config > $BASEDIR/data/config.data || exit 2 installf -f -c cfgdata $PKGINST || exit 2 fi exit 0 |
This illustrates a rare instance in which installf is appropriate in a class action script. Because a space file has been used to reserve room on a specific file system, this new file may be safely added even though it is not included in the pkgmap file.
# the product manager for this package has suggested that # the configuration data is so valuable that it should be # backed up to $PKGSAV before it is removed! while read path do # path names appear in reverse lexical order. mv $path $PKGSAV || exit 2 rm -f $path || exit 2 done exit 0 |
The package in this case study uses optional information files to define package compatibilities and dependencies, and to present a copyright message during installation.
This case study demonstrates the following techniques:
Using the copyright file
Using the compver file
Using the depend file
For more information on these files, see Creating Information Files.
To meet the requirements in the description, you must:
Create a copyright file.
A copyright file contains the ASCII text of a copyright message. The message shown in the sample file is displayed on the screen during package installation.
Create a compver file.
The pkginfo file shown in the next figure defines this package version as version 3.0. The compver file defines version 3.0 as being compatible with versions 2.3, 2.2, 2.1, 2.1.1, 2.1.3 and 1.7.
Create a depend file.
Files listed in a depend file must already be installed on the system when a package is installed. The example file has 11 packages which must already be on the system at installation time.
PKG=case3 NAME=Case Study #3 CATEGORY=application BASEDIR=/opt ARCH=SPARC VERSION=Version 3.0 CLASSES=none |
Copyright (c) 1999 company_name All Rights Reserved. THIS PACKAGE CONTAINS UNPUBLISHED PROPRIETARY SOURCE CODE OF company_name. The copyright notice above does not evidence any actual or intended publication of such source code |
Version 3.0 Version 2.3 Version 2.2 Version 2.1 Version 2.1.1 Version 2.1.3 Version 1.7 |
P acu Advanced C Utilities Issue 4 Version 1 P cc C Programming Language Issue 4 Version 1 P dfm Directory and File Management Utilities P ed Editing Utilities P esg Extended Software Generation Utilities Issue 4 Version 1 P graph Graphics Utilities P rfs Remote File Sharing Utilities Issue 1 Version 1 P rx Remote Execution Utilities P sgs Software Generation Utilities Issue 4 Version 1 P shell Shell Programming Utilities P sys System Header Files Release 3.1 |
This case study modifies an existing file during package installation using standard classes and class action scripts. It uses one of three modification methods. The other two methods are described in Modifying a File by Using the sed Class and a postinstall Script and Modifying a File by Using The build Class. The file modified is /etc/inittab.
This case study demonstrates how to use installation and removal class action scripts. For more information, see Writing Class Action Scripts.
To modify /etc/inittab during installation, using classes and class action scripts, you must complete the following tasks:
Create a class.
Create a class called inittab. You must provide an installation and a removal class action script for this class. Define the inittab class in the CLASSES parameter in the pkginfo file.
Create an inittab file.
This file contains the information for the entry that you will add to /etc/inittab. Notice in the prototype file figure that inittab is a member of the inittab class and has a file type of e for editable.
Create an installation class action script (i.inittab).
Remember that class action scripts must produce the same results each time they are executed. The class action script performs the following procedures:
Checks if this entry has been added before
If it has, removes any previous versions of the entry
Edits the inittab file and adds the comment lines so you know where the entry is from
Moves the temporary file back into /etc/inittab
Executes the init q command when it receives the ENDOFCLASS indicator
Note that the init q command can be performed by this installation script. A one-line postinstall script is not needed by this approach.
Create a removal class action script (r.inittab).
The removal script is very similar to the installation script. The information added by the installation script is removed and the init q command is executed.
This case study is more complicated than the next one; see Modifying a File by Using the sed Class and a postinstall Script. Instead of providing two files, three are needed and the delivered /etc/inittab file is actually just a place holder containing a fragment of the entry to be inserted. This could have been placed into the i.inittab file except that the pkgadd command must have a file to pass to the i.inittab file. Also, the removal procedure must be placed into a separate file (r.inittab). While this method works fine, it is best reserved for cases involving very complicated installations of multiple files. See Modifying crontab Files During Installation.
The sed program used in Modifying a File by Using the sed Class and a postinstall Script supports multiple package instances since the comment at the end of the inittab entry is based on package instance. The case study in Modifying a File by Using The build Class shows a more streamlined approach to editing /etc/inittab during installation.
PKG=case5 NAME=Case Study #5 CATEGORY=applications BASEDIR=/opt ARCH=SPARC VERSION=Version 1d05 CLASSES=inittab |
i pkginfo i i.inittab i r.inittab e inittab /etc/inittab ? ? ? |
# PKGINST parameter provided by installation service while read src dest do # remove all entries from the table that # associated with this PKGINST sed -e "/^[^:]*:[^:]*:[^:]*:[^#]*#$PKGINST$/d" $dest > /tmp/$$itab || exit 2 sed -e "s/$/#$PKGINST" $src >> /tmp/$$itab || exit 2 mv /tmp/$$itab $dest || exit 2 done if [ "$1" = ENDOFCLASS ] then /sbin/init q || exit 2 fi exit 0 |
# PKGINST parameter provided by installation service while read src dest do # remove all entries from the table that # are associated with this PKGINST sed -e "/^[^:]*:[^:]*:[^:]*:[^#]*#$PKGINST$/d" $dest > /tmp/$$itab || exit 2 mv /tmp/$$itab $dest || exit 2 done /sbin/init q || exit 2 exit 0 |
rb:023456:wait:/usr/robot/bin/setup |
This case study modifies a file which exists on the installation machine during package installation. It uses one of three modification methods. The other two methods are described in Modifying a File by Using Standard Classes and Class Action Scripts and Modifying a File by Using The build Class. The file modified is /etc/inittab.
This case study demonstrates the following techniques:
Using the sed class
For more information on the sed class, see The sed Class Script.
Using a postinstall script
For more information on this script, see Writing Procedure Scripts.
To modify /etc/inittab at the time of installation, using the sed class, you must complete the following tasks:
Add the sed class script to the prototype file.
The name of a script must be the name of the file that will be edited. In this case, the file to be edited is /etc/inittab and so the sed script is named /etc/inittab. There are no requirements for the mode, owner, and group of a sed script (represented in the sample prototype by question marks). The file type of the sed script must be e (indicating that it is editable).
Set the CLASSES parameter to include the sed class.
As shown in the example file, sed is the only class being installed. However, it could be one of any number of classes.
Create a sed class action script.
Your package cannot deliver a copy of /etc/inittab that looks the way you need it to, since /etc/inittab is a dynamic file and you have no way of knowing how it will look at the time of package installation. However, using a sed script allows you to modify the /etc/inittab file during package installation.
Create a postinstall script.
You need to execute the init q command to inform the system that /etc/inittab has been modified. The only place you can perform that action in this example is in a postinstall script. Looking at the example postinstall script, you will see that its only purpose is to execute the init q command.
This approach to editing /etc/inittab during installation has one drawback; you have to deliver a full script (the postinstall script) simply to perform the init q command.
PKG=case4 NAME=Case Study #4 CATEGORY=applications BASEDIR=/opt ARCH=SPARC VERSION=Version 1d05 CLASSES=sed |
i pkginfo i postinstall e sed /etc/inittab ? ? ? |
!remove # remove all entries from the table that are associated # with this package, though not necessarily just # with this package instance /^[^:]*:[^:]*:[^:]*:[^#]*#ROBOT$/d !install # remove any previous entry added to the table # for this particular change /^[^:]*:[^:]*:[^:]*:[^#]*#ROBOT$/d # add the needed entry at the end of the table; # sed(1) does not properly interpret the '$a' # construct if you previously deleted the last # line, so the command # $a\ # rb:023456:wait:/usr/robot/bin/setup #ROBOT # will not work here if the file already contained # the modification. Instead, you will settle for # inserting the entry before the last line! $i\ rb:023456:wait:/usr/robot/bin/setup #ROBOT |
# make init re-read inittab /sbin/init q || exit 2 exit 0 |
This case study modifies a file which exists on the installation machine during package installation. It uses one of three modification methods. The other two methods are described in Modifying a File by Using Standard Classes and Class Action Scripts and Modifying a File by Using the sed Class and a postinstall Script. The file modified is /etc/inittab.
This case study demonstrates how to use the build class. For more information on the build class, see The build Class Script.
This approach to modifying /etc/inittab uses the build class. A build class script is executed as a shell script and its output becomes the new version of the file being executed. In other words, the data file /etc/inittab that is delivered with this package will be executed and the output of that execution will become /etc/inittab.
The build class script is executed during package installation and package removal. The argument install is passed to the file if it is being executed at installation time. Notice in the sample build class script that installation actions are defined by testing for this argument.
To edit /etc/inittab using the build class, you must complete the following tasks:
Define the build file in the prototype file.
The entry for the build file in the prototype file should place it in the build class and define its file type as e. Be certain that the CLASSES parameter in the pkginfo file is defined as build.
Create the build class script.
The sample build class script performs the following procedures:
Edits the /etc/inittab file to remove any existing changes for this package. Notice that the file name /etc/inittab is hardcoded into the sed command.
If the package is being installed, adds the new line to the end of /etc/inittab. A comment tag is included in this new entry to describe where that entry came from.
Executes the init q command.
This solution addresses the drawbacks described in the case studies in Modifying a File by Using Standard Classes and Class Action Scripts and Modifying a File by Using the sed Class and a postinstall Script. Only one short file is needed (beyond the pkginfo and prototype files). The file works with multiple instances of a package since the PKGINST parameter is used, and no postinstall script is required since the init q command can be executed from the build class script.
PKG=case6 NAME=Case Study #6 CATEGORY=applications BASEDIR=/opt ARCH=SPARC VERSION=Version 1d05 CLASSES=build |
i pkginfo e build /etc/inittab ? ? ? |
# PKGINST parameter provided by installation service # remove all entries from the existing table that # are associated with this PKGINST sed -e "/^[^:]*:[^:]*:[^:]*:[^#]*#$PKGINST$/d" /etc/inittab || exit 2 if [ "$1" = install ] then # add the following entry to the table echo "rb:023456:wait:/usr/robot/bin/setup #$PKGINST" || exit 2 fi /sbin/init q || exit 2 exit 0 |
This case study modifies crontab files during package installation.
This case study demonstrates the following techniques:
Using classes and class action scripts
For more information, see Writing Class Action Scripts.
Using the crontab command within a class action script.
The most efficient way to edit more than one file during installation is to define a class and provide a class action script. If you used the build class approach, you would need to deliver one build class script for each crontab file edited. Defining a cron class provides a more general approach. To edit crontab files with this approach, you must:
Define the crontab files that are to be edited in the prototype file.
Create an entry in the prototype file for each crontab file that will be edited. Define the class as cron and the file type as e for each file. Use the actual name of the file to be edited.
Create the crontab files for the package.
These files contain the information you want added to the existing crontab files of the same name.
Create an installation class action script for the cron class.
The sample i.cron script performs the following procedures:
Determines the user ID (UID).
The i.cron script sets the variable user to the base name of the cron class script being processed. That name is the UID. For example, the base name of /var/spool/cron/crontabs/root is root, which is also the UID.
Executes crontab using the UID and the -l option.
Using the -l option tells crontab to send the contents of the crontab file for the defined user to the standard output.
Pipes the output of the crontab command to a sed script that removes any previous entries added with this installation technique.
Puts the edited output into a temporary file.
Adds the data file for the root UID (that was delivered with the package) to the temporary file and adds a tag so you will know where these entries came from.
Executes crontab with the same UID and gives it the temporary file as input.
Create a removal class action script for the cron class.
The r.cron script is the same as the installation script except there is no procedure to add information to the crontab file.
These procedures are performed for every file in the cron class.
The i.cron and r.cron scripts described below are executed by superuser. Editing another user's crontab file as superuser may have unpredictable results. If necessary, change the following entry in each script:
crontab $user < /tmp/$$crontab ||
to
su $user -c "crontab /tmp/$$crontab" ||
PKG=case7 NAME=Case Study #7 CATEGORY=application BASEDIR=/opt ARCH=SPARC VERSION=Version 1.0 CLASSES=cron |
i pkginfo i i.cron i r.cron e cron /var/spool/cron/crontabs/root ? ? ? e cron /var/spool/cron/crontabs/sys ? ? ? |
# PKGINST parameter provided by installation service while read src dest do user=`basename $dest` || exit 2 (crontab -l $user | sed -e "/#$PKGINST$/d" > /tmp/$$crontab) || exit 2 sed -e "s/$/#$PKGINST/" $src >> /tmp/$$crontab || exit 2 crontab $user < /tmp/$$crontab || exit 2 rm -f /tmp/$$crontab done exit 0 |
# PKGINST parameter provided by installation service while read path do user=`basename $path` || exit 2 (crontab -l $user | sed -e "/#$PKGINST$/d" > /tmp/$$crontab) || exit 2 crontab $user < /tmp/$$crontab || exit 2 rm -f /tmp/$$crontab done exit |
41,1,21 * * * * /usr/lib/uucp/uudemon.hour > /dev/null 45 23 * * * ulimit 5000; /usr/bin/su uucp -c "/usr/lib/uucp/uudemon.cleanup" > /dev/null 2>&1 11,31,51 * * * * /usr/lib/uucp/uudemon.poll > /dev/null |
0 * * * 0-6 /usr/lib/sa/sa1 20,40 8-17 * * 1-5 /usr/lib/sa/sa1 5 18 * * 1-5 /usr/lib/sa/sa2 -s 8:00 -e 18:01 -i 1200 -A |
If editing of a group of files will increase total file size by more than 10K, supply a space file so the pkgadd command can allow for this increase. For more information on the space file, see Reserving Additional Space on a Target System.
This package installs a driver.
This case study demonstrates the following techniques:
Installing and loading a driver with a postinstall script
Unloading a driver with a preremove script
For more information on these scripts, see Writing Procedure Scripts.
Create a request script.
The request script determines where the administrator wants the driver objects to be installed, by questioning the administrator and assigning the answer to the $KERNDIR parameter.
The script ends with a routine to make the two parameters CLASSES and KERNDIR available to the installation environment and the postinstall script.
Create a postinstall script.
The postinstall script actually performs the driver installation. It is executed after the two files buffer and buffer.conf have been installed. The postinstall file shown for this example performs the following actions:
Uses the add_drv command to load the driver into the system.
Creates a link for the device using the installf command.
Finalizes the installation using the installf -f command.
Creates a preremove script.
The preremove script uses the rem_drv command to unload the driver from the system, and then removes the link /dev/buffer0.
PKG=bufdev NAME=Buffer Device CATEGORY=system BASEDIR=/ ARCH=INTEL VERSION=Software Issue #19 CLASSES=none |
To install a driver at the time of installation, you must include the object and configuration files for the driver in the prototype file.
In this example, the executable module for the driver is named buffer; the add_drv command operates on this file. The kernel uses the configuration file, buffer.conf, to help configure the driver.
i pkginfo i request i postinstall i preremove f none $KERNDIR/buffer 444 root root f none $KERNDIR/buffer.conf 444 root root |
Looking at the prototype file for this example, notice the following:
Since no special treatment is required for the package objects, you can put them into the standard none class. The CLASSES parameter is set to none in the pkginfo file.
The path names for buffer and buffer.conf begin with the variable $KERNDIR. This variable is set in the request script and allows the administrator to decide where the driver files should be installed. The default directory is /kernel/drv.
There is an entry for the postinstall script (the script that will perform the driver installation).
trap 'exit 3' 15 # determine where driver object should be placed; location # must be an absolute path name that is an existing directory KERNDIR=`ckpath -aoy -d /kernel/drv -p \ “Where do you want the driver object installed”` || exit $? # make parameters available to installation service, and # so to any other packaging scripts cat >$1 <<! CLASSES='$CLASSES' KERNDIR='$KERNDIR' ! exit 0 |
# KERNDIR parameter provided by `request' script err_code=1 # an error is considered fatal # Load the module into the system cd $KERNDIR add_drv -m '* 0666 root sys' buffer || exit $err_code # Create a /dev entry for the character node installf $PKGINST /dev/buffer0=/devices/eisa/buffer*:0 s installf -f $PKGINST |
err_code=1 # an error is considered fatal # Unload the driver rem_drv buffer || exit $err_code # remove /dev file removef $PKGINST /dev/buffer0 ; rm /dev/buffer0 removef -f $PKGINST |
This case study describes how to install a driver using the sed class and procedure scripts. It is also different from the previous case study (see Installing and Removing a Driver With Procedure Scripts) because this package is made up of both absolute and relocatable objects.
This case study demonstrates the following techniques:
Building a prototype file with both absolute and relocatable objects.
For more information on building a prototype file, see Creating a prototype File.
Using a postinstall script
For more information on this script, see Writing Procedure Scripts.
Using a preremove script
For more information on this script, see Writing Procedure Scripts.
Using a copyright file
For more information on this file, see Writing a Copyright Message.
Create a prototype file containing both absolute and relocatable package objects.
This is discussed in detail in The prototype File.
Add the sed class script to the prototype file.
The name of a script must be the name of the file that will be edited. In this case, the file to be edited is /etc/devlink.tab and so the sed script is named /etc/devlink.tab. There are no requirements for the mode, owner, and group of a sed script (represented in the sample prototype by question marks). The file type of the sed script must be e (indicating that it is editable).
Set the CLASSES parameter to include the sed class.
Create a sed class action script (/etc/devlink.tab).
Create a postinstall script.
The postinstall script needs to execute the add_drv command to add the device driver to the system.
Create a preremove script.
The preremove script needs to execute the rem_drv command to remove the device driver from the system, prior to the package being removed.
Create a copyright file.
A copyright file contains the ASCII text of a copyright message. The message shown in the sample file is displayed on the screen during package installation.
PKG=SUNWsst NAME=Simple SCSI Target Driver VERSION=1 CATEGORY=system ARCH=sparc VENDOR=Sun Microsystems BASEDIR=/opt CLASSES=sed |
For example, this case study uses the hierarchical layout of the package objects shown in the figure below.
The package objects are installed in the same places as they are in the pkg directory above. The driver modules (sst and sst.conf) are installed into /usr/kernel/drv and the include file is installed into /usr/include/sys/scsi/targets. The sst, sst.conf, and sst_def.h files are absolute objects. The test program, sstest.c, and its directory SUNWsst are relocatable; their installation location is set by the BASEDIR parameter.
The remaining components of the package (all the control files) go in the top directory of the package on the development machine, except the sed class script. This is called devlink.tab after the file it modifies, and goes into etc, the directory containing the real devlink.tab file.
From the pkg directory, run the pkgproto command as follows:
find usr SUNWsst -print | pkgproto > prototype |
The output from the above command looks like this:
d none usr 0775 pms mts d none usr/include 0775 pms mts d none usr/include/sys 0775 pms mts d none usr/include/sys/scsi 0775 pms mts d none usr/include/sys/scsi/targets 0775 pms mts f none usr/include/sys/scsi/targets/sst_def.h 0444 pms mts d none usr/kernel 0775 pms mts d none usr/kernel/drv 0775 pms mts f none usr/kernel/drv/sst 0664 pms mts f none usr/kernel/drv/sst.conf 0444 pms mts d none SUNWsst 0775 pms mts f none SUNWsst/sstest.c 0664 pms mts |
This prototype file is not yet complete. To complete this file, you need to make the following modifications:
Insert the entries for the control files (file type i), because they have a different format than the other package objects.
Remove entries for directories that already exist on the target system.
Change the access permission and ownership for each entry.
Prepend a slash to the absolute package objects.
This is the final prototype file:
i pkginfo i postinstall i preremove i copyright e sed /etc/devlink.tab ? ? ? f none /usr/include/sys/scsi/targets/sst_def.h 0644 bin bin f none /usr/kernel/drv/sst 0755 root sys f none /usr/kernel/drv/sst.conf 0644 root sys d none SUNWsst 0775 root sys f none SUNWsst/sstest.c 0664 root sys |
The questions marks in the entry for the sed script indicate that the access permissions and ownership of the existing file on the installation machine should not be changed.
In the driver example, a sed class script is used to add an entry for the driver to the file /etc/devlink.tab. This file is used by the devlinks command to create symbolic links from /dev into /devices. This is the sed script:
# sed class script to modify /etc/devlink.tab !install /name=sst;/d $i\ type=ddi_pseudo;name=sst;minor=character rsst\\A1 !remove /name=sst;/d |
The pkgrm command does not run the removal part of the script. You may need to add a line to the preremove script to run sed directly to remove the entry from the /etc/devlink.tab file.
In this example, all the script needs to do is run the add_drv command.
# Postinstallation script for SUNWsst # This does not apply to a client. if [$PKG_INSTALL_ROOT = "/" -o -z $PKG_INSTALL_ROOT]; then SAVEBASE=$BASEDIR BASEDIR=””; export BASEDIR /usr/sbin/add_drv sst STATUS=$? BASEDIR=$SAVEBASE; export BASEDIR if [ $STATUS -eq 0 ] then exit 20 else exit 2 fi else echo "This cannot be installed onto a client." exit 2 fi |
The add_drv command uses the BASEDIR parameter, so the script has to unset BASEDIR before running the command, and restore it afterwards.
One of the actions of the add_drv command is to run devlinks, which uses the entry placed in /etc/devlink.tab by the sed class script to create the /dev entries for the driver.
The exit code from the postinstall script is significant. The exit code 20 tells the pkgadd command to tell the user to reboot the system (necessary after installing a driver), and the exit code 2 tells the pkgadd command to tell the user that the installation partially failed.
In the case of this driver example, it removes the links in /dev and runs the rem_drv command on the driver.
# Pre removal script for the sst driver echo “Removing /dev entries” /usr/bin/rm -f /dev/rsst* echo “Deinstalling driver from the kernel” SAVEBASE=$BASEDIR BASEDIR=””; export BASEDIR /usr/sbin/rem_drv sst BASEDIR=$SAVEBASE; export BASEDIR exit |
The script removes the /dev entries itself; the /devices entries are removed by the rem_drv command.
This is a simple ASCII file containing the text of a copyright notice. The notice is displayed at the beginning of package installation exactly as it appears in the file.
Copyright (c) 1999 Drivers-R-Us, Inc. 10 Device Drive, Thebus, IO 80586 All rights reserved. This product and related documentation is protected by copyright and distributed under licenses restricting its use, copying, distribution and decompilation. No part of this product or related documentation may be reproduced in any form by any means without prior written authorization of Drivers-R-Us and its licensors, if any. |