* clcommit.m4sh, libltdl/config/mailnotify.m4sh: Rewrite option
parsing loop over M4SH_GETOPTS macro, and adjust all clients of
option variables to use generated option names.
---
 ChangeLog                      |    5 +
 clcommit.m4sh                  |  318 ++++++++++----------------------
 libltdl/config/mailnotify.m4sh |  394 ++++++++++++++++++++--------------------
 3 files changed, 306 insertions(+), 411 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index c511b59..6c397c9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2010-06-05  Gary V. Vaughan  <g...@gnu.org>
 
+       Update and simplify all m4sh scripts to use latest getopt.m4sh.
+       * clcommit.m4sh, libltdl/config/mailnotify.m4sh: Rewrite option
+       parsing loop over M4SH_GETOPTS macro, and adjust all clients of
+       option variables to use generated option names.
+
        Add missing quote for literal ? in a shell case statement.
        * libltdl/config/getopt.m4sh (m4go_shortnoargs): Quote initial ?
        correctly for use in a shell case statement.
diff --git a/clcommit.m4sh b/clcommit.m4sh
index 8c14be2..ff27f9d 100644
--- a/clcommit.m4sh
+++ b/clcommit.m4sh
@@ -1,7 +1,7 @@
 AS_INIT[]m4_divert_push([HEADER-COPYRIGHT])dnl
 # @configure_input@
 
-# clcommit (GNU @PACKAGE@) version 2.0.1
+# clcommit (GNU @PACKAGE@) version 2.1
 # Written by Gary V. Vaughan <g...@gnu.org>
 # and Alexandre Oliva <aol...@redhat.com>
 
@@ -32,16 +32,16 @@ AS_INIT[]m4_divert_push([HEADER-COPYRIGHT])dnl
 #           --debug            enable verbose shell tracing
 # -n        --dry-run          don't commit anything
 #           --fast             same as --force --first
-# -F file   --file=FILE        read commit message from FILE
+# -F FILE   --file=FILE        read commit message from FILE
 # -1        --first            extract first entry from ChangeLog, no git diff
 # -f        --force            don't check (unless *followed* by -n), and just
 #                              display commit message instead of running $PAGER
 #           --from=ADDRESS     override default from ADDRESS in commit email
-# -m msg    --message=STRING   set commit message to STRING
+# -m STRING --message=STRING   set commit message to STRING
 #           --msg=STRING          same as -m
 # -p        --push             push the changes back to origin
 # -r [FILE] --rcfile[=FILE]    read default option from FILE [./.clcommitrc]
-# -s addr   --sendmail=ADDRESS send commit email of the differences to ADDRESS
+# -s ADDR   --sendmail=ADDR    send commit email of the differences to ADDRESS
 #           --signature[=FILE] add FILE to the end of the email [~/.signature]
 #           --signoff          add a Signed-off-by attribution at the end
 # -S TEXT   --summary=TEXT     specify a TEXT subject line for the commit email
@@ -83,19 +83,12 @@ m4_divert_pop
 m4_include([getopt.m4sh])
 
 M4SH_VERBATIM([[
-# Global variables:
-opt_commit=:
-opt_first=false
-opt_push=false
-opt_tags=false
-opt_update=:
-opt_verbose=false
-
-git_flags=
-mailnotify_flags=
-sendmail_to=
+# Locations for important files:
+log_dir="`func_mktempdir`"
+log_file="$log_dir/log"
+push_conflicts="$log_dir/git_push.log"
 
-exit_cmd=:
+trap '$RM -r "$log_dir"; exit $EXIT_FAILURE' 1 2 15
 
 # try to find out whether read supports -r
 if echo bt | tr b '\\' | { read -r line; test "X$line" = 'X\t'; } 2>/dev/null
@@ -104,196 +97,81 @@ then
 else
   read_r=read
 fi
+]])
 
