1 #include <config.h>
2 
3 /* If we use history databases, then these routines will */
4 /* get compiled and used.  If we don't, the routines in chkhistory.c will */
5 /* be used. */
6 
7 #include <stdio.h>
8 
9 #include "suck_config.h"
10 #include "suck.h"
11 #include "both.h"
12 #include "chkhistory.h"
13 #include "suckutils.h"
14 #include "phrases.h"
15 #include "timer.h"
16 
17 /* These take care if user had multiple defines in makefile */
18 /* use DBM if we've got it */
19 #ifdef USE_DBM
20 #undef USE_GDBM
21 #undef USE_NDBM
22 #undef USE_DBZ
23 #undef USE_INN2
24 #undef USE_INN23
25 #endif
26 /* else if have GDBM use it */
27 #ifdef USE_GDBM
28 #undef USE_NDBM
29 #undef USE_DBZ
30 #undef USE_INN2
31 #undef USE_INN23
32 #endif
33 /* else if have NDBM use it */
34 #ifdef USE_NDBM
35 #undef USE_DBZ
36 #undef USE_INN2
37 #undef USE_INN23
38 #endif
39 /* use DBZ if we have it */
40 #ifdef USE_DBZ
41 #undef USE_INN2
42 #undef USE_INN23
43 #endif
44 /* use INN2 if we have it */
45 #ifdef USE_INN2
46 #undef USE_INN23
47 #endif
48 
49 #ifdef USE_DBM
50 #include <dbm.h>
51 #define close_history() dbmclose();
52 #endif
53 
54 #ifdef USE_GDBM
55 #include <gdbm.h>
56 static GDBM_FILE dbf = NULL;
57 #define close_history() gdbm_close(dbf)
58 #endif
59 
60 #ifdef USE_NDBM
61 #include <ndbm.h>
62 #ifdef HAVE_FCNTL_H
63 #include <fcntl.h>
64 #endif
65 static DBM *db = NULL;	/* I know this isn't too pretty, but its the easiest way to do it */
66 #define close_history() dbm_close(db)
67 #endif
68 
69 #ifdef USE_DBZ
70 #include <dbz.h>
71 #define close_history() dbmclose()
72 #endif
73 
74 #ifdef USE_INN2
75 #include <sys/types.h>
76 #include <configdata.h>
77 #include <clibrary.h>
78 #include <libinn.h>
79 #include <dbz.h>
80 #define close_history() dbzclose()
81 #endif
82 #ifdef USE_INN23
83 #include <sys/types.h>
84 #include <inn/libinn.h>
85 #include <inn/dbz.h>
86 #define close_history() dbzclose()
87 #define USE_INN2    /* we need the rest of the inn2 code, only the includes are different */
88 #endif
89 
90 #ifdef DMALLOC
91 #include <dmalloc.h>
92 #endif
93 
94 
95 /* function prototypes */
96 int open_history(const char *);
97 int  check_history(char *);
98 /*---------------------------------------------------------------------------------------------------*/
chkhistory(PMaster master)99 void chkhistory(PMaster master) {
100 
101 	PList curr, prev;
102 	int nrfound = 0;
103 
104 	if(master->debug == TRUE) {
105 		do_debug("Opening history database: %s\n", master->history_file);
106 	}
107 
108 	if(open_history(master->history_file) != TRUE) {
109 		error_log(ERRLOG_REPORT, chkh_phrases[0], master->history_file, NULL);
110 	}
111 	else {
112 
113 		print_phrases(master->msgs, chkh_phrases[5], NULL);
114 		fflush(master->msgs);	/* so msg gets printed */
115 		TimerFunc(TIMER_START, 0L, NULL);
116 
117 		/* okay cycle thru our list, checking each against the history DB */
118 		curr = master->head;
119 		prev = NULL;
120 
121 		while(curr != NULL ) {
122 			if(check_history(curr->msgnr) == TRUE) {
123 				if(master->debug == TRUE) {
124 					do_debug("Matched %s, nuking\n", curr->msgnr);
125 				}
126 				/* matched, nuke it */
127 				nrfound++;
128 				master->nritems--;
129 				if(prev == NULL) {
130 					/* remove master node */
131 					master->head = curr->next;
132 					free_one_node(curr);
133 					curr = master->head;	/* next node to check */
134 				}
135 				else {
136 					prev->next = curr->next;
137 					free_one_node(curr);
138 					curr = prev->next;	/* next node to check */
139 				}
140 			}
141 			else {
142 				if(master->debug == TRUE) {
143 					do_debug("Didn't match %s\n", curr->msgnr);
144 				}
145 				/* next node to check */
146 				prev = curr;
147 				curr = curr->next;
148 			}
149 		}
150 		TimerFunc(TIMER_TIMEONLY, 0l, master->msgs);
151 
152 		close_history();
153 		print_phrases(master->msgs, chkh_phrases[3], str_int(nrfound), NULL);
154 	}
155 	return;
156 }
157 /*------------------------------------------------------------------------*/
open_history(const char * history_file)158 int open_history(const char *history_file) {
159 
160 	int retval = FALSE;
161 
162 #if defined (USE_DBM) || defined (USE_DBZ)
163 
164 	if(dbminit(history_file) >= 0) {
165 		retval = TRUE;
166 	}
167 #endif
168 
169 #if defined (USE_INN2)
170 	/* first, set our options */
171 	dbzoptions opt;
172 
173 #ifdef DO_TAGGED_HASH
174 	opt.pag_incore=INCORE_MEM;
175 #else
176 #ifndef USE_INN23
177 	opt.idx_incore=INCORE_MEM;  /* per man page speeds things up, inn-2.3 doesn't need this */
178 #endif
179 #endif
180 	opt.exists_incore=INCORE_MEM;
181 	dbzsetoptions(opt);
182 	retval = dbzinit(history_file);
183 #endif
184 
185 #if defined (USE_NDBM)
186 	if((db = dbm_open(history_file, O_RDONLY, 0)) != NULL) {
187 		retval = TRUE;
188 	}
189 #endif
190 #if defined(USE_GDBM)
191 	if((dbf = gdbm_open(history_file, 1024, GDBM_READER,0,0)) != NULL) {
192 		retval = TRUE;
193 	}
194 #endif
195 
196 	return retval;
197 }
198 /*----------------------------------------------------------------*/
check_history(char * msgid)199 int check_history(char *msgid) {
200 
201 #if defined (USE_DBM) || defined (USE_DBZ) || defined (USE_NDBM)
202 	datum input, result;
203 
204 	input.dptr = msgid;
205 	input.dsize = strlen(msgid) +1;
206 
207 #if defined (USE_DBM)
208 
209 	result = fetch(input);
210 
211 #elif defined (USE_DBZ)
212 
213 	result = dbzfetch(input);
214 
215 #elif defined (USE_NDBM)
216 
217 	result = dbm_fetch(db, input);
218 
219 #endif
220 
221 	return (result.dptr != NULL) ? TRUE : FALSE;
222 #endif /* big if defined */
223 
224 #if defined (USE_INN2)
225 	HASH msgid_hash;
226 
227 	msgid_hash=HashMessageID(msgid);	/* have to hash it first */
228 	return dbzexists(msgid_hash);
229 
230 #endif
231 #if defined(USE_GDBM)
232 	datum input;
233 
234 	input.dptr = msgid;
235 	input.dsize = strlen(msgid)+1;
236 
237 	return gdbm_exists(dbf, input);
238 #endif
239 }
240