ezmlmx 0.68
ezmlmx
Loading...
Searching...
No Matches
idxthread.c
Go to the documentation of this file.
1#include <sys/types.h>
2#include <sys/stat.h>
3#include <unistd.h>
4#include "error.h"
5#include "alloc.h"
6#include "str.h"
7#include "stralloc.h"
8#include "logmsg.h"
9#include "lock.h"
10#include "open.h"
11#include "getln.h"
12#include "scan.h"
13#include "byte.h"
14#include "idx.h"
15#include "errtxt.h"
16#include "buffer.h"
17#include "fmt.h"
18#include "readwrite.h"
19//#include "makehash.h"
20#include "lockfile.h"
21#include "date2yyyymm.h"
22#include "getconf.h"
23
24#define WHO "idxthread"
25#define HASHLEN 20
26
41
42#define DATENO 100
43static stralloc line = {0}; /* primary input */
44static stralloc authline = {0}; /* second line of primary input */
45static stralloc dummyind = {0};
46
47static buffer bi;
48static char indexbuf[1024];
49
50static char strnum[FMT_ULONG];
51
52static struct stat st;
53 /* if no data, these may be the entire table, so need to be static */
54static subentry sdummy;
55static authentry adummy;
56
57static int fdlock;
58
59/* NOTE: These do NOT prevent double locking */
60
61static void die_nomem() { logmsg(WHO,111,FATAL,ERR_NOMEM); }
62static void lockup() { fdlock = lockfile("lock"); }
63static void unlock() { close(fdlock); }
64
70
71static void newsub(subentry *psubt,const char *subject,unsigned int sublen,unsigned long msg)
72{
73 const char *cpfrom;
74 char *cpto;
75 unsigned int cpno;
76
77 psubt->higher = (subentry *) 0;
78 psubt->lower = (subentry *) 0;
79 psubt->firstmsg = msg;
80 psubt->lastmsg = msg;
81 psubt->msginthread = 1;
82 if (!(psubt->sub = alloc ((sublen) * sizeof(char))))
83 die_nomem();
84 cpto = psubt->sub;
85 cpno = sublen;
86 cpfrom = subject;
87 while (cpno--) *(cpto++) = *(cpfrom++);
88 psubt->sublen = sublen;
89}
90
100
101static void newauth(authentry *pautht,const char *author,unsigned int authlen,unsigned long msg)
102{
103 const char *cpfrom;
104 char *cpto;
105 unsigned int cpno;
106
107 pautht->higher = (subentry *) 0;
108 pautht->lower = (subentry *) 0;
109 pautht->firstmsg = msg;
110 if (!(pautht->auth = alloc ((authlen) * sizeof(char))))
111 die_nomem();
112 cpto = pautht->auth;
113 cpno = authlen;
114 cpfrom = author;
115 while (cpno--)
116 *(cpto++) = *(cpfrom++);
117 pautht->authlen = authlen;
118}
119
120static void init_dummy(void)
121{
122 unsigned int i;
123
124 if (!stralloc_ready(&dummyind,HASHLEN + 1)) die_nomem();
125 for (i = 0; i< HASHLEN; i++)
126 dummyind.s[i] = 'a';
127 dummyind.len = HASHLEN;
128 if (!stralloc_append(&dummyind," ")) die_nomem();
129}
130
155
156void idx_mkthreads(msgentry **pmsgtable,subentry **psubtable,
157 authentry **pauthtable, dateentry **pdatetable,
158 unsigned long msg_from,unsigned long msg_to,
159 unsigned long msg_latest,int locked)
160{
161 unsigned long idxlatest; /* need to lock for this (last) index file */
162 unsigned long msg; /* current msg number */
163 unsigned long endmsg; /* max msg in this idx file */
164 unsigned long tmpmsg; /* index entry's msg number */
165 unsigned long idx; /* current index file no */
166 unsigned long idxto; /* index containing end of range */
167 unsigned long ulmrange; /* total # of messages in range */
168 char *subject; /* subject on line */
169 unsigned int sublen; /* length of subject */
170 char *auth;
171 unsigned int authlen;
172 unsigned int pos,posa;
173 unsigned long submax; /* max subject num in subtable */
174 subentry *psubnext; /* points to next entry in subtable */
175 subentry *psubt; /* points to entry in subtable */
176 authentry *pauthnext; /* points to next entry in authtable */
177 authentry *pautht; /* points to entry in authtable */
178 int fd; /* index file handle */
179 int flagmissingindex; /* current index file is missing */
180 int flagauth; /* read index entry has author info */
181 int hasauth; /* current msg's entry has author info */
182 msgentry *pmsgt;
183 int res;
184 int match;
185 unsigned int datepos,datemax;
186 unsigned int datetablesize,datetableunit;
187 unsigned int lastdate = 0;
188 unsigned int thisdate;
189 msgentry *x, *y;
190
191 /* a few unnecessary sanity checks */
192
193 if (msg_to > msg_latest)
194 msg_to = msg_latest;
195 if (msg_to < msg_from)
196 logmsg(WHO,100,FATAL,"Program error: bad range in idx_mkthreads");
197 ulmrange = msg_to - msg_from + 1;
198 if (!(*pmsgtable = (msgentry *) alloc(ulmrange * sizeof(msgentry))))
199 die_nomem();
200 y = *pmsgtable;
201 x = y + ulmrange; /* clear */
202 while (--x >= y) {
203 x->subnum = 0;
204 x->authnum = 0;
205 x->date = 0;
206 }
207
208 /* max entries - acceptable waste for now */
209
210 if (!(*psubtable = (subentry *) alloc((ulmrange + 1) * sizeof(subentry))))
211 die_nomem();
212
213 if (!(*pauthtable = (authentry *) alloc((ulmrange + 1) * sizeof(authentry))))
214 die_nomem();
215
216 datetableunit = DATENO * sizeof(dateentry);
217 datetablesize = datetableunit;
218
219 if (!(*pdatetable = (dateentry *) alloc(datetablesize)))
220 die_nomem();
221
222 datepos = 0;
223 datemax = DATENO - 2; /* entry 0 and end marker */
224 lastdate = 0;
225
226 idxlatest = msg_latest / 100;
227 idxto = msg_to / 100;
228 submax = 0;
229 psubnext = *psubtable; /* dummy node to get tree going. Basically, */
230 psubt = &sdummy; /* assure that subject > psubt-sub and that */
231 init_dummy(); /* below ok unless HASHLEN > 40 */
232 psubt->sub = (char *)" ";
233 psubt->sublen = 40; /* there is something to hold psubt->higher */
234 psubt->higher = (subentry *) 0;
235 psubt->lower = (subentry *) 0;
236 pauthnext = *pauthtable;
237 pautht = &adummy;
238 pautht->auth = psubt->sub;
239 pautht->authlen = psubt->sublen;
240 pautht->higher = (authentry *) 0;
241 pautht->lower = (authentry *) 0;
242
243 for (idx = msg_from / 100; idx <= idxto; idx++) { /* make index file name */
244 if (!stralloc_copys(&line,"archive/")) die_nomem();
245 if (!stralloc_catb(&line,strnum,fmt_ulong(strnum,idx))) die_nomem();
246 if (!stralloc_cats(&line,"/index")) die_nomem();
247 if (!stralloc_0(&line)) die_nomem();
248 if (!locked && idx == idxlatest)
249 lockup();
250 flagmissingindex = 0;
251 fd = open_read(line.s);
252 if (fd == -1) {
253 if (errno == ENOENT) { /* this means the index is not here but the lists is supposedly indexed */
254 flagmissingindex = 1;
255 } else
256 logmsg(WHO,111,FATAL,B(ERR_OPEN,line.s));
257 } else
258 buffer_init(&bi,buffer_unixread,fd,indexbuf,sizeof(indexbuf));
259
260 msg = 100L * idx; /* current msg# */
261 endmsg = msg + 99L; /* max msg in this index */
262 if (!msg) msg = 1L; /* for start to make msg > tmpmsg */
263 tmpmsg = 0L; /* msg number of read index line */
264 if (endmsg > msg_to) /* skip non-asked for subjects */
265 endmsg = msg_to;
266 for (; msg <= endmsg; msg++) {
267 if (!flagmissingindex && (msg > tmpmsg)) {
268 flagauth = 0;
269 if (getln(&bi,&line,&match,'\n') == -1)
270 logmsg(WHO,111,FATAL,B(ERR_READ,"index"));
271 if (!match)
272 flagmissingindex = 1;
273 else {
274 pos = scan_ulong(line.s,&tmpmsg);
275 if (line.s[pos++] == ':') {
276 if (getln(&bi,&authline,&match,'\n') == -1)
277 logmsg(WHO,111,FATAL,B(ERR_READ,"index"));
278 if (!match)
279 flagmissingindex = 1;
280 else {
281 flagauth = 1;
282 }
283 pos++;
284 }
285 }
286 }
287 if (msg < msg_from) /* Nothing before start of range */
288 continue;
289 if (msg == tmpmsg) {
290 subject = line.s + pos;
291 sublen = line.len - pos;
292 if (sublen <= HASHLEN)
293 logmsg(WHO,100,FATAL,ERR_BAD_INDEX);
294 hasauth = flagauth;
295 } else {
296 subject = dummyind.s;
297 sublen = dummyind.len;
298 hasauth = 0;
299 }
300 for (;;) { /* search among already known subjects */
301 res = str_diffn(psubt->sub,subject,HASHLEN);
302 if (res < 0) {
303 if (psubt->higher)
304 psubt = psubt->higher;
305 else {
306 newsub(psubnext,subject,sublen,msg);
307 psubt->higher = psubnext;
308 psubt = psubnext;
309 psubnext++;
310 break;
311 }
312 } else if (res > 0) {
313 if (psubt->lower)
314 psubt = psubt->lower;
315 else {
316 newsub(psubnext,subject,sublen,msg);
317 psubt->lower = psubnext;
318 psubt = psubnext;
319 psubnext++;
320 break;
321 }
322 } else {
323 psubt->lastmsg = msg;
324 (psubt->msginthread)++; /* one more message in thread */
325 break;
326 }
327 }
328
329 /* first subnum =1 (=0 is empty for thread) */
330
331 pmsgt = *pmsgtable + msg - msg_from;
332 pmsgt->subnum = (unsigned int) (psubt - *psubtable + 1);
333 pmsgt->date = lastdate;
334 if (hasauth) {
335 pos = 0;
336 while (authline.s[pos] && authline.s[pos] != ' ')
337 pos++;
338 if (authline.s[++pos]) {
339 thisdate = date2yyyymm(authline.s + pos);
340 if (thisdate) pmsgt->date = thisdate;
341 if (pmsgt->date > lastdate) {
342 lastdate = pmsgt->date;
343 if (datepos >= datemax) { /* more space */
344 datemax += DATENO;
345 if (!alloc_re((void**)pdatetable,datetablesize,datetablesize+datetableunit))
346 die_nomem();
347 }
348 (*pdatetable)[datepos].msg = msg; /* first msg this mo */
349 (*pdatetable)[datepos].date = lastdate;
350 datepos++;
351 }
352 posa = byte_chr(authline.s,authline.len,';');
353 if (authline.len > posa + HASHLEN + 1 && authline.s[pos + 1] != ' ') {
354 /* old: "; auth", new: ";hash auth" */
355 auth = authline.s + posa + 1;
356 authlen = authline.len - posa - 1;
357 } else {
358 auth = dummyind.s;
359 authlen = dummyind.len;
360 }
361 }
362
363 /* allright! Same procedure, but for author */
364
365 for (;;) { /* search among already known authors */
366 res = str_diffn(pautht->auth,auth,HASHLEN);
367 if (res < 0) {
368 if (pautht->higher)
369 pautht = pautht->higher;
370 else {
371 newauth(pauthnext,auth,authlen,msg);
372 pautht->higher = pauthnext;
373 pautht = pauthnext;
374 pauthnext++;
375 break;
376 }
377 } else if (res > 0) {
378 if (pautht->lower)
379 pautht = pautht->lower;
380 else {
381 newauth(pauthnext,auth,authlen,msg);
382 pautht->lower = pauthnext;
383 pautht = pauthnext;
384 pauthnext++;
385 break;
386 }
387 } else {
388 break;
389 }
390 } /* link from message to this author */
391 pmsgt->authnum = (unsigned int) (pautht - *pauthtable + 1);
392 pautht = *pauthtable;
393 }
394
395 psubt = *psubtable; /* setup psubt. Done here rather than before */
396 /* the for loop, so that we can start off the dummy node. */
397 }
398 if (fd != -1)
399 close(fd);
400 if (!locked && idx == idxlatest)
401 unlock(); /* 'locked' refers to locked before calling */
402 }
403 psubnext->sub = (char *) 0; /* end of table marker */
404 pauthnext->auth = (char *) 0; /* end of table marker */
405 (*pdatetable)[datepos].msg = msg_to + 1;
406 (*pdatetable)[datepos].date = lastdate + 1;
407}
408
423
424void idx_mkthread(msgentry **pmsgtable,subentry **psubtable,authentry **pauthtable,
425 unsigned long msg_from,unsigned long msg_to,unsigned long msg_master,unsigned long msg_latest,int locked)
426{
427 subentry *psubt; /* points to last entry in subtable */
428 int ffound; /* msg subject was found in subtable */
429 unsigned long idxlatest; /* need to lock for this (last) index file */
430 unsigned long idxto; /* index for last msg in range */
431 unsigned long idx; /* current index file no */
432 unsigned long msg; /* index entry's msg number */
433 unsigned long ulmrange; /* total # of messages in range */
434 int flagauth; /* there is author info */
435 int firstfound = 1; /* = 1 until first message in thread found */
436 int res; /* comparison result */
437 char *auth;
438 unsigned int authlen;
439 authentry *pauthnext; /* points to next entry in authtable */
440 authentry *pautht; /* points to entry in authtable */
441 unsigned int pos;
442 int fd; /* index file handle */
443 int match;
444 msgentry *pmsgt;
445 msgentry *x,*y;
446
447 if ((ulmrange = msg_to - msg_from +1) <= 0)
448 logmsg(WHO,100,FATAL,"Program error: bad range in idx_mkthreads");
449 if (!(*pmsgtable = (msgentry *) alloc(ulmrange * sizeof(msgentry))))
450 die_nomem();
451 y = *pmsgtable;
452 x = y + ulmrange;
453 while (--x >= y) {
454 x->subnum = 0;
455 x->authnum = 0;
456 x->date = 0;
457 }
458
459 if (!(*psubtable = (subentry *) alloc(2 * sizeof(subentry))))
460 die_nomem();
461
462 if (!(*pauthtable = (authentry *) alloc((ulmrange + 1) * sizeof(authentry))))
463 die_nomem();
464
465 pauthnext = *pauthtable;
466 pautht = &adummy;
467 init_dummy();
468 pautht->auth = (char*)" ";
469 pautht->authlen = 21;
470 pautht->higher = (authentry *) 0;
471 pautht->lower = (authentry *) 0;
472 idxlatest = msg_latest / 100;
473 idxto = msg_to / 100;
474 idx = msg_master / 100; /* index for master subject */
475
476 /* Get master subject */
477
478 if (!stralloc_copys(&line,"archive/")) die_nomem();
479 if (!stralloc_catb(&line,strnum,fmt_ulong(strnum,idx))) die_nomem();
480 if (!stralloc_cats(&line,"/index")) die_nomem();
481 if (!stralloc_0(&line)) die_nomem();
482 ffound = 0;
483 if (!locked && idx == idxlatest)
484 lockup();
485 fd = open_read(line.s);
486 psubt = *psubtable;
487 if (fd == -1) {
488 if (errno != ENOENT)
489 logmsg(WHO,111,FATAL,B(ERR_OPEN,line.s));
490 else
491 logmsg(WHO,111,FATAL,ERR_NOINDEX); /* temp - admin can fix! */
492 } else {
493 buffer_init(&bi,buffer_unixread,fd,indexbuf,sizeof(indexbuf));
494
495 for(;;) {
496 if (getln(&bi,&line,&match,'\n') == -1)
497 logmsg(WHO,111,FATAL,B(ERR_OPEN,"index"));
498 if (!match)
499 break;
500 pos=scan_ulong(line.s,&msg);
501 if (line.s[pos++] == ':') { /* marker for author info */
502 pos++;
503 flagauth = 1;
504 } else
505 flagauth = 0;
506 if (msg == msg_master) {
507 newsub(psubt,line.s + pos,line.len - pos,msg);/* need to update msg later! */
508 ffound = 1;
509 break;
510 }
511 if (flagauth) { /* skip author line */
512 if (getln(&bi,&line,&match,'\n') == -1)
513 logmsg(WHO,111,FATAL,B(ERR_OPEN,"index"));
514 if (!match)
515 break;
516 }
517 }
518 close(fd);
519 }
520 if (!locked && idx == idxlatest)
521 unlock();
522 if (!ffound)
523 logmsg(WHO,100,FATAL,ERR_NOINDEX);
524
525 for (idx = msg_from / 100; idx <= idxto; idx++) { /* make index file name */
526 if (!stralloc_copys(&line,"archive/")) die_nomem();
527 if (!stralloc_catb(&line,strnum,fmt_ulong(strnum,idx))) die_nomem();
528 if (!stralloc_cats(&line,"/index")) die_nomem();
529 if (!stralloc_0(&line)) die_nomem();
530 if (!locked && idx == idxlatest)
531 lockup();
532
533 fd = open_read(line.s);
534
535 if (fd == -1) {
536 if (errno != ENOENT)
537 logmsg(WHO,111,FATAL,B(ERR_OPEN,line.s));
538 } else {
539 buffer_init(&bi,buffer_unixread,fd,indexbuf,sizeof(indexbuf));
540
541 for(;;) {
542 if (getln(&bi,&line,&match,'\n') == -1)
543 logmsg(WHO,111,FATAL,B(ERR_READ,"index"));
544 if (!match)
545 break;
546 pos=scan_ulong(line.s,&msg);
547 if (line.s[pos++] == ':') {
548 pos++;
549 flagauth = 1;
550 if (getln(&bi,&authline,&match,'\n') == -1)
551 logmsg(WHO,111,FATAL,B(ERR_READ,"index"));
552 if (!match)
553 break;
554 } else
555 flagauth = 0;
556
557 if (msg < msg_from) continue; /* Nothing before start of range */
558 if (msg > msg_to) break; /* Don't do anything after range */
559
560 if (!str_diffn(psubt->sub,line.s + pos,HASHLEN)) {
561 pmsgt = *pmsgtable + msg - msg_from;
562 if (firstfound) { /* update to first message with this subj */
563 psubt->firstmsg = msg;
564 firstfound = 0;
565 }
566 psubt->lastmsg = msg;
567 pmsgt->subnum = 1;
568 if (flagauth) {
569 if (*authline.s)
570 pmsgt->date = date2yyyymm(authline.s + 1);
571 pos = byte_chr(authline.s,authline.len,';');
572 if (authline.len > pos + HASHLEN + 1 && authline.s[pos+1] != ' ') {
573 /* old: "; auth", new: ";hash auth" */
574 auth = authline.s + pos + 1;
575 authlen = authline.len - pos - 1;
576 } else {
577 auth = dummyind.s;
578 authlen = dummyind.len;
579 }
580
581 for (;;) { /* search among already known authors */
582 res = str_diffn(pautht->auth,auth,HASHLEN);
583 if (res < 0) {
584 if (pautht->higher)
585 pautht = pautht->higher;
586 else {
587 newauth(pauthnext,auth,authlen,msg);
588 pautht->higher = pauthnext;
589 pautht = pauthnext;
590 pauthnext++;
591 break;
592 }
593 } else if (res > 0) {
594 if (pautht->lower)
595 pautht = pautht->lower;
596 else {
597 newauth(pauthnext,auth,authlen,msg);
598 pautht->lower = pauthnext;
599 pautht = pauthnext;
600 pauthnext++;
601 break;
602 }
603 } else {
604 break;
605 }
606 } /* link from message to this author */
607
608 pmsgt->authnum = (unsigned int) (pautht - *pauthtable + 1);
609 pautht = *pauthtable;
610 }
611 }
612 }
613 close(fd);
614 } // finished reading
615
616 if (!locked && idx == idxlatest) unlock();
617 } // outer for loop done
618 ++psubt;
619 psubt->sub = (char *) 0; /* end of table marker */
620 pauthnext->auth = (char *) 0; /* end of table marker */
621}
622
635
636void idx_mklist(msgentry **pmsgtable,subentry **psubtable,authentry **pauthtable,
637 unsigned long msg_from,unsigned long msg_to)
638{
639 unsigned long ulmrange;
640 msgentry *x,*y;
641 subentry *psubt;
642 authentry *pautht;
643
644 if ((ulmrange = msg_to - msg_from +1) <= 0)
645 logmsg(WHO,111,FATAL,"bad range in idx_mkthreads");
646
647 if (!(*pmsgtable = (msgentry *) alloc(ulmrange * sizeof(msgentry))))
648 die_nomem();
649
650 y = *pmsgtable;
651 x = y + ulmrange;
652 while (--x >= y) {
653 x->subnum = 1;
654 x->authnum = 0;
655 x->date = 0;
656 }
657
658 if (!(*psubtable = (subentry *) alloc(2 * sizeof(subentry))))
659 die_nomem();
660 psubt = *psubtable;
661 newsub(psubt,dummyind.s,dummyind.len,msg_from);
662 psubt->lastmsg = msg_to;
663 ++psubt;
664 psubt->sub = (char *) 0;
665 if (!(*pauthtable = (authentry *) alloc(sizeof(authentry))))
666 die_nomem(); /* nodata. Avoid dangling ptr. */
667 pautht = *pauthtable;
668 pautht->auth = 0; /* tells app that there are no author data */
669 pautht->higher = (authentry *) 0;
670 pautht->lower = (authentry *) 0;
671}
672
682
683void idx_destroythread(msgentry *msgtable,subentry *subtable,authentry *authtable)
684{
685 subentry *psubt;
686 authentry *pautht;
687
688 psubt = subtable; /* free subjects */
689 while (psubt->sub) {
690 alloc_free(psubt->sub);
691 psubt++;
692 }
693
694 pautht = authtable; /* free authors */
695 while (pautht->auth) {
696 alloc_free(pautht->auth);
697 pautht++;
698 }
699
700 alloc_free(subtable); /* free subtable */
701 alloc_free(authtable); /* free authtable */
702 alloc_free(msgtable); /* free msgtable */
703 subtable = (subentry *) 0; /* kill pointers */
704 authtable = (authentry *) 0;
705 msgtable = (msgentry *) 0;
706}
Error messages. If you translate these, I would urge you to keep the English version as well....
#define ERR_BAD_INDEX
Definition errtxt.h:64
#define ERR_NOMEM
Definition errtxt.h:14
#define ERR_OPEN
Definition errtxt.h:30
#define ERR_READ
Definition errtxt.h:18
#define ERR_NOINDEX
Definition errtxt.h:63
int lockfile(const char *)
Definition lockfile.c:15
void die_nomem()
Definition getconf.c:17
#define WHO
Definition author.c:1
void unlock()
Definition ezmlm-get.c:179
void lockup()
Definition ezmlm-get.c:169
char indexbuf[1024]
Definition ezmlm-get.c:163
buffer bi
int fdlock
Definition ezmlm-cron.c:71
int fd
Definition ezmlm-cgi.c:141
stralloc author
Definition ezmlm-cgi.c:118
int match
Definition ezmlm-cgi.c:140
stralloc subject
Definition ezmlm-cgi.c:119
void idx_mkthread(msgentry **pmsgtable, subentry **psubtable, authentry **pauthtable, unsigned long msg_from, unsigned long msg_to, unsigned long msg_master, unsigned long msg_latest, int locked)
Definition idxthread.c:424
#define HASHLEN
Definition idxthread.c:25
void idx_destroythread(msgentry *msgtable, subentry *subtable, authentry *authtable)
Definition idxthread.c:683
void idx_mklist(msgentry **pmsgtable, subentry **psubtable, authentry **pauthtable, unsigned long msg_from, unsigned long msg_to)
Definition idxthread.c:636
void idx_mkthreads(msgentry **pmsgtable, subentry **psubtable, authentry **pauthtable, dateentry **pdatetable, unsigned long msg_from, unsigned long msg_to, unsigned long msg_latest, int locked)
Definition idxthread.c:156
#define DATENO
Definition idxthread.c:42
unsigned int date2yyyymm(const char *s)
Definition date2yyyymm.c:18
unsigned int date
Definition idx.h:330
unsigned long authnum
Definition idx.h:329
unsigned long subnum
Definition idx.h:328
void * higher
Definition idx.h:334
unsigned long firstmsg
Definition idx.h:342
char * sub
Definition idx.h:336
unsigned char msginthread
Definition idx.h:344
unsigned long lastmsg
Definition idx.h:343
void * lower
Definition idx.h:335
unsigned int sublen
Definition idx.h:341
void * higher
Definition idx.h:348
unsigned long firstmsg
Definition idx.h:356
unsigned long authlen
Definition idx.h:355
void * lower
Definition idx.h:349
char * auth
Definition idx.h:350
const char * logmsg(const char *dir, unsigned long num, unsigned long listno, unsigned long subs, int done)
Definition loginfo.c:32