[comp.sources.misc] v16i089: "MH & xmh: Email for Users and Programmers", Part01/01

jerry@ora.com (Jerry Peek) (02/02/91)

Submitted-by: jerry@ora.com (Jerry Peek)
Posting-number: Volume 16, Issue 89
Archive-name: mh-scripts/part01

These files are Bourne shell scripts that use MH electronic mail commands.  
The scripts come from the Nutshell Handbook called "MH & xmh: Email for 
Users and Programmers" published by O'Reilly & Associates, Inc. 
Whether you have the book or not, these scripts should be useful if you
use MH.  (If you don't use MH, look at the kinds of things you could do.)

--Jerry Peek, jerry@ora.com

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# NOTE: Tabstops in these files are set at 4-column intervals.
#
# Wrapped by ora!jerry on Sat Jan 12 18:30:42 EST 1991
# Contents:  README append babyl2mh distprompter fixsubj fols incs mhprofile
#	recomp replf resend.fixmsg rmmer scandrafts showpr vmsmail2mh xmhprint
 
echo extracting - README
sed 's/^X//' > "README" <<'X//E*O*F README//'
XINTRODUCTION:  These files are Bourne shell scripts that use MH electronic
Xmail commands.  The scripts come from the Nutshell Handbook called "MH & xmh:
XEmail for Users and Programmers" published by O'Reilly & Associates, Inc. 
XThe book will be available this month (January, 1991).
X
XWhether you have the book or not, these scripts should be useful if you
Xuse MH.  (If you don't use MH, look at the kinds of things you could do.
XBecause MH isn't a "one-mail-program-does-all" system and its programs are
Xall run by the UNIX shell, shell programming with MH is easy.)
XEach file has a comment block that explains the program; individual
Xparts of the scripts are commented, too.  Although the book has complete
Xexplanations, people who have some experience with shell programming and
XMH should be able to use these without the book.
X
X
XDO THEY WORK?:  I developed these scripts under BSD UNIX and SunOS; I've
Xused most of them myself for months or years.  The book's reviewers tested
Xthem on other flavors of UNIX.  Still, there could be some portability or
Xother problems.  If you don't have MH 6.7 installed, you could run into a
Xfew problems there.  There are also some compatibility problems, like
X"echo -n" vs. "echo \c", that I haven't tried to code around; remember
Xthat these are intended more as examples than as portable bulletproof code.
X
XIf you find problems, though, please send me mail.  Of course, some
Xsystem-dependent stuff like variables that hold the pathnames of files and
Xprograms will have to be edited to work on your computer.  Also, some
Xobscure problems and system dependencies are explained in the book.
XBut I'd be GLAD to get your mail (and answer it as soon as I can).
X
XBecause these scripts come directly from the book, I'm not sure what to
Xdo about patches and patchlevel.h files for the comp.sources.misc
Xarchives.  The book versions won't be patched; they'll just be updated.
XThe latest versions should always be available on the uunet.uu.net
Xcomputer for anonymous ftp and uucp; get the tar file named MHxmh.tar.Z
Xfrom the nutshell/MHxmh directory.
X
X
XDESCRIPTIONS:  Here are one-line descriptions of the script files.
XEven if you don't need the capabilities that a particular program gives,
Xyou might want to look at the scripts anyway for examples of MH programming.
X
Xappend        Append file(s) to an MH mail message at "What now?" prompt
Xdistprompter  Replaces "prompter" editor for MH "dist" command
Xfixsubj       Fix (add or change) "Subject:" on a mail message
Xfols          Show list of folders in columns, current folder marked
Xmhprofile     Grab matching line(s) from MH profile file
Xrecomp        Re-compose a draft mesage in MH draft folder
Xreplf         Refile current message into folder, reply to it
Xresend.fixmsg Editor for fixing up returned mail (use with "resend")
Xrmmer         Move mail to DELETE (sub-)folder for "find" to delete later
Xscandrafts    Scan MH draft folder; return to original folder or stay
Xshowpr        Show MH message(s) with pr(1), custom heading
Xxmhprint      Print command for xmh
X
X
XAUTHORSHIP, COPYING, ETC.:  These programs are in the public domain.
XOf course, you use them at your own risk.  I wrote most of them myself.
XI adapted two of them, "append" and "replf", from scripts that come
Xwith the MH distribution; Marshall Rose, John Romine and Bob Desinger
Xwere authors of those scripts, I believe.  If you make changes or fix
Xbugs, I'd really appreciate getting a mail message about that and/or
Xa copy of your fixed script.  If I use the changes, I'll give you
Xcredit... and people who use the scripts will appreciate your help!
X
X--Jerry Peek, jerry@ora.com, +1 617 354-5800
X//E*O*F README//
chmod u=rw,g=r,o=r README
 
echo extracting - append
sed 's/^X//' > "append" <<'X//E*O*F append//'
X#! /bin/sh
X# $Header: /u3/acs/jdpeek/.bin/RCS/append,v 1.10 90/10/13 09:48:04 jdpeek book $
X###	append - append file(s) to an MH mail message
X###	Usage:   What now? e append file [files...]
X##
X##	THIS SCRIPT LETS YOU APPEND ONE OR MORE FILES TO A DRAFT MH MAIL
X##	MESSAGE; IT ALSO ALLOWS WILDCARDS AND ENVARIABLES.
X##	YOU CALL IT AS AN EDITOR, AT THE What now? PROMPT.
X##	FOR EXAMPLE, TO APPEND A COPY OF YOUR FILE report TO YOUR DRAFT:
X##		What now? e append report
X##
X##	AFTER IT APPENDS THE FILE(S), YOU GET ANOTHER What now? PROMPT.
X##	IF YOU WANT TO SEPARATE THE FILES WITH BLANK LINES, ROWS OF DASHES,
X##	OR WHATEVER, AN EASY WAY IS TO MAKE A LITTLE FILE NAMED SOMETHING
X##	LIKE SEP WITH THAT SEPARATOR IN IT.  THIS NEXT EXAMPLE SHOWS HOW TO
X##	APPEND ALL THE FILES FROM THE $HOME/proj DIRECTORY WHOSE NAMES END
X##	WITH .out, THEN YOUR SEPARATOR FILE, THEN THE FILE .signature:
X##		What now? e append $HOME/proj/*.out sep .signature
X#
X# Original, apparently by John Romine, from the paper
X# "MH.5: How to process 200 messages a day and still get some
X# real work done," in the Summer 1985 USENIX Proceedings.
X# Hacked more by Jerry Peek, with hints from John Romine.
X
Xcase $# in
X0)	echo 1>&2 "`basename $0`: shouldn't get here!"; exit 1;;
X1)	echo 1>&2 "Usage: e[dit] `basename $0` file [files...]"; exit 1 ;;
X*)	while :
X	do
X		case $# in
X		1)	msg=$1; break ;;
X		*)	files="$files $1"; shift ;;
X		esac
X	done
X	;;
Xesac
X
X# eval EXPANDS ENVIRONMENT VARIABLES IN $files; BUT PROTECT >> FROM eval:
Xeval cat $files '>>' $msg
X//E*O*F append//
chmod u=rwx,g=rx,o=rx append
 
