#!/bin/sh
# vim:ts=4:sts=4:fdm=marker:cms=\ #\ %s
# $Id: update-inetd.sh 286 2009-03-01 11:20:28Z robert $
#
# rlinetd's version of update-inetd.
# Robert Luberda <robert@debian.org>, 2001, 2009
#

set -e

PATH=/usr/sbin:$PATH

# global variables
g_version='$Revision: 286 $'
g_rlinconfdir="/etc/rlinetd.d"
g_ucfdir="/var/lib/rlinetd/ucf"

g_debug=0
g_need_reload=0
g_line=""
g_mode=""

# error - prints error message and exits the program  # {{{
error() 
{
	msg="$1"
	echo "update-inetd: $msg" >&2
	debug "Program arguments: --$g_mode \"$line\""
	exit 1
} # }}}

# debug - prints debug info # {{{
debug()
{
	[ $g_debug -eq 1 ] || return 0
	msg="$1"
	echo "$msg"
} # }}}

# ucf_ack - asks user a question using ucf # {{{
ucf_ask() 
{
	cachedfile="$1"
	conffile="$2"

	if [ ! -e "$conffile" ] || ! cmp -s "$cachedfile" "$conffile"; then
		debug "Running ucf on $cachedfile and $conffile"
		# note: --debconf-ok would causes ucf to hang if db_stop has been called
        # (e.g. samba's postinst does this)
		ucf --three-way "$cachedfile" "$conffile"
		ucfr "rlinetd" "$conffile"
		g_need_reload=1
	else
		debug "$cachedfile and $conffile identical, skipping ucf"
	fi

} # }}}

# ucf_purge - purges ucf configuration # {{{
ucf_purge()
{
	conffile="$1"

	debug "Removing $conffile from ucf"
	ucf --purge "$conffile"
    ucfr --purge "rlinetd" "$conffile" || true
	g_need_reload=1
} # }}}

# enable_disable_util - enables or disables an entry # {{{
enable_disable_util()
{
	cachedfile="$1"
	conffile="$2"
	enable="$3"

	debug "Setting enable to $3 in $cachedfile"

	sed -e "s/^\([ \t]*enabled[ \t][ \t]*\).*$/\1$enable;/" < "$cachedfile" >  "$cachedfile.tmp"
	mv "$cachedfile.tmp"  "$cachedfile"


	ucf_ask "$cachedfile" "$conffile"

} # }}}

# enable - calls enable_disable_util to enable an entry # {{{
enable()
{
	enable_disable_util "$1" "$2" "yes"
} # }}}

# disable - calls enable_disable_util to disable an entry # {{{
disable()
{
	enable_disable_util "$1" "$2" "no"
} # }}}

# remove - removes an entry # {{{
remove()
{
	cachedfile="$1"
	conffile="$2"

	debug "Removing $cachedfile, $conffile"

	rm -f "$cachedfile" "$conffile"
	ucf_purge "$conffile"

} # }}}

# add - adds a new entry # {{{
add()
{
	line="$1"
	files=`inetd2rlinetd --force-overwrite --print-file-names -l "$line" "$g_ucfdir"`
	debug "Converted $line saved in $files"
	[ -z "$file" ] || return 0

	for file in $files; do
		file="${file##*/}"
		case "$file" in
			*_udp)
				basename="${file%_*}"
				if [ ! -e "$g_rlinconfdir/$file" ] &&
					[ ! -e "$g_ucfdir/$basename" ]  &&
					[ -f "$g_rlinconfdir/$basename" ]; then
					# rename previous versions of file
					debug "Renaming $g_rlinconfdir/$basename to $g_rlinconfdir/$file"
					mv -f "$g_rlinconfdir/$basename" "$g_rlinconfdir/$file"
				fi
				;;
		esac

		ucf_ask "$g_ucfdir/$file" "$g_rlinconfdir/$file"
	done
} # }}}

# operation  - calls add, remove, enable or disable # {{{
operation()
{
	operation="$1"
	line="$2"

	[ -n "$line" ] || error "--$operation requires argument"

	debug "Running $operation for $line"

	# add
	if [ "$operation" = "add" ]; then
		add "$line"
		return 0
	fi

	# disable, enable, remove; line can be comma separated list of values
	service=""
	while [ "$line" != "$service" ] ; do
		service="${line%,*}"
		line="${line#*,}"
		found=0
		for proto in "" _udp; do
			basefile="${service}${proto}"
			file="$g_ucfdir/$basefile"
			debug "Checking for file $file"
			if [ -e "$file" ]; then
				found=1
				"$operation" "$file" "$g_rlinconfdir/$basefile"
			fi
		done

		if [ $found -eq 0 ]; then
			echo "Cannot find cached rlinetd's config files for service $service, ignoring $operation request" >&2;
		fi
	done
} # }}}

# reload_rlinetd - reloads rlinetd daemon # {{{
reload_rlinetd()
{
	if [ "$g_need_reload" -eq 0 ]; then
		debug "Configuration not changed, not reloading rlinetd"
		return 0
	fi

	debug "Reloading rlinetd config files"

    killall -HUP rlinetd || true
} # }}}


# MAIN FUNCTION # {{{

# parse arguments # {{{
ignore_next=0
for i in "$@" ; do
    # note: the original update-inetd allows things  like "--add --comment-chars XX LINE_TO_ADD"
    if [ "$ignore_next" -eq 1 ] ; then
		ignore_next=0
		continue
	fi

	case "$i" in
		"--add"|"--remove"|"--disable"|"--enable")
			[ -z "$mode" ] || error "$i conflicts with --$mode"
			g_mode="$i"
			g_mode="${g_mode#--}"
			;;
		"--debug")
			g_debug=1
			;;
		"--version")
			echo "rlinetd's version of update-inetd"
			echo "version: $g_version"
			exit 0
			;;
		"--multi"|"--verbose")
			# ignore
			;;
		"--file"|"--group"|"--comment-chars")
			ignore_next=1
			;;
		"--*")
			echo "Unknown option \`$i\' passed to $0, ignoring" >&2;
			;;	
		*)	if [ -n "$g_mode" ] ; then
				[ -z "$g_line" ] || error "--$g_mode requires only one argument"
				g_line="$i"
			fi
			;;
	esac
done # }}}

# do our job
[ -z "$g_mode" ] || operation "$g_mode" "$g_line"

# reload configuration
reload_rlinetd

# execute real update-inetd
real_upd=`dpkg-divert --truename /usr/sbin/update-inetd`
[ -x "$real_upd" ] && exec "$real_upd" "$@"

exit 0
 # }}}
