Browse code

shared/optparser.c, clamscan: use the new option parser

git-svn: trunk@4580

Tomasz Kojm authored on 2008/12/30 19:33:43
Showing 9 changed files
... ...
@@ -1,3 +1,13 @@
1
+Tue Dec 30 11:43:10 CET 2008 (tk)
2
+---------------------------------
3
+ * shared/optparser.c, clamscan: use the new option parser; changes in switches:
4
+   --no-mail -> --scan-mail, --no-phishing-sigs -> --phishing-sigs,
5
+   --no-phishing-scan-urls -> --phishing-scan-urls,
6
+   --no-algorithmic -> --algorithmic-detection, --no-pe -> --scan-pe,
7
+   --no-elf -> --scan-elf, --no-ole2 -> --scan-ole2, --no-pdf -> --scan-pdf,
8
+   --no-html -> --scan-html, --no-archive -> --scan-archive
9
+   See clamscan(1) for more information
10
+
1 11
 Mon Dec 29 19:08:25 CET 2008 (tk)
2 12
 ---------------------------------
3 13
  * libclamav: add default.h
... ...
@@ -24,12 +24,10 @@ clamscan_SOURCES = \
24 24
     $(top_srcdir)/shared/output.h \
25 25
     $(top_srcdir)/shared/getopt.c \
26 26
     $(top_srcdir)/shared/getopt.h \
27
-    $(top_srcdir)/shared/cfgparser.c \
28
-    $(top_srcdir)/shared/cfgparser.h \
27
+    $(top_srcdir)/shared/optparser.c \
28
+    $(top_srcdir)/shared/optparser.h \
29 29
     $(top_srcdir)/shared/misc.c \
30 30
     $(top_srcdir)/shared/misc.h \
31
-    $(top_srcdir)/shared/options.c \
32
-    $(top_srcdir)/shared/options.h \
33 31
     clamscan.c \
34 32
     clamscan_opt.h \
35 33
     others.c \
... ...
@@ -73,8 +73,8 @@ am__installdirs = "$(DESTDIR)$(bindir)"
73 73
 binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
74 74
 PROGRAMS = $(bin_PROGRAMS)
75 75
 am_clamscan_OBJECTS = output.$(OBJEXT) getopt.$(OBJEXT) \
76
-	cfgparser.$(OBJEXT) misc.$(OBJEXT) options.$(OBJEXT) \
77
-	clamscan.$(OBJEXT) others.$(OBJEXT) manager.$(OBJEXT)
76
+	optparser.$(OBJEXT) misc.$(OBJEXT) clamscan.$(OBJEXT) \
77
+	others.$(OBJEXT) manager.$(OBJEXT)
78 78
 clamscan_OBJECTS = $(am_clamscan_OBJECTS)
79 79
 clamscan_LDADD = $(LDADD)
80 80
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
... ...
@@ -255,12 +255,10 @@ clamscan_SOURCES = \
255 255
     $(top_srcdir)/shared/output.h \
256 256
     $(top_srcdir)/shared/getopt.c \
257 257
     $(top_srcdir)/shared/getopt.h \
258
-    $(top_srcdir)/shared/cfgparser.c \
259
-    $(top_srcdir)/shared/cfgparser.h \
258
+    $(top_srcdir)/shared/optparser.c \
259
+    $(top_srcdir)/shared/optparser.h \
260 260
     $(top_srcdir)/shared/misc.c \
261 261
     $(top_srcdir)/shared/misc.h \
262
-    $(top_srcdir)/shared/options.c \
263
-    $(top_srcdir)/shared/options.h \
264 262
     clamscan.c \
265 263
     clamscan_opt.h \
266 264
     others.c \
... ...
@@ -358,12 +356,11 @@ mostlyclean-compile:
358 358
 distclean-compile:
359 359
 	-rm -f *.tab.c
360 360
 
361
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfgparser.Po@am__quote@
362 361
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clamscan.Po@am__quote@
363 362
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@
364 363
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manager.Po@am__quote@
365 364
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@
366
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Po@am__quote@
365
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/optparser.Po@am__quote@
367 366
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/others.Po@am__quote@
368 367
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/output.Po@am__quote@
369 368
 
... ...
@@ -416,19 +413,19 @@ getopt.obj: $(top_srcdir)/shared/getopt.c
416 416
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
417 417
 @am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o getopt.obj `if test -f '$(top_srcdir)/shared/getopt.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/getopt.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/getopt.c'; fi`
418 418
 
419
-cfgparser.o: $(top_srcdir)/shared/cfgparser.c
420
-@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cfgparser.o -MD -MP -MF $(DEPDIR)/cfgparser.Tpo -c -o cfgparser.o `test -f '$(top_srcdir)/shared/cfgparser.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/cfgparser.c
421
-@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/cfgparser.Tpo $(DEPDIR)/cfgparser.Po
422
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$(top_srcdir)/shared/cfgparser.c' object='cfgparser.o' libtool=no @AMDEPBACKSLASH@
419
+optparser.o: $(top_srcdir)/shared/optparser.c
420
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT optparser.o -MD -MP -MF $(DEPDIR)/optparser.Tpo -c -o optparser.o `test -f '$(top_srcdir)/shared/optparser.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/optparser.c
421
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/optparser.Tpo $(DEPDIR)/optparser.Po
422
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$(top_srcdir)/shared/optparser.c' object='optparser.o' libtool=no @AMDEPBACKSLASH@
423 423
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
424
-@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cfgparser.o `test -f '$(top_srcdir)/shared/cfgparser.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/cfgparser.c
424
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o optparser.o `test -f '$(top_srcdir)/shared/optparser.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/optparser.c
425 425
 
426
-cfgparser.obj: $(top_srcdir)/shared/cfgparser.c
427
-@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cfgparser.obj -MD -MP -MF $(DEPDIR)/cfgparser.Tpo -c -o cfgparser.obj `if test -f '$(top_srcdir)/shared/cfgparser.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/cfgparser.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/cfgparser.c'; fi`
428
-@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/cfgparser.Tpo $(DEPDIR)/cfgparser.Po
429
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$(top_srcdir)/shared/cfgparser.c' object='cfgparser.obj' libtool=no @AMDEPBACKSLASH@
426
+optparser.obj: $(top_srcdir)/shared/optparser.c
427
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT optparser.obj -MD -MP -MF $(DEPDIR)/optparser.Tpo -c -o optparser.obj `if test -f '$(top_srcdir)/shared/optparser.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/optparser.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/optparser.c'; fi`
428
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/optparser.Tpo $(DEPDIR)/optparser.Po
429
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$(top_srcdir)/shared/optparser.c' object='optparser.obj' libtool=no @AMDEPBACKSLASH@
430 430
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
431
-@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cfgparser.obj `if test -f '$(top_srcdir)/shared/cfgparser.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/cfgparser.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/cfgparser.c'; fi`
431
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o optparser.obj `if test -f '$(top_srcdir)/shared/optparser.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/optparser.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/optparser.c'; fi`
432 432
 
433 433
 misc.o: $(top_srcdir)/shared/misc.c
