#!/bin/sh
# This is a shell library to interface to the Debian configuration management
# system.

###############################################################################
# Initialization.

_DEBCONF_IMPL=
if [ "${DEBCONF_USE_CDEBCONF:-}" ]; then
	# Use cdebconf if explicitly requested.
	_DEBCONF_IMPL=cdebconf
elif [ -x /usr/share/debconf/frontend ] && \
     [ ! -h /usr/share/debconf/frontend ]; then
	# Fall back to debconf, but only if installed.  (cdebconf currently
	# installs /usr/share/debconf/frontend as a symlink to
	# /usr/lib/cdebconf/debconf.)
	_DEBCONF_IMPL=debconf
else
	# Last resort: use cdebconf although not explicitly requested.
	_DEBCONF_IMPL=cdebconf
fi

# Check to see if a FrontEnd is running.
if [ ! "${DEBIAN_HAS_FRONTEND:-}" ]; then
	# Since there is no FrontEnd, this program execs a FrontEnd.
	# It will then run a new copy of $0 that can talk to it.
	if [ "$_DEBCONF_IMPL" = cdebconf ]; then
		exec /usr/lib/cdebconf/debconf -- $0 "$@"
	else
		export PERL_DL_NONLAZY=1
		exec /usr/share/debconf/frontend $0 "$@"
	fi
fi

# Only do this once.
if [ -z "${DEBCONF_REDIR:-}" ]; then
	# Redirect standard output to standard error. This prevents common
	# mistakes by making all the output of the postinst or whatever
	# script is using this library not be parsed as confmodule commands.
	#
	# To actually send something to standard output, send it to fd 3.
	exec 3>&1
	if [ "$_DEBCONF_IMPL" = cdebconf ]; then
		exec 1>&5
	else
		exec 1>&2
	fi
	DEBCONF_REDIR=1
	export DEBCONF_REDIR
fi

# In cdebconf, the original stdin/stdout/stderr fds are duplicated onto fds
# DEBCONF_OLD_FD_BASE to DEBCONF_OLD_FD_BASE + 2. These values are exported
# so that you can get the original fds back. This is kind of a hack:
# ideally, we might use something like a socket for the debconf protocol
# instead of stdio.
DEBCONF_OLD_FD_BASE='4'
export DEBCONF_OLD_FD_BASE

###############################################################################
# Commands.

_db_cmd () {
	local _db_internal_IFS="$IFS"
	IFS=' '
	printf '%s\n' "$*" >&3
	# Set to newline to get whole line.
	IFS='
'
	read -r _db_internal_line
	IFS="$_db_internal_IFS"

	# Disgusting, but it's the only good way to split the line,
	# preserving all other whitespace.
	RET="${_db_internal_line#[! 	][ 	]}"
	local _db_status="${_db_internal_line%%[ 	]*}"
	case "$_db_status" in
		1)	# escaped data
			if [ "$_DEBCONF_IMPL" = cdebconf ]; then
				_DEBCONF_ESCAPE=/usr/lib/cdebconf/debconf-escape
			else
				_DEBCONF_ESCAPE=debconf-escape
			fi
			RET="$(printf '%s' "$RET" | $_DEBCONF_ESCAPE -u)"
			return 0
			;;
	esac
	return "$_db_status"
}

db_beginblock ()	{ _db_cmd "BEGINBLOCK" "$@"; }
db_capb ()	{ _db_cmd "CAPB" "$@"; }
db_clear ()	{ _db_cmd "CLEAR" "$@"; }
db_data ()	{ _db_cmd "DATA" "$@"; }
db_endblock ()	{ _db_cmd "ENDBLOCK" "$@"; }
db_fget ()	{ _db_cmd "FGET" "$@"; }
db_fset ()	{ _db_cmd "FSET" "$@"; }
db_get ()	{ _db_cmd "GET" "$@"; }
db_go ()	{ _db_cmd "GO" "$@"; }
db_info ()	{ _db_cmd "INFO" "$@"; }
db_input ()	{ _db_cmd "INPUT" "$@"; }
db_metaget ()	{ _db_cmd "METAGET" "$@"; }
db_progress ()	{ _db_cmd "PROGRESS" "$@"; }
db_purge ()	{ _db_cmd "PURGE" "$@"; }
db_register ()	{ _db_cmd "REGISTER" "$@"; }
db_reset ()	{ _db_cmd "RESET" "$@"; }
db_set ()	{ _db_cmd "SET" "$@"; }
db_settitle ()	{ _db_cmd "SETTITLE" "$@"; }
db_subst ()	{ _db_cmd "SUBST" "$@"; }
db_title ()	{ _db_cmd "TITLE" "$@"; }
db_unregister ()	{ _db_cmd "UNREGISTER" "$@"; }
db_version ()	{ _db_cmd "VERSION" "$@"; }
db_x_loadtemplatefile ()	{ _db_cmd "X_LOADTEMPLATEFILE" "$@"; }

# An old alias for input.
db_text () {
	db_input "$@"
}

# Cannot read a return code, since there is none and it would block.
db_stop () {
	echo STOP >&3
}