#!/bin/sh

# Script freely provided by Bill Landry (bill@inetmsg.com); however, use
# at your own peril! (:-O).  Comments, suggestions, and recommendations
# for improving this script are always welcome.  Feel free to report any
# issues, as well.
#
# Version 2.0a (updated 2/8/09)
#   - Moved all SecuriteInfo *.gz files out of the clam_dbs directory and
#     placed them instead into the si_dirs directory.  Also moved the MBL and
#     SecuriteInfo timestamp files (last-*-update.txt) out of the clam_dbs
#     directory and placed them into the config_dir (based on suggestions
#     from Panagiotis Christias).
#   - Added a variable about whether to create a backup database file before
#     moving an updated database file into the clam_dbs directory (based on
#     suggestions from Panagiotis Christias).
#   - Added a check to confirm that the local SecuriteInfo .gz file exists
#     before doing an "rsync -z" (time condition) test against the remote
#     rsync server's file.
#   - Added a check to test that the uncompressed SecuriteInfo database files
#     exist, are greater than zero, and are newer than the existing database
#     files before proceeding with further database testing and processing.
#   - Added a check to test that the MalwarePatrol database file exists,
#     is greater than zero, and is newer than the existing database file
#     before proceeding with further database testing and processing.
#   - Changed "test_dir" to "temp_dir" since we no longer test database files
#     in this directory.  It is now only used as a temporary location for
#     copying files to before moving them into the clam_dbs directory.
#   - Database files for all unofficial database providers are now kept in
#     their working sub-directories.  The only directory that remains empty
#     between updates now is the temp_dir directory.
#
# Version 2.0 (update 2/6/09)
#   - Added some missing variable quotes and also added some additional
#     checks to confirm which database providers and database files to
#     update (based on suggestions from Alex Pleiner).
#   - Major rearrangement of the scripts layout in order to make the flow
#     more logical.  Also consolidated some of the functions and variable
#     names so they could be reused in different parts of the script.
#   - Added a time variable to the SecuriteInfo checks so that the update
#     checks could be configured on an hourly or daily basis (based on
#     request from Bill Maidment).
#   - Removed use of "." to define the current directory and instead used
#     absolute path.  This also removed the requirement for the shell to
#     cd into the clamav directory.
#
# Version 1.9d (updated 2/5/09)
#   - Added variable "reload_dbs" to enable/disable database reloads after
#     a database has been updated.
#   - Added variable "reload_opt" to select or set how to reload the
#     databases after an update, if "reload_dbs" variable is set to "yes"
#     (based on request from Bob Hutchinson).
#
# Version 1.9c (updated 2/4/09)
#   - Added missing "&&" operators to the rsync download sections of the
#     script (thanks to Paul Henson for catching this).
#
# Version 1.9b (updated 2/4/09)
#   - Changed final directory permissions execution from "chmod 0664" to
#     "chmod u+Xrw" so as not to change sub-directory permissions (based
#     on recommendation from Daniel McDonald).
#   - Consolidated working directory path to a single variable to simplify
#     script directory location changes (based on request from Justin Davis).
#   - Changed clamd database reload command from "kill -USR2 `cat $clamd_pid`"
#     to "clamdscan --reload" (inspired by Malcolm Scott).
#   - Inadvertently removed a script line from the rsync download section
#     that saved a backup copy of the running database file before the
#     database was updated - it's now been re-added.
#
# Version 1.9a (updated 2/4/09)
#   - Added variable to silence rsync output, as already done for curl
#     (based on request from Daniel McDonald).
#   - Changed the rsync "-a" (archive) flag to "-rt" in order to ignore
#     source ownership & permission settings when files are downloaded
#     (based on feedback from Jeff Dairiki).
#
# Version 1.9 (updated 2/3/09) - Thanks to Jeff Dairiki & Steve Basford for
# their suggestions of using "--include-from=FILE" and "--exclude=PATTERN"
# with rsync to control database file downloads via a single connection.
#   - Rewrote SaneSecurity and MSRBL rsync sections.  Now all user specified
#     databases will be downloaded over a single connection.
#   - Script output will now show which SaneSecurity and MSRBL mirror the
#     connection was made to.
#   - Script output will also show the success or failure of GPG signature
#     testing and clamscan database integrity testing for each updated file.
#   - Database files now have permissions set (chmod & chown) before they
#     are moved into the clamav working directory.  A final check is also
#     still done at the end of the script, as well.
#   - Some variable names have changed or been removed, as well as some
#     directory paths added, removed, or changed to better accomodate single
#     rsync connection downloads, so carefully review the user configuration
#     section before using the script.
#
# Version 1.8a (updated 2/1/09)
#   - Added sanesecurity.ftm & sanesecurity.ftm.sig to the SaneSecurity
#     rsync database downloads (this helps clamav determine the signature
#     type to use when scanning email files).
#   - Added output for GPG signature test results (reports good or bad
#     GPG signature test results).
#   - If using clamd daemon monitoring and crash restart, added a check
#     to see if clamd's lock file still exists after the crash and deletes
#     it if it does (the orphaned clamd lock file can sometimes prevent
#     clamd from restarting after a crash has occurred).
#
# Version 1.8 (updated 1/21/09)
#   - Changed SaneSecurity downloads from using curl to rsync.
#   - Automatically download and import SaneSecurity GPG key to keyring.
#   - Automatically download, and check for updated SaneSecurity GPG
#     Signature files.
#   - Test SaneSecurity database downloads against GPG Signature files
#     before integrity testing databases with clamscan.  If either test
#     fails, that database file will not be updated.
#   - Added and modified working directory paths to better accommodate
#     gpg Signature testing.
#
# Version 1.7d (updated 10/5/08 - Thanks to Burt Heymanson for his
# contribution to this update - silence curl output)
#   - Added 2 new SaneSecurity databases: junk.ndb & rogue.hdb.
#   - Added a configuration option to silence curl output to only report
#     errors to stderr rather than all download stats.
#
# Version 1.7c (updated 9/25/07 - Thanks to Dennis Peterson and Jan-Perter
# Cornet for the perl solution for calculating seconds since epoch)
#   - Added timeout values to curl and rsync downloads in order to prevent
#     the script from hanging on a non-responsive host site.
#   - Apparently Solaris does not support "date +%s", which calculates
#     the number of seconds since epoch.  This date function is used to
#     calculate when to do MBL downloads.  A perl solution has been added
#     as a fall-back option.  If "date +%s" is not supported and perl is
#     not found on the system, the script will report a warning message
#     and skip MBL updates, but the script will continue processing other
#     third-party database updates.
#
# Version 1.7b (updated 9/23/07)
#   - Changed all script "`expr ...`" interger expressions to the shell
#     supported "$((...))" format, which is what was being used in all
#     other newer sections of the script.  So this change should not
#     pose any problems, but if it does, please let me know.
#   - Changed all clamscan database file tests from using /dev/null,
#     which was causing an access permissions issues to the temporary
#     directory for some users, to a direct path to a temp test file.
#
# Version 1.7a (updated 9/10/07)
#   - Added secondary perl socket test to detect if clamd is running.
#     This test uses the 'IO::Socket::UNIX' perl module.  If socat is
#     not found on the system, then the script will attempt to use the
#     perl module instead (the user will be warned if neither socat nor
#     IO::Socket::UNIX are found, but the script will still run updates).
#   - Added two new SecuriteInfo database file URLs.
#   - Updated comments to reflect the additional perl socket test.
#
# Version 1.7 (updated 9/7/07)
#   - Added a check to see if ClamD is running or not.  This can be used
#     if clamd is running in "LocalSocket" mode (*NOT* TCP/IP mode), and
#     socat is installed on the system (a check for socat is done).  This
#     test can be enabled in the "User Edit" section below.
#   - Added a user configurable variable to attempt to restart clamd if
#     it's detected to not be running.
#   - Added notification when database file updates are *NOT* detected and
#     databases are *NOT* reloaded, rather than just when they are detected.
#   - Added more portable secondary randomization code, removing the
#     requirement to have the bash shell installed.
#   - Added general improvements to the time randomization code so that
#     the time interval does not always end with a zero.
#   - Added user configurable min and max variables for setting time
#     randomization intervals (defaults to min=60 and max=600 seconds).
#   - Added terminal detection to determine whether the script is being
#     run manually or via cron.  If run manually, the script will now
#     prompt the user to see if they want to delay the script execution
#     (random) or not.  If "yes" is selected, then the script will pause
#     and display a visual countdown in seconds until script execution.
#   - Added a variable that the user must set before the script will run.
#     This will effectively require that script users at least minimally
#     review the "User Edit Section" before running the script.
#   - Rearranged some sections, timestame placement, and updated comments.
#
# Version 1.6 (updated 8/27/07)
#   - Added support for SecuriteInfo and Malware Black List
#     database file downloads.
#   - Changed the script name from ss-msrbl.sh to unofficial-sigs.sh
#     since there are now 4 different database providers supported.
#   - Since the MBL database is dynamically created and therefor
#     cannot be checked for change before downloading, a variable was
#     added so that a specific download time interval can be set (see
#     the "USER EDIT SECTION" below).
#   - Added database file download time randomization (to disable
#     randomization, see the "USER EDIT SECTION" below for details).
#
# Version 1.5 (updated 8/17/07 - Thanks to Dan Larsson for his
# contributions to this update)
#   - Added separate variable for ClamAV group ID for setting
#     appropriate file group access permissions.
#   - Added variables for database file update URLs.
#   - Added support for automatic reloading of databases when
#     updates are found.
#
# Version 1.4 (updated 7/13/07)
#   - Added checks to verify that the database files exist,
#     and if not, do an initial download, decompress and test.
#   - Added variables for clamav database location path and
#     clamd user account (the account that clamd runs under).
#   - Added/modified script comments.
#
# Version 1.3
#   - Added checks to either confirm the existence of the
#     temporary working directories or to create them.
#   - Changed "cp --reply=yes" to "cp -f".  If this
#     causes problems with older versions of "cp",
#     you will need to change it back.
#
# Version 1.2
#   - Repointed URLs for SaneSecurity downloads to
#     the new mirror redirect links.
#
# Version 1.1
#   - Converted MSRBL downloads from curl to rsync.
#
# Version 1.0 (initial script created).

