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