Home
Add lawn-hark.sh script from pazz0. - gopher-lawn - The gopher lawn gopher directory project. HTML git clone git://bitreich.org/gopher-lawn/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/gopher-lawn/ DIR Log DIR Files DIR Refs DIR Tags --- DIR commit ee7a798530add04897221c9b89c3212a41836375 DIR parent 3c4d6c01eaac78599e65e5cc246ba8ed7f554765 HTML Author: Christoph Lohmann <20h@r-36.net> Date: Wed, 30 Aug 2023 21:03:27 +0200 Add lawn-hark.sh script from pazz0. Diffstat: A lawn-hark/lawn-hark.sh | 234 +++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+), 0 deletions(-) --- DIR diff --git a/lawn-hark/lawn-hark.sh b/lawn-hark/lawn-hark.sh @@ -0,0 +1,234 @@ +#!/bin/bash +# +# Originally written by pazz0. +# + +errorthreshold=3 +timeout=15 +onionsocksproxy="127.0.0.1:9050" + +function tcpdial() { + if [ -z "${1##*.onion}" ]; + then + nc -w "${timeout}" -X 5 -x "${onionsocksproxy}" "$1" "$2" \ + 2>/dev/null + else + nc -w "${timeout}" "$1" "$2" 2>/dev/null + fi +} + +function checkgopher() { + if [ "$#" -gt 3 ]; + then + data="$(printf "%s\t%s\r\n" "$3" "$4" \ + | tcpdial "$1" "$2" \ + | dd bs=128 count=1 2>/dev/null)" + else + data="$(printf "%s\r\n" "$3" \ + | tcpdial "$1" "$2" \ + | dd bs=128 count=1 2>/dev/null)" + fi + + if [ -z "${data}" ]; + then + printf "Can't connect, timeout or no content\n" + return 1 + fi + + if [ -z "${data##3?* *}" ]; + then + printf "Got type '3' on first line\n" + return 1 + fi + + if [ -z "${data##Error: File or directory not found!*}" ] \ + || [ -z "${data##Error: Access denied!*}" ]; + then + printf "Got Gophernicus error\n" + return 1 + fi + + return 0 +} + +function checkhttp() { + # max. one redirect (2) for http->https things + bc="$(curl -L --max-redirs 2 -m "${timeout}" -f "$1" 2>/dev/null \ + | dd bs=16 count=1 2>/dev/null \ + | wc -c \ + | xargs)" + if [ "${bc}" -eq 0 ]; + then + printf "Can't connect, timout, too many redirects or no content\n" + return 1 + fi + + return 0 +} + +function checkcso() { + bc="$(printf "status\r\n" \ + | tcpdial "$1" "$2" \ + | dd bs=16 count=1 2>/dev/null \ + | wc -c \ + | xargs)" + if [ "${bc}" -eq 0 ]; + then + printf "Can't connect, timeout or no content\n" + return 1 + fi + + return 0 +} + +function checkraw() { + bc="$(tcpdial "$1" "$2" \ + | dd bs=16 count=1 2>/dev/null \ + | wc -c \ + | xargs)" + if [ "${bc}" -eq 0 ]; + then + printf "Can't connect, timeout or no content\n" + return 1 + fi + + return 0 +} + +checktime="$(date +%s)" +statedir="$1" + +if [ -z "${statedir}" ]; +then + printf "You need to specify a state dir.\n" >&2 + exit 1 +fi + +mkdir -p "${statedir}" +if [ ! -d "${statedir}" ]; +then + printf "%s is not a directory! Aborting.\n" "${statedir}" >&2 + exit 1 +fi + +shift + +for f; +do + type="" + selector="" + host="" + port="" + + while read -r line; + do + value="$(printf '%s\n' "${line}" \ + | cut -f 2- -d ':' \ + | sed -n 's/^[[:space:]]*\(.*\)$/\1/p')" + case "${line}" in + Type:* ) + type="${value}" + ;; + Selector:* ) + selector="${value}" + ;; + Host:* ) + host="${value}" + ;; + Port:* ) + port="${value}" + ;; + esac + done < "$f" + + if [ -z "${type}" ] \ + || [ -z "${host}" ] \ + || [ -z "${port}" ]; + then + printf "ERROR\t%s\tInvalid entry!\n" "${f}" >&2 + continue + fi + + #printf "DEBUG\t%s\tchecking\t%s\t%s\t%s\t%s\n" "${f}" "${type}" "${selector}" "${host}" "${port}" + + case "${type}" in + cso ) + error="$(checkcso "${host}" "${port}")" + ;; + telnet ) + error="$(checkraw "${host}" "${port}")" + ;; + error ) + error="Type = 'error'" + ;; + link ) + if [ -n "${selector}" ] && [ -z "${selector##URL:*}" ]; + then + url="${selector##URL:}" + case "${url}" in + http://* | https://* ) + error="$(checkhttp "${url}")" + ;; + ssh://* ) + sshhost="${url##ssh://}" + sshhost="${sshhost##*@}" + sshhost="${sshhost%%/*}" + sshport="22" + if [ -z "${sshhost##*:*}" ]; + then + sshport="${sshhost##*:}" + sshhost="${sshhost%%:*}" + fi + error="$(checkraw "${sshhost}" "${sshport}")" + ;; + * ) + printf "TODO\t%s\tCan't handle %s\n" "${f}" "${url}" + continue + ;; + esac + else + error="$(checkgopher "${host}" "${port}" "${selector}")" + fi + ;; + search ) + error="$(checkgopher "${host}" "${port}" "${selector}" "")" + ;; + text | uuencoded | * ) + error="$(checkgopher "${host}" "${port}" "${selector}")" + ;; + esac + + lastcheck="" + errorcount=0 + statefile="${statedir}/$(basename "$f")" + if [ -f "${statefile}" ]; + then + IFS=" " read -r lastcheck errorcount < "${statefile}" + fi + + if [ -n "${error}" ]; + then + errorcount=$((errorcount + 1)) + else + errorcount=0 + fi + + if [ ${errorcount} -ge ${errorthreshold} ]; + then + printf "ERROR\t%s\t%s\n" "${f}" "${error}" >&2 + fi + + printf "%s\t%s\n" "${checktime}" "${errorcount}" > "${statefile}" +done + +# garbage collection +find "${statedir}" -type f | while read -r f; +do + IFS=" " read -r lastcheck errorcount < "${f}" + + if [ ${lastcheck} -ne ${checktime} ]; + then + rm -f "${f}" + fi +done +