#! /bin/bash
#	$Id$
#
# Warning, this file was automatically created by the HylaFAX configure script
#
# HylaFAX Facsimile Software
#
# Copyright (c) 1990-1996 Sam Leffler
# Copyright (c) 1991-1996 Silicon Graphics, Inc.
# HylaFAX is a trademark of Silicon Graphics
# 
# Permission to use, copy, modify, distribute, and sell this software and 
# its documentation for any purpose is hereby granted without fee, provided
# that (i) the above copyright notices and this permission notice appear in
# all copies of the software and related documentation, and (ii) the names of
# Sam Leffler and Silicon Graphics may not be used in any advertising or
# publicity relating to the software without the specific, prior written
# permission of Sam Leffler and Silicon Graphics.
# 
# THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
# EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
# WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
# 
# IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
# ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
# OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
# WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
# LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
# OF THIS SOFTWARE.
#

#
# VERSION:	6.6.23
# DATE:		Sun Nov  8 22:47:02 UTC 2026
# TARGET:	x86_64-unknown-linux-gnu
#

#
# faxaddbrooktrout [device channel]
#
# This script interactively configures a HylaFAX server
# from keyboard input on a standard terminal.  There may
# be some system dependencies in here; hard to say with
# this mountain of shell code!
#
SPOOL=/var/spool/hylafax

while [ x"$1" != x"" ] ; do
    case $1 in
    -*)	    echo "Usage: $0 [device channel]"; exit 1;;
    *)	    CHANDEV=$1;;
    esac
    shift
done

test -f $SPOOL/etc/setup.cache || {
    cat<<EOF

FATAL ERROR: $SPOOL/etc/setup.cache is missing!

The file $SPOOL/etc/setup.cache is not present.  This
probably means the machine has not been setup using the faxsetup(8C)
command.  Read the documentation on setting up HylaFAX before you
startup a server system.

EOF
    exit 1
}
. $SPOOL/etc/setup.cache	# common configuration stuff
. $SPOOL/etc/setup.modem	# modem-specific stuff

#
# Deduce the effective user id:
#   1. POSIX-style, the id program
#   2. the old whoami program
#   3. last gasp, check if we have write permission on /dev
#
euid=`id|$SED -e 's/.*uid=[0-9]*(\([^)]*\)).*/\1/'`
test -z "$euid" && euid=`(whoami) 2>/dev/null`
test -z "$euid" -a -w /dev && euid=root
if [ "$euid" != "root" ]; then
    echo "Sorry, but you must run this script as the super-user!"
    exit 1
fi

# security
TMPDIR=/tmp/.faxaddbrooktrout$$
umask 077
rm -rf $TMPDIR
mkdir $TMPDIR || exit 1

SH=$SCRIPT_SH			# shell for use below
CPATH=$SPOOL/etc/config		# prefix of configuration file
OUT=$TMPDIR/addbrooktrout$$     # temp file in which device output is recorded
SVR4UULCKN=$LIBEXEC/lockname	# SVR4 UUCP lock name construction program
ONDELAY=$LIBEXEC/ondelay	# prgm to open devices blocking on carrier
CAT="$CAT -u"			# something to do unbuffered reads and writes
FAX=hylafax			# identity of the fax user
GROUP=/etc/group		# where to go for group entries
PROTOGID=hylafax		# group who's gid we use for FAX user
defPROTOGID=10			# use this gid if PROTOGID doesn't exist
MODEMCONFIG=$SPOOL/config	# location of prototype modem config files
RMCMD="$RM -f"			# forced removal

#
# Build a list of config files in a portable way for grepping...
#

cd $MODEMCONFIG
CONFIG_LIST=""
for file in *; do
  if [ -f "$file" ]; then
    CONFIG_LIST="$CONFIG_LIST $file"
  fi
done

#
# Prompt the user for a string that can not be null.
#
promptForNonNullStringParameter()
{
    x=""
    while [ -z "$x" ]; do
	prompt "$2 [$1]?"; read x
	if [ "$x" ]; then
	    # strip leading and trailing white space
	    x=`echo "$x" | $SED -e 's/^[ 	]*//' -e 's/[ 	]*$//'`
	else
	    x="$1"
	fi
    done
    param="$x"
}

#
# Prompt the user for a string that can be null.
#
promptForStringParameter()
{
    prompt "$2 [$1]?"; read x
    if [ "$x" ]; then
	# strip leading and trailing white space
	x=`echo "$x" | $SED -e 's/^[ 	]*//' -e 's/[ 	]*$//'`
    else
	x="$1"
    fi
    param="$x"
}

