# -*-Shell-script-*-
#
# functions	This file contains functions to be used by most or all
#		shell scripts in the /etc/init.d directory.
#

# Make sure umask is sane
umask 022

# Set up a default search path.
PATH="/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin"
export PATH

# Get a sane screen width
[ -z "${COLUMNS:-}" ] && COLUMNS=80

RES_COL=60
MOVE_TO_COL="echo -en \\033[${RES_COL}G"
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
SETCOLOR_FAILURE="echo -en \\033[1;31m"
SETCOLOR_WARNING="echo -en \\033[1;33m"
SETCOLOR_NORMAL="echo -en \\033[0;39m"

# Check if $pid (could be plural) are running
checkpid() {
	local i

	for i in $* ; do
		[ -d "/proc/$i" ] && return 0
	done
	return 1
}
	

# A function to start a program.
daemon() {
	# Test syntax.
	local gotbase= force=
	local base= user= nice= bg= pid=
	nicelevel=0
	while [ "$1" != "${1##[-+]}" ]; do
	  case $1 in
	    '')    echo $"$0: Usage: daemon [+/-nicelevel] {program}"
	           return 1;;
	    --check)
		   base=$2
		   gotbase="yes"
		   shift 2
		   ;;
	    --check=?*)
	    	   base=${1#--check=}
		   gotbase="yes"
		   shift
		   ;;
	    --user)
		   user=$2
		   shift 2
		   ;;
	    --user=?*)
	           user=${1#--user=}
		   shift
		   ;;
	    --force)
	    	   force="force"
		   shift
		   ;;
	    [-+][0-9]*)
	    	   nice="nice -n $1"
	           shift
		   ;;
	    *)     echo $"$0: Usage: daemon [+/-nicelevel] {program}"
	           return 1;;
	  esac
	done

        # Save basename.
        [ -z "$gotbase" ] && base=${1##*/}

        # See if it's already running. Look *only* at the pid file.
	if [ -f /var/run/${base}.pid ]; then
		local line p
		read line < /var/run/${base}.pid
		for p in $line ; do
			[ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && pid="$pid $p"
		done
	fi
	
	[ -n "${pid:-}" -a -z "${force:-}" ] && return

	# Echo daemon
#        echo -n " $base"

	# And start it up.
	"$*"
	[ "$?" -eq 0 ] && success $"$base startup" || failure $"$base startup"
}

# A function to stop a program.
killproc() {
	RC=0; delay=3
	# Test syntax.
	if [ "$#" -eq 0 ]; then
		echo $"Usage: killproc [ -d delay] {program} [signal]"
		return 1
	fi
	if [ "$1" = "-d" ]; then
		delay=$2
		shift 2
	fi

	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=${1##*/}

        # Find pid.
	pid=
	if [ -f /var/run/${base}.pid ]; then
		local line p
		read line < /var/run/${base}.pid
		for p in $line ; do
			[ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && pid="$pid $p"
		done
	fi
	if [ -z "$pid" ]; then
		pid=`pidof -o $$ -o $PPID -o %PPID -x $1 || \
			pidof -o $$ -o $PPID -o %PPID -x $base`
	fi

        # Kill it.
        if [ -n "${pid:-}" ] ; then
#                echo -n "$base "
		if [ "$notset" -eq "1" ] ; then
		       if checkpid $pid 2>&1; then
			   # TERM first, then KILL if not dead
			   kill -TERM $pid >/dev/null 2>&1
			   sleep .1
			   if checkpid $pid && sleep 1 &&
			      checkpid $pid && sleep $delay &&
			      checkpid $pid ; then
                                kill -KILL $pid >/dev/null 2>&1
				sleep .1
			   fi
		        fi
			checkpid $pid
			RC=$?
			[ "$RC" -eq 0 ] && failure $"$base shutdown" || success $"$base shutdown"
			RC=$((! $RC))
		# use specified level only
		else
		        if checkpid $pid; then
	                	kill $killlevel $pid >/dev/null 2>&1
				RC=$?
				[ "$RC" -eq 0 ] && success $"$base $killlevel" || failure $"$base $killlevel"
			fi
		fi
	else
	    failure $"$base shutdown"
	    RC=1
	fi

        # Remove pid file if any.
	if [ "$notset" = "1" ]; then
            rm -f /var/run/$base.pid
	fi
	return $RC
}

# A function to find the pid of a program. Looks *only* at the pidfile
pidfileofproc() {
	local base=${1##*/}
	
	# Test syntax.
	if [ "$#" = 0 ] ; then
		echo $"Usage: pidfileofproc {program}"
		return 1
	fi

	# First try "/var/run/*.pid" files
	if [ -f /var/run/$base.pid ] ; then
	        local line p pid=
		read line < /var/run/$base.pid
		for p in $line ; do
		       [ -z "${p//[0-9]/}" -a -d /proc/$p ] && pid="$pid $p"
		done
	        if [ -n "$pid" ]; then
	                echo $pid
	                return 0
	        fi
	fi
}

# A function to find the pid of a program.
pidofproc() {
	base=${1##*/}

	# Test syntax.
	if [ "$#" = 0 ]; then
		echo $"Usage: pidofproc {program}"
		return 1
	fi

	# First try "/var/run/*.pid" files
	if [ -f /var/run/$base.pid ]; then
	        local line p pid=
		read line < /var/run/$base.pid
		for p in $line ; do
		       [ -z "${p//[0-9]/}" -a -d /proc/$p ] && pid="$pid $p"
		done
	        if [ -n "$pid" ]; then
	                echo $pid
	                return 0
	        fi
	fi
	pidof -o $$ -o $PPID -o %PPID -x $1 || \
		pidof -o $$ -o $PPID -o %PPID -x $base
}

status() {
	local base=${1##*/}
	local pid

	# Test syntax.
	if [ "$#" = 0 ] ; then
		echo $"Usage: status {program}"
		return 1
	fi

	# First try "pidof"
	pid=`pidof -o $$ -o $PPID -o %PPID -x $1 || \
	     pidof -o $$ -o $PPID -o %PPID -x ${base}`
	if [ -n "$pid" ]; then
	        echo $"${base} (pid $pid) is running..."
	        return 0
	fi

	# Next try "/var/run/*.pid" files
	if [ -f /var/run/${base}.pid ] ; then
	        read pid < /var/run/${base}.pid
	        if [ -n "$pid" ]; then
	                echo $"${base} dead but pid file exists"
	                return 1
	        fi
	fi
	# See if /var/lock/subsys/${base} exists
	if [ -f /var/lock/subsys/${base} ]; then
		echo $"${base} dead but subsys locked"
		return 2
	fi
	echo $"${base} is stopped"
	return 3
}

echo_success() {
	$MOVE_TO_COL
	echo -n "[  "
	$SETCOLOR_SUCCESS
	echo -n $"OK"
	$SETCOLOR_NORMAL
	echo -n "  ]"
	echo -ne "\r"
	return 0
}

echo_failure() {
	$MOVE_TO_COL
	echo -n "["
	$SETCOLOR_FAILURE
	echo -n $"FAILED"
	$SETCOLOR_NORMAL
	echo -n "]"
	echo -ne "\r"
	return 1
}

echo_passed() {
	$MOVE_TO_COL
	echo -n "["
	$SETCOLOR_WARNING
	echo -n $"PASSED"
	$SETCOLOR_NORMAL
	echo -n "]"
	echo -ne "\r"
	return 1
}

echo_warning() {
	$MOVE_TO_COL
	echo -n "["
	$SETCOLOR_WARNING
	echo -n $"WARNING"
	$SETCOLOR_NORMAL
	echo -n "]"
	echo -ne "\r"
	return 1
}

# Log that something succeeded
success() {
	echo_success
	return 0
}

# Log that something failed
failure() {
	rc=$?
	echo_failure
	return $rc
}

# Log that something passed, but may have had errors. Useful for fsck
passed() {
	rc=$?
	echo_passed
	return $rc
}  

# Log a warning
warning() {
	rc=$?
	echo_warning
	return $rc
}  

# Run some action
action() {
	STRING=$1
	echo -n "$STRING "
	shift
	bash -c "$*" && success "$STRING" || failure "$STRING"
	rc=$?
	echo
	return $rc
}
