[comp.sources.misc] v17i077: rotate_log - logfile management utility, Part01/01

scs@lokkur.dexter.mi.us (Steve Simmons) (04/04/91)

Submitted-by: Steve Simmons <scs@lokkur.dexter.mi.us>
Posting-number: Volume 17, Issue 77
Archive-name: rotate_log/part01

Tired of writing yet another log trimming sequence in yet another shell
script?  Then this little ditty is for you.  It rotates logs, compresses
them, cleans out the old logs, kills the oldest logs, lets you invoke
custom commands along the way, complains politely if anything is wrong,
and has a hot cup of coffee waiting for you in the morning.

OK, it won't do the coffee.  But it does everything else, and has managed
to worm it's way into crontabs all over the joint.  Today I was putting
it in to clean Yet Another Log, and saw that our operators are using it,
our other system programmer is using it, etc, etc.  They're even
reading the man page.  Since it's such a success at work, it must
be time to throw it to the wolves, er, world.  Enjoy!

Steve Simmons
scs@lokkur.dexter.mi.us
----
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  ReadMe rotate_log rotate_log.8
# Wrapped by scs@lokkur.dexter.mi.us on Wed Apr  3 19:52:54 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'ReadMe' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ReadMe'\"
else
echo shar: Extracting \"'ReadMe'\" \(805 characters\)
sed "s/^X//" >'ReadMe' <<'END_OF_FILE'
XTired of writing yet another log trimming sequence in yet another shell
Xscript?  Then this little ditty is for you.  It rotates logs, compresses
Xthem, cleans out the old logs, kills the oldest logs, lets you invoke
Xcustom commands along the way, complains politely if anything is wrong,
Xand has a hot cup of coffee waiting for you in the morning.
X
XOK, it won't do the coffee.  But it does everything else, and has managed
Xto worm it's way into crontabs all over the joint.  Today I was putting
Xit in to clean Yet Another Log, and saw that our operators are using it,
Xour other system programmer is using it, etc, etc.  They're even
Xreading the man page.  Since it's such a success at work, it must
Xbe time to throw it to the wolves, er, world.  Enjoy!
X
XSteve Simmons
Xscs@lokkur.dexter.mi.us
XApril 3, 1991
END_OF_FILE
if test 805 -ne `wc -c <'ReadMe'`; then
    echo shar: \"'ReadMe'\" unpacked with wrong size!
