Never been to CodeSnippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world (or not, you can keep them private!)

Compile ClamAV from source on Mac OS X (See related posts)

The following instructions for compiling & installing the ClamAV virus scanner on Mac OS X require an admin user account and Xcode. Works despite some compiler warnings. Use at your own risk!

1. disable an already installed ClamAV system

clamconf      # get your ClamAV configuration
clamconf -n
clamconf | grep DatabaseOwner


# the following applies to the already installed ClamAV system of user clamavadmin at /private/var/clamavadmin
# cf. Run ClamAV from a system service agent account, http://textsnippets.com/posts/show/1406
# cf. Automated virus scanning with ClamAV on Mac OS X 10.4, http://textsnippets.com/posts/show/1357


# view clamd.log in another Terminal window
open /bin/bash
sudo tail -n 50 -f /private/var/clamavadmin/log/clamd.log

# SHUTDOWN clamd 
# cf. man clamd
(sleep 3; echo PING; sleep 3; echo exit) | telnet -u /private/var/clamavadmin/tmp/clamd
(sleep 3; echo SHUTDOWN; sleep 3; echo exit) | telnet -u /private/var/clamavadmin/tmp/clamd

# alternative: sudo /opt/local/bin/port install socat
echo PING | /opt/local/bin/socat - /private/var/clamavadmin/tmp/clamd     
echo SHUTDOWN | /opt/local/bin/socat - /private/var/clamavadmin/tmp/clamd  

# alternative
function clamd_local_socket() {

   local_socket="$(/usr/local/bin/clamconf -n | awk -F '"' '/LocalSocket/ {print $2}')"

   if [[ -z "$local_socket" ]] || [[ ! -S "$local_socket" ]]; then    # cf. help test
      printf "No such local unix socket: $local_socket \n"
      return 1
   fi

   #printf -- "$@\x00$local_socket" | /usr/bin/sudo ruby -rsocket -n -e '
   printf -- "$@\x00$local_socket" | ruby -rsocket -n -e '
      args = $_.split(/\000/, 2)
      unix_socket = UNIXSocket::open(args.last)
      unix_socket.send(args.first, 0)
      print unix_socket.recvfrom(1000).first
      unix_socket.close
   '

return 0
}

clamd_local_socket PING
clamd_local_socket SHUTDOWN


function clamavadmin_perms() {

   if [[ -d "/private/var/clamavadmin" ]]; then
      printf '\nSetting permissions in the clamavadmin directory: /private/var/clamavadmin\n\n'
   else
      printf '\nNo clamavadmin directory at: /private/var/clamavadmin\n\n'
      return 1
   fi

   declare sudo=/usr/bin/sudo

   $sudo /bin/mkdir -p /private/var/clamavadmin/log
   $sudo /bin/mkdir -p /private/var/clamavadmin/tmp
   $sudo /bin/mkdir -p /private/var/clamavadmin/share/clamav   # ClamAV database directory
   $sudo /usr/bin/touch /private/var/clamavadmin/log/clamd.log 
   $sudo /usr/bin/touch /private/var/clamavadmin/log/freshclam.log

   $sudo /usr/sbin/chown -R clamavadmin:clamavadmin /private/var/clamavadmin
   $sudo /bin/chmod -R 0750 /private/var/clamavadmin 
   #$sudo /bin/chmod -R 0770 /private/var/clamavadmin   # for debugging only
   $sudo /bin/chmod 0777 /private/var/clamavadmin/tmp/clamd 2>/dev/null  # local unix socket file
   $sudo /usr/bin/find /private/var/clamavadmin -print0 | /usr/bin/xargs -0 $sudo /bin/ls -ldG
   return 0
}


# restart clamd after SHUTDOWN (socket file removed)
#if [[ -e "/private/var/clamavadmin/tmp/clamd" ]]; then sudo /bin/rm -f "/private/var/clamavadmin/tmp/clamd" ; fi
#sudo "$(/usr/bin/which clamd)" -c /private/var/clamavadmin/clamd.conf
#clamavadmin_perms


# get running clamav launchd services
launchctl list | grep -i clam
sudo launchctl list | grep -i clam

launchctl unload -w ~/Library/LaunchAgents/net.clamav.dirwatcher.plist 2>/dev/null
sudo launchctl unload -w /Library/LaunchDaemons/net.clamav.dirwatcherd.plist 2>/dev/null
sudo launchctl unload -w /Library/LaunchDaemons/net.clamav.clamd.plist 2>/dev/null
sudo launchctl unload -w /Library/LaunchDaemons/net.clamav.update.clamd.db.plist 2>/dev/null

# check for: <key>Disabled</key><true/>
open -e ~/Library/LaunchAgents/net.clamav.dirwatcher.plist
sudo nano /Library/LaunchDaemons/net.clamav.dirwatcherd.plist
sudo nano /Library/LaunchDaemons/net.clamav.clamd.plist
sudo nano /Library/LaunchDaemons/net.clamav.update.clamd.db.plist