######################################################################################
# START OF USER CONFIGURATION SECTION - SET PROGRAM PATHS AND OTHER VARIABLE OPTIONS #
######################################################################################

# Edit quoted variables below to meet your own particular
# needs/requirements, but do not remove the "quote" marks.

# Set and export program paths.
export PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"

# Set ClamD user and group accounts.
clam_user="clamav"
clam_group="clamav"

# Set path to ClamAV database files location.  If unsure, check
# your clamd.conf file for the "DatabaseDirectory" path setting.
clam_dbs="/var/lib/clamav"

# Set path to clamd.pid file (see clamd.conf for path location).
clamd_pid="/var/run/clamd.pid"

# If you would like to reload the clamd databases after an update,
# change the following variable to "yes".
reload_dbs="no"

# Set the reload or restart option if the "reload_dbs" variable above
# is set to "yes" (only select 'ONE' of the following options or the
# last uncommented variable option will be the one used).
#reload_opt="clamdscan --reload" #Signals socket to reload dbs
#reload_opt="kill -USR2 `cat $clamd_pid`" #Signals PID to reload dbs
#reload_opt="service clamd restart" #Signals clamd to do full restart
#reload_opt="" #Set custom or system specific reload/restart option

# If running clamd in "LocalSocket" mode (*NOT* in TCP/IP mode), and
# either "SOcket Cat" (socat) or the "IO::Socket::UNIX" perl module
# are installed on the system, and you want to report whether clamd
# is running or not, uncomment the "clamd_socket" variable below (you
# will be warned if neither socat nor IO::Socket::UNIX are found, but
# the script will still run).  You will also need to set the correct
# path to your clamd socket file (if unsure of the path, check the
# "LocalSocket" setting in your clamd.conf file for socket location).
#clamd_socket="/tmp/clamd.socket"

