#! /bin/sh
# $Header: /u3/acs/jdpeek/.bin/RCS/fixsubj,v 1.9 90/10/13 10:01:45 jdpeek book $
#
###	fixsubj - fix (add or change) "Subject:" on a mail message
###	Usage: fixsubj [+folder] [msgnum [msgnums]] -s 'new subj'
##
##	SOME PEOPLE DON'T BOTHER TO PUT A Subject: LINE ON THEIR MAIL
##	MESSAGES.  THAT MAKES IT HARD, LATER, WHEN YOU scan YOUR MAIL.
##	fixsubj LETS YOU ADD YOUR OWN Subject: LINE TO MESSAGE(S).
##	YOU CAN USE THE SAME SUBJECT ON MANY MESSAGES BY GIVING ALL NUMBERS.
##
##	IF A MESSAGE ALREADY HAS A SUBJECT, fixsubj WILL TELL YOU
##	AND ASK YOU IF YOU WANT TO EDIT IT BY HAND, USE THE DEFAULT
##	FROM -s), OR SKIP IT.
##
##	TO USE IT, TYPE:
##		% fixsubj -s 'this is the subject'	(FOR THE CURRENT MESSAGE)
##	OR SOMETHING LIKE
##		% fixsubj +foo last -s 'a subject'	(last MESSAGE IN foo FOLDER)
##		% fixsubj -s 'my day' 23-25 42	(MESSAGES 23, 24, 25, AND 42)
##	...AND SO ON.  THE SUBJECT, AFTER THE -s, SHOULD BE "ONE WORD" TO
##	THE SHELL... YOU'LL USUALLY NEED TO QUOTE IT.  YOU CAN PUT THE
##	OPTIONAL FOLDER NAME (STARTS WITH A +) AND MESSAGE NUMBERS (NUMBERS,
##	WORDS LIKE last, first:20, first-33, etc.) IN ANY ORDER.

editor=${VISUAL-${EDITOR-/usr/ucb/vi}}   # TEXT EDITOR
line="/usr/ucb/head -1"		# READS ONE LINE
mh=/usr/local/mh			# WHERE MH COMMANDS LIVE
myname="`basename $0`"		# BASENAME OF THIS PROGRAM
scanopts="-noclear -noheader -noreverse" # BYPASS MH PROFILE
stat=1	# DEFAULT EXIT STATUS; SET TO 0 BEFORE NORMAL EXIT
temp=/tmp/FIXSUBJ$$
temperr=/tmp/FIXSUBJe$$		# HOLDS ERRORS FROM while LOOP
usage="Usage: $myname [+folder] [msgnum] -s 'subject'"

trap 'rm -f $temp $temperr; exit $stat' 0 1 2 15
> $temp
> $temperr
chmod 600 $temp $temperr

# PARSE COMMAND LINE:
while :
do
	case "$1" in
	"")	break ;;	# NO MORE ARGUMENTS
	-help) echo "$usage" 1>&2; stat=0; exit ;;
	[@+]*) folder="$1"; shift ;;
	-s*)
		case "$2" in
		"")	echo "$usage
			(Missing subject.)" 1>&2
			exit
			;;
		*)	newsubj="$2"
			shift; shift
			;;
		esac
		;;
	*)	msgs="$msgs $1"; shift ;;
	esac
done

case "$newsubj" in
"")	echo "$usage
	(Missing subject.)" 1>&2
	exit
	;;
esac

# FOLDER PATH; IF NO $folder GIVEN, DEFAULTS TO CURRENT:
folpath="`$mh/mhpath $folder`" || exit

# MAKE LIST OF MESSAGE NUMBERS AND SUBJECTS, ONE PER LINE.
# IF NO Subject: IN MESSAGE, $subjnow WILL BE EMPTY.
# FEED INTO LOOP.  IF NO msgs ON COMMAND LINE, SET TO cur.
#
# sh WILL RUN THIS IN A SUB-SHELL, SO exit WILL ONLY END
# THE LOOP, NOT THE WHOLE SCRIPT.  WORK-AROUND: PUT INTERNAL
# ERRORS ON FILE DESCRIPTOR 3 AND COLLECT AT END OF LOOP:
$mh/scan $scanopts -width 200 -format "%(msg) %{subject}" ${msgs=cur} |
while read msg subjnow
do
	msgpath=$folpath/$msg

	# IF MESSAGE IS UNREADABLE, scan (MH6.6 AND BEFORE)
	# WILL PRINT A LINE (TO STANDARD OUTPUT!) LIKE THIS,
	# WITH LEADING BLANKS UNLESS msgnum > 999:
	#   <msgnum>  unreadable
	# IF THERE ARE LEADING BLANKS, SOME BOURNE SHELLS WILL
	# COPY BOTH THE MESSAGE NUMBER AND THE unreadable INTO
	# subjnow, AND LEAVE $msg EMPTY.  TRY TO FIX BOTH CASES:
	case "$msg" in
	"")	echo "$myname: quitting, message $msg $subjnow" 1>&3; break ;;
	esac
	case "$subjnow" in
	unreadable)
		echo "$myname: quitting: can't read message '$msg'." 1>&3
		break
		;;
	"")	# GLUE Subject AND X-Original-Subject TO TOP.
		# IF YOUR SHELL DOESN'T UNDERSTAND "<<-", REPLACE IT
		# WITH "<<" AND SHIFT LINES TO LEFT-HAND EDGE:
		cat - $msgpath > $temp <<- ENDOFHDR
		Subject: $newsubj
		X-Original-Subject: (none)
		ENDOFHDR
		cp $temp $msgpath || {
			echo "$myname: quitting: can't replace ${msgpath}?" 1>&3
			break
		}
		;;
	*)	# MESSAGE HAS A SUBJECT ALREADY; ASK USER:
		# LOOP UNTIL GET ANSWER:
		while :
		do
			# SAME NOTE AS ABOVE ABOUT REPLACING "<<-"...
			cat <<- ENDOFMSG

			Message $msg already has a subject:
			... $subjnow
			Type c to change subject to '$newsubj'
			Type e to edit the message yourself with $editor
			Type s to skip this message and go on to the next (if any)
			Type q to quit and not change any more messages.
			ENDOFMSG
			echo -n "And the answer is? " 1>&2
			ans="`$line </dev/tty`"
			case "$ans" in
			s*)	break ;; # CONTINUE OUTER (MESSAGE) LOOP
			q*)	break 2 ;;
			e*)	$editor $msgpath </dev/tty >/dev/tty 2>/dev/tty
				break
				;;
			c*) # NOTE: FIX "<<-" AND LINES IF SHELL NEEDS:
				ed - $msgpath <<- !ENDOFEDIT! >$temp 2>&1
				/^Subject: /s/^/X-Original-/
				i
				Subject: $newsubj
				.
				w
				q
				!ENDOFEDIT!
				if [ ! -s $temp ]
				then break
				else
					echo "$myname: error editing '$msg':" 1>&2
					cat "$temp" 1>&2
					echo "Should you edit it by hand?  Try again:
					" 1>&2
				fi
				;;
			*)	echo "Please try again..." 1>&2 ;;
			esac	# END OF case "$ans"
		done		# END OF while :
		;;
	esac			# END OF case "$subjnow"
done 3> $temperr	# END OF while read msg subjnow

if test -s $temperr
then cat $temperr 1>&2
else stat=0
fi
exit
