Pages

Monday, December 12, 2011

Slackware package management

Introduction

The Slackware package management is one of the easiest to understand and to use. All packages are just ordinary compressed (gzip) tar files, since Slackware 13.37 the tar files are compressed with xz. All files in the package are already at their places except for the leading slash. Symbolic links will be created during package instalation. To look into a package you can use tar. First make sure you have access to the packages, eg. mount the CD/DVD iso image: 

# mkdir -p /mnt/loop
# mount -o loop,ro slackware-13.37-install-dvd.iso /mnt/loop/

In all coming examples I will use the mounted DVD iso so I won't show the two commands again. Now take a peak into a package:

# tar tfv /mnt/loop/slackware/y/bsd-games-2.13-i486-11.txz
...
drwxr-xr-x root/root         0 2010-05-15 20:10 usr/games/
-rwxr-xr-x root/root      4808 2010-05-15 20:10 usr/games/cfscores
-rwxr-xr-x root/root     27144 2010-05-15 20:10 usr/games/cribbage
...

The listing above shows the directory usr/games and the two binaries cfscores and cribbage. You could go into / and extract the tar file then the directory /usr/games would be created and the binaries under it. The disadvantage is that the package wouldn't show up in the package database. The package database is a single directory containing a text file (metadata) for each package with its content. The package database is under /var/log/packages:

# less /var/log/packages/bsd-games-2.13-i486-11
...
usr/games/
usr/games/cfscores
usr/games/cribbage
...

The package database is needed to remove a package again and just only the package and its content. So you don't have to keep track the content of your Slackware installation by yourself. When a package will be removed then the associated metadata file in the package database will be read, the content in it will be removed from your harddisk and the metadata file itself will be removed.
There are a few tools available in Slackware to install and remove a package:

installpkg: installes a package
removepkg: removes a package
explodepkg: extract a package
upgradepkg: upgrades a package
makepkg: creates a package
pkgtool: dialog managed frontend (not described here)

As you can see most command names are speaking for them self. The commands itself are located under /sbin/ and they are just ordinary Shell scripts:

# file /sbin/*pkg*
/sbin/explodepkg: POSIX shell script, ASCII text executable
/sbin/installpkg: POSIX shell script, ASCII text executable
/sbin/makepkg:    POSIX shell script, ASCII text executable
/sbin/pkgtool:    POSIX shell script, ASCII text executable
/sbin/removepkg:  POSIX shell script, ASCII text executable
/sbin/upgradepkg: POSIX shell script, ASCII text executable

Installing a package

Installing a package with installpkg isn't too hard, just execute installpkg with the desired package:

# installpkg /mnt/loop/slackware/y/bsd-games-2.13-i486-11.txz
Verifying package bsd-games-2.13-i486-11.txz.
Installing package bsd-games-2.13-i486-11.txz [OPT]:
PACKAGE DESCRIPTION:
# bsd-games (Classic BSD text games collection)
#
# Games that go in /usr/games:  adventure arithmetic atc backgammon
#   banner battlestar bcd caesar canfield cfscores countmail cribbage
#   factor fish fortune gomoku hangman hunt mille monop morse number
#   phantasia pig pom ppt primes quiz rain random robots rot13 sail
#   snake snscore teachgammon trek wargames worm worms wump
#
# Adds a call to 'fortune' to /etc/profile.d/ so that users will get a
# fortune message when they log in.
#
Executing install script for bsd-games-2.13-i486-11.txz.
Package bsd-games-2.13-i486-11.txz installed.

If you were unsure if the package could overwrite already existing files then use the --warn option:

# installpkg --warn /mnt/loop/slackware/y/bsd-games-2.13-i486-11.txz
...
/usr/games/cfscores
/usr/games/cribbage
...

The --warn option will check if the file that should be installed is already available on your harddisk. It will give a list of all already available or installed files. The package will not be installed. To install a package in a alternate root directory use the --root option. The default root is / of course. First create an alternate root directory and then install the package:

# mkdir -p /a
# installpkg --root /a /mnt/loop/slackware/y/bsd-games-2.13-i486-11.txz
Verifying package bsd-games-2.13-i486-11.txz.
Installing package bsd-games-2.13-i486-11.txz [OPT]:
PACKAGE DESCRIPTION:
# bsd-games (Classic BSD text games collection)
#
# Games that go in /usr/games:  adventure arithmetic atc backgammon
#   banner battlestar bcd caesar canfield cfscores countmail cribbage
#   factor fish fortune gomoku hangman hunt mille monop morse number
#   phantasia pig pom ppt primes quiz rain random robots rot13 sail
#   snake snscore teachgammon trek wargames worm worms wump
#
# Adds a call to 'fortune' to /etc/profile.d/ so that users will get a
# fortune message when they log in.
#
Executing install script for bsd-games-2.13-i486-11.txz.
Package bsd-games-2.13-i486-11.txz installed.

Now take a look your alternate root directory:

# ls /a
etc/  usr/  var/

When you take a closer look into /a/var then you will figure out that the package database will also be created in the alternate root destination:

# ls /a/var/log/packages/
bsd-games-2.13-i486-11

The --warn and --root options can not be combined. If you remove the package bsd-games from the original root / but keep in /a installed then the --warn option won't work:

# installpkg --warn --root /a /mnt/loop/slackware/y/bsd-games-2.13-i486-11.txz

Nothing will happen, no listing will be produced.
When installing Slackware from CD/DVD you will see these fancy boxes during package installation. These can be shown with the --infobox option:

# installpkg --infobox /mnt/loop/slackware/y/bsd-games-2.13-i486-11.txz



With the --menu option you will get a fancy dialog box that will ask you for confirmation if the package should be really installed:

# installpkg --menu /mnt/loop/slackware/y/bsd-games-2.13-i486-11.txz



Instead of growing the output you can reduce the output with the --terse option:

# installpkg --terse /mnt/loop/slackware/y/bsd-games-2.13-i486-11.txz
bsd-games-2.13-i486-11: Classic BSD text games collection                [5.3M]

Inside Slackware package managment there is something known as priorities. By setting priorities you can influence if a package will be installed or not. There are 4 priorities:

ADD: install this package
REC: installation of this package is recommended
OPT: installation of this package is optional
SKP: don't install this package

The priorities are set in a specific tagfile. Each software collection on the DVD has a specific tagfile:

# cat /mnt/loop/slackware/y/tagfile
bsd-games:OPT

Of course the bsd-games are only optional, but now force to install them. To do so create a new tagfile in /root:

# vi /root/tagfile
bsd-games:ADD

Now install the bsd-games package from the DVD again with the --menu and --tagfile option:

# installpkg --menu --tagfile /root/tagfile /mnt/loop/slackware/y/bsd-games-2.13-i486-11.txz

Instead of asking you if the package should be installed it will be installed directly (normally with the --menu option you will get asked to install the package or not). Now change the priority to SKP:

# vi /root/tagfile
bsd-games:SKP

And install the package again:

# installpkg --menu --tagfile /root/tagfile /mnt/loop/slackware/y/bsd-games-2.13-i486-11.txz

As you can see the package will not be installed, you will get back to your command line immediatly. If you change the priority inside the tagfile to REC or OPT then you will get asked again if you want to install the package. So where is the difference? Try it and take a look at the title of the menu, when you change the priority to REC the title will show up like this:

Package Name: bsd-games-2.13-i486-11 [REC]

Notice the [REC] at the end of the title. The same if you change the priority to OPT:

Package Name: bsd-games-2.13-i486-11 [OPT]

The title will change to [OPT]. This is informational for the user so he can get a direction if the package should be installed or not and if he don't know the package. The ADD priority can be overridden by using the --ask option. First change the priority to ADD inside your tagfile:

# vi /root/tagfile
bsd-games:ADD

