#!/bin/ksh -p
#
# Copyright (c) 2001 by Sun Microsystems, Inc.
# All rights reserved.
#
####################################################
#
# *** must run as user root ***
#
# There are no Messaging Server instances in SUNoneMS6.x releases
# ha_ip_config [ip-address ims-server-root ims-instance-name
#               [slapd-instance-name]]
#
#	This shell script will configure an iMS instance
#	for use in an HA configuration.
#
#	  ip-address          -- IP address associated with the
#	                         HA logical host name.
#
#	  ims-server-root     -- Absolute directory path to the
#	                         top-level iMS directory.
#
#	  There are no Messaging Server instances in SUNoneMS6.x releases
#	  ims-instance-name   -- Name of the iMS instance
#	                         to configure.  Do not include
#	                         the leading "msg-".
#
#	  slapd-instance-name -- Optional name of an LDAP server
#	                         instance to configure.  Do not include
#	                         the leading "slapd-".  If omitted,
#	                         then no LDAP configuration changes
#	                         are made.
#
#	If these four optional parameters are not supplied,
#	then the script will prompt for them.
#
#	With this information, the script updates the following:
#	- <server-root>/msg-<instance-name>/imta/config/dispatcher.cnf
#
#	NOTE: In SunOneMS6.x releases, dispatcher.cnf is located under
#	- <server-root>/config/dispatcher.cnf
#
#	  By adding or changing the INTERFACE_ADDRESS settings.
#
#	- <server-root>/msg-<instance-name>/imta/config/job_controller.cnf
#
#	NOTE: In SunOneMS6.x releases, job_controller.cnf is located under
#	- <server-root>/config/job_controller.cnf
#
#	  By adding or changing the INTERFACE_ADDRESS setting.
#
#	- <server-root>/slapd-<instance-name>/config/slapd.conf
#	  By adding or changing the listenhost setting.
#
#	- The service.listenaddr configutil parameter.
#
####################################################

####################################################
#
# Create descriptor 4 as a dup of the original stdout.
# Functions which want to print user visible output
# to the original stdout have the option of using
# descriptor 4.
#
####################################################
exec 4>&1

# Some utilities we rely upon
typeset -r CAT="/usr/bin/cat"
typeset -r CHOWN="/usr/bin/chown"
typeset -r GETFACL="/usr/bin/getfacl"
typeset -r GREP="/usr/bin/grep -hsi"
typeset -r LS="/usr/bin/ls"
typeset -r MV="/usr/bin/mv"
typeset -r RM="/usr/bin/rm"
typeset -r SED="/usr/bin/sed"
typeset -r SETFACL="/usr/bin/setfacl"

#####################################################
#
# I18N
#
#	Note - If a "locale" directory is found
#	in the same directory from which scinstall is
#	run, the TEXTDOMAINDIR is set to that directory.
#	This will typically be the case when running
#	from cd-rom (or, a copy of the cd-rom).
#
#####################################################
typeset -x TEXTDOMAIN=
typeset -x TEXTDOMAINDIR=

typeset -r YES="$(gettext 'yes')"
typeset -r NO="$(gettext 'no')"
typeset -r SERVER_ROOT_STR="$(gettext 'iMS server root')"
typeset -r INSTANCE_NAME_STR="$(gettext 'iMS instance name')"
typeset -r LDAP_INSTANCE_NAME_STR="$(gettext 'LDAP instance name')"
typeset -r IP_ADDRESS_STR="$(gettext 'Logical IP address')"

