Browse code

major cleanup

git-svn: trunk@2023

Tomasz Kojm authored on 2006/06/15 20:59:39
Showing 2 changed files
... ...
@@ -1,3 +1,7 @@
1
+Thu Jun 15 13:57:38 CEST 2006 (tk)
2
+----------------------------------
3
+  * sigtool/sigtool.c: major cleanup
4
+
1 5
 Mon Jun 12 14:24:35 BST 2006 (njh)
2 6
 ----------------------------------
3 7
   * libclamav/message.c:	Better detection of binhex encoded EICAR
... ...
@@ -40,363 +40,341 @@
40 40
 #include <sys/wait.h>
41 41
 #include <dirent.h>
42 42
 
43
-#include "options.h"
44
-#include "others.h"
45
-#include "strings.h"
46
-#include "md5.h"
47
-#include "cvd.h"
48
-#include "str.h"
49
-#include "memory.h"
50
-#include "output.h"
51
-#include "cfgparser.h"
52
-#include "misc.h"
53 43
 #include "vba.h"
54
-#include "../clamscan/others.h"
55
-#include "../libclamav/others.h"
56
-#include "../libclamav/str.h"
57
-#include "../libclamav/ole2_extract.h"
58
-#include "../libclamav/htmlnorm.h"
59
-
60
-#ifndef	O_BINARY
61
-#define	O_BINARY	0
62
-#endif
63
-
64
-void help(void);
65
-char *getdsig(const char *host, const char *user, const char *data);
66
-void cvdinfo(struct optstruct *opt);
67
-int build(struct optstruct *opt);
68
-int unpack(struct optstruct *opt);
69
-int listdb(const char *filename);
70
-int listdir(const char *dirname);
71
-void listsigs(struct optstruct *opt);
72 44
 
45
+#include "shared/options.h"
46
+#include "shared/memory.h"
47
+#include "shared/output.h"
48
+#include "shared/cfgparser.h"
49
+#include "shared/misc.h"
73 50
 
