#!/bin/sh

#
# user_killall_too_many_connections
#
# (c) by SinusPL '2003, ver. 0.2
#
# URL: http://sinuspl.net/unix/user_killall_too_many_connections
#

#
# crontab:
#
# set up your crontab to
#
# user_killall_too_many_connections | grep -v -e OK -e Start
#
# and you will get all the kills mailed (if you are paranoid)
#

# irc config
# interesting IRC servers, space separated
IRCSERVERS="130.240.22.200 141.24.101.9 194.64.239.50 130.133.254.2 131.188.3.83 129.13.73.225 194.97.2.2 129.143.67.242 131.159.72.15 206.252.192.195 206.252.192.197"
# users with max 1 connection, comma separated
USERS_MAX1="ALL" # default, this variable is only a dummy
# users with max 2 connection, space separated
USERS_MAX2=""
# users with max 3 connection, space separated
USERS_MAX3=""
# users with max 4 connection, space separated
USERS_MAX4=""
# users with max 5 connection, space separated
USERS_MAX5=""
# vip users, unlimited, space separated
USERS_VIP="sinuspl"

# cmd and file config
HOME_DIR="/usr/home"
LSOF_CMD="/usr/local/sbin/lsof"
SKILL_CMD="/usr/local/bin/skill"
TEMPFOO=`basename $0`
TMPFILE=`mktemp /tmp/${TEMPFOO}.XXXXXX` # lsofin
PS="/bin/ps auxw"
BC="/usr/bin/bc"
KILLING_PID="/var/run/killing.pid"

###
### DONT'T TOUCH ANYTHING BELOW THIS
###

echo -n "==> Start at "; date

if [ -f $KILLING_PID ]; then
	echo "==> Warning, lockfile found!"
	if [ `$PS | grep -v "grep" | grep $TEMPFOO | wc -l` ]; then
		echo "==> There can only be one killing running, exiting..."
		exit 1
	else
		echo "==> Stale lockfile found, removing..."
		# delete PID and tempfile
		rm -rf $KILLING_PID $TMPFILE
	fi
#else
#	echo "No running killing, continuing...";
fi

# create PID
touch $KILLING_PID

# create connections
GREP_IP_STRING=`for IRC_IP in $IRCSERVERS; do echo -n "-e $IRC_IP "; done`

# user pid cmd family proto connection
$LSOF_CMD -i -n | grep ESTAB | awk '{ print $3 " " $2 " " $1 " " $5 " " $8 " " $9 }' | grep $GREP_IP_STRING | sort > $TMPFILE

cd $HOME_DIR
for USER in *
do
	if [ "$USER" = "quota.user" -o "$USER" = "quota.group" -o "$USER" = "lost+found" ]; then
		echo "==> Skipping other dir/file ($USER)" > /dev/null
	else
		USER_ID=`id -u $USER`
		IS_VIP="0"
		IS_VIP=`echo $USERS_VIP | grep -c $USER | $BC`
		echo -n "==> Processing user $USER($USER_ID): "
		# lowest match
		if [ `echo $USERS_MAX5 | grep $USER` ]; then
			echo -n "5 max, "
			MAX_CONN=5
		elif [ `echo $USERS_MAX4 | grep $USER` ]; then
			echo -n "4 max, "
			MAX_CONN=4
		elif [ `echo $USERS_MAX3 | grep $USER` ]; then
			echo -n "3 max, "
			MAX_CONN=3
		elif [ `echo $USERS_MAX2 | grep $USER` ]; then
			echo -n "2 max, "
			MAX_CONN=2
		else
			echo -n "1 max, "
			MAX_CONN=1 # default, don't change
		fi

		NUM_CONN=`cat $TMPFILE | grep -c $USER | $BC`
		echo -n "$NUM_CONN active, "
		if [ "$NUM_CONN" != "0" ]; then
			echo -n "more than 0, "
			if [ "$IS_VIP" != "0" ]; then
				echo -n "is VIP, OK"
			else
				# here we get the bad dude ;-)
				IS_OK=`echo "$NUM_CONN <= $MAX_CONN " | $BC`
				if [ "$IS_OK" != "1" ]; then
					echo -n "BAD DUDE, cleaning ;-)"
					$SKILL_CMD -9 -u $USER >/dev/null
				else
					echo -n "but OK"
				fi
			fi
		else
			echo -n "OK"
		fi
	echo
	fi
done

# delete PID and tempfile
rm -rf $KILLING_PID $TMPFILE

# exit gracefully like a gentelman
exit 0;