sudo reboot

export PATH=/usr/local/bin:/usr/local/sbin:/usr/local/lib:/usr/local/include:/usr/bin:/bin:/usr/sbin:/sbin


2. compile & install gawk on Mac OS X

# http://www.gnu.org/software/gawk/
cd ~/Desktop
curl -L -O http://ftp.gnu.org/pub/gnu/gawk/gawk-3.1.6.tar.gz
tar -xzf gawk-3.1.6.tar.gz
cd gawk-3.1.6
./configure --help
./configure --disable-nls --prefix=/usr/local
make
sudo make install
/usr/local/bin/gawk --version


3. compile & install the GNU Multiple Precision Arithmetic Library

# http://gmplib.org
# http://gmplib.org/macos.html

cd ~/Desktop
curl -L -O ftp://ftp.gnu.org/gnu/gmp/gmp-4.2.2.tar.gz   # cf. fwftp, http://textsnippets.com/posts/show/1284
tar -xzf gmp-4.2.2.tar.gz
cd gmp-4.2.2

./configure --help
./configure

make
make check
sudo make install

# test
sudo find /usr/local -iregex ".*gmp.*" -print0 | xargs -0 sudo ls -ldG
otool -Lv /usr/local/lib/libgmp.3.4.2.dylib


4. create ClamAV user & group

# to set up a ClamAV user & group run the first script from: http://textsnippets.com/posts/show/1405

#--------------------------------------------------

You are going to create a system service agent account!

Enter first name: clamavadmin

Note: The last name is optional and defaults to "agent" if you just press <return>!
Enter last name: 

Note: The user shell is optional and defaults to "/usr/bin/false" if you just press <return>!
Enter user shell: /bin/bash

Note: The home directory is optional and defaults to "/private/var/empty" if you just press <return>!
Enter home directory: /private/var/clamavadmin

System service agent account:  clamavadmin  successfully created!

#--------------------------------------------------


sudo mkdir -p /private/var/clamavadmin/log
sudo touch /private/var/clamavadmin/log/clamd.log 
sudo touch /private/var/clamavadmin/log/freshclam.log
sudo mkdir -p /private/var/clamavadmin/tmp

# make sure permissions are set correctly in /private/var/clamavadmin
clamavadmin_perms   # see function above


# add clamavadmin to group admin and group $(logname)
# add $(logname) to group clamavadmin
sudo dscl . -append /Groups/admin GroupMembership clamavadmin
sudo dscl . -append /Groups/$(logname) GroupMembership clamavadmin
sudo dscl . -append /Groups/clamavadmin GroupMembership $(logname)

#sudo dscl . -delete /Groups/admin GroupMembership clamavadmin 
#sudo dscl . -delete /Groups/$(logname) GroupMembership clamavadmin  
#sudo dscl . -delete /Groups/clamavadmin GroupMembership $(logname)   

# test
dscl . -list /Users  | grep -i clamav
dscl . -list /Groups  | grep -i clamav

dscl . -read  /Users/clamavadmin uid
dscl . -read  /Groups/clamavadmin gid

dscl . -search /Groups GroupMembership clamavadmin
printf -- "$(dscl . -search /Groups GroupMembership clamavadmin | awk '{print $1}' | tr '\n' ' ')\n"
id -Gn clamavadmin


5. compile & install ClamAV

# http://wiki.clamav.net/Main/InstallFromSource
# http://downloads.topicdesk.com/docs/Updating_clamav_on_OS_X_Server.pdf
# http://downloads.topicdesk.com/docs/clamav_extras.tar.gz

cd ~/Desktop
open http://freshmeat.net/projects/clamav/
curl -L -O http://freshmeat.net/redir/clamav/29355/url_tgz/clamav-0.92.1.tar.gz
tar -xzf clamav-0.92.1.tar.gz
cd clamav-0.92.1

./configure --help

# Compile bug for clamav 0.92 with latest xcode 
# http://discussions.apple.com/thread.jspa?messageID=6190171
# http://www.mail-archive.com/clamav-users@lists.clamav.net/msg28420.html

CFLAGS="-O0" ./configure \
--prefix=/usr/local --mandir=/usr/local/share/man --sysconfdir=/private/var/clamavadmin \
--with-dbdir=/private/var/clamavadmin/share/clamav --with-datadir=/private/var/clamavadmin/share/clamav \
--with-user=clamavadmin --with-group=clamavadmin \
--enable-bigstack --enable-static --disable-shared

make

sudo make install


# test
man -w    # show directories searched for man pages
man -aW clamd 2>/dev/null
man -aW clamdscan 2>/dev/null
man -aW clamscan 2>/dev/null
man -aW freshclam 2>/dev/null
man -aW clamconf 2>/dev/null


