libtool-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Update and simplify all m4sh scripts to use latest getopt.m4


From: Gary V. Vaughan
Subject: Re: [PATCH] Update and simplify all m4sh scripts to use latest getopt.m4sh.
Date: Sat, 5 Jun 2010 16:08:47 +0700

Itchy trigger finger. I meant to add:

Okay to push?

On Jun 5, 2010, at 11:45 AM, Gary V. Vaughan <address@hidden> wrote:

* 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  <address@hidden>

+    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 <address@hidden>
# and Alexandre Oliva <address@hidden>

@@ -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"],
+  address@hidden,        [--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],            [],            [],
+  address@hidden,    [--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"],
+  address@hidden,        [--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 address@hidden"
- $GIT commit$git_flags -F $log_file ${1+"$@"} || exit $EXIT_FAILURE
+    func_verbose "$GIT commit $git_flags -F $log_file address@hidden"
+    $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 <address@hidden>

-# 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' address@hidden
+#    echo 'From: address@hidden' > headers
+#    echo 'To: address@hidden' >> headers
+#    echo 'Subject: FYI: PATCHFILE' >> headers
+#    echo 'Cc: address@hidden' >> 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 <address@hidden>

@@ -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],            [],            [],
+  address@hidden,    [--filename],            [],            [],
+  address@hidden,    [--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

[Prev in Thread] Current Thread [Next in Thread]