From 874ea21685828f2c993b442d7a64087daa8fb290 Mon Sep 17 00:00:00 2001 From: tv Date: Tue, 5 Oct 2021 22:37:51 +0200 Subject: ircsink: initial commit Mostly an import of irc-announce from stockholm 63b933c. --- bin/ircsink | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100755 bin/ircsink (limited to 'bin') 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 "$@" -- cgit v1.2.3