#
# Prompt the user for a numeric value.
#
promptForNumericParameter()
{
    x=""
    while [ -z "$x" ]; do
	prompt "$2 [$1]?"; read x
	if [ "$x" ]; then
	    # strip leading and trailing white space
	    x=`echo "$x" | $SED -e 's/^[ 	]*//' -e 's/[ 	]*$//'`
	    match=`expr "$x" : "\([0-9]*\)"`
	    if [ "$match" != "$x" ]; then
		echo ""
		echo "This must be entirely numeric; please correct it."
		echo ""
		x="";
	    fi
	else
	    x="$1"
	fi
    done
    param="$x"
}

#
# Prompt the user for a C-style numeric value.
#
promptForCStyleNumericParameter()
{
    x=""
    while [ -z "$x" ]; do
	prompt "$2 [$1]?"; read x
	if [ "$x" ]; then
	    # strip leading and trailing white space and C-style 0x prefix
	    x=`echo "$x" | $SED -e 's/^[ 	]*//' -e 's/[ 	]*$//'`
	    match=`expr "$x" : "\([0-9]*\)" \| "$x" : "\(0x[0-9a-fA-F]*\)"`
	    if [ "$match" != "$x" ]; then
		echo ""
		echo "This must be entirely numeric; please correct it."
		echo ""
		x="";
	    fi
	else
	    x="$1"
	fi
    done
    param="$x"
}

#
# Prompt the user for a boolean value.
#
promptForBooleanParameter()
{
    x=""
    while [ -z "$x" ]; do
	prompt "$2 [$1]?"; read x
	if [ "$x" ]; then
	    # strip leading and trailing white space
	    x=`echo "$x" | $SED -e 's/^[ 	]*//' -e 's/[ 	]*$//'`
	    case "$x" in
	    n|no|off)	x=no;;
	    y|yes|on)	x=yes;;
	    *)
cat <<EOF

"$x" is not a valid boolean parameter setting;
use one of: "yes", "on", "no", or "off".
EOF
		x="";;
	    esac
	else
	    x="$1"
	fi
    done
    param="$x"
}

faxGID=`$GREP "^$PROTOGID:" $GROUP | cut -d: -f3`
if [ -z "$faxGID" ]; then faxGID=$defPROTOGID; fi

isValidBrooktrout ()
{
    D=$1
    C=$2
    case $D in
	boston)
	    if [ ! -c /dev/boston ]; then
		echo "No /dev/boston - needed for TR1034 and SR140" 
	    fi
	    ;;
    esac
}

DEVICE=`echo $CHANDEV | sed -n -e 's/^\(boston\).*/\1/p'`
CHANNEL=`echo $CHANDEV | sed -n -e 's/^\(boston\)\([0-9][0-9][0-9]\?\)$/\2/p'`
while [ -z "$CHANNEL" -o -z "$DEVICE" -o -n "`isValidBrooktrout $DEVICE $CHANNEL`" ]; do
    test -n "`isValidBrooktrout $DEVICE $CHANNEL`" && echo "$DEVICE device driver is not running." || \
    test "$DEVICE" == "" && echo "Device channel must be boston (TR1034/SR140) followed by a 2 or 3 digit channel number." || \
    test "$DEVICE" != "" -a "$CHANNEL" == "" && echo "The device name must be followed by a 2 or 3 digit channel number."
    prompt "Device channel to configure [$CHANDEV]?"; read CHANDEV
    if [ -z "$CHANDEV" ]; then
	exit
    fi
    DEVICE=`echo $CHANDEV | sed -n -e 's/^\(boston\).*/\1/p'`
    CHANNEL=`echo $CHANDEV | sed -n -e 's/^\(boston\)\([0-9][0-9][0-9]\?\)$/\2/p'`
done

JUNK="$OUT"
trap "$RMCMD \$JUNK; $RMCMD -r $TMPDIR; exit 1" 0 1 2 15

CONFIG=$CPATH.$CHANDEV			# HylaFAX configuration filename

cat<<EOF

Ok, time to setup a configuration file for the modem.  The manual
page config(5F) may be useful during this process.  Also be aware
that at any time you can safely interrupt this procedure.

EOF

#
# Configuration parameters specific to server operation
# (as opposed to that of the fax modem).  The required
# parameters are *always* emitted in the final created
# configuration file; otherwise parameters are emitted
# only if the configured value differs from the default
# value known to be used by the server.
#
# NB: the order of some parameters is important; e.g.
#     FAXNumber must be after AreaCode and CountryCode.
#
RequiredServerParameters="
    CountryCode
    AreaCode
    FAXNumber
    LongDistancePrefix
    InternationalPrefix
    DialStringRules
    ServerTracing
    SessionTracing
    RecvFileMode
    LogFileMode
    DeviceMode
    RingsBeforeAnswer
    GettyArgs
