# Copyright 1999-2005 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header$ # RC functions to work with daemons # Basically we're a fancy wrapper for start-stop-daemon # and should be called as such. This means that our init scripts # should work as is with zero modification :) # Actually, the above is a small as lie we have some init scripts which try to # get start-stop-daemon to launch a shell script. While this does work with # the start-stop-daemon program in /sbin, it does cause a problem for us # when we're testing for the daemon to be running. I (Roy Marples) view this # as behaviour by design as start-stop-daemon should not be used to run shell # scripts! # At the time of writing, the only culprit I know of is courier-imap. # There may be others! RC_GOT_DAEMON="yes" [[ ${RC_GOT_FUNCTIONS} != "yes" ]] && source /sbin/functions.sh RC_RETRY_KILL="no" RC_RETRY_TIMEOUT=1 RC_RETRY_COUNT=5 RC_FAIL_ON_ZOMBIE="no" RC_KILL_CHILDREN="no" RC_WAIT_ON_START="0.1" # Override default settings with user settings ... [[ -f /etc/conf.d/rc ]] && source /etc/conf.d/rc # void rc_shift_args(void) # # Proccess vars - makes things easier by using the shift command rc_shift_args() { while [[ $# != "0" ]]; do if [[ $1 != "-"* && -n ${addvar} ]]; then eval "${addvar}=\"${!addvar} $1\"" shift continue fi unset addvar case $1 in -S|--start) stopping=false ;; -K|--stop) stopping=true ;; -n|--name) addvar="name" ;; -x|--exec|-a|--startas) addvar="cmd" ;; -p|--pidfile) addvar="pidfile" ;; --pid=*) pidfile="${1##--pid=}" ;; -s|--signal) addvar="signal" ;; -t|--test|-o|--oknodo) nothing=true ;; esac shift done } # void rc_setup_daemon_vars(void) # # Setup our vars based on the start-stop-daemon command rc_setup_daemon_vars() { local name i local -a sargs=( "${args%% \'--\' *}" ) local -a eargs local x=${args// \'--\' /} [[ ${x} != ${args} ]] && eargs=( "${args##* \'--\' }" ) rc_shift_args ${sargs[@]} [[ -z ${cmd} ]] && cmd="${name}" # The env command launches daemons in a special environment # so we need to cater for this if [[ ${cmd} == "/usr/bin/env" ]]; then j=${#eargs[@]} for (( i=0; i/dev/null fi else /bin/kill -s ${signal} ${pid} 2>/dev/null || return 0 fi LC_ALL=C /bin/sleep ${s} done return 1 } # bool rc_kill_pid(int pid, bool session) # # Kills the given pid/session # Returns 1 if we fail to kill the pid (if it's valid) otherwise 0 rc_kill_pid() { local pid=$1 session=${2:-false} rc_try_kill_pid ${pid} ${signal} ${session} && return 0 [[ ${RC_RETRY_KILL} == "yes" ]] \ && rc_try_kill_pid ${pid} KILL ${session} && return 0 return 1 } # char* pidof(char* cmd, ...) # # Returns a space seperated list of pids associated with the command # This is to handle the rpc.nfsd program which acts weird pidof() { local arg args for arg in "$@"; do [[ ${arg##*/} == "rpc.nfsd" ]] && arg="${arg%/*}/nfsd" args="${args} '"${arg}"'" done eval /bin/pidof -x ${args} } # bool is_daemon_running(char* cmd, char* pidfile) # # Returns 0 if the given daemon is running, otherwise 1 # If a pidfile is supplied, the pid inside it must match # a pid in the list of pidof ${cmd} is_daemon_running() { local cmd pidfile pids pid if [[ $# == "1" ]]; then cmd="$1" else local i j="$#" for (( i=0; i/dev/null # We don't want to echo ebegin/eend elif [[ -n ${pidfile} ]]; then rc_stop_daemon fi return ${retval} } # bool rc_stop_daemon(void) # # Instead of calling start-stop-daemon we instead try and # kill the process ourselves and any children left over # Returns 0 if everything was successful otherwise 1 rc_stop_daemon() { local pid pids retval=0 if [[ -n ${cmd} ]]; then if ! is_daemon_running ${cmd} ${pidfile} ; then [[ ${RC_FAIL_ON_ZOMBIE} == "yes" ]] && return 1 fi pids=$( pidof ${cmd} ) fi if [[ -s ${pidfile} ]]; then read pid < ${pidfile} # Check that the given program is actually running the pid if [[ -n ${pids} ]]; then pids=" ${pids} " [[ ${pids// ${pid} } == ${pids} ]] && return 1 fi pids=${pid} fi for pid in ${pids}; do if [[ ${RC_FAIL_ON_ZOMBIE} == "yes" ]]; then /bin/ps -p ${pid} &>/dev/null || return 1 fi if rc_kill_pid ${pid} false ; then # Remove the pidfile if the process didn't [[ -f ${pidfile} ]] && /bin/rm -f ${pidfile} else retval=1 fi if [[ ${RC_KILL_CHILDREN} == "yes" ]]; then rc_kill_pid ${pid} true || retval=1 fi done return ${retval} } # int start-stop-daemon(...) # # Provide a wrapper to start-stop-daemon # Return the result of start_daemon or stop_daemon depending on # how we are called start-stop-daemon() { local args=$( requote "$@" ) local cmd pidfile pid stopping nothing=false signal=TERM rc_setup_daemon_vars # We pass --oknodo and --test directly to start-stop-daemon and return if ${nothing}; then eval /sbin/start-stop-daemon "${args}" return $? fi if ${stopping}; then rc_stop_daemon else rc_start_daemon fi } # vim:ts=4