#!/bin/sh
# $Id: clamav.SlackBuild,v 1.60 2018/10/28 13:40:59 root Exp root $

# Copyright 2006-2018  Eric Hameleers, Eindhoven, NL
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
#  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
#  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
#  EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
#  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
#  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
#  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
#  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# -----------------------------------------------------------------------------
# Slackware SlackBuild script 
# ===========================
# By:        Eric Hameleers
# For:       clamav
# URL:       http://clamav.net/
# Needs:     
# Changelog:
# 0.80-1:    30/nov/2004 by Eric Hameleers
#            * Initial build.
# 0.80-2:   02/dec/2004 by Eric Hameleers
#            * Fix permissions on "/var/run/clamav" directory
# 0.81-1:   02/feb/2005 by Eric Hameleers
#            * Rebuilt for new version
# 0.83-1:   15/feb/2005 by Eric Hameleers
#            * Rebuilt for new version
# 0.83-2:   15/feb/2005 by Eric Hameleers
#            * Patch freshclam.conf and clamav.conf for better package
#              defaults. Make rc.clamav executable. Add option to rc.clamav
#              to disable milter support.
# 0.84-1:   30/apr/2005 by Eric Hameleers
#            * Rebuilt for new version
# 0.85-1:   14/may/2005 by Eric Hameleers
#            * Add '--enable-id-check' to configure command.
# 0.85.1-1:  21/may/2005 by Eric Hameleers
#            * Rebuilt for the new release.
# 0.86.1-1:  27/jun/2005 by Eric Hameleers
#            * Rebuilt for the new release.
# 0.86.2-1:  27/jul/2005 by Eric Hameleers
#            * Rebuilt for the new release.
# 0.87-1:    16/sep/2005 by Eric Hameleers
#            * Rebuilt for the new release. Removed 'contrib' from the doc
#            directory as none of it makes any sense.
# 0.87.1-1:  08/nov/2005 by Eric Hameleers
#            * Rebuilt for the new release.
# 0.88-1:    10/jan/2006 by Eric Hameleers
#            * Rebuilt for the new release.
# 0.88.1-1:  04/apr/2006 by Eric Hameleers
#            * Rebuilt for the new release.
# 0.88.2-1:  29/may/2006 by Eric Hameleers
#            * Rebuilt for the new release.
# 0.88.2-2:  15/jun/2006 by Eric Hameleers
#            * Fixed permission for directory '/var/run/clamav' again
#              (it is now 771 so that the AllowSupplementaryGroups works)
# 0.88.3-1:  22/jul/2006 by Eric Hameleers
#            * Rebuilt for the new release. Since 'configure' now uses the new
#              DATAROOTDIR, explicitly configure the mandir.
# 0.88.4-1:  10/aug/2006 by Eric Hameleers
#            * Rebuilt for the new release.
# 0.88.5-1:  18/oct/2006 by Eric Hameleers
#            * Rebuilt for the new release.
# 0.88.6-1:  07/nov/2006 by Eric Hameleers
#            * New release. Patched the default value of 'DatabaseDirectory' in
#              the /etc/*.conf files to be '/usr/share/clamav', to reflect what
#              this package uses instead of '/var/lib/clamav'. Also correctly
#              creates clamav user/group and assigns ownership if the target
#              root is not that of the running machine (using chroot).
# 0.88.7-1:  13/dec/2006 by Eric Hameleers
#            * New release.
# 0.90-1:    14/feb/2007 by Eric Hameleers
#            * New release. Since clamav's .conf files changed quite a bit,
#              I had to re-do the .patch files.
# 0.90.1-1:  05/mar/2007 by Eric Hameleers
#            * New release.
# 0.90.2-1:  16/apr/2007 by Eric Hameleers
#            * New release.
# 0.90.3-1:  02/jun/2007 by Eric Hameleers
#            * New release.
# 0.91.1-1:  23/jul/2007 by Eric Hameleers
#            * New release.
# 0.91.2-1:  22/aug/2007 by Eric Hameleers
#            * New release.
# 0.92-1:    22/dec/2007 by Eric Hameleers
#            * New release.
# 0.92.1-1:  13/feb/2008 by Eric Hameleers
#            * New release. And the day I buried my dad.
# 0.93-1:    15/apr/2008 by Eric Hameleers
#            * New release. Note that if you build this release while you
#              still have a previous clamav package installed, the binaries
#              will link dynamically to the present libclamunrar_iface.so.3
#              which will be gone after you run upgradepkg. This results in
#              runtime errors. Remedy: build this release after removing an
#              existing clamav from your disk.
# 0.93.1-1:  10/jun/2008 by Eric Hameleers
#            * New release.
# 0.93.3-1:  09/jul/2008 by Eric Hameleers
#            * New release.
# 0.94-1:    04/sep/2008 by Eric Hameleers
#            * New release. Add "--disable-check" to 'configure', to avoid
#              a (harmless) warning about missing 'check'.
# 0.94.1-1:  10/nov/2008 by Eric Hameleers
#            * New release.
# 0.94.2-1:  28/nov/2008 by Eric Hameleers
#            * New release.
# 0.95-1:    24/mar/2009 by Eric Hameleers
#            * New release.
# 0.95.1-1:  17/apr/2009 by Eric Hameleers
#            * New release.
# 0.95.2-1:  11/jun/2009 by Eric Hameleers
#            * New release.
# 0.95.3-1:  30/oct/2009 by Eric Hameleers
#            * New release.
# 0.96-1:    02/apr/2010 by Eric Hameleers
#            * New release.
# 0.96.1-1:  27/may/2010 by Eric Hameleers
#            * New release plugs a critical hole.
# 0.96.3-1:  21/sep/2010 by Eric Hameleers
#            * New release.
# 0.96.4-1:  26/oct/2010 by Eric Hameleers
#            * New release.
# 0.96.5-1:  02/dec/2010 by Eric Hameleers
#            * New release.
# 0.97-1:    11/feb/2011 by Eric Hameleers
#            * New release.
# 0.97.1-1:  11/jun/2011 by Eric Hameleers
#            * New release.
# 0.97.2-1:  19/aug/2011 by Eric Hameleers
#            * New release.
# 0.97.3-1:  24/nov/2011 by Eric Hameleers
#            * New release.
# 0.97.4-1:  21/mar/2012 by Eric Hameleers
#            * New release.
# 0.97.5-1:  17/jun/2012 by Eric Hameleers
#            * New release.
# 0.98-1:    20/Sep/2013 by Eric Hameleers
#            * Update.
# 0.98.7-1:  31/may/2015 by Eric Hameleers
#            * Update.
# 0.99.2-1:  05/aug/2017 by Eric Hameleers
#            * Update. Adopted the enhancements from the SBo copy.
#              Enable milter.
# 0.100.2-1: 28/oct/2018 by Eric Hameleers
#            * Update. The 'AllowSupplementaryGroups' keyword is deprecated
#              since 0.100 because it is now used by default.
# 
# Run 'sh clamav.SlackBuild' to build a Slackware package.
# The package (.tgz) plus descriptive .txt file are created in /tmp .
# Install using 'installpkg'. 
#
# -----------------------------------------------------------------------------