"
#
# Some of these things are also modem-dependent.  It's a
# hard call whether to treat them as server-related and
# propagate them to a new config file or to treat them as
# modem-specific and taken them from the prototype modem
# configuration file.
#
OptionalServerParameters="
    LocalIdentifier
    LogFacility
    ClocalAsRoot
    PriorityScheduling
    TagLineFont
    TagLineFormat
    QualifyCID
    QualifyTSI

    AdaptiveAnswer
    AnswerRotary
    AnswerBias
    NoCarrierRetrys

    PercentGoodLines
    MaxConsecutiveBadLines

    MaxRecvPages

    JobReqBusy
    JobReqNoCarrier
    JobReqNoAnswer
    JobReqNoFConn
    JobReqDataConn
    JobReqProto
    JobReqOther
    PollModemWait
    PollLockWait
    LockDataCalls
    LockVoiceCalls

    FaxRcvdCmd
    NotifyCmd
    PollRcvdCmd

    RingData
    RingFax
    RingVoice

    UUCPLockDir
    UUCPLockTimeout
    UUCPLockType

    PagerMaxMsgLength

    IXOService
    IXODeviceID
    IXOMaxUnknown
    IXOIDProbe
    IXOIDTimeout
    IXOLoginRetries
    IXOLoginTimeout
    IXOGATimeout
    IXOXmitRetries
    IXOXmitTimeout
    IXOAckTimeout
"
ServerParameters="$RequiredServerParameters $OptionalServerParameters"
#
# Default values for server configuration parameters.
#
defaultFAXNumber=\"\"
defaultLocalIdentifier=\"\"
defaultAreaCode=\"\"
defaultCountryCode=\"\"
defaultLongDistancePrefix=\"\"
defaultInternationalPrefix=\"\"
defaultDialStringRules=\"\"
defaultServerTracing=1
defaultSessionTracing=1
defaultRecvFileMode=0600
defaultLogFileMode=0600
defaultDeviceMode=0600
defaultRingsBeforeAnswer=0
defaultGettyArgs=\"\"
defaultQualifyTSI=\"\"
defaultJobReqBusy=180
defaultJobReqNoCarrier=300
defaultJobReqNoAnswer=300
defaultJobReqNoFConn=300
defaultJobReqDataConn=300
defaultJobReqProto=60
defaultJobReqOther=300
defaultPollModemWait=30
defaultPollLockWait=30
defaultTagLineFont=\"\"
defaultTagLineFormat="\"From %%n|%c|Page %%P of %%T\""
defaultPercentGoodLines=95
defaultMaxConsecutiveBadLines=5
defaultMaxRecvPages=1000
defaultLogFacility=daemon
defaultClocalAsRoot=\"\"
defaultPriorityScheduling=\"\"
defaultAdaptiveAnswer=\"\"
defaultAnswerRotary=\"\"
defaultAnswerBias=\"\"
defaultFaxRcvdCmd=\"\"
defaultNoCarrierRetrys=\"\"
defaultNotifyCmd=\"bin/notify\"
defaultPollRcvdCmd=\"\"
defaultQualifyCID=\"\"
defaultRingData=\"\"
defaultRingFax=\"\"
defaultRingVoice=\"\"
defaultUUCPLockDir=\"$UUCP_LOCKDIR\"
defaultUUCPLockTimeout=30
defaultUUCPLockType=\"$UUCP_LOCKTYPE\"
defaultLockDataCalls=Yes
defaultLockVoiceCalls=Yes
defaultPagerMaxMsgLength=\"\"
defaultIXOService=\"\"
defaultIXODeviceID=\"\"
defaultIXOMaxUnknown=\"\"
defaultIXOIDProbe=\"\"
defaultIXOIDTimeout=\"\"
defaultIXOLoginRetries=\"\"
defaultIXOLoginTimeout=\"\"
defaultIXOGATimeout=\"\"
defaultIXOXmitRetries=\"\"
defaultIXOXmitTimeout=\"\"
defaultIXOAckTimeout=\"\"

#
# Initialize server parameters from the defaults.
#
setupServerParameters()
{
    for i in $ServerParameters; do
	eval $i=\$default$i
    done
}

#
# Get server config values from an existing config file.
#
getServerParameters()
{
    eval `$SED -e 's/[ 	]*#.*$//' \
	-e "s;\([^:]*\):[ 	]*\(.*\);\1='\2';" $1`
}

