]> diplodocus.org Git - nmh/blobdiff - uip/mhmail
mhshow: Avoid SEGV when user's command has two or fewer words.
[nmh] / uip / mhmail
index 7353e9a19977b6ef0796869dc7ef2acc1c0deffc..b94886f08af1de10bc9d23962baf23117d419eeb 100755 (executable)
@@ -48,26 +48,45 @@ finddir() {
   esac
 }
 
+help() {
+  printf '%s\n' "$usage"
+  #### Print the nmh intro text.
+  ${nmhbindir}/mhparam -help | sed -n -e '/^$/,$p'
+  exit
+}
+
+#### Convenience function to allow concise code below.
+die() {
+    [ $# -gt 0 ]  &&  printf '%s\n' "$1" >&2
+    exit 1
+}
+
+
 bindir=`finddir $0`
 nmhbindir=`cd "$bindir" && pwd`
+nmhlibexecdir=`$nmhbindir/mhparam libexecdir`
+case `printf 'OK\n' | tail -n 1 2>&1` in
+  OK) tail='tail -n ' ;;
+  *)  tail='tail -' ;;
+esac
 
 
 #### Checks for missing mandatory arguments.
 checkforargs() {
   if [ $attacharg -eq 1 ]; then
-    printf 'mhmail: missing argument to -attach\n' >&2; exit 1
+    die 'mhmail: missing argument to -attach'
   elif [ $bodyarg -eq 1 ]; then
-    printf 'mhmail: missing argument to -body\n' >&2; exit 1
+    die 'mhmail: missing argument to -body'
   elif [ $ccarg -eq 1  -a  "$cclist"x = x ]; then
-    printf 'mhmail: missing argument to -cc\n' >&2; exit 1
+    die 'mhmail: missing argument to -cc'
   elif [ $fromarg -eq 1 ]; then
-    printf 'mhmail: missing argument to -from\n' >&2; exit 1
+    die 'mhmail: missing argument to -from'
   elif [ $headerfieldarg -eq 1 ]; then
-    printf 'mhmail: missing argument to -headerfield\n' >&2; exit 1
+    die 'mhmail: missing argument to -headerfield'
   elif [ $subjectarg -eq 1 ]; then
-    printf 'mhmail: missing argument to -subject\n' >&2; exit 1
+    die 'mhmail: missing argument to -subject'
   elif [ $toarg -eq 1 ]; then
-    printf 'mhmail: missing argument to -to\n' >&2; exit 1
+    die 'mhmail: missing argument to -to'
   fi
 }
 
@@ -80,8 +99,7 @@ fi
 tolist=                     ## To: addresses
 toarg=0                     ## whether currently handling -to
 attacharg=0                 ## whether currently handling -attach
-attach_send_switch_added=0  ## whether added "-attach Nmh-Attachment" switch
-attachind=Nmh-Attachment    ## attachment indicator
+attachind=Attach            ## attachment indicator
 body=                       ## contents of the message body
 bodyarg=0                   ## whether currently handling -body
 cclist=                     ## Cc: addresses
@@ -110,21 +128,16 @@ for arg in "$@"; do
        mhmailswitch=1
        attacharg=1
        use_send=1
-       if [ $attach_send_switch_added -eq 0 ]; then
-         #### Override any send -attach switch in user's profile.
-         postsendargs="${postsendargs:+$postsendargs }-attach $attachind"
-         attach_send_switch_added=1
-       fi ;;
+       ;;
     -b|-bo|-bod|-body) mhmailswitch=1; bodyarg=1 ;;
     -c|-cc) mhmailswitch=1; ccarg=1 ;;
     -f|-fr|-fro|-from) mhmailswitch=1; fromarg=1 ;;
     -hea|-head|-heade|-header|-headerf|-headerfi|-headerfie|-headerfiel|\
 -headerfield) mhmailswitch=1; headerfieldarg=1 ;;
-    -hel|-help) printf '%s\n' "$usage"; exit ;;
+    -hel|-help) help ;;
     -nose|-nosen|-nosend) mhmailswitch=1; sendsw=0 ;;
     -p|-pr|-pro|-prof|-profi|-profil|-profile) mhmailswitch=1; use_send=1 ;;
-    -resend) printf 'mhmail: did you mean -resent instead of -resend?\n' >&2
-       exit 1 ;;
+    -resend) die 'mhmail: did you mean -resent instead of -resend?' ;;
     -r|-re|-res|-rese|-resen|-resent) mhmailswitch=1; resent=1 ;;
     -se|-sen|-send) mhmailswitch=1; sendsw=1 ;;
     -su|-sub|-subj|-subje|-subjec|-subject) mhmailswitch=1; subjectarg=1 ;;
@@ -160,7 +173,8 @@ for arg in "$@"; do
          #### It's not strictly necessary to have one space after
          #### the : that separates the header field name from the
          #### body, but do it to avoid surprising someone.
-         add=`printf %s "$arg" | sed -e 's/:/: /' -e 's/:  /: /'`
+         #### Solaris sed wants the trailing newline in its input.
+         add=`printf '%s\n' "$arg" | sed -e 's/:/: /' -e 's/:  /: /'`
          headerfieldlist="${headerfieldlist:+$headerfieldlist}$add
 "
          headerfieldarg=0