# Set initial variables:

PRGNAM=clamav
VERSION=${VERSION:-"0.100.2"}
BUILD=${BUILD:-1}
TAG=${TAG:-alien}

# The 2-letter ISO code of the country that hosts your clamav mirror:
ISOCC=${ISOCC:-"nl"}

# Read "README.slackware" for compatibility with amavisd-new
CLAMUSR=clamav
CLAMGRP=clamav

# Where do we look for sources?
SRCDIR=$(cd $(dirname $0); pwd)

# Place to build (TMP) package (PKG) and output (OUTPUT) the program:
TMP=${TMP:-"/tmp/build"}
PKG=$TMP/package-$PRGNAM
OUTPUT=${OUTPUT:-"/tmp"}

SOURCE="$SRCDIR/${PRGNAM}-${VERSION}.tar.gz"
SRCURL="http://www.clamav.net/downloads/production/${PRGNAM}-${VERSION}.tar.gz"

##
## --- with a little luck, you won't have to edit below this point --- ##
##

# Automatically determine the architecture we're building on:
MARCH=$( uname -m )
if [ -z "$ARCH" ]; then
  case "$MARCH" in
    i?86)    export ARCH=i586 ;;
    armv7hl) export ARCH=$MARCH ;;
    arm*)    export ARCH=arm ;;
    # Unless $ARCH is already set, use uname -m for all other archs:
    *)       export ARCH=$MARCH ;;
  esac
