Browse code

new config file parser

git-svn: trunk@1596

Tomasz Kojm authored on 2005/06/01 09:42:33
Showing 21 changed files
... ...
@@ -1,3 +1,16 @@
1
+Wed Jun  1 02:39:14 CEST 2005 (tk)
2
+----------------------------------
3
+  * misc/cfgparser.c: reimplementation of config parser:
4
+			- all options require arguments (old ones without
5
+			  args must be now followed by boolean values: yes, no,
6
+			  1, 0, or true, false)
7
+			- optional arguments (as in NotifyClamd) are no longer
8
+			  supported
9
+			- default values are directly associated with options
10
+  * clamd/defaults.h: remove
11
+  * clamd, clamdscan, freshclam: use new parser scheme
12
+  * etc/clamd.conf: remove DisableDefaultScanOptions
13
+
1 14
 Tue May 31 19:15:01 BST 2005 (njh)
2 15
 ----------------------------------
3 16
   * libclamav/mbox.c:	Fix mishandling of fast track uuencoded files
... ...
@@ -1,5 +1,5 @@
1 1
 #
2
-#  Copyright (C) 2002 - 2004 Tomasz Kojm <tkojm@clamav.net>
2
+#  Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>
3 3
 #
4 4
 #  This program is free software; you can redistribute it and/or modify
5 5
 #  it under the terms of the GNU General Public License as published by
... ...
@@ -33,7 +33,6 @@ clamd_SOURCES = \
33 33
     options.c \
34 34
     options.h \
35 35
     clamd.c \
36
-    defaults.h \
37 36
     tcpserver.c \
38 37
     tcpserver.h \
39 38
     localserver.c \
... ...
@@ -49,7 +49,6 @@
49 49
 #include "tcpserver.h"
50 50
 #include "localserver.h"
51 51
 #include "others.h"
52
-#include "defaults.h"
53 52
 #include "memory.h"
54 53
 #include "output.h"
55 54
 #include "shared.h"
... ...
@@ -101,9 +100,9 @@ void clamd(struct optstruct *opt)
101 101
     if(optc(opt, 'c'))
102 102
 	cfgfile = getargc(opt, 'c');
103 103
     else
104
-	cfgfile = CL_DEFAULT_CFG;
104
+	cfgfile = CONFDIR"/clamd.conf";
105 105
 