echo extracting - babyl2mh
sed 's/^X//' > "babyl2mh" <<'X//E*O*F babyl2mh//'
X#! /bin/sh
X# $Header: /u3/acs/jdpeek/.bin/RCS.Z/babyl2mh,v 1.1 90/03/22 03:57:05 jdpeek Exp $
X###	babyl2mh - slow way to convert Emacs Rmail files to MH
X###	Usage: babyl2mh +mh-folder [RMAIL-FILE]
X
X#	NOTE: PROGRAM HASN'T BEEN TESTED THOROUGHLY.
X# 	CHECK THE MESSAGES!
X#	Placed in the public domain.  Use at your own risk.
X#		--Jerry Peek, 22 March 1990
X
Xdfltprot=600	# DEFAULT MESSAGE PROTECTION (IF NONE IN MH PROFILE)
Xfolopts="-fast -nolist -nototal -nopack -norecurse"
Xmh=/usr/local/mh
Xmhprofile=/u3/acs/jdpeek/.bin/mhprofile	# READS MH PROFILE
Xscanopts="-noclear -noheader -noreverse"
X
Xcase "$1" in
X[@+]?*)
X	# IF $1 DOESN'T EXIST, folder WILL CREATE IT (SIGH).
X	# THAT'S BECAUSE stdout IS REDIRECTED AWAY FROM TERMINAL.
X	if $mh/folder $folopts "$1" >/dev/null
X	then
X		# GET PATHNAME OF FOLDER, LAST MESSAGE NUMBER:
X		folpath="`$mh/mhpath`" || exit
X		firstmsg="`$mh/scan -format '%(msg)' last`" || exit
X	else
X		echo "`basename $0`: no folder.  quitting." 1>&2
X		exit 1
X	fi
X	;;
X*)	echo "Usage: `basename $0` +folder|@folder [file]
X	('$1' doesn't start with + or @.)" 1>&2
X	exit 1
X	;;
Xesac
X
Xif [ -n "$2" -a \( ! -r "$2" \) ]
Xthen
X	echo "`basename $0`: quitting: can't read Rmail file '$2'." 1>&2
X	exit 1
Xfi
X
X# GET PROTECTION MODE FROM MH PROFILE (IF NONE, USE $dfltprot):
Xmsgprot="`$mhprofile -b msg-protect`" || msgprot=$dfltprot
X
X# MAKE SHELL ARCHIVE FILE ON awk'S STANDARD OUTPUT.
X# PIPE IT INTO sh TO CREATE THE MESSAGE FILES...
Xawk "BEGIN {
X	folpath=\"$folpath\" # STORE AS STRING, WITH QUOTES
X	msgprot=$msgprot     # STORE AS NUMBER (NO QUOTES)
X	msgnum=$firstmsg"'   # CHANGE FROM DOUBLE- TO SINGLE-QUOTES
X	gotflags=0
X	gotgoodhdr=0
X	gotbadhdr=0
X}
X# SKIP BABYL HEADER:
XNR==1, /\037\014/ {
X	next
X}
X# PROCESS MESSAGES.  USE gotflags, ETC. TO "REMEMBER"
X# WHEN WE HAVE PASSED EACH PART OF EACH MESSAGE.
X{
X	# MESSAGE ENDS WITH CTRL-UNDERSCORE AT START OF A LINE.
X	# PRINT SHELL COMMANDS AND RESET FLAGS:
X	if ($0 ~ /^\037/) {
X		printf "END-OF-%s/%d\n\n", folpath, msgnum
X		# SET PROTECTION (INEFFICIENT; SHOULD DO ALL MSGS. AT ONCE)
X		printf "chmod %d %s/%d\n", msgprot, folpath, msgnum
X		gotflags = 0
X		gotgoodhdr = 0
X		gotbadhdr = 0
X		next
X	}
X	# INSTEAD OF FLAGS LINE (LIKE "1,,"), PRINT START OF ARCHIVE:
X	if (gotflags == 0) {
X		gotflags = 1
X		msgnum += 1
X		printf "/bin/cat > %s/%d << \\END-OF-%s/%d\n", \
X			folpath, msgnum, folpath, msgnum
X		next
X	}
X	# PRINT THE FULL HEADER (UP TO FIRST BLANK LINE):
X	if (gotgoodhdr == 0) {
X		if ($0 !~ /^$/) {
X			print
X			next
X		}
X		else {
X			gotgoodhdr = 1
X			next
X		}
X	}
X	# SKIP THE SHORT HEADER (UP TO NEXT BLANK LINE):
X	if (gotbadhdr == 0 && $0 !~ /^$/)
X		next
X	gotbadhdr = 1
X	# PRINT THE MESSAGE (UP TO ^_):
X	print
X	next
X}' $2 |
X/bin/sh -e	# EXIT ON ANY ERROR
X
Xexit # RETURN STATUS FROM PIPE ABOVE
X//E*O*F babyl2mh//
chmod u=rwx,g=rx,o=rx babyl2mh
 
echo extracting - distprompter
sed 's/^X//' > "distprompter" <<'X//E*O*F distprompter//'
X#! /bin/sh
X# $Header: /u3/acs/jdpeek/.bin/RCS/distprompter,v 1.4 90/10/12 09:03:48 jdpeek book $
X###	distprompter - replaces "prompter" for MH "dist" command
X###	Usage (in .mh_profile):    dist: -editor distprompter
X##
X##	BY DEFAULT, THE MH dist COMMAND USES prompter TO EDIT THE DRAFT
X##	MESSAGE.  FOR dist, THAT'S NOT A GREAT CHOICE BECAUSE:
X##		- IF YOU ACCIDENTALLY TYPE A BODY, THE MESSAGE CAN'T BE SENT
X##		- YOU ALWAYS HAVE TO PRESS CONTROL-D TO SKIP THE BODY
X##
X##	distprompter IS AN EDITOR DESIGNED FOR dist.  IT READS THE
X##	EMPTY HEADER THAT dist GIVES IT, LINE BY LINE.  IF A COMPONENT
X##	IS EMPTY, IT PROMPTS YOU.  IF A COMPONENT IS FINISHED, IT DOESN'T
X##	PROMPT.  IF A COMPONENT IS ILLEGAL (NOT Resent-xxx:), IT COMPLAINS.
X##	WHEN IT'S READ THE HEADER, IT EXITS; YOU DON'T NEED CONTROL-D.
X
Xmyname="`basename $0`"
Xerr=/tmp/DISTPRe$$ header=/tmp/DISTPRd$$
X> $header
Xchmod 600 $header
X
Xstat=1	# DEFAULT EXIT STATUS; RESET TO 0 FOR NORMAL EXITS
Xtrap 'rm -f $header $err; exit $stat' 0
Xtrap 'echo "$myname: Interrupt!  Cleaning up..." 1>&2; exit' 1 2 15
X
Xif [ ! -w "$1" -o -z "$1" ]
Xthen
X	echo 1>&2 "$myname: quitting: missing or unwritable draft
X	'$1'"
X	exit
Xfi
X
X# READ DRAFT (A COPY OF distcomps FILE) LINE-BY-LINE.
X# ACT LIKE prompter, BUT EXIT AFTER WE'VE READ DRAFT FILE
X# (WHEN YOU USE dist, THE DRAFT FILE IS ONLY A HEADER).
Xwhile read label line
Xdo
X	case "$label" in
X	[Rr]esent-?*:)
X		case "$line" in
X		?*) # SHOW LINE ON SCREEN AND PUT INTO HEADER FILE:
X			echo "$label $line"
X			echo "$label $line" 1>&3
X			;;
X		*)	# FILL IT IN OURSELVES:
X			echo -n "$label "
X			# stdin IS FROM DRAFT, SO READ DIRECTLY FROM tty:
X			ans="`/usr/ucb/head -1 </dev/tty`"
X			case "$ans" in
X			"") ;;	# EMPTY; DO NOTHING
X			*)	echo "$label $ans" 1>&3 ;;
X			esac
X			;;
X		esac
X		;;
X	""|---*) # END OF HEADER
X		echo "-------" 1>&3
X		break	# PROBABLY NOT NEEDED...
X		;;
X	*)	echo "$myname: illegal header component
X		'$label $line'" 1>&2
X		break
X		;;
X	esac
Xdone <$1 2>$err 3>$header
X
X# IF THE ERROR FILE HAD SOMETHING IN IT, SHOW IT AND QUIT:
Xif [ -s $err ]
Xthen
X	/bin/cat $err 1>&2
X	echo "$myname: quitting." 1>&2
Xelse
X	if /bin/cp $header $1
X	then stat=0
X	else echo "$myname: can't replace draft '$1'?"
X	fi
Xfi
Xexit
X//E*O*F distprompter//
chmod u=rwx,g=rx,o=rx distprompter
 