fi

case "$ARCH" in
  i?86)      SLKCFLAGS="-O2 -march=${ARCH} -mtune=i686"
             SLKLDFLAGS=""; LIBDIRSUFFIX=""
             ;;
  x86_64)    SLKCFLAGS="-O2 -fPIC"
             SLKLDFLAGS="-L/usr/lib64"; LIBDIRSUFFIX="64"
             ;;
  armv7hl)   SLKCFLAGS="-O2 -march=armv7-a -mfpu=vfpv3-d16"
             SLKLDFLAGS=""; LIBDIRSUFFIX=""
             ;;
  *)         SLKCFLAGS="-O2"
             SLKLDFLAGS=""; LIBDIRSUFFIX=""
             ;;
esac

case "$ARCH" in
  arm*)      TARGET=$ARCH-slackware-linux-gnueabi ;;
  *)         TARGET=$ARCH-slackware-linux ;;
esac

# Exit the script on errors:
set -e
trap 'echo "$0 FAILED at line $LINENO!" | tee $OUTPUT/error-${PRGNAM}.log' ERR
# Catch unitialized variables:
set -u
P1=${1:-1}

# Save old umask and set to 0022:
_UMASK_=$(umask)
umask 0022

# Prepare a sane build environment:
mkdir -p $TMP/tmp-$PRGNAM # location to build the source
rm -rf $TMP/tmp-$PRGNAM/* # remove the remnants of previous build
mkdir -p $PKG             # place for the package to be built
rm -rf $PKG/*             # erase old package's contents
mkdir -p $OUTPUT          # place for the package to be saved

# Source file availability:
if ! [ -f ${SOURCE} ]; then
  echo "Source '$(basename ${SOURCE})' not available yet..."
  # Check if the $SRCDIR is writable at all - if not, download to $OUTPUT
  [ -w "$SRCDIR" ] || SOURCE="$OUTPUT/$(basename $SOURCE)"
  if [ -f ${SOURCE} ]; then echo "Ah, found it!"; continue; fi
  if ! [ "x${SRCURL}" == "x" ]; then
    echo "Will download file to $(dirname $SOURCE)"
    wget -nv -T 20 -O "${SOURCE}" "${SRCURL}" || true
    if [ $? -ne 0 -o ! -s "${SOURCE}" ]; then
      echo "Downloading '$(basename ${SOURCE})' failed... aborting the build."
      mv -f "${SOURCE}" "${SOURCE}".FAIL
      exit 1
    fi
  else
    echo "File '$(basename ${SOURCE})' not available... aborting the build."
    exit 1
  fi
fi

if [ "$P1" == "--download" ]; then
  echo "Download complete."
  exit 0
fi

# --- PACKAGE BUILDING ---

echo "++"
echo "|| $PRGNAM-$VERSION"
echo "++"

cd $TMP/tmp-$PRGNAM

echo "Extracting the source archive(s) for $PRGNAM..."
tar -xvf $SOURCE
cd ${PRGNAM}-${VERSION}
chown -R root:root .
chmod -R u+w,go+r-w,a+rX-st .
touch $OUTPUT/patch-${PRGNAM}.log

# Specify the desired mirror in the update config file
# http://www.iana.org/cctld/cctld-whois.htm
sed -i "s/^\#DatabaseMirror.*/DatabaseMirror db.${ISOCC}.clamav.net/" \
  etc/freshclam.conf.sample
sed \
  -e "s/^Example/#Example/" \
  -e "s/^\#LogSyslog/LogSyslog/" \
  -e "s/^\#LogFacility/LogFacility/" \
  -e "s/^\#PidFile.*/PidFile \/var\/run\/clamav\/freshclam.pid/" \
  -e "s/^\#UpdateLogFile.*/UpdateLogFile \/var\/log\/clamav\/freshclam.log/" \
  -e "s/^\#DatabaseOwner.*/DatabaseOwner clamav/" \
  -e "s/^\#NotifyClamd.*/NotifyClamd \/etc\/clamd.conf/" \
  -i etc/freshclam.conf.sample
