- The MIME content cache functionality has been mostly non-functional since
the development on nmh, and consequently all of the content caching code
and related switches (-cache/-rcache/-wcache) have been removed.
+- Support for generating and reassembling message/partial messags has been
+ removed; it seems that this has been broken since 1.5 and there is very
+ little support across MUAs.
-------------------
DEPRECATED FEATURES
switches are:
-compress [bzip2 | compress | gzip | lzma | none]
-from <sender>
- -[delay] <delay> (expressed in seconds)
-version
-help
Can use PERSON environment variable instead of -from switch.'
#### 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
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 ;;
*) 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
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
"$nmhlibexecdir/viamail" -to "$to" -subject "$subject" \
-from "$from" -parameters "type=tar$conversion" \
-comment "extract with $uncompress | tar xvpf -" \
- -delay "$delay" -verbose
+ -verbose
/* Flags for subtypes of MESSAGE */
#define MESSAGE_UNKNOWN 0x00
#define MESSAGE_RFC822 0x01
-#define MESSAGE_PARTIAL 0x02
-#define MESSAGE_EXTERNAL 0x03
-
-/* Structure for message/partial */
-struct partial {
- char *pm_partid;
- int pm_partno;
- int pm_maxno;
- int pm_marked;
- int pm_stored;
-};
+#define MESSAGE_EXTERNAL 0x02
/* Structure for message/external */
struct exbody {
---- --------
text plain, enriched
multipart mixed, alternative, digest, parallel
-message rfc822, partial, external-body
+message rfc822, external-body
application octet-stream, postscript
image jpeg, gif, png
audio basic
---- --------
text plain, enriched
multipart mixed, alternative, digest, parallel
-message rfc822, partial, external-body
+message rfc822, external-body
application octet-stream, postscript
image jpeg, gif, png
audio basic
character sets, look at the
.IR less (1)
manual entry for information about the LESSCHARDEF environment variable.)
-.SS "Messages of Type message/partial"
-.B mhshow
-cannot directly display messages of type partial.
-You must first reassemble them into a normal message using
-.BR mhstore .
-Check
-.IR mhstore (1)
-for details.
.SS "External Access"
For contents of type message/external-body,
.B mhshow
---- --------
text plain, enriched
multipart mixed, alternative, digest, parallel
-message rfc822, partial, external-body
+message rfc822, external-body
application octet-stream, postscript
image jpeg, gif, png
audio basic
.nf
mhstore-store-text: %m%P.txt
mhstore-store-text: +inbox
-mhstore-store-message/partial: +
mhstore-store-audio/basic: | raw2audio -e ulaw -s 8000 -c 1 > %m%P.au
mhstore-store-image/jpeg: %m%P.jpg
mhstore-store-application/PostScript: %m%P.ps
.I ask
behaves the same as
.IR always .
-.SS "Reassembling Messages of Type message/partial"
-.B mhstore
-is also able to reassemble messages that have been
-split into multiple messages of type \*(lqmessage/partial\*(rq.
-.PP
-When asked to store a content containing a partial message,
-.B mhstore
-will try to locate all of the portions and combine them accordingly.
-The default is to store the combined parts as a new message in the
-current folder, although this can be changed using formatting
-strings as discussed above. Thus, if someone has sent you a
-message in several parts (such as the output from
-.BR sendfiles ),
-you can easily reassemble them into a single message in the
-following fashion:
-.PP
-.RS 5
-.nf
-$ mhlist 5-8
- msg part type/subtype size description
- 5 message/partial 47K part 1 of 4
- 6 message/partial 47K part 2 of 4
- 7 message/partial 47K part 3 of 4
- 8 message/partial 18K part 4 of 4
-$ mhstore 5-8
-reassembling partials 5,6,7,8 to folder inbox as message 9
-$ mhlist -verbose 9
- msg part type/subtype size description
- 9 application/octet-stream 118K
- (extract with uncompress | tar xvpf -)
- type=tar
- conversions=compress
-.fi
-.RE
-.PP
-This will store exactly one message, containing the sum of the
-parts. It doesn't matter whether the partials are specified in
-order, since
-.B mhstore
-will sort the partials, so that they are combined in the correct
-order. But if
-.B mhstore
-can not locate every partial necessary to reassemble the message,
-it will not store anything.
.SS "External Access"
For contents of type message/external-body,
\fImhstore\fR supports these access-types:
.RB [ \-messageid
.IR localname " | " random ]
.RB [ \-push " | " \-nopush ]
-.RB [ \-split
-.IR seconds ]
.RB [ \-verbose " | " \-noverbose ]
.RB [ \-watch " | " \-nowatch ]
.RB [ \-mts
for more
information.
.PP
-If
-.B \-split
-is specified,
-.B send
-will split the draft into one
-or more partial messages prior to sending. This makes use of the
-MIME features in
-.BR nmh .
-Note however that if
-.B send
-is
-invoked under
-.BR dist ,
-then this switch is ignored\0--\0it makes
-no sense to redistribute a message in this fashion. Sometimes you want
-.B send
-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. The argument to
-.B \-split
-tells it how long
-to pause between postings.
-.PP
.B send
with no
.I file
transaction;
.B \-watch
is a no-op on those systems.
-.PP
-Using
-.B \-split
-.I 0
-doesn't work correctly.
.br
.RB [ \-from
.IR sender ]
-.RI [ "\-delay n" " | " \-n ]
.br
.B \-to
.I recipient
.B tar
command, and then mail the compressed
archive to the \*(lqrecipient\*(rq with the given \*(lqsubject\*(rq.
-The archive
-will be automatically split up into as many messages as necessary
-in order to get past most mailers.
.PP
The
.B \-to
.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. The
-.B \-delay
-switch specifies the number of seconds to pause in between postings,
-e.g.,
-.PP
-.RS 5
-sendfiles -delay 30 -to recipient -subject \*(lqsubject\*(rq files\0...
-.RE
-.PP
-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
+When the message is received, invoke
.B mhstore
once for
-the list of messages. The default is for
-.B mhstore
-to store
-the combined parts as a new message in the current folder, although
-this can be changed using storage formatting strings. You can then
-use
-.B mhlist
-to find out what's inside; possibly followed by
+the received message. The default is for
.B mhstore
-again to write the archive to a file where you can
+to write the archive to a file where you can
subsequently uncompress and untar it. For instance:
.PP
.RS 5
.nf
-$ mhlist 5-8
- msg part type/subtype size description
- 5 message/partial 47K part 1 of 4
- 6 message/partial 47K part 2 of 4
- 7 message/partial 47K part 3 of 4
- 8 message/partial 18K part 4 of 4
-$ mhstore 5-8
-reassembling partials 5,6,7,8 to folder inbox as message 9
$ mhlist -verbose 9
msg part type/subtype size description
9 application/octet-stream 118K
.PP
.RS 5
.nf
-$ mhlist 5-8
- msg part type/subtype size description
- 5 message/partial 47K part 1 of 4
- 6 message/partial 47K part 2 of 4
- 7 message/partial 47K part 3 of 4
- 8 message/partial 18K part 4 of 4
-$ mhstore 5-8
-reassembling partials 5,6,7,8 to folder inbox as message 9
$ mhlist -verbose 9
msg part type/subtype size description
9 application/octet-stream 118K
run_prog mhstore -noverbose -file `mhpath 11` -part 2 -outfile - >"$actual" 2>&1
check "$expected" "$actual"
-# check reassembly of message/partial messages (RFC 1521, 7.3.2)
-start_test 'reassembly of message/partial messages (RFC 1521, 7.3.2)'
-msgfile=`mhpath new`
-cat >"$msgfile" <<'EOF'
-To: recipient@example.com
-From: sender@example.com
-Subject: mhlist test
-MIME-Version: 1.0
-Content-Type: message/partial; id="test-mhstore message/partial test"; number=1
-
-Content-Type: text/plain; charset="iso-8859-1"
-
-This is part one of three.
-EOF
-
-msgfile=`mhpath new`
-cat >"$msgfile" <<'EOF'
-To: recipient@example.com
-From: sender@example.com
-Subject: mhlist test
-MIME-Version: 1.0
-Content-Type: message/partial; id="test-mhstore message/partial test"; number=2
-
-This is part two of three.
-EOF
-
-msgfile=`mhpath new`
-cat >"$msgfile" <<'EOF'
-To: recipient@example.com
-From: sender@example.com
-Subject: mhlist test
-MIME-Version: 1.0
-Content-Type: message/partial; id="test-mhstore message/partial test"; number=3;
- total=3
-
-This is part three of three.
-EOF
-
-run_test 'mhstore last:3' \
- 'reassembling partials 12,13,14 to folder inbox as message 15'
-
-cat >"$expected" <<'EOF'
-This is part one of three.
-This is part two of three.
-This is part three of three.
-EOF
-run_test 'mhstore last' 'storing message 15 as file 15.txt'
-check "$expected" 15.txt
-
# cd into Mail directory because it gets cleaned up by the exit trap.
cd Mail
switches are:
-compress [bzip2 | compress | gzip | lzma | none]
-from <sender>
- -[delay] <delay> (expressed in seconds)
-version
-help
Can use PERSON environment variable instead of -from switch.
switches are:
-compress [bzip2 | compress | gzip | lzma | none]
-from <sender>
- -[delay] <delay> (expressed in seconds)
-version
-help
Can use PERSON environment variable instead of -from switch."
switches are:
-compress [bzip2 | compress | gzip | lzma | none]
-from <sender>
- -[delay] <delay> (expressed in seconds)
-version
-help
Can use PERSON environment variable instead of -from switch."
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
- 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
- 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" "$MH_TEST_DIR/tmp"
static void free_header (CT);
static void free_text (CT);
static void free_multi (CT);
-static void free_partial (CT);
static void free_external (CT);
static void free_pmlist (PM *);
case CT_MESSAGE:
switch (ct->c_subtype) {
- case MESSAGE_PARTIAL:
- free_partial (ct);
- break;
-
case MESSAGE_EXTERNAL:
free_external (ct);
break;
}
-static void
-free_partial (CT ct)
-{
- struct partial *p;
-
- if (!(p = (struct partial *) ct->c_ctparams))
- return;
-
- free(p->pm_partid);
-
- free(p);
- ct->c_ctparams = NULL;
-}
-
-
static void
free_external (CT ct)
{
static void list_single_message (CT, int, int, int, int);
static int list_debug (CT);
static int list_multi (CT, int, int, int, int, int);
-static int list_partial (CT, int, int, int, int, int);
static int list_external (CT, int, int, int, int, int);
static int list_encoding (CT);
case CT_MESSAGE:
switch (ct->c_subtype) {
- case MESSAGE_PARTIAL:
- return list_partial (ct, toplevel, realsize, verbose,
- debug, dispo);
-
case MESSAGE_EXTERNAL:
return list_external (ct, toplevel, realsize, verbose,
debug, dispo);
}
-/*
- * list content information for type "message/partial"
- */
-
-static int
-list_partial (CT ct, int toplevel, int realsize, int verbose, int debug,
- int dispo)
-{
- struct partial *p = (struct partial *) ct->c_ctparams;
-
- list_content (ct, toplevel, realsize, verbose, debug, dispo);
- if (verbose) {
- printf ("\t [message %s, part %d", p->pm_partid, p->pm_partno);
- if (p->pm_maxno)
- printf (" of %d", p->pm_maxno);
- puts("]");
- }
-
- return OK;
-}
-
-
/*
* list content information for type "message/external"
*/
*/
struct k2v SubMessage[] = {
{ "rfc822", MESSAGE_RFC822 },
- { "partial", MESSAGE_PARTIAL },
{ "external-body", MESSAGE_EXTERNAL },
{ NULL, MESSAGE_UNKNOWN } /* this one must be last! */
};
case MESSAGE_RFC822:
break;
- case MESSAGE_PARTIAL:
- {
- PM pm;
- struct partial *p;
-
- NEW0(p);
- ct->c_ctparams = (void *) p;
-
- /* scan for parameters "id", "number", and "total" */
- for (pm = ci->ci_first_pm; pm; pm = pm->pm_next) {
- if (!strcasecmp (pm->pm_name, "id")) {
- p->pm_partid = mh_xstrdup(FENDNULL(pm->pm_value));
- continue;
- }
- if (!strcasecmp (pm->pm_name, "number")) {
- if (sscanf (pm->pm_value, "%d", &p->pm_partno) != 1
- || p->pm_partno < 1) {
-invalid_param:
- inform("invalid %s parameter for \"%s/%s\" type in message %s's %s field",
- pm->pm_name, ci->ci_type, ci->ci_subtype,
- ct->c_file, TYPE_FIELD);
- return NOTOK;
- }
- continue;
- }
- if (!strcasecmp (pm->pm_name, "total")) {
- if (sscanf (pm->pm_value, "%d", &p->pm_maxno) != 1
- || p->pm_maxno < 1)
- goto invalid_param;
- continue;
- }
- }
-
- if (!p->pm_partid
- || !p->pm_partno
- || (p->pm_maxno && p->pm_partno > p->pm_maxno)) {
- inform("invalid parameters for \"%s/%s\" type in message %s's %s field",
- ci->ci_type, ci->ci_subtype, ct->c_file, TYPE_FIELD);
- return NOTOK;
- }
- }
- break;
-
case MESSAGE_EXTERNAL:
{
int exresult;
switch (subtype) {
case MESSAGE_RFC822:
return "rfc822";
- case MESSAGE_PARTIAL:
- return "partial";
case MESSAGE_EXTERNAL:
return "external";
default:
static int show_multi_internal (CT, int, int, int, int, struct format *);
static int show_multi_aux (CT, int, char *, struct format *);
static int show_message_rfc822 (CT, int, struct format *);
-static int show_partial (CT, int);
static int show_external (CT, int, int, int, int, struct format *);
static int parse_display_string (CT, char *, int *, int *, char *, char *,
size_t, int multipart);
case CT_MESSAGE:
switch (ct->c_subtype) {
- case MESSAGE_PARTIAL:
- return show_partial (ct, alternate);
-
case MESSAGE_EXTERNAL:
return show_external (ct, alternate, concatsw, textonly,
inlineonly, fmt);
}
-/*
- * Show content of type "message/partial".
- */
-
-static int
-show_partial (CT ct, int alternate)
-{
- NMH_UNUSED (alternate);
-
- content_error (NULL, ct,
- "in order to display this message, you must reassemble it");
- return NOTOK;
-}
-
-
/*
* Show content of type "message/external".
*
static int store_generic (CT, mhstoreinfo_t);
static int store_application (CT, mhstoreinfo_t);
static int store_multi (CT, mhstoreinfo_t);
-static int store_partial (CT, mhstoreinfo_t);
static int store_external (CT, mhstoreinfo_t);
-static int ct_compar (CT *, CT *);
-static int store_content (CT, CT, mhstoreinfo_t);
+static int store_content (CT, mhstoreinfo_t);
static int output_content_file (CT, int);
static int output_content_folder (char *, char *);
static int parse_format_string (CT, char *, char *, int, char *);
static void get_storeproc (CT);
-static int copy_some_headers (FILE *, CT);
static char *clobber_check (char *, mhstoreinfo_t);
/*
case CT_MESSAGE:
switch (ct->c_subtype) {
- case MESSAGE_PARTIAL:
- return store_partial (ct, info);
-
case MESSAGE_EXTERNAL:
return store_external (ct, info);
if (info->autosw && ct->c_type != CT_MESSAGE)
get_storeproc (ct);
- return store_content (ct, NULL, info);
+ return store_content (ct, info);
}
}
}
- return store_content (ct, NULL, info);
+ return store_content (ct, info);
}
}
-/*
- * Reassemble and store the contents of a collection
- * of messages of type "message/partial".
- */
-
-static int
-store_partial (CT ct, mhstoreinfo_t info)
-{
- int cur, hi, i;
- CT p, *ctp, *ctq;
- CT *base;
- struct partial *pm, *qm;
-
- qm = (struct partial *) ct->c_ctparams;
- if (qm->pm_stored)
- return OK;
-
- hi = i = 0;
- for (ctp = info->cts; *ctp; ctp++) {
- p = *ctp;
- if (p->c_type == CT_MESSAGE && p->c_subtype == ct->c_subtype) {
- pm = (struct partial *) p->c_ctparams;
- if (!pm->pm_stored
- && strcmp (qm->pm_partid, pm->pm_partid) == 0) {
- pm->pm_marked = pm->pm_partno;
- if (pm->pm_maxno)
- hi = pm->pm_maxno;
- pm->pm_stored = 1;
- i++;
- }
- else
- pm->pm_marked = 0;
- }
- }
-
- if (hi == 0) {
- inform("missing (at least) last part of multipart message");
- return NOTOK;
- }
-
- base = mh_xcalloc(i + 1, sizeof *base);
- ctq = base;
- for (ctp = info->cts; *ctp; ctp++) {
- p = *ctp;
- if (p->c_type == CT_MESSAGE && p->c_subtype == ct->c_subtype) {
- pm = (struct partial *) p->c_ctparams;
- if (pm->pm_marked)
- *ctq++ = p;
- }
- }
- *ctq = NULL;
-
- if (i > 1)
- qsort(base, i, sizeof(*base), (qsort_comp) ct_compar);
-
- cur = 1;
- for (ctq = base; *ctq; ctq++) {
- p = *ctq;
- pm = (struct partial *) p->c_ctparams;
- if (pm->pm_marked == cur) {
- cur++;
- continue;
- }
-
- if (pm->pm_marked == cur - 1) {
- inform("duplicate part %d of %d part multipart message, continuing...",
- pm->pm_marked, hi);
- continue;
- }
-
-missing_part:
- inform("missing %spart %d of %d part multipart message",
- cur != hi ? "(at least) " : "", cur, hi);
- goto losing;
- }
- if (hi != --cur) {
- cur = hi;
- goto missing_part;
- }
-
- /*
- * Now cycle through the sorted list of messages of type
- * "message/partial" and save/append them to a file.
- */
-
- ctq = base;
- ct = *ctq++;
- if (store_content (ct, NULL, info) == NOTOK) {
-losing:
- free(base);
- return NOTOK;
- }
-
- for (; *ctq; ctq++) {
- p = *ctq;
- if (store_content (p, ct, info) == NOTOK)
- goto losing;
- }
-
- free(base);
- return OK;
-}
-
-
/*
* Store content from a message of type "message/external".
*/
}
-/*
- * Compare the numbering from two different
- * message/partials (needed for sorting).
- */
-
-static int
-ct_compar (CT *a, CT *b)
-{
- struct partial *am = (struct partial *) ((*a)->c_ctparams);
- struct partial *bm = (struct partial *) ((*b)->c_ctparams);
-
- return am->pm_marked - bm->pm_marked;
-}
-
-
/*
* Store contents of a message or message part to
* a folder, a file, the standard output, or pass
* the contents to a command.
- *
- * If the current content to be saved is a followup part
- * to a collection of messages of type "message/partial",
- * then field "p" is a pointer to the Content structure
- * to the first message/partial in the group.
*/
static int
-store_content (CT ct, CT p, mhstoreinfo_t info)
+store_content (CT ct, mhstoreinfo_t info)
{
bool appending = false;
int msgnum = 0;
- bool is_partial = false;
- bool first_partial = false;
- bool last_partial = false;
char *cp, buffer[BUFSIZ];
- /*
- * Do special processing for messages of
- * type "message/partial".
- *
- * We first check if this content is of type
- * "message/partial". If it is, then we need to check
- * whether it is the first and/or last in the group.
- *
- * Then if "p" is a valid pointer, it points to the Content
- * structure of the first partial in the group. So we copy
- * the file name and/or folder name from that message. In
- * this case, we also note that we will be appending.
- */
- if (ct->c_type == CT_MESSAGE && ct->c_subtype == MESSAGE_PARTIAL) {
- struct partial *pm = (struct partial *) ct->c_ctparams;
-
- /* Yep, it's a message/partial */
- is_partial = true;
-
- /* But is it the first and/or last in the collection? */
- if (pm->pm_partno == 1)
- first_partial = true;
- if (pm->pm_maxno && pm->pm_partno == pm->pm_maxno)
- last_partial = true;
-
- /*
- * If "p" is a valid pointer, then it points to the
- * Content structure for the first message in the group.
- * So we just copy the filename or foldername information
- * from the previous iteration of this function.
- */
- if (p) {
- appending = true;
- if (! ct->c_storage) {
- ct->c_storage = mh_xstrdup(FENDNULL(p->c_storage));
-
- /* record the folder name */
- if (p->c_folder) {
- ct->c_folder = mh_xstrdup(p->c_folder);
- }
- }
- goto got_filename;
- }
- }
-
/*
* Get storage formatting string.
*
/*
* If necessary, link the file into a folder and remove
- * the temporary file. If this message is a partial,
- * then only do this if it is the last one in the group.
+ * the temporary file.
*/
- if (ct->c_folder && (!is_partial || last_partial)) {
+ if (ct->c_folder) {
msgnum = output_content_folder (ct->c_folder, ct->c_storage);
(void) m_unlink (ct->c_storage);
if (msgnum == NOTOK)
* Now print out the name/number of the message
* that we are storing.
*/
- if (is_partial) {
- if (first_partial)
- fprintf (stderr, "reassembling partials ");
- if (last_partial)
- fputs(ct->c_file, stderr);
- else
- fprintf (stderr, "%s,", ct->c_file);
- } else {
- fprintf (stderr, "storing message %s", ct->c_file);
- if (ct->c_partno)
- fprintf (stderr, " part %s", ct->c_partno);
- }
+ fprintf (stderr, "storing message %s", ct->c_file);
+ if (ct->c_partno)
+ fprintf (stderr, " part %s", ct->c_partno);
/*
- * Unless we are in the "middle" of group of message/partials,
- * we now print the name of the file, folder, and/or message
+ * We now print the name of the file, folder, and/or message
* to which we are storing the content.
*/
- if (!is_partial || last_partial) {
- if (ct->c_folder) {
- fprintf (stderr, " to folder %s as message %d\n", ct->c_folder,
- msgnum);
- } else if (!strcmp(ct->c_storage, "-")) {
- fprintf (stderr, " to stdout\n");
- } else {
- int cwdlen = strlen (info->cwd);
-
- fprintf (stderr, " as file %s\n",
- !has_prefix(ct->c_storage, info->cwd)
- || ct->c_storage[cwdlen] != '/'
- ? ct->c_storage : ct->c_storage + cwdlen + 1);
+ if (ct->c_folder) {
+ fprintf (stderr, " to folder %s as message %d\n", ct->c_folder,
+ msgnum);
+ } else if (!strcmp(ct->c_storage, "-")) {
+ fprintf (stderr, " to stdout\n");
+ } else {
+ int cwdlen = strlen (info->cwd);
+
+ fprintf (stderr, " as file %s\n",
+ !has_prefix(ct->c_storage, info->cwd)
+ || ct->c_storage[cwdlen] != '/'
+ ? ct->c_storage : ct->c_storage + cwdlen + 1);
}
- }
}
return OK;
static int
output_content_file (CT ct, int appending)
{
- int filterstate;
char *file, buffer[BUFSIZ];
long pos, last;
FILE *fp;
}
}
- /*
- * Filter the header fields of the initial enclosing
- * message/partial into the file.
- */
- if (ct->c_type == CT_MESSAGE && ct->c_subtype == MESSAGE_PARTIAL) {
- struct partial *pm = (struct partial *) ct->c_ctparams;
-
- if (pm->pm_partno == 1)
- copy_some_headers (fp, ct);
- }
-
for (;;) {
switch (cc = read (fd, buffer, sizeof(buffer))) {
case NOTOK:
}
}
- /*
- * Copy a few of the header fields of the initial
- * enclosing message/partial into the file.
- */
- filterstate = 0;
- if (ct->c_type == CT_MESSAGE && ct->c_subtype == MESSAGE_PARTIAL) {
- struct partial *pm = (struct partial *) ct->c_ctparams;
-
- if (pm->pm_partno == 1) {
- copy_some_headers (fp, ct);
- filterstate = 1;
- }
- }
-
while (fgets (buffer, sizeof buffer, ct->c_fp)) {
if ((pos += strlen (buffer)) > last) {
int diff;
if (diff >= 0)
buffer[diff] = '\0';
}
- /*
- * If this is the first content of a group of
- * message/partial contents, then we only copy a few
- * of the header fields of the enclosed message.
- */
- if (filterstate) {
- switch (buffer[0]) {
- case ' ':
- case '\t':
- if (filterstate < 0)
- buffer[0] = 0;
- break;
-
- case '\n':
- filterstate = 0;
- break;
-
- default:
- if (!uprf (buffer, XXX_FIELD_PRF)
- && !uprf (buffer, VRSN_FIELD)
- && !uprf (buffer, "Subject:")
- && !uprf (buffer, "Encrypted:")
- && !uprf (buffer, "Message-ID:")) {
- filterstate = -1;
- buffer[0] = 0;
- break;
- }
- filterstate = 1;
- break;
- }
- }
fputs (buffer, fp);
if (pos >= last)
break;
}
-/*
- * Copy some of the header fields of the initial message/partial
- * message into the header of the reassembled message.
- */
-
-static int
-copy_some_headers (FILE *out, CT ct)
-{
- HF hp;
-
- hp = ct->c_first_hf; /* start at first header field */
-
- while (hp) {
- /*
- * A few of the header fields of the enclosing
- * messages are not copied.
- */
- if (!uprf (hp->name, XXX_FIELD_PRF)
- && strcasecmp (hp->name, VRSN_FIELD)
- && strcasecmp (hp->name, "Subject")
- && strcasecmp (hp->name, "Encrypted")
- && strcasecmp (hp->name, "Message-ID"))
- fprintf (out, "%s:%s", hp->name, hp->value);
- hp = hp->next; /* next header field */
- }
-
- return OK;
-}
-
/******************************************************************************/
/* -clobber support */
X("nomsgid", 0, NMSGDSW) \
X("push", 0, PUSHSW) \
X("nopush", 0, NPUSHSW) \
- X("split seconds", 0, SPLITSW) \
X("unique", -6, UNIQSW) \
X("nounique", -8, NUNIQSW) \
X("verbose", 0, VERBSW) \
extern bool forwsw;
extern int inplace;
extern bool pushsw;
-extern int splitsw;
extern bool unique;
extern bool verbsw;
pushsw = false;
continue;
- case SPLITSW:
- if (!(cp = *argp++) || sscanf (cp, "%d", &splitsw) != 1)
- die("missing argument to %s", argp[-2]);
- continue;
-
case UNIQSW:
unique = true;
continue;
bool forwsw = true;
int inplace = 1;
bool pushsw;
-int splitsw = -1;
bool unique;
bool verbsw;
static int tmp_fd (void);
static void anno (int, struct stat *);
static void annoaux (int);
-static int splitmsg (char **, int, char *, char *, struct stat *, int);
static int sendaux (char **, int, char *, char *, struct stat *);
static void handle_sendfrom(char **, int *, char *, const char *);
static int get_from_header_info(const char *, const char **, const char **, const char **);
int status, i;
pid_t child;
char buffer[BUFSIZ], file[BUFSIZ];
- struct stat sts;
char **buildvec, *buildprogram;
char *volatile drft = draft;
/* nvecs is volatile to prevent warning from gcc about possible clobbering
handle_sendfrom(vec, nvecsp, draft, auth_svc);
}
- /*
- * Check if we need to split the message into
- * multiple messages of type "message/partial".
- */
- if (splitsw >= 0 && !distfile && stat ((char *) drft, &sts) != NOTOK
- && sts.st_size >= CPERMSG) {
- status = splitmsg (vec, nvecs, program, drft,
- st, splitsw) ? NOTOK : OK;
- } else {
- status = sendaux (vec, nvecs, program, drft, st) ? NOTOK : OK;
- }
+ status = sendaux (vec, nvecs, program, drft, st) ? NOTOK : OK;
/* rename the original draft */
if (rename_drft && status == OK &&
return status;
}
-/*
- * Split large message into several messages of
- * type "message/partial" and send them.
- */
-
-static int
-splitmsg (char **vec, int vecp, char *program, char *drft,
- struct stat *st, int delay)
-{
- int compnum, nparts, partno, state, status;
- long pos, start;
- time_t clock;
- char *cp, *dp, buffer[NMH_BUFSIZ], msgid[BUFSIZ];
- char subject[BUFSIZ];
- char name[NAMESZ], partnum[BUFSIZ];
- FILE *in;
- m_getfld_state_t gstate;
-
- if ((in = fopen (drft, "r")) == NULL)
- adios (drft, "unable to open for reading");
-
- cp = dp = NULL;
- start = 0L;
-
- /*
- * Scan through the message and examine the various header fields,
- * as well as locate the beginning of the message body.
- */
- gstate = m_getfld_state_init(in);
- m_getfld_track_filepos2(&gstate);
- for (compnum = 1;;) {
- int bufsz = sizeof buffer;
- switch (state = m_getfld2(&gstate, name, buffer, &bufsz)) {
- case FLD:
- case FLDPLUS:
- compnum++;
-
- /*
- * This header field is discarded.
- */
- if (!strcasecmp (name, "Message-ID")) {
- while (state == FLDPLUS) {
- bufsz = sizeof buffer;
- state = m_getfld2(&gstate, name, buffer, &bufsz);
- }
- } else if (uprf (name, XXX_FIELD_PRF)
- || !strcasecmp (name, VRSN_FIELD)
- || !strcasecmp (name, "Subject")
- || !strcasecmp (name, "Encrypted")) {
- /*
- * These header fields are copied to the enclosed
- * header of the first message in the collection
- * of message/partials. For the "Subject" header
- * field, we also record it, so that a modified
- * version of it, can be copied to the header
- * of each message/partial in the collection.
- */
- if (!strcasecmp (name, "Subject")) {
- strncpy (subject, buffer, BUFSIZ);
- trim_suffix_c(subject, '\n');
- }
-
- dp = add (concat (name, ":", buffer, NULL), dp);
- while (state == FLDPLUS) {
- bufsz = sizeof buffer;
- state = m_getfld2(&gstate, name, buffer, &bufsz);
- dp = add (buffer, dp);
- }
- } else {
- /*
- * These header fields are copied to the header of
- * each message/partial in the collection.
- */
- cp = add (concat (name, ":", buffer, NULL), cp);
- while (state == FLDPLUS) {
- bufsz = sizeof buffer;
- state = m_getfld2(&gstate, name, buffer, &bufsz);
- cp = add (buffer, cp);
- }
- }
-
- start = ftell (in) + 1;
- continue;
-
- case BODY:
- case FILEEOF:
- break;
-
- case LENERR:
- case FMTERR:
- die("message format error in component #%d", compnum);
-
- default:
- die("getfld () returned %d", state);
- }
-
- break;
- }
- m_getfld_state_destroy (&gstate);
- if (cp == NULL)
- die("headers missing from draft");
-
- nparts = 1;
- pos = start;
- while (fgets (buffer, sizeof buffer, in)) {
- long len;
-
- if ((pos += (len = strlen (buffer))) > CPERMSG) {
- nparts++;
- pos = len;
- }
- }
-
- /* Only one part, nothing to split */
- if (nparts == 1) {
- free (cp);
- free(dp);
-
- fclose (in);
- return sendaux (vec, vecp, program, drft, st);
- }
-
- if (!pushsw) {
- printf ("Sending as %d Partial Messages\n", nparts);
- fflush (stdout);
- }
- status = OK;
-
- vec[vecp++] = "-partno";
- vec[vecp++] = partnum;
- if (delay == 0)
- vec[vecp++] = "-queued";
-
- time (&clock);
- snprintf (msgid, sizeof(msgid), "%s", message_id (clock, 0));
-
- fseek (in, start, SEEK_SET);
- for (partno = 1; partno <= nparts; partno++) {
- char tmpdrf[BUFSIZ];
- FILE *out;
-
- char *cp = m_mktemp2(drft, invo_name, NULL, &out);
- if (cp == NULL) {
- die("unable to create temporary file");
- }
- strncpy(tmpdrf, cp, sizeof(tmpdrf));
-
- /*
- * Output the header fields
- */
- fputs (cp, out);
- fprintf (out, "Subject: %s (part %d of %d)\n", subject, partno, nparts);
- fprintf (out, "%s: %s\n", VRSN_FIELD, VRSN_VALUE);
- fprintf (out, "%s: message/partial; id=\"%s\";\n", TYPE_FIELD, msgid);
- fprintf (out, "\tnumber=%d; total=%d\n", partno, nparts);
- fprintf (out, "%s: part %d of %d\n\n", DESCR_FIELD, partno, nparts);
-
- /*
- * If this is the first in the collection, output the
- * header fields we are encapsulating at the beginning
- * of the body of the first message.
- */
- if (partno == 1) {
- if (dp)
- fputs (dp, out);
- fprintf (out, "Message-ID: %s\n", msgid);
- fprintf (out, "\n");
- }
-
- pos = 0;
- for (;;) {
- long len;
-
- if (!fgets (buffer, sizeof buffer, in)) {
- if (partno == nparts)
- break;
- die("premature eof");
- }
-
- if ((pos += (len = strlen (buffer))) > CPERMSG) {
- fseek (in, -len, SEEK_CUR);
- break;
- }
-
- fputs (buffer, out);
- }
-
- if (fflush (out))
- adios (tmpdrf, "error writing to");
-
- fclose (out);
-
- if (!pushsw && verbsw) {
- putchar('\n');
- fflush (stdout);
- }
-
- /* Pause here, if a delay is specified */
- if (delay > 0 && 1 < partno && partno <= nparts) {
- if (!pushsw) {
- printf ("pausing %d seconds before sending part %d...\n",
- delay, partno);
- fflush (stdout);
- }
- sleep ((unsigned int) delay);
- }
-
- snprintf (partnum, sizeof(partnum), "%d", partno);
- status = sendaux (vec, vecp, program, tmpdrf, st);
- (void) m_unlink (tmpdrf);
- if (status != OK)
- break;
-
- /*
- * This is so sendaux will only annotate
- * the altmsg the first time it is called.
- */
- annotext = NULL;
- }
-
- free (cp);
- free(dp);
-
- fclose (in); /* close the draft */
- return status;
-}
-
/*
* Annotate original message, and
X("parameters arguments", 0, PARAMSW) \
X("description text", 0, DESCRIPTSW) \
X("comment text", 0, COMMENTSW) \
- X("delay seconds", 0, DELAYSW) \
X("verbose", 0, VERBSW) \
X("noverbose", 0, NVERBSW) \
X("version", 0, VERSIONSW) \
#undef X
extern int debugsw;
-extern int splitsw;
extern bool verbsw;
/*
* static prototypes
*/
-static int via_mail (char *, char *, char *, char *, char *, int, char *);
+static int via_mail (char *, char *, char *, char *, char *, char *);
int
main (int argc, char **argv)
{
- int delay = 0;
char *f1 = NULL, *f2 = NULL, *f3 = NULL;
- char *f4 = NULL, *f5 = NULL, *f7 = NULL;
+ char *f4 = NULL, *f5 = NULL, *f6 = NULL;
char *cp, buf[BUFSIZ];
char **argp, **arguments;
if (!(f5 = *argp++))
die("missing argument to %s", argp[-2]);
continue;
- case DELAYSW:
- if (!(cp = *argp++) || *cp == '-')
- die("missing argument to %s", argp[-2]);
-
- /*
- * If there is an error, just reset the delay parameter
- * to -1. We will set a default delay later.
- */
- if (sscanf (cp, "%d", &delay) != 1)
- delay = -1;
- continue;
case FROMSW:
- if (!(f7 = *argp++))
+ if (!(f6 = *argp++))
die("missing argument to %s", argp[-2]);
continue;
if (!f1)
die("missing -viamail \"mailpath\" switch");
- via_mail (f1, f2, f3, f4, f5, delay, f7);
+ via_mail (f1, f2, f3, f4, f5, f6);
return 0; /* dead code to satisfy the compiler */
}
static int
via_mail (char *mailsw, char *subjsw, char *parmsw, char *descsw,
- char *cmntsw, int delay, char *fromsw)
+ char *cmntsw, char *fromsw)
{
int status, vecp;
char tmpfil[BUFSIZ], *program;
if (fstat (fileno (fp), &st) == NOTOK)
adios ("failed", "fstat of %s", tmpfil);
- if (delay < 0)
- splitsw = 10;
- else
- splitsw = delay;
-
status = 0;
vec = argsplit(postproc, &program, &vecp);
extern bool forwsw;
extern int inplace;
extern bool pushsw;
-extern int splitsw;
extern bool unique;
extern bool verbsw;
pushed = 0;
continue;
- case SPLITSW:
- if (!(cp = *argp++) || sscanf (cp, "%d", &splitsw) != 1) {
- inform("missing argument to %s", argp[-2]);
- return;
- }
- continue;
-
case UNIQSW:
unique = true;
continue;