#!/bin/sh

VERSION='@version@'
PREFIX=@prefix@
if [ -z "$SHIRC_CONF" ]; then SHIRC_CONF="$PREFIX/etc/shirc.conf"; fi
# source systemwide config
if [ -r "$SHIRC_CONF" ]; then . $SHIRC_CONF; fi
# source user local config
if [ -r "${HOME}/.shircrc" ]; then . ${HOME}/.shircrc; fi
if [ -z "$SHIRC_CHDIR" ]; then SHIRC_CHDIR=/tmp/shirc; fi

if [ -z "$2" ]; then
	echo "- shirc-link version $VERSION -"
	echo "Usage: "`basename $0`" [<user>@]<host> <channel>"
	exit 1
fi

LHOST=`hostname | cut -d. -f1`
RHOSTSSH="$1"
CHANNEL="$2"
RHOST=`echo "${RHOSTSSH}" | cut -d@ -f2`
if [ -z "$RHOST" ]; then
	RHOST=${RHOSTSSH}
fi
umask 000

if [ "$3" = "local" ]; then
	MODE=local
	# This is not always readable info...
	# We need a way to prevent endless loops, so IP address
	# might be a good solution, but..
	RADDR=`echo $SSH_CLIENT | awk '{print $1}'`
else
	MODE=connect
fi

if [ "$4" = "debug" ]; then
	DEBUG=DEBUG
fi

trap 'cleanup' 1 5 2 3 9 13

cleanup()
{
	if [ -n "$CLEANINGUP" ]; then
		return
	fi
	CLEANINGUP="yes"
	opwd=$PWD; cd ${SHIRC_CHDIR}/${CHANNEL}.users
	for ruser in *@${RHOST}:*; do
		if [ "$ruser" = "*@${RHOST}:*" ]; then
			break
		fi
		name=`echo "$ruser" | cut -d: -f1`
		echo "*** ${name} left channel ${CHANNEL}" >&${CHANNELFD}
		rm $ruser
	done
	cd $opwd
	if [ "$MODE" = "connect" ]; then
		echo "**** link to ${RHOST} closed" >&$CHANNELFD
	else # MODE = "local"
		echo "**** link from ${RHOST} closed" >&$CHANNELFD
		kill $readpid
	fi
	rm -f ${SHIRC_CHDIR}/${CHANNEL}.links/${RHOST}
	exec 3>&-
	exit
}

handshake()
{
	echo "-link- opened"
	if [ -r ${SHIRC_CHDIR}/${CHANNEL}.topic ]; then
		echo "-link- topic: "`cat ${SHIRC_CHDIR}/${CHANNEL}.topic`
	fi
	ls ${SHIRC_CHDIR}/${CHANNEL}.users/ |
		cut -d: -f1 | sort -u |
		grep -v "@${RHOST}" |
		sed 's/^/-link- user in: /'
	if [ -n "$DEBUG" ]; then
		{
			echo "${LHOST} send: -link- opened"
			ls ${SHIRC_CHDIR}/${CHANNEL}.users/ |
				cut -d: -f1 | sort -u |
				grep -v "@${RHOST}" |
				sed "s/^/${LHOST} send: -link- user in: /"
		} >&2
	fi
}

parselink()
{
	while read line; do
		if [ -n "$DEBUG" ]; then
			echo "${LHOST} recv: $line" >&2
		fi
		user=`expr "$line" : '^<\([^>]*\)> *.*' 2> /dev/null`
		if [ -n "$user" ]; then
			phrase=`expr "$line" : '^<[^>]*> \(.*\)$' 2> /dev/null`
			echo "<${user}@${RHOST}> ${phrase}" >&$CHANNELFD
			continue
		fi

		user=`expr "$line" : '^\*\*\* \([^ ]*\) ' 2> /dev/null`
		message=`expr "$line" : '^\*\*\* [^ ]* \(.*\)$' 2> /dev/null`
		if [ -n "$user" ]; then
			echo "*** ${user}@${RHOST} $message" >&$CHANNELFD
			topic=`expr "$message" : '^changed the topic to .\(.*\).$' 2> /dev/null`
			if [ -n "$topic" ]; then
				echo "$topic" > ${SHIRC_CHDIR}/${CHANNEL}.topic
			fi
			continue
		fi

		linkmsg=`expr "$line" : '^-link- \(.*\)' 2> /dev/null`
		if [ "$linkmsg" = "opened" ]; then
			if [ "$MODE" = "local" ]; then
				echo "**** link from ${RHOST} opened by ${LOGNAME}" >&$CHANNELFD 
			else
				echo "**** link to ${RHOST} opened by ${LOGNAME}" >&$CHANNELFD 
			fi
			echo "$$" > ${SHIRC_CHDIR}/${CHANNEL}.links/${RHOST}
			continue
		fi
		ruser=`expr "$linkmsg" : 'user in: \(.*\)' 2> /dev/null`
		if [ -n "$ruser" ]; then
			touch "${SHIRC_CHDIR}/${CHANNEL}.users/${ruser}@${RHOST}:$$"
			echo "*** ${ruser}@${RHOST} joined channel ${CHANNEL}" >&$CHANNELFD
			continue
		fi
		ruser=`expr "$linkmsg" : 'user out: \(.*\)' 2> /dev/null`
		if [ -n "$ruser" ]; then
			rm "${SHIRC_CHDIR}/${CHANNEL}.users/${ruser}@${RHOST}:$$"
			echo "*** ${ruser}@${RHOST} left channel ${CHANNEL}" >&$CHANNELFD
			continue
		fi
		topic=`expr "$linkmsg" : 'topic: \(.*\)' 2> /dev/null`
		if [ -n "$topic" ]; then
			if [ $MODE = 'connect' ]; then
				echo "$topic" > ${SHIRC_CHDIR}/${CHANNEL}.topic
				echo "**** topic@${RHOST}: $topic" >&$CHANNELFD 
			fi
			continue
		fi
	done
}

parselog()
{
	tail -n0 -f ${SHIRC_CHDIR}/${CHANNEL}.log | {
	while read line; do

		if echo "$line" | grep -q "@${RHOST}"; then
			continue;
		fi

		if echo "$line" | grep -q "^\*\*\*\* "; then
			continue;
		fi

		userout=`expr "$line" : '^\*\*\* \([^ ]*\) left channel .*' 2> /dev/null`
		if [ -n "$userout" ]; then
			if [ -n "$DEBUG" ]; then
				echo "${LHOST} send: -link- user out: $userout" >&2
			fi
			echo "-link- user out: $userout"
			continue;
		fi
		userin=`expr "$line" : '^\*\*\* \([^ ]*\) joined channel .*' 2> /dev/null`
		if [ -n "$userin" ]; then
			if [ -n "$DEBUG" ]; then
				echo "${LHOST} send: -link- user in: $userin" >&2
			fi
			echo "-link- user in: $userin"
			continue;
		fi
		if [ -n "$DEBUG" ]; then
			echo "${LHOST} send: $line" >&2
		fi
		echo "$line"
	done 
	}
}

local()
{
	{
	 handshake
	 parselog 
	} &
	readpid=$!
	parselink
	cleanup
}

connect()
{
	{
	 handshake
	 parselog
	} |
	ssh ${RHOSTSSH} "shirc-link ${LHOST} \\${CHANNEL} local ${DEBUG}" |
	parselink
	cleanup
}


mkdir -p ${SHIRC_CHDIR}/${CHANNEL}.users
mkdir -p ${SHIRC_CHDIR}/${CHANNEL}.links
exec 3>>${SHIRC_CHDIR}/${CHANNEL}.log
CHANNELFD=3
if [ "$MODE" = "local" ]; then
	local
else
	connect
fi
