diff options
Diffstat (limited to 'lsb-bootscripts/lib/lsb/init-functions')
-rw-r--r-- | lsb-bootscripts/lib/lsb/init-functions | 583 |
1 files changed, 583 insertions, 0 deletions
diff --git a/lsb-bootscripts/lib/lsb/init-functions b/lsb-bootscripts/lib/lsb/init-functions new file mode 100644 index 000000000..338f3e00b --- /dev/null +++ b/lsb-bootscripts/lib/lsb/init-functions @@ -0,0 +1,583 @@ +# Begin /lib/lsb/init-funtions + +# Provides initialization funtions as defined by the Linux Standard Base +# specification, version 3.1.0 + +# Source rc configuration if not inherited from the environment +if [ "${RC_BASE}" = "" ]; then + . /etc/default/rc +fi + +# Source the distro functions file +if [ "${DISTRO_MINI}" != "" ]; then + . "${RC_BASE}/init.d/${DISTRO_MINI}-functions" +fi + +################################################################################ +# 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 + # succesful 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. + rm -f "${pidfile}" + # 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" ] # signal is used to terminate the program + then + # account for empty pidlist (pid file still exists and nosignal 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 + else + # just check one last time and if still alive, fail + sleep 1 + 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 "/var/run/${progname}.pid" ] + then + rm -f "/var/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 it's job, and evaluate kills 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/[^/]*$//'` + progname=`echo "${program}" | sed "s@${prefix}@@"` + # if a PID file exists with that name, assume that is it. + if [ -e "/var/run/${progname}.pid" ] + then + pidfile="/var/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="${pids}${pid} " + else + exitstatus="1" + fi + done + + if [ -z "${lpids}" -a ! -f "${pidfile}" ]; then + return 3 + else + echo "${lpids}" + return "${exitstatus}" + fi +} +################################################################################ +# log_success_msg() # +# Usage: log_success_msg [$MESSAGE | "message"] # +# # +# Purpose: Print a successful status message to the screen and optionally # +# a boot log file. # +# # +# Inputs: accepts one string value, either a quoted string or optionally # +# the value of $MESSAGE if set in the running environment. # +# # +# Return values: Not used # +################################################################################ +log_success_msg() +{ + echo -n -e "${PREFIX_SUCCESS}${@}" + echo -e "${SET_COL}${BRACKET}[${SUCCESS} OK ${BRACKET}]${NORMAL}" + if [ "${BOOTLOG_ENAB}" = "yes" ]; then + if [ $( hostname ) = "(none)" ]; then + BTTIMESPEC="" + else + BTTIMESPEC="$(echo `date -u +"%b %d %T"` `hostname`) " + fi + if [ "${RUNLEVEL}" != "0" -a "${RUNLEVEL}" != "6" ]; then + echo "${BTTIMESPEC}bootlog: ${@} Successful" >> /run/.bootlog + fi + fi + return 0 +} + +################################################################################ +# log_failure_msg() # +# Usage: log_failure_msg [$MESSAGE | "message"] # +# # +# Purpose: Print a failure status message to the screen and optionally # +# a boot log file. # +# # +# Inputs: accepts one string value, either a quoted string or optionally # +# the value of $MESSAGE if set in the running environment. # +# # +# Return values: Not used # +################################################################################ +log_failure_msg() +{ + echo -n -e "${PREFIX_FAILURE}${@}" + echo -e "${SET_COL}${BRACKET}[${FAILURE} FAIL ${BRACKET}]${NORMAL}" + if [ "${BOOTLOG_ENAB}" = "yes" ]; then + if [ $( hostname ) = "(none)" ]; then + BTTIMESPEC="" + else + BTTIMESPEC="$(echo `date -u +"%b %d %T"` `hostname`) " + fi + if [ "${RUNLEVEL}" != "0" -a "${RUNLEVEL}" != "6" ]; then + echo "${BTTIMESPEC}bootlog: ${@} Failed!" >> /run/.bootlog + fi + fi + return 0 +} + +################################################################################ +# log_warning_msg() # +# Usage: log_warning_msg [$MESSAGE | "message"] # +# # +# Purpose: Print a warning status message to the screen and optionally # +# a boot log file. # +# # +# Inputs: accepts one string value, either a quoted string or optionally # +# the value of $MESSAGE if set in the running environment. # +# # +# Return values: Not used # +################################################################################ +log_warning_msg() +{ + echo -n -e "${PREFIX_WARNING}${@}" + echo -e "${SET_COL}${BRACKET}[${WARNING} WARN ${BRACKET}]${NORMAL}" + if [ "${BOOTLOG_ENAB}" = "yes" ]; then + if [ $( hostname ) = "(none)" ]; then + BTTIMESPEC="" + else + BTTIMESPEC="$(echo `date -u +"%b %d %T"` `hostname`) " + fi + if [ "${RUNLEVEL}" != "0" -a "${RUNLEVEL}" != "6" ]; then + echo "${BTTIMESPEC}bootlog: ${@} Warning" >> /run/.bootlog + fi + fi + return 0 +} + +################################################################################ +# check_signal() # +# Usage: check_signal [ -{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 or -{signal} or {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 +} + +# End /lib/lsb/init-functions |