#!/bin/bash
#
# Functions defined in this file are used by many rc scripts.
# 
# Author:	Miquel van Smoorenburg, <miquels@drinkel.nl.mugnet.org>
# Hacked by:	Greg Galloway and Marc Ewing
# Changed by:	Dmitry V. Levin

# Set the initial default search path for use by startup scripts.
export PATH="/sbin:/usr/sbin:/usr/local/sbin:/lib/initrd/bin:/bin:/usr/bin:/usr/local/bin"

. shell-error
. shell-var

SourceIfExists()     { [ -f "$1" ] && . "$@"; }
SourceIfExecutable() { [ -x "$1" ] && . "$@"; }
SourceIfNotEmpty()   { [ -s "$1" ] && . "$@"; }
ExecIfExecutable()   { [ -x "$1" ] && "$@"; }
absolute() { { command -v "$@"; } 2>/dev/null; }

message_time=1
SHOW_TIMESTAMP=1
QUIET=no
LANG=C

SourceIfNotEmpty /etc/sysconfig/init

LANGUAGE="$LANG"
LC_ALL="$LANG"

export LANG LANGUAGE LC_ALL

TO_COL=
COLOR_BANNER=
COLOR_FAILURE=
COLOR_INFO=
COLOR_NORMAL=
COLOR_SUCCESS=
COLOR_WARNING=

BOOTUP="${BOOTUP:-color}"
CONSOLETYPE=$(absolute consoletype) && [ "$($CONSOLETYPE)" = serial ] &&
	BOOTUP=serial

[ "$BOOTUP" != color ] ||
	SourceIfNotEmpty /etc/init.d/outformat

[ "${LOGLEVEL:--1}" -ge 0 ] 2>/dev/null ||
	LOGLEVEL=1

if [ -z "${RUN_INITRD-}" ] && [ -z "${RDLOG-}" ]; then
	! grep -qs rdlog=console /proc/cmdline ||
		export RDLOG=console
fi

start_daemon()
{
	# Process options.
	local ANNOUNCE=1 BACKGROUND='' BASENAME='' CHECK='' CMDNAME='' DISPNAME='' EXPECT='' FLAGS='' LOCKFILE='' MAKE_PIDFILE='' NICE=0 PIDFILE='' STATUS='' SU='' WHICH=''

	while [ "$1" != "${1##[-+]}" ]; do
		case "$1" in
		--) shift
			break
			;;
		--announce)
			ANNOUNCE=1
			;;
		--no-announce)
			ANNOUNCE=
			;;
		--background)
			BACKGROUND='--background'
			;;
		--check) shift
			CHECK="$1"
			;;
		--displayname) shift
			DISPNAME="$1"
			;;
		--expect-user) shift
			;;
		--lockfile) shift
			LOCKFILE="$1"
			;;
		--make-pidfile)
			BACKGROUND='--background'
			MAKE_PIDFILE='--make-pidfile'
			;;
		--name) shift
			CMDNAME="$1"
			;;
		--pidfile) shift
			PIDFILE="$1"
			;;
		--user|--set-user) shift
			;;
		[-+][0-9]*)
			NICE="$1"
			;;
		*)
			echo "start_daemon: unrecognized option: $1" >&2
			return 1
			;;
		esac
		shift
	done

	if [ -z "$1" ]; then
		msg_usage "start_daemon [options]... {program}..."
		return 1
	fi
	if [ -n "$CHECK" ] && [ -n "$CMDNAME" ]; then
		echo >&2 "start_daemon: --check and --name are mutually exclusive options"
		return 1
	fi
	if [ -n "$CMDNAME" ] && [ -z "$PIDFILE" ]; then
		echo >&2 "start_daemon: --name is set but --pidfile is not set"
		return 1
	fi

	# We need the absolute pathname.
	[ -z "$CHECK" ] || CHECK="$(absolute "$CHECK")" || return 1
	WHICH="$(absolute "$1")" || return 1
	if [ -n "$CMDNAME" ]; then
		BASENAME="${CMDNAME##*/}"
	elif [ -n "$CHECK" ]; then
		BASENAME="${CHECK##*/}"
	else
		BASENAME="${1##*/}"
	fi
	shift
	[ -n "$BASENAME" ] || return 1
	[ -n "$DISPNAME" ] || DISPNAME="$BASENAME"

	[ "${RDLOG-}" != 'console' ] ||
		ANNOUNCE=''

	# Use a safe umask
	#umask 077

	# Don't export these because they may be invalid under another UID and the
	# directories may be gone while the daemon is still running.
	local HOME='' TMP='' TMPDIR=''

	FLAGS="--start -N $NICE"
	if [ -n "$CMDNAME" ]; then
		FLAGS="$FLAGS --startas $WHICH --name $CMDNAME"
	elif [ -n "$CHECK" ]; then
		FLAGS="$FLAGS --exec $CHECK --startas $WHICH"
	else
		FLAGS="$FLAGS --exec $WHICH"
	fi
	[ -z "$PIDFILE" ] || FLAGS="$FLAGS --pidfile $PIDFILE"
	[ -z "$BACKGROUND" ] || FLAGS="$FLAGS $BACKGROUND"
	[ -z "$MAKE_PIDFILE" ] || FLAGS="$FLAGS $MAKE_PIDFILE"

	# Announce the action.
	[ -z "$ANNOUNCE" ] || msg_starting "$DISPNAME"

	# Actually start the daemon.
	start-stop-daemon $FLAGS -- "$@"
	STATUS=$?

	if [ $STATUS = 0 ]; then
		[ -z "$LOCKFILE" ] || touch "$LOCKFILE"
		[ "$BOOTUP" != verbose ] || echo -n " $DISPNAME "
		success "$BASENAME startup"
	else
		failure "$BASENAME startup"
	fi

	return $STATUS
}

