1) Added -from switch.
2) sendfiles will now construct a From address, using the sender's
localmbox, if the user does not specify it with -from or the PERSON
environment variable.
3) Added support for bzip2, lzma, and zip compression methods. Added
a new switch to select the method: -compress <method>. Because
support for the old -compress with was broken (it did not use
-c with compress/uncompress) and it was undocumented, it has
been replaced. Retained old -gzip and -none switches for backward
compatibility even though they were undocumented.
4) Allow the recipient argument to be preceded by the optional -to
switch iff the subject argument is preceded by the optional
-subject switch. Allow the delay value to be specified using the
optional -delay switch.
5) Added -version and -help switches.
6) All switches can now be abbreviated.
/etc/sendfiles no longer needs to be configured. It's easier to
support make distcheck by having it figure out its path at runtime.
In viamail, set postproc to post in the same directory as itself, if
invoked with a full path. This allows it to support make distcheck.
viamail does not read the profile so its postproc is otherwise
hard-coded at compile time.
Added test-sendfiles.
/config/version.c
/etc/mhn.defaults
/etc/mts.conf
-/etc/sendfiles
/man/*.[1578]
/man/man.sed
/man/mh-chart.man
test/post/test-post-dcc test/post/test-post-fcc \
test/post/test-post-multifrom test/post/test-post-envelope \
test/post/test-post-group test/post/test-mts test/post/test-messageid \
- test/prompter/test-prompter \
+ test/post/test-sendfiles test/prompter/test-prompter \
test/rcv/test-rcvdist test/rcv/test-rcvpack test/rcv/test-rcvstore \
test/rcv/test-rcvtty test/refile/test-refile \
test/repl/test-if-str test/repl/test-trailing-newline \
##
## Stuff that should be cleaned via "make clean"
##
-CLEANFILES = config/version.c sbr/sigmsg.h etc/mts.conf etc/sendfiles \
+CLEANFILES = config/version.c sbr/sigmsg.h etc/mts.conf \
etc/mhn.defaults man/man.sed man/mh-chart.man $(man_MANS)
clean-local:
@rm -rf RPM a.out.dSYM uip/a.out.dSYM
## Files we need to include in the distribution which aren't found by
## Automake using the automatic rules
##
-EXTRA_DIST = config/version.sh sbr/sigmsg.awk etc/mts.conf.in etc/sendfiles.in \
- etc/mhn.defaults.sh $(MHNSEARCHPROG) DATE MACHINES \
+EXTRA_DIST = config/version.sh sbr/sigmsg.awk etc/mts.conf.in \
+ etc/mhn.defaults.sh etc/sendfiles $(MHNSEARCHPROG) DATE MACHINES \
docs/ChangeLog_MH-3_to_MH-6.6 \
docs/ChangeLog_MH-6.7.0_to_MH-6.8.4.html \
man/ali.man man/anno.man man/ap.man man/burst.man man/comp.man \
@rm -f $@
$(srcdir)/etc/mhn.defaults.sh $(MHNSEARCHPATH) $(MHNSEARCHPROG) > $@
-etc/sendfiles: $(srcdir)/etc/sendfiles.in Makefile
- @rm -f $@
- $(SED) -e 's,%libdir%,$(libdir),' < $(srcdir)/etc/sendfiles.in > $@
-
##
## Use configure to set up default LN, but through a make variable so
## that it can be overridden at install time.
--- /dev/null
+#!/bin/sh
+#
+# Sends multiple files and/or directories in a MIME message.
+# Requires tar and any specified compression program.
+#
+# This code is Copyright (c) 2012, by the authors of nmh. See the
+# COPYRIGHT file in the root directory of the nmh distribution for
+# complete copyright information.
+
+usage='Usage: sendfiles [switches] -to recipient -subject subject '"\
+"'file1 [file2 ...]
+ or
+ sendfiles [switches] recipient subject file1 [file2 ...]
+ switches are:
+ -compress [bzip2 | compress | gzip | lzma | none | zip]
+ -from <sender>
+ -[delay] <delay> (expressed in seconds)
+ -version
+ -help
+ Can use PERSON environment variable instead of -from switch.'
+
+
+#### Find location of a program. Bourne shell just puts the name in
+#### $0 if it's found from the PATH, so search that if necessary.
+finddir() {
+ case $1 in
+ */*) dirname "$1" ;;
+ * ) IFS=:
+ for d in $PATH; do
+ [ -f "${d:=.}/$1" -a -x "$d/$1" ] && printf %s "$d" && break
+ done ;;
+ esac
+}
+
+die() {
+ printf '%s\n' "$usage"; exit ${1:-1}
+}
+
+bindir=`finddir $0`
+nmhbindir=`cd "$bindir" && pwd`
+nmhlibdir=`$nmhbindir/mhparam libdir`
+
+
+#### Process switches.
+compress= ## compress method
+compressarg=0 ## whether currently handling -compress
+delay= ## delay value
+delayarg=0 ## whether currently handling -delay
+from= ## From: contents
+fromarg=0 ## whether currently handling -from
+subject= ## Subject: contents
+subjectarg=0 ## whether currently handling -subject
+to= ## To: address
+toarg=0 ## whether currently handling -to
+for arg in "$@"; do
+ case $arg in
+ -c|-co|-com|-comp|-compr|-compre|-compres|-compress) compressarg=1 ;;
+ -d|-de|-del|-dela|-delay) delayarg=1 ;;
+ -[0-9]|-[0-9][0-9]|-[0-9][0-9][0-9]|-[0-9][0-9][0-9][0-9])
+ delay=`printf '%s\n' "$arg" | sed -e 's%-%%'` ;;
+ -f|-fr|-fro|-from) fromarg=1 ;;
+ #### Support -gzip for backward compatibility.
+ -gzip) compress=gzip ;;
+ -h|-he|-hel|-help) die 0 ;;
+ #### Support -none for backward compatibility.
+ -none) compress=none ;;
+ -s|-su|-sub|-subj|-subje|-subjec|-subject) subjectarg=1 ;;
+ -t|-to) toarg=1 ;;
+ -v|-ve|-ver|-vers|-versi|-versio|-version)
+ "$nmhlibdir/viamail" -version | sed 's/viamail/sendfiles/'; exit ;;
+ -*) die ;;
+ *) if [ $compressarg -eq 1 ]; then
+ compress="$arg"
+ compressarg=0
+ elif [ $delayarg -eq 1 ]; then
+ delay="$arg"
+ delayarg=0
+ elif [ $fromarg -eq 1 ]; then
+ from="$arg"
+ fromarg=0
+ elif [ $subjectarg -eq 1 ]; then
+ subject="$arg"
+ subjectarg=0
+ elif [ $toarg -eq 1 ]; then
+ to="$arg"
+ toarg=0
+ else
+ #### Argument doesn't apply to a switch, so we're done with switches.
+ break
+ fi ;;
+ esac
+ shift
+done
+
+#### Check for switch after non-switch argument.
+for arg in "$@"; do
+ case $arg in
+ -*) die ;;
+ esac
+done
+
+#### Check for required arguments (to, subject, file(s)).
+if [ x"$to" = x ]; then
+ if [ x"$subject" = x ]; then
+ if [ $# -ge 3 ]; then
+ to="$1"; shift
+ subject="$1"; shift
+ else
+ die
+ fi
+ else
+ die
+ fi
+else
+ [ x"$subject" = x -o $# -lt 1 ] && die
+fi
+
+#### Check for missing mandatory arguments.
+checkforargs() {
+ if [ $compressarg -eq 1 ]; then
+ printf 'sendfiles: missing argument to -compress\n' >&2; exit 1
+ elif [ $delayarg -eq 1 ]; then
+ printf 'sendfiles: missing argument to -delay\n' >&2; exit 1
+ elif [ $fromarg -eq 1 ]; then
+ printf 'sendfiles: missing argument to -from\n' >&2; exit 1
+ elif [ $subjectarg -eq 1 ]; then
+ printf 'sendfiles: missing argument to -subject\n' >&2; exit 1
+ elif [ $toarg -eq 1 ]; then
+ printf 'sendfiles: missing argument to -to\n' >&2; exit 1
+ fi
+}
+
+checkforargs
+[ $# -eq 0 ] && die
+
+
+if [ x"$from" = x ]; then
+ if [ x"$PERSON" = x ]; then
+ from=`"$nmhlibdir/ap" -format '%(localmbox)' 0`
+ else
+ from="$PERSON"
+ fi
+fi
+
+
+#### Determine compression method and descriptive info.
+if [ x"$compress" = x ]; then
+ for compressor in gzip bzip2 lzma zip compress none; do
+ if [ x"`finddir $compressor`" = x ]; then :; else
+ compress="$compressor"
+ break
+ fi
+ done
+fi
+
+case $compress in
+ bzip2) uncompress=bzcat; conversion='; x-conversions=bzip2' ;;
+ compress) compress='compress -c'; uncompress='uncompress -c';
+ conversion='; x-conversions=compress' ;;
+ gzip) compress='gzip -c'; uncompress='gzip -cd'
+ conversion='; x-conversions=gzip' ;;
+ lzma) compress='lzma -c'; uncompress='lzma -cd'
+ conversion='; x-conversions=lzma' ;;
+ zip) compress='zip -q'; uncompress='unzip -p'
+ conversion='; x-conversions=zip' ;;
+ none) compress=cat uncompress=cat; conversion= ;;
+ *) printf 'sendfiles: unknown compression method "%s"\n' \
+ "$compress" >&2
+ die ;;
+esac
+
+
+#### Send using viamail.
+tar cvf - "$@" | $compress | \
+ "$nmhlibdir/viamail" -to "$to" -subject "$subject" \
+ -from "$from" -parameters "type=tar$conversion" \
+ -comment "extract with $uncompress | tar xvpf -" \
+ -delay "$delay" -verbose
+++ /dev/null
-#!/bin/sh
-#
-# Send multiples files and/or directories as a tar/compressed
-# image, in a MIME message.
-#
-
-DELAY=0
-FROM=
-
-# compression method (none, gzip or compress)
-METHOD=none
-# compression filter
-COMPRESS=cat
-# uncompression filter
-UNCOMPRESS=cat
-# compression description to append to content-type
-CONVERSION=
-
-# default compression method based on installed software
-# prefer compress over gzip for backward compatibility
-if command -v compress >/dev/null 2>&1 ; then
- METHOD=compress
-elif command -v gzip >/dev/null 2>&1 ; then
- METHOD=gzip
-fi
-
-# handle command-line options to override compression method and delay
-while [ $# -gt 3 ]; do
- case "$1" in
- -gzip) METHOD=gzip
- shift
- ;;
- -compress) METHOD=compress
- shift
- ;;
- -none) METHOD=none
- shift
- ;;
- -*) DELAY="`echo $1 | sed -e 's%-%%'`"
- shift
- ;;
- *) break
- ;;
- esac
-done
-
-# set variables based on chosen compression method
-if [ $METHOD = compress ]; then
- COMPRESS=compress
- UNCOMPRESS=uncompress
- CONVERSION="; x-conversions=compress"
-elif [ $METHOD = gzip ]; then
- COMPRESS="gzip -c"
- UNCOMPRESS="gzip -dc"
- CONVERSION="; x-conversions=gzip"
-fi
-
-if [ ! -z "$PERSON" ]; then
- FROM="-from $PERSON"
-fi
-
-if [ $# -lt 3 ]; then
- echo 'usage: sendfiles: "mailpath" "subject-string" directory-or-file ...' 1>&2
- exit 1;
-fi
-
-mailpath="$1"
-echo "mailpath = $mailpath" 1>&2
-shift
-
-subject="$1"
-echo "subject-string = $subject" 1>&2
-shift
-
-echo "files = $*" 1>&2
-
-tar cvf - "$@" | $COMPRESS | \
- %libdir%/viamail -to "$mailpath" -subject "$subject" \
- -parameters "type=tar$CONVERSION" \
- -comment "extract with $UNCOMPRESS | tar xvpf -" \
- -delay "$DELAY" \
- -verbose $FROM
.HP 5
.na
.B sendfiles
-.RB [ \-bzip2 " | " \-compress " | " \-gzip " | " \-lzma " | " \-none " | " -zip ]
+.RB [ -compress
+.IR bzip2 " | " compress " | " gzip " | " lzma " | " none " | " zip ]
.br
.RB [ \-from
.IR sender ]
-.RI [ \-delay ]
+.RI [ "\-delay n" " | " \-n ]
.RB [ \-version ]
.RB [ \-help ]
.br
+.B \-to
+.I recipient
+.B \-subject
+.IR subject " | "
.I recipient
.I subject
+.br
.I file/directory1
.RI [ file/directory2
\&...]
of files and directories via electronic mail.
.PP
.RS 5
-sendfiles recipient \*(lqsubject\*(rq files\0...
+sendfiles -to recipient -subject \*(lqsubject\*(rq files\0...
.RE
.PP
.B sendfiles
in order to get past most mailers.
.PP
The
+.B \-to
+switch specifies the recipient. The
+.B \-subject
+switch specifies the subject. Alternatively, these two required values
+can be provided without their corresponding switch names.
+.PP
+The
.B \-from
switch can, and should, be used to specify the sender's mailbox (name
and email address). Alternatively, the
in
.IR mh-format (5).
.PP
-The remaining command line switches select the compression program.
-One of these can be used to override the run-time determination of
-the compression program by
+The
+.B \-compress
+command line switch can be used to override the run-time determination
+of the compression program by
.BR sendfiles .
+.B \-compress
+.I none
+(alternatively,
+.BR \-none )
+disables compression.
.PP
Sometimes you want
.B sendfiles
to pause after posting a partial
message. This is usually the case when you are running
.B sendmail
-and expect to generate a lot of partial messages. If the first
-argument given to
-.B sendfiles
-starts with a dash, then it is
-interpreted as the number of seconds to pause in between postings,
+and expect to generate a lot of partial messages. The
+.B \-delay
+switch specifies the number of seconds to pause in between postings,
e.g.,
.PP
.RS 5
-sendfiles -30 recipient \*(lqsubject\*(rq files\0...
+sendfiles -delay 30 -to recipient -subject \*(lqsubject\*(rq files\0...
.RE
.PP
-will pause 30 seconds in between each posting.
+will pause 30 seconds in between each posting. An alternate form of
+the switch with just the delay time,
+.BR \-30 ,
+for example, is also supported.
.PP
.SS "Extracting the Received Files"
When these messages are received, invoke
--- /dev/null
+#!/bin/sh
+######################################################
+#
+# Test sendfiles
+#
+######################################################
+
+set -e
+
+if test -z "$MH_OBJ_DIR"; then
+ srcdir=`dirname $0`/../..
+ MH_OBJ_DIR=`cd $srcdir && pwd`; export MH_OBJ_DIR
+fi
+
+. "$MH_OBJ_DIR/test/common.sh"
+
+setup_test
+
+expected=$MH_TEST_DIR/$$.expected
+expected_err=$MH_TEST_DIR/$$.expected_err
+actual=$MH_TEST_DIR/$$.actual
+actual_err=$MH_TEST_DIR/$$.actual_err
+localmbox=`$MH_LIB_DIR/ap -format "%(localmbox)" 0`
+#### Use this script itself for the test file.
+testfiledir="$srcdir/test/post"
+testfile=`basename $0`
+
+(cd "$MH_TEST_DIR" &&
+mkdir -p tmp &&
+cat >"$expected_err" <<EOF
+$testfile
+EOF
+)
+#### Copy fakesendmail and the testfile because we cd to the
+#### test directory, because tar doesn't like absolute paths.
+cp "$srcdir/test/fakesendmail" "$testfiledir/$testfile" "$MH_TEST_DIR"
+
+#### Use sendmail/pipe below to override default mts.
+mts_fakesendmail="$MHMTSCONF-fakesendmail"
+sed -e 's/^mts:.*/mts: sendmail\/pipe/' "$MHMTSCONF" > "$mts_fakesendmail"
+printf 'sendmail: %s/fakesendmail\n' "$MH_TEST_DIR" >>"$mts_fakesendmail"
+MHMTSCONF="$mts_fakesendmail"
+
+# $1: uncompress command
+# $2: argument style:
+# new: -to recipient -subject subject
+# old: recipient subject
+# remaining arguments: sendfiles switches
+test_sendfiles ()
+{
+ uncompress="$1"; shift
+ argstyle="$1"; shift
+
+ if [ "$argstyle" = 'new' ]; then
+ (cd "$MH_TEST_DIR" &&
+ sendfiles "$@" -to recipient@example.com -subject "sendfiles test" \
+ "$testfile" >/dev/null 2>"$actual_err")
+ elif [ "$argstyle" = 'old' ]; then
+ (cd "$MH_TEST_DIR" &&
+ sendfiles "$@" recipient@example.com "sendfiles test" \
+ "$testfile" >/dev/null 2>"$actual_err")
+ fi
+
+ check "$expected_err" "$actual_err" 'keep first'
+
+ # fakesendmail drops the message and any cc's into this mbox.
+ mbox="$MH_TEST_DIR"/Mail/fakesendmail.mbox
+ inc -silent -file "$mbox"
+ rm -f "$mbox" "$mbox.map"
+
+ mhlist -verbose last | sed -e 's/ *$//' >"$actual"
+ (cd $MH_TEST_DIR/tmp &&
+ contents=`mhstore -noauto last 2>&1 | \
+ sed -e 's/storing message.*as file //'` &&
+ $uncompress "$contents" | tar xpf - && rm -f "$contents")
+
+ rmm last
+ check "$testfiledir/$testfile" "$MH_TEST_DIR/tmp/$testfile" \
+ 'keep first'
+
+ [ -f "$expected" ] && check "$expected" "$actual" || rm -f "$actual"
+}
+
+
+# check -help
+cat >"$expected" <<EOF
+Usage: sendfiles [switches] -to recipient -subject subject file1 [file2 ...]
+ or
+ sendfiles [switches] recipient subject file1 [file2 ...]
+ switches are:
+ -compress [bzip2 | compress | gzip | lzma | none | zip]
+ -from <sender>
+ -[delay] <delay> (expressed in seconds)
+ -version
+ -help
+ Can use PERSON environment variable instead of -from switch.
+EOF
+
+sendfiles -help >"$actual" 2>&1
+check "$expected" "$actual"
+
+# check -version
+case `sendfiles -v` in
+ sendfiles\ --*) ;;
+ * ) printf '%s: sendfiles -v generated unexpected output\n' "$0" >&2
+ failed=`expr ${failed:-0} + 1`;;
+esac
+
+# check unknown switch
+run_test 'sendfiles -nonexistent' "Usage: sendfiles [switches] -to recipient \
+-subject subject file1 [file2 ...]
+ or
+ sendfiles [switches] recipient subject file1 [file2 ...]
+ switches are:
+ -compress [bzip2 | compress | gzip | lzma | none | zip]
+ -from <sender>
+ -[delay] <delay> (expressed in seconds)
+ -version
+ -help
+ Can use PERSON environment variable instead of -from switch."
+
+# check unknown compression method
+run_test 'sendfiles -compress unknown to subject file' \
+'sendfiles: unknown compression method "unknown"'"
+Usage: sendfiles [switches] -to recipient \
+-subject subject file1 [file2 ...]
+ or
+ sendfiles [switches] recipient subject file1 [file2 ...]
+ switches are:
+ -compress [bzip2 | compress | gzip | lzma | none | zip]
+ -from <sender>
+ -[delay] <delay> (expressed in seconds)
+ -version
+ -help
+ Can use PERSON environment variable instead of -from switch."
+
+# Check basic operation, using specified compression method.
+# Don't check the mhlist output, by not creating an $expected file,
+# because it will vary with compression method and compressed file
+# size.
+[ "`findprog bzip2`" ] && test_sendfiles 'bzip2 -cd' new -compress bzip2
+[ "`findprog compress`" ] && test_sendfiles uncompress new -compress compress
+[ "`findprog gzip`" ] && test_sendfiles 'gzip -cd' new -compress gzip
+[ "`findprog gzip`" ] && test_sendfiles 'gzip -cd' new -gzip
+[ "`findprog lzma`" ] && test_sendfiles 'lzma -cd' new -compress lzma
+[ "`findprog zip`" ] && test_sendfiles 'unzip -p' new -compress zip
+
+# check with no compression
+cat >"$expected" <<EOF
+ msg part type/subtype size description
+ 11 application/octet-stream 10K
+ type="tar"
+ (extract with cat | tar xvpf -)
+EOF
+
+test_sendfiles cat new -compress none
+
+# check with no compression, -none
+cat >"$expected" <<EOF
+ msg part type/subtype size description
+ 11 application/octet-stream 10K
+ type="tar"
+ (extract with cat | tar xvpf -)
+EOF
+
+test_sendfiles cat new -none
+
+# check old argument style (without -to and -subject)
+cat >"$expected" <<EOF
+ msg part type/subtype size description
+ 11 application/octet-stream 10K
+ type="tar"
+ (extract with cat | tar xvpf -)
+EOF
+
+test_sendfiles cat old -compress none
+
+# check -from
+cat >"$expected" <<EOF
+ msg part type/subtype size description
+ 11 application/octet-stream 10K
+ type="tar"
+ (extract with cat | tar xvpf -)
+EOF
+
+test_sendfiles cat new -compress none -from 'Sender <sender@example.com>'
+
+# check PERSON environment variable
+cat >"$expected" <<EOF
+ msg part type/subtype size description
+ 11 application/octet-stream 10K
+ type="tar"
+ (extract with cat | tar xvpf -)
+EOF
+
+PERSON='Sender <sender@example.com>' test_sendfiles cat new -compress none
+
+# check -delay, though for a small file it doesn't do anything
+cat >"$expected" <<EOF
+ msg part type/subtype size description
+ 11 application/octet-stream 10K
+ type="tar"
+ (extract with cat | tar xvpf -)
+EOF
+
+test_sendfiles cat new -compress none -delay 5
+
+# check old style -delay, though for a small file it doesn't do anything
+cat >"$expected" <<EOF
+ msg part type/subtype size description
+ 11 application/octet-stream 10K
+ type="tar"
+ (extract with cat | tar xvpf -)
+EOF
+
+test_sendfiles cat new -compress none -5
+
+rm -fr "$MH_TEST_DIR/fakesendmail" "$MH_TEST_DIR/$testfile" \
+ "$expected_err" "$MH_TEST_DIR/tmp"
+
+
+exit ${failed:-0}
int delay = 0;
char *f1 = NULL, *f2 = NULL, *f3 = NULL;
char *f4 = NULL, *f5 = NULL, *f7 = NULL;
+ static char postpath[PATH_MAX];
char *cp, buf[BUFSIZ];
char **argp, **arguments;
if (!f1)
adios (NULL, "missing -viamail \"mailpath\" switch");
+ /* viamail doesn't read the context and postproc isn't always what
+ we want, such as when running make distcheck. If we have the
+ absolute path, set postproc to point to post in the same
+ directory as this executable.
+ This could be generalized to handle relative paths (by
+ converting to absolute), to find the full path from PATH given
+ just the basename, and to squash out ../ but it's only needed
+ here. viamail is typically called from sendfiles, which
+ provides the absolute path.
+ */
+ if (argv[0] && argv[0][0] == '/' &&
+ strlen(argv[0]) - 3 < sizeof postpath) {
+ strncpy (postpath, argv[0], sizeof postpath - 1);
+ postpath[sizeof postpath - 1] = '\0';
+ if ((cp = strrchr (postpath, '/'))) {
+ struct stat st;
+
+ *(cp + 1) = '\0';
+ /* strlen ("post") <= sizeof postpath - (cp - postpath) - 2
+ but use strncat just in case the code above changes. */
+ strncat (postpath, "post", sizeof postpath - (cp - postpath) - 2);
+
+ if (stat (postpath, &st) == OK) {
+ postproc = postpath;
+ }
+ }
+ }
+
via_mail (f1, f2, f3, f4, f5, delay, f7);
return 0; /* dead code to satisfy the compiler */
}