#####################################################
#
# Some global variables
#
#   PROG               -- Program name
#   ABSPROG            -- Complete path to program
#   SERVER_ROOT        -- Absolute path to the iMS top-level directory
#   INSTANCES          -- List of iMS instances in server root directory
#   INSTANCE_NAME      -- Name of the iMS instance to configure
#   INSTANCE_PATH      -- Absolute path to the iMS instance
#   CONFIG_LDAP        -- Also configure an LDAP server instance?
#   LDAP_INSTANCES     -- List of LDAP server instances in server root dir
#   LDAP_INSTANCE_NAME -- LDAP server instance name
#   LDAP_INSTANCE_PATH -- Absolute path to the LDAP server instance
#   IP_ADDRESS         -- Dotted decimal IP address for the
#                           HA logical host name
#   FIRST              -- Flag indicating if first pass in interactive mode
#   UID                -- Numeric UID
#   UNAME              -- Username
#   IMTA_USER          -- Username for iMS messaging servers
#   REDO               -- User wishes to change answers
#####################################################
typeset -r PROG=${0##*/}
typeset -r ABSPROG=${0}

typeset INSTANCES=
typeset INSTANCE_NAME=
typeset INSTANCE_PATH=
integer CONFIG_LDAP=1
typeset LDAP_INSTANCES=
typeset LDAP_INSTANCE_NAME=
typeset LDAP_INSTANCE_PATH=
typeset IP_ADDRESS=
integer FIRST=1
typeset UID=
typeset UNAME=
typeset IMTA_USER=
integer REDO=0

#####################################################
#
# ha_verify_isroot()
#
#	Print an error message and return non-zero
#	if the user is not root.
#
#	Return values:
#	  0 - User is root
#	  1 - User is not root
#
######################################################
ha_verify_isroot()
{
	UID=$(expr "$(id)" : 'uid=\([0-9]*\)*')
	UNAME=$(expr "$(id)" : 'uid=[0-9]*(\([^)]*\))*')

	# make sure uid was set
	if [[ -z "${UID}" ]]; then
		printf "$(gettext 'Cannot get uid')\n" >&2
		return 1
	fi

	# check for root
	if [[ ${UID} -ne 0 ]]; then
		printf "$(gettext 'Must be root')\n" >&2
		return 1
	fi

	return 0
}

#####################################################
#
# ha_get_imta_user
#
#	Determine the username used by the iMS servers.
#
#	Return values:
#	  0 - Success
#	  1 - Unable to determine the username
#
#####################################################
ha_get_imta_user()
{

	# Try using configutil first
	#IMTA_USER=$(${1}/configutil -o local.serveruid)
	IMTA_USER=$(${1}/sbin/configutil -o local.serveruid)
	if [[ ! -z "${IMTA_USER}" ]]; then
		return 0
	fi

	# Try searching the imta_tailor file
	#IMTA_USER=$(${GREP} IMTA_USER= ${1}/imta/config/imta_tailor)
	IMTA_USER=$(${GREP} IMTA_USER= ${1}/config/imta_tailor)
	IMTA_USER=$(expr ${IMTA_USER} : 'IMTA_USER=\(.*\)')
	if [[ ! -z "${IMTA_USER}" ]]; then
		return 0
	fi

	# Give up
	printf "$(gettext '%s: Cannot determine uid for iMS servers')\n" ${PROG} >&2
	return 1
}

####################################################
#
# ha_print_prompt text
#
#	text - the prompt
#
#	Print the given "text" as a prompt.
#
#	Return values:
#	  0 - Always
#
####################################################
ha_print_prompt()
{
	set -f
	typeset text="$(echo $*)"
	set +f

	printf "%s " "${text}"

	return 0
}

####################################################
#
# ha_print_para text
#
#	text - the text of the paragraph
#
#	Print the given "text" as a formatted paragraph to stdout.
#
#	Return values:
#	  0 - Always
#
####################################################
ha_print_para()
{
	set -f
	typeset text="$(echo $*)"

	echo "${text}" | fmt -w 76
	echo

	return 0
}

####################################################
#
# ha_prompt "prompt" [default [nonl]]
#
#	prompt	- the prompt string
#	default	- the default value
#	nonl	- no extra newline after answer
#
#	Display the prompt and return the user's answer.
#
#	If the trailing character of the prompt is ? or :, and
#	there is a "default", the trailer is re-positioned after
#	the "default".
#
#	The prompt is printed on file descriptor 4, and the answer
#	is printed to stdout.  File descriptor 4 should be
#	dupped to the original stdout before this function is called.
#
#	Return values:
#	  0 - proceed
#	  1 - ^D was typed
#
####################################################
ha_prompt()
{
	set -f
	typeset prompt="$(echo ${1})"
	typeset default="${2}"
	typeset nonl="${3}"
	set +f

	typeset answer=
	typeset trailer
	typeset foo
	integer i

	# The caller of this function should have already opened
	# descriptor 4 as a dup of the original stdout.

	# Dup this function's stdout to descriptor 5.
	# Then, re-direct stdout to descriptor 4.

	# So, the default stdout from this function will go to
	# the original stdout (probably the tty).  Descriptor 5
	# has the answer printed to it.

	exec 5>&1
	exec 1>&4

	# if there is a default value, shift the terminating ? or : character
	if [[ -n "${default}" ]]; then
		trailer=
		if [[ "${prompt}" = *\? ]]; then
			trailer="?"
		elif [[ "${prompt}" = *: ]]; then
			trailer=":"
		fi
		if [[ -n "${trailer}" ]]; then
			prompt="${prompt%${trailer}}"
			prompt="${prompt} [${default}]${trailer}"
		else
			prompt="${prompt} [${default}]"
		fi
	fi

	#
	# Display the prompt and get the user's response
	# Loop until an answer is given.   Or, if there is a
	# default, the user need not supply an answer.
	#
	# It is not legal for the user to supply more than one value.
	#
	let i=0
	while true
	do
		# If this is not the first time through, beep
		[[ ${i} -gt 0 ]] && echo "\c"
		let i=1

		# Prompt and get response
		ha_print_prompt "${prompt}"
		read answer foo

		# Return 1 on EOF
		if [[ $? -eq 1 ]]; then
			echo
			return 1
		fi

		# If more than one arg, repeat prompt
		if [[ -n "${foo}" ]]; then
			continue
		fi

		# If no answer and default, default is the answer
		if [[ -z "${answer}" ]] && [[ -n "${default}" ]]; then
			answer="${default}"
		fi

		# If still no answer, repeat prompt
		if [[ -z "${answer}" ]]; then
			continue
		fi

		# Okay
		break
	done

	# Unless "nonl" was given, print extra newline
	if [[ -z "${nonl}" ]]; then
		echo
	fi

	echo "${answer}" >&5

	return 0
}

####################################################
#
# ha_prompt_yesno "prompt" [default]
#
#	prompt	- the prompt string
#	default	- the default value
#
#	Display the yes/no prompt and return the user's answer.
#
#	The user may y, yes, Y, YES, n, no, N, or NO.
#	Function will always print "yes" or "no" on stdout.
#
#	The prompt is printed on file descriptor 4, and the answer
#	is printed to stdout.  File descriptor 4 should be
#	dupped to the original stdout before this function is called.
#
#	Return values:
#	  0 - proceed
#	  1 - ^D was typed
#
####################################################
ha_prompt_yesno()
{
	typeset prompt="${1}"
	typeset default="${2}"
	typeset answer=
	integer i

	# if there is a terminating ? and ${YES} is yes and ${NO} is no,
	# add (yes/no) and shift the terminating "?"
	if [[ "${YES}" = "yes" ]] &&
	    [[ "${NO}" = "no" ]] &&
	    [[ "${prompt}" = *\? ]]; then
		prompt="${prompt%\?}"
		prompt="${prompt} (yes/no)?"
	fi

	let i=0
	while true
	do
		# If this is not the first time through, beep
		[[ ${i} -gt 0 ]] && echo "\c" >&4
		let i=1

		# Prompt and get response
		answer=$(ha_prompt "${prompt}" "${default}" "nonl")

		# Return 1 on EOF
		if [[ $? -eq 1 ]]; then
			echo >&4
			return 1
		fi

		# I18N sensitive answer always returns "yes" or "no" string
		case ${answer} in
		${YES} | yes | y | YES | Y)
			answer="yes"
			break
			;;

		${NO} | no | n | NO | N)
			answer="no"
			break
			;;

		*)
			answer=
			;;
		esac
	done
	echo >&4

	echo "${answer}"

	return 0
}

####################################################
#
# ha_verify_server_root server-root
#
#	server-root -- Absolute path to the iMS server
#	               root
#
#	Ensure that server-root specifies an existing
#	directory file.
#
#	Return values:
#	  0 - Valid
#	  1 - Invalid
#
####################################################
ha_verify_server_root()
{
	# Make sure that the path is valid and specifies a directory
	INSTANCES=
	LDAP_INSTANCES=
	if [[ -d "${1}" ]]; then
		# Directory exists.  See if it includes any msg-* directories
		#INSTANCES="$(${LS} -1dp ${1}/msg-* 2>/dev/null | ${GREP} '.*/$' | ${SED} 's|.*/msg-||' | ${SED} 's|/||')"
		#if [[ ! -z ${INSTANCES} ]]; then
			LDAP_INSTANCES="$(${LS} -1dp ${1}/slapd-* 2>/dev/null | ${GREP} '.*/$' | ${SED} 's|.*/slapd-||' | ${SED} 's|/||')"
			return 0
		#else
		#	printf "$(gettext 'iMS server root does not contain any msg-* subdirectories')\n\n"
		#	return 1
		#fi
	fi
	if [[ ! -e "${1}" ]]; then
		printf "$(gettext 'iMS server root path does not exist')\n\n"
	else
		printf "$(gettext 'iMS server root path does not specify a directory')\n\n"
	fi
	return 1
}

####################################################
#
# ha_get_server_root
#
#	Prompt the user for the iMS server root and
#	validate its correctness.
#
#	Return values:
#	  0 - proceed
#	  1 - ^D was typed
#
####################################################
ha_get_server_root()
{
	typeset answer

	if [[ ${FIRST} -eq 1 ]]; then
		ha_print_para "$(gettext '
			Please specify the path to the top level directory in
			which iMS is installed.')"
	fi

	while true
	do
		# Get the path to the server root directory
		answer=$(ha_prompt "${SERVER_ROOT_STR}:" "${SERVER_ROOT}") || return 1
		ha_verify_server_root "${answer}" || continue
		break
	done

	SERVER_ROOT=${answer}

	return 0
}

####################################################
#
# ha_verify_ims_instance instance-path
#
#	instance-path -- Abosolute file directory path
#	                 to the iMS instance to configure
#
#	Ensure that instance path specifies an existing
#	directory file.
#
#	Return values:
#	  0 - Valid
#	  1 - Invalid
#
####################################################
ha_verify_ims_instance()
{
	# Make sure that the instance name is valid
	if [[ ! -d "${1}" ]]; then
		printf "$(gettext 'iMS instance does not exist')\n\n"
		return 1
	fi
	if [[ ! -d "${1}/imta/config" ]]; then
		printf "$(gettext 'iMS instance does not appear valid; is missing imta/config subdirectory')\n\n"
		return 1
	fi
	return 0
}

