blob: 0f2d81ee9ca4644103c0378fa2a37a2390439374 [file] [log] [blame]
/*
* 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)
{
struct optnode *newnode;
int i, found = 0;
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) {
for(i = 0; accepted_long[i]; i++)
if(!strcmp(accepted_long[i], longname))
found = 1;
if(!found) {
if(optshort)
mprintf("WARNING: Ignoring option --%s (-%c)\n", longname, optshort);
else
mprintf("WARNING: Ignoring 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)
{
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) == -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) == -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;
}