~ubuntu-branches/debian/sid/clamav/sid

« back to all changes in this revision

Viewing changes to .pc/0006-Add-upstream-systemd-support-for-clamav-daemon-and-c.patch/shared/optparser.c

  • Committer: Package Import Robot
  • Author(s): Scott Kitterman, Sebastian Andrzej Siewior, Andreas Cadhalpun, Scott Kitterman, Javier Fernández-Sanguino
  • Date: 2015-01-28 00:25:13 UTC
  • mfrom: (1.3.15)
  • Revision ID: package-import@ubuntu.com-20150128002513-4apvvjyr1213db8x
Tags: 0.98.6+dfsg-1
[ Sebastian Andrzej Siewior ]
* update "fix-ssize_t-size_t-off_t-printf-modifier", include of misc.h was
  missing but was pulled in via the systemd patch.
* Don't leak return codes from libmspack to clamav API. (Closes: #774686).

[ Andreas Cadhalpun ]
* Add patch to avoid emitting incremental progress messages when not
  outputting to a terminal. (Closes: #767350)
* Update lintian-overrides for unused-file-paragraph-in-dep5-copyright.
* clamav-base.postinst: always chown /var/log/clamav and /var/lib/clamav
  to clamav:clamav, not only on fresh installations. (Closes: #775400)
* Adapt the clamav-daemon and clamav-freshclam logrotate scripts,
  so that they correctly work under systemd.
* Move the PidFile variable from the clamd/freshclam configuration files
  to the init scripts. This makes the init scripts more robust against
  misconfiguration and avoids error messages with systemd. (Closes: #767353)
* debian/copyright: drop files from Files-Excluded only present in github
  tarballs
* Drop Workaround-a-bug-in-libc-on-Hurd.patch, because hurd got fixed.
  (see #752237)
* debian/rules: Remove useless --with-system-tommath --without-included-ltdl
  configure options.

[ Scott Kitterman ]
* Stop stripping llvm when repacking the tarball as the system llvm on some
  releases is too old to use
* New upstream bugfix release
  - Library shared object revisions.
  - Includes a patch from Sebastian Andrzej Siewior making ClamAV pid files
    compatible with systemd.
  - Fix a heap out of bounds condition with crafted Yoda's crypter files.
    This issue was discovered by Felix Groebert of the Google Security Team.
  - Fix a heap out of bounds condition with crafted mew packer files. This
    issue was discovered by Felix Groebert of the Google Security Team.
  - Fix a heap out of bounds condition with crafted upx packer files. This
    issue was discovered by Kevin Szkudlapski of Quarkslab.
  - Fix a heap out of bounds condition with crafted upack packer files. This
    issue was discovered by Sebastian Andrzej Siewior. CVE-2014-9328.
  - Compensate a crash due to incorrect compiler optimization when handling
    crafted petite packer files. This issue was discovered by Sebastian
    Andrzej Siewior.
* Update lintian override for embedded zlib to match new so version

[ Javier Fernández-Sanguino ]
* Updated Spanish Debconf template translation (Closes: #773563)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (C) 2008-2013 Sourcefire, Inc.
 
3
 *
 
4
 *  Author: Tomasz Kojm <tkojm@clamav.net>
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License version 2 as
 
8
 *  published by the Free Software Foundation.
 
9
 *
 
10
 *  This program is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
18
 *  MA 02110-1301, USA.
 
19
 */
 
20
 
 
21
/*
 
22
 * TODO:
 
23
 * - clamconf, milter
 
24
 * - clamconf: generation/verification/updating of config files and man page entries
 
25
 * - automatically generate --help pages (use the first line from the description)
 
26
 */
 
27
 
 
28
#if HAVE_CONFIG_H
 
29
#include "clamav-config.h"
 
30
#endif
 
31
 
 
32
#include <stdio.h>
 
33
#include <stdlib.h>
 
34
#include <string.h>
 
35
#include <errno.h>
 
36
#ifdef HAVE_STRINGS_H
 
37
#include <strings.h>
 
38
#endif
 
39
#include <ctype.h>
 
40
 
 
41
#include "libclamav/clamav.h"
 
42
#include "shared/optparser.h"
 
43
#include "shared/misc.h"
 
44
 
 
45
#include "libclamav/regex/regex.h"
 
46
#include "libclamav/default.h"
 
47
#include "libclamav/others.h"
 
48
 
 
49
#include "getopt.h"
 
50
 
 
51
#define MAXCMDOPTS  120
 
52
 
 
53
#define MATCH_NUMBER "^[0-9]+$"
 
54
#define MATCH_SIZE "^[0-9]+[KM]?$"
 
55
#define MATCH_BOOL "^(yes|true|1|no|false|0)$"
 
56
 
 
57
#define FLAG_MULTIPLE   1 /* option can be used multiple times */
 
58
#define FLAG_REQUIRED   2 /* arg is required, even if there's a default value */
 
59
#define FLAG_HIDDEN     4 /* don't print in clamconf --generate-config */
 
60
#define FLAG_REG_CASE   8 /* case-sensitive regex matching */
 
61
 
 
62
const struct clam_option __clam_options[] = {
 
63
    /* name,   longopt, sopt, argtype, regex, num, str, flags, owner, description, suggested */
 
64
 
 
65
    /* cmdline only */
 
66
    { NULL, "help", 'h', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_SIGTOOL | OPT_MILTER | OPT_CLAMCONF | OPT_CLAMDTOP | OPT_CLAMBC, "", "" },
 
67
    { NULL, "config-file", 'c', CLOPT_TYPE_STRING, NULL, 0, CONFDIR_CLAMD, FLAG_REQUIRED, OPT_CLAMD | OPT_CLAMDSCAN | OPT_CLAMDTOP, "", "" },
 
68
    { NULL, "config-file", 0, CLOPT_TYPE_STRING, NULL, 0, CONFDIR_FRESHCLAM, FLAG_REQUIRED, OPT_FRESHCLAM, "", "" },
 
69
    { NULL, "config-file", 'c', CLOPT_TYPE_STRING, NULL, 0, CONFDIR_MILTER, FLAG_REQUIRED, OPT_MILTER, "", "" },
 
70
    { NULL, "version", 'V', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_SIGTOOL | OPT_MILTER | OPT_CLAMCONF | OPT_CLAMDTOP | OPT_CLAMBC, "", "" },
 
71
    { NULL, "debug", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMBC | OPT_CLAMD | OPT_FRESHCLAM | OPT_CLAMSCAN | OPT_SIGTOOL, "", "" },
 
72
    { NULL, "gen-json", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN | OPT_SIGTOOL, "", "" },
 
73
    { NULL, "verbose", 'v', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM | OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_SIGTOOL, "", "" },
 
74
    { NULL, "dumpcerts", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "Dump authenticode certificate chain.", "" },
 
75
    { NULL, "quiet", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM | OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_SIGTOOL, "", "" },
 
76
    { NULL, "leave-temps", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "", "" },
 
77
    { NULL, "no-warnings", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM, "", "" },
 
78
    { NULL, "stdout", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM | OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_SIGTOOL, "", "" },
 
79
    { NULL, "daemon", 'd', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM, "", "" },
 
80
    { NULL, "no-dns", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM, "", "" },
 
81
    { NULL, "list-mirrors", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM, "", "" },
 
82
    { NULL, "update-db", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_FRESHCLAM, "", "" },
 
83
    { NULL, "reload", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMDSCAN, "", "" },
 
84
    { NULL, "multiscan", 'm', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMDSCAN, "", "" },
 
85
    { NULL, "fdpass", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMDSCAN, "", "" },
 
86
    { NULL, "stream", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMDSCAN, "", "" },
 
87
    { NULL, "allmatch", 'z', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN, "", "" },
 
88
    { NULL, "database", 'd', CLOPT_TYPE_STRING, NULL, -1, DATADIR, FLAG_REQUIRED | FLAG_MULTIPLE, OPT_CLAMSCAN, "", "" }, /* merge it with DatabaseDirectory (and fix conflict with --datadir */
 
89
    { NULL, "recursive", 'r', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "", "" },
 
90
    { NULL, "gen-mdb", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "Always generate MDB entries for PE sections", "" },
 
91
    { NULL, "follow-dir-symlinks", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 1, NULL, 0, OPT_CLAMSCAN, "", "" },
 
92
    { NULL, "follow-file-symlinks", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 1, NULL, 0, OPT_CLAMSCAN, "", "" },
 
93
    { NULL, "bell", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "", "" },
 
94
    { NULL, "no-summary", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN, "", "" },
 
95
    { NULL, "file-list", 'f', CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN, "", "" },
 
96
    { NULL, "infected", 'i', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN, "", "" },
 
97
    { NULL, "suppress-ok-results", 'o', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "", "" },
 
98
    { NULL, "move", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN, "", "" },
 
99
    { NULL, "copy", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN, "", "" },
 
100
    { NULL, "remove", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN, "", "" },
 
101
    { NULL, "exclude", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMSCAN, "", "" },
 
102
    { NULL, "exclude-dir", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMSCAN, "", "" },
 
103
    { NULL, "include", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMSCAN, "", "" },
 
104
    { NULL, "include-dir", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMSCAN, "", "" },
 
105
    { NULL, "structured-ssn-format", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 0, NULL, 0, OPT_CLAMSCAN, "", "" },
 
106
    { NULL, "hex-dump", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_SIGTOOL, "", "" },
 
107
    { NULL, "md5", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_SIGTOOL, "", "" },
 
108
    { NULL, "sha1", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_SIGTOOL, "", "" },
 
109
    { NULL, "sha256", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_SIGTOOL, "", "" },
 
110
    { NULL, "mdb", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_SIGTOOL, "", "" },
 
111
    { NULL, "print-certs", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
 
112
    { NULL, "html-normalise", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
 
113
    { NULL, "utf16-decode", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
 
114
    { NULL, "build", 'b', CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
 
115
    { NULL, "max-bad-sigs", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 3000, NULL, 0, OPT_SIGTOOL, "Maximum number of mismatched signatures when building a CVD. Zero disables this limit.", "3000" },
 
116
    { NULL, "flevel", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, CL_FLEVEL, NULL, 0, OPT_SIGTOOL, "Feature level to put in the CVD", "" },
 
117
    { NULL, "cvd-version", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 0, NULL, 0, OPT_SIGTOOL, "Version number of the CVD to build", "" },
 
118
    { NULL, "unsigned", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_SIGTOOL, "", "" },
 
119
    { NULL, "no-cdiff", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_SIGTOOL, "", "" },
 
120
    { NULL, "server", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
 
121
    { NULL, "unpack", 'u', CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
 
122
    { NULL, "unpack-current", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
 
123
    { NULL, "info", 'i', CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
 
124
    { NULL, "list-sigs", 'l', CLOPT_TYPE_STRING, NULL, -1, DATADIR, 0, OPT_SIGTOOL, "", "" },
 
125
    { NULL, "find-sigs", 'f', CLOPT_TYPE_STRING, NULL, -1, DATADIR, FLAG_REQUIRED, OPT_SIGTOOL, "", "" },
 
126
    { NULL, "decode-sigs", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_SIGTOOL, "", "" },
 
127
    { NULL, "test-sigs", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
 
128
    { NULL, "vba", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
 
129
    { NULL, "vba-hex", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
 
130
    { NULL, "diff", 'd', CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
 
131
    { NULL, "compare", 'c', CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
 
132
    { NULL, "run-cdiff", 'r', CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
 
133
    { NULL, "verify-cdiff", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
 
134
    { NULL, "defaultcolors", 'd', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMDTOP, "", "" },
 
135
 
 
136
    { NULL, "config-dir", 'c', CLOPT_TYPE_STRING, NULL, 0, CONFDIR, FLAG_REQUIRED, OPT_CLAMCONF, "", "" },
 
137
    { NULL, "non-default", 'n', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMCONF, "", "" },
 
138
    { NULL, "generate-config", 'g', CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMCONF, "", "" },
 
139
 
 
140
    { NULL, "force-interpreter", 'f', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMBC, "Force using the interpreter instead of the JIT", "" },
 
141
    { NULL, "trust-bytecode", 't', CLOPT_TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMBC, "Trust loaded bytecode (default yes)", ""},
 
142
    { NULL, "info", 'i', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMBC, "Load and print bytecode information without executing", ""},
 
143
    { NULL, "printsrc", 'p', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMBC, "Print source code of bytecode", ""},
 
144
    { NULL, "printbcir", 'c', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMBC, "Print IR of bytecode signature", ""},
 
145
    { NULL, "input", 'r', CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMBC, "Input file to run the bytecode n", ""},
 
146
    { NULL, "trace", 'T', CLOPT_TYPE_NUMBER, MATCH_NUMBER, 7, NULL, 0, OPT_CLAMBC, "bytecode trace level",""},
 
147
    { NULL, "no-trace-showsource", 's', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMBC, "Don't show source line during tracing",""},
 
148
 
 
149
    { NULL, "archive-verbose", 'a', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "", ""},
 
150
 
 
151
    /* cmdline only - deprecated */
 
152
    { NULL, "bytecode-trust-all", 't', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", ""},
 
153
    { NULL, "http-proxy", 0, CLOPT_TYPE_STRING, NULL, 0, NULL, 0, OPT_FRESHCLAM | OPT_DEPRECATED, "", "" },
 
154
    { NULL, "proxy-user", 0, CLOPT_TYPE_STRING, NULL, 0, NULL, 0, OPT_FRESHCLAM | OPT_DEPRECATED, "", "" },
 
155
    { NULL, "log-verbose", 0, CLOPT_TYPE_BOOL, NULL, 0, NULL, 0, OPT_FRESHCLAM | OPT_DEPRECATED, "", "" },
 
156
    { NULL, "force", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
157
    { NULL, "disable-summary", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN | OPT_DEPRECATED, "", "" },
 
158
    { NULL, "disable-archive", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
159
    { NULL, "no-archive", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
160
    { NULL, "no-pe", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
161
    { NULL, "no-elf", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
162
    { NULL, "no-ole2", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
163
    { NULL, "no-pdf", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
164
    { NULL, "no-html", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
165
    { NULL, "no-mail", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
166
    { NULL, "no-phishing-sigs", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
167
    { NULL, "no-phishing-scan-urls", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
168
    { NULL, "no-algorithmic", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
169
    { NULL, "no-phishing-restrictedscan", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
170
    { NULL, "max-ratio", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
171
    { NULL, "max-space", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
172
    { NULL, "block-max", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
173
    { NULL, "unzip", 0, CLOPT_TYPE_STRING, NULL, -1, "foo", 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
174
    { NULL, "unrar", 0, CLOPT_TYPE_STRING, NULL, -1, "foo", 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
175
    { NULL, "arj", 0, CLOPT_TYPE_STRING, NULL, -1, "foo", 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
176
    { NULL, "unzoo", 0, CLOPT_TYPE_STRING, NULL, -1, "foo", 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
177
    { NULL, "lha", 0, CLOPT_TYPE_STRING, NULL, -1, "foo", 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
178
    { NULL, "jar", 0, CLOPT_TYPE_STRING, NULL, -1, "foo", 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
179
    { NULL, "tar", 0, CLOPT_TYPE_STRING, NULL, -1, "foo", 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
180
    { NULL, "tgz", 0, CLOPT_TYPE_STRING, NULL, -1, "foo", 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
181
    { NULL, "deb", 0, CLOPT_TYPE_STRING, NULL, -1, "foo", 0, OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
182
 
 
183
    /* config file/cmdline options */
 
184
    { "LogFile", "log", 'l', CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMD | OPT_MILTER | OPT_CLAMSCAN | OPT_CLAMDSCAN, "Save all reports to a log file.", "/tmp/clamav.log" },
 
185
 
 
186
    { "StatsHostID", "stats-host-id", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_FRESHCLAM | OPT_CLAMD | OPT_CLAMSCAN, "HostID in the form of an UUID to use when submitting statistical information. See the clamscan manpage for more information.", "default" },
 
187
 
 
188
    { "StatsEnabled", "enable-stats", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_CLAMSCAN, "Enable submission of statistical data", "yes" },
 
189
 
 
190
    { "StatsPEDisabled", "disable-pe-stats", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Disable submission of PE section statistical data", "no" },
 
191
 
 
192
    { "StatsTimeout", "stats-timeout", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, -1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN | OPT_FRESHCLAM, "Timeout in seconds to timeout communication with the stats server.", "10" },
 
193
 
 
194
    { "LogFileUnlock", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_MILTER, "By default the log file is locked for writing and only a single\ndaemon process can write to it. This option disables the lock.", "yes" },
 
195
 
 
196
    { "LogFileMaxSize", NULL, 0, CLOPT_TYPE_SIZE, MATCH_SIZE, 1048576, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER, "Maximum size of the log file.\nValue of 0 disables the limit.", "5M" },
 
197
 
 
198
    { "LogTime", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER, "Log time with each message.", "yes" },
 
199
 
 
200
    { "LogClean", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Log all clean files.\nUseful in debugging but drastically increases the log size.", "yes" },
 
201
 
 
202
    { "LogSyslog", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER, "Use the system logger (can work together with LogFile).", "yes" },
 
203
 
 
204
    { "LogFacility", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, "LOG_LOCAL6", FLAG_REQUIRED, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER, "Type of syslog messages.\nPlease refer to 'man syslog' for the facility names.", "LOG_MAIL" },
 
205
 
 
206
    { "LogVerbose", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER, "Enable verbose logging.", "yes" },
 
207
 
 
208
    { "LogRotate", "log-rotate", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER, "Rotate log file. Requires LogFileMaxSize option set prior to this option.", "yes" },
 
209
 
 
210
    { "ExtendedDetectionInfo", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Log additional information about the infected file, such as its\nsize and hash, together with the virus name.", "yes" },
 
211
 
 
212
    { "PidFile", "pid", 'p', CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER, "Save the process ID to a file.", "/var/run/clam.pid" },
 
213
 
 
214
    { "TemporaryDirectory", "tempdir", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMD | OPT_MILTER | OPT_CLAMSCAN | OPT_SIGTOOL, "This option allows you to change the default temporary directory.", "/tmp" },
 
215
 
 
216
    { "DatabaseDirectory", "datadir", 0, CLOPT_TYPE_STRING, NULL, -1, DATADIR, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_SIGTOOL, "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" },
 
217
 
 
218
    { "OfficialDatabaseOnly", "official-db-only", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Only load the official signatures published by the ClamAV project.", "no" },
 
219
 
 
220
    { "LocalSocket", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMD, "Path to a local socket file the daemon will listen on.", "/tmp/clamd.socket" },
 
221
 
 
222
    { "LocalSocketGroup", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMD, "Sets the group ownership on the unix socket.", "virusgroup" },
 
223
 
 
224
    { "LocalSocketMode", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMD, "Sets the permissions on the unix socket to the specified mode.", "660" },
 
225
 
 
226
    { "FixStaleSocket", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_MILTER, "Remove a stale socket after unclean shutdown", "yes" },
 
227
 
 
228
    { "TCPSocket", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, -1, NULL, 0, OPT_CLAMD, "A TCP port number the daemon will listen on.", "3310" },
 
229
 
 
230
    /* FIXME: add a regex for IP addr */
 
231
    { "TCPAddr", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "By default clamd binds to INADDR_ANY.\nThis option allows you to restrict the TCP address and provide\nsome degree of protection from the outside world.", "127.0.0.1" },
 
232
 
 
233
    { "MaxConnectionQueueLength", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 200, NULL, 0, OPT_CLAMD, "Maximum length the queue of pending connections may grow to.", "30" },
 
234
 
 
235
    { "StreamMaxLength", NULL, 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXFILESIZE, NULL, 0, OPT_CLAMD, "Close the STREAM session when the data size limit is exceeded.\nThe value should match your MTA's limit for the maximum attachment size.", "25M" },
 
236
 
 
237
    { "StreamMinPort", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 1024, NULL, 0, OPT_CLAMD, "The STREAM command uses an FTP-like protocol.\nThis option sets the lower boundary for the port range.", "1024" },
 
238
 
 
239
    { "StreamMaxPort", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 2048, NULL, 0, OPT_CLAMD, "This option sets the upper boundary for the port range.", "2048" },
 
240
 
 
241
    { "MaxThreads", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 10, NULL, 0, OPT_CLAMD | OPT_MILTER, "Maximum number of threads running at the same time.", "20" },
 
242
 
 
243
    { "ReadTimeout", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 120, NULL, 0, OPT_CLAMD, "This option specifies the time (in seconds) after which clamd should\ntimeout if a client doesn't provide any data.", "120" },
 
244
 
 
245
    { "CommandReadTimeout", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 5, NULL, 0, OPT_CLAMD, "This option specifies the time (in seconds) after which clamd should\ntimeout if a client doesn't provide any initial command after connecting.", "5" },
 
246
 
 
247
    { "SendBufTimeout", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 500, NULL, 0, OPT_CLAMD, "This option specifies how long to wait (in miliseconds) if the send buffer\nis full. Keep this value low to prevent clamd hanging.", "200"},
 
248
 
 
249
    { "ReadTimeout", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 120, NULL, 0, OPT_MILTER, "Waiting for data from clamd will timeout after this time (seconds).", "300" },
 
250
 
 
251
    { "MaxQueue", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 100, NULL, 0, OPT_CLAMD, "Maximum number of queued items (including those being processed by MaxThreads\nthreads). It is recommended to have this value at least twice MaxThreads\nif possible.\nWARNING: you shouldn't increase this too much to avoid running out of file\n descriptors, the following condition should hold:\n MaxThreads*MaxRecursion + MaxQueue - MaxThreads  + 6 < RLIMIT_NOFILE\n (usual max for RLIMIT_NOFILE is 1024)\n", "200" },
 
252
 
 
253
    { "IdleTimeout", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 30, NULL, 0, OPT_CLAMD, "This option specifies how long (in seconds) the process should wait\nfor a new job.", "60" },
 
254
 
 
255
    { "ExcludePath", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "Don't scan files/directories whose names match the provided\nregular expression. This option can be specified multiple times.", "^/proc/\n^/sys/" },
 
256
 
 
257
    { "MaxDirectoryRecursion", "max-dir-recursion", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 15, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Maximum depth the directories are scanned at.", "15" },
 
258
 
 
259
    { "FollowDirectorySymlinks", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Follow directory symlinks.", "no" },
 
260
 
 
261
    { "FollowFileSymlinks", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Follow symlinks to regular files.", "no" },
 
262
 
 
263
    { "CrossFilesystems", "cross-fs", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Scan files and directories on other filesystems.", "yes" },
 
264
 
 
265
    { "SelfCheck", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 600, NULL, 0, OPT_CLAMD, "This option specifies the time intervals (in seconds) in which clamd\nshould perform a database check.", "600" },
 
266
 
 
267
    { "DisableCache", "disable-cache", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option allows you to disable clamd's caching feature.", "no" },
 
268
 
 
269
    { "VirusEvent", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMD, "Execute a command when a virus is found. In the command string %v will be\nreplaced with the virus name. Additionally, two environment variables will\nbe defined: $CLAM_VIRUSEVENT_FILENAME and $CLAM_VIRUSEVENT_VIRUSNAME.", "/usr/bin/mailx -s \"ClamAV VIRUS ALERT: %v\" alert < /dev/null" },
 
270
 
 
271
    { "ExitOnOOM", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Stop the daemon when libclamav reports an out of memory condition.", "yes" },
 
272
 
 
273
    { "AllowAllMatchScan", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD, "Permit use of the ALLMATCHSCAN command.", "yes" },
 
274
 
 
275
    { "Foreground", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER, "Don't fork into background.", "no" },
 
276
 
 
277
    { "Debug", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM, "Enable debug messages in libclamav.", "no" },
 
278
 
 
279
    { "LeaveTemporaryFiles", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Don't remove temporary files (for debugging purposes).", "no" },
 
280
 
 
281
    { "User", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMD | OPT_MILTER, "Run the daemon as a specified user (the process must be started by root).", "clamav" },
 
282
 
 
283
    { "AllowSupplementaryGroups", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER, "Initialize a supplementary group access (the process must be started by root).", "no" },
 
284
 
 
285
    /* Scan options */
 
286
    { "Bytecode", "bytecode", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "With this option enabled ClamAV will load bytecode from the database. It is highly recommended you keep this option on, otherwise you'll miss detections for many new viruses.", "yes" },
 
287
 
 
288
    { "BytecodeSecurity", NULL, 0, CLOPT_TYPE_STRING, "^(TrustSigned|Paranoid)$", -1, "TrustSigned", 0, OPT_CLAMD, 
 
289
        "Set bytecode security level.\nPossible values:\n\tTrustSigned - trust bytecode loaded from signed .c[lv]d files,\n\t\t insert runtime safety checks for bytecode loaded from other sources\n\tParanoid - don't trust any bytecode, insert runtime checks for all\nRecommended: TrustSigned, because bytecode in .cvd files already has these checks.","TrustSigned"},
 
290
 
 
291
    { "BytecodeTimeout", "bytecode-timeout", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 5000, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, 
 
292
        "Set bytecode timeout in miliseconds.","5000"},
 
293
 
 
294
    { "BytecodeUnsigned", "bytecode-unsigned", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, 
 
295
        "Allow loading bytecode from outside digitally signed .c[lv]d files.","no"},
 
296
 
 
297
    { "BytecodeMode", "bytecode-mode", 0, CLOPT_TYPE_STRING, "^(Auto|ForceJIT|ForceInterpreter|Test)$", -1, "Auto", FLAG_REQUIRED, OPT_CLAMD | OPT_CLAMSCAN,
 
298
        "Set bytecode execution mode.\nPossible values:\n\tAuto - automatically choose JIT if possible, fallback to interpreter\nForceJIT - always choose JIT, fail if not possible\nForceInterpreter - always choose interpreter\nTest - run with both JIT and interpreter and compare results. Make all failures fatal.","Auto"},
 
299
 
 
300
    { "BytecodeStatistics", "bytecode-statistics", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_CLAMBC, "Collect and print bytecode execution statistics.", "no" },
 
301
 
 
302
   { "DetectPUA", "detect-pua", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Detect Potentially Unwanted Applications.", "yes" },
 
303
 
 
304
    { "ExcludePUA", "exclude-pua", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD | OPT_CLAMSCAN, "Exclude a specific PUA category. This directive can be used multiple times.\nSee http://www.clamav.net/doc/pua.html for the complete list of PUA\ncategories.", "NetTool\nPWTool" },
 
305
 
 
306
    { "IncludePUA", "include-pua", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD | OPT_CLAMSCAN, "Only include a specific PUA category. This directive can be used multiple\ntimes.", "Spy\nScanner\nRAT" },
 
307
 
 
308
    { "AlgorithmicDetection", "algorithmic-detection", 0, CLOPT_TYPE_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" },
 
309
 
 
310
    { "ScanPE", "scan-pe", 0, CLOPT_TYPE_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.\nIf you turn off this option, the original files will still be scanned, but\nwithout additional processing.", "yes" },
 
311
 
 
312
    { "ScanELF", "scan-elf", 0, CLOPT_TYPE_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.\nIf you turn off this option, the original files will still be scanned, but\nwithout additional processing.", "yes" },
 
313
 
 
314
    { "DetectBrokenExecutables", "detect-broken", 0, CLOPT_TYPE_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" },
 
315
 
 
316
    { "ScanMail", "scan-mail", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Enable the built in email scanner.\nIf you turn off this option, the original files will still be scanned, but\nwithout parsing individual messages/attachments.", "yes" },
 
317
 
 
318
    { "ScanPartialMessages", NULL, 0, CLOPT_TYPE_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" },
 
319
 
 
320
    { "PhishingSignatures", "phishing-sigs", 0, CLOPT_TYPE_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" },
 
321
 
 
322
    { "PhishingScanURLs", "phishing-scan-urls", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Scan URLs found in mails for phishing attempts using heuristics.", "yes" },
 
323
 
 
324
    { "PhishingAlwaysBlockCloak", "phishing-cloak", 0, CLOPT_TYPE_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" },
 
325
 
 
326
    { "PhishingAlwaysBlockSSLMismatch", "phishing-ssl", 0, CLOPT_TYPE_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.", "" },
 
327
 
 
328
    { "PartitionIntersection", "partition-intersection", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Detect partition intersections in raw disk images using heuristics.", "yes" },
 
329
 
 
330
    { "HeuristicScanPrecedence", "heuristic-scan-precedence", 0, CLOPT_TYPE_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" },
 
331
 
 
332
    { "StructuredDataDetection", "detect-structured", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Enable the Data Loss Prevention module.", "no" },
 
333
 
 
334
    { "StructuredMinCreditCardCount", "structured-cc-count", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, CLI_DEFAULT_MIN_CC_COUNT, 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" },
 
335
 
 
336
    { "StructuredMinSSNCount", "structured-ssn-count", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, CLI_DEFAULT_MIN_SSN_COUNT, 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" },
 
337
 
 
338
    { "StructuredSSNFormatNormal", NULL, 0, CLOPT_TYPE_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" },
 
339
 
 
340
    { "StructuredSSNFormatStripped", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "With this option enabled the DLP module will search for valid\nSSNs formatted as xxxyyzzzz", "no" },
 
341
 
 
342
    { "ScanHTML", "scan-html", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Perform HTML/JavaScript/ScriptEncoder normalisation and decryption.\nIf you turn off this option, the original files will still be scanned, but\nwithout additional processing.", "yes" },
 
343
 
 
344
    { "ScanOLE2", "scan-ole2", 0, CLOPT_TYPE_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.\nIf you turn off this option, the original files will still be scanned, but\nwithout additional processing.", "yes" },
 
345
 
 
346
    { "OLE2BlockMacros", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "With this option enabled OLE2 files with VBA macros, which were not\ndetected by signatures will be marked as \"Heuristics.OLE2.ContainsMacros\".", "no" },
 
347
 
 
348
    { "ScanPDF", "scan-pdf", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option enables scanning within PDF files.\nIf you turn off this option, the original files will still be scanned, but\nwithout decoding and additional processing.", "yes" },
 
349
 
 
350
    { "ScanSWF", "scan-swf", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option enables scanning within SWF files.\nIf you turn off this option, the original files will still be scanned, but\nwithout decoding and additional processing.", "yes" },
 
351
 
 
352
    { "ScanArchive", "scan-archive", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Scan within archives and compressed files.\nIf you turn off this option, the original files will still be scanned, but\nwithout unpacking and additional processing.", "yes" },
 
353
 
 
354
    { "ArchiveBlockEncrypted", "block-encrypted", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Mark encrypted archives as viruses (Encrypted.Zip, Encrypted.RAR).", "no" },
 
355
 
 
356
    { "ForceToDisk", "force-to-disk", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option causes memory or nested map scans to dump the content to disk.\nIf you turn on this option, more data is written to disk and is available\nwhen the leave-temps option is enabled at the cost of more disk writes.", "no" },
 
357
 
 
358
    { "MaxScanSize", "max-scansize", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXSCANSIZE, 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\ndamage.", "100M" },
 
359
 
 
360
    { "MaxFileSize", "max-filesize", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXFILESIZE, NULL, 0, OPT_CLAMD | OPT_MILTER | OPT_CLAMSCAN, "Files/messages larger than this limit won't be scanned. Affects the input\nfile itself as well as files contained inside it (when the input file is\nan archive, a document 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\ndamage to the system.", "25M" },
 
361
 
 
362
    { "MaxRecursion", "max-recursion", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, CLI_DEFAULT_MAXRECLEVEL, 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\ndamage to the system.", "16" },
 
363
 
 
364
    { "MaxFiles", "max-files", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, CLI_DEFAULT_MAXFILES, 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\ndamage to the system.", "10000" },
 
365
 
 
366
    /* Engine maximums */
 
367
    { "MaxEmbeddedPE", "max-embeddedpe", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXEMBEDDEDPE, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum size of a file to check for embedded PE.\nFiles larger than this value will skip the additional analysis step.\nNegative values are not allowed.\nWARNING: setting this limit too high may result in severe damage or impact performance.", "10M" },
 
368
 
 
369
    { "MaxHTMLNormalize", "max-htmlnormalize", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXHTMLNORMALIZE, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum size of a HTML file to normalize.\nHTML files larger than this value will not be normalized or scanned.\nNegative values are not allowed.\nWARNING: setting this limit too high may result in severe damage or impact performance.", "10M" },
 
370
 
 
371
    { "MaxHTMLNoTags", "max-htmlnotags", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXHTMLNOTAGS, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum size of a normalized HTML file to scan.\nHTML files larger than this value after normalization will not be scanned.\nNegative values are not allowed.\nWARNING: setting this limit too high may result in severe damage or impact performance.", "2M" },
 
372
 
 
373
    { "MaxScriptNormalize", "max-scriptnormalize", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXSCRIPTNORMALIZE, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum size of a script file to normalize.\nScript content larger than this value will not be normalized or scanned.\nNegative values are not allowed.\nWARNING: setting this limit too high may result in severe damage or impact performance.", "5M" },
 
374
 
 
375
    { "MaxZipTypeRcg", "max-ziptypercg", 0, CLOPT_TYPE_SIZE, MATCH_SIZE, CLI_DEFAULT_MAXZIPTYPERCG, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum size of a ZIP file to reanalyze type recognition.\nZIP files larger than this value will skip the step to potentially reanalyze as PE.\nNegative values are not allowed.\nWARNING: setting this limit too high may result in severe damage or impact performance.", "1M" },
 
376
 
 
377
    { "MaxPartitions", "max-partitions", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, CLI_DEFAULT_MAXPARTITIONS, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum number of partitions of a raw disk image to be scanned.\nRaw disk images with more partitions than this value will have up to the value number partitions scanned.\nNegative values are not allowed.\nWARNING: setting this limit too high may result in severe damage or impact performance.", "128" },
 
378
 
 
379
    { "MaxIconsPE", "max-iconspe", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, CLI_DEFAULT_MAXICONSPE, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "This option sets the maximum number of icons within a PE to be scanned.\nPE files with more icons than this value will have up to the value number icons scanned.\nNegative values are not allowed.\nWARNING: setting this limit too high may result in severe damage or impact performance.", "100" },
 
380
 
 
381
    { "TimeLimit", "timelimit", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 0, NULL, 0, OPT_CLAMSCAN, "This clamscan option is currently for testing only. It sets the engine parameter CL_ENGINE_TIME_LIMIT. The value is in milliseconds.", "0" },
 
382
 
 
383
    /* OnAccess settings */
 
384
    { "ScanOnAccess", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD, "This option enables on-access scanning (Linux only)", "no" },
 
385
 
 
386
    { "OnAccessIncludePath", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "This option specifies a directory (including all files and directories\ninside it), which should be scanned on access. This option can\nbe used multiple times.", "/home\n/students" },
 
387
 
 
388
    { "OnAccessExcludePath", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "This option allows excluding directories from on-access scanning. It can\nbe used multiple times.", "/home/bofh\n/root" },
 
389
 
 
390
    { "OnAccessExcludeUID", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "With this option you can whitelist specific UIDs. Processes with these UIDs\nwill be able to access all files.\nThis option can be used multiple times (one per line).", "0" },
 
391
 
 
392
    { "OnAccessMaxFileSize", NULL, 0, CLOPT_TYPE_SIZE, MATCH_SIZE, 5242880, NULL, 0, OPT_CLAMD, "Files larger than this value will not be scanned in on access.", "5M" },
 
393
 
 
394
    /* FIXME: mark these as private and don't output into clamd.conf/man */
 
395
    { "DevACOnly", "dev-ac-only", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, FLAG_HIDDEN, OPT_CLAMD | OPT_CLAMSCAN, "", "" },
 
396
 
 
397
    { "DevACDepth", "dev-ac-depth", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, -1, NULL, FLAG_HIDDEN, OPT_CLAMD | OPT_CLAMSCAN, "", "" },
 
398
 
 
399
#ifdef HAVE__INTERNAL__SHA_COLLECT
 
400
    { "DevCollectHashes", "dev-collect-hashes", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, FLAG_HIDDEN, OPT_CLAMD | OPT_CLAMSCAN, "", "" },
 
401
#endif
 
402
    { "DevPerformance", "dev-performance", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, FLAG_HIDDEN, OPT_CLAMD | OPT_CLAMSCAN, "", "" },
 
403
    { "DevLiblog", "dev-liblog", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, FLAG_HIDDEN, OPT_CLAMD, "", "" },
 
404
 
 
405
    /* Freshclam-only entries */
 
406
 
 
407
    /* FIXME: drop this entry and use LogFile */
 
408
    { "UpdateLogFile", "log", 'l', CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_FRESHCLAM, "Save all reports to a log file.", "/var/log/freshclam.log" },
 
409
 
 
410
    { "DatabaseOwner", "user", 'u', CLOPT_TYPE_STRING, NULL, -1, CLAMAVUSER, FLAG_REQUIRED, OPT_FRESHCLAM, "When started by root freshclam will drop privileges and switch to the user\ndefined in this option.", CLAMAVUSER },
 
411
 
 
412
    { "Checks", "checks", 'c', CLOPT_TYPE_NUMBER, MATCH_NUMBER, 12, NULL, 0, OPT_FRESHCLAM, "This option defined how many times daily freshclam should check for\na database update.", "24" },
 
413
 
 
414
    { "DNSDatabaseInfo", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, "current.cvd.clamav.net", FLAG_REQUIRED, OPT_FRESHCLAM, "Use DNS to verify the virus database version. Freshclam uses DNS TXT records\nto verify the versions of the database and software itself. With this\ndirective you can change the database verification domain.\nWARNING: Please don't change it unless you're configuring freshclam to use\nyour own database verification domain.", "current.cvd.clamav.net" },
 
415
 
 
416
    { "DatabaseMirror", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_FRESHCLAM, "DatabaseMirror specifies to which mirror(s) freshclam should connect.\nYou should have at least two entries: db.XY.clamav.net (or db.XY.ipv6.clamav.net\nfor IPv6) and database.clamav.net (in this order). Please replace XY with your\ncountry code (see http://www.iana.org/cctld/cctld-whois.htm).\ndatabase.clamav.net is a round-robin record which points to our most reliable\nmirrors. It's used as a fall back in case db.XY.clamav.net is not working.", "db.XY.clamav.net\ndatabase.clamav.net" },
 
417
 
 
418
    { "PrivateMirror", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_FRESHCLAM, "This option allows you to easily point freshclam to private mirrors.\nIf PrivateMirror is set, freshclam does not attempt to use DNS\nto determine whether its databases are out-of-date, instead it will\nuse the If-Modified-Since request or directly check the headers of the\nremote database files. For each database, freshclam first attempts\nto download the CLD file. If that fails, it tries to download the\nCVD file. This option overrides DatabaseMirror, DNSDatabaseInfo\nand Scripted Updates. It can be used multiple times to provide\nfall-back mirrors.", "mirror1.mynetwork.com\nmirror2.mynetwork.com" },
 
419
 
 
420
    { "MaxAttempts", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 3, NULL, 0, OPT_FRESHCLAM, "This option defines how many attempts freshclam should make before giving up.", "5" },
 
421
 
 
422
    { "ScriptedUpdates", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_FRESHCLAM, "With this option you can control scripted updates. It's highly recommended to keep them enabled.", "yes" },
 
423
 
 
424
    { "TestDatabases", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_FRESHCLAM, "With this option enabled, freshclam will attempt to load new\ndatabases into memory to make sure they are properly handled\nby libclamav before replacing the old ones.", "yes" },
 
425
 
 
426
    { "CompressLocalDatabase", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM, "By default freshclam will keep the local databases (.cld) uncompressed to\nmake their handling faster. With this option you can enable the compression.\nThe change will take effect with the next database update.", "" },
 
427
 
 
428
    { "ExtraDatabase", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_FRESHCLAM, "Download an additional 3rd party signature database distributed through\nthe ClamAV mirrors. This option can be used multiple times.\nHere you can find a list of available databases:\nhttp://www.clamav.net/download/cvd/3rdparty", "dbname1\ndbname2" },
 
429
 
 
430
    { "DatabaseCustomURL", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_FRESHCLAM, "With this option you can provide custom sources (http:// or file://) for database files.\nThis option can be used multiple times.", "http://myserver.com/mysigs.ndb\nfile:///mnt/nfs/local.hdb" },
 
431
 
 
432
    { "HTTPProxyServer", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_FRESHCLAM, "If you're behind a proxy, please enter its address here.", "your-proxy" },
 
433
 
 
434
    { "HTTPProxyPort", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, -1, NULL, 0, OPT_FRESHCLAM, "HTTP proxy's port", "8080" },
 
435
 
 
436
    { "HTTPProxyUsername", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_FRESHCLAM, "A user name for the HTTP proxy authentication.", "username" },
 
437
 
 
438
    { "HTTPProxyPassword", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_FRESHCLAM, "A password for the HTTP proxy authentication.", "pass" },
 
439
 
 
440
    { "HTTPUserAgent", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_FRESHCLAM, "If your servers are behind a firewall/proxy which does a User-Agent\nfiltering you can use this option to force the use of a different\nUser-Agent header.", "default" },
 
441
 
 
442
    { "NotifyClamd", "daemon-notify", 0, CLOPT_TYPE_STRING, NULL, -1, CONFDIR_CLAMD, 0, OPT_FRESHCLAM, "Send the RELOAD command to clamd after a successful update.", "yes" },
 
443
 
 
444
    { "OnUpdateExecute", "on-update-execute", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_FRESHCLAM, "Run a command after a successful database update.", "command" },
 
445
 
 
446
    { "OnErrorExecute", "on-error-execute", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_FRESHCLAM, "Run a command when a database update error occurs.", "command" },
 
447
 
 
448
    { "OnOutdatedExecute", "on-outdated-execute", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_FRESHCLAM, "Run a command when freshclam reports an outdated version.\nIn the command string %v will be replaced with the new version number.", "command" },
 
449
 
 
450
    /* FIXME: MATCH_IPADDR */
 
451
    { "LocalIPAddress", "local-address", 'a', CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_FRESHCLAM, "With this option you can provide a client address for the database downlading.\nUseful for multi-homed systems.", "aaa.bbb.ccc.ddd" },
 
452
 
 
453
    { "ConnectTimeout", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 30, NULL, 0, OPT_FRESHCLAM, "Timeout in seconds when connecting to database server.", "30" },
 
454
 
 
455
    { "ReceiveTimeout", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 30, NULL, 0, OPT_FRESHCLAM, "Timeout in seconds when reading from database server.", "30" },
 
456
 
 
457
    { "SubmitDetectionStats", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_FRESHCLAM, "When enabled freshclam will submit statistics to the ClamAV Project about\nthe latest virus detections in your environment. The ClamAV maintainers\nwill then use this data to determine what types of malware are the most\ndetected in the field and in what geographic area they are.\nFreshclam will connect to clamd in order to get recent statistics.", "/path/to/clamd.conf" },
 
458
 
 
459
    { "DetectionStatsCountry", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_FRESHCLAM, "Country of origin of malware/detection statistics (for statistical\npurposes only). The statistics collector at ClamAV.net will look up\nyour IP address to determine the geographical origin of the malware\nreported by your installation. If this installation is mainly used to\nscan data which comes from a different location, please enable this\noption and enter a two-letter code (see http://www.iana.org/domains/root/db/)\nof the country of origin.", "country-code" },
 
460
 
 
461
    { "DetectionStatsHostID", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_FRESHCLAM, "This option enables support for our \"Personal Statistics\" service.\nWhen this option is enabled, the information on malware detected by\nyour clamd installation is made available to you through our website.\nTo get your HostID, log on http://www.stats.clamav.net and add a new\nhost to your host list. Once you have the HostID, uncomment this option\nand paste the HostID here. As soon as your freshclam starts submitting\ninformation to our stats collecting service, you will be able to view\nthe statistics of this clamd installation by logging into\nhttp://www.stats.clamav.net with the same credentials you used to\ngenerate the HostID. For more information refer to:\nhttp://www.clamav.net/doc/cctts.html\nThis feature requires SubmitDetectionStats to be enabled.", "unique-id" },
 
462
 
 
463
    { "SafeBrowsing", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_FRESHCLAM, "This option enables support for Google Safe Browsing. When activated for\nthe first time, freshclam will download a new database file (safebrowsing.cvd)\nwhich will be automatically loaded by clamd and clamscan during the next\nreload, provided that the heuristic phishing detection is turned on. This\ndatabase includes information about websites that may be phishing sites or\npossible sources of malware. When using this option, it's mandatory to run\nfreshclam at least every 30 minutes.\nFreshclam uses the ClamAV's mirror infrastructure to distribute the\ndatabase and its updates but all the contents are provided under Google's\nterms of use. See http://www.google.com/transparencyreport/safebrowsing\nand http://www.clamav.net/doc/safebrowsing.html for more information.", "yes" },
 
464
 
 
465
    { "Bytecode", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_FRESHCLAM, "This option enables downloading of bytecode.cvd, which includes additional\ndetection mechanisms and improvements to the ClamAV engine.", "yes" },
 
466
 
 
467
    { "DisableCertCheck", "nocerts", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Disable authenticode certificate chain verification in PE files.", "no" },
 
468
 
 
469
    /* Deprecated options */
 
470
 
 
471
    { "MailMaxRecursion", NULL, 0, CLOPT_TYPE_NUMBER, NULL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
 
472
    { "ArchiveMaxScanSize", NULL, 0, CLOPT_TYPE_SIZE, NULL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
 
473
    { "ArchiveMaxRecursion", NULL, 0, CLOPT_TYPE_NUMBER, NULL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
 
474
    { "ArchiveMaxFiles", NULL, 0, CLOPT_TYPE_NUMBER, NULL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
 
475
    { "ArchiveMaxCompressionRatio", NULL, 0, CLOPT_TYPE_NUMBER, NULL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
 
476
    { "ArchiveBlockMax", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
 
477
    { "ArchiveLimitMemoryUsage", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
 
478
    { "MailFollowURLs", "mail-follow-urls", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
 
479
    { "ClamukoScanOnAccess", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
 
480
    { "ClamukoScannerCount", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 3, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
 
481
    { "ClamukoScanOnOpen", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
 
482
    { "ClamukoScanOnClose", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
 
483
    { "ClamukoScanOnExec", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
 
484
    { "ClamukoIncludePath", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD | OPT_DEPRECATED, "", "" },
 
485
    { "ClamukoExcludePath", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD | OPT_DEPRECATED, "", "" },
 
486
    { "ClamukoExcludeUID", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD | OPT_DEPRECATED, "", "" },
 
487
    { "ClamukoMaxFileSize", NULL, 0, CLOPT_TYPE_SIZE, MATCH_SIZE, 5242880, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
 
488
 
 
489
    /* Milter specific options */
 
490
 
 
491
    { "ClamdSocket", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_MILTER, "Define the clamd socket to connect to for scanning.\nThis option is mandatory! Syntax:\n  ClamdSocket unix:path\n  ClamdSocket tcp:host:port\nThe first syntax specifies a local unix socket (needs an absolute path) e.g.:\n  ClamdSocket unix:/var/run/clamd/clamd.socket\nThe second syntax specifies a tcp local or remote tcp socket: the\nhost can be a hostname or an ip address; the \":port\" field is only required\nfor IPv6 addresses, otherwise it defaults to 3310\n  ClamdSocket tcp:192.168.0.1\nThis option can be repeated several times with different sockets or even\nwith the same socket: clamd servers will be selected in a round-robin fashion.", "tcp:scanner.mydomain:7357" },
 
492
 
 
493
    { "MilterSocket",NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER, "Define the interface through which we communicate with sendmail.\nThis option is mandatory! Possible formats are:\n[[unix|local]:]/path/to/file - to specify a unix domain socket;\ninet:port@[hostname|ip-address] - to specify an ipv4 socket;\ninet6:port@[hostname|ip-address] - to specify an ipv6 socket.", "/tmp/clamav-milter.socket\ninet:7357" },
 
494
 
 
495
    { "MilterSocketGroup", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER, "Define the group ownership for the (unix) milter socket.", "virusgroup" },
 
496
 
 
497
    { "MilterSocketMode", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER, "Sets the permissions on the (unix) milter socket to the specified mode.", "660" },
 
498
 
 
499
    { "LocalNet", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_MILTER, "Messages originating from these hosts/networks will not be scanned\nThis option takes a host(name)/mask pair in CIRD notation and can be\nrepeated several times. If \"/mask\" is omitted, a host is assumed.\nTo specify a locally orignated, non-smtp, email use the keyword \"local\".", "local\n192.168.0.0/24\n1111:2222:3333::/48" },
 
500
 
 
501
    { "OnClean", NULL, 0, CLOPT_TYPE_STRING, "^(Accept|Reject|Defer|Blackhole|Quarantine)$", -1, "Accept", 0, OPT_MILTER, "Action to be performed on clean messages (mostly useful for testing).\nThe following actions are available:\nAccept: the message is accepted for delievery\nReject: immediately refuse delievery (a 5xx error is returned to the peer)\nDefer: return a temporary failure message (4xx) to the peer\nBlackhole: like Accept but the message is sent to oblivion\nQuarantine: like Accept but message is quarantined instead of being delivered", "Accept" },
 
502
 
 
503
    { "OnInfected", NULL, 0, CLOPT_TYPE_STRING, "^(Accept|Reject|Defer|Blackhole|Quarantine)$", -1, "Quarantine", 0, OPT_MILTER, "Action to be performed on clean messages (mostly useful for testing).\nThe following actions are available:\nAccept: the message is accepted for delievery\nReject: immediately refuse delievery (a 5xx error is returned to the peer)\nDefer: return a temporary failure message (4xx) to the peer\nBlackhole: like Accept but the message is sent to oblivion\nQuarantine: like Accept but message is quarantined instead of being delivered", "Quarantine" },
 
504
 
 
505
    { "OnFail", NULL, 0, CLOPT_TYPE_STRING, "^(Accept|Reject|Defer)$", -1, "Defer", 0, OPT_MILTER, "Action to be performed on error conditions (this includes failure to\nallocate data structures, no scanners available, network timeouts, unknown\nscanner replies and the like.\nThe following actions are available:\nAccept: the message is accepted for delievery;\nReject: immediately refuse delievery (a 5xx error is returned to the peer);\nDefer: return a temporary failure message (4xx) to the peer.", "Defer" },
 
506
 
 
507
    { "RejectMsg", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER, "This option allows you to set a specific rejection reason for infected messages\nand it's therefore only useful together with \"OnInfected Reject\"\nThe string \"%v\", if present, will be replaced with the virus name.", "MTA specific" },
 
508
 
 
509
    { "AddHeader", NULL, 0, CLOPT_TYPE_STRING, "^(No|Replace|Yes|Add)$", -1, "no", 0, OPT_MILTER, "If this option is set to \"Replace\" (or \"Yes\"), an \"X-Virus-Scanned\" and an\n\"X-Virus-Status\" headers will be attached to each processed message, possibly\nreplacing existing headers.\nIf it is set to Add, the X-Virus headers are added possibly on top of the\nexisting ones.\nNote that while \"Replace\" can potentially break DKIM signatures, \"Add\" may\nconfuse procmail and similar filters.", "Replace" },
 
510
 
 
511
    { "ReportHostname", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER, "When AddHeader is in use, this option allows you to set the reported\nhostname. This may be desirable in order to avoid leaking internal names.\nIf unset the real machine name is used.", "my.mail.server.name" },
 
512
 
 
513
    { "VirusAction", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER, "Execute a command when an infected message is processed.\nThe following parameters are passed to the invoked program in this order:\nvirus name, queue id, sender, destination, subject, message id, message date.\nNote #1: this requires MTA macroes to be available (see LogInfected below)\nNote #2: the process is invoked in the context of clamav-milter\nNote #3: clamav-milter will wait for the process to exit. Be quick or fork to\navoid unnecessary delays in email delievery", "/usr/local/bin/my_infected_message_handler" },
 
514
 
 
515
    { "Chroot", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER, "Chroot to the specified directory.\nChrooting is performed just after reading the config file and before\ndropping privileges.", "/newroot" },
 
516
 
 
517
    { "Whitelist", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER, "This option specifies a file which contains a list of basic POSIX regular\nexpressions. Addresses (sent to or from - see below) matching these regexes\nwill not be scanned.  Optionally each line can start with the string \"From:\"\nor \"To:\" (note: no whitespace after the colon) indicating if it is,\nrespectively, the sender or recipient that is to be whitelisted.\nIf the field is missing, \"To:\" is assumed.\nLines starting with #, : or ! are ignored.", "/etc/whitelisted_addresses" },
 
518
 
 
519
    { "SkipAuthenticated", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER, "Messages from authenticated SMTP users matching this extended POSIX\nregular expression (egrep-like) will not be scanned.\nAs an alternative, a file containing a plain (not regex) list of names (one\nper line) can be specified using the prefix \"file:\".\ne.g. SkipAuthenticated file:/etc/good_guys\n\nNote: this is the AUTH login name!", "SkipAuthenticated ^(tom|dick|henry)$" },
 
520
 
 
521
    { "LogInfected", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER, "This option allows you to tune what is logged when a message is infected.\nPossible values are Off (the default - nothing is logged),\nBasic (minimal info logged), Full (verbose info logged)\nNote:\nFor this to work properly in sendmail, make sure the msg_id, mail_addr,\nrcpt_addr and i macroes are available in eom. In other words add a line like:\nMilter.macros.eom={msg_id}, {mail_addr}, {rcpt_addr}, i\nto your .cf file. Alternatively use the macro:\ndefine(`confMILTER_MACROS_EOM', `{msg_id}, {mail_addr}, {rcpt_addr}, i')\nPostfix should be working fine with the default settings.", "Basic" },
 
522
 
 
523
    { "LogClean", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER, "This option allows you to tune what is logged when no threat is found in a scanned message.\nSee LogInfected for possible values and caveats.\nUseful in debugging but drastically increases the log size.", "Basic" },
 
524
 
 
525
    { "SupportMultipleRecipients", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_MILTER, "This option affects the behaviour of LogInfected, LogClean and VirusAction\nwhen a message with multiple recipients is scanned:\nIf SupportMultipleRecipients is off (the default)\nthen one single log entry is generated for the message and, in case the\nmessage is determined to be malicious, the command indicated by VirusAction\nis executed just once. In both cases only the last recipient is reported.\nIf SupportMultipleRecipients is on:\nthen one line is logged for each recipient and the command indicated\nby VirusAction is also executed once for each recipient.\n\nNote: although it's probably a good idea to enable this option, the default value\nis currently set to off for legacy reasons.", "yes" },
 
526
 
 
527
    /* Deprecated milter options */
 
528
 
 
529
    { "ArchiveBlockEncrypted", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", "" },
 
530
    { "DatabaseDirectory", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", "" },
 
531
    { "Debug", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", "" },
 
532
    { "DetectBrokenExecutables", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", "" },
 
533
    { "LeaveTemporaryFiles", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", "" },
 
534
    { "LocalSocket", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", "" },
 
535
    { "MailFollowURLs", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", "" },
 
536
    { "MaxScanSize", NULL, 0, CLOPT_TYPE_SIZE, MATCH_SIZE, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", "" },
 
537
    { "MaxFiles", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", "" },
 
538
    { "MaxRecursion", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", "" },
 
539
    { "PhishingSignatures", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", "" },
 
540
    { "ScanArchive", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", "" },
 
541
    { "ScanHTML", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", "" },
 
542
    { "ScanMail", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", "" },
 
543
    { "ScanOLE2", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", "" },
 
544
    { "ScanPE", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", "" },
 
545
    { "StreamMaxLength", NULL, 0, CLOPT_TYPE_SIZE, MATCH_SIZE, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", "" },
 
546
    { "TCPAddr", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", "" },
 
547
    { "TCPSocket", NULL, 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", "" },
 
548
    { "TemporaryDirectory", NULL, 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED, "", "" },
 
549
 
 
550
    { NULL, NULL, 0, 0, NULL, 0, NULL, 0, 0, NULL, NULL }
 
551
};
 
552
const struct clam_option *clam_options = __clam_options;
 
553
 
 
554
const struct optstruct *optget(const struct optstruct *opts, const char *name)
 
555
{
 
556
    while(opts) {
 
557
        if((opts->name && !strcmp(opts->name, name)) || (opts->cmd && !strcmp(opts->cmd, name)))
 
558
            return opts;
 
559
        opts = opts->next;
 
560
    }
 
561
    return NULL;
 
562
}
 
563
 
 
564
static struct optstruct *optget_i(struct optstruct *opts, const char *name)
 
565
{
 
566
    while(opts) {
 
567
        if((opts->name && !strcmp(opts->name, name)) || (opts->cmd && !strcmp(opts->cmd, name)))
 
568
            return opts;
 
569
        opts = opts->next;
 
570
    }
 
571
    return NULL;
 
572
}
 
573
 
 
574
/*
 
575
static void optprint(const struct optstruct *opts)
 
576
{
 
577
        const struct optstruct *h;
 
578
 
 
579
    printf("\nOPTIONS:\n\n");
 
580
 
 
581
    while(opts) {
 
582
        printf("OPT_NAME: %s\n", opts->name);
 
583
        printf("OPT_CMD: %s\n", opts->cmd);
 
584
        printf("OPT_STRARG: %s\n", opts->strarg ? opts->strarg : "NONE");
 
585
        printf("OPT_NUMARG: %d\n", opts->numarg);
 
586
        h = opts;
 
587
        while((h = h->nextarg)) {
 
588
            printf("SUBARG_OPT_STRARG: %s\n", h->strarg ? h->strarg : "NONE");
 
589
            printf("SUBARG_OPT_NUMARG: %d\n", h->numarg);
 
590
        }
 
591
        printf("----------------\n");
 
592
        opts = opts->next;
 
593
    }
 
594
}
 
595
*/
 
596
 
 
597
static int optadd(struct optstruct **opts, struct optstruct **opts_last, const char *name, const char *cmd, const char *strarg, long long numarg, int flags, int idx)
 
598
{
 
599
        struct optstruct *newnode;
 
600
 
 
601
 
 
602
    newnode = (struct optstruct *) malloc(sizeof(struct optstruct));
 
603
 
 
604
    if(!newnode)
 
605
        return -1;
 
606
 
 
607
    if(name) {
 
608
        newnode->name = strdup(name);
 
609
        if(!newnode->name) {
 
610
            free(newnode);
 
611
            return -1;
 
612
        }
 
613
    } else {
 
614
        newnode->name = NULL;
 
615
    }
 
616
 
 
617
    if(cmd) {
 
618
        newnode->cmd = strdup(cmd);
 
619
        if(!newnode->cmd) {
 
620
            free(newnode->name);
 
621
            free(newnode);
 
622
            return -1;
 
623
        }
 
624
    } else {
 
625
        newnode->cmd = NULL;
 
626
    }
 
627
 
 
628
    if(strarg) {
 
629
        newnode->strarg = strdup(strarg);
 
630
        if(!newnode->strarg) {
 
631
            free(newnode->cmd);
 
632
            free(newnode->name);
 
633
            free(newnode);
 
634
            return -1;
 
635
        }
 
636
        newnode->enabled = 1;
 
637
    } else {
 
638
        newnode->strarg = NULL;
 
639
        newnode->enabled = 0;
 
640
    }
 
641
    newnode->numarg = numarg;
 
642
    if(numarg && numarg != -1)
 
643
        newnode->enabled = 1;
 
644
    newnode->nextarg = NULL;
 
645
    newnode->next = NULL;
 
646
    newnode->active = 0;
 
647
    newnode->flags = flags;
 
648
    newnode->idx = idx;
 
649
    newnode->filename = NULL;
 
650
 
 
651
    if(!*opts_last) {
 
652
        newnode->next = *opts;
 
653
        *opts = newnode;
 
654
        *opts_last = *opts;
 
655
    } else {
 
656
        (*opts_last)->next = newnode;
 
657
        *opts_last = newnode;
 
658
    }
 
659
    return 0;
 
660
}
 
661
 
 
662
static int optaddarg(struct optstruct *opts, const char *name, const char *strarg, long long numarg)
 
663
{
 
664
        struct optstruct *pt, *h, *new;
 
665
 
 
666
 
 
667
    if(!(pt = optget_i(opts, name))) {
 
668
        fprintf(stderr, "ERROR: optaddarg: Unregistered option %s\n", name);
 
669
        return -1;
 
670
    }
 
671
 
 
672
    if(pt->flags & FLAG_MULTIPLE) {
 
673
        if(!pt->active) {
 
674
            if(strarg) {
 
675
                free(pt->strarg);
 
676
                pt->strarg = strdup(strarg);
 
677
                if(!pt->strarg) {
 
678
                    fprintf(stderr, "ERROR: optaddarg: strdup() failed\n");
 
679
                    return -1;
 
680
                }
 
681
            }
 
682
            pt->numarg = numarg;
 
683
        } else {
 
684
            new = (struct optstruct *) calloc(1, sizeof(struct optstruct));
 
685
            if(!new) {
 
686
                fprintf(stderr, "ERROR: optaddarg: malloc() failed\n");
 
687
                return -1;
 
688
            }
 
689
            if(strarg) {
 
690
                new->strarg = strdup(strarg);
 
691
                if(!new->strarg) {
 
692
                    fprintf(stderr, "ERROR: optaddarg: strdup() failed\n");
 
693
                    free(new);
 
694
                    return -1;
 
695
                }
 
696
            }
 
697
            new->numarg = numarg;
 
698
            h = pt;
 
699
            while(h->nextarg)
 
700
                h = h->nextarg;
 
701
            h->nextarg = new;
 
702
        }
 
703
    } else {
 
704
        if(pt->active)
 
705
            return 0;
 
706
 
 
707
        if(strarg) {
 
708
            free(pt->strarg);
 
709
            pt->strarg = strdup(strarg);
 
710
            if(!pt->strarg) {
 
711
                fprintf(stderr, "ERROR: optaddarg: strdup() failed\n");
 
712
                return -1;
 
713
            }
 
714
        }
 
715
        pt->numarg = numarg;
 
716
    }
 
717
 
 
718
    pt->active = 1;
 
719
    if(pt->strarg || (pt->numarg && pt->numarg != -1))
 
720
        pt->enabled = 1;
 
721
    else
 
722
        pt->enabled = 0;
 
723
 
 
724
    return 0;
 
725
}
 
726
 
 
727
void optfree(struct optstruct *opts)
 
728
{
 
729
        struct optstruct *h, *a;
 
730
        int i;
 
731
 
 
732
    if(opts && opts->filename) {
 
733
        for(i = 0; opts->filename[i]; i++)
 
734
            free(opts->filename[i]);
 
735
        free(opts->filename);
 
736
    }
 
737
 
 
738
    while(opts) {
 
739
        a = opts->nextarg;
 
740
        while(a) {
 
741
            if(a->strarg) {
 
742
                free(a->name);
 
743
                free(a->cmd);
 
744
                free(a->strarg);
 
745
                h = a;
 
746
                a = a->nextarg;
 
747
                free(h);
 
748
            } else {
 
749
                a = a->nextarg;
 
750
            }
 
751
        }
 
752
        free(opts->name);
 
753
        free(opts->cmd);
 
754
        free(opts->strarg);
 
755
        h = opts;
 
756
        opts = opts->next;
 
757
        free(h);
 
758
    }
 
759
    return;
 
760
}
 
761
 
 
762
struct optstruct *optparse(const char *cfgfile, int argc, char **argv, int verbose, int toolmask, int ignore, struct optstruct *oldopts)
 
763
{
 
764
        FILE *fs = NULL;
 
765
        const struct clam_option *optentry;
 
766
        char *pt;
 
767
        const char *name = NULL, *arg;
 
768
        int i, err = 0, lc = 0, sc = 0, opt_index, line = 0, ret;
 
769
        struct optstruct *opts = NULL, *opts_last = NULL, *opt;
 
770
        char buffer[512], *buff;
 
771
        struct option longopts[MAXCMDOPTS];
 
772
        char shortopts[MAXCMDOPTS];
 
773
        regex_t regex;
 
774
        long long numarg, lnumarg;
 
775
        int regflags = REG_EXTENDED | REG_NOSUB;
 
776
 
 
777
 
 
778
    if(oldopts)
 
779
        opts = oldopts;
 
780
 
 
781
    shortopts[sc++] = ':';
 
782
    for(i = 0; ; i++) {
 
783
        optentry = &clam_options[i];
 
784
        if(!optentry->name && !optentry->longopt)
 
785
            break;
 
786
 
 
787
        if(((optentry->owner & toolmask) && ((optentry->owner & toolmask) != OPT_DEPRECATED)) || (ignore && (optentry->owner & ignore))) {
 
788
            if(!oldopts && optadd(&opts, &opts_last, optentry->name, optentry->longopt, optentry->strarg, optentry->numarg, optentry->flags, i) < 0) {
 
789
                fprintf(stderr, "ERROR: optparse: Can't register new option (not enough memory)\n");
 
790
                optfree(opts);
 
791
                return NULL;
 
792
            }
 
793
 
 
794
            if(!cfgfile) {
 
795
                if(optentry->longopt) {
 
796
                    if(lc >= MAXCMDOPTS) {
 
797
                        fprintf(stderr, "ERROR: optparse: longopts[] is too small\n");
 
798
                        optfree(opts);
 
799
                        return NULL;
 
800
                    }
 
801
                    longopts[lc].name = optentry->longopt;
 
802
                    if(!(optentry->flags & FLAG_REQUIRED) && (optentry->argtype == CLOPT_TYPE_BOOL || optentry->strarg))
 
803
                        longopts[lc].has_arg = 2;
 
804
                    else
 
805
                        longopts[lc].has_arg = 1;
 
806
                    longopts[lc].flag = NULL;
 
807
                    longopts[lc++].val = optentry->shortopt;
 
808
                }
 
809
                if(optentry->shortopt) {
 
810
                    if(sc + 2 >= MAXCMDOPTS) {
 
811
                        fprintf(stderr, "ERROR: optparse: shortopts[] is too small\n");
 
812
                        optfree(opts);
 
813
                        return NULL;
 
814
                    }
 
815
                    shortopts[sc++] = optentry->shortopt;
 
816
                    if(optentry->argtype != CLOPT_TYPE_BOOL) {
 
817
                        shortopts[sc++] = ':';
 
818
                        if(!(optentry->flags & FLAG_REQUIRED) && optentry->strarg)
 
819
                            shortopts[sc++] = ':';
 
820
                    }
 
821
                }
 
822
            }
 
823
        }
 
824
    }
 
825
 
 
826
    if(cfgfile) {
 
827
        if((fs = fopen(cfgfile, "r")) == NULL) {
 
828
            /* don't print error messages here! */
 
829
            optfree(opts);
 
830
            return NULL;
 
831
        }
 
832
    } else {
 
833
        if(MAX(sc, lc) > MAXCMDOPTS) {
 
834
            fprintf(stderr, "ERROR: optparse: (short|long)opts[] is too small\n");
 
835
            optfree(opts);
 
836
            return NULL;
 
837
        }
 
838
        shortopts[sc] = 0;
 
839
        longopts[lc].name = NULL;
 
840
        longopts[lc].flag = NULL;
 
841
        longopts[lc].has_arg = longopts[lc].val = 0;
 
842
    }
 
843
 
 
844
    while(1) {
 
845
 
 
846
        if(cfgfile) {
 
847
            if(!fgets(buffer, sizeof(buffer), fs))
 
848
                break;
 
849
 
 
850
            buff = buffer;
 
851
            for(i = 0; i < (int) strlen(buff) - 1 && (buff[i] == ' ' || buff[i] == '\t'); i++);
 
852
            buff += i;
 
853
            line++;
 
854
            if(strlen(buff) <= 2 || buff[0] == '#')
 
855
                continue;
 
856
 
 
857
            if(!strncmp("Example", buff, 7)) {
 
858
                if(verbose)
 
859
                    fprintf(stderr, "ERROR: Please edit the example config file %s\n", cfgfile);
 
860
                err = 1;
 
861
                break;
 
862
            }
 
863
 
 
864
            if(!(pt = strpbrk(buff, " \t"))) {
 
865
                if(verbose)
 
866
                    fprintf(stderr, "ERROR: Missing argument for option at line %d\n", line);
 
867
                err = 1;
 
868
                break;
 
869
            }
 
870
            name = buff;
 
871
            *pt++ = 0;
 
872
            for(i = 0; i < (int) strlen(pt) - 1 && (pt[i] == ' ' || pt[i] == '\t'); i++);
 
873
            pt += i;
 
874
            for(i = strlen(pt); i >= 1 && (pt[i - 1] == ' ' || pt[i - 1] == '\t' || pt[i - 1] == '\n'); i--);
 
875
            if(!i) {
 
876
                if(verbose)
 
877
                    fprintf(stderr, "ERROR: Missing argument for option at line %d\n", line);
 
878
                err = 1;
 
879
                break;
 
880
            }
 
881
            pt[i] = 0;
 
882
            arg = pt;
 
883
            if(*arg == '"') {
 
884
                arg++; pt++;
 
885
                pt = strrchr(pt, '"');
 
886
                if(!pt) {
 
887
                    if(verbose)
 
888
                        fprintf(stderr, "ERROR: Missing closing parenthesis in option %s at line %d\n", name, line);
 
889
                    err = 1;
 
890
                    break;
 
891
                }
 
892
                *pt = 0;
 
893
                if(!strlen(arg)) {
 
894
                    if(verbose)
 
895
                        fprintf(stderr, "ERROR: Empty argument for option %s at line %d\n", name, line);
 
896
                    err = 1;
 
897
                    break;
 
898
                }
 
899
            }
 
900
 
 
901
        } else {
 
902
            opt_index = 0;
 
903
            ret = my_getopt_long(argc, argv, shortopts, longopts, &opt_index);
 
904
            if(ret == -1)
 
905
                break;
 
906
 
 
907
            if(ret == ':') {
 
908
                fprintf(stderr, "ERROR: Incomplete option passed (missing argument)\n");
 
909
                err = 1;
 
910
                break;
 
911
            } else if(!ret || strchr(shortopts, ret)) {
 
912
                name = NULL;
 
913
                if(ret) {
 
914
                    for(i = 0; i < lc; i++) {
 
915
                        if(ret == longopts[i].val) {
 
916
                            name = longopts[i].name;
 
917
                            break;
 
918
                        }
 
919
                    }
 
920
                } else {
 
921
                    name = longopts[opt_index].name;
 
922
                }
 
923
                if(!name) {
 
924
                    fprintf(stderr, "ERROR: optparse: No corresponding long name for option '-%c'\n", (char) ret);
 
925
                    err = 1;
 
926
                    break;
 
927
                }
 
928
                optarg ? (arg = optarg) : (arg = NULL);
 
929
            } else {
 
930
                fprintf(stderr, "ERROR: Unknown option passed\n");
 
931
                err = 1;
 
932
                break;
 
933
            }
 
934
        }
 
935
 
 
936
        if(!name) {
 
937
            fprintf(stderr, "ERROR: Problem parsing options (name == NULL)\n");
 
938
            err = 1;
 
939
            break;
 
940
        }
 
941
 
 
942
        opt = optget_i(opts, name);
 
943
        if(!opt) {
 
944
            if(cfgfile) {
 
945
                if(verbose)
 
946
                    fprintf(stderr, "ERROR: Parse error at line %d: Unknown option %s\n", line, name);
 
947
            }
 
948
            err = 1;
 
949
            break;
 
950
        }
 
951
        optentry = &clam_options[opt->idx];
 
952
 
 
953
        if(ignore && (optentry->owner & ignore) && !(optentry->owner & toolmask)) {
 
954
            if(cfgfile) {
 
955
                if(verbose)
 
956
                    fprintf(stderr, "WARNING: Ignoring unsupported option %s at line %u\n", opt->name, line);
 
957
            } else {
 
958
                if(verbose) {
 
959
                    if(optentry->shortopt)
 
960
                        fprintf(stderr, "WARNING: Ignoring unsupported option --%s (-%c)\n", optentry->longopt, optentry->shortopt);
 
961
                    else
 
962
                        fprintf(stderr, "WARNING: Ignoring unsupported option --%s\n", optentry->longopt);
 
963
                }
 
964
            }
 
965
            continue;
 
966
        }
 
967
 
 
968
        if(optentry->owner & OPT_DEPRECATED) {
 
969
            if(toolmask & OPT_DEPRECATED) {
 
970
                if(optaddarg(opts, name, "foo", 1) < 0) {
 
971
                    if(cfgfile)
 
972
                        fprintf(stderr, "ERROR: Can't register argument for option %s\n", name);
 
973
                    else
 
974
                        fprintf(stderr, "ERROR: Can't register argument for option --%s\n", optentry->longopt);
 
975
                    err = 1;
 
976
                    break;
 
977
                }
 
978
            } else {
 
979
                if(cfgfile) {
 
980
                    if(verbose)
 
981
                        fprintf(stderr, "WARNING: Ignoring deprecated option %s at line %u\n", opt->name, line);
 
982
                } else {
 
983
                    if(verbose) {
 
984
                        if(optentry->shortopt)
 
985
                            fprintf(stderr, "WARNING: Ignoring deprecated option --%s (-%c)\n", optentry->longopt, optentry->shortopt);
 
986
                        else
 
987
                            fprintf(stderr, "WARNING: Ignoring deprecated option --%s\n", optentry->longopt);
 
988
                    }
 
989
                }
 
990
            }
 
991
            continue;
 
992
        }
 
993
 
 
994
        if(!cfgfile && !arg && optentry->argtype == CLOPT_TYPE_BOOL) {
 
995
            arg = "yes"; /* default to yes */
 
996
        } else if(optentry->regex) {
 
997
            if(!(optentry->flags & FLAG_REG_CASE))
 
998
                regflags |= REG_ICASE;
 
999
 
 
1000
            if(cli_regcomp(&regex, optentry->regex, regflags)) {
 
1001
                fprintf(stderr, "ERROR: optparse: Can't compile regular expression %s for option %s\n", optentry->regex, name);
 
1002
                err = 1;
 
1003
                break;
 
1004
            }
 
1005
            ret = cli_regexec(&regex, arg, 0, NULL, 0);
 
1006
            cli_regfree(&regex);
 
1007
            if(ret == REG_NOMATCH) {
 
1008
                if(cfgfile) {
 
1009
                    fprintf(stderr, "ERROR: Incorrect argument format for option %s\n", name);
 
1010
                } else {
 
1011
                    if(optentry->shortopt)
 
1012
                        fprintf(stderr, "ERROR: Incorrect argument format for option --%s (-%c)\n", optentry->longopt, optentry->shortopt);
 
1013
                    else
 
1014
                        fprintf(stderr, "ERROR: Incorrect argument format for option --%s\n", optentry->longopt);
 
1015
                }
 
1016
                err = 1;
 
1017
                break;
 
1018
            }
 
1019
        }
 
1020
 
 
1021
        numarg = -1;
 
1022
        switch(optentry->argtype) {
 
1023
            case CLOPT_TYPE_STRING:
 
1024
                if(!arg)
 
1025
                    arg = optentry->strarg;
 
1026
                if(!cfgfile && !strlen(arg)) {
 
1027
                    if(optentry->shortopt)
 
1028
                        fprintf(stderr, "ERROR: Option --%s (-%c) requires a non-empty string argument\n", optentry->longopt, optentry->shortopt);
 
1029
                    else
 
1030
                        fprintf(stderr, "ERROR: Option --%s requires a non-empty string argument\n", optentry->longopt);
 
1031
                    err = 1;
 
1032
                    break;
 
1033
                }
 
1034
                break;
 
1035
 
 
1036
            case CLOPT_TYPE_NUMBER:
 
1037
                if (arg)
 
1038
                    numarg = atoi(arg);
 
1039
                else
 
1040
                    numarg = 0;
 
1041
                arg = NULL;
 
1042
                break;
 
1043
 
 
1044
            case CLOPT_TYPE_SIZE:
 
1045
                errno = 0;
 
1046
                if(arg)
 
1047
                    lnumarg = strtoul(arg, &buff, 0);
 
1048
                else {
 
1049
                    numarg = 0;
 
1050
                    break;
 
1051
                }
 
1052
                if(errno != ERANGE) {
 
1053
                    switch(*buff) {
 
1054
                    case 'M':
 
1055
                    case 'm':
 
1056
                        if(lnumarg <= UINT_MAX/(1024*1024)) lnumarg *= 1024*1024;
 
1057
                        else errno = ERANGE;
 
1058
                        break;
 
1059
                    case 'K':
 
1060
                    case 'k':
 
1061
                        if(lnumarg <= UINT_MAX/1024) lnumarg *= 1024;
 
1062
                        else errno = ERANGE;
 
1063
                        break;
 
1064
                    case '\0':
 
1065
                        break;
 
1066
                    default:
 
1067
                        if(cfgfile) {
 
1068
                            fprintf(stderr, "ERROR: Can't parse numerical argument for option %s\n", name);
 
1069
                        } else {
 
1070
                            if(optentry->shortopt)
 
1071
                                fprintf(stderr, "ERROR: Can't parse numerical argument for option --%s (-%c)\n", optentry->longopt, optentry->shortopt);
 
1072
                            else
 
1073
                                fprintf(stderr, "ERROR: Can't parse numerical argument for option --%s\n", optentry->longopt);
 
1074
                        }
 
1075
                        err = 1;
 
1076
                    }
 
1077
                }
 
1078
 
 
1079
                arg = NULL;
 
1080
                if(err) break;
 
1081
                if(errno == ERANGE) {
 
1082
                    if(cfgfile) {
 
1083
                        fprintf(stderr, "WARNING: Numerical value for option %s too high, resetting to 4G\n", name);
 
1084
                    } else {
 
1085
                        if(optentry->shortopt)
 
1086
                            fprintf(stderr, "WARNING: Numerical value for option --%s (-%c) too high, resetting to 4G\n", optentry->longopt, optentry->shortopt);
 
1087
                        else
 
1088
                            fprintf(stderr, "WARNING: Numerical value for option %s too high, resetting to 4G\n", optentry->longopt);
 
1089
                    }
 
1090
                    lnumarg = UINT_MAX;
 
1091
                }
 
1092
 
 
1093
                numarg = lnumarg ? lnumarg : UINT_MAX;
 
1094
                break;
 
1095
 
 
1096
            case CLOPT_TYPE_BOOL:
 
1097
                if(!strcasecmp(arg, "yes") || !strcmp(arg, "1") || !strcasecmp(arg, "true"))
 
1098
                    numarg = 1;
 
1099
                else
 
1100
                    numarg = 0;
 
1101
 
 
1102
                arg = NULL;
 
1103
                break;
 
1104
        }
 
1105
 
 
1106
        if(err)
 
1107
            break;
 
1108
 
 
1109
        if(optaddarg(opts, name, arg, numarg) < 0) {
 
1110
            if(cfgfile)
 
1111
                fprintf(stderr, "ERROR: Can't register argument for option %s\n", name);
 
1112
            else
 
1113
                fprintf(stderr, "ERROR: Can't register argument for option --%s\n", optentry->longopt);
 
1114
            err = 1;
 
1115
            break;
 
1116
        }
 
1117
    }
 
1118
 
 
1119
    if(fs)
 
1120
        fclose(fs);
 
1121
 
 
1122
    if(err) {
 
1123
        optfree(opts);
 
1124
        return NULL;
 
1125
    }
 
1126
 
 
1127
    if(!cfgfile && opts && (optind < argc)) {
 
1128
        opts->filename = (char **) calloc(argc - optind + 1, sizeof(char *));
 
1129
        if(!opts->filename) {
 
1130
            fprintf(stderr, "ERROR: optparse: calloc failed\n");
 
1131
            optfree(opts);
 
1132
            return NULL;
 
1133
        }
 
1134
        for(i = optind; i < argc; i++) {
 
1135
            opts->filename[i - optind] = strdup(argv[i]);
 
1136
            if(!opts->filename[i - optind]) {
 
1137
                fprintf(stderr, "ERROR: optparse: strdup failed\n");
 
1138
                optfree(opts);
 
1139
                return NULL;
 
1140
            }
 
1141
        }
 
1142
    }
 
1143
 
 
1144
    /* optprint(opts); */
 
1145
 
 
1146
    return opts;
 
1147
}
 
1148
 
 
1149
struct optstruct *optadditem(const char *name, const char *arg, int verbose, int toolmask, int ignore,
 
1150
                            struct optstruct *oldopts)
 
1151
{
 
1152
        int i, err = 0, sc = 0, lc=0, line = 0, ret;
 
1153
        struct optstruct *opts = NULL, *opts_last = NULL, *opt;
 
1154
        char *buff;
 
1155
        regex_t regex;
 
1156
        long long numarg, lnumarg;
 
1157
        int regflags = REG_EXTENDED | REG_NOSUB;
 
1158
    const struct clam_option *optentry = NULL;
 
1159
    
 
1160
    if(oldopts)
 
1161
        opts = oldopts;
 
1162
    
 
1163
    
 
1164
    for(i = 0; ; i++) {
 
1165
        optentry = &clam_options[i];
 
1166
        if(!optentry->name && !optentry->longopt)
 
1167
            break;
 
1168
        
 
1169
        if(((optentry->owner & toolmask) && ((optentry->owner & toolmask) != OPT_DEPRECATED)) || (ignore && (optentry->owner & ignore))) {
 
1170
            if(!oldopts && optadd(&opts, &opts_last, optentry->name, optentry->longopt, optentry->strarg, optentry->numarg, optentry->flags, i) < 0) {
 
1171
                fprintf(stderr, "ERROR: optparse: Can't register new option (not enough memory)\n");
 
1172
                optfree(opts);
 
1173
                return NULL;
 
1174
            }
 
1175
            
 
1176
        }
 
1177
    }
 
1178
    
 
1179
    if(MAX(sc, lc) > MAXCMDOPTS) {
 
1180
            fprintf(stderr, "ERROR: optparse: (short|long)opts[] is too small\n");
 
1181
            optfree(opts);
 
1182
            return NULL;
 
1183
        }
 
1184
    
 
1185
    while(1) {
 
1186
        if(!name) {
 
1187
            fprintf(stderr, "ERROR: Problem parsing options (name == NULL)\n");
 
1188
            err = 1;
 
1189
            break;
 
1190
        }
 
1191
        
 
1192
        opt = optget_i(opts, name);
 
1193
        if(!opt) {
 
1194
            if(verbose)
 
1195
                fprintf(stderr, "ERROR: Parse error at line %d: Unknown option %s\n", line, name);
 
1196
            err = 1;
 
1197
            break;
 
1198
        }
 
1199
        optentry = &clam_options[opt->idx];
 
1200
        
 
1201
        if(ignore && (optentry->owner & ignore) && !(optentry->owner & toolmask)) {
 
1202
            if(verbose)
 
1203
                fprintf(stderr, "WARNING: Ignoring unsupported option %s at line %u\n", opt->name, line);
 
1204
            continue;
 
1205
        }
 
1206
        
 
1207
        if(optentry->owner & OPT_DEPRECATED) {
 
1208
            if(toolmask & OPT_DEPRECATED) {
 
1209
                if(optaddarg(opts, name, "foo", 1) < 0) {
 
1210
                    fprintf(stderr, "ERROR: Can't register argument for option %s\n", name);
 
1211
                    err = 1;
 
1212
                    break;
 
1213
                }
 
1214
            } else {
 
1215
                if(verbose)
 
1216
                    fprintf(stderr, "WARNING: Ignoring deprecated option %s at line %u\n", opt->name, line);
 
1217
            }
 
1218
            continue;
 
1219
        }
 
1220
        
 
1221
        if(optentry->regex) {
 
1222
            if(!(optentry->flags & FLAG_REG_CASE))
 
1223
                regflags |= REG_ICASE;
 
1224
            
 
1225
            if(cli_regcomp(&regex, optentry->regex, regflags)) {
 
1226
                fprintf(stderr, "ERROR: optparse: Can't compile regular expression %s for option %s\n", optentry->regex, name);
 
1227
                err = 1;
 
1228
                break;
 
1229
            }
 
1230
            ret = cli_regexec(&regex, arg, 0, NULL, 0);
 
1231
            cli_regfree(&regex);
 
1232
            if(ret == REG_NOMATCH) {
 
1233
                fprintf(stderr, "ERROR: Incorrect argument format for option %s\n", name);
 
1234
                err = 1;
 
1235
                break;
 
1236
            }
 
1237
        }
 
1238
        
 
1239
        numarg = -1;
 
1240
        switch(optentry->argtype) {
 
1241
            case CLOPT_TYPE_STRING:
 
1242
                if(!arg)
 
1243
                    arg = optentry->strarg;
 
1244
                
 
1245
                break;
 
1246
                
 
1247
            case CLOPT_TYPE_NUMBER:
 
1248
                if (arg)
 
1249
                    numarg = atoi(arg);
 
1250
                else
 
1251
                    numarg = 0;
 
1252
                arg = NULL;
 
1253
                break;
 
1254
                
 
1255
            case CLOPT_TYPE_SIZE:
 
1256
                errno = 0;
 
1257
                if(arg)
 
1258
                    lnumarg = strtoul(arg, &buff, 0);
 
1259
                else {
 
1260
                    numarg = 0;
 
1261
                    break;
 
1262
                }
 
1263
                if(errno != ERANGE) {
 
1264
                    switch(*buff) {
 
1265
                        case 'M':
 
1266
                        case 'm':
 
1267
                            if(lnumarg <= UINT_MAX/(1024*1024)) lnumarg *= 1024*1024;
 
1268
                            else errno = ERANGE;
 
1269
                            break;
 
1270
                        case 'K':
 
1271
                        case 'k':
 
1272
                            if(lnumarg <= UINT_MAX/1024) lnumarg *= 1024;
 
1273
                            else errno = ERANGE;
 
1274
                            break;
 
1275
                        case '\0':
 
1276
                            break;
 
1277
                        default:
 
1278
                            fprintf(stderr, "ERROR: Can't parse numerical argument for option %s\n", name);
 
1279
                            err = 1;
 
1280
                    }
 
1281
                }
 
1282
                
 
1283
                arg = NULL;
 
1284
                if(err) break;
 
1285
                if(errno == ERANGE) {
 
1286
                    fprintf(stderr, "WARNING: Numerical value for option %s too high, resetting to 4G\n", name);
 
1287
                    lnumarg = UINT_MAX;
 
1288
                }
 
1289
                
 
1290
                numarg = lnumarg ? lnumarg : UINT_MAX;
 
1291
                break;
 
1292
                
 
1293
            case CLOPT_TYPE_BOOL:
 
1294
                if(!strcasecmp(arg, "yes") || !strcmp(arg, "1") || !strcasecmp(arg, "true"))
 
1295
                    numarg = 1;
 
1296
                else
 
1297
                    numarg = 0;
 
1298
                
 
1299
                arg = NULL;
 
1300
                break;
 
1301
        }
 
1302
        
 
1303
        if(err)
 
1304
            break;
 
1305
        
 
1306
        if(optaddarg(opts, name, arg, numarg) < 0) {
 
1307
            fprintf(stderr, "ERROR: Can't register argument for option --%s\n", optentry->longopt);
 
1308
            err = 1;
 
1309
        }
 
1310
        break;
 
1311
    }
 
1312
    
 
1313
    if(err) {
 
1314
        optfree(opts);
 
1315
        return NULL;
 
1316
    }
 
1317
      
 
1318
    return opts;
 
1319
}