Now install the package with the --menu, --tagfail and --ask option:

# installpkg --menu --tagfile /root/tagfile --ask /mnt/loop/slackware/y/bsd-games-2.13-i486-11.txz

Regardless that the ADD priority is set, you will get asked to install the package. The title has changed again:

Package Name: bsd-games-2.13-i486-11 [ADD]

While installing a package you can create the md5sum of the package. This is done with the --md5sum option:

# installpkg --md5sum /mnt/loop/slackware/y/bsd-games-2.13-i486-11.txz

Now take a look at the metadata file for the package:

# less /var/log/packages/bsd-games-2.13-i486-11
PACKAGE NAME:     bsd-games-2.13-i486-11
COMPRESSED PACKAGE SIZE:     1.7M
UNCOMPRESSED PACKAGE SIZE:     5.3M
PACKAGE LOCATION: /mnt/loop/slackware/y/bsd-games-2.13-i486-11.txz
PACKAGE MD5SUM: eb5f8e2a42a35021bab92b6142ca8058
PACKAGE DESCRIPTION:
...

Note the PACKAGE MD5SUM line between PACKAGE LOCATION and PACKAGE DESCRIPTION. If you install a package without the --md5sum then the PACKAGE MD5SUMM line will not appear:

# installpkg /mnt/loop/slackware/y/bsd-games-2.13-i486-11.txz
# less /var/log/packages/bsd-games-2.13-i486-11
PACKAGE NAME:     bsd-games-2.13-i486-11
COMPRESSED PACKAGE SIZE:     1.7M
UNCOMPRESSED PACKAGE SIZE:     5.3M
PACKAGE LOCATION: /mnt/loop/slackware/y/bsd-games-2.13-i486-11.txz
PACKAGE DESCRIPTION:
...

Keep in mind that generating the md5sum during installation will slow down the installation process. To get a quick help about all options use execute installpkg without any option:

# installpkg
...
options:      --warn (warn if files will be overwritten, but do not install)
...

Or just use the man page:

# man installpkg
...

Removing a package

Removing a package is much easier. The easiest way to remove a package is this:

# removepkg bsd-games

Removing package /var/log/packages/bsd-games-2.13-i486-11...
Removing files:
...
  --> Deleting /usr/games/adventure
  --> Deleting /usr/games/arithmetic
...

As package name you can use various names like these:

bsd-games
bsd-games-2.13
bsd-games-2.13-i486-11
/var/log/packages/bsd-games-2.13-i486-11
...

If a file is owned by another package it will not be deleted. Empty directories will be deleted. Non empty directories will not be deleted. Just like installpkg removepkg has a -warn option:

# removepkg -warn bsd-games
Only warning... not actually removing any files.
Here's what would be removed (and left behind) if you
removed the package(s):
...
  --> /usr/games/adventure would be deleted
  --> /usr/games/arithmetic would be deleted
...

The package will not be deleted, the -warn option shows you only the files and directories that would be deleted. Before ultimatly remove a package you may want to to keep the content but not in the package specific folder(s). Then use the -preserve option. The -preserve option will create the entire package structure under /var/log/setup/tmp/preserved_packages:

# removepkg -preserve bsd-games
...
# ls /var/log/setup/tmp/preserved_packages/bsd-games-2.13-i486-11/
etc/  install/  usr/  var/

Under /var/log/setup/tmp/preserved_packages a new directory will be created with the name of the package, in this case bsd-games-2.13-i486-11. Under this directory you can find the complete content of the original package. The package is removed from the original folders on your harddisk and the metadata under /var/log/packages too. But you can still have acces to the files under /var/log/setup/tmp/preserved_packages. To create a copy of the package but not to remove the package use the -copy option:

# removepkg -copy bsd-games

With the -copy option the original package is untouched but was copied to /var/log/setup/tmp/preserved_packages:

# ls /var/log/setup/tmp/preserved_packages/bsd-games-2.13-i486-11/usr/games/a*
/var/log/setup/tmp/preserved_packages/bsd-games-2.13-i486-11/usr/games/adventure*
/var/log/setup/tmp/preserved_packages/bsd-games-2.13-i486-11/usr/games/atc*
/var/log/setup/tmp/preserved_packages/bsd-games-2.13-i486-11/usr/games/arithmetic*
# ls /usr/games/a*
/usr/games/adventure*
/usr/games/arithmetic*
/usr/games/atc*

To keep track of what was deleted etc use the -keep option. During package removal sever lists will be created for the file that has to be deleted etc. These files are dynamically generated under /var/log/setup/tmp:

# removepkg -keep bsd-games
...
# ls /var/log/setup/tmp/
...
delete_list10187

Eg. the file delete_list10187 contains a list of files which were deleted:

# less /var/log/setup/tmp/delete_list10187
...
usr/games/
usr/games/adventure
usr/games/arithmetic
...

Just like installpkg you can remove packages from a different root directory. Inconsequential like all options in removepkg (note that all options in installpkg begin with a double hyphen, in removepkg they begin with a single hyphen) there is no -root option. Instead you have to define the ROOT variable:

# ROOT=/a removepkg bsd-games

Removing package /a/var/log/packages/bsd-games-2.13-i486-11...
Removing files:
...
  --> Deleting /a/usr/games/adventure
  --> Deleting /a/usr/games/arithmetic
...

Now /a will be used as your root directory and the package will be removed. When executing removepkg without any option or package you well get a neat help:



# removepkg
Usage: removepkg [-copy] [-keep] [-preserve] [-warn] packagename ...

Or just use the man page:

man removepkg
...

Extracting a package

Before you install a package you may want to extract it in a safe place. This is what explodepkg is about. explodepkg has no options or anything, it will just extract the package at your current location. For testing purpose create a new folder and change into it:

# mkdir -p /root/txz
# cd /root/txz

Now run explodepkg with a package from the mounted DVD:

# explodepkg /mnt/loop/slackware/y/bsd-games-2.13-i486-11.txz
Exploding package /mnt/loop/slackware/y/bsd-games-2.13-i486-11.txz in current directory:
...
usr/games/
usr/games/cfscores
usr/games/cribbage
...
An installation script was detected in ./install/doinst.sh, but
was not executed.

Take a look at your current location:

# ls
etc/  install/  usr/  var/

The complete package was extracted which would be normally installed under /.

Upgrading a package

To upgrade a package use upgradepkg. As an example make sure that the package bsd-games-2.13-i486-11.txz is installed:

# installpkg /mnt/loop/slackware/y/bsd-games-2.13-i486-11.txz
...

Then create a new directory and copy the bsd-games package with a higher version to the directory:

# mkdir -p /root/txz
# cp /mnt/loop/slackware/y/bsd-games-2.13-i486-11.txz /root/txz/bsd-games-2.13-i486-12.txz

Note the 11 and the 12 at the end of both package names. This will be the initial situation for the next few examples - bsd-games-2.13-i486-11.txz installed and bsd-games-2.13-i486-12.txz ready on your harddisk. Now run a simple upgrade:

# cd /root/txz
# upgradepkg bsd-games-2.13-i486-12.txz

+==============================================================================
| Upgrading bsd-games-2.13-i486-11 package using ./bsd-games-2.13-i486-12.txz
+==============================================================================

Pre-installing package bsd-games-2.13-i486-12...

Removing package /var/log/packages/bsd-games-2.13-i486-11-upgraded-2011-12-12,17:51:53...

