mirror of https://github.com/Cisco-Talos/clamav
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
309 lines
6.5 KiB
309 lines
6.5 KiB
/*
|
|
* Copyright (C) 2001 - 2007 Tomasz Kojm <tkojm@clamav.net>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#if HAVE_CONFIG_H
|
|
#include "clamav-config.h"
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#define _GNU_SOURCE
|
|
#include "getopt.h"
|
|
|
|
#include "options.h"
|
|
#include "output.h"
|
|
|
|
|
|
static int register_option(struct optstruct *opt, const char *optlong, char optshort, const struct option *options_long, const char * const *accepted_long, const char * const *deprecated_long)
|
|
{
|
|
struct optnode *newnode;
|
|
int i, found;
|
|
const char *longname = NULL;
|
|
|
|
|
|
if(optshort) {
|
|
for(i = 0; options_long[i].name; i++) {
|
|
if(options_long[i].val == optshort) {
|
|
longname = options_long[i].name;
|
|
break;
|
|
}
|
|
}
|
|
} else
|
|
longname = optlong;
|
|
|
|
if(!longname) {
|
|
mprintf("!register_option: No long option for -%c\n", optshort);
|
|
return -1;
|
|
}
|
|
|
|
if(accepted_long) {
|
|
found = 0;
|
|
for(i = 0; accepted_long[i]; i++)
|
|
if(!strcmp(accepted_long[i], longname)) {
|
|
found = 1;
|
|
break;
|
|
}
|
|
|
|
if(!found) {
|
|
if(optshort)
|
|
mprintf("WARNING: Ignoring option --%s (-%c)\n", longname, optshort);
|
|
else
|
|
mprintf("WARNING: Ignoring option --%s\n", longname);
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if(deprecated_long) {
|
|
found = 0;
|
|
for(i = 0; deprecated_long[i]; i++) {
|
|
if(!strcmp(deprecated_long[i], longname)) {
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(found) {
|
|
if(optshort)
|
|
mprintf("WARNING: Ignoring deprecated option --%s (-%c)\n", longname, optshort);
|
|
else
|
|
mprintf("WARNING: Ignoring deprecated option --%s\n", longname);
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
newnode = (struct optnode *) malloc(sizeof(struct optnode));
|
|
if(!newnode) {
|
|
mprintf("!register_long_option: malloc failed\n");
|
|
return -1;
|
|
}
|
|
|
|
newnode->optshort = optshort;
|
|
|
|
if(optarg) {
|
|
newnode->optarg = (char *) malloc(strlen(optarg) + 1);
|
|
if(!newnode->optarg) {
|
|
mprintf("!register_long_option: malloc failed\n");
|
|
free(newnode);
|
|
return -1;
|
|
}
|
|
strcpy(newnode->optarg, optarg);
|
|
} else
|
|
newnode->optarg = NULL;
|
|
|
|
newnode->optlong = (char *) malloc(strlen(longname) + 1);
|
|
if(!newnode->optlong) {
|
|
mprintf("ERROR: register_long_option: malloc failed\n");
|
|
free(newnode->optarg);
|
|
free(newnode);
|
|
return -1;
|
|
}
|
|
strcpy(newnode->optlong, longname);
|
|
|
|
newnode->next = opt->optlist;
|
|
opt->optlist = newnode;
|
|
return 0;
|
|
}
|
|
|
|
void opt_free(struct optstruct *opt)
|
|
{
|
|
struct optnode *handler, *prev;
|
|
|
|
if(!opt)
|
|
return;
|
|
|
|
handler = opt->optlist;
|
|
while(handler) {
|
|
if(handler->optarg)
|
|
free(handler->optarg);
|
|
if(handler->optlong)
|
|
free(handler->optlong);
|
|
prev = handler;
|
|
handler = handler->next;
|
|
free(prev);
|
|
}
|
|
|
|
if(opt->filename)
|
|
free(opt->filename);
|
|
|
|
free(opt);
|
|
}
|
|
|
|
struct optstruct *opt_parse(int argc, char * const *argv, const char *getopt_short, const struct option *options_long, const char * const *accepted_long, const char * const *deprecated_long)
|
|
{
|
|
int ret, opt_index, i, len;
|
|
struct optstruct *opt;
|
|
const char *longname;
|
|
|
|
|
|
opt = (struct optstruct *) calloc(1, sizeof(struct optstruct));
|
|
if(!opt) {
|
|
mprintf("!opt_parse: calloc failed\n");
|
|
return NULL;
|
|
}
|
|
|
|
while(1) {
|
|
opt_index = 0;
|
|
ret = getopt_long(argc, argv, getopt_short, options_long, &opt_index);
|
|
|
|
if(ret == -1)
|
|
break;
|
|
|
|
switch(ret) {
|
|
case 0:
|
|
if(register_option(opt, options_long[opt_index].name, 0, options_long, accepted_long, deprecated_long) == -1) {
|
|
opt_free(opt);
|
|
return NULL;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if(strchr(getopt_short, ret)) {
|
|
if(opt_index)
|
|
longname = options_long[opt_index].name;
|
|
else
|
|
longname = NULL;
|
|
|
|
if(register_option(opt, longname, ret, options_long, accepted_long, deprecated_long) == -1) {
|
|
opt_free(opt);
|
|
return NULL;
|
|
}
|
|
|
|
} else {
|
|
mprintf("!Unknown option passed.\n");
|
|
opt_free(opt);
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(optind < argc) {
|
|
len = 0;
|
|
|
|
/* count length of non-option arguments */
|
|
for(i = optind; i < argc; i++)
|
|
len += strlen(argv[i]);
|
|
|
|
len += argc - optind - 1;
|
|
opt->filename = (char *) calloc(len + 64, sizeof(char));
|
|
if(!opt->filename) {
|
|
mprintf("!opt_parse: calloc failed\n");
|
|
opt_free(opt);
|
|
return NULL;
|
|
}
|
|
|
|
for(i = optind; i < argc; i++) {
|
|
strncat(opt->filename, argv[i], strlen(argv[i]));
|
|
if(i != argc - 1)
|
|
strncat(opt->filename, "\t", 1);
|
|
}
|
|
}
|
|
|
|
return opt;
|
|
}
|
|
|
|
int opt_check(const struct optstruct *opt, const char *optlong)
|
|
{
|
|
struct optnode *handler;
|
|
|
|
if(!opt) {
|
|
mprintf("!opt_check: opt == NULL\n");
|
|
return 0;
|
|
}
|
|
|
|
handler = opt->optlist;
|
|
|
|
while(handler) {
|
|
if(handler->optlong && !strcmp(handler->optlong, optlong))
|
|
return 1;
|
|
|
|
handler = handler->next;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
char *opt_arg(const struct optstruct *opt, const char *optlong)
|
|
{
|
|
struct optnode *handler;
|
|
|
|
if(!opt) {
|
|
mprintf("!opt_arg: opt == NULL\n");
|
|
return 0;
|
|
}
|
|
|
|
handler = opt->optlist;
|
|
|
|
while(handler) {
|
|
if(handler->optlong && !strcmp(handler->optlong, optlong))
|
|
return handler->optarg;
|
|
|
|
handler = handler->next;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
char *opt_firstarg(const struct optstruct *opt, const char *optlong, const struct optnode **optnode)
|
|
{
|
|
const struct optnode *handler;
|
|
|
|
if(!opt) {
|
|
mprintf("!opt_firstarg: opt == NULL\n");
|
|
return 0;
|
|
}
|
|
|
|
handler = opt->optlist;
|
|
|
|
while(handler) {
|
|
if(handler->optlong && !strcmp(handler->optlong, optlong)) {
|
|
*optnode = handler;
|
|
return handler->optarg;
|
|
}
|
|
handler = handler->next;
|
|
}
|
|
|
|
*optnode = NULL;
|
|
return NULL;
|
|
}
|
|
|
|
char *opt_nextarg(const struct optnode **optnode, const char *optlong)
|
|
{
|
|
struct optnode *handler;
|
|
|
|
if(!optnode || !*optnode) {
|
|
mprintf("!opt_nextarg: *optnode == NULL\n");
|
|
return 0;
|
|
}
|
|
|
|
handler = (*optnode)->next;
|
|
|
|
while(handler) {
|
|
if(handler->optlong && !strcmp(handler->optlong, optlong)) {
|
|
*optnode = handler;
|
|
return handler->optarg;
|
|
}
|
|
handler = handler->next;
|
|
}
|
|
|
|
*optnode = NULL;
|
|
return NULL;
|
|
}
|
|
|