Browse code

* libclamav: introduce new API calls for engine management (THIS REVISION IS NOT BACKWARD COMPATIBLE): cl_init(), cl_engine_new(), cl_engine_set/get(), cl_engine_compile(), cl_engine_dup(), cl_engine_free(); make minor modifications to other calls; move cl_engine to others.h; integrate limits into cl_engine * clamd, clamscan: use new API; drop hardcoded default limits and depend on those set by libclamav * clamav-milter, unit_tests: TODO, **don't compile in this rev**

git-svn: trunk@4385

Tomasz Kojm authored on 2008/11/13 01:41:18
Showing 27 changed files
... ...
@@ -1,3 +1,14 @@
1
+Wed Nov 12 16:31:34 CET 2008 (tk)
2
+---------------------------------
3
+ * libclamav: introduce new API calls for engine management (THIS REVISION IS
4
+	      NOT BACKWARD COMPATIBLE): cl_init(), cl_engine_new(),
5
+	      cl_engine_set/get(), cl_engine_compile(), cl_engine_dup(),
6
+	      cl_engine_free(); make minor modifications to other calls;
7
+	      move cl_engine to others.h; integrate limits into cl_engine
8
+ * clamd, clamscan: use new API; drop hardcoded default limits and depend on
9
+		    those set by libclamav
10
+ * clamav-milter, unit_tests: TODO, **don't compile in this rev**
11
+
1 12
 Wed Nov 12 13:06:33 EET 2008 (edwin)
2 13
 ------------------------------------
3 14
  * contrib/clamdtop/Makefile, contrib/clamdtop/TODO,
... ...
@@ -96,7 +96,7 @@ int main(int argc, char **argv)
96 96
         struct passwd *user = NULL;
97 97
 #endif
98 98
 	time_t currtime;
99
-	struct cl_engine *engine = NULL;
99
+	struct cl_engine *engine;
100 100
 	const char *dbdir, *cfgfile;
101 101
 	char *pua_cats = NULL;
102 102
 	int ret, tcpsock = 0, localsock = 0, i;
... ...
@@ -223,9 +223,6 @@ int main(int argc, char **argv)
223 223
     logg_size = cfgopt(copt, "LogFileMaxSize")->numarg;
224 224
     logg_verbose = mprintf_verbose = cfgopt(copt, "LogVerbose")->enabled;
225 225
 
226
-    if(cfgopt(copt, "Debug")->enabled) /* enable debug messages in libclamav */
227
-	cl_debug();
228
-
229 226
     if((cpt = cfgopt(copt, "LogFile"))->enabled) {
230 227
 	char timestr[32];
231 228
 	logg_file = cpt->strarg;
... ...
@@ -245,6 +242,16 @@ int main(int argc, char **argv)
245 245
     } else
246 246
 	logg_file = NULL;
247 247
 
248
+    if((ret = cl_init(CL_INIT_DEFAULT))) {
249
+	logg("!Can't initialize libclamav: %s\n", cl_strerror(ret));
250
+	logg_close();
251
+	freecfg(copt);
252
+	return 1;
253
+    }
254
+
255
+    if(cfgopt(copt, "Debug")->enabled) /* enable debug messages in libclamav */
256
+	cl_debug();
257
+
248 258
 #if defined(USE_SYSLOG) && !defined(C_AIX)
249 259
     if(cfgopt(copt, "LogSyslog")->enabled) {
250 260
 	    int fac = LOG_LOCAL6;
... ...
@@ -302,6 +309,13 @@ int main(int argc, char **argv)
302 302
     else
303 303
 	logg("#Log file size limit disabled.\n");
304 304
 
305
+    if(!(engine = cl_engine_new(CL_ENGINE_DEFAULT))) {
306
+	logg("!Can't initialize antivirus engine\n");
307
+	logg_close();
308
+	freecfg(copt);
309
+	return 1;
310
+    }
311
+
305 312
     /* load the database(s) */
306 313
     dbdir = cfgopt(copt, "DatabaseDirectory")->strarg;
307 314
     logg("#Reading databases from %s\n", dbdir);
... ...
@@ -318,6 +332,7 @@ int main(int argc, char **argv)
318 318
 		    logg("!Can't allocate memory for pua_cats\n");
319 319
 		    logg_close();
320 320
 		    freecfg(copt);
321
+		    cl_engine_free(engine);
321 322
 		    return 1;
322 323
 		}
323 324
 		logg("# %s", cpt->strarg);
... ...
@@ -337,6 +352,7 @@ int main(int argc, char **argv)
337 337
 		logg_close();
338 338
 		freecfg(copt);
339 339
 		free(pua_cats);
340
+		cl_engine_free(engine);
340 341
 		return 1;
341 342
 	    }
342 343
 	    dboptions |= CL_DB_PUA_INCLUDE;
... ...
@@ -361,15 +377,15 @@ int main(int argc, char **argv)
361 361
 	}
362 362
 
363 363
 	if(pua_cats) {
364
-	    /* FIXME with the new API */
365
-	    if((ret = cli_initengine(&engine, dboptions))) {
366
-		logg("!cli_initengine() failed: %s\n", cl_strerror(ret));
364
+	    if((ret = cl_engine_set(engine, CL_ENGINE_PUA_CATEGORIES, pua_cats))) {
365
+		logg("!cli_engine_set(CL_ENGINE_PUA_CATEGORIES) failed: %s\n", cl_strerror(ret));
367 366
 		logg_close();
368 367
 		freecfg(copt);
369 368
 		free(pua_cats);
369
+		cl_engine_free(engine);
370 370
 		return 1;
371 371
 	    }
372
-	    engine->pua_cats = pua_cats;
372
+	    free(pua_cats);
373 373
 	}
374 374
     } else {
375 375
 	logg("#Not loading PUA signatures.\n");
... ...
@@ -395,25 +411,20 @@ int main(int argc, char **argv)
395 395
 	logg("#Max A-C depth set to %u\n", cpt->numarg);
396 396
     }
397 397
 
398
-    if((ret = cl_load(dbdir, &engine, &sigs, dboptions))) {
398
+    if((ret = cl_load(dbdir, engine, &sigs, dboptions))) {
399 399
 	logg("!%s\n", cl_strerror(ret));
400 400
 	logg_close();
401 401
 	freecfg(copt);
402
-	return 1;
403
-    }
404
-
405
-    if(!engine) {
406
-	logg("!Database initialization error.\n");
407
-	logg_close();
408
-	freecfg(copt);
402
+	cl_engine_free(engine);
409 403
 	return 1;
410 404
     }
411 405
 
412 406
     logg("#Loaded %u signatures.\n", sigs);
413
-    if((ret = cl_build(engine)) != 0) {
414
-	logg("!Database initialization error: %s\n", cl_strerror(ret));;
407
+    if((ret = cl_engine_compile(engine)) != 0) {
408
+	logg("!Database initialization error: %s\n", cl_strerror(ret));
415 409
 	logg_close();
416 410
 	freecfg(copt);
411
+	cl_engine_free(engine);
417 412
 	return 1;
418 413
     }
419 414
 
... ...
@@ -425,6 +436,7 @@ int main(int argc, char **argv)
425 425
 	    logg("!Error at WSAStartup(): %d\n", WSAGetLastError());
426 426
 	    logg_close();
427 427
 	    freecfg(copt);
428
+	    cl_engine_free(engine);
428 429
 	    return 1;
429 430
 	}
430 431
 #endif
... ...
@@ -432,6 +444,7 @@ int main(int argc, char **argv)
432 432
 	if(lsockets[nlsockets] == -1) {
433 433
 	    logg_close();
434 434
 	    freecfg(copt);
435
+	    cl_engine_free(engine);
435 436
 	    return 1;
436 437
 	}
437 438
 	nlsockets++;
... ...
@@ -444,6 +457,7 @@ int main(int argc, char **argv)
444 444
 	    freecfg(copt);
445 445
 	    if(tcpsock)
446 446
 		closesocket(lsockets[0]);
447
+	    cl_engine_free(engine);
447 448
 	    return 1;
448 449
 	}
449 450
 	nlsockets++;
... ...
@@ -461,6 +475,7 @@ int main(int argc, char **argv)
461 461
 	    logg("!daemonize() failed\n");
462 462
 	    logg_close();
463 463
 	    freecfg(copt);
464
+	    cl_engine_free(engine);
464 465
 	    return 1;
465 466
 	}
466 467
 #ifdef C_BSD
... ...
@@ -175,7 +175,7 @@ void *clamukoth(void *arg)
175 175
 		}
176 176
 	    }
177 177
 
