#!/bin/sh
#
# Copyright (c) 2001 Michal Moskal <malekith@pld.org.pl>.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
#    must display the following acknowledgement:
#	This product includes software developed by Michal Moskal.
# 4. Neither the name of the author nor the names of any co-contributors
#    may be used to endorse or promote products derived from this software
#    without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY MICHAL MOSKAL AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $Id: shirc,v 1.6 2002/05/23 17:19:42 dzimi Exp $
#

default_server=irc.pld.org.pl
default_nick=inst-$$
default_port=6667
port=$default_port
fifo=/tmp/shirc.$$
chan="#PLDHelp"

# pids to kill
killme=

cleanup () {
  # this is cruel... however i see no better way with ash...
  ps x | grep shirc | while read pid rest ; do 
    if [ $pid -ne $$ ] ; then
      kill $pid 2> /dev/null
    fi
  done
  rm -f $fifo.in $fifo.out
  exit
}

trap cleanup 2
trap cleanup 0

# start input and output process
start_inout() {
  mknod $fifo.in p || exit 1
  mknod $fifo.out p || exit 1
  
  ( 
    while : ; do
      read x < /dev/tty
      echo "U$x" >> $fifo.in
    done
  ) &
  killme="$killme $!"
  
  ( while : ; do
      cat $fifo.out
    done ) | nc $IRCSERVER $port | (
    while read x ; do
      echo "S$x" >> $fifo.in
    done
    echo "SDEAD" >> $fifo.in
  ) &
  killme="$killme $!"
}

# send given words, using irc's :last arg convention
send() {
  local x
  x=$( id=1
  while [ $id -lt $# ] ; do
    eval echo -n \$$id
    echo -n " "
    id=$(($id+1))
  done
  eval echo :\$$id ) 
  echo $x >> $fifo.out
}

cat <<EOF

Welcome to shIRC. This is _very_ simple IRC client, that is supposed
to be just a little helper, and a way to ask a question during 
PLD Linux installation process. This also means that this simple
script ain't particullary rfc-compilant, esp. it require server to
speak uppercase (most server do anyway).

Everything wthout a '/' in front is sent to $chan.

Commands:
/msg nick|#chan msg...
/quit
/bye == Ctrl-C == /quit
/m == /msg
/sh command... - send command along with it's output to channel

EOF

echo 'Version: $Id: shirc,v 1.6 2002/05/23 17:19:42 dzimi Exp $'
echo

test "$IRCSERVER" || {
  echo -n "Enter IRC server [$default_server]: "
  read IRCSERVER
  test "$IRCSERVER" || IRCSERVER=$default_server
}

test "$IRCNICK" || {
  echo -n "Enter nick [$default_nick]: "
  read IRCNICK
  test "$IRCNICK" || IRCNICK=$default_nick
}

echo

start_inout

send USER plduser pldmachine server "I'm trying to install PLD, HELP!"
send NICK $IRCNICK
send JOIN $chan

# say sth to $chan
say () {
  echo "<$IRCNICK/$chan> $*"
  send PRIVMSG $chan "$*"
}

# parse server response
parse () {
  x=$1
  cmd=`echo $x | sed -e 's/^S:[^ ]* */S/' | sed -e 's/^S\([a-zA-Z0-9_-]*\).*/\1/'`
  case $cmd in
    [0-9][0-9][0-9] )
      txt=`echo $x | sed -e 's/^S:[^ ]* *\([0-9][0-9][0-9]\) [^ ]* :\?\(.*\)/\2/'`
      echo "$cmd $txt"
      ;;
    PRIVMSG )
      from=`echo $x | sed -e 's/S:\?//' | sed -e 's/[ !].*//'`
      to=`echo $x | sed -e 's/.*PRIVMSG *\([^ ]*\).*/\1/'`
      txt=`echo $x | sed -e 's/.*PRIVMSG *\([^ ]*\) *:\?\(.*\)/\2/'`
      case $to in
        \#* )
	  echo "<$from/$to> $txt"
	  ;;
	* )
	  echo "[msg <- $from] $txt"
	  ;;
      esac
      ;;
    * )
      echo $x | sed -e 's/^S//'
      ;;
  esac
}

while : ; do
  while read x ; do
    case $x in
      SDEAD )
        echo "*** Server died."
        ;;
      SPING* )
        send PONG `echo $x | sed -e 's/SPING//'`
        echo "*** Ping/Pong"
        ;;
      S* )
        parse "$x"
        ;;
      U/qui* | U/bye* )
        cleanup
        ;;
      U/sh\ * )
        cmd=`echo $x | sed -e 's|U/sh *||'`
	say "sh -c '$cmd' ->"
	sh -c "$cmd" | while read line ; do
	  say "% $line"
	done
        ;;
      U/m\ * | U/msg\ * )
        targ=`echo $x | sed -e 's/[^ ]* *\([^ ]*\) *\(.*\)/\1/'`
        msg="`echo $x | sed -e 's/[^ ]* *\([^ ]*\) *\(.*\)/\2/'`"
        send PRIVMSG $targ "$msg" 
        echo "(msg -> $targ) $msg"
        ;;
      U/nick\ * )
        newnick=`echo $x | sed -e 's|U/nick *||'`
	IRCNICK=$newnick
	send NICK $newnick
	;;
      U/* )
        echo $x | sed -e 's|^U/||' > $fifo.out
        ;;
      U* )
        x=$(echo $x | sed -e s/^U//)
        say "$x"
        ;;
    esac
  done < $fifo.in
done