fi
# end of 'ReadMe'
fi
if test -f 'rotate_log' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'rotate_log'\"
else
echo shar: Extracting \"'rotate_log'\" \(10991 characters\)
sed "s/^X//" >'rotate_log' <<'END_OF_FILE'
X: 
X# Shell script to rotate a log.  Usage:
X#
X# rotate_log log [ -L src_dir ] [ -n n ] [ -c ] [ -B backup_dir ]
X#	[ -b backup_name ] [ -m mode ] [ -o owner ] [ -g group ]
X#	[ -M mode ] [ -O owner ] [ -G group ] [ -e prolog_cmd ]
X#	[ -E postlog_cmd ] logfile
X#
X# where the switches mean:
X#
X#  -L	Name of the directory 'log' is found in.
X#  -n	Number of backup copies to keep.
X#  -c   Compress the backup copy.
X#  -B   Dir to keep the backup copies in.
X#  -b   Name of backup copy. 
X#  -m   Mode of new log.
X#  -o   Owner of new log (only root can use this option).
X#  -g   Group of new log (only root can use this option).
X#  -M   Mode of backup copy.
X#  -O   Owner of backup copy (only root can use this option).
X#  -G   Group of backup copy (only root can use this option).
X#  -e	Command to be executed immediately before copying the logfile.
X#  -E	Command to be executed immediately after copying the logfile.
X#
X# Stylistic note -- any error that says 'Unexpected error' means I
X# thought this particular error can't happen.
X#
X# This program is Copyright 1989, Steven C. Simmons.  It may be freely
X# redistributed provided this notice remains intact and any changes you
X# make are clearly marked as such.
X#
X# $Source: /home/lokkur/scs/src/rotate_log/RCS/rotate_log,v $
X#
X# $Revision: 0.5 $
X#
X# $Author: scs $	$Date: 91/04/03 19:49:00 $
X#
X# $State: Exp $	$Locker:  $
X#
X# $Log:	rotate_log,v $
X# Revision 0.5  91/04/03  19:49:00  scs
X# Parameterized locations of chmod, chgrp, chown.
X# 
X# Revision 0.4  89/12/12  09:35:59  scs
X# Bug fixes to pick up more defaults.
X# 
X# Revision 0.3  89/12/11  21:34:25  scs
X# Broke out commands separately to avoid ksh wierdness.  Ported
X# to system V.2 sh, ksh.  Removed some BSDisms that makes it more
X# portable.
X# 
X# Revision 0.2  89/12/11  20:53:51  scs
X# Improved error checking on source directory.  Corrected erroneous
X# error message.
X# 
X# Revision 0.1  89/12/11  19:39:31  scs
X# Initial revision.
X# 
XSCRIPT=`basename $0`
X#
X#  Commonly used commands
X#
XMV=/bin/mv
XCP=/bin/cp
XCHMOD=/bin/chmod
XCHOWN=/etc/chown
XCHGRP=/bin/chgrp
X#
X#  Assign default values as needed
X#
XSOURCE_DIR=""
XSOURCE_NAME=""
XBACKUP_NAME=""
XBACKUP_DIR=""
XBACKUP_COUNT="3"
XCOMPRESS=""
XSOURCE_MODE=""
XSOURCE_OWNER=""
XSOURCE_GROUP=""
XBACKUP_MODE=""
XBACKUP_OWNER=""
XBACKUP_GROUP=""
X#
X#  Basic switch parsing.  Right now, this forces us to use whitespace
X#  between switch char and actual execution.  Whenever we get data
X#  for a switch, errorcheck it immediately.
X#
Xwhile [ "$#" -gt "0" ] ; do
X	case $1 in
X	-L )	if [ "$2" = "" ] ; then
X			echo "${SCRIPT}: The $1 switch requires a directory name.  Aborting."
X			exit 0
X		fi
X		if [ -w "${2}" -a -d "${2}" ] ; then
X			:
X		else
X			echo "${SCRIPT}: Sorry, you cannot modify the directory ${2}.  Aborting."
X			exit 0
X		fi
X		SOURCE_DIR="${2}/"
X		shift
X		;;
X	-b )	if [ "$2" = "" ] ; then
X			echo "${SCRIPT}: The $1 switch requires a backup name.  Aborting."
X			exit 0
X		fi
X		BACKUP_NAME="$2"
X		shift
X		;;
X	-B )	if [ "$2" = "" ] ; then
X			echo "${SCRIPT}: The $1 switch requires a directory name.  Aborting."
X			exit 0
X		fi
X		if [ -w "${2}" -a -d "${2}" ] ; then
X			:
X		else
X			echo "${SCRIPT}: Sorry, you cannot create files in ${DIR}.  Aborting."
X			exit 0
X		fi
X		BACKUP_DIR="${2}/"
X		shift
X		;;
X	-n )	if [ "$2" = "" ] ; then
X			echo "${SCRIPT}: The $1 switch requires a backup count.  Aborting."
X			exit 0
X		fi
X		if echo $2 | grep '[^0-9]' > /dev/null 2>&1 ; then
X			echo "${SCRIPT}: The backup count ($2) must be a positive number.  Aborting."
X			exit 0
X		fi
X		if [ $2 -eq 0 ] ; then
X			echo "${SCRIPT}: The backup count ($2) must be greater than zero.  Aborting."
X			exit 0
X		fi
X		BACKUP_COUNT="$2"
X		shift
X		;;
X	-c )	COMPRESS="compress"
X		;;
X	-m )	if [ "$2" = "" ] ; then
X			echo "${SCRIPT}: The $1 switch requires a permissions mode.  Aborting."
X			exit 0
X		fi
X		SOURCE_MODE="$CHMOD $2"
X		shift
X		;;
X	-M )	if [ "$2" = "" ] ; then
X			echo "${SCRIPT}: The $1 switch requires a permissions mode.  Aborting."
X			exit 0
X		fi
X		BACKUP_MODE="$CHMOD $2"
X		shift
X		;;
X	-o )	if [ "$2" = "" ] ; then
X			echo "${SCRIPT}: The $1 switch requires the name of the new owner.  Aborting."
X			exit 0
X		fi
X		if grep '^${2}:' < /etc/passwd > /dev/null 2>&1 ; then
X			echo "${SCRIPT}: No such login id as $2.  Aborting."
X			exit 0
X		fi
X		SOURCE_OWNER="$CHOWN $2"
X		shift
X		;;
X	-O )	if [ "$2" = "" ] ; then
X			echo "${SCRIPT}: The $1 switch requires the name of the new owner.  Aborting."
X			exit 0
X		fi
X		if grep '^${2}:' < /etc/passwd > /dev/null 2>&1 ; then
X			echo "${SCRIPT}: No such login id as $2.  Aborting."
X			exit 0
X		fi
X		BACKUP_OWNER="$CHOWN $2"
X		shift
X		;;
X	-g )	if [ "$2" = "" ] ; then
X			echo "${SCRIPT}: The $1 switch requires the name of the new group.  Aborting."
X			exit 0
X		fi
X		if grep '^${2}:' < /etc/group > /dev/null 2>&1 ; then
X			echo "${SCRIPT}: No such group as $2.  Aborting."
X			exit 0
X		fi
X		SOURCE_GROUP="$CHGRP $2"
X		shift
X		;;
X	-G )	if [ "$2" = "" ] ; then
X			echo "${SCRIPT}: The $1 switch requires the name of the new group.  Aborting."
X			exit 0
X		fi
X		if grep '^${2}:' < /etc/group > /dev/null 2>&1 ; then
X			echo "${SCRIPT}: No such group as $2.  Aborting."
X			exit 0
X		fi
X		BACKUP_GROUP="$CHGRP $2"
X		shift
X		;;
X	-e )	if [ "$2" = "" ] ; then
X			echo "${SCRIPT}: The $1 switch requires a command to be executed.  Aborting."
X			exit 0
X		fi
X		CMD_BEFORE="${2}"
X		shift
X		;;
X	-E )	if [ "$2" = "" ] ; then
X			echo "${SCRIPT}: The $1 switch requires a command to be executed.  Aborting."
X			exit 0
X		fi
X		CMD_AFTER="${2}"
X		shift
X		;;
X	-* )	echo "${SCRIPT}: No such switch as $1.  Aborting."
X		exit 0
X		;;
X	* )	if [ "${SOURCE_NAME}" != "" ] ; then
X			echo "${SCRIPT}: You must specify only one log file.  Aborting."
X			exit 0
X		else
X			SOURCE_NAME=$1
X		fi
X		;;
X	esac
X	shift
Xdone
Xif [ "${SOURCE_NAME}" = "" ] ; then
X	echo "${SCRIPT}: You must specify a log file.  Aborting."
X	exit 0
Xfi
X#
X#  Do sanity checks
X#
X#  If he specified a source directory or backup directory, the source
X#  and backup file names cannot contain a slash.
X#
Xif [ "${SOURCE_DIR}" != "" ] ; then
X	if echo $SOURCE_NAME | grep / > /dev/null ; then
X		cat << EOF
X${SCRIPT}: If you specify a source directory (eg, -L ${SOURCE_DIR}),
Xthen the log file name (${SOURCE_NAME}) must be a simple file name,
Xie, not containing any slashes.  Aborting.
XEOF
X		exit 0
X	fi
X	#
X	#  If they don't explicitly select a backup directory but the
X	#  do specify a log directory, use the same for both.
X	#
X	if [ "${BACKUP_DIR}" = "" ] ; then
X		BACKUP_DIR="${SOURCE_DIR}"
X	fi
Xfi
Xif [ "${BACKUP_DIR}" != "" ] ; then
X	if echo $BACKUP_NAME | grep / > /dev/null ; then
X		cat << EOF
X${SCRIPT}: If you specify a backup directory (eg, -B ${BACKUP_DIR}),
Xthen the backup log name (${BACKUP_NAME}) must be a simple file name,
Xie, not containing any slashes.  Aborting.
XEOF
X		exit 0
X	fi
Xfi
X#
X#  Make sure we can mod the directory where the log is.
X#
Xif [ -w `dirname "${SOURCE_NAME}"` ] ;  then
X	:
Xelse
X	cat << EOF
X${SCRIPT}: Sorry, you do not have permission to move/rename the
Xlog file (file '`basename ${SOURCE_NAME}`', directory '`dirname ${SOURCE_NAME}`').  Aborting.
XEOF
X	exit 0
Xfi
X#
X#  Make sure we can read/write the log itself.
X#
XSOURCE_PATH="${SOURCE_DIR}${SOURCE_NAME}"
Xif [ -w "${SOURCE_PATH}" -a -r "${SOURCE_PATH}" ] ; then
X	:
Xelse
X	echo "${SCRIPT}: Sorry, you do not have permission to read and modify"
X	echo "the file '${SOURCE_PATH}'.  Aborting."
X	exit 0
Xfi
X#
X#  Make sure root operations are only run by root
X#
Xif [ "${BACKUP_OWNER}" != "" -o "${SOURCE_OWNER}" != "" -o "${BACKUP_GROUP}" != "" -o "${SOURCE_GROUP}" != "" ]
Xthen
X	set `who am i`
X	if [ "root" != "$1" ] ; then
X		echo "${SCRIPT}: Sorry, you can only change owner or group if you are root."
X		echo "Aborting."
X		exit 0
X	fi
Xfi
X#
X#  Build the list of backup names, in reverse order.  Make them
X#  full pathnames.
X#
Xif [ "${BACKUP_NAME}" = "" ] ; then
X	BACKUP_NAME="${SOURCE_NAME}"
Xfi
Xwhile expr $BACKUP_COUNT \> 0 > /dev/null ; do
X	BACKUP_COUNT=`expr $BACKUP_COUNT - 1`
X	BACKUP_FILES="${BACKUP_FILES} ${BACKUP_DIR}${BACKUP_NAME}.${BACKUP_COUNT}"
Xdone
X#
X#  Rotate the existing backups.  Assume no change in permissions, etc.
X#
Xset ${BACKUP_FILES}
Xif [ "${1}" = "" ] ; then
X	echo "${SCRIPT}: unexpected error in using backup list.  Aborting."
X	exit 0
Xfi
XOLDEST="${1}"
Xshift
Xwhile [ "$1" != "" ] ; do
X	NEXT="${1}"
X	rm -f "${OLDEST}" "${OLDEST}.Z"
X	if [ -f "${NEXT}" ] ; then
X		${MV} "${NEXT}" "${OLDEST}"
X	elif [ -f "${NEXT}.Z" ] ; then
X		${MV} "${NEXT}.Z" "${OLDEST}.Z"
X	else
X		echo "${SCRIPT}: Missing backup log ${NEXT} or ${NEXT}.Z.  Continuing."
X	fi
X	OLDEST="${NEXT}"
X	shift
Xdone
X#
X#  Copy the current log to be the first backup.  Use full pathnames
X#  as appropriate.
X#
Xif [ "${SOURCE_DIR}" != "" ] ; then
X	if cd "${SOURCE_DIR}" ; then
X		:
X	else
X		echo "${SCRIPT}: unexpected error in command 'cd ${SOURCE_DIR}'.  Aborting."
X		exit 0
X	fi
Xfi
Xrm -f "${NEXT}" "${NEXT}.Z"
Xif [ "${CMD_BEFORE}" != "" ] ; then
X	${CMD_BEFORE}
Xfi
Xif ${MV} "${SOURCE_NAME}" "${NEXT}" ; then
X	:
Xelse
X	echo "${SCRIPT}: unexpected error making first backup.  Aborting."
X	exit 0
Xfi
Xif [ "${CMD_AFTER}" != "" ] ; then
X	${CMD_AFTER}
Xfi
Xrm -f "${SOURCE_NAME}" "${SOURCE_NAME}".Z
Xif cat > "${SOURCE_NAME}" < /dev/null ; then
X	:
Xelse
X	echo "${SCRIPT}: unexpected error emptying log file.  Continuing."
Xfi
X#
X#  Set ownership and permission on the log as requested.
X#
Xif [ "${SOURCE_MODE}" != "" ] ; then
X	if ${CHMOD} ${SOURCE_MODE} "${SOURCE_NAME}" ; then
X		:
X	else
X		echo "${SCRIPT}: unexpected error executing command '${CHMOD} ${SOURCE_MODE} ${SOURCE_NAME}'."
X		echo "Aborting."
X		exit 0
X	fi
Xfi
Xif [ "${SOURCE_OWNER}" != "" ] ; then
X	if ${CHOWN} ${SOURCE_OWNER} "${SOURCE_NAME}" ; then
X		:
X	else
X		echo "${SCRIPT}: unexpected error executing command '${CHOWN} ${SOURCE_OWNER} ${SOURCE_NAME}'."
X		echo "Aborting."
X		exit 0
X	fi
Xfi
Xif [ "${SOURCE_GROUP}" != "" ] ; then
X	if ${CHGRP} ${SOURCE_GROUP} "${SOURCE_NAME}" ; then
X		:
X	else
X		echo "${SCRIPT}: unexpected error executing command '${CHGRP} ${SOURCE_GROUP} ${SOURCE_NAME}'."
X		echo "Aborting."
X		exit 0
X	fi
Xfi
X#
X#  Set ownerships and permissions as requested on the backed up log.
X#  Note that the compress must come last in this sequence.
X#
Xif [ "${BACKUP_MODE}" != "" ] ; then
X	if ${CHMOD} ${BACKUP_MODE} "${NEXT}" ; then
X		:
X	else
X		echo "${SCRIPT}: unexpected error executing command '${CHMOD} ${BACKUP_MODE} ${NEXT}'."
X		echo "Aborting."
X		exit 0
X	fi
Xfi
Xif [ "${BACKUP_OWNER}" != "" ] ; then
X	if ${CHOWN} ${BACKUP_OWNER} "${NEXT}" ; then
X		:
X	else
X		echo "${SCRIPT}: unexpected error executing command '${CHOWN} ${BACKUP_OWNER} ${NEXT}'."
X		echo "Aborting."
X		exit 0
X	fi
Xfi
Xif [ "${BACKUP_GROUP}" != "" ] ; then
X	if ${CHGRP} ${BACKUP_GROUP} "${NEXT}" ; then
X		:
X	else
X		echo "${SCRIPT}: unexpected error executing command '${CHGRP} ${BACKUP_GROUP} ${NEXT}'."
X		echo "Aborting."
X		exit 0
X	fi
Xfi
Xif [ "${COMPRESS}" != "" ] ; then
X	if ${COMPRESS} "${NEXT}" ; then
X		:
X	else
X		echo "${SCRIPT}: unexpected error executing command '${COMPRESS} ${NEXT}'."
X		echo "Aborting."
X		exit 0
X	fi
Xfi
END_OF_FILE
if test 10991 -ne `wc -c <'rotate_log'`; then
    echo shar: \"'rotate_log'\" unpacked with wrong size!