# If you would like to attemtp to restart ClamD if detected not running,
# uncomment the next 2 lines.  Confirm the path to the "clamd_lock" file
# (usually can be found in the clamd init script) and also enter the clamd
# start command for your particular distro for the "start_clamd" variable
# (the sample start command shown below should work for most linux distros).
# NOTE: these 2 variables are dependant on the "clamd_socket" variable
# shown above - if not enabled, then the following 2 variables will be
# ignored, whether enabled or not.
#clamd_lock="/var/lock/subsys/clamd"
#start_clamd="service clamd start"

# Set working directory paths (edit to meet your own needs). If these
# directories do not exist, the script will attempt to create them.
# Top level working directory path:
work_dir="/usr/unofficial-dbs"
# ---
# Working sub-directory names:
ss_dir="$work_dir/ss-dbs"
msrbl_dir="$work_dir/msrbl-dbs"
si_dir="$work_dir/si-dbs"
mbl_dir="$work_dir/mbl-dbs"
config_dir="$work_dir/configs"
gpg_dir="$work_dir/gpg-key"
temp_dir="$work_dir/temp-dir"

# Enable or disable download time randomization.  This allows the script to
# be executed via cron, but the actual database file checking will pause
# for a random number of seconds between the "min" and "max" time settings
# specified below.  This helps to more evenly distribute load on the host
# download sites.  To disable, set the following variable to "no".
enable_random="yes"

# If download time randomization is enabled above (enable_random="yes"),
# then set the min and max radomization times intervals (in seconds).
min_sleep_time="60"    # Default minimum is 60 seconds (1 minute).
max_sleep_time="600"   # Default maximum is 600 seconds (10 minutes).

# ========================
# SaneSecurity Database(s)
# ========================
# Add/remove/modify database file names between quote marks as needed.
# To disable any of the SaneSecurity database file downloads, remove
# the appropriate database file name line(s) below.  To disable all
# SaneSecurity database downloads, comment out all of the following lines.
ss_dbs="
   phish.ndb
   scam.ndb
   junk.ndb
   rogue.hdb
   spear.ndb
   spamimg.hdb
   lott.ndb
   spam.ldb
   sanesecurity.ftm
"

# =================
# MSRBL Database(s)
# =================
# Add/remove/modify database file names between quote marks as needed.
# To disable any of the MSRBL database file downloads, remove
# the appropriate database file name line(s) below.  To disable all
# MSRBL database downloads, comment out all of the following lines.
msrbl_dbs="
   MSRBL-Images.hdb
   MSRBL-SPAM.ndb
"

# ========================
# SecuriteInfo Database(s)
# ========================
# Add/remove/modify database file names between quote marks as needed.
# To disable any SecuriteInfo database downloads, remove the appropriate
# line(s) below.  To disable all SecuriteInfo database file downloads,
# comment out all of the following lines.
si_dbs="
   vx.hdb
   honeynet.hdb
   securiteinfo.hdb
   antispam.ndb
"

# Since the SecuriteInfo databases are only updated a few time each
# month, set a time interval to do database update checks.
si_update_hours="4"   # Default is 4 hours (6 update checks daily).