####################################################
#
# ha_get_ims_instance
#
#	Prompt the user for the iMS instance name and
#	validate its correctness.
#
#	Return values:
#	  0 - proceed
#	  1 - ^D was typed
#
####################################################
ha_get_ims_instance()
{
	typeset answer
	typeset instance_path

	if [[ ${FIRST} -eq 1 ]]; then
		ha_print_para "$(gettext '
			Next, please specify the name of the iMS instance for
			which to effect the configuration changes.  Omit the
			leading \"msg-\" from the name. Possible instances
			include:
		')"
		echo "${INSTANCES}" | ${SED} 's/^/	/'
		echo
	fi

	# If we don't have a default for the iMS instance name, then
	# pick the first name from the list of possible choices
	if [[ -z "${INSTANCE_NAME}" ]]; then
		INSTANCE_NAME="$(echo "${INSTANCES}" | ${SED} -n -e '/./p' -e '/./q')"
	fi

	while true
	do
		# Get the instance name
		answer=$(ha_prompt "${INSTANCE_NAME_STR}:" "${INSTANCE_NAME}") || return 1

		instance_path="${SERVER_ROOT}/msg-${answer}"
		ha_verify_ims_instance "${instance_path}" || continue
		break
	done

	INSTANCE_NAME=${answer}
	INSTANCE_PATH=${instance_path}

	return 0
}

####################################################
#
# ha_verify_ldap_instance instance-path
#
#	instance-path -- Abosolute file directory path
#	                 to the LDAP server instance
#	                 to configure
#
#	Ensure that instance path specifies an existing
#	directory file.
#
#	Return values:
#	  0 - Valid
#	  1 - Invalid
#
####################################################
ha_verify_ldap_instance()
{
	# Make sure that the instance name is valid
	if [[ ! -d "${1}" ]]; then
		printf "$(gettext 'LDAP server instance does not exist')\n\n"
		return 1
	fi
	if [[ ! -d "${1}/config" ]]; then
		printf "$(gettext 'LDAP server instance does not appear valid; is missing config subdirectory')\n\n"
		return 1
	fi

	return 0
}

####################################################
#
# ha_get_ldap_instance
#
#	Prompt the user for the LDAP configurtion
#	server's instance name and validate its correctness.
#
#	Return values:
#	  0 - proceed
#	  1 - ^D was typed
#
####################################################
ha_get_ldap_instance()
{
	typeset answer
	typeset default
	typeset instance_path

	if [[ -z ${LDAP_INSTANCES} ]]; then
		ha_print_para "$(gettext '
			The iMS server root directory does not contain any
			slapd-* subdirectories.  Skipping configuration of
			LDAP servers.
		')"
		CONFIG_LDAP=0
		LDAP_INSTANCE_NAME=
		LDAP_INSTANCE_PATH=
		return 0
	fi

	if [[ ${CONFIG_LDAP} -ne 0 ]]; then
		default="${YES}"
	else
		default="${NO}"
	fi

	answer=$(ha_prompt_yesno "$(gettext 'Also configure an LDAP server instance in the same iMS server root')" "${default}") || return 1
	if [[ "${answer}" != "yes" ]]; then
		CONFIG_LDAP=0
		LDAP_INSTANCE_NAME=
		LDAP_INSTANCE_PATH=
		return 0
	fi

	if [[ ${FIRST} -eq 1 ]]; then
		ha_print_para "$(gettext '
			Please specify the name of the LDAP server instance
			for which to effect the configuration changes.  This
			LDAP server instance must live in a subdirectory of
			the iMS server root previously specified.  Omit
			the leading \"slapd-\" from the LDAP server instance
			name.  Possible instances include:
		')"
		echo "${LDAP_INSTANCES}" | ${SED} 's/^/	/'
		echo
	fi

	# If we don't have a default for the LDAP instance, then
	#  -- use the same instance name as for the iMS instance
	#     provided that there is a matching LDAP instance, or
	#  -- use the first LDAP instance name for our list of
	#     possible choices
	if [[ -z "${LDAP_INSTANCE_NAME}" ]]; then
		echo "${LDAP_INSTANCES}" | ${GREP} "${INSTANCE_NAME}" > /dev/null
		if [[ $? -eq 0 ]]; then
			LDAP_INSTANCE_NAME="${INSTANCE_NAME}"
		else
			LDAP_INSTANCE_NAME="$(echo "${LDAP_INSTANCES}" | ${SED} -n -e '/./p' -e '/./q')"
		fi
	fi

	while true
	do
		# Get the instance name
		answer=$(ha_prompt "${LDAP_INSTANCE_NAME_STR}:" "${LDAP_INSTANCE_NAME}") || return 1

		instance_path="${SERVER_ROOT}/slapd-${answer}"
		ha_verify_ldap_instance "${instance_path}" || continue
		break
	done

	LDAP_INSTANCE_NAME=${answer}
	LDAP_INSTANCE_PATH=${instance_path}

	return 0
}

