summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'functions/rc.sh')
-rw-r--r--functions/rc.sh462
1 files changed, 462 insertions, 0 deletions
diff --git a/functions/rc.sh b/functions/rc.sh
new file mode 100644
index 0000000..519d847
--- /dev/null
+++ b/functions/rc.sh
@@ -0,0 +1,462 @@
+# Copyright 1999-2024 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+# shellcheck shell=sh disable=3043
+
+# This file contains alternative implementations for some of the functions and
+# utilities provided by OpenRC. Please refer to ../functions.sh for coding
+# conventions.
+
+# The following variables affect initialisation and/or function behaviour.
+
+# EERROR_QUIET : whether error printing functions should be silenced
+# EINFO_LOG : whether printing functions should call esyslog()
+# EINFO_QUIET : whether info message printing functions should be silenced
+# EINFO_VERBOSE : whether v-prefixed functions should do anything
+# IFS : multiple message operands are joined by its first character
+# INSIDE_EMACS : whether to work around an emacs-specific bug in _eend()
+# NO_COLOR : whether colored output should be suppressed
+# RC_NOCOLOR : like NO_COLOR but deprecated
+# TERM : whether to work around an emacs-specific bug in _eend()
+# TEST_GENFUNCS : used for testing the behaviour of get_bootparam()
+
+#------------------------------------------------------------------------------#
+
+#
+# Prints a message indicating the onset of a given process, provided that
+# EINFO_QUIET is false. It is expected that eend eventually be called, so as to
+# indicate whether the process completed successfully or not.
+#
+ebegin()
+{
+ local msg
+
+ if ! yesno "${EINFO_QUIET}"; then
+ msg=$*
+ while _ends_with_newline "${msg}"; do
+ msg=${msg%"${genfun_newline}"}
+ done
+ _eprint "${GOOD}" "${msg} ...${genfun_newline}"
+ fi
+}
+
+#
+# Prints an indicator to convey the completion of a given process, provided that
+# EINFO_QUIET is false. It is expected that it be paired with an earlier call to
+# ebegin. The first parameter shall be taken as an exit status value, making it
+# possible to distinguish between success and failure. If unspecified, it shall
+# default to 0. The remaining parameters, if any, shall be taken as a diagnostic
+# message to convey as an error where the exit status is not 0.
+#
+eend()
+{
+ GENFUN_CALLER=${GENFUN_CALLER:-eend} _eend eerror "$@"
+}
+
+#
+# Declare the eerror, einfo and ewarn functions. These wrap errorn, einfon and
+# ewarnn respectively, the difference being that a newline is appended.
+#
+for _ in eerror einfo ewarn; do
+ eval "
+ $_ ()
+ {
+ ${_}n \"\${*}\${genfun_newline}\"
+ }
+ "
+done
+
+#
+# Prints an error message without appending a newline, provided that
+# EERROR_QUIET is false. If printed, the message shall also be conveyed to the
+# esyslog function.
+#
+eerrorn()
+{
+ if ! yesno "${EERROR_QUIET}"; then
+ _eprint "${BAD}" "$@" >&2
+ esyslog "daemon.err" "${0##*/}" "$@"
+ fi
+ return 1
+}
+
+#
+# Decreases the level of indentation used by various printing functions. If no
+# numerical parameter is given, or if it is negative, increase by 2 spaces.
+#
+eindent()
+{
+ if ! is_int "$1" || [ "$1" -le 0 ]; then
+ set -- 2
+ fi
+ _esetdent "$(( ${#genfun_indent} + $1 ))"
+}
+
+#
+# Prints an informational message without appending a newline, provided that
+# EINFO_QUIET is false.
+#
+einfon()
+{
+ if ! yesno "${EINFO_QUIET}"; then
+ _eprint "${GOOD}" "$@"
+ fi
+}
+
+#
+# Decreases the level of indentation used by various printing functions. If no
+# numerical parameter is given, or if it is negative, decrease by 2 spaces.
+#
+eoutdent()
+{
+ if ! is_int "$1" || [ "$1" -le 0 ]; then
+ set -- 2
+ fi
+ _esetdent "$(( ${#genfun_indent} - $1 ))"
+}
+
+#
+# Invokes the logger(1) utility, provided that EINFO_LOG is true. The first
+# parameter shall be taken as a priority level, the second as the message tag,
+# and the remaining parameters as the message to be logged.
+#
+esyslog()
+{
+ local pri tag msg
+
+ if [ "$#" -lt 2 ]; then
+ warn "esyslog: too few arguments (got $#, expected at least 2)"
+ return 1
+ elif yesno "${EINFO_LOG}" && hash logger 2>/dev/null; then
+ pri=$1 tag=$2
+ shift 2
+ msg=$*
+ if _is_visible "${msg}"; then
+ # This is not strictly portable because POSIX defines
+ # no options whatsoever for logger(1).
+ logger -p "${pri}" -t "${tag}" -- "${msg}"
+ fi
+ fi
+}
+
+#
+# Prints a warning message without appending a newline, provided that
+# EINFO_QUIET is false. If printed, the message shall also be conveyed to the
+# esyslog function.
+#
+ewarnn()
+{
+ if ! yesno "${EINFO_QUIET}"; then
+ _eprint "${WARN}" "$@" >&2
+ esyslog "daemon.warning" "${0##*/}" "$@"
+ fi
+}
+
+#
+# This behaves as the eend function does, except that the given diagnostic
+# message shall be presented as a warning rather than an error.
+#
+ewend()
+{
+ GENFUN_CALLER=${GENFUN_CALLER:-ewend} _eend ewarn "$@"
+}
+
+#
+# Determines whether the kernel cmdline contains the specified parameter as a
+# component of a comma-separated list specified in the format of gentoo=<list>.
+#
+get_bootparam()
+(
+ # Gentoo cmdline parameters are comma-delimited, so a search
+ # string containing a comma must not be allowed to match.
+ # Similarly, the empty string must not be allowed to match.
+ case $1 in ''|*,*) return 1 ;; esac
+
+ # Reset the value of IFS because there is no telling what it may be.
+ IFS=$(printf ' \n\t')
+
+ if [ "${TEST_GENFUNCS}" = 1 ]; then
+ read -r cmdline
+ else
+ read -r cmdline < /proc/cmdline
+ fi || return
+
+ # Disable pathname expansion. The definition of this function
+ # is a compound command that incurs a subshell. Therefore, the
+ # prior state of the option does not need to be recalled.
+ set -f
+ for opt in ${cmdline}; do
+ gentoo_opt=${opt#gentoo=}
+ if [ "${opt}" != "${gentoo_opt}" ]; then
+ case ,${gentoo_opt}, in
+ *,"$1",*) return 0
+ esac
+ fi
+ done
+ return 1
+)
+
+#
+# Takes the first parameter as a reference file/directory then determines
+# whether any of the following parameters refer to newer files/directories.
+#
+is_older_than()
+{
+ local ref
+
+ if [ "$#" -eq 0 ]; then
+ warn "is_older_than: too few arguments (got $#, expected at least 1)"
+ return 1
+ elif [ -e "$1" ]; then
+ ref=$1
+ else
+ ref=
+ fi
+ shift
+ { test "$#" -gt 0 && printf '%s\0' "$@"; } \
+ | "${genfun_bin_find}" -L -files0-from - ${ref:+-newermm} ${ref:+"${ref}"} -printf '\n' -quit \
+ | read -r _
+}
+
+#
+# Declare the vebegin, veerror, veindent, veinfo, veinfon, veoutdent and vewarn
+# functions. These differ from their non-v-prefixed counterparts in that they
+# only have an effect where EINFO_VERBOSE is true.
+#
+for _ in vebegin veerror veindent veinfo veinfon veoutdent vewarn; do
+ eval "
+ $_ ()
+ {
+ if yesno \"\${EINFO_VERBOSE}\"; then
+ ${_#v} \"\$@\"
+ fi
+ }
+ "
+done
+
+veend()
+{
+ if yesno "${EINFO_VERBOSE}"; then
+ GENFUN_CALLER=veend eend "$@"
+ elif [ "$#" -gt 0 ] && { ! is_int "$1" || [ "$1" -lt 0 ]; }; then
+ _warn_for_args veend "$1"
+ false
+ else
+ return "$1"
+ fi
+}
+
+vewend()
+{
+ if yesno "${EINFO_VERBOSE}"; then
+ GENFUN_CALLER=vewend ewend "$@"
+ elif [ "$#" -gt 0 ] && { ! is_int "$1" || [ "$1" -lt 0 ]; }; then
+ _warn_for_args vewend "$1"
+ false
+ else
+ return "$1"
+ fi
+}
+
+#
+# Determines whether the first parameter is truthy. The values taken to be true
+# are "yes", "true", "on" and "1", whereas their opposites are taken to be
+# false. The empty string is also taken to be false. All pattern matching is
+# performed case-insensitively.
+#
+yesno()
+{
+ local arg
+
+ if [ "$#" -eq 0 ]; then
+ warn "yesno: too few arguments (got $#, expected 1)"
+ return 1
+ fi
+ arg=$1
+ for _ in 1 2; do
+ case ${arg} in
+ [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0|'')
+ return 1
+ ;;
+ [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
+ return 0
+ esac
+ if [ "$_" -ne 1 ] || ! is_identifier "$1"; then
+ break
+ else
+ # The value appears to be a legal variable name. Treat
+ # it as a name reference and try again, once only.
+ eval "arg=\$$1"
+ fi
+ done
+ _warn_for_args yesno "$@"
+ false
+}
+
+#------------------------------------------------------------------------------#
+
+#
+# Called by eend, ewend, veend and vewend. See the definition of eend for an
+# overall description of its purpose.
+#
+_eend()
+{
+ local col efunc msg retval
+
+ efunc=$1
+ shift
+ if [ "$#" -eq 0 ]; then
+ retval=0
+ elif ! is_int "$1" || [ "$1" -lt 0 ]; then
+ _warn_for_args "${GENFUN_CALLER}" "$1"
+ retval=1
+ msg=
+ else
+ retval=$1
+ shift
+ msg=$*
+ fi
+
+ if [ "${retval}" -ne 0 ]; then
+ # If a message was given, print it with the specified function.
+ if _is_visible "${msg}"; then
+ "${efunc}" "${msg}"
+ fi
+ # Generate an indicator for ebegin's unsuccessful conclusion.
+ if _update_tty_level <&1; [ "${genfun_tty}" -eq 0 ]; then
+ msg="[ !! ]"
+ else
+ msg="${BRACKET}[ ${BAD}!!${BRACKET} ]${NORMAL}"
+ fi
+ elif yesno "${EINFO_QUIET}"; then
+ return "${retval}"
+ else
+ # Generate an indicator for ebegin's successful conclusion.
+ if _update_tty_level <&1; [ "${genfun_tty}" -eq 0 ]; then
+ msg="[ ok ]"
+ else
+ msg="${BRACKET}[ ${GOOD}ok${BRACKET} ]${NORMAL}"
+ fi
+ fi
+
+ if [ "${genfun_tty}" -eq 2 ]; then
+ # Save the cursor position with DECSC, move it up by one line
+ # with CUU, position it horizontally with CHA, print the
+ # indicator, then restore the cursor position with DECRC.
+ col=$(( genfun_cols > 6 ? genfun_cols - 6 : 1 ))
+ printf '\0337\033[1A\033[%dG %s\0338' "$(( col + genfun_offset ))" "${msg}"
+ else
+ # The standard output refers either to an insufficiently capable
+ # terminal or to something other than a terminal. Print the
+ # indicator, using <space> characters to indent to the extent
+ # that the last character falls on the 80th column. This hinges
+ # on the fair assumption that a newline was already printed.
+ printf '%80s\n' "${msg}"
+ fi
+
+ return "${retval}"
+}
+
+#
+# Determines whether the given string is newline-terminated.
+#
+_ends_with_newline()
+{
+ test "${genfun_newline}" \
+ && ! case $1 in *"${genfun_newline}") false ;; esac
+}
+
+#
+# Called by ebegin, eerrorn, einfon, and ewarnn.
+#
+_eprint()
+{
+ local color
+
+ color=$1
+ shift
+ if [ -t 1 ]; then
+ printf ' %s*%s %s%s' "${color}" "${NORMAL}" "${genfun_indent}" "$*"
+ else
+ printf ' * %s%s' "${genfun_indent}" "$*"
+ fi
+}
+
+#
+# Called by eindent, eoutdent, veindent and veoutdent. It is here that the
+# variable containing the horizontal whitespace is updated.
+#
+_esetdent()
+{
+ if [ "$1" -lt 0 ]; then
+ set -- 0
+ fi
+ genfun_indent=$(printf "%${1}s" '')
+}
+
+#
+# Tries to determine whether the terminal supports ECMA-48 SGR color sequences.
+#
+_has_color_terminal()
+{
+ local colors
+
+ # The tput(1) invocation is not portable, though ncurses suffices. In
+ # this day and age, it is exceedingly unlikely that it will be needed.
+ if _has_dumb_terminal; then
+ false
+ elif colors=$(tput colors 2>/dev/null) && is_int "${colors}"; then
+ test "${colors}" -gt 0
+ else
+ true
+ fi
+}
+
+#
+# Determines whether the first parameter contains any visible characters.
+#
+_is_visible()
+{
+ ! case $1 in *[[:graph:]]*) false ;; esac
+}
+
+#------------------------------------------------------------------------------#
+
+# Determine whether the use of color is to be wilfully avoided.
+if [ -n "${NO_COLOR}" ]; then
+ # See https://no-color.org/.
+ RC_NOCOLOR=yes
+else
+ for _; do
+ case $_ in
+ --nocolor|--nocolour|-C)
+ RC_NOCOLOR=yes
+ break
+ esac
+ done
+fi
+
+if ! _has_color_terminal || yesno "${RC_NOCOLOR}"; then
+ unset -v BAD BRACKET GOOD HILITE NORMAL WARN
+else
+ # Define some ECMA-48 SGR sequences for color support. These variables
+ # are public, in so far as users of the library may be expanding them.
+ # Conveniently, these sequences are documented by console_codes(4).
+ BAD=$(printf '\033[31;01m')
+ BRACKET=$(printf '\033[34;01m')
+ GOOD=$(printf '\033[32;01m')
+ # shellcheck disable=2034
+ HILITE=$(printf '\033[36;01m')
+ NORMAL=$(printf '\033[0m')
+ WARN=$(printf '\033[33;01m')
+fi
+
+# In Emacs, M-x term opens an "eterm-color" terminal, whose implementation of
+# the CHA (ECMA-48 CSI) sequence suffers from an off-by-one error.
+if [ "${INSIDE_EMACS}" ] && [ "${TERM}" = "eterm-color" ]; then
+ genfun_offset=-1
+else
+ genfun_offset=0
+fi
+
+# shellcheck disable=2034
+RC_GOT_FUNCTIONS=yes