burst: Fixed handling of trailing text; removed -inplace and -quiet.
authormarkus schnalke <meillo@marmaro.de>
Tue, 1 May 2012 08:28:52 +0000 (10:28 +0200)
committermarkus schnalke <meillo@marmaro.de>
Tue, 1 May 2012 08:28:52 +0000 (10:28 +0200)
The trailing text had been part of the last message extracted, now it is
ignored, conforming to the documentation.
Removing the -inplace switch (thus making -noinplace the default) simplified
the code and removed the possibility to lose data.
-quiet supressed warnings (``message is not in digest format''). Warnings
should be displayed. To though suppress them, redirect stderr to /dev/null.
I was unsure if I should make -verbose the default (i.e. remove -verbose
but have -quiet) as it provides similar useful information like inc(1).
I decided against it, because in Unix silence rules. However, I like to have
``burst: -verbose'' in my profile.

man/burst.man1
uip/burst.c

index 5569f75..aba0457 100644 (file)
@@ -10,8 +10,6 @@ burst \- explode digests into messages
 .B burst
 .RI [ +folder ]
 .RI [ msgs ]
 .B burst
 .RI [ +folder ]
 .RI [ msgs ]
-.RB [ \-inplace " | " \-noinplace ]
-.RB [ \-quiet " | " \-noquiet ]
 .RB [ \-verbose " | " \-noverbose ]
 .RB [ \-version ]
 .RB [ \-help ]
 .RB [ \-verbose " | " \-noverbose ]
 .RB [ \-version ]
 .RB [ \-help ]
@@ -21,27 +19,9 @@ burst \- explode digests into messages
 considers the specified messages in the named folder to be
 Internet digests, and explodes them in that folder.
 .PP
 considers the specified messages in the named folder to be
 Internet digests, and explodes them in that folder.
 .PP
