#! /bin/sh
# $Id: forwedit 0.6 1997/06/06 03:33:39 jpeek book4 $
#
### forwedit - editor for MH forw command; makes Subject same as original msg
### Usage (in MH profile):
###     forw: -editor forwedit
### optional, name an editor to use after this script: default is prompter(1):
###     forwedit: -editor someeditor
###
### forwbatch - same as forwedit, but doesn't run an interactive editor
##
##  forwedit sets the Subject: header field of your draft forwarded message
##  to be the same as the subject of the original message with (fwd) after.
##  If you forward more than one message, it uses "Forwarded messages".
##  (You can configure this by setting the $draftsubj shell variable.)
##
##  After doing that, forwedit calls an editor for you to compose the draft
##  header and body; it tries the MH profile entries "forwedit: -editor xxx"
##  and "Editor:", then the environment variables VISUAL and EDITOR.  The
##  default editor is prompter(1).  forwbatch does not invoke an editor.
#
#   Note: there are calls to external utilities in here that could be
#   replaced with hardcoded values to speed up execution on slow systems:
#   "echo a | /bin/tr" and two calls to $mhdir/mhparam.
#   If you have an older MH, you won't have mhparam(1); use the "mhprofile"
#   script from "MH & xmh" Nutshell Handbook instead... or hardcode an editor.
#
#   After you make a "forwedit" file, make a link to it named "forwbatch".
#
#   Tabstops in this code are set at 4 (in vi, use ":se ts=4 sw=4").
#
#   Thanx to David Goodwin, Dan Eisenbud, and Axel Belinfante
#   for bug reports and patches.
#
#   USE AT YOUR OWN RISK.  SEEMS TO WORK, BUT IT'S YOUR RESPONSIBILITY!
#   Please tell me about bugs and fixes: Jerry Peek <jpeek@jpeek.com>
# 
#                             NO WARRANTY
# 
#   BECAUSE THIS PROGRAM IS AVAILABLE FREE OF CHARGE, THERE IS NO WARRANTY
# FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
# OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
# PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
# OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
# TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
# PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
# REPAIR OR CORRECTION.
# 
#   IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
# WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
# REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
# INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
# OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
# TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
# YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
# PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGES.


# Note: $draftsubj is set toward middle of script; configure if you want
mhdir=/usr/local/mh     # Where MH binaries like mhparam live
msgedit=/bin/ed         # For editing draft header
myname=`basename $0`    # Name of this program
showbad="/bin/cat -v"   # Command to show non-printable characters

case $# in
1)  draft="$1"
    if [ ! -r "$draft" -o ! -w "$draft" -o ! -s "$draft" ]; then
        echo "$myname aborting: can't read/write draft '$draft'" 1>&2
        exit 1
    fi
    ;;
*)  echo "$myname aborting: I need one command line argument; I got $#:
    '$*'" 1>&2
    exit 1
    ;;
esac

# Scan message number(s) from $mhmessages environment variable
# (only set with "forw -annotate"; else we scan cur).  Store subject(s).
# If multiple messages, $mhmessages can look like "1-5 23"; let scan(1)
# break those up.
origsubj=`$mhdir/scan -width 1000 -format '%{subject}' ${mhmessages-cur}` || {
    echo "$myname aborting: 'scan ${mhmessages-cur}' failed?" 1>&2
    exit 1
}

# Get subject for forwarded message draft.
# If $origsubj contains a newline, there were multiple messages (and
# "forw -annotate" was used... no way to get this info without -annotate).
# If subject already has "(fwd)", don't add another.
# (To get fancier here, use expr(1) or echo|sed to customize subject.)
case "$origsubj" in
*"
"*) draftsubj="Forwarded messages" ;;
*"(fwd)"*)  draftsubj="$origsubj" ;;
*)  draftsubj="$origsubj (fwd)" ;;
esac

# Edit draft by finding first Subject: line and gluing in $draftsubj.
# This works because ed(1) starts at end of draft; search will wrap
# forward to start of draft and find Subject: in draft header.
#
# ed(1) should be silent.  If it returns any errors, complain and quit.
# Note: ed(1) can bomb on really big messages.
# If this is a problem, replace with sed(1) and a temporary file.
#
# Start by storing a control-A character in $A.  This makes a delimiter
# for ed that's almost surely not in $draftsubj (else, ed could bomb).
# Using echo and tr means we don't have to hardcode a control character here:
A=`echo a | /bin/tr a '\001'`
scmd="/^[Ss]ubject:/s${A}\$${A}$draftsubj${A}"  # substitute command for ed(1)
# echo $scmd, a newline, and a "w" (write) command to ed(1);
# save stderr and stdout, if any, in $edout:
edout=`echo "$scmd
w" | $msgedit - $draft 2>&1`
# Test exit status ($?) and ed output ($edout); should be 0 and empty.
# If not, complain and show editing command we tried:
case "$?$edout" in
0"")
    # Test name script was invoked with to decide if editor should be called:
    case "$myname" in
    forwedit)
        # Find editor to use on draft (default: prompter(1)) and run it:
        profline=`$mhdir/mhparam "$myname"`
        if editor=`expr "$profline" : '.*-editor  *\([^ ]*\)'`
        then :
        elif editor=`$mhdir/mhparam editor`
        then :
        else editor=${editor:-${VISUAL-${EDITOR-$mhdir/prompter}}}
        fi
        exec $editor "$draft"   # Save a process by execing editor
        # Always an error if we get here:  exec failed.
        echo "$myname aborting: 'exec $editor $draft' failed" 1>&2
        exit 1
        ;;
    forwbatch)  ;;  # Don't run interactive editor
    *)  echo "$0: Fatal error: bad invocation name." 1>&2; exit 1;;
    esac
    ;;
*)  # non-zero exit status or ed output.  Complain and quit:
    echo "$myname: '$msgedit - $draft' failed with editor command:
    $scmd" | $showbad 1>&2
    echo "Output, if any, was:
    $edout" 1>&2
    exit 1
    ;;
esac
