# functions This file contains functions to be used by most or all
# shell scripts in the /etc/init.d directory.
#
-# Version: @(#) /etc/init.d/functions $Revision: 1.11 $ $Date: 1999/07/05 08:08:36 $
+# $Id: functions,v 1.64 2001/05/15 16:03:38 baggins Exp $
#
# Author: Miquel van Smoorenburg, <miquels@drinkel.nl.mugnet.org>
# Hacked by: Greg Galloway and Marc Ewing
# Modified for PLD by:
-# Marek Obuchowicz <elephant@shadow.eu.org>
+# Marek Obuchowicz <elephant@pld.org.pl>
# Arkadiusz Mi¶kiewicz <misiek@pld.org.pl>
+# Micha³ Kochanowicz <mkochano@pld.org.pl>
# 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
# Colors workaround
-unset tput || :
-if [ "$COLOR_INIT" == "no" ]; then
- tput()
- {
- :
- }
-elif [ ! -d /usr/share/terminfo ]; then
- tput()
- {
- if [ "$2" == "1" ]; then echo -ne "\033[0;31m"
- elif [ "$2" == "2" ]; then echo -ne "\033[0;32m"
- elif [ "$2" == "5" ]; then echo -ne "\033[0;35m"
- elif [ "$2" == "6" ]; then echo -ne "\033[0;36m"
- elif [ "$2" == "7" ]; then echo -ne "\033[0;37m"
- fi
- }
-else
-unset tput || :
-fi
+termput()
+{
+ if [ ! -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
+ tput "$@"
+ 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 broke 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 [ -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"
+}
+
+msg_network_down()
+{
+ nls "ERROR: Networking is down. %s can't be run." "$1"
+}
+
+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
+ text=$(nls "$@")
+ echo -n "$text"
+ awk "BEGIN { for (j=length(\"$text\"); j<$INIT_COL; j++) printf \".\" }"
+}
+
+# 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()
{
- text="$*"..................................................................................
- echo -ne `echo $text | cut -c1-65`
+ 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()
{
- echo -n "`tput setaf 6`[`tput setaf 5` BUSY `tput setaf 6`]`tput setaf 7`"
+ progress "BUSY" 5
}
ok()
{
- echo "`tput setaf 6`[`tput setaf 2` DONE `tput setaf 6`]`tput setaf 7`"
+ progress "DONE"
+ echo
}
started()
{
- echo "`tput setaf 6`[`tput setaf 2` WORK `tput setaf 6`]`tput setaf 7`"
+ progress "WORK"
+ echo
}
fail()
{
- echo "`tput setaf 6`[`tput setaf 1` FAIL `tput setaf 6`]`tput setaf 7`"
+ progress "FAIL" 1
+ echo
+ return 1
}
died()
{
- echo "`tput setaf 6`[`tput setaf 1` DIED `tput setaf 6`]`tput setaf 7`"
+ progress "DIED" 1
+ echo
+ return 1
}
deltext()
{
- echo -ne '\b\b\b\b\b\b\b\b'
+ termput hpa $INIT_COL
}
# Usage run_cmd Message command_to_run
run_cmd()
{
- _ERRORS=""
- MESSAGE=$1
- show "$MESSAGE"; busy
+ 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="`initlog -c \"$*\"`"; then
- deltext; ok
+ if errors=$(HOME=/tmp TMPDIR=/tmp initlog -c "$*" 2>&1); then
+ ok
+ log_success "$1 $message"
else
- deltext; fail; echo $_ERRORS
+ fail
+ log_failed "$1 $message"
+ exit_code=1
fi
- exit_code=$?
- unset _ERRORS
+ [ -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 usefull on read-only filesystem too)
daemon()
{
- nicelevel=0
- _ERRORS=""
+ typeset errors="" prog=""
+ typeset -i exit_code=0
[ -z "$DEFAULT_SERVICE_RUN_NICE_LEVEL" ] && DEFAULT_SERVICE_RUN_NICE_LEVEL=0
- # Test syntax.
- case $1 in
- '') echo '$0: Usage: daemon [+/-nicelevel] {program}'
- return 1;;
- -*|+*) SERVICE_RUN_NICE_LEVEL=$1
- shift;;
- esac
+ # Test syntax. Don't use -o instead || here - this will broke ksh --misiek
+ while [ "$1" != "${1##-}" ] || [ "$1" != "${1##+}" ]; do
+ case $1 in
+ '') msg_usage " daemon [--user user] [+/-nicelevel] {program}"
+ return 1
+ ;;
+ --check)
+ # for compatibility with redhat/mandrake
+ nls "warning: --check option is ignored!"
+ shift
+ shift
+ ;;
+ --user)
+ shift
+ prog="/bin/su $1 -c"
+ shift
+ ;;
+ -*|+*) SERVICE_RUN_NICE_LEVEL=$1
+ shift;;
+ esac
+ done
+ prog="$prog "$*""
# make sure it doesn't core dump anywhere; while this could mask
# problems with the daemon, it also closes some security problems
# And start it up.
busy
- if _ERRORS="`nice -n ${SERVICE_RUN_NICE_LEVEL:-$DEFAULT_SERVICE_RUN_NICE_LEVEL} initlog -c "$*" 2>&1`"; then
- deltext
+ if errors=$(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
- deltext
+ exit_code=1
fail
- echo $_ERRORS
+ log_failed "$1 startup"
+ [ -n "$errors" ] && echo "$errors"
fi
- unset _ERRORS
+ return $exit_code
}
# A function to stop a program.
killproc()
{
+ typeset notset killlevel base pid
# Test syntax.
if [ $# = 0 ]; then
- echo "Usage: killproc {program} [signal]"
+ msg_usage " killproc {program} [signal]"
return 1
fi
busy
- TMPFILE=`mktemp /tmp/init-XXXXXX`
-
- notset=0
+ typeset -i notset=0
# check for second arg to be kill level
- if [ "$2" != "" ] ; then
+ if [ -n "$2" ] ; then
killlevel=$2
else
notset=1
fi
# Save basename.
- base=`basename $1`
+ base=$(basename $1)
# Find pid.
- pid=`pidofproc $base`
+ pid=$(pidofproc $base)
# Kill it.
- if [ "$pid" != "" ] ; then
- if [ "$notset" = 1 ] ; then
- # TERM first, then KILL if not dead
- kill -TERM $pid >$TMPFILE 2>&1
- usleep 100000
- dead=`ps -o pid= $pid`
- if [ "$dead" != "" ]; then
- sleep 3
- kill -KILL $pid >$TMPFILE 2>&1
+ if [ -n "$pid" ] ; then
+ if [ "$notset" = "1" ] ; then
+ if ps h $pid>/dev/null 2>&1; then
+ # TERM first, then KILL if not dead
+ kill -TERM $pid >/dev/null 2>&1
+ usleep 100000
+ if ps h $pid >/dev/null 2>&1 ; then
+ sleep 1
+ if ps h $pid >/dev/null 2>&1 ; then
+ sleep 3
+ if ps h $pid >/dev/null 2>&1 ; then
+ kill -KILL $pid >/dev/null 2>&1
+ fi
+ fi
+ fi
+ if (ps h $pid >/dev/null 2>&1); then
+ fail
+ log_failed "$1 shutdown"
+ else
+ ok
+ log_success "$1 shutdown"
+ fi
+ else
+ died
+ log_failed "$1 shutdown"
fi
# use specified level only
else
- kill $killlevel $pid >$TMPFILE 2>&1
+ if ps h $pid >/dev/null 2>&1; then
+ if (kill $killlevel $pid); then
+ ok
+ log_success "$1 shutdown"
+ else
+ fail
+ log_failed "$1 shutdown"
+ fi
+ else
+ died
+ log_failed "$1 shutdown"
+ fi
fi
else
- rm -f /var/run/$base.pid
- deltext
- fail
- return
+ died
+ log_failed "$1 shutdown"
fi
# Remove pid file if any.
- rm -f /var/run/$base.pid
-
- if [ -z "`cat $TMPFILE`" ]; then
- deltext
- ok
- else
- deltext
- died
+ if [ "$notset" = "1" ]; then
+ rm -f /var/run/$base.pid
fi
- rm -f $TMPFILE
}
# A function to find the pid of a program.
pidofproc()
{
+ typeset pid
# Test syntax.
if [ $# = 0 ] ; then
- echo "Usage: pidofproc {program}"
+ msg_usage " pidofproc {program}"
return 1
fi
# First try "/var/run/*.pid" files
if [ -f /var/run/$1.pid ] ; then
- pid=`head -1 /var/run/$1.pid`
- if [ "$pid" != "" ] ; then
+ pid=$(head -1 /var/run/$1.pid)
+ if [ -n "$pid" ] ; then
echo $pid
return 0
fi
fi
# Next try "pidof"
- #pid=`pidof $1`
- if [ "$pid" != "" ] ; then
+ pid=$(pidof -o $$ -o $PPID -o %PPID -x $1)
+ if [ -n "$pid" ] ; then
echo $pid
return 0
fi
- # Finally try to extract it from ps
- pids=`ps -C $1 -o pid=`
-
- # Return the first PID, which is not our
- for pid in $pids ; do
- if [ $pid != $$ ] ; then
- echo $pid
- return 0
- fi
- done
-
- return 1
+ # Finally try to extract it from ps
+ ps ax | awk 'BEGIN { prog=ARGV[1]; ARGC=1 }
+ { if ((prog == $5) || (("(" prog ")") == $5) ||
+ (("[" prog "]") == $5) ||
+ ((prog ":") == $5)) { print $1 ; exit 0 } }' $1
}
status()
{
# Test syntax.
if [ $# = 0 ] ; then
- echo "Usage: status {program}"
+ msg_usage " status {subsys} [{daemon}]"
return 1
fi
+ subsys=$1
+ daemon=${2:-$subsys}
+
# First try "pidof"
- pid=`pidof $1`
- if [ "$pid" != "" ] ; then
- echo "$1 (pid $pid) is running..."
+ pid=$(pidof -o $$ -o $PPID -o %PPID -x $daemon)
+ if [ -n "$pid" ] ; then
+ nls "%s (pid %s) is running..." "$daemon" "$pid"
return 0
else
- pid=`echo \`ps -C $1 -o pid= \``
+ 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
- echo "$1 (pid $pid) is running..."
+ nls "%s (pid %s) is running..." "$daemon" "$pid"
return 0
fi
fi
# Next try "/var/run/*.pid" files
- if [ -f /var/run/$1.pid ] ; then
- pid=`head -1 /var/run/$1.pid`
- if [ "$pid" != "" ] ; then
- echo "$1 dead but pid file exists"
+ if [ -f /var/run/$daemon.pid ] ; then
+ pid=$(head -1 /var/run/$1.pid)
+ if [ -n "$pid" ] ; then
+ nls "%s dead but pid file exists" "$1"
return 1
fi
fi
- # See if /var/lock/subsys/$1 exists
- if [ -f /var/lock/subsys/$1 ]; then
- echo "$1 dead but subsys locked"
+ # See if /var/lock/subsys/$subsys exists
+ if [ -f /var/lock/subsys/$subsys ]; then
+ nls "%s dead but subsys locked" "$daemon"
return 2
fi
- echo "$1 is stopped"
+ 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
+}
+
+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
+
+ # It's important that is_no() should always return logical
+ # negation of is_yes(). Really ALWAYS. --misiek
+ # NOTE: This means that passing value which mean neither "yes" nor
+ # "no" will return "true", beacause it does not mean "yes". Weird,
+ # isn't it? :) --mkochano
+ if is_yes "$1" ; then
+ return 1
+ else
+ return 0
+ fi
+}
+
+# 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}.o"); 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 SOON. --misiek
+msg_Network_Down () { msg_network_down "$*"; }
+msg_Already_Running () { msg_already_running "$*"; }
+msg_Not_Running () { msg_not_running "$*"; }
+msg_Usage () { msg_usage "$*"; }
+
+# This must be last line !
+# vi:syntax=sh:tw=78:ts=8:sw=4