# =========================
# MalwarePatrol Database(s)
# =========================
# Add/remove/modify database file names between quote marks as needed.
# To disable any of the MalwarePatrol database file downloads, remove
# the appropriate database file name line(s) below.  To disable all
# MalwarePatrol database downloads, comment out all of the following lines.
mbl_dbs="
   mbl.db
"

# Since the MalwarePatrol database file is dynamically created,
# there is no way to test for changes prior to downloading.  For this
# reason, you will need to set a reasonable time interval in "hours"
# for MBL database file downloads.  As shown below, this has been
# set to update every "6" hours, which seems appropriate (that's 4
# file downloads per day)  Change only if you REALLY feel you must.
# However, I would not suggest going below every 4 hour lest you risk
# being blacklisted by the MalwarePatrol site.
mbl_update_hours="6"   # Default is 6 hours (4 downloads daily).

# If you want to silence the stats reported by curl and/or rsync,
# change the following variables to "yes".
curl_silence="no"   # Default is "no" to report curl stats
rsync_silence="no"  # Default is "no" to report rsync stats

# If you would like to make a backup copy of the current running database
# file before updating, leave the following variable set to "yes".
keep_db_backup="yes"

# Set the following variable to "yes" once you have completed the
# "USER CONFIGURATION SECTION" of this script.
user_configuration_complete="no"

#######################################################################################
# END OF USER CONFIGURATION SECTION - YOU SHOULD NOT NEED TO EDIT ANYTHING BELOW HERE #
#######################################################################################

# Check to see if the script's "USER CONFIGURATION SECTION" has been completed.
if [ "$user_configuration_complete" != "yes" ]
   then
      echo ""
      echo "               *** SCRIPT CONFIGURATION HAS NOT BEEN COMPLETED ***"
      echo "   Please review and configure the 'USER CONFIGURATION SECTION' of the script."
      echo "    Once the user configuration section has been completed, rerun the script."
      echo ""
   exit 1
fi

# Check to see if the working directories shown above were created.
# If not, create them.  Otherwise, ignore and proceed with script.
mkdir -p $ss_dir $msrbl_dir $si_dir $mbl_dir $config_dir $gpg_dir $temp_dir

# Move any existing SecuriteInfo source *.gz files from the clam_dbs
# directory to the si_dir directory.
for gz_file in `ls $clam_dbs/*.?db.gz 2> /dev/null` ; do
   mv -f $gz_file $si_dir
done

# Move any existing SecuriteInfo & MalwarePatrol timestamp files from
# the clam_dbs directory to the config_dir directory.
for txt_file in `ls $clam_dbs/last-*-update.txt 2> /dev/null` ; do
   mv -f $txt_file $config_dir
done

# Create "scan-test.txt" file for clamscan database integrity testing.
if [ ! -s "$config_dir/scan-test.txt" ] ; then
   echo "This is the clamscan test file..." > $config_dir/scan-test.txt
fi

# Create the SaneSecurity rsync "include" file (defines which files to download).
ss_include_dbs="$config_dir/ss-include-dbs.txt"
if [ -n "$ss_dbs" ] ; then
   rm -f $ss_include_dbs
   for db_name in $ss_dbs ; do
      echo "$db_name*" >> $ss_include_dbs
   done
fi

# Create the MSRBL rsync "include" file (defines which files to download).
msrbl_include_dbs="$config_dir/msrbl-include-dbs.txt"
if [ -n "$msrbl_dbs" ] ; then
   rm -f $msrbl_include_dbs
   for db_name in $msrbl_dbs ; do
      echo "$db_name" >> $msrbl_include_dbs
   done
fi

# Unofficial signature database provider URLs
ss_url="rsync.sanesecurity.net"
msrbl_url="rsync.mirror.msrbl.com"
si_url="clamav.securiteinfo.com"
mbl_url="www.malware.com.br/cgi/submit?action=list_clamav"

# Download SaneSecurity GPG Key and import to keyring.
if [ ! -s "$gpg_dir/publickey.gpg" ]
   then
      curl -s -S --connect-timeout 15 --max-time 60 -L -R http://www.sanesecurity.net/publickey.gpg -o $gpg_dir/publickey.gpg && \
      test -s $gpg_dir/publickey.gpg && \
      gpg --import $gpg_dir/publickey.gpg && \
      echo "GPG Key Successfully Imported To Local Keyring"
      echo ""
fi

# Silence curl output and only report errors - useful if script is run via cron.
if [ "$curl_silence" = "yes" ]
   then
      curl_output_level="-s -S"
fi

# Silence rsync output and only report errors - useful if script is run via cron.
if [ "$rsync_silence" = "yes" ]
   then
      rsync_output_level="-q"
fi