# get an overview of your ClamAV file & folder permissions in /usr/local
sudo find /usr/local -iregex ".*clam.*" -print0 | xargs -0 sudo ls -ldG
#sudo find /usr/local \( -type f -or -type d \) -iregex ".*clam.*" -print0 | xargs -0 sudo ls -ldG

# set ClamAV file & folder permissions in /usr/local
# note: you may not need: -not -name "*.png"
sudo find /usr/local -not -name "*.png" -iregex ".*clam.*" -print0 | xargs -0 sudo chown clamavadmin:clamavadmin
sudo find /usr/local -not -name "*.png" -iregex ".*clam.*" -print0 | xargs -0 sudo chmod 0750

# reset permissions in /usr/local
# note: you may not need: -not -name "*.png"
#sudo find /usr/local  -not -name "*.png" -iregex ".*clam.*" -print0 | xargs -0 sudo chown root:wheel  
#sudo find /usr/local  -not -name "*.png" -iregex ".*clam.*" -print0 | xargs -0 sudo chmod 0755



# /private/var/clamavadmin/clamd.conf

sudo cp -p /private/var/clamavadmin/clamd.conf /private/var/clamavadmin/clamd.conf.orig

sudo sh -c '
cat << EOF > /private/var/clamavadmin/clamd.conf

LogFileMaxSize 10M
LogTime yes
FixStaleSocket yes
TCPAddr 127.0.0.1
MaxConnectionQueueLength 30
MaxThreads 20
ExitOnOOM yes
ScanOLE2 yes  # Microsoft Office documents and .msi files
ScanPDF yes
ArchiveMaxFileSize 100M
ArchiveMaxCompressionRatio 0
#VirusEvent echo virus: %v >> /path/to/file.txt

DatabaseDirectory /private/var/clamavadmin/share/clamav    # hardcoded
LogFile /private/var/clamavadmin/log/clamd.log
TemporaryDirectory /private/var/clamavadmin/tmp
LocalSocket /private/var/clamavadmin/tmp/clamd

EOF
'

sudo nano /private/var/clamavadmin/clamd.conf


# /private/var/clamavadmin/freshclam.conf

sudo cp -p /private/var/clamavadmin/freshclam.conf /private/var/clamavadmin/freshclam.conf.orig 

sudo sh -c '
cat << EOF > /private/var/clamavadmin/freshclam.conf

UpdateLogFile /private/var/clamavadmin/log/freshclam.log
LogFileMaxSize 2M
LogTime yes
LogVerbose yes
DatabaseOwner clamavadmin
Debug yes
NotifyClamd /private/var/clamavadmin/clamd.conf   # send the RELOAD command to clamd
DatabaseDirectory /private/var/clamavadmin/share/clamav    # hardcoded
DatabaseMirror database.clamav.net

#Checks 24   # number of database checks per day
#OnUpdateExecute command
#OnErrorExecute command
#OnOutdatedExecute command   # run command when freshclam reports outdated version
#ConnectTimeout 60
#ReceiveTimeout 60

EOF
'

sudo nano /private/var/clamavadmin/freshclam.conf


/usr/local/bin/clamconf
/usr/local/bin/clamconf -n


# make sure permissions are set correctly in /private/var/clamavadmin
clamavadmin_perms   # see function above


# view clamd.log in another Terminal window
open /bin/bash
sudo tail -n 50 -f /private/var/clamavadmin/log/clamd.log

# view freshclam.log in another Terminal window
open /bin/bash
sudo tail -n 50 -f /private/var/clamavadmin/log/freshclam.log


