cred source

Home
#!/usr/bin/env bash
#
#	cred 1.0 (06-Sep-2022) - Copyright (C) 2016, 2022 Dario Niedermann
#
#	Check REmote Document, report if it changed since last check
#
#	$Id: cred.m4,v 1.11 2022-09-06 10:51:28+02 ndr Rel $

umask 077
myName="${0##*/}";      fNamePrefix="${myName}-"
myVerbosity=0;          wgetVerbosity='q'
myVersion=`sed -ne 3p "$0" | tr ' \t' "\n\n" | grep '^[0-9]' | head -n1`
myPlatform=`uname -sm`
wgetVersion=`wget -V | head -n1 | tr ' ' '\n' | head -n3 | tail -n1`
userAgent="cred/$myVersion ($myPlatform) Wget/$wgetVersion"
unset urls reportUnchanged chkConnection
pingServer="${PINGSERVER:-www.pingtest.net}"

if [ -e /dev/stderr -a -w /dev/stderr ]; then
	echoerr() { echo -e $myName: $@ >>/dev/stderr ; }
else
	echoerr() { echo -e $myName: $@ ; }
fi

debugMsg() { [ $myVerbosity -gt 1 ] && echoerr $@ ; }


mkHomeCredDir()
{
	echoerr "warning: creating 'cred/' in your home directory. See cred(1)"
	echoerr '         section ENVIRONMENT, on how to use a different dir.'
	mkdir ~/cred
	if [ $? -ne 0 ]; then
		echoerr 'could not create ~/cred -- giving up.'
		exit 73
	else
		cd ~/cred
	fi
}


pickSuitableWorkingDir()
{
	local d dirFound

	debugMsg "Picking a suitable working directory... "

	unset dirFound
	for d in "$CREDDIR" "$HOME/cred" "$TMPDIR" "$HOME/tmp" /tmp ; do
		if [ -d "$d" -a -w "$d" ]; then
			dirFound=1; cd "$d"
			[ -d cred -a -w cred ] && cd cred
			break
		fi
	done
	# no suitable directory found? make your own in ~
	[ -z "$dirFound" ] && mkHomeCredDir
	[ "${PWD##*/}" = cred ] && unset fNamePrefix
	debugMsg "'$PWD' will do"
}


findMailer()
{
	local rc mailPrgCandidate 

	debugMsg "Looking for a 'mail' program..."
	for mailPrgCandidate in /{,usr/{,local/}}bin/{m,M}ail{,x} ; do
		debugMsg "Looking for $mailPrgCandidate ..."
		mailPrg=`which $mailPrgCandidate`
		rc=$? ; [ $rc -eq 0 ] && break
	done
	if [ $rc -ne 0 ]; then
		echoerr 'The "mail" program was not found.' \
		        'Will report to stdout.'
	fi
	debugMsg "Found $mailPrg"

	export MAILRC=/dev/null
	export LC_ALL=en_US.utf8 # just so mailx won't complain of multibyte
	                         # chars. Making the locale configurable
	                         # might be a good idea, though
	mailOpts="-n -S 'sendcharsets=iso-8859-1,utf-8,utf-16' \
	          -r ${myName}@localhost"
	return $rc
}


sendMail()
{
	if ! findMailer ; then return 1 ; fi

	if [ $diffExit -gt 0 ]; then
		echo "See: <${url}>"  | $mailPrg $mailOpts      \
		-s "Changes at $remoteHostName !"  "$USER"
	else
		if [ -n "$reportUnchanged" ]; then
			echo "Unchanged: <${url}>" | $mailPrg $mailOpts \
			-s "No changes at $remoteHostName"  "$USER"
		fi
	fi
}


reportToStdout()
{
	if [ $diffExit -ne 0 ]; then
		echo "$myName: '$url' has changed"
	else
		[ -n "$reportUnchanged" ] && echo "$myName: '$url' is unchanged"
	fi
}


sendMailOrReportToStdout()
{
	local mailRc

	[ -z "$noMail" ] && sendMail
	mailRc=$?
	[ -n "$noMail" -o $mailRc -ne 0 ] && reportToStdout
}


checkRequirements()
{
	local p found

	for p in wget openssl ping ; do
		which $p > /dev/null 2>&1 ; found=$?
		exitmsg="essential program '$p' not found -- exiting"
		contmsg="program '$p' not found -- disabling connection check"
		if [ $found -ne 0 ]; then	# program not found
			case $p in
				wget|openssl) echoerr "$exitmsg"; exit 69 ;;
				ping)         [ -n "$chkConnection" ] && \
				                  echoerr "$contmsg"
				              unset chkConnection ;;
			esac
		fi
	done
}


checkConnection()
{
	[ -z "$chkConnection" ] && return 0     # check unwanted, skip it
	# else...
	ping -q -c1 $pingServer > /dev/null  2>&1
	[ $? -ne 0 ] && exit 0    # no connection? exit without errors
}


