#! /bin/sh # Written by Miquel van Smoorenburg . # Modified for Debian GNU/Linux # by Ian Murdock . # Clamav version by Magnus Ekdahl # Heavily reworked by Stephen Gran # ### BEGIN INIT INFO # Provides: clamav-daemon # Required-Start: $remote_fs $syslog # Should-Start: # Required-Stop: $remote_fs $syslog # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: ClamAV daemon # Description: Clam AntiVirus userspace daemon ### END INIT INFO PATH=/sbin:/bin:/usr/sbin:/usr/bin DAEMON=/usr/sbin/clamd NAME="clamd" DESC="ClamAV daemon" CLAMAVCONF=/etc/clamav/clamd.conf SUPERVISOR=/usr/bin/daemon SUPERVISORNAME=daemon SUPERVISORPIDFILE="/var/run/clamav/daemon-clamd.pid" SUPERVISORARGS="--name=$NAME --respawn $DAEMON -F $SUPERVISORPIDFILE" DATABASEDIR="/var/lib/clamav" [ -x "$DAEMON" ] || exit 0 [ -r /etc/default/clamav-daemon ] && . /etc/default/clamav-daemon status_of_proc () { local pidfile daemon name status pidfile= OPTIND=1 while getopts p: opt ; do case "$opt" in p) pidfile="$OPTARG";; esac done shift $(($OPTIND - 1)) if [ -n "$pidfile" ]; then pidfile="-p $pidfile" fi daemon="$1" name="$2" status="0" pidofproc $pidfile $daemon >/dev/null || status="$?" if [ "$status" = 0 ]; then log_success_msg "$name is running" return 0 else log_failure_msg "$name is not running" return $status fi } to_lower() { word="$1" lcword=$(echo "$word" | tr A-Z a-z) echo "$lcword" } is_true() { var="$1" lcvar=$(to_lower "$var") [ 'true' = "$lcvar" ] || [ 'yes' = "$lcvar" ] || [ 1 = "$lcvar" ] return $? } is_false() { var="$1" lcvar=$(to_lower "$var") [ 'false' = "$lcvar" ] || [ 'no' = "$lcvar" ] || [ 0 = "$lcvar" ] return $? } ucf_cleanup() { # This only does something if I've fucked up before # Not entirely impossible :( configfile=$1 if [ `grep "$configfile" /var/lib/ucf/hashfile | wc -l` -gt 1 ]; then grep -v "$configfile" /var/lib/ucf/hashfile > /var/lib/ucf/hashfile.tmp grep "$configfile" /var/lib/ucf/hashfile | tail -n 1 >> /var/lib/ucf/hashfile.tmp mv /var/lib/ucf/hashfile.tmp /var/lib/ucf/hashfile fi } add_to_ucf() { configfile=$1 ucffile=$2 if ! grep -q "$configfile" /var/lib/ucf/hashfile; then md5sum $configfile >> /var/lib/ucf/hashfile cp $configfile $ucffile fi } ucf_upgrade_check() { configfile=$1 sourcefile=$2 ucffile=$3 if [ -f "$configfile" ]; then add_to_ucf $configfile $ucffile ucf --three-way --debconf-ok "$sourcefile" "$configfile" else [ -d /var/lib/ucf/cache ] || mkdir -p /var/lib/ucf/cache cp $sourcefile $configfile add_to_ucf $configfile $ucffile fi } slurp_config() { CLAMAVCONF="$1" if [ -e "$CLAMAVCONF" ]; then for variable in `egrep -v '^[[:space:]]*(#|$)' "$CLAMAVCONF" | awk '{print $1}'`; do case "$variable" in DatabaseMirror) if [ -z "$DatabaseMirror" ]; then for i in `grep ^$variable $CLAMAVCONF | awk '{print $2}'`; do value="$value $i" done else continue fi ;; DatabaseCustomURL) if [ -z "$DatabaseCustomURL" ]; then for i in `grep ^$variable $CLAMAVCONF | awk '{print $2}'`; do value="$value $i" done else continue fi ;; IncludePUA) if [ -z "$IncludePUA" ]; then for i in `grep ^$variable $CLAMAVCONF | awk '{print $2}'`; do value="$i $value" done else continue fi ;; ExcludePUA) if [ -z "$ExcludePUA" ]; then for i in `grep ^$variable $CLAMAVCONF | awk '{print $2}'`; do value="$i $value" done else continue fi ;; ExtraDatabase) if [ -z "$ExtraDatabase" ]; then for i in `grep ^$variable $CLAMAVCONF | awk '{print $2}'`; do value="$value $i" done else continue fi ;; VirusEvent|OnUpdateExecute|OnErrorExecute|RejectMsg) value=`grep ^$variable $CLAMAVCONF | head -n1 | sed -e s/$variable\ //` ;; *) value=`grep ^$variable $CLAMAVCONF | head -n1 | awk '{print $2}'` ;; esac if [ -z "$value" ]; then export "$variable"="true" elif [ "$value" != "$variable" ]; then export "$variable"="$value" else export "$variable"="true" fi unset value done fi } make_dir() { DIR=$1 if [ -d "$DIR" ]; then return 0; fi [ -n "$User" ] || User=clamav mkdir -p -m 0755 "$DIR" chown "$User" "$DIR" } # Debconf Functions isdigit () { case $1 in [[:digit:]]*) ISDIGIT=1 ;; *) ISDIGIT=0 ;; esac } inputdigit () { ISDIGIT=0 while [ "$ISDIGIT" = '0' ]; do db_input "$1" "$2" || true if ! db_go; then return 30 fi db_get $2 || true isdigit $RET if [ "$ISDIGIT" = '0' ]; then db_input critical clamav-base/numinfo || true db_go fi done return 0 } StateGeneric() { PRIO=$1 QUESTION=$2 NEXT=$3 LAST=$4 db_input $PRIO $QUESTION || true if db_go; then STATE=$NEXT else STATE=$LAST fi } StateGenericDigit() { PRIO=$1 QUESTION=$2 NEXT=$3 LAST=$4 inputdigit $PRIO $QUESTION || true if db_go; then STATE=$NEXT else STATE=$LAST fi } . /lib/lsb/init-functions if [ ! -f "$CLAMAVCONF" ]; then log_failure_msg "There is no configuration file for Clamav." log_failure_msg "Please either dpkg-reconfigure $DESC, or copy the example from" log_failure_msg "/usr/share/doc/clamav-base/examples/ to $CLAMAVCONF and run" log_failure_msg "'/etc/init.d/clamav-daemon start'" exit 1; fi slurp_config "$CLAMAVCONF" if [ -n "$Example" ]; then log_failure_msg "Clamav is not configured." log_failure_msg "Please edit $CLAMAVCONF and run '/etc/init.d/clamav-daemon start'" exit 0 fi if is_true "$Foreground"; then if [ ! -x "$SUPERVISOR" ] ; then log_failure_msg "Foreground specified, but $SUPERVISORNAME not found" exit 0 else RUN_SUPERVISED=1 fi fi [ -n "$User" ] || User=clamav [ -n "$DataBaseDirectory" ] || DataBaseDirectory=/var/run/clamav make_dir "$DataBaseDirectory" make_dir $(dirname "$SUPERVISORPIDFILE") THEPIDFILE="`grep ^PidFile $CLAMAVCONF | awk '{print $2}'`" [ -n "$THEPIDFILE" ] || THEPIDFILE='/var/run/clamav/clamd.pid' make_dir $(dirname "$THEPIDFILE") chown $User $(dirname "$THEPIDFILE") if [ -f "$THEPIDFILE" ]; then CLAMDPID=`pidofproc -p $THEPIDFILE $DAEMON` RUNNING=$? else CLAMDPID=`pidofproc $DAEMON` RUNNING=$? fi if [ -z "$RUN_SUPERVISED" ]; then PID="$CLAMDPID" else [ -e "$SUPERVISORPIDFILE" ] && PID=`cat $SUPERVISORPIDFILE` fi [ "$PID" = '1' ] && unset PID case "$1" in start) OPTIND=1 # Check for database existance (start will fail if it's missing) for db in main daily; do if [ ! -e "$DATABASEDIR"/"$db".cvd ] && [ ! -d "$DATABASEDIR"/"$db".inc ] && [ ! -e "$DATABASEDIR"/"$db".cld ]; then log_failure_msg "Clamav signatures not found in $DATABASEDIR" log_failure_msg "Please retrieve them using freshclam or install the clamav-data package" log_failure_msg "Then run '/etc/init.d/clamav-daemon start'" exit 0 fi done if [ -z "$RUN_SUPERVISED" ] ; then log_daemon_msg "Starting $DESC" "$NAME " start-stop-daemon --start -o -c $User --exec $DAEMON ret=$? else log_daemon_msg "Starting $DESC" "$NAME (supervised) " $SUPERVISOR $SUPERVISORARGS ret=$? fi log_end_msg $ret ;; stop) log_daemon_msg "Stopping $DESC" "$NAME" OPTIND=1 if [ -n "$PID" ]; then kill -15 -"$PID" ret=$? sleep 1 if kill -0 "$PID" 2>/dev/null; then ret=$? log_progress_msg "Waiting . " cnt=0 while kill -0 "$PID" 2>/dev/null; do ret=$? cnt=`expr "$cnt" + 1` if [ "$cnt" -gt 15 ]; then kill -9 -"$PID" break fi sleep 2 log_progress_msg ". " done fi else if [ -z "$RUN_SUPERVISED" ] ; then killproc -p $THEPIDFILE ret=$? else killproc -p $SUPERVISORPIDFILE ret=$? fi fi if [ -n "$ret" ]; then log_end_msg $ret else log_end_msg $? fi ;; status) status_of_proc "$DAEMON" "$NAME" exit $? ;; restart|force-reload) $0 stop $0 start ;; reload-database) OPTIND=1 log_daemon_msg "Reloading database for $DESC" "$NAME" if [ "$RUNNING" = 0 ] && [ -n "$CLAMDPID" ]; then kill -USR2 $CLAMDPID fi log_end_msg $? ;; reload-log) OPTIND=1 log_daemon_msg "Reloading log file for $DESC" "$NAME" if [ "$RUNNING" = 0 ] && [ -n "$CLAMDPID" ]; then kill -HUP $CLAMDPID fi log_end_msg $? ;; *) log_failure_msg "Usage: $0 {start|stop|restart|force-reload|reload-log|reload-database|status}" >&2 exit 1 ;; esac exit 0