#
# initscripts functions
#

# width:

STAT_COL=80
if [ ! -t 1 ]; then
  USECOLOR=""

# stty will fail when stdin isn't a terminal
elif [ -t 0 ]; then
  STAT_COL="$(/bin/stty size)"
  # stty gives "rows cols"; strip the rows number, we just want columns
  STAT_COL="${STAT_COL##* }"

else
  # is /usr/share/terminfo already mounted, and TERM recognized?
  /bin/tput cols &>/dev/null
  if [ $? -eq 0 ]; then
    STAT_COL=$(/bin/tput cols)
  fi
fi
if [ "0$STAT_COL" -eq 0 ]; then
  # if output was 0 (serial console), set default width to 80
  STAT_COL=80
  USECOLOR=""
fi

# we use 13 characters for our own stuff
STAT_COL=$(($STAT_COL - 13))

# disable colors on broken terminals
TERM_COLORS="$(/bin/tput colors 2>/dev/null)"
if [ $? = 3 ]; then
	TERM_COLORS=8
elif [ -n "${TERM_COLORS}" ]; then
	case "${TERM_COLORS}" in
		*[!0-9]*)
			USECOLOR=""
			;;
		*)
			[ "${TERM_COLORS}" -lt 8 ] && USECOLOR=""
			;;
	esac
else
	USECOLOR=""
fi
unset TERM_COLORS

# clear the TZ envvar, so daemons always respect /etc/localtime
unset TZ

# colors:
if [ "$USECOLOR" = "YES" -o "$USECOLOR" = "yes" ]; then
	C_MAIN="\033[1;37;40m"      # main text
	C_OTHER="\033[1;34;40m"     # prefix & brackets
	C_SEPARATOR="\033[1;30;40m" # separator

	C_BUSY="\033[0;36;40m"      # busy
	C_FAIL="\033[1;31;40m"      # failed
	C_DONE="\033[1;37;40m"      # completed
	C_BKGD="\033[1;35;40m"      # backgrounded

	C_H1="\033[1;37;40m"        # highlight text 1
	C_H2="\033[1;36;40m"        # highlight text 2

	C_CLEAR="\033[1;0m"
fi

if [ -t 1 ]; then
	SAVE_POSITION="\033[s"
	RESTORE_POSITION="\033[u"
	DEL_TEXT="\033[$(($STAT_COL+4))G"
else
	SAVE_POSITION=""
	RESTORE_POSITION=""
	DEL_TEXT=""
fi

# prefixes:

PREFIX_REG="::"
PREFIX_HL=" >"

# functions:

deltext() {
	printf "${DEL_TEXT}"
}

printhl() {
	printf "${C_OTHER}${PREFIX_HL} ${C_H1}${1}${C_CLEAR} \n"
}

printsep() {
	printf "\n${C_SEPARATOR}   ------------------------------\n"
}

stat_bkgd() {
	printf "${C_OTHER}${PREFIX_REG} ${C_MAIN}${1}${C_CLEAR} "
	deltext
	printf "   ${C_OTHER}[${C_BKGD}BKGD${C_OTHER}]${C_CLEAR} "
}

stat_busy() {
	printf "${C_OTHER}${PREFIX_REG} ${C_MAIN}${1}${C_CLEAR} "
	printf "${SAVE_POSITION}"
	deltext
	printf "   ${C_OTHER}[${C_BUSY}BUSY${C_OTHER}]${C_CLEAR} "
}

stat_append() {
	printf "${RESTORE_POSITION}"
	printf -- "${C_MAIN}${1}${C_CLEAR}"
	printf "${SAVE_POSITION}"
}

stat_done() {
	deltext
	printf "   ${C_OTHER}[${C_DONE}DONE${C_OTHER}]${C_CLEAR} \n"
}

stat_fail() {
	deltext
	printf "   ${C_OTHER}[${C_FAIL}FAIL${C_OTHER}]${C_CLEAR} \n"
}

