#! /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 "$@"