#! /bin/sh
##
## %CopyrightBegin%
##
## SPDX-License-Identifier: Apache-2.0
##
## Copyright Ericsson AB 2009-2025. All Rights Reserved.
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
##     http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
## %CopyrightEnd%
##
#

#
## run-ns
##
## $0 IPAddress PortNum SubDir
##
## Helper script to run a very local name server for this test suite,
## on a given port number, with a test specific configuration.
##
## * Create a work directory ./SubDir, create a $CONF_FILE there
##   that includes $INC_FILE that refers to the zone files.
## * Locate name server and check its version.
## * Zopy zone files and $INC_FILE from `dirname $0`/SubDir to ./SubDir.
## * Start name server in ./SubDir with logging to $LOG_FILE there.
## * Wait for "quit" on stdin.
## * Terminate name server and wait for it.
##
## Prints status lines starting with tag and colon (think mail header):
##   Skip: have given up; no point in starting this name server
##   Error: have given up; failed to start name server
##   Running: name server is running, waiting for "quit"
##   Other tags: diagnostics info
#

unset LDPATH CDPATH ENV BASH_ENV
IFS=' 	'
PATH=/usr/sbin:/sbin:/usr/bin:/bin
SHELL=/bin/sh
export PATH SHELL

NS=knotd
LOG_FILE=ns.log
CONF_FILE=knot.conf
INC_FILE=knot_inc.conf

ERROR="Error: "
error () {
    r=$?
    echo "$ERROR$*"
    exit $r
}

skip () {
    r=$?
    echo "Skip: $*"
    exit $r
}

ME="$0"
SELF=$$

# Check argument: IP address
test :"$1" != : || \
    error "Empty argument 1: IP address !"
IP="$1"

# Check argument: Port number
expr "0$2" + 0 '>' 0  '&'  "0$2" + 0 '<' 65536 >/dev/null 2>&1 || \
    error "Invalid argument 2: port number !"
PORT="$2"

# Check argument: Work/Zone subdir
test :"$3" != : || \
    error "Empty argument 3: Work/Zone subdir!"
SRCDIR="`dirname "$ME"`/$3"
test -d "$SRCDIR" || \
    error "Missing zone directory: $SRCDIR !"
test -f "$SRCDIR/$INC_FILE" || \
    error "Missing include file: $SRCDIR/$INC_FILE !"
DIR="$3"

# Locate name server and check version.
for n in /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin
do
    test -x "$n/$NS" && { NS="$n/$NS"; break; }
done

NS_VER="`"$NS" -V 2>&1`" || \
    skip "$NS: Not found!"
NS_VER="`echo "$NS_VER" | head -1`"
{ echo "$NS_VER" |
      grep -q -e ' 2[.]9[.]' -e ' 2[.][1-9][0-9][0-9]*[.]' \
           -e ' [3-9][.]' -e ' [1-9][0-9][0-9]*[.]'
} || skip "$NS_VER < 2.9"

# Create working directory and cd to it
mkdir "$DIR" >/dev/null 2>&1
cd "$DIR" >/dev/null 2>&1 || \
    error "Cannot cd: $DIR !"
DIR="$(pwd)"

# Create $CONF_FILE
cat >"$CONF_FILE" <<CONF_FILE
#
# $CONF_FILE for $NS_VER
# Generated by $ME.
#
# Copyright: see $ME.
#
server:
    listen: $IP@$PORT
    user: "$LOGNAME"
    rundir: $DIR

log:
  - target: stdout
    any: info

control:
    listen: /tmp/knot.$SELF.sock

database:
    storage: "$DIR"

template:
  - id: default
    storage: "$DIR"

include: $INC_FILE
CONF_FILE

# Copy all subdir files
( cd "$SRCDIR" && ls -1 ) | while read f; do
    cp -fp "$SRCDIR/$f" .
done

# Start command
set -- "$NS" -c "$CONF_FILE"

# Start nameserver
echo "Cwd: $DIR"
echo "Nameserver: $NS_VER"
echo "IP: $IP"
echo "Port: $PORT"
echo "Command: $@"
"$@" >"$LOG_FILE" 2>&1 </dev/null &
NS_PID=$!
echo "Pid: $NS_PID"
trap "kill $NS_PID >/dev/null 2>&1; wait $NS_PID >/dev/null 2>&1" \
    0 1 2 3 15
NS_STARTED=" info: server started .* PID $NS_PID\$"

# Wait for nameserver to start, start timer kill sub process
{ sleep 5 &&
      { echo "\n$ERROR$NS failed to start"
        kill $SELF
      }
} &
TIMER=$!

{
    echo $(exec /bin/sh -c 'echo $PPID') # Subshell PID
    exec tail -f "$LOG_FILE"
} | {
    read TAIL_PID
    sed -n "/$NS_STARTED/q"
    kill $TAIL_PID # Cannot trust SIGPIPE to stop tail
}
kill $TIMER

echo "Running: Enter \`\`quit'' to terminate nameserver[$NS_PID]..."
while read LINE; do
    test :"$LINE" = :'quit' && break
done
echo "Closing: Terminating nameserver..."
