#!/usr/bin/env ksh
# $Id: msync.ksh,v 4.52 2012/08/12 18:57:25 ksb Exp $
# Make sure this master source (or meta source) structure is stable:
#	modes are distribution quality,
#	co'd files are specified version,
#	RCS or CVS dirs are lint clean (SVN and git in future),
#	the make macro SOURCE catches all the files in the top-level directories
#		(this is not from msrc, it is totally local policy),
#	honor the GEN macro to suppess files that are not SOURCE:
#		(once again this is local policy only),
#	recurse into SUBDIRs under -R:
#		subdirs match this version (again, local policy for rcsvg),
#	check that every SEND file not in GEN exists (is readable really).
# Bugs:
#	We know about level2s stuff more than we should, but I got sick of
#	getting all the way to building a package to have the versions bug
#	make me go around the loop again.
#
# N.B. import VersionFunc, MSYNC_GROUP from the environment.
#
# We guess at the "ksb version" for this product, if not given.
# ksb always uses the major revision number of the mkcmd template or
# the msrc recipe (Makefile) as the key {1.x -> One, 2.x -> Two and the
# like}. Under -N we'll disclose the computed symbolic name: change that
# logic to your local policy (if you have one) and rename this program.
#
typeset PROGNAME PfSPAT MYTEMP
PROGNAME=`basename $0 .ksh`
PfSPAT=${TMPDIR:-/tmp}/msYncXXXXXX
MYTEMP=`mktemp -d "$PfSPAT" ` || exit 73
trap 'rm -rf $MYTEMP' EXIT

# The site policy to find the local symbolic version from a revision	(ksb)
# number.  It might consult the date, or some other local data source.
: ${VersionFunc:="VersionDefault"}
function VersionDefault {
	sed -e 's/^0\.[0-9.]*/Zero/' -e 's/^1\.[0-9.]*/One/' \
		-e 's/^2\.[0-9.]*/Two/' -e 's/^3\.[0-9.]*/Three/' \
		-e 's/^4\.[0-9.]*/Four/' -e 's/^5\.[0-9.]*/Five/' \
		-e 's/^6\.[0-9.]*/Six/' -e 's/^7\.[0-9.]*/Seven/' \
		-e 's/^8\.[0-9.]*/Eight/' -e 's/^9\.[0-9.]*/Nine/' \
		-e 's/^10\.[0-9.]*/Ten/' -e 's/^11\.[0-9.]*/Eleven/' \
		-e 's/^12\.[0-9.]*/Twelve/' -e 's/^13\.[0-9.]*/Thirteen/' \
		-e 's/^14\.[0-9.]*/Fourteen/' -e 's/^15\.[0-9.]*/Fifteen/' \
		-e 's/^16\.[0-9.]*/Sixteen/' -e 's/^17\.[0-9.]*/Seventeen/' \
		-e 's/^18\.[0-9.]*/Eighteen/' -e 's/^19\.[0-9.]*/Nineteen/' \
		-e 's/^20\.[0-9.]*/Twenty/' -e 's/^[0-9].*/Max/'
}

