|
|
1.1 root 1: /* sortm.c - sort messages in a folder by date/time */
2:
3: #include "../h/mh.h"
4: #include "../zotnet/tws.h"
5: #include <stdio.h>
6:
7: /* */
8:
9: static struct swit switches[] = {
10: #define DATESW 0
11: "datefield field", 0,
12:
13: #define VERBSW 1
14: "verbose", 0,
15: #define NVERBSW 2
16: "noverbose", 0,
17:
18: #define HELPSW 3
19: "help", 4,
20:
21: NULL, NULL
22: };
23:
24: /* */
25:
26: struct smsg {
27: int s_msg;
28: struct tws s_tws;
29: };
30:
31: static struct smsg *smsgs;
32:
33:
34: int msgsort ();
35:
36: struct tws *getws ();
37:
38:
39: long time ();
40:
41: /* */
42:
43: /* ARGSUSED */
44:
45: main (argc, argv)
46: int argc;
47: char **argv;
48: {
49: int verbosw = 0,
50: msgp = 0,
51: i,
52: msgnum;
53: char *cp,
54: *maildir,
55: *datesw = NULL,
56: *folder = NULL,
57: buf[100],
58: **ap,
59: **argp,
60: *arguments[MAXARGS],
61: *msgs[MAXARGS];
62: struct msgs *mp;
63:
64: invo_name = r1bindex (argv[0], '/');
65: if ((cp = m_find (invo_name)) != NULL) {
66: ap = brkstring (cp = getcpy (cp), " ", "\n");
67: ap = copyip (ap, arguments);
68: }
69: else
70: ap = arguments;
71: (void) copyip (argv + 1, ap);
72: argp = arguments;
73:
74: /* */
75:
76: while (cp = *argp++) {
77: if (*cp == '-')
78: switch (smatch (++cp, switches)) {
79: case AMBIGSW:
80: ambigsw (cp, switches);
81: done (1);
82: case UNKWNSW:
83: adios (NULLCP, "-%s unknown", cp);
84: case HELPSW:
85: (void) sprintf (buf, "%s [+folder] [msgs] [switches]",
86: invo_name);
87: help (buf, switches);
88: done (1);
89:
90: case DATESW:
91: if (datesw)
92: adios (NULLCP, "only one date field at a time!");
93: if (!(datesw = *argp++) || *datesw == '-')
94: adios (NULLCP, "missing argument to %s", argp[-2]);
95: continue;
96:
97: case VERBSW:
98: verbosw++;
99: continue;
100: case NVERBSW:
101: verbosw = 0;
102: continue;
103: }
104: if (*cp == '+' || *cp == '@') {
105: if (folder)
106: adios (NULLCP, "only one folder at a time!");
107: else
108: folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
109: }
110: else
111: msgs[msgp++] = cp;
112: }
113:
114: /* */
115:
116: if (!m_find ("path"))
117: free (path ("./", TFOLDER));
118: if (!msgp)
119: msgs[msgp++] = "all";
120: if (!datesw)
121: datesw = "Date";
122: if (!folder)
123: folder = m_getfolder ();
124: maildir = m_maildir (folder);
125:
126: if (chdir (maildir) == NOTOK)
127: adios (maildir, "unable to change directory to");
128: if (!(mp = m_gmsg (folder)))
129: adios (NULLCP, "unable to read folder %s", folder);
130: if (mp -> hghmsg == 0)
131: adios (NULLCP, "no messages in %s", folder);
132:
133: for (msgnum = 0; msgnum < msgp; msgnum++)
134: if (!m_convert (mp, msgs[msgnum]))
135: done (1);
136: m_setseq (mp);
137:
138: if ((i = read_dates (mp, datesw)) <= 0)
139: adios (NULLCP, "no messages to sort");
140: qsort ((char *) smsgs, i, sizeof *smsgs, msgsort);
141: file_dates (mp, verbosw);
142:
143: m_replace (pfolder, folder);
144: m_sync (mp);
145: m_update ();
146:
147: done (0);
148: }
149:
150: /* */
151:
152: static int read_dates (mp, datesw)
153: register struct msgs *mp;
154: register char *datesw;
155: {
156: int msgnum;
157: struct tws tb;
158: register struct smsg *s;
159: register struct tws *tw;
160:
161: twscopy (&tb, dtwstime ());
162:
163: smsgs = (struct smsg *)
164: calloc ((unsigned) (mp -> hghsel - mp -> lowsel + 2),
165: sizeof *smsgs);
166: if (smsgs == NULL)
167: adios (NULLCP, "unable to allocate sort storage");
168:
169: s = smsgs;
170: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) {
171: tw = NULL;
172: if (mp -> msgstats[msgnum] & SELECTED) {
173: if ((tw = getws (datesw, msgnum)) == NULL)
174: tw = msgnum != mp -> lowsel ? &((s - 1) -> s_tws) : &tb;
175: }
176: else
177: if (mp -> msgstats[msgnum] & EXISTS)
178: tw = &tb;
179:
180: if (tw) {
181: s -> s_msg = msgnum;
182: twscopy (&s -> s_tws, tw);
183: s++;
184: }
185: }
186:
187: s -> s_msg = 0;
188: return (s - smsgs);
189: }
190:
191: /* */
192:
193: static struct tws *getws (datesw, msg)
194: register char *datesw;
195: int msg;
196: {
197: int compnum,
198: state;
199: register char *hp,
200: *msgnam;
201: char buf[BUFSIZ],
202: nam[NAMESZ];
203: register struct tws *tw;
204: register FILE *in;
205:
206: if ((in = fopen (msgnam = m_name (msg), "r")) == NULL) {
207: admonish (msgnam, "unable to read message");
208: return NULL;
209: }
210:
211: /* */
212:
213: for (compnum = 1, state = FLD, hp = NULL;;) {
214: switch (state = m_getfld (state, nam, buf, sizeof buf, in)) {
215: case FLD:
216: case FLDEOF:
217: case FLDPLUS:
218: compnum++;
219: if (hp != NULL)
220: free (hp), hp = NULL;
221: hp = add (buf, NULLCP);
222: while (state == FLDPLUS) {
223: state = m_getfld (state, nam, buf, sizeof buf, in);
224: hp = add (buf, hp);
225: }
226: if (uleq (nam, datesw))
227: break;
228: if (state != FLDEOF)
229: continue;
230:
231: case BODY:
232: case BODYEOF:
233: case FILEEOF:
234: admonish (NULLCP, "no %s field in message %d", datesw, msg);
235:
236: case LENERR:
237: case FMTERR:
238: if (state == LENERR || state == FMTERR)
239: admonish (NULLCP,
240: "format error in message %d(header #%d)",
241: msg, compnum);
242: if (hp != NULL)
243: free (hp);
244: (void) fclose (in);
245: return NULL;
246:
247: default:
248: adios (NULLCP, "internal error -- you lose");
249: }
250: break;
251: }
252:
253: if ((tw = dparsetime (hp)) == NULL)
254: admonish (NULLCP, "unable to parse %s field in message %d",
255: datesw, msg);
256:
257: if (hp != NULL)
258: free (hp);
259: (void) fclose (in);
260: return tw;
261: }
262:
263: /* */
264:
265: static int msgsort (a, b)
266: register struct smsg *a,
267: *b;
268: {
269: return twsort (&a -> s_tws, &b -> s_tws);
270: }
271:
272: /* */
273:
274: static file_dates (mp, verbosw)
275: register struct msgs *mp;
276: int verbosw;
277: {
278: register int i,
279: j,
280: k;
281: short stats;
282: char f1[BUFSIZ],
283: f2[BUFSIZ],
284: tmpfil[BUFSIZ];
285:
286: (void) strcpy (tmpfil, m_scratch ("", invo_name));
287:
288: for (i = 0; j = smsgs[i++].s_msg;)
289: if (i != j) {
290: (void) strcpy (f1, m_name (i));
291: (void) strcpy (f2, m_name (j));
292: if (mp -> msgstats[i] & EXISTS) {
293: if (verbosw)
294: printf ("swap messages %s and %s\n", f2, f1);
295:
296: if (rename (f1, tmpfil) == NOTOK) {
297: admonish (tmpfil, "unable to rename %s to ", f1);
298: continue;
299: }
300:
301: if (rename (f2, f1) == NOTOK) {
302: admonish (f1, "unable to rename %s to", f2);
303: continue;
304: }
305:
306: if (rename (tmpfil, f2) == NOTOK) {
307: admonish (f2, "unable to rename %s to", tmpfil);
308: continue;
309: }
310:
311: for (k = i; smsgs[k].s_msg; k++)
312: if (smsgs[k].s_msg == i) {
313: smsgs[k].s_msg = j;
314: break;
315: }
316: }
317: else {
318: if (verbosw)
319: printf ("message %s becomes message %s\n", f2, f1);
320:
321: if (rename (f2, f1) == NOTOK) {
322: admonish (f1, "unable to rename %s to ", f2);
323: continue;
324: }
325: }
326:
327: smsgs[i - 1].s_msg = i;
328: stats = mp -> msgstats[i];
329: mp -> msgstats[i] = mp -> msgstats[j];
330: mp -> msgstats[j] = stats;
331: if (mp -> curmsg == j)
332: m_setcur (mp, i);
333: mp -> msgflags |= SEQMOD;
334: }
335: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.