#! /bin/sh
# ^^^ SHELL SHOULD HAVE BUILT-IN echo FOR SPEED
# $Header: /home/jerry/.bin/RCS/mhlinks,v 1.4 92/08/09 23:26:32 jerry mh_contrib $
###	mhlinks - find MH message(s) in all folders linked to named message(s)
###	Usage: mhlinks [folder] [msgs]
##
##	mhlinks SEARCHES THROUGH A DATABASE OF ALL YOUR MH MESSAGES.  IT LISTS
##	THE MESSAGE NUMBERS LINKED TO THE CURRENT MESSAGE OR TO THE MESSAGE(S)
##	YOU NAME ON THE COMMAND LINE.  THE DATABASE IS BUILD EVERY NIGHT
##	(OR HOWEVER OFTEN YOU DO IT) BY THE PROGRAM mhlinks.build.
##
##	USE THIS SCRIPT TO FIND ALL THE LINKS TO A MESSAGE YOU NEED TO
##	REMOVE... OR FOR ANY REASON YOU NEED TO FIND ALL THE LINKS.
##	THIS SCRIPT ISN'T FOOLPROOF; IF A MESSAGE HAS BEEN REPLACED RECENTLY,
##	OR IF YOU'VE CHANGED THE LINKS, USE THE scanlinks SCRIPT INSTEAD.
##	THIS SCRIPT WILL TRY TO WARN YOU WHEN THAT'S A PROBLEM.

#	TABSTOPS IN THIS CODE SET AT 4
#
#	USE AT YOUR OWN RISK.  SEEMS TO WORK, BUT IT'S YOUR RESPONSIBILITY!
#	PLEASE TELL ME ABOUT BUGS AND FIXES: Jerry Peek, jerry@ora.com

builder=mhlinks.build	# PROGRAM THAT BUILDS $db FILE FROM at OR cron
current=scanlinks		# PROGRAM THAT SEARCHES $mhdir, NOT $db

filelist=/tmp/MHLINKf$$						# UNCOMPRESSED $db FILE
folopts="-nolist -nototal -nopack -fast"	# OVERRIDE MH PROFILE
mh=/usr/local/mh							# WHERE MH PROGRAMS LIVE
mhdir="`$mh/mhpath +`" || exit 1			# USER'S MH MAIL DIRECTORY
myname="`basename $0`"						# NAME OF THIS PROGRAM
scanopts="-noclear -noheader -noreverse"	# OVERRIDE MH PROFILE
search=/home/jerry/.bin/bm					# FAST SEARCH (OR JUST USE grep)
smsglist=/tmp/MHLINKm$$						# MESSAGE(S) WE WANT TO FIND
stat=1				# DEFAULT EXIT STATUS; SET TO 0 BEFORE NORMAL EXIT
zcat=/usr/ucb/zcat							# UNCOMPRESSES $db FILE

umask 077									# MAKE TEMP FILES PRIVATE
trap 'rm -f $filelist $smsglist; exit $stat' 0 1 2 15

# MESSAGE DATABASE FILE WITH LINES THAT LIST EACH I-NUMBER AND
# MESSAGE(S) WITH THAT I-NUMBER... LIKE THIS:
# 123 a/234 prog/c/14
# 127 a/453 misc/24 reports/17 
# EACH LINE ENDS WITH A SPACE.  SO, EACH MESSAGE HAS SPACES AROUND IT.
db=$mhdir/mhlinks.list.Z
$zcat $db > $filelist || {
	echo 1>&2 "$myname: can't read database '$db'.
		Be sure '$builder' script is running from 'cron'."
	exit 1
}

while :
do
	case "$1" in
	"")	break ;;
	[+@]*) sfolder="$1" ;;	# "SOURCE" FOLDER (LOOK FOR LINKS FROM HERE)
	-*)	echo "$myname: warning: ignoring '$1'." 1>&2 ;;
	*)	smsgargs="$smsgargs $1" ;;	# "SOURCE" MESSAGES
	esac

	shift
done

# DON'T JUST DO folder +xxxx; IF FOLDER DOESN'T EXIST, IT'LL ASK create?
# IF sfolder WASN'T SET ON COMMAND LINE, DEFAULTS TO CURRENT FOLDER.
# NOTE: NEW MH 6.7.2 %(folder) ESCAPE FOR scan MIGHT REPLACE sfolname= LINE:
sfolpath=`$mh/mhpath $sfolder`
if [ $? -ne 0 -o \( ! -d "$sfolpath" \) ]
then echo "$myname: quitting: missing '$sfolder'?" 1>&2; exit
else sfolname="`$mh/folder $folopts $sfolder`" || exit
fi

if mhdir="`$mh/mhpath +`"
then
	cd $mhdir || exit
else
	echo "$myname: quitting: problem with MH directory." 1>&2
	exit
fi

# IF NO MESSAGES NAMED ON COMMAND LINE, USE CURRENT MESSAGE IN FOLDER.
# STRIP OFF $mhdir PATH; ADD SINGLE SPACE AT START AND END, LIKE:
#  inbox/23
$mh/scan $scanopts -format "${sfolname}/%(msg)" ${smsgargs=cur} > $smsglist || exit

# QUICK HACK.  CAN WE BE MORE EFFICIENT FOR LOTS OF MESSAGES
# BY MAKING A PATTERN FILE FOR fgrep, sed, ETC?
for file in `cat $smsglist`
do
	# LIST MESSAGE; inum GOES INTO $2, FILENAMES INTO $3 ON.
	# SPACES AROUND NAME MAKE SURE NO OTHER MESSAGES ARE MATCHED:
	set x `$search " $file " $filelist`
	case $# in
	1)	echo 1>&2 "$myname: can't find '$file' in database.
		Try '$current' program instead."
		;;
	*)	# COMPARE LAST-INODE-MODIFIED TIME OF DATABASE TO THE MESSAGE.
		# IF THE MESSAGE COMES FIRST, WARN USER.
		# THIS COULD BE DONE FASTER, ESPECIALLY FOR LONG $smsglist!
		case "`/bin/ls -cdt $db $file`" in
		${db}*)	;;
		*)	echo "$myname: WARNING: database entry for $file may be old.
			Try '$current' program instead." 1>&2
			;;
		esac
		# STEP THROUGH MESSAGES, ARRANGE LIST STARTING WITH $file:
		out=
		shift; shift	# GET RID OF x AND I-NUMBER
		for arg	
		do
			case "$arg" in
			$file)	;;
			*)	out="$out $arg" ;;
			esac
		done
		echo $file $out
		;;
	esac
done
stat=0	# SORT OF PRESUMPTUOUS
exit