####################################################
#
# ha_verify_ip_address ip-address
#
#	ip-address -- IP address associated with the
#	              HA logical host name.
#
#	Ensure that ip-address is syntactically
#	correct.
#
#	Return values:
#	  0 - Valid
#	  1 - Invalid
#
####################################################
ha_verify_ip_address()
{
	echo "${1}" | ${GREP} '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*' > /dev/null
	if [[ $? -eq 0 ]]; then
		return 0
	fi
	printf "$(gettext 'IP address is not in dotted decimal form, a.b.c.d')\n\n"

	return 1
}

####################################################
#
# ha_get_ip_address
#
#	Prompt the user for the IP address associated
#	with the HA logical host name and validate it
#	for syntactical correctness (a.b.c.d).
#
#	Return values:
#	  0 - proceed
#	  1 - ^D was typed
#
####################################################
ha_get_ip_address()
{
	typeset answer

	if [[ ${FIRST} -eq 1 ]]; then
		ha_print_para "$(gettext '
			Please specify the IP address assigned to
			the HA logical host name.  Use dotted decimal form,
			a.b.c.d
		')"
	fi

	while true
	do
		# Get the IP address
		answer=$(ha_prompt "${IP_ADDRESS_STR}:" "${IP_ADDRESS}") || return 1
		ha_verify_ip_address "${answer}" || continue
		break
	done

	IP_ADDRESS=${answer}

	return 0
}

####################################################
#
# ha_confirm_answers
#
#	Display the answers to the server root, instance
#	name, and IP address prompts.  Then provide the
#	user the opportunity to change their answers.
#
#	Return values:
#	  0 - Got an answer
#	  1 - ^D was typed
#
####################################################
ha_confirm_answers()
{
	typeset answer

	if [[ ${CONFIG_LDAP} -ne 0 ]]; then
		printf "\t${IP_ADDRESS_STR}: ${IP_ADDRESS}
\t${SERVER_ROOT_STR}: ${SERVER_ROOT}
#\t${INSTANCE_NAME_STR}: ${INSTANCE_NAME}
\t${LDAP_INSTANCE_NAME_STR}: ${LDAP_INSTANCE_NAME}\n\n"
	else
		printf "\t${IP_ADDRESS_STR}: ${IP_ADDRESS}
\t${SERVER_ROOT_STR}: ${SERVER_ROOT}\n\n"
#\t${INSTANCE_NAME_STR}: ${INSTANCE_NAME}\n\n"
	fi

	answer=$(ha_prompt_yesno "$(gettext 'Do you wish to change any of the above choices?')" "${NO}") || return 1
	if [[ "${answer}" != "yes" ]]; then
		REDO=0
	else
		REDO=1
	fi

	return 0
}

####################################################
#
# ha_print_usage
#
#	Print usage of this script.
#
#	Return values:
#	  0 - Always
#
####################################################
ha_print_usage()
{
	# There are no Messaging Server instances in SUNoneMS6.x releases
	#echo "$(gettext 'usage'): ${PROG} [$(gettext 'ip-address') $(gettext 'ims-server-root') $(gettext 'ims-instance-name') [$(gettext 'ldap-instance-name')]]" >&2
	echo "$(gettext 'usage'): ${PROG} [$(gettext 'ip-address') $(gettext 'ims-server-root') [$(gettext 'ldap-instance-name')]]" >&2
	return 0
}


####################################################
#
# ha_undo config-file stage
#
#	config-file -- Name of the config file to undo
#
#	stage -- 1: Delete new config-file, file.ha
#	         2: Restore old config-file, file.pre-ha
#
#	This function attempts to restore an old configuration
#	file.  If there is no old configuration file then any
#	existing one is deleted.
#
#	Return values:
#	  0 - Always
#
####################################################
ha_undo()
{
	typeset file="${1}"
	integer stage="${2}"

	if [[ $stage -eq 1 ]]; then
		${RM} -f ${file}.ha
	elif [[ $stage -eq 2 ]]; then
		if [[ -e "${file}.pre-ha" ]]; then
			${MV} -f ${file}.pre-ha ${file}
		else
			${RM} -f ${file}
		fi
	fi

	return 0
}