# If ClamD status check is enabled ("clamd_socket" variable is uncommented
# and the socket path is correctly specified in "User Edit" section above),
# then test to see if clamd is running or not.
if [ -n "$clamd_socket" ]
   then
      socat="`which socat 2> /dev/null`"
      if [ -n "$socat" -a -x "$socat" ]
         then
            socket_cat1=1
            if [ "`echo PING | socat - "$clamd_socket" 2> /dev/null`" = "PONG" ]
               then
                  socket_cat2=1
                  echo "===================="
                  echo "= ClamD is running ="
                  echo "===================="
            fi
         else
            if [ "`perl -e 'use IO::Socket::UNIX; print $IO::Socket::UNIX::VERSION,"\n"' 2> /dev/null`" ]
               then
                  io_socket1=1
                  if [ "`perl -MIO::Socket::UNIX -we '$s = IO::Socket::UNIX->new(shift); $s->print("PING"); \
                     print $s->getline; $s->close' "$clamd_socket" 2> /dev/null`" = "PONG" ]
                     then
                        io_socket2=1
                        echo "===================="
                        echo "= ClamD is running ="
                        echo "===================="
                  fi
            fi
      fi
      if [ -z "$socket_cat1" -a -z "$io_socket1" ]
         then
            echo ""
            echo "                         --- WARNING ---"
            echo "   It appears that neither 'SOcket CAT' (socat) nor the perl module"
            echo "   'IO::Socket::UNIX' are installed on the system.  In order to run"
            echo "   the ClamD socket test to determine whether ClamD is running or"
            echo "   or not, either 'socat' or 'IO::Socket::UNIX' must be installed."
            echo ""
            echo "   You can silence this warning by either installing 'socat' or the"
            echo "   'IO::Socket::UNIX' perl module, or by simply commenting out the"
            echo "   'clamd_socket' variable in the 'USER EDIT SECTION' of the script."
         else
            if [ -z "$socket_cat2" -a -z "$io_socket2" ]
               then
                  echo ""
                  echo "     *************************"
                  echo "     *     !!! ALERT !!!     *"
                  echo "     * CLAMD IS NOT RUNNING! *"
                  echo "     *************************"
                  echo ""
                  if [ -n "$start_clamd" ]
                     then
                        echo "     Attempting to start ClamD..."
                        echo ""
                        if [ -n "$socket_cat1" ]
                           then
                              [ "`rm -f $clamd_lock 2> /dev/null`" -a "`$start_clamd 2> /dev/null`" -a "`sleep 5`" ]
                              if [ "`echo PING | socat - "$clamd_socket" 2> /dev/null`" = "PONG" ]
                                 then
                                    echo "===================================="
                                    echo "= ClamD was successfully restarted ="
                                    echo "===================================="
                                 else
                                    echo "     *************************"
                                    echo "     *     !!! PANIC !!!     *"
                                    echo "     * CLAMD FAILED TO START *"
                                    echo "     *************************"
                                    echo ""
                                    echo "Check to confirm that the clamd start process defined for"
                                    echo "the 'start_clamd' variable in the 'USER EDIT SECTION' is"
                                    echo "set correctly for your particular distro.  If it is, then"
                                    echo "check your logs to determine why clamd failed to start."
                                    echo ""
                                 exit 1
                              fi
                           else
                              if [ -n "$io_socket1" ]
                                 then
                                    [ "`rm -f $clamd_lock 2> /dev/null`" -a "`$start_clamd 2> /dev/null`" -a "`sleep 5`" ]
                                    if [ "`perl -MIO::Socket::UNIX -we '$s = IO::Socket::UNIX->new(shift); \
                                       $s->print("PING"); print $s->getline; $s->close' "$clamd_socket" \
                                       2> /dev/null`" = "PONG" ]
                                       then
                                          echo "===================================="
                                          echo "= ClamD was successfully restarted ="
                                          echo "===================================="
                                       else
                                          echo "     *************************"
                                          echo "     *     !!! PANIC !!!     *"
                                          echo "     * CLAMD FAILED TO START *"
                                          echo "     *************************"
                                          echo ""
                                          echo "Check to confirm that the clamd start process defined for"
                                          echo "the 'start_clamd' variable in the 'USER EDIT SECTION' is"
                                          echo "set correctly for your particular distro.  If it is, then"
                                          echo "check your logs to determine why clamd failed to start."
                                          echo ""
                                       exit 1
                                    fi
                              fi
                        fi
                  fi
            fi
      fi
fi

# Database update check, time randomization section.  This script now
# provides support for both bash and non-bash enabled system shells.
if [ "$enable_random" = "yes" ] ; then
   if [ -n "$RANDOM" 2> /dev/null ]
      then
         sleep_time=$(($RANDOM * $(($max_sleep_time - $min_sleep_time)) / 32767 + $min_sleep_time))
      else
         sleep_time=0
         while [ "$sleep_time" -lt "$min_sleep_time" -o "$sleep_time" -gt "$max_sleep_time" ] ; do
            sleep_time=`head -1 /dev/urandom | cksum | awk '{print $2}'`
         done
   fi
   if [ ! -t 0 ]
      then
         echo ""
         echo "`date` - Pausing database file updates for $sleep_time seconds..."
         sleep $sleep_time
         echo ""
         echo "`date` - Pause complete, checking for new database files..."
      else
         echo ""
         echo -n "Running script manually, do you want to pause execution (y/n)?: "
         read response
         while [ "$response" != "y" -a "$response" != "n" ] ; do
            echo -n "Expecting either 'y' or 'n', do you want to pause script execution (y/n)?: "
            read response
         done
         if [ "$response" = "y" ]
            then
               seconds=$sleep_time
               echo "Starting unofficial ClamAV database updates on `date`"
               echo ""
               while [ "$sleep_time" -ne 0 ] ; do
                  echo -ne "Pausing database updates for $seconds seconds. Time remaining: $sleep_time \r"
                  sleep 1
                  sleep_time=$(($sleep_time - 1))
               done
               echo ""
               echo "Pause complete, `date`, checking for new database files..."
            else
               echo "Running unofficial ClamAV database updates..."
         fi
   fi
