summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbin/ircsink182
1 files changed, 182 insertions, 0 deletions
diff --git a/bin/ircsink b/bin/ircsink
new file mode 100755
index 0000000..a86c183
--- /dev/null
+++ b/bin/ircsink
@@ -0,0 +1,182 @@
+#! /bin/sh
+#
+# ircsink - send stdin to IRC
+#
+# SYNOPSIS
+# ircsink [--nick=NICK] [--port=PORT] [--secure]
+# --server=SERVER --target=TARGET
+#
+# ircsink --help
+#
+# DESCRIPTION
+# ircsink sends lines from standard input to the specified IRC target.
+#
+# --help
+#
+# --nick=NICK (default: the system's host name)
+#
+# --port=PORT (default: 6667, or 6697 if --secure is specified)
+#
+# --secure
+# If specified, then the connection will be made using openssl.
+# Otherwise netcat will be used.
+#
+# --server=SERVER
+#
+# --target=TARGET
+# The target for receiving PRIVMSGs.
+# Can be either a channel's or a user's name.
+#
+
+set -efu
+
+main() {(
+
+ exec 3<&0
+
+ _args=$(getopt -n "$0" -s sh \
+ -l help,nick:,port:,secure,server:,target: \
+ -- "$0" "$@")
+ eval set -- "$_args"
+ unset _args
+
+ help=
+ nick=
+ port=
+ secure=
+ server=
+ target=
+ while :; do
+ case $1 in
+ --help) help=1; shift;;
+ --nick) nick=$2; shift 2;;
+ --port) port=$2; shift 2;;
+ --secure) secure=1; shift;;
+ --server) server=$2; shift 2;;
+ --target) target=$2; shift 2;;
+ --) shift; break;;
+ esac
+ done
+ case $# in
+ 0) :;;
+ 1) echo "$0: bad argument: $*" >&2; exit 1;;
+ *) echo "$0: bad arguments: $*" >&2; exit 1;;
+ esac
+
+ if test "$help" = 1; then
+ print_help
+ exit
+ fi
+
+ if test -t 3; then
+ echo "$0: error: ircsink cannot be used interactively" >&2
+ exit 1
+ fi
+
+ if test -z "$nick"; then
+ nick=$(hostname)
+ fi
+
+ if test -z "$port"; then
+ case $secure in
+ '') port=6667;;
+ 1) port=6697;;
+ *)
+ echo "$0: missing argument: --port" >&2
+ exit 1
+ ;;
+ esac
+ fi
+
+ if test -z "$server"; then
+ echo "$0: missing argument: --server" >&2
+ exit 1
+ fi
+
+ if test -z "$target"; then
+ echo "$0: missing argument: --target" >&2
+ exit 1
+ fi
+
+ is_channel() {
+ case $1 in
+ \#*) :;;
+ *) ! :;;
+ esac
+ }
+
+ # echo2 and cat2 are used output to both, stdout and stderr
+ # This is used to see what we send to the irc server. (debug output)
+ echo2() { echo "$*"; echo "$*" >&2; }
+ cat2() {
+ awk '{
+ print $0
+ print $0 > "/dev/stderr"
+ }'
+ }
+
+ # privmsg_cat transforms stdin to a privmsg
+ privmsg_cat() {
+ awk -v target="$target" '{ print "PRIVMSG "target" :"$0 }'
+ }
+
+ ircat() {
+ if test "$secure" = 1; then
+ openssl s_client -connect "$server:$port"
+ else
+ nc "$server" "$port"
+ fi
+ }
+
+ # ircin is used to feed the output of netcat back to the "irc client"
+ # so we can implement expect-like behavior with sed^_^
+ # XXX mkselfdestructingtmpfifo would be nice instead of this cruft
+ tmpdir=$(mktemp --tmpdir -d ircsink_XXXXXXXX)
+ cd "$tmpdir"
+ mkfifo ircin
+ trap cleanup EXIT
+ cleanup() {
+ trap - EXIT
+ rm ircin
+ cd "$OLDPWD"
+ rmdir "$tmpdir"
+ }
+
+ {
+ echo2 "USER $LOGNAME 0 * :$LOGNAME@$(hostname)"
+ echo2 "NICK $nick"
+
+ awk 'match($0, /PING(.*)/, m) {print "PONG", m[1]; exit}'
+
+ # wait for MODE message
+ sed -n '/^:[^ ]* MODE /q'
+
+ if is_channel "$target"; then
+ echo2 "JOIN $target"
+ fi
+
+ privmsg_cat <&3 \
+ | cat2
+
+ if is_channel "$target"; then
+ echo2 "PART $target"
+
+ # wait for PART confirmation
+ sed -n '/:'"$nick"'![^ ]* PART /q'
+ fi
+
+ echo2 'QUIT :Gone to have lunch'
+ } < ircin \
+ | ircat | tee -a ircin
+)}
+
+print_help() {
+ sed -nr '
+ 0,/^$/{
+ /^#!/d
+ s/^#($| )//p
+ }
+ ' "$0"
+}
+
+main "$@"