echo extracting - fixsubj
sed 's/^X//' > "fixsubj" <<'X//E*O*F fixsubj//'
X#! /bin/sh
X# $Header: /u3/acs/jdpeek/.bin/RCS/fixsubj,v 1.9 90/10/13 10:01:45 jdpeek book $
X#
X###	fixsubj - fix (add or change) "Subject:" on a mail message
X###	Usage: fixsubj [+folder] [msgnum [msgnums]] -s 'new subj'
X##
X##	SOME PEOPLE DON'T BOTHER TO PUT A Subject: LINE ON THEIR MAIL
X##	MESSAGES.  THAT MAKES IT HARD, LATER, WHEN YOU scan YOUR MAIL.
X##	fixsubj LETS YOU ADD YOUR OWN Subject: LINE TO MESSAGE(S).
X##	YOU CAN USE THE SAME SUBJECT ON MANY MESSAGES BY GIVING ALL NUMBERS.
X##
X##	IF A MESSAGE ALREADY HAS A SUBJECT, fixsubj WILL TELL YOU
X##	AND ASK YOU IF YOU WANT TO EDIT IT BY HAND, USE THE DEFAULT
X##	FROM -s), OR SKIP IT.
X##
X##	TO USE IT, TYPE:
X##		% fixsubj -s 'this is the subject'	(FOR THE CURRENT MESSAGE)
X##	OR SOMETHING LIKE
X##		% fixsubj +foo last -s 'a subject'	(last MESSAGE IN foo FOLDER)
X##		% fixsubj -s 'my day' 23-25 42	(MESSAGES 23, 24, 25, AND 42)
X##	...AND SO ON.  THE SUBJECT, AFTER THE -s, SHOULD BE "ONE WORD" TO
X##	THE SHELL... YOU'LL USUALLY NEED TO QUOTE IT.  YOU CAN PUT THE
X##	OPTIONAL FOLDER NAME (STARTS WITH A +) AND MESSAGE NUMBERS (NUMBERS,
X##	WORDS LIKE last, first:20, first-33, etc.) IN ANY ORDER.
X
Xeditor=${VISUAL-${EDITOR-/usr/ucb/vi}}   # TEXT EDITOR
Xline="/usr/ucb/head -1"		# READS ONE LINE
Xmh=/usr/local/mh			# WHERE MH COMMANDS LIVE
Xmyname="`basename $0`"		# BASENAME OF THIS PROGRAM
Xscanopts="-noclear -noheader -noreverse" # BYPASS MH PROFILE
Xstat=1	# DEFAULT EXIT STATUS; SET TO 0 BEFORE NORMAL EXIT
Xtemp=/tmp/FIXSUBJ$$
Xtemperr=/tmp/FIXSUBJe$$		# HOLDS ERRORS FROM while LOOP
Xusage="Usage: $myname [+folder] [msgnum] -s 'subject'"
X
Xtrap 'rm -f $temp $temperr; exit $stat' 0 1 2 15
X> $temp
X> $temperr
Xchmod 600 $temp $temperr
X
X# PARSE COMMAND LINE:
Xwhile :
Xdo
X	case "$1" in
X	"")	break ;;	# NO MORE ARGUMENTS
X	-help) echo "$usage" 1>&2; stat=0; exit ;;
X	[@+]*) folder="$1"; shift ;;
X	-s*)
X		case "$2" in
X		"")	echo "$usage
X			(Missing subject.)" 1>&2
X			exit
X			;;
X		*)	newsubj="$2"
X			shift; shift
X			;;
X		esac
X		;;
X	*)	msgs="$msgs $1"; shift ;;
X	esac
Xdone
X
Xcase "$newsubj" in
X"")	echo "$usage
X	(Missing subject.)" 1>&2
X	exit
X	;;
Xesac
X
X# FOLDER PATH; IF NO $folder GIVEN, DEFAULTS TO CURRENT:
Xfolpath="`$mh/mhpath $folder`" || exit
X
X# MAKE LIST OF MESSAGE NUMBERS AND SUBJECTS, ONE PER LINE.
X# IF NO Subject: IN MESSAGE, $subjnow WILL BE EMPTY.
X# FEED INTO LOOP.  IF NO msgs ON COMMAND LINE, SET TO cur.
X#
X# sh WILL RUN THIS IN A SUB-SHELL, SO exit WILL ONLY END
X# THE LOOP, NOT THE WHOLE SCRIPT.  WORK-AROUND: PUT INTERNAL
X# ERRORS ON FILE DESCRIPTOR 3 AND COLLECT AT END OF LOOP:
X$mh/scan $scanopts -width 200 -format "%(msg) %{subject}" ${msgs=cur} |
Xwhile read msg subjnow
Xdo
X	msgpath=$folpath/$msg
X
X	# IF MESSAGE IS UNREADABLE, scan (MH6.6 AND BEFORE)
X	# WILL PRINT A LINE (TO STANDARD OUTPUT!) LIKE THIS,
X	# WITH LEADING BLANKS UNLESS msgnum > 999:
X	#   <msgnum>  unreadable
X	# IF THERE ARE LEADING BLANKS, SOME BOURNE SHELLS WILL
X	# COPY BOTH THE MESSAGE NUMBER AND THE unreadable INTO
X	# subjnow, AND LEAVE $msg EMPTY.  TRY TO FIX BOTH CASES:
X	case "$msg" in
X	"")	echo "$myname: quitting, message $msg $subjnow" 1>&3; break ;;
X	esac
X	case "$subjnow" in
X	unreadable)
X		echo "$myname: quitting: can't read message '$msg'." 1>&3
X		break
X		;;
X	"")	# GLUE Subject AND X-Original-Subject TO TOP.
X		# IF YOUR SHELL DOESN'T UNDERSTAND "<<-", REPLACE IT
X		# WITH "<<" AND SHIFT LINES TO LEFT-HAND EDGE:
X		cat - $msgpath > $temp <<- ENDOFHDR
X		Subject: $newsubj
X		X-Original-Subject: (none)
X		ENDOFHDR
X		cp $temp $msgpath || {
X			echo "$myname: quitting: can't replace ${msgpath}?" 1>&3
X			break
X		}
X		;;
X	*)	# MESSAGE HAS A SUBJECT ALREADY; ASK USER:
X		# LOOP UNTIL GET ANSWER:
X		while :
X		do
X			# SAME NOTE AS ABOVE ABOUT REPLACING "<<-"...
X			cat <<- ENDOFMSG
X
X			Message $msg already has a subject:
X			... $subjnow
X			Type c to change subject to '$newsubj'
X			Type e to edit the message yourself with $editor
X			Type s to skip this message and go on to the next (if any)
X			Type q to quit and not change any more messages.
X			ENDOFMSG
X			echo -n "And the answer is? " 1>&2
X			ans="`$line </dev/tty`"
X			case "$ans" in
X			s*)	break ;; # CONTINUE OUTER (MESSAGE) LOOP
X			q*)	break 2 ;;
X			e*)	$editor $msgpath </dev/tty >/dev/tty 2>/dev/tty
X				break
X				;;
X			c*) # NOTE: FIX "<<-" AND LINES IF SHELL NEEDS:
X				ed - $msgpath <<- !ENDOFEDIT! >$temp 2>&1
X				/^Subject: /s/^/X-Original-/
X				i
X				Subject: $newsubj
X				.
X				w
X				q
X				!ENDOFEDIT!
X				if [ ! -s $temp ]
X				then break
X				else
X					echo "$myname: error editing '$msg':" 1>&2
X					cat "$temp" 1>&2
X					echo "Should you edit it by hand?  Try again:
X					" 1>&2
X				fi
X				;;
X			*)	echo "Please try again..." 1>&2 ;;
X			esac	# END OF case "$ans"
X		done		# END OF while :
X		;;
X	esac			# END OF case "$subjnow"
Xdone 3> $temperr	# END OF while read msg subjnow
X
Xif test -s $temperr
Xthen cat $temperr 1>&2
Xelse stat=0
Xfi
Xexit
X//E*O*F fixsubj//
chmod u=rwx,g=rx,o=rx fixsubj
 
echo extracting - fols
sed 's/^X//' > "fols" <<'X//E*O*F fols//'
X#! /bin/sh
X# $Header: /u3/acs/jdpeek/.bin/RCS/fols,v 1.7 90/10/13 08:45:31 jdpeek book $
X###	fols - Show list of folders, in columns, current folder marked
X###	Usage: fols [ -recurse ]  << (just -r is enough...)
X##
X##	THE folder -fast PROGRAM GIVES A LIST OF YOUR TOP-LEVEL FOLDERS
X##	IN ONE COLUMN.  IF YOU HAVE A LOT OF FOLDERS, THIS CAN BE A PAIN
X##	BECAUSE THE LIST CAN SCROLL OFF YOUR SCREEN.  fols REFORMATS THE
X##	folder -fast OUTPUT INTO FOUR COLUMNS.  IT MARKS THE CURRENT FOLDER
X##	WITH A +.  IF ANY FOLDER NAMES ARE TOO LONG FOR A COLUMN, IT
X##	CUTS OUT THE MIDDLE OF THE NAME AND REPLACES IT WITH AN "=".
X##
X##	BY DEFAULT, fols ONLY SHOWS THE TOP-LEVEL FOLDERS.  THE -r SWITCH
X##	MAKES IT RECURSIVE, LIKE folder -recurse -fast.
X##
X##	HERE'S AN EXAMPLE.  THE EXAMPLE WITH -r SHOWS A SET OF SUB-FOLDERS
X##	NINE LEVELS DEEP, STARTING WITH A SUB-FOLDER NAMED test/l1:
X##
X##	% fols
X##	drafts             haha               inbox+             scans
X##	scantest           test               test2              test3
X##	% fols -r
X##	drafts             haha               haha/sub           inbox+
X##	scans              scantest           test               test/MaIlSoRt9818
X##	test/haha          test/l1            test/l1/l2         test/l1/l2/l3
X##	test/l1/l2/l3/l4   test/l1/=/l3/l4/l5 test/l1/=/l4/l5/l6 test/l1/=/l5/l6/l7
X##	test/l1/=/l6/l7/l8 test/l1/=/l7/l8/l9 test2              test3
X
Xfolopts="-fast -nolist -nototal -nopack" # OVERRIDE MH PROFILE
Xmh=/usr/local/mh  # WHERE MH COMMMANDS ARE
Xrec=
X
Xcase "$#$1" in
X0"") ;;
X1-r*) rec=-recurse ;;
X*)	echo "Usage: `basename $0` [ -recurse ] (just -r is enough)" 1>&2
X	exit 1
X	;;
Xesac
X
X# USE BACKQUOTES TO "PASTE" THE CURRENT FOLDER NAME
X# INTO THE sed EXPRESSION THAT ADDS A + TO END.
X# THEN, IN ANY LINE WHICH HAS AT LEAST 19 CHARACTERS,
X# SAVE FIRST 8 AND LAST 9 CHARACTERS AND REPLACE
X# MIDDLE CHARACTER(S) WITH AN = SIGN.  FINALLY, GIVE
X# TO pr WITH LINE LENGTH OF 1 TO MAKE INTO 4 COLUMNS:
X$mh/folders $rec $folopts |
X/bin/sed -e "s@^`$mh/folder $folopts`\$@&+@" \
X	-e 's/^\(........\)...*\(.........\)$/\1=\2/' |
X/bin/pr -l1 -4 -w78 -t
X//E*O*F fols//
chmod u=rwx,g=rx,o=rx fols
 
echo extracting - incs
sed 's/^X//' > "incs" <<'X//E*O*F incs//'
X#! /bin/sh
X#	$Header: /u1/acs/jdpeek/.bin/RCS/incs,v 1.9 90/07/03 07:18:22 jdpeek Exp $
X#
X###	incs - incorporate messages, then show them
X###	Usage: incs [+folder] [-inc options]
X##
X##	incs DOES AN inc, THEN A show OF ALL MESSAGES inc'D.  IF YOU SET THE
X##	ENVIRONMENT VARIABLE $INCSHOW TO THE NAME OF A PROGRAM (LIKE
X##	mail.review), THEN incs WILL USE IT INSTEAD OF show.
X##
X##	IF YOU GIVE IT A FOLDER NAME, LIKE THIS:
X##		% incs +newmail
X##	IT'LL INCORPORATE THE MAIL INTO THE FOLDER YOU NAME (HERE, newmail).
X
Xumask 077	# MAKE TEMP FILE PRIVATE
Xtemp=/tmp/INCS$$
Xinc=/usr/local/mh/inc
Xstat=1	# DEFAULT EXIT STATUS; RESET TO 0 ON NORMAL EXIT
Xtrap 'rm -f $temp; exit $stat' 0 1 2 15
X
X# ONLY SHOW MESSAGE IF inc ACTUALLY INCORPORATED ONE.
X# BE SURE inc CHANGES CURRENT MESSAGE (OVERRIDE .mh_profile):
Xif $inc -changecur $* > $temp
Xthen
X	cat $temp
X	${INCSHOW-show} cur-last
X	stat=0
Xfi
X//E*O*F incs//
chmod u=rwx,g=rx,o=rx incs
 
