#! /bin/sh
#
# bacula       This shell script takes care of starting and stopping
#	       the bacula daemons.
#
#   This is pretty much watered down version of the RedHat script
#   that works on Solaris as well as Linux, but it won't work everywhere.
#
# description: It comes by night and sucks the vital essence from your computers.
#

PSCMD="ps -e -o pid,command"

#
# On Solaris, you may need to use nawk, or alternatively,
#  add the GNU binaries to your path, such as /usr/xpg4/bin
#
AWK=/usr/bin/gawk

# All these are not *really* needed but it makes it
#  easier to "steal" this code for the development 
#  environment where they are different.
#  
BACFDBIN=/usr/sbin
BACFDCFG=/etc/bacula
BACSDBIN=/usr/sbin
BACSDCFG=/etc/bacula
BACDIRBIN=/usr/sbin
BACDIRCFG=/etc/bacula
PIDDIR=/var/run
SUBSYSDIR=/var/run/subsys

DIR_PORT=9101
FD_PORT=9102
SD_PORT=9103

DIR_USER=
DIR_GROUP=
FD_USER=
FD_GROUP=
SD_USER=
SD_GROUP=

PIDOF=/bin/pidof	

# A function to stop a program.
killproc() {
    RC=0
    # Test syntax.
    if [ $# = 0 ]; then
	echo "Usage: killproc {program} [signal]"
	return 1
    fi

    notset=0
    # check for third arg to be kill level
    if [ "$3" != "" ] ; then
	killlevel=$3
    else
	notset=1
	killlevel="-9"
    fi

    # Get base program name
    base=`basename $1`

    # Find pid.
    pid=`pidofproc $base $2`

    # Kill it.
    if [ "$pid" != "" ] ; then
	if [ "$notset" = "1" ] ; then
	    if ps -p $pid>/dev/null 2>&1; then
		# TERM first, then KILL if not dead
		kill -TERM $pid 2>/dev/null
		sleep 1
		if ps -p $pid >/dev/null 2>&1 ; then
		    sleep 1
		    if ps -p $pid >/dev/null 2>&1 ; then
			sleep 3
			if ps -p $pid >/dev/null 2>&1 ; then
			    kill -KILL $pid 2>/dev/null
			fi
		    fi
		fi
	     fi
	     ps -p $pid >/dev/null 2>&1
	     RC=$?
	     [ $RC -eq 0 ] && failure "$base shutdown" || success "$base shutdown"
	#    RC=$((! $RC))
	# use specified level only
	else
	    if ps -p $pid >/dev/null 2>&1; then
		kill $killlevel $pid 2>/dev/null
		RC=$?
		[ $RC -eq 0 ] && success "$base $killlevel" || failure "$base $killlevel"
	    fi
	fi
    else
	failure "$base shutdown"
    fi
    # Remove pid file if any.
    if [ "$notset" = "1" ]; then
	rm -f ${PIDDIR}/$base.$2.pid
    fi
    return $RC
}

# A function to find the pid of a program.
pidofproc() {
    pid=""
    # Test syntax.
    if [ $# = 0 ] ; then
	echo "Usage: pidofproc {program}"
	return 1
    fi

    # Get base program name
    base=`basename $1`

    # First try PID file
    if [ -f ${PIDDIR}/$base.$2.pid ] ; then
	pid=`head -n 1 ${PIDDIR}/$base.$2.pid`
	if [ "$pid" != "" ] ; then
	    echo $pid
	    return 0
	fi
    fi

    # Next try "pidof"
   if [ -x ${PIDOF} ] ; then
       pid=`${PIDOF} $1`
   fi
   if [ "$pid" != "" ] ; then
       echo $pid
       return 0
   fi

    # Finally try to extract it from ps
    ${PSCMD} | grep $1 | ${AWK} '{ print $1 }' | tr '\n' ' '
    return 0
}

status() {
    pid=""
    # Test syntax.
    if [ $# = 0 ] ; then
	echo "Usage: status {program}"
	return 1
    fi

    # Get base program name
    base=`basename $1`

   # First try "pidof"
   if [ -x ${PIDOF} ] ; then
       pid=`${PIDOF} $1`
   fi
   if [ "$pid" != "" ] ; then
       echo "$base (pid $pid) is running..."
       return 0
   else
       pid=`${PSCMD} | ${AWK} 'BEGIN { prog=ARGV[1]; ARGC=1 } 
	     { if ((prog == $2) || (("(" prog ")") == $2) ||
		  (("[" prog "]") == $2) ||
		  ((prog ":") == $2)) { print $1 ; exit 0 } }' $1`
       if [ "$pid" != "" ] ; then
	   echo "$base (pid $pid) is running..."
	   return 0
       fi
   fi

    # Next try the PID files
    if [ -f ${PIDDIR}/$base.$2.pid ] ; then
	pid=`head -n 1 ${PIDDIR}/$base.$2.pid`
	if [ "$pid" != "" ] ; then
	    echo "$base dead but pid file exists"
	    return 1
	fi
    fi
    # See if the subsys lock exists
    if [ -f ${SUBSYSDIR}/$base ] ; then
	echo "$base dead but subsys locked"
	return 2
    fi
    echo "$base is stopped"
    return 3
}

success() {
  return 0
}

failure() {
  rc=$?
  return $rc
}

OS=`uname -s`

# if /lib/tls exists, force Bacula to use the glibc pthreads instead
if [ -d "/lib/tls" -a $OS = "Linux" ] ; then
     export LD_ASSUME_KERNEL=2.4.19
fi

case "$1" in
    start)
       [ -x ${BACSDBIN}/bacula-sd ] && {
	  echo "Starting the Bacula Storage daemon"
	  OPTIONS=''
	  if [ "${SD_USER}" != '' ]; then
	     OPTIONS="${OPTIONS} -u ${SD_USER}"
	  fi

	  if [ "${SD_GROUP}" != '' ]; then
	     OPTIONS="${OPTIONS} -g ${SD_GROUP}"
	  fi

	  ${BACSDBIN}/bacula-sd $2 ${OPTIONS} -v -c ${BACSDCFG}/bacula-sd.conf
       }

       [ -x ${BACFDBIN}/bacula-fd ] && {
	  echo "Starting the Bacula File daemon"
	  OPTIONS=''
	  if [ "${FD_USER}" != '' ]; then
	     OPTIONS="${OPTIONS} -u ${FD_USER}"
	  fi

	  if [ "${FD_GROUP}" != '' ]; then
	     OPTIONS="${OPTIONS} -g ${FD_GROUP}"
	  fi

	  ${BACFDBIN}/bacula-fd $2 ${OPTIONS} -v -c ${BACFDCFG}/bacula-fd.conf
       }

       [ -x ${BACDIRBIN}/bacula-dir ] && { 
	   sleep 2
	   echo "Starting the Bacula Director daemon"
	  OPTIONS=''
	  if [ "${DIR_USER}" != '' ]; then
	     OPTIONS="${OPTIONS} -u ${DIR_USER}"
	  fi

	  if [ "${DIR_GROUP}" != '' ]; then
	     OPTIONS="${OPTIONS} -g ${DIR_GROUP}"
	  fi

	  ${BACDIRBIN}/bacula-dir $2 ${OPTIONS} -v -c ${BACDIRCFG}/bacula-dir.conf
       }
       ;;

    stop)
       # Stop the FD first so that SD will fail jobs and update catalog
       [ -x ${BACFDBIN}/bacula-fd ] && {
	  echo "Stopping the Bacula File daemon"
	  killproc ${BACFDBIN}/bacula-fd ${FD_PORT}
       }

       [ -x ${BACSDBIN}/bacula-sd ] && {
	  echo "Stopping the Bacula Storage daemon"
	  killproc ${BACSDBIN}/bacula-sd ${SD_PORT}
       }

       [ -x ${BACDIRBIN}/bacula-dir ] && {
	  echo "Stopping the Bacula Director daemon"
	  killproc ${BACDIRBIN}/bacula-dir ${DIR_PORT}
       }
       echo
       ;;

    restart)
       $0 stop
       sleep 5
       $0 start
       ;;

    status)
       [ -x ${BACSDBIN}/bacula-sd   ] && status ${BACSDBIN}/bacula-sd  ${SD_PORT}
       [ -x ${BACFDBIN}/bacula-fd   ] && status ${BACFDBIN}/bacula-fd  ${FD_PORT}
       [ -x ${BACDIRBIN}/bacula-dir ] && status ${BACDIRBIN}/bacula-dir ${DIR_PORT}
       ;;

    *)
       echo "Usage: $0 {start|stop|restart|status}"
       exit 1
       ;;
esac
exit 0