stop_daemon()
{
	# Process options.
	local ANNOUNCE=1 BASENAME='' CMDNAME='' DEFAULT=true DISPNAME='' EXPECT='' FLAGS='' LOCKFILE='' MESSAGE='' NAME='' PIDFILE='' RETRY='' SIGNAL='' STATUS='' WHICH=''

	# start-stop-daemon wants a signal number.
	SIGNAL="$(/bin/kill -l TERM)" || SIGNAL=15
	while [ $# -ge 1 ]; do
		case "$1" in
		--) shift
			[ -z "$NAME" ] || return 1
			NAME="$1"
			break
			;;
		--announce)
			ANNOUNCE=1
			;;
		--no-announce)
			ANNOUNCE=
			;;
		--displayname) shift
			DISPNAME="$1"
			;;
		--expect-user) shift
			;;
		--lockfile) shift
			LOCKFILE="$1"
			;;
		--name) shift
			CMDNAME="$1"
			;;
		--pidfile) shift
			PIDFILE="$1"
			;;
		--retry) shift
			RETRY="$1"
			;;
		-[0-9]*)
			SIGNAL="${1##-}"
			DEFAULT=false
			;;
		-*)
			SIGNAL="${1##-}"
			SIGNAL="$(/bin/kill -l -- "$SIGNAL")" || return 1
			DEFAULT=false
			ANNOUNCE=
			;;
		# Allow the process name to be in any argument for Red Hat compatibility.
		*)
			[ -z "$NAME" ] || return 1
			NAME="$1"
			;;
		esac
		shift
	done

	# We need the absolute pathname for /proc/*/exe checks.
	if [ -z "$NAME" ]; then
		msg_usage "stop_daemon [options]... {program}..."
		return 1
	fi
	WHICH="$(absolute "$NAME")" || return 1
	[ -n "$CMDNAME" ] &&
		BASENAME="${CMDNAME##*/}" ||
		BASENAME="${NAME##*/}" || return 1

	[ -n "$DISPNAME" ] || DISPNAME="$BASENAME"

	[ "${RDLOG-}" != 'console' ] ||
		ANNOUNCE=''

	# Try to guess the PID file if one isn't specified manually.
	if [ -z "$PIDFILE" ]; then
		PIDFILE="/var/run/$BASENAME.pid"
		[ -f "$PIDFILE" ] || PIDFILE=
	elif [ "$PIDFILE" = none ]; then
		PIDFILE=
	fi

	if [ -n "$CMDNAME" ] && [ -z "$PIDFILE" ]; then
		echo "stop_daemon: --name is set but --pidfile is not set" >&2
		return 1
	fi

	FLAGS="--stop -q"
	[ -z "$CMDNAME" ] &&
		FLAGS="$FLAGS --exec $WHICH" ||
		FLAGS="$FLAGS --name $CMDNAME"
	[ -z "$PIDFILE" ] || FLAGS="$FLAGS --pidfile $PIDFILE"