echo extracting - mhprofile
sed 's/^X//' > "mhprofile" <<'X//E*O*F mhprofile//'
X#! /bin/sh
X# $Header: /u3/acs/jdpeek/.bin/RCS/mhprofile,v 1.4 90/10/13 08:41:27 jdpeek book $
X#
X###	mhprofile - show matching line(s) from MH profile file
X###	Usage: mhprofile [-b] component-name
X##
X##	USE mhprofile TO READ A LINE FROM THE .mh_profile FILE.
X##	FOR EXAMPLE, IF YOU WANT TO READ THE "DRAFT-FOLDER" LINE, TYPE:
X##		$ mhprofile draft-folder
X##		Draft-Folder: drafts
X##	THE -b OPTION STRIPS OFF THE COMPONENT NAME.  EXAMPLE:
X##		$ mhprofile -b draft-folder
X##		drafts
X##
X##	RETURNS 0 IF MATCH FOUND, 1 IF NO MATCHES, 2 ON ERRORS
X
Xgrep=/bin/grep	# HAS -i OPTION, HANDLES REGULAR EXPRESSIONS
Xsed=/bin/sed
Xprofile=${MH-${HOME?}/.mh_profile}  # COMPLAIN AND EXIT IF $HOME NOT SET
X
X# GET -b OPTION, IF ANY, AND shift IT AWAY:
Xcase "$1" in
X-b)	stripname=y; shift;;
X-*)	echo "Usage: `basename $0` [-b] component-name
X	(I don't understand '$1')." 1>&2
X	exit 2
X	;;
Xesac
X
X# ONLY REMAINING ARGUMENT SHOULD BE A COMPONENT NAME:
Xcase $# in
X1)	;;
X*)	echo "Usage: `basename $0` [-b] component-name
X	(wrong number of arguments)." 1>&2
X	exit 2
X	;;
Xesac
X
X# IF grep FAILS, RETURN ITS STATUS (1=NO MATCH, 2=ERROR):
Xlines="`$grep -i \"^${1}:\" $profile`" || exit
X
X# IF -b SET, USE sed TO SEARCH AND STRIP OFF LABEL+BLANKS.
X# ASSUME NO BLANKS IN NAME, ":" AND MAYBE BLANKS AFTER NAME:
Xcase "$stripname" in
Xy)	echo "$lines" | $sed -n 's/^[^:]*: *//p' ;;
X*)	echo "$lines" ;;
Xesac
Xexit 0	# A LITTLE PRESUMPTUOUS?
X//E*O*F mhprofile//
chmod u=rwx,g=rx,o=rx mhprofile
 
echo extracting - recomp
sed 's/^X//' > "recomp" <<'X//E*O*F recomp//'
X#! /bin/sh
X# $Header: /u3/acs/jdpeek/.bin/RCS/recomp,v 1.6 90/10/13 08:25:07 jdpeek book $
X###	recomp - re-compose a draft mesage in MH draft folder
X###	Usage: recomp [msgnum]
X#
X##	WHEN YOU TYPE q AT A What now? PROMPT, IT LEAVES THE DRAFT MESSAGE
X##	WITHOUT SENDING IT.  IF YOU HAVE A DRAFT FOLDER, THE COMMAND LINE
X##	YOU'D TYPE TO RE-COMPOSE THE DRAFT IS LONG, LIKE:
X##		comp -use -draftm 3 -draftf +drafts -editor vi.
X##	ALSO, IT CAN BE HARD TO REMEMBER THE DRAFT NUMBER--SO YOU HAVE TO
X##	scan THE DRAFT FOLDER, THEN REMEMBER TO CHANGE YOUR FOLDER BACK.
X##	
X##	THIS SCRIPT HELPS WITH THAT.  IF YOU GIVE IT A MESSAGE NUMBER IN THE
X##	DRAFT FOLDER, IT STARTS comp -use ON THAT MESSAGE WITH YOUR FAVORITE
X##	EDITOR PROGRAM.  WITHOUT A MESSAGE NUMBER, recomp scanS THE DRAFT
X##	FOLDER, THEN LETS YOU ENTER THE NUMBER OF THE MESSAGE YOU WANT TO
X##	RE-COMPOSE AND STARTS comp -use.
X##
X##	WHEN YOU EXIT YOUR EDITOR, YOU GET THE USUAL What now? PROMPT.
X
Xdraftf=+drafts	# NAME OF DRAFT FOLDER
Xfolopts="-fast -norecurse -nolist -nototal -nopack"
Xmh=/usr/local/mh	# WHERE MH PROGRAMS LIVE
X
X# THIS CAN LEAVE US IN THE $draftf FOLDER.  SO, PUSH
X# CURRENT FOLDER ON STACK AND COME BACK AFTER EDITING:
X$mh/folder -push $folopts $draftf >/dev/null || {
X	echo "`basename $0`: quitting: problem with draft folder '$draftf'." 1>&2
X	exit 1
X}
Xstat=1   # DEFAULT EXIT STATUS; RESET TO 0 FOR NORMAL EXITS
Xtrap '$mh/folder -pop $folopts >/dev/null; exit $stat' 0
Xtrap 'echo "`basename $0`: Interrupt!  Cleaning up..." 1>&2' 1 2 15
X
Xcase $# in
X0)	# THEY DIDN'T GIVE MESSAGE NUMBER; SHOW THEM FOLDER:
X	if $mh/scan
X	then
X		echo -n "Which draft message number do you want to re-edit? "
X		read msgnum
X	else
X		echo "`basename $0`: quitting: no messages in your $draftf folder?" 1>&2
X		exit
X	fi
X	;;
X1)	msgnum="$1" ;;
X*)	echo "I don't understand '$*'.
X	I need the draft message number, if you know it... otherwise, nothing.
X	Usage: `basename $0` [msgnum]" 1>&2
X	exit
X	;;
Xesac
X
X$mh/comp -use -e ${VISUAL-${EDITOR-${EDIT-vi}}} -draftm $msgnum -draftf $draftf
Xstat=$?   # SAVE comp'S STATUS (IT'S USUALLY 0) FOR OUR exit
X//E*O*F recomp//
chmod u=rwx,g=rx,o=rx recomp
 
echo extracting - replf
sed 's/^X//' > "replf" <<'X//E*O*F replf//'
X#! /bin/sh
X# $Header: /u3/acs/jdpeek/.bin/RCS/replf,v 1.3 90/10/13 08:31:54 jdpeek book $
X###	replf - refile current message into folder, then reply to it
X###	Usage: replf +folder [switches for repl]
X##
X##	DO YOU USE MH FOLDERS A LOT?  YOU PROBABLY inc MAIL INTO YOUR inbox,
X##	THEN YOU replY TO SOME MESSAGES AND refile THE ORIGINALS INTO SOME
X##	OTHER FOLDER.  THE PROBLEM IS THAT IF YOU USE AN Fcc: LINE TO PUT
X##	A COPY OF THE REPLY IN THE DESTINATION FOLDER, IT IS STORED BEFORE
X##	THE ORIGINAL MESSAGE.  ALSO, IT'S A PAIN TO refile THE ORIGINAL,
X##	THEN TYPE THE SAME NAME ON THE Fcc LINE.  SO, IT'D BE CONVENIENT
X##	TO DO ALL THAT IN ONE STEP.  replf LETS YOU DO THAT.
X##
X##	replf USES refile TO MOVE THE *CURRENT* MESSAGE INTO THE FOLDER YOU
X##	NAME.  (IT ONLY WORKS FOR THE CURRENT MESSAGE!)  THEN, IT STARTS
X##	repl WITH THE -fcc +folder SWITCH, SO THAT AN Fcc: OF YOUR MESSAGE
X##	WILL GO INTO THAT FOLDER, TOO.
X##
X##	WATCH OUT: THIS VERSION OF replf HAS ONE PROBLEM:  YOU CAN'T USE
X##		What now? push 
X##	TO SEND THE DRAFT.  THAT'S BECAUSE THE TEMPORARY FILES replf MAKES
X##	ARE REMOVED BEFORE THE MESSAGE IS SENT.  USE send INSTEAD.
X#
X#	Original from Marshall T. Rose and John L. Romine in
X#	MH6.6 distribution.  Revised by Jerry Peek, 2/25/90.
X
Xcontext=/tmp/ctx$$	# COPY OF MH context FILE
Xmh=/usr/local/mh	# WHERE MH COMMANDS LIVE
Xprofile=/tmp/prf$$	# COPY OF .mh_profile FILE
Xstat=1	# DEFAULT EXIT STATUS; RESET TO 0 BEFORE NORMAL exit
X
X/bin/rm -f $profile $context
Xtrap '/bin/rm -f $profile $context; exit $stat' 0 1 2 15
X
X# PARSE COMMAND LINE:
Xfolder=   switches=
Xfor arg
Xdo
X	case "$arg" in
X	+*|@*) # IT'S A FOLDER
X		case "$folder" in
X		"")	folder="$arg" ;;
X		*)	echo "`basename $0`: '$arg'?  Only one folder at a time." 1>&2
X			exit
X			;;
X		esac
X		;;
X	*)	switches="$switches $arg" ;;
X	esac
Xdone
X
Xcase "$folder" in
X"")	echo "usage: `basename $0` +folder [switches for repl]" 1>&2
X	exit
X	;;
Xesac
X
X# MAKE TEMPORARY context AND .mh_profile FILES.
X# THEN, RESET $MH AND $MHCONTEXT UNTIL END OF THIS SCRIPT:
X/bin/cp ${MHCONTEXT-`$mh/mhpath +`/context} $context || exit
X# READ NEXT TWO LINES, PLUS A COPY OF USER'S STANDARD
X# .mh_profile, INTO NEW $profile:
X/bin/cat - ${MH-$HOME/.mh_profile} << \END > $profile || exit
XMH-Sequences:
XPrevious-Sequence: pseq
XEND
X
XMH=$profile MHCONTEXT=$context
Xexport MH MHCONTEXT
X
X# REFILE MESSAGE INTO $folder.
X# NEW MESSAGE NUMBER IS IN THE pseq OF $folder.
X$mh/refile $folder || exit
X$mh/repl $folder pseq -fcc $folder $switches
Xstat=$?		# EXIT WITH STATUS OF repl
Xexit
X//E*O*F replf//
chmod u=rwx,g=rx,o=rx replf
 
