test/install-mh/test-install-mh \
test/locking/test-datalocking test/locking/test-spoollocking \
test/manpages/test-manpages \
+ test/mhbuild/test-attach \
test/mhbuild/test-forw test/mhbuild/test-header-encode \
test/mhbuild/test-utf8-body \
test/mhfixmsg/test-mhfixmsg \
+This document describes the previous attach interface. The attach
+interface has changes for nmh 1.6 and later. The interface is
+documented in send(1), whatnow(1), and mhbuild(1). No configuration
+is required, and the same commands exist in whatnow; the two main
+differences are that the header is now named "Attach", and mhbuild takes
+care of the actual header processing.
+
Jon Steinhart's (jon@fourwinds.com) Attachment Handling Mods
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
directive that send(1) will use.
- mhbuild(1) now supports the -auto/-noauto flags (to be used by send(1)
when invoking mhbuild automatically).
+- mhbuild(1) now is automatically run by send, to insure that all outgoing
+ messages have proper MIME formatting.
+- A new header, "Attach", is supported by mhbuild; it is used to replace
+ previous functionality (which by default used a header named
+ Nmh-Attachment).
-----------------
OBSOLETE FEATURES
extern struct swit anoyes[]; /* standard yes/no switches */
-#define ATTACHFORMATS 3 /* Number of send attach formats. */
-
/*
* general folder attributes
*/
#define LINK "@" /* Name of link to file to which you are */
/* replying. */
-#define NMH_ATTACH_HEADER "Nmh-Attachment" /* Default header for -attach */
-
/*
* credentials management
*/
* that the composition file is already in MIME format
* and will not be processed further. Otherwise, an
* error is generated.
+ * dist - A flag to indicate if we are being run by "dist". In
+ * that case, add no MIME headers to the message. Existing
+ * headers will still be encoded by RFC 2047.
* directives - A flag to control whether or not build directives are
* processed by default.
* encoding - The default encoding to use when doing RFC 2047 header
* -auto flag is set and a MIME-Version header is encountered, the return
* value is NULL.
*/
-CT build_mime (char *infile, int autobuild, int directives, int encoding);
+CT build_mime (char *infile, int autobuild, int dist, int directives,
+ int encoding);
int add_header (CT, char *, char *);
int get_ctinfo (char *, CT, int);
int sc_width(void);
int build_form (char *, char *, int *, char *, char *, char *, char *,
char *, char *);
-int sendsbr (char **, int, char *, char *, struct stat *, int, char *, int);
+int sendsbr (char **, int, char *, char *, struct stat *, int);
int SOprintf (char *, ...);
int what_now (char *, int, int, char *, char *,
int, struct msgs *, char *, int, char *, int);
.B nmh
will not invoke
.B mhbuild
-automatically, unless you
-add this line to your
-.I \&.mh\(ruprofile
-file:
-.PP
-.RS 5
-.nf
-automimeproc: 1
-.fi
-.RE
-.PP
-Otherwise, you must specifically give the command
+automatically; you must specifically give the command
.PP
.RS 5
.nf
(profile, default: vi)
.RE
.PP
-.BR automimeproc :
-.RS 5
-If defined and set to 1, then the
-.B whatnow
-program will automatically
-invoke the buildmimeproc (discussed below) to process each message as a MIME
-composition draft before it is sent.
-(profile, no default)
-.RE
-.PP
.BR Msg\-Protect :
600
.RS 5
-.TH MHBUILD %manext1% "March 21, 2013" "%nmhversion%"
+.TH MHBUILD %manext1% "January 23, 2014" "%nmhversion%"
.\"
.\" %nmhwarning%
.\"
.RB [ \-headerencoding
.IR encoding\-algorithm
.RB " | " \-autoheaderencoding ]
+.RB [ \-dist ]
.RB [ \-version ]
.RB [ \-help ]
.ad
is present, then the listing will show any \*(lqextra\*(rq information
that is present in the message, such as comments in the
\*(lqContent-Type\*(rq header.
+.SS "Simplified Attachment Interface"
+For users who wish to simply attach files to text content,
+.B mhbuild
+will scan the composition file for \*(lqAttach\*(rq headers. An
+\*(lqAttach\*(rq header contains a filename that will be appended to the
+message using normal MIME encapsulation rules. One filename is allowed
+per \*(lqAttach\*(rq header, but multiple \*(lqAttach\*(rq headers are
+allowed ber composition file.
+.PP
+These files will be appended after any other MIME content, including any
+content specified by
+.B mhbuild
+directives (see below). See
+.IR send (1)
+for more details.
.SS "Translating the Composition File"
.B mhbuild
is essentially a filter to aid in the composition of MIME
switch will cause
.B mhbuild
to exit without error if the input file already has valid MIME headers.
-.PP
-It is also possible to have the
-.B whatnow
-program invoke
-.B mhbuild
-automatically when a message is sent. To do this, you must add the line
-.PP
-.RS 5
-automimeproc: 1
-.RE
-.PP
-to your
-.I \&.mh\(ruprofile
-file.
+The use of
+.B \-auto
+also enables the
+.B \-nodirectives
+switch.
.PP
Finally, you should consider adding this line to your profile:
.PP
.RE
.PP
will work as you expect.
+.PP
+The
+.B \-dist
+switch is intended to be used by
+.BR dist .
+It will cause mhbuild to not generate any MIME headers in the composition
+file (such as \*(lqMIME-Version\*(rq or \*(lqContent-Type\*(rq), but it
+will still encode message headers according to RFC 2047.
.SS "User Environment"
Because the environment in which
.B mhbuild
.B nmh
will not invoke
.B mhbuild
-automatically, unless you
-add this line to your
-.I \&.mh\(ruprofile
-file:
-.PP
-.RS 5
-automimeproc: 1
-.RE
-.PP
-Otherwise, you must specifically give the command
+automatically; you must specifically give the command
.PP
.RS 5
What now? mime
.\"
.\" %nmhwarning%
.\"
-.TH SEND %manext1% "December 22, 2013" "%nmhversion%"
+.TH SEND %manext1% "January 23, 2014" "%nmhversion%"
.SH NAME
send \- send a message
.SH SYNOPSIS
\&...]
.RB [ \-version ]
.RB [ \-help ]
-.RB [ \-attach
-.IR header-field-name ]
-.RB [ \-noattach ]
-.RB [ \-attachformat
-.IR 0 " | " 1 " | " 2 ]
.ad
.SH DESCRIPTION
.B Send
are actually performed by
.BR post .
.PP
-By default the draft is scanned for a header named
-.IR Nmh-Attachment .
+Before
+.B send
+gives the message to
+.B post
+for delivery, the message is processed by
+.B mhbuild
+to perform any necessary MIME encoding of the outgoing message. This
+can be changed by the
+.I buildmimeproc
+profile component.
+.B mhbuild
+is invoked with the
+.B \-auto
+switch, so
+.B mhbuild
+directives are not processed by default. See
+.IR mhbuild (1)
+for more information.
+.PP
+.B mhbuild
+will scan the message draft for a header named
+.IR Attach .
The draft is converted to a MIME message if one or more matches are found.
-This conversion occurs before all other processing. The header name
-can be changed with the
-.B \-attach
-option. This behavior can be disabled completely with the
-.B \-noattach
-option. The
-.B whatnow
+This conversion occurs before all other processing. The
+.IR whatnow (1)
man page describes the user interface for managing MIME attachments via
this mechanism.
.PP
The first part of the MIME message is the draft body if that body contains
any non-blank characters.
-The body of each header field whose name matches the
-.I header-field-name
-is interpreted as a file name, and each file named is included as a separate
+The body of each
+.I Attach
+header field is interpreted as a file name, and each file named is included as a separate
part in the MIME message.
.PP
Determination of the content MIME type inserted into the Content-Type
installation was configured. If a program, such as
.B file
with a
-.B --mime
+.B \-\-mime
or
-.B -i
+.B \-i
option, was found that can specify the type of a file as a MIME type
string, then that will be used. To determine if your
.B nmh
.IR mhshow (1)
for more details and example syntax.
.PP
-Each part contains a name attribute that is the last component of the path name.
-A
-.I x-unix-mode
-attribute containing the file mode accompanies each part.
-Finally, a description attribute is generated by running the
-.I file
-command on the file.
-.PP
-The
-.B -attachformat
-option specifies the MIME header field formats: a value of
-.B 0
-includes the
-.I x-unix-mode
-attribute as noted above. A value of
-.BR 1 ,
-the default,
-suppresses that, puts the file name in the
-\*(lqContent-Description\*(rq header, and
-adds a \*(lqContent-Disposition\*(rq header. A value of
-.B 2
-adds the file
-.I modification-date
-parameter to the \*(lqContent-Disposition\*(rq header. You can
-specify one value in your profile, and override it for individual
-messages at the
-.I whatnow
-prompt.
-.PP
-Here are example message part headers, for an attachment, for each of the
-.B -attachformat
-values:
+Each attached MIME part contains a
+\*(lqContent-Description\*(rq header that includes the filename, and
+adds a \*(lqContent-Disposition\*(rq header.
+Here is an example of MIME part headers for an attachment:
.PP
.nf
--attachformat 0:
-Content-Type: text/plain; name="VERSION"; x-unix-mode="0644";
- charset="us-ascii"
-Content-Description: ASCII text
-
--attachformat 1:
Content-Type: text/plain; name="VERSION"; charset="us-ascii"
Content-Description: VERSION
Content-Disposition: attachment; filename="VERSION"
-
--attachformat 2:
-Content-Type: text/plain; name="VERSION"; charset="us-ascii"
-Content-Description: VERSION
-Content-Disposition: attachment; filename="VERSION"; modification-date="Mon, 19 Dec 2005 22:39:51 -0600"
.fi
.PP
If
.RB ` \-noverbose '
.RB ` \-nowatch '
.RB ` "\-width\ 72" '
-.RB ` "\-attach\ Nmh-Attachment" '
-.RB ` "\-attachformat\ 1" '
.fi
.SH CONTEXT
None
.RI [ file ]
.RB [ \-version ]
.RB [ \-help ]
-.RB [ \-attach
-.IR header-field-name ]
-.RB [ \-noattach ]
.ad
.SH DESCRIPTION
.B Whatnow
^Editor:~^To override the default editor
^<lasteditor>\-next:~^To name an editor to be used after exit
^~^from <lasteditor>
-^automimeproc:~^If value is 1, and the draft is a MIME
-^~^composition file, then automatically call
-^~^buildmimeproc prior to sending.
^buildmimeproc:~^Program to translate MIME composition files
^fileproc:~^Program to refile the message
^lproc:~^Program to list the contents of a message
.SH DEFAULTS
.nf
.RB ` \-prompt "' defaults to \*(lqWhat\ Now?\ \*(rq"
-.RB ` \-attach "' defaults to \*(lqNmh-Attachment\*(rq"
.fi
.SH BUGS
If the initial edit fails,
test_dist +inbox 1 -noedit -to somebody@example.com -fcc +outbox
run_test 'scan +outbox -width 6 2' ' 2 '
+#
+# Check that dist encodes headers using RFC-2047 properly
+#
+
+export LC_ALL=en_US.UTF-8
+
+cat >"$expected" <<EOF
+From: Test1 <test1@example.com>
+To: Some User <user@example.com>
+Date: Fri, 29 Sep 2006 00:00:00
+Message-Id: 1@test.nmh
+Subject: Testing message 1
+Resent-From: =?UTF-8?Q?Mr_F=C3=B8o_Bar?= <foo@bar.com>
+Resent-To: =?UTF-8?Q?Mr_Nobod=C3=BF?= <nobody@nowhere.com>
+Resent-Date:
+
+This is message number 1
+EOF
+
+test_dist +inbox 1 -noedit -from 'Mr Føo Bar <foo@bar.com>' \
+ -to 'Mr Nobodÿ <nobody@nowhere.com>' -fcc +outbox
exit ${failed:-0}
draft="$MH_TEST_DIR/$$.draft"
expected="$MH_TEST_DIR/$$.expected"
-actual="$MH_TEST_DIR/$$.actual"
#
# Test out a simple draft, one part.
------
EOF
-mhbuild "$draft"
+run_prog mhbuild "$draft"
-cat > "$actual" <<EOF
+cat > "$expected" <<EOF
To: Mr Test <mrtest@example.com>
cc:
Fcc: +outbox
/9g=
EOF
-check "$draft" "$actual"
+check "$draft" "$expected"
#
# Check out more common case, one (or more) attachments
This is a test
EOF
-mhbuild "$draft"
+run_prog mhbuild "$draft"
-cat "$draft"
+cat > "$expected" <<EOF
+To: Mr Test <mrtest@example.com>
+cc:
+Fcc: +outbox
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0"
+
+------- =_aaaaaaaaaa0
+Content-Type: text/plain; charset="us-ascii"
+
+This is a test
+
+------- =_aaaaaaaaaa0
+Content-Type: image/jpeg; name="tiny.jpg"
+Content-Description: tiny.jpg
+Content-Disposition: attachment; filename="tiny.jpg"
+Content-Transfer-Encoding: base64
+
+/9g=
+
+------- =_aaaaaaaaaa0--
+EOF
+
+check "$draft" "$expected"
+
+#
+# An empty Attach header
+#
+
+cat > "$draft" <<EOF
+To: Mr Test <mrtest@example.com>
+cc:
+Fcc: +outbox
+Attach:
+------
+This is a test of an empty attach header.
+EOF
+
+run_prog mhbuild "$draft"
+
+cat > "$expected" <<EOF
+To: Mr Test <mrtest@example.com>
+cc:
+Fcc: +outbox
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+
+This is a test of an empty attach header.
+EOF
+
+check "$draft" "$expected"
+
+#
+# Check a completely empty message
+#
+
+cat > "$draft" <<EOF
+To: Mr Test <mrtest@example.com>
+cc:
+Fcc: +outbox
+Subject: Test of an empty body
+EOF
+
+run_prog mhbuild "$draft"
+
+cat > "$expected" <<EOF
+To: Mr Test <mrtest@example.com>
+cc:
+Fcc: +outbox
+Subject: Test of an empty body
+MIME-Version: 1.0
+Content-Type: text/plain
+EOF
+
+check "$draft" "$expected"
+
+#
+# Make sure we fail if we run into a MIME-Version header
+#
+
+cat > "$draft" <<EOF
+To: Mr Test <mrtest@example.com>
+cc:
+Fcc: +outbox
+Subject: Test of an already-MIMEified message
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+
+This is a preformatted MIME content test.
+EOF
+
+set +e
+run_test 'eval mhbuild "$draft"' "mhbuild: draft shouldn't contain MIME-Version: field"
+set -e
+
+#
+# Run it again using -auto
+#
+
+run_prog mhbuild -auto "$draft"
+
+cat > "$expected" <<EOF
+To: Mr Test <mrtest@example.com>
+cc:
+Fcc: +outbox
+Subject: Test of an already-MIMEified message
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+
+This is a preformatted MIME content test.
+EOF
+
+check "$draft" "$expected"
+
+#
+# Make sure -dist does nothing but encode headers
+#
+
+cat > "$draft" <<EOF
+To: Señor Test <mrtest@example.com>
+cc:
+Fcc: +outbox
+Subject: An empty dist test
+EOF
+
+LC_ALL=en_US.UTF-8 run_prog mhbuild -dist "$draft"
+
+cat > "$expected" <<EOF
+To: =?UTF-8?Q?Se=C3=B1or_Test?= <mrtest@example.com>
+cc:
+Fcc: +outbox
+Subject: An empty dist test
+EOF
+
+check "$draft" "$expected"
#
-# Two parts, one attachment
+# Two parts, one attachment; make sure mixing of multiparts at different
+# levels works
#
+cat > "$draft" <<EOF
+To: Mr Test <mrtest@example.com>
+cc:
+Fcc: +outbox
+Subject: A more complete multipart test
+Attach: ${srcdir}/test/mhbuild/tiny.jpg
+--------
+#begin alternative
+#<text/plain
+This is some tëxt.
+#<text/html
+<html>
+<body>
+This is some HTML tëxt.
+</body>
+</html>
+#end
+EOF
+
+LC_ALL=en_US.UTF-8 run_prog mhbuild "$draft"
+
+cat > "$expected" <<EOF
+To: Mr Test <mrtest@example.com>
+cc:
+Fcc: +outbox
+Subject: A more complete multipart test
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0"
+
+------- =_aaaaaaaaaa0
+Content-Type: multipart/alternative; boundary="----- =_aaaaaaaaaa1"
+
+------- =_aaaaaaaaaa1
+Content-Type: text/plain; charset="UTF-8"
+Content-Transfer-Encoding: quoted-printable
+
+This is some t=C3=ABxt.
+
+------- =_aaaaaaaaaa1
+Content-Type: text/html; charset="UTF-8"
+Content-Transfer-Encoding: quoted-printable
+
+<html>
+<body>
+This is some HTML t=C3=ABxt.
+</body>
+</html>
+
+------- =_aaaaaaaaaa1--
+
+------- =_aaaaaaaaaa0
+Content-Type: image/jpeg; name="tiny.jpg"
+Content-Description: tiny.jpg
+Content-Disposition: attachment; filename="tiny.jpg"
+Content-Transfer-Encoding: base64
+
+/9g=
+
+------- =_aaaaaaaaaa0--
+EOF
+
+check "$draft" "$expected"
+
exit ${failed:-0}
From: Mr Nobody <nobody@example.com>
To: Somebody <somebody@example.com>
Subject: Test
-Nmh-Attachment: $MH_TEST_DIR/attachment.txt
+Attach: $MH_TEST_DIR/attachment.txt
This is a test.
EOF
From: Mr Nobody <nobody@example.com>
To: Somebody <somebody@example.com>
Subject: Test
-Nmh-Attachment: $MH_TEST_DIR/attachment.txt
+Attach: $MH_TEST_DIR/attachment.txt
¡Ay, caramba!
EOF
DATA
To: recipient@example.com
From: sender8@localhost
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
Message-ID:
From: Mr Nobody <nobody@example.com>
To: Somebody Else <somebody@example.com>
Subject: Test
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
This is a test
From: Mr Nobody <nobody@example.com>
To: Somebody Else <somebody@example.com>
Subject: Test
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
Message-ID:
From: Mr Nobody <nobody@example.com>
To: Somebody Else <somebody@example.com>
Subject: Test
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
Message-ID:
From: Mr Nobody <nobody@example.com>
To: Somebody Else <somebody@example.com>
Subject: Test
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
This is a test
From: Mr Nobody <nobody@example.com>
To: Somebody Else <somebody@example.com>
Subject: Test
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
This is a test
From: Mr Nobody <nobody@example.com>
To: Somebody Else <somebody@example.com>
Subject: Test
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
This is a test
From: Mr Nobody <nobody@example.com>
To: Somebody Else <somebody@example.com>
Subject: Test
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
This is a test
From: Mr Nobody <nobody@example.com>
To: Somebody Else <somebody@example.com>
Subject: Test
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
This is a test
From: Mr Nobody <nobody@example.com>
To: Blind List: ;
Subject: blind list test
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
This is test of a blind list.
From: Mr Nobody <nobody@example.com>
To: Blind List: ;
Subject: blind list test
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
This is test of a blind list.
From: Mr Nobody <nobody@example.com>
To: "named.list" <one@example.com>, "named.list" <two@example.com>
Subject: named list test
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
This is test of a named list.
From: Mr Nobody <nobody@example.com>
To: Somebody Else <somebody@example.com>
Subject: Test
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
This is a test
From: Mr Nobody <nobody@example.com>
To: Somebody Else <somebody@example.com>
Subject: Test
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
This is a test
To: Somebody One <somebody1@example.com>,
Somebody Two <somebody2@example.com>
Subject: Test Bcc
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
This is test of Bcc recipients.
To: Somebody One <somebody1@example.com>,
Somebody Two <somebody2@example.com>
Subject: Test Bcc
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
This is test of Bcc recipients.
To: Somebody One <somebody1@example.com>,
Somebody Two <somebody2@example.com>
Subject: Test Dcc
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
This is test of Dcc recipients.
Sender: Mr Nobody Three <nobody3@example.com>
To: Somebody Else <somebody@example.com>
Subject: Sender test
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
This is a test of the Sender header.
Sender: Mr Nobody Three <nobody3@example.com>
To: Somebody Else <somebody@example.com>
Subject: Envelope-From test
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
This is a test of the Envelope-From header.
Mr Nobody Two <nobody2@example.com>
To: Somebody Else <somebody@example.com>
Subject: Envelope-From and Sender test
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
Sender: nobody4@example.com
From: Mr Nobody One <nobody1@example.com>
To: Somebody Else <somebody@example.com>
Subject: Solo Envelope-From test
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
This is a solo test of the Envelope-From header.
From: Mr Nobody One <nobody1@example.com>
To: Somebody Else <somebody@example.com>
Subject: Blank Envelope-From test
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
This is a blank test of the Envelope-From header.
From: Mr Nobody <nobody@example.com>
To: Somebody Else <somebody@example.com>
Subject: Fcc test
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
This is a fcc test
From: Mr Nobody <nobody@example.com>
To: Somebody Else <somebody@example.com>
Subject: Fcc test
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
This is a fcc test
From: Mr Nobody <nobody@example.com>
To: our-group: ;
Subject: Group test
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
This is test of group recipients.
To: Somebody One <somebody1@example.com>,
Somebody Two <somebody2@example.com>
Subject: Test multiple
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
Date:
This is test of multiple recipients.
# whatnow's exit status is always 1 so that is not a failure
set +e
echo "attach $testname_quoted" | \
- run_prog whatnow -attach foo -noedit -prompt '' 2>>$actualerr >>$actual
+ run_prog whatnow -noedit -prompt '' 2>>$actualerr >>$actual
echo "alist" | \
- run_prog whatnow -attach foo -noedit -prompt '' 2>>$actualerr >>$actual
+ run_prog whatnow -noedit -prompt '' 2>>$actualerr >>$actual
echo "detach $testname_quoted" | \
- run_prog whatnow -attach foo -noedit -prompt '' 2>>$actualerr >>$actual
+ run_prog whatnow -noedit -prompt '' 2>>$actualerr >>$actual
echo "alist" | \
- run_prog whatnow -attach foo -noedit -prompt '' 2>>$actualerr >>$actual
+ run_prog whatnow -noedit -prompt '' 2>>$actualerr >>$actual
set -e
check "$expectederr" "$actualerr"
cat >"$expected" <<EOF
whatnow: attach command requires file argument(s).
whatnow: attach command requires file argument(s).
-#text/plain; name="context" <> [context]{attachment} ${MH_TEST_DIR}/Mail/context
+Attaching ${MH_TEST_DIR}/Mail/context as a text/plain
EOF
else
cat >"$expected" <<EOF
at -v
whatnow: attach command requires file argument(s).
at -v Mail/context
-#text/plain; name="context" <> [context]{attachment} ${MH_TEST_DIR}/Mail/context
+Attaching ${MH_TEST_DIR}/Mail/context as a text/plain
quit -delete
EOF
fi
#include <h/utils.h>
#include <h/tws.h>
-static int get_line(FILE *, char *, size_t);
#ifdef MIMETYPEPROC
static char *get_file_info(const char *, const char *);
#endif /* MIMETYPEPROC */
-int
-attach(char *attachment_header_field_name, char *draft_file_name,
- char *body_file_name, size_t body_file_name_len,
- char *composition_file_name, size_t composition_file_name_len,
- int attachformat)
-{
- char buf[PATH_MAX + 6]; /* miscellaneous buffer */
- int c; /* current character for body copy */
- int has_attachment; /* draft has at least one attachment */
- int has_body; /* draft has a message body */
- int length; /* of attachment header field name */
- char *p; /* miscellaneous string pointer */
- struct stat st; /* file status buffer */
- FILE *body_file = NULL; /* body file pointer */
- FILE *draft_file; /* draft file pointer */
- int field_size; /* size of header field buffer */
- char *field; /* header field buffer */
- FILE *composition_file; /* composition file pointer */
- char *build_directive; /* mhbuild directive */
-
-
- /*
- * Open up the draft file.
- */
-
- if ((draft_file = fopen(draft_file_name, "r")) == (FILE *)0)
- adios(NULL, "can't open draft file `%s'.", draft_file_name);
-
- /*
- * Allocate a buffer to hold the header components as they're read in.
- * This buffer might need to be quite large, so we grow it as needed.
- */
-
- field = (char *)mh_xmalloc(field_size = 256);
-
- /*
- * Scan the draft file for a header field name, with a non-empty
- * body, that matches the -attach argument. The existence of one
- * indicates that the draft has attachments. Bail out if there
- * are no attachments because we're done. Read to the end of the
- * headers even if we have no attachments.
- */
-
- length = strlen(attachment_header_field_name);
-
- has_attachment = 0;
-
- while (get_line(draft_file, field, field_size) != EOF && *field != '\0' &&
- *field != '-') {
- if (strncasecmp(field, attachment_header_field_name, length) == 0 &&
- field[length] == ':') {
- for (p = field + length + 1; *p == ' ' || *p == '\t'; p++)
- ;
- if (strlen (p) > 0) {
- has_attachment = 1;
- }
- }
- }
-
- if (has_attachment == 0)
- return (DONE);
-
- /*
- * We have at least one attachment. Look for at least one non-blank line
- * in the body of the message which indicates content in the body.
- */
-
- has_body = 0;
-
- while (get_line(draft_file, field, field_size) != EOF) {
- for (p = field; *p != '\0'; p++) {
- if (*p != ' ' && *p != '\t') {
- has_body = 1;
- break;
- }
- }
-
- if (has_body)
- break;
- }
-
- /*
- * Make names for the temporary files.
- */
-
- (void)strncpy(body_file_name,
- m_mktemp(m_maildir(invo_name), NULL, NULL),
- body_file_name_len);
- (void)strncpy(composition_file_name,
- m_mktemp(m_maildir(invo_name), NULL, NULL),
- composition_file_name_len);
-
- if (has_body)
- body_file = fopen(body_file_name, "w");
-
- composition_file = fopen(composition_file_name, "w");
-
- if ((has_body && body_file == (FILE *)0) || composition_file == (FILE *)0) {
- clean_up_temporary_files(body_file_name, composition_file_name);
- adios(NULL, "unable to open all of the temporary files.");
- }
-
- /*
- * Start at the beginning of the draft file. Copy all
- * non-attachment header fields to the temporary composition
- * file. Then add the dashed line separator.
- */
-
- rewind(draft_file);
-
- while (get_line(draft_file, field, field_size) != EOF && *field != '\0' &&
- *field != '-')
- if (strncasecmp(field, attachment_header_field_name, length) != 0 ||
- field[length] != ':')
- (void)fprintf(composition_file, "%s\n", field);
-
- (void)fputs("--------\n", composition_file);
-
- /*
- * Copy the message body to a temporary file.
- */
-
- if (has_body) {
- while ((c = getc(draft_file)) != EOF)
- putc(c, body_file);
-
- (void)fclose(body_file);
- }
-
- /*
- * Add a mhbuild MIME composition file line for the body if there was one.
- * Set the default content type to text/plain so that mhbuild takes care
- * of any necessary encoding.
- */
-
- if (has_body)
- /*
- * Make sure that the attachment file exists and is readable.
- */
- if (stat(body_file_name, &st) != OK ||
- access(body_file_name, R_OK) != OK) {
- advise(NULL, "unable to access file \"%s\"", body_file_name);
- return NOTOK;
- }
-
- if ((build_directive = construct_build_directive (body_file_name,
- "text/plain",
- attachformat)) == NULL) {
- clean_up_temporary_files(body_file_name, composition_file_name);
- adios (NULL, "exiting due to failure in attach()");
- } else {
- (void) fputs(build_directive, composition_file);
- free(build_directive);
- }
-
- /*
- * Now, go back to the beginning of the draft file and look for
- * header fields that specify attachments. Add a mhbuild MIME
- * composition file for each.
- */
-
- rewind(draft_file);
-
- while (get_line(draft_file, field, field_size) != EOF && *field != '\0' &&
- *field != '-') {
- if (strncasecmp(field, attachment_header_field_name, length) == 0 &&
- field[length] == ':') {
- for (p = field + length + 1; *p == ' ' || *p == '\t'; p++)
- ;
-
- /* Skip empty attachment_header_field_name lines. */
- if (strlen (p) > 0) {
- struct stat st;
- if (stat(p, &st) == OK && access(p, R_OK) == OK) {
- if (S_ISREG (st.st_mode)) {
- /* Don't set the default content type so that
- construct_build_directive() will try to infer
- it from the file type. */
- if ((build_directive = construct_build_directive (p, 0,
- attachformat)) == NULL) {
- clean_up_temporary_files(body_file_name,
- composition_file_name);
- adios (NULL, "exiting due to failure in attach()");
- } else {
- (void) fputs(build_directive, composition_file);
- free(build_directive);
- }
- } else {
- adios (NULL, "unable to attach %s, not a plain file",
- p);
- }
- } else {
- adios (NULL, "unable to access file \"%s\"", p);
- }
- }
- }
- }
-
- (void)fclose(composition_file);
-
- /*
- * We're ready to roll! Run mhbuild on the composition file.
- * Note that mhbuild is in the context as buildmimeproc.
- */
-
- (void)sprintf(buf, "%s %s", buildmimeproc, composition_file_name);
-
- if (system(buf) != 0) {
- clean_up_temporary_files(body_file_name, composition_file_name);
- return NOTOK;
- }
-
- return OK;
-}
-
-void
-clean_up_temporary_files(const char *body_file_name,
- const char *composition_file_name)
-{
- (void) unlink(body_file_name);
- (void) unlink(composition_file_name);
-
- return;
-}
-
-static int
-get_line(FILE *draft_file, char *field, size_t field_size)
-{
- int c; /* current character */
- size_t n; /* number of bytes in buffer */
- char *p; /* buffer pointer */
-
- /*
- * Get a line from the input file, growing the field buffer as
- * needed. We do this so that we can fit an entire line in the
- * buffer making it easy to do a string comparison on both the
- * field name and the field body which might be a long path name.
- */
-
- for (n = 0, p = field; (c = getc(draft_file)) != EOF; *p++ = c) {
- if (c == '\n' && (c = getc(draft_file)) != ' ' && c != '\t') {
- (void)ungetc(c, draft_file);
- c = '\n';
- break;
- }
-
- if (++n >= field_size - 1) {
- field = (char *)mh_xrealloc((void *)field, field_size += 256);
-
- p = field + n - 1;
- }
- }
-
- /*
- * NUL-terminate the field..
- */
-
- *p = '\0';
-
- return (c);
-}
-
/*
* Try to use external command to determine mime type, and possibly
* encoding. Caller is responsible for free'ing returned memory.
return cp ? strdup(cp) : NULL;
}
#endif /* MIMETYPEPROC */
-
-
-/*
- * Construct an mhbuild directive for the draft file. This starts
- * with the content type. Append a file name attribute, and depending
- * on attachformat value a private x-unix-mode attribute and a
- * description obtained (if possible) by running the "file" command on
- * the file. Caller is responsible for free'ing returned memory.
- */
-char *
-construct_build_directive (char *file_name, const char *default_content_type,
- int attachformat) {
- char *build_directive = NULL; /* Return value. */
- char *content_type; /* mime content type */
- char cmd[PATH_MAX + 8]; /* file command buffer */
- struct stat st; /* file status buffer */
- char *p; /* miscellaneous temporary variables */
- int c; /* current character */
-
- if ((content_type = mime_type (file_name)) == NULL) {
- /*
- * Check the file name for a suffix. Scan the context for
- * that suffix on a mhshow-suffix- entry. We use these
- * entries to be compatible with mhnshow, and there's no
- * reason to make the user specify each suffix twice. Context
- * entries of the form "mhshow-suffix-contenttype" in the name
- * have the suffix in the field, including the dot.
- */
- struct node *np; /* context scan node pointer */
- static FILE *fp = NULL; /* pointer for mhn.defaults */
-
- if (fp == NULL && (fp = fopen (p = etcpath ("mhn.defaults"), "r"))) {
- readconfig ((struct node **) NULL, fp, p, 0);
- fclose(fp);
- }
-
- if ((p = strrchr(file_name, '.')) != NULL) {
- for (np = m_defs; np; np = np->n_next) {
- if (strncasecmp(np->n_name, "mhshow-suffix-", 14) == 0 &&
- strcasecmp(p, np->n_field ? np->n_field : "") == 0) {
- content_type = strdup (np->n_name + 14);
- break;
- }
- }
- }
-
- if (content_type == NULL && default_content_type != NULL) {
- content_type = strdup (default_content_type);
- }
- }
-
- /*
- * No content type was found, either because there was no matching
- * entry in the context or because the file name has no suffix.
- * Open the file and check for non-ASCII characters. Choose the
- * content type based on this check.
- */
- if (content_type == NULL) {
- int binary; /* binary character found flag */
- FILE *fp;
-
- if ((fp = fopen(file_name, "r")) == (FILE *)0) {
- advise(NULL, "unable to access file \"%s\"", file_name);
- return NULL;
- }
-
- binary = 0;
-
- while ((c = getc(fp)) != EOF) {
- if (c > 127 || c < 0) {
- binary = 1;
- break;
- }
- }
-
- (void) fclose(fp);
-
- content_type =
- strdup (binary ? "application/octet-stream" : "text/plain");
- }
-
- switch (attachformat) {
- case 0: {
- struct stat st;
- FILE *fp;
- char m[4];
-
- /* Insert name, file mode, and Content-Id. */
- if (stat(file_name, &st) != OK || access(file_name, R_OK) != OK) {
- advise(NULL, "unable to access file \"%s\"", file_name);
- return NULL;
- }
-
- snprintf (m, sizeof m, "%.3ho", (unsigned short)(st.st_mode & 0777));
- build_directive = concat ("#", content_type, "; name=\"",
- ((p = strrchr(file_name, '/')) == NULL)
- ? file_name
- : p + 1,
- "\"; x-unix-mode=0", m, NULL);
-
- if (strlen(file_name) > PATH_MAX) {
- advise(NULL, "attachment file name `%s' too long.", file_name);
- return NULL;
- }
-
- (void) sprintf(cmd, "file '%s'", file_name);
-
- if ((fp = popen(cmd, "r")) != NULL &&
- fgets(cmd, sizeof (cmd), fp) != NULL) {
- *strchr(cmd, '\n') = '\0';
-
- /*
- * The output of the "file" command is of the form
- *
- * file: description
- *
- * Strip off the "file:" and subsequent white space.
- */
- for (p = cmd; *p != '\0'; p++) {
- if (*p == ':') {
- for (p++; *p != '\0'; p++) {
- if (*p != '\t')
- break;
- }
- break;
- }
- }
-
- if (*p != '\0') {
- /* Insert Content-Description. */
- build_directive =
- concat (build_directive, " [ ", p, " ]", NULL);
- }
-
- (void) pclose(fp);
- }
- break;
- }
- case 1:
- if (stringdex (m_maildir(invo_name), file_name) == 0) {
- /* Content had been placed by send into a temp file.
- Don't generate Content-Disposition header, because
- it confuses Microsoft Outlook, Build 10.0.6626, at
- least. */
- build_directive = concat ("#", content_type, " <>", NULL);
- } else {
- /* Suppress Content-Id, insert simple Content-Disposition
- and Content-Description with filename.
- The Content-Disposition type needs to be "inline" for
- MS Outlook and BlackBerry calendar programs to properly
- handle a text/calendar attachment. */
- p = strrchr(file_name, '/');
- build_directive = concat ("#", content_type, "; name=\"",
- (p == NULL) ? file_name : p + 1,
- "\" <> [",
- (p == NULL) ? file_name : p + 1,
- "]{",
- strcmp ("text/calendar", content_type)
- ? "attachment" : "inline",
- "}", NULL);
- }
-
- break;
- case 2:
- if (stringdex (m_maildir(invo_name), file_name) == 0) {
- /* Content had been placed by send into a temp file.
- Don't generate Content-Disposition header, because
- it confuses Microsoft Outlook, Build 10.0.6626, at
- least. */
- build_directive = concat ("#", content_type, " <>", NULL);
- } else {
- /* Suppress Content-Id, insert Content-Disposition with
- modification date and Content-Description wtih filename.
- The Content-Disposition type needs to be "inline" for
- MS Outlook and BlackBerry calendar programs to properly
- handle a text/calendar attachment. */
-
- if (stat(file_name, &st) != OK || access(file_name, R_OK) != OK) {
- advise(NULL, "unable to access file \"%s\"", file_name);
- return NULL;
- }
-
- p = strrchr(file_name, '/');
- build_directive = concat ("#", content_type, "; name=\"",
- (p == NULL) ? file_name : p + 1,
- "\" <> [",
- (p == NULL) ? file_name : p + 1,
- "]{",
- strcmp ("text/calendar", content_type)
- ? "attachment" : "inline",
- "; modification-date=\"",
- dtime (&st.st_mtime, 0),
- "}", NULL);
- }
-
- break;
- default:
- advise (NULL, "unsupported attachformat %d", attachformat);
- }
-
- free(content_type);
-
- /*
- * Finish up with the file name.
- */
- build_directive = concat (build_directive, " ", file_name, "\n", NULL);
-
- return build_directive;
-}
X("version", 0, VERSIONSW) \
X("help", 0, HELPSW) \
X("debug", -5, DEBUGSW) \
+ X("dist", -4, DISTSW) \
#define X(sw, minchars, id) id,
DEFINE_SWITCH_ENUM(MHBUILD);
int
main (int argc, char **argv)
{
- int sizesw = 1, headsw = 1, directives = 1, autobuild = 0;
+ int sizesw = 1, headsw = 1, directives = 1, autobuild = 0, dist = 0;
int *icachesw;
char *cp, buf[BUFSIZ];
char buffer[BUFSIZ], *compfile = NULL;
case DEBUGSW:
debugsw = 1;
continue;
+ case DISTSW:
+ dist = 1;
+ continue;
}
}
if (compfile)
unlink_infile = 1;
/* build the content structures for MIME message */
- ct = build_mime (infile, autobuild, directives, header_encoding);
+ ct = build_mime (infile, autobuild, dist, directives, header_encoding);
/*
* If ct == NULL, that means that -auto was set and a MIME version
*/
/* build the content structures for MIME message */
- ct = build_mime (compfile, autobuild, directives, header_encoding);
+ ct = build_mime (compfile, autobuild, dist, directives, header_encoding);
/*
* If ct == NULL, that means -auto was set and we found a MIME version
static int init_decoded_content (CT);
static void setup_attach_content(CT, char *);
static char *fgetstr (char *, int, FILE *);
-static int user_content (FILE *, char *, char *, CT *);
+static int user_content (FILE *, char *, CT *);
static void set_id (CT, int);
static int compose_content (CT);
static int scan_content (CT);
*/
CT
-build_mime (char *infile, int autobuild, int directives, int header_encoding)
+build_mime (char *infile, int autobuild, int dist, int directives,
+ int header_encoding)
{
int compnum, state;
char buf[BUFSIZ], name[NAMESZ];
* Now add the MIME-Version header field
* to the list of header fields.
*/
- np = add (VRSN_FIELD, NULL);
- vp = concat (" ", VRSN_VALUE, "\n", NULL);
- add_header (ct, np, vp);
+
+ if (! dist) {
+ np = add (VRSN_FIELD, NULL);
+ vp = concat (" ", VRSN_VALUE, "\n", NULL);
+ add_header (ct, np, vp);
+ }
/*
* We initally assume we will find multiple contents in the
struct part *part;
CT p;
- if (user_content (in, infile, buf, &p) == DONE) {
+ if (user_content (in, buf, &p) == DONE) {
admonish (NULL, "ignoring spurious #end");
continue;
}
part->mp_part = p;
}
- /*
- * close the composition draft since
- * it's not needed any longer.
- */
- fclose (in);
-
/*
* Add any Attach headers to the list of MIME parts at the end of the
* message.
free(at_prev);
}
- /* check if any contents were found */
- if (!m->mp_parts)
- adios (NULL, "no content directives found");
+ /*
+ * To allow for empty message bodies, if we've found NO content at all
+ * yet cook up an empty text/plain part.
+ */
+
+ if (!m->mp_parts) {
+ CT p;
+ struct part *part;
+ struct text *t;
+
+ if ((p = (CT) calloc (1, sizeof(*p))) == NULL)
+ adios(NULL, "out of memory");
+
+ init_decoded_content(p);
+
+ if (get_ctinfo ("text/plain", p, 0) == NOTOK)
+ done (1);
+
+ p->c_type = CT_TEXT;
+ p->c_subtype = TEXT_PLAIN;
+ p->c_encoding = CE_7BIT;
+ p->c_file = getcpy(infile);
+ /*
+ * Sigh. ce_file contains the "decoded" contents of this part.
+ * So this seems like the best option available since we're going
+ * to call scan_content() on this.
+ */
+ p->c_cefile.ce_file = getcpy("/dev/null");
+ p->c_begin = ftell(in);
+ p->c_end = ftell(in);
+
+ if ((t = (struct text *) calloc (1, sizeof (*t))) == NULL)
+ adios (NULL, "out of memory");
+
+ t->tx_charset = CHARSET_SPECIFIED;
+ p->c_ctparams = t;
+
+ if ((part = (struct part *) calloc (1, sizeof(*part))) == NULL)
+ adios (NULL, "out of memory");
+ *pp = part;
+ pp = &part->mp_next;
+ part->mp_part = p;
+ }
+
+ /*
+ * close the composition draft since
+ * it's not needed any longer.
+ */
+ fclose (in);
/*
* If only one content was found, then remove and
}
/* Build the rest of the header field structures */
- build_headers (ct);
+ if (! dist)
+ build_headers (ct);
return ct;
}
*/
static int
-user_content (FILE *in, char *file, char *buf, CT *ctp)
+user_content (FILE *in, char *buf, CT *ctp)
{
int extrnal, vrsn;
char *cp, **ap;
struct part *part;
CT p;
- if (user_content (in, file, buffer, &p) == DONE) {
+ if (user_content (in, buffer, &p) == DONE) {
if (!m->mp_parts)
adios (NULL, "empty \"#begin ... #end\" sequence");
return OK;
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
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 ;;
X("saslmaxssf", SASLminc(-10), SASLMXSSFSW) \
X("saslmech mechanism", SASLminc(-5), SASLMECHSW) \
X("user username", SASLminc(-4), USERSW) \
- X("attach", 6, ATTACHSW) \
- X("noattach", 0, NOATTACHSW) \
+ X("attach", -6, ATTACHSW) \
+ X("noattach", -8, NOATTACHSW) \
X("attachformat", 7, ATTACHFORMATSW) \
X("port server-port-name/number", 4, PORTSW) \
X("tls", TLSminc(-3), TLSSW) \
char *msgs[MAXARGS], **vec;
struct msgs *mp;
struct stat st;
- char *attach = NMH_ATTACH_HEADER; /* header field name for attachments */
- int attachformat = 1; /* mhbuild format specifier for attachments */
setlocale(LC_ALL, "");
invo_name = r1bindex (argv[0], '/');
continue;
case ATTACHSW:
- if (!(attach = *argp++) || *attach == '-')
- adios (NULL, "missing argument to %s", argp[-2]);
+ advise(NULL, "The -attach switch is deprecated");
continue;
case NOATTACHSW:
- attach = NULL;
+ advise(NULL, "The -noattach switch is deprecated");
continue;
case ATTACHFORMATSW:
- if (! *argp || **argp == '-')
- adios (NULL, "missing argument to %s", argp[-1]);
- else {
- attachformat = atoi (*argp);
- if (attachformat < 0 ||
- attachformat > ATTACHFORMATS - 1) {
- advise (NULL, "unsupported attachformat %d",
- attachformat);
- continue;
- }
- }
- ++argp;
+ advise(NULL, "The -attachformat switch is deprecated");
continue;
}
} else {
closefds (3);
for (msgnum = 0; msgnum < msgp; msgnum++) {
- switch (sendsbr (vec, vecp, program, msgs[msgnum], &st, 1, attach,
- attachformat)) {
+ switch (sendsbr (vec, vecp, program, msgs[msgnum], &st, 1)) {
case DONE:
done (++status);
case NOTOK:
#include <h/mime.h>
#include <h/tws.h>
#include <h/utils.h>
+#include <h/mts.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
static jmp_buf env;
-/*
- * external prototypes
- */
-int sendsbr (char **, int, char *, char *, struct stat *, int, char *, int);
-char *getusername (void);
-
/*
* static prototypes
*/
int
sendsbr (char **vec, int vecp, char *program, char *drft, struct stat *st,
- int rename_drft, char *attachment_header_field_name, int attachformat)
+ int rename_drft)
{
- int status;
+ int status, i;
+ pid_t child;
char buffer[BUFSIZ], file[BUFSIZ];
struct stat sts;
- char *original_draft; /* name of original draft file */
- char *p; /* string pointer for building file name */
- char composition_file_name[PATH_MAX + 1]; /* name of mhbuild composition temporary file */
- char body_file_name[PATH_MAX + 1]; /* name of temporary file for body content */
-
- /*
- * Save the original name of the draft file. The name of the draft file is changed
- * to a temporary file containing the built MIME message if there are attachments.
- * We need the original name so that it can be renamed after the message is sent.
- */
-
- original_draft = drft;
+ char **buildvec, *buildprogram;
/*
- * There might be attachments if a header field name for attachments is supplied.
- * Convert the draft to a MIME message. Use the mhbuild composition file for the
- * draft if there was a successful conversion because that now contains the MIME
- * message. A nice side effect of this is that it leaves the original draft file
- * untouched so that it can be retrieved and modified if desired.
+ * Run the mimebuildproc (which is by default mhbuild) on the message
+ * with the addition of the "-auto" flag
*/
- if (attachment_header_field_name != (char *)0) {
- switch (attach(attachment_header_field_name, drft,
- body_file_name, sizeof body_file_name,
- composition_file_name, sizeof composition_file_name,
- attachformat)) {
- case OK:
- drft = composition_file_name;
- break;
+ switch (child = fork()) {
+ case NOTOK:
+ adios("fork", "unable to");
+ break;
- case NOTOK:
- return (NOTOK);
+ case OK:
+ buildvec = argsplit(buildmimeproc, &buildprogram, &i);
+ buildvec[i++] = "-auto";
+ if (distfile)
+ buildvec[i++] = "-dist";
+ buildvec[i++] = drft;
+ buildvec[i] = NULL;
+ execvp(buildprogram, buildvec);
+ fprintf(stderr, "unable to exec ");
+ perror(buildmimeproc);
+ _exit(-1);
+ break;
- case DONE:
- break;
- }
+ default:
+ if (pidXwait(child, buildmimeproc))
+ return NOTOK;
+ break;
}
done=armed_done;
/* rename the original draft */
if (rename_drft && status == OK &&
- rename (original_draft, strncpy (buffer, m_backup (original_draft), sizeof(buffer))) == NOTOK)
+ rename (drft, strncpy (buffer, m_backup (drft), sizeof(buffer))) == NOTOK)
advise (buffer, "unable to rename %s to", drft);
break;
if (distfile)
unlink (distfile);
- /*
- * Get rid of any temporary files that we created for attachments. Also get rid of
- * the renamed composition file that mhbuild leaves as a turd. It looks confusing,
- * but we use the body file name to help build the renamed composition file name.
- */
-
- if (drft == composition_file_name) {
- clean_up_temporary_files(body_file_name, composition_file_name);
-
- if (strlen(composition_file_name) >= sizeof (composition_file_name) - 6)
- advise((char *)0, "unable to remove original composition file.");
-
- else {
- if ((p = strrchr(composition_file_name, '/')) == (char *)0)
- p = composition_file_name;
- else
- p++;
-
- (void)strcpy(body_file_name, p);
- *p++ = ',';
- (void)strcpy(p, body_file_name);
- (void)strcat(p, ".orig");
-
- (void)unlink(composition_file_name);
- }
- }
-
return status;
}
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;
setlocale(LC_ALL, "");
invo_name = r1bindex (argv[0], '/');
- /* foil search of user profile/context */
- if (context_foil (NULL) == -1)
- done (1);
+ context_read();
arguments = getarguments (invo_name, argc, argv, 0);
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 */
}
vec[vecp++] = cp;
}
- switch (sendsbr (vec, vecp, program, tmpfil, &st, 0, (char *)0, 0)) {
+ switch (sendsbr (vec, vecp, program, tmpfil, &st, 0)) {
case DONE:
case NOTOK:
status++;
X("prompt string", 4, PRMPTSW) \
X("version", 0, VERSIONSW) \
X("help", 0, HELPSW) \
- X("attach header-field-name", 0, ATTACHSW) \
- X("noattach", 0, NOATTACHSW) \
+ X("attach header-field-name", -6, ATTACHSW) \
+ X("noattach", -8, NOATTACHSW) \
+
#define X(sw, minchars, id) id,
DEFINE_SWITCH_ENUM(WHATNOW);
char buf[BUFSIZ], prompt[BUFSIZ];
char **argp, **arguments;
struct stat st;
- char *attach = NMH_ATTACH_HEADER;/* attachment header field name */
char cwd[PATH_MAX + 1]; /* current working directory */
char file[PATH_MAX + 1]; /* file name buffer */
char shell[PATH_MAX + 1]; /* shell response buffer */
continue;
case ATTACHSW:
- if (!(attach = *argp++) || *attach == '-')
- adios (NULL, "missing argument to %s", argp[-2]);
+ advise(NULL, "The -attach switch is deprecated");
continue;
case NOATTACHSW:
- attach = NULL;
+ advise(NULL, "The -noattach switch is deprecated");
continue;
}
}
* -n numbers listing
*/
- if (attach == (char *)0) {
- advise((char *)0, "can't list because no header field name was given.");
- break;
- }
-
l = (char *)0;
n = 0;
advise((char *)0, "usage is alist [-ln].");
else
- annolist(drft, attach, l, n);
+ annolist(drft, ATTACH_FIELD, l, n);
break;
int verbose = 0;
char **ap;
- if (attach == (char *)0) {
- advise((char *)0, "can't attach because no header field name was given.");
- break;
- }
-
for (ap = argp+1; *ap; ++ap) {
if (strcmp(*ap, "-v") == 0) {
++argp;
if ((f = popen_in_dir(cwd, buf, "r")) != (FILE *)0) {
while (fgets(shell, sizeof (shell), f) != (char *)0) {
- char *build_directive;
+ char *ctype;
*(strchr(shell, '\n')) = '\0';
if (*shell == '/') {
- (void)annotate(drft, attach, shell, 1, 0, -2, 1);
- if (verbose) {
- build_directive =
- construct_build_directive (shell, NULL, 1);
- }
+ strncpy(file, shell, sizeof(file));
+ file[sizeof(file) - 1] = '\0';
} else {
- (void)sprintf(file, "%s/%s", cwd, shell);
- (void)annotate(drft, attach, file, 1, 0, -2, 1);
- if (verbose) {
- build_directive =
- construct_build_directive (file, NULL, 1);
- }
+ snprintf(file, sizeof(file), "%s/%s", cwd, shell);
+ }
+
+ annotate(drft, ATTACH_FIELD, file, 1, 0, -2, 1);
+ if (verbose) {
+ ctype = mime_type(file);
}
if (verbose) {
- printf ("%s", build_directive);
- free (build_directive);
+ printf ("Attaching %s as a %s", file, ctype);
+ free (ctype);
}
}
* Detach files from current draft.
*/
- if (attach == (char *)0) {
- advise((char *)0, "can't detach because no header field name was given.");
- break;
- }
-
/*
* Scan the arguments for a -n. Mixed file names and numbers aren't allowed,
* so this catches a -n anywhere in the argument list.
if (**arguments != '\0') {
n = atoi(*arguments);
- (void)annotate(drft, attach, (char *)0, 1, 0, n, 1);
+ annotate(drft, ATTACH_FIELD, (char *)0, 1, 0, n, 1);
for (argp = arguments + 1; *argp != (char *)0; argp++) {
if (atoi(*argp) > n) {
if ((f = popen_in_dir(cwd, buf, "r")) != (FILE *)0) {
while (fgets(shell, sizeof (shell), f) != (char *)0) {
*(strchr(shell, '\n')) = '\0';
- (void)annotate(drft, attach, shell, 1, 0, 0, 1);
+ annotate(drft, ATTACH_FIELD, shell, 1, 0, 0, 1);
}
pclose(f);
} else {
int i, vecp;
char *cp, *sp, **vec, *program;
- /* Translate MIME composition file, if necessary */
- if ((cp = context_find ("automimeproc"))
- && (!strcmp (cp, "1"))
- && check_draft (file)
- && (buildfile (NULL, file) == NOTOK))
- return 0;
-
- /* For backwards compatibility */
- if ((cp = context_find ("automhnproc"))
- && check_draft (file)
- && (i = editfile (&cp, NULL, file, NOUSE, NULL, NULL, NULL, 0, 0)))
- return 0;
-
/*
* If the sendproc is the nmh command `send', then we call
* those routines directly rather than exec'ing the command.
char *cp, buf[BUFSIZ], **argp, *program;
char **arguments, *savearg[MAXARGS], **vec;
struct stat st;
- char *attach = NMH_ATTACH_HEADER;/* attachment header field name */
- int attachformat = 1; /* mhbuild format specifier for
- attachments */
#ifndef lint
int distsw = 0;
continue;
case SNDATTACHSW:
- if (!(attach = *argp++) || *attach == '-') {
- advise (NULL, "missing argument to %s", argp[-2]);
- return;
- }
+ advise(NULL, "The -attach switch is deprecated");
continue;
case SNDNOATTACHSW:
- attach = NULL;
+ advise(NULL, "The -noattach switch is deprecated");
continue;
case SNDATTACHFORMAT:
- if (! *argp || **argp == '-')
- adios (NULL, "missing argument to %s", argp[-1]);
- else {
- attachformat = atoi (*argp);
- if (attachformat < 0 ||
- attachformat > ATTACHFORMATS - 1) {
- advise (NULL, "unsupported attachformat %d",
- attachformat);
- continue;
- }
- }
- ++argp;
+ advise(NULL, "The -attachformat switch is deprecated");
continue;
}
}
closefds (3);
- if (sendsbr (vec, vecp, program, file, &st, 1, attach, attachformat) == OK)
+ if (sendsbr (vec, vecp, program, file, &st, 1) == OK)
done (0);
}