#	[ -z "$RETRY" ] || FLAGS="$FLAGS --retry $RETRY"

	if [ "$DEFAULT" = true ]; then
		MESSAGE="$BASENAME shutdown"
	else
		MESSAGE="sending signal $SIGNAL to $BASENAME"
	fi

	# Announce the action.
	[ -z "$ANNOUNCE" ] || msg_stopping "$DISPNAME"

	# Actually tell the daemon to stop.
	start-stop-daemon $FLAGS --signal "$SIGNAL"
	STATUS=$?

	if [ $STATUS = 0 ]; then
		[ -z "$PIDFILE" ] || rm -f "$PIDFILE"
		[ -z "$LOCKFILE" ] || rm -f "$LOCKFILE"
		[ "$BOOTUP" != verbose ] || echo -n " $DISPNAME "
		success "$MESSAGE"
	else
		failure "$MESSAGE"
	fi

	return $STATUS
}

status()
{
	# Test syntax.
	if [ $# = 0 ]; then
		msg_usage "status [options]... {program}"
		return 1
	fi

	# Process options.
	local BASENAME='' CMDNAME='' DISPNAME='' EXPECT='' FLAGS='' LOCKFILE='' PIDFILE='' WHICH=''

	while [ "$1" != "${1##-}" ]; do
		case "$1" in
		--) shift
			break
			;;
		--displayname) shift
			DISPNAME="$1"
			;;
		--expect-user) shift
			;;
		--lockfile) shift
			LOCKFILE="$1"
			;;
		--name) shift
			CMDNAME="$1"
			;;
		--pidfile) shift
			PIDFILE="$1"
			;;
		*)
			echo "status: unrecognized option: $1" >&2
			return 1
			;;
		esac
		shift
	done

	# We need the absolute pathname for /proc/*/exe checks.
	if [ -z "$1" ]; then
		msg_usage "status [options]... {program}"
		return 1
	fi
	WHICH="$(absolute "$1")" || return 1
	[ -n "$CMDNAME" ] &&
		BASENAME="${CMDNAME##*/}" ||
		BASENAME="${1##*/}" || return 1

	[ -n "$DISPNAME" ] || DISPNAME="$BASENAME"

	# Try to guess the PID file if one isn't specified manually.
	if [ -z "$PIDFILE" ]; then
		PIDFILE="/var/run/$BASENAME.pid"
		test -f "$PIDFILE" || PIDFILE=
	elif [ "$PIDFILE" = none ]; then
		PIDFILE=
	fi

	if [ -n "$CMDNAME" ] && [ -z "$PIDFILE" ]; then
		echo "status: --name is set but --pidfile is not set" >&2
		return 1
	fi

	# Actually determine the status.
	FLAGS="--stop --test"
	[ -z "$CMDNAME" ] &&
		FLAGS="$FLAGS --exec $WHICH" ||
		FLAGS="$FLAGS --name $CMDNAME"
	[ -z "$PIDFILE" ] || FLAGS="$FLAGS --pidfile $PIDFILE"

	# Report it.
	if start-stop-daemon $FLAGS >/dev/null; then
		echo "$DISPNAME is running"
		return 0
	fi

	if [ -n "$PIDFILE" ] && [ -f "$PIDFILE" ]; then
		echo "$DISPNAME is dead, but stale PID file exists"
		return 1
	fi

	[ -n "$LOCKFILE" ] || LOCKFILE="/var/lock/subsys/$BASENAME"
	if [ -f "$LOCKFILE" ]; then
		echo "$DISPNAME is dead, but subsystem is locked"
		return 2
	fi

	echo "$DISPNAME is stopped"
	return 3
}