434 434
 @am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT misc.o -MD -MP -MF $(DEPDIR)/misc.Tpo -c -o misc.o `test -f '$(top_srcdir)/shared/misc.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/misc.c
... ...
@@ -444,20 +441,6 @@ misc.obj: $(top_srcdir)/shared/misc.c
444 444
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
445 445
 @am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o misc.obj `if test -f '$(top_srcdir)/shared/misc.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/misc.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/misc.c'; fi`
446 446
 
447
-options.o: $(top_srcdir)/shared/options.c
448
-@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT options.o -MD -MP -MF $(DEPDIR)/options.Tpo -c -o options.o `test -f '$(top_srcdir)/shared/options.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/options.c
449
-@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/options.Tpo $(DEPDIR)/options.Po
450
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$(top_srcdir)/shared/options.c' object='options.o' libtool=no @AMDEPBACKSLASH@
451
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
452
-@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o options.o `test -f '$(top_srcdir)/shared/options.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/options.c
453
-
454
-options.obj: $(top_srcdir)/shared/options.c
455
-@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT options.obj -MD -MP -MF $(DEPDIR)/options.Tpo -c -o options.obj `if test -f '$(top_srcdir)/shared/options.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/options.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/options.c'; fi`
456
-@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/options.Tpo $(DEPDIR)/options.Po
457
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$(top_srcdir)/shared/options.c' object='options.obj' libtool=no @AMDEPBACKSLASH@
458
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
459
-@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o options.obj `if test -f '$(top_srcdir)/shared/options.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/options.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/options.c'; fi`
460
-
461 447
 mostlyclean-libtool:
462 448
 	-rm -f *.lo
463 449
 
... ...
@@ -38,14 +38,13 @@
38 38
 #include <sys/resource.h>
39 39
 #endif
40 40
 
41
-#include "clamscan_opt.h"
42 41
 #include "others.h"
43 42
 #include "global.h"
44 43
 #include "manager.h"
45 44
 
46 45
 #include "shared/misc.h"
47 46
 #include "shared/output.h"
48
-#include "shared/options.h"
47
+#include "shared/optparser.h"
49 48
 
50 49
 #include "libclamav/str.h"
51 50
 #include "libclamav/clamav.h"
... ...
@@ -68,8 +67,8 @@ int main(int argc, char **argv)
68 68
 	struct timezone tz;
69 69
 	sigset_t sigset;
70 70
 #endif
71
-	struct optstruct *opt;
72
-	const char *pt;
71
+	struct optstruct *opts;
72
+	const struct optstruct *opt;
73 73
 
74 74
 #if defined(C_WINDOWS) && defined(CL_THREAD_SAFE)
75 75
     if(!pthread_win32_process_attach_np()) {
... ...
@@ -84,25 +83,25 @@ int main(int argc, char **argv)
84 84
     sigprocmask(SIG_SETMASK, &sigset, NULL);
85 85
 #endif
86 86
 
87
-    opt = opt_parse(argc, argv, clamscan_shortopt, clamscan_longopt, NULL, clamscan_deprecated);
88
-    if(!opt) {
89
-	mprintf("!Can't parse the command line\n");
87
+
88
+    if((opts = optparse(NULL, argc, argv, 1, OPT_CLAMSCAN, NULL)) == NULL) {
89
+	mprintf("!Can't parse command line options\n");
90 90
 	return 40;
91 91
     }
92 92
 
93
-    if(opt_check(opt, "verbose")) {
93
+    if(optget(opts, "verbose")->enabled) {
94 94
 	mprintf_verbose = 1;
95 95
 	logg_verbose = 1;
96 96
     }
97 97
 
98
-    if(opt_check(opt, "quiet"))
98
+    if(optget(opts, "quiet")->enabled)
99 99
 	mprintf_quiet = 1;
100 100
 
101
-    if(opt_check(opt, "stdout"))
101
+    if(optget(opts, "stdout")->enabled)
102 102
 	mprintf_stdout = 1;
103 103
 
104 104
 
105
-    if(opt_check(opt, "debug")) {
105
+    if(optget(opts, "debug")->enabled) {
106 106
 #if defined(C_LINUX)
107 107
 	    /* njh@bandsman.co.uk: create a dump if needed */
108 108
 	    struct rlimit rlim;
... ...
@@ -114,103 +113,39 @@ int main(int argc, char **argv)
114 114
 	cl_debug(); /* enable debug messages */
115 115
     }
116 116
 
117
-    if(opt_check(opt, "version")) {
118
-	print_version(opt_arg(opt, "database"));
119
-	opt_free(opt);
117
+    if(optget(opts, "version")->enabled) {
118
+	print_version(optget(opts, "database")->strarg);
119
+	optfree(opts);
120 120
 	return 0;
121 121
     }
122 122
 
123
-    if(opt_check(opt, "help")) {
124
-	opt_free(opt);
123
+    if(optget(opts, "help")->enabled) {
124
+	optfree(opts);
125 125
     	help();
126 126
 	return 0;
127 127
     }
128 128
 
129
-    if(opt_check(opt, "recursive"))
129
+    if(optget(opts, "recursive")->enabled)
130 130
 	recursion = 1;
131 131
 
132
-    if(opt_check(opt, "infected"))
132
+    if(optget(opts, "infected")->enabled)
133 133
 	printinfected = 1;
134 134
 
135
-    if(opt_check(opt, "bell"))
135
+    if(optget(opts, "bell")->enabled)
136 136
 	bell = 1;
137 137
 
138 138
     /* initialize logger */
139
-    if(opt_check(opt, "log")) {
140
-	logg_file = opt_arg(opt, "log");
139
+    if((opt = optget(opts, "log"))->enabled) {
140
+	logg_file = opt->strarg;
141 141
 	if(logg("#\n-------------------------------------------------------------------------------\n\n")) {
142 142
 	    mprintf("!Problem with internal logger.\n");
143
-	    opt_free(opt);
143
+	    optfree(opts);
144 144
 	    return 62;
145 145
 	}
146 146
     } else 
147 147
 	logg_file = NULL;
148 148
 
149 149
 
150
-    /* validate some numerical options */
151
-
152
-    if(opt_check(opt, "max-scansize")) {
153
-	pt = opt_arg(opt, "max-scansize");
154
-	if(!strchr(pt, 'M') && !strchr(pt, 'm')) {
155
-	    if(!cli_isnumber(pt)) {
156
-		logg("!--max-scansize requires a natural number\n");
157
-		opt_free(opt);
158
-		return 40;
159
-	    }
160
-	}
161
-    }
162
-
163
-    if(opt_check(opt, "max-filesize")) {
164
-	pt = opt_arg(opt, "max-filesize");
165
-	if(!strchr(pt, 'M') && !strchr(pt, 'm')) {
166
-	    if(!cli_isnumber(pt)) {
167
-		logg("!--max-filesize requires a natural number\n");
168
-		opt_free(opt);
169
-		return 40;
170
-	    }
171
-	}
172
-    }
173
-
174
-    if(opt_check(opt, "max-files")) {
175
-	if(!cli_isnumber(opt_arg(opt, "max-files"))) {
176
-	    logg("!--max-files requires a natural number\n");
177
-	    opt_free(opt);
178
-	    return 40;
179
-	}
180
-    }
181
-
182
-    if(opt_check(opt, "max-recursion")) {
183
-	if(!cli_isnumber(opt_arg(opt, "max-recursion"))) {
184
-	    logg("!--max-recursion requires a natural number\n");
185
-	    opt_free(opt);
186
-	    return 40;
187
-	}
188
-    }
189
-
190
-    if(opt_check(opt, "max-mail-recursion")) {
191
-	if(!cli_isnumber(opt_arg(opt, "max-mail-recursion"))) {
192
-	    logg("!--max-mail-recursion requires a natural number\n");
193
-	    opt_free(opt);
194
-	    return 40;
195
-	}
196
-    }
197
-
198
-    if(opt_check(opt, "max-dir-recursion")) {
199
-	if(!cli_isnumber(opt_arg(opt, "max-dir-recursion"))) {
200
-	    logg("!--max-dir-recursion requires a natural number\n");
201
-	    opt_free(opt);
202
-	    return 40;
203
-	}
204
-    }
205
-
206
-    if(opt_check(opt, "max-ratio")) {
207
-	if(!cli_isnumber(opt_arg(opt, "max-ratio"))) {
208
-	    logg("!--max-ratio requires a natural number\n");
209
-	    opt_free(opt);
210
-	    return 40;
211
-	}
212
-    }
213
-
214 150
     memset(&info, 0, sizeof(struct s_info));
215 151
 
216 152
 #ifdef C_WINDOWS
... ...
@@ -226,9 +161,9 @@ int main(int argc, char **argv)
226 226
     gettimeofday(&t1, &tz);
227 227
 #endif
228 228
 
229
-    ret = scanmanager(opt);
229
+    ret = scanmanager(opts);
230 230
 
231
-    if(!opt_check(opt, "disable-summary") && !opt_check(opt, "no-summary")) {
231
+    if(!optget(opts, "no-summary")->enabled) {
232 232
 #ifdef C_WINDOWS
233 233
 	gettimeofday(&t2, NULL);
234 234
 #else
... ...
@@ -248,14 +183,14 @@ int main(int argc, char **argv)
248 248
 	    logg("Not removed: %u\n", info.notremoved);
249 249
 	}
250 250
 	if(info.notmoved) {
251
-	    logg("Not %s: %u\n", opt_check(opt, "copy") ? "moved" : "copied", info.notmoved);
251
+	    logg("Not %s: %u\n", optget(opts, "copy")->enabled ? "moved" : "copied", info.notmoved);
252 252
 	}
253 253
 	mb = info.blocks * (CL_COUNT_PRECISION / 1024) / 1024.0;
254 254
 	logg("Data scanned: %2.2lf MB\n", mb);
255 255
 	logg("Time: %u.%3.3u sec (%u m %u s)\n", ds, dms/1000, ds/60, ds%60);
256 256
     }
257 257
 
258
-    opt_free(opt);
258
+    optfree(opts);
259 259
 
260 260
 #if defined(C_WINDOWS) && defined(CL_THREAD_SAFE)
261 261
     if(!pthread_win32_process_detach_np()) {
... ...
@@ -285,15 +220,14 @@ void help(void)
285 285
     mprintf("    --no-summary                         Disable summary at end of scanning\n");
286 286
     mprintf("    --infected            -i             Only print infected files\n");
287 287
     mprintf("    --bell                               Sound bell on virus detection\n");
288
-
289 288
     mprintf("\n");
290 289
     mprintf("    --tempdir=DIRECTORY                  Create temporary files in DIRECTORY\n");
291
-    mprintf("    --leave-temps                        Do not remove temporary files\n");
290
+    mprintf("    --leave-temps[=yes/no(*)]            Do not remove temporary files\n");
292 291
     mprintf("    --database=FILE/DIR   -d FILE/DIR    Load virus database from FILE or load\n");
293
-    mprintf("                                         all .cvd and .db[2] files from DIR\n");
292
+    mprintf("                                         all supported db files from DIR\n");
294 293
     mprintf("    --log=FILE            -l FILE        Save scan report to FILE\n");
295
-    mprintf("    --recursive           -r             Scan subdirectories recursively\n");
296
-    mprintf("    --remove                             Remove infected files. Be careful!\n");
294
+    mprintf("    --recursive[=yes/no(*)]  -r          Scan subdirectories recursively\n");
295
+    mprintf("    --remove[=yes/no(*)]                 Remove infected files. Be careful!\n");
297 296
     mprintf("    --move=DIRECTORY                     Move infected files into DIRECTORY\n");
298 297
     mprintf("    --copy=DIRECTORY                     Copy infected files into DIRECTORY\n");
299 298
 #ifdef HAVE_REGEX_H
... ...
@@ -308,37 +242,38 @@ void help(void)
308 308
     mprintf("    --include-dir=PATT                   Only scan directories containing PATT\n");
309 309
 #endif
310 310
     mprintf("\n");
311
-    mprintf("    --detect-pua                         Detect Possibly Unwanted Applications\n");
311
+    mprintf("    --detect-pua[=yes/no(*)]             Detect Possibly Unwanted Applications\n");
312 312
     mprintf("    --exclude-pua=CAT                    Skip PUA sigs of category CAT\n");
313 313
     mprintf("    --include-pua=CAT                    Load PUA sigs of category CAT\n");
314
-    mprintf("    --detect-structured                  Detect structured data (SSN, Credit Card)\n");
314
+    mprintf("    --detect-structured[=yes/no(*)]      Detect structured data (SSN, Credit Card)\n");
315 315
     mprintf("    --structured-ssn-format=X            SSN format (0=normal,1=stripped,2=both)\n");
316 316
     mprintf("    --structured-ssn-count=N             Min SSN count to generate a detect\n");
317 317
     mprintf("    --structured-cc-count=N              Min CC count to generate a detect\n");
318
-    mprintf("    --no-mail                            Disable mail file support\n");
319
-    mprintf("    --no-phishing-sigs                   Disable signature-based phishing detection\n");
320
-    mprintf("    --no-phishing-scan-urls              Disable url-based phishing detection\n");
321
-    mprintf("    --heuristic-scan-precedence          Stop scanning as soon as a heuristic match is found\n");
322
-    mprintf("    --phishing-ssl                       Always block SSL mismatches in URLs (phishing module)\n");
323
-    mprintf("    --phishing-cloak                     Always block cloaked URLs (phishing module)\n");
324
-    mprintf("    --no-algorithmic                     Disable algorithmic detection\n");
325
-    mprintf("    --no-pe                              Disable PE analysis\n");
326
-    mprintf("    --no-elf                             Disable ELF support\n");
327
-    mprintf("    --no-ole2                            Disable OLE2 support\n");
328
-    mprintf("    --no-pdf                             Disable PDF support\n");
329
-    mprintf("    --no-html                            Disable HTML support\n");
330
-    mprintf("    --no-archive                         Disable archive support\n");
331
-    mprintf("    --detect-broken                      Try to detect broken executable files\n");
332
-    mprintf("    --block-encrypted                    Block encrypted archives\n");
333
-    mprintf("    --mail-follow-urls                   Download and scan URLs\n");
318
+    mprintf("    --scan-mail[=yes(*)/no]              Scan mail files\n");
319
+    mprintf("    --phishing-sigs[=yes(*)/no]          Signature-based phishing detection\n");
320
+    mprintf("    --phishing-scan-urls[=yes(*)/no]     URL-based phishing detection\n");
321
+    mprintf("    --heuristic-scan-precedence[=yes/no(*)] Stop scanning as soon as a heuristic match is found\n");
322
+    mprintf("    --phishing-ssl[=yes/no(*)]           Always block SSL mismatches in URLs (phishing module)\n");
323
+    mprintf("    --phishing-cloak[=yes/no(*)]         Always block cloaked URLs (phishing module)\n");
324
+    mprintf("    --algorithmic-detection[=yes(*)/no]  Algorithmic detection\n");
325
+    mprintf("    --scan-pe[=yes(*)/no]                Scan PE files\n");
326
+    mprintf("    --scan-elf[=yes(*)/no]               Scan ELF files\n");
327
+    mprintf("    --scan-ole2[=yes(*)/no]              Scan OLE2 containers\n");
328
+    mprintf("    --scan-pdf[=yes(*)/no]               Scan PDF files\n");
329
+    mprintf("    --scan-html[=yes(*)/no]              Scan HTML files\n");
330
+    mprintf("    --scan-archive[=yes(*)/no]           Scan archive files (supported by libclamav)\n");
331
+    mprintf("    --detect-broken[=yes/no(*)]          Try to detect broken executable files\n");
332
+    mprintf("    --block-encrypted[=yes/no(*)]        Block encrypted archives\n");
333
+    mprintf("    --mail-follow-urls[=yes/no(*)]       Download and scan URLs\n");
334 334
     mprintf("\n");
335 335
     mprintf("    --max-filesize=#n                    Files larger than this will be skipped and assumed clean\n");
336
-    mprintf("    --max-scansize=#n                    The maximum amount of data to scan for each container file (*)\n");
337
-    mprintf("    --max-files=#n                       The maximum number of files to scan for each container file (*)\n");
338
-    mprintf("    --max-recursion=#n                   Maximum archive recursion level for container file (*)\n");
336
+    mprintf("    --max-scansize=#n                    The maximum amount of data to scan for each container file (**)\n");
337
+    mprintf("    --max-files=#n                       The maximum number of files to scan for each container file (**)\n");
338
+    mprintf("    --max-recursion=#n                   Maximum archive recursion level for container file (**)\n");
339 339
     mprintf("    --max-dir-recursion=#n               Maximum directory recursion level\n");
340 340
 
341 341
     mprintf("\n");
342
-    mprintf("(*) Certain files (e.g. documents, archives, etc.) may in turn contain other\n");
343
-    mprintf("    files inside. The above options ensure safe processing of this kind of data.\n\n");
342
+    mprintf("(*) Default scan settings\n");
343
+    mprintf("(**) Certain files (e.g. documents, archives, etc.) may in turn contain other\n");
344
+    mprintf("   files inside. The above options ensure safe processing of this kind of data.\n\n");
344 345
 }
... ...
@@ -51,7 +51,7 @@
51 51
 #include "others.h"
52 52
 #include "global.h"
53 53
 
54
-#include "shared/options.h"
54
+#include "shared/optparser.h"
55 55
 #include "shared/output.h"
56 56
 #include "shared/misc.h"
57 57
 
... ...
@@ -75,13 +75,12 @@ dev_t procdev;
75 75
 #define	O_BINARY    0
76 76
 #endif
77 77
 
78
-static void move_infected(const char *filename, const struct optstruct *opt);
78
+static void move_infected(const char *filename, const struct optstruct *opts);
79 79
 
80
-static int scanfile(const char *filename, struct cl_engine *engine, const struct optstruct *opt, unsigned int options)
80
+static int scanfile(const char *filename, struct cl_engine *engine, const struct optstruct *opts, unsigned int options)
81 81
 {
82 82
 	int ret = 0, fd, included, printclean = 1;
83
-	const struct optnode *optnode;
84
-	char *argument;
83
+	const struct optstruct *opt;
85 84
 	const char *virname;
86 85
 #ifdef C_LINUX
87 86
 	struct stat sb;
... ...
@@ -96,29 +95,26 @@ static int scanfile(const char *filename, struct cl_engine *engine, const struct
96 96
 	    }
97 97
 #endif    
98 98
 
99
-    if(opt_check(opt, "exclude")) {
100
-	argument = opt_firstarg(opt, "exclude", &optnode);
101
-	while(argument) {
102
-	    if(match_regex(filename, argument) == 1) {
99
+    if((opt = optget(opts, "exclude"))->enabled) {
100
+	while(opt) {
101
+	    if(match_regex(filename, opt->strarg) == 1) {
103 102
 		if(!printinfected)
104 103
 		    logg("~%s: Excluded\n", filename);
105 104
 		return 0;
106 105
 	    }
107
-	    argument = opt_nextarg(&optnode, "exclude");
106
+	    opt = opt->nextarg;
108 107
 	}
109 108
     }
110 109
 
111
-   if(opt_check(opt, "include")) {
110
+    if((opt = optget(opts, "include"))->enabled) {
112 111
 	included = 0;
113
-	argument = opt_firstarg(opt, "include", &optnode);
114
-	while(argument && !included) {
115
-	    if(match_regex(filename, argument) == 1) {
112
+	while(opt) {
113
+	    if(match_regex(filename, opt->strarg) == 1) {
116 114
 		included = 1;
117 115
 		break;
118 116
 	    }
119
-	    argument = opt_nextarg(&optnode, "include");
117
+	    opt = opt->nextarg;
120 118
 	}
121
-
122 119
 	if(!included) {
123 120
 	    if(!printinfected)
124 121
 		logg("~%s: Excluded\n", filename);
... ...
@@ -167,55 +163,50 @@ static int scanfile(const char *filename, struct cl_engine *engine, const struct
167 167
     close(fd);
168 168
 
169 169
     if(ret == CL_VIRUS) {
170
-	if(opt_check(opt, "remove")) {
170
+	if(optget(opts, "remove")->enabled) {
171 171
 	    if(unlink(filename)) {
172 172
 		logg("^%s: Can't remove\n", filename);
173 173
 		info.notremoved++;
174 174
 	    } else {
175 175
 		logg("~%s: Removed\n", filename);
176 176
 	    }
177
-	} else if(opt_check(opt, "move") || opt_check(opt, "copy"))
178
-            move_infected(filename, opt);
177
+	} else if(optget(opts, "move")->enabled || optget(opts, "copy")->enabled)
178
+            move_infected(filename, opts);
179 179
     }
180 180
 
181 181
     return ret;
182 182
 }
183 183
 
184
-static int scandirs(const char *dirname, struct cl_engine *engine, const struct optstruct *opt, unsigned int options, unsigned int depth)
184
+static int scandirs(const char *dirname, struct cl_engine *engine, const struct optstruct *opts, unsigned int options, unsigned int depth)
185 185
 {
186 186
 	DIR *dd;
187 187
 	struct dirent *dent;
188 188
 	struct stat statbuf;
189 189
 	char *fname;
190 190
 	int scanret = 0, included;
191
-	unsigned int maxdepth;
192
-	const struct optnode *optnode;
193
-	char *argument;
191
+	const struct optstruct *opt;
194 192
 
195 193
 
196
-    if(opt_check(opt, "exclude-dir")) {
197
-	argument = opt_firstarg(opt, "exclude-dir", &optnode);
198
-	while(argument) {
199
-	    if(match_regex(dirname, argument) == 1) {
194
+    if((opt = optget(opts, "exclude-dir"))->enabled) {
195
+	while(opt) {
196
+	    if(match_regex(dirname, opt->strarg) == 1) {
200 197
 		if(!printinfected)
201 198
 		    logg("~%s: Excluded\n", dirname);
202 199
 		return 0;
203 200
 	    }
204
-	    argument = opt_nextarg(&optnode, "exclude-dir");
201
+	    opt = opt->nextarg;
205 202
 	}
206 203
     }
207 204
 
208
-   if(opt_check(opt, "include-dir")) {
205
+    if((opt = optget(opts, "include-dir"))->enabled) {
209 206
 	included = 0;
210
-	argument = opt_firstarg(opt, "include-dir", &optnode);
211
-	while(argument && !included) {
212
-	    if(match_regex(dirname, argument) == 1) {
207
+	while(opt) {
208
+	    if(match_regex(dirname, opt->strarg) == 1) {
213 209
 		included = 1;
214 210
 		break;
215 211
 	    }
216
-	    argument = opt_nextarg(&optnode, "include-dir");
212
+	    opt = opt->nextarg;
217 213
 	}
218
-
219 214
 	if(!included) {
220 215
 	    if(!printinfected)
221 216
 		logg("~%s: Excluded\n", dirname);
... ...
@@ -223,12 +214,7 @@ static int scandirs(const char *dirname, struct cl_engine *engine, const struct
223 223
 	}
224 224
     }
225 225
 
226
-    if(opt_check(opt, "max-dir-recursion"))
227
-        maxdepth = atoi(opt_arg(opt, "max-dir-recursion"));
228
-    else
229
-        maxdepth = 15;
230
-
231
-    if(depth > maxdepth)
226
+    if(depth > (unsigned int) optget(opts, "max-dir-recursion")->numarg)
232 227
 	return 0;
233 228
 
234 229
     info.dirs++;
... ...
@@ -251,11 +237,11 @@ static int scandirs(const char *dirname, struct cl_engine *engine, const struct
251 251
 		    /* stat the file */
252 252
 		    if(lstat(fname, &statbuf) != -1) {
253 253
 			if(S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode) && recursion) {
254
-			    if(scandirs(fname, engine, opt, options, depth) == 1)
254
+			    if(scandirs(fname, engine, opts, options, depth) == 1)
255 255
 				scanret++;
256 256
 			} else {
257 257
 			    if(S_ISREG(statbuf.st_mode))
258
-				scanret += scanfile(fname, engine, opt, options);
258
+				scanret += scanfile(fname, engine, opts, options);
259 259
 			}
260 260
 		    }
261 261
 		    free(fname);
... ...
@@ -278,7 +264,7 @@ static int scandirs(const char *dirname, struct cl_engine *engine, const struct
278 278
 
279 279
 }
280 280
 
281
-static int scanstdin(const struct cl_engine *engine, const struct optstruct *opt, int options)
281
+static int scanstdin(const struct cl_engine *engine, const struct optstruct *opts, int options)
282 282
 {
283 283
 	int ret;
284 284
 	const char *virname, *tmpdir;
... ...
@@ -286,8 +272,8 @@ static int scanstdin(const struct cl_engine *engine, const struct optstruct *opt
286 286
 	size_t bread;
287 287
 	FILE *fs;
288 288
 
289
-    if(opt_check(opt, "tempdir")) {
290
-	tmpdir = opt_arg(opt, "tempdir");
289
+    if(optget(opts, "tempdir")->enabled) {
290
+	tmpdir = optget(opts, "tempdir")->strarg;
291 291
     } else {
292 292
 	/* check write access */
293 293
 	tmpdir = getenv("TMPDIR");
... ...
@@ -344,36 +330,26 @@ static int scanstdin(const struct cl_engine *engine, const struct optstruct *opt
344 344
     return ret;
345 345
 }
346 346
 
347
-int scanmanager(const struct optstruct *opt)
347
+int scanmanager(const struct optstruct *opts)
348 348
 {
349 349
 	mode_t fmode;
350 350
 	int ret = 0, fmodeint, i, x;
351 351
 	unsigned int options = 0, dboptions = 0;
352 352
 	struct cl_engine *engine;
353 353
 	struct stat sb;
354
-	char *file, cwd[1024], *pua_cats = NULL, *argument;
355
-	const char *pt;
356
-	const struct optnode *optnode;
354
+	char *file, cwd[1024], *pua_cats = NULL;
355
+	const struct optstruct *opt;
357 356
 #ifndef C_WINDOWS
358 357
 	struct rlimit rlim;
359 358
 #endif
360 359
 	uint64_t val64;
361 360
 	uint32_t val32;
362 361
 
363
-    if(!opt_check(opt, "no-phishing-sigs"))
362
+    if(optget(opts, "phishing-sigs")->enabled)
364 363
 	dboptions |= CL_DB_PHISHING;
365 364
 
366
-    if(!opt_check(opt,"no-phishing-scan-urls"))
365
+    if(optget(opts,"phishing-scan-urls")->enabled)
367 366
 	dboptions |= CL_DB_PHISHING_URLS;
368
-    if(opt_check(opt,"phishing-ssl")) {
369
-	options |= CL_SCAN_PHISHING_BLOCKSSL;
370
-    }
371
-    if(opt_check(opt,"phishing-cloak")) {
372
-	options |= CL_SCAN_PHISHING_BLOCKCLOAK;
373
-    }
374
-    if(opt_check(opt,"heuristic-scan-precedence")) {
375
-	options |= CL_SCAN_HEURISTIC_PRECEDENCE;
376
-    }
377 367
 
378 368
     if((ret = cl_init(CL_INIT_DEFAULT))) {
379 369
 	logg("!Can't initialize libclamav: %s\n", cl_strerror(ret));
... ...
@@ -385,29 +361,26 @@ int scanmanager(const struct optstruct *opt)
385 385
 	return 50;
386 386
     }
387 387
 
388
-    if(opt_check(opt, "detect-pua")) {
388
+    if(optget(opts, "detect-pua")->enabled) {
389 389
 	dboptions |= CL_DB_PUA;
390
-
391
-	if(opt_check(opt, "exclude-pua")) {
390
+	if((opt = optget(opts, "exclude-pua"))->enabled) {
392 391
 	    dboptions |= CL_DB_PUA_EXCLUDE;
393
-	    argument = opt_firstarg(opt, "exclude-pua", &optnode);
394
-	    i = 0;
395
-	    while(argument) {
396
-		if(!(pua_cats = realloc(pua_cats, i + strlen(argument) + 3))) {
392
+	    while(opt) {
393
+		if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) {
397 394
 		    logg("!Can't allocate memory for pua_cats\n");
398 395
 		    cl_engine_free(engine);
399 396
 		    return 70;
400 397
 		}
401
-		sprintf(pua_cats + i, ".%s", argument);
402
-		i += strlen(argument) + 1;
398
+		sprintf(pua_cats + i, ".%s", opt->strarg);
399
+		i += strlen(opt->strarg) + 1;
403 400
 		pua_cats[i] = 0;
404
-		argument = opt_nextarg(&optnode, "exclude-pua");
401
+		opt = opt->nextarg;
405 402
 	    }
406 403
 	    pua_cats[i] = '.';
407 404
 	    pua_cats[i + 1] = 0;
408 405
 	}
409 406
 
410
-	if(opt_check(opt, "include-pua")) {
407
+	if((opt = optget(opts, "include-pua"))->enabled) {
411 408
 	    if(pua_cats) {
412 409
 		logg("!--exclude-pua and --include-pua cannot be used at the same time\n");
413 410
 		cl_engine_free(engine);
... ...
@@ -415,17 +388,16 @@ int scanmanager(const struct optstruct *opt)
415 415
 		return 40;
416 416
 	    }
417 417
 	    dboptions |= CL_DB_PUA_INCLUDE;
418
-	    argument = opt_firstarg(opt, "include-pua", &optnode);
419 418
 	    i = 0;
420
-	    while(argument) {
421
-		if(!(pua_cats = realloc(pua_cats, i + strlen(argument) + 3))) {
419
+	    while(opt) {
420
+		if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) {
422 421
 		    logg("!Can't allocate memory for pua_cats\n");
423 422
 		    return 70;
424 423
 		}
425
-		sprintf(pua_cats + i, ".%s", argument);
426
-		i += strlen(argument) + 1;
424
+		sprintf(pua_cats + i, ".%s", opt->strarg);
425
+		i += strlen(opt->strarg) + 1;
427 426
 		pua_cats[i] = 0;
428
-		argument = opt_nextarg(&optnode, "include-pua");
427
+		opt = opt->nextarg;
429 428
 	    }
430 429
 	    pua_cats[i] = '.';
431 430
 	    pua_cats[i + 1] = 0;
... ...
@@ -442,32 +414,31 @@ int scanmanager(const struct optstruct *opt)
442 442
 	}
443 443
     }
444 444
 
445
-    if(opt_check(opt, "dev-ac-only")) {
445
+    if(optget(opts, "dev-ac-only")->enabled) {
446 446
 	val32 = 1;
447 447
 	cl_engine_set(engine, CL_ENGINE_AC_ONLY, &val32);
448 448
     }
449 449
 
450
-    if(opt_check(opt, "dev-ac-depth")) {
451
-	val32 = atoi(opt_arg(opt, "dev-ac-depth"));
450
+    if(optget(opts, "dev-ac-depth")->enabled) {
451
+	val32 = optget(opts, "dev-ac-depth")->numarg;
452 452
 	cl_engine_set(engine, CL_ENGINE_AC_MAXDEPTH, &val32);
453 453
     }
454 454
 
455
-    if(opt_check(opt, "leave-temps")) {
455
+    if(optget(opts, "leave-temps")->enabled) {
456 456
 	val32 = 1;
457 457
 	cl_engine_set(engine, CL_ENGINE_KEEPTMP, &val32);
458 458
     }
459 459
 
460
-    if(opt_check(opt, "tempdir")) {
461
-	pt = opt_arg(opt, "tempdir");
462
-	if((ret = cl_engine_set(engine, CL_ENGINE_TMPDIR, pt))) {
460
+    if((opt = optget(opts, "tempdir"))->enabled) {
461
+	if((ret = cl_engine_set(engine, CL_ENGINE_TMPDIR, opt->strarg))) {
463 462
 	    logg("!cli_engine_set(CL_ENGINE_TMPDIR) failed: %s\n", cl_strerror(ret));
464 463
 	    cl_engine_free(engine);
465 464
 	    return 50;
466 465
 	}
467 466
     }
468 467
 
469
-    if(opt_check(opt, "database")) {
470
-	if((ret = cl_load(opt_arg(opt, "database"), engine, &info.sigs, dboptions))) {
468
+    if((opt = optget(opts, "database"))->enabled) {
469
+	if((ret = cl_load(opt->strarg, engine, &info.sigs, dboptions))) {
471 470
 	    logg("!%s\n", cl_strerror(ret));
472 471
 	    cl_engine_free(engine);
473 472
 	    return 50;
... ...
@@ -493,18 +464,8 @@ int scanmanager(const struct optstruct *opt)
493 493
 
494 494
     /* set limits */
495 495
 
496
-    if(opt_check(opt, "max-scansize")) {
497
-	char *cpy, *ptr;
498
-	ptr = opt_arg(opt, "max-scansize");
499
-	if(tolower(ptr[strlen(ptr) - 1]) == 'm') {
500
-	    cpy = calloc(strlen(ptr), 1);
501
-	    strncpy(cpy, ptr, strlen(ptr) - 1);
502
-	    cpy[strlen(ptr)-1]='\0';
503
-	    val64 = atoi(cpy) * 1024 * 1024;
504
-	    free(cpy);
505
-	} else
506
-	    val64 = atoi(ptr) * 1024;
507
-
496
+    if((opt = optget(opts, "max-scansize"))->enabled) {
497
+	val64 = opt->numarg;
508 498
 	if((ret = cl_engine_set(engine, CL_ENGINE_MAX_SCANSIZE, &val64))) {
509 499
 	    logg("!cli_engine_set(CL_ENGINE_MAX_SCANSIZE) failed: %s\n", cl_strerror(ret));
510 500
 	    cl_engine_free(engine);
... ...
@@ -512,18 +473,8 @@ int scanmanager(const struct optstruct *opt)
512 512
 	}
513 513
     }
514 514
 
515
-    if(opt_check(opt, "max-filesize")) {
516
-	char *cpy, *ptr;
517
-	ptr = opt_arg(opt, "max-filesize");
518
-	if(tolower(ptr[strlen(ptr) - 1]) == 'm') {
519
-	    cpy = calloc(strlen(ptr), 1);
520
-	    strncpy(cpy, ptr, strlen(ptr) - 1);
521
-	    cpy[strlen(ptr)-1]='\0';
522
-	    val64 = atoi(cpy) * 1024 * 1024;
523
-	    free(cpy);
524
-	} else
525
-	    val64 = atoi(ptr) * 1024;
526
-
515
+    if((opt = optget(opts, "max-filesize"))->enabled) {
516
+	val64 = opt->numarg;
527 517
 	if((ret = cl_engine_set(engine, CL_ENGINE_MAX_FILESIZE, &val64))) {
528 518
 	    logg("!cli_engine_set(CL_ENGINE_MAX_FILESIZE) failed: %s\n", cl_strerror(ret));
529 519
 	    cl_engine_free(engine);
... ...
@@ -544,8 +495,8 @@ int scanmanager(const struct optstruct *opt)
544 544
     }
545 545
 #endif
546 546
 
547
-    if(opt_check(opt, "max-files")) {
548
-	val32 = atoi(opt_arg(opt, "max-files"));
547
+    if((opt = optget(opts, "max-files"))->enabled) {
548
+	val32 = opt->numarg;
549 549
 	if((ret = cl_engine_set(engine, CL_ENGINE_MAX_FILES, &val32))) {
550 550
 	    logg("!cli_engine_set(CL_ENGINE_MAX_FILES) failed: %s\n", cl_strerror(ret));
551 551
 	    cl_engine_free(engine);
... ...
@@ -553,8 +504,8 @@ int scanmanager(const struct optstruct *opt)
553 553
 	}
554 554
     }
555 555
 
556
-    if(opt_check(opt, "max-recursion")) {
557
-	val32 = atoi(opt_arg(opt, "max-recursion"));
556
+    if((opt = optget(opts, "max-recursion"))->enabled) {
557
+	val32 = opt->numarg;
558 558
 	if((ret = cl_engine_set(engine, CL_ENGINE_MAX_RECURSION, &val32))) {
559 559
 	    logg("!cli_engine_set(CL_ENGINE_MAX_RECURSION) failed: %s\n", cl_strerror(ret));
560 560
 	    cl_engine_free(engine);
... ...
@@ -562,63 +513,55 @@ int scanmanager(const struct optstruct *opt)
562 562
 	}
563 563
     }
564 564
 
565
-    /* set options */
565
+    /* set scan options */
566
+    if(optget(opts,"phishing-ssl")->enabled)
567
+	options |= CL_SCAN_PHISHING_BLOCKSSL;
566 568
 
567
-    if(opt_check(opt, "disable-archive") || opt_check(opt, "no-archive"))
568
-	options &= ~CL_SCAN_ARCHIVE;
569
-    else
569
+    if(optget(opts,"phishing-cloak")->enabled)
570
+	options |= CL_SCAN_PHISHING_BLOCKCLOAK;
571
+
572
+    if(optget(opts,"heuristic-scan-precedence")->enabled)
573
+	options |= CL_SCAN_HEURISTIC_PRECEDENCE;
574
+
575
+    if(optget(opts, "scan-archive")->enabled)
570 576
 	options |= CL_SCAN_ARCHIVE;
571 577
 
572
-    if(opt_check(opt, "detect-broken"))
578
+    if(optget(opts, "detect-broken")->enabled)
573 579
 	options |= CL_SCAN_BLOCKBROKEN;
574 580
 
575
-    if(opt_check(opt, "block-encrypted"))
581
+    if(optget(opts, "block-encrypted")->enabled)
576 582
 	options |= CL_SCAN_BLOCKENCRYPTED;
577 583
 
578
-    if(opt_check(opt, "no-pe"))
579
-	options &= ~CL_SCAN_PE;
580
-    else
584
+    if(optget(opts, "scan-pe")->enabled)
581 585
 	options |= CL_SCAN_PE;
582 586
 
583
-    if(opt_check(opt, "no-elf"))
584
-	options &= ~CL_SCAN_ELF;
585
-    else
587
+    if(optget(opts, "scan-elf")->enabled)
586 588
 	options |= CL_SCAN_ELF;
587 589
 
588
-    if(opt_check(opt, "no-ole2"))
589
-	options &= ~CL_SCAN_OLE2;
590
-    else
590
+    if(optget(opts, "scan-ole2")->enabled)
591 591
 	options |= CL_SCAN_OLE2;
592 592
 
593
-    if(opt_check(opt, "no-pdf"))
594
-	options &= ~CL_SCAN_PDF;
595
-    else
593
+    if(optget(opts, "scan-pdf")->enabled)
596 594
 	options |= CL_SCAN_PDF;
597 595
 
598
-    if(opt_check(opt, "no-html"))
599
-	options &= ~CL_SCAN_HTML;
600
-    else
596
+    if(optget(opts, "scan-html")->enabled)
601 597
 	options |= CL_SCAN_HTML;
602 598
 
603
-    if(opt_check(opt, "no-mail")) {
604
-	options &= ~CL_SCAN_MAIL;
605
-    } else {
599
+    if(optget(opts, "scan-mail")->enabled) {
606 600
 	options |= CL_SCAN_MAIL;
607 601
 
608
-	if(opt_check(opt, "mail-follow-urls"))
602
+	if(optget(opts, "mail-follow-urls")->enabled)
609 603
 	    options |= CL_SCAN_MAILURL;
610 604
     }
611 605
 
612
-    if(opt_check(opt, "no-algorithmic"))
613
-	options &= ~CL_SCAN_ALGORITHMIC;
614
-    else
606
+    if(optget(opts, "algorithmic-detection")->enabled)
615 607
 	options |= CL_SCAN_ALGORITHMIC;
616 608
 
617
-    if(opt_check(opt, "detect-structured")) {
609
+    if(optget(opts, "detect-structured")->enabled) {
618 610
 	options |= CL_SCAN_STRUCTURED;
619 611
 
620
-	if(opt_check(opt, "structured-ssn-format")) {
621
-	    switch(atoi(opt_arg(opt, "structured-ssn-format"))) {
612
+	if((opt = optget(opts, "structured-ssn-format"))->enabled) {
613
+	    switch(opt->numarg) {
622 614
 		case 0:
623 615
 		    options |= CL_SCAN_STRUCTURED_SSN_NORMAL;
624 616
 		    break;
... ...
@@ -636,8 +579,8 @@ int scanmanager(const struct optstruct *opt)
636 636
 	    options |= CL_SCAN_STRUCTURED_SSN_NORMAL;
637 637
 	}
638 638
 
639
-	if(opt_check(opt, "structured-ssn-count")) {
640
-	    val32 = atoi(opt_arg(opt, "structured-ssn-count"));
639
+	if((opt = optget(opts, "structured-ssn-count"))->enabled) {
640
+	    val32 = opt->numarg;
641 641
 	    if((ret = cl_engine_set(engine, CL_ENGINE_MIN_SSN_COUNT, &val32))) {
642 642
 		logg("!cli_engine_set(CL_ENGINE_MIN_SSN_COUNT) failed: %s\n", cl_strerror(ret));
643 643
 		cl_engine_free(engine);
... ...
@@ -645,8 +588,8 @@ int scanmanager(const struct optstruct *opt)
645 645
 	    }
646 646
 	}
647 647
 
648
-	if(opt_check(opt, "structured-cc-count")) {
649
-	    val32 = atoi(opt_arg(opt, "structured-cc-count"));
648
+	if((opt = optget(opts, "structured-cc-count"))->enabled) {
649
+	    val32 = opt->numarg;
650 650
 	    if((ret = cl_engine_set(engine, CL_ENGINE_MIN_CC_COUNT, &val32))) {
651 651
 		logg("!cli_engine_set(CL_ENGINE_MIN_CC_COUNT) failed: %s\n", cl_strerror(ret));
652 652
 		cl_engine_free(engine);
... ...
@@ -654,8 +597,9 @@ int scanmanager(const struct optstruct *opt)
654 654
 	    }
655 655
 	}
656 656
 
657
-    } else
657
+    } else {
658 658
 	options &= ~CL_SCAN_STRUCTURED;
659
+    }
659 660
 
660 661
 #ifdef C_LINUX
661 662
     procdev = (dev_t) 0;
... ...
@@ -664,20 +608,20 @@ int scanmanager(const struct optstruct *opt)
664 664
 #endif
665 665
 
666 666
     /* check filetype */
667
-    if(opt->filename == NULL || strlen(opt->filename) == 0) {
667
+    if(opts->filename == NULL || strlen(opts->filename) == 0) {
668 668
 
669 669
 	/* we need full path for some reasons (eg. archive handling) */
670 670
 	if(!getcwd(cwd, sizeof(cwd))) {
671 671
 	    logg("!Can't get absolute pathname of current working directory\n");
672 672
 	    ret = 57;
673 673
 	} else
674
-	    ret = scandirs(cwd, engine, opt, options, 1);
674
+	    ret = scandirs(cwd, engine, opts, options, 1);
675 675
 
676
-    } else if(!strcmp(opt->filename, "-")) { /* read data from stdin */
677
-	ret = scanstdin(engine, opt, options);
676
+    } else if(!strcmp(opts->filename, "-")) { /* read data from stdin */
677
+	ret = scanstdin(engine, opts, options);
678 678
 
679 679
     } else {
680
-	for (x = 0; (file = cli_strtok(opt->filename, x, "\t")) != NULL; x++) {
680
+	for (x = 0; (file = cli_strtok(opts->filename, x, "\t")) != NULL; x++) {
681 681
 	    if((fmodeint = fileinfo(file, 2)) == -1) {
682 682
 		logg("^Can't access file %s\n", file);
683 683
 		perror(file);
... ...
@@ -694,11 +638,11 @@ int scanmanager(const struct optstruct *opt)
694 694
 
695 695
 		switch(fmode & S_IFMT) {
696 696
 		    case S_IFREG:
697
-			ret = scanfile(file, engine, opt, options);
697
+			ret = scanfile(file, engine, opts, options);
698 698
 			break;
699 699
 
700 700
 		    case S_IFDIR:
701
-			ret = scandirs(file, engine, opt, options, 1);
701
+			ret = scandirs(file, engine, opts, options, 1);
702 702
 			break;
703 703
 
704 704
 		    default:
... ...
@@ -722,18 +666,18 @@ int scanmanager(const struct optstruct *opt)
722 722
     return ret;
723 723
 }
724 724
 
725
-static void move_infected(const char *filename, const struct optstruct *opt)
725
+static void move_infected(const char *filename, const struct optstruct *opts)
726 726
 {
727 727
 	char *movedir, *movefilename, numext[4 + 1];
728 728
 	const char *tmp;
729 729
 	struct stat ofstat, mfstat;
730 730
 	int n, len, movefilename_size;
731
-	int moveflag = opt_check(opt, "move");
731
+	int moveflag = optget(opts, "move")->enabled;
732 732
 	struct utimbuf ubuf;
733 733
 
734 734
 
735
-    if((moveflag && !(movedir = opt_arg(opt, "move"))) ||
736
-	(!moveflag && !(movedir = opt_arg(opt, "copy")))) {
735
+    if((moveflag && !(movedir = optget(opts, "move")->strarg)) ||
736
+	(!moveflag && !(movedir = optget(opts, "copy")->strarg))) {
737 737
         /* Should never reach here */
738 738
         logg("!opt_arg() returned NULL\n");
739 739
         info.notmoved++;
... ...
@@ -19,8 +19,8 @@
19 19
 #ifndef __MANAGER_H
20 20
 #define __MANAGER_H
21 21
 
22
-#include "shared/options.h"
22
+#include "shared/optparser.h"
23 23
 
24
-int scanmanager(const struct optstruct *opt);
24
+int scanmanager(const struct optstruct *opts);
25 25
 
26 26
 #endif
... ...
@@ -1,4 +1,4 @@
1
-.TH "clamscan" "1" "February 12, 2007" "ClamAV @VERSION@" "Clam AntiVirus"
1
+.TH "clamscan" "1" "December 30, 2008" "ClamAV @VERSION@" "Clam AntiVirus"
2 2
 .SH "NAME"
3 3
 .LP 
4 4
 clamscan \- scan files and directories for viruses
... ...
@@ -10,7 +10,7 @@ clamscan [options] [file/directory/\-]
10 10
 clamscan is a command line anti\-virus scanner.
11 11
 .SH "OPTIONS"
12 12
 .LP 
13
-
13
+Most of the options are simple switches which enable or disable some features. Options marked with [=yes/no(*)] can be optionally followed by =yes/=no; if they get called without the boolean argument the scanner will assume 'yes'. The asterisk marks the default internal setting for a given option.
14 14
 .TP 
15 15
 \fB\-h, \-\-help\fR
16 16
 Print help information and exit.
... ...
@@ -60,7 +60,7 @@ Only scan file/directory names containing PATT. It may be used multiple times.
60 60
 \fB\-i, \-\-infected\fR
61 61
 Only print infected files.
62 62
 .TP 
63
-\fB\-\-remove\fR
63
+\fB\-\-remove[=yes/no(*)]\fR
64 64
 Remove infected files. \fBBe careful.\fR
65 65
 .TP 
66 66
 \fB\-\-move=DIRECTORY\fR
... ...
@@ -69,7 +69,7 @@ Move infected files into DIRECTORY. Directory must be writable for the '@CLAMAVU
69 69
 \fB\-\-copy=DIRECTORY\fR
70 70
 Copy infected files into DIRECTORY. Directory must be writable for the '@CLAMAVUSER@' user or unprivileged user running clamscan.
71 71
 .TP 
72
-\fB\-\-detect\-pua\fR
72
+\fB\-\-detect\-pua[=yes/no(*)]\fR
73 73
 Detect Possibly Unwanted Applications.
74 74
 .TP 
75 75
 \fB\-\-exclude\-pua=CATEGORY\fR
... ...
@@ -78,8 +78,8 @@ Exclude a specific PUA category. This option can be used multiple times. See htt
78 78
 \fB\-\-include\-pua=CATEGORY\fR
79 79
 Only include a specific PUA category. This option can be used multiple times. See http://www.clamav.net/support/pua for the complete list of PUA
80 80
 .TP 
81
-\fB\-\-detect\-structured\fR
82
-Enable the DLP (Data Loss Prevention) module which provides detection of SSN and Credit Card numbers.
81
+\fB\-\-detect\-structured[=yes/no(*)]\fR
82
+Use the DLP (Data Loss Prevention) module to detect SSN and Credit Card numbers inside documents/text files.
83 83
 .TP 
84 84
 \fB\-\-structured\-ssn\-format=X\fR
85 85
 X=0: search for valid SSNs formatted as xxx-yy-zzzz (normal); X=1: search for valid SSNs formatted as xxxyyzzzz (stripped); X=2: search for both formats. Default is 0.
... ...
@@ -90,52 +90,52 @@ This option sets the lowest number of Social Security Numbers found in a file to
90 90
 \fB\-\-structured\-cc\-count=#n\fR
91 91
 This option sets the lowest number of Credit Card numbers found in a file to generate a detect (default: 3).
92 92
 .TP 
93
-\fB\-\-no\-mail\fR
94
-Disable scanning of mail files.
93
+\fB\-\-scan\-mail[=yes(*)/no]\fR
94
+Scan mail files.
95 95
 .TP 
96
-\fB\-\-no\-phishing\-sigs\fR
97
-Disable signature-based phishing detection.
96
+\fB\-\-phishing\-sigs[=yes(*)/no]\fR
97
+Use the signature-based phishing detection.
98 98
 .TP 
99
-\fB\-\-no\-phishing\-scan\-urls\fR
100
-Disable url-based heuristic phishing detection. This disables Phishing.Heuristics.Email.*
99
+\fB\-\-phishing\-scan\-urls[=yes(*)/no]\fR
100
+Use the url-based heuristic phishing detection (Phishing.Heuristics.Email.*)
101 101
 .TP
102
-\fB\-\-heuristic\-scan\-precedence\fR
102
+\fB\-\-heuristic\-scan\-precedence[=yes/no(*)]\fR
103 103
 Allow heuristic match to take precedence. When enabled, if a heuristic scan (such as phishingScan) detects a possible virus/phish it will stop scan immediately. Recommended, saves CPU scan-time. When disabled, virus/phish detected by heuristic scans will be reported only at the end of a scan. If an archive contains both a heuristically detected  virus/phish, and a real malware, the real malware will be reported Keep this disabled if you intend to handle "*.Heuristics.*" viruses  differently from "real" malware. If a non-heuristically-detected virus (signature-based) is found first,  the scan is interrupted immediately, regardless of this config option.
104 104
 .TP
105
-\fB\-\-phishing\-ssl\fR
106
-Always block SSL mismatches in URLs (might lead to false positives!).
105
+\fB\-\-phishing\-ssl[=yes/no(*)]\fR
106
+Block SSL mismatches in URLs (might lead to false positives!).
107 107
 .TP
108
-\fB\-\-phishing\-cloak\fR
109
-Always block cloaked URLs (might lead to some false positives).
108
+\fB\-\-phishing\-cloak[=yes/no(*)]\fR
109
+Block cloaked URLs (might lead to some false positives).
110 110
 .TP
111
-\fB\-\-no\-algorithmic\fR
112
-In some cases (eg. complex malware, exploits in graphic files, and others), ClamAV uses special algorithms to provide accurate detection. This option disables the algorithmic detection.
111
+\fB\-\-algorithmic\-detection[=yes(*)/no]\fR
112
+In some cases (eg. complex malware, exploits in graphic files, and others), ClamAV uses special algorithms to provide accurate detection. This option can be used to control the algorithmic detection.
113 113
 .TP 
114
-\fB\-\-no\-pe\fR
115
-PE stands for Portable Executable \- it's an executable file format used in all 32\-bit versions of Windows operating systems. By default ClamAV performs deeper analysis of executable files and attempts to decompress popular executable packers such as UPX, Petite, and FSG. This option \fBdisables\fR PE support and should be used with care!
114
+\fB\-\-scan\-pe[=yes(*)/no]\fR
115
+PE stands for Portable Executable \- it's an executable file format used in all 32\-bit versions of Windows operating systems. By default ClamAV performs deeper analysis of executable files and attempts to decompress popular executable packers such as UPX, Petite, and FSG.
116 116
 .TP 
117
-\fB\-\-no\-elf\fR
118
-Executable and Linking Format is a standard format for UN*X executables. This option \fBdisables\fR ELF support.
117
+\fB\-\-scan\-elf[=yes(*)/no]\fR
118
+Executable and Linking Format is a standard format for UN*X executables. This option controls the ELF support.
119 119
 .TP 
120
-\fB\-\-no\-ole2\fR
121
-Disable support for Microsoft Office documents and .msi files.
120
+\fB\-\-scan\-ole2[=yes(*)/no]\fR
121
+Scan Microsoft Office documents and .msi files.
122 122
 .TP 
123
-\fB\-\-no\-pdf\fR
124
-Disable scanning within PDF files.
123
+\fB\-\-scan\-pdf[=yes(*)/no]\fR
124
+Scan within PDF files.
125 125
 .TP 
126
-\fB\-\-no\-html\fR
127
-Disable support for HTML detection and normalisation.
126
+\fB\-\-scan\-html[=yes(*)/no]\fR
127
+Detect, normalize/decrypt and scan HTML files and embedded scripts.
128 128
 .TP 
129
-\fB\-\-no\-archive\fR
130
-Disable archive support built in libclamav.
129
+\fB\-\-scan\-archive[=yes(*)/no]\fR
130
+Scan archives supported by libclamav.
131 131
 .TP 
132
-\fB\-\-detect\-broken\fR
132
+\fB\-\-detect\-broken[=yes/no(*)]\fR
133 133
 Mark broken executables as viruses (Broken.Executable).
134 134
 .TP 
135
-\fB\-\-block\-encrypted\fR
135
+\fB\-\-block\-encrypted[=yes/no(*)]\fR
136 136
 Mark encrypted archives as viruses (Encrypted.Zip, Encrypted.RAR).
137 137
 .TP 
138
-\fB\-\-mail\-follow\-urls\fR
138
+\fB\-\-mail\-follow\-urls[=yes/no(*)]\fR
139 139
 If an email contains URLs ClamAV can download and scan them. \fBWARNING: This option may open your system to a DoS attack. Never use it on loaded servers.\fR
140 140
 .TP 
141 141
 \fB\-\-max\-files=#n\fR
... ...
@@ -20,7 +20,7 @@
20 20
 
21 21
 /*
22 22
  * TODO:
23
- * - freshclam, clamscan, clamdscan, clamconf, milter
23
+ * - clamdscan, clamconf, milter
24 24
  * - clamconf: generation/verification/updating of config files and man page entries
25 25
  * - automatically generate --help pages (use the first line from the description)
26 26
  */
... ...
@@ -44,7 +44,7 @@
44 44
 
45 45
 #include "getopt.h"
46 46
 
47
-#define MAXCMDOPTS  64
47
+#define MAXCMDOPTS  80
48 48
 #define MAX(a,b) (a > b ? a : b)
49 49
 
50 50
 #define MATCH_NUMBER "^[0-9]+$"
... ...
@@ -67,21 +67,66 @@ static const struct clam_option {
67 67
     /* name,   longopt, sopt, argtype, regex, num, str, mul, owner, description, suggested */
68 68
 
69 69
     /* cmdline only */
70
-    { NULL, "help", 'h', OPT_BOOL, NULL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM, "", "" },
71
-    { NULL, "config-file", 'c', OPT_STRING, NULL, 0, CONFDIR"/clamd.conf", 0, OPT_CLAMD, "", "" },
70
+    { NULL, "help", 'h', OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_CLAMSCAN | OPT_CLAMDSCAN, "", "" },
71
+    { NULL, "config-file", 'c', OPT_STRING, NULL, 0, CONFDIR"/clamd.conf", 0, OPT_CLAMD | OPT_CLAMDSCAN, "", "" },
72 72
     { NULL, "config-file", 0, OPT_STRING, NULL, 0, CONFDIR"/freshclam.conf", 0, OPT_FRESHCLAM, "", "" },
73
-    { NULL, "version", 'V', OPT_BOOL, NULL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM, "", "" },
74
-    { NULL, "debug", 0, OPT_BOOL, NULL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM, "", "" },
75
-    { NULL, "verbose", 'v', OPT_BOOL, NULL, 0, NULL, 0, OPT_FRESHCLAM, "", "" },
76
-    { NULL, "quiet", 0, OPT_BOOL, NULL, 0, NULL, 0, OPT_FRESHCLAM, "", "" },
77
-    { NULL, "no-warnings", 0, OPT_BOOL, NULL, 0, NULL, 0, OPT_FRESHCLAM, "", "" },
78
-    { NULL, "stdout", 0, OPT_BOOL, NULL, 0, NULL, 0, OPT_FRESHCLAM, "", "" },
79
-    { NULL, "daemon", 'd', OPT_BOOL, NULL, 0, NULL, 0, OPT_FRESHCLAM, "", "" },
80
-    { NULL, "no-dns", 0, OPT_BOOL, NULL, 0, NULL, 0, OPT_FRESHCLAM, "", "" },
73
+    { NULL, "version", 'V', OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_CLAMSCAN | OPT_CLAMDSCAN, "", "" },
74
+    { NULL, "debug", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_CLAMSCAN, "", "" },
75
+    { NULL, "verbose", 'v', OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM | OPT_CLAMSCAN | OPT_CLAMDSCAN, "", "" },
76
+    { NULL, "quiet", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM | OPT_CLAMSCAN | OPT_CLAMDSCAN, "", "" },
77
+    { NULL, "leave-temps", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "", "" },
78
+    { NULL, "no-warnings", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM, "", "" },
79
+    { NULL, "stdout", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM | OPT_CLAMSCAN | OPT_CLAMDSCAN, "", "" },
80
+    { NULL, "daemon", 'd', OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM, "", "" },
81
+    { NULL, "no-dns", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM, "", "" },
82
+    { NULL, "list-mirrors", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM, "", "" },
83
+    { NULL, "submit-stats", 0, OPT_STRING, NULL, 0, CONFDIR"/clamd.conf", 0, OPT_FRESHCLAM, "", "" }, /* Don't merge this one with SubmitDetectionStats */
84
+    { NULL, "reload", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMDSCAN, "", "" },
85
+    { NULL, "multiscan", 'm', OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMDSCAN, "", "" },
86
+    { NULL, "database", 'd', OPT_STRING, NULL, -1, DATADIR, 0, OPT_CLAMSCAN, "", "" }, /* merge it with DatabaseDirectory (and fix conflict with --datadir */
87
+    { NULL, "recursive", 'r', OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "", "" },
88
+    { NULL, "bell", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "", "" },
89
+    { NULL, "no-summary", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "", "" },
90
+    { NULL, "infected", 'i', OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "", "" },
91
+    { NULL, "log", 'l', OPT_STRING, NULL, -1, NULL, 0, OPT_CLAMSCAN, "", "" },
92
+    { NULL, "move", 0, OPT_STRING, NULL, -1, NULL, 0, OPT_CLAMSCAN, "", "" },
93
+    { NULL, "copy", 0, OPT_STRING, NULL, -1, NULL, 0, OPT_CLAMSCAN, "", "" },
94
+    { NULL, "remove", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "", "" },
95
+    { NULL, "exclude", 0, OPT_STRING, NULL, -1, NULL, 1, OPT_CLAMSCAN, "", "" },
96
+    { NULL, "exclude-dir", 0, OPT_STRING, NULL, -1, NULL, 1, OPT_CLAMSCAN, "", "" },
97
+    { NULL, "include", 0, OPT_STRING, NULL, -1, NULL, 1, OPT_CLAMSCAN, "", "" },
98
+    { NULL, "include-dir", 0, OPT_STRING, NULL, -1, NULL, 1, OPT_CLAMSCAN, "", "" },
99
+    { NULL, "structured-ssn-format", 0, OPT_NUMBER, MATCH_NUMBER, 0, NULL, 1, OPT_CLAMSCAN, "", "" },
100
+
101
+    /* cmdline only - deprecated */
81 102
     { NULL, "http-proxy", 0, OPT_STRING, NULL, 0, NULL, 0, OPT_FRESHCLAM | OPT_DEPRECATED, "", "" },
82 103
     { NULL, "proxy-user", 0, OPT_STRING, NULL, 0, NULL, 0, OPT_FRESHCLAM | OPT_DEPRECATED, "", "" },
83
-    { NULL, "list-mirrors", 0, OPT_BOOL, NULL, 0, NULL, 0, OPT_FRESHCLAM, "", "" },
84
-    { NULL, "submit-stats", 0, OPT_STRING, NULL, 0, CONFDIR"/clamd.conf", 0, OPT_FRESHCLAM, "", "" }, /* Don't merge this one with SubmitDetectionStats */
104
+    { NULL, "force", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
105
+    { NULL, "disable-summary", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
106
+    { NULL, "disable-archive", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
107
+    { NULL, "no-archive", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
108
+    { NULL, "no-pe", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
109
+    { NULL, "no-elf", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
110
+    { NULL, "no-ole2", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
111
+    { NULL, "no-pdf", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
112
+    { NULL, "no-html", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
113
+    { NULL, "no-mail", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
114
+    { NULL, "no-phishing-sigs", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
115
+    { NULL, "no-phishing-scan-urls", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
116
+    { NULL, "no-algorithmic", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
117
+    { NULL, "no-phishing-restrictedscan", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
118
+    { NULL, "max-ratio", 0, OPT_NUMBER, MATCH_NUMBER, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
119
+    { NULL, "max-space", 0, OPT_SIZE, MATCH_SIZE, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
120
+    { NULL, "block-max", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
121
+    { NULL, "unzip", 0, OPT_STRING, NULL, -1, "foo", 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
122
+    { NULL, "unrar", 0, OPT_STRING, NULL, -1, "foo", 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
123
+    { NULL, "arj", 0, OPT_STRING, NULL, -1, "foo", 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
124
+    { NULL, "unzoo", 0, OPT_STRING, NULL, -1, "foo", 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
125
+    { NULL, "lha", 0, OPT_STRING, NULL, -1, "foo", 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
126
+    { NULL, "jar", 0, OPT_STRING, NULL, -1, "foo", 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
127
+    { NULL, "tar", 0, OPT_STRING, NULL, -1, "foo", 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
128
+    { NULL, "tgz", 0, OPT_STRING, NULL, -1, "foo", 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
129
+    { NULL, "deb", 0, OPT_STRING, NULL, -1, "foo", 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
85 130
 
86 131
     /* config file/cmdline options */
87 132
     { "LogFile", "log", 'l', OPT_STRING, NULL, -1, NULL, 0, OPT_CLAMD | OPT_MILTER, "Save all reports to a log file.", "/tmp/clamav.log" },
... ...
@@ -102,7 +147,7 @@ static const struct clam_option {
102 102
 
103 103
     { "PidFile", "pid", 'p', OPT_STRING, NULL, -1, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER, "Save the process ID to a file.", "/var/run/clamd.pid" },
104 104
 
105
-    { "TemporaryDirectory", NULL, 0, OPT_STRING, NULL, -1, NULL, 0, OPT_CLAMD | OPT_MILTER, "This option allows you to change the default temporary directory.", "/tmp" },
105
+    { "TemporaryDirectory", "tempdir", 0, OPT_STRING, NULL, -1, NULL, 0, OPT_CLAMD | OPT_MILTER | OPT_CLAMSCAN, "This option allows you to change the default temporary directory.", "/tmp" },
106 106
 
107 107
     { "DatabaseDirectory", "datadir", 0, OPT_STRING, NULL, -1, DATADIR, 0, OPT_CLAMD | OPT_FRESHCLAM, "This option allows you to change the default database directory.\nIf you enable it, please make sure it points to the same directory in\nboth clamd and freshclam.", "/var/lib/clamav" },
108 108
 
... ...
@@ -131,7 +176,7 @@ static const struct clam_option {
131 131
 
132 132
     { "ExcludePath", NULL, 0, OPT_STRING, NULL, -1, NULL, 1, OPT_CLAMD, "Don't scan files/directories whose names match the provided\nregular expression. This option can be specified multiple times.", "^/proc/" },
133 133
 
134
-    { "MaxDirectoryRecursion", NULL, 0, OPT_NUMBER, MATCH_NUMBER, 15, NULL, 0, OPT_CLAMD, "Maximum depth the directories are scanned at.", "15" },
134
+    { "MaxDirectoryRecursion", "max-dir-recursion", 0, OPT_NUMBER, MATCH_NUMBER, 15, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Maximum depth the directories are scanned at.", "15" },
135 135
 
136 136
     { "FollowDirectorySymlinks", NULL, 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Follow directory symlinks.", "no" },
137 137
 
... ...
@@ -155,63 +200,63 @@ static const struct clam_option {
155 155
 
156 156
     /* Scan options */
157 157
 
158
-    { "DetectPUA", NULL, 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Detect Potentially Unwanted Applications.", "yes" },
158
+    { "DetectPUA", "detect-pua", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Detect Potentially Unwanted Applications.", "yes" },
159 159
 
160
-    { "ExcludePUA", NULL, 0, OPT_STRING, NULL, -1, NULL, 1, OPT_CLAMD, "Exclude a specific PUA category. This directive can be used multiple times.\nSee http://www.clamav.net/support/pua for the complete list of PUA\ncategories.", "NetTool" },
160
+    { "ExcludePUA", "exclude-pua", 0, OPT_STRING, NULL, -1, NULL, 1, OPT_CLAMD | OPT_CLAMSCAN, "Exclude a specific PUA category. This directive can be used multiple times.\nSee http://www.clamav.net/support/pua for the complete list of PUA\ncategories.", "NetTool" },
161 161
 
162
-    { "IncludePUA", NULL, 0, OPT_STRING, NULL, -1, NULL, 1, OPT_CLAMD, "Only include a specific PUA category. This directive can be used multiple\ntimes.", "Spy" },
162
+    { "IncludePUA", "include-pua", 0, OPT_STRING, NULL, -1, NULL, 1, OPT_CLAMD | OPT_CLAMSCAN, "Only include a specific PUA category. This directive can be used multiple\ntimes.", "Spy" },
163 163
 
164
-    { "AlgorithmicDetection", NULL, 0, OPT_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD, "In some cases (eg. complex malware, exploits in graphic files, and others),\nClamAV uses special algorithms to provide accurate detection. This option\ncontrols the algorithmic detection.", "yes" },
164
+    { "AlgorithmicDetection", "algorithmic-detection", 0, OPT_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "In some cases (eg. complex malware, exploits in graphic files, and others),\nClamAV uses special algorithms to provide accurate detection. This option\ncontrols the algorithmic detection.", "yes" },
165 165
 
166
-    { "ScanPE", NULL, 0, OPT_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD, "PE stands for Portable Executable - it's an executable file format used\nin all 32- and 64-bit versions of Windows operating systems. This option\nallows ClamAV to perform a deeper analysis of executable files and it's also\nrequired for decompression of popular executable packers such as UPX or FSG.", "yes" },
166
+    { "ScanPE", "scan-pe", 0, OPT_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "PE stands for Portable Executable - it's an executable file format used\nin all 32- and 64-bit versions of Windows operating systems. This option\nallows ClamAV to perform a deeper analysis of executable files and it's also\nrequired for decompression of popular executable packers such as UPX or FSG.", "yes" },
167 167
 
168
-    { "ScanELF", NULL, 0, OPT_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD, "Executable and Linking Format is a standard format for UN*X executables.\nThis option allows you to control the scanning of ELF files.", "yes" },
168
+    { "ScanELF", "scan-elf", 0, OPT_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Executable and Linking Format is a standard format for UN*X executables.\nThis option allows you to control the scanning of ELF files.", "yes" },
169 169
 
170
-    { "DetectBrokenExecutables", NULL, 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "With this option enabled clamav will try to detect broken executables\n(both PE and ELF) and mark them as Broken.Executable.", "yes" },
170
+    { "DetectBrokenExecutables", "detect-broken", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "With this option enabled clamav will try to detect broken executables\n(both PE and ELF) and mark them as Broken.Executable.", "yes" },
171 171
 
172
-    { "ScanMail", NULL, 0, OPT_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD, "Enable the built in email scanner.", "yes" },
172
+    { "ScanMail", "scan-mail", 0, OPT_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Enable the built in email scanner.", "yes" },
173 173
 
174
-    { "MailFollowURLs", NULL, 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "If an email contains URLs ClamAV can download and scan them.\nWARNING: This option may open your system to a DoS attack. Please don't use\nthis feature on highly loaded servers.", "no" },
174
+    { "MailFollowURLs", "mail-follow-urls", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "If an email contains URLs ClamAV can download and scan them.\nWARNING: This option may open your system to a DoS attack. Please don't use\nthis feature on highly loaded servers.", "no" },
175 175
 
176 176
     { "ScanPartialMessages", NULL, 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Scan RFC1341 messages split over many emails. You will need to\nperiodically clean up $TemporaryDirectory/clamav-partial directory.\nWARNING: This option may open your system to a DoS attack. Please don't use\nthis feature on highly loaded servers.", "no" },
177 177
 
178
-    { "PhishingSignatures", NULL, 0, OPT_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD, "With this option enabled ClamAV will try to detect phishing attempts by using\nsignatures.", "yes" },
178
+    { "PhishingSignatures", "phishing-sigs", 0, OPT_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "With this option enabled ClamAV will try to detect phishing attempts by using\nsignatures.", "yes" },
179 179
 
180
-    { "PhishingScanURLs", NULL, 0, OPT_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD, "Scan URLs found in mails for phishing attempts using heuristics.", "yes" },
180
+    { "PhishingScanURLs", "phishing-scan-urls", 0, OPT_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Scan URLs found in mails for phishing attempts using heuristics.", "yes" },
181 181
 
182
-    { "PhishingAlwaysBlockCloak", NULL, 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Always block cloaked URLs, even if they're not in the database.\nThis feature can lead to false positives.", "no" },
182
+    { "PhishingAlwaysBlockCloak", "phishing-cloak", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Always block cloaked URLs, even if they're not in the database.\nThis feature can lead to false positives.", "no" },
183 183
 
184
-    { "PhishingAlwaysBlockSSLMismatch", NULL, 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Always block SSL mismatches in URLs, even if they're not in the database.\nThis feature can lead to false positives.", "" },
184
+    { "PhishingAlwaysBlockSSLMismatch", "phishing-ssl", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Always block SSL mismatches in URLs, even if they're not in the database.\nThis feature can lead to false positives.", "" },
185 185
 
186
-    { "HeuristicScanPrecedence", NULL, 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Allow heuristic match to take precedence.\nWhen enabled, if a heuristic scan (such as phishingScan) detects\na possible virus/phish it will stop scan immediately. Recommended, saves CPU\nscan-time.\nWhen disabled, virus/phish detected by heuristic scans will be reported only\nat the end of a scan. If an archive contains both a heuristically detected\nvirus/phish, and a real malware, the real malware will be reported.\nKeep this disabled if you intend to handle \"*.Heuristics.*\" viruses\ndifferently from \"real\" malware.\nIf a non-heuristically-detected virus (signature-based) is found first,\nthe scan is interrupted immediately, regardless of this config option.", "yes" },
186
+    { "HeuristicScanPrecedence", "heuristic-scan-precedence", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Allow heuristic match to take precedence.\nWhen enabled, if a heuristic scan (such as phishingScan) detects\na possible virus/phish it will stop scan immediately. Recommended, saves CPU\nscan-time.\nWhen disabled, virus/phish detected by heuristic scans will be reported only\nat the end of a scan. If an archive contains both a heuristically detected\nvirus/phish, and a real malware, the real malware will be reported.\nKeep this disabled if you intend to handle \"*.Heuristics.*\" viruses\ndifferently from \"real\" malware.\nIf a non-heuristically-detected virus (signature-based) is found first,\nthe scan is interrupted immediately, regardless of this config option.", "yes" },
187 187
 
188
-    { "StructuredDataDetection", NULL, 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Enable the Data Loss Prevention module.", "no" },
188
+    { "StructuredDataDetection", "detect-structured", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Enable the Data Loss Prevention module.", "no" },
189 189
 
190
-    { "StructuredMinCreditCardCount", NULL, 0, OPT_NUMBER, MATCH_NUMBER, 3, NULL, 0, OPT_CLAMD, "This option sets the lowest number of Credit Card numbers found in a file\nto generate a detect.", "5" },
190
+    { "StructuredMinCreditCardCount", "structured-cc-count", 0, OPT_NUMBER, MATCH_NUMBER, 3, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the lowest number of Credit Card numbers found in a file\nto generate a detect.", "5" },
191 191
 
192
-    { "StructuredMinSSNCount", NULL, 0, OPT_NUMBER, MATCH_NUMBER, 3, NULL, 0, OPT_CLAMD, "This option sets the lowest number of Social Security Numbers found\nin a file to generate a detect.", "5" },
192
+    { "StructuredMinSSNCount", "structured-ssn-count", 0, OPT_NUMBER, MATCH_NUMBER, 3, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the lowest number of Social Security Numbers found\nin a file to generate a detect.", "5" },
193 193
 
194 194
     { "StructuredSSNFormatNormal", NULL, 0, OPT_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD, "With this option enabled the DLP module will search for valid\nSSNs formatted as xxx-yy-zzzz.", "yes" },
195 195
 
196 196
     { "StructuredSSNFormatStripped", NULL, 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "With this option enabled the DLP module will search for valid\nSSNs formatted as xxxyyzzzz", "no" },
197 197
 
198
-    { "ScanHTML", NULL, 0, OPT_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD, "Perform HTML/JavaScript/ScriptEncoder normalisation and decryption.", "yes" },
198
+    { "ScanHTML", "scan-html", 0, OPT_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Perform HTML/JavaScript/ScriptEncoder normalisation and decryption.", "yes" },
199 199
 
200
-    { "ScanOLE2", NULL, 0, OPT_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD, "This option enables scanning of OLE2 files, such as Microsoft Office\ndocuments and .msi files.", "yes" },
200
+    { "ScanOLE2", "scan-ole2", 0, OPT_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option enables scanning of OLE2 files, such as Microsoft Office\ndocuments and .msi files.", "yes" },
201 201
 
202
-    { "ScanPDF", NULL, 0, OPT_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD, "This option enables scanning within PDF files.", "yes" },
202
+    { "ScanPDF", "scan-pdf", 0, OPT_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option enables scanning within PDF files.", "yes" },
203 203
 
204
-    { "ScanArchive", NULL, 0, OPT_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD, "Scan within archives and compressed files.", "yes" },
204
+    { "ScanArchive", "scan-archive", 0, OPT_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Scan within archives and compressed files.", "yes" },
205 205
 
206
-    { "ArchiveBlockEncrypted", NULL, 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Mark encrypted archives as viruses (Encrypted.Zip, Encrypted.RAR).", "no" },
206
+    { "ArchiveBlockEncrypted", "block-encrypted", 0, OPT_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Mark encrypted archives as viruses (Encrypted.Zip, Encrypted.RAR).", "no" },
207 207
 
208
-    { "MaxScanSize", NULL, 0, OPT_SIZE, MATCH_SIZE, -1, NULL, 0, OPT_CLAMD, "This option sets the maximum amount of data to be scanned for each input file.\nArchives and other containers are recursively extracted and scanned up to this\nvalue.\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result in severe damage.", "100M" },
208
+    { "MaxScanSize", "max-scansize", 0, OPT_SIZE, MATCH_SIZE, -1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum amount of data to be scanned for each input file.\nArchives and other containers are recursively extracted and scanned up to this\nvalue.\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result in severe damage.", "100M" },
209 209
 
210
-    { "MaxFileSize", NULL, 0, OPT_SIZE, MATCH_SIZE, -1, NULL, 0, OPT_CLAMD | OPT_MILTER, "Files larger than this limit won't be scanned. Affects the input file itself\nas well as files contained inside it (when the input file is an archive, a\ndocument or some other kind of container).\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result in severe damage to the system.", "25M" },
210
+    { "MaxFileSize", "max-filesize", 0, OPT_SIZE, MATCH_SIZE, -1, NULL, 0, OPT_CLAMD | OPT_MILTER | OPT_CLAMSCAN, "Files larger than this limit won't be scanned. Affects the input file itself\nas well as files contained inside it (when the input file is an archive, a\ndocument or some other kind of container).\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result in severe damage to the system.", "25M" },
211 211
 
212
-    { "MaxRecursion", NULL, 0, OPT_NUMBER, MATCH_NUMBER, -1, NULL, 0, OPT_CLAMD, "Nested archives are scanned recursively, e.g. if a Zip archive contains a RAR\nfile, all files within it will also be scanned. This option specifies how\ndeeply the process should be continued.\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result in severe damage to the system.", "16" },
212
+    { "MaxRecursion", "max-recursion", 0, OPT_NUMBER, MATCH_NUMBER, -1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Nested archives are scanned recursively, e.g. if a Zip archive contains a RAR\nfile, all files within it will also be scanned. This option specifies how\ndeeply the process should be continued.\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result in severe damage to the system.", "16" },
213 213
 
214
-    { "MaxFiles", NULL, 0, OPT_NUMBER, MATCH_NUMBER, -1, NULL, 0, OPT_CLAMD, "Number of files to be scanned within an archive, a document, or any other\ncontainer file.\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result in severe damage to the system.", "10000" },
214
+    { "MaxFiles", "max-files", 0, OPT_NUMBER, MATCH_NUMBER, -1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Number of files to be scanned within an archive, a document, or any other\ncontainer file.\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result in severe damage to the system.", "10000" },
215 215
 
216 216
     { "ClamukoScanOnAccess", NULL, 0, OPT_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD, "This option enables Clamuko. Dazuko needs to be already configured and\nrunning.", "no" },
217 217
 
... ...
@@ -228,9 +273,9 @@ static const struct clam_option {
228 228
     { "ClamukoMaxFileSize", NULL, 0, OPT_SIZE, MATCH_SIZE, 5242880, NULL, 0, OPT_CLAMD, "Files larger than this value will not be scanned.", "5M" },
229 229
 
230 230
     /* FIXME: mark these as private and don't output into clamd.conf/man */
231
-    { "DevACOnly", NULL, 0, OPT_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD, "", "" },
231
+    { "DevACOnly", "dev-ac-only", 0, OPT_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "", "" },
232 232
 
233
-    { "DevACDepth", NULL, 0, OPT_NUMBER, MATCH_NUMBER, -1, NULL, 0, OPT_CLAMD, "", "" },
233
+    { "DevACDepth", "dev-ac-depth", 0, OPT_NUMBER, MATCH_NUMBER, -1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "", "" },
234 234
 
235 235
     /* Freshclam-only entries */
236 236
 
... ...
@@ -291,8 +336,8 @@ static const struct clam_option {
291 291
     { "ArchiveMaxRecursion", NULL, 0, OPT_NUMBER, NULL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
292 292
     { "ArchiveMaxFiles", NULL, 0, OPT_NUMBER, NULL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
293 293
     { "ArchiveMaxCompressionRatio", NULL, 0, OPT_NUMBER, NULL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
294
-    { "ArchiveBlockMax", NULL, 0, OPT_BOOL, NULL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
295
-    { "ArchiveLimitMemoryUsage", NULL, 0, OPT_BOOL, NULL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
294
+    { "ArchiveBlockMax", NULL, 0, OPT_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
295
+    { "ArchiveLimitMemoryUsage", NULL, 0, OPT_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
296 296
 
297 297
     /* Milter specific options */
298 298
 /*
... ...
@@ -427,6 +472,7 @@ static int optadd(struct optstruct **opts, const char *name, const char *cmd, co
427 427
     newnode->active = 0;
428 428
     newnode->multiple = multiple;
429 429
     newnode->idx = idx;
430
+    newnode->filename = NULL;
430 431
 
431 432
     newnode->next = *opts;
432 433
     *opts = newnode;
... ...
@@ -500,6 +546,9 @@ void optfree(struct optstruct *opts)
500 500
 {
501 501
     	struct optstruct *h, *a;
502 502
 
503
+    if(opts && opts->filename)
504
+	free(opts->filename);
505
+
503 506
     while(opts) {
504 507
 	a = opts->nextarg;
505 508
 	while(a) {
... ...
@@ -828,6 +877,28 @@ struct optstruct *optparse(const char *cfgfile, int argc, char * const *argv, in
828 828
 	return NULL;
829 829
     }
830 830
 
831
+    if(!cfgfile && (optind < argc)) {
832
+        lc = 0;
833
+
834
+	/* count length of non-option arguments */
835
+	for(i = optind; i < argc; i++)
836
+	    lc += strlen(argv[i]);
837
+
838
+	lc += argc - optind + 1;
839
+	opts->filename = (char *) calloc(lc, sizeof(char));
840
+	if(!opts->filename) {
841
+	    fprintf(stderr, "ERROR: optparse: calloc failed\n");
842
+	    optfree(opt);
843
+	    return NULL;
844
+	}
845
+
846
+        for(i = optind; i < argc; i++) {
847
+	    strncat(opts->filename, argv[i], strlen(argv[i]));
848
+	    if(i != argc - 1)
849
+		strncat(opts->filename, "\t", 1);
850
+	}
851
+    }
852
+
831 853
     /* optprint(opts); */
832 854
 
833 855
     return opts;
... ...
@@ -30,7 +30,9 @@
30 30
 #define OPT_CLAMD	1
31 31
 #define OPT_FRESHCLAM	2
32 32
 #define OPT_MILTER	4
33
-#define OPT_DEPRECATED	8
33
+#define OPT_CLAMSCAN	8
34
+#define OPT_CLAMDSCAN	16
35
+#define OPT_DEPRECATED	32
34 36
 
35 37
 struct optstruct {
36 38
     char *name;
... ...
@@ -43,6 +45,8 @@ struct optstruct {
43 43
     int idx;
44 44
     struct optstruct *nextarg;
45 45
     struct optstruct *next;
46
+
47
+    char *filename; /* cmdline */
46 48
 };
47 49
 
48 50
 const struct optstruct *optget(const struct optstruct *opts, const char *name);