diff options
| author | davidovski <david@davidovski.xyz> | 2022-03-29 23:36:22 +0100 | 
|---|---|---|
| committer | davidovski <david@davidovski.xyz> | 2022-03-29 23:36:22 +0100 | 
| commit | df88860947686a5e6507fc5d60ff33eac1158c6b (patch) | |
| tree | d1dc7f2f003b08afb6d45f7170d7a0dd353060d3 /xi/lib/services/init-functions | |
| parent | 33d239ecb3d66db2b005afbe68a7029c3f2d2ee0 (diff) | |
Diffstat (limited to 'xi/lib/services/init-functions')
| -rw-r--r-- | xi/lib/services/init-functions | 810 | 
1 files changed, 810 insertions, 0 deletions
diff --git a/xi/lib/services/init-functions b/xi/lib/services/init-functions new file mode 100644 index 0000000..ece4d79 --- /dev/null +++ b/xi/lib/services/init-functions @@ -0,0 +1,810 @@ +#!/bin/sh +######################################################################## +# +# Begin /lib/lsb/init-funtions +# +# Description : Run Level Control Functions +# +# Authors     : Gerard Beekmans - gerard@linuxfromscratch.org +#             : DJ Lucas - dj@linuxfromscratch.org +# Update      : Bruce Dubbs - bdubbs@linuxfromscratch.org +# +# Version     : LFS 7.0 +# +# Notes       : With code based on Matthias Benkmann's simpleinit-msb +#               http://winterdrache.de/linux/newboot/index.html +# +#               The file should be located in /lib/lsb +# +######################################################################## + +## Environmental setup +# Setup default values for environment +umask 022 +export PATH="/bin:/usr/bin:/sbin:/usr/sbin" + +## Set color commands, used via echo +# Please consult `man console_codes for more information +# under the "ECMA-48 Set Graphics Rendition" section +# +# Warning: when switching from a 8bit to a 9bit font, +# the linux console will reinterpret the bold (1;) to +# the top 256 glyphs of the 9bit font.  This does +# not affect framebuffer consoles + +NORMAL="\\033[0;39m"         # Standard console grey +SUCCESS="\\033[1;32m"        # Success is green +WARNING="\\033[1;33m"        # Warnings are yellow +FAILURE="\\033[1;31m"        # Failures are red +INFO="\\033[1;36m"           # Information is light cyan +BRACKET="\\033[1;34m"        # Brackets are blue + +# Use a colored prefix +BMPREFIX="      " +SUCCESS_PREFIX="${SUCCESS}  *  ${NORMAL} " +FAILURE_PREFIX="${FAILURE}*****${NORMAL} " +WARNING_PREFIX="${WARNING} *** ${NORMAL} " +SKIP_PREFIX="${INFO}  S   ${NORMAL}" + +SUCCESS_SUFFIX="${BRACKET}[${SUCCESS}  OK  ${BRACKET}]${NORMAL}" +FAILURE_SUFFIX="${BRACKET}[${FAILURE} FAIL ${BRACKET}]${NORMAL}" +WARNING_SUFFIX="${BRACKET}[${WARNING} WARN ${BRACKET}]${NORMAL}" +SKIP_SUFFIX="${BRACKET}[${INFO} SKIP ${BRACKET}]${NORMAL}" + +BOOTLOG=/run/bootlog +KILLDELAY=3 +SCRIPT_STAT="0" + +# Set any user specified environment variables e.g. HEADLESS +[ -r /etc/sysconfig/rc.site ]  && . /etc/sysconfig/rc.site + +## Screen Dimensions +# Find current screen size +if [ -z "${COLUMNS}" ]; then +   COLUMNS=$(stty size) +   COLUMNS=${COLUMNS##* } +fi + +# When using remote connections, such as a serial port, stty size returns 0 +if [ "${COLUMNS}" = "0" ]; then +   COLUMNS=80 +fi + +## Measurements for positioning result messages +COL=$((${COLUMNS} - 8)) +WCOL=$((${COL} - 2)) + +## Set Cursor Position Commands, used via echo +SET_COL="\\033[${COL}G"      # at the $COL char +SET_WCOL="\\033[${WCOL}G"    # at the $WCOL char +CURS_UP="\\033[1A\\033[0G"   # Up one line, at the 0'th char +CURS_ZERO="\\033[0G" + +################################################################################ +# start_daemon()                                                               # +# Usage: start_daemon [-f] [-n nicelevel] [-p pidfile] pathname [args...]      # +#                                                                              # +# Purpose: This runs the specified program as a daemon                         # +#                                                                              # +# Inputs: -f: (force) run the program even if it is already running.           # +#         -n nicelevel: specify a nice level. See 'man nice(1)'.               # +#         -p pidfile: use the specified file to determine PIDs.                # +#         pathname: the complete path to the specified program                 # +#         args: additional arguments passed to the program (pathname)          # +#                                                                              # +# Return values (as defined by LSB exit codes):                                # +#       0 - program is running or service is OK                                # +#       1 - generic or unspecified error                                       # +#       2 - invalid or excessive argument(s)                                   # +#       5 - program is not installed                                           # +################################################################################ +start_daemon() +{ +    local force="" +    local nice="0" +    local pidfile="" +    local pidlist="" +    local retval="" + +    # Process arguments +    while true +    do +        case "${1}" in + +            -f) +                force="1" +                shift 1 +                ;; + +            -n) +                nice="${2}" +                shift 2 +                ;; + +            -p) +                pidfile="${2}" +                shift 2 +                ;; + +            -*) +                return 2 +                ;; + +            *) +                program="${1}" +                break +                ;; +        esac +    done + +    # Check for a valid program +    if [ ! -e "${program}" ]; then return 5; fi + +    # Execute +    if [ -z "${force}" ]; then +        if [ -z "${pidfile}" ]; then +            # Determine the pid by discovery +            pidlist=`pidofproc "${1}"` +            retval="${?}" +        else +            # The PID file contains the needed PIDs +            # Note that by LSB requirement, the path must be given to pidofproc, +            # however, it is not used by the current implementation or standard. +            pidlist=`pidofproc -p "${pidfile}" "${1}"` +            retval="${?}" +        fi + +        # Return a value ONLY +        # It is the init script's (or distribution's functions) responsibilty +        # to log messages! +        case "${retval}" in + +            0) +                # Program is already running correctly, this is a +                # successful start. +                return 0 +                ;; + +            1) +                # Program is not running, but an invalid pid file exists +                # remove the pid file and continue +                rm -f "${pidfile}" +                ;; + +            3) +                # Program is not running and no pidfile exists +                # do nothing here, let start_deamon continue. +                ;; + +            *) +                # Others as returned by status values shall not be interpreted +                # and returned as an unspecified error. +                return 1 +                ;; +        esac +    fi + +    # Do the start! +    nice -n "${nice}" "${@}" +} + +################################################################################ +# killproc()                                                                   # +# Usage: killproc [-p pidfile] pathname [signal]                               # +#                                                                              # +# Purpose: Send control signals to running processes                           # +#                                                                              # +# Inputs: -p pidfile, uses the specified pidfile                               # +#         pathname, pathname to the specified program                          # +#         signal, send this signal to pathname                                 # +#                                                                              # +# Return values (as defined by LSB exit codes):                                # +#       0 - program (pathname) has stopped/is already stopped or a             # +#           running program has been sent specified signal and stopped         # +#           successfully                                                       # +#       1 - generic or unspecified error                                       # +#       2 - invalid or excessive argument(s)                                   # +#       5 - program is not installed                                           # +#       7 - program is not running and a signal was supplied                   # +################################################################################ +killproc() +{ +    local pidfile +    local program +    local prefix +    local progname +    local signal="-TERM" +    local fallback="-KILL" +    local nosig +    local pidlist +    local retval +    local pid +    local delay="30" +    local piddead +    local dtime + +    # Process arguments +    while true; do +        case "${1}" in +            -p) +                pidfile="${2}" +                shift 2 +                ;; + +             *) +                 program="${1}" +                 if [ -n "${2}" ]; then +                     signal="${2}" +                     fallback="" +                 else +                     nosig=1 +                 fi + +                 # Error on additional arguments +                 if [ -n "${3}" ]; then +                     return 2 +                 else +                     break +                 fi +                 ;; +        esac +    done + +    # Check for a valid program +    if [ ! -e "${program}" ]; then return 5; fi + +    # Check for a valid signal +    check_signal "${signal}" +    if [ "${?}" -ne "0" ]; then return 2; fi + +    # Get a list of pids +    if [ -z "${pidfile}" ]; then +        # determine the pid by discovery +        pidlist=`pidofproc "${1}"` +        retval="${?}" +    else +        # The PID file contains the needed PIDs +        # Note that by LSB requirement, the path must be given to pidofproc, +        # however, it is not used by the current implementation or standard. +        pidlist=`pidofproc -p "${pidfile}" "${1}"` +        retval="${?}" +    fi + +    # Return a value ONLY +    # It is the init script's (or distribution's functions) responsibilty +    # to log messages! +    case "${retval}" in + +        0) +            # Program is running correctly +            # Do nothing here, let killproc continue. +            ;; + +        1) +            # Program is not running, but an invalid pid file exists +            # Remove the pid file. + +            progname=${program##*/} + +            if [[ -e "/run/${progname}.pid" ]]; then +                pidfile="/run/${progname}.pid" +                rm -f "${pidfile}" +            fi + +            # This is only a success if no signal was passed. +            if [ -n "${nosig}" ]; then +                return 0 +            else +                return 7 +            fi +            ;; + +        3) +            # Program is not running and no pidfile exists +            # This is only a success if no signal was passed. +            if [ -n "${nosig}" ]; then +                return 0 +            else +                return 7 +            fi +            ;; + +        *) +            # Others as returned by status values shall not be interpreted +            # and returned as an unspecified error. +            return 1 +            ;; +    esac + +    # Perform different actions for exit signals and control signals +    check_sig_type "${signal}" + +    if [ "${?}" -eq "0" ]; then # Signal is used to terminate the program + +        # Account for empty pidlist (pid file still exists and no +        # signal was given) +        if [ "${pidlist}" != "" ]; then + +            # Kill the list of pids +            for pid in ${pidlist}; do + +                kill -0 "${pid}" 2> /dev/null + +                if [ "${?}" -ne "0" ]; then +                    # Process is dead, continue to next and assume all is well +                    continue +                else +                    kill "${signal}" "${pid}" 2> /dev/null + +                    # Wait up to ${delay}/10 seconds to for "${pid}" to +                    # terminate in 10ths of a second + +                    while [ "${delay}" -ne "0" ]; do +                        kill -0 "${pid}" 2> /dev/null || piddead="1" +                        if [ "${piddead}" = "1" ]; then break; fi +                        sleep 0.1 +                        delay="$(( ${delay} - 1 ))" +                    done + +                    # If a fallback is set, and program is still running, then +                    # use the fallback +                    if [ -n "${fallback}" -a "${piddead}" != "1" ]; then +                        kill "${fallback}" "${pid}" 2> /dev/null +                        sleep 1 +                        # Check again, and fail if still running +                        kill -0 "${pid}" 2> /dev/null && return 1 +                    fi +                fi +            done +        fi + +        # Check for and remove stale PID files. +        if [ -z "${pidfile}" ]; then +            # Find the basename of $program +            prefix=`echo "${program}" | sed 's/[^/]*$//'` +            progname=`echo "${program}" | sed "s@${prefix}@@"` + +            if [ -e "/run/${progname}.pid" ]; then +                rm -f "/run/${progname}.pid" 2> /dev/null +            fi +        else +            if [ -e "${pidfile}" ]; then rm -f "${pidfile}" 2> /dev/null; fi +        fi + +    # For signals that do not expect a program to exit, simply +    # let kill do its job, and evaluate kill's return for value + +    else # check_sig_type - signal is not used to terminate program +        for pid in ${pidlist}; do +            kill "${signal}" "${pid}" +            if [ "${?}" -ne "0" ]; then return 1; fi +        done +    fi +} + +################################################################################ +# pidofproc()                                                                  # +# Usage: pidofproc [-p pidfile] pathname                                       # +#                                                                              # +# Purpose: This function returns one or more pid(s) for a particular daemon    # +#                                                                              # +# Inputs: -p pidfile, use the specified pidfile instead of pidof               # +#         pathname, path to the specified program                              # +#                                                                              # +# Return values (as defined by LSB status codes):                              # +#       0 - Success (PIDs to stdout)                                           # +#       1 - Program is dead, PID file still exists (remaining PIDs output)     # +#       3 - Program is not running (no output)                                 # +################################################################################ +pidofproc() +{ +    local pidfile +    local program +    local prefix +    local progname +    local pidlist +    local lpids +    local exitstatus="0" + +    # Process arguments +    while true; do +        case "${1}" in + +            -p) +                pidfile="${2}" +                shift 2 +                ;; + +            *) +                program="${1}" +                if [ -n "${2}" ]; then +                    # Too many arguments +                    # Since this is status, return unknown +                    return 4 +                else +                    break +                fi +                ;; +        esac +    done + +    # If a PID file is not specified, try and find one. +    if [ -z "${pidfile}" ]; then +        # Get the program's basename +        prefix=`echo "${program}" | sed 's/[^/]*$//'` + +        if [ -z "${prefix}" ]; then +           progname="${program}" +        else +           progname=`echo "${program}" | sed "s@${prefix}@@"` +        fi + +        # If a PID file exists with that name, assume that is it. +        if [ -e "/run/${progname}.pid" ]; then +            pidfile="/run/${progname}.pid" +        fi +    fi + +    # If a PID file is set and exists, use it. +    if [ -n "${pidfile}" -a -e "${pidfile}" ]; then + +        # Use the value in the first line of the pidfile +        pidlist=`/bin/head -n1 "${pidfile}"` +        # This can optionally be written as 'sed 1q' to repalce 'head -n1' +        # should LFS move /bin/head to /usr/bin/head +    else +        # Use pidof +        pidlist=`pidof "${program}"` +    fi + +    # Figure out if all listed PIDs are running. +    for pid in ${pidlist}; do +        kill -0 ${pid} 2> /dev/null + +        if [ "${?}" -eq "0" ]; then +            lpids="${lpids}${pid} " +        else +            exitstatus="1" +        fi +    done + +    if [ -z "${lpids}" -a ! -f "${pidfile}" ]; then +        return 3 +    else +        echo "${lpids}" +        return "${exitstatus}" +    fi +} + +################################################################################ +# statusproc()                                                                 # +# Usage: statusproc [-p pidfile] pathname                                      # +#                                                                              # +# Purpose: This function prints the status of a particular daemon to stdout    # +#                                                                              # +# Inputs: -p pidfile, use the specified pidfile instead of pidof               # +#         pathname, path to the specified program                              # +#                                                                              # +# Return values:                                                               # +#       0 - Status printed                                                     # +#       1 - Input error. The daemon to check was not specified.                # +################################################################################ +statusproc() +{ +   local pidfile +   local pidlist + +   if [ "${#}" = "0" ]; then +      echo "Usage: statusproc [-p pidfle] {program}" +      exit 1 +   fi + +   # Process arguments +   while true; do +       case "${1}" in + +           -p) +               pidfile="${2}" +               shift 2 +               ;; + +           *) +               if [ -n "${2}" ]; then +                   echo "Too many arguments" +                   return 1 +               else +                   break +               fi +               ;; +       esac +   done + +   if [ -n "${pidfile}" ]; then +      pidlist=`pidofproc -p "${pidfile}" $@` +   else +      pidlist=`pidofproc $@` +   fi + +   # Trim trailing blanks +   pidlist=`echo "${pidlist}" | sed -r 's/ +$//'` + +   base="${1##*/}" + +   if [ -n "${pidlist}" ]; then +      /bin/echo -e "${INFO}${base} is running with Process" \ +         "ID(s) ${pidlist}.${NORMAL}" +   else +      if [ -n "${base}" -a -e "/run/${base}.pid" ]; then +         /bin/echo -e "${WARNING}${1} is not running but" \ +            "/run/${base}.pid exists.${NORMAL}" +      else +         if [ -n "${pidfile}" -a -e "${pidfile}" ]; then +            /bin/echo -e "${WARNING}${1} is not running" \ +               "but ${pidfile} exists.${NORMAL}" +         else +            /bin/echo -e "${INFO}${1} is not running.${NORMAL}" +         fi +      fi +   fi +} + +################################################################################ +# timespec()                                                                   # +#                                                                              # +# Purpose: An internal utility function to format a timestamp                  # +#          a boot log file.  Sets the STAMP variable.                          # +#                                                                              # +# Return value: Not used                                                       # +################################################################################ +timespec() +{ +   STAMP="$(echo `date +"%b %d %T %:z"` `hostname`) " +   return 0 +} + +################################################################################ +# log_success_msg()                                                            # +# Usage: log_success_msg ["message"]                                           # +#                                                                              # +# Purpose: Print a successful status message to the screen and                 # +#          a boot log file.                                                    # +#                                                                              # +# Inputs: $@ - Message                                                         # +#                                                                              # +# Return values: Not used                                                      # +################################################################################ +log_success_msg() +{ +    /bin/echo -n -e "${BMPREFIX}${@}" +    /bin/echo -e "${CURS_ZERO}${SUCCESS_PREFIX}${SET_COL}${SUCCESS_SUFFIX}" + +    # Strip non-printable characters from log file +    logmessage=`echo "${@}" | sed 's/\\\033[^a-zA-Z]*.//g'` + +    timespec +    /bin/echo -e "${STAMP} ${logmessage} OK" >> ${BOOTLOG} + +    return 0 +} + +log_success_msg2() +{ +    /bin/echo -n -e "${BMPREFIX}${@}" +    /bin/echo -e "${CURS_ZERO}${SUCCESS_PREFIX}${SET_COL}${SUCCESS_SUFFIX}" + +    echo " OK" >> ${BOOTLOG} + +    return 0 +} + +################################################################################ +# log_failure_msg()                                                            # +# Usage: log_failure_msg ["message"]                                           # +#                                                                              # +# Purpose: Print a failure status message to the screen and                    # +#          a boot log file.                                                    # +#                                                                              # +# Inputs: $@ - Message                                                         # +#                                                                              # +# Return values: Not used                                                      # +################################################################################ +log_failure_msg() +{ +    /bin/echo -n -e "${BMPREFIX}${@}" +    /bin/echo -e "${CURS_ZERO}${FAILURE_PREFIX}${SET_COL}${FAILURE_SUFFIX}" + +    # Strip non-printable characters from log file + +    timespec +    logmessage=`echo "${@}" | sed 's/\\\033[^a-zA-Z]*.//g'` +    /bin/echo -e "${STAMP} ${logmessage} FAIL" >> ${BOOTLOG} + +    return 0 +} + +log_failure_msg2() +{ +    /bin/echo -n -e "${BMPREFIX}${@}" +    /bin/echo -e "${CURS_ZERO}${FAILURE_PREFIX}${SET_COL}${FAILURE_SUFFIX}" + +    echo "FAIL" >> ${BOOTLOG} + +    return 0 +} + +################################################################################ +# log_warning_msg()                                                            # +# Usage: log_warning_msg ["message"]                                           # +#                                                                              # +# Purpose: Print a warning status message to the screen and                    # +#          a boot log file.                                                    # +#                                                                              # +# Return values: Not used                                                      # +################################################################################ +log_warning_msg() +{ +    /bin/echo -n -e "${BMPREFIX}${@}" +    /bin/echo -e "${CURS_ZERO}${WARNING_PREFIX}${SET_COL}${WARNING_SUFFIX}" + +    # Strip non-printable characters from log file +    logmessage=`echo "${@}" | sed 's/\\\033[^a-zA-Z]*.//g'` +    timespec +    /bin/echo -e "${STAMP} ${logmessage} WARN" >> ${BOOTLOG} + +    return 0 +} + +log_skip_msg() +{ +    /bin/echo -n -e "${BMPREFIX}${@}" +    /bin/echo -e "${CURS_ZERO}${SKIP_PREFIX}${SET_COL}${SKIP_SUFFIX}" + +    # Strip non-printable characters from log file +    logmessage=`echo "${@}" | sed 's/\\\033[^a-zA-Z]*.//g'` +    /bin/echo "SKIP" >> ${BOOTLOG} + +    return 0 +} + +################################################################################ +# log_info_msg()                                                               # +# Usage: log_info_msg message                                                  # +#                                                                              # +# Purpose: Print an information message to the screen and                      # +#          a boot log file.  Does not print a trailing newline character.      # +#                                                                              # +# Return values: Not used                                                      # +################################################################################ +log_info_msg() +{ +    /bin/echo -n -e "${BMPREFIX}${@}" + +    # Strip non-printable characters from log file +    logmessage=`echo "${@}" | sed 's/\\\033[^a-zA-Z]*.//g'` +    timespec +    /bin/echo -n -e "${STAMP} ${logmessage}" >> ${BOOTLOG} + +    return 0 +} + +log_info_msg2() +{ +    /bin/echo -n -e "${@}" + +    # Strip non-printable characters from log file +    logmessage=`echo "${@}" | sed 's/\\\033[^a-zA-Z]*.//g'` +    /bin/echo -n -e "${logmessage}" >> ${BOOTLOG} + +    return 0 +} + +################################################################################ +# evaluate_retval()                                                            # +# Usage: Evaluate a return value and print success or failure as appropriate  # +#                                                                              # +# Purpose: Convenience function to terminate an info message                   # +#                                                                              # +# Return values: Not used                                                      # +################################################################################ +evaluate_retval() +{ +   local error_value="${?}" + +   if [ ${error_value} = 0 ]; then +      log_success_msg2 +   else +      log_failure_msg2 +   fi +} + +################################################################################ +# check_signal()                                                               # +# Usage: check_signal [ -{signal} ]                                            # +#                                                                              # +# Purpose: Check for a valid signal.  This is not defined by any LSB draft,    # +#          however, it is required to check the signals to determine if the    # +#          signals chosen are invalid arguments to the other functions.        # +#                                                                              # +# Inputs: Accepts a single string value in the form of -{signal}               # +#                                                                              # +# Return values:                                                               # +#       0 - Success (signal is valid                                           # +#       1 - Signal is not valid                                                # +################################################################################ +check_signal() +{ +    local valsig + +    # Add error handling for invalid signals +    valsig=" -ALRM -HUP -INT -KILL -PIPE -POLL -PROF -TERM -USR1 -USR2" +    valsig="${valsig} -VTALRM -STKFLT -PWR -WINCH -CHLD -URG -TSTP -TTIN" +    valsig="${valsig} -TTOU -STOP -CONT -ABRT -FPE -ILL -QUIT -SEGV -TRAP" +    valsig="${valsig} -SYS -EMT -BUS -XCPU -XFSZ -0 -1 -2 -3 -4 -5 -6 -8 -9" +    valsig="${valsig} -11 -13 -14 -15 " + +    echo "${valsig}" | grep -- " ${1} " > /dev/null + +    if [ "${?}" -eq "0" ]; then +        return 0 +    else +        return 1 +    fi +} + +################################################################################ +# check_sig_type()                                                             # +# Usage: check_signal [ -{signal} | {signal} ]                                 # +#                                                                              # +# Purpose: Check if signal is a program termination signal or a control signal # +#          This is not defined by any LSB draft, however, it is required to    # +#          check the signals to determine if they are intended to end a        # +#          program or simply to control it.                                    # +#                                                                              # +# Inputs: Accepts a single string value in the form or -{signal} or {signal}   # +#                                                                              # +# Return values:                                                               # +#       0 - Signal is used for program termination                             # +#       1 - Signal is used for program control                                 # +################################################################################ +check_sig_type() +{ +    local valsig + +    # The list of termination signals (limited to generally used items) +    valsig=" -ALRM -INT -KILL -TERM -PWR -STOP -ABRT -QUIT -2 -3 -6 -9 -14 -15 " + +    echo "${valsig}" | grep -- " ${1} " > /dev/null + +    if [ "${?}" -eq "0" ]; then +        return 0 +    else +        return 1 +    fi +} + +################################################################################ +# wait_for_user()                                                              # +#                                                                              # +# Purpose: Wait for the user to respond if not a headless system               # +#                                                                              # +################################################################################ +wait_for_user() +{ +   # Wait for the user by default +   [ "${HEADLESS=0}" = "0" ] && read ENTER +   return 0 +} + +################################################################################ +# is_true()                                                                    # +#                                                                              # +# Purpose: Utility to test if a variable is true | yes | 1                     # +#                                                                              # +################################################################################ +is_true() +{ +   [ "$1" = "1" ] || [ "$1" = "yes" ] || [ "$1" = "true" ] ||  [ "$1" = "y" ] || +   [ "$1" = "t" ] +} + +# End /lib/lsb/init-functions  | 