show_tstamp()
{
	[ -z "${SHOW_TIMESTAMP-}" ] || /sbin/timestamp boottime
}

is_quiet()
{
	! shell_var_is_no "$QUIET"
}

msg()
{
	! is_quiet || return 0
	show_tstamp
	printf '%s\n' "$*"
}

__SERVICE_MESSAGE=
__SERVICE_STATUS=

echo_msg()
{
	[ -n "$*" ] || return 0
	__msg()
	{
		show_tstamp
		printf '%s ' "$*"
	}
	is_quiet && __SERVICE_MESSAGE="$(__msg "$@")" && return ||:
	__msg "$@"
}

echo_newline()
{
	! is_quiet || [ "$__SERVICE_STATUS" = failure ] || return 0
	__SERVICE_STATUS=
	echo
}

echo_success()
{
	__SERVICE_STATUS=success
	! is_quiet || return 0
	[ "${#__SERVICE_MESSAGE}" = 0 ] || printf '%s ' "$__SERVICE_MESSAGE"
	printf '%s[ %sDONE%s ]\r' "$TO_COL" "$COLOR_SUCCESS" "$COLOR_NORMAL"
}

echo_failure()
{
	__SERVICE_STATUS=failure
	[ "${#__SERVICE_MESSAGE}" = 0 ] || printf '%s ' "$__SERVICE_MESSAGE"
	printf '%s[%sFAILED%s]\r' "$TO_COL" "$COLOR_FAILURE" "$COLOR_NORMAL"
	return 1
}

echo_passed()
{
	__SERVICE_STATUS=passed
	! is_quiet || return 1
	[ "${#__SERVICE_MESSAGE}" = 0 ] || printf '%s ' "$__SERVICE_MESSAGE"
	printf '%s[%sPASSED%s]\r' "$TO_COL" "$COLOR_WARNING" "$COLOR_NORMAL"
	return 1
}

# Log that something succeeded
success()
{
	if [ "${RDLOG-}" = 'console' ]; then
		[ -z "${INITLOG_FILE-}" ] ||
			message "$1 succeeded" >"$INITLOG_FILE"
		return 0
	fi
	echo_success
	echo_newline
	return 0
}

# Log that something failed
failure()
{
	local rc=$?
	if [ "${RDLOG-}" = 'console' ]; then
		[ -z "${INITLOG_FILE-}" ] ||
			message "$1 failed" >"$INITLOG_FILE"
		return $rc
	fi
	echo_failure
	echo_newline
	return $rc
}

# Log that something passed, but may have had errors. Useful for fsck
passed()
{
	local rc=$?
	if [ "${RDLOG-}" = 'console' ]; then
		[ -z "${INITLOG_FILE-}" ] ||
			message "$1 passed" >"$INITLOG_FILE"
		return $rc
	fi
	echo_passed
	echo_newline
	return $rc
}

# Run some action. Log its output.
action()
{
	local STRING rc
	STRING="$1"
	shift
	[ "${RDLOG-}" = 'console' ] || echo_msg "$STRING"
	"$@"
	rc=$?
	[ $rc -eq 0 ] && success "$STRING" || failure "$STRING"
	return $rc
}

action_shell()
{
	local STRING rc
	STRING="$1"
	shift
	[ "${RDLOG-}" = 'console' ] || echo_msg "$STRING"
	("$@")
	rc=$?
	[ $rc -eq 0 ] && success "$STRING" || failure "$STRING"
	return $rc
}

msg_starting()
{
	echo_msg "Starting $1 service: "
}

msg_already_running()
{
	echo_msg "Service $1 is already running."
}


msg_stopping()
{
	echo_msg "Stopping $1 service: "
}

msg_not_running()
{
	echo_msg "Service $1 is not running."
}

msg_reloading()
{
	echo_msg "Reloading $1 service: "
}

msg_usage()
{
	printf "Usage: %s\n" "$*" >&2
}
