#!/bin/sh

### systemd startup script prelude for rwsender

# The canonical pathname for this file is
# /usr/libexec/silk/rwsender_startup

PROGRAM_NAME="rwsender"

# Which instance from a multiple-instance systemd config (i.e.
# "service@instance") this is, or blank if none.

SYSTEMD_INSTANCE_SUFFIX=""
if [ -n "$1" ]; then
    SYSTEMD_INSTANCE_SUFFIX=".$1"
fi

# The SYSTEMD_INSTANCE_SUFFIX is used as part of the filename of the
# config file, as well as the log file base name.

SCRIPT_CONFIG_FILENAME="${PROGRAM_NAME}${SYSTEMD_INSTANCE_SUFFIX}.conf"

### Above this from SiLK's src/startup/snippet-systemd_header.sh

### Below this from SiLK's src/startup/snippet-common_prelude.sh

# PROGRAM_NAME and SCRIPT_CONFIG_FILENAME should be set before this point.

# PROGRAM_NAME is the name of the executable program being managed by
# this script.

# SCRIPT_CONFIG_FILENAME is the name of the configuration file from
# which to read environment variables. Typically some variation on
# "${PROGRAM_NAME}.conf".

# SCRIPT_CONFIG_LOCATION is the directory where the
# ${SCRIPT_CONFIG_FILENAME} config file is located. It can be set via an
# environment variable. If the envar is not set, then /usr/etc is
# used.

# If $SCRIPT_CONFIG_LOCATION/sysconfig/$SCRIPT_CONFIG_FILENAME exists, a
# warning will be emitted (since the default location of these files has
# changed on some systems.)

SCRIPT_CONFIG="${SCRIPT_CONFIG_LOCATION:=/usr/etc}/${SCRIPT_CONFIG_FILENAME}"
DEPRECATED_SCRIPT_CONFIG="${SCRIPT_CONFIG_LOCATION}/sysconfig/${SCRIPT_CONFIG_FILENAME}"

if [ -f "$DEPRECATED_SCRIPT_CONFIG" ]; then
    echo "$0: *** WARNING: Config files should be placed directly in '${SCRIPT_CONFIG_LOCATION}', but '${DEPRECATED_SCRIPT_CONFIG}' exists." 1>&2
    echo "$0: *** WARNING: Move any existing configuration from '${DEPRECATED_SCRIPT_CONFIG}' to '${SCRIPT_CONFIG}'." 1>&2
fi

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

. "${SCRIPT_CONFIG}"

if [ "x$ENABLED" = "x" ] ; then
    echo "$0: Not enabled in '${SCRIPT_CONFIG}', exiting." 1>&2
    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}\\(.*\\)"
}

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

RETVAL=0

PROGRAM_PATH="${BIN_DIR}/${PROGRAM_NAME}"

PROG_OPTIONS=""

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

### Below this from SiLK's src/sendrcv/snippet-rwsender_startup.sh

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

### Below this from SiLK's src/startup/snippet-systemd_footer.sh
### systemd startup script footer: Final checks and execution.

# Always set the log level
PROG_OPTIONS="${PROG_OPTIONS} --log-level=${LOG_LEVEL}"

# And for systemd services, don't daemonize
PROG_OPTIONS="${PROG_OPTIONS} --no-daemon"

LOG_BASENAME="${PROGRAM_NAME}${SYSTEMD_INSTANCE_SUFFIX}"
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

#######################################################################
/bin/echo "Starting ${PROGRAM_NAME}${SYSTEMD_INSTANCE_SUFFIX}"

if [ X`whoami` = "X${USER}" ] ; then
    eval "${EXTRA_ENVVAR} exec ${PROGRAM_PATH} ${PROG_OPTIONS} ${EXTRA_OPTIONS}"
else
    exec su - ${USER} -c "${EXTRA_ENVVAR} exec ${PROGRAM_PATH} ${PROG_OPTIONS} ${EXTRA_OPTIONS}"
fi


#######################################################################
# @OPENSOURCE_LICENSE_START@
#
# SiLK 3.24
#
# Copyright 2025 Carnegie Mellon University.
#
# NO WARRANTY. THIS CARNEGIE MELLON UNIVERSITY AND SOFTWARE ENGINEERING
# INSTITUTE MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON
# UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR
# IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF
# FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS
# OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT
# MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT,
# TRADEMARK, OR COPYRIGHT INFRINGEMENT.
#
# Licensed under a GNU GPL 2.0-style license, please see LICENSE.txt or
# contact permission@sei.cmu.edu for full terms.
#
# [DISTRIBUTION STATEMENT A] This material has been approved for public
# release and unlimited distribution.  Please see Copyright notice for
# non-US Government use and distribution.
#
# This Software includes and/or makes use of Third-Party Software each
# subject to its own license.
#
# DM25-0915
#
# @OPENSOURCE_LICENSE_END@
#######################################################################
