#!/bin/dash
# Convenience service wrapper
# (C) James Budiono 2014, 2022
# License: GPL Version 3 or later.

### configuration
SERVICE_DIR=/etc/init.d
RESERVED=":S01logging:S40network:README.md:"
[ -e /etc/servicemanager ] && . /etc/servicemanager	# override default settings

### re-run as root - does not return if privilege escalation is needed
run_as_root() {
	if [ $(id -u) -ne 0 ]; then
		if [ "$DISPLAY" ] && type gtksu > /dev/null && ! [ "$NO_GTKSU" ]; then
			exec gtksu "Service Control" "$0" "$@"
		else
			exec su -c "$0 $*"
		fi
	fi
}

### check for reserved services which we don't want to show
# $1-service file
is_reserved() {
	local p=${1##*/}
	case "$RESERVED" in 
		*:${p}:*) return 0
	esac
	return 1
}

# $1-service filename, output: SNAME=service name
get_service_name() {
	case ${1#$SERVICE_DIR/} in
		*-*) SNAME=${1#*-} ;;
		S??*) SNAME=${1#S??} ;;
		rc.*) SNAME=${1#rc.} ;;
		*) SNAME=${1} ;;
	esac
}

### helper
#$1-service-file,$2-service-name, output DESC and HELP
get_service_description() {
	local p
	DESC="" HELP=""
	
	# attempt to find description and help from service file itself
	while read -r p; do
		case "$p" in
			*[Dd]escription:*) DESC=${p#*: } ;;
			*[Hh]elp*) HELP=${p#*: } ;;
		esac
	done << EOF
$(grep -iE '^#.*(description:|help:)' $SERVICE_DIR/$1 2>/dev/null)
EOF

	# legacy way of getting description and help
	if [ -z "$DESC" ]; then
		OIFS=$IFS; IFS=";"
		for p in $SERVICE_DESC; do
			if [ $2 = "${p%%|*}" ]; then
				DESC=${p##*|}
				break
			fi
		done
		
		for p in $SERVICE_HELP; do
			if [ $2 = "${p%%|*}" ]; then
				HELP=${p##*|}
				break
			fi
		done
		IFS=$OIFS
	fi
}

# $1-service name
find_service() {
	# first try: *-* pattern
	SERVICE=$(echo $SERVICE_DIR/*-$1)
	[ -e "$SERVICE" ] && return
	# 2nd try: S??* pattern
	SERVICE=$(echo $SERVICE_DIR/S??$1)
	[ -e "$SERVICE" ] && return
	# 3rd try: rc.* pattern
	SERVICE=$(echo $SERVICE_DIR/rc.$1)
	[ -e "$SERVICE" ] && return
	# last try: actual name
	SERVICE=$SERVICE_DIR/$1
	[ -e "$SERVICE" ] && return
	echo "$1" is not a service.
	exit 1
}

### main
case "$1" in
	--help|-h|"")
		echo "Usage: ${0##*/} --help | --list | --status-all | --enable service |"
		echo "       --disable service | service-name [svc-command | --full-restart]"
		echo "       Usual svc-commands: start stop status restart"
		;;
	--list)
		for sfile in $SERVICE_DIR/*; do
			disabled="(disabled)"
			test -x $sfile && disabled=""		
			sfile=${sfile#$SERVICE_DIR/}
			is_reserved $sfile && continue
			get_service_name $sfile
			get_service_description $sfile $SNAME
			printf "%s %s\n  %s\n" "$SNAME" "$disabled" "$DESC"
		done
		;;
	--status-all)
		for sfile in $SERVICE_DIR/*; do
			sfile=${sfile#$SERVICE_DIR/}
			is_reserved $sfile && continue
			sh $SERVICE_DIR/$sfile status
		done
		;;
	--enable)
		run_as_root "$@"
		shift
		find_service "$1" &&
		get_service_name $SERVICE &&
		chmod +x $SERVICE &&
		echo $SNAME enabled
		;;
	--disable)
		run_as_root "$@"
		shift
		find_service "$1" &&
		get_service_name $SERVICE &&
		chmod -x $SERVICE &&
		echo $SNAME disabled
		;;
	*) 
	find_service "$1";
	case "$2" in
		--full-restart)
			run_as_root "$@"
			sh $SERVICE stop
			sleep 1
			sh $SERVICE start
			;;
		""|status)
			sh $SERVICE status
			;;
		*)
			run_as_root "$@"
			sh $SERVICE "$2"
			;;
	esac
	;;
esac
