#!/bin/bash
#
# ***** BEGIN LICENSE BLOCK *****
# Zimbra Collaboration Suite Server
# Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Synacor, Inc.
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software Foundation,
# version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
# You should have received a copy of the GNU General Public License along with this program.
# If not, see <https://www.gnu.org/licenses/>.
# ***** END LICENSE BLOCK *****
#

PID=""
PIDFILE="/opt/zimbra/data/ldap/state/run/slapd.pid"

mkdir -p "/opt/zimbra/data/ldap/state/run/"

source /opt/zimbra/bin/zmshutil || exit 1
zmsetvars

if [ "x$ldap_is_master" = "xfalse" ]; then
    if [ "x$ldap_url" = "x$ldap_master_url" ] && [ "x$1" != "xstop" ]; then
        echo "ldap_url and ldap_master_url cannot be the same on an ldap replica"
        exit 1
    fi
fi

getpid()
{
    if [ -f $PIDFILE ]; then
        PID=$(cat $PIDFILE)
    fi
}

checkrunning()
{
    getpid
    if [ "x$PID" = "x" ]; then
        RUNNING=0
    else
        if ps --no-headers -p "$PID" -o cmd 2>/dev/null |grep slapd >/dev/null 2>&1 ; then
            RUNNING=1
        else
            PID=""
            RUNNING=0
        fi
    fi
}

checkListening()
{
    SEARCHTIMEOUT=30 #timelimit for ldapsearch
    if [ x"$ldap_common_require_tls" = "x0" ]; then
        /opt/zimbra/common/bin/ldapsearch -x -l $SEARCHTIMEOUT -b "" -s base -H ldapi:/// >/dev/null 2>&1
    else
        /opt/zimbra/common/bin/ldapsearch -ZZ -x -l $SEARCHTIMEOUT -b "" -s base -H ldapi:/// >/dev/null 2>&1
    fi
    if [ $? -ne 0 ]; then
        LISTENING=0
    else
        LISTENING=1
    fi
}

doDebugStart() {
    TIMEOUT=60 # timelimit for command
    /opt/zimbra/libexec/zmslapd -l LOCAL0 -h "${bind_url} ldapi:///" \
            -F /opt/zimbra/data/ldap/config -d 1 2>&1 | grep -e "failed" -e "error" &
    cmd_pid=$!
    sleep $TIMEOUT | (
        read nothing # wait on sleep to finish
        kill $cmd_pid 2>/dev/null; # otherwise abort the command!
    ) &
    sleep_pid=$!
    wait $cmd_pid
    kill -ALRM $sleep_pid 2>/dev/null # kill sleep if still running
    echo ""
    exit 1
}


start()
{
    checkrunning
    if [ $RUNNING != 0 ]; then
        echo "slapd already running: pid $PID"
        exit 1
    fi
    # Our ldap url should be the first in the list in localconfig
    bind_url=$ldap_bind_url
    if [ x"$bind_url" = "x" ]; then
        bind_url=$(echo "${ldap_url}" | awk '{print $1}')
    fi
    for ((i =0; i <= 30; i++)); do
        checkrunning
        if [ $RUNNING = 0 ]; then
            if ((i % 5 == 0)); then
                /opt/zimbra/libexec/zmslapd -l LOCAL0 \
                -h "${bind_url} ldapi:///" -F /opt/zimbra/data/ldap/config
            fi
        else
            break
        fi
        sleep 1
    done
    if [ "x$PID" = "x" ]; then
        echo "Failed to start slapd.  Attempting debug start to determine error."
        doDebugStart
    else
        echo "Started slapd: pid $PID"
    fi
    for ((i =0; i < 30; i++)); do
        checkListening
        if [ $LISTENING = 1 ]; then
            break
        fi
        sleep 1
    done
    if [ $LISTENING = 0 ]; then
        echo "Error: Unable to check that slapd is listening to connections"
        exit 1
    fi
}

stop()
{
    checkrunning

    if [ $RUNNING = 0 ]; then
        echo "slapd not running"
        exit 0
    fi
    echo -n "Killing slapd with pid $PID"
    kill -TERM $PID
    for ((i =0; i < 1500; i++)); do
        if ! kill -0 $PID 2> /dev/null; then
            echo " done."
            exit 0
        fi
        if ((i % 5 == 0)); then
            echo -n "."
        fi
        sleep 1
    done
    if kill -TERM $PID; then
        echo " gave up waiting!"
        exit 1
    fi
    echo " done."
    exit 0
}

status()
{
    checkrunning
    if [ $RUNNING = 0 ]; then
        exit 1
    else
        echo "slapd running pid: $PID"
        exit 0
    fi
}

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