#
# Echo the configuration lines for those server parameters
# whose value is different from the default value.  Note
# that we handle the case where there is embedded whitespace
# by enclosing the parameter value in quotes.
#
echoServerSedCommands()
{
    (for i in $RequiredServerParameters; do
	eval echo \"$i:\$$i:\"
     done
     for i in $OptionalServerParameters; do
	eval echo \"$i:\$$i:\$default$i\"
     done) | $AWK -F: '
function p(tag, value)
{
    tabs = substr("\t\t\t", 1, 3-int((length(tag)+1)/8));
    if (match(value, "^[^\"].*[ ]") == 0)
	printf "%s:%s%s\\\n", tag, tabs, value
    else
	printf "%s:%s\"%s\"\\\n", tag, tabs, value
}
BEGIN	{ printf "/^#.*BEGIN-SERVER/,/^#.*END-SERVER/c\\\n" }
$2 != $3{ p($1, $2) }
END	{ printf "#\n" }'	# terminate input text to ``c'' command
}

#
# Compile a table of configuration parameters prompts into
# a shell program that can be ``eval'd'' to prompt the user
# for changes to the current parameter settings.
#
compilePrompts()
{
    $AWK -F'[	]+' '
function p(t)
{
    printf "promptFor%sParameter \"$%s\" \"%s\";%s=\"$param\"\n", t, $2, $3, $2
}
$1 == "#"	{ p("Numeric"); next }
$1 == "C#"	{ p("CStyleNumeric"); next }
$1 == "S"	{ p("String"); next }
$1 == "NNS"	{ p("NonNullString"); next }
$1 == "B"	{ p("Boolean"); next }
		{ printf "promptFor%s\n", $1 }
'
}

#
# Verify that the fax number, area code, and country
# code jibe.  Perhaps this is too specific to the USA?
#
checkFaxNumber()
{
    pat="[\"]*+$CountryCode[-. ]*$AreaCode[-. ]*[0-9][- .0-9]*[\"]*"
    match=`expr "$FAXNumber" : "\($pat\)"`
    if [ "$match" != "$FAXNumber" ]; then
	cat<<EOF

Your facsimile phone number ($FAXNumber) does not agree with your
country code ($CountryCode) or area code ($AreaCode).  The number
should be a fully qualified international dialing number of the form:

    +$CountryCode $AreaCode <local phone number>

Spaces, hyphens, and periods can be included for legibility.  For example,

    +$CountryCode.$AreaCode.555.1212

is a possible phone number (using your country and area codes).
EOF
	ok=no;
    fi
}

#
# Verify that a number is octal and if not, add a prefixing "0".
#
checkOctalNumber()
{
    param=$1
    if [ "`expr "$param" : '\(.\)'`" != 0 ]; then
	param="0${param}"
	return 0
    else
	return 1
    fi
}

checkForLocalFile()
{
    f="`echo $1 | $SED 's/\"//g'`"
    if [ ! -f $SPOOL/$f ]; then
	cat<<EOF

Warning, the $2 file,

    $SPOOL/$f

does not exist, or is not a plain file.  This file must
reside in the $SPOOL directory tree.
EOF
	ok=no;
    fi
}

#
# Print the current server configuration parameters.
#
printServerConfig()
{
    (for i in $ServerParameters; do
	eval echo \"$i:\$$i:\$default$i\"
    done) | $AWK -F: '
function p(tag, value)
{
    tabs = substr("\t\t\t", 1, 3-int((length(tag)+1)/8));
    printf "%s:%s%s\n", tag, tabs, value
}
BEGIN	{ printf "\nThe non-default server configuration parameters are:\n\n" }
$2 != $3{ p($1, $2) }
END	{ printf "\n" }'
}

setupServerParameters
SCHEDCONFIG=$CPATH
if [ -f $SCHEDCONFIG ]; then
    echo "Reading scheduler config file $SCHEDCONFIG."
    echo ""
    getServerParameters $SCHEDCONFIG
fi
if [ -f $CONFIG ]; then
    echo "Hey, there is an existing config file $CONFIG..."
    getServerParameters $CONFIG
    ok="skip"				# skip prompting first time through
else
    echo "No existing configuration, let's do this from scratch."
    echo ""
    getServerParameters $MODEMCONFIG/skel # get from skeletal file
    ok="prompt"				# prompt for parameters
fi

if [ -z "$FAXNumber" ]; then
    FAXNumber="+$CountryCode $AreaCode 555-1212"
fi

isOK()
{
    x="$1"
    test -z "$x" -o "$x" = y -o "$x" = yes
}
isNotOK()
{
    x="$1"
    test -n "$x" -a "$x" != y -a "$x" != yes
}

#
# Prompt user for server-related configuration parameters
# and do consistency checking on what we get.
#
PROMPTS=$TMPDIR/faxpr$$
JUNK="$JUNK $PROMPTS"
while isNotOK $ok; do
    if [ "$ok" != skip ]; then
	test -f $PROMPTS || compilePrompts>$PROMPTS<<EOF