echo extracting - resend.fixmsg
sed 's/^X//' > "resend.fixmsg" <<'X//E*O*F resend.fixmsg//'
X#! /bin/sh
X# $Header: /u3/acs/jdpeek/.bin/RCS/resend.fixmsg,v 1.5 90/10/13 09:39:23 jdpeek book $
X###	resend.fixmsg - editor for fixing up returned mail
X###	Usage in .mh_profile:   resend: -editor resend.fixmsg -nodashmunging
X##
X##	TO USE THIS, FIRST MAKE A VERSION OF forw NAMED resend
X##	(MAKE SYMBOLIC LINK TO forw, ETC.).  THEN, ADD THE ENTRY
X##	SHOWN ABOVE TO YOUR .mh_profile.
X##
X##	WHEN YOU START resend, IT BUILDS A DRAFT AND CALLS
X##	resend.fixmsg TO EDIT IT.  resend.fixmsg MAKES THE MESSAGE
X##	LOOK ALMOST EXACTLY AS IT DID THE FIRST TIME YOU COMPOSED
X##	IT, THEN POPS YOU INTO AN EDITOR (DEFAULT: vi) TO FIX THE
X##	ADDRESS.
X
X# $1 IS PATH TO DRAFT MESSAGE (forw SETS THIS).
X# 
X# HERE'S WHAT ed SCRIPT DOES TO THE DRAFT THAT forw BUILT:
X# DELETE LINES THROUGH FIRST "To: (you)".
X# DELETE LINES TO BUT NOT INCLUDING NEXT "To: (original)".
X# ZAP Date:/From:/Sender: LINES THAT MAILER PUT IN MESSAGE.
X# ZAP FROM BLANK LINE BEFORE "---- End of Forwarded Message"
X# THROUGH THE END OF THE FILE.
X/bin/ed - $1 << "END"
X1,/^To: /d
X1,/^To: /-1d
X1,/^$/g/^Date: /d
X1,/^$/g/^From: /d
X1,/^$/g/^Sender: /d
X$
X?^------- End of Forwarded Message?-1,$d
Xw
Xq
XEND
X
X# EDIT WITH $EDITOR (DEFAULT: vi).  exec TO SAVE A PROCESS:
Xexec ${EDITOR-vi} $1
X//E*O*F resend.fixmsg//
chmod u=rwx,g=rx,o=rx resend.fixmsg
 
echo extracting - rmmer
sed 's/^X//' > "rmmer" <<'X//E*O*F rmmer//'
X#! /bin/sh
X# $Header: /u3/acs/jdpeek/.bin/RCS/rmmer,v 3.4 90/11/21 06:52:02 jdpeek Exp $
X###	rmmer - move mail to @DELETE for "find" to clean up
X###	Usage in .mh_profile:    rmmproc: rmmer
X###	rmmer.one_fdr - move mail to +DELETE for "find" to clean up
X###	Usage in .mh_profile:    rmmproc: rmmer.one_fdr
X##
X##	rmmer IS DESIGNED TO BE USED WITH THE MH MAIL rmm COMMAND.
X##	INSTEAD OF JUST ADDING A COMMA (,) TO THE MESSAGE NAME, LIKE
X##	STANDARD rmm DOES, rmmer MOVES THE MESSAGE INTO A SUB-FOLDER
X##	NAMED "DELETE".  A SYSTEM PROGRAM SHOULD CLEAN OUT THAT FOLDER
X##	EVERY SO OFTEN (YOU MAY HAVE TO SET THAT UP, TOO).  ANYHOW,
X##	THE IDEA IS THAT MESSAGES IN A "DELETE" SUB-FOLDER ARE EASY TO
X##	RECOVER IF YOU REMOVED ONE BY ACCIDENT.
X##
X##	FOR EXAMPLE, LET'S SAY YOU JUST DELETED A MESSAGE BY ACCIDENT.
X##	TO GET IT BACK, YOU GO TO THE SUB-FOLDER.  YOUR MESSAGE WILL
X##	BE THE LAST ONE IN THE SUB-FOLDER BECAUSE YOU JUST REMOVED IT.
X##	TO RECOVER THE DELETED MESSAGE, MOVE IT BACK TO THE PARENT FOLDER
X##	(WHERE IT WAS BEFORE) WITH refile.  AFTER YOU RECOVER IT, IT'LL
X##	BE THE LAST MESSAGE IN THE FOLDER.  HERE GOES:
X##		% rmm
X##		% show last @DELETE
X##		(Message inbox/DELETE:25)
X##			(message appears -- this is the one you "deleted")
X##		% refile @..
X##		% show last @..
X##		(Message inbox:54)
X##			(same message appears -- now it's back in the parent folder)
X##
X##	IF YOU DON'T WANT rmmer TO USE A SUB-FOLDER--AND, INSTEAD, PUT
X##	ALL THE MESSAGES IN A CENTRAL "DELETE" FOLDER--YOU CAN CALL THE
X##	PROGRAM WITH THE NAME rmmer.one_fdr AND THAT'LL DO IT.
X
X# TABSTOPS ARE SET AT 4 IN THIS CODE
X
Xtempchr=',' 		# CHARACTER rmm ADDS TO "REMOVE" MESSAGE
Xmh=/usr/local/mh	# MH COMMANDS ARE IN THIS DIRECTORY
Xmoveto=DELETE		# NAME OF FOLDER FOR DELETED MESSAGES
Xmvdir=/bin			# DIRECTORY WHERE mv COMMAND LIVES
X
Xawk=/bin/awk  mkdir=/bin/mkdir  touch=/bin/touch  tr=/bin/tr
X
X# USE PROGRAM NAME TO SET PATH TO DESTINATION FOLDER:
Xcase "$0" in
X*rmmer) destfol="@$moveto" ;;
X*rmmer.one_fdr) destfol="+$moveto" ;;
X*)	echo "$0 aborting: can't find my name." 1>&2; exit 1 ;;
Xesac
X
Xstat=1	# DEFAULT EXIT STATUS; RESET TO 0 BEFORE NORMAL EXIT
Xtrap 'rm -f $MH; exit $stat' 0
Xtrap 'echo "$0: Interrupt!  $* may not be removed." 1>&2; exit' 1 2 15
X
X# TO AVOID ENDLESS LOOPS WHERE THE rmm IN rmmer RUNS rmmproc,
X# MAKE TEMPORARY .mh_profile TO BYPASS USER'S rmmproc: rmmer.
X# MAKE WHILE MH IS SHELL VARIABLE, THEN export TO USE IT:
XMH=/tmp/RMMER$$
Xecho "Path: `$mh/mhpath +`" > $MH || exit
Xexport MH
X
X# rmm SETS CURRENT DIRECTORY TO FOLDER, SO IT'S EASY TO MAKE
X# NEW SUB-FOLDER.  (LET USER MAKE THEIR OWN "+DELETE" ONCE.)
Xif [ "$destfol" = "@$moveto" -a ! -d "$moveto" ]
Xthen $mkdir $moveto || exit
Xfi
X
X# rmm PUTS SINGLE MESSAGE NUMBERS INTO $* (LIKE 12 13 14).
X# UPDATE LAST-MOD TIME SO find -mtime WON'T DELETE TOO SOON:
X$touch $* >/dev/null 2>&1
X
X$mh/rmm $* || exit	# ADDS $tempchr TO MESSAGE NUMBERS
X
X# IF <= 7 MESSAGES, REFILE EACH WITH mv AND mhpath new.
X# OTHERWISE, SAVE TIME BY GETTING FIRST UNUSED MESSAGE NUMBER
X# IN $destfol AND USING PLAIN mv COMMANDS IN A LOOP:
Xcase $# in
X[1-7])
X	for m
X	do $mvdir/mv ${tempchr}$m `$mh/mhpath new $destfol` || exit
X	done
X	;;
X*)	newpath="`$mh/mhpath new $destfol`" || exit	# FIRST MSG.
X	PATH=${mvdir}:$PATH; export PATH	# GET THE RIGHT mv
X	# GIVE awk NUMBERS LIKE 23 24, SPLIT ONTO SEPARATE LINES
X	# BY TURNING SPACES INTO NEWLINES.  OUTPUT mv COMMANDS
X	# THAT THE SHELL READS (BY eval) AND RUNS, LIKE THIS:
X	#	mv ,23 /xxx/Mail/inbox/DELETE/99;
X	#	mv ,24 /xxx/Mail/inbox/DELETE/100;
X	# **HUGE** MESSAGE LISTS MAY CAUSE LONG-LINE PROBLEMS.
X	eval `
X	echo $* | $tr ' ' '\012' | $awk '
X	BEGIN {
X		# SPLIT PATH OF FIRST UNUSED MESSAGE INTO part ARRAY:
X		np = split("'$newpath'", part, "/")
X		# BUILD ALL BUT THE LAST PIECE INTO DIRECTORY NAME:
X		for (i = 2; i < np; i++)
X			dir = dir "/" part[i]
X		# LAST part IS FIRST NEW MESSAGE NUMBER; PUT IN new.
X		# MAKE SURE awk TREATS AS INTEGER BY ADDING ZERO:
X		new = part[np] + 0
X	}
X	{
X		# READ MESSAGE NUMBERS, OUTPUT COMMANDS:
X		printf "mv ,%d %s/%d;", $1, dir, new++
X	}'`
X	;;
Xesac
X
Xstat=0
Xexit
X//E*O*F rmmer//
chmod u=rwx,g=rx,o=rx rmmer
 