Verifying package bsd-games-2.13-i486-12.txz.
Installing package bsd-games-2.13-i486-12.txz:
PACKAGE DESCRIPTION:
# bsd-games (Classic BSD text games collection)
#
# Games that go in /usr/games:  adventure arithmetic atc backgammon
#   banner battlestar bcd caesar canfield cfscores countmail cribbage
#   factor fish fortune gomoku hangman hunt mille monop morse number
#   phantasia pig pom ppt primes quiz rain random robots rot13 sail
#   snake snscore teachgammon trek wargames worm worms wump
#
# Adds a call to 'fortune' to /etc/profile.d/ so that users will get a
# fortune message when they log in.
#
Executing install script for bsd-games-2.13-i486-12.txz.
Package bsd-games-2.13-i486-12.txz installed.

Package bsd-games-2.13-i486-11 upgraded with new package ./bsd-games-2.13-i486-12.txz.

First all files and directories will be installed. Then all files and directories will be deleted which were in the old package but aren't in the new package anymore. If directories will be deleted depends if they were empty etc (see removepkg). In this case no files were deleted because there were no changes. To perform a dry run to see what would happen use the --dry-run option (first create the initial situation again):

# upgradepkg --dry-run bsd-games-2.13-i486-12.txz
bsd-games-2.13-i486-12 would upgrade: bsd-games-2.13-i486-11

Nothing more to show because the packages are identical. If you want to upgrade a package that is not installed so for then use the --install-new option. This will install a package instead of upgrading it. First remove any installed bsd-games package:

# removepkg /var/log/packages/bsd-games*
...

Then install the new package using upgradepkg with the --install-new option:

# upgradepkg --install-new /root/txz/bsd-games-2.13-i486-12.txz

+==============================================================================
| Installing new package /root/txz/bsd-games-2.13-i486-12.txz
+==============================================================================

Verifying package bsd-games-2.13-i486-12.txz.
Installing package bsd-games-2.13-i486-12.txz:
...

If you try to upgrade a package which is already upgrade then you will get an error:

# upgradepkg /root/txz/bsd-games-2.13-i486-12.txz

+==============================================================================
| Skipping package bsd-games-2.13-i486-12 (already installed)
+==============================================================================

You can force upgrading with the --reinstall option:

# upgradepkg --reinstall /root/txz/bsd-games-2.13-i486-12.txz

+==============================================================================
| Upgrading bsd-games-2.13-i486-12 package using /root/txz/bsd-games-2.13-i486-12.txz
+==============================================================================

Pre-installing package bsd-games-2.13-i486-12...

Removing package /var/log/packages/bsd-games-2.13-i486-12-upgraded-2011-12-12,18:06:07...

Verifying package bsd-games-2.13-i486-12.txz.
Installing package bsd-games-2.13-i486-12.txz:
...

Also upgradepkg has a --verbose option for more detailed output but it is not shown here, you can test it by your self.

To see a little help for upgradepkg run upgradepkg without any option or package name:

# upgradepkg

Usage: upgradepkg newpackage [newpackage2 ... ]
       upgradepkg oldpackage%newpackage [oldpackage2%newpackage2 ... ]
...

Or take a look at the man page:

# man upgradepkg
...

Creating a package: Basic

Creating a Slackware isn't a hard job. In contrast to rpm or deb it is very easy. I will show you how to compile a small (but very cool) piece of software, how to create a appropiate directory structure and finally how to create a Slackware package that you can install and remove with the default tools installpkg and removepkg. To show you how to create a Slackware package I will use Lua but you can use what ever you want. Lua is a very small and easy to compile piece of software and should work out of the box. First get the software:

# cd /usr/src
# wget http://www.lua.org/ftp/lua-5.1.4.tar.gz
...

Then extract the source and change into the new directory:

# tar xf lua-5.1.4.tar.gz
# cd lua-5.1.4

Now build the software using make but don't install it:

# make linux
...

In the src directory you have a couple of files which are more less important: two binaries (lua and luac), headers (lua.h, luaconf.h, lualib.h and lauxlib.h), a library (liblua.a) and two man pages for lua and luac (lua.1 and luac.1). The next thing you have to do is to create a directory structure that fits your system. Binaries are stored under /usr/bin, headers under /usr/include, libraries under /usr/lib and man pages under /usr/man:

