#!/bin/sh

#######################################################################
# RCSIDENT("$SiLK: rwsender.init.d.in 8845fdf19700 2018-11-13 22:39:40Z mthomas $")
#######################################################################

# rwsender start/control script
#
# /etc/init.d/rwsender
# chkconfig: - 20 95
# description: SiLK network transfer sending daemon
# processname: rwsender
### BEGIN INIT INFO
# Provides: rwsender
# Required-Start: $local_fs $remote_fs $network $named $syslog $time
# Required-Stop: $local_fs $remote_fs $network $named $syslog $time
# Short-Description: start and stop SiLK rwsender daemon
# Description: SiLK daemon to watch a directory for files and transfer the
#              files across the network to one or more rwreceiver processes
### END INIT INFO

MYNAME=rwsender

# Determine whether our name has an addendum
BASENAME='s:\(.*/\)*\([^/]*\)$:\2:'
SEDEXT1='s/\(.*\)\.init\.d$/\1/'
SEDEXT2='s/\(.*\)\.sh$/\1/'
SCRIPTNAME=`echo $0 | sed ${BASENAME} | sed ${SEDEXT1} | sed ${SEDEXT2}`
PRETEST="\\(${MYNAME}\\)\\(-.*\\)*\$"
SUFTEST="${MYNAME}\\(-.*\\)\$"
PREFIX=`expr "x${SCRIPTNAME}" : "x${PRETEST}"`
SUFFIX=`expr "x${SCRIPTNAME}" : "x${SUFTEST}"`

if [ "x$PREFIX" != "x$MYNAME" ] ; then
    SUFFIX=
fi

# SCRIPT_CONFIG_LOCATION is the directory where the ${MYNAME}.conf
# file is located.  It can be set via an environment variable.  If the
# envar is not set, then DEFAULT_SCRIPT_CONFIG_LOCATION is used.  If
# that is not set as well, the --sysconfdir value passed to configure
# is used, which defaults to ${prefix}/etc.
DEFAULT_SCRIPT_CONFIG_LOCATION=
if [ "x$SCRIPT_CONFIG_LOCATION" = "x" ] ; then
    if [ "x$DEFAULT_SCRIPT_CONFIG_LOCATION" = "x" ] ; then
        SCRIPT_CONFIG_LOCATION="/etc"
    else
        SCRIPT_CONFIG_LOCATION="$DEFAULT_SCRIPT_CONFIG_LOCATION"
    fi
fi
SCRIPT_CONFIG=${SCRIPT_CONFIG_LOCATION}/${MYNAME}${SUFFIX}.conf

#######################################################################

if [ ! -f "${SCRIPT_CONFIG}" ] ; then
    echo "$0: ${SCRIPT_CONFIG} does not exist."
    exit 0
fi

. "${SCRIPT_CONFIG}"

if [ "x$ENABLED" = "x" ] ; then
    exit 0
fi


#######################################################################
# SHELL FUNCTIONS

# check_empty VARNAME VALUE
#
#    Verifies that VALUE has a value.  If it doesn't, a message is
#    printed that the VARNAME variable is unset and script exits.
check_empty()
{
    if [ "x$2" = "x" ] ; then
        echo "$0: the \${$1} variable has not been set."
        exit 1
    fi
}

# check_dir VARNAME DIR
#
#    Verifies that VARNAME is set.  Next, verifies that the directory
#    DIR exists.  If not and if $CREATE_DIRECTORIES is set, the
#    directory is created.  Otherwise, an error is printed and the
#    script exits.
check_dir()
{
    check_empty "$1" "$2"
    if [ ! -d "$2" ] ; then
        if [ "${CREATE_DIRECTORIES}" = "yes" ] ; then
            mkdir -p "$2" || { echo "$0: Could not create $2" ; exit 1 ; }
            chown -h "${USER}" "$2" || { echo "$0: Could not chown $2 to ${USER}"; exit 1 ; }
        else
            echo "$0: the $2 directory does not exist."
            exit 1
        fi
    else
        chown -h "${USER}" "$2" || { echo "$0: Could not chown $2 to ${USER}"; exit 1 ; }
    fi
}

# Variables for building Basic Regular Expressions
TAB="	"                       # Contains a literal tab
WHITE="[ ${TAB}]"
WHITEPLUS="${WHITE}${WHITE}*"
NONWHITE="[^ ${TAB}]"
NONWHITEPLUS="${NONWHITE}${NONWHITE}*"
STRINGWHITE="\\(${NONWHITEPLUS}\\)${WHITEPLUS}"

