an IRC client in 40 lines of shell script

Kragen Javier Sitaker kragen at pobox.com
Mon Feb 18 22:08:19 EST 2008


So I'm installing an OS on my laptop, and for whatever reason, the
Debian Etch install disk thought it would be a good idea to initialize
the whole disk to random data *before* rather than *after* the rest of
the install.  Writing to the whole disk takes a long time --- a few hours ---
and so I'm left with the Debian netinst environment to play with.

So I decided to IRC.  Unfortunately, the only programming language I could
find is sh, and there don't seem to be any IRC clients.  And I can't get
the ssh client to work --- I was able to install the ssh client from the
udeb on the CD-ROM with udpkg -i path/to/openssl-client-whatever.udeb.  But
it depends on libnsl.so.1, and I don't know what udeb I have to install to
get that.

So I wrote my own IRC client in shell.  The output is a little ugly, and
there's no line editing or multiple window support, but otherwise it's just
like any other IRC client to use.  Almost.

#!/bin/sh
# In the grim future of the Debian netinst disk, there is only nc.
# And dd and sh, of course.
: ${2?"Usage: $0 ircserver nickname"}
ircserver="$1"
nickname="$2"
grimdir="`dirname "$0"`"
case "$grimdir" in /*) ;; *) grimdir="../$grimdir" ;; esac

tmpdir=".tmp.grimirc.$$"
mkdir "$tmpdir"
cd "$tmpdir"
trap 'cd ..; rm -rf "$tmpdir"' 0

(echo user grimirc hostname "$ircserver" :grimirc user
echo nick "$nickname"
> grimirc-responses
tail -f grimirc-responses &
while read command
	do case "$command" in
	/join*) echo "joining">/dev/tty
		set $command; currentchan="$2"
		echo "$command" > .grimtmp
		dd bs=1 skip=1 < .grimtmp 2>/dev/null;;
	/*) echo "$command" > .grimtmp
		 dd bs=1 skip=1 < .grimtmp 2>/dev/null;;
	*) echo "PRIVMSG $currentchan :$command"
	esac
done) | "$grimdir/grimdebuglog" | nc "$ircserver" 6667 | while read response
	do echo "$response"
	case "$response" in
	"PING "*) echo "responding to ping"
		set $response
		shift
		echo "PONG $*" >> grimirc-responses
	esac
done

This depends on this little script, "grimdebuglog":
#!/bin/sh
# "grimdebuglog": Helper for grimirc.

while read line
	do echo "debug: $line" >/dev/tty
	echo "$line"
done

I'm posting this mail with a similar program:
#!/bin/sh
# Wrapper around nc to support logging (incl. downloading) and file sending
tmp=".grimmodem7.$$.tmp"
logfile=".grimmodem7.$$.logfile"
trap 'rm -f "$tmp" "$logfile"' 0
while read line; do
	case "$line" in
	..*) echo "$line" > "$tmp"
		dd bs=1 skip=1 < "$tmp"
		rm -f "$tmp" ;;
	".send "*) set $line
		cat "$2"
		echo "sent $2" >/dev/tty ;;
	".log "*) set $line
		rm -f "$logfile"
		ln -s "$2" "$logfile"
		touch "$2"
		ls -l "$logfile" > /dev/tty ;;
	*) echo "$line" ;;
	esac
done | nc "$@" | while read line; do
	if [ -e "$logfile" ] ; then echo "$line" >> "$logfile"; fi
	echo "$line"
done

Hope it works!


More information about the Kragen-hacks mailing list