#	CountryCode		Country code
#	AreaCode		Area code
NNS	FAXNumber		Phone number of fax modem
S	LocalIdentifier		Local identification string (for TSI/CIG)
#	LongDistancePrefix	Long distance dialing prefix
#	InternationalPrefix	International dialing prefix
NNS	DialStringRules		Dial string rules file (relative to $SPOOL)
C#	ServerTracing		Tracing during normal server operation
C#	SessionTracing		Tracing during send and receive sessions
#	RecvFileMode		Protection mode for received facsimile
#	LogFileMode		Protection mode for session logs
#	DeviceMode		Protection mode for $CHANDEV
#	RingsBeforeAnswer	Rings to wait before answering
S	GettyArgs		Command line arguments to getty program
S	QualifyTSI		\
	Pathname of TSI access control list file (relative to $SPOOL)
S	QualifyCID		\
	Pathname of Caller-ID access control list file (relative to $SPOOL)
S	TagLineFont		Tag line font file (relative to $SPOOL)
S	TagLineFormat		Tag line format string
C#	UUCPLockTimeout		\
	Time before purging a stale UUCP lock file (secs)
B	LockDataCalls		Hold UUCP lockfile during inbound data calls
B	LockVoiceCalls		Hold UUCP lockfile during inbound voice calls
#	PercentGoodLines	\
	Percent good lines to accept during copy quality checking
#	MaxConsecutiveBadLines	\
	Max consecutive bad lines to accept during copy quality checking
#	MaxRecvPages		\
	Max number of pages to accept in a received facsimile
S	LogFacility		Syslog facility name for ServerTracing messages
B	ClocalAsRoot		Set UID to 0 to manipulate CLOCAL
B	PriorityScheduling	Use available priority job scheduling mechanism
EOF
	. $PROMPTS
    fi
    checkOctalNumber $RecvFileMode &&	RecvFileMode=$param
    checkOctalNumber $Log$param
    checkOctalNumber $DeviceMode &&	DeviceMode=$param
    checkForLocalFile $DialStringRules "dial string rules"
    checkFaxNumber;
    if [ "$TagLineFont" != "" -a "$TagLineFont" != '""' ]; then
	checkForLocalFile $TagLineFont "tag line font";
    fi
    printServerConfig; prompt "Are these ok [yes]?"; read ok
done

#
# We've got all the server-related parameters, now for the modem ones.
#

Manufacturer="" Model="" ProtoType=skel

#
# Select a configuration file for a modem based on the
# deduced modem type.  Each routine below sends a set
# of commands to the modem to figure out the modem model
# and manufacturer and then compares them against the
# set of known values in associated config files.
# Note that this is done with a tricky bit of shell
# hacking--generating a case statement that is then
# eval'd with the result being the setup of the
# ProtoType shell variable.
#
configureDevice()
{
    Manufacturer="Brooktrout"
    echo "Modem manufacturer is \"$Manufacturer\"."

    case "$DEVICE" in
      boston) Model="TR1034";;
    esac
    echo "Modem model is \"$Model\"."

    eval `(cd $MODEMCONFIG; \
	$GREP 'CONFIG:[ 	]*BT' $CONFIG_LIST |\
	$AWK -F: '
	    BEGIN { print "case \"$Manufacturer-$Model\" in" }
	    FILENAME ~ /^OLD/ { next }
	    FILENAME ~ /^config\./ { next }
	    { print $4 ") ProtoType=" $1 ";;" }
	    END { print "*) ProtoType=unknown;;"; print "esac" }
	')`
}

configureDevice

#
# Given a modem type, manufacturer and model, select
# a prototype configuration file to work from.
#
echo ""
echo "Using prototype configuration file $ProtoType..."
proto=$MODEMCONFIG/$ProtoType
if [ ! -f $proto ]; then
    echo "Uh oh, I can't find the prototype file"
    echo ""
    echo "\"$proto\""
    echo ""
    echo "There is nothing more that I can do; I'm bailing out..."
    exit 1
fi

#
# Prompt the user for a bit order.
#
promptForBitOrderParameter()
{
    x=""
    while [ -z "$x" ]; do
	prompt "$2 [$1]?"; read x
	if [ "$x" ]; then
	    # strip leading and trailing white space
	    x=`echo "$x" | $SED -e 's/^[ 	]*//' -e 's/[ 	]*$//'`
	    case "$x" in
	    [lL]*)	x=LSB2MSB;;
	    [mM]*)	x=MSB2LSB;;
	    *)
cat <<EOF

"$x" is not a valid bit order parameter setting; use one of:

lsb2msb		for x86-style machines
msb2lsb		for other machines

EOF
		x="";;
	    esac
	else
	    x="$1"
	fi
    done
    param="$x"
}

ModemParameters="
    BtCallFile
    CallTimeout
"

#
# Get the default modem parameter values
# from the prototype configuration file.
#
getModemProtoParameters()
{
    eval `$SED -e 's/[ 	]*#.*$//' \
	 -e "s;\([^:]*\):[ 	]*\(.*\);proto\1='\2'\;\1='\2';" $1`
}

#
# Setup the sed commands for crafting the configuration file:
#
echoModemSedCommands()
{
    ModemCmds=""

    (for i in $ModemParameters; do
	eval echo \"$i:\$$i:\$proto$i\"
    done) | $AWK -F: '
function p(tag, value)
{
    if (match(value, "^[^\"].*[ ]") == 0)
	printf "/^%s:/s/\\(:[ 	]*\\).*/\\1%s/\n", tag, value
    else
	printf "/^%s:/s/\\(:[ 	]*\\).*/\\1\"%s\"/\n", tag, value
}
$2 != $3{ p($1, $2) }
END	{ printf "/CONFIG:/d\n" }'
}

#
# Print the current modem-related parameters.
#
printModemConfig()
{
    (for i in $ModemParameters; do
	eval echo \"$i:\$$i:\$proto$i\"
    done) | $AWK -F: '
function p(tag, value)
{
    tabs = substr("\t\t\t", 1, 3-int((length(tag)+1)/8));
    printf "%s:%s%s\n", tag, tabs, value
}
BEGIN	{ printf "\nThe modem configuration parameters are:\n\n" }
$3 != ""{ p($1, $2) }
END	{ printf "\n" }'
}

promptFor()
{
    eval test \"\$proto$2\" && {
	eval promptFor${1}Parameter \"\$$2\" \"$3\";
	eval $2=\"\$param\";
    }
}

#
# Compile a table of configuration parameters prompts into
# a shell program that can be ``eval'd'' to prompt the user
# for changes to the current parameter settings.
#
compileModemPrompts()
{
    $AWK -F'[	]+' '
function p(t)
{
    printf "test -n \"$proto%s\" && { promptFor%sParameter \"$%s\" \"%s\";%s=\"$param\"; }\n", $2, t, $2, $3, $2
}
$1 == "#"	{ p("Numeric"); next }
$1 == "C#"	{ p("CStyleNumeric"); next }
$1 == "S"	{ p("String"); next }
$1 == "NNS"	{ p("NonNullString"); next }
$1 == "BO"	{ p("BitOrder"); next }
$1 == "FC"	{ p("FlowControl"); next }
$1 == "B"	{ p("Boolean"); next }
$1 == "AT"	{ p("ATCmd"); next }
		{ print }
'
}

#
# Build the script that prompts the user to edit the current
# modem configuration parameters.  Note that we can only edit
# parameters that are in the prototype config file; thus all
# the checks to see if the prototype value exists.
#
buildModemPrompts()
{
    compileModemPrompts<<EOF
NNS	BtCallFile		Brooktrout device configuration file
#	CallTimeout		Call Timeout (ms)
EOF
}

#
# Construct the configuration file.
#
getModemProtoParameters $proto
rm -f $PROMPTS
ok=skip
while isNotOK $ok; do
    if [ "$ok" != skip ]; then
	test -f $PROMPTS || buildModemPrompts>$PROMPTS
	. $PROMPTS
    fi
    printModemConfig
    prompt "Are these ok [yes]?"; read ok
done
TMPSED=$TMPDIR/faxsed$$; JUNK="$JUNK $TMPSED"
(echoServerSedCommands; echoModemSedCommands)>$TMPSED

#
# All done with the prompting; edit up a config file!
#
echo ""
echo "Creating new configuration file $CONFIG..."
JUNK="$JUNK $CONFIG.new"
if $SED -f $TMPSED $proto >$CONFIG.new; then
    if cmp -s $CONFIG.new $CONFIG >/dev/null 2>&1; then
	echo "...nothing appears to have changed; leaving the original file."
	$RMCMD $CONFIG.new
    else
	if [ -f $CONFIG ]; then
	    echo "...saving current file as $CONFIG.sav."
	    mv $CONFIG $CONFIG.sav
	fi
	$MV $CONFIG.new $CONFIG
	$CHOWN $FAX $CONFIG
	$CHGRP $faxGID $CONFIG
	$CHMOD 644 $CONFIG
    fi
else
    echo ""
    echo "*** Sorry, something went wrong building $CONFIG.new."
    echo "*** The original config file is unchanged; I'm terminating before"
    echo "***    I do something stupid."
    echo ""
    exit 1
fi

#
# Create FIFO.<device channel> special file and remove any old one.
#
FIFO=$SPOOL/FIFO.$DEVID
test -p $FIFO || {
    prompt "Creating fifo $FIFO for faxgetty..."
    if (mkfifo $FIFO) >/dev/null 2>&1; then
	echo "done."
    elif (mknod $FIFO p) >/dev/null 2>&1; then
	echo "done."
    else
	echo ""
	echo "*** Unable to create fifo \"$FIFO\"; terminating."
	exit 1
    fi
}
$CHOWN $FAX $FIFO; $CHGRP $faxGID $FIFO; $CHMOD 600 $FIFO

echo "Done setting up the modem configuration."

echo ""

#
# Configuration parameters specific to scheduler operation.
# Required parameters are *always* emitted in the created
# configuration file; optional parameters are emitted
# only if the configured value differs from the default
# value known to be used by the server.
#
# NB: the order of some parameters is important; e.g.
#     DialStringRules must be after AreaCode and CountryCode.
#
RequiredSchedulerParameters="
    LogFacility
    CountryCode
    AreaCode
    LongDistancePrefix
    InternationalPrefix
    DialStringRules
    ServerTracing
"
OptionalSchedulerParameters="
    ContCoverPage
    ContCoverCmd
    DestControls
    MaxConcurrentJobs
    MaxDials
    MaxSendPages
    MaxTries
    ModemGroup
    PostScriptTimeout
    PS2FaxCmd
    SendFaxCmd
    SendPageCmd
    SendUUCPCmd
    SessionTracing
    TimeOfDay
    Use2D
"
defaultContCoverPage=
defaultContCoverCmd=\"bin/mkcover\"
defaultDestControls=
defaultMaxConcurrentJobs=1
defaultMaxDials=12
defaultMaxSendPages=0xffffffff
defaultMaxTries=3
defaultModemGroup=
defaultPostScriptTimeout=180
defaultPS2FaxCmd=\"bin/ps2fax\"
defaultSendFaxCmd=\"bin/faxsend\"
defaultSendPageCmd=\"bin/pagesend\"
defaultSendUUCPCmd=\"bin/uucpsend\"
defaultSessionTracing=0xffffffff
defaultTimeOfDay=\"Any\"
defaultUse2D=Yes
#
# NB: these defaults are set above
#
OptionalParameters="
    $OptionalSchedulerParameters
    JobReqOther
    NotifyCmd
    UUCPLockDir
    UUCPLockTimeout
    UUCPLockType
"
SchedulerParameters="
    $RequiredSchedulerParameters
    $OptionalParameters
"
#
# The following parameters are checked to make sure
# they have values consistent with what was just written
# to the modem configuration file.  It is ok for some
# of these to be different, but usually they should be
# the same so if they disagree we prompt the user to
# see if we should propagate the new values from the
# modem config file to the scheduler config file.
#
CheckedParameters="
    LogFacility
    CountryCode
    AreaCode
    LongDistancePrefix
    InternationalPrefix
    DialStringRules
    JobReqOther
    NotifyCmd
    UUCPLockDir
    UUCPLockTimeout
    UUCPLockType
"

#
# Echo the configuration lines for those scheduler parameters
# whose value is different from the default value.  Note
# that we handle the case where there is embedded whitespace
# by enclosing the parameter value in quotes.
#
echoSchedulerParameters()
{
    (for i in $RequiredSchedulerParameters; do
	eval echo \"$i:\$$i:\"
     done
     for i in $OptionalSchedulerParameters; do
	eval echo \"$i:\$$i:\$default$i\"
     done) | $AWK -F: '
function p(tag, value)
{
    tabs = substr("\t\t\t", 1, 3-int((length(tag)+1)/8));
    if (match(value, "^[^\"].*[ ]") == 0)
	printf "%s:%s%s\n", tag, tabs, value
    else
	printf "%s:%s\"%s\"\n", tag, tabs, value
}
$2 != $3{ p($1, $2) }'
}

#
# Print the current server configuration parameters.
#
printSchedulerConfig()
{
    (for i in $SchedulerParameters; do
	eval echo \"$i:\$$i:\$default$i\"
    done) | $AWK -F: '
function p(tag, value)
{
    tabs = substr("\t\t\t", 1, 3-int((length(tag)+1)/8));
    printf "%s:%s%s\n", tag, tabs, value
}
BEGIN	{ printf "\nThe non-default scheduler parameters are:\n\n" }
$2 != $3{ p($1, $2) }
END	{ printf "\n" }'
}