echo extracting - scandrafts
sed 's/^X//' > "scandrafts" <<'X//E*O*F scandrafts//'
X#! /bin/sh
X#	$Header: /u3/acs/jdpeek/.bin/RCS/scandrafts,v 1.5 90/10/13 09:08:29 jdpeek book $
X###	scandrafts - scan MH draft folder; return to original folder if no -stay
X###	Usage: scandrafts [-stay] [scan arguments]
X##
X##	THIS SCRIPT IS NICE WHEN YOU'RE WONDERING WHAT'S IN YOUR DRAFT
X##	FOLDER, OR YOU NEED TO WORK IN IT.
X##	
X##	BY DEFAULT, scandrafts SHOWS A LIST OF THE MESSAGES YOU'VE ALREADY
X##	SENT (THESE MESSAGES ARE IN FILES WITH A COMMA OR POUND SIGN BEFORE
X##	THEIR NAMES).  THEN, IT  scanS YOUR DRAFT FOLDER, AND POPS YOU BACK
X##	TO YOUR CURRENT FOLDER.
X##	
X##	IF YOU USE THE -stay OPTION, scandrafts WILL START A SHELL WITH
X##	BOTH THE CURRENT DIRECTORY AND CURRENT FOLDER IN THE DRAFT FOLDER.
X##	THAT WAY, YOU CAN RESTORE ONE OF THE ALREADY-SENT MESSAGES AND/OR
X##	refile IT TO ANOTHER FOLDER (IN CASE YOU FORGOT TO GIVE YOURSELF A
X##	COPY WHEN YOU SENT IT).  OR, YOU CAN DO EXTENSIVE WORK ON THE
X##	DRAFTS, MORE DIRECTLY THAN A SCRIPT LIKE recomp WILL LET YOU.
X##	
X##	HERE'S A DEMONSTRATION:
X##	
X##	$ scandrafts -stay 
X##	Draft message(s) you've already sent:
X##	
X##	,1:Subject: Re: SC or GA islands
X##	,5:Subject: Re: our previous message about banners dialups etc
X##	,6:Subject: Re: Can you help?
X##	,7:Subject: Out this morning
X##	
X##	To get them back, use 'mv'.
X##	===================================================================
X##	Draft message(s) you haven't sent:
X##	
X##	   1  03/07*To:alison@mvus.cs  Project status<<Alison, the project
X##	   2  empty
X##	   3+ 03/07*To:kx9cq@cornell.  Scientific Visualization Demo<<I re
X##	
X##		You'll be in a /usr/local/bin/ksh shell in the +drafts folder.
X##		To quit, type control-d.
X##	scandrafts> rmm 2 
X##	scandrafts> mv ,6 6 
X##	scandrafts> scan 
X##	   1  03/07*To:alison@mvus.cs  Project status<<Alison, the project
X##	   3+ 03/07*To:kx9cq@cornell.  Scientific Visualization Demo<<I re
X##	   6  03/04*To:warren          Re: Can you help?<<Warren, you aske
X##	scandrafts> refile 6 +outbox 
X##	scandrafts> ^D 
X##	[folder +inbox now current]
X##	$
X
Xargs=	# RESET IN CASE THERE'S AN args ENVIRONMENT VARIABLE
Xfolopts="-fast -nolist -nototal -nopack"
Xmh=/usr/local/mh
Xmhprf=/XXXXXXXXXXXXXXXXXX/mhprofile   # READS MH PROFILE
Xpageprog=${PAGER-/usr/ucb/more}	# DISPLAYS SCREEN-BY-SCREEN
Xstat=1	# DEFAULT EXIT STATUS; RESET TO 0 FOR NORMAL EXITS
Xtemp=/tmp/SCANDRFTS$$
X>$temp
Xchmod 600 $temp
Xtrap 'rm -f $temp; exit $stat' 0 1 2 15
X
X# IF -stay SWITCH IS SET, SET $stay TO y:
Xfor arg
Xdo
X	case "$arg" in
X	-stay)	stay=y ;;
X	*)	args="$args $arg" ;;
X	esac
Xdone
X
X# GET DRAFT FOLDER NAME:
Xdraftfold="`$mhprf -b draft-folder`" || {
X	echo "`basename $0`: quitting: can't find your 'Draft-Folder'." 1>&2
X	exit
X}
X
X$mh/folder $folopts -push +$draftfold >/dev/null || exit
Xfolpath=`$mh/mhpath +$draftfold` || exit
Xcd $folpath || exit
X
X# IF ANY UN-SENT DRAFTS, SHOW THEM; THEN, scan FOLDER.
X# PIPE ALL OF IT TO PAGER SO NONE OF IT SCROLLS OFF SCREEN:
Xgrep "^Subject: " [,#]*[1-9]* >$temp 2>/dev/null
X(if test -s $temp
Xthen
X	echo "Draft message(s) you've already sent:
X	"
X	cat $temp
X	echo
X	case "$stay" in
X	y) echo "To get them back, use 'mv'." ;;
X	*) echo "To get them back, use 'cd $folpath' and 'mv'." ;;
X	esac
X	echo "============================================================="
X	echo "Draft message(s) you haven't sent:
X	"
Xfi
X$mh/scan $args 2>&1) | $pageprog
X
X# USE THEIR $SHELL, IF DEFINED... OTHERWISE, USE sh:
Xcase "$stay" in
Xy) echo "
X	You'll be in a ${SHELL-Bourne} shell in the +$draftfold folder.
X	To quit, type control-d."
X	PS1="scandrafts> " ${SHELL-sh}
X	;;
Xesac
X
X# POP FOLDER BACK; PUT NEWLINE BEFORE MESSAGE:
Xecho "
X[folder +`$mh/folder $folopts -pop` now current]"
Xstat=0
X//E*O*F scandrafts//
chmod u=rwx,g=rx,o=rx scandrafts
 