# ws_strip STRING
#
#   Strips leading and trailing whitespace from STRING and returns it
ws_strip()
{
    echo $1 | sed -e "s/^${WHITE}*\\(${NONWHITEPLUS}\\(${WHITE}*${NONWHITEPLUS}\\)*\\)${WHITE}*\$/\\1/"
}

# cut_1 STRING
#
#    Returns first "token" from STRING or the empty string for an
#    empty STRING
cut_1()
{
    expr "x$1" : "x\\(${NONWHITE}*\\)"
}

# cut_2 STRING
#
#    Returns second "token" from STRING
cut_2()
{
    expr "x$1" : "x${NONWHITEPLUS}${WHITEPLUS}\\(${NONWHITEPLUS}\\)"
}

# cut_2rest STRING
#
#    Returns from second "token" to end of STRING
cut_2rest()
{
    expr "x$1" : "x${NONWHITEPLUS}${WHITEPLUS}\\(.*\\)"
}

# cut_3rest STRING
#
#    Returns from third "token" to end of STRING
cut_3rest()
{
    expr "x$1" : "x${NONWHITEPLUS}${WHITEPLUS}${NONWHITEPLUS}${WHITEPLUS}\\(.*\\)"
}

#######################################################################

# for backwards compatibility
if [ "x${BIN_DIR}" = "x" ] ; then
    #echo "Warning: SENDER_BIN deprecated in ${SCRIPT_CONFIG}.  Use BIN_DIR instead" 1>&2
    BIN_DIR="${SENDER_BIN}"
fi


RETVAL=0

PROG=rwsender
PROG_PATH="${BIN_DIR}/${PROG}"
PIDFILE="${PID_DIR}/${PROG}${SUFFIX}.pid"
LOG_BASENAME="${PROG}${SUFFIX}"
PROG_OPTIONS=""

if [ ! -x "${PROG_PATH}" ] ; then
    echo "$0: could not find an executable ${PROG_PATH}."
    exit 1
fi

check_empty "IDENTIFIER" "${IDENTIFIER}"
PROG_OPTIONS="${PROG_OPTIONS} --identifier=${IDENTIFIER}"

# Add GnuTLS options
if test -n "${TLS_CA}" ; then
    PROG_OPTIONS="${PROG_OPTIONS} --tls-ca='${TLS_CA}'"
    if test -n "${TLS_PKCS12}" ; then
        PROG_OPTIONS="${PROG_OPTIONS} --tls-pkcs12='${TLS_PKCS12}'"
    elif test -z "${TLS_KEY}" || test -z "${TLS_CERT}" ; then
        echo "$0: Setting TLS_CA requires setting either TLS_PKCS12 or both TLS_KEY and TLS_CERT."
        exit 1
    else
        PROG_OPTIONS="${PROG_OPTIONS} --tls-key='${TLS_KEY}' --tls-cert='${TLS_CERT}'"
    fi
    if test -n "${TLS_PRIORITY}" ; then
        PROG_OPTIONS="${PROG_OPTIONS} --tls-priority='${TLS_PRIORITY}'"
    fi
    if test -n "${TLS_SECURITY}" ; then
        PROG_OPTIONS="${PROG_OPTIONS} --tls-security=${TLS_SECURITY}"
    fi
    if test -n "${TLS_CRL}" ; then
        PROG_OPTIONS="${PROG_OPTIONS} --tls-crl='${TLS_CRL}'"
    fi
    if test -n "${TLS_DEBUG_LEVEL}" ; then
        PROG_OPTIONS="${PROG_OPTIONS} --tls-debug-level=${TLS_DEBUG_LEVEL}"
    fi
fi


check_empty "MODE" "${MODE}"
IFS=
case "${MODE}" in
    server)
        check_empty "RECEIVER_CLIENTS" "${RECEIVER_CLIENTS}"
        check_empty "PORT" "${PORT}"
        PROG_OPTIONS="${PROG_OPTIONS} --server-port=${PORT}"
        while read -r LINE ; do
            LINE=`ws_strip ${LINE}`
            CLIENT=`cut_1 ${LINE}`
            FILTER=`cut_2rest ${LINE}`
            PROG_OPTIONS="${PROG_OPTIONS} --client-ident=${CLIENT}"
            if [ "x${FILTER}" != "x" ] ; then
                PROG_OPTIONS="${PROG_OPTIONS} --filter=${CLIENT}:'${FILTER}'"
            fi
        done <<EOF
