#!/bin/sh
#
# Copyright (c) 2006 Dominic Fandrey <lon_kamikaze@gmx.de>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#

version=1.1

# Get a list of all startup script paths.
{
	# Obtain script paths.
	. /etc/defaults/rc.conf
	suggested_script_paths="/etc/rc.d $local_startup"

	# Sort out inexistand paths.
	script_paths=
	for path in $suggested_script_paths; {
		[ -d "$path" ] && script_paths="$script_paths $path"
	}
	# Remove the space at the beginning.
	script_paths=$(echo "$script_paths" | sed -E 's|^ ||1')
}

# Use the script call as a command given to the selected startscript.
# Several commands can be realized with symlinks to this script,
# such as stop, status, onestart and so on. All with the prefix 'rc'.
command=$(echo $0 | sed -E 's|^.*/rc||1')

# Outputs a list of all services provided by the available startup scripts.
start_list() {
	# Grep for services over all startup scripts.
	# This looks a bit messy because it is not relying on a fixed amount
	# of spaces and tabs.
	for script_path in $script_paths; {
		grep -Eh '#[[:space:]]*PROVIDE:[[:space:]]*' $script_path/* | sed 's|#[[:space:]]*PROVIDE:[[:space:]]*||1' | sed 's|[[:space:]]+||g'
	}
}

# Option triggers.
option_mode=0

# Display help.
start_help() {
	echo "rcstart ($command) v$version
usage:	rc$command [-v] [-n] [-p] [-s] [-l] [-h] [services]"
}

# Handle options.
start_options() {
	case $1 in
		"-v" | "--verbose") {
			option_mode=1
			return 0
		};;
		"-n" | "--not-verbose" ) {
			option_mode=0
			return 0
		};;
		"-p" | "--paths") {
			printf "$(echo "$script_paths" | sed -E 's|[[:space:]]+|\\n|g')\n"
			return 0
		};;
		"-s" | "--services") {
			start_list
			return 0
		};;
		"-l" | "--locate") {
			option_mode=2
			return 0
		};;
		"-h" | "--help") {
			start_help
			return 0
		};;
		-? | --*) {
			echo "Unknown parameter \"$1\""
			return 0
		};;
		-*) {
			# Split parameters.
			parameter_tail=$(echo $1 | sed -E 's|^[-].||1')
			parameter=$(echo $1 | sed -E "s|$parameter_tail\$||1")
			# Handle the first parameter.
			start_options $parameter
			# Handle the following parameters.
			start_options -$parameter_tail
			return 0
		};;
	esac

	# The given parameter is not an option.
	return 1
}

# Looks for the scripts that provide the service given as the first parameter.
# This paramter is treated as a regular expression.
start_script() {
	# This is the regular expression to find a service.
	provide_expr="#[[:space:]]*PROVIDE:[[:space:]]*"
	service_expr="$provide_expr$1[[:space:]]*\$"

	# Go through the list of script_paths and execute the first
	# script that provides the wanted service.
	for script_path in $script_paths; {
		# Find matching scripts in this folder.
		scripts=$(grep -El "$service_expr" $script_path/* 2> /dev/null)
		for script in $scripts; {
			# Ignore non executable scripts.
			[ -x $script ] || continue

			# Get the name of the provided service.
			service=$(grep -E "$service_expr" $script | sed -E "s|$provide_expr||1" | sed 's|[[:space:]]+||g')

			# locate mode
			if [ $option_mode -eq 2 ]; then
				echo "$service:	$script"
				continue
			fi

			# verbose mode
			if [ $option_mode -eq 1 ]; then
				echo "$service command:	$script $command"
				eval "$script $command"
				echo "$service returned:	$?"
				continue
			fi

			eval "$script $command"
			continue
		}
	}
}

# Run the requested services.
for parameter; {
	if ! start_options "$parameter" ; then
		start_script "$parameter"
	fi
}