showLicenseOrVersion()
{
	sed -n -e '3p' "$0" |sed -e 's/^#[[:blank:]]\+//'
	if [ "$1" = '-L' -o "${1:0:-2}" = '--licen' ]; then
		echo
		sed -n -e '/^-----$/,$p' "$0" |sed -e 1d
	fi
}


showHelp()
{
	sed -n -e '/^Usage/,/^-----$/p' "$0" \
	| sed -e "s/PROGNAME/$myName/;2d;"'$d'
}


showUsageAndExit()
{
	[ -n "$1" ] && echoerr "$1"	# print optional passed-in msg
	grep -A1 '^Usage' "$0" |sed -e "s,PROGNAME,$myName,"
	exit 64
}


incrementVerbosity()
{
	myVerbosity=$((++myVerbosity))
	wgetVerbosity=v
	[ $myVerbosity -gt 1 ] && wgetVerbosity=d	# >1 = debug cred & wget
}


warnDeprecated()
{
  echoerr 'warning: the -c option is deprecated and ignored in this version'
  echoerr 'warning: it will be removed in the future -- update your usage!'
}


mkFileNameFromUrl()
{
	local temp suffix

	unset fileName; temp="${url#*://}"	# remove initial scheme://
	remoteHostName="${temp%%/*}"		# remove from 1st / to end

	# a file name suffix is made from the URL's hash. This is to prevent
	# 'a.com/index.html' and 'b.com/index.html' from ending up written
	# to the same file
	suffix=`echo -n "$url"| openssl dgst -md5|tr ' '  '\n'  \
	        | tail -n1 | fold -w4 | head -n1`
	fileName="${fNamePrefix}${remoteHostName}-$suffix"
}


checkForChangesAndReport()
{
	if [ -e "$fileName" ]; then
		mv "$fileName" "$fileName~"
		mv "$fileName~~" "$fileName"

		diff -q "$fileName" "$fileName~" > /dev/null 2>&1
		diffExit=$?
		sendMailOrReportToStdout
	else                                     # 1st download
		mv "$fileName~~" "$fileName"
		[ -n "$reportUnchanged" ] && \
			echo "'$url' not previously checked"
	fi
}

#--------------------------------------------------------------------------- CLI
[ $# -lt 1 ] && showUsageAndExit 'no arguments'
# else...
temp=$(getopt -n "$myName" -o chnsvLNV -l comment,help,licence,license,nomail,report-unchanged,verbose,only-if-connected,version -- "$@")

[ $? -ne 0 ] && showUsageAndExit

debugMsg 'Reading command line options...'
eval set -- "$temp"
debugMsg "Got command line options: $temp"

while true; do
	debugMsg "Examining argument '$1'"
	case "$1" in
		-c|--comment)            warnDeprecated;            shift   ;;
		-v|--verbose)            incrementVerbosity;        shift   ;;
		-s|--report-unchanged)   reportUnchanged=y;         shift   ;;
		-n|--nomail)             noMail=y;                  shift   ;;
		-N|--only-if-connected)  chkConnection=y;           shift   ;;
		-h|--help)               showHelp;                  exit    ;;
		-L|-V|--licence|--license|--version)
		                         showLicenseOrVersion $1;   exit    ;;
		--)                                          shift; break   ;;
		*)                       echoerr 'Internal error!'; exit 70 ;;
	esac
done
[ $# -eq 0 ] && showUsageAndExit 'no URL specified'
#---------------------------------------------------------------------------/CLI

urls="$@";  debugMsg "URL(s) wanted: $urls"

checkRequirements
checkConnection
pickSuitableWorkingDir

for url in $urls ; do
	mkFileNameFromUrl
	wget  -"$wgetVerbosity"  -U "$userAgent"  -O "${fileName}~~"  "$url"
	wgetErr=$?
	if [ $wgetErr -eq 0 ]; then
		checkForChangesAndReport
	else
		echoerr "wget returned error $wgetErr on '$url'"
	fi
done
exit 0
Usage: PROGNAME [OPTION]... URL...
Try `PROGNAME --help' for more information.
Check document at URL, report if it has changed since last check

  -v, --verbose             output messages detailing program operation;
                            specify twice for extra verbosity
  -n, --nomail              do not send email; report results to STDOUT
  -s, --report-unchanged    also report when file at URL did not change
  -N, --only-if-connected   if no net connection, exit without errors
  -V, --version             display program version
  -L, --licence, --license  display program version and licence
  -h, --help                display this help and exit

Report bugs to:  Dario Niedermann  <dario@darioniedermann.it>
cred home page: <https://www.darioniedermann.it/sw/cred.html>
-----
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
“Cred” is Copyright © Dario Niedermann — Released with no warranty under the terms of the GPLv3 license. Written and tested on Linux using GNU tools.
HomeNo Javascript iconValid HTML 4.01 StrictValid CSS!