/*
* sortm.c -- sort messages in a folder by date/time
*
- * $Id$
+ * This code is Copyright (c) 2002, by the authors of nmh. See the
+ * COPYRIGHT file in the root directory of the nmh distribution for
+ * complete copyright information.
*/
#include <h/mh.h>
-#include <zotnet/tws/tws.h>
-
-/*
- * We allocate space for messages (msgs array)
- * this number of elements at a time.
- */
-#define MAXMSGS 256
-
+#include <h/tws.h>
+#include <h/utils.h>
static struct swit switches[] = {
#define DATESW 0
int nmsgs;
char *subjsort = (char *) 0; /* sort on subject if != 0 */
-unsigned long datelimit = 0;
+time_t datelimit = 0;
int submajor = 0; /* if true, sort on subject-major */
int verbose;
int
main (int argc, char **argv)
{
- int nummsgs, maxmsgs, i, msgnum;
- char *cp, *maildir, *datesw = NULL;
+ int i, msgnum;
+ unsigned char *cp;
+ char *maildir, *datesw = NULL;
char *folder = NULL, buf[BUFSIZ], **argp;
- char **arguments, **msgs;
+ char **arguments;
+ struct msgs_array msgs = { 0, 0, NULL };
struct msgs *mp;
struct smsg **dlist;
argp = arguments;
/*
- * Allocate the initial space to record message
- * names and ranges.
- */
- nummsgs = 0;
- maxmsgs = MAXMSGS;
- if (!(msgs = (char **) malloc ((size_t) (maxmsgs * sizeof(*msgs)))))
- adios (NULL, "unable to allocate storage");
-
- /*
* Parse arguments
*/
while ((cp = *argp++)) {
if (folder)
adios (NULL, "only one folder at a time!");
else
- folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
- } else {
- /*
- * Check if we need to allocate more space
- * for message names/ranges.
- */
- if (nummsgs >= maxmsgs) {
- maxmsgs += MAXMSGS;
- if (!(msgs = (char **) realloc (msgs,
- (size_t) (maxmsgs * sizeof(*msgs)))))
- adios (NULL, "unable to reallocate msgs storage");
- }
- msgs[nummsgs++] = cp;
- }
+ folder = pluspath (cp);
+ } else
+ app_msgarg(&msgs, cp);
}
if (!context_find ("path"))
free (path ("./", TFOLDER));
- if (!nummsgs)
- msgs[nummsgs++] = "all";
+ if (!msgs.size)
+ app_msgarg(&msgs, "all");
if (!datesw)
datesw = "date";
if (!folder)
adios (NULL, "no messages in %s", folder);
/* parse all the message ranges/sequences and set SELECTED */
- for (msgnum = 0; msgnum < nummsgs; msgnum++)
- if (!m_convert (mp, msgs[msgnum]))
+ for (msgnum = 0; msgnum < msgs.size; msgnum++)
+ if (!m_convert (mp, msgs.msgs[msgnum]))
done (1);
seq_setprev (mp); /* set the previous sequence */
/*
* sort a list of pointers to our "messages to be sorted".
*/
- dlist = (struct smsg **) malloc ((nmsgs+1) * sizeof(*dlist));
- if (! dlist)
- adios (NULL, "couldn't allocate sort memory");
+ dlist = (struct smsg **) mh_xmalloc ((nmsgs+1) * sizeof(*dlist));
for (i = 0; i < nmsgs; i++)
dlist[i] = &smsgs[i];
dlist[nmsgs] = 0;
if (verbose) { /* announce what we're doing */
if (subjsort)
- printf ("sorting by %s-major %s-minor\n",
+ printf ("sorting by %s-major %s-minor\n",
submajor ? subjsort : datesw,
submajor ? datesw : subjsort);
else
}
/* first sort by date, or by subject-major, date-minor */
- qsort ((char *) dlist, nmsgs, sizeof(*dlist),
+ qsort ((char *) dlist, nmsgs, sizeof(*dlist),
(qsort_comp) (submajor && subjsort ? txtsort : dsort));
/*
struct smsg **slist, **flist;
register struct smsg ***il, **fp, **dp;
- slist = (struct smsg **) malloc ((nmsgs+1) * sizeof(*slist));
- if (! slist)
- adios (NULL, "couldn't allocate sort memory");
+ slist = (struct smsg **) mh_xmalloc ((nmsgs+1) * sizeof(*slist));
memcpy((char *)slist, (char *)dlist, (nmsgs+1)*sizeof(*slist));
qsort((char *)slist, nmsgs, sizeof(*slist), (qsort_comp) subsort);
* make up the final list, chronological but with
* all the same subjects grouped together.
*/
- flist = (struct smsg **) malloc ((nmsgs+1) * sizeof(*flist));
- if (! flist)
- adios (NULL, "couldn't allocate msg list");
+ flist = (struct smsg **) mh_xmalloc ((nmsgs+1) * sizeof(*flist));
fp = flist;
for (dp = dlist; *dp;) {
register struct smsg **s = il[(*dp++)->s_msg];
*/
while (*s && (*s)->s_subj[0] &&
strcmp((*s)->s_subj, s[-1]->s_subj) == 0 &&
- (datelimit == 0 ||
+ (datelimit == 0 ||
(*s)->s_clock - s[-1]->s_clock <= datelimit)) {
il[(*s)->s_msg] = 0;
*fp++ = *s++;
free (dlist);
dlist = flist;
}
+
+ /*
+ * At this point, dlist is a sorted array of pointers to smsg structures,
+ * each of which contains a message number.
+ */
+
rename_msgs (mp, dlist);
context_replace (pfolder, folder); /* update current folder */
seq_save (mp); /* synchronize message sequences */
context_save (); /* save the context file */
folder_free (mp); /* free folder/message structure */
- return done (0);
+ done (0);
+ return 1;
}
-static int
+static int
read_hdrs (struct msgs *mp, char *datesw)
{
int msgnum;
case FLDEOF:
case FLDPLUS:
compnum++;
- if (!strcasecmp (nam, datesw)) {
+ if (!mh_strcasecmp (nam, datesw)) {
datecomp = add (buf, datecomp);
while (state == FLDPLUS) {
state = m_getfld (state, nam, buf, sizeof(buf), in);
}
if (!subjsort || subjcomp)
break;
- } else if (subjsort && !strcasecmp (nam, subjsort)) {
+ } else if (subjsort && !mh_strcasecmp (nam, subjsort)) {
subjcomp = add (buf, subjcomp);
while (state == FLDPLUS) {
state = m_getfld (state, nam, buf, sizeof(buf), in);
/*
* try to make the subject "canonical": delete
* leading "re:", everything but letters & smash
- * letters to lower case.
+ * letters to lower case.
*/
- register char *cp, *cp2, c;
+ register char *cp, *cp2;
+ register unsigned char c;
cp = subjcomp;
cp2 = subjcomp;
- if (strcmp (subjsort, "subject") == 0)
+ if (strcmp (subjsort, "subject") == 0) {
while ((c = *cp)) {
if (! isspace(c)) {
if(uprf(cp, "re:"))
cp += 2;
- else {
- if (isalnum(c))
- *cp2++ = isupper(c) ? tolower(c) : c;
+ else
break;
- }
}
cp++;
}
+ }
+
while ((c = *cp++)) {
if (isalnum(c))
*cp2++ = isupper(c) ? tolower(c) : c;
-
}
+
*cp2 = '\0';
}
else
/*
* sort on dates.
*/
-static int
+static int
dsort (struct smsg **a, struct smsg **b)
{
if ((*a)->s_clock < (*b)->s_clock)
/*
* sort on subjects.
*/
-static int
+static int
subsort (struct smsg **a, struct smsg **b)
{
register int i;
return (dsort (a, b));
}
-static int
+static int
txtsort (struct smsg **a, struct smsg **b)
{
register int i;
{
int nxt, old, new;
char *newname, oldname[BUFSIZ];
+ char newbuf[MAXPATHLEN + 1];
for (;;) {
nxt = mlist[msg] - smsgs; /* mlist[msg] is a ptr into smsgs */
if (verbose)
printf ("message %d becomes message %d\n", old, new);
+ (void)snprintf(oldname, sizeof (oldname), "%s/%d", mp->foldpath, old);
+ (void)snprintf(newbuf, sizeof (newbuf), "%s/%d", mp->foldpath, new);
+ ext_hook("ref-hook", oldname, newbuf);
+
if (rename (oldname, newname) == NOTOK)
adios (newname, "unable to rename %s to", oldname);
if (mp->curmsg == old)
seq_setcur (mp, new);
- if (nxt == endmsg)
+ if (nxt == endmsg)
break;
msg = nxt;
int i, j, old, new;
seqset_t tmpset;
char f1[BUFSIZ], tmpfil[BUFSIZ];
+ char newbuf[MAXPATHLEN + 1];
struct smsg *sp;
strncpy (tmpfil, m_name (mp->hghmsg + 1), sizeof(tmpfil));
for (i = 0; i < nmsgs; i++) {
- if (! (sp = mlist[i]))
+ if (! (sp = mlist[i]))
continue; /* did this one */
j = sp - smsgs;
if (verbose)
printf ("renaming message chain from %d to %d\n", old, new);
+ /*
+ * Run the external hook to refile the old message as the
+ * temporary message number that is off of the end of the
+ * messages in the folder.
+ */
+
+ (void)snprintf(f1, sizeof (f1), "%s/%d", mp->foldpath, old);
+ (void)snprintf(newbuf, sizeof (newbuf), "%s/%d", mp->foldpath, mp->hghmsg + 1);
+ ext_hook("ref-hook", f1, newbuf);
+
if (rename (f1, tmpfil) == NOTOK)
adios (tmpfil, "unable to rename %s to ", f1);
+
get_msg_flags (mp, &tmpset, old);
rename_chain (mp, mlist, j, i);
+
+ /*
+ * Run the external hook to refile the temorary message number
+ * to the real place.
+ */
+
+ (void)snprintf(f1, sizeof (f1), "%s/%d", mp->foldpath, new);
+ ext_hook("ref-hook", newbuf, f1);
+
if (rename (tmpfil, m_name(new)) == NOTOK)
adios (m_name(new), "unable to rename %s to", tmpfil);