Building a package : This should all be done as _root_ in order to get file permissions correct. Make a new directory with the name of the package you want to create, and change into this directory. mkdir DOCperl56; cd DOCperl56 Untar the base package archive. tar xf /tmp/pkg.tar Edit the files in the src directory. These are : copyright Whatever is relevant, or leave it blank. depend List any relevant dependencies. Instructions are in the file. pkginfo Info about the package you are creating : PKG Package name - eg, DOCperl56 NAME Shortish descriptive name of the package. eg, "DOC Perl 5.6.0" ARCH "sparc" VERSION Free-form version string. eg, "5.6.0" CATEGORY "system" for System packages, "application" for apps DESC Description of what the package contains BASEDIR Base directory for installation. Offset from the relocation path (see below) VENDOR Who made the package - eg, your name HOTLINE Support phone number - eg, your number EMAIL Support email - eg, your email pkgproto.tmpl Don't touch! Copy the files to be installed into the "reloc" directory. Files in here will be installed relative to the "BASEDIR" listed above. eg, if you create a reloc/perl5.6.0 directory with a BASEDIR of "/opt", all files in it will be installed into /opt/perl5.6.0 The permissions of the files in this directory are those that files will be installed with, so check they are as you expect. From the base directory of your package, run "/usr/ccs/bin/make". After a lot of rattling this should display "## Packaging complete." This will have created a directory under "pkgspool" with the name of your package - this is your package! As the directory-tree style package format is often difficult to work with, you might like to convert your package into a single file. To do this, change into the pkgspool directory and run pkgtrans . eg, pkgtrans . DOCperl56.pkg This will create a file called (in this case) "DOCperl56.pkg", which is your package! Relocating files Generally you'll want your files to be installed all under the one tree - eg, under /opt/productname. However, on occasion you'll want to install files elsewhere - say for config files in /etc/, etc. To do this, you need to do a few things... Create another directory (or directories) under reloc to store these files in. eg, if you want to put some files in /etc/, then create reloc/etc/ Normally when you run a "make" it will run both a "make pkgproto" and a "make spoolpkg". In this case you'll need to run these two individually, and make some changes in between. So, run the "make pkgproto" - this will create (or update) the src/pkgproto file, including putting in (incorrect) entries for your non-relocatable files. eg, if you'd created a file reloc/etc/myapp.conf then the pkgproto file would have put in two entries : d none etc 0755 root other f none etc/myapp.conf 0644 root other The first of these is saying to create the "etc" directory. Obviously this directory will already exist, so you can delete this line (some people will say you should leave this line. My preference is to remove it for directories you know will exist - such as /etc, but to leave it there for directories where you can't be certain - such as /usr/local) The second is trying to install /etc/myapp.conf, but by default will install it under your normal relocation tree. In order to tell it to install it under the root tree, we need to change file line to : f none /etc/myapp.conf=etc/myapp.conf 0644 root other ie, we've put "/etc/myapp.conf=" before what it already had, which will cause it to install the file in that location. Once you've made this change, you can create the package with "make spoolpkg". Keep in mind that if you re-run "make pkgproto" (or even just "make") will will remove any changes you've made to the pkgproto file!! Pre/Post Install/Remove scripts Packages can be setup to automatically run scripts before or after they are installed or removed. For example, you might want to add something to /etc/inetd.conf when a package is installed, and remove it when the package is removed. In order to do this, you use a script called "preinstall", "postinstall", "preremove" or "postremove", which live in the "src" directory of the package tree. As a rule, the "pre" scripts should be used for checking things are OK to continue, and the "post" scripts to actually make changes. So for our example above with a change to inetd.conf, this should be done in the postinstall/postremove scripts. If you wanted to check that the program you were removing wasn't still running, you'd do that in a preremove script, etc. The most important thing to remember about pre/post scripts are that they should be shell scripts (and need #!/bin/sh at the top), and that they must exit with a return code of 0 unless you want the package install/remove to fail (which you might want to do - for example if the program being removed was still in use). So, say that we wanted to add an entry to /etc/services, but only if it didn't already exist. We could put the following in the postinstall script : #!/bin/sh MYVERS=2.2.1a # Add SWAT port to /etc/services if it's not already there if [ -z "`egrep '^swat[ \\t]' $PKG_INSTALL_ROOT/etc/services`" ]; then echo "Adding SWAT config to /etc/services" echo "swat 901/tcp # Samba web GUI" >> $PKG_INSTALL_ROOT/etc/services fi Note the $PKG_INSTALL_ROOT variable. This is important as we might be installing the package using the -R option (such as during Jumpstart), in which case we want to edit the services file under that root directory, not under the root directory on the server which is running the pkgadd (eg, we dont want to run it under the Jumpstart miniroot). If the package is being installed locally on the current machine, PKG_INSTALL_ROOT will exist, but will be empty. If we also wanted to create a symlink pointing to out freshly installed package, we could use : # Add a symlink /opt/samba/prod only if it doesnt exist. if [ ! -r $CLIENT_BASEDIR/samba/prod ]; then echo Linking $CLIENT_BASEDIR/samba/prod to $CLIENT_BASEDIR/samba/$MYVERS ln -s $MYVERS $CLIENT_BASEDIR/samba/prod else echo $CLIENT_BASEDIR/samba/prod already exists - not creating link echo 'Note that SWAT may not be pointing to this version of Samba!' fi In this case we've use $CLIENT_BASEDIR for the offset to the directory our package was installed in. This directory relates to the "reloc" directory in the package, and includes the PKG_INSTALL_ROOT path from above. The best way to get a better handle on pre/post install/remove scripts is to look through some existing packages (eg, SUN/VRTS/etc ones) and see what they are doing. Request If you want to ask the user any questions whilst they are installing a package you need to use a "request" script, which also lives in the "src" directory. The script takes the form of : #!/bin/sh START_APACHE=`ckyorn -Q -p 'Do you want to put a start script for apache in /etc/rc3.d/ ?' | cut -c1 | tr "YN" "yn"` echo "START_APACHE=$START_APACHE" > $1 exit 0 Any variables you set in the $1 file (NOT variable you set in the shell script, you must write them out to the file passed in $1 in the format above) will be available to you in the pre/post install scripts. So for the above example, the following would be in the postinstall script : #!/bin/sh # Create a start script if requested if [ "$START_APACHE" = "y" ]; then ln -s ../init.d/myapache $PKG_INSTALL_ROOT/etc/rc3.d/S60myapache fi exit 0 In order to get your package to actually use these files you need to put an entry for them in your "pkgproto" and/or "pkgproto.tmplt" (remember that if you put it in pkgproto only it will be blown away if you re-run a "make pkgproto"). These entries are simply the letter "i" followed by the name of the file - one for each file. eg : i postinstall i preremove