File: //lib/MailScanner/init/msmilter-init
#!/bin/bash
# This script provides MSMilter daemon initialization across
# multiple Unices.
#
# Author: Shawn Iverson <shawniverson@efa-project.org>
# 20 Aug 2018
# The below block contains various items for different Unices
# Some are required based on OS, so do not change them.
# $FreeBSD$
#
# PROVIDE: MSMilter
# Debian
#
### BEGIN INIT INFO
# Provides: MSMilter
# Required-Start: $remote_fs $network $syslog
# Required-Stop: $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: MSMilter daemon
# Description: starts MSMilter using internal daemon mechanism
### END INIT INFO
# RHEL
#
# chkconfig: 345 80 20
# description: MSMilter daemon
# processname: MSMilter
PATH=$PATH:/usr/sbin:/usr/bin:/bin:/sbin
export PATH
NAME=MSMilter
DAEMON=/usr/sbin/MSMilter
QUICKPEEK=/usr/sbin/ms-peek
ms_conf=/etc/MailScanner/MailScanner.conf
# enable logging of non-critical notices to the maillog: yes/no
VERBOSE=yes
# basic config file
if [ -f /etc/MailScanner/defaults ] ; then
. /etc/MailScanner/defaults
else
echo "Aborted: missing configuration file /etc/MailScanner/defaults"
exit 1
fi
# Exit if the MSMilter executable is not installed
[ -x $DAEMON ] || exit 0
[ -d /var/run ] || mkdir -p /var/run
# Don't start if MailScanner is not configured
if [ $run_mailscanner = 0 ]; then
cat <<-EOF
Edit the file /etc/MailScanner/MailScanner.conf according to
your needs. When complete, edit /etc/MailScanner/defaults and set
the variable to enable MailScanner to run:
run_mailscanner=1
EOF
exit 0
fi
PIDFILE="`${QUICKPEEK} MilterPIDFile ${ms_conf}`"
if [ -z $PIDFILE ]; then
PIDFILE="/var/run/MSMilter.pid"
fi
#
# Function that starts the daemon/service
#
do_start()
{
# Return
# 0 if daemon has been started
# 2 if daemon could not be started
# 3 unknown error
# check if the daemon is already running
# should have already been checked in the CASE
# statement below
# starts the daemon
$DAEMON $ms_conf
RETVAL="$?"
if [ $RETVAL -eq 0 ]; then
return 0
else
# unable to start the daemon
return 2
fi
# we should never get this far
return 3
}
#
# Function that stops the daemon/service
#
do_stop()
{
# Return
# 0 if daemon has been stopped
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
# 3 unknown error
# get the PID
if [ -f $PIDFILE ] ; then
PID=$(head -n 1 $PIDFILE)
else
# no pid
PID=
fi
# no pid so MSMilter should not be running
if [ "x$PID" = "x" ]; then
return 1
else
ps wwp $PID|grep -q '[M]SMilter' > /dev/null 2>&1
RETVAL="$?"
fi
if [ $RETVAL -eq 0 ]; then
# MSMilter is running. kill it
kill -15 $PID
# Check again, up to 1.5 ish minutes
COUNTER=0
while [ $COUNTER -lt 40 ]; do
ps wwp $PID|grep -q '[M]SMilter' > /dev/null 2>&1
RETVAL="$?"
if [[ $RETVAL -eq 0 ]]; then
COUNTER=$((COUNTER+1))
sleep 2
else
COUNTER=40
fi
done
if [ $RETVAL -eq 0 ]; then
# Process never stopped
do_deadpid
RETVAL="$?"
if [ $RETVAL -eq 1 ]; then
return 2
else
return 0
fi
fi
# remove pid file
if [ -f $PIDFILE ] ; then
rm -f $PIDFILE
fi
# Stop successful
return 0
else
# MSMilter not running but PID is present
do_deadpid
RETVAL="$?"
if [ $RETVAL -eq 0 ]; then
# Successfully removed dead PID
return 1
else
# Unable to stop
return 2
fi
fi
# we should never get this far
return 3
}
#
# Function to handle a dead PID/rogue MSMilter processes
#
# Returns: 1 if unable to stop rogue processes gracefully
# 0 if success
do_deadpid()
{
[ "$VERBOSE" != no ] && logger -i -p mail.notice "Found a possible dead PID. Stopping all $NAME rogue processes ..."
kill -15 $(ps axww | grep '[M]SMilter' | awk '{print $1}') > /dev/null 2>&1
# Check again
if [ $(ps axww | grep -q '[M]SMilter' ) ]; then
# Unable to stop rogue processes
return 1
fi
if [ -f $PIDFILE ] ; then
rm -f $PIDFILE
fi
return 0
}
case "$1" in
start)
# check if a PID file exists
if [ -f $PIDFILE ] ; then
# get the PID
PID=$(head -n 1 $PIDFILE)
# check to see if running and belongs to MSMilter
ps wwp $PID|grep -q '[M]SMilter' > /dev/null 2>&1
# get the return
RETVAL="$?"
# if 0 it is already running
if [ $RETVAL -eq 0 ]; then
echo "$NAME is already running"
exit 0
else
do_deadpid
RETVAL="$?"
if [ $RETVAL -eq 1 ]; then
# Rogue process(es) detected, could not kill automatically
echo "$NAME is defunct, use 'kill' option to remove any rogue processes."
exit 1
fi
fi
fi
[ "$VERBOSE" != no ] && logger -i -p mail.notice "Starting $NAME "
# make sure the correct permissions are set
echo "$NAME starting ... "
sleep 1
do_start
STARTRETVAL="$?"
if [ $STARTRETVAL -eq 0 ]; then
[ "$VERBOSE" != no ] && logger -i -p mail.notice "$NAME started"
sleep 1;
PID=$(head -n 1 $PIDFILE)
echo "$NAME started with process id $PID"
else
logger -i -p mail.notice "$NAME failed to start"
do_deadpid
exit 1
fi
;;
stop)
[ "$VERBOSE" != no ] && logger -i -p mail.notice "Stopping $NAME "
do_stop
RETVAL="$?"
# error in do_stop - this should never trigger
if [ $RETVAL -eq 3 ]; then
echo "There was a fatal error in stopping the daemon. Use the"
echo "'kill' option to force any running processes to stop."
exit 1
fi
# MSMilter could not be stopped
if [ $RETVAL -eq 2 ]; then
logger -i -p mail.notice "WARN: $NAME $DESC could not be stopped"
echo "ERROR: Unable to stop $NAME"
echo "ERROR: Use the 'kill' option to force stop"
exit 1
fi
# MSMilter was not running
if [ $RETVAL -eq 1 ]; then
echo "$NAME is already stopped"
exit 0
fi
# successfully stopped
if [ $RETVAL -eq 0 ]; then
[ "$VERBOSE" != no ] && logger -i -p mail.notice "$NAME stopped"
echo "$NAME stopped"
fi
;;
status)
if [ -f $PIDFILE ] ; then
# get the PID
PID=$(head -n 1 $PIDFILE)
# check to see if running and belongs to MSMilter
ps wwp $PID|grep -q '[M]SMilter' > /dev/null 2>&1
# get the return
RETVAL="$?"
# if 0 it is already running
if [ $RETVAL -eq 0 ]; then
echo "$NAME is running under process id $PID"
exit 0
else
do_deadpid
RETVAL="$?"
if [ $RETVAL -eq 0 ]; then
echo "$NAME had a dead PID. Any rogue processes were killed."
else
# Rogue process(es) detected, could not kill automatically
echo "$NAME is defunct, use 'kill' option to remove any rogue processes."
exit 1
fi
fi
fi
echo "$NAME is not running"
exit 0
;;
restart)
echo "Restarting $NAME ..."
[ "$VERBOSE" != no ] && logger -i -p mail.notice "Restarting $NAME "
do_stop
RETVAL="$?"
# error in do_stop - this should never trigger
if [ $RETVAL -eq 3 ]; then
echo "There was a fatal error in restarting the daemon. Use the"
echo "'kill' option to force any running processes to stop and then start."
exit 1
fi
# MSMilter could not be stopped
if [ $RETVAL -eq 2 ]; then
echo "ERROR: Unable to restart $NAME"
echo "ERROR: Use the 'kill' option to force stop and then start."
exit 1
fi
do_start
STARTRETVAL="$?"
if [ $STARTRETVAL -eq 0 ]; then
if [ -f $PIDFILE ] ; then
[ "$VERBOSE" != no ] && logger -i -p mail.notice "$NAME restarted"
PID=$(head -n 1 $PIDFILE)
echo "$NAME restarted with process id $PID"
exit 0
else
logger -i -p mail.notice "$NAME failed to start"
echo "$NAME failed to start ... doh!"
exit 1
fi
else
logger -i -p mail.notice "$NAME failed to start"
echo "$NAME failed to start ... doh!"
do_deadpid
exit 1
fi
;;
reload)
echo "Reloading $NAME ..."
[ "$VERBOSE" != no ] && logger -i -p mail.notice "Reloading $NAME "
do_stop
RETVAL="$?"
# error in do_stop - this should never trigger
if [ $RETVAL -eq 3 ]; then
echo "There was a fatal error in restarting the daemon. Use the"
echo "'kill' option to force any running processes to stop and then start."
exit 1
fi
# MSMilter could not be stopped
if [ $RETVAL -eq 2 ]; then
echo "ERROR: Unable to restart $NAME"
echo "ERROR: Use the 'kill' option to force stop and then start."
exit 1
fi
do_start
STARTRETVAL="$?"
if [ $STARTRETVAL -eq 0 ]; then
if [ -f $PIDFILE ] ; then
[ "$VERBOSE" != no ] && logger -i -p mail.notice "$NAME restarted"
PID=$(head -n 1 $PIDFILE)
echo "$NAME restarted with process id $PID"
exit 0
else
logger -i -p mail.notice "$NAME failed to start"
echo "$NAME failed to start ... doh!"
exit 1
fi
else
logger -i -p mail.notice "$NAME failed to start"
do_deadpid
exit 1
fi
;;
kill)
[ "$VERBOSE" != no ] && logger -i -p mail.notice "Killing $NAME "
echo "Killing $NAME and children ... mwa ha ha ha!"
kill -9 $(ps axww | grep '[M]SMilter' | awk '{print $1}') > /dev/null 2>&1
# remove pid file
if [ -f $PIDFILE ] ; then
rm -f $PIDFILE
fi
# create stopped file
touch $stopped_lockfile
;;
*)
echo " Usage: { start | stop | reload | restart | kill | status }" >&2
exit 3
;;
esac
exit 0