-# Locations for important files:
-signature_file=
-log_dir="`func_mktempdir`"
-log_file="$log_dir/log"
-push_conflicts="$log_dir/git_push.log"
-
-trap '$RM -r "$log_dir"; exit $EXIT_FAILURE' 1 2 15
-
-set -e
-
-# Parse options once, thoroughly.  This comes as soon as possible in
-# the script to make things like `clcommit --version' happen quickly.
-{
-  # sed scripts:
-  my_sed_single_opt='1s/^\(..\).*$/\1/;q'
-  my_sed_single_rest='1s/^..\(.*\)$/\1/;q'
-  my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q'
-  my_sed_long_arg='1s/^--[^=]*=//'
-
-  # this just eases exit handling
-  while test $# -gt 0; do
-    opt="$1"
-    shift
-    case $opt in
-
-      --author|-a)     test $# = 0 && func_missing_arg $opt && break
-                       func_quote_for_eval "$1"
-                       git_flags="$git_flags 
--author=$func_quote_for_eval_result"
-                       shift
-                       ;;
-
-      --[cC]hange[lL]og|-C)
-                       test $# = 0 && func_missing_arg $opt && break
-                       if test -f "$1"; then :; else
-                         func_error "ChangeLog file \`$1' does not exist"
-                         break
-                       fi
-                       ChangeLog="$1"
-                       shift
-                       ;;
-
-      --debug)         func_echo "enabling shell trace mode"
-                       mailnotify_flags="$mailnotify_flags --debug"
-                       set -x
-                       ;;
-
-      --dry-run|-n)    opt_commit=false; opt_update=:          ;;
-
-      --fast)          set dummy --force --first ${1+"$@"}; shift      ;;
-
-      --file|-F)       test $# = 0 && func_missing_arg $opt && break
-                       if $opt_first || test -f "$log_file"; then
-                         func_error "you can have at most one of -m, -F and -1"
-                         break
-                       fi
-                       if cat < "$1" > "$log_file"; then :; else
-                         break
-                       fi
-                       shift
-                       ;;
-
-      --first|-1)      if test -f "$log_File"; then
-                         func_error "you can have at most one of -m, -F and -1"
-                         break
-                       fi
-                       opt_first=:
-                       ;;
-
-      --force|-f)      opt_update=false; PAGER=cat             ;;
-
-      --from)          test $# = 0 && func_missing_arg $opt && break
-                       func_quote_for_eval "$1"
-                       mailnotify_flags="$mailnotify_flags 
--from=$func_quote_for_eval_result"
-                       shift
-                       ;;
-
-      --message|--msg|-m)
-                       test $# = 0 && func_missing_arg $opt && break
-                       if $opt_first || test -f "$log_file"; then
-                         func_error "you can have at most one of -m, -F and -1"
-                         break
-                       fi
-                       echo "$1" > "$log_file"
-                       shift
-                       ;;
-
-      --push|-p)       opt_push=:                              ;;
-
-      --rcfile|-r)     rc_file="./.clcommitrc"
-                       if test $# -gt 0; then
-                         case $1 in
-                           -*)                         ;;
-                           *)  rc_file="$1"; shift     ;;
-                         esac
-                       fi
-                       if test -f "$rc_file"; then :; else
-                         func_error "rcfile \`$rc_file' does not exist"
-                         exit_cmd=exit
-                         break
-                       fi
-                       # The funny quoting allows keeping one option per
-                       # line in $rc_file:
-                       eval set dummy `echo \`cat $rc_file\` \${1+"\$@"}`
-                       shift
-                       ;;
-
-      --sendmail|-s)   test $# = 0 && func_missing_arg $opt && break
-                       func_quote_for_eval "$1"
-                       sendmail_to="$func_quote_for_eval_result"
-                       shift
-                       ;;
-
-      --signature)     test $# = 0 && func_missing_arg $opt && break
-                       signature_file="$HOME/.signature"
-                       case $1 in
-                         -*) ;;
-                         *)  signature_file="$1"; shift ;;
-                       esac
-                       if test -f "$signature_file"; then :; else
-                         func_error "\`$signature_file': file not found"
-                         break
-                       fi
-                       ;;
-
-      --signoff)       git_flags="$git_flags --signoff"        ;;
-
-      --summary|-S)    test $# = 0 && func_missing_arg $opt && break
-                       summary="$1"
-                       shift
-                       ;;
-
-      --tags)          opt_tags=:                              ;;
-
-      --verbose|-v)    opt_verbose=:                           ;;
-
-      # Separate optargs to long options:
-      --*=*)
-                       arg=`echo "$opt" | $SED "$my_sed_long_arg"`
-                       opt=`echo "$opt" | $SED "$my_sed_long_opt"`
-                       set dummy "$opt" "$arg" ${1+"$@"}
-                       shift
-                       ;;
-
-      # Separate optargs to short options:
-      -a*|-m*|-F*|-C*|-S*|-s*)
-                       arg=`echo "$opt" |$SED "$my_sed_single_rest"`
-                       opt=`echo "$opt" |$SED "$my_sed_single_opt"`
-                       set dummy "$opt" "$arg" ${1+"$@"}
-                       shift
-                       ;;
-
-      # Separate non-argument short options:
-      -1*|-f*|-p*|-n*|-q*)
-                       rest=`echo "$opt" |$SED "$my_sed_single_rest"`
-                       opt=`echo "$opt" |$SED "$my_sed_single_opt"`
-                       set dummy "$opt" "-$rest" ${1+"$@"}
-                       shift
-                       ;;
-
-      -\?|-h)          func_usage                                      ;;
-      --help)          func_help                                       ;;
-      --version)       func_version                                    ;;
-      --)              break                                           ;;
-      -*)              func_fatal_help "unrecognized option \`$opt'"   ;;
-      *)               set dummy "$opt" ${1+"$@"};     shift; break            
;;
-    esac
-  done
-
-  if test -z "$sendmail_to"; then
+dnl SHORT      LONG                           DEFAULT                INIT
+dnl ----------------------------------------------------------------------
+M4SH_GETOPTS(
+  [1],         [--first],                      [],                     [],
+  [a^!],       [--author],                     [],                     [
+       git_flags="${git_flags+$git_flags }--author=$opt_author"],
+  [...@],              [--changelog|--Change[Ll]og],   [],                     
[],
+  [F!],                [--file],                       [],                     
[
+       cat "[$]1" > "$log_file" || break],
+  [f],         [--force],                      [],                     [
+       PAGER=cat],
+  [m!],                [--message|--msg],              [],                     
[
+       echo "[$]1" > "$log_file"],
+  [n],         [--dry-run|--dryrun],           [],                     [
+       mailnotify_flags="${mailnotify_flags+$mailnotify_flags }--dry-run"],
+  [p],         [--push],                       [],                     [],
+  [...@?],     [--rcfile],                     [./.clcommitrc],        [
+       # The funny quoting allows keeping one option per line in $opt_rcfile:
+       eval set dummy `echo \`cat $opt_rcfile\` '${1+"[$]@"}'`
+       shift],
+  [S!],                [--summary],                    [],                     
[],
+  [s^!],       [--sendmail],                   [],                     [],
+  [v],         [--verbose],                    [],                     [
+       mailnotify_flags="${mailnotify_flags+$mailnotify_flags }--verbose"],
+  [],          [--fast],                       [],                     [
+       set dummy --force --first ${1+"[$]@"}; shift],
+  [^!],                [--from],                       [],                     
[
+       mailnotify_flags="${mailnotify_flags+$mailnotify_flags 
}--from=$opt_from"],
+  [...@?],             [--signature],                  [],                     
[
+       test -n "$opt_signature" || opt_signature="$HOME/.signature"],
+  [],          [--signoff],                    [],                     [
+       git_flags="${git_flags+$git_flags }$opt"],
+  [],          [--tags],                       [],                     [],
+ [
+  # pass debug flag along to mailnotify
+  $opt_debug &&
+      mailnotify_flags="${mailnotify_flags+$mailnotify_flags }--debug"
+
+  # validate $opt_first, $opt_file and $opt_message
+  if $opt_first; then
+      test -n "$opt_file$opt_message" &&
+          func_error "you can have at most one of -m, -F and -1"
+  else
+      test -n "$opt_file" && test -n "$opt_message" &&
+          func_error "you can have at most one of -m, -F and -1"
+  fi
 
+  # validate $opt_from and $opt_signature
+  test -n "$opt_sendmail" || {
     # can't have a from address without a destination address
-    test -n "$sendmail_from" &&
+    test -n "$opt_from" &&
       func_error "can't use --from without --sendmail." && exit_cmd=exit
 
     # can't use a signature file without a destination address
-    test -n "$signature_file" &&
+    test -n "$opt_signature" &&
       func_error "can't use --signature without --sendmail." && exit_cmd=exit
-  fi
+  }
 
-  $opt_tags && test x"$opt_push" = xfalse &&
-    func_error "can't use --tags without --push." && exit_cmd=exit
+  # validate $opt_tags
+  $opt_push || {
+      $opt_tags &&
+          func_error "can't use --tags without --push." && exit_cmd=exit
+  }
+])
 
