[go: up one dir, main page]

File: chkhistory.c

package info (click to toggle)
suck 3.10.1-3
  • links: PTS
  • area: main
  • in suites: slink
  • size: 728 kB
  • ctags: 727
  • sloc: ansic: 8,357; sh: 585; makefile: 212; java: 144; perl: 24
file content (144 lines) | stat: -rw-r--r-- 4,348 bytes parent folder | download
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);
	}
}