comparison uip/burst.c @ 0:bce86c4163a3

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