X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/9ca1024919eb864456ca64ed2439dc5a51bab243..475fef2edee9db3c63fc089df76f8e93e3d598cd:/uip/burst.c?ds=inline diff --git a/uip/burst.c b/uip/burst.c index 93fd5e03..71b226c1 100644 --- a/uip/burst.c +++ b/uip/burst.c @@ -9,38 +9,48 @@ #include #include - -static struct swit switches[] = { -#define INPLSW 0 - { "inplace", 0 }, -#define NINPLSW 1 - { "noinplace", 0 }, -#define QIETSW 2 - { "quiet", 0 }, -#define NQIETSW 3 - { "noquiet", 0 }, -#define VERBSW 4 - { "verbose", 0 }, -#define NVERBSW 5 - { "noverbose", 0 }, -#define VERSIONSW 6 - { "version", 0 }, -#define HELPSW 7 - { "help", 0 }, - { NULL, 0 } -}; +#include + +#define BURST_SWITCHES \ + X("inplace", 0, INPLSW) \ + X("noinplace", 0, NINPLSW) \ + X("mime", 0, MIMESW) \ + X("nomime", 0, NMIMESW) \ + X("automime", 0, AUTOMIMESW) \ + X("quiet", 0, QIETSW) \ + X("noquiet", 0, NQIETSW) \ + X("verbose", 0, VERBSW) \ + X("noverbose", 0, NVERBSW) \ + X("version", 0, VERSIONSW) \ + X("help", 0, HELPSW) \ + +#define X(sw, minchars, id) id, +DEFINE_SWITCH_ENUM(BURST); +#undef X + +#define X(sw, minchars, id) { sw, minchars, id }, +DEFINE_SWITCH_ARRAY(BURST, switches); +#undef X struct smsg { off_t s_start; off_t s_stop; }; +/* + * For the MIME parsing routines + */ + +int debugsw = 0; + /* * static prototypes */ -static int find_delim (int, struct smsg *); -static void burst (struct msgs **, int, struct smsg *, int, int, int, char *); -static void cpybrst (FILE *, FILE *, char *, char *, int); +static int find_delim (int, struct smsg *, int *); +static void find_mime_parts (CT, struct smsg *, int *); +static void burst (struct msgs **, int, struct smsg *, int, int, int, + char *, int); +static void cpybrst (FILE *, FILE *, char *, char *, int, int); /* * A macro to check to see if we have reached a message delimiter @@ -56,7 +66,7 @@ static void cpybrst (FILE *, FILE *, char *, char *, int); int main (int argc, char **argv) { - int inplace = 0, quietsw = 0, verbosw = 0; + int inplace = 0, quietsw = 0, verbosw = 0, mimesw = 1; int hi, msgnum, numburst; char *cp, *maildir, *folder = NULL, buf[BUFSIZ]; char **argp, **arguments; @@ -64,13 +74,7 @@ main (int argc, char **argv) struct smsg *smsgs; struct msgs *mp; -#ifdef LOCALE - setlocale(LC_ALL, ""); -#endif - invo_name = r1bindex (argv[0], '/'); - - /* read user profile/context */ - context_read(); + if (nmh_init(argv[0], 1)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; @@ -100,6 +104,16 @@ main (int argc, char **argv) inplace = 0; continue; + case MIMESW: + mimesw = 2; + continue; + case NMIMESW: + mimesw = 0; + continue; + case AUTOMIMESW: + mimesw = 1; + continue; + case QIETSW: quietsw++; continue; @@ -137,7 +151,7 @@ main (int argc, char **argv) adios (maildir, "unable to change directory to"); /* read folder and create message structure */ - if (!(mp = folder_read (folder))) + if (!(mp = folder_read (folder, 1))) adios (NULL, "unable to read folder %s", folder); /* check for empty folder */ @@ -160,11 +174,12 @@ main (int argc, char **argv) /* burst all the SELECTED messages */ for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected (mp, msgnum)) { - if ((numburst = find_delim (msgnum, smsgs)) >= 1) { + if ((numburst = find_delim (msgnum, smsgs, &mimesw)) >= 1) { if (verbosw) printf ("%d message%s exploded from digest %d\n", numburst, numburst > 1 ? "s" : "", msgnum); - burst (&mp, msgnum, smsgs, numburst, inplace, verbosw, maildir); + burst (&mp, msgnum, smsgs, numburst, inplace, verbosw, + maildir, mimesw); } else { if (numburst == 0) { if (!quietsw) @@ -205,18 +220,49 @@ main (int argc, char **argv) /* * Scan the message and find the beginning and * end of all the messages in the digest. + * + * If requested, see if the message is MIME-formatted and contains any + * message/rfc822 parts; if so, burst those parts. */ static int -find_delim (int msgnum, struct smsg *smsgs) +find_delim (int msgnum, struct smsg *smsgs, int *mimesw) { int wasdlm = 0, msgp; off_t pos; char c, *msgnam; char buffer[BUFSIZ]; FILE *in; + CT content; - if ((in = fopen (msgnam = m_name (msgnum), "r")) == NULL) + msgnam = m_name (msgnum); + + /* + * If mimesw is 1 or 2, try to see if it's got proper MIME formatting. + */ + + if (*mimesw > 0) { + content = parse_mime(msgnam); + if (! content && *mimesw == 2) + return 0; + else if (content) { + smsgs[0].s_start = 0; + smsgs[0].s_stop = content->c_begin - 1; + msgp = 1; + find_mime_parts(content, smsgs, &msgp); + free_content(content); + if (msgp == 1 && *mimesw == 2) { + adios (msgnam, "does not have any message/rfc822 parts"); + } else if (msgp > 1) { + *mimesw = 1; + return (msgp - 1); + } + } + } + + *mimesw = 0; + + if ((in = fopen (msgnam, "r")) == NULL) adios (msgnam, "unable to read message"); for (msgp = 0, pos = 0L; msgp <= MAXFOLDER;) { @@ -277,13 +323,51 @@ find_delim (int msgnum, struct smsg *smsgs) } +/* + * Find any MIME content in the message that is a message/rfc822 and add + * it to the list of messages to burst. + */ + +static void +find_mime_parts (CT content, struct smsg *smsgs, int *msgp) +{ + struct multipart *m; + struct part *part; + + /* + * If we have a message/rfc822, then it's easy. + */ + + if (content->c_type == CT_MESSAGE && + content->c_subtype == MESSAGE_RFC822) { + smsgs[*msgp].s_start = content->c_begin; + smsgs[*msgp].s_stop = content->c_end; + (*msgp)++; + return; + } + + /* + * Otherwise, if we do have multiparts, try all of the sub-parts. + */ + + if (content->c_type == CT_MULTIPART) { + m = (struct multipart *) content->c_ctparams; + + for (part = m->mp_parts; part; part = part->mp_next) + find_mime_parts(part->mp_part, smsgs, msgp); + } + + return; +} + + /* * Burst out the messages in the digest into the folder */ static void burst (struct msgs **mpp, int msgnum, struct smsg *smsgs, int numburst, - int inplace, int verbosw, char *maildir) + int inplace, int verbosw, char *maildir, int mimesw) { int i, j, mode; char *msgnam; @@ -373,8 +457,14 @@ burst (struct msgs **mpp, int msgnum, struct smsg *smsgs, int numburst, i = inplace ? msgnum + numburst : mp->hghmsg; for (j = numburst; j >= (inplace ? 0 : 1); i--, j--) { + char *tempfile; + + if ((tempfile = m_mktemp2(NULL, invo_name, NULL, &out)) == NULL) { + adios(NULL, "unable to create temporary file in %s", + get_temp_dir()); + } + strncpy (f2, tempfile, sizeof(f2)); strncpy (f1, m_name (i), sizeof(f1)); - strncpy (f2, m_mktemp(invo_name, NULL, &out), sizeof(f2)); if (verbosw && i != msgnum) printf ("message %d of digest %d becomes message %d\n", j, msgnum, i); @@ -382,7 +472,7 @@ burst (struct msgs **mpp, int msgnum, struct smsg *smsgs, int numburst, chmod (f2, mode); fseeko (in, smsgs[j].s_start, SEEK_SET); cpybrst (in, out, msgnam, f2, - (int) (smsgs[j].s_stop - smsgs[j].s_start)); + (int) (smsgs[j].s_stop - smsgs[j].s_start), mimesw); fclose (out); if (i == msgnum) { @@ -410,6 +500,7 @@ burst (struct msgs **mpp, int msgnum, struct smsg *smsgs, int numburst, #define S1 0 #define S2 1 #define S3 2 +#define S4 3 /* * Copy a mesage which is being burst out of a digest. @@ -417,11 +508,11 @@ burst (struct msgs **mpp, int msgnum, struct smsg *smsgs, int numburst, */ static void -cpybrst (FILE *in, FILE *out, char *ifile, char *ofile, int len) +cpybrst (FILE *in, FILE *out, char *ifile, char *ofile, int len, int mime) { register int c, state; - for (state = S1; (c = fgetc (in)) != EOF && len > 0; len--) { + for (state = mime ? S4 : S1; (c = fgetc (in)) != EOF && len > 0; len--) { if (c == 0) continue; switch (state) { @@ -462,6 +553,10 @@ cpybrst (FILE *in, FILE *out, char *ifile, char *ofile, int len) break; } break; + + case S4: + fputc (c, out); + break; } }