-  # Bail if the options were screwed
-  $exit_cmd $EXIT_FAILURE
-}
+M4SH_VERBATIM([[
+# Bail out on command errors!
+set -e
 
 # func_check_conflicts
 func_check_conflicts ()
 {
+    func_verbose "checking for commit conflicts..."
     if $GIT push --dry-run > "$push_conflicts" 2>&1; then :; else
       cat "$push_conflicts" >&2
       func_fatal_error "some conflicts were found with upstream repository, 
aborting..."
@@ -304,25 +182,25 @@ func_check_conflicts ()
 # func_check_commit_msg
 func_check_commit_msg ()
 {
-    if test -z "$ChangeLog"; then
+    if test -z "$opt_changelog"; then
       for f in ${1+"$@"}; do
         case "$f" in
           ChangeLog* | */ChangeLog*)
-            if test -z "$ChangeLog"; then
-             ChangeLog="$f"
+            if test -z "$opt_changelog"; then
+             opt_changelog="$f"
            else
-             func_fatal_error "multiple ChangeLog files: $ChangeLog and $f"
+             func_fatal_error "multiple ChangeLog files: $opt_changelog and $f"
            fi
          ;;
         esac
       done
     fi
 
-    func_verbose "$progname: checking commit message..."
+    func_verbose "checking commit message..."
     separate_summary=:         # whether to separate summary lines for git
     if $opt_first; then
       skipping=:
-      $SED 's,^,+,' < ${ChangeLog-ChangeLog} |
+      $SED 's,^,+,' < ${opt_changelog-ChangeLog} |
         while $read_r line; do
           case "$line" in
             "+") if $skipping; then skipping=false; else break; fi;;
@@ -345,7 +223,7 @@ func_check_commit_msg ()
         done |
           $SED 's,^\+  ,,' > "$log_file" || exit $EXIT_FAILURE
     else
-      $GIT diff ${ChangeLog-ChangeLog} |
+      $GIT diff ${opt_changelog-ChangeLog} |
         while $read_r line; do
           case $line in
             "--- "*) :;;
@@ -387,13 +265,19 @@ func_commit ()
     test $# -gt 0 && subject="$@"
 
     test $# -gt 0 || { set dummy -a; shift; }
-    func_verbose "$GIT commit$git_flags -F $log_file ${...@}"
-    $GIT commit$git_flags -F $log_file ${1+"$@"} || exit $EXIT_FAILURE
+    func_verbose "$GIT commit $git_flags -F $log_file ${...@}"
+    $opt_dry_run ||
+        $GIT commit $git_flags -F $log_file ${1+"$@"} || exit $EXIT_FAILURE
 
-    if $opt_push; then
-      $GIT push
-      $opt_tags && $GIT push --tags
-    fi
+    $opt_push && {
+      func_verbose "$GIT push"
+      $opt_dry_run || $GIT push
+
+      $opt_tags && {
+         func_verbose "$GIT push --tags"
+         $opt_dry_run || $GIT push --tags
+      }
+    }
 
     :
 }
@@ -403,7 +287,7 @@ func_commit ()
 func_mailnotify ()
 {
     notify_file="${log_dir}/notify"
-    func_verbose "Mailing commit notification to $sendmail_to"
+    func_verbose "Mailing commit notification to \"$opt_sendmail\""
 
     {
       echo Subject: $subject
@@ -417,9 +301,9 @@ func_mailnotify ()
       echo ""
       echo "Log Message:"
       $SED -e 's,^,    ,' "$log_file"
-      test -f "$signature_file" && {
+      test -f "$opt_signature" && {
         echo '-- '
-       cat "$signature_file"
+       cat "$opt_signature"
       }
     } > "$notify_file"
 
@@ -434,11 +318,10 @@ func_mailnotify ()
     my_mail_body=`$SED -e '2,$p;d' "$notify_file"`
     echo "$my_mail_body" > "$notify_file"
 
-    func_verbose "mailing commit notification to \"$sendmail_to\""
     func_quote_for_eval "$my_mail_subject"
     func_show_eval "$MAILNOTIFY $mailnotify_flags \
         -s $func_quote_for_eval_result -m 'text/plain' -f '$notify_file' \
-       -- $sendmail_to"
+       -- $opt_sendmail"
 }
 
 
@@ -458,17 +341,18 @@ func_mailnotify ()
     func_error "*** They should be used to separate distinct commits."
   fi
 
-  $opt_update && $opt_push && func_check_conflicts
+  # $opt_force says to force the changes through without checking for conflicts
+  $opt_push && {
+      $opt_force || func_check_conflicts
+  }
 
   # Do not check for empty $log_file again, even though the user might have
   # zeroed it out.  If s/he did, it was probably intentional.
-  if $opt_commit; then
-    func_commit ${1+"$@"}
-  fi
+  func_commit ${1+"$@"}
 
-  # Send a copy of the log_file if sendmail_to was set:
+  # Send a copy of the log_file if opt_sendmail was set:
   subject=`sed -n '1p' "$log_file"`
-  if test -n "$sendmail_to"; then
+  if test -n "$opt_sendmail"; then
     if ! $opt_push; then
       func_warning "Mail notification NOT sent for commit to local repository."
     else
diff --git a/libltdl/config/mailnotify.m4sh b/libltdl/config/mailnotify.m4sh
index a95f201..d8a24e3 100644
--- a/libltdl/config/mailnotify.m4sh
+++ b/libltdl/config/mailnotify.m4sh
@@ -1,10 +1,10 @@
 AS_INIT[]m4_divert_push([HEADER-COPYRIGHT])dnl
 # @configure_input@
 
-# mailnotify (GNU @PACKAGE@) version 0.6
+# mailnotify (GNU @PACKAGE@) version 1.0
 # Written by Gary V. Vaughan <g...@gnu.org>
 
-# Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+# Copyright (C) 2004, 2006, 2010 Free Software Foundation, Inc.
 # This is free software; see the source for copying conditions.  There is NO
 # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
@@ -24,19 +24,17 @@ AS_INIT[]m4_divert_push([HEADER-COPYRIGHT])dnl
 # or obtained by writing to the Free Software Foundation, Inc.,
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
-# Usage: $progname [OPTION]... [--] to-address...
+# Usage: $progname [OPTIONS]...
 #
-#           --debug             enable verbose shell tracing
-# -C ADDR   --carbon-copy=ADDR  send a carbon-copy to ADDR
-# -F ADDR   --from=ADDR         override default from address with ADDR
+# -x        --debug             enable verbose shell tracing
+#           --dry-run           don't actually post the mime message
 # -f FILE   --filename=FILE     content of this part
+# -h FILE   --headers=FILE      read additional headers from FILE
 # -m TYPE   --mime-type=TYPE    mime-type of this part
-# -n                            another mime part (-f, -m) to follow
 # -o FILE   --output-file=FILE  output to FILE instead of sending
-# -s TEXT   --subject=TEXT      set subject header
 # -v        --verbose           run in verbose mode
 #           --version           print version information
-# -h,-?     --help              print short or long help message
+# -?        --help              print short or long help message
 
 # Assemble a (possibly multi-part) mime message and hand it to the local
 # sendmail for onward delivery.  MUAs tend to mangle patch attachments in
@@ -48,12 +46,19 @@ AS_INIT[]m4_divert_push([HEADER-COPYRIGHT])dnl
 # For example to send a patch as an attachment, assuming the patch itself
 # is in PATCHFILE:
 #
-#    echo 'Applied to HEAD' > body
-#    $progname -f body -m text/plain -n -f PATCHFILE -m text/x-patch \
-#        -s 'FYI: PATCHFILE' patch-l...@foo.org
+#    echo 'From: m...@example.org' > headers
+#    echo 'To: patch-l...@foo.org' >> headers
+#    echo 'Subject: FYI: PATCHFILE' >> headers
+#    echo 'Cc: some...@example.org' >> headers
+#    echo 'Applied this patch to HEAD' > body
+#    $progname -h headers -f body -m text/plain -f PATCHFILE -m text/x-patch
+#
+# There is no set order or requirement for mail headers in the headers
+# file, though you will obviously need someone's address in 'To:', and
+# it's not polite to omit the 'Subject:' header...
 
 # You will probably find using this script in conjunction with clcommit
-# or cvsapply will save you an awful lot of typing.
+# saves you a lot of typing.
 
 # Report bugs to <g...@gnu.org>
 
@@ -66,134 +71,78 @@ m4_divert_pop
 m4_include([getopt.m4sh])
 
 M4SH_VERBATIM([[
-# Global variables:
-multipart=1
-outputfile=""
-
 sed_mail_address='s,^.*<\(.*\)>.*$,\1,'
+]])
 
-# Parse options once, thoroughly.  This comes as soon as possible in
-# the script to make things like `mailnotify --version' happen quickly.
-{
-  # sed scripts:
-  my_sed_single_opt='1s/^\(..\).*$/\1/;q'
-  my_sed_single_rest='1s/^..\(.*\)$/\1/;q'
-  my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q'
-  my_sed_long_arg='1s/^--[^=]*=//'
-
-  while test $# -gt 0; do
-    opt="$1"
-    shift
-    case $opt in
-      --debug)         func_echo "enabling shell trace mode"
-                       set -x
-                       ;;
-
-      -C|--carbon-copy) test $# -eq 0 && func_missing_arg "$opt" && break
-                       func_quote_for_eval "$1"
-                       cc="$func_quote_for_eval_result"
-                       shift
-                       ;;
-
-      -F|--from)       test $# -eq 0 && func_missing_arg "$opt" && break
-                       func_quote_for_eval "$1"
-                       from="$func_quote_for_eval_result"
-                       shift
-                       ;;
-
-      -f|--filename)   test $# -eq 0 && func_missing_arg "$opt" && break
-                       if test -f "$1"; then :; else
-                         func_error "\`$1' does not exist"
-                         exit_cmd=exit
-                         break
-                       fi
-                       eval datafile$multipart=\"$1\"
-                       shift
-                       ;;
-
-      -m|--mime-type)  test $# -eq 0 && func_missing_arg "$opt" && break
-                       case $1 in
-                         text/*) ;;
-                         */*) func_error "only text/* mime-types supported"
-                              ;;
-                         *)   func_error "invalid mime-type, \`$1'"
-                              exit_cmd=exit
-                              ;;
-                       esac
-                       eval ctype$multipart=\"$1\"
-                       shift
-                       ;;
-
-      -n)              if eval test -z \"\$ctype$multipart\" ||
-                          eval test -z \"\$datafile$multipart\"; then
-                         func_fatal_error "One part is incomplete -- each part 
needs a filename and a mime-type"
-                       fi
-                       multipart=`expr 1 + $multipart`
-                       ;;
-
-      -o|--output-file)        test $# -eq 0 && func_missing_arg "$opt" && 
break
-                       func_quote_for_eval "$1"
-                       outputfile="$func_quote_for_eval_result"
-                       shift
-                       ;;
-
-      -s|--subject)    test $# -eq 0 && func_missing_arg "$opt" && break
-                       func_quote_for_eval "$1"
-                       subject="$func_quote_for_eval_result"
-                       shift
-                       ;;
-
-      -v|--verbose)    opt_verbose=:                   ;;
-
-      # Separate optargs to long options:
-      
--carbon-copy=*|--from=*|--filename=*|--mime-type=*|--output-file=*|--subject=*)
-                       arg=`echo "$opt" | $SED "$my_sed_long_arg"`
-                       opt=`echo "$opt" | $SED "$my_sed_long_opt"`
-                       set -- "$opt" "$arg" ${1+"$@"}
-                       ;;
-
-      # Separate optargs to short options:
-      -C*|-F*|-f*|-m*|-o*|-s*)
-                       arg=`echo "$opt" |$SED "$my_sed_single_rest"`
-                       opt=`echo "$opt" |$SED "$my_sed_single_opt"`
-                       set -- "$opt" "$arg" ${1+"$@"}
-                       ;;
-
-      # Separate non-argument short options:
-      -n*|-v*)
-                       rest=`echo "$opt" |$SED "$my_sed_single_rest"`
-                       opt=`echo "$opt" |$SED "$my_sed_single_opt"`
-                       set -- "$opt" "-$rest" ${1+"$@"}
-                       ;;
-
-      -\?|-h)          func_usage                                      ;;
-      --help)          func_help                                       ;;
-      --version)       func_version                                    ;;
-      --)              break                                           ;;
-      -*)              func_fatal_help "unrecognized option \`$opt'"   ;;
-      *)               set -- "$opt" ${1+"$@"};      break             ;;
-    esac
-  done
-
-  test $# -gt 0 ||
-    func_fatal_help "no destination address"
-
-  if test -z "$outputfile"; then
-    if test -z "$subject" ||
-       eval test -z \"\$ctype$multipart\" ||
-       eval test -z \"\$datafile$multipart\"; then
+dnl SHORT      LONG                           DEFAULT                INIT
+dnl ----------------------------------------------------------------------
+dnl There are several options supported below for backwards compatibility,
+dnl but which are not mentioned in the help.
+M4SH_GETOPTS(
+  [C^!],       [--carbon-copy],                [],                     [],
+  [F^!],       [--from],                       [],                     [],
+  [...@+],     [--filename],                   [],                     [],
+  [...@!],     [--headers],                    [],                     [],
+  [m+!],       [--mime-type],                  [],                     [
+       case [$]1 in
+         text/*) ;;
+         */*) func_error "\`[$]1': only text/* mime-types supported"
+              ;;
+         *)   func_error "invalid mime-type, \`[$]1'"
+              exit_cmd=exit
+              ;;
+       esac],
+  [n],         [],                             [],                     [],
+  [o!],                [--output-file],                [],                     
[],
+  [s^!],       [--subject],                    [],                     [],
+  [v],         [--verbose],                    [],                     [],
+  [],          [--dry-run|--dryrun],           [],                     [],
+ [
+  # ensure destination address(es) available
+  test [$]# -gt 0 ||
+    grep '^\(To\|Cc\|Bcc\): ' "${opt_headers-nosuchfile}" >/dev/null 2>&1 ||
+      func_fatal_help "no destination address"
+
+  # validate headers
+  test "$opt_headers" && {
+    test -n "$opt_carbon_copy" && grep "^Cc: *" "$opt_headers" >/dev/null 2>&1 
&& {
+      func_error "specify \`Cc:' in either \`$opt_headers' or with 
\`--carbon-copy'."
+      exit_cmd=exit
+    }
+    test -n "$opt_from" && grep "^From: *" "$opt_headers" >/dev/null 2>&1 && {
+      func_error "specify \`From:' in either \`$opt_headers' or with 
\`--from'."
+      exit_cmd=exit
+    }
+    test -n "$opt_subject" && grep "^Subject: *" "$opt_headers" >/dev/null 
2>&1 && {
+      func_error "specify \`Subject:' in either \`$opt_headers' or with 
\`--subject'."
+      exit_cmd=exit
+    }
+  }
+
+  # validate mime parts
+  if test "${opt_mime_type_num-0}" -ne "${opt_filename_num-0}"; then
+    func_fatal_error "One part is incomplete -- each part needs a filename and 
a mime-type"
+  fi
+  if test -z "$opt_output_file"; then
+    test -f "$opt_headers" || if test -z "$opt_subject" ||
+       eval test -z \"\$opt_mime_type_$opt_mime_type_num\" ||
+       eval test -z \"\$opt_filename_$opt_filename_num\"; then
       func_fatal_error "if output is not directed to a file -s, -f, and -m are 
all required"
     fi
   else
-    eval test -n \"\$datafile$multipart\" ||
+    eval test -n \"\$opt_filename_$opt_filename_num\" ||
         func_fatal_error "-f is required."
-    eval test -n \"\$ctype$multipart\" ||
+    eval test -n \"\$opt_mime_type_$opt_mime_type_num\" ||
         func_fatal_error "with output directed to a file, -m is required"
   fi
-  eval test -f \"\$datafile$multipart\" ||
-    eval func_fatal_error \"\$datafile$multipart: file not found\"
-}
 
+  # validate $opt_dry_run
+  $opt_dry_run && SENDMAIL="echo $SENDMAIL"
+])
+
+M4SH_VERBATIM([[
+# Bail out on command errors!
+set -e
 
 # func_headers outfile destination
 # Generate common headers to OUTFILE, where DESTINATION is a comma
@@ -209,14 +158,26 @@ func_headers ()
        }
        d'
 
-    {
+    $opt_dry_run || {
        echo "User-Agent: $PROGRAM/`$SED \"$my_sed_version_no\" < $progpath`"
        echo "MIME-Version: 1.0"
-       test -n "$from" && eval echo From: $from
-       eval echo To: $my_destination
-       test -n "$cc" && eval echo CC: $cc
-       test -n "$subject" && eval echo Subject: $subject
+
+       # Deprecated command line options take precedence at the moment
+       my_elide="Bcc"
+       test -n "$opt_from" &&
+           my_elide="${my_elide+$my_elide\|}From" && eval echo From: $opt_from
+       test -n "$my_destination" &&
+           my_elide="${my_elide+$my_elide\|}To" && eval echo To: 
$my_destination
+       test -n "$opt_carbon_copy" &&
+           my_elide="${my_elide+$my_elide\|}Cc" && eval echo CC: 
$opt_carbon_copy
+       test -n "$opt_subject" &&
+           my_elide="${my_elide+$my_elide\|}Subject" && eval echo Subject: 
$opt_subject
+
+       # Plus any additional headers
+       test -n "$opt_headers" && $SED "/^\($my_elide\): */d" "$opt_headers"
     } > "$my_outfile"
+
+    :
 }
 
 
@@ -226,11 +187,11 @@ func_single_content ()
 {
     my_outfile="$1"
 
-    cat >> "$my_outfile" <<EOF
-Content-Type: $ctype1;
+    $opt_dry_run || cat >> "$my_outfile" <<EOF
+Content-Type: $opt_mime_type_1;
 Content-Transfer-Encoding: 7bit
 
-`cat $datafile1`
+`cat $opt_filename_1`
 EOF
 }
 
@@ -241,7 +202,8 @@ func_multipart_content ()
 {
     my_outfile="$1"
     boundary="boundary-${HOST}-$$-`date | tr ' :' -`"
-    cat <<EOF >> "$my_outfile"
+    $opt_dry_run || {
+       cat <<EOF >> "$my_outfile"
 Content-Type: multipart/mixed;
        boundary="$boundary"
 
@@ -249,31 +211,34 @@ This is a multimedia message in MIME format.  If you are 
reading
 this prefix, your mail reader does not understand MIME.  You may
 wish to look into upgrading to a mime-aware mail reader.
 EOF
-    i=0
-    while test $i -lt $multipart
-    do
-      i=`expr 1 + $i`
-      eval file=\"\$datafile$i\"
-      name=`echo "$file" | $SED $basename`
-      {
-       echo ""
-       echo "--$boundary"
-       if test $i -gt 1; then
-           eval echo \"Content-Type: \$ctype$i\;\"
-           echo "        name=\"$name\""
-       else
-           eval echo \"Content-Type: \$ctype$i\"
-       fi
-       echo "Content-Transfer-Encoding: 7bit"
-       echo ""
-       cat "$file"
-      } >> "$my_outfile"
-    done
-    {
-      echo ""
-      echo "--${boundary}--"
-      echo ""
-    } >> "$my_outfile"
+       i=0
+       while test $i -lt $opt_filename_num
+       do
+           i=`expr 1 + $i`
+           eval file=\"\$opt_filename_$i\"
+           name=`echo "$file" | $SED $basename`
+           {
+               echo ""
+               echo "--$boundary"
+               if test $i -gt 1; then
+                   eval echo \"Content-Type: \$opt_mime_type_$i\;\"
+                   echo "        name=\"$name\""
+               else
+                   eval echo \"Content-Type: \$opt_mime_type_$i\"
+               fi
+               echo "Content-Transfer-Encoding: 7bit"
+               echo ""
+               cat "$file"
+           } >> "$my_outfile"
+       done
+       {
+           echo ""
+           echo "--${boundary}--"
+           echo ""
+       } >> "$my_outfile"
+    }
+
+    :
 }
 
 
@@ -289,25 +254,29 @@ func_sendmail ()
     my_destination="$2"
     my_from="$3"
 
+    $opt_dry_run && my_infile=/dev/null
+
     from_name=`eval echo "X$my_from" | $Xsed -e 's, *<.*> *$,,'`
     from_addr=`eval echo "X$my_from" | $Xsed -e "$sed_mail_address"`
 
     save_PATH="$PATH"
     PATH="/usr/lib:/usr/sbin:$PATH"
 
-    save_IFS="$IFS"
-    IFS=':'
-    for try_sendmail_dir in $PATH; do
+    $opt_dry_run || {
+        save_IFS="$IFS"
+        IFS=':'
+        for try_sendmail_dir in $PATH; do
+            IFS="$save_IFS"
+           PATH="$save_PATH"
+           if test -x "$try_sendmail_dir/$SENDMAIL"; then
+               SENDMAIL="$try_sendmail_dir/$SENDMAIL"
+               break
+           fi
+        done
         IFS="$save_IFS"
-       PATH="$save_PATH"
-       if test -x "$try_sendmail_dir/$SENDMAIL"; then
-           SENDMAIL="$try_sendmail_dir/$SENDMAIL"
-           break
-       fi
-    done
-    IFS="$save_IFS"
-    PATH="$save_PATH"
-    test -x "$SENDMAIL" || func_fatal_error "sendmail executable not found"
+        PATH="$save_PATH"
+        test -x "$SENDMAIL" || func_fatal_error "sendmail executable not found"
+    }
 
     func_verbose "Delivering mail, please wait..."
     if test -n "$from_name"; then
@@ -319,13 +288,40 @@ func_sendmail ()
     fi
     if test $? -eq 0; then
         func_verbose "...succeeded."
-        $RM $my_infile
+        $opt_dry_run || $RM $my_infile
     else
         func_fatal_error "Mail delivery failed, draft mail is in $my_infile"
     fi
 }
 
 