echo extracting - showpr
sed 's/^X//' > "showpr" <<'X//E*O*F showpr//'
X#! /bin/sh
X# $Header: /u3/acs/jdpeek/.bin/RCS/showpr,v 2.2 90/10/13 10:30:57 jdpeek book $
X###	showpr - show MH message(s) with pr(1), custom heading, maybe mhl(1)
X###	Usage: showpr [fdr] [msgs] [-mhl] [-format 'mh-format-str'] [-pr 'pr-opts']
X##
X##	THE EASY WAY TO PRINT MESSAGES IN MH ISN'T ESPECIALLY GREAT.  YOU CAN
X##	PRINT YOUR MAIL MESSAGES LIKE THIS (ASSUMING YOUR PRINTER PROGRAM IS
X##	NAMED lpr), BUT ALL THE MESSAGES WILL BE RUN TOGETHER:
X##		% show 23 24 29 | lpr
X##	OR, YOU CAN USE pr(1) TO MAKE SIMPLE HEADERS (WITH THE FOLDER AND
X##	MESSAGE NUMBER), PAGE NUMBERS, AND START EACH MESSAGE ON A NEW PAGE:
X##		% show -showproc pr 23 24 29 | lpr
X##	
X##	THE showpr PROGRAM LETS YOU DO MORE.  IT CAN USE mhl, IF YOU WANT, TO
X##	CLEAN UP THE MESSAGE BEFORE PRINTING.  YOU CAN CUSTOMIZE THE PAGE HEADING
X##	-- INCLUDING THE MESSAGE SUBJECT, FOR INSTANCE.  AND YOU CAN PASS OPTIONS TO
X##	pr, TO TELL IT HOW TO FORMAT YOUR MESSAGE.  FINALLY, YOU CAN STORE DEFAULT
X##	showpr OPTIONS IN YOUR .mh_profile FILE, BECAUSE showpr CALLS THE mhprofile
X##	SCRIPT TO GET THEM.
X##	
X##	THE COMMAND LINE USES mh-format STRINGS LIKE THE ONES YOU'D GIVE TO
X##	THE scan COMMAND.  HERE ARE SOME EXAMPLES.  SOME OF THESE MIGHT LOOK
X##	COMPLICATED, BUT REMEMBER THAT YOU CAN STORE ANY SET OF OPTIONS AS
X##	DEFAULTS IN YOUR .mh_profile FILE:
X##	
X##	TO PRINT THE CURRENT MESSAGE, WITH THE MESSAGE SUBJECT IN EACH PAGE
X##	HEADING (IF YOU HAVEN'T PUT ANY showpr OPTIONS IN YOUR .mh_profile):
X##		% showpr | lpr
X##	TO PRINT THE LAST 3 MESSAGES, WITH THE MESSAGE SUBJECT IN EACH PAGE
X##	HEADING; FORMAT THE MESSAGES WITH mhl; AND TELL pr TO USE
X##	ITS OPTIONS -f (SEPARATE PAGES WITH FORMFEEDS) AND -l50
X##	(MAKE PAGE LENGTH 50 LINES):
X##		% showpr -mhl -pr '-f -l50' last:3
X##	(YOU CAN SHORTEN THOSE OPTIONS TO -m AND -p, IF YOU WANT.)
X##	
X##	HERE'S MORE.  TO PRINT THE LAST 3 MESSAGES WITH mhl FORMATTING, WITH
X##	THE "From" ADDRESS AND MESSAGE DATE IN THE HEADING, LIKE THIS:
X##		Mar 11 08:49 1990  From: al@phlabs.ph.com  Date: 11/23/89  Page 2 
X##	USE A COMMAND LINE LIKE THIS (SPLIT ONTO TWO LINES FOR READABILITY):
X##		showpr -m -f 'from: %(friendly{from})  \
X##	    	date: %(mon{date})/%(mday{date})/%(year{date})' last:3 | lpr
X##	TO MAKE THAT EASIER, YOU COULD PUT THE FOLLOWING LINE IN
X##	YOUR .mh_profile FILE (NOTE: ALTHOUGH IT'S SPLIT ONTO TWO LINES
X##	HERE, YOU SHOULD PUT IT ALL ON *ONE* LINE IN YOUR .mh_profile FILE):
X##		showpr: -m -f 'from: %(friendly{from})  \
X##		       date: %(mon{date})/%(mday{date})/%(year{date})'
X##	THEN GET THAT FORMATTING AND PRINT YOUR MESSAGES WITH:
X##		% showpr last:3 | lpr
X##	
X##	FINALLY, ABOUT mhl.  YOU CAN MAKE AN mhl FORM FILE NAMED mhl.showpr
X##	AND PUT IT IN YOUR MH DIRECTORY (LIKE /xxx/yyy/Mail/mhl.showpr).
X##	IF YOU DO, AND IF YOU USE THE -mhl OPTION, THEN showpr WILL
X##	FORMAT YOUR MESSAGES WITH mhl -form mhl.showpr.
X##	OTHERWISE, THE -mhl OPTION USES THE STANDARD mhl.format FILE.
X
X# NOTE: TABSTOPS ARE SET AT 4 IN THIS CODE.
X
Xfolopts="-nolist -nototal -nopack"
Xmh=/usr/local/mh			# WHERE MOST MH PROGRAMS LIVE
Xmhl=/usr/local/lib/mh/mhl	# WHERE mhl LIVES
Xmhprofile=/XXXXXXXXXXXXXXXXXX/mhprofile	# READS MH PROFILE
Xmyname="`basename $0`"
Xpr=/bin/pr
Xprwidth=55	# MAX WIDTH OF -h FIELD IN $pr + 5 FOR MSG NUM
Xscanopts="-noclear -noheader -noreverse"
Xstat=1	# DEFAULT EXIT STATUS, RESET TO 0 BEFORE NORMAL EXIT
Xusage="usage: $myname [fdr] [msgs] [-mhl] [-format 'mh-format-str'] [-pr 'pr-opts']"
X
X# RESET "COMMAND LINE" PARAMETERS.  FIRST, AN x, WHICH WE
X# shift AWAY, IN CASE THERE ARE NO OTHER PARAMETERS.
X# THEN, MH PROFILE OPTIONS (IGNORE mhprofile RETURN STATUS).
X# LAST, ORIGINAL COMMAND LINE ARGS (WITH SHELL BUG PATCH):
Xeval set x `$mhprofile -b $myname` '${1+"$@"}'
Xshift
X
X# PARSE set ARGS.  IF OPTIONS REPEATED, LAST ONES PREVAIL:
Xwhile :
Xdo
X	case "$1" in
X	"")	break ;;	# NO MORE ARGUMENTS
X	[+@]*)	newfdr="$1" ;;
X	-h*) # HELP:
X		echo "$usage
X		\$Revision: 2.2 $ \$Date: 90/10/13 10:30:57 $"
X		exit
X		;;
X	-m*) # SET mhlopts AS FLAG TO USE mhl.
X		mhlopts="-nobell -noclear -nofaceproc -nomoreproc"
X		# USE mhl.showpr FILE, IF ANY:
X		if test -r `$mh/mhpath +`/mhl.showpr
X		then mhlopts="$mhlopts -form mhl.showpr"
X		fi
X		;;
X	-f*)
X		case "$2" in
X		"")	echo "$usage
X			(Missing string after '-format')." 1>&2
X			exit
X			;;
X		*)	format="$2"; shift ;;
X		esac
X		;;
X	-p*)
X		case "$2" in
X		"")	echo "$usage
X			(Missing string after '-pr')." 1>&2
X			exit
X			;;
X		+*|-*)	propts="$2"; shift ;;
X		*)	echo "$usage
X			(Bad options after '-pr')." 1>&2
X			exit
X			;;
X		esac
X		;;
X	*)	msgs="$msgs $1" ;;
X	esac
X
X	shift
Xdone
X
X# SET FORMAT OF pr HEADER.  IF NO -format OPTION, AND IF NO
X# "showpr:" LINE IN MH PROFILE, DEFAULT TO MESSAGE SUBJECT:
X: ${format='%{subject}'}
X
X# CHANGE FOLDER (IF USER GAVE ONE), GET NAME.
Xfolder="`$mh/folder $folopts -fast $newfdr`"
Xcd `$mh/mhpath +` || exit	# cd TO MH DIRECTORY
X
X# scan ALL MESSAGES; FEED TO LOOP.  IF NONE, DEFAULT TO cur:
Xscan -width $prwidth $scanopts -format "%(msg) $format" ${msgs-cur} |
Xwhile read msgnum heading
Xdo
X	# IF MESSAGE UNREADABLE, MH 6.6 scan PRINTS (TO stdout!)
X	# LIKE THIS, WITH LEADING BLANKS UNLESS msgnum > 999:
X	#   <msgnum>  unreadable
X	# IF THERE ARE LEADING BLANKS, SOME sh'S WILL COPY BOTH
X	# MESSAGE NUMBER AND unreadable INTO $heading, AND LEAVE
X	# $msgnum EMPTY.  TRY TO CATCH BOTH CASES:
X	case "$msgnum" in
X	"")	echo "$myname: skipping, message $msgnum $heading" 1>&2; continue ;;
X	esac
X	case "$heading" in
X	unreadable) echo "$myname: skipping unreadable message '$msgnum'." 1>&2; continue ;;
X	esac
X
X	msgpath=$folder/$msgnum
X	case "$mhlopts" in
X	"")  $pr $propts -h "$heading" $msgpath || break ;;
X	*) $mhl $mhlopts $msgpath | $pr $propts -h "$heading" || break ;;
X	esac
Xdone
X
Xstat=0
Xexit
X//E*O*F showpr//
chmod u=rwx,g=rx,o=rx showpr
 