${RECEIVER_CLIENTS}
EOF
        ;;
    client)
        check_empty "RECEIVER_SERVERS" "${RECEIVER_SERVERS}"
        while read -r LINE ; do
            LINE=`ws_strip ${LINE}`
            SERVER=`cut_1 ${LINE}`
            ADDR=`cut_2 ${LINE}`
            FILTER=`cut_3rest ${LINE}`
            PROG_OPTIONS="${PROG_OPTIONS} --server-address=${SERVER}:${ADDR}"
            if [ "x${FILTER}" != "x" ] ; then
                PROG_OPTIONS="${PROG_OPTIONS} --filter=${SERVER}:'${FILTER}'"
            fi
        done <<EOF
${RECEIVER_SERVERS}
EOF
        ;;
    *)
        echo "$0: Unexpected MODE ${MODE}."
        echo "Set to \"client\" or \"server\"."
        exit 1
        ;;
esac
unset IFS

check_dir "INCOMING_DIR"   "${INCOMING_DIR}"
check_dir "PROCESSING_DIR" "${PROCESSING_DIR}"
check_dir "ERROR_DIR"      "${ERROR_DIR}"

PROG_OPTIONS="${PROG_OPTIONS} --mode=${MODE} --incoming-directory='${INCOMING_DIR}' --processing-directory='${PROCESSING_DIR}' --error-directory='${ERROR_DIR}'"

if [ "x${LOCAL_COPIES}" != "x" ] ; then
    case "${LOCAL_COPIES}" in
        link)
            ;;
        copy)
            PROG_OPTIONS="${PROG_OPTIONS} --unique-local-copies"
            ;;
        *)
            echo "$0: Unexpected LOCAL_COPIES ${LOCAL_COPIES}."
            echo "Set to \"link\" or \"copy\"."
            exit 1
            ;;
    esac
fi

if [ "x${POLLING_INTERVAL}" != "x" ] ; then
    PROG_OPTIONS="${PROG_OPTIONS} --polling-interval=${POLLING_INTERVAL}"
fi


if [ "x${PRIORITIES}" != "x" ] ; then
    IFS=
    while read -r LINE ; do
        LINE=`ws_strip ${LINE}`
        PRIORITY=`cut_1 ${LINE}`
        REGEXP=`cut_2rest ${LINE}`
        PROG_OPTIONS="${PROG_OPTIONS} --priority=${PRIORITY}:'${REGEXP}'"
    done <<EOF
${PRIORITIES}
EOF
    unset IFS
fi


if [ "x${LOCAL_DIRS}" != "x" ] ; then
    check_empty LOCAL_IDENT "${LOCAL_IDENT}"
    IFS=
    count=0
    while read -r LINE ; do
        LINE=`ws_strip ${LINE}`
        DIR=`cut_1 ${LINE}`
        REGEXP=`cut_2rest ${LINE}`
        check_dir LOCAL_DIRS "${DIR}"
        if [ "x${REGEXP}" = "x" ] ; then
            PROG_OPTIONS="${PROG_OPTIONS} --local-directory=:'${DIR}'"
        else
            count=`expr 1 + $count`
            id="${LOCAL_IDENT}$count"
            PROG_OPTIONS="${PROG_OPTIONS} --local-directory=${id}:'${DIR}' --filter=${id}:'${REGEXP}'"
        fi
    done <<EOF
${LOCAL_DIRS}
EOF
    unset IFS
fi

if [ "x${SEND_ATTEMPTS}" != "x" ] ; then
    PROG_OPTIONS="${PROG_OPTIONS} --send-attempts=${SEND_ATTEMPTS}"
fi


#######################################################################

check_dir   "PID_DIR"  "${PID_DIR}"
PROG_OPTIONS="${PROG_OPTIONS} --pidfile='${PIDFILE}' --log-level=${LOG_LEVEL}"

case "${LOG_TYPE}" in
    syslog)
        PROG_OPTIONS="${PROG_OPTIONS} --log-destination=syslog"
        ;;
    legacy)
        check_dir "LOG_DIR" "${LOG_DIR}"
        PROG_OPTIONS="${PROG_OPTIONS} --log-directory='${LOG_DIR}' --log-basename='${LOG_BASENAME}'"
        ;;
    *)
        echo "$0: Unexpected LOG_TYPE ${LOG_TYPE}."
        echo "Set to \"legacy\" or \"syslog\"."
        exit 1
        ;;
esac


#######################################################################

# Check if $pid is running
checkpid() {
    kill -0 $1 >/dev/null 2>&1 && return 0
    return 1
}


# Get the process id from the PIDFILE
getPid() {
    RETVAL=1
    if [ -f $PIDFILE ] ; then
        RETVAL=2
        read pid < ${PIDFILE}
        if [ "X$pid" != "X" ] ; then
            RETVAL=3
            # Found a pid
            if checkpid $pid ; then
                echo $pid
                RETVAL=0
            fi
        fi
    fi
    echo ""
    return $RETVAL
}


status() {
    if [ $# -gt 0 ] ; then
        doEcho=0
    else
        doEcho=1
    fi

    # first check if the process is running
    pid=`getPid`
    RETVAL=$?

    if [ $doEcho -eq 1 ] ; then
        case "$RETVAL" in
          0)
            echo "${PROG} is running with pid $pid"
            ;;
          1)
            echo "${PROG} is stopped"
            ;;
          *)
            echo "${PROG} is dead but pid file exists"
            ;;
        esac
    fi
    return $RETVAL
}


start() {
    (status 'silent')
    pStat=$?
    if [ $pStat -eq 0 ] ; then
        status
        return 0
    fi

    /bin/echo -n "Starting ${PROG}:	"
    /bin/rm -f ${PIDFILE} 2> /dev/null

    if [ X`whoami` = "X${USER}" ] ; then
        eval "${PROG_PATH} ${PROG_OPTIONS} ${EXTRA_OPTIONS} &"
    else
        su - ${USER} -c "${PROG_PATH} ${PROG_OPTIONS} ${EXTRA_OPTIONS} &"
    fi
    RETVAL=$?
    if [ "$RETVAL" -ne "0" ] ; then
        echo "[Failed]"
    else
        sleep 1
        PID=`getPid`
        if [ "x$PID" = "x" ] ; then
            echo "[Failed]"
            RETVAL=1
        else
            echo '[OK]'
        fi
    fi
    return $RETVAL
}


stop() {
    Pid=`getPid`
    if [ "X${Pid}" = "X" ] ; then
        echo "${PROG} not running"
        return 1
    fi
    /bin/echo -n "Stopping ${PROG}:	"
    /bin/kill -s INT $Pid
    for s in 1 2 3 4 5 6 ; do
        sleep $s
        if checkpid $Pid ; then
            :
        else
            break;
        fi
    done
    if checkpid $Pid ; then
        /bin/kill -s KILL $Pid
        sleep 1
    fi
    (checkpid $Pid)
    RETVAL=$?
    [ "$RETVAL" -eq "1" ] && echo '[OK]' || echo '[FAILED]'
    /bin/rm -f ${PIDFILE} 2> /dev/null
    return $RETVAL
}


restart(){
    (stop)
    (start)
}


case "$1" in
  start)
    (start)
    RETVAL=$?
    ;;

  stop)
    (stop)
    RETVAL=$?
    ;;

  restart)
    (restart)
    RETVAL=$?
    ;;

  force-reload)
    (restart)
    RETVAL=$?
    ;;

  status)
    (status)
    RETVAL=$?
    ;;

  *)
    echo $"Usage: $0 {start|stop|status|restart|force-reload}"
    RETVAL=1
    ;;
esac

exit $RETVAL


#######################################################################
# @OPENSOURCE_LICENSE_START@
#
# Use of the SILK system and related source code is subject to the terms
# of the following licenses:
#
# GNU General Public License (GPL) Rights pursuant to Version 2, June 1991
# Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013
#
# NO WARRANTY
#
# ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER
# PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY
# PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN
# "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
# KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT
# LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE,
# MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE
# OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT,
# SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY
# TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF
# WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES.
# LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF
# CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON
# CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE
# DELIVERABLES UNDER THIS LICENSE.
#
# Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie
# Mellon University, its trustees, officers, employees, and agents from
# all claims or demands made against them (and any related losses,
# expenses, or attorney's fees) arising out of, or relating to Licensee's
# and/or its sub licensees' negligent use or willful misuse of or
# negligent conduct or willful misconduct regarding the Software,
# facilities, or other rights or assistance granted by Carnegie Mellon
# University under this License, including, but not limited to, any
# claims of product liability, personal injury, death, damage to
# property, or violation of any laws or regulations.
#
# Carnegie Mellon University Software Engineering Institute authored
# documents are sponsored by the U.S. Department of Defense under
# Contract FA8702-15-D-0002. Carnegie Mellon University retains
# copyrights in all material produced under this contract. The U.S.
# Government retains a non-exclusive, royalty-free license to publish or
# reproduce these documents, or allow others to do so, for U.S.
# Government purposes only pursuant to the copyright license under the
# contract clause at 252.227.7013.
#
# @OPENSOURCE_LICENSE_END@
#######################################################################