+# func_extract_email_from_header re_header headerfile
+func_extract_email ()
+{
+    my_re_header="$1"
+    my_headerfile="$2"
+    $as_unset func_extract_email_result
+
+    save_IFS="$IFS"
+    IFS='
+'
+    for to in : `grep "$my_re_header" "$my_headerfile" 2>/dev/null`; do
+       IFS="$save_IFS"
+       test "X$to" = X: && continue
+
+       line=`echo "$to" | $SED "s,$my_re_header,,"`
+
+       IFS=,
+       for addr in $line; do
+           IFS="$save_IFS"
+           func_quote_for_eval "$addr"
+           to_addr=`echo "$func_quote_for_eval_result" | $SED 
"$sed_mail_address"`
+           test -n "$to_addr" || to_addr="$func_quote_for_eval_result"
+           
func_extract_email_result="${func_extract_email_result+$func_extract_email_result
 }$to_addr"
+       done
+    done
+    IFS="$save_IFS"
+}
 
 ## ----- ##
 ## main. ##
@@ -333,47 +329,57 @@ func_sendmail ()
 
 {
   tmp_dir="`func_mktempdir`"
+  headers="$tmp_dir/headers"
   fname="$tmp_dir/mail"
+
   trap '$RM -r "$tmp_dir"; exit $EXIT_FAILURE' 1 2 15
 
   # Generate a comma separated list of destination addresses for the
   # mail headers:
-  destination=""
+  $as_unset destination
   for to in : ${1+"$@"}
   do
       test "X$to" = X: && continue
 
       func_quote_for_eval "$to"
-
-      case $destination in
-         "") destination="$func_quote_for_eval_result" ;;
-          *)  destination="$destination, $func_quote_for_eval_result" ;;
-      esac
+      destination="${destination+$destination, }$func_quote_for_eval_result"
   done