stat_die() {
	retval=1
	[ "$1" = "" ] || retval=$1
	stat_fail
	exit $retval
}

status() {
	stat_busy "$1"
	shift
	$* >/dev/null 2>&1
	if [ $? -eq 0 ]; then
		stat_done
		return 0
	else
		stat_fail
		return 1
	fi
}

#  usage : in_array( $needle, $haystack )
# return : 0 - found
#          1 - not found
# Copied from makepkg
in_array() {
  local needle=$1; shift
  [ -z "$1" ] && return 1 # Not Found
  local item
  for item in "$@"; do
    local c="${item:0:1}"
    if [ "x$c" = "x@" ]; then
      item="${item:1}"
    fi
    [ "$item" = "$needle" ] && return 0 # Found
  done
  return 1 # Not Found
}

# daemons:

add_daemon() {
	[ -d /var/run/daemons ] || /bin/mkdir -p /var/run/daemons
	/bin/touch /var/run/daemons/$1
}

rm_daemon() {
	/bin/rm -f /var/run/daemons/$1
}

ck_daemon() {
	[ -f /var/run/daemons/$1 ] && return 1
	return 0
}

ck_depends() {
	for daemon in $@; do
		if ck_daemon $daemon; then
			/etc/rc.d/$daemon start
		fi
	done
}

start_daemon() {
	/etc/rc.d/$1 start
}

start_daemon_bkgd() {
	stat_bkgd "Starting $1"
	(/etc/rc.d/$1 start) &>/dev/null &
}

stop_daemon() {
	/etc/rc.d/$1 stop
}

# Status functions
status_started() {
  deltext
  echo -ne "$C_OTHER[${C_STRT}STARTED$C_OTHER]$C_CLEAR "
}

status_stopped() {
  deltext
  echo -ne "$C_OTHER[${C_STRT}STOPPED$C_OTHER]$C_CLEAR "
}

ck_status() {
  ck_daemon $1
  if [ $? -eq 1 ]; then
    status_started
  else
    status_stopped
  fi		
}

###############################
# Custom hooks in initscripts #
###############################
# Hooks can be used to include custom code in various places in the rc.* scripts
#
# Define a hook function in a functions.d file using:
#  function_name() {
#    ...
#  }
#  add_hook hook_name function_name
# It is allowed to register several hook functions for the same hook
# Is is also allowed to register the same hook function for several hooks
#
# Currently, the following hooks exist:
# sysinit_start: at the beginning of rc.sysinit
# multi_start: at the beginning of rc.multi
# single_start: at the beginning of rc.single
# shutdown_start: at the beginning of rc.shutdown
# sysinit_end: at the end of rc.sysinit
# multi_end: at the end of rc.multi
# single_end: at the end of rc.single
# sysinit_udevlaunched: after udev has been launched in rc.sysinit
# single_udevlaunched: after udev has been launched in rc.single
# sysinit_udevsettled: after uevents have settled in rc.sysinit
# single_udevsettled: after uevents have settled in rc.single
# sysinit_premount: before local filesystems are mounted, but after root is mounted read-write in rc.sysinit
# shutdown_prekillall: before all processes are being killed in rc.shutdown
# single_prekillall: before all processes are being killed in rc.single
# shutdown_postkillall: after all processes have been killed in rc.shutdown
# single_postkillall: after all processes have been killed in rc.single
# shutdown_poweroff: directly before powering off in rc.shutdown
#
# Make sure to never override the add_hook and run_hook functions via functions.d

declare -A hook_funcs

add_hook() {
	[ -z "$1" -o -z "$2" ] && return 1
	hook_funcs["$1"]="${hook_funcs["$1"]} $2"
}

run_hook() {
	local func

	[ -z "$1" ] && return 1
	for func in ${hook_funcs["$1"]}; do
		${func}
	done
}

# Source additional functions at the end to allow overrides
for f in /etc/rc.d/functions.d/*; do
  if [ -e $f ]; then
    . $f
  fi
done

# End of file
# vim: set ft=sh sw=2 ts=2 et:
