123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #!/bin/bash
  2. usage() {
  3. local self=$(basename "$0")
  4. echo "usage: $self [options] message" >&2
  5. echo "usage: $self [options] -f message_file|-" >&2
  6. echo "options: [-h host] [-p port] [-n nick] [-c context] [-u user]" >&2
  7. exit 2
  8. }
  9. mkcommands() {
  10. local user="$1"
  11. local nick="$2"
  12. local message
  13. echo "NICK $nick"
  14. echo "USER $nick 8 * :notifirc bot"
  15. while read message;
  16. do
  17. echo "PRIVMSG $user :$message"
  18. done
  19. echo "QUIT"
  20. }
  21. mknick() {
  22. case "$context" in
  23. "") echo "$nick" ;;
  24. *) echo "$nick|$context" ;;
  25. esac
  26. }
  27. die() {
  28. local msg="fatal: $1"
  29. log "$msg"
  30. log "-----END *-----"
  31. echo "$msg" >&2
  32. exit 3
  33. }
  34. warn() {
  35. local msg="warning: $1"
  36. echo "$msg" >&2
  37. log "$msg"
  38. }
  39. log_pipe() {
  40. local line
  41. while IFS= read line;
  42. do
  43. log "$line"
  44. done
  45. }
  46. log() {
  47. echo "$1" >>"$logfile"
  48. }
  49. load_defaults() {
  50. local rcfile=$1
  51. test -e "$rcfile" || return 0
  52. test -f "$rcfile" || {
  53. warn "defaults file is not a file: $rcfile"
  54. return 3
  55. }
  56. test -r "$rcfile" || {
  57. warn "defaults file not readable: $rcfile"
  58. return 3
  59. }
  60. bash -n "$rcfile" || {
  61. warn "syntax error in defaults file: $rcfile"
  62. return 3
  63. }
  64. . "$rcfile" || {
  65. warn "error in defaults file: $rcfile"
  66. return 3
  67. }
  68. }
  69. read_file() {
  70. local fpath=$1
  71. local limit_l=3
  72. local limit_c=80
  73. local lines_read=0
  74. local suff=""
  75. grep . "$fpath" \
  76. | while true;
  77. do
  78. test $lines_read -ge $limit_l && break
  79. IFS= read line || break
  80. (( lines_read++ ))
  81. test ${#line} -gt $limit_c && suff=…
  82. line=${line:0:$limit_c}$suff
  83. log "read from $fpath: $line"
  84. echo "$line"
  85. done
  86. }
  87. choose_logfile() {
  88. local path
  89. {
  90. echo /var/log/notifirc.log
  91. echo "$HOME/.notifirc.log"
  92. echo /tmp/notifirc.log
  93. } \
  94. | while read path;
  95. do
  96. if test -w "$(dirname "$path")" \
  97. || test -w "$path";
  98. then
  99. echo "$path"
  100. break
  101. fi
  102. done
  103. }
  104. main() {
  105. local context nick host port user message logfile msgfile
  106. logfile=$(choose_logfile)
  107. test -n "$logfile" || {
  108. echo "could not find writable logfile location" >&2
  109. echo "logging will be off!" >&2
  110. logfile=/dev/null
  111. }
  112. load_defaults /etc/notifirc.rc
  113. load_defaults "$HOME/.notifirc.rc"
  114. while true; do case $1 in
  115. -c) context=$2; shift 2 || usage ;;
  116. -f) msgfile=$2; shift 2 || usage ;;
  117. -h) host=$2; shift 2 || usage ;;
  118. -n) nick=$2; shift 2 || usage ;;
  119. -p) port=$2; shift 2 || usage ;;
  120. -u) user=$2; shift 2 || usage ;;
  121. --) shift; break ;;
  122. -*) usage ;;
  123. *) break ;;
  124. esac done
  125. message="$*"
  126. test -n "$host" || usage
  127. test -n "$port" || usage
  128. test -n "$user" || usage
  129. test -n "$nick" || nick="notifirc"
  130. test -z "$message$msgfile" && usage
  131. log "-----BEGIN sending notification-----"
  132. log "host='$host'"
  133. log "port='$port'"
  134. log "nick='$nick'"
  135. log "context='$context'"
  136. log "user='$user'"
  137. log "msgfile='$msgfile'"
  138. log "message='$message'"
  139. {
  140. test -n "$message" && printf '%s\n' "$message"
  141. test -n "$msgfile" && read_file "$msgfile"
  142. } \
  143. | mkcommands "$user" "$(mknick)" \
  144. | nc "$host" "$port" 2>&1 \
  145. | log_pipe
  146. log "-----END sending notification-----"
  147. }
  148. main "$@"