####################################################
#
# ha_shuffle file
#
#	file -- Name of the config file to replace.
#
#	Make a new configuration file active, displacing
#	any old configuration file:
#
#	# getfacl config-file > config-file.acl
#	# mv config-file old-config-file.pre-ha
#	# mv config-file.ha config-file
#	# setfacl -f config-file.acl config-file
#	# rm config-file.acl
#
#	Return values:
#	  0 - Allow user to change answers
#	  1 - Accept answers as is
#
####################################################
ha_shuffle()
{
	typeset file="${1}"
	typeset newfile="${file}.ha"
	typeset oldfile="${file}.pre-ha"
	integer got_acl=0
	integer do_restore=0

	# If an old configuration file exists, then obtain it's ACL
	# and then move it out of harms way.  By moving it out of
	# harm's way, we can later undo the change should a downstream
	# problem occur or should the sys admin later wish to back
	# out the change

	if [[ -e "${file}" ]]; then
		${GETFACL} ${file} > ${file}.acl
		if [[ $? -eq 0 ]]; then
			got_acl=1
		fi

		${MV} -f ${file} ${oldfile}
		if [[ $? -ne 0 ]]; then
			printf "$(gettext 'Unable to move an existing configuration file')\n" >&2
			if [[ $got_acl -ne 0 ]]; then
				${RM} -f ${file}.acl
			fi
			return 1
		fi
		do_restore=1
	fi

	# Now, move the new configuration file on top of the old one

	${MV} -f ${newfile} ${file}
	if [[ $? -ne 0 ]]; then
		printf "$(gettext 'Unable to move new configuration file into place')\n" >&2
		if [[ do_restore -ne 0 ]]; then
			${MV} -f ${oldfile} ${file}
			if [[ $? -ne 0 ]]; then
				printf "$(gettext 'Unable to restore the old configuration file')\n" >&2
			fi
		fi
		return 1
	fi

	# Attempt to set the permissions to be that of the
	# original file.  If there was no original file or if
	# we were unable to get an ACL for the original file,
	# then set the file to be owned by IMTA_USER, if known.

	if [[ $got_acl -ne 0 ]]; then
		typeset user="$(${SED} -n -e 's|^# *owner: *\(.*\)$|\1|p' <${file}.acl)"
		typeset group="$(${SED} -n -e 's|^# *group: *\(.*\)$|\1|p' <${file}.acl)"
		${SETFACL} -f ${file}.acl ${file}
		${CHOWN} ${user}:${group} ${file}
		${RM} -f ${file}.acl
	elif [[ -z "$IMTA_USER" ]]; then
		${CHOWN} ${IMTA_USER} ${file}
	fi

	return 0
}


####################################################
#
# ha_change_file file option pattern
#
#	file    -- Name of the config file to update
#	option  -- Option and value to set
#	pattern -- sed pattern for searching for the option
#
#	Create a new version of the configuration file
#	name file.ha and containing the specified option
#	setting.  If the configuration file already has
#	the option set, then it is replaced with the new
#	value.  Otherwise, the option is pre-pended to
#	the file.
#	any old c
#
#	Return values:
#	  0 - Success
#	  1 - Update failed
#
####################################################
ha_change_file()
{
	typeset file="${1}"
	typeset option="${2}"
	typeset pattern="${3}"

	# Provide some feedback
	echo "$(gettext 'Updating the file') ${file}"

	# See if the file contains the option already

	${GREP} "${pattern}" ${file} > /dev/null

	# Effect the change

	if [[ $? -eq 0 ]]; then

		# Match(es) found; replace with ${option}

		${SED} -e "s|${pattern}|${option}|g" < ${file} > ${file}.ha
		if [[ $? -eq 0 ]]; then
			return 0
		fi
	else

		# No matches found, or the file doesn't exist
		# Add ${option} to the file

		echo "${option}" | ${CAT} -s - ${file} > ${file}.ha
		if [[ $? -eq 0 ]]; then
			return 0
		fi
	fi

	# Something went wrong
	${RM} -f ${file}.ha
	printf "$(gettext 'Update failed')\n" >&2
	return 1
}