sed \
  -e "s/^Example/#Example/" \
  -e "s/^\#LogSyslog/LogSyslog/" \
  -e "s/^\#LogFacility/LogFacility/" \
  -e "s/^\#LogFile\ .*/LogFile \/var\/log\/clamav\/clamd.log/" \
  -e "s/^\#PidFile.*/PidFile \/var\/run\/clamd.pid/" \
  -e "s/^\#LocalSocket\ .*/LocalSocket \/var\/run\/clamav\/clamd.socket/" \
  -e "s/^\#LocalSocketGroup.*/LocalSocketGroup clamav/" \
  -e "s/^\#LocalSocketMode/LocalSocketMode/" \
  -e "s/^\#FixStaleSocket/FixStaleSocket/" \
  -e "s/^\#User.*/User clamav/" \
  -e "s/^\#ExitOnOOM/ExitOnOOM/" \
  -i etc/clamd.conf.sample

chown -R root:root .
chmod -R u+w,go+r-w,a+X-s .

# Compiling the package source:
echo Building ...

# Thanks to SlackBuilds.org, Matteo Bernardini <ponce@slackbuilds.org>:
# Check if json-c is there: if it is, build over it to enable
# the file properties collection and analysis feature
# http://blog.clamav.net/2014/11/intro-to-collection-and-analysis-of.html
if pkg-config --exists json-c ; then
  do_jsonc="--with-libjson"
else
  do_jsonc=""
fi

# Slackware 15.0 and newer have postfix by default, so include milter support
# only if we detect its presence:
if [ -f /usr/lib${LIBDIRSUFFIX}/libmilter.a ]; then
   do_milter="--enable-milter"
else
   do_milter="--disable-milter"
fi

# We need the "clamav" user and group to exist at the time of
# configuring the software...
# Add the 'clamav' group if it doesn't already exist:
/usr/sbin/groupadd ${CLAMGRP} 2> /dev/null || true
# Add the 'clamav' user if it doesn't exist already:
/usr/sbin/useradd -c "ClamAV user" -g ${CLAMGRP} \
   -s "/bin/false" ${CLAMUSR} 2> /dev/null || true

LDFLAGS="$SLKLDFLAGS" \
CFLAGS="$SLKCFLAGS" \
CXXFLAGS="$SLKCFLAGS" \
./configure \
  --prefix=/usr \
  --libdir=/usr/lib${LIBDIRSUFFIX} \
  --localstatedir=/var \
  --sysconfdir=/etc \
  --mandir=/usr/man \
  --with-user=${CLAMUSR} --with-group=${CLAMGRP} \
  --with-dbdir=/usr/share/clamav \
  --enable-id-check \
  --enable-clamdtop \
  --disable-check \
  --disable-static \
  --build=$TARGET \
  $do_jsonc \
  $do_milter \
  2>&1 | tee $OUTPUT/configure-${PRGNAM}.log
  # deprecated:
  #--with-libcurl --with-tcpwrappers \
make 2>&1 | tee $OUTPUT/make-${PRGNAM}.log

# Install all the needed stuff to the package dir;
make DESTDIR=$PKG install 2>&1 |tee $OUTPUT/install-${PRGNAM}.log

# Prepare the config files:
cd $PKG/etc
mv clamd.conf.sample clamd.conf.new
mv freshclam.conf.sample freshclam.conf.new
mv clamav-milter.conf.sample clamav-milter.conf.new
cd -

# Where to store the pid, db and log files:
mkdir -p $PKG/var/run/clamav
mkdir -p $PKG/usr/share/clamav
mkdir -p $PKG/var/log/clamav

# Ensure that any db files are removed along with the package:
touch \
  $PKG/usr/share/clamav/main.cvd \
  $PKG/usr/share/clamav/bytecode.cvd \
  $PKG/usr/share/clamav/daily.cvd \
  $PKG/usr/share/clamav/mirrors.dat

