Mercurial > hg > Applications > mh
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 } |