|
|
1.1 root 1: /* burst.c - explode digests into individual messages */
2:
3: #include "../h/mh.h"
4: #include <stdio.h>
5: #include <sys/types.h>
6: #include <sys/stat.h>
7:
8: /* */
9:
10: static struct swit switches[] = {
11: #define INPLSW 0
12: "inplace", 0,
13: #define NINPLSW 1
14: "noinplace", 0,
15:
16: #define QIETSW 2
17: "quiet", 0,
18: #define NQIETSW 3
19: "noquiet", 0,
20:
21: #define VERBSW 4
22: "verbose", 0,
23: #define NVERBSW 5
24: "noverbose", 0,
25:
26: #define HELPSW 6
27: "help", 4,
28:
29: NULL, NULL
30: };
31:
32: /* */
33:
34: static char delim3[] = "-------";
35:
36:
37: static struct msgs *mp;
38:
39: struct smsg {
40: long s_start;
41: long s_stop;
42: };
43:
44: /* */
45:
46: /* ARGSUSED */
47:
48: main (argc, argv)
49: int argc;
50: char **argv;
51: {
52: int inplace = 0,
53: quietsw = 0,
54: verbosw = 0,
55: msgp = 0,
56: hi,
57: msgnum;
58: char *cp,
59: *maildir,
60: *folder = NULL,
61: buf[100],
62: **ap,
63: **argp,
64: *arguments[MAXARGS],
65: *msgs[MAXARGS];
66: struct smsg *smsgs;
67:
68: invo_name = r1bindex (argv[0], '/');
69: if ((cp = m_find (invo_name)) != NULL) {
70: ap = brkstring (cp = getcpy (cp), " ", "\n");
71: ap = copyip (ap, arguments);
72: }
73: else
74: ap = arguments;
75: (void) copyip (argv + 1, ap);
76: argp = arguments;
77:
78: /* */
79:
80: while (cp = *argp++) {
81: if (*cp == '-')
82: switch (smatch (++cp, switches)) {
83: case AMBIGSW:
84: ambigsw (cp, switches);
85: done (1);
86: case UNKWNSW:
87: adios (NULLCP, "-%s unknown\n", cp);
88: case HELPSW:
89: (void) sprintf (buf, "%s [+folder] [msgs] [switches]",
90: invo_name);
91: help (buf, switches);
92: done (1);
93:
94: case INPLSW:
95: inplace++;
96: continue;
97: case NINPLSW:
98: inplace = 0;
99: continue;
100:
101: case QIETSW:
102: quietsw++;
103: continue;
104: case NQIETSW:
105: quietsw = 0;
106: continue;
107:
108: case VERBSW:
109: verbosw++;
110: continue;
111: case NVERBSW:
112: verbosw = 0;
113: continue;
114: }
115: if (*cp == '+' || *cp == '@') {
116: if (folder)
117: adios (NULLCP, "only one folder at a time!");
118: else
119: folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
120: }
121: else
122: msgs[msgp++] = cp;
123: }
124:
125: /* */
126:
127: if (!m_find ("path"))
128: free (path ("./", TFOLDER));
129: if (!msgp)
130: msgs[msgp++] = "cur";
131: if (!folder)
132: folder = m_getfolder ();
133: maildir = m_maildir (folder);
134:
135: if (chdir (maildir) == NOTOK)
136: adios (maildir, "unable to change directory to");
137: if (!(mp = m_gmsg (folder)))
138: adios (NULLCP, "unable to read folder %s", folder);
139: if (mp -> hghmsg == 0)
140: adios (NULLCP, "no messages in %s", folder);
141:
142: for (msgnum = 0; msgnum < msgp; msgnum++)
143: if (!m_convert (mp, msgs[msgnum]))
144: done (1);
145: m_setseq (mp);
146:
147: smsgs = (struct smsg *)
148: calloc ((unsigned) (MAXFOLDER + 2), sizeof *smsgs);
149: if (smsgs == NULL)
150: adios (NULLCP, "unable to allocate burst storage");
151:
152: hi = mp -> hghmsg + 1;
153: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
154: if (mp -> msgstats[msgnum] & SELECTED)
155: burst (smsgs, msgnum, inplace, quietsw, verbosw);
156:
157: free ((char *) smsgs);
158:
159: m_replace (pfolder, folder);
160: if (inplace) {
161: if (mp -> lowsel != mp -> curmsg)
162: m_setcur (mp, mp -> lowsel);
163: }
164: else
165: if (hi <= mp -> hghmsg)
166: m_setcur (mp, hi);
167: m_sync (mp);
168: m_update ();
169:
170: done (0);
171: }
172:
173: /* */
174:
175: static burst (smsgs, msgnum, inplace, quietsw, verbosw)
176: register struct smsg *smsgs;
177: int msgnum,
178: inplace,
179: quietsw,
180: verbosw;
181: {
182: int i,
183: j,
184: ld3,
185: wasdlm,
186: mode,
187: msgp;
188: register long pos;
189: register char c,
190: *msgnam;
191: char buffer[BUFSIZ],
192: f1[BUFSIZ],
193: f2[BUFSIZ],
194: f3[BUFSIZ];
195: struct stat st;
196: register FILE *in,
197: *out;
198:
199: ld3 = strlen (delim3);
200:
201: if ((in = fopen (msgnam = m_name (msgnum), "r")) == NULL)
202: adios (msgnam, "unable to read message");
203:
204: mode = fstat (fileno (in), &st) != NOTOK ? (st.st_mode & 0777)
205: : m_gmprot ();
206: for (msgp = 1, pos = 0L; msgp <= MAXFOLDER;) {
207: while (fgets (buffer, sizeof buffer, in) != NULL
208: && buffer[0] == '\n')
209: pos += (long) strlen (buffer);
210: if (feof (in))
211: break;
212: (void) fseek (in, pos, 0);
213: smsgs[msgp].s_start = pos;
214:
215: for (c = NULL;
216: fgets (buffer, sizeof buffer, in) != NULL;
217: c = buffer[0])
218: if (strncmp (buffer, delim3, ld3) == 0
219: && peekc (in) == '\n'
220: && (msgp == 1 || c == '\n'))
221: break;
222: else
223: pos += (long) strlen (buffer);
224:
225: wasdlm = strncmp (buffer, delim3, ld3) == 0;
226: if (smsgs[msgp].s_start != pos)
227: smsgs[msgp++].s_stop = c == '\n' && wasdlm ? pos - 1 : pos;
228: if (feof (in)) {
229: if (wasdlm) {
230: smsgs[msgp - 1].s_stop -= ((long) strlen (buffer) + 1);
231: msgp++; /* fake "End of XXX Digest" */
232: }
233: break;
234: }
235: pos += (long) strlen (buffer);
236: }
237:
238: /* */
239:
240: switch (--msgp) { /* toss "End of XXX Digest" */
241: case 0:
242: adios (NULLCP, "burst() botch -- you lose big");
243:
244: case 1:
245: if (!quietsw)
246: admonish (NULLCP, "message %d not in digest format", msgnum);
247: (void) fclose (in);
248: return;
249:
250: default:
251: if (verbosw)
252: printf ("%d message%s exploded from digest %d\n",
253: msgp - 1, msgp - 1 != 1 ? "s" : "", msgnum);
254: if (msgp == 2) /* XXX */
255: msgp++;
256: break;
257: }
258:
259: if ((mp = m_remsg (mp, 0, mp -> hghmsg + msgp)) == NULL)
260: adios (NULLCP, "unable to allocate folder storage");
261:
262: /* */
263:
264: msgp--;
265: j = mp -> hghmsg;
266: mp -> hghmsg += msgp - 1;
267: mp -> nummsg += msgp - 1;
268: if (mp -> hghsel > msgnum)
269: mp -> hghsel += msgp - 1;
270:
271: if (inplace && msgp > 1)
272: for (i = mp -> hghmsg; j > msgnum; i--, j--) {
273: (void) strcpy (f1, m_name (i));
274: (void) strcpy (f2, m_name (j));
275: if (mp -> msgstats[j] & EXISTS) {
276: if (verbosw)
277: printf ("message %d becomes message %d\n", j, i);
278:
279: if (rename (f2, f1) == NOTOK)
280: admonish (f1, "unable to rename %s to", f2);
281: mp -> msgstats[i] = mp -> msgstats[j];
282: mp -> msgstats[j] = NULL;
283: mp -> msgflags |= SEQMOD;
284: }
285: }
286:
287: mp -> msgstats[msgnum] &= ~SELECTED;
288: i = inplace ? msgnum + msgp - 1 : mp -> hghmsg;
289: for (j = msgp; j >= (inplace ? 1 : 2); i--, j--) {
290: (void) strcpy (f1, m_name (i));
291: (void) strcpy (f2, m_scratch ("", invo_name));
292: if (verbosw && i != msgnum)
293: printf ("message %d of digest %d becomes message %d\n",
294: j, msgnum, i);
295:
296: if ((out = fopen (f2, "w")) == NULL)
297: adios (f2, "unable to write message");
298: (void) chmod (f2, mode);
299: (void) fseek (in, pos = smsgs[j].s_start, 0);
300: cpybrst (in, out, msgnam, f2,
301: (int) (smsgs[j].s_stop - smsgs[j].s_start));
302: (void) fclose (out);
303:
304: if (i == msgnum) {
305: (void) strcpy (f3, m_backup (f1));
306: if (rename (f1, f3) == NOTOK)
307: admonish (f3, "unable to rename %s to", f1);
308: }
309: if (rename (f2, f1) == NOTOK)
310: admonish (f1, "unable to rename %s to", f2);
311: mp -> msgstats[i] = mp -> msgstats[msgnum];
312: mp -> msgflags |= SEQMOD;
313: }
314:
315: (void) fclose (in);
316: }
317:
318:
319: /* */
320:
321: #define S1 0
322: #define S2 1
323: #define S3 2
324:
325: static cpybrst (in, out, ifile, ofile, len)
326: register FILE *in,
327: *out;
328: register char *ifile,
329: *ofile;
330: register int len;
331: {
332: register int c,
333: state;
334:
335: for (state = S1; (c = fgetc (in)) != EOF && len > 0; len--) {
336: if (c == NULL)
337: continue;
338: switch (state) {
339: case S1:
340: switch (c) {
341: case '-':
342: state = S3;
343: break;
344:
345: default:
346: state = S2;
347: case '\n':
348: (void) fputc (c, out);
349: break;
350: }
351: break;
352:
353: case S2:
354: switch (c) {
355: case '\n':
356: state = S1;
357: default:
358: (void) fputc (c, out);
359: break;
360: }
361: break;
362:
363: case S3:
364: switch (c) {
365: case ' ':
366: state = S2;
367: break;
368:
369: default:
370: state = c == '\n' ? S1 : S2;
371: (void) fputc ('-', out);
372: (void) fputc (c, out);
373: break;
374: }
375: break;
376: }
377: }
378:
379: if (ferror (in))
380: adios (ifile, "error reading");
381: if (ferror (out))
382: adios (ofile, "error writing");
383: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.