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