typeset slide GRPOF VERSION RECUR_SUBDIR PreList VEROF LEVEL3
slide='P=$1; shift; set _ -`expr _"$P" : _'\''-.\(.*\)'\''` ${1+"$@"}; shift'
case $PROGNAME in
*verof*)
	VEROF=true
	;;
*)
	VEROF=false
	;;
esac
GRPOF=false
VERSION=false
RECUR_SUBDIR=false
LEVEL3=""
PreList=""
: ${DIFF_OPTS:=""} ${SPEC_FILE:=ITO.spec}
while [ $# -gt 0 ] ; do
	case "$1" in
	--)
		shift
		break
		;;
	-G)
		GRPOF=true
		shift
		;;
	-G*)
		GRPOF=true
		eval "$slide"
		;;
	-N)
		VEROF=true
		shift
		;;
	-N*)
		VEROF=true
		eval "$slide"
		;;
	-V)
		VERSION=true
		shift
		;;
	-V*)
		VERSION=true
		eval "$slide"
		;;
	-m)	# note that -m could have embedded spaces, but not quotes
		PreList="$PreList -m \"$2\""
		shift; shift
		;;
	-m*)
		PreList="$PreList \"$1\""
		shift
		;;
	-R)
		RECUR_SUBDIR=true
		shift
		;;
	-R*)
		RECUR_SUBDIR=true
		eval "$slide"
		;;
	-3)
		LEVEL3=true
		shift
		;;
	-3*)
		LEVEL3=true
		eval "$slide"
		;;
	-h*)	echo "$PROGNAME: [-3R] [-m prereq] [diff-opts] [version] [directory]"
		echo "$PROGNAME: -G [directory|file]"
		echo "$PROGNAME: -N [directory|file]"
		echo "$PROGNAME: -h"
		echo "$PROGNAME: -V"
		echo "3          directory is a level3 package source"
		echo "h          output only this help message"
		echo "m prereq   specify __msrc replacement (optionany :cleanup)"
		echo "G          output the expected group ownership for source files"
		echo "N          output the default symbolic name for directory"
		echo "R          recurse into SUBDIRs"
		echo "V          output only our version information"
		echo "diff-opts  [-bciuw] [-C lines] [-u lines] [-U lines]"
		echo "version    compare to this desired symbolic revision name"
		echo "directory  target source directory, or directory's makefile"
		exit 0
		;;
	-[bciw])
		DIFF_OPTS="$DIFF_OPTS $1"
		shift
		;;
	-[bciw]*)
		DIFF_OPTS="$DIFF_OPTS `expr _\"$1\" : '_\(..\).*'`"
		eval "$slide"
		;;
	-[uUC])
		DIFF_OPTS="$DIFF_OPTS $1$2"
		shift;shift
		;;
	-[uUC]*)
		DIFF_OPTS="$DIFF_OPTS $1"
		shift
		;;
	-*)
		echo "$PROGNAME: usage [diff-opts] [version] [directory]"
		echo "$PROGNAME: usage -G [version] [directory|file]"
		echo "$PROGNAME: usage -N [version] [directory|file]"
		echo "$PROGNAME: usage -h"
		echo "$PROGNAME: usage -V"
		exit 64
		;;
	*)
		break
		;;
	esac
done

typeset FileWhich PreReq DIR DIRNAME VFROM VER KeyFile Target MkGroup
FileWhich=/dev/null
PreReq=`eval msrc $PreList -V | tr -s '\t ' '  ' | sed -n -e 's/.*make hooks*: *//p'`
VFROM=""
VER=""
if $VEROF || $GRPOF ; then
	: nada
elif [ _-- = _"$1" ] ; then
	shift