fi

# Check and save current system time since epoch for time related database downloads.
# However, if unsuccessful, issue a warning that we cannot calculate times since epoch.
if [ -n "$si_dbs" -o -n "mbl_dbs" ]
   then
      if [ `date +%s` -gt 0 2> /dev/null ]
         then
            current_time=`date +%s`
         else
            if [ `perl -le print+time 2> /dev/null` ]
               then
                  current_time=`perl -le print+time`
            fi
      fi
   else
      echo ""
      echo "                           --- WARNING ---"
      echo "The system's date function does not appear to support 'date +%s', nor was 'perl' found"
      echo "on the system.  The SecuriteInfo and MalwarePatrol updates were bypassed at this time."
      echo ""
      echo "You can silence this warning by either commenting out the 'si_dbs' and 'mbl_dbs'"
      echo "variables in the 'USER CONFIGURATION' section of the script, or by installing perl or"
      echo "the GNU date utility, either of which can calculate the needed seconds since epoch."
      si_dbs=""
      mbl_dbs=""
fi

# Check to see if "last-si-update.txt" file exists, if not set "last_si_update" variable to "0"
if [ -n "$si_dbs" ] ; then
   if [ -s "$config_dir/last-si-update.txt" ]
      then
         last_si_update=`cat $config_dir/last-si-update.txt`
      else
         last_si_update="0"
   fi
fi

# Check to see if "last-mbl-update.txt" file exists, if not set "last_mbl_update" variable to "0"
if [ -n "$mbl_dbs" ] ; then
   if [ -s "$config_dir/last-mbl-update.txt" ]
      then
         last_mbl_update=`cat $config_dir/last-mbl-update.txt`
      else
         last_mbl_update="0"
   fi
fi


# Check for SaneSecurity database & signature file updates.
if [ -n "$ss_dbs" ] ; then
   db_file=""
   ss_mirror_ip=`host $ss_url | head -1 | awk '{print $NF}'`
   ss_mirror_name=`host $ss_mirror_ip | awk '{print $NF}' | sed 's/\(.*\)./\1/'`
   ss_mirror_site_info="$ss_mirror_name $ss_mirror_ip"
   echo ""
   echo "======================================================================"
   echo "SaneSecurity Database & Signature File Updates"
   echo "======================================================================"
   echo ""
   echo "SaneSecurity mirror site used: $ss_mirror_site_info"
   rsync $rsync_output_level --include-from=$ss_include_dbs --exclude=* --timeout=30 \
      -rtz --stats rsync://$ss_mirror_ip/sanesecurity $ss_dir/ | tail -15
   for db_file in $ss_dbs ; do
      if [ -s "$clam_dbs/$db_file" -a "$ss_dir/$db_file" -nt "$clam_dbs/$db_file" ] ; then
         echo ""
         echo "Testing updated database file: $db_file"
         gpg --trust-model always -q --verify $ss_dir/$db_file.sig && \
         clamscan --quiet -d $ss_dir/$db_file $ss_dir/$db_file.sig && \
         echo "Clamscan reports $db_file database integrity tested good" && \
         cp -f -p $ss_dir/$db_file $temp_dir && \
         chown $clam_user:$clam_group $temp_dir/$db_file && \
         chmod 0644 $temp_dir/$db_file && \
         test "$keep_db_backup" = "yes" && cp -f $clam_dbs/$db_file $clam_dbs/$db_file-bak && \
         mv -f $temp_dir/$db_file $clam_dbs && \
         do_clamd_reload=1
      fi
      if [ ! -s "$clam_dbs/$db_file" ] ; then
         echo ""
         echo "Testing updated database file: $db_file"
         gpg --trust-model always -q --verify $ss_dir/$db_file.sig && \
         clamscan --quiet -d $ss_dir/$db_file $ss_dir/$db_file.sig && \
         echo "Clamscan reports $db_file database integrity tested good" && \
         cp -f -p $ss_dir/$db_file $temp_dir && \
         chown $clam_user:$clam_group $temp_dir/$db_file && \
         chmod 0644 $temp_dir/$db_file && \
         mv -f $temp_dir/$db_file $clam_dbs && \
         do_clamd_reload=1
      fi
   done
fi

