#!/bin/sh # Simple irc-like chat system # All channels are logged (they are actually files) # Only one channel at the time can be joined *sorry* # VERSION='0.7' #--< config >--# PREFIX=@prefix@ if [ -z "$SHIRC_CONF" ]; then SHIRC_CONF="$PREFIX/etc/shirc.conf" fi # source systemwide config if [ -n "$SHIRC_CONF" ]; then . $SHIRC_CONF; fi # source user local config if [ -r "$HOME/.shircrc" ]; then . $HOME/.shircrc; fi if [ -z "$SHIRC_MODPATH" ]; then SHIRC_MODPATH=$PREFIX/lib/shirc:$HOME/.shirc/mod fi if [ -z "$SHIRC_CHDIR" ]; then SHIRC_CHDIR=/tmp/shirc; fi #--< init >--# umask 000 mkdir -p $SHIRC_CHDIR JOINNAME= JOINPID= JOINFILE= OFILTER= IFILTER= MODULES=$0 # the ``help'' command will grep in these prompt="> " trap 'CMD_quit' 1 5 2 3 9 #--< core commands >--# #HELP# /list [] - Get list of channels (containing in their name) CMD_list() { owd=$PWD; cd $SHIRC_CHDIR echo -e "Name\tOwner\tUsers\tTopic" for name in `ls *$1* 2> /dev/null | cut -d . -f 1 | sort -u`; do owner=`ls -l $name.log | awk '{print $3}'` users=`wc -l $name.users | awk '{print $1}'` topic=`cat $name.topic 2> /dev/null` echo -n "$name " echo -n "$owner " echo -n "$users " echo -n "$topic" echo done cd $owd } #HELP# /join - join or create channel CMD_join() { ch=$1 if [ -z "$ch" ]; then echo "Join which channel ?" return fi if [ -n "$JOINNAME" ]; then CMD_part fi JOINFILE="$SHIRC_CHDIR/$ch.log" JOINNAME=$ch touch $JOINFILE 2> /dev/null echo "$LOGNAME" >> $SHIRC_CHDIR/$ch.users # announce the join notify "$LOGNAME joined channel $ch" if [ -n "$OFILTER" ]; then tail -n 1 -f $JOINFILE | ( $OFILTER ) & else tail -n 1 -f $JOINFILE & fi JOINPID=$! prompt="$JOINNAME> " # run onjoin hook if [ -r "$HOME/.shirc/onjoin" ]; then CMD_source $HOME/.shirc/onjoin fi } #HELP# /part - leave current channel (a new join will do) CMD_part() { # stop listening on other channel if [ -n "$JOINNAME" ]; then kill $JOINPID cp $SHIRC_CHDIR/$JOINNAME.users /tmp/$$ grep -v "^$LOGNAME$" /tmp/$$ > $SHIRC_CHDIR/$JOINNAME.users rm -f /tmp/$$ # announce the departure notify "$LOGNAME left channel $ch" unset JOINNAME unset JOINPID unset JOINFILE prompt="> " fi } #HELP# - send to the currently joined channel CMD_say() { if [ -z "$JOINFILE" ]; then echo "You must first join a channel" return fi what=$* if [ -n "$IFILTER" ]; then echo "<$LOGNAME> $*" | $IFILTER >> $JOINFILE else echo "<$LOGNAME> $*" >> $JOINFILE fi } #HELP# /users [] - list users in or current channel CMD_users() { if [ -n "$1" ]; then ch=$1 elif [ -n "$JOINNAME" ]; then ch=$JOINNAME else echo "You must specify a channel name or join one" return fi if [ ! -r "$SHIRC_CHDIR/$ch.log" ]; then echo "Channel '$ch' does not exist (or file is not readable)" return fi owner=`ls -l $SHIRC_CHDIR/$ch.log | awk '{print $3}'` users=`cat "$SHIRC_CHDIR/$ch.users" 2> /dev/null` echo -n "Users on '$ch': " for u in $users; do if [ "$u" = "$owner" ]; then echo -n '@' fi echo -n "$u " done echo } #HELP# /channels - list joined channels (currently only one) CMD_channels() { if [ -n "$JOINNAME" ]; then echo "$JOINNAME" else echo "You are not joined to any channel" fi } #HELP# /load - load functions from CMD_load() { # Need an argument if [ -z "$1" ]; then echo "Load what ?" >&2 return fi file= for dir in `echo $SHIRC_MODPATH | tr ':' ' '`; do if [ -r $dir/$1 ]; then file=$dir/$1 break fi done if [ -z "$file" ]; then echo "Can't find $1 in $SHIRC_MODPATH" >&2 return fi if echo "$MODULES" | grep -q " $file" ; then echo "Module $1 already loaded" >&2 return fi # Error loading ? if ! . $file 2> /dev/null; then echo "Error loading $1" >&2 return fi MODULES="$MODULES $file" echo "Module '$file' loaded" >&2 } #HELP# /source - read commands from CMD_source() { if [ -z "$1" ]; then echo "Source what?" >&2 return; fi if [ ! -r "$1" ]; then echo "Can't find or read '$1'" return fi op=$prompt; prompt= parsestream < $1 prompt=$op } #HELP# /topic [] - get or set topic for current channel CMD_topic() { arg=$@ if [ -z "$JOINFILE" ]; then echo "You must first join a channel" return fi if [ -z "$arg" ]; then if ! cat $SHIRC_CHDIR/$JOINNAME.topic 2> /dev/null; then echo "No topic for $JOINNAME" fi else echo "$arg" > $SHIRC_CHDIR/$JOINNAME.topic notify "$LOGNAME changed the topic to '$arg'" fi } #HELP# /quit - exit safely CMD_quit() { if [ -n "$JOINNAME" ]; then CMD_part fi echo "Goodbye" exit } #HELP# /help - show this help CMD_help() { echo "shirc $VERSION" grep '^#HELP#' $MODULES | cut -d '#' -f 3- #echo "Core commands:" #grep '^#HELP#' $0 | cut -d '#' -f 3- #echo "User defined commands:" #grep '^#HELP#' $HOME/.shircrc 2>/dev/null | cut -d '#' -f 3- } #--< end of core commands >--# notify() { if [ -z "$JOINNAME" ]; then return fi echo "*** $@" >> $JOINFILE } parsestream() { echo -n "$prompt" >&2 while read line; do cmd=`expr "$line" : '^/\([^ ]*\) *.*' 2> /dev/null` args=`expr "$line" : '^/[^ ]* *\(.*\)' 2> /dev/null` if [ -n "$cmd" ]; then if grep "^CMD_$cmd" $MODULES >/dev/null 2>&1; then CMD_$cmd $args else echo "Unknown command: $cmd" fi elif [ -n "$line" ]; then CMD_say "$line" fi echo -n "$prompt" >&2 done } #--< main >--# # run onstart hook if [ -r $HOME/.shirc/onstart ]; then CMD_source $HOME/.shirc/onstart fi echo "Type /help for a list of available commands" parsestream CMD_quit