#!/bin/sh

# Wrapper for user OpenRC service management.
# User services expected to be in ${REF_ETC}/init.d
# Configs for user services expected to be in ${REF_ETC}/conf.d

# TODO: installation of aliases (or 'lnsvc' for aliasing in /opt/)

: ${TOOL_ROOT:=${TOOL_ROOT:-"/opt"}}

REF_ETC=${TOOL_ROOT}/etc

SAV=svcsaved

# Figure out system OpenRC root

if [ -d /etc/init.d ]; then
	RC_ROOT=/etc
else
	if [ -d /etc/openrc/init.d ]; then
		RC_ROOT=/etc/openrc
	else
		echo "Unable to determine OpenRC root. Is OpenRC installed?"
		exit 1
	fi
fi

usage()
{
	echo "Usage: $(basename $0) <add|del> svc_name [runlevel]"
	echo "When 'add' is specified, this script creates symlinks for"
	echo "${REF_ETC}/[init.d,conf.d]/svc_name in ${RC_ROOT}/[init.d,conf.d] and"
	echo "adds svc_name to the specified runlevel (\"default\" is used if no runlevel"
	echo "is given); if the symlinks already exist, it will be removed;"
	echo "if ${RC_ROOT}/[init.d,conf.d]/svc_name point to files, these files"
	echo "will be backed up with \"${SAV}\" extension."
	echo "When 'del' is specified, reverse operations are performed."
}

case $# in
	2)
		RUNLEVEL=default
		;;
	3)
		RUNLEVEL=$3
		;;
	*)
		usage
		exit 1
		;;
esac

# need_move() target_name backup_extension
# Parameters:
#	target_name - name of filesystem object to check;
#	backup_extension - extension to append to backup of the target.
# Returns:
#  0 - no operations are necessary
#  1 - manual intervention is required
#  2 - move operation shall be enought for cleanup
#  3 - unlink operation shall be enought for cleanup

need_move()
{
	TGT=$1
	SAV=$2
	[ -L ${TGT} ] && return 3
	if [ -f ${TGT} ]; then
		if [ -f ${TGT}.${SAV} ]; then
			echo "Both ${TGT} and ${TGT}.${SAV} already exist."
			echo "Unable to continue; please, perform manual cleanup."
			return 1
		fi
		return 2
	fi
	return 0
}

pre_insert()
{
	case $3 in
		2)
			mv ${RC_ROOT}/$2/$1 ${RC_ROOT}/$2/$1.${SAV}
			;;
		3)
			rm ${RC_ROOT}/$2/$1
			;;
		*)
			;;
	esac
}

insert_service()
{
	SAV=svcsaved
	need_move ${RC_ROOT}/init.d/$1 ${SAV}
	NEEDMV1=$?
	need_move ${RC_ROOT}/conf.d/$1 ${SAV}
	NEEDMV2=$?
	[ ${NEEDMV1} -eq 1 ] && return 1
	[ ${NEEDMV2} -eq 1 ] && return 1
	if ! [ -f ${REF_ETC}/init.d/$1 ]; then
		echo "No service $1 found in ${REF_ETC}/init.d, exiting."
		return 1
	fi
	pre_insert $1 init.d ${NEEDMV1}
	ln -s ${REF_ETC}/init.d/$1 ${RC_ROOT}/init.d/$1
	if ! [ -f ${REF_ETC}/conf.d/$1 ]; then
		echo "Warning: no config for service $1 found in ${REF_ETC}/conf.d"
	else
		pre_insert $1 conf.d ${NEEDMV2}
		ln -s ${REF_ETC}/conf.d/$1 ${RC_ROOT}/conf.d/$1
	fi
	rc-update add $1 ${RUNLEVEL}
}

plugout()
{
	need_move ${RC_ROOT}/$2/$1 ${SAV}
	[ $? -eq 3 ] && rm ${RC_ROOT}/$2/$1
	[ -f ${RC_ROOT}/$2/$1.${SAV} ] && mv ${RC_ROOT}/$2/$1.${SAV} ${RC_ROOT}/$2/$1
}

plugout_service()
{
	plugout $1 init.d
	plugout $1 conf.d
	rc-update del $1 ${RUNLEVEL}
}

case $1 in
	add)
		insert_service $2
		;;
	del)
		plugout_service $2
		;;
	*)
		usage
		exit 1
		;;
esac
