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

if [ -n "${RC_LIBEXECDIR}" ]; then
	. "${RC_LIBEXECDIR}"/sh/functions.sh
else

# void _esetdent(int num)
#
#    hard set the indent used for e-commands.
#    num defaults to 0
#
_esetdent() {
	local i="$1"
	[ ${i} -gt 0 ] || i=0
	RC_INDENTATION=$(printf '%*s' ${i} '')
}

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

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

# bool yesno(char* variable_name)
# bool yesno(char* string)
#
# 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() {
	# Check the value directly first.
	case "$1" in
    "") return 1;;
	[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

	# Then check the value of the var.
	# Note: this breaks when the var contains a double quote.
	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
}

# void esyslog(char* priority, char* tag, char* message)
#
#    use the system logger to log a message
#
esyslog() {
	local pri tag

	if type logger >/dev/null 2>&1; then
		pri="$1"
		tag="$2"

		shift 2
		if [ -z "$*" ]; then
			return 0
		fi

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

	return 0
}

# void einfon(char* message)
#
#    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}%b" "$*"
	LAST_E_CMD="einfon"
}

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

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

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

	LAST_E_CMD="ewarn"
}

# void ewarn(char* message)
#
#    show a warning message (with a newline) and log it
#
ewarn() {
	ewarnn "$*\n"
}

# void eerrorn(char* message)
#
#    show an error message (without a newline) and log it
#
eerrorn() {
	if yesno "${EINFO_QUIET}"; then
		printf " %b" "$*" >/dev/stderr
	else
		if ! yesno "${RC_ENDCOL}" && [ "${LAST_E_CMD}" = "ebegin" ]; then
			printf "\n"
		fi
		printf " ${BAD}*${NORMAL} ${RC_INDENTATION}%b" "$*" >/dev/stderr
	fi

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

	LAST_E_CMD="eerror"
}

# void eerror(char* message)
#
#    show an error message (with a newline) and log it
#
eerror() {
	eerrorn "$*\n"
}

# void ebegin(char* message)
#
#    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"
}

# void _eend(int error, char *efunc, char* errstr)
#
#    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 [ -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 "%*s%b\n" $(( COLS - LAST_E_LEN - 6 )) '' "${msg}"
	fi

	return ${retval}
}

# void eend(int error, char* errstr)
#
#    indicate the completion of process
#    if error, show errstr via eerror
#
eend() {
	local retval="${1:-0}"
	shift

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

	LAST_E_CMD="eend"
	return ${retval}
}

# void ewend(int error, char* errstr)
#
#    indicate the completion of process
#    if error, show errstr via ewarn
#
ewend() {
	local retval="${1:-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 "$@"; }
veindent()  { ! yesno "${EINFO_VERBOSE}" || eindent; }
veoutdent() { ! yesno "${EINFO_VERBOSE}" || eoutdent; }
veend() {
	yesno "${EINFO_VERBOSE}" && { eend "$@"; return $?; }
	return ${1:-0}
}
vewend() {
	yesno "${EINFO_VERBOSE}" && { ewend "$@"; return $?; }
	return ${1:-0}
}

# bool get_bootparam(param)
#
#   return 0 if gentoo=param was passed to the kernel
#
#   EXAMPLE:  if get_bootparam "nodevfs"; then ....
#
get_bootparam() {
	awk -v param="$1" '
		BEGIN { ret = 1 }
		{
			for (i = 1; i < NF; ++i)
				if ($i ~ /^gentoo=/) {
					params = substr($i, 8)
					# This might incorrectly pass if someone does:
					#	get_bootparam "nodevfs,foo"
					# But people should not be using a , to start with.
					if (index("," params ",", "," param ",")) {
						ret = 0
						exit 0
					}
				}
		}
		END { exit ret }
	' </proc/cmdline 2>/dev/null
}

# bool is_older_than(reference, files/dirs to check)
#
#   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 ref="$1"
	shift

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

	return 1
}

##############################################################################
#                                                                            #
# This should be the last code in here, please add all functions above!!     #
#                                                                            #
# *** START LAST CODE ***                                                    #
#                                                                            #
##############################################################################

# Override defaults with user settings ...
if [ -r /etc/gentoo.conf ]; then
	. /etc/gentoo.conf
fi

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

# Can the terminal handle endcols?
RC_ENDCOL="yes"

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

# 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
	export CONSOLETYPE=$(
		# This matches the logic in the old consoletype helper that we
		# had in baselayout-1.  It isn't exactly portable, but it is
		# good enough for Linux, and doesn't break when it fails.
		dev_t=$(stat -c %d /proc/self/fd/0 2>/dev/null)
		if [ "${dev_t}" != "3" ]; then
			if [ -n "$(TERM=linux setterm -blank 2>/dev/null)" ]; then
				echo "serial"
			else
				echo "vt"
			fi
		else
			echo "pty"
		fi
	)
fi
if [ "${CONSOLETYPE}" = "serial" ]; then
	RC_NOCOLOR="yes"
	RC_ENDCOL="no"
fi

# Should we use color?
: ${NOCOLOR:=${RC_NOCOLOR:-no}}
# Lastly check if the user disabled it with --nocolor argument.
case " $* " in
*" --nocolor "*|*" -C "*)
	NOCOLOR="yes"
	;;
esac

# Setup COLS and ENDCOL so eend can line up the [ ok ].
COLS=${COLUMNS:-0}		# bash's internal COLUMNS variable
if [ "${COLS:-0}" -eq 0 ]; then
	COLS=$(set -- $(stty size 2>/dev/null); echo "$2")
fi
[ "${COLS:-0}" -gt 0 ] || COLS=80

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

# Setup the colors so our messages all look pretty
if yesno "${NOCOLOR}"; then
	GOOD= WARN= BAD= NORMAL= HILITE= BRACKET=
else
	GOOD='\033[32;01m'
	WARN='\033[33;01m'
	BAD='\033[31;01m'
	HILITE='\033[36;01m'
	BRACKET='\033[34;01m'
	NORMAL='\033[0m'
fi

fi
# vim:ts=4
