1 #include <config.h>
2
3 /* If we don't use history databases, then these routines will */
4 /* get compiled and used. If we do, the routines in chkhistory_db.c will */
5 /* be used. */
6
7 #include <stdio.h>
8 #include <string.h>
9 #include <stdlib.h>
10
11 #ifdef DMALLOC
12 #include <dmalloc.h>
13 #endif
14
15 #include "suck_config.h"
16 #include "suck.h"
17 #include "both.h"
18 #include "chkhistory.h"
19 #include "suckutils.h"
20 #include "phrases.h"
21 #include "timer.h"
22 #include "ssort.h"
23
24 /* this is almost a duplicate of dedupe_list() */
25 /* put items in array, qsort it, then work thru history file, and use bsearch to match em */
chkhistory(PMaster master)26 void chkhistory(PMaster master) {
27 FILE *fhist;
28 PList *array, ptr, curr, prev, tptr;
29 int nrin=0, nrfound=0;
30 long valinhist = 0, nrinhist = 0;
31 char *cptr, linein[MAXLINLEN+1];
32
33 if((fhist = fopen(master->history_file, "r")) == NULL) {
34 MyPerror(master->history_file);
35 }
36 else {
37 if(master->debug == TRUE) {
38 do_debug("Chking %d master->nritems\nReading history file - %s\n",
39 master->nritems, master->history_file);
40 }
41 print_phrases(master->msgs, chkh_phrases[1], NULL);
42 fflush(master->msgs); /* so msg gets printed */
43
44 TimerFunc(TIMER_START, 0L, NULL);
45
46 /* 1. throw em into the array */
47 if((array = calloc(master->nritems, sizeof(PList))) == NULL) {
48 error_log(ERRLOG_REPORT, chkh_phrases[4], NULL);
49 }
50 else {
51 ptr = master->head;
52 nrin = 0;
53 while(ptr != NULL) {
54 array[nrin] = ptr;
55 nrin++;
56 ptr = ptr->next;
57 }
58 if(master->debug == TRUE) {
59 do_debug("Added %d items to array for ssort, master->nritems = %d\n", nrin, master->nritems);
60 }
61 /* step 2, sort em */
62 ssort(array, nrin, 1); /* start with depth of 1 cause all start with < */
63
64 /* step 3, find and mark dupes */
65 /* history file can have two valid types of lines */
66 /* the ones we are interested in is the ones that start with < */
67 /* we ignore the ones that start with [ and report the rest */
68 while(fgets(linein, MAXLINLEN, fhist) != NULL) {
69 nrinhist++;
70 if(linein[0] == '<') {
71 /* make sure we have valid msgid and null terminate it */
72 if((cptr = strchr(linein, '>')) == NULL) {
73 error_log(ERRLOG_REPORT, chkh_phrases[2], linein, NULL);
74 }
75 else {
76 valinhist++;
77 *(cptr+1) = '\0';
78 if((tptr = my_bsearch(array, linein, nrin)) != NULL) {
79 /* found in our array flag for deletion */
80 /* it returns a PList * */
81 tptr->delete = TRUE;
82 nrfound++;
83 }
84 }
85 }
86 }
87 if(ferror(fhist) != 0) {
88 error_log(ERRLOG_REPORT, chkh_phrases[6], master->history_file, NULL);
89 clearerr(fhist);
90 }
91
92 if(master->debug == TRUE) {
93 do_debug("%d lines in history, %d valid lines, %d duplicates found\n", nrinhist, valinhist, nrfound);
94 }
95 /* step 4, delete em */
96 curr = master->head;
97 prev = NULL;
98 while(curr != NULL) {
99 if( curr->delete == TRUE) {
100 /* nuke it */
101 master->nritems--;
102 if(prev == NULL) {
103 /* remove master node */
104 master->head = curr->next;
105 free_one_node(curr);
106 curr = master->head;
107 }
108 else {
109 prev->next = curr->next;
110 free_one_node(curr);
111 curr = prev->next;
112 }
113 }
114 else {
115 prev = curr;
116 curr = curr->next;
117 }
118 }
119
120 /* all done free up mem */
121 free(array);
122 }
123 fclose(fhist);
124 TimerFunc(TIMER_TIMEONLY, 0l, master->msgs);
125 print_phrases(master->msgs, chkh_phrases[3], str_int(nrfound), NULL);
126 }
127 }
128
129