# functions This file contains functions to be used by most or all # shell scripts in the /etc/init.d directory. # # $Id$ # # Author: Miquel van Smoorenburg, # Hacked by: Greg Galloway and Marc Ewing # Modified for PLD by: # Marek Obuchowicz # Arkadiusz Mi¶kiewicz # Michał Kochanowicz # First set up a default search path. export PATH="/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin" # Set defaults INIT_COL=67 # Source configuration if available - may override default values [ -r /etc/sysconfig/system ] && . /etc/sysconfig/system [ -z "$COLUMNS" ] && COLUMNS=80 is_yes() { # Test syntax if [ $# = 0 ] ; then msg_usage " is_yes {value}" return 2 fi # Check value case "$1" in yes|Yes|YES|true|True|TRUE|on|On|ON|Y|y|1) # true returns zero return 0 ;; *) # false returns one return 1 ;; esac } is_no() { # Test syntax if [ $# = 0 ] ; then msg_usage " is_no {value}" return 2 fi case "$1" in no|No|NO|false|False|FALSE|off|Off|OFF|N|n|0) # true returns zero return 0 ;; *) # false returns one return 1 ;; esac } if is_yes "$FASTRC"; then INIT_DOTS=$(awk "BEGIN{for(\$i=0;\$i<$INIT_COL;\$i++)printf(\".\");}") initlog() { RESULT=0 while [ "$1" != "${1##-}" ] || [ "$1" != "${1##+}" ]; do case $1 in -c) shift $1 RESULT=$? break ;; *) shift ;; esac done return $RESULT } fi kernelver() { awk '{split($3,v,"."); printf("%03d%03d%03d\n", v[1],v[2],v[3]);}' /proc/version } kernelverser() { awk '{split($3,v,"."); printf("%03d%03d\n", v[1],v[2]);}' /proc/version } kernelvermser() { awk '{split($3,v,"."); printf("%03d\n", v[1]);}' /proc/version } # Colors workaround termput() { if is_yes "$FASTRC" || [ ! -d /usr/share/terminfo ] || \ [ ! -x /usr/bin/tput -a ! -x /bin/tput ]; then case "$1" in hpa) echo -ne "\033[$(($2+1))G" ;; cuu*) echo -ne "\033[${2}A" ;; el) echo -ne "\033[0K" ;; setaf) is_yes "$COLOR_INIT" && echo -ne "\033[0;3${2}m" ;; op) termput setaf 9 ;; esac else # check if we are on proper terminal tput longname > /dev/null 2>&1 || return case "$1" in hpa | cuu* | el) tput "$@" ;; setaf) is_yes "$COLOR_INIT" && tput "$@" ;; op) tput setaf 9 ;; esac fi } # printf equivalent printf_() { typeset text m text="$1" ; shift ; if [ $# -gt 0 ]; then m="$1"; shift; while [ $# -gt 0 ]; do m="$m\",\"$1" ; shift ; done fi awk "BEGIN {printf \"$text\", \"$m\"; }" } # National language support function nls() { typeset msg_echo old_nls_domain text message msg_echo='\n' old_nls_domain="$NLS_DOMAIN" # parse command line # don't use -o instead || here - this will break ksh --misiek while [ "$1" != "${1##-}" ] || [ "$1" != "${1##+}" ]; do case "$1" in --nls-domain) shift NLS_DOMAIN="$1" shift ;; -n) msg_echo='' shift ;; esac done message="$1" shift # empty message, so we return --misiek if [ -z "$message" ]; then NLS_DOMAIN="$old_nls_domain" echo -en "$msg_echo" return fi if is_yes "$FASTRC"; then printf "$message" "$@" elif [ -x /bin/gettext -o -x /usr/bin/gettext ]; then text=$(TEXTDOMAINDIR="/etc/sysconfig/locale" gettext -e --domain="${NLS_DOMAIN:-rc-scripts}" "$message") printf_ "$text" "$@" else printf_ "$message" "$@" fi echo -en "$msg_echo" NLS_DOMAIN="$old_nls_domain" } rc_splash() { typeset action action="$1" if ! is_no "$BOOT_SPLASH"; then [ -x /bin/splash ] && /bin/splash "$action" fi : $((progress++)) } msg_network_down() { nls "ERROR: Networking is down. %s can't be run." "$1" >&2 } msg_starting() { show "Starting %s service" "$1" } msg_already_running() { nls "%s service is already running." "$1" } msg_stopping() { show "Stopping %s service" "$1" } msg_not_running() { nls "%s service is not running." "$1" } msg_reloading() { show "Reloading %s service" "$1" } msg_usage() { nls "Usage: %s" "$*" } # Some functions to handle PLD-style messages show() { typeset text if is_yes "$FASTRC"; then echo -n "$INIT_DOTS" termput hpa 0 printf "$@" termput hpa $INIT_COL else text=$(nls "$@") echo -n "$text" awk "BEGIN { for (j=length(\"$text\"); j<$INIT_COL; j++) printf \".\" }" fi } # Displays message in square brackests ("[ DONE ]"). Takes two arguments. # First is the text to display, second is color number to use (argument to # tput setaf). If second argument is not given, default (2, green) will be # used). progress() { typeset COLOR if [ -n "$2" ]; then COLOR="$2"; else COLOR="2"; fi deltext echo -n "$(termput setaf 6)[$(termput setaf "$COLOR") $(nls --nls-domain rc-scripts "$1") $(termput setaf 6)]$(termput op)" } busy() { progress "BUSY" 5 } ok() { progress "DONE" echo } started() { progress "WORK" echo } fail() { progress "FAIL" 1 echo return 1 } died() { progress "DIED" 1 echo return 1 } deltext() { termput hpa $INIT_COL } # Check if $pid (could be plural) are running checkpid() { while [ "$1" ]; do [ -d "/proc/$1" ] && return 0 shift done return 1 } # Usage run_cmd Message command_to_run run_cmd() { typeset exit_code errors message force_err typeset -i force_err=0 typeset -i exit_code=0 case "$1" in -a) force_err=1 shift ;; esac message=$1 show "$message"; busy shift if errors=$(HOME=/tmp TMPDIR=/tmp initlog -c "$*" 2>&1); then ok log_success "$1 $message" else fail log_failed "$1 $message" exit_code=1 fi [ -n "$errors" ] && [ $exit_code -eq 1 -o $force_err -eq 1 ] && echo "$errors" return $exit_code } # A function to start a program (now it's useful on read-only filesystem too) daemon() { typeset errors="" prog="" limits="" typeset -i exit_code=0 [ -z "$DEFAULT_SERVICE_RUN_NICE_LEVEL" ] && DEFAULT_SERVICE_RUN_NICE_LEVEL=0 # "-u unlimited" (-p for ksh) to make sure daemons will be able to fork. # "-c 0" to make sure it doesn't core dump anywhere; while this could mask # problems with the daemon, it also closes some security problems. # Users' limits are set via pam_limits. [ -z "$DEFAULT_SERVICE_LIMITS" ] && DEFAULT_SERVICE_LIMITS_HARD="-u unlimited -c 0" # Test syntax. Don't use -o instead || here - this will break ksh --misiek while [ "$1" != "${1##-}" ] || [ "$1" != "${1##+}" ]; do case $1 in '') msg_usage " daemon [--user user] [+/-nicelevel] {program}" return 2 ;; --check) # for compatibility with redhat/mandrake nls "warning: --check option is ignored!" shift shift ;; --user) shift [ "$1" != "root" ] && prog="/bin/su $1 -c \"" shift ;; -*|+*) SERVICE_RUN_NICE_LEVEL=$1 shift;; esac done # If command to execute ends with quotation mark, add remaining # arguments and close quotation. if [ "$prog" != "${prog%\"}" ]; then prog="$prog $*\"" else prog="$prog $*" fi if [ -n "$KSH_VERSION" ]; then limits="`echo ${SERVICE_LIMITS:-$DEFAULT_SERVICE_LIMITS} | sed -e 's/-\([SH]\?\)u/-\1p/'`" elif [ -n "$ZSH_VERSION" ]; then limits="${SERVICE_LIMITS:-$DEFAULT_SERVICE_LIMITS}" elif [ -n "$BASH_VERSION" ]; then limits="${SERVICE_LIMITS:-$DEFAULT_SERVICE_LIMITS}" # elif [ -n "`$SH -c 'echo ${.sh.version}' 2>/dev/null`" ]; then fi while echo "$limits" | grep -q '[^ ]'; do ulimit `echo ${limits} | sed -e 's/^ *\(-[^-]*\)\(-.*\)\?$/\1/'` limits="`echo ${limits} | sed -e 's/^ *\(-[^-]*\)\(-.*\)\?$/\2/'`" done # And start it up. busy if errors=$(USER=root HOME=/tmp TMPDIR=/tmp nice -n ${SERVICE_RUN_NICE_LEVEL:-$DEFAULT_SERVICE_RUN_NICE_LEVEL} initlog -c "$prog" 2>&1); then log_success "$1 startup" ok else exit_code=1 fail log_failed "$1 startup" [ -n "$errors" ] && echo "$errors" fi return $exit_code } # A function to stop a program. killproc() { typeset notset killlevel base pid result # Test syntax. if [ $# = 0 ]; then msg_usage " killproc {program} [signal]" return 2 fi busy typeset -i notset=0 # check for second arg to be kill level if [ -n "$2" ] ; then killlevel=$2 else notset=1 killlevel="-9" fi # Save basename. base=$(basename "$1") # Find pid. pid=$(pidofproc "$1") [ -z "$pid" ] && pid=$(pidofproc "$base") # Kill it. if [ -n "$pid" -a "$pid" != "$$" ] && checkpid $pid 2>&1 ; then if [ "$notset" = "1" ] ; then if checkpid $pid 2>&1; then # TERM first, then KILL if not dead kill -TERM $pid usleep 100000 if checkpid $pid && sleep 1 && checkpid $pid && sleep 3 && checkpid $pid; then kill -KILL $pid usleep 100000 fi fi checkpid $pid result=$? if [ "$result" -eq 0 ]; then fail log_failed "$1 shutdown" else ok log_success "$1 shutdown" fi result=$(( ! $result )) else # use specified level only if checkpid $pid > /dev/null 2>&1; then kill $killlevel $pid result=$? if [ "$result" -eq 0 ]; then ok log_success "$1 got $killlevel" else result=7 fail log_failed "$1 didn't get $killlevel" fi else result=7 died log_failed "$1 shutdown" fi fi else died log_failed "$1 shutdown" result=7 fi # Remove pid file if any. if [ "$notset" = "1" ]; then rm -f /var/run/${base}.pid fi return $result } # A function to find the pid of a program. pidofproc() { typeset pid base base=$(basename "$1") # Test syntax. if [ $# = 0 ] ; then msg_usage " pidofproc {program}" return 2 fi # First try "/var/run/*.pid" files if [ -f /var/run/${base}.pid ] ; then typeset line p pid pid= read line < /var/run/${base}.pid for p in $line; do [ -z "$(echo "$p" | sed 's/[0-9]//g')" ] && pid="$pid $p" done if [ -n "$pid" ]; then echo $pid return 0 fi fi # Next try "pidof" pidof -o $$ -o $PPID -o %PPID -x "$1" } status() { typeset base pid subsys daemon subsys=$1 daemon=${2:-$subsys} base=$(basename $daemon) # Test syntax. if [ $# = 0 ] ; then msg_usage " status {subsys} [{daemon}]" return 2 fi # First try "pidof" pid=$(pidof -o $$ -o $PPID -o %PPID -x $daemon) if [ "$pid" != "" ]; then nls "%s (pid %s) is running..." "$daemon" "$pid" return 0 # else # pid=`ps ax | awk 'BEGIN { prog=ARGV[1]; ARGC=1 } # { if ((prog == $5) || (("(" prog ")") == $5) || # (("[" prog "]") == $5) || # ((prog ":") == $5)) { print $1 ; exit 0 } }' $1` # if [ "$pid" != "" ]; then # nls "%s (pid %s) is running..." "$daemon" "$pid" # return 0 # fi fi # Next try "/var/run/*.pid" files if [ -f /var/run/${base}.pid ]; then read pid < /var/run/${base}.pid if [ "$pid" != "" ]; then nls "%s dead but pid file exists" "$subsys" return 1 fi fi # See if /var/lock/subsys/$subsys exists if [ -f /var/lock/subsys/$subsys ]; then nls "%s dead but subsys locked" "$subsys" return 2 fi nls "%s is stopped" "$subsys" return 3 } # Confirm whether we really want to run this service confirm() { typeset answer nls -n "Start service %s (Y)es/(N)o/(C)ontinue? [Y] " "$1" read answer case $answer in y|Y|t|T|j|J|"") return 0 ;; c|C|k|K|w|W) return 2 ;; n|N) return 1 ;; *) confirm $1 return $? ;; esac } # module is needed (ie. is requested, is available and isn't loaded already) is_module() { # module name without .o at end if ! (lsmod | grep -q "$1"); then if (ls -R /lib/modules/$(uname -r)/ 2> /dev/null | grep -q "${1}.\(\|k\)o\(\|.gz\)"); then # true return 0 fi fi # false return 1 } _modprobe() { typeset parsed single die args foo result parsed=no while is_no "$parsed" ; do case "$1" in "single") single=yes shift ;; "die") die=yes shift ;; -*) args="$args $1" shift ;; *) parsed=yes ;; esac done if is_yes "${single}" ; then foo="$@" show "Loading %s kernel module(s)" "$foo" busy fi if [ -x /sbin/modprobe ] ; then /sbin/modprobe -s $args "$@" result=$? else deltext ; fail result=1 fi if is_yes "${single}" ; then deltext if [ $result == "0" ] ; then is_yes "$single" && ok else fail if is_yes "$die" ; then nls "Could not load %s kernel module(s)" "$@" exit 1 fi fi fi } log_success () { initlog -n $0 -s "$1 $2" -e 1 } log_failed () { initlog -n $0 -s "$1 $2" -e 2 } # RedHat/Mandrake specific functions action () { STRING=$1; shift; run_cmd "$STRING" "$*"; } success () { return 0; } failure () { return 1; } # TO BE REMOVED IN AC. --ankry msg_Network_Down () { msg_network_down "$*"; } msg_Already_Running () { msg_already_running "$*"; } msg_Not_Running () { msg_not_running "$*"; } msg_Usage () { msg_usage "$*"; } #/* # * Local variables: # * mode: sh # * indent-tabs-mode: notnil # * End: # * # */ # vi: syntax=sh:shiftwidth=8: