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