# Copyright 1999-2005 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header$ RC_GOT_FUNCTIONS="yes" # daemontools dir SVCDIR="/var/lib/supervise" # Check /etc/conf.d/rc for a description of these ... svcdir="/var/lib/init.d" svclib="/lib/rcscripts" svcmount="no" svcfstype="tmpfs" svcsize=1024 # Different types of dependencies deptypes="need use" # Different types of order deps ordtypes="before after" # # Internal variables # # Dont output to stdout? RC_QUIET_STDOUT="no" RC_VERBOSE=${RC_VERBOSE:-no} # Should we use color? RC_NOCOLOR=${RC_NOCOLOR:-no} # Can the terminal handle endcols? RC_ENDCOL="yes" # # Default values for rc system # RC_TTY_NUMBER=11 RC_NET_STRICT_CHECKING="no" RC_PARALLEL_STARTUP="no" RC_USE_CONFIG_PROFILE="yes" # # Default values for e-message indentation and dots # RC_INDENTATION='' RC_DEFAULT_INDENT=2 #RC_DOT_PATTERN=' .' RC_DOT_PATTERN='' # Override defaults with user settings ... [ -f /etc/conf.d/rc ] && source /etc/conf.d/rc # void import_addon(char *addon) # # Import code from the specified addon if it exists # import_addon() { local addon=${svclib}/addons/$1 if [[ -r ${addon} ]] ; then source "${addon}" return 0 fi return 1 } # void splash(...) # # Notify bootsplash/splashutils/gensplash/whatever about # important events. # splash() { return 0 } # This will override the splash() function... if ! import_addon splash-functions.sh ; then [ -f /sbin/splash-functions.sh ] && source /sbin/splash-functions.sh fi # void profiling(...) # # Notify bootsplash/whatever about important events. # profiling() { return 0 } import_addon profiling-functions.sh # void bootlog(...) # # Notify bootlogger about important events. bootlog() { return 0 } import_addon bootlogger.sh # void get_bootconfig() # # Get the BOOTLEVEL and SOFTLEVEL by setting # 'bootlevel' and 'softlevel' via kernel # parameters. # get_bootconfig() { local copt= local newbootlevel= local newsoftlevel= if [[ -r /proc/cmdline ]] ; then for copt in $( 0 )) || (( i = RC_DEFAULT_INDENT )) esetdent $(( ${#RC_INDENTATION} + i )) } # void eoutdent(int num) # # decrease the indent used for e-commands. # eoutdent() { local i=$1 (( i > 0 )) || (( i = RC_DEFAULT_INDENT )) esetdent $(( ${#RC_INDENTATION} - i )) } # void esetdent(int num) # # hard set the indent used for e-commands. # num defaults to 0 # esetdent() { local i=$1 (( i < 0 )) && (( i = 0 )) RC_INDENTATION=$(printf "%${i}s" '') } # void einfo(char* message) # # show an informative message (with a newline) # einfo() { einfon "$*\n" LAST_E_CMD=einfo return 0 } # void einfon(char* message) # # show an informative message (without a newline) # einfon() { [[ ${RC_QUIET_STDOUT} == yes ]] && return 0 [[ ${RC_ENDCOL} != yes && ${LAST_E_CMD} == ebegin ]] && echo echo -ne " ${GOOD}*${NORMAL} ${RC_INDENTATION}$*" LAST_E_CMD=einfon return 0 } # void ewarn(char* message) # # show a warning message + log it # ewarn() { if [[ ${RC_QUIET_STDOUT} == yes ]]; then echo " $*" else [[ ${RC_ENDCOL} != yes && ${LAST_E_CMD} == ebegin ]] && echo echo -e " ${WARN}*${NORMAL} ${RC_INDENTATION}$*" fi # Log warnings to system log esyslog "daemon.warning" "rc-scripts" "$*" LAST_E_CMD=ewarn return 0 } # void eerror(char* message) # # show an error message + log it # eerror() { if [[ ${RC_QUIET_STDOUT} == yes ]]; then echo " $*" >/dev/stderr else [[ ${RC_ENDCOL} != yes && ${LAST_E_CMD} == ebegin ]] && echo echo -e " ${BAD}*${NORMAL} ${RC_INDENTATION}$*" fi # Log errors to system log esyslog "daemon.err" "rc-scripts" "$*" LAST_E_CMD=eerror return 0 } # void ebegin(char* message) # # show a message indicating the start of a process # ebegin() { local msg="$*" dots spaces=${RC_DOT_PATTERN//?/ } [[ ${RC_QUIET_STDOUT} == yes ]] && return 0 if [[ -n ${RC_DOT_PATTERN} ]]; then dots=$(printf "%$(( COLS - 3 - ${#RC_INDENTATION} - ${#msg} - 7 ))s" '') dots=${dots//${spaces}/${RC_DOT_PATTERN}} msg="${msg}${dots}" else msg="${msg} ..." fi einfon "${msg}" [[ ${RC_ENDCOL} == yes ]] && echo LAST_E_LEN=$(( 3 + ${#RC_INDENTATION} + ${#msg} )) LAST_E_CMD=ebegin return 0 } # void _eend(int error, char *efunc, char* errstr) # # indicate the completion of process, called from eend/ewend # if error, show errstr via efunc # # This function is private to functions.sh. Do not call it from a # script. # _eend() { local retval=${1:-0} efunc=${2:-eerror} msg shift 2 if [[ ${retval} == 0 ]]; then [[ ${RC_QUIET_STDOUT} == yes ]] && return 0 msg="${BRACKET}[ ${GOOD}ok${BRACKET} ]${NORMAL}" else if [[ -c /dev/null ]]; then rc_splash "stop" &>/dev/null & else rc_splash "stop" & fi if [[ -n "$*" ]]; then ${efunc} "$*" fi msg="${BRACKET}[ ${BAD}!!${BRACKET} ]${NORMAL}" fi if [[ ${RC_ENDCOL} == yes ]]; then echo -e "${ENDCOL} ${msg}" else [[ ${LAST_E_CMD} == ebegin ]] || LAST_E_LEN=0 printf "%$(( COLS - LAST_E_LEN - 6 ))s%b\n" '' "${msg}" fi return ${retval} } # void eend(int error, char* errstr) # # indicate the completion of process # if error, show errstr via eerror # eend() { local retval=${1:-0} shift _eend ${retval} eerror "$*" LAST_E_CMD=eend return $retval } # void ewend(int error, char* errstr) # # indicate the completion of process # if error, show errstr via ewarn # ewend() { local retval=${1:-0} shift _eend ${retval} ewarn "$*" LAST_E_CMD=ewend return $retval } # v-e-commands honor RC_VERBOSE which defaults to no. # The condition is negated so the return value will be zero. veinfo() { [[ "${RC_VERBOSE}" != yes ]] || einfo "$@"; } veinfon() { [[ "${RC_VERBOSE}" != yes ]] || einfon "$@"; } vewarn() { [[ "${RC_VERBOSE}" != yes ]] || ewarn "$@"; } veerror() { [[ "${RC_VERBOSE}" != yes ]] || eerror "$@"; } vebegin() { [[ "${RC_VERBOSE}" != yes ]] || ebegin "$@"; } veend() { [[ "${RC_VERBOSE}" == yes ]] && { eend "$@"; return $?; } return ${1:-0} } veend() { [[ "${RC_VERBOSE}" == yes ]] && { ewend "$@"; return $?; } return ${1:-0} } # char *KV_major(string) # # Return the Major (X of X.Y.Z) kernel version # KV_major() { [[ -z $1 ]] && return 1 local KV=$@ echo ${KV%%.*} } # char *KV_minor(string) # # Return the Minor (Y of X.Y.Z) kernel version # KV_minor() { [[ -z $1 ]] && return 1 local KV=$@ KV=${KV#*.} echo ${KV%%.*} } # char *KV_micro(string) # # Return the Micro (Z of X.Y.Z) kernel version. # KV_micro() { [[ -z $1 ]] && return 1 local KV=$@ KV=${KV#*.*.} echo ${KV%%[^[:digit:]]*} } # int KV_to_int(string) # # Convert a string type kernel version (2.4.0) to an int (132096) # for easy compairing or versions ... # KV_to_int() { [[ -z $1 ]] && return 1 local KV_MAJOR=$(KV_major "$1") local KV_MINOR=$(KV_minor "$1") local KV_MICRO=$(KV_micro "$1") local KV_int=$(( KV_MAJOR * 65536 + KV_MINOR * 256 + KV_MICRO )) # We make version 2.2.0 the minimum version we will handle as # a sanity check ... if its less, we fail ... if [[ ${KV_int} -ge 131584 ]] ; then echo "${KV_int}" return 0 fi return 1 } # int get_KV() # # Return the kernel version (major, minor and micro concated) as an integer. # Assumes X and Y of X.Y.Z are numbers. Also assumes that some leading # portion of Z is a number. # e.g. 2.4.25, 2.6.10, 2.6.4-rc3, 2.2.40-poop, 2.0.15+foo # get_KV() { local KV=$(uname -r) echo $(KV_to_int "${KV}") return $? } # bool get_bootparam(param) # # return 0 if gentoo=param was passed to the kernel # # EXAMPLE: if get_bootparam "nodevfs" ; then .... # get_bootparam() { local x copt params retval=1 [ ! -r "/proc/cmdline" ] && return 1 for copt in $(< /proc/cmdline) do if [ "${copt%=*}" = "gentoo" ] then params="$(gawk -v PARAMS="${copt##*=}" ' BEGIN { split(PARAMS, nodes, ",") for (x in nodes) print nodes[x] }')" # Parse gentoo option for x in ${params} do if [ "${x}" = "$1" ] then # echo "YES" retval=0 fi done fi done return ${retval} } # Safer way to list the contents of a directory, # as it do not have the "empty dir bug". # # char *dolisting(param) # # print a list of the directory contents # # NOTE: quote the params if they contain globs. # also, error checking is not that extensive ... # dolisting() { local x= local y= local tmpstr= local mylist= local mypath="$*" if [ "${mypath%/\*}" != "${mypath}" ] then mypath="${mypath%/\*}" fi for x in ${mypath} do [ ! -e "${x}" ] && continue if [ ! -d "${x}" ] && ( [ -L "${x}" -o -f "${x}" ] ) then mylist="${mylist} $(ls "${x}" 2> /dev/null)" else [ "${x%/}" != "${x}" ] && x="${x%/}" cd "${x}"; tmpstr="$(ls)" for y in ${tmpstr} do mylist="${mylist} ${x}/${y}" done fi done echo "${mylist}" } # void save_options(char *option, char *optstring) # # save the settings ("optstring") for "option" # save_options() { local myopts="$1" shift if [ ! -d "${svcdir}/options/${myservice}" ] then mkdir -p -m 0755 "${svcdir}/options/${myservice}" fi echo "$*" > "${svcdir}/options/${myservice}/${myopts}" return 0 } # char *get_options(char *option) # # get the "optstring" for "option" that was saved # by calling the save_options function # get_options() { if [ -f "${svcdir}/options/${myservice}/$1" ] then echo "$(< ${svcdir}/options/${myservice}/$1)" fi return 0 } # char *add_suffix(char * configfile) # # Returns a config file name with the softlevel suffix # appended to it. For use with multi-config services. add_suffix() { if [ "${RC_USE_CONFIG_PROFILE}" = "yes" -a -e "$1.${DEFAULTLEVEL}" ] then echo "$1.${DEFAULTLEVEL}" else echo "$1" fi return 0 } # char *get_base_ver() # # get the version of baselayout that this system is running # get_base_ver() { [[ ! -r /etc/gentoo-release ]] && return 0 local ver=$( 1) { print "More than one entry for '$*' found in /etc/fstab!" > "/dev/stderr" } } ' /etc/fstab } # char *reverse_list(list) # # Returns the reversed order of list # reverse_list() { for (( i = $# ; i > 0 ; --i )); do echo -n "${!i} " done } # void start_addon(addon) # # Starts addon. # start_addon() { local addon=$1 (import_addon ${addon}-start.sh) return 0 } # void start_volumes() # # Starts all volumes in RC_VOLUME_ORDER. # start_volumes() { local x= for x in ${RC_VOLUME_ORDER}; do start_addon "${x}" done return 0 } # void stop_addon(addon) # # Stops addon. # stop_addon() { local addon=$1 (import_addon ${addon}-stop.sh) return 0 } # void stop_volumes() # # Stops all volumes in RC_VOLUME_ORDER (reverse order). # stop_volumes() { local x= for x in $(reverse_list ${RC_VOLUME_ORDER}); do stop_addon "${x}" done return 0 } # bool is_older_than(reference, files/dirs to check) # # return 0 if any of the files/dirs are newer than # the reference file # # EXAMPLE: if is_older_than a.out *.o ; then ... is_older_than() { local x= local ref="$1" shift for x in "$@" ; do [[ ${x} -nt ${ref} ]] && return 0 if [[ -d ${x} ]] ; then is_older_than "${ref}" "${x}"/* && return 0 fi done return 1 } ############################################################################## # # # This should be the last code in here, please add all functions above!! # # # # *** START LAST CODE *** # # # ############################################################################## if [ -z "${EBUILD}" ] ; then # Setup a basic $PATH. Just add system default to existing. # This should solve both /sbin and /usr/sbin not present when # doing 'su -c foo', or for something like: PATH= rcscript start PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/sbin:${PATH}" if [ "$(/sbin/consoletype 2> /dev/null)" = "serial" ] ; then # We do not want colors/endcols on serial terminals RC_NOCOLOR="yes" RC_ENDCOL="no" fi for arg in "$@" ; do case "${arg}" in # Lastly check if the user disabled it with --nocolor argument --nocolor|-nc) RC_NOCOLOR="yes" ;; esac done if [ -r "/proc/cmdline" ] ; then setup_defaultlevels fi else # Should we use colors ? if [[ $* != *depend* ]]; then # Check user pref in portage RC_NOCOLOR="$(portageq envvar NOCOLOR 2>/dev/null)" [ "${RC_NOCOLOR}" = "true" ] && RC_NOCOLOR="yes" else # We do not want colors during emerge depend RC_NOCOLOR="yes" # No output is seen during emerge depend, so this is not needed. RC_ENDCOL="no" fi fi if [[ -n ${EBUILD} && $* == *depend* ]]; then # We do not want stty to run during emerge depend COLS=80 else # Setup COLS and ENDCOL so eend can line up the [ ok ] COLS=${COLUMNS:-0} # bash's internal COLUMNS variable (( COLS == 0 )) && COLS=$(stty size 2>/dev/null | cut -d' ' -f2) (( COLS > 0 )) || (( COLS = 80 )) # width of [ ok ] == 7 fi if [[ ${RC_ENDCOL} == yes ]]; then ENDCOL=$'\e[A\e['$(( COLS - 7 ))'G' else ENDCOL='' fi # Setup the colors so our messages all look pretty if [[ ${RC_NOCOLOR} == yes ]]; then unset GOOD WARN BAD NORMAL HILITE BRACKET else GOOD=$'\e[32;01m' WARN=$'\e[33;01m' BAD=$'\e[31;01m' NORMAL=$'\e[0m' HILITE=$'\e[36;01m' BRACKET=$'\e[34;01m' fi ############################################################################## # # # *** END LAST CODE *** # # # # This should be the last code in here, please add all functions above!! # # # ############################################################################## # vim:ts=4