106
-    if((copt = parsecfg(cfgfile, 1)) == NULL) {
106
+    if((copt = getcfg(cfgfile, 1)) == NULL) {
107 107
 	fprintf(stderr, "ERROR: Can't open/parse the config file %s\n", cfgfile);
108 108
 	exit(1);
109 109
     }
... ...
@@ -112,29 +111,16 @@ void clamd(struct optstruct *opt)
112 112
 
113 113
     /* initialize logger */
114 114
 
115
-    if(cfgopt(copt, "LogFileUnlock"))
116
-	logg_lock = 0;
115
+    logg_lock = cfgopt(copt, "LogFileUnlock")->enabled;
116
+    logg_time = cfgopt(copt, "LogTime")->enabled;
117
+    logok = cfgopt(copt, "LogClean")->enabled;
118
+    logg_size = cfgopt(copt, "LogFileMaxSize")->numarg;
119
+    logg_verbose = cfgopt(copt, "LogVerbose")->enabled;
117 120
 
118
-    if(cfgopt(copt, "LogTime"))
119
-	logg_time = 1;
120
-
121
-    if(cfgopt(copt, "LogClean"))
122
-	logok = 1;
123
-
124
-    if((cpt = cfgopt(copt, "LogFileMaxSize")))
125
-	logg_size = cpt->numarg;
126
-    else
127
-	logg_size = CL_DEFAULT_LOGSIZE;
128
-
129
-    if(cfgopt(copt, "Debug")) /* enable debug messages in libclamav */
121
+    if(cfgopt(copt, "Debug")->enabled) /* enable debug messages in libclamav */
130 122
 	cl_debug();
131 123
 
132
-    if(cfgopt(copt, "LogVerbose"))
133
-	logg_verbose = 1;
134
-    else
135
-	logg_verbose = 0;
136
-
137
-    if((cpt = cfgopt(copt, "LogFile"))) {
124
+    if((cpt = cfgopt(copt, "LogFile"))->enabled) {
138 125
 	logg_file = cpt->strarg;
139 126
 	if(strlen(logg_file) < 2 || (logg_file[0] != '/' && logg_file[0] != '\\' && logg_file[1] != ':')) {
140 127
 	    fprintf(stderr, "ERROR: LogFile requires full path.\n");
... ...
@@ -148,16 +134,14 @@ void clamd(struct optstruct *opt)
148 148
     } else
149 149
 	logg_file = NULL;
150 150
 
151
-
152 151
 #if defined(USE_SYSLOG) && !defined(C_AIX)
153
-    if(cfgopt(copt, "LogSyslog")) {
152
+    if(cfgopt(copt, "LogSyslog")->enabled) {
154 153
 	    int fac = LOG_LOCAL6;
155 154
 
156
-	if((cpt = cfgopt(copt, "LogFacility"))) {
157
-	    if((fac = logg_facility(cpt->strarg)) == -1) {
158
-		fprintf(stderr, "ERROR: LogFacility: %s: No such facility.\n", cpt->strarg);
159
-		exit(1);
160
-	    }
155
+	cpt = cfgopt(copt, "LogFacility");
156
+	if((fac = logg_facility(cpt->strarg)) == -1) {
157
+	    fprintf(stderr, "ERROR: LogFacility: %s: No such facility.\n", cpt->strarg);
158
+	    exit(1);
161 159
 	}
162 160
 
163 161
 	openlog("clamd", LOG_PID, fac);
... ...
@@ -183,13 +167,13 @@ void clamd(struct optstruct *opt)
183 183
 
184 184
     /* check socket type */
185 185
 
186
-    if(cfgopt(copt, "TCPSocket") && cfgopt(copt, "LocalSocket")) {
187
-	fprintf(stderr, "ERROR: You can select one mode only (local/TCP).\n");
188
-	logg("!Two modes (local & TCP) selected.\n");
186
+    if(cfgopt(copt, "TCPSocket")->enabled && cfgopt(copt, "LocalSocket")->enabled) {
187
+	fprintf(stderr, "ERROR: You can only select one mode (local or TCP).\n");
188
+	logg("!Two modes (local and TCP) selected.\n");
189 189
 	exit(1);
190
-    } else if(cfgopt(copt, "TCPSocket")) {
190
+    } else if(cfgopt(copt, "TCPSocket")->enabled) {
191 191
 	tcpsock = 1;
192
-    } else if(cfgopt(copt, "LocalSocket")) {
192
+    } else if(cfgopt(copt, "LocalSocket")->enabled) {
193 193
 	tcpsock = 0;
194 194
     } else {
195 195
 	fprintf(stderr, "ERROR: You must select server type (local/tcp).\n");
... ...
@@ -199,14 +183,14 @@ void clamd(struct optstruct *opt)
199 199
 
200 200
     /* drop privileges */
201 201
 #ifndef C_OS2
202
-    if(geteuid() == 0 && (cpt = cfgopt(copt, "User"))) {
202
+    if(geteuid() == 0 && (cpt = cfgopt(copt, "User"))->enabled) {
203 203
 	if((user = getpwnam(cpt->strarg)) == NULL) {
204 204
 	    fprintf(stderr, "ERROR: Can't get information about user %s.\n", cpt->strarg);
205 205
 	    logg("!Can't get information about user %s.\n", cpt->strarg);
206 206
 	    exit(1);
207 207
 	}
208 208
 
209
-	if(cfgopt(copt, "AllowSupplementaryGroups")) {
209
+	if(cfgopt(copt, "AllowSupplementaryGroups")->enabled) {
210 210
 #ifdef HAVE_INITGROUPS
211 211
 	    if(initgroups(cpt->strarg, user->pw_gid)) {
212 212
 		fprintf(stderr, "ERROR: initgroups() failed.\n");
... ...
@@ -243,18 +227,14 @@ void clamd(struct optstruct *opt)
243 243
 #endif
244 244
 
245 245
     /* set the temporary dir */
246
-    if((cpt = cfgopt(copt, "TemporaryDirectory")))
246
+    if((cpt = cfgopt(copt, "TemporaryDirectory"))->enabled)
247 247
 	cl_settempdir(cpt->strarg, 0);
248 248
 
249
-    if(cfgopt(copt, "LeaveTemporaryFiles"))
249
+    if(cfgopt(copt, "LeaveTemporaryFiles")->enabled)
250 250
 	cl_settempdir(NULL, 1);
251 251
 
252 252
     /* load the database(s) */
253
-    if((cpt = cfgopt(copt, "DatabaseDirectory")) || (cpt = cfgopt(copt, "DataDirectory")))
254
-	dbdir = cpt->strarg;
255
-    else
256
-	dbdir = cl_retdbdir();
257
-
253
+    dbdir = cfgopt(copt, "DatabaseDirectory")->strarg;
258 254
     logg("Reading databases from %s\n", dbdir);
259 255
 
260 256
     if((ret = cl_loaddbdir(dbdir, &root, &virnum))) {
... ...
@@ -277,7 +257,7 @@ void clamd(struct optstruct *opt)
277 277
     }
278 278
 
279 279
     /* fork into background */
280
-    if(!cfgopt(copt, "Foreground"))
280
+    if(!cfgopt(copt, "Foreground")->enabled)
281 281
 	daemonize();
282 282
 
283 283
     if(tcpsock)
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2002 - 2004 Tomasz Kojm <tkojm@clamav.net>
2
+ *  Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>
3 3
  *
4 4
  *  This program is free software; you can redistribute it and/or modify
5 5
  *  it under the terms of the GNU General Public License as published by
... ...
@@ -35,7 +35,6 @@
35 35
 #include "cfgparser.h"
36 36
 #include "dazukoio.h"
37 37
 #include "clamuko.h"
38
-#include "defaults.h"
39 38
 #include "output.h"
40 39
 
41 40
 struct dazuko_access *acc;
... ...
@@ -92,15 +91,15 @@ void *clamukoth(void *arg)
92 92
 	logg("Clamuko: Correctly registered with Dazuko.\n");
93 93
 
94 94
     /* access mask */
95
-    if(cfgopt(tharg->copt, "ClamukoScanOnOpen")) {
95
+    if(cfgopt(tharg->copt, "ClamukoScanOnOpen")->enabled) {
96 96
 	logg("Clamuko: Scan-on-open mode activated.\n");
97 97
 	mask |= DAZUKO_ON_OPEN;
98 98
     }
99
-    if(cfgopt(tharg->copt, "ClamukoScanOnClose")) {
99
+    if(cfgopt(tharg->copt, "ClamukoScanOnClose")->enabled) {
100 100
 	logg("Clamuko: Scan-on-close mode activated.\n");
101 101
 	mask |= DAZUKO_ON_CLOSE;
102 102
     }
103
-    if(cfgopt(tharg->copt, "ClamukoScanOnExec")) {
103
+    if(cfgopt(tharg->copt, "ClamukoScanOnExec")->enabled) {
104 104
 	logg("Clamuko: Scan-on-exec mode activated.\n");
105 105
 	mask |= DAZUKO_ON_EXEC;
106 106
     }
... ...
@@ -117,7 +116,7 @@ void *clamukoth(void *arg)
117 117
 	return NULL;
118 118
     }
119 119
 
120
-    if((pt = cfgopt(tharg->copt, "ClamukoIncludePath"))) {
120
+    if((pt = cfgopt(tharg->copt, "ClamukoIncludePath"))->enabled) {
121 121
 	while(pt) {
122 122
 	    if((dazukoAddIncludePath(pt->strarg))) {
123 123
 		logg("!Clamuko: Dazuko -> Can't include path %s\n", pt->strarg);
... ...
@@ -134,7 +133,7 @@ void *clamukoth(void *arg)
134 134
 	return NULL;
135 135
     }
136 136
 
137
-    if((pt = cfgopt(tharg->copt, "ClamukoExcludePath"))) {
137
+    if((pt = cfgopt(tharg->copt, "ClamukoExcludePath"))->enabled) {
138 138
 	while(pt) {
139 139
 	    if((dazukoAddExcludePath(pt->strarg))) {
140 140
 		logg("!Clamuko: Dazuko -> Can't exclude path %s\n", pt->strarg);
... ...
@@ -147,11 +146,7 @@ void *clamukoth(void *arg)
147 147
 	}
148 148
     }
149 149
 
150
-    if((pt = cfgopt(tharg->copt, "ClamukoMaxFileSize"))) {
151
-	sizelimit = pt->numarg;
152
-    } else
153
-	sizelimit = CL_DEFAULT_CLAMUKOMAXFILESIZE;
154
-
150
+    sizelimit = cfgopt(tharg->copt, "ClamukoMaxFileSize")->numarg;
155 151
     if(sizelimit)
156 152
 	logg("Clamuko: Max file size limited to %d bytes.\n", sizelimit);
157 153
     else
158 154
deleted file mode 100644
... ...
@@ -1,35 +0,0 @@
1
-/*
2
- *  Copyright (C) 2002 Tomasz Kojm <zolw@konarski.edu.pl>
3
- *
4
- *  This program is free software; you can redistribute it and/or modify
5
- *  it under the terms of the GNU General Public License as published by
6
- *  the Free Software Foundation; either version 2 of the License, or
7
- *  (at your option) any later version.
8
- *
9
- *  This program is distributed in the hope that it will be useful,
10
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
- *  GNU General Public License for more details.
13
- *
14
- *  You should have received a copy of the GNU General Public License
15
- *  along with this program; if not, write to the Free Software
16
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
- */
18
-
19
-#ifndef __DEFAULTS_H
20
-#define __DEFAULTS_H
21
-
22
-#define CL_DEFAULT_CFG CONFDIR"/clamd.conf"
23
-#define CL_DEFAULT_BACKLOG 15
24
-#define CL_DEFAULT_MAXTHREADS 10
25
-#define CL_DEFAULT_SCANTIMEOUT 120
26
-#define CL_DEFAULT_LOGSIZE 1048576
27
-#define CL_DEFAULT_CLAMUKOMAXFILESIZE 5 * 1048576
28
-#define CL_DEFAULT_SELFCHECK 1800
29
-#define CL_DEFAULT_MAXWHILEWAIT 120
30
-#define CL_DEFAULT_MAXPORTSCAN 1000
31
-#define CL_DEFAULT_MAXDIRREC 15
32
-#define CL_DEFAULT_STREAMMAXLEN 10 * 1048576
33
-#define CL_DEFAULT_IDLETIMEOUT 30
34
-
35
-#endif
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2002 - 2004 Tomasz Kojm <tkojm@clamav.net>
2
+ *  Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>
3 3
  *
4 4
  *  This program is free software; you can redistribute it and/or modify
5 5
  *  it under the terms of the GNU General Public License as published by
... ...
@@ -31,7 +31,6 @@
31 31
 
32 32
 #include "options.h"
33 33
 #include "cfgparser.h"
34
-#include "defaults.h"
35 34
 #include "others.h"
36 35
 #include "server.h"
37 36
 #include "output.h"
... ...
@@ -64,7 +63,7 @@ int localserver(const struct optstruct *opt, const struct cfgstruct *copt, struc
64 64
 		logg("!Socket file %s is in use by another process.\n", server.sun_path);
65 65
 		exit(1);
66 66
 	    }
67
-	    if(cfgopt(copt, "FixStaleSocket")) {
67
+	    if(cfgopt(copt, "FixStaleSocket")->enabled) {
68 68
 		logg("^Socket file %s exists. Unclean shutdown? Removing...\n", server.sun_path);
69 69
 		if(unlink(server.sun_path) == -1) {
70 70
 		    estr = strerror(errno);
... ...
@@ -89,11 +88,7 @@ int localserver(const struct optstruct *opt, const struct cfgstruct *copt, struc
89 89
 
90 90
     logg("Unix socket file %s\n", server.sun_path);
91 91
 
92
-    if((cpt = cfgopt(copt, "MaxConnectionQueueLength")))
93
-	backlog = cpt->numarg;
94
-    else
95
-	backlog = CL_DEFAULT_BACKLOG;
96
-
92
+    backlog = cfgopt(copt, "MaxConnectionQueueLength")->numarg;
97 93
     logg("Setting connection queue length to %d\n", backlog);
98 94
 
99 95
     if(listen(sockfd, backlog) == -1) {
... ...
@@ -77,7 +77,7 @@ void virusaction(const char *filename, const char *virname, const struct cfgstru
77 77
 	pid_t pid;
78 78
 	struct cfgstruct *cpt;
79 79
 
80
-    if(!(cpt = cfgopt(copt, "VirusEvent")))
80
+    if(!(cpt = cfgopt(copt, "VirusEvent"))->enabled)
81 81
 	return;
82 82
 
83 83
     /* NB: we need to fork here since this function modifies the environment. 
... ...
@@ -45,7 +45,6 @@
45 45
 #include "cfgparser.h"
46 46
 #include "others.h"
47 47
 #include "scanner.h"
48
-#include "defaults.h"
49 48
 #include "memory.h"
50 49
 #include "shared.h"
51 50
 #include "output.h"
... ...
@@ -102,11 +101,7 @@ int dirscan(const char *dirname, const char **virname, unsigned long int *scanne
102 102
 	int ret = 0, scanret = 0, maxdirrec = 0;
103 103
 
104 104
 
105
-    if((cpt = cfgopt(copt, "MaxDirectoryRecursion")))
106
-	maxdirrec = cpt->numarg;
107
-    else
108
-	maxdirrec = CL_DEFAULT_MAXDIRREC;
109
-
105
+    maxdirrec = cfgopt(copt, "MaxDirectoryRecursion")->numarg;
110 106
     if(maxdirrec) {
111 107
 	if(*reclev > maxdirrec) {
112 108
 	    logg("*Directory recursion limit exceeded at %s\n", dirname);
... ...
@@ -139,14 +134,14 @@ int dirscan(const char *dirname, const char **virname, unsigned long int *scanne
139 139
 
140 140
 		    /* stat the file */
141 141
 		    if(lstat(fname, &statbuf) != -1) {
142
-			if((S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)) || (S_ISLNK(statbuf.st_mode) && (checksymlink(fname) == 1) && cfgopt(copt, "FollowDirectorySymlinks"))) {
142
+			if((S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)) || (S_ISLNK(statbuf.st_mode) && (checksymlink(fname) == 1) && cfgopt(copt, "FollowDirectorySymlinks")->enabled)) {
143 143
 			    if(dirscan(fname, virname, scanned, root, limits, options, copt, odesc, reclev, contscan) == 1) {
144 144
 				free(fname);
145 145
 				closedir(dd);
146 146
 				return 1;
147 147
 			    }
148 148
 			} else {
149
-			    if(S_ISREG(statbuf.st_mode) || (S_ISLNK(statbuf.st_mode) && (checksymlink(fname) == 2) && cfgopt(copt, "FollowFileSymlinks"))) {
149
+			    if(S_ISREG(statbuf.st_mode) || (S_ISLNK(statbuf.st_mode) && (checksymlink(fname) == 2) && cfgopt(copt, "FollowFileSymlinks")->enabled)) {
150 150
 
151 151
 #ifdef C_LINUX
152 152
 				if(procdev && (statbuf.st_dev == procdev))
... ...
@@ -219,7 +214,7 @@ int scan(const char *filename, unsigned long int *scanned, const struct cl_node
219 219
 
220 220
     switch(sb.st_mode & S_IFMT) {
221 221
 	case S_IFLNK:
222
-	    if(!cfgopt(copt, "FollowFileSymlinks"))
222
+	    if(!cfgopt(copt, "FollowFileSymlinks")->enabled)
223 223
 		break;
224 224
 	    /* else go to the next case */
225 225
 	case S_IFREG: 
... ...
@@ -297,7 +292,7 @@ int scanfd(const int fd, unsigned long int *scanned, const struct cl_node *root,
297 297
 
298 298
 int scanstream(int odesc, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, const struct cfgstruct *copt)
299 299
 {
300
-	int ret, portscan = CL_DEFAULT_MAXPORTSCAN, sockfd, port = 0, acceptd;
300
+	int ret, portscan = 1000, sockfd, port = 0, acceptd;
301 301
 	int tmpd, bread, retval, timeout, btread, min_port, max_port;
302 302
 	long int size = 0, maxsize = 0;
303 303
 	short bound = 0, rnd_port_first = 1;
... ...
@@ -310,22 +305,14 @@ int scanstream(int odesc, unsigned long int *scanned, const struct cl_node *root
310 310
 
311 311
 
312 312
     /* get min port */
313
-    if((cpt = cfgopt(copt, "StreamMinPort"))) {
314
-	if(cpt->numarg < 1024 || cpt->numarg > 65535)
315
-	    min_port = 1024;
316
-	else 
317
-	    min_port = cpt->numarg;
318
-    } else 
313
+    min_port = cfgopt(copt, "StreamMinPort")->numarg;
314
+    if(min_port < 1024 || min_port > 65535)
319 315
 	min_port = 1024;
320 316
 
321 317
     /* get max port */
322
-    if((cpt = cfgopt(copt, "StreamMaxPort"))) {
323
-	if(cpt->numarg < min_port || cpt->numarg > 65535)
324
-	    max_port = 65535;
325
-	else
326
-	    max_port = cpt->numarg;
327
-    } else
328
-	max_port = 2048;
318
+    max_port = cfgopt(copt, "StreamMaxPort")->numarg;
319
+    if(max_port < min_port || max_port > 65535)
320
+	max_port = 65535;
329 321
 
330 322
     /* bind to a free port */
331 323
     while(!bound && --portscan) {
... ...
@@ -343,7 +330,7 @@ int scanstream(int odesc, unsigned long int *scanned, const struct cl_node *root
343 343
 	server.sin_family = AF_INET;
344 344
 	server.sin_port = htons(port);
345 345
 
346
-	if((cpt = cfgopt(copt, "TCPAddr"))) {
346
+	if((cpt = cfgopt(copt, "TCPAddr"))->enabled) {
347 347
 	    pthread_mutex_lock(&gh_mutex);
348 348
 	    if((he = gethostbyname(cpt->strarg)) == 0) {
349 349
 		logg("!gethostbyname(%s) error: %s\n", cpt->strarg);
... ...
@@ -365,11 +352,7 @@ int scanstream(int odesc, unsigned long int *scanned, const struct cl_node *root
365 365
 	    bound = 1;
366 366
     }
367 367
 
368
-    if((cpt = cfgopt(copt, "ReadTimeout")))
369
-	timeout = cpt->numarg;
370
-    else
371
-	timeout = CL_DEFAULT_SCANTIMEOUT;
372
-
368
+    timeout = cfgopt(copt, "ReadTimeout")->numarg;
373 369
     if(timeout == 0)
374 370
     	timeout = -1;
375 371
 
... ...
@@ -418,11 +401,7 @@ int scanstream(int odesc, unsigned long int *scanned, const struct cl_node *root
418 418
 	return -1;
419 419
     }
420 420
 
421
-    if((cpt = cfgopt(copt, "StreamMaxLength")))
422
-	maxsize = cpt->numarg;
423
-    else
424
-	maxsize = CL_DEFAULT_STREAMMAXLEN;
425
-
421
+    maxsize = cfgopt(copt, "StreamMaxLength")->numarg;
426 422
 
427 423
     btread = sizeof(buff);
428 424
 
... ...
@@ -439,7 +418,7 @@ int scanstream(int odesc, unsigned long int *scanned, const struct cl_node *root
439 439
 	    mdprintf(odesc, "Temporary file -> write ERROR\n");
440 440
 	    logg("!ScanStream %d: Can't write to temporary file.\n", port);
441 441
 	    close(tmpd);
442
-	    if(!cfgopt(copt, "LeaveTemporaryFiles"))
442
+	    if(!cfgopt(copt, "LeaveTemporaryFiles")->enabled)
443 443
 		unlink(tmpname);
444 444
 	    free(tmpname);
445 445
 	    return -1;
... ...
@@ -469,7 +448,7 @@ int scanstream(int odesc, unsigned long int *scanned, const struct cl_node *root
469 469
     lseek(tmpd, 0, SEEK_SET);
470 470
     ret = cl_scandesc(tmpd, &virname, scanned, root, limits, options);
471 471
     close(tmpd);
472
-    if(!cfgopt(copt, "LeaveTemporaryFiles"))
472
+    if(!cfgopt(copt, "LeaveTemporaryFiles")->enabled)
473 473
 	unlink(tmpname);
474 474
     free(tmpname);
475 475
 
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2002 - 2004 Tomasz Kojm <tkojm@clamav.net>
2
+ *  Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>
3 3
  *			      Trog <trog@clamav.net>
4 4
  *
5 5
  *  This program is free software; you can redistribute it and/or modify
... ...
@@ -35,7 +35,6 @@
35 35
 #include "server.h"
36 36
 #include "thrmgr.h"
37 37
 #include "session.h"
38
-#include "defaults.h"
39 38
 #include "clamuko.h"
40 39
 #include "others.h"
41 40
 #include "memory.h"
... ...
@@ -75,12 +74,7 @@ void scanner_thread(void *arg)
75 75
     sigfillset(&sigset);
76 76
     pthread_sigmask(SIG_SETMASK, &sigset, NULL);
77 77
 
78
-    if((cpt = cfgopt(conn->copt, "ReadTimeout"))) {
79
-	timeout = cpt->numarg;
80
-    } else {
81
-	timeout = CL_DEFAULT_SCANTIMEOUT;
82
-    }
83
-
78
+    timeout = cfgopt(conn->copt, "ReadTimeout")->numarg;
84 79
     if(!timeout)
85 80
     	timeout = -1;
86 81
 
... ...
@@ -188,11 +182,7 @@ static struct cl_node *reload_db(struct cl_node *root, const struct cfgstruct *c
188 188
 	root = NULL;
189 189
     }
190 190
 
191
-    if((cpt = cfgopt(copt, "DatabaseDirectory")) || (cpt = cfgopt(copt, "DataDirectory"))) {
192
-	dbdir = cpt->strarg;
193
-    } else {
194
-	dbdir = cl_retdbdir();
195
-    }
191
+    dbdir = cfgopt(copt, "DatabaseDirectory")->strarg;
196 192
     logg("Reading databases from %s\n", dbdir);
197 193
 
198 194
     if(dbstat == NULL) {
... ...
@@ -225,7 +215,7 @@ static struct cl_node *reload_db(struct cl_node *root, const struct cfgstruct *c
225 225
 
226 226
 int acceptloop_th(int socketd, struct cl_node *root, const struct cfgstruct *copt)
227 227
 {
228
-	int new_sd, max_threads, stdopt;
228
+	int new_sd, max_threads;
229 229
 	unsigned int options = 0;
230 230
 	threadpool_t *thr_pool;
231 231
 	struct sigaction sigact;
... ...
@@ -256,7 +246,7 @@ int acceptloop_th(int socketd, struct cl_node *root, const struct cfgstruct *cop
256 256
 
257 257
     /* save the PID */
258 258
     mainpid = getpid();
259
-    if((cpt = cfgopt(copt, "PidFile"))) {
259
+    if((cpt = cfgopt(copt, "PidFile"))->enabled) {
260 260
 	    FILE *fd;
261 261
 	old_umask = umask(0006);
262 262
 	if((fd = fopen(cpt->strarg, "w")) == NULL) {
... ...
@@ -269,95 +259,55 @@ int acceptloop_th(int socketd, struct cl_node *root, const struct cfgstruct *cop
269 269
     }
270 270
 
271 271
     logg("*Listening daemon: PID: %d\n", getpid());
272
-    if((cpt = cfgopt(copt, "MaxThreads"))) {
273
-	max_threads = cpt->numarg;
274
-    } else {
275
-	max_threads = CL_DEFAULT_MAXTHREADS;
276
-    }
272
+    max_threads = cfgopt(copt, "MaxThreads")->numarg;
277 273
 
278
-    if(cfgopt(copt, "DisableDefaultScanOptions")) {
279
-	logg("RECOMMENDED OPTIONS DISABLED.\n");
280
-	stdopt = 0;
281
-    } else {
282
-	options |= CL_SCAN_STDOPT;
283
-	stdopt = 1;
284
-    }
285
-
286
-    if(stdopt || cfgopt(copt, "ScanArchive") || cfgopt(copt, "ClamukoScanArchive")) {
274
+    if(cfgopt(copt, "ScanArchive")->enabled || cfgopt(copt, "ClamukoScanArchive")->enabled) {
287 275
 
288 276
 	/* set up limits */
289 277
 	memset(&limits, 0, sizeof(struct cl_limits));
290 278
 
291
-	if((cpt = cfgopt(copt, "ArchiveMaxFileSize"))) {
292
-	    if((limits.maxfilesize = cpt->numarg)) {
293
-		logg("Archive: Archived file size limit set to %d bytes.\n", limits.maxfilesize);
294
-	    } else {
295
-		logg("^Archive: File size limit protection disabled.\n");
296
-	    }
297
-	} else {
298
-	    limits.maxfilesize = 10485760;
279
+	if((limits.maxfilesize = cfgopt(copt, "ArchiveMaxFileSize")->numarg)) {
299 280
 	    logg("Archive: Archived file size limit set to %d bytes.\n", limits.maxfilesize);
281
+	} else {
282
+	    logg("^Archive: File size limit protection disabled.\n");
300 283
 	}
301 284
 
302
-	if((cpt = cfgopt(copt, "ArchiveMaxRecursion"))) {
303
-	    if((limits.maxreclevel = cpt->numarg)) {
304
-		logg("Archive: Recursion level limit set to %d.\n", limits.maxreclevel);
305
-	    } else {
306
-		logg("^Archive: Recursion level limit protection disabled.\n");
307
-	    }
308
-	} else {
309
-	    limits.maxreclevel = 8;
285
+	if((limits.maxreclevel = cfgopt(copt, "ArchiveMaxRecursion")->numarg)) {
310 286
 	    logg("Archive: Recursion level limit set to %d.\n", limits.maxreclevel);
287
+	} else {
288
+	    logg("^Archive: Recursion level limit protection disabled.\n");
311 289
 	}
312 290
 
313
-	if((cpt = cfgopt(copt, "ArchiveMaxFiles"))) {
314
-	    if((limits.maxfiles = cpt->numarg)) {
315
-		logg("Archive: Files limit set to %d.\n", limits.maxfiles);
316
-	    } else {
317
-		logg("^Archive: Files limit protection disabled.\n");
318
-	    }
319
-	} else {
320
-	    limits.maxfiles = 1000;
291
+	if((limits.maxfiles = cfgopt(copt, "ArchiveMaxFiles")->numarg)) {
321 292
 	    logg("Archive: Files limit set to %d.\n", limits.maxfiles);
293
+	} else {
294
+	    logg("^Archive: Files limit protection disabled.\n");
322 295
 	}
323 296
 
324
-	if((cpt = cfgopt(copt, "ArchiveMaxCompressionRatio"))) {
325
-	    if((limits.maxratio = cpt->numarg)) {
326
-		logg("Archive: Compression ratio limit set to %d.\n", limits.maxratio);
327
-	    } else {
328
-		logg("^Archive: Compression ratio limit disabled.\n");
329
-	    }
330
-	} else {
331
-	    limits.maxratio = 250;
297
+	if((limits.maxratio = cfgopt(copt, "ArchiveMaxCompressionRatio")->numarg)) {
332 298
 	    logg("Archive: Compression ratio limit set to %d.\n", limits.maxratio);
299
+	} else {
300
+	    logg("^Archive: Compression ratio limit disabled.\n");
333 301
 	}
334 302
 
335
-	if(cfgopt(copt, "ArchiveLimitMemoryUsage")) {
303
+	if(cfgopt(copt, "ArchiveLimitMemoryUsage")->enabled) {
336 304
 	    limits.archivememlim = 1;
337 305
 	    logg("Archive: Limited memory usage.\n");
338 306
 	} else {
339 307
 	    limits.archivememlim = 0;
340 308
 	}
341
-
342 309
     }
343 310
 
344
-    if(stdopt || cfgopt(copt, "ScanArchive")) {
311
+    if(cfgopt(copt, "ScanArchive")->enabled) {
345 312
 	logg("Archive support enabled.\n");
346 313
 	options |= CL_SCAN_ARCHIVE;
347 314
 
348
-	if(cfgopt(copt, "ScanRAR")) {
349
-	    logg("Archive: RAR support enabled.\n");
350
-	} else {
351
-	    logg("Archive: RAR support disabled.\n");
352
-	    options |= CL_SCAN_DISABLERAR;
353
-	}
354
-
355
-	if(cfgopt(copt, "ArchiveBlockEncrypted")) {
315
+	if(cfgopt(copt, "ArchiveBlockEncrypted")->enabled) {
356 316
 	    logg("Archive: Blocking encrypted archives.\n");
357 317
 	    options |= CL_SCAN_BLOCKENCRYPTED;
358 318
 	}
359 319
 
360
-	if(cfgopt(copt, "ArchiveBlockMax")) {
320
+	if(cfgopt(copt, "ArchiveBlockMax")->enabled) {
361 321
 	    logg("Archive: Blocking archives that exceed limits.\n");
362 322
 	    options |= CL_SCAN_BLOCKMAX;
363 323
 	}
... ...
@@ -366,11 +316,11 @@ int acceptloop_th(int socketd, struct cl_node *root, const struct cfgstruct *cop
366 366
 	logg("Archive support disabled.\n");
367 367
     }
368 368
 
369
-    if(stdopt || cfgopt(copt, "ScanPE")) {
369
+    if(cfgopt(copt, "ScanPE")->enabled) {
370 370
 	logg("Portable Executable support enabled.\n");
371 371
 	options |= CL_SCAN_PE;
372 372
 
373
-	if(cfgopt(copt, "DetectBrokenExecutables")) {
373
+	if(cfgopt(copt, "DetectBrokenExecutables")->enabled) {
374 374
 	    logg("Detection of broken executables enabled.\n");
375 375
 	    options |= CL_SCAN_BLOCKBROKEN;
376 376
 	}
... ...
@@ -379,11 +329,11 @@ int acceptloop_th(int socketd, struct cl_node *root, const struct cfgstruct *cop
379 379
 	logg("Portable Executable support disabled.\n");
380 380
     }
381 381
 
382
-    if(stdopt || cfgopt(copt, "ScanMail")) {
382
+    if(cfgopt(copt, "ScanMail")->enabled) {
383 383
 	logg("Mail files support enabled.\n");
384 384
 	options |= CL_SCAN_MAIL;
385 385
 
386
-	if(cfgopt(copt, "MailFollowURLs")) {
386
+	if(cfgopt(copt, "MailFollowURLs")->enabled) {
387 387
 	    logg("Mail: URL scanning enabled.\n");
388 388
 	    options |= CL_SCAN_MAILURL;
389 389
 	}
... ...
@@ -392,26 +342,21 @@ int acceptloop_th(int socketd, struct cl_node *root, const struct cfgstruct *cop
392 392
 	logg("Mail files support disabled.\n");
393 393
     }
394 394
 
395
-    if(stdopt || cfgopt(copt, "ScanOLE2")) {
395
+    if(cfgopt(copt, "ScanOLE2")->enabled) {
396 396
 	logg("OLE2 support enabled.\n");
397 397
 	options |= CL_SCAN_OLE2;
398 398
     } else {
399 399
 	logg("OLE2 support disabled.\n");
400 400
     }
401 401
 
402
-    if(stdopt || cfgopt(copt, "ScanHTML")) {
402
+    if(cfgopt(copt, "ScanHTML")->enabled) {
403 403
 	logg("HTML support enabled.\n");
404 404
 	options |= CL_SCAN_HTML;
405 405
     } else {
406 406
 	logg("HTML support disabled.\n");
407 407
     }
408 408
 
409
-    if((cpt = cfgopt(copt, "SelfCheck"))) {
410
-	selfchk = cpt->numarg;
411
-    } else {
412
-	selfchk = CL_DEFAULT_SELFCHECK;
413
-    }
414
-
409
+    selfchk = cfgopt(copt, "SelfCheck")->numarg;
415 410
     if(!selfchk) {
416 411
 	logg("Self checking disabled.\n");
417 412
     } else {
... ...
@@ -421,7 +366,7 @@ int acceptloop_th(int socketd, struct cl_node *root, const struct cfgstruct *cop
421 421
     pthread_attr_init(&thattr);
422 422
     pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_DETACHED);
423 423
 
424
-    if(cfgopt(copt, "ClamukoScanOnLine") || cfgopt(copt, "ClamukoScanOnAccess"))
424
+    if(cfgopt(copt, "ClamukoScanOnAccess")->enabled)
425 425
 #ifdef CLAMUKO
426 426
     {
427 427
 	pthread_attr_init(&clamuko_attr);
... ...
@@ -483,11 +428,7 @@ int acceptloop_th(int socketd, struct cl_node *root, const struct cfgstruct *cop
483 483
     pthread_mutex_init(&exit_mutex, NULL);
484 484
     pthread_mutex_init(&reload_mutex, NULL);
485 485
 
486
-
487
-    if((cpt = cfgopt(copt, "IdleTimeout")))
488
-	idletimeout = cpt->numarg;
489
-    else
490
-	idletimeout = CL_DEFAULT_IDLETIMEOUT;
486
+    idletimeout = cfgopt(copt, "IdleTimeout")->numarg;
491 487
 
492 488
     if((thr_pool=thrmgr_new(max_threads, idletimeout, scanner_thread)) == NULL) {
493 489
 	logg("!thrmgr_new failed\n");
... ...
@@ -512,7 +453,7 @@ int acceptloop_th(int socketd, struct cl_node *root, const struct cfgstruct *cop
512 512
 		logg("SIGHUP caught: re-opening log file.\n");
513 513
 		logg_close();
514 514
 		sighup = 0;
515
-		if(!logg_file && (cpt = cfgopt(copt, "LogFile")))
515
+		if(!logg_file && (cpt = cfgopt(copt, "LogFile"))->enabled)
516 516
 		    logg_file = cpt->strarg;
517 517
 	}
518 518
 
... ...
@@ -563,7 +504,7 @@ int acceptloop_th(int socketd, struct cl_node *root, const struct cfgstruct *cop
563 563
 	    time(&reloaded_time);
564 564
 	    pthread_mutex_unlock(&reload_mutex);
565 565
 #ifdef CLAMUKO
566
-	    if(cfgopt(copt, "ClamukoScanOnLine") || cfgopt(copt, "ClamukoScanOnAccess")) {
566
+	    if(cfgopt(copt, "ClamukoScanOnAccess")->enabled) {
567 567
 		logg("Stopping and restarting Clamuko.\n");
568 568
 		pthread_kill(clamuko_pid, SIGUSR1);
569 569
 		pthread_join(clamuko_pid, NULL);
... ...
@@ -581,7 +522,7 @@ int acceptloop_th(int socketd, struct cl_node *root, const struct cfgstruct *cop
581 581
      */
582 582
     thrmgr_destroy(thr_pool);
583 583
 #ifdef CLAMUKO
584
-    if(cfgopt(copt, "ClamukoScanOnLine") || cfgopt(copt, "ClamukoScanOnAccess")) {
584
+    if(cfgopt(copt, "ClamukoScanOnAccess")->enabled) {
585 585
 	logg("Stopping Clamuko.\n");
586 586
 	pthread_kill(clamuko_pid, SIGUSR1);
587 587
 	pthread_join(clamuko_pid, NULL);
... ...
@@ -594,7 +535,7 @@ int acceptloop_th(int socketd, struct cl_node *root, const struct cfgstruct *cop
594 594
     close(socketd);
595 595
 
596 596
 #ifndef C_OS2
597
-    if((cpt = cfgopt(copt, "LocalSocket"))) {
597
+    if((cpt = cfgopt(copt, "LocalSocket"))->enabled) {
598 598
 	if(unlink(cpt->strarg) == -1)
599 599
 	    logg("!Can't unlink the socket file %s\n", cpt->strarg);
600 600
 	else
... ...
@@ -602,7 +543,7 @@ int acceptloop_th(int socketd, struct cl_node *root, const struct cfgstruct *cop
602 602
     }
603 603
 #endif
604 604
 
605
-    if((cpt = cfgopt(copt, "PidFile"))) {
605
+    if((cpt = cfgopt(copt, "PidFile"))->enabled) {
606 606
 	if(unlink(cpt->strarg) == -1)
607 607
 	    logg("!Can't unlink the pid file %s\n", cpt->strarg);
608 608
 	else
... ...
@@ -34,7 +34,6 @@
34 34
 
35 35
 #include "cfgparser.h"
36 36
 #include "others.h"
37
-#include "defaults.h"
38 37
 #include "scanner.h"
39 38
 #include "server.h"
40 39
 #include "clamuko.h"
... ...
@@ -82,13 +81,13 @@ int command(int desc, const struct cl_node *root, const struct cl_limits *limits
82 82
 
83 83
     if(!strncmp(buff, CMD1, strlen(CMD1))) { /* SCAN */
84 84
 	if(scan(buff + strlen(CMD1) + 1, NULL, root, limits, options, copt, desc, 0) == -2)
85
-	    if(cfgopt(copt, "ExitOnOOM"))
85
+	    if(cfgopt(copt, "ExitOnOOM")->enabled)
86 86
 		return COMMAND_SHUTDOWN;
87 87
 
88 88
     } else if(!strncmp(buff, CMD2, strlen(CMD2))) { /* RAWSCAN */
89 89
 	opt = options & ~CL_SCAN_ARCHIVE;
90 90
 	if(scan(buff + strlen(CMD2) + 1, NULL, root, NULL, opt, copt, desc, 0) == -2)
91
-	    if(cfgopt(copt, "ExitOnOOM"))
91
+	    if(cfgopt(copt, "ExitOnOOM")->enabled)
92 92
 		return COMMAND_SHUTDOWN;
93 93
 
94 94
     } else if(!strncmp(buff, CMD3, strlen(CMD3))) { /* QUIT */
... ...
@@ -103,19 +102,14 @@ int command(int desc, const struct cl_node *root, const struct cl_limits *limits
103 103
 
104 104
     } else if(!strncmp(buff, CMD6, strlen(CMD6))) { /* CONTSCAN */
105 105
 	if(scan(buff + strlen(CMD6) + 1, NULL, root, limits, options, copt, desc, 1) == -2)
106
-	    if(cfgopt(copt, "ExitOnOOM"))
106
+	    if(cfgopt(copt, "ExitOnOOM")->enabled)
107 107
 		return COMMAND_SHUTDOWN;
108 108
 
109 109
     } else if(!strncmp(buff, CMD7, strlen(CMD7))) { /* VERSION */
110
-	    const char *dbdir;
110
+	    const char *dbdir = cfgopt(copt, "DatabaseDirectory")->strarg;
111 111
 	    char *path;
112 112
 	    struct cl_cvd *daily;
113 113
 
114
-	if((cpt = cfgopt(copt, "DatabaseDirectory")) || (cpt = cfgopt(copt, "DataDirectory")))
115
-	    dbdir = cpt->strarg;
116
-	else
117
-	    dbdir = cl_retdbdir();
118
-
119 114
 	if(!(path = mmalloc(strlen(dbdir) + 11))) {
120 115
 	    mdprintf(desc, "Memory allocation error - SHUTDOWN forced\n");
121 116
 	    return COMMAND_SHUTDOWN;
... ...
@@ -138,7 +132,7 @@ int command(int desc, const struct cl_node *root, const struct cl_limits *limits
138 138
 
139 139
     } else if(!strncmp(buff, CMD8, strlen(CMD8))) { /* STREAM */
140 140
 	if(scanstream(desc, NULL, root, limits, options, copt) == CL_EMEM)
141
-	    if(cfgopt(copt, "ExitOnOOM"))
141
+	    if(cfgopt(copt, "ExitOnOOM")->enabled)
142 142
 		return COMMAND_SHUTDOWN;
143 143
 
144 144
     } else if(!strncmp(buff, CMD9, strlen(CMD9))) { /* SESSION */
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2002 Tomasz Kojm <zolw@konarski.edu.pl>
2
+ *  Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>
3 3
  *
4 4
  *  This program is free software; you can redistribute it and/or modify
5 5
  *  it under the terms of the GNU General Public License as published by
... ...
@@ -30,10 +30,8 @@
30 30
 #include <errno.h>
31 31
 #include <netdb.h>
32 32
 
33
-
34 33
 #include "options.h"
35 34
 #include "cfgparser.h"
36
-#include "defaults.h"
37 35
 #include "others.h"
38 36
 #include "server.h"
39 37
 #include "output.h"
... ...
@@ -52,8 +50,7 @@ int tcpserver(const struct optstruct *opt, const struct cfgstruct *copt, struct
52 52
     server.sin_family = AF_INET;
53 53
     server.sin_port = htons(cfgopt(copt, "TCPSocket")->numarg);
54 54
 
55
-
56
-    if((taddr = cfgopt(copt, "TCPAddr"))) {
55
+    if((taddr = cfgopt(copt, "TCPAddr"))->enabled) {
57 56
 	if ((he = gethostbyname(taddr->strarg)) == 0) {
58 57
 	    logg("!gethostbyname(%s) error: %s\n", taddr->strarg, strerror(errno));
59 58
 	    exit(1);
... ...
@@ -65,9 +62,6 @@ int tcpserver(const struct optstruct *opt, const struct cfgstruct *copt, struct
65 65
 
66 66
     if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
67 67
 	estr = strerror(errno);
68
-	/*
69
-	fprintf(stderr, "ERROR: socket() error: %s\n", estr);
70
-	*/
71 68
 	logg("!socket() error: %s\n", estr);
72 69
 	exit(1);
73 70
     }
... ...
@@ -78,38 +72,25 @@ int tcpserver(const struct optstruct *opt, const struct cfgstruct *copt, struct
78 78
 
79 79
     if(bind(sockfd, (struct sockaddr *) &server, sizeof(struct sockaddr_in)) == -1) {
80 80
 	estr = strerror(errno);
81
-	/* 
82
-	fprintf(stderr, "ERROR: can't bind(): %s\n", estr);
83
-	*/
84 81
 	logg("!bind() error: %s\n", estr);
85 82
 	exit(1);
86 83
     } else {
87
-	if ( taddr != NULL && *taddr->strarg )
84
+	if(taddr->enabled)
88 85
 	    logg("Bound to address %s on port %d\n", taddr->strarg, cfgopt(copt, "TCPSocket")->numarg);
89 86
 	else
90 87
 	    logg("Bound to port %d\n", cfgopt(copt, "TCPSocket")->numarg);
91 88
     }
92 89
 
93
-    if((cpt = cfgopt(copt, "MaxConnectionQueueLength")))
94
-	backlog = cpt->numarg;
95
-    else
96
-	backlog = CL_DEFAULT_BACKLOG;
97
-
90
+    backlog = cfgopt(copt, "MaxConnectionQueueLength")->numarg;
98 91
     logg("Setting connection queue length to %d\n", backlog);
99 92
 
100 93
     if(listen(sockfd, backlog) == -1) {
101 94
 	estr = strerror(errno);
102
-	/*
103
-	fprintf(stderr, "ERROR: listen() error: %s\n", estr);
104
-	*/
105 95
 	logg("!listen() error: %s\n", estr);
106 96
 	exit(1);
107 97
     }
108 98
 
109
-    /* if(cfgopt(copt, "UseProcesses"))
110
-	acceptloop_proc(sockfd, root, copt);
111
-    else */
112
-	acceptloop_th(sockfd, root, copt);
99
+    acceptloop_th(sockfd, root, copt);
113 100
 
114 101
     return 0;
115 102
 }
... ...
@@ -318,7 +318,7 @@ int dconnect(const struct optstruct *opt)
318 318
     if(!clamav_conf)
319 319
 	clamav_conf = DEFAULT_CFG;
320 320
 
321
-    if((copt = parsecfg(clamav_conf, 1)) == NULL) {
321
+    if((copt = getcfg(clamav_conf, 1)) == NULL) {
322 322
 	mprintf("@Can't parse the configuration file.\n");
323 323
 	return -1;
324 324
     }
... ...
@@ -329,10 +329,10 @@ int dconnect(const struct optstruct *opt)
329 329
     /* Set default address to connect to */
330 330
     server2.sin_addr.s_addr = inet_addr("127.0.0.1");    
331 331
 
332
-    if(cfgopt(copt, "TCPSocket") && cfgopt(copt, "LocalSocket")) {
332
+    if(cfgopt(copt, "TCPSocket")->enabled && cfgopt(copt, "LocalSocket")->enabled) {
333 333
 	mprintf("@Clamd is not configured properly.\n");
334 334
 	return -1;
335
-    } else if((cpt = cfgopt(copt, "LocalSocket"))) {
335
+    } else if((cpt = cfgopt(copt, "LocalSocket"))->enabled) {
336 336
 
337 337
 	server.sun_family = AF_UNIX;
338 338
 	strncpy(server.sun_path, cpt->strarg, sizeof(server.sun_path));
... ...
@@ -350,7 +350,7 @@ int dconnect(const struct optstruct *opt)
350 350
 	    return -1;
351 351
 	}
352 352
 
353
-    } else if((cpt = cfgopt(copt, "TCPSocket"))) {
353
+    } else if((cpt = cfgopt(copt, "TCPSocket"))->enabled) {
354 354
 
355 355
 	if((sockd = socket(SOCKET_INET, SOCK_STREAM, 0)) < 0) {
356 356
 	    perror("socket()");
... ...
@@ -361,7 +361,7 @@ int dconnect(const struct optstruct *opt)
361 361
 	server2.sin_family = AF_INET;
362 362
 	server2.sin_port = htons(cpt->numarg);
363 363
 
364
-	if((cpt = cfgopt(copt, "TCPAddr"))) {
364
+	if((cpt = cfgopt(copt, "TCPAddr"))->enabled) {
365 365
 	    if ((he = gethostbyname(cpt->strarg)) == 0) {
366 366
 		close(sockd);
367 367
 		perror("gethostbyname()");
... ...
@@ -1,5 +1,5 @@
1 1
 ##
2
-## Example config file for the Clam AV daemon
2
+## Example config file for the Clam AV daemyes
3 3
 ## Please read the clamd.conf(5) manual before editing this file.
4 4
 ##
5 5
 
... ...
@@ -18,8 +18,8 @@ Example
18 18
 # copy the configuration file, change the LogFile variable, and run
19 19
 # the daemon with --config-file option).
20 20
 # This option disables log file locking.
21
-# Default: disabled
22
-#LogFileUnlock
21
+# Default: no
22
+#LogFileUnlock yes
23 23
 
24 24
 # Maximal size of the log file.
25 25
 # Value of 0 disables the limit.
... ...
@@ -30,17 +30,17 @@ Example
30 30
 #LogFileMaxSize 2M
31 31
 
32 32
 # Log time with each message.
33
-# Default: disabled
34
-#LogTime
33
+# Default: no
34
+#LogTime yes
35 35
 
36 36
 # Also log clean files. Useful in debugging but drastically increases the
37 37
 # log size.
38
-# Default: disabled
39
-#LogClean
38
+# Default: no
39
+#LogClean yes
40 40
 
41 41
 # Use system logger (can work together with LogFile).
42
-# Default: disabled
43
-#LogSyslog
42
+# Default: no
43
+#LogSyslog yes
44 44
 
45 45
 # Specify the type of syslog messages - please refer to 'man syslog'
46 46
 # for facility names.
... ...
@@ -48,8 +48,8 @@ Example
48 48
 #LogFacility LOG_MAIL
49 49
 
50 50
 # Enable verbose logging.
51
-# Default: disabled
52
-#LogVerbose
51
+# Default: no
52
+#LogVerbose yes
53 53
 
54 54
 # This option allows you to save a process identifier of the listening
55 55
 # daemon (main thread).
... ...
@@ -68,22 +68,22 @@ Example
68 68
 # recommend the local mode.
69 69
 
70 70
 # Path to a local socket file the daemon will listen on.
71
-# Default: disabled
71
+# Default: disabled (must be specified by a user)
72 72
 LocalSocket /tmp/clamd
73 73
 
74 74
 # Remove stale socket after unclean shutdown.
75
-# Default: disabled
76
-FixStaleSocket
75
+# Default: no
76
+#FixStaleSocket yes
77 77
 
78 78
 # TCP port address.
79
-# Default: disabled
79
+# Default: no
80 80
 #TCPSocket 3310
81 81
 
82 82
 # TCP address.
83 83
 # By default we bind to INADDR_ANY, probably not wise.
84
-# Enable the following to provide some degree of protection
84
+# Enable the following to provide some degree of protectiyes
85 85
 # from the outside world.
86
-# Default: disabled
86
+# Default: no
87 87
 #TCPAddr 127.0.0.1
88 88
 
89 89
 # Maximum length the queue of pending connections may grow to.
... ...
@@ -123,12 +123,12 @@ FixStaleSocket
123 123
 #MaxDirectoryRecursion 20
124 124
 
125 125
 # Follow directory symlinks.
126
-# Default: disabled
127
-#FollowDirectorySymlinks
126
+# Default: no
127
+#FollowDirectorySymlinks yes
128 128
 
129 129
 # Follow regular file symlinks.
130
-# Default: disabled
131
-#FollowFileSymlinks
130
+# Default: no
131
+#FollowFileSymlinks yes
132 132
 
133 133
 # Perform internal sanity check (database integrity and freshness).
134 134
 # Default: 1800 (30 min)
... ...
@@ -136,38 +136,31 @@ FixStaleSocket
136 136
 
137 137
 # Execute a command when virus is found. In the command string %v will
138 138
 # be replaced by a virus name.
139
-# Default: disabled
139
+# Default: no
140 140
 #VirusEvent /usr/local/bin/send_sms 123456789 "VIRUS ALERT: %v"
141 141
 
142 142
 # Run as a selected user (clamd must be started by root).
143
-# Default: disabled
143
+# Default: don't drop privileges
144 144
 #User clamav
145 145
 
146 146
 # Initialize supplementary group access (clamd must be started by root).
147
-# Default: disabled
148
-#AllowSupplementaryGroups
147
+# Default: no
148
+#AllowSupplementaryGroups no
149 149
 
150 150
 # Stop daemon when libclamav reports out of memory condition.
151
-#ExitOnOOM
151
+#ExitOnOOM yes
152 152
 
153 153
 # Don't fork into background.
154
-# Default: disabled
155
-#Foreground
154
+# Default: no
155
+#Foreground yes
156 156
 
157 157
 # Enable debug messages in libclamav.
158
-# Default: disabled
159
-#Debug
158
+# Default: no
159
+#Debug yes
160 160
 
161 161
 # Do not remove temporary files (for debug purposes).
162
-# Default: disabled
163
-#LeaveTemporaryFiles
164
-
165
-
166
-# By default clamd uses scan options recommended by libclamav. This option
167
-# disables recommended options and allows you to enable selected ones below.
168
-# DO NOT TOUCH IT unless you know what you are doing.
169
-# Default: disabled
170
-#DisableDefaultScanOptions
162
+# Default: no
163
+#LeaveTemporaryFiles yes
171 164
 
172 165
 ##
173 166
 ## Executable files
... ...
@@ -178,13 +171,13 @@ FixStaleSocket
178 178
 # ClamAV to perform a deeper analysis of executable files and it's also
179 179
 # required for decompression of popular executable packers such as UPX, FSG,
180 180
 # and Petite.
181
-# Default: enabled
182
-#ScanPE
181
+# Default: yes
182
+#ScanPE yes
183 183
 
184 184
 # With this option clamav will try to detect broken executables and mark
185 185
 # them as Broken.Executable
186
-# Default: disabled
187
-#DetectBrokenExecutables
186
+# Default: no
187
+#DetectBrokenExecutables yes
188 188
 
189 189
 
190 190
 ##
... ...
@@ -192,22 +185,22 @@ FixStaleSocket
192 192
 ##
193 193
 
194 194
 # This option enables scanning of Microsoft Office document macros.
195
-# Default: enabled
196
-#ScanOLE2
195
+# Default: yes
196
+#ScanOLE2 yes
197 197
 
198 198
 ##
199 199
 ## Mail files
200 200
 ##
201 201
 
202 202
 # Enable internal e-mail scanner.
203
-# Default: enabled
204
-#ScanMail
203
+# Default: yes
204
+#ScanMail yes
205 205
 
206 206
 # If an email contains URLs ClamAV can download and scan them.
207 207
 # WARNING: This option may open your system to a DoS attack.
208 208
 #	   Never use it on loaded servers.
209
-# Default: disabled
210
-#MailFollowURLs
209
+# Default: no
210
+#MailFollowURLs no
211 211
 
212 212
 
213 213
 ##
... ...
@@ -215,8 +208,8 @@ FixStaleSocket
215 215
 ##
216 216
 
217 217
 # Perform HTML normalisation and decryption of MS Script Encoder code.
218
-# Default: enabled
219
-#ScanHTML
218
+# Default: yes
219
+#ScanHTML yes
220 220
 
221 221
 
222 222
 ##
... ...
@@ -224,15 +217,8 @@ FixStaleSocket
224 224
 ##
225 225
 
226 226
 # ClamAV can scan within archives and compressed files.
227
-# Default: enabled
228
-#ScanArchive
229
-
230
-# Due to license issues libclamav does not support RAR 3.0 archives (only the
231
-# old 2.0 format is supported). Because some users report stability problems
232
-# with unrarlib it's disabled by default and you must uncomment the directive
233
-# below to enable RAR 2.0 support.
234
-# Default: disabled
235
-#ScanRAR
227
+# Default: yes
228
+#ScanArchive yes
236 229
 
237 230
 # The options below protect your system against Denial of Service attacks
238 231
 # using archive bombs.
... ...
@@ -247,7 +233,7 @@ FixStaleSocket
247 247
 # deep the process should be continued.
248 248
 # Value of 0 disables the limit.
249 249
 # Default: 8
250
-#ArchiveMaxRecursion 9
250
+#ArchiveMaxRecursion 10
251 251
 
252 252
 # Number of files to be scanned within an archive.
253 253
 # Value of 0 disables the limit.
... ...
@@ -262,18 +248,18 @@ FixStaleSocket
262 262
 
263 263
 # Use slower but memory efficient decompression algorithm.
264 264
 # only affects the bzip2 decompressor.
265
-# Default: disabled
266
-#ArchiveLimitMemoryUsage
265
+# Default: no
266
+#ArchiveLimitMemoryUsage yes
267 267
 
268 268
 # Mark encrypted archives as viruses (Encrypted.Zip, Encrypted.RAR).
269
-# Default: disabled
270
-#ArchiveBlockEncrypted
269
+# Default: no
270
+#ArchiveBlockEncrypted no
271 271
 
272 272
 # Mark archives as viruses (e.g. RAR.ExceededFileSize, Zip.ExceededFilesLimit)
273 273
 # if ArchiveMaxFiles, ArchiveMaxFileSize, or ArchiveMaxRecursion limit is
274 274
 # reached.
275
-# Default: disabled
276
-#ArchiveBlockMax
275
+# Default: no
276
+#ArchiveBlockMax no
277 277
 
278 278
 
279 279
 ##
... ...
@@ -283,14 +269,14 @@ FixStaleSocket
283 283
 ##
284 284
 
285 285
 # Enable Clamuko. Dazuko (/dev/dazuko) must be configured and running.
286
-# Default: disabled
287
-#ClamukoScanOnAccess
286
+# Default: no
287
+#ClamukoScanOnAccess yes
288 288
 
289 289
 # Set access mask for Clamuko.
290
-# Default: disabled
291
-#ClamukoScanOnOpen
292
-#ClamukoScanOnClose
293
-#ClamukoScanOnExec
290
+# Default: no
291
+#ClamukoScanOnOpen yes
292
+#ClamukoScanOnClose yes
293
+#ClamukoScanOnExec yes
294 294
 
295 295
 # Set the include paths (all files in them will be scanned). You can have
296 296
 # multiple ClamukoIncludePath directives but each directory must be added
... ...
@@ -301,7 +287,7 @@ FixStaleSocket
301 301
 
302 302
 # Set the exclude paths. All subdirectories are also excluded.
303 303
 # Default: disabled
304
-#ClamukoExcludePath /home/guru
304
+#ClamukoExcludePath /home/bofh
305 305
 
306 306
 # Don't scan files larger than ClamukoMaxFileSize
307 307
 # Value of 0 disables the limit.
... ...
@@ -18,19 +18,19 @@ Example
18 18
 #UpdateLogFile /var/log/freshclam.log
19 19
 
20 20
 # Enable verbose logging.
21
-# Default: disabled
22
-#LogVerbose
21
+# Default: no
22
+#LogVerbose yes
23 23
 
24 24
 # Use system logger (can work together with UpdateLogFile).
25
-# Default: disabled
26
-#LogSyslog
25
+# Default: no
26
+#LogSyslog yes
27 27
 
28 28
 # Specify the type of syslog messages - please refer to 'man syslog'
29 29
 # for facility names.
30 30
 # Default: LOG_LOCAL6
31 31
 #LogFacility LOG_MAIL
32 32
 
33
-# This option allows you to save the process identifier of the daemon
33
+# This option allows you to save the process identifier of the daemyes
34 34
 # Default: disabled
35 35
 #PidFile /var/run/freshclam.pid
36 36
 
... ...
@@ -40,18 +40,19 @@ Example
40 40
 #DatabaseOwner clamav
41 41
 
42 42
 # Initialize supplementary group access (freshclam must be started by root).
43
-# Default: disabled
44
-#AllowSupplementaryGroups
43
+# Default: no
44
+#AllowSupplementaryGroups yes
45 45
 
46 46
 # Use DNS to verify virus database version. Freshclam uses DNS TXT records
47 47
 # to verify database and software versions. With this directive you can change
48 48
 # the database verification domain.
49
-# Default: enabled, pointing to current.cvd.clamav.net
49
+# WARNING: Do not touch it unless you're configuring freshclam to use your
50
+# own database verification domain.
51
+# Default: current.cvd.clamav.net
50 52
 #DNSDatabaseInfo current.cvd.clamav.net
51 53
 
52 54
 # Uncomment the following line and replace XY with your country
53 55
 # code. See http://www.iana.org/cctld/cctld-whois.htm for the full list.
54
-# Default: There is no default, which results in an error when running freshclam
55 56
 #DatabaseMirror db.XY.clamav.net
56 57
 
57 58
 # database.clamav.net is a round-robin record which points to our most 
... ...
@@ -81,11 +82,8 @@ DatabaseMirror database.clamav.net
81 81
 #LocalIPAddress aaa.bbb.ccc.ddd
82 82
 
83 83
 # Send the RELOAD command to clamd.
84
-# Default: disabled
85
-#NotifyClamd
86
-# By default it uses the hardcoded configuration file but you can force an
87
-# another one.
88
-#NotifyClamd /config/file/path
84
+# Default: no
85
+#NotifyClamd /path/to/clamd.conf
89 86
 
90 87
 # Run command after successful database update.
91 88
 # Default: disabled
... ...
@@ -96,9 +94,9 @@ DatabaseMirror database.clamav.net
96 96
 #OnErrorExecute command
97 97
 
98 98
 # Don't fork into background.
99
-# Default: disabled
100
-#Foreground
99
+# Default: no
100
+#Foreground yes
101 101
 
102 102
 # Enable debug messages in libclamav.
103
-# Default: disabled
104
-#Debug
103
+# Default: no
104
+#Debug yes
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2002 Tomasz Kojm <zolw@konarski.edu.pl>
2
+ *  Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>
3 3
  *
4 4
  *  This program is free software; you can redistribute it and/or modify
5 5
  *  it under the terms of the GNU General Public License as published by
... ...
@@ -36,6 +36,4 @@
36 36
 #define UNPGROUP "clamav"
37 37
 #endif
38 38
 
39
-#define CL_DEFAULT_CHECKS 12
40
-#define CL_DEFAULT_MAXATTEMPTS 3
41 39
 #define CL_MAX_CHILDREN 5
... ...
@@ -112,11 +112,11 @@ int freshclam(struct optstruct *opt)
112 112
 
113 113
     /* parse the config file */
114 114
     if((cfgfile = getargl(opt, "config-file"))) {
115
-	copt = parsecfg(cfgfile, 1);
115
+	copt = getcfg(cfgfile, 1);
116 116
     } else {
117 117
 	/* TODO: force strict permissions on freshclam.conf */
118
-	if((copt = parsecfg((cfgfile = CONFDIR"/freshclam.conf"), 1)) == NULL)
119
-	    copt = parsecfg((cfgfile = CONFDIR"/clamd.conf"), 1);
118
+	if((copt = getcfg((cfgfile = CONFDIR"/freshclam.conf"), 1)) == NULL)
119
+	    copt = getcfg((cfgfile = CONFDIR"/clamd.conf"), 1);
120 120
     }
121 121
 
122 122
     if(!copt) {
... ...
@@ -127,7 +127,7 @@ int freshclam(struct optstruct *opt)
127 127
     if(optl(opt, "http-proxy") || optl(opt, "proxy-user"))
128 128
 	mprintf("WARNING: Proxy settings are now only configurable in the config file.\n");
129 129
 
130
-    if(cfgopt(copt, "HTTPProxyPassword")) {
130
+    if(cfgopt(copt, "HTTPProxyPassword")->enabled) {
131 131
 	if(stat(cfgfile, &statbuf) == -1) {
132 132
 	    mprintf("@Can't stat %s (critical error)\n", cfgfile);
133 133
 	    return 56;
... ...
@@ -144,7 +144,7 @@ int freshclam(struct optstruct *opt)
144 144
     /* freshclam shouldn't work with root privileges */
145 145
     if(optc(opt, 'u')) {
146 146
 	unpuser = getargc(opt, 'u');
147
-    } else if((cpt = cfgopt(copt, "DatabaseOwner"))) {
147
+    } else if((cpt = cfgopt(copt, "DatabaseOwner"))->enabled) {
148 148
 	unpuser = cpt->strarg;
149 149
     } else {
150 150
 	unpuser = UNPUSER;
... ...
@@ -156,7 +156,7 @@ int freshclam(struct optstruct *opt)
156 156
 	    exit(60); /* this is critical problem, so we just exit here */
157 157
 	}
158 158
 
159
-	if(cfgopt(copt, "AllowSupplementaryGroups")) {
159
+	if(cfgopt(copt, "AllowSupplementaryGroups")->enabled) {
160 160
 #ifdef HAVE_INITGROUPS
161 161
 	    if(initgroups(unpuser, user->pw_gid)) {
162 162
 		mprintf("@initgroups() failed.\n");
... ...
@@ -186,7 +186,7 @@ int freshclam(struct optstruct *opt)
186 186
 
187 187
     /* initialize some important variables */
188 188
 
189
-    if(optl(opt, "debug") || cfgopt(copt, "Debug"))
189
+    if(optl(opt, "debug") || cfgopt(copt, "Debug")->enabled)
190 190
 	cl_debug();
191 191
 
192 192
     if(optc(opt, 'v'))
... ...
@@ -205,7 +205,7 @@ int freshclam(struct optstruct *opt)
205 205
 
206 206
     /* initialize logger */
207 207
 
208
-    if(cfgopt(copt, "LogVerbose"))
208
+    if(cfgopt(copt, "LogVerbose")->enabled)
209 209
 	logg_verbose = 1;
210 210
 
211 211
     if(optc(opt, 'l')) {
... ...
@@ -214,7 +214,7 @@ int freshclam(struct optstruct *opt)
214 214
 	    mprintf("!Problem with internal logger.\n");
215 215
 	    exit(62);
216 216
 	}
217
-    } else if((cpt = cfgopt(copt, "UpdateLogFile"))) {
217
+    } else if((cpt = cfgopt(copt, "UpdateLogFile"))->enabled) {
218 218
 	logg_file = cpt->strarg; 
219 219
 	if(logg("--------------------------------------\n")) {
220 220
 	    mprintf("!Problem with internal logger.\n");
... ...
@@ -224,10 +224,10 @@ int freshclam(struct optstruct *opt)
224 224
 	logg_file = NULL;
225 225
 
226 226
 #if defined(USE_SYSLOG) && !defined(C_AIX)
227
-    if(cfgopt(copt, "LogSyslog")) {
227
+    if(cfgopt(copt, "LogSyslog")->enabled) {
228 228
 	    int fac = LOG_LOCAL6;
229 229
 
230
-	if((cpt = cfgopt(copt, "LogFacility"))) {
230
+	if((cpt = cfgopt(copt, "LogFacility"))->enabled) {
231 231
 	    if((fac = logg_facility(cpt->strarg)) == -1) {
232 232
 		mprintf("!LogFacility: %s: No such facility.\n", cpt->strarg);
233 233
 		exit(62);
... ...
@@ -241,14 +241,10 @@ int freshclam(struct optstruct *opt)
241 241
 #endif
242 242
 
243 243
     /* change the current working directory */
244
-    if(optl(opt, "datadir")) {
244
+    if(optl(opt, "datadir"))
245 245
 	newdir = getargl(opt, "datadir");
246
-    } else {
247
-	if((cpt = cfgopt(copt, "DatabaseDirectory")))
248
-	    newdir = cpt->strarg;
249
-	else
250
-	    newdir = VIRUSDBDIR;
251
-    }
246
+    else
247
+	newdir = cfgopt(copt, "DatabaseDirectory")->strarg;
252 248
 
253 249
     if(chdir(newdir)) {
254 250
 	mprintf("Can't change dir to %s\n", newdir);
... ...
@@ -264,20 +260,17 @@ int freshclam(struct optstruct *opt)
264 264
 	memset(&sigact, 0, sizeof(struct sigaction));
265 265
 	sigact.sa_handler = daemon_sighandler;
266 266
 
267
-	if(optc(opt, 'c')) {
267
+	if(optc(opt, 'c'))
268 268
 	    checks = atoi(getargc(opt, 'c'));
269
-	} else if((cpt = cfgopt(copt, "Checks"))) {
270
-	    checks = cpt->numarg;
271
-	} else {
272
-	    checks = CL_DEFAULT_CHECKS;
273
-	}
269
+	else
270
+	    checks = cfgopt(copt, "Checks")->numarg;
274 271
 
275 272
 	if(checks <= 0) {
276 273
 	    mprintf("@Number of checks must be a positive integer.\n");
277 274
 	    exit(41);
278 275
 	}
279 276
 
280
-	if(!cfgopt(copt, "DNSDatabaseInfo")) {
277
+	if(!cfgopt(copt, "DNSDatabaseInfo")->enabled || optl(opt, "no-dns")) {
281 278
 	    if(checks > 50) {
282 279
 		mprintf("@Number of checks must be between 1 and 50.\n");
283 280
 		exit(41);
... ...
@@ -286,12 +279,12 @@ int freshclam(struct optstruct *opt)
286 286
 
287 287
 	bigsleep = 24 * 3600 / checks;
288 288
 
289
-	if(!cfgopt(copt, "Foreground"))
289
+	if(!cfgopt(copt, "Foreground")->enabled)
290 290
 	    daemonize();
291 291
 
292 292
 	if (optc(opt, 'p')) {
293 293
 	    pidfile = getargc(opt, 'p');
294
-	} else if ((cpt = cfgopt(copt, "PidFile"))) {
294
+	} else if ((cpt = cfgopt(copt, "PidFile"))->enabled) {
295 295
 	    pidfile = cpt->strarg;
296 296
 	}
297 297
 	if (pidfile) {
... ...
@@ -315,7 +308,7 @@ int freshclam(struct optstruct *opt)
315 315
 
316 316
 	        if(optl(opt, "on-error-execute"))
317 317
 		    arg = getargl(opt, "on-error-execute");
318
-		else if((cpt = cfgopt(copt, "OnErrorExecute")))
318
+		else if((cpt = cfgopt(copt, "OnErrorExecute"))->enabled)
319 319
 		    arg = cpt->strarg;
320 320
 
321 321
 		if(arg)
... ...
@@ -353,7 +346,7 @@ int freshclam(struct optstruct *opt)
353 353
 	if(ret > 1)
354 354
 	    system(getargl(opt, "on-error-execute"));
355 355
 
356
-    } else if((cpt = cfgopt(copt, "OnErrorExecute"))) {
356
+    } else if((cpt = cfgopt(copt, "OnErrorExecute"))->enabled) {
357 357
 	if(ret > 1)
358 358
 	    system(cpt->strarg);
359 359
     }
... ...
@@ -370,15 +363,10 @@ int download(const struct cfgstruct *copt, const struct optstruct *opt)
370 370
 	struct cfgstruct *cpt;
371 371
 
372 372
 
373
-    if((cpt = cfgopt(copt, "MaxAttempts")))
374
-	maxattempts = cpt->numarg;
375
-    else
376
-	maxattempts = CL_DEFAULT_MAXATTEMPTS;
377
-
378
-
373
+    maxattempts = cfgopt(copt, "MaxAttempts")->numarg;
379 374
     mprintf("*Max retries == %d\n", maxattempts);
380 375
 
381
-    if((cpt = cfgopt(copt, "DatabaseMirror")) == NULL) {
376
+    if(!(cpt = cfgopt(copt, "DatabaseMirror"))->enabled) {
382 377
 	mprintf("@You must specify at least one database mirror.\n");
383 378
 	return 56;
384 379
     } else {
... ...
@@ -76,10 +76,7 @@ int downloadmanager(const struct cfgstruct *copt, const struct optstruct *opt, c
76 76
 #endif
77 77
 
78 78
 #ifdef HAVE_RESOLV_H
79
-    if((cpt = cfgopt(copt, "DNSDatabaseInfo")))
80
-	dnsdbinfo = cpt->strarg;
81
-    else
82
-	dnsdbinfo = "current.cvd.clamav.net";
79
+    dnsdbinfo = cfgopt(copt, "DNSDatabaseInfo")->strarg;
83 80
 
84 81
     if(optl(opt, "no-dns")) {
85 82
 	dnsreply = NULL;
... ...
@@ -150,7 +147,7 @@ int downloadmanager(const struct cfgstruct *copt, const struct optstruct *opt, c
150 150
 
151 151
     if(optl(opt, "localip")) {
152 152
         localip = getargl(opt, "localip");
153
-    } else if((cpt = cfgopt(copt, "LocalIPAddress"))) {
153
+    } else if((cpt = cfgopt(copt, "LocalIPAddress"))->enabled) {
154 154
 	localip = cpt->strarg;
155 155
     }
156 156
 
... ...
@@ -179,7 +176,7 @@ int downloadmanager(const struct cfgstruct *copt, const struct optstruct *opt, c
179 179
 	free(dnsreply);
180 180
 
181 181
     if(updated) {
182
-	if(cfgopt(copt, "HTTPProxyServer")) {
182
+	if(cfgopt(copt, "HTTPProxyServer")->enabled) {
183 183
 	    mprintf("Database updated (%d signatures) from %s\n", signo, hostname);
184 184
 	    logg("Database updated (%d signatures) from %s\n", signo, hostname);
185 185
 	} else {
... ...
@@ -194,18 +191,14 @@ int downloadmanager(const struct cfgstruct *copt, const struct optstruct *opt, c
194 194
 		clamav_conf = CONFDIR"/clamd.conf";
195 195
 
196 196
 	    notify(clamav_conf);
197
-	} else if((cpt = cfgopt(copt, "NotifyClamd"))) {
198
-		const char *clamav_conf = cpt->strarg;
199
-	    if(!clamav_conf)
200
-		clamav_conf = CONFDIR"/clamd.conf";
201
-
202
-	    notify(clamav_conf);
197
+	} else if((cpt = cfgopt(copt, "NotifyClamd"))->enabled) {
198
+	    notify(cpt->strarg);
203 199
 	}
204 200
 #endif
205 201
 
206 202
 	if(optl(opt, "on-update-execute"))
207 203
 	    arg = getargl(opt, "on-update-execute");
208
-	else if((cpt = cfgopt(copt, "OnUpdateExecute")))
204
+	else if((cpt = cfgopt(copt, "OnUpdateExecute"))->enabled)
209 205
 	    arg = cpt->strarg;
210 206
 
211 207
 	if(arg) {
... ...
@@ -263,14 +256,14 @@ int downloaddb(const char *localname, const char *remotename, const char *hostna
263 263
     }
264 264
 
265 265
     /* Initialize proxy settings */
266
-    if((cpt = cfgopt(copt, "HTTPProxyServer"))) {
266
+    if((cpt = cfgopt(copt, "HTTPProxyServer"))->enabled) {
267 267
 	proxy = cpt->strarg;
268 268
 	if(strncasecmp(proxy, "http://", 7) == 0)
269 269
 	    proxy += 7;
270 270
 
271
-	if((cpt = cfgopt(copt, "HTTPProxyUsername"))) {
271
+	if((cpt = cfgopt(copt, "HTTPProxyUsername"))->enabled) {
272 272
 	    user = cpt->strarg;
273
-	    if((cpt = cfgopt(copt, "HTTPProxyPassword"))) {
273
+	    if((cpt = cfgopt(copt, "HTTPProxyPassword"))->enabled) {
274 274
 		pass = cpt->strarg;
275 275
 	    } else {
276 276
 		mprintf("HTTPProxyUsername requires HTTPProxyPassword\n");
... ...
@@ -280,7 +273,7 @@ int downloaddb(const char *localname, const char *remotename, const char *hostna
280 280
 	    }
281 281
 	}
282 282
 
283
-	if((cpt = cfgopt(copt, "HTTPProxyPort")))
283
+	if((cpt = cfgopt(copt, "HTTPProxyPort"))->enabled)
284 284
 	    port = cpt->numarg;
285 285
 
286 286
 	mprintf("Connecting via %s\n", proxy);
... ...
@@ -295,7 +288,6 @@ int downloaddb(const char *localname, const char *remotename, const char *hostna
295 295
 	    hostfd = wwwconnect(hostname, proxy, port, ipaddr, localip);
296 296
 
297 297
 	if(hostfd < 0) {
298
-            mprintf("@No servers could be reached. Giving up\n");
299 298
 	    if(current)
300 299
 		cl_cvdfree(current);
301 300
 	    return 52;
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2002, 2003 Tomasz Kojm <zolw@konarski.edu.pl>
2
+ *  Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>
3 3
  *
4 4
  *  This program is free software; you can redistribute it and/or modify
5 5
  *  it under the terms of the GNU General Public License as published by
... ...
@@ -47,15 +47,15 @@ int notify(const char *cfgfile)
47 47
 	char *socktype;
48 48
 
49 49
 
50
-    if((copt = parsecfg(cfgfile, 1)) == NULL) {
50
+    if((copt = getcfg(cfgfile, 1)) == NULL) {
51 51
 	mprintf("@Clamd was NOT notified: Can't find or parse configuration file %s\n", cfgfile);
52 52
 	return 1;
53 53
     }
54 54
 
55
-    if(cfgopt(copt, "TCPSocket") && cfgopt(copt, "LocalSocket")) {
55
+    if(cfgopt(copt, "TCPSocket")->enabled && cfgopt(copt, "LocalSocket")->enabled) {
56 56
 	mprintf("@Clamd was NOT notified: Both socket types (TCP and local) declared in %s\n", cfgfile);
57 57
 	return 1;
58
-    } else if((cpt = cfgopt(copt, "LocalSocket"))) {
58
+    } else if((cpt = cfgopt(copt, "LocalSocket"))->enabled) {
59 59
 	socktype = "UNIX";
60 60
 	server.sun_family = AF_UNIX;
61 61
 	strncpy(server.sun_path, cpt->strarg, sizeof(server.sun_path));
... ...
@@ -73,7 +73,7 @@ int notify(const char *cfgfile)
73 73
 	    return 1;
74 74
 	}
75 75
 
76
-    } else if((cpt = cfgopt(copt, "TCPSocket"))) {
76
+    } else if((cpt = cfgopt(copt, "TCPSocket"))->enabled) {
77 77
 
78 78
 	socktype = "TCP";
79 79
 #ifdef PF_INET
... ...
@@ -89,7 +89,7 @@ int notify(const char *cfgfile)
89 89
 	server2.sin_family = AF_INET;
90 90
 	server2.sin_port = htons(cpt->numarg);
91 91
 
92
-	if ((cpt = cfgopt(copt, "TCPAddr"))) {
92
+	if((cpt = cfgopt(copt, "TCPAddr"))->enabled) {
93 93
 	    if ((he = gethostbyname(cpt->strarg)) == 0) {
94 94
 		perror("gethostbyname()");
95 95
 		mprintf("@Clamd was NOT notified: Can't resolve hostname '%s'\n", cpt->strarg);
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2002 - 2004 Tomasz Kojm <tkojm@clamav.net>
2
+ *  Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>
3 3
  *
4 4
  *  This program is free software; you can redistribute it and/or modify
5 5
  *  it under the terms of the GNU General Public License as published by
... ...
@@ -32,110 +32,122 @@
32 32
 #include "memory.h"
33 33
 #include "misc.h"
34 34
 
35
-struct cfgstruct *parsecfg(const char *cfgfile, int messages)
35
+static int regcfg(struct cfgstruct **copt, char *optname, char *strarg, int numarg, short multiple);
36
+
37
+struct cfgstruct *getcfg(const char *cfgfile, int verbose)
36 38
 {
37 39
 	char buff[LINE_LENGTH], *name, *arg;
38 40
 	FILE *fs;
39
-	int line = 0, i, found, ctype, calc;
41
+	int line = 0, i, found, ctype, calc, val;
40 42
 	struct cfgstruct *copt = NULL;
41 43
 	struct cfgoption *pt;
42 44
 
43 45
 	struct cfgoption cfg_options[] = {
44
-	    {"LogFile", OPT_STR},
45
-	    {"LogFileUnlock", OPT_NOARG},
46
-	    {"LogFileMaxSize", OPT_COMPSIZE},
47
-	    {"LogTime", OPT_NOARG},
48
-	    {"LogClean", OPT_NOARG},
49
-	    {"LogVerbose", OPT_NOARG}, /* clamd + freshclam */
50
-	    {"LogSyslog", OPT_NOARG},
51
-	    {"LogFacility", OPT_STR},
52
-	    {"PidFile", OPT_STR},
53
-	    {"TemporaryDirectory", OPT_STR},
54
-	    {"DisableDefaultScanOptions", OPT_NOARG},
55
-	    {"ScanPE", OPT_NOARG},
56
-	    {"DetectBrokenExecutables", OPT_NOARG},
57
-	    {"ScanMail", OPT_NOARG},
58
-	    {"MailFollowURLs", OPT_NOARG},
59
-	    {"ScanHTML", OPT_NOARG},
60
-	    {"ScanOLE2", OPT_NOARG},
61
-	    {"ScanArchive", OPT_NOARG},
62
-	    {"ScanRAR", OPT_NOARG},
63
-	    {"ArchiveMaxFileSize", OPT_COMPSIZE},
64
-	    {"ArchiveMaxRecursion", OPT_NUM},
65
-	    {"ArchiveMaxFiles", OPT_NUM},
66
-	    {"ArchiveMaxCompressionRatio", OPT_NUM},
67
-	    {"ArchiveLimitMemoryUsage", OPT_NOARG},
68
-	    {"ArchiveBlockEncrypted", OPT_NOARG},
69
-	    {"ArchiveBlockMax", OPT_NOARG},
70
-	    {"DataDirectory", OPT_STR}, /* obsolete */
71
-	    {"DatabaseDirectory", OPT_STR}, /* clamd + freshclam */
72
-	    {"TCPAddr", OPT_STR},
73
-	    {"TCPSocket", OPT_NUM},
74
-	    {"LocalSocket", OPT_STR},
75
-	    {"MaxConnectionQueueLength", OPT_NUM},
76
-	    {"StreamMaxLength", OPT_COMPSIZE},
77
-	    {"StreamMinPort", OPT_NUM},
78
-	    {"StreamMaxPort", OPT_NUM},
79
-	    {"MaxThreads", OPT_NUM},
80
-	    {"ReadTimeout", OPT_NUM},
81
-	    {"IdleTimeout", OPT_NUM},
82
-	    {"MaxDirectoryRecursion", OPT_NUM},
83
-	    {"FollowDirectorySymlinks", OPT_NOARG},
84
-	    {"FollowFileSymlinks", OPT_NOARG},
85
-	    {"ExitOnOOM", OPT_NOARG},
86
-	    {"Foreground", OPT_NOARG}, /* clamd + freshclam */
87
-	    {"Debug", OPT_NOARG},
88
-	    {"LeaveTemporaryFiles", OPT_NOARG},
89
-	    {"FixStaleSocket", OPT_NOARG},
90
-	    {"User", OPT_STR},
91
-	    {"AllowSupplementaryGroups", OPT_NOARG},
92
-	    {"SelfCheck", OPT_NUM},
93
-	    {"VirusEvent", OPT_FULLSTR},
94
-	    {"ClamukoScanOnLine", OPT_NOARG}, /* old name */
95
-	    {"ClamukoScanOnAccess", OPT_NOARG},
96
-	    {"ClamukoScanOnOpen", OPT_NOARG},
97
-	    {"ClamukoScanOnClose", OPT_NOARG},
98
-	    {"ClamukoScanOnExec", OPT_NOARG},
99
-	    {"ClamukoIncludePath", OPT_STR},
100
-	    {"ClamukoExcludePath", OPT_STR},
101
-	    {"ClamukoMaxFileSize", OPT_COMPSIZE},
102
-	    {"ClamukoScanArchive", OPT_NOARG},
103
-	    {"DatabaseOwner", OPT_STR}, /* freshclam */
104
-	    {"Checks", OPT_NUM}, /* freshclam */
105
-	    {"UpdateLogFile", OPT_STR}, /* freshclam */
106
-	    {"DNSDatabaseInfo", OPT_STR}, /* freshclam */
107
-	    {"DatabaseMirror", OPT_STR}, /* freshclam */
108
-	    {"MaxAttempts", OPT_NUM}, /* freshclam */
109
-	    {"HTTPProxyServer", OPT_STR}, /* freshclam */
110
-	    {"HTTPProxyPort", OPT_NUM}, /* freshclam */
111
-	    {"HTTPProxyUsername", OPT_STR}, /* freshclam */
112
-	    {"HTTPProxyPassword", OPT_STR}, /* freshclam */
113
-	    {"NotifyClamd", OPT_OPTARG}, /* freshclam */
114
-	    {"OnUpdateExecute", OPT_FULLSTR}, /* freshclam */
115
-	    {"OnErrorExecute", OPT_FULLSTR}, /* freshclam */
116
-	    {"LocalIPAddress", OPT_STR}, /* freshclam */
46
+	    {"LogFile",	OPT_STR, -1, NULL, 0},
47
+	    {"LogFileUnlock", OPT_BOOL, 0, NULL, 0},
48
+	    {"LogFileMaxSize", OPT_COMPSIZE, 1048576, NULL, 0},
49
+	    {"LogTime", OPT_BOOL, 0, NULL, 0},
50
+	    {"LogClean", OPT_BOOL, 0, NULL, 0},
51
+	    {"LogVerbose", OPT_BOOL, 0, NULL, 0}, /* clamd + freshclam */
52
+	    {"LogSyslog", OPT_BOOL, 0, NULL, 0},
53
+	    {"LogFacility", OPT_STR, -1, "LOG_LOCAL6", 0},
54
+	    {"PidFile", OPT_STR, -1, NULL, 0},
55
+	    {"TemporaryDirectory", OPT_STR, -1, NULL, 0},
56
+	    {"ScanPE", OPT_BOOL, 1, NULL, 0},
57
+	    {"DetectBrokenExecutables", OPT_BOOL, 0, NULL, 0},
58
+	    {"ScanMail", OPT_BOOL, 1, NULL, 0},
59
+	    {"MailFollowURLs", OPT_BOOL, 0, NULL, 0},
60
+	    {"ScanHTML", OPT_BOOL, 1, NULL, 0},
61
+	    {"ScanOLE2", OPT_BOOL, 1, NULL, 0},
62
+	    {"ScanArchive", OPT_BOOL, 1, NULL, 0},
63
+	    {"ArchiveMaxFileSize", OPT_COMPSIZE, 10485760, NULL, 0},
64
+	    {"ArchiveMaxRecursion", OPT_NUM, 8, NULL, 0},
65
+	    {"ArchiveMaxFiles", OPT_NUM, 1000, NULL, 0},
66
+	    {"ArchiveMaxCompressionRatio", OPT_NUM, 250, NULL, 0},
67
+	    {"ArchiveLimitMemoryUsage", OPT_BOOL, 0, NULL, 0},
68
+	    {"ArchiveBlockEncrypted", OPT_BOOL, 0, NULL, 0},
69
+	    {"ArchiveBlockMax", OPT_BOOL, 0, NULL, 0},
70
+	    {"DatabaseDirectory", OPT_STR, -1, DATADIR, 0}, /* clamd + freshclam */
71
+	    {"TCPAddr", OPT_STR, -1, NULL, 0},
72
+	    {"TCPSocket", OPT_NUM, -1, NULL, 0},
73
+	    {"LocalSocket", OPT_STR, -1, NULL, 0},
74
+	    {"MaxConnectionQueueLength", OPT_NUM, 15, NULL, 0},
75
+	    {"StreamMaxLength", OPT_COMPSIZE, 10485760, NULL, 0},
76
+	    {"StreamMinPort", OPT_NUM, 1024, NULL, 0},
77
+	    {"StreamMaxPort", OPT_NUM, 2048, NULL, 0},
78
+	    {"MaxThreads", OPT_NUM, 10, NULL, 0},
79
+	    {"ReadTimeout", OPT_NUM, 120, NULL, 0},
80
+	    {"IdleTimeout", OPT_NUM, 30, NULL, 0},
81
+	    {"MaxDirectoryRecursion", OPT_NUM, 15, NULL, 0},
82
+	    {"FollowDirectorySymlinks", OPT_BOOL, 0, NULL, 0},
83
+	    {"FollowFileSymlinks", OPT_BOOL, 0, NULL, 0},
84
+	    {"ExitOnOOM", OPT_BOOL, 0, NULL, 0},
85
+	    {"Foreground", OPT_BOOL, 0, NULL, 0}, /* clamd + freshclam */
86
+	    {"Debug", OPT_BOOL, 0, NULL, 0},
87
+	    {"LeaveTemporaryFiles", OPT_BOOL, 0, NULL, 0},
88
+	    {"FixStaleSocket", OPT_BOOL, 0, NULL, 0},
89
+	    {"User", OPT_STR, -1, NULL, 0},
90
+	    {"AllowSupplementaryGroups", OPT_BOOL, 0, NULL, 0},
91
+	    {"SelfCheck", OPT_NUM, 1800, NULL, 0},
92
+	    {"VirusEvent", OPT_FULLSTR, -1, NULL, 0},
93
+	    {"ClamukoScanOnAccess", OPT_BOOL, 0, NULL, 0},
94
+	    {"ClamukoScanOnOpen", OPT_BOOL, 0, NULL, 0},
95
+	    {"ClamukoScanOnClose", OPT_BOOL, 0, NULL, 0},
96
+	    {"ClamukoScanOnExec", OPT_BOOL, 0, NULL, 0},
97
+	    {"ClamukoIncludePath", OPT_STR, 0, NULL, 0},
98
+	    {"ClamukoExcludePath", OPT_STR, 0, NULL, 0},
99
+	    {"ClamukoMaxFileSize", OPT_COMPSIZE, 5242880, NULL, 0},
100
+	    {"ClamukoScanArchive", OPT_BOOL, 0, NULL, 0},
101
+	    {"DatabaseOwner", OPT_STR, -1, NULL, 0}, /* freshclam */
102
+	    {"Checks", OPT_NUM, 12, NULL, 0}, /* freshclam */
103
+	    {"UpdateLogFile", OPT_STR, -1, NULL, 0}, /* freshclam */
104
+	    {"DNSDatabaseInfo", OPT_STR, -1, "current.cvd.clamav.net", 0}, /* freshclam */
105
+	    {"DatabaseMirror", OPT_STR, -1, NULL, 1}, /* freshclam */
106
+	    {"MaxAttempts", OPT_NUM, 3, NULL, 0}, /* freshclam */
107
+	    {"HTTPProxyServer", OPT_STR, -1, NULL, 0}, /* freshclam */
108
+	    {"HTTPProxyPort", OPT_NUM, -1, NULL, 0}, /* freshclam */
109
+	    {"HTTPProxyUsername", OPT_STR, -1, NULL, 0}, /* freshclam */
110
+	    {"HTTPProxyPassword", OPT_STR, -1, NULL, 0}, /* freshclam */
111
+	    {"NotifyClamd", OPT_STR, -1, NULL, 0}, /* freshclam */
112
+	    {"OnUpdateExecute", OPT_FULLSTR, -1, NULL, 0}, /* freshclam */
113
+	    {"OnErrorExecute", OPT_FULLSTR, -1, NULL, 0}, /* freshclam */
114
+	    {"LocalIPAddress", OPT_STR, -1, NULL, 0}, /* freshclam */
117 115
 	    {0, 0}
118 116
 	};
119 117
 
120 118
 
121
-    if((fs = fopen(cfgfile, "r")) == NULL)
119
+    for(i = 0; ; i++) {
120
+	pt = &cfg_options[i];
121
+	if(!pt->name)
122
+	    break;
123
+
124
+	if(regcfg(&copt, strdup(pt->name), pt->strarg ? strdup(pt->strarg) : NULL, pt->numarg, pt->multiple) < 0) {
125
+	    fprintf(stderr, "ERROR: Can't register new options (not enough memory)\n");
126
+	    freecfg(copt);
127
+	    return NULL;
128
+	}
129
+    }
130
+
131
+    if((fs = fopen(cfgfile, "r")) == NULL) {
132
+	/* do not print error message here! */
133
+	freecfg(copt);
122 134
 	return NULL;
135
+    }
123 136
 
124 137
     while(fgets(buff, LINE_LENGTH, fs)) {
125
-
126 138
 	line++;
127 139
 
128 140
 	if(buff[0] == '#')
129 141
 	    continue;
130 142
 
131 143
 	if(!strncmp("Example", buff, 7)) {
132
-	    if(messages)
144
+	    if(verbose)
133 145
 		fprintf(stderr, "ERROR: Please edit the example config file %s.\n", cfgfile);
134 146
 	    fclose(fs);
147
+	    freecfg(copt);
135 148
 	    return NULL;
136 149
 	}
137 150
 
138
-
139 151
 	if((name = cli_strtok(buff, 0, " \r\n"))) {
140 152
 	    arg = cli_strtok(buff, 1, " \r\n");
141 153
 	    found = 0;
... ...
@@ -147,41 +159,61 @@ struct cfgstruct *parsecfg(const char *cfgfile, int messages)
147 147
 			switch(pt->argtype) {
148 148
 			    case OPT_STR:
149 149
 				if(!arg) {
150
-				    if(messages)
151
-					fprintf(stderr, "ERROR: Parse error at line %d: Option %s requires string as argument.\n", line, name);
150
+				    if(verbose)
151
+					fprintf(stderr, "ERROR: Parse error at line %d: Option %s requires string argument.\n", line, name);
152 152
 				    fclose(fs);
153
+				    freecfg(copt);
154
+				    return NULL;
155
+				}
156
+				if(regcfg(&copt, name, arg, -1, pt->multiple) < 0) {
157
+				    fprintf(stderr, "ERROR: Can't register new options (not enough memory)\n");
158
+				    fclose(fs);
159
+				    freecfg(copt);
153 160
 				    return NULL;
154 161
 				}
155
-				copt = regcfg(copt, name, arg, 0);
156 162
 				break;
157 163
 			    case OPT_FULLSTR:
164
+				/* an ugly hack of the above case */
158 165
 				if(!arg) {
159
-				    if(messages)
160
-					fprintf(stderr, "ERROR: Parse error at line %d: Option %s requires string as argument.\n", line, name);
166
+				    if(verbose)
167
+					fprintf(stderr, "ERROR: Parse error at line %d: Option %s requires string argument.\n", line, name);
161 168
 				    fclose(fs);
169
+				    freecfg(copt);
162 170
 				    return NULL;
163 171
 				}
164
-				/* FIXME: this one is an ugly hack of the above case */
165 172
 				free(arg);
166 173
 				arg = strstr(buff, " ");
167 174
 				arg = strdup(++arg);
168
-				copt = regcfg(copt, name, arg, 0);
175
+				if(regcfg(&copt, name, arg, -1, pt->multiple) < 0) {
176
+				    fprintf(stderr, "ERROR: Can't register new options (not enough memory)\n");
177
+				    fclose(fs);
178
+				    freecfg(copt);
179
+				    return NULL;
180
+				}
169 181
 				break;
170 182
 			    case OPT_NUM:
171 183
 				if(!arg || !isnumb(arg)) {
172
-				    if(messages)
184
+				    if(verbose)
173 185
 					fprintf(stderr, "ERROR: Parse error at line %d: Option %s requires numerical argument.\n", line, name);
174 186
 				    fclose(fs);
187
+				    freecfg(copt);
188
+				    return NULL;
189
+				}
190
+				if(regcfg(&copt, name, NULL, atoi(arg), pt->multiple) < 0) {
191
+				    fprintf(stderr, "ERROR: Can't register new options (not enough memory)\n");
192
+				    fclose(fs);
193
+				    freecfg(copt);
194
+				    free(arg);
175 195
 				    return NULL;
176 196
 				}
177
-				copt = regcfg(copt, name, NULL, atoi(arg));
178 197
 				free(arg);
179 198
 				break;
180 199
 			    case OPT_COMPSIZE:
181 200
 				if(!arg) {
182
-				    if(messages)
201
+				    if(verbose)
183 202
 					fprintf(stderr, "ERROR: Parse error at line %d: Option %s requires argument.\n", line, name);
184 203
 				    fclose(fs);
204
+				    freecfg(copt);
185 205
 				    return NULL;
186 206
 				}
187 207
 				ctype = tolower(arg[strlen(arg) - 1]);
... ...
@@ -189,9 +221,10 @@ struct cfgstruct *parsecfg(const char *cfgfile, int messages)
189 189
 				    char *cpy = (char *) mcalloc(strlen(arg), sizeof(char));
190 190
 				    strncpy(cpy, arg, strlen(arg) - 1);
191 191
 				    if(!isnumb(cpy)) {
192
-					if(messages)
192
+					if(verbose)
193 193
 					    fprintf(stderr, "ERROR: Parse error at line %d: Option %s requires numerical (raw/K/M) argument.\n", line, name);
194 194
 					fclose(fs);
195
+					freecfg(copt);
195 196
 					return NULL;
196 197
 				    }
197 198
 				    if(ctype == 'm')
... ...
@@ -201,44 +234,69 @@ struct cfgstruct *parsecfg(const char *cfgfile, int messages)
201 201
 				    free(cpy);
202 202
 				} else {
203 203
 				    if(!isnumb(arg)) {
204
-					if(messages)
204
+					if(verbose)
205 205
 					    fprintf(stderr, "ERROR: Parse error at line %d: Option %s requires numerical (raw/K/M) argument.\n", line, name);
206 206
 					fclose(fs);
207
+					freecfg(copt);
207 208
 					return NULL;
208 209
 				    }
209 210
 				    calc = atoi(arg);
210 211
 				}
211
-				copt = regcfg(copt, name, NULL, calc);
212 212
 				free(arg);
213
-				break;
214
-			    case OPT_NOARG:
215
-				if(arg) {
216
-				    if(messages)
217
-					fprintf(stderr, "ERROR: Parse error at line %d: Option %s doesn't support arguments (got '%s').\n", line, name, arg);
213
+				if(regcfg(&copt, name, NULL, calc, pt->multiple) < 0) {
214
+				    fprintf(stderr, "ERROR: Can't register new options (not enough memory)\n");
218 215
 				    fclose(fs);
216
+				    freecfg(copt);
219 217
 				    return NULL;
220 218
 				}
221
-				copt = regcfg(copt, name, NULL, 0);
222 219
 				break;
223
-			    case OPT_OPTARG:
224
-				copt = regcfg(copt, name, arg, 0);
220
+			    case OPT_BOOL:
221
+
222
+				if(!arg) {
223
+				    if(verbose)
224
+					fprintf(stderr, "ERROR: Parse error at line %d: Option %s requires boolean argument.\n", line, name);
225
+				    fclose(fs);
226
+				    freecfg(copt);
227
+				    return NULL;
228
+				}
229
+
230
+				if(!strcasecmp(arg, "yes") || !strcmp(arg, "1") || !strcasecmp(arg, "true")) {
231
+				    val = 1;
232
+				} else if(!strcasecmp(arg, "no") || !strcmp(arg, "0") || !strcasecmp(arg, "false")) {
233
+				    val = 0;
234
+				} else {
235
+				    if(verbose)
236
+					fprintf(stderr, "ERROR: Parse error at line %d: Option %s requires boolean argument.\n", line, name);
237
+				    fclose(fs);
238
+				    freecfg(copt);
239
+				    return NULL;
240
+				}
241
+				free(arg);
242
+				if(regcfg(&copt, name, NULL, val, pt->multiple) < 0) {
243
+				    fprintf(stderr, "ERROR: Can't register new options (not enough memory)\n");
244
+				    fclose(fs);
245
+				    freecfg(copt);
246
+				    return NULL;
247
+				}
225 248
 				break;
226 249
 			    default:
227
-				if(messages)
250
+				if(verbose)
228 251
 				    fprintf(stderr, "ERROR: Parse error at line %d: Option %s is of unknown type %d\n", line, name, pt->argtype);
229 252
 				free(name);
230 253
 				free(arg);
231
-				break;
254
+				freecfg(copt);
255
+				return NULL;
232 256
 			}
233 257
 		    }
234 258
 		} else
235 259
 		    break;
236
-	    } 
260
+	    }
237 261
 
238 262
 	    if(!found) {
239
-		if(messages)
263
+		if(verbose)
240 264
 		    fprintf(stderr, "ERROR: Parse error at line %d: Unknown option %s.\n", line, name);
241 265
 		fclose(fs);
266
+		freecfg(copt);
242 267
 		return NULL;
243 268
 	    }
244 269
 	}
... ...
@@ -253,7 +311,7 @@ void freecfg(struct cfgstruct *copt)
253 253
     	struct cfgstruct *handler;
254 254
     	struct cfgstruct *arg;
255 255
 
256
-    while (copt) {
256
+    while(copt) {
257 257
 	arg = copt->nextarg;
258 258
 	while(arg) {
259 259
 	    if(arg->strarg) {
... ...
@@ -265,12 +323,12 @@ void freecfg(struct cfgstruct *copt)
265 265
 	    } else
266 266
 		arg = arg->nextarg;
267 267
 	}
268
-	if(copt->optname) {
268
+	if(copt->optname)
269 269
 	    free(copt->optname);
270
-	}
271
-	if(copt->strarg) {
270
+
271
+	if(copt->strarg)
272 272
 	    free(copt->strarg);
273
-	}
273
+
274 274
 	handler = copt;
275 275
 	copt = copt->next;
276 276
 	free(handler);
... ...
@@ -278,48 +336,79 @@ void freecfg(struct cfgstruct *copt)
278 278
     return;
279 279
 }
280 280
 
281
-struct cfgstruct *regcfg(struct cfgstruct *copt, char *optname, char *strarg, int numarg)
281
+struct cfgstruct *cfgopt(const struct cfgstruct *copt, const char *optname)
282
+{
283
+	struct cfgstruct *handler;
284
+
285
+    handler = (struct cfgstruct *) copt;
286
+
287
+    while(1) {
288
+	if(handler) {
289
+	    if(handler->optname)
290
+		if(!strcmp(handler->optname, optname))
291
+		    return handler;
292
+	} else break;
293
+	handler = handler->next;
294
+    }
295
+
296
+    return NULL;
297
+}
298
+
299
+static int regcfg(struct cfgstruct **copt, char *optname, char *strarg, int numarg, short multiple)
282 300
 {
283 301
 	struct cfgstruct *newnode, *pt;
284 302
 
303
+
285 304
     newnode = (struct cfgstruct *) mmalloc(sizeof(struct cfgstruct));
305
+
306
+    if(!newnode)
307
+	return -1;
308
+
286 309
     newnode->optname = optname;
287 310
     newnode->nextarg = NULL;
288 311
     newnode->next = NULL;
312
+    newnode->enabled = 0;
313
+    newnode->multiple = multiple;
289 314
 
290
-    if(strarg)
315
+    if(strarg) {
291 316
 	newnode->strarg = strarg;
292
-    else {
317
+	newnode->enabled = 1;
318
+    } else {
293 319
 	newnode->strarg = NULL;
294
-	newnode->numarg = numarg;
295 320
     }
296 321
 
297
-    if((pt = cfgopt(copt, optname))) {
298
-	while(pt->nextarg)
299
-	    pt = pt->nextarg;
322
+    newnode->numarg = numarg;
323
+    if(numarg != -1 && numarg != 0)
324
+	newnode->enabled = 1;
300 325
 
301
-	pt->nextarg = newnode;
302
-	return copt;
303
-    } else {
304
-	newnode->next = copt;
305
-	return newnode;
306
-    }
307
-}
326
+    if((pt = cfgopt(*copt, optname))) {
327
+	if(pt->multiple) {
308 328
 
309
-struct cfgstruct *cfgopt(const struct cfgstruct *copt, const char *optname)
310
-{
311
-	struct cfgstruct *handler;
329
+	    if(pt->enabled) {
330
+		while(pt->nextarg)
331
+		    pt = pt->nextarg;
312 332
 
313
-    handler = (struct cfgstruct *) copt;
333
+		pt->nextarg = newnode;
334
+	    } else {
335
+		pt->strarg = newnode->strarg;
336
+		pt->numarg = newnode->numarg;
337
+		pt->enabled = newnode->enabled;
338
+		free(newnode);
339
+	    }
340
+	    return 3; /* registered additional argument */
314 341
 
315
-    while(1) {
316
-	if(handler) {
317
-	    if(handler->optname)
318
-		if(!strcmp(handler->optname, optname))
319
-		    return handler;
320
-	} else break;
321
-	handler = handler->next;
322
-    }
342
+	} else {
343
+	    pt->strarg = newnode->strarg;
344
+	    pt->numarg = newnode->numarg;
345
+	    pt->enabled = newnode->enabled;
346
+	    free(newnode);
347
+	    return 2;
348
+	}
323 349
 
324
-    return NULL;
350
+    } else {
351
+	newnode->next = *copt;
352
+	*copt = newnode;
353
+	return 1;
354
+    }
325 355
 }
356
+
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2002 - 2004 Tomasz Kojm <tkojm@clamav.net>
2
+ *  Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>
3 3
  *
4 4
  *  This program is free software; you can redistribute it and/or modify
5 5
  *  it under the terms of the GNU General Public License as published by
... ...
@@ -21,31 +21,32 @@
21 21
 
22 22
 #define LINE_LENGTH 1024
23 23
 
24
-
25 24
 #define OPT_STR 1 /* string argument */
26 25
 #define OPT_NUM 2 /* numerical argument */
27 26
 #define OPT_COMPSIZE 3 /* convert kilobytes (k) and megabytes (m) to bytes */
28
-#define OPT_NOARG 4 /* no argument */
29
-#define OPT_OPTARG 5 /* argument is optional, it's registered as string */
30
-#define OPT_FULLSTR 6 /* string argument, but get a full line */
27
+#define OPT_BOOL 4 /* boolean value */
28
+#define OPT_FULLSTR 5 /* string argument, but get a full line */
31 29
 
32 30
 struct cfgoption {
33 31
     const char *name;
34 32
     int argtype;
33
+    int numarg;
34
+    const char *strarg;
35
+    short multiple;
35 36
 };
36 37
 
37 38
 struct cfgstruct {
38 39
     char *optname;
39 40
     char *strarg;
40 41
     int numarg;
42
+    short enabled;
43
+    short multiple;
41 44
     struct cfgstruct *nextarg;
42 45
     struct cfgstruct *next;
43 46
 };
44 47
 
45 48
 
46
-struct cfgstruct *parsecfg(const char *cfgfile, int messages);
47
-
48
-struct cfgstruct *regcfg(struct cfgstruct *copt, char *optname, char *strarg, int numarg);
49
+struct cfgstruct *getcfg(const char *cfgfile, int verbose);
49 50
 
50 51
 struct cfgstruct *cfgopt(const struct cfgstruct *copt, const char *optname);
51 52
 
... ...
@@ -44,8 +44,8 @@ char *freshdbdir(void)
44 44
 
45 45
     /* try to find fresh directory */
46 46
     dbdir = cl_retdbdir();
47
-    if((copt = parsecfg(CONFDIR"/clamd.conf", 0))) {
48
-	if((cpt = cfgopt(copt, "DatabaseDirectory")) || (cpt = cfgopt(copt, "DataDirectory"))) {
47
+    if((copt = getcfg(CONFDIR"/clamd.conf", 0))) {
48
+	if((cpt = cfgopt(copt, "DatabaseDirectory"))->enabled || (cpt = cfgopt(copt, "DataDirectory"))->enabled) {
49 49
 	    if(strcmp(dbdir, cpt->strarg)) {
50 50
 		    char *daily = (char *) mmalloc(strlen(cpt->strarg) + strlen(dbdir) + 15);
51 51
 		sprintf(daily, "%s/daily.cvd", cpt->strarg);