74
-int main(int argc, char **argv)
75
-{
76
-        struct optstruct *opt;
77
-	const char *short_options = "hvVb:i:u:l::";
78
-	static struct option long_options[] = {
79
-	    {"help", 0, 0, 'h'},
80
-	    {"quiet", 0, 0, 0},
81
-	    {"debug", 0, 0, 0},
82
-	    {"verbose", 0, 0, 'v'},
83
-	    {"stdout", 0, 0, 0},
84
-	    {"version", 0, 0, 'V'},
85
-	    {"tempdir", 1, 0, 0},
86
-	    {"hex-dump", 0, 0, 0},
87
-	    {"md5", 0, 0, 0},
88
-	    {"html-normalise", 1, 0, 0},
89
-	    {"build", 1, 0, 'b'},
90
-	    {"server", 1, 0, 0},
91
-	    {"unpack", 1, 0, 'u'},
92
-	    {"unpack-current", 1, 0, 0},
93
-	    {"info", 1, 0, 'i'},
94
-	    {"list-sigs", 2, 0, 'l'},
95
-	    {"vba", 1, 0 ,0},
96
-	    {"vba-hex", 1, 0, 0},
97
-	    {0, 0, 0, 0}
98
-    	};
99
-
100
-
101
-    opt = opt_parse(argc, argv, short_options, long_options, NULL);
102
-    if(!opt) {
103
-	mprintf("!Can't parse the command line\n");
104
-	return 1;
105
-    }
106
-
107
-    if(opt_check(opt, "quiet"))
108
-	mprintf_quiet = 1;
51
+#include "libclamav/cvd.h"
52
+#include "libclamav/others.h"
53
+#include "libclamav/str.h"
54
+#include "libclamav/ole2_extract.h"
55
+#include "libclamav/htmlnorm.h"
109 56
 
110
-    if(opt_check(opt, "stdout"))
111
-	mprintf_stdout = 1;
112 57
 
113
-    if(opt_check(opt, "debug"))
114
-	cl_debug();
58
+static int hexdump(void)
59
+{
60
+	char buffer[FILEBUFF], *pt;
61
+	int bytes;
115 62
 
116
-    if(opt_check(opt, "version")) {
117
-	print_version();
118
-	opt_free(opt);
119
-	exit(0);
120
-    }
121 63
 
122
-    if(opt_check(opt, "help")) {
123
-	opt_free(opt);
124
-    	help();
64
+    while((bytes = read(0, buffer, FILEBUFF)) > 0) {
65
+	pt = cli_str2hex(buffer, bytes);
66
+	if(write(1, pt, 2 * bytes) == -1) {
67
+	    logg("!hexdump: Can't write to stdout\n");
68
+	    free(pt);
69
+	    return -1;
70
+	}
71
+	free(pt);
125 72
     }
126 73
 
127
-    if(opt_check(opt, "hex-dump")) {
128
-	    char buffer[FILEBUFF];
129
-	    int bytes;
130
-	    char *pt;
74
+    if(bytes == -1)
75
+	return -1;
131 76
 
132
-	while((bytes = read(0, buffer, FILEBUFF)) > 0) {
133
-	    pt = cli_str2hex(buffer, bytes);
134
-	    write(1, pt, 2 * bytes);
135
-	    free(pt);
136
-	}
77
+    return 0;
78
+}
137 79
 
138
-    } else if(opt_check(opt, "md5")) {
139
-	    char *md5, *filename;
140
-	    int i;
141
-	    struct stat sb;
80
+static int md5sig(struct optstruct *opt)
81
+{
82
+	char *md5, *filename;
83
+	int i;
84
+	struct stat sb;
142 85
 
143
-	mprintf_stdout = 1;
144 86
 
145
-	if(opt->filename) {
146
-
147
-	    for(i = 0; (filename = cli_strtok(opt->filename, i, "\t")); i++) {
148
-		if(stat(filename, &sb) == -1) {
149
-		    logg("!Can't access file %s\n", filename);
150
-		    perror(filename);
151
-		} else {
152
-		    if((sb.st_mode & S_IFMT) == S_IFREG) {
153
-			if((md5 = cli_md5file(filename))) {
154
-			    logg("%s:%d:%s\n", md5, sb.st_size, filename);
155
-			    free(md5);
156
-			} else
157
-			    logg("!Can't generate MD5 checksum for %s\n", filename);
87
+    if(opt->filename) {
88
+	for(i = 0; (filename = cli_strtok(opt->filename, i, "\t")); i++) {
89
+	    if(stat(filename, &sb) == -1) {
90
+		logg("!md5sig: Can't access file %s\n", filename);
91
+		perror("md5sig");
92
+		free(filename);
93
+		return -1;
94
+	    } else {
95
+		if((sb.st_mode & S_IFMT) == S_IFREG) {
96
+		    if((md5 = cli_md5file(filename))) {
97
+			logg("%s:%d:%s\n", md5, sb.st_size, filename);
98
+			free(md5);
99
+		    } else {
100
+			logg("!md5sig: Can't generate MD5 checksum for %s\n", filename);
101
+			free(filename);
102
+			return -1;
158 103
 		    }
159 104
 		}
160
-
161
-		free(filename);
162 105
 	    }
163 106
 
164
-	} else {
165
-
166
-	    md5 = cli_md5stream(stdin, NULL);
167
-	    logg("%s\n", md5);
168
-	    free(md5);
169
-	}
170
-
171
-    } else if(opt_check(opt, "html-normalise")) {
172
-	    int fd;
173
-
174
-	if((fd = open(opt_arg(opt, "html-normalise"), O_RDONLY)) == -1) {
175
-	    logg("Can't open file %s\n", opt_arg(opt, "html-normalise"));
176
-	    opt_free(opt);
177
-	    exit(1);
107
+	    free(filename);
178 108
 	}
179 109
 
180
-	html_normalise_fd(fd, ".", NULL);
181
-
182
-	close(fd);
183
-
184
-    } else if(opt_check(opt, "build")) {
185
-	if(!opt_check(opt, "server")) {
186
-	    logg("!--server is required in this mode\n");
187
-	    opt_free(opt);
188
-	    exit(10);
110
+    } else { /* stream */
111
+	md5 = cli_md5stream(stdin, NULL);
112
+	if(!md5) {
113
+	    logg("!md5sig: Can't generate MD5 checksum for input stream\n");
114
+	    return -1;
189 115
 	}
116
+	logg("%s\n", md5);
117
+	free(md5);
118
+    }
190 119
 
191
-	build(opt);
120
+    return 0;
121
+}
192 122
 
193
-    } else if(opt_check(opt, "unpack")) {
123
+static int htmlnorm(struct optstruct *opt)
124
+{
125
+	int fd;
194 126
 
195
-	unpack(opt);
196 127
 
197
-    } else if(opt_check(opt, "unpack-current")) {
128
+    if((fd = open(opt_arg(opt, "html-normalise"), O_RDONLY)) == -1) {
129
+	logg("!htmlnorm: Can't open file %s\n", opt_arg(opt, "html-normalise"));
130
+	return -1;
131
+    }
198 132
 
199
-	unpack(opt);
133
+    html_normalise_fd(fd, ".", NULL);
134
+    close(fd);
200 135
 
201
-    } else if(opt_check(opt, "info")) {
136
+    return 0;
137
+}
202 138
 
203
-	cvdinfo(opt);
139
+static unsigned int countlines(const char *filename)
140
+{
141
+	FILE *fd;
142
+	char buff[1024];
143
+	unsigned int lines = 0;
204 144
 
205
-    } else if(opt_check(opt, "list-sigs")) {
206 145
 
207
-	listsigs(opt);
146
+    if((fd = fopen(filename, "r")) == NULL)
147
+	return 0;
208 148
 
209
-    } else if(opt_check(opt, "vba") || opt_check(opt, "vba-hex")) {
210
-            int fd, hex_output=0;
211
-	    char *dir;
149
+    while(fgets(buff, sizeof(buff), fd)) {
150
+	if(buff[0] == '#') continue;
151
+	lines++;
152
+    }
212 153
 
154
+    fclose(fd);
155
+    return lines;
156
+}
213 157
 
214
-	if (opt_check(opt, "vba-hex"))
215
-		hex_output = 1;
216
- 
217
-        /* generate the temporary directory */
218
-        dir = cli_gentemp(NULL);
219
-        if(mkdir(dir, 0700)) {
220
-            logg("vba dump: Can't create temporary directory %s\n", dir);
221
-	    free(dir);
222
-	    opt_free(opt);
223
-            return 1;
224
-        }
225
-
226
-        if((fd = open(opt_arg(opt, "vba"), O_RDONLY)) == -1) {
227
-	    if((fd = open(opt_arg(opt, "vba-hex"), O_RDONLY)) == -1) {
228
-        	logg("Can't open file %s\n", opt_arg(opt, "vba"));
229
-		opt_free(opt);
230
-        	exit(1);
231
-	    }
232
-        }
158
+static char *getdsig(const char *host, const char *user, const char *data)
159
+{
160
+	char buff[256], cmd[128], *pass, *pt;
161
+        struct sockaddr_in server;
162
+	int sockd, bread, len;
233 163
 
234
-        if(cli_ole2_extract(fd, dir, NULL)) {
235
-            cli_rmdirs(dir);
236
-            free(dir);
237
-	    close(fd);
238
-	    opt_free(opt);
239
-            return 1;
240
-        }
241 164
 
242
-	close(fd);
243
-        sigtool_vba_scandir(dir, hex_output);
244
-        cli_rmdirs(dir);
245
-        free(dir);
165
+#ifdef PF_INET
166
+    if((sockd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
167
+#else
168
+    if((sockd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
169
+#endif
170
+	perror("socket()");
171
+	logg("!getdsig: Can't create socket\n");
172
+	return NULL;
173
+    }
246 174
 
247
-    } else {
175
+    server.sin_family = AF_INET;
176
+    server.sin_addr.s_addr = inet_addr(host);
177
+    server.sin_port = htons(33101);
248 178
 
249
-	help();
179
+    if(connect(sockd, (struct sockaddr *) &server, sizeof(struct sockaddr_in)) < 0) {
180
+        close(sockd);
181
+	perror("connect()");
182
+	logg("!getdsig: Can't connect to ClamAV Signing Service at %s\n", host);
183
+	return NULL;
250 184
     }
251 185
 
252
-}
253
-
254
-static int countlines(const char *filename)
255
-{
256
-	FILE *fd;
257
-	char buff[65536];
258
-	int lines = 0;
186
+    memset(cmd, 0, sizeof(cmd));
187
+    pass = getpass("Password:");
188
+    snprintf(cmd, sizeof(cmd) - 16, "ClamSign:%s:%s:", user, pass);
189
+    len = strlen(cmd);
190
+    pt = cmd + len;
191
+    memcpy(pt, data, 16);
192
+    len += 16;
259 193
 
194
+    if(write(sockd, cmd, len) < 0) {
195
+	logg("!getdsig: Can't write to socket\n");
196
+	close(sockd);
197
+	memset(cmd, 0, len);
198
+	memset(pass, 0, strlen(pass));
199
+	return NULL;
200
+    }
260 201
 
261
-    if((fd = fopen(filename, "r")) == NULL)
262
-	return 0;
202
+    memset(cmd, 0, len);
203
+    memset(pass, 0, strlen(pass));
204
+    memset(buff, 0, sizeof(buff));
263 205
 
264
-    while(fgets(buff, sizeof(buff), fd)) {
265
-	if(buff[0] == '#') continue;
266
-	lines++;
206
+    if((bread = read(sockd, buff, sizeof(buff))) > 0) {
207
+	if(!strstr(buff, "Signature:")) {
208
+	    logg("!getdsig: Error generating digital signature\n");
209
+	    logg("!getdsig: Answer from remote server: %s\n", buff);
210
+	    close(sockd);
211
+	    return NULL;
212
+	} else {
213
+	    logg("Signature received (length = %d)\n", strlen(buff) - 10);
214
+	}
267 215
     }
268 216
 
269
-    fclose(fd);
270
-    return lines;
217
+    close(sockd);
218
+    pt = buff;
219
+    pt += 10;
220
+    return strdup(pt);
271 221
 }
272 222
 
273
-int build(struct optstruct *opt)
223
+static int build(struct optstruct *opt)
274 224
 {
275
-	int ret, no = 0, realno = 0, bytes, itmp;
225
+	int ret, itmp;
226
+	size_t bytes;
227
+	unsigned int sigs = 0, lines = 0;
276 228
 	struct stat foo;
277
-	char buffer[FILEBUFF], *tarfile = NULL, *gzfile = NULL, header[513],
229
+	char buffer[FILEBUFF], *tarfile, *gzfile, header[513],
278 230
 	     smbuff[30], *pt, *dbdir;
279 231
         struct cl_node *root = NULL;
280
-	FILE *tar, *cvd, *fd;
232
+	FILE *tar, *cvd;
281 233
 	gzFile *gz;
282 234
 	time_t timet;
283 235
 	struct tm *brokent;
284 236
 	struct cl_cvd *oldcvd = NULL;
285 237
 
286 238
 
287
-    if(stat("COPYING", &foo) == -1) {
288
-	logg("COPYING file not found in current working directory.\n");
289
-	opt_free(opt);
290
-	exit(1);
239
+    if(!opt_check(opt, "server")) {
240
+	logg("!build: --server is required for --build\n");
241
+	return -1;
291 242
     }
292 243
 
293
-    if(stat("main.db", &foo) == -1 && stat("daily.db", &foo) == -1 && stat("main.hdb", &foo) == -1 && stat("daily.hdb", &foo) == -1 && stat("main.ndb", &foo) == -1 && stat("daily.ndb", &foo) == -1 && stat("main.zmd", &foo) == -1 && stat("main.rmd", &foo) == -1 && stat("daily.zmd", &foo) == -1 && stat("daily.rmd", &foo) == -1) {
294
-	logg("Virus database not found in current working directory.\n");
295
-	opt_free(opt);
296
-	exit(1);
244
+    if(stat("COPYING", &foo) == -1) {
245
+	logg("!build: COPYING file not found in current working directory.\n");
246
+	return -1;
297 247
     }
298 248
 
299
-    cl_debug(); /* enable debug messages */
300
-
301
-    if((ret = cl_loaddbdir(".", &root, &no))) {
302
-	logg("!Can't load database: %s\n", cl_strerror(ret));
303
-	opt_free(opt);
304
-	exit(1);
249
+    if(stat("main.db", &foo) == -1 && stat("daily.db", &foo) == -1 &&
250
+       stat("main.hdb", &foo) == -1 && stat("daily.hdb", &foo) == -1 &&
251
+       stat("main.ndb", &foo) == -1 && stat("daily.ndb", &foo) == -1 &&
252
+       stat("main.zmd", &foo) == -1 && stat("daily.zmd", &foo) == -1 &&
253
+       stat("main.rmd", &foo) == -1 && stat("daily.rmd", &foo) == -1)
254
+    {
255
+	logg("!build: No virus database file  found in current directory\n");
256
+	return -1;
305 257
     }
306 258
 
307
-    cl_free(root);
259
+    cl_debug(); /* enable debug messages in libclamav */
308 260
 
309
-    logg("Database properly parsed.\n");
261
+    if((ret = cl_loaddbdir(".", &root, &sigs))) {
262
+	logg("!build: Can't load database: %s\n", cl_strerror(ret));
263
+	return -1;
264
+    } else {
265
+	cl_free(root);
266
+    }
310 267
 
311
-    if(!no) {
312
-	logg("^There are no signatures in the database(s).\n");
268
+    if(!sigs) {
269
+	logg("!build: There are no signatures in database files\n");
313 270
     } else {
314
-	logg("Signatures: %d\n", no);
315
-	realno = countlines("main.db") + countlines("daily.db") + countlines("main.hdb") + countlines("daily.hdb") + countlines("main.ndb") + countlines("daily.ndb") + countlines("main.zmd") + countlines("daily.zmd") + countlines("main.rmd") + countlines("daily.rmd") + countlines("main.fp") + countlines("daily.fp");
316
-	if(realno != no) {
317
-	    logg("!Signatures in database: %d. Loaded: %d.\n", realno, no);
318
-	    logg("Please check the current directory and remove unnecessary databases\n");
319
-	    logg("or install the latest ClamAV version.\n");
320
-	    opt_free(opt);
321
-	    exit(1);
271
+	logg("Signatures: %d\n", sigs);
272
+	lines = countlines("main.db") + countlines("daily.db") +
273
+		countlines("main.hdb") + countlines("daily.hdb") +
274
+		countlines("main.ndb") + countlines("daily.ndb") +
275
+		countlines("main.zmd") + countlines("daily.zmd") +
276
+		countlines("main.rmd") + countlines("daily.rmd") +
277
+		countlines("main.fp") + countlines("daily.fp");
278
+
279
+	if(lines != sigs) {
280
+	    logg("!build: Signatures in database: %d, loaded by libclamav: %d\n", lines, sigs);
281
+	    logg("!build: Please check the current directory and remove unnecessary databases\n");
282
+	    logg("!build: or install the latest ClamAV version.\n");
283
+	    return -1;
322 284
 	}
323 285
     }
324 286
 
325
-    tarfile = cli_gentemp(".");
287
+    if(!(tarfile = cli_gentemp("."))) {
288
+	logg("!build: Can't generate temporary name for tarfile\n");
289
+	return -1;
290
+    }
326 291
 
327 292
     switch(fork()) {
328 293
 	case -1:
329
-	    logg("!Can't fork.\n");
330
-	    opt_free(opt);
331
-	    exit(1);
294
+	    logg("!build: Can't fork.\n");
295
+	    free(tarfile);
296
+	    return -1;
332 297
 	case 0:
333 298
 	    {
334
-		char *args[] = { "tar", "-cvf", NULL, "COPYING", "main.db", "daily.db", "Notes", "viruses.db3", "main.hdb", "daily.hdb", "main.ndb", "daily.ndb", "main.zmd", "daily.zmd", "main.rmd", "daily.rmd", "main.fp", "daily.fp", NULL };
299
+		char *args[] = { "tar", "-cvf", NULL, "COPYING", "main.db",
300
+				 "daily.db", "main.hdb", "daily.hdb",
301
+				 "main.ndb", "daily.ndb", "main.zmd",
302
+				 "daily.zmd", "main.rmd", "daily.rmd",
303
+				 "main.fp", "daily.fp", NULL };
335 304
 		args[2] = tarfile;
336 305
 		execv("/bin/tar", args);
337
-		logg("!Can't execute tar\n");
306
+		logg("!build: Can't execute tar\n");
338 307
 		perror("tar");
339
-		opt_free(opt);
340
-		exit(1);
308
+		free(tarfile);
309
+		return -1;
341 310
 	    }
342 311
 	default:
343 312
 	    wait(NULL);
344 313
     }
345 314
 
346 315
     if(stat(tarfile, &foo) == -1) {
347
-	logg("!Can't generate tar file.\n");
348
-	opt_free(opt);
349
-	exit(1);
316
+	logg("!build: Tar archive was not created\n");
317
+	free(tarfile);
318
+	return -1;
350 319
     }
351 320
 
352 321
     if((tar = fopen(tarfile, "rb")) == NULL) {
353
-	logg("!Can't open file %s\n", tarfile);
354
-	opt_free(opt);
355
-	exit(1);
322
+	logg("!build: Can't open file %s\n", tarfile);
323
+	free(tarfile);
324
+	return -1;
325
+    }
326
+
327
+    if(!(gzfile = cli_gentemp("."))) {
328
+	logg("!build: Can't generate temporary name for gzfile\n");
329
+	free(tarfile);
330
+	fclose(tar);
331
+	return -1;
356 332
     }
357 333
 
358
-    gzfile = cli_gentemp(".");
359 334
     if((gz = gzopen(gzfile, "wb")) == NULL) {
360
-	logg("!Can't open file %s to write.\n", gzfile);
361
-	opt_free(opt);
362
-	exit(1);
335
+	logg("!build: Can't open file %s to write.\n", gzfile);
336
+	free(tarfile);
337
+	fclose(tar);
338
+	free(gzfile);
339
+	return -1;
363 340
     }
364 341
 
365
-    while((bytes = fread(buffer, 1, FILEBUFF, tar)) > 0)
366
-	gzwrite(gz, buffer, bytes);
342
+    while((bytes = fread(buffer, 1, FILEBUFF, tar)) > 0) {
343
+	if(!gzwrite(gz, buffer, bytes)) {
344
+	    logg("!build: Can't gzwrite to %s\n", gzfile);
345
+	    fclose(tar);
346
+	    gzclose(gz);
347
+	    free(tarfile);
348
+	    free(gzfile);
349
+	    return -1;
350
+	}
351
+    }
367 352
 
368 353
     fclose(tar);
354
+    gzclose(gz);
369 355
     unlink(tarfile);
370 356
     free(tarfile);
371 357
 
372
-    gzclose(gz);
373
-
374
-
375
-    /* try to read cvd header of old database */
358
+    /* try to read cvd header of current database */
376 359
     dbdir = freshdbdir();
377
-    sprintf(buffer, "%s/%s", dbdir, opt_arg(opt, "build"));
360
+    snprintf(buffer, sizeof(buffer), "%s/%s", dbdir, opt_arg(opt, "build"));
378 361
     free(dbdir);
379
-    if((oldcvd = cl_cvdhead(buffer)) == NULL)
380
-	logg("^CAN'T READ CVD HEADER OF CURRENT DATABASE %s\n", buffer);
381
-
382
-    /* generate header */
383
-
384
-    /* magic string */
362
+    if((oldcvd = cl_cvdhead(buffer)) == NULL) {
363
+	logg("^build: CAN'T READ CVD HEADER OF CURRENT DATABASE %s\n", buffer);
364
+	sleep(3);
365
+    }
385 366
 
367
+    /* build header */
386 368
     strcpy(header, "ClamAV-VDB:");
387 369
 
388 370
     /* time */
389
-
390 371
     time(&timet);
391 372
     brokent = localtime(&timet);
392 373
     setlocale(LC_TIME, "C");
393
-    strftime(smbuff, 30, "%d %b %Y %H-%M %z", brokent);
374
+    strftime(smbuff, sizeof(smbuff), "%d %b %Y %H-%M %z", brokent);
394 375
     strcat(header, smbuff);
395 376
 
396
-    /* version number */
397
-
398
-    /* ... increment version number by one */
399
-
377
+    /* increment version number by one */
400 378
     if(oldcvd) {
401 379
 	sprintf(smbuff, ":%d:", oldcvd->version + 1);
402 380
     } else {
... ...
@@ -408,7 +386,7 @@ int build(struct optstruct *opt)
408 408
     strcat(header, smbuff);
409 409
 
410 410
     /* number of signatures */
411
-    sprintf(smbuff, "%d:", no);
411
+    sprintf(smbuff, "%d:", sigs);
412 412
     strcat(header, smbuff);
413 413
 
414 414
     /* functionality level */
... ...
@@ -416,28 +394,52 @@ int build(struct optstruct *opt)
416 416
     strcat(header, smbuff);
417 417
 
418 418
     /* MD5 */
419
-    pt = cli_md5file(gzfile);
419
+    if(!(pt = cli_md5file(gzfile))) {
420
+	logg("!build: Can't generate MD5 checksum for gzfile\n");
421
+	unlink(gzfile);
422
+	free(gzfile);
423
+	return -1;
424
+    }
420 425
     strcat(header, pt);
421 426
     free(pt);
422 427
     strcat(header, ":");
423 428
 
424 429
     /* ask for builder name */
425 430
     fflush(stdin);
426
-    logg("Builder id: ");
427
-    fscanf(stdin, "%s", smbuff);
431
+    logg("Builder name: ");
432
+    if(fgets(smbuff, sizeof(smbuff), stdin)) {
433
+	cli_chomp(smbuff);
434
+    } else {
435
+	logg("!build: Can't get builder name\n");
436
+	unlink(gzfile);
437
+	free(gzfile);
438
+	return -1;
439
+    }
428 440
 
429 441
     /* digital signature */
430
-    fd = fopen(gzfile, "rb");
431
-    pt = cli_md5stream(fd, buffer);
432
-    fclose(fd);
442
+    if(!(tar = fopen(gzfile, "rb"))) {
443
+	logg("!build: Can't open file %s for reading\n", gzfile);
444
+	unlink(gzfile);
445
+	free(gzfile);
446
+	return -1;
447
+    }
448
+
449
+    if(!(pt = cli_md5stream(tar, (unsigned char *) buffer))) {
450
+	logg("!build: Can't generate MD5 checksum for %s\n", gzfile);
451
+	unlink(gzfile);
452
+	free(gzfile);
453
+	return -1;
454
+    }
433 455
     free(pt);
456
+    rewind(tar);
457
+
434 458
     if(!(pt = getdsig(opt_arg(opt, "server"), smbuff, buffer))) {
435
-	logg("No digital signature - no CVD file...\n");
459
+	logg("!build: Can't get digital signature from remote server\n");
436 460
 	unlink(gzfile);
437
-	opt_free(opt);
438
-	exit(1);
461
+	free(gzfile);
462
+	fclose(tar);
463
+	return -1;
439 464
     }
440
-
441 465
     strcat(header, pt);
442 466
     free(pt);
443 467
     strcat(header, ":");
... ...
@@ -449,194 +451,191 @@ int build(struct optstruct *opt)
449 449
     sprintf(header + strlen(header), ":%d", (int) timet);
450 450
 
451 451
     /* fill up with spaces */
452
-
453
-    while(strlen(header) < 512)
452
+    while(strlen(header) < sizeof(header) - 1)
454 453
 	strcat(header, " ");
455 454
 
456 455
     /* build the final database */
457
-
458 456
     pt = opt_arg(opt, "build");
459
-    if((cvd = fopen(pt, "wb")) == NULL) {
460
-	logg("!Can't write the final database %s\n", pt);
457
+    if(!(cvd = fopen(pt, "wb"))) {
458
+	logg("!build: Can't create final database %s\n", pt);
461 459
 	unlink(gzfile);
462
-	opt_free(opt);
463
-	exit(1);
460
+	free(gzfile);
461
+	fclose(tar);
462
+	return -1;
464 463
     }
465 464
 
466
-    fwrite(header, 1, 512, cvd);
467
-
468
-    if((tar = fopen(gzfile, "rb")) == NULL) {
469
-	logg("!Can't open file %s for reading.\n", gzfile);
470
-	opt_free(opt);
471
-	exit(1);
465
+    if(fwrite(header, 1, 512, cvd) != 512) {
466
+	logg("!build: Can't write to %s\n", pt);
467
+	fclose(cvd);
468
+	fclose(tar);
469
+	unlink(pt);
470
+	unlink(gzfile);
471
+	free(gzfile);
472
+	return -1;
472 473
     }
473 474
 
474
-    while((bytes = fread(buffer, 1, FILEBUFF, tar)) > 0)
475
-	fwrite(buffer, 1, bytes, cvd);
475
+    while((bytes = fread(buffer, 1, FILEBUFF, tar)) > 0) {
476
+	if(fwrite(buffer, 1, bytes, cvd) != bytes) {
477
+	    fclose(tar);
478
+	    fclose(cvd);
479
+	    unlink(pt);
480
+	    logg("!build: Can't write to %s\n", gzfile);
481
+	    unlink(gzfile);
482
+	    free(gzfile);
483
+	    return -1;
484
+	}
485
+    }
476 486
 
477 487
     fclose(tar);
478 488
     fclose(cvd);
479
-
480
-    unlink(gzfile);
489
+    if(unlink(gzfile) == -1) {
490
+	logg("^build: Can't unlink %s\n", gzfile);
491
+	return -1;
492
+    }
481 493
     free(gzfile);
482 494
 
483
-    logg("Database %s created.\n", pt);
495
+    logg("Database %s created\n", pt);
496
+
497
+    return 0;
498
+}
499
+
500
+static int unpack(struct optstruct *opt)
501
+{
502
+	char *name, *dbdir;
503
+
504
+
505
+    if(opt_check(opt, "unpack-current")) {
506
+	dbdir = freshdbdir();
507
+	name = mcalloc(strlen(dbdir) + strlen(opt_arg(opt, "unpack-current")) + 2, sizeof(char));
508
+	sprintf(name, "%s/%s", dbdir, opt_arg(opt, "unpack-current"));
509
+	free(dbdir);
510
+    } else
511
+	name = strdup(opt_arg(opt, "unpack"));
484 512
 
485
-    /* try to load final cvd */
513
+    if(cvd_unpack(name, ".") == -1) {
514
+	logg("!unpack: Can't unpack CVD file %s\n", name);
515
+	free(name);
516
+	return -1;
517
+    }
518
+
519
+    free(name);
486 520
     return 0;
487 521
 }
488 522
 
489
-void cvdinfo(struct optstruct *opt)
523
+static int cvdinfo(struct optstruct *opt)
490 524
 {
491 525
 	struct cl_cvd *cvd;
492 526
 	char *pt;
493 527
 	int ret;
494 528
 
529
+
495 530
     pt = opt_arg(opt, "info");
496 531
     if((cvd = cl_cvdhead(pt)) == NULL) {
497
-	logg("!Can't read/parse CVD header from %s\n", pt);
498
-	opt_free(opt);
499
-	exit(1);
532
+	logg("!cvdinfo: Can't read/parse CVD header of %s\n", pt);
533
+	return -1;
500 534
     }
501 535
 
536
+    pt = strchr(cvd->time, '-');
537
+    *pt = ':';
502 538
     logg("Build time: %s\n", cvd->time);
503 539
     logg("Version: %d\n", cvd->version);
504 540
     logg("Signatures: %d\n", cvd->sigs);
505 541
     logg("Functionality level: %d\n", cvd->fl);
506 542
     logg("Builder: %s\n", cvd->builder);
507 543
     logg("MD5: %s\n", cvd->md5);
508
-
509 544
     logg("Digital signature: %s\n", cvd->dsig);
510 545
 
511 546
 #ifndef HAVE_GMP
512
-    logg("Digital signature support not compiled in.\n");
547
+    logg("^Digital signature support not compiled in.\n");
513 548
 #endif
514 549
 
550
+    pt = opt_arg(opt, "info");
515 551
     if((ret = cl_cvdverify(pt)))
516
-	logg("!Verification: %s\n", cl_strerror(ret));
552
+	logg("!cvdinfo: Verification: %s\n", cl_strerror(ret));
517 553
     else
518 554
 	logg("Verification OK.\n");
519 555
 
520
-    /* free */
556
+    cl_cvdfree(cvd);
557
+    return 0;
521 558
 }
522 559
 
523
-char *getdsig(const char *host, const char *user, const char *data)
524
-{
525
-	char buff[300], cmd[100], *pass, *pt;
526
-        struct sockaddr_in server;
527
-	int sockd, bread, len;
528
-
560
+static int listdb(const char *filename);
529 561
 
530
-#ifdef PF_INET
531
-    if((sockd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
532
-#else
533
-    if((sockd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
534
-#endif
535
-	perror("socket()");
536
-	logg("!Can't create the socket.\n");
537
-	return NULL;
538
-    }
562
+static int listdir(const char *dirname)
563
+{
564
+	DIR *dd;
565
+	struct dirent *dent;
566
+	char *dbfile;
539 567
 
540
-    server.sin_family = AF_INET;
541
-    server.sin_addr.s_addr = inet_addr(host);
542
-    server.sin_port = htons(33101);
543 568
 
544
-    if(connect(sockd, (struct sockaddr *) &server, sizeof(struct sockaddr_in)) < 0) {
545
-        close(sockd);
546
-	perror("connect()");
547
-	logg("!Can't connect to ClamAV Signing Service at %s.\n", host);
548
-	return NULL;
569
+    if((dd = opendir(dirname)) == NULL) {
570
+        logg("!listdir: Can't open directory %s\n", dirname);
571
+        return -1;
549 572
     }
550 573
 
551
-    memset(cmd, 0, sizeof(cmd));
552
-    pass = getpass("Password:");
553
-    sprintf(cmd, "ClamSign:%s:%s:", user, pass);
554
-    len = strlen(cmd);
555
-    pt = cmd;
556
-    pt += len;
557
-    memcpy(pt, data, 16);
558
-    len += 16;
574
+    while((dent = readdir(dd))) {
575
+#ifndef C_INTERIX
576
+	if(dent->d_ino)
577
+#endif
578
+	{
579
+	    if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..") &&
580
+	    (cli_strbcasestr(dent->d_name, ".db")  ||
581
+	     cli_strbcasestr(dent->d_name, ".hdb") ||
582
+	     cli_strbcasestr(dent->d_name, ".ndb") ||
583
+	     cli_strbcasestr(dent->d_name, ".zmd") ||
584
+	     cli_strbcasestr(dent->d_name, ".rmd") ||
585
+	     cli_strbcasestr(dent->d_name, ".cvd"))) {
559 586
 
560
-    if(write(sockd, cmd, len) < 0) {
561
-	logg("!Can't write to the socket.\n");
562
-	close(sockd);
563
-	memset(cmd, 0, len);
564
-	memset(pass, 0, strlen(pass));
565
-	return NULL;
566
-    }
587
+		dbfile = (char *) mcalloc(strlen(dent->d_name) + strlen(dirname) + 2, sizeof(char));
567 588
 
568
-    memset(cmd, 0, len);
569
-    memset(pass, 0, strlen(pass));
589
+		if(!dbfile) {
590
+		    logg("!listdir: Can't allocate memory for dbfile\n");
591
+		    closedir(dd);
592
+		    return -1;
593
+		}
594
+		sprintf(dbfile, "%s/%s", dirname, dent->d_name);
570 595
 
571
-    memset(buff, 0, sizeof(buff));
572
-    if((bread = read(sockd, buff, sizeof(buff))) > 0) {
573
-	if(!strstr(buff, "Signature:")) {
574
-	    logg("!Signature generation error.\n");
575
-	    logg("ClamAV SDaemon: %s.\n", buff);
576
-	    close(sockd);
577
-	    return NULL;
578
-	} else {
579
-	    logg("Signature received (length = %d).\n", strlen(buff) - 10);
596
+		if(listdb(dbfile) == -1) {
597
+		    logg("!listdb: Error listing database %s\n", dbfile);
598
+		    free(dbfile);
599
+		    closedir(dd);
600
+		    return -1;
601
+		}
602
+		free(dbfile);
603
+	    }
580 604
 	}
581 605
     }
582 606
 
583
-    close(sockd);
584
-    pt = buff;
585
-    pt += 10;
586
-    return strdup(pt);
587
-}
588
-
589
-int unpack(struct optstruct *opt)
590
-{
591
-	char *name, *dbdir;
592
-
593
-    if(opt_check(opt, "unpack-current")) {
594
-	dbdir = freshdbdir();
595
-	name = mcalloc(strlen(dbdir) + strlen(opt_arg(opt, "unpack-current")) + 2, sizeof(char));
596
-	sprintf(name, "%s/%s", dbdir, opt_arg(opt, "unpack-current"));
597
-	free(dbdir);
598
-    } else
599
-	name = strdup(opt_arg(opt, "unpack"));
600
-
601
-    if(cvd_unpack(name, ".") == -1) {
602
-	logg("!Can't unpack CVD file %s\n", name);
603
-	free(name);
604
-	opt_free(opt);
605
-	exit(1);
606
-    }
607
-
608
-    free(name);
609
-    opt_free(opt);
610
-    exit(0);
607
+    closedir(dd);
608
+    return 0;
611 609
 }
612 610
 
613
-int listdb(const char *filename)
611
+static int listdb(const char *filename)
614 612
 {
615
-	FILE *fd, *tmpd;
616
-	char *buffer, *pt, *start, *dir, *tmp;
617
-	int line = 0, bytes;
613
+	FILE *fd;
614
+	char *buffer, *pt, *start, *dir;
615
+	int line = 0;
618 616
 	const char *tmpdir;
619 617
 
620 618
 
621 619
     if((fd = fopen(filename, "rb")) == NULL) {
622
-	logg("!listdb(): Can't open file %s\n", filename);
620
+	logg("!listdb: Can't open file %s\n", filename);
623 621
 	return -1;
624 622
     }
625 623
 
626
-    if(!(buffer = (char *) mmalloc(FILEBUFF))) {
627
-	logg("!listdb(): Can't allocate memory.\n");
624
+    if(!(buffer = (char *) mcalloc(FILEBUFF, 1))) {
625
+	logg("!listdb: Can't allocate memory for buffer\n");
628 626
 	fclose(fd);
629 627
 	return -1;
630 628
     }
631 629
 
632
-    memset(buffer, 0, FILEBUFF);
633 630
     /* check for CVD file */
634 631
     fgets(buffer, 12, fd);
635 632
     rewind(fd);
636 633
 
637 634
     if(!strncmp(buffer, "ClamAV-VDB:", 11)) {
638
-
639
-	fseek(fd, 512, SEEK_SET);
635
+	free(buffer);
636
+	fclose(fd);
640 637
 
641 638
 	tmpdir = getenv("TMPDIR");
642 639
 	if(tmpdir == NULL)
... ...
@@ -646,73 +645,45 @@ int listdb(const char *filename)
646 646
 	    tmpdir = "/tmp";
647 647
 #endif
648 648
 
649
-	dir = cli_gentemp(tmpdir);
650
-	if(mkdir(dir, 0700)) {
651
-	    logg("!listdb(): Can't create temporary directory %s\n", dir);
652
-	    free(buffer);
653
-	    fclose(fd);
649
+	if(!(dir = cli_gentemp(tmpdir))) {
650
+	    logg("!listdb: Can't generate temporary name\n");
654 651
 	    return -1;
655 652
 	}
656 653
 
657
-	/* FIXME: it seems there is some problem with current position indicator
658
-	* after gzdopen() call in cli_untgz(). Temporarily we need this wrapper:
659
-	*/
660
-
661
-	/* start */
662
-
663
-	tmp = cli_gentemp(tmpdir);
664
-	if((tmpd = fopen(tmp, "wb+")) == NULL) {
665
-	    logg("!listdb(): Can't create temporary file %s\n", tmp);
654
+	if(mkdir(dir, 0700)) {
655
+	    logg("!listdb: Can't create temporary directory %s\n", dir);
666 656
 	    free(dir);
667
-	    free(tmp);
668
-	    free(buffer);
669
-	    fclose(fd);
670 657
 	    return -1;
671 658
 	}
672 659
 
673
-	while((bytes = fread(buffer, 1, FILEBUFF, fd)) > 0)
674
-	    fwrite(buffer, 1, bytes, tmpd);
675
-
676
-	free(buffer);
677
-	fclose(fd);
678
-
679
-	fflush(tmpd);
680
-	fseek(tmpd, 0L, SEEK_SET);
681
-
682
-	if(cli_untgz(fileno(tmpd), dir)) {
683
-	    logg("!listdb(): Can't unpack CVD file.\n");
684
-	    cli_rmdirs(dir);
660
+	if(cvd_unpack(filename, dir) == -1) {
661
+	    logg("!listdb: Can't unpack CVD file %s\n", filename);
662
+	    rmdirs(dir);
685 663
 	    free(dir);
686
-	    fclose(tmpd);
687
-	    unlink(tmp);
688
-	    free(tmp);
689
-	    free(buffer);
690 664
 	    return -1;
691 665
 	}
692 666
 
693
-	fclose(tmpd);
694
-	unlink(tmp);
695
-	free(tmp);
696
-
697
-	/* wrapper end */
698
-
699 667
 	/* list extracted directory */
700
-	listdir(dir);
668
+	if(listdir(dir) == -1) {
669
+	    logg("!listdb: Can't unpack CVD file %s\n", filename);
670
+	    rmdirs(dir);
671
+	    free(dir);
672
+	    return -1;
673
+	}
701 674
 
702
-	cli_rmdirs(dir);
675
+	rmdirs(dir);
703 676
 	free(dir);
704 677
 
705 678
 	return 0;
706 679
     }
707 680
 
708
-    if(cli_strbcasestr(filename, ".db") || cli_strbcasestr(filename, ".db2")) {
709
-	/* old style database */
681
+    if(cli_strbcasestr(filename, ".db")) { /* old style database */
710 682
 
711 683
 	while(fgets(buffer, FILEBUFF, fd)) {
712 684
 	    line++;
713 685
 	    pt = strchr(buffer, '=');
714 686
 	    if(!pt) {
715
-		logg("!listdb(): Malformed pattern line %d (file %s).\n", line, filename);
687
+		logg("!listdb: Malformed pattern line %d (file %s)\n", line, filename);
716 688
 		fclose(fd);
717 689
 		free(buffer);
718 690
 		return -1;
... ...
@@ -727,7 +698,7 @@ int listdb(const char *filename)
727 727
 	    logg("%s\n", start);
728 728
 	}
729 729
 
730
-    } else if(cli_strbcasestr(filename, ".hdb")) {
730
+    } else if(cli_strbcasestr(filename, ".hdb")) { /* hash database */
731 731
 
732 732
 	while(fgets(buffer, FILEBUFF, fd)) {
733 733
 	    line++;
... ...
@@ -735,7 +706,7 @@ int listdb(const char *filename)
735 735
 	    start = cli_strtok(buffer, 2, ":");
736 736
 
737 737
 	    if(!start) {
738
-		logg("!listdb(): Malformed pattern line %d (file %s).\n", line, filename);
738
+		logg("!listdb: Malformed pattern line %d (file %s)\n", line, filename);
739 739
 		fclose(fd);
740 740
 		free(buffer);
741 741
 		return -1;
... ...
@@ -756,7 +727,7 @@ int listdb(const char *filename)
756 756
 	    start = cli_strtok(buffer, 0, ":");
757 757
 
758 758
 	    if(!start) {
759
-		logg("!listdb(): Malformed pattern line %d (file %s).\n", line, filename);
759
+		logg("!listdb: Malformed pattern line %d (file %s)\n", line, filename);
760 760
 		fclose(fd);
761 761
 		free(buffer);
762 762
 		return -1;
... ...
@@ -775,62 +746,13 @@ int listdb(const char *filename)
775 775
     return 0;
776 776
 }
777 777
 
778
-int listdir(const char *dirname)
779
-{
780
-	DIR *dd;
781
-	struct dirent *dent;
782
-	char *dbfile;
783
-
784
-
785
-    if((dd = opendir(dirname)) == NULL) {
786
-        logg("!Can't open directory %s\n", dirname);
787
-        return -1;
788
-    }
789
-
790
-    while((dent = readdir(dd))) {
791
-#ifndef C_INTERIX
792
-	if(dent->d_ino)
793
-#endif
794
-	{
795
-	    if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..") &&
796
-	    (cli_strbcasestr(dent->d_name, ".db")  ||
797
-	     cli_strbcasestr(dent->d_name, ".db2") ||
798
-	     cli_strbcasestr(dent->d_name, ".hdb") ||
799
-	     cli_strbcasestr(dent->d_name, ".ndb") ||
800
-	     cli_strbcasestr(dent->d_name, ".zmd") ||
801
-	     cli_strbcasestr(dent->d_name, ".rmd") ||
802
-	     cli_strbcasestr(dent->d_name, ".cvd"))) {
803
-
804
-		dbfile = (char *) mcalloc(strlen(dent->d_name) + strlen(dirname) + 2, sizeof(char));
805
-
806
-		if(!dbfile) {
807
-		    logg("!listdir(): Can't allocate memory.\n");
808
-		    closedir(dd);
809
-		    return -1;
810
-		}
811
-		sprintf(dbfile, "%s/%s", dirname, dent->d_name);
812
-
813
-		if(listdb(dbfile)) {
814
-		    logg("!listdb(): error listing database %s\n", dbfile);
815
-		    free(dbfile);
816
-		    closedir(dd);
817
-		    return -1;
818
-		}
819
-		free(dbfile);
820
-	    }
821
-	}
822
-    }
823
-
824
-    closedir(dd);
825
-    return 0;
826
-}
827
-
828
-void listsigs(struct optstruct *opt)
778
+static int listsigs(struct optstruct *opt)
829 779
 {
830 780
 	int ret;
831 781
 	const char *name;
832 782
 	char *dbdir;
833 783
 
784
+
834 785
     mprintf_stdout = 1;
835 786
 
836 787
     if((name = opt_arg(opt, "list-sigs"))) {
... ...
@@ -841,15 +763,53 @@ void listsigs(struct optstruct *opt)
841 841
 	free(dbdir);
842 842
     }
843 843
 
844
-    opt_free(opt);
845
-    ret ? exit(1) : exit(0);
844
+    return ret;
845
+}
846
+
847
+static int vbadump(struct optstruct *opt)
848
+{
849
+	int fd, hex_output=0;
850
+	char *dir;
851
+
852
+
853
+    if(opt_check(opt, "vba-hex"))
854
+	hex_output = 1;
855
+ 
856
+    if((fd = open(opt_arg(opt, "vba"), O_RDONLY)) == -1) {
857
+	if((fd = open(opt_arg(opt, "vba-hex"), O_RDONLY)) == -1) {
858
+	    logg("!vbadump: Can't open file %s\n", opt_arg(opt, "vba"));
859
+	    return -1;
860
+	}
861
+    }
862
+
863
+    /* generate the temporary directory */
864
+    dir = cli_gentemp(NULL);
865
+    if(mkdir(dir, 0700)) {
866
+	logg("!vbadump: Can't create temporary directory %s\n", dir);
867
+	free(dir);
868
+	close(fd);
869
+        return -1;
870
+    }
871
+
872
+    if(cli_ole2_extract(fd, dir, NULL)) {
873
+	cli_rmdirs(dir);
874
+        free(dir);
875
+	close(fd);
876
+        return -1;
877
+    }
878
+
879
+    close(fd);
880
+    sigtool_vba_scandir(dir, hex_output);
881
+    rmdirs(dir);
882
+    free(dir);
883
+    return 0;
846 884
 }
847 885
 
848 886
 void help(void)
849 887
 {
850 888
     mprintf("\n");
851 889
     mprintf("             Clam AntiVirus: Signature Tool (sigtool)  "VERSION"\n");
852
-    mprintf("    (C) 2002 - 2005 ClamAV Team - http://www.clamav.net/team.html\n\n");
890
+    mprintf("    (C) 2002 - 2006 ClamAV Team - http://www.clamav.net/team.html\n\n");
853 891
 
854 892
     mprintf("    --help                 -h              show help\n");
855 893
     mprintf("    --version              -V              print version number and exit\n");
... ...
@@ -871,5 +831,85 @@ void help(void)
871 871
     mprintf("    --vba-hex=FILE                         Extract Word6 macro code with hex values\n");
872 872
     mprintf("\n");
873 873
 
874
-    exit(0);
874
+    return;
875
+}
876
+
877
+int main(int argc, char **argv)
878
+{
879
+	int ret = 1;
880
+        struct optstruct *opt;
881
+	const char *short_options = "hvVb:i:u:l::";
882
+	static struct option long_options[] = {
883
+	    {"help", 0, 0, 'h'},
884
+	    {"quiet", 0, 0, 0},
885
+	    {"debug", 0, 0, 0},
886
+	    {"verbose", 0, 0, 'v'},
887
+	    {"stdout", 0, 0, 0},
888
+	    {"version", 0, 0, 'V'},
889
+	    {"tempdir", 1, 0, 0},
890
+	    {"hex-dump", 0, 0, 0},
891
+	    {"md5", 0, 0, 0},
892
+	    {"html-normalise", 1, 0, 0},
893
+	    {"build", 1, 0, 'b'},
894
+	    {"server", 1, 0, 0},
895
+	    {"unpack", 1, 0, 'u'},
896
+	    {"unpack-current", 1, 0, 0},
897
+	    {"info", 1, 0, 'i'},
898
+	    {"list-sigs", 2, 0, 'l'},
899
+	    {"vba", 1, 0 ,0},
900
+	    {"vba-hex", 1, 0, 0},
901
+	    {0, 0, 0, 0}
902
+    	};
903
+
904
+
905
+    opt = opt_parse(argc, argv, short_options, long_options, NULL);
906
+    if(!opt) {
907
+	mprintf("!Can't parse the command line\n");
908
+	return 1;
909
+    }
910
+
911
+    if(opt_check(opt, "quiet"))
912
+	mprintf_quiet = 1;
913
+
914
+    if(opt_check(opt, "stdout"))
915
+	mprintf_stdout = 1;
916
+
917
+    if(opt_check(opt, "debug"))
918
+	cl_debug();
919
+
920
+    if(opt_check(opt, "version")) {
921
+	print_version();
922
+	opt_free(opt);
923
+	return 0;
924
+    }
925
+
926
+    if(opt_check(opt, "help")) {
927
+	opt_free(opt);
928
+    	help();
929
+    }
930
+
931
+    if(opt_check(opt, "hex-dump"))
932
+	ret = hexdump();
933
+    else if(opt_check(opt, "md5"))
934
+	ret = md5sig(opt);
935
+    else if(opt_check(opt, "html-normalise"))
936
+	ret = htmlnorm(opt);
937
+    else if(opt_check(opt, "build"))
938
+	ret = build(opt);
939
+    else if(opt_check(opt, "unpack"))
940
+	ret = unpack(opt);
941
+    else if(opt_check(opt, "unpack-current"))
942
+	ret = unpack(opt);
943
+    else if(opt_check(opt, "info"))
944
+	ret = cvdinfo(opt);
945
+    else if(opt_check(opt, "list-sigs"))
946
+	ret = listsigs(opt);
947
+    else if(opt_check(opt, "vba") || opt_check(opt, "vba-hex"))
948
+	ret = vbadump(opt);
949
+    else
950
+	help();
951
+
952
+
953
+    opt_free(opt);
954
+    return ret ? 1 : 0;
875 955
 }