]> diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/uip/RCS/sortm.c,v
Always check that mktemp()/mktemp2() succeeds before trying to
[nmh] / 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 @