# Copyright 1999-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

#
# All functions in this file should be written in POSIX sh. Please do
# not use bashisms.
#

RC_GOT_FUNCTIONS="yes"

#
#    hard set the indent used for e-commands.
#    num defaults to 0
# This is a private function.
#
_esetdent()
{
	local i="$1"
	[ -z "$i" ] || [ "$i" -lt 0 ] && i=0
	RC_INDENTATION=$(printf "%${i}s" '')
}

#
#    increase the indent used for e-commands.
#
eindent()
{
	local i="$1"
	[ -n "$i" ] && [ "$i" -gt 0 ] || i=$RC_DEFAULT_INDENT
	_esetdent $(( ${#RC_INDENTATION} + i ))
}

#
#    decrease the indent used for e-commands.
#
eoutdent()
{
	local i="$1"
	[ -n "$i" ] && [ "$i" -gt 0 ] || i=$RC_DEFAULT_INDENT
	_esetdent $(( ${#RC_INDENTATION} - i ))
}

#
# this function was lifted from OpenRC. It returns 0 if the argument  or
# the value of the argument is "yes", "true", "on", or "1" or 1
# otherwise.
#
yesno()
{
	[ -z "$1" ] && return 1

	case "$1" in
		[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) return 0;;
		[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0) return 1;;
	esac

	local value=
	eval value=\$${1}
	case "$value" in
		[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) return 0;;
		[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0) return 1;;
		*) vewarn "\$$1 is not set properly"; return 1;;
	esac
}

#
#    use the system logger to log a message
#
esyslog()
{
	local pri=
	local tag=

	if [ -n "$EINFO_LOG" ] && command -v logger > /dev/null 2>&1; then
		pri="$1"
		tag="$2"

		shift 2
		[ -z "$*" ] && return 0

		logger -p "${pri}" -t "${tag}" -- "$*"
	fi

	return 0
}

#
#    show an informative message (without a newline)
#
einfon()
{
	if yesno "${EINFO_QUIET}"; then
		return 0
	fi
	if ! yesno "${RC_ENDCOL}" && [ "${LAST_E_CMD}" = "ebegin" ]; then
		printf "\n"
	fi
	printf " ${GOOD}*${NORMAL} ${RC_INDENTATION}$*"
	LAST_E_CMD="einfon"
	return 0
}

#
#    show an informative message (with a newline)
#
einfo()
{
	einfon "$*\n"
	LAST_E_CMD="einfo"
	return 0
}

#
#    show a warning message (without a newline) and log it
#
ewarnn()
{
	if yesno "${EINFO_QUIET}"; then
		return 0
	else
		if ! yesno "${RC_ENDCOL}" && [ "${LAST_E_CMD}" = "ebegin" ]; then
			printf "\n" >&2
		fi
		printf " ${WARN}*${NORMAL} ${RC_INDENTATION}$*" >&2
	fi

	local name="${0##*/}"
	# Log warnings to system log
	esyslog "daemon.warning" "${name}" "$*"

	LAST_E_CMD="ewarnn"
	return 0
}

#
#    show a warning message (with a newline) and log it
#
ewarn()
{
	if yesno "${EINFO_QUIET}"; then
		return 0
	else
		if ! yesno "${RC_ENDCOL}" && [ "${LAST_E_CMD}" = "ebegin" ]; then
			printf "\n" >&2
		fi
		printf " ${WARN}*${NORMAL} ${RC_INDENTATION}$*\n" >&2
	fi

	local name="${0##*/}"
	# Log warnings to system log
	esyslog "daemon.warning" "${name}" "$*"

	LAST_E_CMD="ewarn"
	return 0
}

#
#    show an error message (without a newline) and log it
#
eerrorn()
{
	if yesno "${EERROR_QUIET}"; then
		return 1
	else
		if ! yesno "${RC_ENDCOL}" && [ "${LAST_E_CMD}" = "ebegin" ]; then
			printf "\n" >&2
		fi
		printf " ${BAD}*${NORMAL} ${RC_INDENTATION}$*" >&2
	fi

	local name="${0##*/}"
	# Log errors to system log
	esyslog "daemon.err" "rc-scripts" "$*"

	LAST_E_CMD="eerrorn"
	return 1
}

#
#    show an error message (with a newline) and log it
#
eerror()
{
	if yesno "${EERROR_QUIET}"; then
		return 1
	else
		if ! yesno "${RC_ENDCOL}" && [ "${LAST_E_CMD}" = "ebegin" ]; then
			printf "\n" >&2
		fi
		printf " ${BAD}*${NORMAL} ${RC_INDENTATION}$*\n" >&2
	fi

	local name="${0##*/}"
	# Log errors to system log
	esyslog "daemon.err" "rc-scripts" "$*"

	LAST_E_CMD="eerror"
	return 1
}

#
#    show a message indicating the start of a process
#
ebegin()
{
	local msg="$*"
	if yesno "${EINFO_QUIET}"; then
		return 0
	fi

	msg="${msg} ..."
	einfon "${msg}"
	if yesno "${RC_ENDCOL}"; then
		printf "\n"
	fi

	LAST_E_LEN="$(( 3 + ${#RC_INDENTATION} + ${#msg} ))"
	LAST_E_CMD="ebegin"
	return 0
}

#
#    indicate the completion of process, called from eend/ewend
#    if error, show errstr via efunc
#
#    This function is private to functions.sh.  Do not call it from a
#    script.
#
_eend()
{
	local retval="${1:-0}" efunc="${2:-eerror}" msg
	shift 2

	if [ "${retval}" = "0" ]; then
		yesno "${EINFO_QUIET}" && return 0
		msg="${BRACKET}[ ${GOOD}ok${BRACKET} ]${NORMAL}"
	else
		if [ -c /dev/null ] ; then
			rc_splash "stop" >/dev/null 2>&1 &
		else
			rc_splash "stop" &
		fi
		if [ -n "$*" ] ; then
			${efunc} "$*"
		fi
		msg="${BRACKET}[ ${BAD}!!${BRACKET} ]${NORMAL}"
	fi

	if yesno "${RC_ENDCOL}"; then
		printf "${ENDCOL}  ${msg}\n"
	else
		[ "${LAST_E_CMD}" = ebegin ] || LAST_E_LEN=0
		printf "%$(( COLS - LAST_E_LEN - 6 ))s%b\n" '' "${msg}"
	fi

	return ${retval}
}

#
#    indicate the completion of process
#    if error, show errstr via eerror
#
eend()
{
	local retval="${1:-0}"
	[ $# -eq 0 ] || shift

	_eend "${retval}" eerror "$*"

	LAST_E_CMD="eend"
	return ${retval}
}

#
#    indicate the completion of process
#    if error, show errstr via ewarn
#
ewend()
{
	local retval="${1:-0}"
	[ $# -eq 0 ] || shift

	_eend "${retval}" ewarn "$*"

	LAST_E_CMD="ewend"
	return ${retval}
}

# v-e-commands honor EINFO_VERBOSE which defaults to no.
# The condition is negated so the return value will be zero.
veinfo()
{
	yesno "${EINFO_VERBOSE}" && einfo "$@"
}

veinfon()
{
	yesno "${EINFO_VERBOSE}" && einfon "$@"
}

vewarn()
{
	yesno "${EINFO_VERBOSE}" && ewarn "$@"
}

veerror()
{
	yesno "${EINFO_VERBOSE}" && eerror "$@"
}

vebegin()
{
	yesno "${EINFO_VERBOSE}" && ebegin "$@"
}

veend()
{
	yesno "${EINFO_VERBOSE}" && { eend "$@"; return $?; }
	return ${1:-0}
}

vewend()
{
	yesno "${EINFO_VERBOSE}" && { ewend "$@"; return $?; }
	return ${1:-0}
}

veindent()
{
	yesno "${EINFO_VERBOSE}" && eindent
}

veoutdent()
{
	yesno "${EINFO_VERBOSE}" && eoutdent
}

#
#   return 0 if gentoo=param was passed to the kernel
#
#   EXAMPLE:  if get_bootparam "nodevfs" ; then ....
#
get_bootparam()
{
	local x copt params retval=1

	[ ! -r /proc/cmdline ] && return 1

	read copts < /proc/cmdline
	for copt in $copts ; do
		if [ "${copt%=*}" = "gentoo" ] ; then
			params=$(gawk -v PARAMS="${copt##*=}" '
				BEGIN {
					split(PARAMS, nodes, ",")
					for (x in nodes)
						print nodes[x]
				}')

			# Parse gentoo option
			for x in ${params} ; do
				if [ "${x}" = "$1" ] ; then
#					echo "YES"
					retval=0
				fi
			done
		fi
	done

	return ${retval}
}

#
#   return 0 if any of the files/dirs are newer than
#   the reference file
#
#   EXAMPLE: if is_older_than a.out *.o ; then ...
is_older_than()
{
	local x=
	local ref="$1"
	[ $# -eq 0 ] || shift

	for x in "$@" ; do
		[ "${x}" -nt "${ref}" ] && return 0
		[ -d "${x}" ] && is_older_than "${ref}" "${x}"/* && return 0
	done

	return 1
}

# This is the main script, please add all functions above this point!

# Dont output to stdout?
EINFO_QUIET="${EINFO_QUIET:-no}"
EINFO_VERBOSE="${EINFO_VERBOSE:-no}"

# Should we use color?
RC_NOCOLOR="${RC_NOCOLOR:-no}"
# Can the terminal handle endcols?
RC_ENDCOL="yes"

# Default values for e-message indentation and dots
RC_INDENTATION=''
RC_DEFAULT_INDENT=2
RC_DOT_PATTERN=''

# Cache the CONSOLETYPE - this is important as backgrounded shells don't
# have a TTY. rc unsets it at the end of running so it shouldn't hang
# around
if [ -z "${CONSOLETYPE}" ] ; then
	CONSOLETYPE="$(consoletype stdout 2>/dev/null )"; export CONSOLETYPE
fi
if [ "${CONSOLETYPE}" = "serial" ] ; then
	RC_NOCOLOR="yes"
	RC_ENDCOL="no"
fi

for arg in "$@" ; do
	case "${arg}" in
		# Lastly check if the user disabled it with --nocolor argument
		--nocolor|--nocolour|-nc|-C)
			RC_NOCOLOR="yes"
			;;
	esac
done

# Setup COLS and ENDCOL so eend can line up the [ ok ]
COLS="${COLUMNS:-0}"            # bash's internal COLUMNS variable
[ "$COLS" -eq 0 ] && \
        COLS="$(set -- $(stty size 2>/dev/null) ; printf "$2\n")"
[ -z "$COLS" ] && COLS=80
[ "$COLS" -gt 0 ] || COLS=80	# width of [ ok ] == 7

if yesno "${RC_ENDCOL}"; then
	ENDCOL='\033[A\033['$(( COLS - 8 ))'C'
else
	ENDCOL=''
fi

# Setup the colors so our messages all look pretty
if yesno "${RC_NOCOLOR}"; then
	unset GOOD WARN BAD NORMAL HILITE BRACKET
elif (command -v tput && tput colors) >/dev/null 2>&1; then
	GOOD="$(tput sgr0)$(tput bold)$(tput setaf 2)"
	WARN="$(tput sgr0)$(tput bold)$(tput setaf 3)"
	BAD="$(tput sgr0)$(tput bold)$(tput setaf 1)"
	HILITE="$(tput sgr0)$(tput bold)$(tput setaf 6)"
	BRACKET="$(tput sgr0)$(tput bold)$(tput setaf 4)"
	NORMAL="$(tput sgr0)"
else
	GOOD=$(printf '\033[32;01m')
	WARN=$(printf '\033[33;01m')
	BAD=$(printf '\033[31;01m')
	HILITE=$(printf '\033[36;01m')
	BRACKET=$(printf '\033[34;01m')
	NORMAL=$(printf '\033[0m')
fi

# If we made it this far, the script succeeded, so don't let failures
# from earlier commands (like `tput`) screw up the $? value.
:

# vim:ts=4
