#! /bin/sh
#
# sendsigs	Kill all remaining processes.
#
# Version:      @(#)sendsigs  2.75  22-Jun-1998  miquels@cistron.nl
#

PATH=/sbin:/bin:/usr/sbin:/usr/bin

OMIT_PIDS=""
OMIT_APPS="pmklogd \
           pmsyslogd \
           cryptofs \
"

# Omit any apps explicitly listed above
for APPNAME in $OMIT_APPS; do
    for PID in $(pidof $APPNAME); do
        OMIT_PIDS="$OMIT_PIDS -o $PID"
    done
done

# Omit any pids listed in the omit directory.  currently only
# watchdog.sh uses this directory.  Beware: killall5 has a hard-coded
# limit to the number of -o options and exits (kills nothing) if that
# number is exceeded.
if [ -d /tmp/sendsigs.omit.d/ ]; then
	for PIDFILE in /tmp/sendsigs.omit.d/*; do
		[ -f "$PIDFILE" ] || continue
		for PID in $(cat $PIDFILE); do
            OMIT_PIDS="$OMIT_PIDS -o $PID"
		done
	done
fi

sync                            # reduce file io load during shutdown

# Kill all processes.
echo "$0: Sending all processes but $OMIT_PIDS the TERM signal..." | logger -s
killall5 -15 $OMIT_PIDS

# Now we loop for up to five seconds waiting until nobody's left.
# Only if we exit because five seconds have elapsed is there any need
# to send the KILLs.
END=$((5 + $(date -S)))
while :; do
    usleep 200000

    # Is there anybody left alive?  Exit if not.  The -l flag causes
    # killall5 to return a list of PIDs it sent a signal to (via
    # kill()) and that kill() says are alive.  When that list is
    # empty we can exit.
    PIDS=$(killall5 0 $OMIT_PIDS -l)
    if [ -z "$PIDS" ]; then     # no more processes remain
        echo "$0: All processes exited on TERM; no need for KILL signal." | logger -s
        break
    fi

    NOW=$(date -S)
    if [ $NOW -ge $END ]; then
        # If we got here, there are processes that didn't respond to
        # TERM within five seconds.  Send them a KILL.
        echo "$0: Sending all processes but $OMIT_PIDS the KILL signal..." | logger -s
        killall5 -9 $OMIT_PIDS
        break;
    fi
done

: exit 0