#
# Check the current contents of the scheduler configuration file
# against that parameters just setup for the per-modem config file.
# If anything has changed (e.g. phone number info), then prompt
# the user to update the file.
#
updateConfig=yes
#
# Initialize server parameters from the defaults.
#
for i in $OptionalSchedulerParameters; do
    eval $i=\$default$i
done
if [ -f $SCHEDCONFIG ]; then
    echo "Checking $SCHEDCONFIG for consistency..."
    #
    # Save current settings in variables with a ``modem'' prefix.
    #
    for i in $CheckedParameters; do
	eval modem$i=\$$i
    done
    #
    # Read old configuration file in as the ``current settings''.
    #
    getServerParameters $SCHEDCONFIG
    #
    # Check current parameter settings against ``modem settings''.
    # If inconsistencies are detected in the parameters that should
    # (by default) be kept consistent, then try to propagate the new
    # parameter settings from the modem config file to the scheduler
    # config file.
    #
    ok=yes
    for i in $CheckedParameters; do
	eval test \"\$$i\" != \"\$modem$i\" && { ok=skip; break; }
    done
    if [ $ok != yes ]; then
	echo "...some parameters are different."
	#
	# Move the ``modem settings'' to the current settings
	# and let the user ok them or change them to what they
	# want.  We do this shuffle w/o touching the default
	# settings so that optional parameter handling works
	# (i.e. that only non-default values for optional params
	# are displayed and/or written to the file).
	#
	for i in $CheckedParameters; do
	    eval $i=\$modem$i
	done
    else
	echo "...everything looks ok; leaving existing file unchanged."
	updateConfig=no
    fi
else
    echo "No scheduler configuration file exists, creating one from scratch."
    ok=skip				# got important params above
fi

rm -f $PROMPTS
while isNotOK $ok; do
    if [ "$ok" != skip ]; then
	test -f $PROMPTS || compilePrompts>$PROMPTS<<EOF
#	CountryCode		Country code
#	AreaCode		Area code
#	LongDistancePrefix	Long distance dialing prefix
#	InternationalPrefix	International dialing prefix
NNS	DialStringRules		Dial string rules file (relative to $SPOOL)
C#	ServerTracing		Tracing during normal server operation
C#	SessionTracing		\
	Default tracing during send and receive sessions
S	ContCoverPage		Continuation cover page (relative to $SPOOL)
C#	PostScriptTimeout	\
	Timeout when converting PostScript documents (secs)
C#	MaxConcurrentJobs	\
	Maximum number of concurrent jobs to a destination
S	ModemGroup		Define a group of modems
S	TimeOfDay		Time of day restrictions for outbound jobs
S	DestControls		\
	Pathname of destination controls file (relative to $SPOOL)
C#	UUCPLockTimeout		\
	Timeout before purging a stale UUCP lock file (secs)
C#	MaxSendPages		Max number of pages to permit in an outbound job
S	LogFacility		Syslog facility name for ServerTracing messages
EOF
	. $PROMPTS
    fi
    checkForLocalFile $DialStringRules "dial string rules"
    if [ "$DestControls" != "" -a "$DestControls" != '""' ]; then
	checkForLocalFile $DestControls "destination controls";
    fi
    printSchedulerConfig; prompt "Are these ok [yes]?"; read ok
done

if [ $updateConfig = yes ]; then
    #
    # All done with the prompting; edit up a config file!
    #
    echo ""
    echo "Creating new configuration file $SCHEDCONFIG..."
    JUNK="$JUNK $SCHEDCONFIG.new"
    echoSchedulerParameters >$SCHEDCONFIG.new 2>/dev/null
    if cmp -s $SCHEDCONFIG.new $SCHEDCONFIG >/dev/null 2>&1; then
	echo "...nothing appears to have changed; leaving the original file."
	rm -f $SCHEDCONFIG.new
    elif [ -s $SCHEDCONFIG.new ]; then
	if [ -f $SCHEDCONFIG ]; then
	    echo "...saving current file as $SCHEDCONFIG.sav."
	    $MV $SCHEDCONFIG $SCHEDCONFIG.sav
	fi
	$MV $SCHEDCONFIG.new $SCHEDCONFIG
	$CHOWN $FAX $SCHEDCONFIG
	$CHGRP $faxGID $SCHEDCONFIG
	$CHMOD 644 $SCHEDCONFIG
    else
	echo ""
	echo "*** Sorry, something went wrong building $SCHEDCONFIG.new."
	echo "*** The original config file is unchanged; check your disk space?"
	echo ""
	exit 1
    fi
fi

echo ""
echo "Don't forget to run faxmodem(8C) (if you have a send-only environment)"
echo "or configure init to run btgetty on $CHANDEV."

exec >/dev/null 2>&1
