#!/bin/sh######################################################################### Begin $rc_base/init.d/functions## Description : Run Level Control Functions## Authors : Gerard Beekmans - gerard@linuxfromscratch.org## Version : 00.00## Notes : With code based on Matthias Benkmann's simpleinit-msb# http://winterdrache.de/linux/newboot/index.html######################################################################### ## Environmental setup# Setup default values for environmentumask 022export PATH="/bin:/usr/bin:/sbin:/usr/sbin" # Signal sent to running processes to refresh their configurationRELOADSIG="HUP" # Number of seconds between STOPSIG and FALLBACK when stopping processesKILLDELAY="3" ## Screen Dimensions# Find current screen sizeif [ -z "${COLUMNS}" ]; then COLUMNS=$(stty size) COLUMNS=${COLUMNS##* }fi # When using remote connections, such as a serial port, stty size returns 0if [ "${COLUMNS}" = "0" ]; then COLUMNS=80fi ## Measurements for positioning result messagesCOL=$((${COLUMNS} - 8))WCOL=$((${COL} - 2)) ## Provide an echo that supports -e and -n# If formatting is needed, $ECHO should be usedcase "`echo -e -n test`" in -[en]*) ECHO=/bin/echo ;; *) ECHO=echo ;;esac ## Set Cursor Position Commands, used via $ECHOSET_COL="\\033[${COL}G" # at the $COL charSET_WCOL="\\033[${WCOL}G" # at the $WCOL charCURS_UP="\\033[1A\\033[0G" # Up one line, at the 0'th char ## 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 consolesNORMAL="\\033[0;39m" # Standard console greySUCCESS="\\033[1;32m" # Success is greenWARNING="\\033[1;33m" # Warnings are yellowFAILURE="\\033[1;31m" # Failures are redINFO="\\033[1;36m" # Information is light cyanBRACKET="\\033[1;34m" # Brackets are blue STRING_LENGTH="0" # the length of the current message #*******************************************************************************# Function - boot_mesg()## Purpose: Sending information from bootup scripts to the console## Inputs: $1 is the message# $2 is the colorcode for the console## Outputs: Standard Output## Dependencies: - sed for parsing strings.# - grep for counting string length.# # Todo: #*******************************************************************************boot_mesg(){ local ECHOPARM="" while true do case "${1}" in -n) ECHOPARM=" -n " shift 1 ;; -*) echo "Unknown Option: ${1}" return 1 ;; *) break ;; esac done ## Figure out the length of what is to be printed to be used ## for warning messages. STRING_LENGTH=$((${#1} + 1)) # Print the message to the screen ${ECHO} ${ECHOPARM} -e "${2}${1}" } boot_mesg_flush(){ # Reset STRING_LENGTH for next message STRING_LENGTH="0"} boot_log(){ # Left in for backwards compatibility :} echo_ok(){ ${ECHO} -n -e "${CURS_UP}${SET_COL}${BRACKET}[${SUCCESS} OK ${BRACKET}]" ${ECHO} -e "${NORMAL}" boot_mesg_flush} echo_failure(){ ${ECHO} -n -e "${CURS_UP}${SET_COL}${BRACKET}[${FAILURE} FAIL ${BRACKET}]" ${ECHO} -e "${NORMAL}" boot_mesg_flush} echo_warning(){ ${ECHO} -n -e "${CURS_UP}${SET_COL}${BRACKET}[${WARNING} WARN ${BRACKET}]" ${ECHO} -e "${NORMAL}" boot_mesg_flush} print_error_msg(){ echo_failure # $i is inherited by the rc script boot_mesg -n "FAILURE:\n\nYou should not be reading this error message.\n\n" ${FAILURE} boot_mesg -n " It means that an unforeseen error took" boot_mesg -n " place in ${i}, which exited with a return value of" boot_mesg " ${error_value}.\n" boot_mesg_flush boot_mesg -n "If you're able to track this" boot_mesg -n " error down to a bug in one of the files provided by" boot_mesg -n " the LFS book, please be so kind to inform us at" boot_mesg " lfs-dev@linuxfromscratch.org.\n" boot_mesg_flush boot_mesg -n "Press Enter to continue..." ${INFO} boot_mesg "" ${NORMAL} read ENTER} check_script_status(){ # $i is inherited by the rc script if [ ! -f ${i} ]; then boot_mesg "${i} is not a valid symlink." ${WARNING} echo_warning continue fi if [ ! -x ${i} ]; then boot_mesg "${i} is not executable, skipping." ${WARNING} echo_warning continue fi} evaluate_retval(){ error_value="${?}" if [ ${error_value} = 0 ]; then echo_ok else echo_failure fi # This prevents the 'An Unexpected Error Has Occurred' from trivial # errors. return 0} print_status(){ if [ "${#}" = "0" ]; then echo "Usage: ${0} {success|warning|failure}" return 1 fi case "${1}" in success) echo_ok ;; warning) # Leave this extra case in because old scripts # may call it this way. case "${2}" in running) ${ECHO} -e -n "${CURS_UP}" ${ECHO} -e -n "\\033[${STRING_LENGTH}G " boot_mesg "Already running." ${WARNING} echo_warning ;; not_running) ${ECHO} -e -n "${CURS_UP}" ${ECHO} -e -n "\\033[${STRING_LENGTH}G " boot_mesg "Not running." ${WARNING} echo_warning ;; not_available) ${ECHO} -e -n "${CURS_UP}" ${ECHO} -e -n "\\033[${STRING_LENGTH}G " boot_mesg "Not available." ${WARNING} echo_warning ;; *) # This is how it is supposed to # be called echo_warning ;; esac ;; failure) echo_failure ;; esac } reloadproc(){ local pidfile="" local failure=0 while true do case "${1}" in -p) pidfile="${2}" shift 2 ;; -*) log_failure_msg "Unknown Option: ${1}" return 2 ;; *) break ;; esac done if [ "${#}" -lt "1" ]; then log_failure_msg "Usage: reloadproc [-p pidfile] pathname" return 2 fi # This will ensure compatibility with previous LFS Bootscripts if [ -n "${PIDFILE}" ]; then pidfile="${PIDFILE}" fi # Is the process running? if [ -z "${pidfile}" ]; then pidofproc -s "${1}" else pidofproc -s -p "${pidfile}" "${1}" fi # Warn about stale pid file if [ "$?" = 1 ]; then boot_mesg -n "Removing stale pid file: ${pidfile}. " ${WARNING} rm -f "${pidfile}" fi if [ -n "${pidlist}" ]; then for pid in ${pidlist} do kill -"${RELOADSIG}" "${pid}" || failure="1" done (exit ${failure}) evaluate_retval else boot_mesg "Process ${1} not running." ${WARNING} echo_warning fi} statusproc(){ local pidfile="" local base="" local ret="" while true do case "${1}" in -p) pidfile="${2}" shift 2 ;; -*) log_failure_msg "Unknown Option: ${1}" return 2 ;; *) break ;; esac done if [ "${#}" != "1" ]; then shift 1 log_failure_msg "Usage: statusproc [-p pidfile] pathname" return 2 fi # Get the process basename base="${1##*/}" # This will ensure compatibility with previous LFS Bootscripts if [ -n "${PIDFILE}" ]; then pidfile="${PIDFILE}" fi # Is the process running? if [ -z "${pidfile}" ]; then pidofproc -s "${1}" else pidofproc -s -p "${pidfile}" "${1}" fi # Store the return status ret=$? if [ -n "${pidlist}" ]; then ${ECHO} -e "${INFO}${base} is running with Process"\ "ID(s) ${pidlist}.${NORMAL}" else if [ -n "${base}" -a -e "/var/run/${base}.pid" ]; then ${ECHO} -e "${WARNING}${1} is not running but"\ "/var/run/${base}.pid exists.${NORMAL}" else if [ -n "${pidfile}" -a -e "${pidfile}" ]; then ${ECHO} -e "${WARNING}${1} is not running"\ "but ${pidfile} exists.${NORMAL}" else ${ECHO} -e "${INFO}${1} is not running.${NORMAL}" fi fi fi # Return the status from pidofproc return $ret} # The below functions are documented in the LSB-generic 2.1.0 #*******************************************************************************# Function - pidofproc [-s] [-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## Outputs: return 0 - Success, pid's in stdout# return 1 - Program is dead, pidfile exists# return 2 - Invalid or excessive number of arguments, # warning in stdout# return 3 - Program is not running## Dependencies: pidof, echo, head## Todo: Remove dependency on head# This replaces getpids# Test changes to pidof##*******************************************************************************pidofproc(){ local pidfile="" local lpids="" local silent="" pidlist="" while true do case "${1}" in -p) pidfile="${2}" shift 2 ;; -s) # Added for legacy opperation of getpids # eliminates several '> /dev/null' silent="1" shift 1 ;; -*) log_failure_msg "Unknown Option: ${1}" return 2 ;; *) break ;; esac done if [ "${#}" != "1" ]; then shift 1 log_failure_msg "Usage: pidofproc [-s] [-p pidfile] pathname" return 2 fi if [ -n "${pidfile}" ]; then if [ ! -r "${pidfile}" ]; then return 3 # Program is not running fi lpids=`head -n 1 ${pidfile}` for pid in ${lpids} do if [ "${pid}" -ne "$$" -a "${pid}" -ne "${PPID}" ]; then kill -0 "${pid}" 2>/dev/null && pidlist="${pidlist} ${pid}" fi if [ "${silent}" != "1" ]; then echo "${pidlist}" fi test -z "${pidlist}" && # Program is dead, pidfile exists return 1 # else return 0 done else pidlist=`pidof -o $$ -o $PPID -x "$1"` if [ "${silent}" != "1" ]; then echo "${pidlist}" fi # Get provide correct running status if [ -n "${pidlist}" ]; then return 0 else return 3 fi fi if [ "$?" != "0" ]; then return 3 # Program is not running fi} #*******************************************************************************# Function - loadproc [-f] [-n nicelevel] [-p pidfile] pathname [args]## Purpose: This runs the specified program as a daemon## Inputs: -f, run the program even if it is already running# -n nicelevel, specifies a nice level. See nice(1).# -p pidfile, uses the specified pidfile# pathname, pathname to the specified program# args, arguments to pass to specified program## Outputs: return 0 - Success# return 2 - Invalid of excessive number of arguments, # warning in stdout# return 4 - Program or service status is unknown## Dependencies: nice, rm## Todo: LSB says this should be called start_daemon# LSB does not say that it should call evaluate_retval# It checks for PIDFILE, which is deprecated.# Will be removed after BLFS 6.0# loadproc returns 0 if program is already running, not LSB compliant##*******************************************************************************loadproc(){ local pidfile="" local forcestart="" local nicelevel="10" # This will ensure compatibility with previous LFS Bootscripts if [ -n "${PIDFILE}" ]; then pidfile="${PIDFILE}" fi while true do case "${1}" in -f) forcestart="1" shift 1 ;; -n) nicelevel="${2}" shift 2 ;; -p) pidfile="${2}" shift 2 ;; -*) log_failure_msg "Unknown Option: ${1}" return 2 #invalid or excess argument(s) ;; *) break ;; esac done if [ "${#}" = "0" ]; then log_failure_msg "Usage: loadproc [-f] [-n nicelevel] [-p pidfile] pathname [args]" return 2 #invalid or excess argument(s) fi if [ -z "${forcestart}" ]; then if [ -z "${pidfile}" ]; then pidofproc -s "${1}" else pidofproc -s -p "${pidfile}" "${1}" fi case "${?}" in 0) log_warning_msg "Unable to continue: ${1} is running" return 0 # 4 ;; 1) boot_mesg "Removing stale pid file: ${pidfile}" ${WARNING} rm -f "${pidfile}" ;; 3) ;; *) log_failure_msg "Unknown error code from pidofproc: ${?}" return 4 ;; esac fi nice -n "${nicelevel}" "${@}" evaluate_retval # This is "Probably" not LSB compliant,# but required to be compatible with older bootscripts return 0} #*******************************************************************************# Function - killproc [-p pidfile] pathname [signal]## Purpose:## Inputs: -p pidfile, uses the specified pidfile# pathname, pathname to the specified program# signal, send this signal to pathname## Outputs: return 0 - Success# return 2 - Invalid of excessive number of arguments, # warning in stdout# return 4 - Unknown Status## Dependencies: kill, rm## Todo: LSB does not say that it should call evaluate_retval# It checks for PIDFILE, which is deprecated.# Will be removed after BLFS 6.0##*******************************************************************************killproc(){ local pidfile="" local killsig=TERM # default signal is SIGTERM pidlist="" # This will ensure compatibility with previous LFS Bootscripts if [ -n "${PIDFILE}" ]; then pidfile="${PIDFILE}" fi while true do case "${1}" in -p) pidfile="${2}" shift 2 ;; -*) log_failure_msg "Unknown Option: ${1}" return 2 ;; *) break ;; esac done if [ "${#}" = "2" ]; then killsig="${2}" elif [ "${#}" != "1" ]; then shift 2 log_failure_msg "Usage: killproc [-p pidfile] pathname [signal]" return 2 fi # Is the process running? if [ -z "${pidfile}" ]; then pidofproc -s "${1}" else pidofproc -s -p "${pidfile}" "${1}" fi # Remove stale pidfile if [ "$?" = 1 ]; then boot_mesg "Removing stale pid file: ${pidfile}." ${WARNING} rm -f "${pidfile}" fi # If running, send the signal if [ -n "${pidlist}" ]; then for pid in ${pidlist} do kill -${killsig} ${pid} 2>/dev/null # Wait up to 3 seconds, for ${pid} to terminate case "${killsig}" in TERM|SIGTERM|KILL|SIGKILL) # sleep in 1/10ths of seconds and # multiply KILLDELAY by 10 local dtime="${KILLDELAY}0" while [ "${dtime}" != "0" ] do kill -0 ${pid} 2>/dev/null || break sleep 0.1 dtime=$(( ${dtime} - 1)) done # If ${pid} is still running, kill it kill -0 ${pid} 2>/dev/null && kill -KILL ${pid} 2>/dev/null ;; esac done # Check if the process is still running if we tried to stop it case "${killsig}" in TERM|SIGTERM|KILL|SIGKILL) if [ -z "${pidfile}" ]; then pidofproc -s "${1}" else pidofproc -s -p "${pidfile}" "${1}" fi # Program was terminated if [ "$?" != "0" ]; then # Remove the pidfile if necessary if [ -f "${pidfile}" ]; then rm -f "${pidfile}" fi echo_ok return 0 else # Program is still running echo_failure return 4 # Unknown Status fi ;; *) # Just see if the kill returned successfully evaluate_retval ;; esac else # process not running print_status warning not_running fi} #*******************************************************************************# Function - log_success_msg "message"## Purpose: Print a success message## Inputs: $@ - Message## Outputs: Text output to screen## Dependencies: echo## Todo: logging##*******************************************************************************log_success_msg(){ ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}" ${ECHO} -e "${SET_COL}""${BRACKET}""[""${SUCCESS}"" OK ""${BRACKET}""]""${NORMAL}" return 0} #*******************************************************************************# Function - log_failure_msg "message"## Purpose: Print a failure message## Inputs: $@ - Message## Outputs: Text output to screen## Dependencies: echo## Todo: logging##*******************************************************************************log_failure_msg() { ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}" ${ECHO} -e "${SET_COL}""${BRACKET}""[""${FAILURE}"" FAIL ""${BRACKET}""]""${NORMAL}" return 0} #*******************************************************************************# Function - log_warning_msg "message"## Purpose: print a warning message## Inputs: $@ - Message## Outputs: Text output to screen## Dependencies: echo## Todo: logging##*******************************************************************************log_warning_msg() { ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}" ${ECHO} -e "${SET_COL}""${BRACKET}""[""${WARNING}"" WARN ""${BRACKET}""]""${NORMAL}" return 0} # End $rc_base/init.d/functions