# Check for MSRBL database file updates.
if [ -n "$msrbl_dbs" ] ; then
   db_file=""
   msrbl_mirror_ip=`host $msrbl_url | head -1 | awk '{print $NF}'`
   msrbl_mirror_name=`host $msrbl_mirror_ip | awk '{print $NF}' | sed 's/\(.*\)./\1/'`
   msrbl_mirror_site_info="$msrbl_mirror_name $msrbl_mirror_ip"
   echo ""
   echo "======================================================================"
   echo "MSRBL Database File Updates"
   echo "======================================================================"
   echo ""
   echo "MSRBL mirror site used: $msrbl_mirror_site_info"
   rsync $rsync_output_level --include-from=$msrbl_include_dbs --exclude=* --timeout=30 \
      -rtz --stats rsync://$msrbl_mirror_ip/msrbl $msrbl_dir/ | tail -15
   for db_file in $msrbl_dbs ; do
      if [ -s "$clam_dbs/$db_file" -a "$msrbl_dir/$db_file" -nt "$clam_dbs/$db_file" ] ; then
         echo ""
         echo "Testing updated database file: $db_file"
         clamscan --quiet -d $msrbl_dir/$db_file $config_dir/scan-test.txt && \
         echo "Clamscan reports $db_file database integrity tested good" && \
         cp -f -p $msrbl_dir/$db_file $temp_dir && \
         chown $clam_user:$clam_group $temp_dir/$db_file && \
         chmod 0644 $temp_dir/$db_file && \
         test "$keep_db_backup" = "yes" && cp -f $clam_dbs/$db_file $clam_dbs/$db_file-bak && \
         mv -f $temp_dir/$db_file $clam_dbs && \
         do_clamd_reload=1
      fi
      if [ ! -s "$clam_dbs/$db_file" ] ; then
         echo ""
         echo "Testing updated database file: $db_file"
         clamscan --quiet -d $msrbl_dir/$db_file $config_dir/scan-test.txt && \
         echo "Clamscan reports $db_file database integrity tested good" && \
         cp -f -p $msrbl_dir/$db_file $temp_dir && \
         chown $clam_user:$clam_group $temp_dir/$db_file && \
         chmod 0644 $temp_dir/$db_file && \
         mv -f $temp_dir/$db_file $clam_dbs && \
         do_clamd_reload=1
      fi
   done
fi

# Check for updated SecuriteInfo database files every set number of
# hours as defined in the "USER CONFIGURATION" section of this script.
if [ -n "$si_dbs" ] ; then
   db_file=""
   update_interval=$(($si_update_hours * 3600))
   time_interval=$(($current_time - $last_si_update))
   if [ "$time_interval" -ge $(($update_interval - 600)) ]
      then
         echo "$current_time" > $config_dir/last-si-update.txt
         for db_file in $si_dbs ; do
            echo ""
            echo "======================================================================"
            echo "SecuriteInfo $db_file Database File Update"
            echo "======================================================================"
            echo ""
            if [ -s "$clam_dbs/$db_file" -a -s "$si_dir/$db_file.gz" ]
               then
                  curl $curl_output_level --connect-timeout 15 --max-time 60 -L -R -z \
                     $si_dir/$db_file.gz -o $si_dir/$db_file.gz http://$si_url/$db_file.gz
                  test -s $si_dir/$db_file.gz && \
                  gunzip -cdf $si_dir/$db_file.gz > $si_dir/$db_file && \
                  test -s $si_dir/$db_file && \
                  test -s "$clam_dir/$db_file" -a "$si_dir/$db_file" -nt "$clam_dbs/$db_file" && \
                  echo "" && \
                  echo "Testing updated database file: $db_file" && \
                  clamscan --quiet -d $si_dir/$db_file $config_dir/scan-test.txt && \
                  echo "Clamscan reports $db_file database integrity tested good" && \
                  cp -f -p $si_dir/$db_file $temp_dir && \
                  chown $clam_user:$clam_group $temp_dir/$db_file && \
                  chmod 0644 $temp_dir/$db_file $si_dir/$db_file.gz && \
                  test "$keep_db_backup" = "yes" && cp -f $clam_dbs/$db_file $clam_dbs/$db_file-bak && \
                  mv -f $temp_dir/$db_file $clam_dbs && \
                  do_clamd_reload=1
               else
                  curl $curl_output_level --connect-timeout 15 --max-time 60 -L -R -o \
                     $si_dir/$db_file.gz http://$si_url/$db_file.gz
                  test -s $si_dir/$db_file.gz && \
                  gunzip -cdf $si_dir/$db_file.gz > $si_dir/$db_file && \
                  test -s $si_dir/$db_file && \
                  echo "" && \
                  echo "Testing updated database file: $db_file" && \
                  clamscan --quiet -d $si_dir/$db_file $config_dir/scan-test.txt && \
                  echo "Clamscan reports $db_file database integrity tested good" && \
                  cp -f -p $si_dir/$db_file $temp_dir && \
                  chown $clam_user:$clam_group $temp_dir/$db_file && \
                  chmod 0644 $temp_dir/$db_file $si_dir/$db_file.gz && \
                  mv -f $temp_dir/$db_file $clam_dbs && \
                  do_clamd_reload=1
            fi
         done
      else
         echo ""
         echo "======================================================================"
         echo "SecuriteInfo Database Files Update"
         echo "======================================================================"
         echo ""
         time_remaining=$(($update_interval - $time_interval))
         hours_left=$(($time_remaining / 3600))
         minutes_left=$(($time_remaining % 3600 / 60))
         echo "$si_update_hours hours have not yet elapsed since the last SecuriteInfo database update checks."
         echo ""
         echo "     --- No update checks were performed at this time ---"
         echo ""
         echo "Next update checks will be performed in approximately $hours_left hour(s), $minutes_left minute(s)"
   fi
