Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / uip / RCS / sortm.c,v
1 head    1.20;
2 access;
3 symbols;
4 locks; strict;
5 comment @ * @;
6
7
8 1.20
9 date    95.12.06.23.46.23;      author jromine; state Exp;
10 branches;
11 next    1.19;
12
13 1.19
14 date    92.12.15.00.20.22;      author jromine; state Exp;
15 branches;
16 next    1.18;
17
18 1.18
19 date    92.12.03.16.50.27;      author jromine; state Exp;
20 branches;
21 next    1.17;
22
23 1.17
24 date    92.12.03.16.28.56;      author jromine; state Exp;
25 branches;
26 next    1.16;
27
28 1.16
29 date    92.11.04.01.03.50;      author jromine; state Exp;
30 branches;
31 next    1.15;
32
33 1.15
34 date    92.01.31.22.28.01;      author jromine; state Exp;
35 branches;
36 next    1.14;
37
38 1.14
39 date    90.12.19.10.02.16;      author mh;      state Exp;
40 branches;
41 next    1.13;
42
43 1.13
44 date    90.12.19.09.42.20;      author mh;      state Exp;
45 branches;
46 next    1.12;
47
48 1.12
49 date    90.04.05.15.02.27;      author sources; state Exp;
50 branches;
51 next    1.11;
52
53 1.11
54 date    90.03.23.13.55.40;      author sources; state Exp;
55 branches;
56 next    1.10;
57
58 1.10
59 date    90.03.23.13.44.45;      author sources; state Exp;
60 branches;
61 next    1.9;
62
63 1.9
64 date    90.03.22.17.11.16;      author sources; state Exp;
65 branches;
66 next    1.8;
67
68 1.8
69 date    90.03.22.17.06.05;      author sources; state Exp;
70 branches;
71 next    1.7;
72
73 1.7
74 date    90.03.22.15.33.44;      author sources; state Exp;
75 branches;
76 next    1.6;
77
78 1.6
79 date    90.03.22.15.11.11;      author sources; state Exp;
80 branches;
81 next    1.5;
82
83 1.5
84 date    90.03.22.15.10.28;      author sources; state Exp;
85 branches;
86 next    1.4;
87
88 1.4
89 date    90.03.22.15.03.10;      author sources; state Exp;
90 branches;
91 next    1.3;
92
93 1.3
94 date    90.03.21.23.23.43;      author sources; state Exp;
95 branches;
96 next    1.2;
97
98 1.2
99 date    90.02.06.13.32.04;      author sources; state Exp;
100 branches;
101 next    1.1;
102
103 1.1
104 date    90.02.06.13.31.45;      author sources; state Exp;
105 branches;
106 next    ;
107
108
109 desc
110 @@
111
112
113 1.20
114 log
115 @fix: use int for msgstats
116 @
117 text
118 @/* sortm.c - sort messages in a folder by date/time */
119 /* 21Apr90 do subject sorts too - from V. Jacobson */
120 #ifndef lint
121 static char ident[] = "@@(#)$Id: sortm.c,v 1.19 1992/12/15 00:20:22 jromine Exp jromine $";
122 #endif  /* lint */
123
124 #include "../h/mh.h"
125 #include "../zotnet/tws.h"
126 #define getws _getws
127 #include <stdio.h>
128 #undef getws
129 #include <sys/types.h>
130 #include <sys/stat.h>
131 #include <ctype.h>
132 #ifdef LOCALE
133 #include        <locale.h>
134 #endif
135 #if     defined(SYS5) && defined(AUX)
136 #define u_short ushort
137 #define u_long  ulong
138 #endif
139
140
141 static struct swit switches[] = {
142 #define DATESW  0
143      "datefield field", 0,
144
145 #define TEXTSW 1
146      "textfield field", 0,
147 #define NSUBJSW 2
148      "notextfield", 0,
149
150 #define SUBJSW 3
151      "subject", -3,             /* backward-compatibility */
152 #define LIMSW 4
153      "limit days", 0,
154 #define NLIMSW 5
155      "nolimit", 0,
156
157 #define VERBSW  6
158      "verbose", 0,
159 #define NVERBSW 7
160      "noverbose", 0,
161
162 #define HELPSW  8
163      "help", 4,
164
165      NULL, 0
166 };
167
168 struct smsg {
169     int s_msg;
170     unsigned long s_clock;
171     char *s_subj;
172 };
173
174 static struct smsg *smsgs;
175 int     nmsgs;
176
177 char   *subjsort = (char *)0;           /* sort on subject if != 0 */
178 u_long  datelimit = 0;
179 int     submajor = 0;           /* if true, sort on subject-major */
180 int     verbose;
181
182 #ifdef __STDC__
183 static int getws (char *datesw, int msg, struct smsg *smsg);
184 #else
185 static int getws ();
186 #endif
187
188 static  int dsort(), read_hdrs (), subsort(), txtsort();
189 static void rename_chain(), rename_msgs();
190
191 /* \f */
192
193 main (argc, argv)
194 int argc;
195 char **argv;
196 {
197     int     msgp = 0,
198             i,
199             msgnum;
200     char   *cp,
201            *maildir,
202            *datesw = NULL,
203            *folder = NULL,
204             buf[100],
205           **ap,
206           **argp,
207            *arguments[MAXARGS],
208            *msgs[MAXARGS];
209     struct msgs *mp;
210     struct smsg **dlist;
211
212 #ifdef LOCALE
213         setlocale(LC_ALL, "");
214 #endif
215     invo_name = r1bindex (argv[0], '/');
216     if ((cp = m_find (invo_name)) != NULL) {
217         ap = brkstring (cp = getcpy (cp), " ", "\n");
218         ap = copyip (ap, arguments);
219     }
220     else
221         ap = arguments;
222     (void) copyip (argv + 1, ap);
223     argp = arguments;
224
225     while (cp = *argp++) {
226         if (*cp == '-')
227             switch (smatch (++cp, switches)) {
228             case AMBIGSW:
229                 ambigsw (cp, switches);
230                 done (1);
231             case UNKWNSW:
232                 adios (NULLCP, "-%s unknown", cp);
233             case HELPSW:
234                 (void) sprintf(buf, "%s [+folder] [msgs] [switches]",
235                           invo_name);
236                 help (buf, switches);
237                 done (1);
238
239             case DATESW:
240                 if (datesw)
241                     adios (NULLCP, "only one date field at a time");
242                 if (!(datesw = *argp++) || *datesw == '-')
243                     adios (NULLCP, "missing argument to %s", argp[-2]);
244                 continue;
245
246             case TEXTSW:
247                 if (subjsort)
248                     adios (NULLCP, "only one text field at a time");
249                 if (!(subjsort = *argp++) || *subjsort == '-')
250                     adios (NULLCP, "missing argument to %s", argp[-2]);
251                 continue;
252
253             case SUBJSW:
254                 subjsort = "subject";
255                 continue;
256             case NSUBJSW:
257                 subjsort = (char *)0;
258                 continue;
259
260             case LIMSW:
261                 if (!(cp = *argp++) || *cp == '-')
262                         adios (NULLCP, "missing argument to %s", argp[-2]);
263                 while (*cp == '0')
264                     cp++;               /* skip any leading zeros */
265                 if (!*cp) {             /* hit end of string */
266                     submajor++;         /* sort subject-major */
267                     continue;
268                 }
269                 if (!isdigit(*cp) || !(datelimit = atoi(cp)))
270                     adios (NULLCP, "impossible limit %s", cp);
271                 datelimit *= 60*60*24;
272                 continue;
273             case NLIMSW:
274                 submajor = 0;   /* use date-major, but */
275                 datelimit = 0;  /* use no limit */
276                 continue;
277
278             case VERBSW:
279                 verbose++;
280                 continue;
281             case NVERBSW:
282                 verbose = 0;
283                 continue;
284             }
285         if (*cp == '+' || *cp == '@@') {
286             if (folder)
287                 adios (NULLCP, "only one folder at a time!");
288             else
289                 folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
290         }
291         else
292             msgs[msgp++] = cp;
293     }
294
295     if (!m_find ("path"))
296         free (path ("./", TFOLDER));
297     if (!msgp)
298         msgs[msgp++] = "all";
299     if (!datesw)
300         datesw = "date";
301     if (!folder)
302         folder = m_getfolder ();
303     maildir = m_maildir (folder);
304
305     if (chdir (maildir) == NOTOK)
306         adios (maildir, "unable to change directory to");
307     if (!(mp = m_gmsg (folder)))
308         adios (NULLCP, "unable to read folder %s", folder);
309     if (mp->hghmsg == 0)
310         adios (NULLCP, "no messages in %s", folder);
311
312     for (msgnum = 0; msgnum < msgp; msgnum++)
313         if (!m_convert (mp, msgs[msgnum]))
314             done (1);
315     m_setseq (mp);
316
317     if ((nmsgs = read_hdrs (mp, datesw)) <= 0)
318         adios (NULLCP, "no messages to sort");
319
320     /*
321      * sort a list of pointers to our "messages to be sorted".
322      */
323     dlist = (struct smsg **) malloc ((nmsgs+1) * sizeof(*dlist));
324     if (! dlist)
325         adios (NULLCP, "couldn't allocate sort memory");
326     for (i = 0; i < nmsgs; i++)
327         dlist[i] = &smsgs[i];
328     dlist[nmsgs] = 0;
329
330     if (verbose)        /* announce what we're doing */
331         if (subjsort)
332             printf ("sorting by %s-major %s-minor\n", 
333                 submajor ? subjsort : datesw,
334                 submajor ? datesw : subjsort);
335         else
336             printf ("sorting by datefield %s\n", datesw);
337
338     /* first sort by date, or by subject-major, date-minor */
339     qsort ((char *) dlist, nmsgs, sizeof(*dlist), 
340             submajor && subjsort ? txtsort : dsort);
341
342     /*
343      * if we're sorting on subject, we need another list
344      * in subject order, then a merge pass to collate the
345      * two sorts.
346      */
347     if (!submajor && subjsort) {        /* already date sorted */
348         struct smsg             **slist,
349                                 **flist;
350         register struct smsg   ***il,
351                                 **fp,
352                                 **dp;
353
354         slist = (struct smsg **) malloc ((nmsgs+1) * sizeof(*slist));
355         if (! slist)
356             adios (NULLCP, "couldn't allocate sort memory");
357         bcopy ((char *)dlist, (char *)slist, (nmsgs+1)*sizeof(*slist));
358         qsort ((char *)slist, nmsgs, sizeof(*slist), subsort);
359
360         /*
361          * make an inversion list so we can quickly find
362          * the collection of messages with the same subj
363          * given a message number.
364          */
365         il = (struct smsg ***) calloc (mp->hghsel+1, sizeof(*il));
366         if (! il)
367             adios (NULLCP, "couldn't allocate msg list");
368         for (i = 0; i < nmsgs; i++)
369             il[slist[i]->s_msg] = &slist[i];
370         /*
371          * make up the final list, chronological but with
372          * all the same subjects grouped together.
373          */
374         flist = (struct smsg **) malloc ((nmsgs+1) * sizeof(*flist));
375         if (! flist)
376             adios (NULLCP, "couldn't allocate msg list");
377         fp = flist;
378         for (dp = dlist; *dp;) {
379             register struct smsg **s = il[(*dp++)->s_msg];
380
381             /* see if we already did this guy */
382             if (! s)
383                 continue;
384
385             *fp++ = *s++;
386             /*
387              * take the next message(s) if there is one,
388              * its subject isn't null and its subject
389              * is the same as this one and it's not too
390              * far away in time.
391              */
392             while (*s && (*s)->s_subj[0] &&
393                    strcmp((*s)->s_subj, s[-1]->s_subj) == 0 &&
394                    (datelimit == 0 || 
395                    (*s)->s_clock - s[-1]->s_clock <= datelimit)) {
396                 il[(*s)->s_msg] = 0;
397                 *fp++ = *s++;
398             }
399         }
400         *fp = 0;
401         (void) free (slist);
402         (void) free (dlist);
403         dlist = flist;
404     }
405     rename_msgs (mp, dlist);
406
407     m_replace (pfolder, folder);
408     m_sync (mp);
409     m_update ();
410     done (0);
411 }
412
413 static int 
414 read_hdrs (mp, datesw)
415 register struct msgs    *mp;
416 register char           *datesw;
417 {
418     int         msgnum;
419     struct tws  tb;
420     register struct smsg *s;
421
422     twscopy (&tb, dtwstime ());
423
424     smsgs = (struct smsg *)
425         calloc ((unsigned) (mp->hghsel - mp->lowsel + 2),
426             sizeof *smsgs);
427     if (smsgs == NULL)
428         adios (NULLCP, "unable to allocate sort storage");
429
430     s = smsgs;
431     for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
432         if (mp->msgstats[msgnum] & SELECTED) {
433             if (getws (datesw, msgnum, s)) {
434                 s->s_msg = msgnum;
435                 s++;
436             }
437         }
438     }
439     s->s_msg = 0;
440     return(s - smsgs);
441 }
442
443 static
444 getws (datesw, msg, smsg)
445 register char *datesw;
446 int msg;
447 register struct smsg *smsg;
448 {
449     register int state;
450     int      compnum;
451     char    *msgnam,
452              buf[BUFSIZ],
453              nam[NAMESZ];
454     register struct tws *tw;
455     register char *datecomp = NULLCP,
456                   *subjcomp = NULLCP;
457     register FILE *in;
458
459     if ((in = fopen (msgnam = m_name (msg), "r")) == NULL) {
460         admonish (msgnam, "unable to read message");
461         return (0);
462     }
463     for (compnum = 1, state = FLD;;) {
464         switch (state = m_getfld (state, nam, buf, sizeof buf, in)) {
465         case FLD:
466         case FLDEOF:
467         case FLDPLUS:
468             compnum++;
469             if (uleq (nam, datesw)) {
470                 datecomp = add (buf, datecomp);
471                 while (state == FLDPLUS) {
472                     state = m_getfld (state, nam, buf, sizeof buf, in);
473                     datecomp = add (buf, datecomp);
474                 }
475                 if (!subjsort || subjcomp)
476                     break;
477             }
478             else if (subjsort && uleq (nam, subjsort)) {
479                 subjcomp = add (buf, subjcomp);
480                 while (state == FLDPLUS) {
481                     state = m_getfld (state, nam, buf, sizeof buf, in);
482                     subjcomp = add (buf, subjcomp);
483                 }
484                 if (datecomp)
485                     break;
486             }
487             else {
488                 /* just flush this guy */
489                 while (state == FLDPLUS)
490                     state = m_getfld (state, nam, buf, sizeof buf, in);
491             }
492             continue;
493
494         case BODY:
495         case BODYEOF:
496         case FILEEOF:
497             break;
498
499         case LENERR:
500         case FMTERR:
501             if (state == LENERR || state == FMTERR)
502                 admonish (NULLCP, "format error in message %d (header #%d)",
503                       msg, compnum);
504             if (datecomp)
505                 free (datecomp);
506             if (subjcomp)
507                 free (subjcomp);
508             (void) fclose (in);
509             return (0);
510
511         default:
512             adios (NULLCP, "internal error -- you lose");
513         }
514         break;
515     }
516
517     if (!datecomp || (tw = dparsetime (datecomp)) == NULL) {
518         struct stat st;
519
520         admonish (NULLCP, "can't parse %s field in message %d",
521               datesw, msg);
522
523         /* use the modify time of the file as its date */
524         (void) fstat (fileno (in), &st);
525         smsg->s_clock = st.st_mtime;
526     }
527     else
528         smsg->s_clock = twclock (tw);
529
530     if (subjsort) {
531         if (subjcomp) {
532             /*
533              * try to make the subject "canonical": delete
534              * leading "re:", everything but letters & smash
535              * letters to lower case. 
536              */
537             register char  *cp,
538                            *cp2,
539                             c;
540
541             cp = subjcomp;
542             cp2 = subjcomp;
543             if (strcmp (subjsort, "subject") == 0)
544                 while (c = *cp) {
545                     if (! isspace(c)) {
546                         if(uprf(cp, "re:"))
547                             cp += 2;
548                         else {
549                             if (isalnum(c))
550                                 *cp2++ = isupper(c) ? tolower(c) : c;
551                             break;
552                         }
553                     }
554                     cp++;
555                 }
556             while (c = *cp++) {
557                 if (isalnum(c))
558                     *cp2++ = isupper(c) ? tolower(c) : c;
559
560             }
561             *cp2 = '\0';
562         }
563         else
564             subjcomp = "";
565
566         smsg->s_subj = subjcomp;
567     }
568     (void) fclose (in);
569     if (datecomp)
570         free (datecomp);
571
572     return (1);
573 }
574
575 /*
576  * sort on dates.
577  */
578 static int 
579 dsort (a, b)
580 register struct smsg **a,
581                      **b;
582 {
583     if ((*a)->s_clock < (*b)->s_clock)
584         return (-1);
585     else if ((*a)->s_clock > (*b)->s_clock)
586         return (1);
587     else if ((*a)->s_msg < (*b)->s_msg)
588         return (-1);
589     else
590         return (1);
591 }
592
593 /*
594  * sort on subjects.
595  */
596 static int 
597 subsort (a, b)
598 register struct smsg **a,
599                      **b;
600 {
601     register int i;
602
603     if (i = strcmp ((*a)->s_subj, (*b)->s_subj))
604         return (i);
605
606     return (dsort (a, b));
607 }
608
609 static int 
610 txtsort (a, b)
611 register struct smsg **a,
612                      **b;
613 {
614     register int i;
615
616     if (i = strcmp ((*a)->s_subj, (*b)->s_subj))
617         return (i);
618     else if ((*a)->s_msg < (*b)->s_msg)
619         return (-1);
620     else
621         return (1);
622 }
623
624 static void   rename_chain (mp, mlist, msg, endmsg)
625 register struct msgs *mp;
626 struct smsg         **mlist;
627 int       msg,
628           endmsg;
629 {
630     int   nxt,
631           old,
632           new;
633     char *newname,
634           oldname[BUFSIZ];
635
636     for (;;) {
637         nxt = mlist[msg] - smsgs;       /* mlist[msg] is a ptr into smsgs */
638         mlist[msg] = (struct smsg *)0;
639         old = smsgs[nxt].s_msg;
640         new = smsgs[msg].s_msg;
641         (void) strcpy (oldname, m_name (old));
642         newname = m_name (new);
643         if (verbose)
644             printf ("message %d becomes message %d\n", old, new);
645
646         if (rename (oldname, newname) == NOTOK)
647             adios (newname, "unable to rename %s to", oldname);
648
649         mp->msgstats[new] = mp->msgstats[old];
650         if (mp->curmsg == old)
651             m_setcur (mp, new);
652
653         if (nxt == endmsg) 
654             break;
655
656         msg = nxt;
657     }
658 /*      if (nxt != endmsg); */
659 /*      rename_chain (mp, mlist, nxt, endmsg); */
660 }
661
662 static void
663 rename_msgs (mp, mlist)
664 register struct msgs *mp;
665 register struct smsg **mlist;
666 {
667     register int i,
668                  j,
669                  old,
670                  new;
671     int          stats;
672     char         f1[BUFSIZ],
673                  tmpfil[BUFSIZ];
674     register struct smsg *sp;
675
676     (void) strcpy (tmpfil, m_name (mp->hghmsg + 1));
677
678     for (i = 0; i < nmsgs; i++) {
679         if (! (sp = mlist[i])) 
680             continue;   /* did this one */
681
682         j = sp - smsgs;
683         if (j == i)
684             continue;   /* this one doesn't move */
685
686         /*
687          * the guy that was msg j is about to become msg i.
688          * rename 'j' to make a hole, then recursively rename
689          * guys to fill up the hole.
690          */
691         old = smsgs[j].s_msg;
692         new = smsgs[i].s_msg;
693         (void) strcpy (f1, m_name (old));
694
695         if (verbose)
696             printf ("renaming message chain from %d to %d\n", old, new);
697
698         if (rename (f1, tmpfil) == NOTOK)
699             adios (tmpfil, "unable to rename %s to ", f1);
700         stats = mp->msgstats[old];
701
702         rename_chain (mp, mlist, j, i);
703         if (rename (tmpfil, m_name(new)) == NOTOK)
704             adios (m_name(new), "unable to rename %s to", tmpfil);
705
706         mp->msgstats[new] = stats;
707         mp->msgflags |= SEQMOD;
708     }
709 }
710 @
711
712
713 1.19
714 log
715 @endif sugar
716 @
717 text
718 @d4 1
719 a4 1
720 static char ident[] = "@@(#)$Id: sortm.c,v 1.18 1992/12/03 16:50:27 jromine Exp jromine $";
721 d554 1
722 a554 1
723     short        stats;
724 @
725
726
727 1.18
728 log
729 @put u_short ifdef under #if AUX
730 @
731 text
732 @d4 2
733 a5 2
734 static char ident[] = "@@(#)$Id: sortm.c,v 1.17 1992/12/03 16:28:56 jromine Exp jromine $";
735 #endif  lint
736 @
737
738
739 1.17
740 log
741 @u_short AUX changes from Jim Guyton
742 @
743 text
744 @d4 1
745 a4 1
746 static char ident[] = "@@(#)$Id: sortm.c,v 1.16 1992/11/04 01:03:50 jromine Exp jromine $";
747 d18 1
748 a18 1
749 #ifdef  SYS5
750 @
751
752
753 1.16
754 log
755 @LOCALE
756 @
757 text
758 @d4 1
759 a4 1
760 static char ident[] = "@@(#)$Id: sortm.c,v 1.15 1992/01/31 22:28:01 jromine Exp jromine $";
761 d18 5
762 @
763
764
765 1.15
766 log
767 @kerberos
768 @
769 text
770 @d4 1
771 a4 1
772 static char ident[] = "@@(#)$Id: sortm.c,v 1.14 1990/12/19 10:02:16 mh Exp jromine $";
773 d15 3
774 d90 3
775 d422 1
776 a422 1
777                 while (c = *cp++) {
778 d424 1
779 a424 3
780                         if ((c == 'r' || c == 'R') &&
781                             (cp[0] == 'e' || cp[0] == 'E') &&
782                             cp[1] == ':')
783 d432 1
784 @
785
786
787 1.14
788 log
789 @convert to tail recursion
790 remove unused variable
791 jlr
792 @
793 text
794 @d4 1
795 a4 1
796 static char ident[] = "@@(#)$Id: sortm.c,v 1.13 90/12/19 09:42:20 mh Exp Locker: mh $";
797 d9 1
798 d11 1
799 d40 1
800 a40 1
801      NULL, NULL
802 d57 6
803 a62 1
804 static  getws();
805 @
806
807
808 1.13
809 log
810 @sortm could lose a message if interrupted.
811 jlr
812 @
813 text
814 @d4 1
815 a4 1
816 static char ident[] = "@@(#)$Id: sortm.c,v 1.12 90/04/05 15:02:27 sources Exp Locker: mh $";
817 d502 9
818 a510 8
819     nxt = mlist[msg] - smsgs;
820     mlist[msg] = 0;
821     old = smsgs[nxt].s_msg;
822     new = smsgs[msg].s_msg;
823     (void) strcpy (oldname, m_name (old));
824     newname = m_name (new);
825     if (verbose)
826         printf ("message %d becomes message %d\n", old, new);
827 d512 2
828 a513 2
829     if (rename (oldname, newname) == NOTOK)
830         adios (newname, "unable to rename %s to", oldname);
831 d515 3
832 a517 3
833     mp->msgstats[new] = mp->msgstats[old];
834     if (mp->curmsg == old)
835         m_setcur (mp, new);
836 d519 7
837 a525 2
838     if (nxt != endmsg)
839         rename_chain (mp, mlist, nxt, endmsg);
840 a538 1
841                  f2[BUFSIZ],
842 @
843
844
845 1.12
846 log
847 @add ID
848 @
849 text
850 @d4 1
851 a4 1
852 static char ident[] = "@@(#)$Id:$";
853 d537 1
854 a537 1
855     (void) strcpy (tmpfil, m_scratch ("", invo_name));
856 @
857
858
859 1.11
860 log
861 @allow numeric strings
862 @
863 text
864 @d3 3
865 @
866
867
868 1.10
869 log
870 @use arbitrary textfield not just "subject"
871 @
872 text
873 @d413 2
874 a414 3
875                             if (isalpha(c))
876                                 *cp2++ = islower(c)?
877                                     c : tolower(c);
878 d420 2
879 a421 2
880                 if (isalpha(c))
881                     *cp2++ = islower(c)? c : tolower(c);
882 @
883
884
885 1.9
886 log
887 @typo
888 @
889 text
890 @d15 4
891 a18 4
892 #define VERBSW  1
893      "verbose", 0,
894 #define NVERBSW 2
895      "noverbose", 0,
896 d21 2
897 a22 5
898      "subject", 0,
899 #define NSUBJSW 4
900      "nosubject", 0,
901
902 #define LIMSW 5
903 d24 1
904 a24 1
905 #define NLIMSW 6
906 d27 6
907 a32 1
908 #define HELPSW  7
909 d47 3
910 a49 2
911 int     subjsort;           /* sort on subject if != 0 */
912 u_long  datelimit = ~0;
913 d53 1
914 a53 1
915 static  int dsort(), read_hdrs (), subsort();
916 d108 7
917 d116 1
918 a116 1
919                 subjsort = 1;
920 d119 1
921 a119 1
922                 subjsort = 0;
923 d125 6
924 d136 2
925 a137 1
926                 datelimit = ~0;         /* should be MAXINT ? */
927 d192 7
928 a198 1
929     qsort ((char *) dlist, nmsgs, sizeof(*dlist), dsort);
930 d200 4
931 d209 1
932 a209 1
933     if (subjsort) {
934 d256 2
935 a257 1
936                    (*s)->s_clock - s[-1]->s_clock <= datelimit) {
937 d340 1
938 a340 1
939             else if (subjsort && uleq (nam, "subject")) {
940 d405 13
941 a417 11
942             while (c = *cp++) {
943                 if (! isspace(c)) {
944                     if ((c == 'r' || c == 'R') &&
945                         (cp[0] == 'e' || cp[0] == 'E') &&
946                         cp[1] == ':')
947                         cp += 2;
948                     else {
949                         if (isalpha(c))
950                             *cp2++ = islower(c)?
951                                 c : tolower(c);
952                         break;
953 a419 1
954             }
955 d471 15
956 @
957
958
959 1.8
960 log
961 @typo
962 @
963 text
964 @d463 1
965 a463 1
966         printf ("message %s becomes message %s\n", old, new);
967 @
968
969
970 1.7
971 log
972 @typo and add -nosubject
973 @
974 text
975 @d444 1
976 a444 2
977 static void
978 rename_chain (mp, mlist, msg, endmsg)
979 d446 3
980 a448 2
981 struct smsg **mlist;
982 int msg, endmsg;
983 d463 1
984 a463 1
985         printf ("message %s becomes message %s\n", f2, f1);
986 @
987
988
989 1.6
990 log
991 @typo
992 @
993 text
994 @d22 2
995 d25 1
996 a25 1
997 #define LIMSW 4
998 d27 2
999 a28 2
1000 #define NLIMSW 5
1001      "nolimit", 0
1002 d30 1
1003 a30 1
1004 #define HELPSW  6
1005 d107 3
1006 @
1007
1008
1009 1.5
1010 log
1011 @add -nolimit
1012 @
1013 text
1014 @d111 1
1015 a111 1
1016                     adios (NULLCP, "impossible limit %d", outputlinelen);
1017 @
1018
1019
1020 1.4
1021 log
1022 @make -verbose messages more standard
1023 @
1024 text
1025 @d25 2
1026 d28 1
1027 a28 1
1028 #define HELPSW  5
1029 d41 1
1030 a41 1
1031 int nmsgs;
1032 d43 3
1033 a45 3
1034 int subjsort;           /* sort on subject if != 0 */
1035 u_long datelimit = ~0;
1036 int verbose;
1037 d109 3
1038 a111 3
1039                     adios (NULLCP, "missing argument to %s", argp[-2]);
1040                 if (! isdigit(*cp) || !(datelimit = atoi(cp)))
1041                     adios (NULLCP, "non-zero number must follow %s", argp[-2]);
1042 d113 3
1043 @
1044
1045
1046 1.3
1047 log
1048 @big rewrite -- sort by subject too!
1049 @
1050 text
1051 @d453 1
1052 a453 1
1053         printf ("    %s becomes %s\n", oldname, newname);
1054 d501 1
1055 a501 1
1056             printf ("renaming chain from %d to %d\n", old, new);
1057 @
1058
1059
1060 1.2
1061 log
1062 @ANSI Compilance
1063 @
1064 text
1065 @d2 1
1066 d7 3
1067 a10 2
1068 /* \f */
1069
1070 d12 2
1071 a13 2
1072 #define DATESW  0
1073     "datefield field", 0,
1074 d15 4
1075 a18 4
1076 #define VERBSW  1
1077     "verbose", 0,
1078 #define NVERBSW 2
1079     "noverbose", 0,
1080 d20 2
1081 a21 2
1082 #define HELPSW  3
1083     "help", 4,
1084 d23 7
1085 a29 1
1086     NULL, NULL
1087 a31 2
1088 /* \f */
1089
1090 d33 3
1091 a35 2
1092     int     s_msg;
1093     struct tws  s_tws;
1094 d39 1
1095 d41 3
1096 d45 3
1097 a47 1
1098 static int     msgsort ();
1099 a48 7
1100 static struct tws *getws ();
1101
1102 static int      read_dates();
1103 static          file_dates();
1104
1105 long    time ();
1106
1107 a50 2
1108 /* ARGSUSED */
1109
1110 d52 2
1111 a53 2
1112 int     argc;
1113 char  **argv;
1114 d55 1
1115 a55 2
1116     int     verbosw = 0,
1117             msgp = 0,
1118 d57 1
1119 a57 1
1120             msgnum;
1121 d59 8
1122 a66 8
1123            *maildir,
1124            *datesw = NULL,
1125            *folder = NULL,
1126             buf[100],
1127           **ap,
1128           **argp,
1129            *arguments[MAXARGS],
1130            *msgs[MAXARGS];
1131 d68 1
1132 a79 2
1133 /* \f */
1134
1135 d83 10
1136 a92 10
1137                 case AMBIGSW: 
1138                     ambigsw (cp, switches);
1139                     done (1);
1140                 case UNKWNSW: 
1141                     adios (NULLCP, "-%s unknown", cp);
1142                 case HELPSW: 
1143                     (void) sprintf (buf, "%s [+folder] [msgs] [switches]",
1144                             invo_name);
1145                     help (buf, switches);
1146                     done (1);
1147 d94 6
1148 a99 6
1149                 case DATESW: 
1150                     if (datesw)
1151                         adios (NULLCP, "only one date field at a time!");
1152                     if (!(datesw = *argp++) || *datesw == '-')
1153                         adios (NULLCP, "missing argument to %s", argp[-2]);
1154                     continue;
1155 d101 18
1156 a118 6
1157                 case VERBSW: 
1158                     verbosw++;
1159                     continue;
1160                 case NVERBSW: 
1161                     verbosw = 0;
1162                     continue;
1163 a129 2
1164 /* \f */
1165
1166 d135 1
1167 a135 1
1168         datesw = "Date";
1169 d144 1
1170 a144 1
1171     if (mp -> hghmsg == 0)
1172 d152 1
1173 a152 1
1174     if ((i = read_dates (mp, datesw)) <= 0)
1175 a153 2
1176     qsort ((char *) smsgs, i, sizeof *smsgs, msgsort);
1177     file_dates (mp, verbosw);
1178 d155 76
1179 a233 1
1180
1181 d237 4
1182 a240 5
1183 /* \f */
1184
1185 static int  read_dates (mp, datesw)
1186 register struct  msgs *mp;
1187 register char   *datesw;
1188 d242 2
1189 a243 2
1190     int     msgnum;
1191     struct tws  tb;
1192 a244 1
1193     register struct tws *tw;
1194 d248 3
1195 a250 3
1196     smsgs = (struct smsg   *)
1197                 calloc ((unsigned) (mp -> hghsel - mp -> lowsel + 2),
1198                         sizeof *smsgs);
1199 d255 6
1200 a260 5
1201     for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) {
1202         tw = NULL;
1203         if (mp -> msgstats[msgnum] & SELECTED) {
1204             if ((tw = getws (datesw, msgnum)) == NULL)
1205                 tw = msgnum != mp -> lowsel ? &((s - 1) -> s_tws) : &tb;
1206 a261 9
1207         else
1208             if (mp -> msgstats[msgnum] & EXISTS)
1209                 tw = &tb;
1210
1211         if (tw) {
1212             s -> s_msg = msgnum;
1213             twscopy (&s -> s_tws, tw);
1214             s++;
1215         }
1216 d263 2
1217 a264 3
1218
1219     s -> s_msg = 0;
1220     return (s - smsgs);
1221 d267 5
1222 a271 5
1223 /* \f */
1224
1225 static struct tws  *getws (datesw, msg)
1226 register char   *datesw;
1227 int     msg;
1228 d273 5
1229 a277 6
1230     int     compnum,
1231             state;
1232     register char  *hp,
1233                    *msgnam;
1234     char    buf[BUFSIZ],
1235             nam[NAMESZ];
1236 d279 3
1237 a281 1
1238     register    FILE *in;
1239 d285 1
1240 a285 1
1241         return NULL;
1242 d287 1
1243 a287 4
1244
1245 /* \f */
1246
1247     for (compnum = 1, state = FLD, hp = NULL;;) {
1248 d289 6
1249 a294 7
1250             case FLD: 
1251             case FLDEOF: 
1252             case FLDPLUS: 
1253                 compnum++;
1254                 if (hp != NULL)
1255                     free (hp), hp = NULL;
1256                 hp = add (buf, NULLCP);
1257 d297 1
1258 a297 1
1259                     hp = add (buf, hp);
1260 d299 1
1261 a299 1
1262                 if (uleq (nam, datesw))
1263 d301 16
1264 a316 2
1265                 if (state != FLDEOF)
1266                     continue;
1267 d318 4
1268 a321 4
1269             case BODY: 
1270             case BODYEOF: 
1271             case FILEEOF: 
1272                 admonish (NULLCP, "no %s field in message %d", datesw, msg);
1273 d323 11
1274 a333 10
1275             case LENERR: 
1276             case FMTERR: 
1277                 if (state == LENERR || state == FMTERR)
1278                     admonish (NULLCP,
1279                             "format error in message %d(header #%d)",
1280                             msg, compnum);
1281                 if (hp != NULL)
1282                     free (hp);
1283                 (void) fclose (in);
1284                 return NULL;
1285 d335 2
1286 a336 2
1287             default: 
1288                 adios (NULLCP, "internal error -- you lose");
1289 d341 2
1290 a342 3
1291     if ((tw = dparsetime (hp)) == NULL)
1292         admonish (NULLCP, "unable to parse %s field in message %d",
1293                 datesw, msg);
1294 d344 49
1295 a392 2
1296     if (hp != NULL)
1297         free (hp);
1298 d394 4
1299 a397 1
1300     return tw;
1301 d400 17
1302 a416 1
1303 /* \f */
1304 d418 7
1305 a424 3
1306 static int  msgsort (a, b)
1307 register struct smsg *a,
1308                      *b;
1309 d426 6
1310 a431 1
1311     return twsort (&a -> s_tws, &b -> s_tws);
1312 d434 11
1313 a444 1
1314 /* \f */
1315 d446 24
1316 a469 3
1317 static  file_dates (mp, verbosw)
1318 register struct  msgs *mp;
1319 int     verbosw;
1320 d471 9
1321 a479 7
1322     register int    i,
1323                     j,
1324                     k;
1325     short   stats;
1326     char    f1[BUFSIZ],
1327             f2[BUFSIZ],
1328             tmpfil[BUFSIZ];
1329 d483 3
1330 a485 7
1331     for (i = 0; j = smsgs[i++].s_msg;)
1332         if (i != j) {
1333             (void) strcpy (f1, m_name (i));
1334             (void) strcpy (f2, m_name (j));
1335             if (mp -> msgstats[i] & EXISTS) {
1336                 if (verbosw)
1337                     printf ("swap messages %s and %s\n", f2, f1);
1338 d487 3
1339 a489 4
1340                 if (rename (f1, tmpfil) == NOTOK) {
1341                     admonish (tmpfil, "unable to rename %s to ", f1);
1342                     continue;
1343                 }
1344 d491 8
1345 a498 4
1346                 if (rename (f2, f1) == NOTOK) {
1347                     admonish (f1, "unable to rename %s to", f2);
1348                     continue;
1349                 }
1350 d500 2
1351 a501 4
1352                 if (rename (tmpfil, f2) == NOTOK) {
1353                     admonish (f2, "unable to rename %s to", tmpfil);
1354                     continue;
1355                 }
1356 d503 3
1357 a505 9
1358                 for (k = i; smsgs[k].s_msg; k++)
1359                     if (smsgs[k].s_msg == i) {
1360                         smsgs[k].s_msg = j;
1361                         break;
1362                     }
1363             }
1364             else {
1365                 if (verbosw)
1366                     printf ("message %s becomes message %s\n", f2, f1);
1367 d507 3
1368 a509 5
1369                 if (rename (f2, f1) == NOTOK) {
1370                     admonish (f1, "unable to rename %s to ", f2);
1371                     continue;
1372                 }
1373             }
1374 d511 3
1375 a513 8
1376             smsgs[i - 1].s_msg = i;
1377             stats = mp -> msgstats[i];
1378             mp -> msgstats[i] = mp -> msgstats[j];
1379             mp -> msgstats[j] = stats;
1380             if (mp -> curmsg == j)
1381                 m_setcur (mp, i);
1382             mp -> msgflags |= SEQMOD;
1383         }
1384 @
1385
1386
1387 1.1
1388 log
1389 @Initial revision
1390 @
1391 text
1392 @d34 1
1393 a34 1
1394 int     msgsort ();
1395 d36 1
1396 a36 1
1397 struct tws *getws ();
1398 d38 2
1399 @