elif [ $# -gt 0 ] ; then
	VFROM="command line specification"
	VER=$1
	shift
fi

# Locate this process over the correct directory, name the key file for
# -N (or -G, but we don't use it)
DIR=.
DIRNAME=""
if [ _-- = _"$1" -o \( $# -gt 0 -a _'' = _"$1" \) ] ; then
	shift
elif [ $# -gt 0 ] ; then
	DIR=$1
	DIRNAME=`echo $DIR/ | tr -s '/' '/' `
	shift
	# Specified file is the control recipe or target file for version name
	case _"$DIRNAME" in
	_./)
		DIRNAME="" ;;
	*)
		if [ -f $DIR ] ; then
			FileWhich=`basename $DIR`
			cd `dirname $DIR`
		else
			cd $DIR
		fi ;;
	esac
fi

# After the directory, then what to do with $*

# If we are in a old-style (1986 version) directory default to the
# version of the Distfile
if [ -f Distfile -a -f Make.host ] ; then
	if $VEROF || $GRPOF ; then
		: ${FileWhich:=Distfile}
	else
		echo "$PROGNAME: master source version prior to 2008"
		exit 65 # DATAERROR
	fi
fi
# When we have a Makefile.meta we are a level3 by default
if [ -f Makefile.meta ] ; then
	: ${LEVEL3:=true}
else
	: ${LEVEL3:=false}
fi
: `pwd` for $FileWhich
# Find the current head of the recipe file (should do svn/svk better)
for CNTL in $FileWhich Msrc.mk msrc.mk Makefile makefile ; do
	[ _/dev/null = _$CNTL ] && continue
	if [ -d RCS -a -f $CNTL ]; then
		co -q -p $CNTL >$MYTEMP/makefile && break
	elif [ -d CVS -a -f $CNTL ]; then
		CVSROOT=`cat CVS/Root`
		REPO=`cat CVS/Repository`
		export MYTEMP CVSROOT REPO
		(cd $MYTEMP && cvs -Q -d $CVSROOT co -d co $REPO/$CNTL)
		cp $TMPDIR/co/$CNTL $MYTEMP/makefile && break
	elif [ -f $CNTL ]; then
		cp $CNTL $MYTEMP/makefile && break
	fi
done

if [ -s $MYTEMP/makefile ] ; then
	: 'ok'
elif $VERSION ; then
	echo "$PROGNAME:" '$Id: msync.ksh,v 4.52 2012/08/12 18:57:25 ksb Exp $'
	echo "$PROGNAME: template for private file space: $PfSPAT"
	exit 0
else
	echo 1>&2 "$PROGNAME: $DIR: not a master source directory"
	exit 65
fi

# The meta information control policy I use:			SITE_POLICY
#	Look for marker Msync(target) and if found runs
#		make -sf $recipe $target
#	rather than this command, set an env variable so we don't loop.
: ${MSYNC_CHECK:=true}
if $MSYNC_CHECK && Target=`MK= mk -smMsync -dtarget $MYTEMP/makefile 2>/dev/null` ; then
	# Don't recurse for -N, -G, or -V, and do not exec here, because
	# we use the recipe in $MYTEMP, which we need to removed on exit.
	if ! $VEROF && ! $GRPOF && ! $VERSION ; then
		MSYNC_CHECK=false make -sf $MYTEMP/makefile $Target
		# XXX we ignore the rest of the dir params :-(	--ksb
		exit $?
	fi
fi

# The control group policy I use:				SITE_POLICY
#	Use a marked line Msync(group) which should output the group name
#	else let $MSYNC_GROUP be the group, if set (default mk rule)
#	else default to "source" (in that rule).
#	Publish the group found for any -R dirs (or additional dirs)
echo '$'"Msync(group): echo \${MSYNC_GROUP:-source}" >$MYTEMP/defrule
MkGroup=`MK= mk -smMsync -dgroup -t$MYTEMP/defrule $MYTEMP/makefile` || {
	echo "$PROGNAME: control group markup failed in $DIRNAME$CNTL"
	exit 69
}
: ${MSYNC_GROUP:=$MkGroup}
export MSYNC_GROUP

# This is a bit of site policy, and really should not be hardcoded here,
# but is is so small and I think it is always correct.		SITE_POLICY
# ZZZ Msync(RCS|CVS|SCCS|SVN|git) might output the correct file?
cat <<! >$MYTEMP/RCS.cf
.	drwxr-xr-x/2020	*	${MkGroup}	-
*,v	-r-?r-??-?	"	"		-
-No_rm_star -r?-r?-?--	"	"		-
*	!-r??r??r-?	"	"		-
!
cat <<! >$MYTEMP/CVS.cf
.	drwxr?x?-?/2000	*	${MkGroup}	-
Entries* -rw-r?-?--	"	"		-
Root	"		"	"		"
Repository "		"	"		"
Tag	"		"	"		"
Checkin.prog "		"	"		"
Update.prog "		"	"		"
-No_rm_star -r?-r?-?--	"	"		-
*	!-r??r???-?	"	"		"
!
# SVN LLL I have no idea what is in a SVN or .svn dir or how to use svk
cat <<! >$MYTEMP/SVN.cf
.	drwxr?x?-?/2020	*	${MkGroup}	-
*	-r??????-?	"	"		-
!
# Later add git, maybe.  SCCS support would be nice too, but
# does anyone still use that?  I'm never sure how far back to go.

# When we didn't get a version (saw "--" or nothing) compute it
# This is site policy, look for your own revision control markup.
# Note that we [b]racket a character here to prevent meta matches on this file.
if [ -z "$VER" ] ; then
	VFROM="version from $CNTL"
	VER=`ident <$MYTEMP/makefile 2>$MYTEMP/ident.err|
	sed -n -e 's/.*\$[R]evision: \(.*\)\$.*/\1/p' \
		-e 's!.*\$[H]eader: .*,v \([0-9.]*\) \([0-9/]* [0-9:]*\) \([^ :]*\).*\$.*!\1!'p \
		-e 's!.*\$[I]d: .*,v \([0-9.]*\) \([0-9/]* [0-9:]*\) \([^ :]*\).*\$.*!\1!'p \
		-e 's!.*\$Fed[E]x: .*,v \([0-9.]*\) \([0-9/]* [0-9:]*\) \([^ :]*\).*\$.*!\1!'p |
	tr -d ' \t' |
	$VersionFunc |
	oue` || exit 65
	if [ -s $MYTEMP/ident.err ] ; then
		: ${VER:=One}
		echo "$PROGNAME: $CNTL must have revision markup, default to \"$VER\""
	fi
fi

# If they like we'll just tell then the local policy symbolic name or
# the source group's name.
if $VEROF ; then
	echo "$VER"
	xapply "Tv=\`$0 -N \"%q1\"\` && [ _$VER != _\$Tv ] && echo \"$PROGNAME: %q1: \$Tv does not match $VER\"" "$@" 1>&2
	exit 0
fi
if $GRPOF ; then
	echo "$MkGroup"
	xapply "Tg=\`$0 -G \"%q1\"\` && [ _$MkGroup != _\$Tg ] && echo \"$PROGNAME: %q1: \$Tg does not match $MkGroup\"" "$@" 1>&2
	exit 0
fi


# Read the msrc macros from make recipe file we found.  Because msrc
# doesn't have a policy for SOURCE/GEN, we mmsrc to fetch those.
# ZZZ we don't catch the source of the macro (viz. make|generated|empty).

msrc -d P `$LEVEL3 && echo " -y INTO=$MYTEMP/dest"` -C/dev/null -m "${PreReq%:*}" -f$MYTEMP/makefile 2>$MYTEMP/bugs |
(cd $MYTEMP; perl -w -e 'my($V) = undef;
	open(my($fh), ">", "/dev/null") or die $!;
	while (<>) {
		chomp;
		if (m/^(\w+): \[.*\]\s*$/o) {
			$V = $1;
			close $fh;
			open($fh, ">", "$V") or die $!;
			next;
		}
		$_ =~ s/^\t+//;
		print $fh "$_\n";
	}'
)
if grep "make: " $MYTEMP/bugs 1>&2 ; then
	echo "$PROGNAME: prerequisites failed" 1>&2
	exit 70
fi
if ! $VERSION && grep -v "^msrc: cat " $MYTEMP/bugs | grep "msrc: " 1>&2 ; then
	echo "$PROGNAME: msrc doesn't love this directory" 1>&2
	exit 65
fi
if MP=`whence mmsrc` ; then
	$MP -f $MYTEMP/makefile -b SOURCE >$MYTEMP/SOURCE
else
	MP="make"
	$MP -f $MYTEMP/makefile -V SOURCE |tr -s ' \t\n' '\n\n\n' |sed -e '/^$/d'
fi >$MYTEMP/SOURCE
if [ ! -s $MYTEMP/SOURCE ] ; then
	$VERSION || echo "$PROGNAME: ${MP##*/}: recipe doesn't render a SOURCE macro (guessed at value)" 1>&2
	find . -type f -print -o -type d -prune >$MYTEMP/SOURCE
fi
oue -D $MYTEMP/source.db -R '' $MYTEMP/SOURCE
if [ _"make" = _"$MP" ] ; then
	$MP -f $MYTEMP/makefile -V GEN
else
	$MP -f $MYTEMP/makefile -b GEN |tr -s ' \t\n' '\n\n\n' |sed -e '/^$/d'
fi | sed -e '/^$/d' >$MYTEMP/GEN
oue -D $MYTEMP/gen.db -R '' $MYTEMP/GEN

# We know enough to report a useful -V output
if $VERSION ; then
	echo "$PROGNAME:" '$Id: msync.ksh,v 4.52 2012/08/12 18:57:25 ksb Exp $'
	echo "$PROGNAME: template for private file space: $PfSPAT"
	if [ -s $MYTEMP/makefile ] ; then
		echo "$PROGNAME: control recipe from \"$CNTL\""
	fi
	echo "$PROGNAME: $VFROM: $VER"
	echo "$PROGNAME: make prereq hook: $PreReq"
	echo "$PROGNAME: MSYNC_GROUP control group: $MkGroup"
	echo "$PROGNAME: MSYNC_CHECK recipe indirection: $MSYNC_CHECK"
	if [ ! -z "$Target" ] ; then
		echo "$PROGNAME: control Msync(target): $Target"
	fi
	exit 0
fi

# Called for each directory listed to check for compliance
ScanSrc () {
	if [ -f $1/.cvsignore ] ; then
		echo ".cvsignore" |oue -D $MYTEMP/source.db -R ''
	fi
	for file in `/bin/ls -1 $1`
	do
		if [ ! -d "$1/$file" ] ; then
			[ -n "`echo "$file" |oue -vI $MYTEMP/gen.db`" ] && continue
			[ -L "$1/$file" ] && continue
			echo "$file" |oue -I $MYTEMP/source.db -D $MYTEMP/elim.db >>$MYTEMP/missing
			continue
		fi
		# the RCS or CVS may be a symbolic link to a directory
		case "$file" in
		CVS|RCS|SVN)
			echo "$file	drwxr-xr-x/2020	*	${MkGroup}		-" >>$MYTEMP/ck.cf
			if [ _. = _$1 ] ; then
				instck -C $MYTEMP/${file##*/}.cf ${file##*/} 2>&1
			else
				instck -C $MYTEMP/${file##*/}.cf $1/${file##*/} 2>&1
			fi
			if [ 1 -ne $(ls -dl . ${file##*/} | oue -k '%[1 1]' | wc -l) ] ; then
				echo "$PROGNAME: ${file##*/} directory is not the same mode as parent"
			fi ;;
		*)
			echo "$file	dr-xr-xr-x/2220	*	${MkGroup}		-" >>$MYTEMP/ck.cf
			echo "$file" >>$MYTEMP/founddir
			;;
		esac
	done
	oue -I $MYTEMP/gen.db -iR '%k	r??r?????	*	*	-' /dev/null >>$MYTEMP/ck.cf
	cat <<! >>$MYTEMP/ck.cf
# plain files
a.out	!00755/07022	*	${MkGroup}		-
core	!0		*	"			-
errs	!0		*	"			-
lint.out !0		*	"			-
FRC	!0		*	"			-
!
	if [ -d $1/RCS ] ; then
		cat <<!
RCS	d---------/02775 *	${MkGroup}		-
RCS/.	"		*	"			"
RCS/..	"		*	"			"
RCS/*,v	r-?r-??-?	*	"			-
RCS/*	!r-?r-??-?	*	"			"
RCS/.*	!r-?r-??-?	*	"			"
!
	fi >>$MYTEMP/ck.cf
	# We could do better here. --ksb
	if [ -d $1/CVS ] ; then
		cat <<!
CVS	d---------/02775 *	${MkGroup}		-
CVS/.	"		*	"			"
CVS/..	"		*	"			"
CVS/*	-r??r???-?	*	"			-
CVS/.*	!r??r???-?	*	"			"
!
	fi >>$MYTEMP/ck.cf
	# hg, SVN, git checks? ZZZ
	instck -C$MYTEMP/ck.cf $1 2>&1

	# XXX We can exceed the command-line argument max on the rcsdiff,
	# we need glob and xapply to avoid that, but it doesn't happen much.
	# XXX We could ski -No_rm_star here
	if [ _"$1/RCS/*" != _"`echo $1/RCS/*`" ] ; then
		rlog -R -L $1/RCS/* 2>&1 |sed -e "s,^,Locked file: ,"
		( cd $1 && rcsdiff $DIFF_OPTS -q -r"$VER" RCS/* ) 2>&1 |
		sed -e "s!^rcsdiff: !rcsdiff: ${DIRNAME}!"
	elif [ _"$1/CVS/*" != _"`echo $1/CVS/*`" ] ; then
		cvs -Q status -l |grep ^File: |grep -v "Status: Up-to-date"
		( cd $1 && cvs -q diff $DIFF_OPTS -l -r"$VER" . ) 2>&1 |
		sed -e "s!^Index: !Index: ${DIRNAME}!"
	fi
	# SVN or .svn, (for above) I don't use that enough to know LLL

	# Look for missing GEN files or source files or Cache dirs
	oue -I $MYTEMP/gen.db -iR '%k' /dev/null |
	xapply -f '[ -f "%q1" -o -e "%q1.host" ] || echo "'"$PROGNAME"': GEN: %q1: missing file" 1>&2' -
}

ScanSrc . >$MYTEMP/bugs
# Check for missing SEND files not in GEN (these may not be instanced in
# a clean structure when the wrong prereq target is specified).
if [ ! -s $MYTEMP/bugs ] ; then
	if [ -s $MYTEMP/SEND -o 1 -eq `wc -c < $MYTEMP/SEND` ] ; then
		cat $MYTEMP/SEND
	else
		oue -I $MYTEMP/source.db -i /dev/null
	fi |
	oue -I $MYTEMP/gen.db |
	xapply -f '[ -r "%q1" ] || echo "'"$PROGNAME: $DIRNAME$CNTL"'": SEND file \"%1\" not readable' - >>$MYTEMP/bugs
fi

# Check SUBDIRs too, as set in the recipe or is none are set check dirs
# we found.  We also consult IGNORE here, for ones we found. -- ksb
if $RECUR_SUBDIR ; then
	(	# subshell because we change argv
	if [ -s $MYTEMP/SUBDIR ] ; then
		set _ "$@" `< $MYTEMP/SUBDIR`
	elif [ -s $MYTEMP/founddir ] ; then
		set _ "$@" `oue -vd $MYTEMP/founddir $MYTEMP/IGNORE`
	else
		set _
	fi
	shift
	xapply 'echo "In directory %q1"
		'"$0 -R -- '$VER' \"%q1\"" "$@"
	)>>$MYTEMP/bugs
fi

if [ -s "$MYTEMP/bugs" ] ; then
	cat $MYTEMP/bugs
elif [ -s "$MYTEMP/missing" ] ; then
	COUNT=`wc -l < $MYTEMP/missing`
	PL=""
	[ 1 -eq $COUNT ] || PL="s"
	echo "$PROGNAME: $DIRNAME$CNTL: might be missing" $COUNT "file$PL from the SOURCE macro:"
	fmt $MYTEMP/missing |sed -e 's/^/	/'
else
	echo "$PROGNAME: $DIR in sync at $VER"
fi
oue -I $MYTEMP/source.db -i /dev/null |
sed -e p -e 's/\(.*[/]\)/\1RCS\//' -e '/^[^/]*$/s!^!RCS/!' |
xapply -2 -f '[ -d "%Q1" ] && exit 0
	if [ ! -d %[2/-$] ] ; then
		[ -f "%q2,v" ] || echo "'"$PROGNAME"': '"$DIR"': missing RCS cache"
	elif [ -f %q1,v ] ; then
		echo "'"$PROGNAME"': RCS cache file '"${DIRNAME}"'%q1,v should be in an RCS subdirectory"
	else
		[ -f "%q2,v" ] || echo "'"$PROGNAME"': '"$DIR"': missing RCS cache for %q1"
	fi' - - |oue
if [ ! -f "$SPEC_FILE" ] ; then
	: nada
elif KEYFILE=`MK= mk -smKeyFile ${SPEC_FILE}` ; then
	SPEC_VER=`sed -n -e 's/Version[ :	]*\([.0-9]*\)$/\1/p' $SPEC_FILE | head -1`
	if [ ! -e "$KEYFILE" ] ; then
		echo "$PROGNAME: $SPEC_FILE: $KEYFILE: key file missing"
	elif ! KEY_VER=`ident $KEYFILE | sed -n -e 's/.*\$Id: [^ ]* \([.0-9]*\) .*/\1/p' | head -1` ; then
		echo "$PROGNAME: $KEYFILE has no version information"
	elif [ _"$SPEC_VER" != _"$KEY_VER" ] ; then
		echo "$PROGNAME: RPM control $SPEC_FILE claims version \"$SPEC_VER\", but key file $KEYFILE claims \"$KEY_VER\""
	fi
fi

if [ $# -ge 1 ] ; then
	set _ `for i ; do
		case "$i" in
		/*)	echo $i ;;
		*)	echo $OLDPWD/$i ;;
		esac
	done`
	shift
	xapply "$0`$RECUR_SUBDIR && echo " -R"` -- '$VER' \"%q1\"" "$@"
fi

# Update a clean target, if one was requested under -m (e.g. "-m :").
if expr "$PreReq" : '.*:.*' >/dev/null ; then
	make -sf $MYTEMP/makefile ${PreReq##*:} || {
		echo "$PROGNAME: make: ${PreReq##*:}: failed" 1>&2
		exit 70
	}
	oue -I $MYTEMP/gen.db -iR '%k' /dev/null |
	xapply -e "TARGET=${PreReq##*:}" -f '[ -f "%q1" ] && echo "'"$PROGNAME"': GEN: %q1: not removed by update of cleanup target $TARGET" 1>&2' -
fi
exit 0
