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