: ########################################################################## # Shellscript: checklinks - check symbolic links # Version : 0.2 (beta) # Author : Heiner Steven (stv) # Date : 10.11.95 # SCCS-Id. : @(#) checklinks 1.1 04/02/18 ########################################################################## # Description # ########################################################################## PN=`basename "$0"` # program name VER='0.2 (beta)' # Mail should be a mail program knowing how to set the mail subject Mail=mail [ -x /bin/mailx ] && Mail=/bin/mailx Links="${TMPDIR:=/tmp}/cl.lnk.$$" # File for symbolic links InvLinks="$TMPDIR/cl.inv.$$" # File for invalid links Mails="$TMPDIR/cl.$$" # Base name for mail text Usage () { echo >&2 "$PN - check symbolic links, $VER (stv '98) Usage: $PN [-hm] [-f linkfile] [-r user] [entry ...] -f: file containing names of symbolik links -h: print this help -m: send mail to the creators of invalid symbolical links -r: mail to pseudo-users is sent to this user (default is $LOGNAME) All symbolic links starting with link or directory 'entry' are followed. If the target does not exist, the link and the (non-existant) target are printed. The \"-r\" option may only be used with the \"-m\" option." exit 1 } Msg () { for i do echo "$PN: $i" >&2 done } Fatal () { Msg "$@"; exit 1; } AbsPath () { D=`dirname $1` N=`basename $1` (cd $D; echo "`pwd`/$N") } Admin= SendMail=no LinkFile= set -- `getopt hf:mr: "$@"` || Usage while [ $# -gt 0 ] do case "$1" in -f) LinkFile="$2"; shift;; -m) SendMail=yes;; -r) Admin="$2"; shift;; --) shift; break;; -h) Usage;; -*) Usage;; *) break;; # First entry esac shift done [ -n "$Admin" -a $SendMail = no ] && Fatal "the \"-r\" option needs the \"-m\" option" : ${Admin:=$LOGNAME} # Set default Hostname=`uname -n` trap 'rm -f "$Links" "$InvLinks" "$Mails."* > /dev/null 2>&1' 0 trap "exit 2" 1 2 3 15 # Create file $Links with the names of symbolic links if [ -n "$LinkFile" ] then [ $# -gt 0 ] && Fatal "no arguments allowed with -f option" [ -f "$LinkFile" -a -r "$LinkFile" ] || Fatal "cannot read $LinkFile" cp "$LinkFile" "$Links" || exit else # Create file with links [ $# -lt 1 ] && set -- `pwd` # No arguments: set default Msg "Creating list of symbolic links starting with $*..." find "$@" -type l -print > $Links || exit fi [ -s "$Links" ] || exit 0 set -u if [ $SendMail = yes ] then # We will need to postprocess the list of invalid links. # Save it to a file: exec 3>&1 > "$InvLinks" fi Msg "Checking links..." while read Link do [ -h "$Link" ] || { Msg "no symbolic link: $Link"; continue; } Ref=`ls -ld "$Link" 2>/dev/null | awk '{print $NF}'` [ -n "$Ref" ] || # Should never occur! { Msg "cannot determine target for link $Link"; continue; } case "$Ref" in /*) ;; # Absolute path name *) Ref="`dirname "$Link"`/$Ref";; esac Target=`ls -ld "$Ref" 2>/dev/null` [ -z "$Target" ] && echo "$Link $Ref" done < $Links if [ $SendMail = yes ] then # Restore old stdout exec 1>&3 3>&- OldIFS="$IFS" IFS=" " export IFS users=" " # need leading space exec 3<&0 0< "$InvLinks" while read link ref do user=`ls -ld "$link" | awk '{print $3}'` [ -z "$user" ] && continue # should not occur! # Don't send mail to pseudo-users case "$user" in root|bin|nobody|daemon|uucp) user=$Admin;; esac echo "$link $ref" >> $Mails.$user case "$users" in *" $user "*) ;; *) users="${users}$user ";; esac done exec 0<&3 3<&- IFS="$OldIFS" export IFS for user in $users do echo " Hello $user, The following symbolical links created by you (or an installation program running with your login id) do not point to a valid target. Please check the links, and remove invalid ones. The links were checked `date` on host \"$Hostname\" starting with directory/directories "$@" The following list consists of two columns: the location of the symbolical link, and the (invalid) target the link points to. ________________________________________ " | cat - $Mails.$user | $Mail -s "Invalid symbolical links" $user $Admin done fi