-
   func_headers "$fname" "$destination"
-  if test $multipart -gt 1; then
+
+  if test $opt_filename_num -gt 1; then
       func_multipart_content "$fname"
   else
       func_single_content "$fname"
   fi
 
-  # Generate a space delimited list of destination addresses for sendmail:
-  if test -z "$outputfile"; then
-      destination=""
+  # Generate a list of destination addresses for sendmail:
+  if test -z "$opt_output_file"; then
+      $as_unset destination
       for to in : ${1+"$@"}
       do
           test "X$to" = X: && continue
 
          func_quote_for_eval "$to"
 
-          to_addr=`echo "$func_quote_for_eval_result" | sed 
"$sed_mail_address"`
+          to_addr=`echo "$func_quote_for_eval_result" | $SED 
"$sed_mail_address"`
          test -n "$to_addr" || to_addr="$func_quote_for_eval_result"
-         destination="$destination $to_addr"
+         destination="${destination+$destination }$to_addr"
       done
-      func_sendmail "$fname" "$destination" "$from"
+      func_extract_email '^To: *' "$opt_headers"
+      destination="${destination+$destination }$func_extract_email_result"
+      func_extract_email '^Cc: *' "$opt_headers"
+      destination="${destination+$destination }$func_extract_email_result"
+      func_extract_email '^Bcc: *' "$opt_headers"
+      destination="${destination+$destination }$func_extract_email_result"
+
+      test -n "$opt_from" || {
+         func_extract_email '^From: *' "$opt_headers"
+         opt_from="$func_extract_email_result"
+      }
+
+      func_sendmail "$fname" "$destination" "$opt_from"
   else
-      mv $fname $outputfile || exit $EXIT_FAILURE
+      mv $fname $opt_output_file || exit $EXIT_FAILURE
   fi
 
   $RM -r "$tmp_dir"
-- 
1.7.1

Reply via email to