|
|
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: static void burst(), cpybrst();
9:
10: /* */
11:
12: static struct swit switches[] = {
13: #define INPLSW 0
14: "inplace", 0,
15: #define NINPLSW 1
16: "noinplace", 0,
17:
18: #define QIETSW 2
19: "quiet", 0,
20: #define NQIETSW 3
21: "noquiet", 0,
22:
23: #define VERBSW 4
24: "verbose", 0,
25: #define NVERBSW 5
26: "noverbose", 0,
27:
28: #define HELPSW 6
29: "help", 4,
30:
31: NULL, NULL
32: };
33:
34: /* */
35:
36: static char delim3[] = "-------";
37:
38:
39: static struct msgs *mp;
40:
41: struct smsg {
42: long s_start;
43: long s_stop;
44: };
45:
46: /* */
47:
48: /* ARGSUSED */
49:
50: main(argc, argv)
51: int argc;
52: char **argv;
53: {
54: int inplace = 0,
55: quietsw = 0,
56: verbosw = 0,
57: msgp = 0,
58: hi,
59: msgnum;
60: char *cp,
61: *maildir,
62: *folder = NULL,
63: buf[100],
64: **ap,
65: **argp,
66: *arguments[MAXARGS],
67: *msgs[MAXARGS];
68: struct smsg *smsgs;
69:
70: invo_name = r1bindex (argv[0], '/');
71: if ((cp = m_find (invo_name)) != NULL) {
72: ap = brkstring (cp = getcpy (cp), " ", "\n");
73: ap = copyip (ap, arguments);
74: }
75: else
76: ap = arguments;
77: (void) copyip (argv + 1, ap);
78: argp = arguments;
79:
80: /* */
81:
82: while (cp = *argp++) {
83: if (*cp == '-')
84: switch (smatch (++cp, switches)) {
85: case AMBIGSW:
86: ambigsw (cp, switches);
87: done (1);
88: case UNKWNSW:
89: adios (NULLCP, "-%s unknown\n", cp);
90: case HELPSW:
91: (void) sprintf (buf, "%s [+folder] [msgs] [switches]",
92: invo_name);
93: help (buf, switches);
94: done (1);
95:
96: case INPLSW:
97: inplace++;
98: continue;
99: case NINPLSW:
100: inplace = 0;
101: continue;
102:
103: case QIETSW:
104: quietsw++;
105: continue;
106: case NQIETSW:
107: quietsw = 0;
108: continue;
109:
110: case VERBSW:
111: verbosw++;
112: continue;
113: case NVERBSW:
114: verbosw = 0;
115: continue;
116: }
117: if (*cp == '+' || *cp == '@') {
118: if (folder)
119: adios (NULLCP, "only one folder at a time!");
120: else
121: folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
122: }
123: else
124: msgs[msgp++] = cp;
125: }
126:
127: /* */
128:
129: if (!m_find ("path"))
130: free (path ("./", TFOLDER));
131: if (!msgp)
132: msgs[msgp++] = "cur";
133: if (!folder)
134: folder = m_getfolder ();
135: maildir = m_maildir (folder);
136:
137: if (chdir (maildir) == NOTOK)
138: adios (maildir, "unable to change directory to");
139: if (!(mp = m_gmsg (folder)))
140: adios (NULLCP, "unable to read folder %s", folder);
141: if (mp -> hghmsg == 0)
142: adios (NULLCP, "no messages in %s", folder);
143:
144: for (msgnum = 0; msgnum < msgp; msgnum++)
145: if (!m_convert (mp, msgs[msgnum]))
146: done (1);
147: m_setseq (mp);
148:
149: smsgs = (struct smsg *)
150: calloc ((unsigned) (MAXFOLDER + 2), sizeof *smsgs);
151: if (smsgs == NULL)
152: adios (NULLCP, "unable to allocate burst storage");
153:
154: hi = mp -> hghmsg + 1;
155: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
156: if (mp -> msgstats[msgnum] & SELECTED)
157: burst (smsgs, msgnum, inplace, quietsw, verbosw);
158:
159: free ((char *) smsgs);
160:
161: m_replace (pfolder, folder);
162: if (inplace) {
163: if (mp -> lowsel != mp -> curmsg)
164: m_setcur (mp, mp -> lowsel);
165: }
166: else
167: if (hi <= mp -> hghmsg)
168: m_setcur (mp, hi);
169: m_sync (mp);
170: m_update ();
171:
172: done (0);
173: }
174:
175: /* */
176:
177: static void
178: burst(smsgs, msgnum, inplace, quietsw, verbosw)
179: register struct smsg *smsgs;
180: int msgnum, inplace, quietsw, 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 void
326: cpybrst(in, out, ifile, ofile, len)
327: register FILE *in, *out;
328: register char *ifile, *ofile;
329: register int len;
330: {
331: register int c,
332: state;
333:
334: for (state = S1; (c = fgetc (in)) != EOF && len > 0; len--) {
335: if (c == NULL)
336: continue;
337: switch (state) {
338: case S1:
339: switch (c) {
340: case '-':
341: state = S3;
342: break;
343:
344: default:
345: state = S2;
346: case '\n':
347: (void) fputc (c, out);
348: break;
349: }
350: break;
351:
352: case S2:
353: switch (c) {
354: case '\n':
355: state = S1;
356: default:
357: (void) fputc (c, out);
358: break;
359: }
360: break;
361:
362: case S3:
363: switch (c) {
364: case ' ':
365: state = S2;
366: break;
367:
368: default:
369: state = c == '\n' ? S1 : S2;
370: (void) fputc ('-', out);
371: (void) fputc (c, out);
372: break;
373: }
374: break;
375: }
376: }
377:
378: if (ferror (in))
379: adios (ifile, "error reading");
380: if (ferror (out))
381: adios (ofile, "error writing");
382: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.