Commit | Line | Data |
---|---|---|
f8beb284 MW |
1 | /*$Id: ezmlm-archive.c,v 1.13 1999/11/28 20:13:32 lindberg Exp $*/ |
2 | /*$Name: ezmlm-idx-040 $*/ | |
3 | ||
4 | #include "alloc.h" | |
5 | #include "error.h" | |
6 | #include "stralloc.h" | |
7 | #include "str.h" | |
8 | #include "sig.h" | |
9 | #include "getconf.h" | |
10 | #include "strerr.h" | |
11 | #include "getln.h" | |
12 | #include "substdio.h" | |
13 | #include "readwrite.h" | |
14 | #include "fmt.h" | |
15 | #include "sgetopt.h" | |
16 | #include "idxthread.h" | |
17 | #include "makehash.h" | |
18 | #include "idx.h" | |
19 | #include "errtxt.h" | |
20 | ||
21 | #define FATAL "ezmlm-archive: fatal: " | |
22 | #define WARNING "ezmlm-archive: warning: inconsistent index: " | |
23 | ||
24 | substdio ssin; | |
25 | char inbuf[1024]; | |
26 | substdio ssout; | |
27 | char outbuf[1024]; | |
28 | substdio ssnum; | |
29 | char numbuf[16]; | |
30 | ||
31 | stralloc line = {0}; | |
32 | stralloc num = {0}; | |
33 | stralloc fn = {0}; | |
34 | stralloc fnn = {0}; | |
35 | ||
36 | char strnum[FMT_ULONG]; | |
37 | int flagerror = 0; | |
38 | int flagsync = 1; /* sync() by default, not for -c or -f or -t */ | |
39 | char *dir; | |
40 | ||
41 | struct ca { | |
42 | char *s; /* start */ | |
43 | unsigned int l; /* length */ | |
44 | } ca; | |
45 | ||
46 | void die_usage() { | |
47 | strerr_die1x(100, | |
48 | "ezmlm-archive: usage: " | |
49 | "ezmlm-archive [-cCFsSTvV] [-f min_msg] [-t max_msg] dir"); | |
50 | } | |
51 | ||
52 | void die_nomem() { strerr_die2x(111,FATAL,ERR_NOMEM); } | |
53 | ||
54 | void close_proper(ss,s,sn) | |
55 | /* flush,sync,close,move sn->s) */ | |
56 | substdio *ss; | |
57 | char *s, *sn; | |
58 | { | |
59 | if (substdio_flush(ss) == -1) | |
60 | strerr_die6sys(111,FATAL,ERR_FLUSH,dir,"/",s,": "); | |
61 | if (flagsync) | |
62 | if (fsync(ss->fd) == -1) | |
63 | strerr_die6sys(111,FATAL,ERR_SYNC,dir,"/",s,": "); | |
64 | if (close(ss->fd) == -1) | |
65 | strerr_die6sys(111,FATAL,ERR_CLOSE,dir,"/",s,": "); | |
66 | if (rename(sn,s) == -1) | |
67 | strerr_die6sys(111,FATAL,ERR_MOVE,dir,"/",sn,": "); | |
68 | } | |
69 | ||
70 | void write_threads(msgtable,subtable,authtable,datetable,from,to) | |
71 | /* Add the current threading data to the thread database without dups */ | |
72 | /* Writes the subject index first, then processes the individual files */ | |
73 | msgentry *msgtable; subentry *subtable; authentry *authtable; | |
74 | dateentry *datetable; | |
75 | unsigned long from,to; | |
76 | { | |
77 | msgentry *pmsgt; | |
78 | subentry *psubt,*psubtm, *psubtlast; | |
79 | subentry *presubt = (subentry *)0; | |
80 | authentry *pautht; | |
81 | dateentry *pdatet; | |
82 | char *cp,*cp1; | |
83 | unsigned long msg; | |
84 | unsigned long ulmsginthread; | |
85 | unsigned long subnum; | |
86 | unsigned long authnum; | |
87 | unsigned long msgnum; | |
88 | unsigned int pos,l; | |
89 | unsigned int startdate,nextdate; | |
90 | unsigned int startmsg,nextmsg; | |
91 | int fd = -1; | |
92 | int fdn = -1; | |
93 | int match; | |
94 | int ffound; | |
95 | int lineno; | |
96 | int res; | |
97 | ||
98 | psubtm = subtable; /* now for new threads */ | |
99 | pdatet = datetable; | |
100 | nextmsg = 0L; | |
101 | nextdate = pdatet->date; | |
102 | while (psubtm->sub) { /* these are in msgnum order */ | |
103 | if (!presubt) /* for rewind */ | |
104 | if (psubtm->lastmsg >= nextmsg) | |
105 | presubt = psubtm; /* this thread extends beyond current month */ | |
106 | if (psubtm->firstmsg >= nextmsg) { /* done with this month */ | |
107 | if (fdn != -1) close_proper(&ssout,fn.s,fnn.s); | |
108 | psubtlast = psubtm; /* last thread done */ | |
109 | if (presubt) /* need to rewind? */ | |
110 | psubtm = presubt; /* do it */ | |
111 | psubt = psubtm; /* tmp pointer to reset done flag */ | |
112 | presubt = (subentry *)0; /* reset rewind pointer */ | |
113 | pdatet++; /* next month */ | |
114 | startdate = nextdate; /* startdate */ | |
115 | nextdate = pdatet->date; /* end date */ | |
116 | startmsg = nextmsg; /* first message in month */ | |
117 | nextmsg = pdatet->msg; /* first message in next month */ | |
118 | if (!stralloc_copys(&fn,"archive/threads/")) die_nomem(); | |
119 | if (!stralloc_catb(&fn,strnum,fmt_uint(strnum,startdate))) die_nomem(); | |
120 | if (!stralloc_copy(&fnn,&fn)) die_nomem(); | |
121 | if (!stralloc_0(&fn)) die_nomem(); | |
122 | if (!stralloc_cats(&fnn,"n")) die_nomem(); | |
123 | if (!stralloc_0(&fnn)) die_nomem(); | |
124 | if ((fdn = open_trunc(fnn.s)) == -1) | |
125 | strerr_die6sys(111,FATAL,ERR_CREATE,dir,"/",fnn.s,": "); | |
126 | substdio_fdbuf(&ssout,write,fdn,outbuf,sizeof(outbuf)); | |
127 | if ((fd = open_read(fn.s)) == -1) { | |
128 | if (errno != error_noent) | |
129 | strerr_die6sys(111,FATAL,ERR_OPEN,dir,"/",fn.s,": "); | |
130 | } else { | |
131 | substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf)); | |
132 | for (;;) { | |
133 | if (getln(&ssin,&line,&match,'\n') == -1) | |
134 | strerr_die6sys(111,FATAL,ERR_READ,dir,"/",fn.s,": "); | |
135 | if (!match) break; | |
136 | pos = scan_ulong(line.s,&msgnum); | |
137 | pos++; /* skip ':' */ | |
138 | if (msgnum >= from) | |
139 | continue; /* ignore entries from threading range */ | |
140 | if (line.len < pos + HASHLEN) { | |
141 | flagerror = -1; /* and bad ones */ | |
142 | continue; | |
143 | } | |
144 | psubt = subtable; | |
145 | cp = line.s + pos; | |
146 | ffound = 0; /* search among already known subjects */ | |
147 | for (;;) { | |
148 | res = str_diffn(psubt->sub,cp,HASHLEN); | |
149 | if (res < 0) { | |
150 | if (psubt->higher) | |
151 | psubt = psubt->higher; | |
152 | else | |
153 | break; | |
154 | } else if (res > 0) { | |
155 | if (psubt->lower) | |
156 | psubt = psubt->lower; | |
157 | else | |
158 | break; | |
159 | } else { | |
160 | ffound = 1; | |
161 | break; | |
162 | } | |
163 | } | |
164 | if (!ffound) { | |
165 | if (substdio_put(&ssout,line.s,line.len) == -1) | |
166 | strerr_die6sys(111,FATAL,ERR_WRITE,dir,"/",fnn.s,": "); | |
167 | } else { /* new # of msg in thread */ | |
168 | cp += HASHLEN; /* HASHLEN [#] Subject always \n at end */ | |
169 | if (*(cp++) == ' ' && *(cp++) == '[') { | |
170 | cp += scan_ulong(cp,&ulmsginthread); | |
171 | if (*cp == ']') { | |
172 | psubt->msginthread += (unsigned char) (ulmsginthread & 0xff); | |
173 | } | |
174 | } else | |
175 | flagerror = -5; | |
176 | } | |
177 | } | |
178 | close(fd); | |
179 | } | |
180 | continue; | |
181 | } | |
182 | ||
183 | if (psubtm->firstmsg < nextmsg && psubtm->lastmsg >= startmsg) { | |
184 | if (!stralloc_copyb(&line,strnum,fmt_ulong(strnum,psubtm->lastmsg))) | |
185 | die_nomem(); | |
186 | if (!stralloc_cats(&line,":")) die_nomem(); | |
187 | if (!stralloc_catb(&line,psubtm->sub,HASHLEN)) die_nomem(); | |
188 | if (!stralloc_cats(&line," [")) die_nomem(); | |
189 | if (!stralloc_catb(&line,strnum, | |
190 | fmt_ulong(strnum,(unsigned long) psubtm->msginthread))) | |
191 | die_nomem(); | |
192 | if (!stralloc_cats(&line,"]")) die_nomem(); | |
193 | if (!stralloc_catb(&line,psubtm->sub + HASHLEN,psubtm->sublen - HASHLEN)) | |
194 | die_nomem(); /* has \n */ | |
195 | if (substdio_put(&ssout,line.s,line.len) == -1) | |
196 | strerr_die6sys(111,FATAL,ERR_WRITE,dir,"/",fnn.s,": "); | |
197 | } | |
198 | psubtm++; | |
199 | } | |
200 | if (fdn != -1) | |
201 | close_proper(&ssout,fn.s,fnn.s); | |
202 | ||
203 | psubt = subtable; | |
204 | while (psubt->sub) { /* now the threads */ | |
205 | if (!stralloc_copys(&fn,"archive/subjects/")) die_nomem(); | |
206 | if (!stralloc_catb(&fn,psubt->sub,2)) die_nomem(); | |
207 | if (!stralloc_0(&fn)) die_nomem(); | |
208 | if (mkdir(fn.s,0755) == -1) | |
209 | if (errno != error_exist) | |
210 | strerr_die6sys(111,FATAL,ERR_CREATE,dir,"/",fn.s,": "); | |
211 | fn.s[fn.len - 1] = '/'; | |
212 | if (!stralloc_catb(&fn,psubt->sub+2,HASHLEN-2)) die_nomem(); | |
213 | if (!stralloc_copy(&fnn,&fn)) die_nomem(); | |
214 | if (!stralloc_cats(&fnn,"n")) die_nomem(); | |
215 | if (!stralloc_0(&fn)) die_nomem(); | |
216 | if (!stralloc_0(&fnn)) die_nomem(); | |
217 | if ((fdn = open_trunc(fnn.s)) == -1) | |
218 | strerr_die4sys(111,FATAL,ERR_CREATE,fnn.s,": "); | |
219 | substdio_fdbuf(&ssout,write,fdn,outbuf,sizeof(outbuf)); | |
220 | if ((fd = open_read(fn.s)) == -1) { | |
221 | if (errno != error_noent) | |
222 | strerr_die4sys(111,FATAL,ERR_OPEN,fn.s,": "); | |
223 | if (substdio_puts(&ssout,psubt->sub) == -1) /* write subject */ | |
224 | strerr_die6sys(111,FATAL,ERR_WRITE,dir,"/",fnn.s,": "); | |
225 | } else { /* copy data */ | |
226 | substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf)); | |
227 | lineno = 0; | |
228 | for (;;) { | |
229 | if (getln(&ssin,&line,&match,'\n') == -1) | |
230 | strerr_die6sys(111,FATAL,ERR_READ,dir,"/",fn.s,": "); | |
231 | if (!match) break; | |
232 | if (!lineno) { /* write subject */ | |
233 | if (line.len < HASHLEN + 1 || line.s[HASHLEN] != ' ') | |
234 | flagerror = -3; | |
235 | if (substdio_put(&ssout,line.s,line.len) == -1) | |
236 | strerr_die6sys(111,FATAL,ERR_WRITE,dir,"/",fnn.s,": "); | |
237 | lineno = 1; | |
238 | continue; | |
239 | } | |
240 | (void) scan_ulong(line.s,&msgnum); | |
241 | if (msgnum >= from) break; | |
242 | if (substdio_put(&ssout,line.s,line.len) == -1) | |
243 | strerr_die6sys(111,FATAL,ERR_WRITE,dir,"/",fnn.s,": "); | |
244 | } | |
245 | (void) close(fd); /* close old index */ | |
246 | } | |
247 | ||
248 | subnum = (unsigned long) (psubt - subtable + 1); /* idx of this subj */ | |
249 | pmsgt = msgtable + psubt->firstmsg - from; /* first message entry */ | |
250 | for (msg = psubt->firstmsg; msg <= psubt->lastmsg; msg++) { | |
251 | if (pmsgt->subnum == subnum) { | |
252 | if (!stralloc_copyb(&line,strnum,fmt_ulong(strnum,msg))) die_nomem(); | |
253 | if (!stralloc_cats(&line,":")) die_nomem(); | |
254 | if (!stralloc_catb(&line,strnum,fmt_uint(strnum,pmsgt->date))) | |
255 | die_nomem(); | |
256 | if (!stralloc_cats(&line,":")) die_nomem(); | |
257 | if (pmsgt->authnum) { | |
258 | pautht = authtable + pmsgt->authnum - 1; | |
259 | cp = pautht->auth; | |
260 | cp1 = cp + str_chr(cp,' '); | |
261 | if (cp + HASHLEN != cp1) | |
262 | strerr_die1x(100,ERR_BAD_INDEX); | |
263 | if (!stralloc_cats(&line,cp)) | |
264 | die_nomem(); /* hash */ | |
265 | } else | |
266 | if (!stralloc_cats(&line,"\n")) die_nomem(); | |
267 | if (substdio_put(&ssout,line.s,line.len) == -1) | |
268 | strerr_die6sys(111,FATAL,ERR_WRITE,dir,"/",fnn.s,": "); | |
269 | } | |
270 | pmsgt++; | |
271 | } | |
272 | close_proper(&ssout,fn.s,fnn.s); | |
273 | psubt++; | |
274 | } | |
275 | ||
276 | /* (no master author index) */ | |
277 | pautht = authtable; | |
278 | while (pautht->auth) { /* now the authors */ | |
279 | if (!stralloc_copys(&fn,"archive/authors/")) die_nomem(); | |
280 | if (!stralloc_catb(&fn,pautht->auth,2)) die_nomem(); | |
281 | if (!stralloc_0(&fn)) die_nomem(); | |
282 | if (mkdir(fn.s,0755) == -1) | |
283 | if (errno != error_exist) | |
284 | strerr_die6sys(111,FATAL,ERR_CREATE,dir,"/",fn.s,": "); | |
285 | fn.s[fn.len - 1] = '/'; | |
286 | if (!stralloc_catb(&fn,pautht->auth+2,HASHLEN-2)) die_nomem(); | |
287 | if (!stralloc_copy(&fnn,&fn)) die_nomem(); | |
288 | if (!stralloc_cats(&fnn,"n")) die_nomem(); | |
289 | if (!stralloc_0(&fn)) die_nomem(); | |
290 | if (!stralloc_0(&fnn)) die_nomem(); | |
291 | if ((fdn = open_trunc(fnn.s)) == -1) | |
292 | strerr_die4sys(111,FATAL,ERR_CREATE,fnn.s,": "); | |
293 | substdio_fdbuf(&ssout,write,fdn,outbuf,sizeof(outbuf)); | |
294 | if ((fd = open_read(fn.s)) == -1) { | |
295 | if (errno != error_noent) | |
296 | strerr_die4sys(111,FATAL,ERR_OPEN,fn.s,": "); | |
297 | else { /* didn't exist before: write author */ | |
298 | if (substdio_put(&ssout,pautht->auth,pautht->authlen) == -1) | |
299 | strerr_die6sys(111,FATAL,ERR_WRITE,dir,"/",fnn.s,": "); | |
300 | } | |
301 | } else { /* copy data */ | |
302 | substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf)); | |
303 | lineno = 0; | |
304 | for (;;) { | |
305 | if (getln(&ssin,&line,&match,'\n') == -1) | |
306 | strerr_die6sys(111,FATAL,ERR_READ,dir,"/",fn.s,": "); | |
307 | if (!match) break; | |
308 | if (!lineno) { /* write author */ | |
309 | if (line.len < HASHLEN + 1 || line.s[HASHLEN] != ' ') | |
310 | flagerror = - 4; | |
311 | if (substdio_put(&ssout,line.s,line.len) == -1) | |
312 | strerr_die6sys(111,FATAL,ERR_WRITE,dir,"/",fnn.s,": "); | |
313 | lineno = 1; | |
314 | continue; | |
315 | } | |
316 | (void) scan_ulong(line.s,&msgnum); | |
317 | if (msgnum >= from) break; | |
318 | if (substdio_put(&ssout,line.s,line.len) == -1) | |
319 | strerr_die6sys(111,FATAL,ERR_WRITE,dir,"/",fnn.s,": "); | |
320 | } | |
321 | (void) close(fd); /* close old index */ | |
322 | } | |
323 | ||
324 | authnum = (unsigned long) (pautht - authtable + 1); /* idx of this auth */ | |
325 | pmsgt = msgtable + pautht->firstmsg - from; /* first message entry */ | |
326 | for (msg = pautht->firstmsg; msg <= to; msg++) { | |
327 | if (pmsgt->authnum == authnum) { | |
328 | if (!stralloc_copyb(&line,strnum,fmt_ulong(strnum,msg))) die_nomem(); | |
329 | if (!stralloc_cats(&line,":")) die_nomem(); | |
330 | if (!stralloc_catb(&line,strnum,fmt_uint(strnum,pmsgt->date))) | |
331 | die_nomem(); | |
332 | if (!stralloc_cats(&line,":")) die_nomem(); | |
333 | if (pmsgt->subnum) { | |
334 | psubt = subtable + pmsgt->subnum - 1; | |
335 | if (!stralloc_catb(&line,psubt->sub,psubt->sublen)) | |
336 | die_nomem(); | |
337 | } | |
338 | if (substdio_put(&ssout,line.s,line.len) == -1) | |
339 | strerr_die6sys(111,FATAL,ERR_WRITE,dir,"/",fnn.s,": "); | |
340 | } | |
341 | pmsgt++; | |
342 | } | |
343 | close_proper(&ssout,fn.s,fnn.s); | |
344 | pautht++; | |
345 | } | |
346 | } | |
347 | ||
348 | int main(argc,argv) | |
349 | int argc; | |
350 | char **argv; | |
351 | { | |
352 | unsigned long archnum = 0L; | |
353 | unsigned long to = 0L; | |
354 | unsigned long max; | |
355 | int fd; | |
356 | int fdlock; | |
357 | int flagcreate = 0; | |
358 | int flagsyncall = 0; | |
359 | int opt; | |
360 | msgentry *msgtable; | |
361 | subentry *subtable; | |
362 | authentry *authtable; | |
363 | dateentry *datetable; | |
364 | ||
365 | (void) umask(022); | |
366 | sig_pipeignore(); | |
367 | ||
368 | while ((opt = getopt(argc,argv,"cCf:FsSt:TvV")) != opteof) | |
369 | switch (opt) { | |
370 | case 'c': flagcreate = 1; | |
371 | flagsync = 0; | |
372 | break; /* start at beginning of archive */ | |
373 | case 'C': flagcreate = 0; | |
374 | break; /* Do only archnum+1 => num */ | |
375 | case 'f': if (optarg) { | |
376 | (void) scan_ulong(optarg,&archnum); | |
377 | archnum = (archnum / 100) * 100; | |
378 | } | |
379 | flagsync = 0; | |
380 | break; | |
381 | case 'F': archnum = 0; break; | |
382 | case 's': flagsyncall = 1; break; | |
383 | case 'S': flagsyncall = 0; break; | |
384 | case 't': if (optarg) { | |
385 | (void) scan_ulong(optarg,&to); | |
386 | } | |
387 | flagsync = 0; | |
388 | break; | |
389 | case 'T': to = 0; break; | |
390 | case 'v': | |
391 | case 'V': strerr_die2x(0,"ezmlm-archive version: ",EZIDX_VERSION); | |
392 | default: | |
393 | die_usage(); | |
394 | } | |
395 | ||
396 | if (flagsyncall) flagsync = 1; /* overrides */ | |
397 | dir = argv[optind++]; | |
398 | if (!dir) die_usage(); | |
399 | if (chdir(dir) == -1) | |
400 | strerr_die4sys(111,FATAL,ERR_SWITCH,dir,": "); | |
401 | ||
402 | if (mkdir("archive/threads",0755) == -1) | |
403 | if (errno != error_exist) | |
404 | strerr_die4sys(111,FATAL,ERR_CREATE,dir,"/archive/threads: "); | |
405 | if (mkdir("archive/subjects",0755) == -1) | |
406 | if (errno != error_exist) | |
407 | strerr_die4sys(111,FATAL,ERR_CREATE,dir,"/archive/subjects: "); | |
408 | if (mkdir("archive/authors",0755) == -1) | |
409 | if (errno != error_exist) | |
410 | strerr_die4sys(111,FATAL,ERR_CREATE,dir,"/archive/authors: "); | |
411 | ||
412 | /* Lock list to assure that no ezmlm-send is working on it */ | |
413 | /* and that the "num" message is final */ | |
414 | fdlock = open_append("lock"); | |
415 | if (fdlock == -1) | |
416 | strerr_die2sys(111,FATAL,ERR_OPEN_LOCK); | |
417 | if (lock_ex(fdlock) == -1) { | |
418 | (void) close(fdlock); | |
419 | strerr_die2sys(111,FATAL,ERR_OBTAIN_LOCK); | |
420 | } | |
421 | /* get num */ | |
422 | if (!getconf_line(&num,"num",0,FATAL,dir)) | |
423 | strerr_die1x(100,ERR_EMPTY_LIST); | |
424 | (void) close(fdlock); | |
425 | ||
426 | if (!stralloc_0(&num)) die_nomem(); /* parse num */ | |
427 | (void) scan_ulong(num.s,&max); | |
428 | if (!to || to > max) to = max; | |
429 | ||
430 | fdlock = open_append("archive/lock"); /* lock index */ | |
431 | if (fdlock == -1) | |
432 | strerr_die4sys(111,FATAL,ERR_OPEN,dir,"/archive/lock: "); | |
433 | if (lock_ex(fdlock) == -1) { | |
434 | (void) close(fdlock); | |
435 | strerr_die4sys(111,FATAL,ERR_OBTAIN,dir,"/archive/lock: "); | |
436 | } | |
437 | if (!flagcreate && !archnum) { /* adjust archnum (from) / to */ | |
438 | if (getconf_line(&num,"archnum",0,FATAL,dir)) { | |
439 | if (!stralloc_0(&num)) die_nomem(); | |
440 | (void) scan_ulong(num.s,&archnum); | |
441 | archnum++; | |
442 | } | |
443 | } | |
444 | ||
445 | if (archnum > to) | |
446 | _exit(0); /* nothing to do */ | |
447 | ||
448 | /* do the subject threading */ | |
449 | idx_mkthreads(&msgtable,&subtable,&authtable,&datetable, | |
450 | archnum,to,max,0,FATAL); | |
451 | /* update the index */ | |
452 | write_threads(msgtable,subtable,authtable,datetable,archnum,to); | |
453 | /* update archnum */ | |
454 | if ((fd = open_trunc("archnumn")) == -1) | |
455 | strerr_die4sys(111,FATAL,ERR_CREATE,dir,"/archnumn: "); | |
456 | substdio_fdbuf(&ssnum,write,fd,numbuf,sizeof(numbuf)); | |
457 | if (substdio_put(&ssnum,strnum,fmt_ulong(strnum,to)) == -1) | |
458 | strerr_die6sys(111,FATAL,ERR_WRITE,dir,"/",fnn.s,": "); | |
459 | if (substdio_puts(&ssnum,"\n") == -1) | |
460 | strerr_die6sys(111,FATAL,ERR_WRITE,dir,"/",fnn.s,": "); | |
461 | close_proper(&ssnum,"archnum","archnumn"); | |
462 | switch (flagerror) { | |
463 | case 0: | |
464 | _exit(0); /* go bye-bye */ | |
465 | case -1: | |
466 | strerr_die2x(99,WARNING,"threads entry with illegal format"); | |
467 | case -2: | |
468 | strerr_die2x(99,WARNING,"thread in index, but threadfile missing"); | |
469 | case -3: | |
470 | strerr_die2x(99,WARNING,"a subject file lacks subject"); | |
471 | case -4: | |
472 | strerr_die2x(99,WARNING,"an author file lacks author/hash"); | |
473 | case -5: | |
474 | strerr_die2x(99,WARNING,"threads entry lacks message count"); | |
475 | default: | |
476 | strerr_die2x(99,WARNING,"something happened that isn't quite right"); | |
477 | } | |
478 | } | |
479 |