-If
-.B \-inplace
-is given, each digest is replaced by the \*(lqtable
-of contents\*(rq for the digest (the original digest is removed).
-.B Burst
-then renumbers all of the messages following the digest in the
-folder to make room for each of the messages contained within the digest.
-These messages are placed immediately after the digest.
-.PP
-If
-.B \-noinplace
-is given, each digest is preserved, no table of contents
-is produced, and the messages contained within the digest are placed at
-the end of the folder.  Other messages are not tampered with in any way.
-.PP
-The
-.B \-quiet
-switch directs
-.B burst
-to be silent about reporting
-messages that are not in digest format.
+The messages contained within the digest are placed at the end of the folder.
+The digest is preserved.
+No other messages are tampered with in any way.
 .PP
 The
 .B \-verbose
 .PP
 The
 .B \-verbose
@@ -53,11 +33,11 @@ actions that it is taking to explode the digest.
 It turns out that
 .B burst
 works equally well on forwarded messages
 It turns out that
 .B burst
 works equally well on forwarded messages
-and blind\-carbon\-copies as on Internet digests, provided that the
-former two were generated by
-.B forw
-or
-.BR send .
+and blind\-carbon\-copies as on Internet digests, provided that they
+use RFC 934 message encapsulation.
+.PP
+To extract messages encapsulated with MIME, use
+.BR mhstore (1).
 
 .SH FILES
 .fc ^ ~
 
 .SH FILES
 .fc ^ ~
@@ -77,7 +57,7 @@ or
 .fi
 
 .SH "SEE ALSO"
 .fi
 
 .SH "SEE ALSO"
-inc(1), pack(1),
+mhstore(1),
 .I "Proposed Standard for Message Encapsulation"
 (RFC\-934)
 
 .I "Proposed Standard for Message Encapsulation"
 (RFC\-934)
 
@@ -85,26 +65,13 @@ inc(1), pack(1),
 .nf
 .RB ` +folder "' defaults to the current folder"
 .RB ` msgs "' defaults to cur"
 .nf
 .RB ` +folder "' defaults to the current folder"
 .RB ` msgs "' defaults to cur"
-.RB ` \-noinplace '
-.RB ` \-noquiet '
 .RB ` \-noverbose '
 .fi
 
 .SH CONTEXT
 .RB ` \-noverbose '
 .fi
 
 .SH CONTEXT
-If a folder is given, it will become the current folder.  If
-.B \-inplace
-is given, then the first message burst becomes the current message.
-This leaves the context ready for a
-.B show
-of the table of contents
-of the digest, and a
-.B next
-to see the first message of the digest. If
-.B \-noinplace
-is given, then the first message extracted from the
-first digest burst becomes the current message.  This leaves the context
-in a similar, but not identical, state to the context achieved when using
-.BR \-inplace .
+If a folder is given, it will become the current folder.
+The first message extracted from the
+first digest burst becomes the current message.
 
 .SH BUGS
 The
 
 .SH BUGS
 The
@@ -128,17 +95,9 @@ finding an encapsulation boundary
 prematurely and splitting a single encapsulated message into two or
 more messages.  These erroneous digestifying programs should be fixed.
 .PP
 prematurely and splitting a single encapsulated message into two or
 more messages.  These erroneous digestifying programs should be fixed.
 .PP
-Furthermore, any text which appears after the last encapsulated message
+Any text which appears after the last encapsulated message
 is not placed in a separate message by
 .BR burst .
 In the case of
 digestified messages, this text is usually an \*(lqEnd of digest\*(rq
 is not placed in a separate message by
 .BR burst .
 In the case of
 digestified messages, this text is usually an \*(lqEnd of digest\*(rq
-string.  As a result of this possibly un\-friendly behavior on the
-part of
-.BR burst ,
-note that when the
-.B \-inplace
-option is used,
-this trailing information is lost.  In practice, this is not a problem
-since correspondents usually place remarks in text prior to the first
-encapsulated message, and this information is not lost.
+string.
index d0d06b6..23b737e 100644 (file)
@@ -9,21 +9,13 @@
 #include <h/mh.h>
 
 static struct swit switches[] = {
 #include <h/mh.h>
 
 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
+#define VERBSW 0
        { "verbose", 0 },
        { "verbose", 0 },
-#define NVERBSW 5
+#define NVERBSW 1
        { "noverbose", 0 },
        { "noverbose", 0 },
-#define VERSIONSW 6
+#define VERSIONSW 2
        { "version", 0 },
        { "version", 0 },
-#define HELPSW 7
+#define HELPSW 3
        { "help", 0 },
        { NULL, 0 }
 };
        { "help", 0 },
        { NULL, 0 }
 };
@@ -39,14 +31,14 @@ struct smsg {
 ** static prototypes
 */
 static int find_delim(int, struct smsg *);
 ** static prototypes
 */
 static int find_delim(int, struct smsg *);
-static void burst(struct msgs **, int, struct smsg *, int, int, int, char *);
+static void burst(struct msgs **, int, struct smsg *, int, int, char *);
 static void cpybrst(FILE *, FILE *, char *, char *, int);
 
 
 int
 main(int argc, char **argv)
 {
 static void cpybrst(FILE *, FILE *, char *, char *, int);
 
 
 int
 main(int argc, char **argv)
 {
-       int inplace = 0, quietsw = 0, verbosw = 0;
+       int verbosw = 0;
        int msgp = 0, hi, msgnum, numburst;
        char *cp, *maildir, *folder = NULL, buf[BUFSIZ];
        char **argp, **arguments, *msgs[MAXARGS];
        int msgp = 0, hi, msgnum, numburst;
        char *cp, *maildir, *folder = NULL, buf[BUFSIZ];
        char **argp, **arguments, *msgs[MAXARGS];
@@ -81,20 +73,6 @@ main(int argc, char **argv)
                                print_version(invo_name);
                                done(1);
 
                                print_version(invo_name);
                                done(1);
 
-                       case INPLSW:
-                               inplace++;
-                               continue;
-                       case NINPLSW:
-                               inplace = 0;
-                               continue;
-
-                       case QIETSW:
-                               quietsw++;
-                               continue;
-                       case NQIETSW:
-                               quietsw = 0;
-                               continue;
-
                        case VERBSW:
                                verbosw++;
                                continue;
                        case VERBSW:
                                verbosw++;
                                continue;
@@ -146,41 +124,32 @@ main(int argc, char **argv)
        /* burst all the SELECTED messages */
        for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
                if (is_selected(mp, msgnum)) {
        /* 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)) > 0) {
                                if (verbosw)
                                        printf("%d message%s exploded from digest %d\n", numburst, numburst > 1 ? "s" : "", msgnum);
                                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, verbosw, maildir);
+                       } else if (numburst == 0) {
+                               admonish(NULL, "message %d not in digest format", msgnum);
                        } else {
                        } else {
-                               if (numburst == 0) {
-                                       if (!quietsw)
-                                               admonish(NULL, "message %d not in digest format", msgnum);
-                               }  /* this pair of braces was missing before 1999-07-15 */
-                               else
-                                       adios(NULL, "burst() botch -- you lose big");
+                               adios(NULL, "burst() botch -- you lose big");
                        }
                }
        }
 
                        }
                }
        }
 
-       free((char *) smsgs);
-       context_replace(curfolder, folder);  /* update current folder */
+       free(smsgs);
+       context_replace(curfolder, folder);
 
        /*
 
        /*
-       ** If -inplace is given, then the first message burst becomes
-       ** the current message (which will now show a table of contents).
-       ** Otherwise, the first message extracted from the first digest
+       ** The first message extracted from the first digest
        ** becomes the current message.
        */
        ** becomes the current message.
        */
-       if (inplace) {
-               if (mp->lowsel != mp->curmsg)
-                       seq_setcur(mp, mp->lowsel);
-       } else {
-               if (hi <= mp->hghmsg)
-                       seq_setcur(mp, hi);
+       if (hi <= mp->hghmsg) {
+               seq_setcur(mp, hi);
        }
 
        }
 
-       seq_save(mp);  /* synchronize message sequences */
-       context_save(); /* save the context file */
-       folder_free(mp); /* free folder/message structure */
+       seq_save(mp);
+       context_save();
+       folder_free(mp);
        done(0);
        return 1;
 }
        done(0);
        return 1;
 }
@@ -190,7 +159,6 @@ main(int argc, char **argv)
 ** Scan the message and find the beginning and
 ** end of all the messages in the digest.
 */
 ** Scan the message and find the beginning and
 ** end of all the messages in the digest.
 */
-
 static int
 find_delim(int msgnum, struct smsg *smsgs)
 {
 static int
 find_delim(int msgnum, struct smsg *smsgs)
 {
@@ -206,11 +174,12 @@ find_delim(int msgnum, struct smsg *smsgs)
        if ((in = fopen(msgnam = m_name(msgnum), "r")) == NULL)
                adios(msgnam, "unable to read message");
 
        if ((in = fopen(msgnam = m_name(msgnum), "r")) == NULL)
                adios(msgnam, "unable to read message");
 
-       for (msgp = 0, pos = 0L; msgp <= MAXFOLDER;) {
+       for (msgp = 0, pos = 0L; msgp <= MAXFOLDER; msgp++) {
                while (fgets(buffer, sizeof(buffer), in) && buffer[0] == '\n')
                        pos += (long) strlen(buffer);
                while (fgets(buffer, sizeof(buffer), in) && buffer[0] == '\n')
                        pos += (long) strlen(buffer);
-               if (feof(in))
+               if (feof(in)) {
                        break;
                        break;
+               }
                fseek(in, pos, SEEK_SET);
                smsgs[msgp].s_start = pos;
 
                fseek(in, pos, SEEK_SET);
                smsgs[msgp].s_start = pos;
 
@@ -228,7 +197,7 @@ find_delim(int msgnum, struct smsg *smsgs)
 
                wasdlm = strncmp(buffer, delim3, ld3) == 0;
                if (smsgs[msgp].s_start != pos)
 
                wasdlm = strncmp(buffer, delim3, ld3) == 0;
                if (smsgs[msgp].s_start != pos)
-                       smsgs[msgp++].s_stop = (c == '\n' && wasdlm) ?
+                       smsgs[msgp].s_stop = (c == '\n' && wasdlm) ?
                                        pos - 1 : pos;
                if (feof(in)) {
                        break;
                                        pos - 1 : pos;
                if (feof(in)) {
                        break;
@@ -237,21 +206,20 @@ find_delim(int msgnum, struct smsg *smsgs)
        }
 
        fclose(in);
        }
 
        fclose(in);
-       return (msgp - 1);  /* toss "End of XXX Digest" */
+       return (msgp > 0) ? msgp-1 : 0;  /* toss "End of XXX Digest" */
 }
 
 
 /*
 ** Burst out the messages in the digest into the folder
 */
 }
 
 
 /*
 ** Burst out the messages in the digest into the folder
 */
-
 static void
 burst(struct msgs **mpp, int msgnum, struct smsg *smsgs, int numburst,
 static void
 burst(struct msgs **mpp, int msgnum, struct smsg *smsgs, int numburst,
-       int inplace, int verbosw, char *maildir)
+       int verbosw, char *maildir)
 {
        int i, j, mode;
        char *msgnam;
 {
        int i, j, mode;
        char *msgnam;
-       char f1[BUFSIZ], f2[BUFSIZ], f3[BUFSIZ];
+       char destfil[BUFSIZ];
        FILE *in, *out;
        struct stat st;
        struct msgs *mp;
        FILE *in, *out;
        struct stat st;
        struct msgs *mp;
@@ -264,130 +232,57 @@ burst(struct msgs **mpp, int msgnum, struct smsg *smsgs, int numburst,
        mp = *mpp;
 
        /*
        mp = *mpp;
 
        /*
-       ** See if we have enough space in the folder
+       ** Ensure we have enough space in the folder
        ** structure for all the new messages.
        */
        ** structure for all the new messages.
        */
-       if ((mp->hghmsg + numburst > mp->hghoff) &&
-               !(mp = folder_realloc(mp, mp->lowoff, mp->hghmsg + numburst)))
+       if ((mp->hghmsg + numburst > mp->hghoff) && !(mp = folder_realloc(mp,
+                       mp->lowoff, mp->hghmsg + numburst)))
                adios(NULL, "unable to allocate folder storage");
        *mpp = mp;
 
                adios(NULL, "unable to allocate folder storage");
        *mpp = mp;
 
-       j = mp->hghmsg;  /* old value */
-       mp->hghmsg += numburst;
-       mp->nummsg += numburst;
-
        /*
        /*
-       ** If this is not the highest SELECTED message, then
-       ** increment mp->hghsel by numburst, since the highest
-       ** SELECTED is about to be slid down by that amount.
-       */
-       if (msgnum < mp->hghsel)
-               mp->hghsel += numburst;
-
-       /*
-       ** If -inplace is given, renumber the messages after the
-       ** source message, to make room for each of the messages
-       ** contained within the digest.
-       **
-       ** This is equivalent to refiling a message from the point
-       ** of view of the external hooks.
-       */
-       if (inplace) {
-               for (i = mp->hghmsg; j > msgnum; i--, j--) {
-                       strncpy(f1, m_name(i), sizeof(f1));
-                       strncpy(f2, m_name(j), sizeof(f2));
-                       if (does_exist(mp, j)) {
-                               if (verbosw)
-                                       printf("message %d becomes message %d\n", j, i);
-
-                               if (rename(f2, f1) == NOTOK)
-                                       admonish(f1, "unable to rename %s to", f2);
-
-                               snprintf(f1, sizeof (f1), "%s/%d", maildir, i);
-                               snprintf(f2, sizeof (f2), "%s/%d", maildir, j);
-                               ext_hook("ref-hook", f1, f2);
-
-                               copy_msg_flags(mp, i, j);
-                               clear_msg_flags(mp, j);
-                               mp->msgflags |= SEQMOD;
-                       }
-               }
-       }
-
-       unset_selected(mp, msgnum);
-
-       /* new hghmsg is hghmsg + numburst
-       **
        ** At this point, there is an array of numburst smsgs, each
        ** element of which contains the starting and stopping offsets
        ** At this point, there is an array of numburst smsgs, each
        ** element of which contains the starting and stopping offsets
-       ** (seeks) of the message in the digest.  The inplace flag is set
-       ** if the original digest is replaced by a message containing
-       ** the table of contents.  smsgs[0] is that table of contents.
-       ** Go through the message numbers in reverse order (high to low).
-       **
-       ** Set f1 to the name of the destination message, f2 to the name
-       ** of a scratch file.  Extract a message from the digest to the
-       ** scratch file.  Move the original message to a backup file if
-       ** the destination message number is the same as the number of
-       ** the original message, which only happens if the inplace flag
-       ** is set.  Then move the scratch file to the destination message.
-       **
-       ** Moving the original message to the backup file is equivalent
-       ** to deleting the message from the point of view of the external
-       ** hooks.  And bursting each message is equivalent to adding a
-       ** new message.
+       ** (seeks) of the message in the digest. Go through the message
+       ** numbers. Ignore smsgs[0], which is the table of contents.
        */
        */
-
-       i = inplace ? msgnum + numburst : mp->hghmsg;
-       for (j = numburst; j >= (inplace ? 0 : 1); i--, j--) {
-               strncpy(f1, m_name(i), sizeof(f1));
-               strncpy(f2, m_mktemp(invo_name, NULL, &out), sizeof(f2));
-
-               if (verbosw && i != msgnum)
+       for (j=1, i=mp->hghmsg+1; j<=numburst; j++, i++) {
+               snprintf(destfil, sizeof destfil, "%s/%d", maildir, i);
+               if (!(out = fopen(destfil, "w"))) {
+                       adios(destfil, "unable to open");
+               }
+               if (verbosw) {
                        printf("message %d of digest %d becomes message %d\n",
                                        j, msgnum, i);
                        printf("message %d of digest %d becomes message %d\n",
                                        j, msgnum, i);
-
-               chmod(f2, mode);
+               }
+               chmod(destfil, mode);
                fseek(in, smsgs[j].s_start, SEEK_SET);
                fseek(in, smsgs[j].s_start, SEEK_SET);
-               cpybrst(in, out, msgnam, f2,
+               cpybrst(in, out, msgnam, destfil,
                                (int) (smsgs[j].s_stop - smsgs[j].s_start));
                fclose(out);
                                (int) (smsgs[j].s_stop - smsgs[j].s_start));
                fclose(out);
-
-               if (i == msgnum) {
-                       strncpy(f3, m_backup(f1), sizeof(f3));
-                       if (rename(f1, f3) == NOTOK)
-                               admonish(f3, "unable to rename %s to", f1);
-
-                       snprintf(f3, sizeof (f3), "%s/%d", maildir, i);
-                       ext_hook("del-hook", f3, NULL);
-               }
-               if (rename(f2, f1) == NOTOK)
-                       admonish(f1, "unable to rename %s to", f2);
-
-               snprintf(f3, sizeof (f3), "%s/%d", maildir, i);
-               ext_hook("add-hook", f3, NULL);
-
+               mp->hghmsg++;
+               mp->nummsg++;
+               /*
+               ** Bursting each message is equivalent to adding a
+               ** new message from the point of view of the external hooks.
+               */
+               ext_hook("add-hook", destfil, NULL);
                copy_msg_flags(mp, i, msgnum);
                mp->msgflags |= SEQMOD;
        }
                copy_msg_flags(mp, i, msgnum);
                mp->msgflags |= SEQMOD;
        }
-
        fclose(in);
 }
 
 
        fclose(in);
 }
 
 
-#define S1  0
-#define S2  1
-#define S3  2
-
 /*
 /*
-** Copy a mesage which is being burst out of a digest.
+** Copy a message which is being burst out of a digest.
 ** It will remove any "dashstuffing" in the message.
 */
 ** It will remove any "dashstuffing" in the message.
 */
-
 static void
 cpybrst(FILE *in, FILE *out, char *ifile, char *ofile, int len)
 {
 static void
 cpybrst(FILE *in, FILE *out, char *ifile, char *ofile, int len)
 {
-       register int c, state;
+       int c;
+       enum { S1, S2, S3 } state;
 
        for (state = S1; (c = fgetc(in)) != EOF && len > 0; len--) {
                if (c == 0)
 
        for (state = S1; (c = fgetc(in)) != EOF && len > 0; len--) {
                if (c == 0)