echo extracting - vmsmail2mh
sed 's/^X//' > "vmsmail2mh" <<'X//E*O*F vmsmail2mh//'
X#! /bin/sh
X# $Header: /u3/acs/jdpeek/.bin/RCS.Z/vmsmail2mh,v 1.2 90/03/22 06:53:59 jdpeek Exp $
X###	vmsmail2mh - split VMS mail messages from EXTRACT/ALL into MH folder
X###	Usage: vmsmail2mh [+folder] [...vmsmsg-files]
X##
X##	AN EASY WAY TO TRANSFER VMS MAIL MESSAGES TO UNIX IS BY EXTRACTING
X##	ALL THE MESSAGES FROM A VMS MAIL FOLDER INTO A FILE... USE:
X##		MAIL> EXTRACT/ALL
X##		_file: FILENAME
X##	THEN, YOU CAN ftp THEM TO THE SYSTEM RUNNING MH.
X##
X##	WHEN YOU GET THEM TO THE MH SYSTEM, vmsmail2mh WILL READ THROUGH
X##	THE FILE (OR STANDARD INPUT, IF YOU DON'T GIVE A FILENAME):
X##		- THE MESSAGES ARE SEPARATED BY FORMFEEDS (CONTROL-L).
X##		  vmsmail2mh WILL CUT THEM INTO SEPARATE MH MESSAGES
X##		  IN THE CURRENT FOLDER (OR +folder IF YOU GIVE ONE).
X##		- THE FORMAT OF THE VMS MAIL MESSAGE IS DIFFERENT.
X##			* Subj: LINES ARE CONVERTED TO Subject: LINES.
X##			* From: LINES ARE SPLIT INTO From: AND Date: LINES.
X##		  ONLY THE FIRST Subj: AND From: IN EACH MESSAGE IS CONVERTED.
X##
X##	BUG: VMS ADDRESSES LIKE:
X##		SMTP%"user@host"
X##		HOST::USER
X##	AREN'T CONVERTED.  IN FACT, *NO* ADDRESSES ARE CONVERTED.
X
X#	NOTE: PROGRAM HASN'T BEEN TESTED THOROUGHLY.
X# 	CHECK THE MESSAGES!
X#	Placed in the public domain.  Use at your own risk.
X#		--Jerry Peek, 22 March 1990
X
Xdfltprot=600	# DEFAULT MESSAGE PROTECTION (IF NONE IN MH PROFILE)
Xfolopts="-fast -nolist -nototal -nopack -norecurse"
Xmh=/usr/local/mh
Xmhprofile=/u3/acs/jdpeek/.bin/mhprofile	# READS MH PROFILE
Xscanopts="-noclear -noheader -noreverse"
X
Xcase "$1" in
X[@+]?*)
X	# IF $1 DOESN'T EXIST, folder WILL CREATE IT (SIGH).
X	# THAT'S BECAUSE stdout IS REDIRECTED AWAY FROM TERMINAL.
X	if $mh/folder $folopts "$1" >/dev/null
X	then
X		# GET PATHNAME OF FOLDER, LAST MESSAGE NUMBER:
X		folpath="`$mh/mhpath`" || exit
X		firstmsg="`$mh/scan -format '%(msg)' last`" || exit
X	else
X		echo "`basename $0`: no folder.  quitting." 1>&2
X		exit 1
X	fi
X	;;
X*)	echo "Usage: `basename $0` +folder|@folder [file]
X	('$1' doesn't start with + or @.)" 1>&2
X	exit 1
X	;;
Xesac
X
Xif [ -n "$2" -a \( ! -r "$2" \) ]
Xthen
X	echo "`basename $0`: quitting: can't read VMS file '$2'." 1>&2
X	exit 1
Xfi
X
X# GET PROTECTION MODE FROM MH PROFILE (IF NONE, USE $dfltprot):
Xmsgprot="`$mhprofile -b msg-protect`" || msgprot=$dfltprot
X
X# MAKE SHELL ARCHIVE FILE ON awk'S STANDARD OUTPUT.
X# PIPE IT INTO sh TO CREATE THE MESSAGE FILES...
Xawk "BEGIN {
X	folpath=\"$folpath\" # STORE AS STRING, WITH QUOTES
X	msgprot=$msgprot     # STORE AS NUMBER (NO QUOTES)
X	msgnum=$firstmsg"'   # CHANGE FROM DOUBLE- TO SINGLE-QUOTES
X	inmsg = 0
X}
X# PROCESS MESSAGES.  EACH MESSAGE STARTS WITH CONTROL-L.
X# HOPE THERE ARE NO LINES WITH JUST A CONTROL-L IN MESSAGES!
X{
X	# MESSAGE STARTS WITH CTRL-L ON A LINE BY ITSELF.
X	# PRINT SHELL COMMANDS AND RESET FLAGS:
X	if ($0 ~ /^\014$/ && inmsg == 1) {
X		printf "END-OF-%s/%d\n", folpath, msgnum
X		# SET PROTECTION (INEFFICIENT; SHOULD DO ALL MSGS. AT ONCE)
X		printf "chmod %d %s/%d\n\n", msgprot, folpath, msgnum
X		inmsg = 0
X	}
X	# AT START OF MESSAGE, PRINT START OF ARCHIVE AND SET FLAGS:
X	if (inmsg == 0) {
X		inmsg = 1
X		msgnum += 1
X		printf "/bin/cat > %s/%d << \\END-OF-%s/%d\n", \
X			folpath, msgnum, folpath, msgnum
X		didsubj = 0
X		didfrom = 0
X		next
X	}
X	# TURN Subj: INTO Subject: AND SET FLAG TO MAKE SURE WE DO NOT
X	# TRASH ANY OTHER Subj: LINES (LIKE IN FORWARDED MESSAGES).
X	# STRIP DATE (14-MAR-1990 15:31:12.02) OFF END OF THE From: LINE
X	# AND MOVE IT TO LINE OF ITS OWN, THEN SET FLAG LIKE ABOVE:
X	if ($1 ~ /^Subj:/ && didsubj == 0) {
X		$1 = "Subject:"
X		didsubj = 1
X		print
X	}
X	else if ($1 ~ /^From:/ && didfrom == 0) {
X		for (i = 1; i <= NF - 3; i++)
X			printf "%s ", $i
X		printf "%s\n", $(NF - 2)
X		printf "Date: %s %s\n", $(NF - 1), $NF
X		didfrom = 1
X	}
X	else
X		print
X}' $2 |		# IF NO $2, WILL READ STANDARD INPUT...
X/bin/sh -e	# EXIT ON ANY ERROR
X
Xexit # RETURN STATUS FROM PIPE ABOVE
X//E*O*F vmsmail2mh//
chmod u=rwx,g=rx,o=rx vmsmail2mh
 
echo extracting - xmhprint
sed 's/^X//' > "xmhprint" <<'X//E*O*F xmhprint//'
X#! /bin/sh
X# $Header: /u3/acs/jdpeek/.bin/RCS/xmhprint,v 1.3 90/10/14 10:43:03 jdpeek book $
X###	xmhprint - print command for xmh
X###	Usage (in .Xdefaults): xmh*PrintCommand: xmhprint [-cmd_num]
X##
X##	THE PRINTER SUPPORT WITH xmh (X11r3 AND x11r4) ISN'T VERY GOOD.
X##	IT HANDS ALL YOUR MESSAGE FILES TO A PRINTER COMMAND AT ONCE.
X##	IT DOESN'T FILTER THEM TO REMOVE UNINTERESTING HEADER LINES.
X##	YOU CAN'T USE A PIPE AS PART OF THE PRINTER COMMAND BECAUSE xmh 
X##	PUTS THE MESSAGE FILENAMES AT THE END OF THE PRINTER COMMAND LINE.
X##	
X##	THIS PROGRAM, xmhprint, TAKES MESSAGE FILENAMES(S) FROM THE
X##	COMMAND LINE, AS WELL AS (MAYBE) ONE OPTION.
X##	THE SHELL SCRIPT GETS THE MESSAGE FILENAMES FROM xmh, AND IT CAN
X##	PROCESS THEM ANY WAY YOU WANT IT TO.
X##	THE OPTIONS LET YOU CHANGE YOUR PRINT SETUP EASILY--INSTEAD OF
X##	STORING A COMPLICATED xmh*PrintCommand IN THE RESOURCE MANAGER,
X##	JUST CHANGE THE OPTION ON THE xmhprint COMMAND LINE IN .Xdefaults:
X##		xmh*PrintCommand: xmhprint -2
X##	
X##	YOU CAN CUSTOMIZE THIS SCRIPT TO FIT YOUR NEEDS.
X##	ADD mhl(1) TO CLEAN UP THE MESSAGE HEADERS, USE OTHER PRINTERS,
X##	USE A POSTSCRIPT FILTER... GO WILD!
X##
X##	STORE ANY lpr OPTIONS IN THE $PRINTER ENVIRONMENT VARIABLE.
X
X# TABSTOPS IN THIS CODE ARE SET AT 4
X
Xerrsubj="xmh*PrintCommand print ERROR" # FOR MAILED ERRORS
X
X# APPEND ALL ERRORS TO FILE (NEEDS CLEANING PERIODICALLY)
Xerrfile=$HOME/.xmh_printerrs
Xexec >> $errfile 2>&1
X
X# GET OPTION (xmh ALWAYS PUTS FILENAMES LAST):
Xcase "$1" in
X-1)	# JUST pr; PUTS PATHNAME IN HEADER.  NOTHING FANCY:
X	shift
X	pr "$@" | lpr
X	exit
X	;;
X-2)	# SHOW SUBJECT IN pr HEADER OF EACH MESSAGE:
X	shift
X	for f
X	do
X		pr -h "`sed -n '/^[sS]ubject: / {
X			s///p
X			q
X		}' $f`" $f
X	done | lpr
X	exit
X	;;
X"")	echo "No filenames or command line arguments!?!" |
X	mail -s "$errsubj" $USER
X	exit 1
X	;;
X*)	# DEFAULT: SEND ALL OPTIONS AND FILENAMES TO lpr:
X	lpr "$@"
X	exit
X	;;
Xesac
X//E*O*F xmhprint//
chmod u=rwx,g=rx,o=rx xmhprint
 
echo Inspecting for damage in transit...
temp=/tmp/shar$$; dtemp=/tmp/.shar$$
trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
cat > $temp <<\!!!
      65     597    3654 README
      39     277    1521 append
     103     441    2745 babyl2mh
      78     375    2209 distprompter
     163     812    4848 fixsubj
      50     324    2100 fols
      28     152     884 incs
      48     232    1400 mhprofile
      55     355    2091 recomp
      76     432    2518 replf
      37     211    1235 resend.fixmsg
     111     722    4068 rmmer
     113     569    3638 scandrafts
     155     940    5697 showpr
     117     655    3844 vmsmail2mh
      61     326    1900 xmhprint
    1299    7420   44352 total
!!!
wc  README append babyl2mh distprompter fixsubj fols incs mhprofile recomp replf resend.fixmsg rmmer scandrafts showpr vmsmail2mh xmhprint | sed 's/^X//' | diff -b $temp - >$dtemp
if [ -s $dtemp ]
then echo "Ouch [diff of wc output]:" ; cat $dtemp
else echo "No problems found."
fi
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.