# test
sudo /usr/local/bin/freshclam -u clamavadmin   # update virus database
sudo /usr/local/bin/clamscan ~/Desktop/clamav-0.92.1/test/*
sudo /usr/local/bin/clamdscan ~/Desktop/clamav-0.92.1/test/*

# now start clamd
if [[ -e "/private/var/clamavadmin/tmp/clamd" ]]; then sudo /bin/rm -f "/private/var/clamavadmin/tmp/clamd" ; fi
sudo /usr/local/sbin/clamd -c /private/var/clamavadmin/clamd.conf

# make sure permissions are set correctly in /private/var/clamavadmin
clamavadmin_perms   # see function above


#--------------------------------------------------


# set up ClamAV launchd items

sudo nano /Library/LaunchDaemons/net.clamav.clamd.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>Disabled</key>
        <true/>
        <key>GroupName</key>
        <string>clamavadmin</string>
        <key>Label</key>
        <string>net.clamav.clamd</string>
        <key>ProgramArguments</key>
        <array>
                <string>/usr/local/sbin/clamd</string>
                <string>-c</string>
                <string>/private/var/clamavadmin/clamd.conf</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>UserName</key>
        <string>clamavadmin</string>
</dict>
</plist>

if [[ -e "/private/var/clamavadmin/tmp/clamd" ]]; then sudo /bin/rm -f "/private/var/clamavadmin/tmp/clamd" ; fi
sudo launchctl load -w /Library/LaunchDaemons/net.clamav.clamd.plist 2>/dev/null
#sudo launchctl unload -w /Library/LaunchDaemons/net.clamav.clamd.plist 2>/dev/null

# make sure permissions are set correctly in /private/var/clamavadmin
clamavadmin_perms   # see function above


#--------------------------------------------------


sudo nano /Library/LaunchDaemons/net.clamav.update.clamd.db.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>Disabled</key>
        <true/>
        <key>GroupName</key>
        <string>clamavadmin</string>
        <key>Label</key>
        <string>net.clamav.update.clamd.db</string>
        <key>ProgramArguments</key>
        <array>
                <string>/private/var/clamavadmin/update_clamd_db.sh</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>StartInterval</key>
        <integer>20000</integer>
        <key>UserName</key>
        <string>clamavadmin</string>
</dict>
</plist>

sudo launchctl load -w /Library/LaunchDaemons/net.clamav.update.clamd.db.plist 2>/dev/null
#sudo launchctl unload -w /Library/LaunchDaemons/net.clamav.update.clamd.db.plist 2>/dev/null

# make sure permissions are set correctly in /private/var/clamavadmin
clamavadmin_perms   # see function above


#--------------------------------------------------


sudo nano /private/var/clamavadmin/update_clamd_db.sh

#!/bin/bash

/bin/sleep 120

exec >/dev/console 2>&1   # write stdout & stderr to console.log

/usr/bin/curl -I -L -s --max-time 15 database.clamav.net 1>/dev/null

if [[ $? -eq 0 ]]; then 

   /bin/sleep 3

   /usr/local/bin/freshclam -u clamavadmin

   /bin/sleep 3

   # cf. /private/var/clamavadmin/freshclam.conf above:
   # NotifyClamd /private/var/clamavadmin/clamd.conf   # send the RELOAD command to clamd

   #echo RELOAD | /opt/local/bin/socat - /private/var/clamavadmin/tmp/clamd
   #/bin/sleep 3
   #echo PING | /opt/local/bin/socat - /private/var/clamavadmin/tmp/clamd
   #/bin/sleep 3

   echo -e "\n$(/bin/date "+%Y-%m-%d %H:%M:%S %Z"): clamd virus database successfully updated\n"
   exit 0

else

   echo -e "\n$(/bin/date "+%Y-%m-%d %H:%M:%S %Z"): updating the clamd virus database failed; no internet connection to database.clamav.net established\n"
   exit 0   # leave launchd item /Library/LaunchDaemons/net.clamav.update.clamd.db.plist undisturbed

fi


#--------------------------------------------------


# make sure permissions are set correctly in /private/var/clamavadmin
clamavadmin_perms   # see function above


#--------------------------------------------------


# cf. http://textsnippets.com/posts/show/1357

sudo nano ~/Documents/ClamAV/watchdirs.sh     

# ...

find=/usr/bin/find
clamdscan=/usr/local/bin/clamdscan
clamscan=/usr/local/bin/clamscan

#clamdscan=/opt/local/bin/clamdscan
#clamscan=/opt/local/bin/clamscan

# ...


#--------------------------------------------------


# cf. http://textsnippets.com/posts/show/1400
open ~/Library/Workflows/Applications/Finder/virusscan.workflow

/usr/local/bin/clamdscan --quiet "$f" 2>/dev/null
#/opt/local/bin/clamdscan --quiet "$f" 2>/dev/null


#--------------------------------------------------

launchctl load -w ~/Library/LaunchAgents/net.clamav.dirwatcher.plist 2>/dev/null
#sudo launchctl load -w /Library/LaunchDaemons/net.clamav.dirwatcherd.plist 2>/dev/null
sudo launchctl load -w /Library/LaunchDaemons/net.clamav.clamd.plist 2>/dev/null
sudo launchctl load -w /Library/LaunchDaemons/net.clamav.update.clamd.db.plist 2>/dev/null


sudo reboot


open -a Console

open /bin/bash
sudo tail -n 50 -f /private/var/clamavadmin/log/clamd.log

open /bin/bash
sudo tail -n 50 -f /private/var/clamavadmin/log/freshclam.log

# make sure permissions are set correctly in /private/var/clamavadmin
clamavadmin_perms   # see function above

sudo find /private/var/clamavadmin -print0 | xargs -0 sudo ls -ldG
sudo find /usr/local -iregex ".*clam.*" -print0 | xargs -0 sudo ls -ldG

You need to create an account or log in to post comments to this site.