Merging upstream version 2.5.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
3d70d3c76b
commit
ee6621a5b2
507 changed files with 19440 additions and 17258 deletions
264
util/argconfig.c
264
util/argconfig.c
|
@ -42,18 +42,11 @@
|
|||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#if __has_attribute(__fallthrough__)
|
||||
#define fallthrough __attribute__((__fallthrough__))
|
||||
#else
|
||||
#define fallthrough do {} while (0)
|
||||
#endif
|
||||
|
||||
static argconfig_help_func *help_funcs[MAX_HELP_FUNC] = { NULL };
|
||||
|
||||
static char END_DEFAULT[] = "__end_default__";
|
||||
|
||||
static const char *append_usage_str = "";
|
||||
|
||||
static int argconfig_parse_val(struct argconfig_commandline_options *s, struct option *option,
|
||||
int index);
|
||||
|
||||
void argconfig_append_usage(const char *str)
|
||||
{
|
||||
append_usage_str = str;
|
||||
|
@ -168,11 +161,7 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct
|
|||
{
|
||||
void *value = (void *)(char *)s->default_value;
|
||||
char *endptr;
|
||||
const char *fopts = NULL;
|
||||
FILE *f;
|
||||
int ret = 0;
|
||||
char **opts = ((char **)value);
|
||||
int remaining_space = CFG_MAX_SUBOPTS - 2;
|
||||
|
||||
switch (s->config_type) {
|
||||
case CFG_STRING:
|
||||
|
@ -190,6 +179,7 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct
|
|||
break;
|
||||
case CFG_BOOL: {
|
||||
int tmp = strtol(optarg, &endptr, 0);
|
||||
|
||||
if (errno || tmp < 0 || tmp > 1 || optarg == endptr)
|
||||
ret = argconfig_error("0 or 1", option[index].name, optarg);
|
||||
else
|
||||
|
@ -201,6 +191,7 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct
|
|||
break;
|
||||
case CFG_SHORT: {
|
||||
unsigned long tmp = strtoul(optarg, &endptr, 0);
|
||||
|
||||
if (errno || tmp >= 1 << 16 || optarg == endptr)
|
||||
ret = argconfig_error("short", option[index].name, optarg);
|
||||
else
|
||||
|
@ -209,6 +200,7 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct
|
|||
}
|
||||
case CFG_POSITIVE: {
|
||||
uint32_t tmp = strtoul(optarg, &endptr, 0);
|
||||
|
||||
if (errno || optarg == endptr)
|
||||
ret = argconfig_error("word", option[index].name, optarg);
|
||||
else
|
||||
|
@ -224,7 +216,7 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct
|
|||
ret = argconfig_error("long integer", option[index].name, optarg);
|
||||
break;
|
||||
case CFG_LONG_SUFFIX:
|
||||
ret = suffix_binary_parse(optarg, &endptr, (uint64_t*)value);
|
||||
ret = suffix_binary_parse(optarg, &endptr, (uint64_t *)value);
|
||||
if (ret)
|
||||
argconfig_error("long suffixed integer", option[index].name, optarg);
|
||||
break;
|
||||
|
@ -233,48 +225,6 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct
|
|||
if (errno || optarg == endptr)
|
||||
ret = argconfig_error("float", option[index].name, optarg);
|
||||
break;
|
||||
case CFG_SUBOPTS:
|
||||
*opts = END_DEFAULT;
|
||||
opts += 2;
|
||||
ret = argconfig_parse_subopt_string(optarg, opts, remaining_space);
|
||||
if (ret) {
|
||||
if (ret == 2)
|
||||
fprintf(stderr, "Error Parsing Sub-Options: Too many options!\n");
|
||||
else
|
||||
fprintf(stderr, "Error Parsing Sub-Options\n");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
break;
|
||||
case CFG_FILE_A:
|
||||
fopts = "a";
|
||||
fallthrough;
|
||||
case CFG_FILE_R:
|
||||
if (!fopts)
|
||||
fopts = "r";
|
||||
fallthrough;
|
||||
case CFG_FILE_W:
|
||||
if (!fopts)
|
||||
fopts = "w";
|
||||
fallthrough;
|
||||
case CFG_FILE_AP:
|
||||
if (!fopts)
|
||||
fopts = "a+";
|
||||
fallthrough;
|
||||
case CFG_FILE_RP:
|
||||
if (!fopts)
|
||||
fopts = "r+";
|
||||
fallthrough;
|
||||
case CFG_FILE_WP:
|
||||
if (!fopts)
|
||||
fopts = "w+";
|
||||
f = fopen(optarg, fopts);
|
||||
if (!f) {
|
||||
fprintf(stderr, "Unable to open %s file: %s\n", s->option, optarg);
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
*((FILE **)value) = f;
|
||||
}
|
||||
break;
|
||||
case CFG_FLAG:
|
||||
*((bool *)value) = true;
|
||||
break;
|
||||
|
@ -285,9 +235,87 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int argconfig_get_val_len(struct argconfig_opt_val *opt_val, const char *str)
|
||||
{
|
||||
struct argconfig_opt_val *v;
|
||||
int len;
|
||||
int match;
|
||||
|
||||
for (len = 1; len <= strlen(str); len++) {
|
||||
match = 0;
|
||||
for (v = opt_val; v && v->str; v++) {
|
||||
if (!strncasecmp(str, v->str, len))
|
||||
match++;
|
||||
}
|
||||
if (match == 1)
|
||||
break;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int argconfig_set_opt_val(enum argconfig_types type, union argconfig_val *opt_val, void *val)
|
||||
{
|
||||
switch (type) {
|
||||
case CFG_FLAG:
|
||||
*(bool *)val = opt_val->bool_val;
|
||||
break;
|
||||
case CFG_LONG_SUFFIX:
|
||||
*(uint64_t *)val = opt_val->long_suffix;
|
||||
break;
|
||||
case CFG_POSITIVE:
|
||||
*(uint32_t *)val = opt_val->positive;
|
||||
break;
|
||||
case CFG_INT:
|
||||
*(int *)val = opt_val->int_val;
|
||||
break;
|
||||
case CFG_LONG:
|
||||
*(unsigned long *)val = opt_val->long_val;
|
||||
break;
|
||||
case CFG_DOUBLE:
|
||||
*(double *)val = opt_val->double_val;
|
||||
break;
|
||||
case CFG_BYTE:
|
||||
*(uint8_t *)val = opt_val->byte;
|
||||
break;
|
||||
case CFG_SHORT:
|
||||
*(uint16_t *)val = opt_val->short_val;
|
||||
break;
|
||||
case CFG_INCREMENT:
|
||||
*(int *)val = opt_val->increment;
|
||||
break;
|
||||
case CFG_STRING:
|
||||
*(char **)val = opt_val->string;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int argconfig_parse_val(struct argconfig_commandline_options *s, struct option *option,
|
||||
int index)
|
||||
{
|
||||
const char *str = optarg;
|
||||
void *val = s->default_value;
|
||||
int len = strlen(optarg);
|
||||
struct argconfig_opt_val *v;
|
||||
int val_len;
|
||||
|
||||
for (v = s->opt_val; v && v->str; v++) {
|
||||
val_len = argconfig_get_val_len(s->opt_val, v->str);
|
||||
if (strncasecmp(str, v->str, len > val_len ? len : val_len))
|
||||
continue;
|
||||
return argconfig_set_opt_val(v->type, &v->val, val);
|
||||
}
|
||||
|
||||
return argconfig_parse_type(s, option, index);
|
||||
}
|
||||
|
||||
bool argconfig_output_format_json(bool set)
|
||||
{
|
||||
static bool output_format_json = false;
|
||||
static bool output_format_json;
|
||||
|
||||
if (set)
|
||||
output_format_json = true;
|
||||
|
@ -295,6 +323,18 @@ bool argconfig_output_format_json(bool set)
|
|||
return output_format_json;
|
||||
}
|
||||
|
||||
static bool argconfig_check_output_format_json(struct argconfig_commandline_options *s)
|
||||
{
|
||||
for (; s && s->option; s++) {
|
||||
if (strcmp(s->option, "output-format") || s->config_type != CFG_STRING)
|
||||
continue;
|
||||
if (!strcmp(*(char **)s->default_value, "json"))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int argconfig_parse(int argc, char *argv[], const char *program_desc,
|
||||
struct argconfig_commandline_options *options)
|
||||
{
|
||||
|
@ -368,94 +408,24 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc,
|
|||
if (!s->default_value)
|
||||
continue;
|
||||
|
||||
ret = argconfig_parse_type(s, long_opts,option_index);
|
||||
if (s->opt_val)
|
||||
ret = argconfig_parse_val(s, long_opts, option_index);
|
||||
else
|
||||
ret = argconfig_parse_type(s, long_opts, option_index);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
if (argconfig_check_output_format_json(options))
|
||||
argconfig_output_format_json(true);
|
||||
|
||||
out:
|
||||
free(short_opts);
|
||||
free(long_opts);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int argconfig_parse_subopt_string(char *string, char **options,
|
||||
size_t max_options)
|
||||
{
|
||||
char **o = options;
|
||||
char *tmp;
|
||||
size_t toklen;
|
||||
|
||||
if (!string || !strlen(string)) {
|
||||
*(o++) = NULL;
|
||||
*(o++) = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
tmp = calloc(strlen(string) + 2, 1);
|
||||
if (!tmp)
|
||||
return 1;
|
||||
strcpy(tmp, string);
|
||||
|
||||
toklen = strcspn(tmp, "=");
|
||||
|
||||
if (!toklen) {
|
||||
free(tmp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
*(o++) = tmp;
|
||||
tmp[toklen] = 0;
|
||||
tmp += toklen + 1;
|
||||
|
||||
while (1) {
|
||||
if (*tmp == '"' || *tmp == '\'' || *tmp == '[' || *tmp == '(' ||
|
||||
*tmp == '{') {
|
||||
|
||||
tmp++;
|
||||
toklen = strcspn(tmp, "\"'])}");
|
||||
|
||||
if (!toklen)
|
||||
return 1;
|
||||
|
||||
*(o++) = tmp;
|
||||
tmp[toklen] = 0;
|
||||
tmp += toklen + 1;
|
||||
|
||||
toklen = strcspn(tmp, ";:,");
|
||||
tmp[toklen] = 0;
|
||||
tmp += toklen + 1;
|
||||
} else {
|
||||
toklen = strcspn(tmp, ";:,");
|
||||
|
||||
if (!toklen)
|
||||
return 1;
|
||||
|
||||
*(o++) = tmp;
|
||||
tmp[toklen] = 0;
|
||||
tmp += toklen + 1;
|
||||
}
|
||||
|
||||
toklen = strcspn(tmp, "=");
|
||||
|
||||
if (!toklen)
|
||||
break;
|
||||
|
||||
*(o++) = tmp;
|
||||
tmp[toklen] = 0;
|
||||
tmp += toklen + 1;
|
||||
|
||||
if ((o - options) > (max_options - 2))
|
||||
return 2;
|
||||
}
|
||||
|
||||
*(o++) = NULL;
|
||||
*(o++) = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int argconfig_parse_comma_sep_array(char *string, int *val,
|
||||
unsigned max_length)
|
||||
int argconfig_parse_comma_sep_array(char *string, int *val, unsigned int max_length)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long v;
|
||||
|
@ -501,7 +471,7 @@ int argconfig_parse_comma_sep_array(char *string, int *val,
|
|||
}
|
||||
|
||||
int argconfig_parse_comma_sep_array_short(char *string, unsigned short *val,
|
||||
unsigned max_length)
|
||||
unsigned int max_length)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long v;
|
||||
|
@ -545,9 +515,8 @@ int argconfig_parse_comma_sep_array_short(char *string, unsigned short *val,
|
|||
}
|
||||
}
|
||||
|
||||
int argconfig_parse_comma_sep_array_long(char *string,
|
||||
unsigned long long *val,
|
||||
unsigned max_length)
|
||||
int argconfig_parse_comma_sep_array_long(char *string, unsigned long long *val,
|
||||
unsigned int max_length)
|
||||
{
|
||||
int ret = 0;
|
||||
char *tmp;
|
||||
|
@ -580,19 +549,6 @@ int argconfig_parse_comma_sep_array_long(char *string,
|
|||
}
|
||||
}
|
||||
|
||||
void argconfig_register_help_func(argconfig_help_func * f)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_HELP_FUNC; i++) {
|
||||
if (help_funcs[i] == NULL) {
|
||||
help_funcs[i] = f;
|
||||
if (i < MAX_HELP_FUNC - 1)
|
||||
help_funcs[i + 1] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool argconfig_parse_seen(struct argconfig_commandline_options *s,
|
||||
const char *option)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue