summaryrefslogtreecommitdiffstats
path: root/bin/tests/system/conf.sh.common
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 07:24:22 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 07:24:22 +0000
commit45d6379135504814ab723b57f0eb8be23393a51d (patch)
treed4f2ec4acca824a8446387a758b0ce4238a4dffa /bin/tests/system/conf.sh.common
parentInitial commit. (diff)
downloadbind9-45d6379135504814ab723b57f0eb8be23393a51d.tar.xz
bind9-45d6379135504814ab723b57f0eb8be23393a51d.zip
Adding upstream version 1:9.16.44.upstream/1%9.16.44upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--bin/tests/system/conf.sh.common744
1 files changed, 744 insertions, 0 deletions
diff --git a/bin/tests/system/conf.sh.common b/bin/tests/system/conf.sh.common
new file mode 100644
index 0000000..e87acca
--- /dev/null
+++ b/bin/tests/system/conf.sh.common
@@ -0,0 +1,744 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+testsock6() {
+ if test -n "$PERL" && $PERL -e "use IO::Socket::INET6;" 2> /dev/null
+ then
+ $PERL "$TOP/bin/tests/system/testsock6.pl" "$@"
+ else
+ false
+ fi
+}
+
+export LANG=C
+
+. ${TOP}/version
+
+#
+# Common lists of system tests to run.
+#
+# The following tests are hard-coded to use ports 5300 and 9953. For
+# this reason, these must be run sequentially.
+#
+# Sequential tests that only run on unix/linux should be added to
+# SEQUENTIAL_UNIX in conf.sh.in; those that only run on windows should
+# be added to SEQUENTIAL_WINDOWS in conf.sh.win32.
+#
+SEQUENTIAL_COMMON="ecdsa eddsa tkey"
+
+#
+# These tests can use ports assigned by the caller (other than 5300
+# and 9953). Because separate blocks of ports can be used for teach
+# test, these tests can be run in parallel.
+#
+# Parallel tests that only run on unix/linux should be added to
+# PARALLEL_UNIX in conf.sh.in; those that only run on windows should
+# be added to PARALLEL_WINDOWS in conf.sh.win32.
+#
+# Note: some of the longer-running tests such as serve-stale and
+# rpzrecurse are scheduled first, in order to get more benefit from
+# parallelism.
+#
+PARALLEL_COMMON="dnssec rpzrecurse serve-stale dupsigs \
+acl \
+additional \
+addzone \
+allow-query \
+auth \
+autosign \
+builtin \
+cacheclean \
+case \
+catz \
+cds \
+chain \
+checkconf \
+checkds \
+checknames \
+checkzone \
+database \
+digdelv \
+dlz \
+dlzexternal \
+dns64 \
+dscp \
+dsdigest \
+dyndb \
+ednscompliance \
+emptyzones \
+fetchlimit \
+filter-aaaa \
+formerr \
+forward \
+geoip2 \
+glue \
+idna \
+inline \
+integrity \
+ixfr \
+journal \
+kasp \
+keepalive \
+keymgr2kasp \
+legacy \
+limits \
+masterfile \
+masterformat \
+metadata \
+mirror \
+mkeys \
+names \
+notify \
+nsec3 \
+nslookup \
+nsupdate \
+nzd2nzf \
+padding \
+pending \
+pipelined \
+qmin \
+reclimit \
+redirect \
+resolver \
+rndc \
+rootkeysentinel \
+rpz \
+rrchecker \
+rrl \
+rrsetorder \
+rsabigexponent \
+runtime \
+sfcache \
+shutdown \
+smartsign \
+sortlist \
+spf \
+staticstub \
+statistics \
+statschannel \
+stress \
+stub \
+synthfromdnssec \
+timeouts \
+tcp \
+tools \
+tsig \
+tsiggss \
+ttl \
+unknown \
+upforwd \
+verify \
+views \
+wildcard \
+xfer \
+xferquota \
+zero \
+zonechecks"
+
+#
+# Set up color-coded test output
+#
+if [ ${SYSTEMTEST_FORCE_COLOR:-0} -eq 1 ] || test -t 1 && type tput > /dev/null 2>&1 && tput setaf 7 > /dev/null 2>&1 ; then
+ export COLOR_END=`tput setaf 4` # blue
+ export COLOR_FAIL=`tput setaf 1` # red
+ export COLOR_INFO=`tput bold` # bold
+ export COLOR_NONE=`tput sgr0`
+ export COLOR_PASS=`tput setaf 2` # green
+ export COLOR_START=`tput setaf 4` # blue
+ export COLOR_WARN=`tput setaf 3` # yellow
+else
+ # set to empty strings so printf succeeds
+ export COLOR_END=''
+ export COLOR_FAIL=''
+ export COLOR_INFO=''
+ export COLOR_NONE=''
+ export COLOR_PASS=''
+ export COLOR_START=''
+ export COLOR_WARN=''
+fi
+
+export SYSTESTDIR="`basename $PWD`"
+
+if type printf > /dev/null 2>&1
+then
+ echofail () {
+ printf "${COLOR_FAIL}%s${COLOR_NONE}\n" "$*"
+ }
+ echowarn () {
+ printf "${COLOR_WARN}%s${COLOR_NONE}\n" "$*"
+ }
+ echopass () {
+ printf "${COLOR_PASS}%s${COLOR_NONE}\n" "$*"
+ }
+ echoinfo () {
+ printf "${COLOR_INFO}%s${COLOR_NONE}\n" "$*"
+ }
+ echostart () {
+ printf "${COLOR_START}%s${COLOR_NONE}\n" "$*"
+ }
+ echoend () {
+ printf "${COLOR_END}%s${COLOR_NONE}\n" "$*"
+ }
+ echo_i() {
+ printf '%s\n' "$*" | while IFS= read -r __LINE ; do
+ echoinfo "I:$SYSTESTDIR:$__LINE"
+ done
+ }
+
+ echo_ic() {
+ printf '%s\n' "$*" | while IFS= read -r __LINE ; do
+ echoinfo "I:$SYSTESTDIR: $__LINE"
+ done
+ }
+
+ echo_d() {
+ printf '%s\n' "$*" | while IFS= read -r __LINE ; do
+ echoinfo "D:$SYSTESTDIR:$__LINE"
+ done
+ }
+else
+ echofail () {
+ echo "$*"
+ }
+ echowarn () {
+ echo "$*"
+ }
+ echopass () {
+ echo "$*"
+ }
+ echoinfo () {
+ echo "$*"
+ }
+ echostart () {
+ echo "$*"
+ }
+ echoend () {
+ echo "$*"
+ }
+
+ echo_i() {
+ echo "$@" | while IFS= read -r __LINE ; do
+ echoinfo "I:$SYSTESTDIR:$__LINE"
+ done
+ }
+
+ echo_ic() {
+ echo "$@" | while IFS= read -r __LINE ; do
+ echoinfo "I:$SYSTESTDIR: $__LINE"
+ done
+ }
+
+ echo_d() {
+ echo "$@" | while IFS= read -r __LINE ; do
+ echoinfo "D:$SYSTESTDIR:$__LINE"
+ done
+ }
+fi
+
+cat_i() {
+ while IFS= read -r __LINE ; do
+ echoinfo "I:$SYSTESTDIR:$__LINE"
+ done
+}
+
+cat_d() {
+ while IFS= read -r __LINE ; do
+ echoinfo "D:$SYSTESTDIR:$__LINE"
+ done
+}
+
+digcomp() {
+ output=`$PERL $SYSTEMTESTTOP/digcomp.pl "$@"`
+ result=$?
+ [ -n "$output" ] && { echo "digcomp failed:"; echo "$output"; } | cat_i
+ return $result
+}
+
+start_server() {
+ $PERL "$TOP_SRCDIR/bin/tests/system/start.pl" "$SYSTESTDIR" "$@"
+}
+
+stop_server() {
+ $PERL "$TOP_SRCDIR/bin/tests/system/stop.pl" "$SYSTESTDIR" "$@"
+}
+
+send() {
+ $PERL "$TOP_SRCDIR/bin/tests/system/send.pl" "$@"
+}
+
+#
+# Useful variables in test scripts
+#
+
+# The following script sets the following algorithm-related variables. These
+# are selected randomly at runtime from a list of supported algorithms. The
+# randomization is deterministic and remains stable for a period of time for a
+# given platform.
+#
+# Default algorithm for testing.
+# DEFAULT_ALGORITHM
+# DEFAULT_ALGORITHM_NUMBER
+# DEFAULT_BITS
+#
+# This is an alternative algorithm for test cases that require more than one
+# algorithm (for example algorithm rollover). Must be different from
+# DEFAULT_ALGORITHM.
+# ALTERNATIVE_ALGORITHM
+# ALTERNATIVE_ALGORITHM_NUMBER
+# ALTERNATIVE_BITS
+#
+# This is an algorithm that is used for tests against the "disable-algorithms"
+# configuration option. Must be different from above algorithms.
+# DISABLED_ALGORITHM
+# DISABLED_ALGORITHM_NUMBER
+# DISABLED_BITS
+#
+# There are multiple algoritms sets to choose from (see get_algorithms.py). To
+# override the default choice, set the ALGORITHM_SET env var (see mkeys system
+# test for example).
+if test -x "$PYTHON" && test -x "$KEYGEN"; then
+ eval "$($PYTHON "$TOP_SRCDIR/bin/tests/system/get_algorithms.py")"
+else
+ # 9.16 workarounds
+ # - for ./configure which calls bin/tests/system/cleanall.sh, which
+ # includes this file before $KEYGEN is compiled
+ # - for our Windows CI which lacks Python
+ DEFAULT_ALGORITHM=ECDSAP256SHA256
+ DEFAULT_ALGORITHM_NUMBER=13
+ DEFAULT_BITS=256
+ ALTERNATIVE_ALGORITHM=RSASHA256
+ ALTERNATIVE_ALGORITHM_NUMBER=8
+ ALTERNATIVE_BITS=1280
+ DISABLED_ALGORITHM=ECDSAP384SHA384
+ DISABLED_ALGORITHM_NUMBER=14
+ DISABLED_BITS=384
+fi
+
+# Default HMAC algorithm.
+export DEFAULT_HMAC=hmac-sha256
+
+#
+# Useful functions in test scripts
+#
+
+# assert_int_equal: compare two integer variables, $1 and $2
+#
+# If $1 and $2 are equal, return 0; if $1 and $2 are not equal, report
+# the error using the description of the tested variable provided in $3
+# and return 1.
+assert_int_equal() {
+ found="$1"
+ expected="$2"
+ description="$3"
+
+ if [ "${expected}" -ne "${found}" ]; then
+ echo_i "incorrect ${description}: got ${found}, expected ${expected}"
+ return 1
+ fi
+
+ return 0
+}
+
+# keyfile_to_keys_section: helper function for keyfile_to_*_keys() which
+# converts keyfile data into a key-style trust anchor configuration
+# section using the supplied parameters
+keyfile_to_keys() {
+ section_name=$1
+ key_prefix=$2
+ shift
+ shift
+ echo "$section_name {"
+ for keyname in $*; do
+ awk '!/^; /{
+ printf "\t\""$1"\" "
+ printf "'"$key_prefix "'"
+ printf $4 " " $5 " " $6 " \""
+ for (i=7; i<=NF; i++) printf $i
+ printf "\";\n"
+ }' $keyname.key
+ done
+ echo "};"
+}
+
+# keyfile_to_dskeys_section: helper function for keyfile_to_*_dskeys()
+# converts keyfile data into a DS-style trust anchor configuration
+# section using the supplied parameters
+keyfile_to_dskeys() {
+ section_name=$1
+ key_prefix=$2
+ shift
+ shift
+ echo "$section_name {"
+ for keyname in $*; do
+ $DSFROMKEY $keyname.key | \
+ awk '!/^; /{
+ printf "\t\""$1"\" "
+ printf "'"$key_prefix "'"
+ printf $4 " " $5 " " $6 " \""
+ for (i=7; i<=NF; i++) printf $i
+ printf "\";\n"
+ }'
+ done
+ echo "};"
+}
+
+# keyfile_to_trusted_keys: convert key data contained in the keyfile(s)
+# provided to a "trust-keys" section suitable for including in a
+# resolver's configuration file
+keyfile_to_trusted_keys() {
+ keyfile_to_keys "trusted-keys" "" $*
+}
+
+# keyfile_to_static_keys: convert key data contained in the keyfile(s)
+# provided to a *static-key* "trust-anchors" section suitable for including in
+# a resolver's configuration file
+keyfile_to_static_keys() {
+ keyfile_to_keys "trust-anchors" "static-key" $*
+}
+
+# keyfile_to_initial_keys: convert key data contained in the keyfile(s)
+# provided to an *initial-key* "trust-anchors" section suitable for including
+# in a resolver's configuration file
+keyfile_to_initial_keys() {
+ keyfile_to_keys "trust-anchors" "initial-key" $*
+}
+
+# keyfile_to_static_ds_keys: convert key data contained in the keyfile(s)
+# provided to a *static-ds* "trust-anchors" section suitable for including in a
+# resolver's configuration file
+keyfile_to_static_ds() {
+ keyfile_to_dskeys "trust-anchors" "static-ds" $*
+}
+
+# keyfile_to_initial_ds_keys: convert key data contained in the keyfile(s)
+# provided to an *initial-ds* "trust-anchors" section suitable for including
+# in a resolver's configuration file
+keyfile_to_initial_ds() {
+ keyfile_to_dskeys "trust-anchors" "initial-ds" $*
+}
+
+# keyfile_to_key_id: convert a key file name to a key ID
+#
+# For a given key file name (e.g. "Kexample.+013+06160") provided as $1,
+# print the key ID with leading zeros stripped ("6160" for the
+# aforementioned example).
+keyfile_to_key_id() {
+ echo "$1" | sed "s/.*+0\{0,4\}//"
+}
+
+# private_type_record: write a private type record recording the state of the
+# signing process
+#
+# For a given zone ($1), algorithm number ($2) and key file ($3), print the
+# private type record with default type value of 65534, indicating that the
+# signing process for this key is completed.
+private_type_record() {
+ _zone=$1
+ _algorithm=$2
+ _keyfile=$3
+
+ _id=$(keyfile_to_key_id "$_keyfile")
+
+ printf "%s. 0 IN TYPE65534 %s 5 %02x%04x0000\n" "$_zone" "\\#" "$_algorithm" "$_id"
+}
+
+# nextpart*() - functions for reading files incrementally
+#
+# These functions aim to facilitate looking for (or waiting for)
+# messages which may be logged more than once throughout the lifetime of
+# a given named instance by outputting just the part of the file which
+# has been appended since the last time we read it.
+#
+# Calling some of these functions causes temporary *.prev files to be
+# created that need to be cleaned up manually (usually by a given system
+# test's clean.sh script).
+#
+# Note that unlike other nextpart*() functions, nextpartread() is not
+# meant to be directly used in system tests; its sole purpose is to
+# reduce code duplication below.
+#
+# A quick usage example:
+#
+# $ echo line1 > named.log
+# $ echo line2 >> named.log
+# $ nextpart named.log
+# line1
+# line2
+# $ echo line3 >> named.log
+# $ nextpart named.log
+# line3
+# $ nextpart named.log
+# $ echo line4 >> named.log
+# $ nextpartpeek named.log
+# line4
+# $ nextpartpeek named.log
+# line4
+# $ nextpartreset named.log
+# $ nextpartpeek named.log
+# line1
+# line2
+# line3
+# line4
+# $ nextpart named.log
+# line1
+# line2
+# line3
+# line4
+# $ nextpart named.log
+# $
+
+# nextpartreset: reset the marker used by nextpart() and nextpartpeek()
+# so that it points to the start of the given file
+nextpartreset() {
+ echo "0" > $1.prev
+}
+
+# nextpartread: read everything that's been appended to a file since the
+# last time nextpart() was called and print it to stdout, print the
+# total number of lines read from that file so far to file descriptor 3
+nextpartread() {
+ [ -f $1.prev ] || nextpartreset $1
+ prev=`cat $1.prev`
+ awk "NR > $prev "'{ print }
+ END { print NR > "/dev/stderr" }' $1 2>&3
+}
+
+# nextpart: read everything that's been appended to a file since the
+# last time nextpart() was called
+nextpart() {
+ nextpartread $1 3> $1.prev.tmp
+ mv $1.prev.tmp $1.prev
+}
+
+# nextpartpeek: read everything that's been appended to a file since the
+# last time nextpart() was called
+nextpartpeek() {
+ nextpartread $1 3> /dev/null
+}
+
+# _search_log: look for message $1 in file $2 with nextpart().
+_search_log() (
+ msg="$1"
+ file="$2"
+ nextpart "$file" | grep -F -e "$msg" > /dev/null
+)
+
+# _search_log_peek: look for message $1 in file $2 with nextpartpeek().
+_search_log_peek() (
+ msg="$1"
+ file="$2"
+ nextpartpeek "$file" | grep -F -e "$msg" > /dev/null
+)
+
+# wait_for_log: wait until message $2 in file $3 appears. Bail out after
+# $1 seconds. This needs to be used in conjunction with a prior call to
+# nextpart() or nextpartreset() on the same file to guarantee the offset is
+# set correctly. Tests using wait_for_log() are responsible for cleaning up
+# the created <file>.prev files.
+wait_for_log() (
+ timeout="$1"
+ msg="$2"
+ file="$3"
+ retry_quiet "$timeout" _search_log "$msg" "$file" && return 0
+ echo_i "exceeded time limit waiting for '$msg' in $file"
+ return 1
+)
+
+# wait_for_log_peek: similar to wait_for_log() but peeking, so the file offset
+# does not change.
+wait_for_log_peek() (
+ timeout="$1"
+ msg="$2"
+ file="$3"
+ retry_quiet "$timeout" _search_log_peek "$msg" "$file" && return 0
+ echo_i "exceeded time limit waiting for '$msg' in $file"
+ return 1
+)
+
+# _retry: keep running a command until it succeeds, up to $1 times, with
+# one-second intervals, optionally printing a message upon every attempt
+_retry() {
+ __retries="${1}"
+ shift
+
+ while :; do
+ if "$@"; then
+ return 0
+ fi
+ __retries=$((__retries-1))
+ if [ "${__retries}" -gt 0 ]; then
+ if [ "${__retry_quiet}" -ne 1 ]; then
+ echo_i "retrying"
+ fi
+ sleep 1
+ else
+ return 1
+ fi
+ done
+}
+
+# retry: call _retry() in verbose mode
+retry() {
+ __retry_quiet=0
+ _retry "$@"
+}
+
+# retry_quiet: call _retry() in silent mode
+retry_quiet() {
+ __retry_quiet=1
+ _retry "$@"
+}
+
+# _repeat: keep running command up to $1 times, unless it fails
+_repeat() (
+ __retries="${1}"
+ shift
+ while :; do
+ if ! "$@"; then
+ return 1
+ fi
+ __retries=$((__retries-1))
+ if [ "${__retries}" -le 0 ]; then
+ break
+ fi
+ done
+ return 0
+)
+
+rndc_reload() {
+ $RNDC -c ../common/rndc.conf -s $2 -p ${CONTROLPORT} reload $3 2>&1 | sed 's/^/'"I:$SYSTESTDIR:$1"' /'
+ # reloading single zone is synchronous, if we're reloading whole server
+ # we need to wait for reload to finish
+ if [ -z "$3" ]; then
+ for __try in 0 1 2 3 4 5 6 7 8 9; do
+ $RNDC -c ../common/rndc.conf -s $2 -p ${CONTROLPORT} status | grep "reload/reconfig in progress" > /dev/null || break
+ sleep 1
+ done
+ fi
+}
+
+rndc_reconfig() {
+ $RNDC -c ../common/rndc.conf -s $2 -p ${CONTROLPORT} reconfig 2>&1 | sed 's/^/'"I:$SYSTESTDIR:$1"' /'
+ for __try in 0 1 2 3 4 5 6 7 8 9; do
+ $RNDC -c ../common/rndc.conf -s $2 -p ${CONTROLPORT} status | grep "reload/reconfig in progress" > /dev/null || break
+ sleep 1
+ done
+}
+
+# rndc_dumpdb: call "rndc dumpdb [...]" and wait until it completes
+#
+# The first argument is the name server instance to send the command to, in the
+# form of "nsX" (where "X" is the instance number), e.g. "ns5". The remaining
+# arguments, if any, are appended to the rndc command line after "dumpdb".
+#
+# Control channel configuration for the name server instance to send the
+# command to must match the contents of bin/tests/system/common/rndc.conf.
+#
+# rndc output is stored in a file called rndc.out.test${n}; the "n" variable is
+# required to be set by the calling tests.sh script.
+#
+# Return 0 if the dump completes successfully; return 1 if rndc returns an exit
+# code other than 0 or if the "; Dump complete" string does not appear in the
+# dump within 10 seconds.
+rndc_dumpdb() {
+ __ret=0
+ __dump_complete=0
+ __server="${1}"
+ __ip="10.53.0.$(echo "${__server}" | tr -c -d "0-9")"
+
+ shift
+ ${RNDC} -c ../common/rndc.conf -p "${CONTROLPORT}" -s "${__ip}" dumpdb "$@" > "rndc.out.test${n}" 2>&1 || __ret=1
+
+ for _ in 0 1 2 3 4 5 6 7 8 9
+ do
+ if grep '^; Dump complete$' "${__server}/named_dump.db" > /dev/null; then
+ mv "${__server}/named_dump.db" "${__server}/named_dump.db.test${n}"
+ __dump_complete=1
+ break
+ fi
+ sleep 1
+ done
+
+ if [ ${__dump_complete} -eq 0 ]; then
+ echo_i "timed out waiting for 'rndc dumpdb' to finish"
+ __ret=1
+ fi
+
+ return ${__ret}
+}
+
+# get_dig_xfer_stats: extract transfer statistics from dig output stored
+# in $1, converting them to a format used by some system tests.
+get_dig_xfer_stats() {
+ LOGFILE="$1"
+ sed -n "s/^;; XFR size: .*messages \([0-9][0-9]*\).*/messages=\1/p" "${LOGFILE}"
+ sed -n "s/^;; XFR size: \([0-9][0-9]*\) records.*/records=\1/p" "${LOGFILE}"
+ sed -n "s/^;; XFR size: .*bytes \([0-9][0-9]*\).*/bytes=\1/p" "${LOGFILE}"
+}
+
+# get_named_xfer_stats: from named log file $1, extract transfer
+# statistics for the last transfer for peer $2 and zone $3 (from a log
+# message which has to contain the string provided in $4), converting
+# them to a format used by some system tests.
+get_named_xfer_stats() {
+ LOGFILE="$1"
+ PEER="`echo $2 | sed 's/\./\\\\./g'`"
+ ZONE="`echo $3 | sed 's/\./\\\\./g'`"
+ MESSAGE="$4"
+ grep " ${PEER}#.*${MESSAGE}:" "${LOGFILE}" | \
+ sed -n "s/.* '${ZONE}\/.* \([0-9][0-9]*\) messages.*/messages=\1/p" | tail -1
+ grep " ${PEER}#.*${MESSAGE}:" "${LOGFILE}" | \
+ sed -n "s/.* '${ZONE}\/.* \([0-9][0-9]*\) records.*/records=\1/p" | tail -1
+ grep " ${PEER}#.*${MESSAGE}:" "${LOGFILE}" | \
+ sed -n "s/.* '${ZONE}\/.* \([0-9][0-9]*\) bytes.*/bytes=\1/p" | tail -1
+}
+
+# copy_setports - Copy Configuration File and Replace Ports
+#
+# Convenience function to copy a configuration file, replacing the tokens
+# QUERYPORT, CONTROLPORT and EXTRAPORT[1-8] with the values of the equivalent
+# environment variables. (These values are set by "run.sh", which calls the
+# scripts invoking this function.)
+#
+# Usage:
+# copy_setports infile outfile
+#
+copy_setports() {
+ # The indirect method of handling the substitution of the PORT variables
+ # (defining "atsign" then substituting for it in the "sed" statement) is
+ # required to prevent the "Configure" script (in the win32utils/ directory)
+ # from replacing the <at>PORT<at> substitution tokens when it processes
+ # this file and produces conf.sh.
+ atsign="@"
+ sed -e "s/${atsign}PORT${atsign}/${PORT}/g" \
+ -e "s/${atsign}EXTRAPORT1${atsign}/${EXTRAPORT1}/g" \
+ -e "s/${atsign}EXTRAPORT2${atsign}/${EXTRAPORT2}/g" \
+ -e "s/${atsign}EXTRAPORT3${atsign}/${EXTRAPORT3}/g" \
+ -e "s/${atsign}EXTRAPORT4${atsign}/${EXTRAPORT4}/g" \
+ -e "s/${atsign}EXTRAPORT5${atsign}/${EXTRAPORT5}/g" \
+ -e "s/${atsign}EXTRAPORT6${atsign}/${EXTRAPORT6}/g" \
+ -e "s/${atsign}EXTRAPORT7${atsign}/${EXTRAPORT7}/g" \
+ -e "s/${atsign}EXTRAPORT8${atsign}/${EXTRAPORT8}/g" \
+ -e "s/${atsign}CONTROLPORT${atsign}/${CONTROLPORT}/g" \
+ -e "s/${atsign}DEFAULT_ALGORITHM${atsign}/${DEFAULT_ALGORITHM}/g" \
+ -e "s/${atsign}DEFAULT_ALGORITHM_NUMBER${atsign}/${DEFAULT_ALGORITHM_NUMBER}/g" \
+ -e "s/${atsign}DEFAULT_BITS${atsign}/${DEFAULT_BITS}/g" \
+ -e "s/${atsign}ALTERNATIVE_ALGORITHM${atsign}/${ALTERNATIVE_ALGORITHM}/g" \
+ -e "s/${atsign}ALTERNATIVE_ALGORITHM_NUMBER${atsign}/${ALTERNATIVE_ALGORITHM_NUMBER}/g" \
+ -e "s/${atsign}ALTERNATIVE_BITS${atsign}/${ALTERNATIVE_BITS}/g" \
+ -e "s/${atsign}DEFAULT_HMAC${atsign}/${DEFAULT_HMAC}/g" \
+ -e "s/${atsign}DISABLED_ALGORITHM${atsign}/${DISABLED_ALGORITHM}/g" \
+ -e "s/${atsign}DISABLED_ALGORITHM_NUMBER${atsign}/${DISABLED_ALGORITHM_NUMBER}/g" \
+ -e "s/${atsign}DISABLED_BITS${atsign}/${DISABLED_BITS}/g" \
+ $1 > $2
+}