Cover V05, I10
Article
Listing 1
Listing 10
Listing 2
Listing 3
Listing 4
Listing 5
Listing 6
Listing 7
Listing 8
Listing 9

oct96.tar


Listing 9: fchange.sh

:
#######################################################
# fchange.sh: log and report changed files
# Copyright (C) 1996 Steve Isaacson
#######################################################
# fchange.sh - new and improved version.
# How to install.
# 1) mkdir $ctrldir and set the value below.
# 2) mkdir $ctrldir/logs
# 3) create $ctrldir/fchange.files
# 4) cp cdiff.sh $ctrldir
# 5) add an entry to your crontab

# make sure this is being run by a posix compliant shell
test "$((1))" = 1 || exec ksh $0 "$@"

test "$debugxv" && set -xv # primitive debugger

# set up trap
trap "cleanup 1" 1 2 15

# make sure everything is in the PATH
PATH=/bin:/usr/bin:/usr/ucb:.:/u/stevei/bin/`uname -n`:$PATH
export PATH

# set up variables
MAILER=/usr/bin/mailx ; export MAILER

# make your changes here
: ${ctrldir:=/u/stevei/fchange}
: ${filesfile:=$ctrldir/fchange.files}
: ${logdir:=$ctrldir/logs}
: ${fnpseudo:=$ctrldir/pseudo.sh}

newlist=$ctrldir/new.list
lastlist=$ctrldir/last.list
difflist=$ctrldir/diff.list
mailout=$ctrldir/mail.out.$$

# If you have access to a decent file locking program,
# define it here.  If not, a simple locking scheme will
# be used below. The one I use is called lockfile.
unset LOCKPROG # assume we don't have it
whence lockfile > /dev/null && \
LOCKPROG="lockfile -n15 -l 0 -r 0"

UNLOCKPROG="rm -f"
LOCKFILE=$ctrldir/fchange.lck

# If abort file is present, exit.
test -f $ctrldir/abort && exit 0

#######################################################
cleanup()
#######################################################
# remove the lock file and exit with the appropriate
# status
{
$UNLOCKPROG $LOCKFILE
rm -f $mailout $difflist
exit $1
}
# cleanup()

# Initial sanity check
cd $ctrldir || cleanup 0

# See if we can fork 20 processes.  If not, then bail.
whence fork > /dev/null && {
fork 20 >/dev/null 2>&1 || exit 0
}

# If file system is full, forget it.
test -x $ctrldir/space.chk && {
$ctrldir/space.chk || cleanup 0
}

# Make sure we have everything we need
whence $ctrldir/cdiff.sh > /dev/null || {
echo "Error: could not find $ctrldir/cdiff.sh"
cleanup 1
}

#######################################################
#                 create lockfile
#######################################################
# primitive locking mechanism

if test "$LOCKPROG"
then
# try to acquire the lock
$LOCKPROG $LOCKFILE >/dev/null 2>&1 || exit 0
else
test -f $LOCKFILE && exit 0 || date > $LOCKFILE
fi

#######################################################
#                 pseudo programs
#######################################################
# If there is a pseudo-file shell script there, run it.

test -x "$fnpseudo" && $fnpseudo

#######################################################
#                    new list
#######################################################
# read files file and create new list.

awk '/^(:|#|$)/ {next}
{print $1}' $filesfile | sort |
xargs ls -l > $newlist 2>&1

#######################################################
#                compare last list
#######################################################
# Compare newlist with lastlist.  If they're the same,
# then there is no work to do and we're done.  If
# newlist and lastlist are different, then there is work
# to do and we'll use the difflist below.

# necessary first-time only
test -f $lastlist || > $lastlist

diff $newlist $lastlist > $difflist && {
rm -f $difflist
cleanup 0
}

#######################################################
#               there is work to do
#######################################################
# Move the newlist to lastlist so we can use it the next
# time we're here.

mv $newlist $lastlist

#######################################################
#                   get to work
#######################################################

# read diff list, grabbing only certain lines.
awk '/^< / {print $NF}' $difflist |
while read fn
do
# grab the line from the files file
grep "$fn " $filesfile
done |
while read fn mail_to
do
# set track and showdiff flags.  default is no
track=no ; showdiff=no

# now check for the flags
case "$mail_to" in
*track)
# set flag and strip off trailing track
track=yes ; mail_to=${mail_to%track}    ;;
*showdiff)
# set flag and strip off trailing showdiff
showdiff=yes ; mail_to=${mail_to%showdiff} ;;
esac

# build unique log file name using the filename
sum=$(echo $fn | sum -r |
awk '{printf("%s_%s\n", $1, $2)}')
logname=$logdir/$sum
diffname=$logdir/$sum.diff
trackname=$logdir/$sum.track

# get last line in the log, or create the log
if test -f $logname
then
last_line=$(tail -1 $logname)
else
last_line=_none_
echo "#_name:$fn : $(date)" > $logname
fi

# get the current information about the file
if test -f $fn -o -c $fn
then
cur_line=$(ls -l $fn)
else
cur_line=_no_file_
fi

# if current line is same as last line, we're done.
test "$cur_line" = "$last_line" && continue

# or else something is different.  so log new
# information.
echo "$cur_line" >> $logname


# and start writing our mail message
{
echo "$sum: $fn"
echo $last_line
echo $cur_line
} > $mailout

test "$track" = yes && {
echo "#_change: $(date)" >> $trackname
cat $fn >> $trackname
$ctrldir/cdiff.sh $trackname >> $mailout
}

test "$showdiff" = yes && {
echo "#_change: $(date)" >> $diffname.new
cat $fn >> $diffname.new

if test -f "$diffname"
then
diff $diffname.new $diffname >> $mailout
else
cat $diffname.new >> $mailout
fi
mv $diffname.new $diffname
}

$MAILER -s "fchange: $fn" "$mail_to" < $mailout \
> /dev/null
done
cleanup 0
============== END: fchange.sh ==================