# mkdir -p /usr/src/build/usr/bin
# mkdir -p /usr/src/build/usr/include
# mkdir -p /usr/src/build/usr/lib
# mkdir -p /usr/src/build/usr/man/man1
# mkdir -p /usr/src/build/install

The above commands will create a reduced layout of your systems directories under /usr/src/build. The install directory will be used later. Now copy all files to the right directory. Binaries into /usr/src/build/usr/bin, headers into /usr/src/build/usr/include and so on:

# cd /usr/src/lua-5.1.4
# cp src/lua src/luac /usr/src/build/usr/bin
# cp src/lua.h src/luaconf.h src/lualib.h src/lauxlib.h /usr/src/build/usr/include
# cp src/liblua.a /usr/src/build/usr/lib
# cp doc/lua.1 doc/luac.1 /usr/src/build/usr/man/man1

Now check that everything is at it's desired directory (tree is still one of my favorite tools):

# tree /usr/src/build
/usr/src/build
|-- install
`-- usr
    |-- bin
    |   |-- lua
    |   `-- luac
    |-- include
    |   |-- lauxlib.h
    |   |-- lua.h
    |   |-- luaconf.h
    |   `-- lualib.h
    |-- lib
    |   `-- liblua.a
    `-- man
        `-- man1
            |-- lua.1
            `-- luac.1

Now go into the unused install directory. Next you have to create a so called slack-desc file which holds the description while installing a Slackware package. It could look like this (the original file was taken from the ppp package and all texts are from http://www.lua.org/about.html):

# cd /usr/src/build/install
# vi slack-desc
# HOW TO EDIT THIS FILE:
# The "handy ruler" below makes it easier to edit a package description.  Line
# up the first '|' above the ':' following the base package name, and the '|'
# on the right side marks the last column you can put a character in.  You must
# make exactly 11 lines for the formatting to be correct.  It's also
# customary to leave one space after the ':'.

   |-----handy-ruler------------------------------------------------------|
lua: lua (a powerful, fast, lightweight, embeddable scripting language)
lua:
lua: Lua combines simple procedural syntax with powerful data description
lua: constructs based on associative arrays and extensible semantics. Lua
lua: is dynamically typed, runs by interpreting bytecode for a
lua: register-based virtual machine, and has automatic memory management
lua: with incremental garbage collection, making it ideal for
lua: configuration, scripting, and rapid prototyping.
lua:
lua:
lua:

Save the file and leave your editor. Finally create the package:

# cd /usr/src/build
# makepkg -l y -c n /tmp/lua-5.1.4-i486-1.txz

That's it. You can install the package now:

# installpkg /tmp/lua-5.1.4-i486-1.txz
Verifying package lua-5.1.4-i486-1.txz.
Installing package lua-5.1.4-i486-1.txz:
PACKAGE DESCRIPTION:
# lua (a powerful, fast, lightweight, embeddable scripting language)
#
# Lua combines simple procedural syntax with powerful data description
# constructs based on associative arrays and extensible semantics. Lua
# is dynamically typed, runs by interpreting bytecode for a
# register-based virtual machine, and has automatic memory management
# with incremental garbage collection, making it ideal for
# configuration, scripting, and rapid prototyping.
#
Package lua-5.1.4-i486-1.txz installed.

For testing purpose run lua:

# lua
lua
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> print "Hello World"
Hello World
> ^D

And remove the package (if necessary):

# removepkg lua

Removing package /var/log/packages/lua-5.1.4-i486-1...
Removing files:
  --> Deleting /usr/bin/lua
  --> Deleting /usr/bin/luac
...

As you can see creating packages for Slackware is real easy.

Creating a package: Advanced

To build a little more advanced package download and compile dovecot first:

# cd /usr/src/
# wget http://www.dovecot.org/releases/2.0/dovecot-2.0.16.tar.gz

Then untar the source and change into the new directory:

# gzip -dc dovecot-2.0.16.tar.gz | tar xf -
# cd dovecot-2.0.16

Now run the configure script and compile the sources:

# ./configure --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64
...
# make
...

Next create a new directory as a placeholder for your new binaries:

# mkdir -p /usr/src/build

Then install the binaries into the build directory:

# make install DESTDIR=/usr/src/build
...

Under /usr/src/build you should have now the complete software for dovecot. The structure of the directories are nearly the same as under your root directory /:

# ls /usr/src/build
etc/  usr/

Now go into the build directory and copy the sample configuration:

# cd /usr/src/build
# cp -r usr/share/doc/dovecot/example-config/* etc/dovecot/

And move dovecot.conf to dovecot.conf.new (I will explain later why):

# mv etc/dovecot/dovecot.conf etc/dovecot/dovecot.conf.new

Under etc/ you will store the configuration and under usr/ are directories for the binaries (bin/ and sbin/) etc. Now change into the build/ directory and create a install/ directory for the Slackware package information:

# cd /usr/src/build
# mkdir install && cd install

Inside the install directory create the slack-desc first:

# vi slack-desc
# HOW TO EDIT THIS FILE:
# The "handy ruler" below makes it easier to edit a package description.  Line
# up the first '|' above the ':' following the base package name, and the '|'
# on the right side marks the last column you can put a character in.  You must
# make exactly 11 lines for the formatting to be correct.  It's also
# customary to leave one space after the ':'.

       |-----handy-ruler------------------------------------------------------|
dovecot: dovecot
dovecot:
dovecot: add any informational description here
dovecot:
dovecot:
dovecot:
dovecot:
dovecot:
dovecot:
dovecot:
dovecot:

Next create the doinst.sh script inside the install directory (the original script was taken from another package):

# vi doinst.sh
#!/bin/sh
config() {
  NEW="$1"
  OLD="`dirname $NEW`/`basename $NEW .new`"
  # If there's no config file by that name, mv it over:
  if [ ! -r $OLD ]; then
    mv $NEW $OLD
  elif [ "`cat $OLD | md5sum`" = "`cat $NEW | md5sum`" ]; then # toss the redundant copy
    rm $NEW
  fi
  # Otherwise, we leave the .new copy for the admin to consider...
}
config etc/dovecot/dovecot.conf.new

While installing a slackware package the doinst.sh script will be executed. In this case the config function tries to figure out if there is already a /etc/dovecot/dovecot.conf configuration file available. When it can find an already existing configuration file, then the new one will be created normally with .new. If no configuration file exist, then it will be moved to dovecot.conf. For each file you want to protect this way you have to add a specific config line inside the doinst.sh script and rename it before you create the package. Finally create the package:

# cd /usr/src/build
# makepkg -l y -c n /tmp/dovecot-2.0.16-i486-1.txz

Now do some testing. First create an alternate root directory where you can test install the new dovecot package:

# mkdir /a

Then create a sample dovecot configuration:

# mkdir -p /a/etc/dovecot
# echo "Sample configuration" > /a/etc/dovecot/dovecot.conf

Check that everything is alright:

# tree /a/
/a/
`-- etc
    `-- dovecot
        `-- dovecot.conf

Now install the new dovecot package with the alternate root path:

# installpkg --root /a /tmp/dovecot-2.0.16-i486-1.txz
...

In this case the original doevcot.conf was untouched and the new configuration file is kept under dovecot.conf.new:

# ls /a/etc/dovecot/dovecot.conf*
/a/etc/dovecot/dovecot.conf
/a/etc/dovecot/dovecot.conf.new

Now remove everything under your alternate root directory:

# rm -rf /a/*

And install the package again:

# installpkg --root /a /tmp/dovecot-2.0.16-i486-1.txz
...

Check the alternate etc directory:

# ls /a/etc/dovecot/dovecot.conf*
/a/etc/dovecot/dovecot.conf

It contains only one dovecot.conf file, the dovecot.conf.new from inside the package was moved to dovecot.conf.