fi
chmod +x 'rotate_log'
# end of 'rotate_log'
fi
if test -f 'rotate_log.8' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'rotate_log.8'\"
else
echo shar: Extracting \"'rotate_log.8'\" \(3321 characters\)
sed "s/^X//" >'rotate_log.8' <<'END_OF_FILE'
X.\" Manual page for rotate_log
X.\"
X.\" $Source: /home/lokkur/scs/src/rotate_log/RCS/rotate_log.8,v $
X.\"
X.\" $Revision: 1.3 $
X.\"
X.\" $Author: scs $	$Date: 89/12/11 17:54:30 $
X.\"
X.\" $State: Exp $	$Locker: scs $
X.\"
X.\" $Log:	rotate_log.8,v $
X."\ Revision 1.3  89/12/11  17:54:30  scs
X."\ Added prolog and postlog commands.
X."\ 
X."\ Revision 1.2  89/12/11  17:34:46  scs
X."\ Corrected minor format errors.
X."\ 
X."\ Revision 1.1  89/12/11  17:29:36  scs
X."\ Initial revision
X."\ 
X.TH ROTATE_LOG 8 89/12/11
X.SH NAME
Xrotate_log \- rotate logfiles, removing the oldest
X.SH SYNOPSIS
X.B
Xrotate_log log [ \-L log_dir ] [ \-n n ] [ \-c ] [ \-B backup_dir ] [ \-b backup_name ] [ \-m mode ] [ \-o owner ] [ \-g group ] [ \-M mode ] [ \-O owner ] [ \-G group ] [ -e "prolog_command" ] [ -E "postlog_command" ] logfile
X.R
X.SH DESCRIPTION
X.B Rotate_log
Xtakes a lot of the drudgery out of managing logfiles.
XIt assume you have a log file
X.I logfile
Xand a series of backup copies
X.I "logfile.0,"
X.I "logfile.1,"
Xetc,
Xwhere 
X.I 0
Xis the newest backup and
X.I N
Xis the oldest.
X.B Rotate_log
Xwill remove the oldest,
Xrename the rest,
Xand empty out the original
X.I logfile.
XIt has lots of options to let you control things:
X.TP
X.B "\-L log_dir"
XAssume the
X.I logfile
Xis in a directory named
X.I log_dir.
X.TP
X.B "\-n n"
XUse
X.I n
Xbackups.
XIf you don't set this, it defaults to three.
X.TP
X.B "\-c"
X.I Compress(1)
Xthe backup copies.
X.TP
X.B "\-B backup_dir"
XPut the backed up log copies in the directory
X.I backup_dir.
X.TP
X.B "\-b backup_name"
XName the backed up log copies
X.I backup_name.
XNote you can use both the 
X.B \-B
Xand
X.B \-b
Xswitches at the same time.
X.TP
X.B "\-m mode"
XSet the mode (permissions) on
X.I logfile
Xto
X.I mode.
X.TP
X.B "\-o owner"
XSet the ownership of
X.I logfile
Xto
X.I owner
X(this option is only available to 
X.I root ).
X.TP
X.B "\-g group"
XSet the group membership of
X.I logfile
Xto
X.I group
X(this option is only available to 
X.I root ).
X.TP
X.B "\-M mode"
XSet the mode (permissions) on
X.I logfile.0
Xto
X.I mode.
X.TP
X.B "\-O owner"
XSet the ownership of
X.I logfile.0
Xto
X.I owner
X(this option is only available to 
X.I root ).
X.TP
X.B "\-O group"
XSet the group membership of
X.I logfile.0
Xto
X.I group
X(this option is only available to 
X.I root ).
X.TP
X.B "\-e prolog_command"
X.I prolog_command
Xis a command to be executed just before moving
X.I logfile
Xto
X.I logfile.0.
XNote that if 
X.I prolog_command
Xhas spaces, blanks, or metacharacters they must be quoted.
X.TP
X.B "\-E postlog_command"
X.I prolog_command
Xis a command to be executed immediately after emptying
X.I logfile
XNote it is only executed if
X.I logfile
Xis successfully emptied.
XNote also that if 
X.I prolog_command
Xhas spaces, blanks, or metacharacters they must be quoted.
X.PP
XNote that the mode and ownership settings apply only the the newly
Xcreated backups.
XIt is assumed that all older backups are already set as desired.
X.SH "ERROR MESSAGES"
XHopefully self-explaining.
XThis command bends over backwards checking for permission before
Xtrying things,
Xand tries very hard to be informative when something isn't right.
X.SH FILES
XNone.
X.SH AUTHOR
XSteve Simmons
X.SH "COPYRIGHT STATUS"
XCopyright 1989 Steve Simmons
X.I (scs@lokkur.dexter.mi.us).
XFreely redistributable provided this copyright remains intact.
X.SH BUGS
XPlease report them to the author, scs@lokkur.dexter.mi.us.
END_OF_FILE
if test 3321 -ne `wc -c <'rotate_log.8'`; then
    echo shar: \"'rotate_log.8'\" unpacked with wrong size!
fi
# end of 'rotate_log.8'
fi
echo shar: End of shell archive.
exit 0

exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.