178
-	    if(scan && cl_scanfile(acc->filename, &virname, NULL, tharg->engine, tharg->limits, tharg->options) == CL_VIRUS) {
178
+	    if(scan && cl_scanfile(acc->filename, &virname, NULL, tharg->engine, tharg->options) == CL_VIRUS) {
179 179
 		logg("Clamuko: %s: %s FOUND\n", acc->filename, virname);
180 180
 		virusaction(acc->filename, virname, tharg->copt);
181 181
 		acc->deny = 1;
... ...
@@ -82,7 +82,6 @@ struct multi_tag {
82 82
     const struct cfgstruct *copt;
83 83
     char *fname;
84 84
     const struct cl_engine *engine;
85
-    const struct cl_limits *limits;
86 85
 };
87 86
 
88 87
 static int checksymlink(const char *path)
... ...
@@ -101,7 +100,7 @@ static int checksymlink(const char *path)
101 101
     return 0;
102 102
 }
103 103
 
104
-static int dirscan(const char *dirname, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, const struct cfgstruct *copt, int odesc, unsigned int *reclev, unsigned int type, threadpool_t *multi_pool)
104
+static int dirscan(const char *dirname, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int options, const struct cfgstruct *copt, int odesc, unsigned int *reclev, unsigned int type, threadpool_t *multi_pool)
105 105
 {
106 106
 	DIR *dd;
107 107
 	struct dirent *dent;
... ...
@@ -174,7 +173,7 @@ static int dirscan(const char *dirname, const char **virname, unsigned long int
174 174
 		    /* stat the file */
175 175
 		    if(lstat(fname, &statbuf) != -1) {
176 176
 			if((S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)) || (S_ISLNK(statbuf.st_mode) && (checksymlink(fname) == 1) && cfgopt(copt, "FollowDirectorySymlinks")->enabled)) {
177
-			    if(dirscan(fname, virname, scanned, engine, limits, options, copt, odesc, reclev, type, multi_pool) == 1) {
177
+			    if(dirscan(fname, virname, scanned, engine, options, copt, odesc, reclev, type, multi_pool) == 1) {
178 178
 				free(fname);
179 179
 				closedir(dd);
180 180
 				return 1;
... ...
@@ -203,7 +202,6 @@ static int dirscan(const char *dirname, const char **virname, unsigned long int
203 203
 					scandata->copt = copt;
204 204
 					scandata->fname = fname;
205 205
 					scandata->engine = engine;
206
-					scandata->limits = limits;
207 206
 					if(!thrmgr_dispatch(multi_pool, scandata)) {
208 207
 					    logg("!thread dispatch failed for multi_pool (file %s)\n", fname);
209 208
 					    mdprintf(odesc, "ERROR: Can't scan file %s\n", fname);
... ...
@@ -221,7 +219,7 @@ static int dirscan(const char *dirname, const char **virname, unsigned long int
221 221
 
222 222
 				    } else { /* CONTSCAN, SCAN */
223 223
 					thrmgr_setactivetask(fname, NULL);
224
-					scanret = cl_scanfile(fname, virname, scanned, engine, limits, options);
224
+					scanret = cl_scanfile(fname, virname, scanned, engine, options);
225 225
 					thrmgr_setactivetask(NULL, NULL);
226 226
 
227 227
 					if(scanret == CL_VIRUS) {
... ...
@@ -288,7 +286,7 @@ static void multiscanfile(void *arg)
288 288
 #endif
289 289
 
290 290
     thrmgr_setactivetask(tag->fname, "MULTISCANFILE");
291
-    ret = cl_scanfile(tag->fname, &virname, NULL, tag->engine, tag->limits, tag->options);
291
+    ret = cl_scanfile(tag->fname, &virname, NULL, tag->engine, tag->options);
292 292
     thrmgr_setactivetask(NULL, NULL);
293 293
 
294 294
     if(ret == CL_VIRUS) {
... ...
@@ -307,7 +305,7 @@ static void multiscanfile(void *arg)
307 307
     return;
308 308
 }
309 309
 
310
-int scan(const char *filename, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, const struct cfgstruct *copt, int odesc, unsigned int type)
310
+int scan(const char *filename, unsigned long int *scanned, const struct cl_engine *engine, unsigned int options, const struct cfgstruct *copt, int odesc, unsigned int type)
311 311
 {
312 312
 	struct stat sb;
313 313
 	int ret = 0;
... ...
@@ -355,7 +353,7 @@ int scan(const char *filename, unsigned long int *scanned, const struct cl_engin
355 355
 #endif
356 356
 	    {
357 357
 		thrmgr_setactivetask(filename, NULL);
358
-		ret = cl_scanfile(filename, &virname, scanned, engine, limits, options);
358
+		ret = cl_scanfile(filename, &virname, scanned, engine, options);
359 359
 		thrmgr_setactivetask(NULL, NULL);
360 360
 	    }
361 361
 
... ...
@@ -384,7 +382,7 @@ int scan(const char *filename, unsigned long int *scanned, const struct cl_engin
384 384
 		}
385 385
 	    }
386 386
 
387
-	    ret = dirscan(filename, &virname, scanned, engine, limits, options, copt, odesc, &reclev, type, multi_pool);
387
+	    ret = dirscan(filename, &virname, scanned, engine, options, copt, odesc, &reclev, type, multi_pool);
388 388
 
389 389
 	    if(multi_pool)
390 390
 		thrmgr_destroy(multi_pool);
... ...
@@ -407,7 +405,7 @@ int scan(const char *filename, unsigned long int *scanned, const struct cl_engin
407 407
  * why it is so nicely formatted.
408 408
  */
409 409
 int scanfd(const int fd, unsigned long int *scanned,
410
-    const struct cl_engine *engine, const struct cl_limits *limits,
410
+    const struct cl_engine *engine,
411 411
     unsigned int options, const struct cfgstruct *copt, int odesc)  
412 412
 {
413 413
 	int ret;
... ...
@@ -425,7 +423,7 @@ int scanfd(const int fd, unsigned long int *scanned,
425 425
 	snprintf(fdstr, sizeof(fdstr), "fd[%d]", fd);
426 426
 
427 427
 	thrmgr_setactivetask(fdstr, NULL);
428
-	ret = cl_scandesc(fd, &virname, scanned, engine, limits, options);
428
+	ret = cl_scandesc(fd, &virname, scanned, engine, options);
429 429
 	thrmgr_setactivetask(NULL, NULL);
430 430
 
431 431
 	if(ret == CL_VIRUS) {
... ...
@@ -443,7 +441,7 @@ int scanfd(const int fd, unsigned long int *scanned,
443 443
 	return ret;
444 444
 }
445 445
 
446
-int scanstream(int odesc, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, const struct cfgstruct *copt)
446
+int scanstream(int odesc, unsigned long int *scanned, const struct cl_engine *engine, unsigned int options, const struct cfgstruct *copt)
447 447
 {
448 448
 	int ret, sockfd, acceptd;
449 449
 	int tmpd, bread, retval, timeout, btread;
... ...
@@ -604,7 +602,7 @@ int scanstream(int odesc, unsigned long int *scanned, const struct cl_engine *en
604 604
     if(retval == 1) {
605 605
 	lseek(tmpd, 0, SEEK_SET);
606 606
 	thrmgr_setactivetask(peer_addr, NULL);
607
-	ret = cl_scandesc(tmpd, &virname, scanned, engine, limits, options);
607
+	ret = cl_scandesc(tmpd, &virname, scanned, engine, options);
608 608
 	thrmgr_setactivetask(NULL, NULL);
609 609
     } else {
610 610
     	ret = -1;
... ...
@@ -26,10 +26,10 @@
26 26
 #include "libclamav/clamav.h"
27 27
 #include "shared/cfgparser.h"
28 28
 
29
-int scan(const char *filename, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, const struct cfgstruct *copt, int odesc, unsigned int type);
29
+int scan(const char *filename, unsigned long int *scanned, const struct cl_engine *engine, unsigned int options, const struct cfgstruct *copt, int odesc, unsigned int type);
30 30
 
31
-int scanfd(const int fd, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, const struct cfgstruct *copt, int odesc);
31
+int scanfd(const int fd, unsigned long int *scanned, const struct cl_engine *engine, unsigned int options, const struct cfgstruct *copt, int odesc);
32 32
 
33
-int scanstream(int odesc, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, const struct cfgstruct *copt);
33
+int scanstream(int odesc, unsigned long int *scanned, const struct cl_engine *engine, unsigned int options, const struct cfgstruct *copt);
34 34
 
35 35
 #endif
... ...
@@ -54,6 +54,7 @@
54 54
 #include "shared.h"
55 55
 #include "libclamav/others.h"
56 56
 #include "libclamav/readdb.h"
57
+#include "libclamav/cltypes.h"
57 58
 
58 59
 #ifndef	C_WINDOWS
59 60
 #define	closesocket(s)	close(s)
... ...
@@ -81,7 +82,6 @@ typedef struct client_conn_tag {
81 81
     const struct cfgstruct *copt;
82 82
     struct cl_engine *engine;
83 83
     time_t engine_timestamp;
84
-    const struct cl_limits *limits;
85 84
     int *socketds;
86 85
     int nsockets;
87 86
 } client_conn_t;
... ...
@@ -114,7 +114,7 @@ static void scanner_thread(void *arg)
114 114
     	timeout = -1;
115 115
 
116 116
     do {
117
-    	ret = command(conn->sd, conn->engine, conn->limits, conn->options, conn->copt, timeout);
117
+    	ret = command(conn->sd, conn->engine, conn->options, conn->copt, timeout);
118 118
 	if (ret < 0) {
119 119
 		break;
120 120
 	}
... ...
@@ -161,7 +161,7 @@ static void scanner_thread(void *arg)
161 161
     shutdown(conn->sd, 2);
162 162
     closesocket(conn->sd);
163 163
     thrmgr_setactiveengine(NULL);
164
-    cl_free(conn->engine);
164
+    cl_engine_free(conn->engine);
165 165
     free(conn);
166 166
     return;
167 167
 }
... ...
@@ -196,8 +196,9 @@ static struct cl_engine *reload_db(struct cl_engine *engine, unsigned int dbopti
196 196
 	const char *dbdir;
197 197
 	int retval;
198 198
 	unsigned int sigs = 0;
199
-	char *pua_cats = NULL;
199
+	char pua_cats[128];
200 200
 
201
+    pua_cats[0] = 0;
201 202
     *ret = 0;
202 203
     if(do_check) {
203 204
 	if(dbstat == NULL) {
... ...
@@ -237,45 +238,38 @@ static struct cl_engine *reload_db(struct cl_engine *engine, unsigned int dbopti
237 237
 
238 238
     /* release old structure */
239 239
     if(engine) {
240
-	if(engine->pua_cats)
241
-	    if(!(pua_cats = strdup(engine->pua_cats)))
240
+	if(dboptions & (CL_DB_PUA_INCLUDE | CL_DB_PUA_EXCLUDE))
241
+	    if(cl_engine_get(engine, CL_ENGINE_PUA_CATEGORIES, pua_cats))
242 242
 		logg("^Can't make a copy of pua_cats\n");
243 243
 
244 244
 	thrmgr_setactiveengine(NULL);
245
-	cl_free(engine);
246
-	engine = NULL;
245
+	cl_engine_free(engine);
247 246
     }
248 247
 
249
-    if(pua_cats) {
250
-	if((retval = cli_initengine(&engine, dboptions))) {
251
-	    logg("!cli_initengine() failed: %s\n", cl_strerror(retval));
252
-	    *ret = 1;
253
-	    free(pua_cats);
254
-	    return NULL;
255
-	}
256
-	engine->pua_cats = pua_cats;
257
-    }
258
-
259
-    if((retval = cl_load(dbdir, &engine, &sigs, dboptions))) {
260
-	logg("!reload db failed: %s\n", cl_strerror(retval));
248
+    if(!(engine = cl_engine_new(CL_ENGINE_DEFAULT))) {
249
+	logg("!Can't initialize antivirus engine\n");
261 250
 	*ret = 1;
262 251
 	return NULL;
263 252
     }
264 253
 
265
-    if(retval) {
266
-	logg("!reload db failed: %s\n", cl_strerror(retval));
254
+    if(strlen(pua_cats)) {
255
+	if((retval = cl_engine_set(engine, CL_ENGINE_PUA_CATEGORIES, pua_cats)))
256
+	    logg("!cl_engine_set(CL_ENGINE_PUA_CATEGORIES): %s\n", cl_strerror(retval));
257
+	cl_engine_free(engine);
267 258
 	*ret = 1;
268 259
 	return NULL;
269 260
     }
270 261
 
271
-    if(!engine) {
262
+    if((retval = cl_load(dbdir, engine, &sigs, dboptions))) {
272 263
 	logg("!reload db failed: %s\n", cl_strerror(retval));
264
+	cl_engine_free(engine);
273 265
 	*ret = 1;
274 266
 	return NULL;
275 267
     }
276 268
 
277
-    if((retval = cl_build(engine)) != 0) {
278
-	logg("!Database initialization error: can't build engine: %s\n", cl_strerror(retval));
269
+    if((retval = cl_engine_compile(engine)) != 0) {
270
+	logg("!Database initialization error: can't compile engine: %s\n", cl_strerror(retval));
271
+	cl_engine_free(engine);
279 272
 	*ret = 1;
280 273
 	return NULL;
281 274
     }
... ...
@@ -297,7 +291,6 @@ int acceptloop_th(int *socketds, int nsockets, struct cl_engine *engine, unsigne
297 297
 	struct rlimit rlim;
298 298
 #endif
299 299
 	mode_t old_umask;
300
-	struct cl_limits limits;
301 300
 	client_conn_t *client_conn;
302 301
 	const struct cfgstruct *cpt;
303 302
 #ifdef HAVE_STRERROR_R
... ...
@@ -307,6 +300,8 @@ int acceptloop_th(int *socketds, int nsockets, struct cl_engine *engine, unsigne
307 307
 	time_t start_time, current_time;
308 308
 	pid_t mainpid;
309 309
 	int idletimeout;
310
+	uint32_t val32;
311
+	uint64_t val64;
310 312
 
311 313
 #ifdef CLAMUKO
312 314
 	pthread_t clamuko_pid;
... ...
@@ -318,73 +313,81 @@ int acceptloop_th(int *socketds, int nsockets, struct cl_engine *engine, unsigne
318 318
 	memset(&sigact, 0, sizeof(struct sigaction));
319 319
 #endif
320 320
 
321
-    /* save the PID */
322
-    mainpid = getpid();
323
-    if((cpt = cfgopt(copt, "PidFile"))->enabled) {
324
-	    FILE *fd;
325
-	old_umask = umask(0006);
326
-	if((fd = fopen(cpt->strarg, "w")) == NULL) {
327
-	    logg("!Can't save PID in file %s\n", cpt->strarg);
328
-	} else {
329
-	    if (fprintf(fd, "%u", (unsigned int) mainpid)<0) {
330
-	    	logg("!Can't save PID in file %s\n", cpt->strarg);
331
-	    }
332
-	    fclose(fd);
321
+    /* set up limits */
322
+    if((cpt = cfgopt(copt, "MaxScanSize"))->enabled) {
323
+	val64 = cpt->numarg;
324
+	if((ret = cl_engine_set(engine, CL_ENGINE_MAX_SCANSIZE, &val64))) {
325
+	    logg("!cli_engine_set(CL_ENGINE_MAX_SCANSIZE) failed: %s\n", cl_strerror(ret));
326
+	    cl_engine_free(engine);
327
+	    return 1;
333 328
 	}
334
-	umask(old_umask);
335 329
     }
336
-
337
-    logg("*Listening daemon: PID: %u\n", (unsigned int) mainpid);
338
-    max_threads = cfgopt(copt, "MaxThreads")->numarg;
339
-
340
-
341
-    memset(&limits, 0, sizeof(struct cl_limits));
342
-
343
-    if((limits.maxscansize = cfgopt(copt, "MaxScanSize")->numarg)) {
344
-    	logg("Limits: Global size limit set to %lu bytes.\n", limits.maxscansize);
345
-    } else {
330
+    cl_engine_get(engine, CL_ENGINE_MAX_SCANSIZE, &val64);
331
+    if(val64)
332
+    	logg("Limits: Global size limit set to %llu bytes.\n", (unsigned long long) val64);
333
+    else
346 334
     	logg("^Limits: Global size limit protection disabled.\n");
347
-    }
348 335
 
349
-    if((limits.maxfilesize = cfgopt(copt, "MaxFileSize")->numarg)) {
350
-    	logg("Limits: File size limit set to %lu bytes.\n", limits.maxfilesize);
351
-    } else {
352
-	logg("^Limits: File size limit protection disabled.\n");
336
+    if((cpt = cfgopt(copt, "MaxFileSize"))->enabled) {
337
+	val64 = cpt->numarg;
338
+	if((ret = cl_engine_set(engine, CL_ENGINE_MAX_FILESIZE, &val64))) {
339
+	    logg("!cli_engine_set(CL_ENGINE_MAX_FILESIZE) failed: %s\n", cl_strerror(ret));
340
+	    cl_engine_free(engine);
341
+	    return 1;
342
+	}
353 343
     }
344
+    cl_engine_get(engine, CL_ENGINE_MAX_FILESIZE, &val64);
345
+    if(val64)
346
+    	logg("Limits: File size limit set to %llu bytes.\n", (unsigned long long) val64);
347
+    else
348
+    	logg("^Limits: File size limit protection disabled.\n");
354 349
 
355 350
 #ifndef C_WINDOWS
356 351
     if(getrlimit(RLIMIT_FSIZE, &rlim) == 0) {
357
-	if((rlim.rlim_max < limits.maxfilesize) || (rlim.rlim_max < limits.maxscansize))
358
-	    logg("^System limit for file size is lower than maxfilesize or maxscansize\n");
352
+	cl_engine_get(engine, CL_ENGINE_MAX_FILESIZE, &val64);
353
+	if(rlim.rlim_max < val64)
354
+	    logg("^System limit for file size is lower than engine->maxfilesize\n");
355
+	cl_engine_get(engine, CL_ENGINE_MAX_SCANSIZE, &val64);
356
+	if(rlim.rlim_max < val64)
357
+	    logg("^System limit for file size is lower than engine->maxscansize\n");
359 358
     } else {
360 359
 	logg("^Cannot obtain resource limits for file size\n");
361 360
     }
362 361
 #endif
363 362
 
364
-    if((limits.maxreclevel = cfgopt(copt, "MaxRecursion")->numarg)) {
365
-        logg("Limits: Recursion level limit set to %u.\n", limits.maxreclevel);
366
-    } else {
367
-        logg("^Limits: Recursion level limit protection disabled.\n");
363
+    if((cpt = cfgopt(copt, "MaxRecursion"))->enabled) {
364
+	val32 = cpt->numarg;
365
+	if((ret = cl_engine_set(engine, CL_ENGINE_MAX_RECURSION, &val32))) {
366
+	    logg("!cli_engine_set(CL_ENGINE_MAX_RECURSION) failed: %s\n", cl_strerror(ret));
367
+	    cl_engine_free(engine);
368
+	    return 1;
369
+	}
368 370
     }
369
-
370
-    if((limits.maxfiles = cfgopt(copt, "MaxFiles")->numarg)) {
371
-        logg("Limits: Files limit set to %u.\n", limits.maxfiles);
372
-    } else {
373
-        logg("^Limits: Files limit protection disabled.\n");
371
+    cl_engine_get(engine, CL_ENGINE_MAX_RECURSION, &val32);
372
+    if(val32)
373
+    	logg("Limits: Recursion level limit set to %u.\n", (unsigned int) val32);
374
+    else
375
+    	logg("^Limits: Recursion level limit protection disabled.\n");
376
+
377
+    if((cpt = cfgopt(copt, "MaxFiles"))->enabled) {
378
+	val32 = cpt->numarg;
379
+	if((ret = cl_engine_set(engine, CL_ENGINE_MAX_FILES, &val32))) {
380
+	    logg("!cli_engine_set(CL_ENGINE_MAX_FILES) failed: %s\n", cl_strerror(ret));
381
+	    cl_engine_free(engine);
382
+	    return 1;
383
+	}
374 384
     }
385
+    cl_engine_get(engine, CL_ENGINE_MAX_FILES, &val32);
386
+    if(val32)
387
+    	logg("Limits: Files limit set to %u.\n", (unsigned int) val32);
388
+    else
389
+    	logg("^Limits: Files limit protection disabled.\n");
375 390
 
376
-    if(cfgopt(copt, "ScanArchive")->enabled) {
377 391
 
392
+    if(cfgopt(copt, "ScanArchive")->enabled) {
378 393
 	logg("Archive support enabled.\n");
379 394
 	options |= CL_SCAN_ARCHIVE;
380 395
 
381
-	if(cfgopt(copt, "ArchiveLimitMemoryUsage")->enabled) {
382
-	    limits.archivememlim = 1;
383
-	    logg("Archive: Limited memory usage.\n");
384
-	} else {
385
-	    limits.archivememlim = 0;
386
-	}
387
-
388 396
 	if(cfgopt(copt, "ArchiveBlockEncrypted")->enabled) {
389 397
 	    logg("Archive: Blocking encrypted archives.\n");
390 398
 	    options |= CL_SCAN_BLOCKENCRYPTED;
... ...
@@ -482,11 +485,27 @@ int acceptloop_th(int *socketds, int nsockets, struct cl_engine *engine, unsigne
482 482
     if(cfgopt(copt, "StructuredDataDetection")->enabled) {
483 483
         options |= CL_SCAN_STRUCTURED;
484 484
 
485
-        limits.min_cc_count = cfgopt(copt, "StructuredMinCreditCardCount")->numarg;
486
-        logg("Structured: Minimum Credit Card Number Count set to %u\n", limits.min_cc_count);
487
-
488
-        limits.min_ssn_count = cfgopt(copt, "StructuredMinSSNCount")->numarg;
489
-        logg("Structured: Minimum Social Security Number Count set to %u\n", limits.min_ssn_count);
485
+	if((cpt = cfgopt(copt, "StructuredMinCreditCardCount"))->enabled) {
486
+	    val32 = cpt->numarg;
487
+	    if((ret = cl_engine_set(engine, CL_ENGINE_MIN_CC_COUNT, &val32))) {
488
+		logg("!cli_engine_set(CL_ENGINE_MIN_CC_COUNT) failed: %s\n", cl_strerror(ret));
489
+		cl_engine_free(engine);
490
+		return 1;
491
+	    }
492
+	}
493
+	cl_engine_get(engine, CL_ENGINE_MIN_CC_COUNT, &val32);
494
+	logg("Structured: Minimum Credit Card Number Count set to %u\n", (unsigned int) val32);
495
+
496
+	if((cpt = cfgopt(copt, "StructuredMinSSNCount"))->enabled) {
497
+	    val32 = cpt->numarg;
498
+	    if((ret = cl_engine_set(engine, CL_ENGINE_MIN_SSN_COUNT, &val32))) {
499
+		logg("!cli_engine_set(CL_ENGINE_MIN_SSN_COUNT) failed: %s\n", cl_strerror(ret));
500
+		cl_engine_free(engine);
501
+		return 1;
502
+	    }
503
+	}
504
+	cl_engine_get(engine, CL_ENGINE_MIN_SSN_COUNT, &val32);
505
+        logg("Structured: Minimum Social Security Number Count set to %u\n", (unsigned int) val32);
490 506
 
491 507
         if(cfgopt(copt, "StructuredSSNFormatNormal")->enabled)
492 508
             options |= CL_SCAN_STRUCTURED_SSN_NORMAL;
... ...
@@ -502,6 +521,25 @@ int acceptloop_th(int *socketds, int nsockets, struct cl_engine *engine, unsigne
502 502
 	logg("Self checking every %u seconds.\n", selfchk);
503 503
     }
504 504
 
505
+    /* save the PID */
506
+    mainpid = getpid();
507
+    if((cpt = cfgopt(copt, "PidFile"))->enabled) {
508
+	    FILE *fd;
509
+	old_umask = umask(0006);
510
+	if((fd = fopen(cpt->strarg, "w")) == NULL) {
511
+	    logg("!Can't save PID in file %s\n", cpt->strarg);
512
+	} else {
513
+	    if (fprintf(fd, "%u", (unsigned int) mainpid)<0) {
514
+	    	logg("!Can't save PID in file %s\n", cpt->strarg);
515
+	    }
516
+	    fclose(fd);
517
+	}
518
+	umask(old_umask);
519
+    }
520
+
521
+    logg("*Listening daemon: PID: %u\n", (unsigned int) mainpid);
522
+    max_threads = cfgopt(copt, "MaxThreads")->numarg;
523
+
505 524
     if(cfgopt(copt, "ClamukoScanOnAccess")->enabled)
506 525
 #ifdef CLAMUKO
507 526
     {
... ...
@@ -511,7 +549,6 @@ int acceptloop_th(int *socketds, int nsockets, struct cl_engine *engine, unsigne
511 511
 	    if(!(tharg = (struct thrarg *) malloc(sizeof(struct thrarg)))) break;
512 512
 	    tharg->copt = copt;
513 513
 	    tharg->engine = engine;
514
-	    tharg->limits = &limits;
515 514
 	    tharg->options = options;
516 515
 	    if(!pthread_create(&clamuko_pid, &clamuko_attr, clamukoth, tharg)) break;
517 516
 	    free(tharg);
... ...
@@ -625,9 +662,8 @@ int acceptloop_th(int *socketds, int nsockets, struct cl_engine *engine, unsigne
625 625
 		    client_conn->sd = new_sd;
626 626
 		    client_conn->options = options;
627 627
 		    client_conn->copt = copt;
628
-		    client_conn->engine = cl_dup(engine);
628
+		    client_conn->engine = cl_engine_dup(engine);
629 629
 		    client_conn->engine_timestamp = reloaded_time;
630
-		    client_conn->limits = &limits;
631 630
 		    client_conn->socketds = socketds;
632 631
 		    client_conn->nsockets = nsockets;
633 632
 		    if(!thrmgr_dispatch(thr_pool, client_conn)) {
... ...
@@ -717,7 +753,7 @@ int acceptloop_th(int *socketds, int nsockets, struct cl_engine *engine, unsigne
717 717
 #endif
718 718
     if(engine) {
719 719
 	thrmgr_setactiveengine(NULL);
720
-	cl_free(engine);
720
+	cl_engine_free(engine);
721 721
     }
722 722
 
723 723
     if(dbstat)
... ...
@@ -68,7 +68,7 @@
68 68
 #include "thrmgr.h"
69 69
 
70 70
 #ifdef HAVE_FD_PASSING
71
-static int recvfd_and_scan(int desc, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, const struct cfgstruct *copt)
71
+static int recvfd_and_scan(int desc, const struct cl_engine *engine, unsigned int options, const struct cfgstruct *copt)
72 72
 {
73 73
 	struct msghdr msg;
74 74
 	struct cmsghdr *cmsg;
... ...
@@ -99,7 +99,7 @@ static int recvfd_and_scan(int desc, const struct cl_engine *engine, const struc
99 99
 		    cmsg->cmsg_level == SOL_SOCKET &&
100 100
 		    cmsg->cmsg_type == SCM_RIGHTS) {
101 101
 			int fd = *(int *)CMSG_DATA(cmsg);
102
-			ret = scanfd(fd, NULL, engine, limits, options, copt, desc);
102
+			ret = scanfd(fd, NULL, engine, options, copt, desc);
103 103
 			close(fd);
104 104
 		}
105 105
 	}
... ...
@@ -107,14 +107,14 @@ static int recvfd_and_scan(int desc, const struct cl_engine *engine, const struc
107 107
 }
108 108
 
109 109
 #else
110
-static int recvfd_and_scan(int desc, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, const struct cfgstruct *copt)
110
+static int recvfd_and_scan(int desc, const struct cl_engine *engine, unsigned int options, const struct cfgstruct *copt)
111 111
 {
112 112
 	mdprintf(desc, "ERROR: FILDES support not compiled in\n");
113 113
 	return -1;
114 114
 }
115 115
 #endif
116 116
 
117
-int command(int desc, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, const struct cfgstruct *copt, int timeout)
117
+int command(int desc, const struct cl_engine *engine, unsigned int options, const struct cfgstruct *copt, int timeout)
118 118
 {
119 119
 	char buff[1025];
120 120
 	int bread;
... ...
@@ -136,7 +136,7 @@ int command(int desc, const struct cl_engine *engine, const struct cl_limits *li
136 136
 
137 137
     if(!strncmp(buff, CMD1, strlen(CMD1))) { /* SCAN */
138 138
 	thrmgr_setactivetask(NULL, CMD1);
139
-	if(scan(buff + strlen(CMD1) + 1, NULL, engine, limits, options, copt, desc, TYPE_SCAN) == -2)
139
+	if(scan(buff + strlen(CMD1) + 1, NULL, engine, options, copt, desc, TYPE_SCAN) == -2)
140 140
 	    if(cfgopt(copt, "ExitOnOOM")->enabled)
141 141
 		return COMMAND_SHUTDOWN;
142 142
 
... ...
@@ -159,24 +159,28 @@ int command(int desc, const struct cl_engine *engine, const struct cl_limits *li
159 159
 
160 160
     } else if(!strncmp(buff, CMD6, strlen(CMD6))) { /* CONTSCAN */
161 161
 	thrmgr_setactivetask(NULL, CMD6);
162
-	if(scan(buff + strlen(CMD6) + 1, NULL, engine, limits, options, copt, desc, TYPE_CONTSCAN) == -2)
162
+	if(scan(buff + strlen(CMD6) + 1, NULL, engine, options, copt, desc, TYPE_CONTSCAN) == -2)
163 163
 	    if(cfgopt(copt, "ExitOnOOM")->enabled)
164 164
 		return COMMAND_SHUTDOWN;
165 165
 
166 166
     } else if(!strncmp(buff, CMD7, strlen(CMD7))) { /* VERSION */
167
+	    uint32_t ver;
168
+
167 169
 	thrmgr_setactivetask(NULL, CMD7);
168
-	if(engine->dbversion[0]) {
170
+	cl_engine_get(engine, CL_ENGINE_DB_VERSION, &ver);
171
+	if(ver) {
169 172
 		char timestr[32];
170
-		time_t t = (time_t) engine->dbversion[1];
173
+		time_t t;
171 174
 
172
-	    mdprintf(desc, "ClamAV %s/%d/%s", get_version(), engine->dbversion[0], cli_ctime(&t, timestr, sizeof(timestr)));
175
+	    cl_engine_get(engine, CL_ENGINE_DB_TIME, &t);
176
+	    mdprintf(desc, "ClamAV %s/%u/%s", get_version(), (unsigned int) ver, cli_ctime(&t, timestr, sizeof(timestr)));
173 177
 	} else {
174 178
 	    mdprintf(desc, "ClamAV %s\n", get_version());
175 179
 	}
176 180
 
177 181
     } else if(!strncmp(buff, CMD8, strlen(CMD8))) { /* STREAM */
178 182
 	thrmgr_setactivetask(NULL, CMD8);
179
-	if(scanstream(desc, NULL, engine, limits, options, copt) == CL_EMEM)
183
+	if(scanstream(desc, NULL, engine, options, copt) == CL_EMEM)
180 184
 	    if(cfgopt(copt, "ExitOnOOM")->enabled)
181 185
 		return COMMAND_SHUTDOWN;
182 186
 
... ...
@@ -194,13 +198,13 @@ int command(int desc, const struct cl_engine *engine, const struct cl_limits *li
194 194
 
195 195
     } else if(!strncmp(buff, CMD13, strlen(CMD13))) { /* MULTISCAN */
196 196
 	thrmgr_setactivetask(buff+strlen(CMD13)+1, CMD13);
197
-	if(scan(buff + strlen(CMD13) + 1, NULL, engine, limits, options, copt, desc, TYPE_MULTISCAN) == -2)
197
+	if(scan(buff + strlen(CMD13) + 1, NULL, engine, options, copt, desc, TYPE_MULTISCAN) == -2)
198 198
 	    if(cfgopt(copt, "ExitOnOOM")->enabled)
199 199
 		return COMMAND_SHUTDOWN;
200 200
 
201 201
     } else if(!strncmp(buff, CMD14, strlen(CMD14))) { /* FILDES */
202 202
 	thrmgr_setactivetask(NULL, CMD14);
203
-	if(recvfd_and_scan(desc, engine, limits, options, copt) == -2)
203
+	if(recvfd_and_scan(desc, engine, options, copt) == -2)
204 204
 	    if(cfgopt(copt, "ExitOnOOM")->enabled)
205 205
 		return COMMAND_SHUTDOWN;
206 206
     } else if(!strncmp(buff, CMD15, strlen(CMD15))) { /* STATS */
... ...
@@ -43,6 +43,6 @@
43 43
 #include "libclamav/clamav.h"
44 44
 #include "shared/cfgparser.h"
45 45
 
46
-int command(int desc, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, const struct cfgstruct *copt, int timeout);
46
+int command(int desc, const struct cl_engine *engine, unsigned int options, const struct cfgstruct *copt, int timeout);
47 47
 
48 48
 #endif
... ...
@@ -60,6 +60,7 @@
60 60
 #include "libclamav/matcher-ac.h"
61 61
 #include "libclamav/str.h"
62 62
 #include "libclamav/readdb.h"
63
+#include "libclamav/cltypes.h"
63 64
 
64 65
 #ifdef C_LINUX
65 66
 dev_t procdev;
... ...
@@ -76,7 +77,7 @@ dev_t procdev;
76 76
 
77 77
 static void move_infected(const char *filename, const struct optstruct *opt);
78 78
 
79
-static int scanfile(const char *filename, struct cl_engine *engine, const struct optstruct *opt, const struct cl_limits *limits, unsigned int options)
79
+static int scanfile(const char *filename, struct cl_engine *engine, const struct optstruct *opt, unsigned int options)
80 80
 {
81 81
 	int ret = 0, fd, included, printclean = 1;
82 82
 	const struct optnode *optnode;
... ...
@@ -149,7 +150,7 @@ static int scanfile(const char *filename, struct cl_engine *engine, const struct
149 149
 
150 150
     info.files++;
151 151
 
152
-    if((ret = cl_scandesc(fd, &virname, &info.blocks, engine, limits, options)) == CL_VIRUS) {
152
+    if((ret = cl_scandesc(fd, &virname, &info.blocks, engine, options)) == CL_VIRUS) {
153 153
 	logg("~%s: %s FOUND\n", filename, virname);
154 154
 	info.ifiles++;
155 155
 
... ...
@@ -180,7 +181,7 @@ static int scanfile(const char *filename, struct cl_engine *engine, const struct
180 180
     return ret;
181 181
 }
182 182
 
183
-static int scandirs(const char *dirname, struct cl_engine *engine, const struct optstruct *opt, const struct cl_limits *limits, unsigned int options, unsigned int depth)
183
+static int scandirs(const char *dirname, struct cl_engine *engine, const struct optstruct *opt, unsigned int options, unsigned int depth)
184 184
 {
185 185
 	DIR *dd;
186 186
 	struct dirent *dent;
... ...
@@ -250,11 +251,11 @@ static int scandirs(const char *dirname, struct cl_engine *engine, const struct
250 250
 		    /* stat the file */
251 251
 		    if(lstat(fname, &statbuf) != -1) {
252 252
 			if(S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode) && recursion) {
253
-			    if(scandirs(fname, engine, opt, limits, options, depth) == 1)
253
+			    if(scandirs(fname, engine, opt, options, depth) == 1)
254 254
 				scanret++;
255 255
 			} else {
256 256
 			    if(S_ISREG(statbuf.st_mode))
257
-				scanret += scanfile(fname, engine, opt, limits, options);
257
+				scanret += scanfile(fname, engine, opt, options);
258 258
 			}
259 259
 		    }
260 260
 		    free(fname);
... ...
@@ -277,7 +278,7 @@ static int scandirs(const char *dirname, struct cl_engine *engine, const struct
277 277
 
278 278
 }
279 279
 
280
-static int scanstdin(const struct cl_engine *engine, const struct cl_limits *limits, int options)
280
+static int scanstdin(const struct cl_engine *engine, int options)
281 281
 {
282 282
 	int ret;
283 283
 	const char *virname, *tmpdir;
... ...
@@ -321,7 +322,7 @@ static int scanstdin(const struct cl_engine *engine, const struct cl_limits *lim
321 321
     logg("*Checking %s\n", file);
322 322
     info.files++;
323 323
 
324
-    if((ret = cl_scanfile(file, &virname, &info.blocks, engine, limits, options)) == CL_VIRUS) {
324
+    if((ret = cl_scanfile(file, &virname, &info.blocks, engine, options)) == CL_VIRUS) {
325 325
 	logg("stdin: %s FOUND\n", virname);
326 326
 	info.ifiles++;
327 327
 
... ...
@@ -345,15 +346,15 @@ int scanmanager(const struct optstruct *opt)
345 345
 	mode_t fmode;
346 346
 	int ret = 0, fmodeint, i, x;
347 347
 	unsigned int options = 0, dboptions = 0;
348
-	struct cl_engine *engine = NULL;
349
-	struct cl_limits limits;
348
+	struct cl_engine *engine;
350 349
 	struct stat sb;
351 350
 	char *file, cwd[1024], *pua_cats = NULL, *argument;
352 351
 	const struct optnode *optnode;
353 352
 #ifndef C_WINDOWS
354 353
 	struct rlimit rlim;
355 354
 #endif
356
-
355
+	uint64_t val64;
356
+	uint32_t val32;
357 357
 
358 358
     if(!opt_check(opt, "no-phishing-sigs"))
359 359
 	dboptions |= CL_DB_PHISHING;
... ...
@@ -376,6 +377,16 @@ int scanmanager(const struct optstruct *opt)
376 376
     if(opt_check(opt, "dev-ac-depth"))
377 377
 	cli_ac_setdepth(AC_DEFAULT_MIN_DEPTH, atoi(opt_arg(opt, "dev-ac-depth")));
378 378
 
379
+    if((ret = cl_init(CL_INIT_DEFAULT))) {
380
+	logg("!Can't initialize libclamav: %s\n", cl_strerror(ret));
381
+	return 50;
382
+    }
383
+
384
+    if(!(engine = cl_engine_new(CL_ENGINE_DEFAULT))) {
385
+	logg("!Can't initialize antivirus engine\n");
386
+	return 50;
387
+    }
388
+
379 389
     if(opt_check(opt, "detect-pua")) {
380 390
 	dboptions |= CL_DB_PUA;
381 391
 
... ...
@@ -386,6 +397,7 @@ int scanmanager(const struct optstruct *opt)
386 386
 	    while(argument) {
387 387
 		if(!(pua_cats = realloc(pua_cats, i + strlen(argument) + 3))) {
388 388
 		    logg("!Can't allocate memory for pua_cats\n");
389
+		    cl_engine_free(engine);
389 390
 		    return 70;
390 391
 		}
391 392
 		sprintf(pua_cats + i, ".%s", argument);
... ...
@@ -400,6 +412,7 @@ int scanmanager(const struct optstruct *opt)
400 400
 	if(opt_check(opt, "include-pua")) {
401 401
 	    if(pua_cats) {
402 402
 		logg("!--exclude-pua and --include-pua cannot be used at the same time\n");
403
+		cl_engine_free(engine);
403 404
 		free(pua_cats);
404 405
 		return 40;
405 406
 	    }
... ...
@@ -421,45 +434,42 @@ int scanmanager(const struct optstruct *opt)
421 421
 	}
422 422
 
423 423
 	if(pua_cats) {
424
-	    /* FIXME with the new API */
425
-	    if((ret = cli_initengine(&engine, dboptions))) {
426
-		logg("!cli_initengine() failed: %s\n", cl_strerror(ret));
424
+	    if((ret = cl_engine_set(engine, CL_ENGINE_PUA_CATEGORIES, pua_cats))) {
425
+		logg("!cli_engine_set(CL_ENGINE_PUA_CATEGORIES) failed: %s\n", cl_strerror(ret));
427 426
 		free(pua_cats);
427
+		cl_engine_free(engine);
428 428
 		return 50;
429 429
 	    }
430
-	    engine->pua_cats = pua_cats;
430
+	    free(pua_cats);
431 431
 	}
432 432
     }
433 433
 
434 434
     if(opt_check(opt, "database")) {
435
-	if((ret = cl_load(opt_arg(opt, "database"), &engine, &info.sigs, dboptions))) {
435
+	if((ret = cl_load(opt_arg(opt, "database"), engine, &info.sigs, dboptions))) {
436 436
 	    logg("!%s\n", cl_strerror(ret));
437
+	    cl_engine_free(engine);
437 438
 	    return 50;
438 439
 	}
439 440
 
440 441
     } else {
441 442
 	    char *dbdir = freshdbdir();
442 443
 
443
-	if((ret = cl_load(dbdir, &engine, &info.sigs, dboptions))) {
444
+	if((ret = cl_load(dbdir, engine, &info.sigs, dboptions))) {
444 445
 	    logg("!%s\n", cl_strerror(ret));
445 446
 	    free(dbdir);
447
+	    cl_engine_free(engine);
446 448
 	    return 50;
447 449
 	}
448 450
 	free(dbdir);
449 451
     }
450 452
 
451
-    if(!engine) {
452
-	logg("!Can't initialize the virus database\n");
453
-	return 50;
454
-    }
455
-
456
-    if((ret = cl_build(engine)) != 0) {
453
+    if((ret = cl_engine_compile(engine)) != 0) {
457 454
 	logg("!Database initialization error: %s\n", cl_strerror(ret));;
455
+	cl_engine_free(engine);
458 456
 	return 50;
459 457
     }
460 458
 
461 459
     /* set limits */
462
-    memset(&limits, 0, sizeof(struct cl_limits));
463 460
 
464 461
     if(opt_check(opt, "max-scansize")) {
465 462
 	char *cpy, *ptr;
... ...
@@ -468,12 +478,17 @@ int scanmanager(const struct optstruct *opt)
468 468
 	    cpy = calloc(strlen(ptr), 1);
469 469
 	    strncpy(cpy, ptr, strlen(ptr) - 1);
470 470
 	    cpy[strlen(ptr)-1]='\0';
471
-	    limits.maxscansize = atoi(cpy) * 1024 * 1024;
471
+	    val64 = atoi(cpy) * 1024 * 1024;
472 472
 	    free(cpy);
473 473
 	} else
474
-	    limits.maxscansize = atoi(ptr) * 1024;
475
-    } else
476
-	limits.maxscansize = 104857600;
474
+	    val64 = atoi(ptr) * 1024;
475
+
476
+	if((ret = cl_engine_set(engine, CL_ENGINE_MAX_SCANSIZE, &val64))) {
477
+	    logg("!cli_engine_set(CL_ENGINE_MAX_SCANSIZE) failed: %s\n", cl_strerror(ret));
478
+	    cl_engine_free(engine);
479
+	    return 50;
480
+	}
481
+    }
477 482
 
478 483
     if(opt_check(opt, "max-filesize")) {
479 484
 	char *cpy, *ptr;
... ...
@@ -482,31 +497,48 @@ int scanmanager(const struct optstruct *opt)
482 482
 	    cpy = calloc(strlen(ptr), 1);
483 483
 	    strncpy(cpy, ptr, strlen(ptr) - 1);
484 484
 	    cpy[strlen(ptr)-1]='\0';
485
-	    limits.maxfilesize = atoi(cpy) * 1024 * 1024;
485
+	    val64 = atoi(cpy) * 1024 * 1024;
486 486
 	    free(cpy);
487 487
 	} else
488
-	    limits.maxfilesize = atoi(ptr) * 1024;
489
-    } else
490
-	limits.maxfilesize = 26214400;
488
+	    val64 = atoi(ptr) * 1024;
489
+
490
+	if((ret = cl_engine_set(engine, CL_ENGINE_MAX_FILESIZE, &val64))) {
491
+	    logg("!cli_engine_set(CL_ENGINE_MAX_FILESIZE) failed: %s\n", cl_strerror(ret));
492
+	    cl_engine_free(engine);
493
+	    return 50;
494
+	}
495
+    }
491 496
 
492 497
 #ifndef C_WINDOWS
493 498
     if(getrlimit(RLIMIT_FSIZE, &rlim) == 0) {
494
-	if((rlim.rlim_max < limits.maxfilesize) || (rlim.rlim_max < limits.maxscansize))
495
-	    logg("^System limit for file size is lower than maxfilesize or maxscansize\n");
499
+	cl_engine_get(engine, CL_ENGINE_MAX_FILESIZE, &val64);
500
+	if(rlim.rlim_max < val64)
501
+	    logg("^System limit for file size is lower than engine->maxfilesize\n");
502
+	cl_engine_get(engine, CL_ENGINE_MAX_SCANSIZE, &val64);
503
+	if(rlim.rlim_max < val64)
504
+	    logg("^System limit for file size is lower than engine->maxscansize\n");
496 505
     } else {
497 506
 	logg("^Cannot obtain resource limits for file size\n");
498 507
     }
499 508
 #endif
500 509
 
501
-    if(opt_check(opt, "max-files"))
502
-	limits.maxfiles = atoi(opt_arg(opt, "max-files"));
503
-    else
504
-        limits.maxfiles = 10000;
510
+    if(opt_check(opt, "max-files")) {
511
+	val32 = atoi(opt_arg(opt, "max-files"));
512
+	if((ret = cl_engine_set(engine, CL_ENGINE_MAX_FILES, &val32))) {
513
+	    logg("!cli_engine_set(CL_ENGINE_MAX_FILES) failed: %s\n", cl_strerror(ret));
514
+	    cl_engine_free(engine);
515
+	    return 50;
516
+	}
517
+    }
505 518
 
506
-    if(opt_check(opt, "max-recursion"))
507
-        limits.maxreclevel = atoi(opt_arg(opt, "max-recursion"));
508
-    else
509
-        limits.maxreclevel = 16;
519
+    if(opt_check(opt, "max-recursion")) {
520
+	val32 = atoi(opt_arg(opt, "max-recursion"));
521
+	if((ret = cl_engine_set(engine, CL_ENGINE_MAX_RECURSION, &val32))) {
522
+	    logg("!cli_engine_set(CL_ENGINE_MAX_RECURSION) failed: %s\n", cl_strerror(ret));
523
+	    cl_engine_free(engine);
524
+	    return 50;
525
+	}
526
+    }
510 527
 
511 528
     /* set options */
512 529
 
... ...
@@ -582,20 +614,27 @@ int scanmanager(const struct optstruct *opt)
582 582
 	    options |= CL_SCAN_STRUCTURED_SSN_NORMAL;
583 583
 	}
584 584
 
585
-	if(opt_check(opt, "structured-ssn-count"))
586
-	    limits.min_ssn_count = atoi(opt_arg(opt, "structured-ssn-count"));
587
-	else
588
-	    limits.min_ssn_count = 3;
585
+	if(opt_check(opt, "structured-ssn-count")) {
586
+	    val32 = atoi(opt_arg(opt, "structured-ssn-count"));
587
+	    if((ret = cl_engine_set(engine, CL_ENGINE_MIN_SSN_COUNT, &val32))) {
588
+		logg("!cli_engine_set(CL_ENGINE_MIN_SSN_COUNT) failed: %s\n", cl_strerror(ret));
589
+		cl_engine_free(engine);
590
+		return 50;
591
+	    }
592
+	}
589 593
 
590
-	if(opt_check(opt, "structured-cc-count"))
591
-	    limits.min_cc_count = atoi(opt_arg(opt, "structured-cc-count"));
592
-	else
593
-	    limits.min_cc_count = 3;
594
+	if(opt_check(opt, "structured-cc-count")) {
595
+	    val32 = atoi(opt_arg(opt, "structured-cc-count"));
596
+	    if((ret = cl_engine_set(engine, CL_ENGINE_MIN_CC_COUNT, &val32))) {
597
+		logg("!cli_engine_set(CL_ENGINE_MIN_CC_COUNT) failed: %s\n", cl_strerror(ret));
598
+		cl_engine_free(engine);
599
+		return 50;
600
+	    }
601
+	}
594 602
 
595 603
     } else
596 604
 	options &= ~CL_SCAN_STRUCTURED;
597 605
 
598
-
599 606
 #ifdef C_LINUX
600 607
     procdev = (dev_t) 0;
601 608
     if(stat("/proc", &sb) != -1 && !sb.st_size)
... ...
@@ -610,10 +649,10 @@ int scanmanager(const struct optstruct *opt)
610 610
 	    logg("!Can't get absolute pathname of current working directory\n");
611 611
 	    ret = 57;
612 612
 	} else
613
-	    ret = scandirs(cwd, engine, opt, &limits, options, 1);
613
+	    ret = scandirs(cwd, engine, opt, options, 1);
614 614
 
615 615
     } else if(!strcmp(opt->filename, "-")) { /* read data from stdin */
616
-	ret = scanstdin(engine, &limits, options);
616
+	ret = scanstdin(engine, options);
617 617
 
618 618
     } else {
619 619
 	for (x = 0; (file = cli_strtok(opt->filename, x, "\t")) != NULL; x++) {
... ...
@@ -633,11 +672,11 @@ int scanmanager(const struct optstruct *opt)
633 633
 
634 634
 		switch(fmode & S_IFMT) {
635 635
 		    case S_IFREG:
636
-			ret = scanfile(file, engine, opt, &limits, options);
636
+			ret = scanfile(file, engine, opt, options);
637 637
 			break;
638 638
 
639 639
 		    case S_IFDIR:
640
-			ret = scandirs(file, engine, opt, &limits, options, 1);
640
+			ret = scandirs(file, engine, opt, options, 1);
641 641
 			break;
642 642
 
643 643
 		    default:
... ...
@@ -650,7 +689,7 @@ int scanmanager(const struct optstruct *opt)
650 650
     }
651 651
 
652 652
     /* free the engine */
653
-    cl_free(engine);
653
+    cl_engine_free(engine);
654 654
 
655 655
     /* overwrite return code */
656 656
     if(info.ifiles)
... ...
@@ -104,80 +104,36 @@ extern "C"
104 104
 /* recommended scan settings */
105 105
 #define CL_SCAN_STDOPT		(CL_SCAN_ARCHIVE | CL_SCAN_MAIL | CL_SCAN_OLE2 | CL_SCAN_PDF | CL_SCAN_HTML | CL_SCAN_PE | CL_SCAN_ALGORITHMIC | CL_SCAN_ELF)
106 106
 
107
-/* aliases for backward compatibility */
108
-#define CL_RAW		CL_SCAN_RAW
109
-#define CL_ARCHIVE	CL_SCAN_ARCHIVE
110
-#define CL_MAIL		CL_SCAN_MAIL
111
-#define CL_OLE2		CL_SCAN_OLE2
112
-#define CL_ENCRYPTED    CL_SCAN_BLOCKENCRYPTED
113
-#define cl_node		cl_engine
114
-#define cl_perror	cl_strerror
115
-
116
-struct cl_engine {
117
-    unsigned int refcount; /* reference counter */
118
-    unsigned short sdb;
119
-    unsigned int dboptions;
120
-    unsigned int dbversion[2];
121
-
122
-    /* Roots table */
123
-    void **root;
124
-
125
-    /* B-M matcher for standard MD5 sigs */
126
-    void *md5_hdb;
127
-
128
-    /* B-M matcher for MD5 sigs for PE sections */
129
-    void *md5_mdb;
130
-
131
-    /* B-M matcher for whitelist db */
132
-    void *md5_fp;
133
-
134
-    /* Zip metadata */
135
-    void *zip_mlist;
136
-
137
-    /* RAR metadata */
138
-    void *rar_mlist;
107
+struct cl_engine;
108
+
109
+#define CL_INIT_DEFAULT	0x0
110
+extern int cl_init(unsigned int options);
111
+
112
+#define CL_ENGINE_DEFAULT   0x0
113
+extern struct cl_engine *cl_engine_new(unsigned int options);
114
+
115
+enum cl_engine_field {
116
+    CL_ENGINE_MAX_SCANSIZE,	    /* uint64_t */
117
+    CL_ENGINE_MAX_FILESIZE,	    /* uint64_t */
118
+    CL_ENGINE_MAX_RECURSION,	    /* uint32_t	*/
119
+    CL_ENGINE_MAX_FILES,	    /* uint32_t */
120
+    CL_ENGINE_MIN_CC_COUNT,	    /* uint32_t */
121
+    CL_ENGINE_MIN_SSN_COUNT,	    /* uint32_t */
122
+    CL_ENGINE_PUA_CATEGORIES,	    /* (char *) */
123
+    CL_ENGINE_DB_VERSION,	    /* uint32_t */
124
+    CL_ENGINE_DB_TIME		    /* uint32_t */
125
+};
139 126
 
140
-    /* Phishing .pdb and .wdb databases*/
141
-    void *whitelist_matcher;
142
-    void *domainlist_matcher;
143
-    void *phishcheck;
127
+extern int cl_engine_set(struct cl_engine *engine, enum cl_engine_field field, const void *val);
144 128
 
145
-    /* Dynamic configuration */
146
-    void *dconf;
129
+extern int cl_engine_get(const struct cl_engine *engine, enum cl_engine_field field, void *val);
147 130
 
148
-    /* Filetype definitions */
149
-    void *ftypes;
131
+extern int cl_engine_compile(struct cl_engine *engine);
150 132
 
151
-    /* Ignored signatures */
152
-    void *ignored;
133
+extern struct cl_engine *cl_engine_dup(struct cl_engine *engine);
153 134
 
154
-    /* PUA categories (to be included or excluded) */
155
-    char *pua_cats;
135
+extern int cl_engine_free(struct cl_engine *engine);
156 136
 
157
-    /* Used for memory pools */
158
-    void *mempool;
159
-};
160
-
161
-struct cl_limits {
162
-    unsigned long int maxscansize;  /* during the scanning of archives this size
163
-				     * will never be exceeded
164
-				     */
165
-    unsigned long int maxfilesize;  /* compressed files will only be decompressed
166
-				     * and scanned up to this size
167
-				     */
168
-    unsigned int maxreclevel;	    /* maximum recursion level for archives */
169
-    unsigned int maxfiles;	    /* maximum number of files to be scanned
170
-				     * within a single archive
171
-				     */
172
-    unsigned short archivememlim;   /* limit memory usage for some unpackers */
173
-
174
-    /* This is for structured data detection.  You can set the minimum
175
-     * number of occurences of an CC# or SSN before the system will
176
-     * generate a notification.
177
-     */
178
-    unsigned int min_cc_count;
179
-    unsigned int min_ssn_count;
180
-};
181 137
 
182 138
 struct cl_stat {
183 139
     char *dir;
... ...
@@ -198,18 +154,15 @@ struct cl_cvd {		    /* field no. */
198 198
 };
199 199
 
200 200
 /* file scanning */
201
-extern int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options);
201
+extern int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int options);
202 202
 
203
-extern int cl_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options);
203
+extern int cl_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int options);
204 204
 
205 205
 /* database handling */
206
-extern int cl_load(const char *path, struct cl_engine **engine, unsigned int *signo, unsigned int options);
206
+extern int cl_load(const char *path, struct cl_engine *engine, unsigned int *signo, unsigned int options);
207 207
 extern const char *cl_retdbdir(void);
208 208
 
209 209
 /* engine handling */
210
-extern int cl_build(struct cl_engine *engine);
211
-extern struct cl_engine *cl_dup(struct cl_engine *engine);
212
-extern void cl_free(struct cl_engine *engine);
213 210
 
214 211
 /* CVD */
215 212
 extern struct cl_cvd *cl_cvdhead(const char *file);
... ...
@@ -178,7 +178,7 @@ int cli_untgz(int fd, const char *destdir)
178 178
     return 0;
179 179
 }
180 180
 
181
-static int cli_tgzload(int fd, struct cl_engine **engine, unsigned int *signo, unsigned int options)
181
+static int cli_tgzload(int fd, struct cl_engine *engine, unsigned int *signo, unsigned int options)
182 182
 {
183 183
 	char osize[13], name[101];
184 184
 	char block[TAR_BLOCKSIZE];
... ...
@@ -500,7 +500,7 @@ int cl_cvdverify(const char *file)
500 500
     return ret;
501 501
 }
502 502
 
503
-int cli_cvdload(FILE *fs, struct cl_engine **engine, unsigned int *signo, unsigned int daily, unsigned int options, unsigned int cld)
503
+int cli_cvdload(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int daily, unsigned int options, unsigned int cld)
504 504
 {
505 505
         char *dir;
506 506
 	struct cl_cvd cvd;
... ...
@@ -544,8 +544,8 @@ int cli_cvdload(FILE *fs, struct cl_engine **engine, unsigned int *signo, unsign
544 544
     }
545 545
 
546 546
     if(daily) {
547
-	(*engine)->dbversion[0] = cvd.version;
548
-	(*engine)->dbversion[1] = cvd.stime;
547
+	engine->dbversion[0] = cvd.version;
548
+	engine->dbversion[1] = cvd.stime;
549 549
     }
550 550
 
551 551
     if(options & CL_DB_CVDNOTMP) {
... ...
@@ -31,7 +31,7 @@ struct cli_dbio {
31 31
     unsigned int size;
32 32
 };
33 33
 
34
-int cli_cvdload(FILE *fs, struct cl_engine **engine, unsigned int *signo, unsigned int daily, unsigned int options, unsigned int cld);
34
+int cli_cvdload(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int daily, unsigned int options, unsigned int cld);
35 35
 int cli_untgz(int fd, const char *destdir);
36 36
 
37 37
 #endif
... ...
@@ -271,29 +271,21 @@ static int chkflevel(const char *entry, int field)
271 271
     return 1;
272 272
 }
273 273
 
274
-int cli_dconf_load(FILE *fs, struct cl_engine **engine, unsigned int options, struct cli_dbio *dbio)
274
+int cli_dconf_load(FILE *fs, struct cl_engine *engine, unsigned int options, struct cli_dbio *dbio)
275 275
 {
276 276
 	char buffer[FILEBUFF];
277 277
 	unsigned int line = 0;
278 278
 	int ret = 0;
279
-	struct cli_dconf *dconf;
280 279
 	uint32_t val;
281 280
 
282 281
 
283
-    if((ret = cli_initengine(engine, options))) {
284
-	cl_free(*engine);
285
-	return ret;
286
-    }
287
-
288
-    dconf = (struct cli_dconf *) (*engine)->dconf;
289
-
290 282
     while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) {
291 283
 	line++;
292 284
 	cli_chomp(buffer);
293 285
 
294 286
 	if(!strncmp(buffer, "PE:", 3) && chkflevel(buffer, 2)) {
295 287
 	    if(sscanf(buffer + 3, "0x%x", &val) == 1) {
296
-		dconf->pe = val;
288
+		engine->dconf->pe = val;
297 289
 	    } else {
298 290
 		ret = CL_EMALFDB;
299 291
 		break;
... ...
@@ -302,7 +294,7 @@ int cli_dconf_load(FILE *fs, struct cl_engine **engine, unsigned int options, st
302 302
 
303 303
 	if(!strncmp(buffer, "ELF:", 4) && chkflevel(buffer, 2)) {
304 304
 	    if(sscanf(buffer + 4, "0x%x", &val) == 1) {
305
-		dconf->elf = val;
305
+		engine->dconf->elf = val;
306 306
 	    } else {
307 307
 		ret = CL_EMALFDB;
308 308
 		break;
... ...
@@ -311,7 +303,7 @@ int cli_dconf_load(FILE *fs, struct cl_engine **engine, unsigned int options, st
311 311
 
312 312
 	if(!strncmp(buffer, "ARCHIVE:", 8) && chkflevel(buffer, 2)) {
313 313
 	    if(sscanf(buffer + 8, "0x%x", &val) == 1) {
314
-		dconf->archive = val;
314
+		engine->dconf->archive = val;
315 315
 	    } else {
316 316
 		ret = CL_EMALFDB;
317 317
 		break;
... ...
@@ -320,7 +312,7 @@ int cli_dconf_load(FILE *fs, struct cl_engine **engine, unsigned int options, st
320 320
 
321 321
 	if(!strncmp(buffer, "DOCUMENT:", 9) && chkflevel(buffer, 2)) {
322 322
 	    if(sscanf(buffer + 9, "0x%x", &val) == 1) {
323
-		dconf->doc = val;
323
+		engine->dconf->doc = val;
324 324
 	    } else {
325 325
 		ret = CL_EMALFDB;
326 326
 		break;
... ...
@@ -329,7 +321,7 @@ int cli_dconf_load(FILE *fs, struct cl_engine **engine, unsigned int options, st
329 329
 
330 330
 	if(!strncmp(buffer, "MAIL:", 5) && chkflevel(buffer, 2)) {
331 331
 	    if(sscanf(buffer + 5, "0x%x", &val) == 1) {
332
-		dconf->mail = val;
332
+		engine->dconf->mail = val;
333 333
 	    } else {
334 334
 		ret = CL_EMALFDB;
335 335
 		break;
... ...
@@ -338,7 +330,7 @@ int cli_dconf_load(FILE *fs, struct cl_engine **engine, unsigned int options, st
338 338
 
339 339
 	if(!strncmp(buffer, "OTHER:", 6) && chkflevel(buffer, 2)) {
340 340
 	    if(sscanf(buffer + 6, "0x%x", &val) == 1) {
341
-		dconf->other = val;
341
+		engine->dconf->other = val;
342 342
 	    } else {
343 343
 		ret = CL_EMALFDB;
344 344
 		break;
... ...
@@ -347,7 +339,7 @@ int cli_dconf_load(FILE *fs, struct cl_engine **engine, unsigned int options, st
347 347
 
348 348
 	if(!strncmp(buffer, "PHISHING:", 9) && chkflevel(buffer, 2)) {
349 349
 	    if(sscanf(buffer + 9, "0x%x", &val) == 1) {
350
-		dconf->phishing = val;
350
+		engine->dconf->phishing = val;
351 351
 	    } else {
352 352
 		ret = CL_EMALFDB;
353 353
 		break;
... ...
@@ -357,7 +349,6 @@ int cli_dconf_load(FILE *fs, struct cl_engine **engine, unsigned int options, st
357 357
 
358 358
     if(ret) {
359 359
 	cli_errmsg("Problem parsing configuration file at line %u\n", line);
360
-	cl_free(*engine);
361 360
 	return ret;
362 361
     }
363 362
 
... ...
@@ -107,5 +107,5 @@ struct cli_dconf *cli_dconf_init(void);
107 107
 #define cli_mp_dconf_init(a) cli_dconf_init()
108 108
 #endif
109 109
 void cli_dconf_print(struct cli_dconf *dconf);
110
-int cli_dconf_load(FILE *fs, struct cl_engine **engine, unsigned int options, struct cli_dbio *dbio);
110
+int cli_dconf_load(FILE *fs, struct cl_engine *engine, unsigned int options, struct cli_dbio *dbio);
111 111
 #endif
... ...
@@ -1,16 +1,18 @@
1 1
 CLAMAV_PUBLIC {
2 2
   global:
3
-    cl_build;
4 3
     cl_cvdfree;
5 4
     cl_cvdhead;
6 5
     cl_cvdparse;
7 6
     cl_cvdverify;
8 7
     cl_debug;
9
-    cl_dup;
10
-    cl_free;
8
+    cl_init;
9
+    cl_engine_new;
10
+    cl_engine_set;
11
+    cl_engine_get;
12
+    cl_engine_compile;
13
+    cl_engine_dup;
14
+    cl_engine_free;
11 15
     cl_load;
12
-    cl_loaddb;
13
-    cl_loaddbdir;
14 16
     cl_retdbdir;
15 17
     cl_retflevel;
16 18
     cl_retver;
... ...
@@ -841,7 +841,7 @@ inline static int ac_addtype(struct cli_matched_type **list, cli_file_t type, of
841 841
 
842 842
 
843 843
     if(type == CL_TYPE_ZIPSFX) {
844
-	if(*list && ctx && ctx->limits && ctx->limits->maxfiles && (*list)->cnt > ctx->limits->maxfiles)
844
+	if(*list && ctx && ctx->engine->maxfiles && (*list)->cnt > ctx->engine->maxfiles)
845 845
 	    return CL_SUCCESS;
846 846
     } else if(*list && (*list)->cnt >= MAX_EMBEDDED_OBJ)
847 847
 	return CL_SUCCESS;
... ...
@@ -1990,30 +1990,29 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re
1990 1990
 	message *mainMessage = messageIn;
1991 1991
 	fileblob *fb;
1992 1992
 	bool infected = FALSE;
1993
-	const int doPhishingScan = mctx->ctx->engine->dboptions&CL_DB_PHISHING_URLS && (DCONF_PHISHING & PHISHING_CONF_ENGINE);
1994
-	const struct cl_limits *limits = mctx->ctx->limits;
1993
+	const struct cl_engine *engine = mctx->ctx->engine;
1994
+	const int doPhishingScan = engine->dboptions&CL_DB_PHISHING_URLS && (DCONF_PHISHING & PHISHING_CONF_ENGINE);
1995 1995
 
1996 1996
 	cli_dbgmsg("in parseEmailBody, %u files saved so far\n",
1997 1997
 		mctx->files);
1998 1998
 
1999
-	if(limits) { /* FIXMELIMITS: this should be better integrated */
2000
-		if(limits->maxreclevel)
2001
-			/*
2002
-			 * This is approximate
2003
-			 */
2004
-			if(recursion_level > limits->maxreclevel) {
1999
+	/* FIXMELIMITS: this should be better integrated */
2000
+	if(engine->maxreclevel)
2001
+		/*
2002
+		 * This is approximate
2003
+		 */
2004
+		if(recursion_level > engine->maxreclevel) {
2005 2005
 
2006 2006
 				cli_dbgmsg("parseEmailBody: hit maximum recursion level (%u)\n", recursion_level);
2007 2007
 				return MAXREC;
2008 2008
 			}
2009
-		if(limits->maxfiles && (mctx->files >= limits->maxfiles)) {
2010
-			/*
2011
-			 * FIXME: This is only approx - it may have already
2012
-			 * been exceeded
2013
-			 */
2014
-			cli_dbgmsg("parseEmailBody: number of files exceeded %u\n", limits->maxfiles);
2015
-			return MAXFILES;
2016
-		}
2009
+	if(engine->maxfiles && (mctx->files >= engine->maxfiles)) {
2010
+		/*
2011
+		 * FIXME: This is only approx - it may have already
2012
+		 * been exceeded
2013
+		 */
2014
+		cli_dbgmsg("parseEmailBody: number of files exceeded %u\n", engine->maxfiles);
2015
+		return MAXFILES;
2017 2016
 	}
2018 2017
 
2019 2018
 	rc = OK;
... ...
@@ -444,20 +444,19 @@ static int ole2_walk_property_tree(int fd, ole2_header_t *hdr, const char *dir,
444 444
 	int32_t idx, current_block, i;
445 445
 	char *dirname;
446 446
 	int ret;
447
-	const struct cl_limits *limits = ctx ? ctx->limits : NULL;
448 447
 
449 448
 	current_block = hdr->prop_start;
450 449
 
451 450
 	if ((prop_index < 0) || (prop_index > (int32_t) hdr->max_block_no) || (rec_level > 100) || (*file_count > 100000)) {
452 451
 		return CL_SUCCESS;
453 452
 	}
454
-	if (limits && limits->maxfiles && (*file_count > limits->maxfiles)) {
455
-		cli_dbgmsg("OLE2: File limit reached (max: %d)\n", limits->maxfiles);
453
+	if (ctx && ctx->engine->maxfiles && (*file_count > ctx->engine->maxfiles)) {
454
+		cli_dbgmsg("OLE2: File limit reached (max: %d)\n", ctx->engine->maxfiles);
456 455
 		return CL_SUCCESS;
457 456
 	}
458 457
 	
459
-	if (limits && limits->maxreclevel && (rec_level > limits->maxreclevel)) {
460
-		cli_dbgmsg("OLE2: Recursion limit reached (max: %d)\n", limits->maxreclevel);
458
+	if (ctx && ctx->engine->maxreclevel && (rec_level > ctx->engine->maxreclevel)) {
459
+		cli_dbgmsg("OLE2: Recursion limit reached (max: %d)\n", ctx->engine->maxreclevel);
461 460
 		return CL_SUCCESS;
462 461
 	}
463 462
 
... ...
@@ -518,11 +517,11 @@ static int ole2_walk_property_tree(int fd, ole2_header_t *hdr, const char *dir,
518 518
 			) return ret;
519 519
 			break;
520 520
 		case 2: /* File */
521
-			if (limits && limits->maxfiles && ctx->scannedfiles + *file_count > limits->maxfiles) {
522
-				cli_dbgmsg("OLE2: files limit reached (max: %u)\n", ctx->limits->maxfiles);
521
+			if (ctx && ctx->engine->maxfiles && ctx->scannedfiles + *file_count > ctx->engine->maxfiles) {
522
+				cli_dbgmsg("OLE2: files limit reached (max: %u)\n", ctx->engine->maxfiles);
523 523
 				return CL_BREAK;
524 524
 			}
525
-			if (!limits || !limits->maxfilesize || prop_block[idx].size <= limits->maxfilesize || prop_block[idx].size <= *scansize) {
525
+			if (!ctx || !ctx->engine->maxfilesize || prop_block[idx].size <= ctx->engine->maxfilesize || prop_block[idx].size <= *scansize) {
526 526
 				(*file_count)++;
527 527
 				*scansize-=prop_block[idx].size;
528 528
 				if ((ret=handler(fd, hdr, &prop_block[idx], dir, ctx)) != CL_SUCCESS)
... ...
@@ -897,9 +896,9 @@ int cli_ole2_extract(int fd, const char *dirname, cli_ctx *ctx, struct uniq **vb
897 897
 
898 898
 	cli_dbgmsg("in cli_ole2_extract()\n");
899 899
 
900
-	if (ctx && ctx->limits && ctx->limits->maxscansize) {
901
-	  if (ctx->limits->maxscansize > ctx->scansize)
902
-	    scansize = ctx->limits->maxscansize - ctx->scansize;
900
+	if (ctx && ctx->engine->maxscansize) {
901
+	  if (ctx->engine->maxscansize > ctx->scansize)
902
+	    scansize = ctx->engine->maxscansize - ctx->scansize;
903 903
 	  else
904 904
 	    return CL_EMAXSIZE;
905 905
 	} else scansize = -1;
... ...
@@ -197,35 +197,178 @@ const char *cl_strerror(int clerror)
197 197
     }
198 198
 }
199 199
 
200
+int cl_init(unsigned int options)
201
+{
202
+    /* put dlopen() stuff here, etc. */
203
+    return CL_SUCCESS;
204
+}
205
+
206
+struct cl_engine *cl_engine_new(unsigned int options)
207
+{
208
+	struct cl_engine *new;
209
+
210
+
211
+    new = (struct cl_engine *) cli_calloc(1, sizeof(struct cl_engine));
212
+    if(!new) {
213
+	cli_errmsg("cl_engine_new: Can't allocate memory for cl_engine\n");
214
+	return NULL;
215
+    }
216
+
217
+    /* Setup default limits */
218
+    new->maxscansize = 104857600;
219
+    new->maxfilesize = 26214400;
220
+    new->maxreclevel = 16;
221
+    new->maxfiles = 10000;
222
+    new->min_cc_count = 3;
223
+    new->min_ssn_count = 3;
224
+
225
+    new->refcount = 1;
226
+
227
+#ifdef USE_MPOOL
228
+    if(!(new->mempool = mp_create())) {
229
+	cli_errmsg("cl_engine_new: Can't allocate memory for memory pool\n");
230
+	free(new);
231
+	return NULL;
232
+    }
233
+#endif
234
+
235
+    new->root = mp_calloc(new->mempool, CLI_MTARGETS, sizeof(struct cli_matcher *));
236
+    if(!new->root) {
237
+	cli_errmsg("cl_engine_new: Can't allocate memory for roots\n");
238
+#ifdef USE_MPOOL
239
+	mp_destroy(new->mempool);
240
+#endif
241
+	free(new);
242
+	return NULL;
243
+    }
244
+
245
+    new->dconf = cli_mp_dconf_init(new->mempool);
246
+    if(!new->dconf) {
247
+	cli_errmsg("cl_engine_new: Can't initialize dynamic configuration\n");
248
+	mp_free(new->mempool, new->root);
249
+#ifdef USE_MPOOL
250
+	mp_destroy(new->mempool);
251
+#endif
252
+	free(new);
253
+	return NULL;
254
+    }
255
+
256
+    cli_dbgmsg("Initialized %s engine\n", cl_retver());
257
+    return new;
258
+}
259
+
260
+int cl_engine_set(struct cl_engine *engine, enum cl_engine_field field, const void *val)
261
+{
262
+    if(!engine || !val)
263
+	return CL_ENULLARG;
264
+
265
+    switch(field) {
266
+	case CL_ENGINE_MAX_SCANSIZE:
267
+	    engine->maxscansize = *((const uint64_t *) val);
268
+	    break;
269
+	case CL_ENGINE_MAX_FILESIZE:
270
+	    engine->maxfilesize = *((const uint64_t *) val);
271
+	    break;
272
+	case CL_ENGINE_MAX_RECURSION:
273
+	    engine->maxreclevel = *((const uint32_t *) val);
274
+	    break;
275
+	case CL_ENGINE_MAX_FILES:
276
+	    engine->maxfiles = *((const uint32_t *) val);
277
+	    break;
278
+	case CL_ENGINE_MIN_CC_COUNT:
279
+	    engine->min_cc_count = *((const uint32_t *) val);
280
+	    break;
281
+	case CL_ENGINE_MIN_SSN_COUNT:
282
+	    engine->min_ssn_count = *((const uint32_t *) val);
283
+	    break;
284
+	case CL_ENGINE_PUA_CATEGORIES:
285
+	    engine->pua_cats = cli_mp_strdup(engine->mempool, (const char *) val);
286
+	    if(!engine->pua_cats)
287
+		return CL_EMEM;
288
+	    break;
289
+	case CL_ENGINE_DB_VERSION:
290
+	case CL_ENGINE_DB_TIME:
291
+	    cli_warnmsg("cl_engine_set: The field is read only\n");
292
+	    return CL_SUCCESS;
293
+	default:
294
+	    cli_errmsg("cl_engine_set: Incorrect field number\n");
295
+	    return CL_ENULLARG; /* FIXME */
296
+    }
297
+
298
+    return CL_SUCCESS;
299
+}
300
+
301
+int cl_engine_get(const struct cl_engine *engine, enum cl_engine_field field, void *val)
302
+{
303
+    if(!engine || !val)
304
+	return CL_ENULLARG;
305
+
306
+    switch(field) {
307
+	case CL_ENGINE_MAX_SCANSIZE:
308
+	    *((uint64_t *) val) = engine->maxscansize;
309
+	    break;
310
+	case CL_ENGINE_MAX_FILESIZE:
311
+	    *((uint64_t *) val) = engine->maxfilesize;
312
+	    break;
313
+	case CL_ENGINE_MAX_RECURSION:
314
+	    *((uint32_t *) val) = engine->maxreclevel;
315
+	    break;
316
+	case CL_ENGINE_MAX_FILES:
317
+	    *((uint32_t *) val) = engine->maxfiles;
318
+	    break;
319
+	case CL_ENGINE_MIN_CC_COUNT:
320
+	    *((uint32_t *) val) = engine->min_cc_count;
321
+	    break;
322
+	case CL_ENGINE_MIN_SSN_COUNT:
323
+	    *((uint32_t *) val) = engine->min_ssn_count;
324
+	    break;
325
+	case CL_ENGINE_PUA_CATEGORIES:
326
+	    if(engine->pua_cats)
327
+		strncpy((char *) val, engine->pua_cats, 128);
328
+	    break;
329
+	case CL_ENGINE_DB_VERSION:
330
+	    *((uint32_t *) val) = engine->dbversion[0];
331
+	    break;
332
+	case CL_ENGINE_DB_TIME:
333
+	    *((uint32_t *) val) = engine->dbversion[1];
334
+	    break;
335
+	default:
336
+	    cli_errmsg("cl_engine_get: Incorrect field number\n");
337
+	    return CL_ENULLARG; /* FIXME */
338
+    }
339
+
340
+    return CL_SUCCESS;
341
+}
342
+
200 343
 int cli_checklimits(const char *who, cli_ctx *ctx, unsigned long need1, unsigned long need2, unsigned long need3) {
201 344
     int ret = CL_SUCCESS;
202 345
     unsigned long needed;
203 346
 
204 347
     /* if called without limits, go on, unpack, scan */
205
-    if(!ctx || !ctx->limits) return CL_CLEAN;
348
+    if(!ctx) return CL_CLEAN;
206 349
 
207 350
     needed = (need1>need2)?need1:need2;
208 351
     needed = (needed>need3)?needed:need3;
209 352
 
210 353
     /* if we have global scan limits */
211
-    if(needed && ctx->limits->maxscansize) {
354
+    if(needed && ctx->engine->maxscansize) {
212 355
         /* if the remaining scansize is too small... */
213
-        if(ctx->limits->maxscansize-ctx->scansize<needed) {
356
+        if(ctx->engine->maxscansize-ctx->scansize<needed) {
214 357
 	    /* ... we tell the caller to skip this file */
215
-	    cli_dbgmsg("%s: scansize exceeded (initial: %lu, remaining: %lu, needed: %lu)\n", who, ctx->limits->maxscansize, ctx->scansize, needed);
358
+	    cli_dbgmsg("%s: scansize exceeded (initial: %lu, remaining: %lu, needed: %lu)\n", who, ctx->engine->maxscansize, ctx->scansize, needed);
216 359
 	    ret = CL_EMAXSIZE;
217 360
 	}
218 361
     }
219 362
 
220 363
     /* if we have per-file size limits, and we are overlimit... */
221
-    if(needed && ctx->limits->maxfilesize && ctx->limits->maxfilesize<needed) {
364
+    if(needed && ctx->engine->maxfilesize && ctx->engine->maxfilesize<needed) {
222 365
 	/* ... we tell the caller to skip this file */
223
-        cli_dbgmsg("%s: filesize exceeded (allowed: %lu, needed: %lu)\n", who, ctx->limits->maxfilesize, needed);
366
+        cli_dbgmsg("%s: filesize exceeded (allowed: %lu, needed: %lu)\n", who, ctx->engine->maxfilesize, needed);
224 367
 	ret = CL_EMAXSIZE;
225 368
     }
226 369
 
227
-    if(ctx->limits->maxfiles && ctx->scannedfiles>=ctx->limits->maxfiles) {
228
-        cli_dbgmsg("%s: files limit reached (max: %u)\n", who, ctx->limits->maxfiles);
370
+    if(ctx->engine->maxfiles && ctx->scannedfiles>=ctx->engine->maxfiles) {
371
+        cli_dbgmsg("%s: files limit reached (max: %u)\n", who, ctx->engine->maxfiles);
229 372
 	return CL_EMAXFILES;
230 373
     }
231 374
     return ret;
... ...
@@ -237,8 +380,8 @@ int cli_updatelimits(cli_ctx *ctx, unsigned long needed) {
237 237
     if (ret != CL_CLEAN) return ret;
238 238
     ctx->scannedfiles++;
239 239
     ctx->scansize+=needed;
240
-    if(ctx->scansize > ctx->limits->maxscansize)
241
-        ctx->scansize = ctx->limits->maxscansize;
240
+    if(ctx->scansize > ctx->engine->maxscansize)
241
+        ctx->scansize = ctx->engine->maxscansize;
242 242
     return CL_CLEAN;
243 243
 }
244 244
 
... ...
@@ -18,6 +18,8 @@
18 18
  *  MA 02110-1301, USA.
19 19
  */
20 20
 
21
+#include "matcher.h"
22
+
21 23
 #ifndef __OTHERS_H_LC
22 24
 #define __OTHERS_H_LC
23 25
 
... ...
@@ -81,7 +83,6 @@ typedef struct {
81 81
     unsigned long int *scanned;
82 82
     const struct cli_matcher *root;
83 83
     const struct cl_engine *engine;
84
-    const struct cl_limits *limits;
85 84
     unsigned long scansize;
86 85
     unsigned int options;
87 86
     unsigned int recursion;
... ...
@@ -90,6 +91,69 @@ typedef struct {
90 90
     struct cli_dconf *dconf;
91 91
 } cli_ctx;
92 92
 
93
+struct cl_engine {
94
+    uint32_t refcount; /* reference counter */
95
+    uint32_t sdb;
96
+    uint32_t dboptions;
97
+    uint32_t dbversion[2];
98
+
99
+    /* Limits */
100
+    uint64_t maxscansize;  /* during the scanning of archives this size
101
+				     * will never be exceeded
102
+				     */
103
+    uint64_t maxfilesize;  /* compressed files will only be decompressed
104
+				     * and scanned up to this size
105
+				     */
106
+    uint32_t maxreclevel;	    /* maximum recursion level for archives */
107
+    uint32_t maxfiles;	    /* maximum number of files to be scanned
108
+				     * within a single archive
109
+				     */
110
+    /* This is for structured data detection.  You can set the minimum
111
+     * number of occurences of an CC# or SSN before the system will
112
+     * generate a notification.
113
+     */
114
+    uint32_t min_cc_count;
115
+    uint32_t min_ssn_count;
116
+
117
+    /* Roots table */
118
+    struct cli_matcher **root;
119
+
120
+    /* B-M matcher for standard MD5 sigs */
121
+    struct cli_matcher *md5_hdb;
122
+
123
+    /* B-M matcher for MD5 sigs for PE sections */
124
+    struct cli_matcher *md5_mdb;
125
+
126
+    /* B-M matcher for whitelist db */
127
+    struct cli_matcher *md5_fp;
128
+
129
+    /* Zip metadata */
130
+    struct cli_meta_node *zip_mlist;
131
+
132
+    /* RAR metadata */
133
+    struct cli_meta_node *rar_mlist;
134
+
135
+    /* Phishing .pdb and .wdb databases*/
136
+    struct regex_matcher *whitelist_matcher;
137
+    struct regex_matcher *domainlist_matcher;
138
+    struct phishcheck *phishcheck;
139
+
140
+    /* Dynamic configuration */
141
+    struct cli_dconf *dconf;
142
+
143
+    /* Filetype definitions */
144
+    struct cli_ftype *ftypes;
145
+
146
+    /* Ignored signatures */
147
+    struct cli_ignored *ignored;
148
+
149
+    /* PUA categories (to be included or excluded) */
150
+    char *pua_cats;
151
+
152
+    /* Used for memory pools */
153
+    mp_t *mempool;
154
+};
155
+
93 156
 #define SCAN_ARCHIVE	    (ctx->options & CL_SCAN_ARCHIVE)
94 157
 #define SCAN_MAIL	    (ctx->options & CL_SCAN_MAIL)
95 158
 #define SCAN_OLE2	    (ctx->options & CL_SCAN_OLE2)
... ...
@@ -124,13 +124,6 @@ struct cli_ignored {
124 124
     struct cli_ignsig *list;
125 125
 };
126 126
 
127
-/* Prototypes for old public functions just to shut up some gcc warnings;
128
- * to be removed in 1.0
129
- */
130
-int cl_loaddb(const char *filename, struct cl_engine **engine, unsigned int *signo);
131
-int cl_loaddbdir(const char *dirname, struct cl_engine **engine, unsigned int *signo);
132
-
133
-
134 127
 char *cli_virname(char *virname, unsigned int official)
135 128
 {
136 129
 	char *newname, *pt;
... ...
@@ -342,49 +335,6 @@ int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hex
342 342
     return CL_SUCCESS;
343 343
 }
344 344
 
345
-int cli_initengine(struct cl_engine **engine, unsigned int options)
346
-{
347
-	int ret;
348
-
349
-
350
-    if(!*engine) {
351
-	cli_dbgmsg("Initializing the engine (%s)\n", cl_retver());
352
-
353
-	*engine = (struct cl_engine *) cli_calloc(1, sizeof(struct cl_engine));
354
-	if(!*engine) {
355
-	    cli_errmsg("Can't allocate memory for the engine structure!\n");
356
-	    return CL_EMEM;
357
-	}
358
-
359
-	(*engine)->refcount = 1;
360
-
361
-#ifdef USE_MPOOL
362
-	if(!((*engine)->mempool = mp_create())) {
363
-	    cli_errmsg("Can't allocate memory for memory pool!\n");
364
-	    return CL_EMEM;
365
-	}
366
-#endif
367
-	(*engine)->root = mp_calloc((*engine)->mempool, CLI_MTARGETS, sizeof(struct cli_matcher *));
368
-	if(!(*engine)->root) {
369
-	    /* no need to free previously allocated memory here */
370
-	    cli_errmsg("Can't allocate memory for roots!\n");
371
-	    return CL_EMEM;
372
-	}
373
-
374
-	(*engine)->dconf = cli_mp_dconf_init((*engine)->mempool);
375
-	if(!(*engine)->dconf) {
376
-	    cli_errmsg("Can't initialize dynamic configuration\n");
377
-	    return CL_EMEM;
378
-	}
379
-
380
-	if((options & CL_DB_PHISHING_URLS) && (((struct cli_dconf*) (*engine)->dconf)->phishing & PHISHING_CONF_ENGINE))
381
-	    if((ret = phishing_init(*engine)))
382
-		return ret;
383
-    }
384
-
385
-    return CL_SUCCESS;
386
-}
387
-
388 345
 static int cli_initroots(struct cl_engine *engine, unsigned int options)
389 346
 {
390 347
 	int i, ret;
... ...
@@ -508,7 +458,7 @@ static int cli_chkpua(const char *signame, const char *pua_cats, unsigned int op
508 508
     return ret;
509 509
 }
510 510
 
511
-static int cli_loaddb(FILE *fs, struct cl_engine **engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio, const char *dbname)
511
+static int cli_loaddb(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio, const char *dbname)
512 512
 {
513 513
 	char buffer[FILEBUFF], *pt, *start;
514 514
 	unsigned int line = 0, sigs = 0;
... ...
@@ -516,12 +466,10 @@ static int cli_loaddb(FILE *fs, struct cl_engine **engine, unsigned int *signo,
516 516
 	struct cli_matcher *root;
517 517
 
518 518
 
519
-    if((ret = cli_initroots(*engine, options))) {
520
-	cl_free(*engine);
519
+    if((ret = cli_initroots(engine, options)))
521 520
 	return ret;
522
-    }
523 521
 
524
-    root = (*engine)->root[0];
522
+    root = engine->root[0];
525 523
 
526 524
     while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) {
527 525
 	line++;
... ...
@@ -537,7 +485,7 @@ static int cli_loaddb(FILE *fs, struct cl_engine **engine, unsigned int *signo,
537 537
 	start = buffer;
538 538
 	*pt++ = 0;
539 539
 
540
-	if((*engine)->ignored && cli_chkign((*engine)->ignored, dbname, line, start))
540
+	if(engine->ignored && cli_chkign(engine->ignored, dbname, line, start))
541 541
 	    continue;
542 542
 
543 543
 	if(*pt == '=') continue;
... ...
@@ -551,13 +499,11 @@ static int cli_loaddb(FILE *fs, struct cl_engine **engine, unsigned int *signo,
551 551
 
552 552
     if(!line) {
553 553
 	cli_errmsg("Empty database file\n");
554
-	cl_free(*engine);
555 554
 	return CL_EMALFDB;
556 555
     }
557 556
 
558 557
     if(ret) {
559 558
 	cli_errmsg("Problem parsing database at line %d\n", line);
560
-	cl_free(*engine);
561 559
 	return ret;
562 560
     }
563 561
 
... ...
@@ -567,50 +513,46 @@ static int cli_loaddb(FILE *fs, struct cl_engine **engine, unsigned int *signo,
567 567
     return CL_SUCCESS;
568 568
 }
569 569
 
570
-static int cli_loadwdb(FILE *fs, struct cl_engine **engine, unsigned int options, struct cli_dbio *dbio)
570
+static int cli_loadwdb(FILE *fs, struct cl_engine *engine, unsigned int options, struct cli_dbio *dbio)
571 571
 {
572 572
 	int ret = 0;
573 573
 
574 574
 
575
-    if(!(((struct cli_dconf *) (*engine)->dconf)->phishing & PHISHING_CONF_ENGINE))
575
+    if(!(engine->dconf->phishing & PHISHING_CONF_ENGINE))
576 576
 	return CL_SUCCESS;
577 577
 
578
-    if(!(*engine)->whitelist_matcher) {
579
-	if((ret = init_whitelist(*engine))) {
580
-	    phishing_done(*engine);
581
-	    cl_free(*engine);
578
+    if(!engine->whitelist_matcher) {
579
+	if((ret = init_whitelist(engine))) {
580
+	    phishing_done(engine);
582 581
 	    return ret;
583 582
 	}
584 583
     }
585 584
 
586
-    if((ret = load_regex_matcher((*engine)->whitelist_matcher, fs, options, 1, dbio))) {
587
-	phishing_done(*engine);
588
-	cl_free(*engine);
585
+    if((ret = load_regex_matcher(engine->whitelist_matcher, fs, options, 1, dbio))) {
586
+	phishing_done(engine);
589 587
 	return ret;
590 588
     }
591 589
 
592 590
     return CL_SUCCESS;
593 591
 }
594 592
 
595
-static int cli_loadpdb(FILE *fs, struct cl_engine **engine, unsigned int options, struct cli_dbio *dbio)
593
+static int cli_loadpdb(FILE *fs, struct cl_engine *engine, unsigned int options, struct cli_dbio *dbio)
596 594
 {
597 595
 	int ret = 0;
598 596
 
599 597
 
600
-    if(!(((struct cli_dconf *) (*engine)->dconf)->phishing & PHISHING_CONF_ENGINE))
598
+    if(!(engine->dconf->phishing & PHISHING_CONF_ENGINE))
601 599
 	return CL_SUCCESS;
602 600
 
603
-    if(!(*engine)->domainlist_matcher) {
604
-	if((ret = init_domainlist(*engine))) {
605
-	    phishing_done(*engine);
606
-	    cl_free(*engine);
601
+    if(!engine->domainlist_matcher) {
602
+	if((ret = init_domainlist(engine))) {
603
+	    phishing_done(engine);
607 604
 	    return ret;
608 605
 	}
609 606
     }
610 607
 
611
-    if((ret = load_regex_matcher((*engine)->domainlist_matcher, fs, options, 0, dbio))) {
612
-	phishing_done(*engine);
613
-	cl_free(*engine);
608
+    if((ret = load_regex_matcher(engine->domainlist_matcher, fs, options, 0, dbio))) {
609
+	phishing_done(engine);
614 610
 	return ret;
615 611
     }
616 612
 
... ...
@@ -618,7 +560,7 @@ static int cli_loadpdb(FILE *fs, struct cl_engine **engine, unsigned int options
618 618
 }
619 619
 
620 620
 #define NDB_TOKENS 6
621
-static int cli_loadndb(FILE *fs, struct cl_engine **engine, unsigned int *signo, unsigned short sdb, unsigned int options, struct cli_dbio *dbio, const char *dbname)
621
+static int cli_loadndb(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned short sdb, unsigned int options, struct cli_dbio *dbio, const char *dbname)
622 622
 {
623 623
 	const char *tokens[NDB_TOKENS];
624 624
 	char buffer[FILEBUFF];
... ...
@@ -629,10 +571,8 @@ static int cli_loadndb(FILE *fs, struct cl_engine **engine, unsigned int *signo,
629 629
 	unsigned int phish = options & CL_DB_PHISHING;
630 630
 
631 631
 
632
-    if((ret = cli_initroots(*engine, options))) {
633
-	cl_free(*engine);
632
+    if((ret = cli_initroots(engine, options)))
634 633
 	return ret;
635
-    }
636 634
 
637 635
     while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) {
638 636
 	line++;
... ...
@@ -653,11 +593,11 @@ static int cli_loadndb(FILE *fs, struct cl_engine **engine, unsigned int *signo,
653 653
 	    break;
654 654
 	}
655 655
 
656
-	if((*engine)->pua_cats && (options & CL_DB_PUA_MODE) && (options & (CL_DB_PUA_INCLUDE | CL_DB_PUA_EXCLUDE)))
657
-	    if(cli_chkpua(virname, (*engine)->pua_cats, options))
656
+	if(engine->pua_cats && (options & CL_DB_PUA_MODE) && (options & (CL_DB_PUA_INCLUDE | CL_DB_PUA_EXCLUDE)))
657
+	    if(cli_chkpua(virname, engine->pua_cats, options))
658 658
 		continue;
659 659
 
660
-	if((*engine)->ignored && cli_chkign((*engine)->ignored, dbname, line, virname))
660
+	if(engine->ignored && cli_chkign(engine->ignored, dbname, line, virname))
661 661
 	    continue;
662 662
 
663 663
 	if((pt = tokens[4])) { /* min version */
... ...
@@ -696,7 +636,7 @@ static int cli_loadndb(FILE *fs, struct cl_engine **engine, unsigned int *signo,
696 696
 	    continue;
697 697
 	}
698 698
 
699
-	root = (*engine)->root[target];
699
+	root = engine->root[target];
700 700
 
701 701
 	if(!(offset = tokens[2])) {
702 702
 	    ret = CL_EMALFDB;
... ...
@@ -719,21 +659,19 @@ static int cli_loadndb(FILE *fs, struct cl_engine **engine, unsigned int *signo,
719 719
 
720 720
     if(!line) {
721 721
 	cli_errmsg("Empty database file\n");
722
-	cl_free(*engine);
723 722
 	return CL_EMALFDB;
724 723
     }
725 724
 
726 725
     if(ret) {
727 726
 	cli_errmsg("Problem parsing database at line %d\n", line);
728
-	cl_free(*engine);
729 727
 	return ret;
730 728
     }
731 729
 
732 730
     if(signo)
733 731
 	*signo += sigs;
734 732
 
735
-    if(sdb && sigs && !(*engine)->sdb) {
736
-	(*engine)->sdb = 1;
733
+    if(sdb && sigs && !engine->sdb) {
734
+	engine->sdb = 1;
737 735
 	cli_dbgmsg("*** Self protection mechanism activated.\n");
738 736
     }
739 737
 
... ...
@@ -900,7 +838,7 @@ static int lsigattribs(char *attribs, struct cli_lsig_tdb *tdb)
900 900
   } while(0);
901 901
 
902 902
 #define LDB_TOKENS 67
903
-static int cli_loadldb(FILE *fs, struct cl_engine **engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio, const char *dbname)
903
+static int cli_loadldb(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio, const char *dbname)
904 904
 {
905 905
 	char *tokens[LDB_TOKENS];
906 906
 	char buffer[32768], *pt;
... ...
@@ -914,10 +852,8 @@ static int cli_loadldb(FILE *fs, struct cl_engine **engine, unsigned int *signo,
914 914
 	struct cli_lsig_tdb tdb;
915 915
 
916 916
 
917
-    if((ret = cli_initroots(*engine, options))) {
918
-	cl_free(*engine);
917
+    if((ret = cli_initroots(engine, options)))
919 918
 	return ret;
920
-    }
921 919
 
922 920
     while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) {
923 921
 	line++;
... ...
@@ -931,11 +867,11 @@ static int cli_loadldb(FILE *fs, struct cl_engine **engine, unsigned int *signo,
931 931
 	    break;
932 932
 	}
933 933
 
934
-	if((*engine)->pua_cats && (options & CL_DB_PUA_MODE) && (options & (CL_DB_PUA_INCLUDE | CL_DB_PUA_EXCLUDE)))
935
-	    if(cli_chkpua(virname, (*engine)->pua_cats, options))
934
+	if(engine->pua_cats && (options & CL_DB_PUA_MODE) && (options & (CL_DB_PUA_INCLUDE | CL_DB_PUA_EXCLUDE)))
935
+	    if(cli_chkpua(virname, engine->pua_cats, options))
936 936
 		continue;
937 937
 
938
-	if((*engine)->ignored && cli_chkign((*engine)->ignored, dbname, line, virname))
938
+	if(engine->ignored && cli_chkign(engine->ignored, dbname, line, virname))
939 939
 	    continue;
940 940
 
941 941
 	if(!(logic = tokens[2])) {
... ...
@@ -959,7 +895,7 @@ static int cli_loadldb(FILE *fs, struct cl_engine **engine, unsigned int *signo,
959 959
 	/* TDB */
960 960
 	memset(&tdb, 0, sizeof(tdb));
961 961
 #ifdef USE_MPOOL
962
-	tdb.mempool = (*engine)->mempool;
962
+	tdb.mempool = engine->mempool;
963 963
 #endif
964 964
 
965 965
 	if(lsigattribs(tokens[1], &tdb) == -1) {
... ...
@@ -993,9 +929,9 @@ static int cli_loadldb(FILE *fs, struct cl_engine **engine, unsigned int *signo,
993 993
 	    continue;
994 994
 	}
995 995
 
996
-	root = (*engine)->root[tdb.target[0]];
996
+	root = engine->root[tdb.target[0]];
997 997
 
998
-	lsig = (struct cli_ac_lsig *) mp_calloc((*engine)->mempool, 1, sizeof(struct cli_ac_lsig));
998
+	lsig = (struct cli_ac_lsig *) mp_calloc(engine->mempool, 1, sizeof(struct cli_ac_lsig));
999 999
 	if(!lsig) {
1000 1000
 	    cli_errmsg("cli_loadldb: Can't allocate memory for lsig\n");
1001 1001
 	    FREE_TDB(tdb);
... ...
@@ -1003,12 +939,12 @@ static int cli_loadldb(FILE *fs, struct cl_engine **engine, unsigned int *signo,
1003 1003
 	    break;
1004 1004
 	}
1005 1005
 
1006
-	lsig->logic = cli_mp_strdup((*engine)->mempool, logic);
1006
+	lsig->logic = cli_mp_strdup(engine->mempool, logic);
1007 1007
 	if(!lsig->logic) {
1008 1008
 	    cli_errmsg("cli_loadldb: Can't allocate memory for lsig->logic\n");
1009 1009
 	    FREE_TDB(tdb);
1010 1010
 	    ret = CL_EMEM;
1011
-	    mp_free((*engine)->mempool, lsig);
1011
+	    mp_free(engine->mempool, lsig);
1012 1012
 	    break;
1013 1013
 	}
1014 1014
 
... ...
@@ -1016,12 +952,12 @@ static int cli_loadldb(FILE *fs, struct cl_engine **engine, unsigned int *signo,
1016 1016
 	memcpy(&lsig->tdb, &tdb, sizeof(tdb));
1017 1017
 
1018 1018
 	root->ac_lsigs++;
1019
-	newtable = (struct cli_ac_lsig **) mp_realloc((*engine)->mempool, root->ac_lsigtable, root->ac_lsigs * sizeof(struct cli_ac_lsig *));
1019
+	newtable = (struct cli_ac_lsig **) mp_realloc(engine->mempool, root->ac_lsigtable, root->ac_lsigs * sizeof(struct cli_ac_lsig *));
1020 1020
 	if(!newtable) {
1021 1021
 	    root->ac_lsigs--;
1022 1022
 	    cli_errmsg("cli_loadldb: Can't realloc root->ac_lsigtable\n");
1023 1023
 	    FREE_TDB(tdb);
1024
-	    mp_free((*engine)->mempool, lsig);
1024
+	    mp_free(engine->mempool, lsig);
1025 1025
 	    ret = CL_EMEM;
1026 1026
 	    break;
1027 1027
 	}
... ...
@@ -1059,13 +995,11 @@ static int cli_loadldb(FILE *fs, struct cl_engine **engine, unsigned int *signo,
1059 1059
 
1060 1060
     if(!line) {
1061 1061
 	cli_errmsg("Empty database file\n");
1062
-	cl_free(*engine);
1063 1062
 	return CL_EMALFDB;
1064 1063
     }
1065 1064
 
1066 1065
     if(ret) {
1067 1066
 	cli_errmsg("Problem parsing database at line %u\n", line);
1068
-	cl_free(*engine);
1069 1067
 	return ret;
1070 1068
     }
1071 1069
 
... ...
@@ -1076,7 +1010,7 @@ static int cli_loadldb(FILE *fs, struct cl_engine **engine, unsigned int *signo,
1076 1076
 }
1077 1077
 
1078 1078
 #define FTM_TOKENS 8	
1079
-static int cli_loadftm(FILE *fs, struct cl_engine **engine, unsigned int options, unsigned int internal, struct cli_dbio *dbio)
1079
+static int cli_loadftm(FILE *fs, struct cl_engine *engine, unsigned int options, unsigned int internal, struct cli_dbio *dbio)
1080 1080
 {
1081 1081
 	const char *tokens[FTM_TOKENS], *pt;
1082 1082
 	char buffer[FILEBUFF];
... ...
@@ -1086,10 +1020,8 @@ static int cli_loadftm(FILE *fs, struct cl_engine **engine, unsigned int options
1086 1086
 	int ret;
1087 1087
 
1088 1088
 
1089
-    if((ret = cli_initroots(*engine, options))) {
1090
-	cl_free(*engine);
1089
+    if((ret = cli_initroots(engine, options)))
1091 1090
 	return ret;
1092
-    }
1093 1091
 
1094 1092
     while(1) {
1095 1093
 	if(internal) {
... ...
@@ -1137,34 +1069,34 @@ static int cli_loadftm(FILE *fs, struct cl_engine **engine, unsigned int options
1137 1137
 	}
1138 1138
 
1139 1139
 	if(atoi(tokens[0]) == 1) { /* A-C */
1140
-	    if((ret = cli_parse_add((*engine)->root[0], tokens[3], tokens[2], rtype, type, strcmp(tokens[1], "*") ? tokens[1] : NULL, 0, NULL, options)))
1140
+	    if((ret = cli_parse_add(engine->root[0], tokens[3], tokens[2], rtype, type, strcmp(tokens[1], "*") ? tokens[1] : NULL, 0, NULL, options)))
1141 1141
 		break;
1142 1142
 
1143 1143
 	} else if(atoi(tokens[0]) == 0) { /* memcmp() */
1144
-	    new = (struct cli_ftype *) mp_malloc((*engine)->mempool, sizeof(struct cli_ftype));
1144
+	    new = (struct cli_ftype *) mp_malloc(engine->mempool, sizeof(struct cli_ftype));
1145 1145
 	    if(!new) {
1146 1146
 		ret = CL_EMEM;
1147 1147
 		break;
1148 1148
 	    }
1149 1149
 	    new->type = type;
1150 1150
 	    new->offset = atoi(tokens[1]);
1151
-	    new->magic = (unsigned char *) cli_mp_hex2str((*engine)->mempool, tokens[2]);
1151
+	    new->magic = (unsigned char *) cli_mp_hex2str(engine->mempool, tokens[2]);
1152 1152
 	    if(!new->magic) {
1153 1153
 		cli_errmsg("cli_loadftm: Can't decode the hex string\n");
1154 1154
 		ret = CL_EMALFDB;
1155
-		mp_free((*engine)->mempool, new);
1155
+		mp_free(engine->mempool, new);
1156 1156
 		break;
1157 1157
 	    }
1158 1158
 	    new->length = strlen(tokens[2]) / 2;
1159
-	    new->tname = cli_mp_strdup((*engine)->mempool, tokens[3]);
1159
+	    new->tname = cli_mp_strdup(engine->mempool, tokens[3]);
1160 1160
 	    if(!new->tname) {
1161
-		mp_free((*engine)->mempool, new->magic);
1162
-		mp_free((*engine)->mempool, new);
1161
+		mp_free(engine->mempool, new->magic);
1162
+		mp_free(engine->mempool, new);
1163 1163
 		ret = CL_EMEM;
1164 1164
 		break;
1165 1165
 	    }
1166
-	    new->next = (*engine)->ftypes;
1167
-	    (*engine)->ftypes = new;
1166
+	    new->next = engine->ftypes;
1167
+	    engine->ftypes = new;
1168 1168
 
1169 1169
 	} else {
1170 1170
 	    cli_dbgmsg("cli_loadftm: Unsupported mode %u\n", atoi(tokens[0]));
... ...
@@ -1175,13 +1107,11 @@ static int cli_loadftm(FILE *fs, struct cl_engine **engine, unsigned int options
1175 1175
 
1176 1176
     if(ret) {
1177 1177
 	cli_errmsg("Problem parsing %s filetype database at line %u\n", internal ? "built-in" : "external", line);
1178
-	cl_free(*engine);
1179 1178
 	return ret;
1180 1179
     }
1181 1180
 
1182 1181
     if(!sigs) {
1183 1182
 	cli_errmsg("Empty %s filetype database\n", internal ? "built-in" : "external");
1184
-	cl_free(*engine);
1185 1183
 	return CL_EMALFDB;
1186 1184
     }
1187 1185
 
... ...
@@ -1190,22 +1120,19 @@ static int cli_loadftm(FILE *fs, struct cl_engine **engine, unsigned int options
1190 1190
 }
1191 1191
 
1192 1192
 #define IGN_TOKENS 3
1193
-static int cli_loadign(FILE *fs, struct cl_engine **engine, unsigned int options, struct cli_dbio *dbio)
1193
+static int cli_loadign(FILE *fs, struct cl_engine *engine, unsigned int options, struct cli_dbio *dbio)
1194 1194
 {
1195 1195
 	const char *tokens[IGN_TOKENS];
1196 1196
 	char buffer[FILEBUFF];
1197 1197
 	unsigned int line = 0;
1198 1198
 	struct cli_ignsig *new;
1199
-	struct cli_ignored *ignored;
1200 1199
 	int ret = CL_SUCCESS;
1201 1200
 
1202 1201
 
1203
-    if(!(ignored = (*engine)->ignored)) {
1204
-	ignored = (*engine)->ignored = (struct cli_ignored *) cli_calloc(sizeof(struct cli_ignored), 1);
1205
-	if(!ignored || hashset_init(&ignored->hs, 64, 50)) {
1206
-	    cl_free(*engine);
1202
+    if(!engine->ignored) {
1203
+	engine->ignored = (struct cli_ignored *) cli_calloc(sizeof(struct cli_ignored), 1);
1204
+	if(!engine->ignored || hashset_init(&engine->ignored->hs, 64, 50))
1207 1205
 	    return CL_EMEM;
1208
-	}
1209 1206
     }
1210 1207
 
1211 1208
     while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) {
... ...
@@ -1213,40 +1140,39 @@ static int cli_loadign(FILE *fs, struct cl_engine **engine, unsigned int options
1213 1213
 	cli_chomp(buffer);
1214 1214
 	cli_strtokenize(buffer, ':', IGN_TOKENS, tokens);
1215 1215
 
1216
-	new = (struct cli_ignsig *) mp_calloc((*engine)->mempool, 1, sizeof(struct cli_ignsig));
1216
+	new = (struct cli_ignsig *) mp_calloc(engine->mempool, 1, sizeof(struct cli_ignsig));
1217 1217
 	if(!new) {
1218 1218
 	    ret = CL_EMEM;
1219 1219
 	    break;
1220 1220
 	}
1221 1221
 
1222
-	new->dbname = cli_mp_strdup((*engine)->mempool, tokens[0]);
1222
+	new->dbname = cli_mp_strdup(engine->mempool, tokens[0]);
1223 1223
 
1224 1224
 	if(!new->dbname) {
1225
-	    mp_free((*engine)->mempool, new);
1225
+	    mp_free(engine->mempool, new);
1226 1226
 	    ret = CL_EMALFDB;
1227 1227
 	    break;
1228 1228
 	}
1229 1229
 
1230 1230
 	new->line = atoi(tokens[1]);
1231 1231
 
1232
-	if((ret = hashset_addkey(&ignored->hs, new->line)))
1232
+	if((ret = hashset_addkey(&engine->ignored->hs, new->line)))
1233 1233
 	    break;
1234 1234
 
1235
-	new->signame = cli_mp_strdup((*engine)->mempool, tokens[2]);
1235
+	new->signame = cli_mp_strdup(engine->mempool, tokens[2]);
1236 1236
 	if(!new->signame) {
1237
-	    mp_free((*engine)->mempool, new->dbname);
1238
-	    mp_free((*engine)->mempool, new);
1237
+	    mp_free(engine->mempool, new->dbname);
1238
+	    mp_free(engine->mempool, new);
1239 1239
 	    ret = CL_EMALFDB;
1240 1240
 	    break;
1241 1241
 	}
1242 1242
 
1243
-	new->next = ignored->list;
1244
-	ignored->list = new;
1243
+	new->next = engine->ignored->list;
1244
+	engine->ignored->list = new;
1245 1245
     }
1246 1246
 
1247 1247
     if(ret) {
1248 1248
 	cli_errmsg("cli_loadign: Problem parsing database at line %u\n", line);
1249
-	cl_free(*engine);
1250 1249
 	return ret;
1251 1250
     }
1252 1251
 
... ...
@@ -1281,24 +1207,24 @@ static int scomp(const void *a, const void *b)
1281 1281
 #define MD5_MDB	    1
1282 1282
 #define MD5_FP	    2
1283 1283
 
1284
-static int cli_md5db_init(struct cl_engine **engine, unsigned int mode)
1284
+static int cli_md5db_init(struct cl_engine *engine, unsigned int mode)
1285 1285
 {
1286 1286
 	struct cli_matcher *bm = NULL;
1287 1287
 	int ret;
1288 1288
 
1289 1289
 
1290 1290
     if(mode == MD5_HDB) {
1291
-	bm = (*engine)->md5_hdb = (struct cli_matcher *) mp_calloc((*engine)->mempool, sizeof(struct cli_matcher), 1);
1291
+	bm = engine->md5_hdb = (struct cli_matcher *) mp_calloc(engine->mempool, sizeof(struct cli_matcher), 1);
1292 1292
     } else if(mode == MD5_MDB) {
1293
-	bm = (*engine)->md5_mdb = (struct cli_matcher *) mp_calloc((*engine)->mempool, sizeof(struct cli_matcher), 1);
1293
+	bm = engine->md5_mdb = (struct cli_matcher *) mp_calloc(engine->mempool, sizeof(struct cli_matcher), 1);
1294 1294
     } else {
1295
-	bm = (*engine)->md5_fp = (struct cli_matcher *) mp_calloc((*engine)->mempool, sizeof(struct cli_matcher), 1);
1295
+	bm = engine->md5_fp = (struct cli_matcher *) mp_calloc(engine->mempool, sizeof(struct cli_matcher), 1);
1296 1296
     }
1297 1297
 
1298 1298
     if(!bm)
1299 1299
 	return CL_EMEM;
1300 1300
 #ifdef USE_MPOOL
1301
-    bm->mempool = (*engine)->mempool;
1301
+    bm->mempool = engine->mempool;
1302 1302
 #endif
1303 1303
     if((ret = cli_bm_init(bm))) {
1304 1304
 	cli_errmsg("cli_md5db_init: Failed to initialize B-M\n");
... ...
@@ -1310,14 +1236,14 @@ static int cli_md5db_init(struct cl_engine **engine, unsigned int mode)
1310 1310
 
1311 1311
 #define MD5_DB			    \
1312 1312
     if(mode == MD5_HDB)		    \
1313
-	db = (*engine)->md5_hdb;    \
1313
+	db = engine->md5_hdb;    \
1314 1314
     else if(mode == MD5_MDB)	    \
1315
-	db = (*engine)->md5_mdb;    \
1315
+	db = engine->md5_mdb;    \
1316 1316
     else			    \
1317
-	db = (*engine)->md5_fp;
1317
+	db = engine->md5_fp;
1318 1318
 
1319 1319
 #define MD5_TOKENS 3
1320
-static int cli_loadmd5(FILE *fs, struct cl_engine **engine, unsigned int *signo, unsigned int mode, unsigned int options, struct cli_dbio *dbio, const char *dbname)
1320
+static int cli_loadmd5(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int mode, unsigned int options, struct cli_dbio *dbio, const char *dbname)
1321 1321
 {
1322 1322
 	const char *tokens[MD5_TOKENS];
1323 1323
 	char buffer[FILEBUFF];
... ...
@@ -1344,54 +1270,54 @@ static int cli_loadmd5(FILE *fs, struct cl_engine **engine, unsigned int *signo,
1344 1344
 	    break;
1345 1345
 	}
1346 1346
 
1347
-	if((*engine)->pua_cats && (options & CL_DB_PUA_MODE) && (options & (CL_DB_PUA_INCLUDE | CL_DB_PUA_EXCLUDE)))
1348
-	    if(cli_chkpua(pt, (*engine)->pua_cats, options))
1347
+	if(engine->pua_cats && (options & CL_DB_PUA_MODE) && (options & (CL_DB_PUA_INCLUDE | CL_DB_PUA_EXCLUDE)))
1348
+	    if(cli_chkpua(pt, engine->pua_cats, options))
1349 1349
 		continue;
1350 1350
 
1351
-	if((*engine)->ignored && cli_chkign((*engine)->ignored, dbname, line, pt))
1351
+	if(engine->ignored && cli_chkign(engine->ignored, dbname, line, pt))
1352 1352
 	    continue;
1353 1353
 
1354
-	new = (struct cli_bm_patt *) mp_calloc((*engine)->mempool, 1, sizeof(struct cli_bm_patt));
1354
+	new = (struct cli_bm_patt *) mp_calloc(engine->mempool, 1, sizeof(struct cli_bm_patt));
1355 1355
 	if(!new) {
1356 1356
 	    ret = CL_EMEM;
1357 1357
 	    break;
1358 1358
 	}
1359 1359
 
1360 1360
 	if(!(pt = tokens[md5_field])) {
1361
-	    mp_free((*engine)->mempool, new);
1361
+	    mp_free(engine->mempool, new);
1362 1362
 	    ret = CL_EMALFDB;
1363 1363
 	    break;
1364 1364
 	}
1365 1365
 
1366
-	if(strlen(pt) != 32 || !(new->pattern = (unsigned char *) cli_mp_hex2str((*engine)->mempool, pt))) {
1366
+	if(strlen(pt) != 32 || !(new->pattern = (unsigned char *) cli_mp_hex2str(engine->mempool, pt))) {
1367 1367
 	    cli_errmsg("cli_loadmd5: Malformed MD5 string at line %u\n", line);
1368
-	    mp_free((*engine)->mempool, new);
1368
+	    mp_free(engine->mempool, new);
1369 1369
 	    ret = CL_EMALFDB;
1370 1370
 	    break;
1371 1371
 	}
1372 1372
 	new->length = 16;
1373 1373
 
1374 1374
 	if(!(pt = tokens[size_field])) {
1375
-	    mp_free((*engine)->mempool, new->pattern);
1376
-	    mp_free((*engine)->mempool, new);
1375
+	    mp_free(engine->mempool, new->pattern);
1376
+	    mp_free(engine->mempool, new);
1377 1377
 	    ret = CL_EMALFDB;
1378 1378
 	    break;
1379 1379
 	}
1380 1380
 	size = atoi(pt);
1381 1381
 
1382
-	new->virname = cli_mp_virname((*engine)->mempool, (char *) tokens[2], options & CL_DB_OFFICIAL);
1382
+	new->virname = cli_mp_virname(engine->mempool, (char *) tokens[2], options & CL_DB_OFFICIAL);
1383 1383
 	if(!new->virname) {
1384
-	    mp_free((*engine)->mempool, new->pattern);
1385
-	    mp_free((*engine)->mempool, new);
1384
+	    mp_free(engine->mempool, new->pattern);
1385
+	    mp_free(engine->mempool, new);
1386 1386
 	    ret = CL_EMALFDB;
1387 1387
 	    break;
1388 1388
 	}
1389 1389
 
1390 1390
 	MD5_DB;
1391 1391
 	if(!db && (ret = cli_md5db_init(engine, mode))) {
1392
-	    mp_free((*engine)->mempool, new->pattern);
1393
-	    mp_free((*engine)->mempool, new->virname);
1394
-	    mp_free((*engine)->mempool, new);
1392
+	    mp_free(engine->mempool, new->pattern);
1393
+	    mp_free(engine->mempool, new->virname);
1394
+	    mp_free(engine->mempool, new);
1395 1395
 	    break;
1396 1396
 	} else {
1397 1397
 	    MD5_DB;
... ...
@@ -1399,9 +1325,9 @@ static int cli_loadmd5(FILE *fs, struct cl_engine **engine, unsigned int *signo,
1399 1399
 
1400 1400
 	if((ret = cli_bm_addpatt(db, new))) {
1401 1401
 	    cli_errmsg("cli_loadmd5: Error adding BM pattern\n");
1402
-	    mp_free((*engine)->mempool, new->pattern);
1403
-	    mp_free((*engine)->mempool, new->virname);
1404
-	    mp_free((*engine)->mempool, new);
1402
+	    mp_free(engine->mempool, new->pattern);
1403
+	    mp_free(engine->mempool, new->virname);
1404
+	    mp_free(engine->mempool, new);
1405 1405
 	    break;
1406 1406
 	}
1407 1407
 
... ...
@@ -1417,13 +1343,11 @@ static int cli_loadmd5(FILE *fs, struct cl_engine **engine, unsigned int *signo,
1417 1417
 
1418 1418
     if(!line) {
1419 1419
 	cli_errmsg("cli_loadmd5: Empty database file\n");
1420
-	cl_free(*engine);
1421 1420
 	return CL_EMALFDB;
1422 1421
     }
1423 1422
 
1424 1423
     if(ret) {
1425 1424
 	cli_errmsg("cli_loadmd5: Problem parsing database at line %u\n", line);
1426
-	cl_free(*engine);
1427 1425
 	return ret;
1428 1426
     }
1429 1427
 
... ...
@@ -1434,7 +1358,7 @@ static int cli_loadmd5(FILE *fs, struct cl_engine **engine, unsigned int *signo,
1434 1434
 }
1435 1435
 
1436 1436
 #define MD_TOKENS 9
1437
-static int cli_loadmd(FILE *fs, struct cl_engine **engine, unsigned int *signo, int type, unsigned int options, struct cli_dbio *dbio, const char *dbname)
1437
+static int cli_loadmd(FILE *fs, struct cl_engine *engine, unsigned int *signo, int type, unsigned int options, struct cli_dbio *dbio, const char *dbname)
1438 1438
 {
1439 1439
 	const char *tokens[MD_TOKENS];
1440 1440
 	char buffer[FILEBUFF];
... ...
@@ -1451,35 +1375,35 @@ static int cli_loadmd(FILE *fs, struct cl_engine **engine, unsigned int *signo,
1451 1451
 	cli_chomp(buffer);
1452 1452
 	cli_strtokenize(buffer, ':', MD_TOKENS, tokens);
1453 1453
 
1454
-	new = (struct cli_meta_node *) mp_calloc((*engine)->mempool, 1, sizeof(struct cli_meta_node));
1454
+	new = (struct cli_meta_node *) mp_calloc(engine->mempool, 1, sizeof(struct cli_meta_node));
1455 1455
 	if(!new) {
1456 1456
 	    ret = CL_EMEM;
1457 1457
 	    break;
1458 1458
 	}
1459 1459
 
1460
-	new->virname = cli_mp_virname((*engine)->mempool, (char *)tokens[0], options & CL_DB_OFFICIAL);
1460
+	new->virname = cli_mp_virname(engine->mempool, (char *)tokens[0], options & CL_DB_OFFICIAL);
1461 1461
 	if(!new->virname) {
1462
-	    mp_free((*engine)->mempool, new);
1462
+	    mp_free(engine->mempool, new);
1463 1463
 	    ret = CL_EMEM;
1464 1464
 	    break;
1465 1465
 	}
1466 1466
 
1467
-	if((*engine)->ignored && cli_chkign((*engine)->ignored, dbname, line, new->virname)) {
1468
-	    mp_free((*engine)->mempool, new->virname);
1469
-	    mp_free((*engine)->mempool, new);
1467
+	if(engine->ignored && cli_chkign(engine->ignored, dbname, line, new->virname)) {
1468
+	    mp_free(engine->mempool, new->virname);
1469
+	    mp_free(engine->mempool, new);
1470 1470
 	    continue;
1471 1471
 	}
1472 1472
 
1473 1473
 	new->encrypted = atoi(tokens[1]);
1474
-	new->filename = cli_mp_strdup((*engine)->mempool, tokens[2]);
1474
+	new->filename = cli_mp_strdup(engine->mempool, tokens[2]);
1475 1475
 	if(!new->filename) {
1476
-	    mp_free((*engine)->mempool, new->virname);
1477
-	    mp_free((*engine)->mempool, new);
1476
+	    mp_free(engine->mempool, new->virname);
1477
+	    mp_free(engine->mempool, new);
1478 1478
 	    ret = CL_EMALFDB;
1479 1479
 	    break;
1480 1480
 	} else {
1481 1481
 	    if(!strcmp(new->filename, "*")) {
1482
-	        mp_free((*engine)->mempool, new->filename);
1482
+	        mp_free(engine->mempool, new->filename);
1483 1483
 		new->filename = NULL;
1484 1484
 	    }
1485 1485
 	}
... ...
@@ -1521,11 +1445,11 @@ static int cli_loadmd(FILE *fs, struct cl_engine **engine, unsigned int *signo,
1521 1521
 	    new->maxdepth = atoi(tokens[8]);
1522 1522
 
1523 1523
 	if(type == 1) {
1524
-	    new->next = (*engine)->zip_mlist;
1525
-	    (*engine)->zip_mlist = new;
1524
+	    new->next = engine->zip_mlist;
1525
+	    engine->zip_mlist = new;
1526 1526
 	} else {
1527
-	    new->next = (*engine)->rar_mlist;
1528
-	    (*engine)->rar_mlist = new;
1527
+	    new->next = engine->rar_mlist;
1528
+	    engine->rar_mlist = new;
1529 1529
 	}
1530 1530
 
1531 1531
 	sigs++;
... ...
@@ -1533,13 +1457,11 @@ static int cli_loadmd(FILE *fs, struct cl_engine **engine, unsigned int *signo,
1533 1533
 
1534 1534
     if(!line) {
1535 1535
 	cli_errmsg("Empty database file\n");
1536
-	cl_free(*engine);
1537 1536
 	return CL_EMALFDB;
1538 1537
     }
1539 1538
 
1540 1539
     if(ret) {
1541 1540
 	cli_errmsg("Problem parsing database at line %d\n", line);
1542
-	cl_free(*engine);
1543 1541
 	return ret;
1544 1542
     }
1545 1543
 
... ...
@@ -1549,9 +1471,9 @@ static int cli_loadmd(FILE *fs, struct cl_engine **engine, unsigned int *signo,
1549 1549
     return CL_SUCCESS;
1550 1550
 }
1551 1551
 
1552
-static int cli_loaddbdir(const char *dirname, struct cl_engine **engine, unsigned int *signo, unsigned int options);
1552
+static int cli_loaddbdir(const char *dirname, struct cl_engine *engine, unsigned int *signo, unsigned int options);
1553 1553
 
1554
-int cli_load(const char *filename, struct cl_engine **engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio)
1554
+int cli_load(const char *filename, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio)
1555 1555
 {
1556 1556
 	FILE *fs = NULL;
1557 1557
 	int ret = CL_SUCCESS;
... ...
@@ -1671,17 +1593,7 @@ int cli_load(const char *filename, struct cl_engine **engine, unsigned int *sign
1671 1671
     return ret;
1672 1672
 }
1673 1673
 
1674
-int cl_loaddb(const char *filename, struct cl_engine **engine, unsigned int *signo) {
1675
-	int ret;
1676
-
1677
-    if((ret = cli_initengine(engine, CL_DB_STDOPT))) {
1678
-	cl_free(*engine);
1679
-	return ret;
1680
-    }
1681
-    return cli_load(filename, engine, signo, CL_DB_STDOPT, NULL);
1682
-}
1683
-
1684
-static int cli_loaddbdir(const char *dirname, struct cl_engine **engine, unsigned int *signo, unsigned int options)
1674
+static int cli_loaddbdir(const char *dirname, struct cl_engine *engine, unsigned int *signo, unsigned int options)
1685 1675
 {
1686 1676
 	DIR *dd;
1687 1677
 	struct dirent *dent;
... ...
@@ -1775,33 +1687,26 @@ static int cli_loaddbdir(const char *dirname, struct cl_engine **engine, unsigne
1775 1775
     return ret;
1776 1776
 }
1777 1777
 
1778
-int cl_loaddbdir(const char *dirname, struct cl_engine **engine, unsigned int *signo) {
1779
-	int ret;
1780
-
1781
-    if((ret = cli_initengine(engine, CL_DB_STDOPT))) {
1782
-	cl_free(*engine);
1783
-	return ret;
1784
-    }
1785
-    return cli_loaddbdir(dirname, engine, signo, CL_DB_STDOPT);
1786
-}
1787
-
1788
-int cl_load(const char *path, struct cl_engine **engine, unsigned int *signo, unsigned int options)
1778
+int cl_load(const char *path, struct cl_engine *engine, unsigned int *signo, unsigned int options)
1789 1779
 {
1790 1780
 	struct stat sb;
1791 1781
 	int ret;
1792 1782
 
1783
+    if(!engine) {
1784
+	cli_errmsg("cl_load: engine == NULL\n");
1785
+	return CL_ENULLARG;
1786
+    }
1793 1787
 
1794 1788
     if(stat(path, &sb) == -1) {
1795 1789
         cli_errmsg("cl_load(): Can't get status of %s\n", path);
1796 1790
         return CL_EIO;
1797 1791
     }
1798 1792
 
1799
-    if((ret = cli_initengine(engine, options))) {
1800
-	cl_free(*engine);
1801
-	return ret;
1802
-    }
1793
+    if((options & CL_DB_PHISHING_URLS) && !engine->phishcheck && (engine->dconf->phishing & PHISHING_CONF_ENGINE))
1794
+	if((ret = phishing_init(engine)))
1795
+	    return ret;
1803 1796
 
1804
-    (*engine)->dboptions = options;
1797
+    engine->dboptions = options;
1805 1798
 
1806 1799
     switch(sb.st_mode & S_IFMT) {
1807 1800
 	case S_IFREG: 
... ...
@@ -2023,7 +1928,7 @@ int cl_statfree(struct cl_stat *dbstat)
2023 2023
     return CL_SUCCESS;
2024 2024
 }
2025 2025
 
2026
-void cl_free(struct cl_engine *engine)
2026
+int cl_engine_free(struct cl_engine *engine)
2027 2027
 {
2028 2028
 	unsigned int i, j;
2029 2029
 	struct cli_meta_node *metapt, *metah;
... ...
@@ -2032,7 +1937,7 @@ void cl_free(struct cl_engine *engine)
2032 2032
 
2033 2033
     if(!engine) {
2034 2034
 	cli_errmsg("cl_free: engine == NULL\n");
2035
-	return;
2035
+	return CL_ENULLARG;
2036 2036
     }
2037 2037
 
2038 2038
 #ifdef CL_THREAD_SAFE
... ...
@@ -2046,7 +1951,7 @@ void cl_free(struct cl_engine *engine)
2046 2046
 #ifdef CL_THREAD_SAFE
2047 2047
 	pthread_mutex_unlock(&cli_ref_mutex);
2048 2048
 #endif
2049
-	return;
2049
+	return CL_SUCCESS;
2050 2050
     }
2051 2051
 
2052 2052
 #ifdef CL_THREAD_SAFE
... ...
@@ -2111,7 +2016,7 @@ void cl_free(struct cl_engine *engine)
2111 2111
 	mp_free(engine->mempool, metah);
2112 2112
     }
2113 2113
 
2114
-    if(((struct cli_dconf *) engine->dconf)->phishing & PHISHING_CONF_ENGINE)
2114
+    if(engine->dconf->phishing & PHISHING_CONF_ENGINE)
2115 2115
 	phishing_done(engine);
2116 2116
     if(engine->dconf)
2117 2117
 	mp_free(engine->mempool, engine->dconf);
... ...
@@ -2125,6 +2030,7 @@ void cl_free(struct cl_engine *engine)
2125 2125
     if(engine->mempool) mp_destroy(engine->mempool);
2126 2126
 #endif
2127 2127
     free(engine);
2128
+    return CL_SUCCESS;
2128 2129
 }
2129 2130
 
2130 2131
 static void cli_md5db_build(struct cli_matcher* root)
... ...
@@ -2150,8 +2056,7 @@ static void cli_md5db_build(struct cli_matcher* root)
2150 2150
 	}
2151 2151
 }
2152 2152
 
2153
-
2154
-int cl_build(struct cl_engine *engine)
2153
+int cl_engine_compile(struct cl_engine *engine)
2155 2154
 {
2156 2155
 	unsigned int i;
2157 2156
 	int ret;
... ...
@@ -2168,7 +2073,7 @@ int cl_build(struct cl_engine *engine)
2168 2168
 #endif
2169 2169
 
2170 2170
     if(!engine->ftypes)
2171
-	if((ret = cli_loadftm(NULL, &engine, 0, 1, NULL)))
2171
+	if((ret = cli_loadftm(NULL, engine, 0, 1, NULL)))
2172 2172
 	    return ret;
2173 2173
 
2174 2174
     for(i = 0; i < CLI_MTARGETS; i++) {
... ...
@@ -2193,10 +2098,10 @@ int cl_build(struct cl_engine *engine)
2193 2193
     return CL_SUCCESS;
2194 2194
 }
2195 2195
 
2196
-struct cl_engine *cl_dup(struct cl_engine *engine)
2196
+struct cl_engine *cl_engine_dup(struct cl_engine *engine)
2197 2197
 {
2198 2198
     if(!engine) {
2199
-	cli_errmsg("cl_dup: engine == NULL\n");
2199
+	cli_errmsg("cl_engine_dup: engine == NULL\n");
2200 2200
 	return NULL;
2201 2201
     }
2202 2202
 
... ...
@@ -57,9 +57,7 @@ char *cli_virname(char *virname, unsigned int official);
57 57
 
58 58
 int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hexsig, uint16_t rtype, uint16_t type, const char *offset, uint8_t target, const uint32_t *lsigid, unsigned int options);
59 59
 
60
-int cli_initengine(struct cl_engine **engine, unsigned int options);
61
-
62
-int cli_load(const char *filename, struct cl_engine **engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio);
60
+int cli_load(const char *filename, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio);
63 61
 
64 62
 char *cli_dbgets(char *buff, unsigned int size, FILE *fs, struct cli_dbio *dbio);
65 63
 
... ...
@@ -567,7 +567,6 @@ static int cli_scanbzip(int desc, cli_ctx *ctx) {
567 567
 static int cli_scanbzip(int desc, cli_ctx *ctx)
568 568
 {
569 569
 	int fd, bytes, ret = CL_CLEAN, bzerror = 0;
570
-	short memlim = 0;
571 570
 	unsigned long int size = 0;
572 571
 	char *buff;
573 572
 	FILE *fs;
... ...
@@ -580,11 +579,7 @@ static int cli_scanbzip(int desc, cli_ctx *ctx)
580 580
 	return CL_EBZIP;
581 581
     }
582 582
 
583
-    if(ctx->limits)
584
-	if(ctx->limits->archivememlim)
585
-	    memlim = 1;
586
-
587
-    if((bfd = BZ2_bzReadOpen(&bzerror, fs, 0, memlim, NULL, 0)) == NULL) {
583
+    if((bfd = BZ2_bzReadOpen(&bzerror, fs, 0, 0, NULL, 0)) == NULL) {
588 584
 	cli_dbgmsg("Bzip: Can't initialize bzip2 library (descriptor: %d).\n", desc);
589 585
 	fclose(fs);
590 586
 	return CL_EBZIP;
... ...
@@ -1142,7 +1137,7 @@ static int cli_scanole2(int desc, cli_ctx *ctx)
1142 1142
 
1143 1143
     cli_dbgmsg("in cli_scanole2()\n");
1144 1144
 
1145
-    if(ctx->limits && ctx->limits->maxreclevel && ctx->recursion >= ctx->limits->maxreclevel)
1145
+    if(ctx->engine->maxreclevel && ctx->recursion >= ctx->engine->maxreclevel)
1146 1146
         return CL_EMAXREC;
1147 1147
 
1148 1148
     /* generate the temporary directory */
... ...
@@ -1552,17 +1547,14 @@ static int cli_scan_structured(int desc, cli_ctx *ctx)
1552 1552
 	unsigned int cc_count = 0;
1553 1553
 	unsigned int ssn_count = 0;
1554 1554
 	int done = 0;
1555
-	const struct cl_limits *lim = NULL;
1556 1555
 	int (*ccfunc)(const unsigned char *buffer, int length);
1557 1556
 	int (*ssnfunc)(const unsigned char *buffer, int length);
1558 1557
 
1559 1558
 
1560
-    if(ctx == NULL || ctx->limits == NULL)
1559
+    if(ctx == NULL)
1561 1560
 	return CL_ENULLARG;
1562 1561
 
1563
-    lim = ctx->limits;
1564
-
1565
-    if(lim->min_cc_count == 1)
1562
+    if(ctx->engine->min_cc_count == 1)
1566 1563
 	ccfunc = dlp_has_cc;
1567 1564
     else
1568 1565
 	ccfunc = dlp_get_cc_count;
... ...
@@ -1570,21 +1562,21 @@ static int cli_scan_structured(int desc, cli_ctx *ctx)
1570 1570
     switch((ctx->options & CL_SCAN_STRUCTURED_SSN_NORMAL) | (ctx->options & CL_SCAN_STRUCTURED_SSN_STRIPPED)) {
1571 1571
 
1572 1572
 	case (CL_SCAN_STRUCTURED_SSN_NORMAL | CL_SCAN_STRUCTURED_SSN_STRIPPED):
1573
-	    if(lim->min_ssn_count == 1)
1573
+	    if(ctx->engine->min_ssn_count == 1)
1574 1574
 		ssnfunc = dlp_has_ssn;
1575 1575
 	    else
1576 1576
 		ssnfunc = dlp_get_ssn_count;
1577 1577
 	    break;
1578 1578
 
1579 1579
 	case CL_SCAN_STRUCTURED_SSN_NORMAL:
1580
-	    if(lim->min_ssn_count == 1)
1580
+	    if(ctx->engine->min_ssn_count == 1)
1581 1581
 		ssnfunc = dlp_has_normal_ssn;
1582 1582
 	    else
1583 1583
 		ssnfunc = dlp_get_normal_ssn_count;
1584 1584
 	    break;
1585 1585
 
1586 1586
 	case CL_SCAN_STRUCTURED_SSN_STRIPPED:
1587
-	    if(lim->min_ssn_count == 1)
1587
+	    if(ctx->engine->min_ssn_count == 1)
1588 1588
 		ssnfunc = dlp_has_stripped_ssn;
1589 1589
 	    else
1590 1590
 		ssnfunc = dlp_get_stripped_ssn_count;
... ...
@@ -1595,20 +1587,20 @@ static int cli_scan_structured(int desc, cli_ctx *ctx)
1595 1595
     }
1596 1596
 
1597 1597
     while(!done && ((result = cli_readn(desc, buf, 8191)) > 0)) {
1598
-	if((cc_count += ccfunc((const unsigned char *)buf, result)) >= lim->min_cc_count)
1598
+	if((cc_count += ccfunc((const unsigned char *)buf, result)) >= ctx->engine->min_cc_count)
1599 1599
 	    done = 1;
1600 1600
 
1601
-	if(ssnfunc && ((ssn_count += ssnfunc((const unsigned char *)buf, result)) >= lim->min_ssn_count))
1601
+	if(ssnfunc && ((ssn_count += ssnfunc((const unsigned char *)buf, result)) >= ctx->engine->min_ssn_count))
1602 1602
 	    done = 1;
1603 1603
     }
1604 1604
 
1605
-    if(cc_count != 0 && cc_count >= lim->min_cc_count) {
1605
+    if(cc_count != 0 && cc_count >= ctx->engine->min_cc_count) {
1606 1606
 	cli_dbgmsg("cli_scan_structured: %u credit card numbers detected\n", cc_count);
1607 1607
 	*ctx->virname = "Structured.CreditCardNumber";
1608 1608
 	return CL_VIRUS;
1609 1609
     }
1610 1610
 
1611
-    if(ssn_count != 0 && ssn_count >= lim->min_ssn_count) {
1611
+    if(ssn_count != 0 && ssn_count >= ctx->engine->min_ssn_count) {
1612 1612
 	cli_dbgmsg("cli_scan_structured: %u social security numbers detected\n", ssn_count);
1613 1613
 	*ctx->virname = "Structured.SSN";
1614 1614
 	return CL_VIRUS;
... ...
@@ -1875,7 +1867,7 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx)
1875 1875
     if(cli_updatelimits(ctx, sb.st_size)!=CL_CLEAN)
1876 1876
         return CL_CLEAN;
1877 1877
 
1878
-    if((SCAN_MAIL || SCAN_ARCHIVE) && ctx->limits && ctx->limits->maxreclevel && ctx->recursion > ctx->limits->maxreclevel) {
1878
+    if((SCAN_MAIL || SCAN_ARCHIVE) && ctx->engine->maxreclevel && ctx->recursion > ctx->engine->maxreclevel) {
1879 1879
         cli_dbgmsg("Archive recursion limit exceeded (level = %u).\n", ctx->recursion);
1880 1880
 	return CL_CLEAN;
1881 1881
     }
... ...
@@ -2108,16 +2100,11 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx)
2108 2108
     }
2109 2109
 }
2110 2110
 
2111
-int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options)
2111
+int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int options)
2112 2112
 {
2113 2113
     cli_ctx ctx;
2114
-    struct cl_limits l_limits;
2115 2114
     int rc;
2116 2115
 
2117
-    if(!limits) {
2118
-	cli_errmsg("cl_scandesc: limits == NULL\n");
2119
-	return CL_ENULLARG;
2120
-    }
2121 2116
     memset(&ctx, '\0', sizeof(cli_ctx));
2122 2117
     ctx.engine = engine;
2123 2118
     ctx.virname = virname;
... ...
@@ -2125,8 +2112,6 @@ int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, cons
2125 2125
     ctx.options = options;
2126 2126
     ctx.found_possibly_unwanted = 0;
2127 2127
     ctx.dconf = (struct cli_dconf *) engine->dconf;
2128
-    ctx.limits = &l_limits;
2129
-    memcpy(&l_limits, limits, sizeof(struct cl_limits));
2130 2128
 
2131 2129
     rc = cli_magic_scandesc(desc, &ctx);
2132 2130
     if(rc == CL_CLEAN && ctx.found_possibly_unwanted)
... ...
@@ -2169,7 +2154,7 @@ static int cli_scanfile(const char *filename, cli_ctx *ctx)
2169 2169
     return ret;
2170 2170
 }
2171 2171
 
2172
-int cl_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options)
2172
+int cl_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int options)
2173 2173
 {
2174 2174
 	int fd, ret;
2175 2175
 
... ...
@@ -2177,7 +2162,7 @@ int cl_scanfile(const char *filename, const char **virname, unsigned long int *s
2177 2177
     if((fd = open(filename, O_RDONLY|O_BINARY)) == -1)
2178 2178
 	return CL_EOPEN;
2179 2179
 
2180
-    ret = cl_scandesc(fd, virname, scanned, engine, limits, options);
2180
+    ret = cl_scandesc(fd, virname, scanned, engine, options);
2181 2181
     close(fd);
2182 2182
 
2183 2183
     return ret;
... ...
@@ -375,12 +375,12 @@ int unspin(char *src, int ssize, struct cli_exe_section *sections, int sectcnt,
375 375
   bitman = bitmap;
376 376
 
377 377
   /* FIXMELIMITS: possibly rewrite to use the limits api */
378
-  if(ctx->limits && ctx->limits->maxfilesize) {
378
+  if(ctx->engine->maxfilesize) {
379 379
     unsigned long int filesize = 0;
380 380
     
381 381
     for (j=0; j<sectcnt; j++) {
382 382
       if (bitmap&1) {
383
-	if ( filesize > ctx->limits->maxfilesize || sections[j].vsz > ctx->limits->maxfilesize - filesize ) return 2;
383
+	if ( filesize > ctx->engine->maxfilesize || sections[j].vsz > ctx->engine->maxfilesize - filesize ) return 2;
384 384
 	filesize += sections[j].vsz;
385 385
       }
386 386
       bitmap>>=1;
... ...
@@ -105,9 +105,9 @@ static int unz(uint8_t *src, uint32_t csize, uint32_t usize, uint16_t method, ui
105 105
       else break;
106 106
     }
107 107
     if(res==1) {
108
-      if(ctx->limits && ctx->limits->maxfilesize && csize > ctx->limits->maxfilesize) {
109
-	cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", ctx->limits->maxfilesize);
110
-	csize = ctx->limits->maxfilesize;
108
+      if(ctx->engine->maxfilesize && csize > ctx->engine->maxfilesize) {
109
+	cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", ctx->engine->maxfilesize);
110
+	csize = ctx->engine->maxfilesize;
111 111
       }
112 112
       if(cli_writen(of, src, csize)!=(int)csize) ret = CL_EIO;
113 113
       else res=0;
... ...
@@ -166,8 +166,8 @@ static int unz(uint8_t *src, uint32_t csize, uint32_t usize, uint16_t method, ui
166 166
       while((res = unz_unz(&strm, Z_NO_FLUSH))==Z_OK) {};
167 167
       if(*avail_out!=sizeof(obuf)) {
168 168
 	written+=sizeof(obuf)-(*avail_out);
169
-	if(ctx->limits && ctx->limits->maxfilesize && written > ctx->limits->maxfilesize) {
170
-	  cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", ctx->limits->maxfilesize);
169
+	if(ctx->engine->maxfilesize && written > ctx->engine->maxfilesize) {
170
+	  cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", ctx->engine->maxfilesize);
171 171
 	  res = Z_STREAM_END;
172 172
 	  break;
173 173
 	}
... ...
@@ -210,8 +210,8 @@ static int unz(uint8_t *src, uint32_t csize, uint32_t usize, uint16_t method, ui
210 210
     while((res = BZ2_bzDecompress(&strm))==BZ_OK || res==BZ_STREAM_END) {
211 211
       if(strm.avail_out!=sizeof(obuf)) {
212 212
 	written+=sizeof(obuf)-strm.avail_out;
213
-	if(ctx->limits && ctx->limits->maxfilesize && written > ctx->limits->maxfilesize) {
214
-	  cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", ctx->limits->maxfilesize);
213
+	if(ctx->engine->maxfilesize && written > ctx->engine->maxfilesize) {
214
+	  cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", ctx->engine->maxfilesize);
215 215
 	  res = BZ_STREAM_END;
216 216
 	  break;
217 217
 	}
... ...
@@ -247,8 +247,8 @@ static int unz(uint8_t *src, uint32_t csize, uint32_t usize, uint16_t method, ui
247 247
     while((res = explode(&strm))==EXPLODE_OK) {
248 248
       if(strm.avail_out!=sizeof(obuf)) {
249 249
 	written+=sizeof(obuf)-strm.avail_out;
250
-	if(ctx->limits && ctx->limits->maxfilesize && written > ctx->limits->maxfilesize) {
251
-	  cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", ctx->limits->maxfilesize);
250
+	if(ctx->engine->maxfilesize && written > ctx->engine->maxfilesize) {
251
+	  cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", ctx->engine->maxfilesize);
252 252
 	  res = 0;
253 253
 	  break;
254 254
 	}
... ...
@@ -537,8 +537,8 @@ int cli_unzip(int f, cli_ctx *ctx) {
537 537
     cli_dbgmsg("cli_unzip: central @%x\n", coff);
538 538
     while(ret==CL_CLEAN && (coff=chdr(map, coff, fsize, &fu, fc+1, &ret, ctx, tmpd))) {
539 539
       fc++;
540
-      if (ctx->limits && ctx->limits->maxfiles && fu>=ctx->limits->maxfiles) {
541
-	cli_dbgmsg("cli_unzip: Files limit reached (max: %u)\n", ctx->limits->maxfiles);
540
+      if (ctx->engine->maxfiles && fu>=ctx->engine->maxfiles) {
541
+	cli_dbgmsg("cli_unzip: Files limit reached (max: %u)\n", ctx->engine->maxfiles);
542 542
 	ret=CL_EMAXFILES;
543 543
       }
544 544
     }
... ...
@@ -548,8 +548,8 @@ int cli_unzip(int f, cli_ctx *ctx) {
548 548
     while (ret==CL_CLEAN && lhoff<fsize && (coff=lhdr(&map[lhoff], fsize-lhoff, &fu, fc+1, NULL, &ret, ctx, tmpd))) {
549 549
       fc++;
550 550
       lhoff+=coff;
551
-      if (ctx->limits && ctx->limits->maxfiles && fu>=ctx->limits->maxfiles) {
552
-	cli_dbgmsg("cli_unzip: Files limit reached (max: %u)\n", ctx->limits->maxfiles);
551
+      if (ctx->engine->maxfiles && fu>=ctx->engine->maxfiles) {
552
+	cli_dbgmsg("cli_unzip: Files limit reached (max: %u)\n", ctx->engine->maxfiles);
553 553
 	ret=CL_EMAXFILES;
554 554
       }
555 555
     }
... ...
@@ -71,11 +71,10 @@ struct cfgoption cfg_options[] = {
71 71
     {"ScanOLE2", OPT_BOOL, 1, NULL, 0, OPT_CLAMD},
72 72
     {"ScanPDF", OPT_BOOL, 1, NULL, 0, OPT_CLAMD},
73 73
     {"ScanArchive", OPT_BOOL, 1, NULL, 0, OPT_CLAMD},
74
-    {"MaxScanSize", OPT_COMPSIZE, 104857600, NULL, 0, OPT_CLAMD},
75
-    {"MaxFileSize", OPT_COMPSIZE, 26214400, NULL, 0, OPT_CLAMD},
76
-    {"MaxRecursion", OPT_NUM, 16, NULL, 0, OPT_CLAMD},
77
-    {"MaxFiles", OPT_NUM, 10000, NULL, 0, OPT_CLAMD},
78
-    {"ArchiveLimitMemoryUsage", OPT_BOOL, 0, NULL, 0, OPT_CLAMD},
74
+    {"MaxScanSize", OPT_COMPSIZE, -1, NULL, 0, OPT_CLAMD},
75
+    {"MaxFileSize", OPT_COMPSIZE, -1, NULL, 0, OPT_CLAMD},
76
+    {"MaxRecursion", OPT_NUM, -1, NULL, 0, OPT_CLAMD},
77
+    {"MaxFiles", OPT_NUM, -1, NULL, 0, OPT_CLAMD},
79 78
     {"ArchiveBlockEncrypted", OPT_BOOL, 0, NULL, 0, OPT_CLAMD},
80 79
     {"DatabaseDirectory", OPT_QUOTESTR, -1, DATADIR, 0, OPT_CLAMD | OPT_FRESHCLAM},
81 80
     {"TCPAddr", OPT_QUOTESTR, -1, NULL, 0, OPT_CLAMD},
... ...
@@ -141,6 +140,7 @@ struct cfgoption cfg_options[] = {
141 141
     {"ArchiveMaxFiles", OPT_NUM, 1000, NULL, 0, OPT_CLAMD | OPT_DEPRECATED},
142 142
     {"ArchiveMaxCompressionRatio", OPT_NUM, 250, NULL, 0, OPT_CLAMD | OPT_DEPRECATED},
143 143
     {"ArchiveBlockMax", OPT_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_DEPRECATED},
144
+    {"ArchiveLimitMemoryUsage", OPT_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_DEPRECATED },
144 145
 
145 146
     {NULL, 0, 0, NULL, 0, 0}
146 147
 };
... ...
@@ -540,7 +540,7 @@ static int build(struct optstruct *opt)
540 540
 	unsigned char buffer[FILEBUFF];
541 541
 	char *tarfile, header[513], smbuff[32], builder[32], *pt, olddb[512], patch[32], broken[32];
542 542
 	const char *dbname, *newcvd;
543
-        struct cl_engine *engine = NULL;
543
+        struct cl_engine *engine;
544 544
 	FILE *cvd, *fh;
545 545
 	gzFile *tar;
546 546
 	time_t timet;
... ...
@@ -560,12 +560,17 @@ static int build(struct optstruct *opt)
560 560
 
561 561
     dbname = strstr(opt_arg(opt, "build"), "main") ? "main" : "daily";
562 562
 
563
-    if((ret = cl_load(".", &engine, &sigs, CL_DB_STDOPT | CL_DB_PUA))) {
563
+    if(!(engine = cl_engine_new(CL_ENGINE_DEFAULT))) {
564
+	mprintf("!build: Can't initialize antivirus engine\n");
565
+	return 50;
566
+    }
567
+
568
+    if((ret = cl_load(".", engine, &sigs, CL_DB_STDOPT | CL_DB_PUA))) {
564 569
 	mprintf("!build: Can't load database: %s\n", cl_strerror(ret));
570
+	cl_engine_free(engine);
565 571
 	return -1;
566
-    } else {
567
-	cl_free(engine);
568 572
     }
573
+    cl_engine_free(engine);
569 574
 
570 575
     if(!sigs) {
571 576
 	mprintf("!build: There are no signatures in database files\n");