@@ -179,11 +193,10 @@ done
 
 #### Check for at least one address and -from.
 if [ "$tolist"x = x ]; then
-  printf 'Usage: mhmail [-t(o)] addrs ... [switches]\n' >&2; exit 1
+  die 'Usage: mhmail [-t(o)] addrs ... [switches]'
 fi
 if [ "$from"x = x ]; then
-  nmhlibdir=`$nmhbindir/mhparam libdir`/
-  from=`${nmhlibdir}ap -format '%(localmbox)' 0`
+  from=`${nmhlibexecdir}/ap -format '%(localmbox)' 0`
 fi
 
 #### Check for missing mandatory arguments.
@@ -204,13 +217,16 @@ if [ "$headerfieldlist" ]; then
   header="$header$headerfieldlist"
 fi
 
-#### Set up a file to supply as a draft to post/send.  And set a
-#### trap to remove it.  send moves the file to a backup, so it will
-#### remove that, too.
+#### Set up a file to supply as a draft to post/send.  And set a trap
+#### to remove it.  send moves the file to a backup and can create a
+#### .orig file, so it will remove them, too.
 umask 077
-tmpdir="${MHTMPDIR:-${TMPDIR:-${TMP:-`$nmhbindir/mhpath +`}}}"
-tmpfile="$tmpdir/mhmail$$"
-tmpfilebackup="\"$tmpdir\"/[,#]mhmail$$"
+tmpdir="${MHTMPDIR:-${TMPDIR:-`$nmhbindir/mhpath +`}}"
+tmpfilename=`cd "$tmpdir"  &&  "${nmhlibexecdir}/mkstemp" -p mhmail`
+[ $? -ne 0 ]  &&  die "mhmail: failed to create temporary file in $tmpdir"
+tmpfile="$tmpdir/$tmpfilename"
+backup_char=`"$nmhbindir"/mhparam sbackup`
+tmpfilebackup="$tmpdir/${backup_char}${tmpfilename}*"
 tmpfileresent=
 
 message_file=
@@ -219,20 +235,19 @@ if [ $resent -eq 0 ]; then
   header="$header
 "
   message_file="$tmpfile"
+elif [ $use_send -eq 0 ]; then
+  postsendargs="${postsendargs:+$postsendargs }-dist"
+  message_file="$tmpfile"
 else
-  if [ $use_send -eq 0 ]; then
-    postsendargs="${postsendargs:+$postsendargs }-dist"
-    message_file="$tmpfile"
-  else
-    #### When resending with send, tmpfile will just contain the
-    #### Resent- header fields.  "$tmpfileresent" will contain
-    #### the message that is being resent.
-    tmpfileresent="$tmpdir/mhmail-resent$$"
-    mhdist=1; export mhdist
-    mhaltmsg=$tmpfileresent; export mhaltmsg
-    message_file="$tmpfileresent"
-    printf '' >"$message_file"  || exit 2
-  fi
+  #### When resending with send, tmpfile will just contain the
+  #### Resent- header fields.  "$tmpfileresent" will contain
+  #### the message that is being resent.
+  tmpfileresent=`"${nmhlibexecdir}/mkstemp" -d "$tmpdir" -p mhmail-resent`
+  [ $? -ne 0 ]  &&  die "mhmail: failed to create temporary file in $tmpdir"
+  mhdist=1; export mhdist
+  mhaltmsg=$tmpfileresent; export mhaltmsg
+  message_file="$tmpfileresent"
+  printf '' >"$message_file"  || exit 2
 fi
 
 trap "rm -f '$tmpfile' $tmpfilebackup ${tmpfileresent:+'$tmpfileresent'}" 0
@@ -250,17 +265,16 @@ if [ "$body"x = x ]; then
   #### Don't allow an empty body (from stdin).  Use string
   #### comparison so we don't have to strip the filename, etc.
   if [ "$tmpfile_size_before" = "$tmpfile_size_after" ]; then
-    printf 'mhmail: empty message not sent, use -body '"''"' to force.\n' >&2
-    exit 1
+    die 'mhmail: empty message not sent, use -body '"''"' to force.'
   fi
 
   #### Add trailing newline to body if it doesn't have one.
-  if [ `tail -n 1 "$message_file" | wc -l` -ne 1 ]; then
+  if [ `${tail}1 "$message_file" | wc -l` -ne 1 ]; then
     printf '\n' >>"$message_file" || exit 2
   fi
 else
   #### Add trailing newline to body if it doesn't have one.
-  [ `printf %s "$body" | tail -n 1 | wc -l` -ne 1 ]  &&  body="$body
+  [ `printf %s "$body" | ${tail}1 | wc -l` -ne 1 ]  &&  body="$body
 "
 
   if [ "$tmpfileresent" ]; then
@@ -283,12 +297,11 @@ else
     post_or_send="$nmhbindir/send"
   fi
 
-  if "$post_or_send" "$tmpfile" $postsendargs; then
+  if "$post_or_send" $postsendargs "$tmpfile"; then
     exit
-  else
-    status=$?
-    mv -f "$tmpfile" dead.letter
-    printf 'Letter saved in dead.letter\n' >&2
-    exit $status
   fi
+  status=$?
+  mv -f "$tmpfile" dead.letter
+  printf 'Letter saved in dead.letter\n' >&2
+  exit $status
 fi