| 1 | #!/bin/bash |
| 2 | # Send an error message via the rsync-protocol to a non-daemon client rsync. |
| 3 | # |
| 4 | # Usage: deny-rsync "message" |
| 5 | |
| 6 | protocol_version=29 |
| 7 | exit_code=4 # same as a daemon that refuses an option |
| 8 | |
| 9 | # e.g. byte_escape 29 => \035 |
| 10 | function byte_escape { |
| 11 | echo -ne "\\0$(printf "%o" $1)" |
| 12 | } |
| 13 | |
| 14 | msg="$1" |
| 15 | if [ "${#msg}" -gt 254 ]; then |
| 16 | # truncate a message that is too long for this naive script to handle |
| 17 | msg="${msg:0:251}..." |
| 18 | fi |
| 19 | msglen=$(( ${#msg} + 1 )) # add 1 for the newline we append below |
| 20 | |
| 21 | # Send protocol version. All numbers are LSB-first 4-byte ints. |
| 22 | echo -ne "$(byte_escape $protocol_version)\\000\\000\\000" |
| 23 | |
| 24 | # Send a zero checksum seed. |
| 25 | echo -ne "\\000\\000\\000\\000" |
| 26 | |
| 27 | # The following is equivalent to rprintf(FERROR_XFER, "%s\n", $msg). |
| 28 | # 1. Message header: ((MPLEX_BASE + FERROR_XFER) << 24) + $msglen. |
| 29 | echo -ne "$(byte_escape $msglen)\\000\\000\\010" |
| 30 | # 2. The actual data. |
| 31 | echo -E "$msg" |
| 32 | |
| 33 | # Make sure the client gets our message, not a write failure. |
| 34 | sleep 1 |
| 35 | |
| 36 | exit $exit_code |