fi

# Download MalwarePatrol database file(s) every set number of hours
# as defined in the "USER CONFIGURATION" section of this script.
if [ -n "$mbl_dbs" ] ; then
   db_file=""
   update_interval=$(($mbl_update_hours * 3600))
   time_interval=$(($current_time - $last_mbl_update))
   if [ "$time_interval" -ge $(($update_interval - 600)) ]
      then
         echo "$current_time" > $config_dir/last-mbl-update.txt
         for db_file in $mbl_dbs ; do
            echo ""
            echo "======================================================================"
            echo "MalwarePatrol $db_file Database File Update"
            echo "======================================================================"
            echo ""
            if [ -s "$clam_dbs/$db_file" ]
               then
                  curl $curl_output_level --connect-timeout 15 --max-time 60 -R -o \
                     $mbl_dir/$db_file http://$mbl_url
                  test -s $mbl_dir/$db_file && \
                  test -s "$clam_dir/$db_file" -a "$mbl_dir/$db_file" -nt "$clam_dbs/$db_file" && \
                  echo "" && \
                  echo "Testing updated database file: $db_file" && \
                  clamscan --quiet -d $mbl_dir/$db_file $config_dir/scan-test.txt && \
                  echo "Clamscan reports $db_file database integrity tested good" && \
                  test "$keep_db_backup" = "yes" && cp -f $clam_dbs/$db_file $clam_dbs/$db_file-bak && \
                  cp -f -p $mbl_dir/$db_file $temp_dir && \
                  chown $clam_user:$clam_group $temp_dir/$db_file && \
                  chmod 0644 $temp_dir/$db_file && \
                  test "$keep_db_backup" = "yes" && cp -f $clam_dbs/$db_file $clam_dbs/$db_file-bak && \
                  mv -f $temp_dir/$db_file $clam_dbs && \
                  do_clamd_reload=1
               else
                  curl $curl_output_level --connect-timeout 15 --max-time 60 -R -o \
                     $mbl_dir/$db_file http://$mbl_url
                  test -s $mbl_dir/$db_file && \
                  echo "" && \
                  echo "Testing updated database file: $db_file" && \
                  clamscan --quiet -d $mbl_dir/$db_file $config_dir/scan-test.txt && \
                  echo "Clamscan reports $db_file database integrity tested good" && \
                  cp -f -p $mbl_dir/$db_file $temp_dir && \
                  chown $clam_user:$clam_group $temp_dir/$db_file && \
                  chmod 0644 $temp_dir/$db_file && \
                  mv -f $temp_dir/$db_file $clam_dbs && \
                  do_clamd_reload=1
            fi
         done
      else
         echo ""
         echo "======================================================================"
         echo "MalwarePatrol Database File Update"
         echo "======================================================================"
         echo ""
         time_remaining=$(($update_interval - $time_interval))
         hours_left=$(($time_remaining / 3600))
         minutes_left=$(($time_remaining % 3600 / 60))
         echo "$mbl_update_hours hours have not yet elapsed since the last $db_file database download."
         echo ""
         echo "     --- No update was performed at this time ---"
         echo ""
         echo "Next download will be performed in approximately $hours_left hour(s), $minutes_left minute(s)"
   fi
fi

# Set appropriate file access permissions
chown -R $clam_user:$clam_group $clam_dbs
chmod u+Xrw $clam_dbs/*

# Remove any possible leftover files left in the $temp_dir working directory
rm -f $temp_dir/*

# Reload all clamd databases if updates detected and $reload_dbs" is
# set to "yes", and neither $reload_opt nor $do_clamd_reload are null.
if [ "$reload_dbs" = "yes" -a -z "$reload_opt" ]
   then
      echo ""
      echo "*******************************************************************************************"
      echo "* Check the USER CONFIGURATION section, 'reload_dbs' enabled but no 'reload_opt' selected *"
      echo "*******************************************************************************************"
   else
      if [ "$reload_dbs" = "yes" -a -n "$do_clamd_reload" -a -n "$reload_opt" ]
         then
            echo ""
            echo "=================================================="
            echo "= Update(s) detected, reloading ClamAV databases ="
            echo "=================================================="
            $reload_opt
         else
            if [ "$reload_dbs" = "yes" -a -z "$do_clamd_reload" ]
               then
                  echo ""
                  echo "========================================================="
                  echo "= No update(s) detected, NOT reloading ClamAV databases ="
                  echo "========================================================="
            fi
      fi
fi

exit $?