# Our rc.d and logrotate scripts:
mkdir -p $PKG/etc/rc.d/
install -D -m 0755 $SRCDIR/rc.clamav $PKG/etc/rc.d/rc.clamav.new
install -D -m 0644 $SRCDIR/logrotate.clamav $PKG/etc/logrotate.d/clamav.new

# Add a post-install script:
mkdir -p $PKG/install
cat <<EOINS > $PKG/install/doinst.sh
# Handle the incoming configuration files:
config() {
  for infile in \$1; do
    NEW="\$infile"
    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...
  done
}

preserve_perms() {
  NEW="\$1"
  OLD="\$(dirname \$NEW)/\$(basename \$NEW .new)"
  if [ -e \$OLD ]; then
    cp -a \$OLD \${NEW}.incoming
    cat \$NEW > \${NEW}.incoming
    mv \${NEW}.incoming \$NEW
  fi
  config \$NEW
}

preserve_perms etc/rc.d/rc.clamav.new
config etc/freshclam.conf.new
config etc/clamd.conf.new
config etc/clamav-milter.conf.new
config etc/logrotate.d/clamav.new

# Create log files
touch var/log/clamav/clamd.log
touch var/log/clamav/freshclam.log

# Only way to create and use the correct uid and gid on the target system,
# is to use chroot:
chroot . <<EOR 2>/dev/null
# Add the '${CLAMGRP}' group if it doesn't already exist:
# Actually, the use of "amavis" group is for compatibility with amavisd-new.
/usr/sbin/groupadd ${CLAMGRP} 2> /dev/null
# Add the '${CLAMUSR}' user if it doesn't already exist:
/usr/sbin/useradd -c "ClamAV user"  \\
  -g ${CLAMGRP} -s "/bin/false" ${CLAMUSR} 2> /dev/null

# Restore the correct permissions
chown ${CLAMUSR} usr/sbin/clamav-milter
chmod 4700 usr/sbin/clamav-milter
chown -R ${CLAMUSR}:${CLAMGRP} var/run/clamav
chmod 771 var/run/clamav
chown -R ${CLAMUSR}:${CLAMGRP} var/log/clamav
chmod 770 var/log/clamav
chmod 660 var/log/clamav/*.log
chown -R ${CLAMUSR}:${CLAMGRP} usr/share/clamav
chmod 770 usr/share/clamav
chmod 660 usr/share/clamav/*
EOR

EOINS
# --- End of 'doinst.sh' script -----------

# Add documentation:
cp $SRCDIR/00README.slackware README.slackware
DOCS="COPYING* ChangeLog.md \
      docs/*.pdf docs/html examples \
      README.slackware"
mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION
cp -a $DOCS $PKG/usr/doc/$PRGNAM-$VERSION || true
cat $SRCDIR/$(basename $0) > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild
chown -R root:root $PKG/usr/doc/$PRGNAM-$VERSION
find $PKG/usr/doc -type f -exec chmod 644 {} \;

# Compress the man page(s):
find $PKG/usr/man -type f -name "*.?" -exec gzip -9f {} \;

# Strip binaries:
find $PKG | xargs file | grep -e "executable" -e "shared object" \
  | grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null

# Add a package description:
mkdir -p $PKG/install
cat $SRCDIR/slack-desc > $PKG/install/slack-desc
if [ -f $SRCDIR/doinst.sh ]; then
  cat $SRCDIR/doinst.sh >> $PKG/install/doinst.sh
fi

# Set ownership to root - the doinst.sh will set things straight again:
chown -R root:root $PKG

# Build the package:
cd $PKG
/sbin/makepkg --linkadd y --chown n $OUTPUT/$PRGNAM-$VERSION-$ARCH-${BUILD}${TAG}.tgz 2>&1 | tee $OUTPUT/makepkg-${PRGNAM}.log
cd $OUTPUT
md5sum $PRGNAM-$VERSION-$ARCH-${BUILD}${TAG}.tgz > $PRGNAM-$VERSION-$ARCH-${BUILD}${TAG}.tgz.md5
cd -
cat $PKG/install/slack-desc | grep "^${PRGNAM}" > $OUTPUT/$PRGNAM-$VERSION-$ARCH-${BUILD}${TAG}.txt

# Restore the original umask:
umask ${_UMASK_}