main()
{
	typeset old_ip_addr=
	typeset old_http_smtphost=
	integer http_smtphost_ok=0
	integer old_ip_addr_ok=0
	integer local_watcherenable_ok=0
	integer local_autorestart_ok=0
	typeset old_local_autorestart=
	typeset old_local_watcherenable=
	integer http_smtphost_undo=0
	integer local_autorestart_undo=0
	integer local_watcherenable_undo=0
	integer disp_cnf_undo=0
	integer jbc_cnf_undo=0
	integer ldap_cnf_undo=0
	integer res

	# Must be root
	ha_verify_isroot || return 1

	# Run in batch or interactive mode
	if [[ $# -eq 2 || $# -eq 3 ]] ; then

		# Batch mode
		# prog [ip-address sever-root instance-name [ldap-instance-name]]

		IP_ADDRESS="${1}"
		SERVER_ROOT="${2}"
		#INSTANCE_NAME="${3}"
		#There are no Messaging Server instances in SunOneMS6.x releases
		#INSTANCE_PATH="${SERVER_ROOT}/msg-${INSTANCE_NAME}"
		INSTANCE_PATH="${SERVER_ROOT}"
		if [[ $# -eq 3 ]]; then
			CONFIG_LDAP=1
			LDAP_INSTANCE_NAME="${3}"
			INSTANCE_PATH="${SERVER_ROOT}/slapd-${LDAP_INSTANCE_NAME}"
		else
			CONFIG_LDAP=0
			LDAP_INSTANCE_NAME=
			INSTANCE_PATH=
		fi

		ha_verify_ip_address "${IP_ADDRESS}" || return 1
		ha_verify_server_root "${SERVER_ROOT}" || return 1
		# There are no Messaging Server instances in SUNoneMS6.x releases
		#ha_verify_ims_instance "${INSTANCE_PATH}" || return 1
		if [[ ${CONFIG_LDAP} -ne 0 ]]; then
			ha_verify_ldap_instance "${LDAP_INSTANCE_PATH}" || return 1
		fi

	elif [[ $# -eq 0 ]] ; then

		# Interactive mode
		SERVER_ROOT=$(expr "${ABSPROG}" : '\(.*\)/bin/msg/install/bin/.*')
		while true
		do
			echo
			ha_get_ip_address || return 1
			ha_get_server_root || return 1
			#ha_get_ims_instance || return 1
			ha_get_ldap_instance || return 1
			REDO=0
			ha_confirm_answers || return 1
			if [[ $REDO -eq 0 ]]; then
				break;
			fi
			FIRST=0
		done
	else

		# Wrong number of parameters specified

		ha_print_usage
		return 1
	fi

	# Obtain the username for the iMS servers.  We first need
	# to know the server root and instance name in order to
	# get this information.

        #ha_get_imta_user "${INSTANCE_PATH}" || return 1
        ha_get_imta_user "${SERVER_ROOT}" || return 1

	# Now act upon this information
	# We make copies of each configuration file,
	# effect the desired changes, and then move
	# these new configuration files into place

	# dispatcher.cnf
	#ha_change_file \
	#	"${INSTANCE_PATH}/imta/config/dispatcher.cnf" \
	#	"${SERVER_ROOT}/config/dispatcher.cnf" \
	#	"INTERFACE_ADDRESS=${IP_ADDRESS}" \
	#	"^!*[iI][nN][tT][eE][rR][fF][aA][cC][eE]_[aA][dD][dD][rR][eE][sS][sS]=.*$" || goto abort
	#dispatcher.cnf
	ha_change_file \
		"${SERVER_ROOT}/config/dispatcher.cnf" \
		"INTERFACE_ADDRESS=${IP_ADDRESS}" \
		"^!*[iI][nN][tT][eE][rR][fF][aA][cC][eE]_[aA][dD][dD][rR][eE][sS][sS]=.*$" || goto abort
	disp_cnf_undo=1

	# job_controller.cnf
	#ha_change_file \
	#	"${INSTANCE_PATH}/imta/config/job_controller.cnf" \
	#	"${SERVER_ROOT}/config/job_controller.cnf" \
	#	"interface_address=${IP_ADDRESS}" \
	#	"^!*[iI][nN][tT][eE][rR][fF][aA][cC][eE]_[aA][dD][dD][rR][eE][sS][sS]=.*$" || goto abort
	#job_controller.cnf
	ha_change_file \
		"${SERVER_ROOT}/config/job_controller.cnf" \
		"interface_address=${IP_ADDRESS}" \
		"^!*[iI][nN][tT][eE][rR][fF][aA][cC][eE]_[aA][dD][dD][rR][eE][sS][sS]=.*$" || goto abort
	jbc_cnf_undo=1

	# slapd.conf
	if [[ ${CONFIG_LDAP} -ne 0 ]]; then
		ha_change_file \
			"${LDAP_INSTANCE_PATH}/config/slapd.conf" \
			"listenhost ${IP_ADDRESS}" \
			"^#*[lL][iI][sS][tT][eE][nN][hH][oO][sS][tT] .*$" || goto abort
		ldap_cnf_undo=1
	fi

	# configutil: set the service.listenaddr parameter

	# Save the old setting
	echo "$(gettext 'Setting the service.listenaddr configutil parameter')"
	#old_ip_addr=$(${INSTANCE_PATH}/imsimta configutil -o service.listenaddr 2>&1)
	old_ip_addr=$(${SERVER_ROOT}/sbin/imsimta configutil -o service.listenaddr 2>&1)
	if [[ $? -ne 0 ]]; then
		old_ip_addr_ok=0
	else
		old_ip_addr_ok=1
	fi
	${SERVER_ROOT}/sbin/imsimta configutil -o service.listenaddr -v ${IP_ADDRESS} 1>/dev/null 2>&1
	if [[ $? -ne 0 ]]; then
		# Unable to effect the service.listenaddr setting
		printf "$(gettext 'Unable to set the service.listenaddr configutil parameter')\n" >&2
		goto abort
	fi
	ip_addr_undo=1

	# configutil: set the service.http.smtphost config parameter

	# Save the old setting
	echo "$(gettext 'Setting the service.http.smtphost configutil parameter')"
	old_http_smtphost=$(${SERVER_ROOT}/sbin/imsimta configutil -o service.http.smtphost 2>&1)
	if [[ $? -ne 0 ]]; then
		http_smtphost_ok=0
	else
		http_smtphost_ok=1
	fi
	${SERVER_ROOT}/sbin/imsimta configutil -o service.http.smtphost -v ${IP_ADDRESS} 1>/dev/null 2>&1
	if [[ $? -ne 0 ]]; then
		# Unable to effect the service.http.smtphost setting
		printf "$(gettext 'Unable to set the service.http.smtphost configutil parameter')\n" >&2
		goto abort
	fi
	http_smtphost_undo=1

	# configutil: set the local.watcher.enable config parameter

	# Save the old setting
	echo "$(gettext 'Setting the local.watcher.enable configutil parameter')"
	old_local_watcherenable=$(${SERVER_ROOT}/sbin/imsimta configutil -o local.watcher.enable 2>&1)
	if [[ $? -ne 0 ]]; then
		local_watcherenable_ok=0
	else
		local_watcherenable_ok=1
	fi
	${SERVER_ROOT}/sbin/imsimta configutil -o local.watcher.enable -v yes 1>/dev/null 2>&1
	if [[ $? -ne 0 ]]; then
		# Unable to effect the local.watcher.enable setting
		printf "$(gettext 'Unable to set the local.watcher.enable configutil parameter')\n" >&2
		goto abort
	fi
	local_watcherenable_undo=1

	# configutil: set the local.autorestart config parameter

	# Save the old setting
	echo "$(gettext 'Setting the local.autorestart configutil parameter')"
	old_local_autorestart=$(${SERVER_ROOT}/sbin/imsimta configutil -o local.autorestart 2>&1)
	if [[ $? -ne 0 ]]; then
		local_autorestart_ok=0
	else
		local_autorestart_ok=1
	fi
	${SERVER_ROOT}/sbin/imsimta configutil -o local.autorestart -v yes 1>/dev/null 2>&1
	if [[ $? -ne 0 ]]; then
		# Unable to effect the local.autorestart setting
		printf "$(gettext 'Unable to set the local.autorestart configutil parameter')\n" >&2
		goto abort
	fi
	local_autorestart_undo=1

	# Now shuffle the files, saving the old configuration files
	# as config-file.pre-ha and putting the new configuration files
	# in place.
	ha_shuffle "${SERVER_ROOT}/config/dispatcher.cnf" || goto abort
	disp_cnf_undo=2
	ha_shuffle "${SERVER_ROOT}/config/job_controller.cnf" || goto abort
	jbc_cnf_undo=2

	if [[ ${CONFIG_LDAP} -ne 0 ]]; then
		ha_shuffle "${LDAP_INSTANCE_PATH}/config/slapd.conf" || goto abort
		ldap_cnf_undo=2
	fi

	# imsimta cnbuild commented out as it is not presently
	# needed -- the changes made do not go into the compiled
	# configuration.

	# Finally, attempt an imsimta cnbuild command
	# typeset cnbuild="$(${INSTANCE_PATH}/imsimta cnbuild)"
	# if [[ -z "${cnbuild}" ]]; then
	#    echo "$(gettext 'iMS configuration successfully recompiled with "imsimta cnbuild"')\n"
	#else
	#	echo "$(gettext 'iMS configuration needs to be recompiled with "imsimta cnbuild"')\n"
	# fi

	printf "$(gettext 'Configuration successfully updated')\n"
	return 0

	# Bail out, attempting to restore the old configuration
 abort:
	printf "$(gettext 'Update failed; could not change one or more settings')\n" >&2
	#ha_undo "${INSTANCE_PATH}/imta/config/dispatcher.cnf" "$disp_cnf_undo"
	ha_undo "${SERVER_ROOT}/config/dispatcher.cnf" "$disp_cnf_undo"
	#ha_undo "${INSTANCE_PATH}/imta/config/job_controller.cnf" "$jbc_cnf_undo"
	ha_undo "${SERVER_ROOT}/config/job_controller.cnf" "$jbc_cnf_undo"
	ha_undo "${LDAP_INSTANCE_PATH}/config/slapd.conf" "$ldap_cnf_undo"
	if [[ $ip_addr_undo -eq 1 && $old_ip_addr_ok -ne 0 ]]; then
		# Attempt to restore the old setting
		#${INSTANCE_PATH}/imsimta configutil -o service.listenaddr -v ${old_ip_addr} 1>/dev/null 2>&1
		${SERVER_ROOT}/sbin/imsimta configutil -o service.listenaddr -v ${old_ip_addr} 1>/dev/null 2>&1
	fi
	if [[ $http_smtphost_undo -eq 1 && $http_smtphost_ok -ne 0 ]]; then
		# Attempt to restore the old setting
		${SERVER_ROOT}/sbin/imsimta configutil -o service.http.smtphost -v ${old_http_smtphost} 1>/dev/null 2>&1
	fi
	if [[ $local_watcherenable_undo -eq 1 && $local_watcherenable_ok -ne 0 ]]; then
		# Attempt to restore the old setting
		${SERVER_ROOT}/sbin/imsimta configutil -o local.watcher.enable -v ${old_local_watcherenable} 1>/dev/null 2>&1
	fi
	if [[ $local_autorestart_undo -eq 1 && $local_autorestart_ok -ne 0 ]]; then
		# Attempt to restore the old setting
		${SERVER_ROOT}/sbin/imsimta configutil -o local.autorestart -v ${old_local_autorestart} 1>/dev/null 2>&1
	fi

	return 1
}

	umask 0
	main $*
	exit $?
