1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
#include <config.h>
/* If we don't use history databases, then these routines will */
/* get compiled and used. If we do, the routines in chkhistory_db.c will */
/* be used. */
#include <stdio.h>
#include <string.h>
#include "suck_config.h"
#include "suck.h"
#include "both.h"
#include "chkhistory.h"
#include "suckutils.h"
#include "phrases.h"
#include "timer.h"
/*---------------------------------------------------------------------------------------------------------------*/
/* In order to not check the entire linked list every time, let's try something different */
/* We'll build an array of pointers to the linked list, based on the first character of the article id */
/* then we only have to check the article ids that match the first character, saving searching thru the list */
/*---------------------------------------------------------------------------------------------------------------*/
#include <stdlib.h>
#define NR_LETTERS 128 /* nr of chars indexed, only 128 since rfc doesn't support > 128 */
void chkhistory(PMaster master) {
FILE *fhist;
char linein[MAXLINLEN+1], *ptr;
int i, j, x, found, nrfound = 0;
PList curr, prev, *lets;
long tlet[NR_LETTERS];
struct {
long nr;
long start;
} letters[NR_LETTERS];
if((fhist = fopen(HISTORY_FILE, "r")) == NULL) {
error_log(ERRLOG_REPORT, chkh_phrases[0], HISTORY_FILE, NULL);
}
else {
print_phrases(master->msgs, chkh_phrases[1], NULL);
fflush(master->msgs); /* so msg gets printed */
TimerFunc(TIMER_START, 0L, NULL);
/* pass one */
/* count the letters, so we can build the array and also index it */
/* initialize the arrays */
for(i=0;i<NR_LETTERS;i++) {
letters[i].nr = letters[i].start = tlet[i] = 0;
}
curr = master->head;
while(curr != NULL) {
letters[((curr->msgnr[1]) % NR_LETTERS)].nr++;
/* the % is in case a wacko article id slips by */
curr = curr->next;
}
/* now build the array with the starting points for each */
/* nr 0 starts on zero so skip it */
for(i=1;i<NR_LETTERS;i++) {
letters[i].start = letters[i-1].start + letters[i-1].nr;
}
/* pass two */
/* first malloc the array */
if ((lets = (PList *) calloc(master->nritems, sizeof(PList))) == NULL) {
error_log(ERRLOG_REPORT, chkh_phrases[4], NULL);
}
else {
/* now put them in place */
curr = master->head;
while(curr != NULL) {
j = (curr->msgnr[1]) % NR_LETTERS;
i = letters[j].start + tlet[j];
tlet[j]++; /* so go to next slot */
lets[i] = curr;
curr = curr->next;
}
/* pass three */
/* now we can read history file and check against first letter only */
/* history file can have two valid types of lines */
/* the ones we are interested in is the ones that start with < */
/* we ignore the ones that start with [ and report the rest */
while(fgets(linein, MAXLINLEN, fhist) != NULL) {
if(linein[0] == '<') {
j = (linein[1]) % NR_LETTERS;
if((ptr = strchr(linein, '>')) == NULL) {
error_log(ERRLOG_REPORT, chkh_phrases[2], linein, NULL);
}
else {
*(ptr+1) = '\0';
/* now that we've isolated the article nr, search our list */
found = FALSE;
for(i=0;i<letters[j].nr && found == FALSE;i++) {
x = letters[j].start+i;
if(lets[x] != NULL && cmp_msgid(linein, lets[x]->msgnr)==TRUE) {
nrfound++;
found = TRUE;
/* now flag it for deletion */
lets[x]->msgnr[0] = '\0'; /* no more article nr */
lets[x] = NULL; /* so don't check it again */
}
}
}
}
else if(linein[0] != '[') {
error_log(ERRLOG_REPORT, chkh_phrases[2], linein, NULL);
}
}
/* pass four */
/* now go thru and delete em */
curr = master->head;
prev = NULL;
while(curr != NULL) {
if( curr->msgnr[0] == '\0') {
/* nuke it */
master->nritems--;
if(prev == NULL) {
/* remove master node */
master->head = curr->next;
free_one_node(curr);
curr = master->head;
}
else {
prev->next = curr->next;
free_one_node(curr);
curr = prev->next;
}
}
else {
prev = curr;
curr = curr->next;
}
}
free(lets);
}
TimerFunc(TIMER_TIMEONLY, 0l, master->msgs);
fclose(fhist);
print_phrases(master->msgs, chkh_phrases[3], str_int(nrfound), NULL);
}
}
|