#! /bin/sh
#########################################################################
#
# Copyright (c) 2007,2008 Symas Corporation
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
#   notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
#   copyright notice, this list of conditions and the following disclaimer
#   in the documentation and/or other materials provided with the
#   distribution.
# * Neither the name of the Symas Corporation nor the names of its
#   contributors may be used to endorse or promote products derived from
#   this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# This script will source the file pointed to by $KRB_CONF_FILE,
# which can change any of several variables that control the
# way this script behaves.
#

# LSB-style init information:
### BEGIN INIT INFO
# Provides: kadmind
# Required-Start: $network $syslog kdc
# Required-Stop:  $network $syslog kdc
# Default-Start:  
# Default-Stop:   
# Description:    Symas OpenLDAP KAdminD
### END INIT INFO
#
# chkconfig-style init information:
# chkconfig:  61 59
# description: Symas OpenLDAP KAdminD

# set path so HP-UX basename is visible for USAGE
PATH=/usr/bin:$PATH
CONF_DIR=/opt/symas/etc/heimdal
SYSTEMCTL=`which systemctl 2>/dev/null`
if [ -x "$SYSTEMCTL" ]; then
  KRB_CONF_FILE=$CONF_DIR/symas-kadmind.conf
else
  KRB_CONF_FILE=$CONF_DIR/symas-heimdal.conf
fi
KDC_CONF_FILE=$CONF_DIR/krb5.conf
KAD_CONF_FILE=$KDC_CONF_FILE
PROD_NAME="Symas OpenLDAP Kerberos kadmind Service"
USAGE="Usage: `basename $0` {start|stop|status|try-restart|condrestart|restart|force-reload|reload|probe|start_msg|stop_msg} [ -d ]"

# Sane values for things that are usually set in symas-heimdal.conf.
# They'll be overridden when symas-heimdal.conf is sourced.
RUN_KAD=Y
KAD_TIMEOUT=60
KAD_LISTEN_PORTS="+"

# Force a PID file check location.
#KAD_PID_OVERRIDE=/var/symas/run/kadmind.pid

# Basic sanity checking
if [ $# -lt 1 ]; then
  echo $USAGE
  exit 1
fi

# What are we running on?
UNAME=`uname`
if [ "$UNAME" = Linux ]; then
  DIST=unknown
  if [ -r /etc/SuSE-release ]; then
    DIST=SuSE
    test -r /etc/rc.config && . /etc/rc.config
    if [ -r /etc/rc.status ]; then
      . /etc/rc.status
      rc_reset
    fi
    fi
    if [ -r /etc/redhat-release ]; then
      DIST=Redhat
      if [ -r /etc/rc.d/init.d/functions ]; then
        . /etc/rc.d/init.d/functions
      fi
      if [ -f /etc/sysconfig/network ] ; then
        . /etc/sysconfig/network
        [ "${NETWORKING}" = "no" ] && exit 0
      fi
    fi
    # Debian requires no specialization at this time
    if [ -r /etc/debian_version ]; then
      DIST=Debian
    fi
  PRELOAD_STMT="LD_PRELOAD=\$KRB_PRELOAD;export LD_PRELOAD"
fi

# Save off the command and remove it from the cmd line.
CMD="$1"
shift

# "portably" echo without a newline
pecho () {
  if [ "x$(echo -n foo\cbar)x" = "x-n foox" ]; then
    # ancient bourne shells only have \c
    echo $1\\c
  elif [ "x$(echo -n foo\\cbar)x" = "x-n foox" ]; then
    # some shells unquote differently
    echo $1\\c
  elif [ "x$(echo -n foo\cbar)x" = "xfoocbarx" ]; then
    # bash likes it csh style
    echo -n $1
  elif [ "x$(echo -n foo\\cbar)x" = "xfoocbarx" ]; then
    # some shells unquote differently
    echo -n $1
  else
    # ouch
    echo $1
  fi
}

# Signal a failure for our UNAME and DIST.
exit_failed () {
  if [ "$UNAME" = Linux -a "$DIST" = SuSE ]; then
    rc_failed $1
    rc_status -v
    rc_exit
  elif [ "$UNAME" = Linux -a "$DIST" = Redhat ]; then
    echo_failure
    echo
    exit 1
  else
    echo "...  failed."
    exit 1
  fi
}

# Signal failure but exit with success.
exit_disabled () {
  echo "...  ignoring."
  exit 0
}

# Signal a success for our UNAME and DIST
exit_success () {
  if [ "$UNAME" = Linux -a "$DIST" = SuSE ]; then
    rc_status -v
    rc_exit
  elif [ "$UNAME" = Linux -a "$DIST" = Redhat ]; then
    echo_success
    echo
    exit 0
  else
    echo "...  done."
    exit 0
  fi
}

pid_file_fix () {
  if [ -n "$KAD_PID_OVERRIDE" ]; then
    PID_FILE=$KAD_PID_OVERRIDE
    return
  fi

  if [ -f /var/symas/run/${PROC}.pid ]; then
    PID_FILE=/var/symas/run/${PROC}.pid
    return
  fi

  if [ -f /var/symas/${PROC}.pid ]; then
    PID_FILE=/var/symas/${PROC}.pid
    return
  fi
}

# Determine if Symas OpenLDAP Kerberos Server is configured. The installer
# only installs symas-kerberos.conf.default, so a missing symas-kerberos.conf
# is an indicator no one's configured Symas OpenLDAP Kerberos Server. Otherwise,
# go ahead and source the file.
if [ ! -f $KRB_CONF_FILE ]; then
  pecho "$PROD_NAME is not configured"
  exit_disabled
else
  . $KRB_CONF_FILE
fi

EXEC_DIR=$LIB

case `basename $0` in
  *kadmindserver|*KAdminDServer|*kadserver|*KADServer)
    PROC=kadmind
    if [ ! -r $KAD_CONF_FILE ]; then
      pecho "$PROD_NAME $PROC has not been configured"
      exit_disabled
    fi
    RUN=$RUN_KAD
    ;;

  *)
    pecho "$PROD_NAME: $0 is not a recognized link for this script"
    exit_failed 1
    ;;
esac

PID_FILE=/var/symas/run/${PROC}.pid
pid_file_fix #TODO: Remove in future release.

# Determine if the daemon is running. This will set the $PID variable
# to the process ID of the proc if it is, otherwise it'll make it zero
# length.
if [ -f $PID_FILE ]; then
  PID=`cat $PID_FILE`
  ps -p $PID | grep $PROC > /dev/null
  if [ "$?" -ne 0 ]; then
    PID=""
  fi
fi

# Now process the command.
case "$CMD" in
  # Display start/stop messages. HP/UX makes these calls
  start_msg)
    echo "Starting $PROD_NAME $PROC"
    ;;
  stop_msg)
    echo "Stopping $PROD_NAME $PROC"
    ;;

  # Start the server
  start)
    # Check the run flag in the Heimdal config file. If not set to
    # "Y", then we say "not configured to run" and exit with
    # a status of success.
    # We'll also exit with success if the process is already
    # running, saying "already running".
    if [ "$RUN" != "Y" ]; then
      pecho "$PROD_NAME $PROC is not configured to run"
      exit_success
    elif [ -n "$PID" ]; then
      pecho "$PROD_NAME $PROC is already running"
      exit_success
    fi
    rm -f ${PID_FILE}
    pecho "$PROD_NAME $PROC starting"
    if [ "$PROC" = kadmind ]; then
      # Perform a check to see if a preload is being requested and if
      # preloading is supported.
      if [ -n "$KRB_PRELOAD" -a -z "$PRELOAD_STMT" ]; then
        pecho "$PROD_NAME: pre-loading is not supported on this platform."
        exit_failed 1
      elif [ -n "$KRB_PRELOAD" ]; then
        eval $PRELOAD_STMT
      fi
      if [ -x "$SYSTEMCTL" ]; then
        $SYSTEMCTL start kadmind
      else
        nohup "$EXEC_DIR/$PROC" -p "$KAD_LISTEN_PORTS" $EXTRA_KAD_ARGS > /dev/null 2>&1 & echo "$!" > ${PID_FILE} &
      fi

      # TODO: If run without appropriate permissions kadmind exits with
      # status 1 but the script is not picking it up. This fix works but
      # adds a full second to it's run time. Looking at other options for
      # the future. -MSW
      sleep 1
      pid_file_fix #TODO: Remove in future release
      if [ ! -f $PID_FILE ]; then
        exit_failed 1
      fi
    fi
    ;;

  # Stop and restart the server
  restart|force-reload)
    $0 stop; $0 start
    exit $?
    ;;

  # restart the server if it was running
  try-restart|condrestart)
    if [ -z "$PID" ]; then
      pecho "$PROD_NAME $PROC is not running"
      exit_failed 7
    fi
    $0 stop && $0 start
    exit $?
    ;;

  # Stop the server
  stop)
    if [ -z "$PID" ]; then
      pecho "$PROD_NAME $PROC is not running"
      exit_success
    fi
    pecho "$PROD_NAME $PROC stopping"
    if [ -x "$SYSTEMCTL" ]; then
      $SYSTEMCTL stop kadmind
    else
      kill $PID
      if [ $? -gt 0 ]; then
        pecho "$PROD_NAME $PROC stopping: kill failed"
        exit_failed 1
      fi
      elapsed=0
      if [ "$PROC" = kadmind ]; then
        timeout=$KAD_TIMEOUT
      fi
      while kill -0 "$PID" 2>/dev/null; do
        pecho "."
        sleep 1
        elapsed=`expr $elapsed + 1`
        if [ $elapsed -gt $timeout ]; then
          exit_failed 1
        fi
      done
      rm -f $PID_FILE 2>/dev/null
    fi
    exit_success
    ;;

  # Report the status of the server
  status)
    if [ -z "$PID" ]; then
      NOT=" not"
    fi
    pecho "$PROD_NAME $PROC is${NOT} running"
    if [ "$UNAME" = Linux -a "$DIST" = SuSE ]; then
      if [ -z "$PID" ]; then
        rc_failed 3
      else
        rc_failed 0
      fi
        rc_status -v
        rc_exit
    else
      echo
      exit 0
    fi
    ;;

  reload)
    pecho "$PROD_NAME $PROC must use restart"
    exit_failed 3
    ;;

  probe)
    if [ "$UNAME" = Linux ]; then
      # -nt is a bashism
      if [ "$KAD_CONF_FILE" -nt "$PID_FILE" ]; then
        echo restart
      fi
    else
      # well, no one else is likely to call probe, but...
      echo restart
    fi
    exit 0
    ;;

  # For starting directly under init, like AIX
  underinit)
    exec "$EXEC_DIR/$PROC" -p "$KAD_LISTEN_PORTS" $ARGS &
    exit 1
    ;;

  *)
    echo $USAGE
    exit 1
    ;;
esac

if [ "$?" != 0 ]; then
  exit_failed 1
else
  exit_success
fi
exit 0
