version 1.42, 2021/08/21 18:39:07 |
version 1.43, 2021/08/21 20:46:43 |
|
|
|
|
struct args { |
struct args { |
struct args_tree tree; |
struct args_tree tree; |
int argc; |
u_int count; |
char **argv; |
struct args_value *values; |
}; |
}; |
|
|
static struct args_entry *args_find(struct args *, u_char); |
static struct args_entry *args_find(struct args *, u_char); |
|
|
return (RB_FIND(args_tree, &args->tree, &entry)); |
return (RB_FIND(args_tree, &args->tree, &entry)); |
} |
} |
|
|
|
/* Copy value. */ |
|
static void |
|
args_copy_value(struct args_value *to, struct args_value *from) |
|
{ |
|
to->type = from->type; |
|
switch (from->type) { |
|
case ARGS_NONE: |
|
break; |
|
case ARGS_COMMANDS: |
|
to->cmdlist = from->cmdlist; |
|
to->cmdlist->references++; |
|
break; |
|
case ARGS_STRING: |
|
to->string = xstrdup(from->string); |
|
break; |
|
} |
|
} |
|
|
/* Get value as string. */ |
/* Get value as string. */ |
static char * |
static const char * |
args_value_as_string(struct args_value *value) |
args_value_as_string(struct args_value *value) |
{ |
{ |
switch (value->type) { |
switch (value->type) { |
case ARGS_NONE: |
case ARGS_NONE: |
return (xstrdup("")); |
return (""); |
case ARGS_COMMANDS: |
case ARGS_COMMANDS: |
return (cmd_list_print(value->cmdlist, 0)); |
if (value->cached == NULL) |
|
value->cached = cmd_list_print(value->cmdlist, 0); |
|
return (value->cached); |
case ARGS_STRING: |
case ARGS_STRING: |
return (xstrdup(value->string)); |
return (value->string); |
} |
} |
} |
} |
|
|
|
|
{ |
{ |
struct args *args; |
struct args *args; |
u_int i; |
u_int i; |
struct args_value *value; |
struct args_value *value, *new; |
u_char flag, argument; |
u_char flag, argument; |
const char *found, *string; |
const char *found, *string, *s; |
char *s; |
|
|
|
if (count == 0) |
if (count == 0) |
return (args_create()); |
return (args_create()); |
|
|
args = args_create(); |
args = args_create(); |
for (i = 1; i < count; /* nothing */) { |
for (i = 1; i < count; /* nothing */) { |
value = &values[i]; |
value = &values[i]; |
|
|
s = args_value_as_string(value); |
|
log_debug("%s: %u = %s", __func__, i, s); |
|
free(s); |
|
|
|
if (value->type != ARGS_STRING) |
if (value->type != ARGS_STRING) |
break; |
break; |
|
|
|
|
args_set(args, flag, NULL); |
args_set(args, flag, NULL); |
continue; |
continue; |
} |
} |
if (*string != '\0') |
new = xcalloc(1, sizeof *value); |
s = xstrdup(string); |
if (*string != '\0') { |
else { |
new->type = ARGS_STRING; |
|
new->string = xstrdup(string); |
|
} else { |
if (i == count) { |
if (i == count) { |
args_free(args); |
args_free(args); |
return (NULL); |
return (NULL); |
} |
} |
s = args_value_as_string(&values[i++]); |
args_copy_value(new, &values[i++]); |
} |
} |
|
s = args_value_as_string(new); |
log_debug("%s: add -%c = %s", __func__, flag, s); |
log_debug("%s: add -%c = %s", __func__, flag, s); |
args_set(args, flag, s); |
args_set(args, flag, new); |
free(s); |
|
break; |
break; |
} |
} |
} |
} |
|
|
|
|
s = args_value_as_string(value); |
s = args_value_as_string(value); |
log_debug("%s: %u = %s", __func__, i, s); |
log_debug("%s: %u = %s", __func__, i, s); |
cmd_append_argv(&args->argc, &args->argv, s); |
|
free(s); |
args->values = xrecallocarray(args->values, |
|
args->count, args->count + 1, sizeof *args->values); |
|
args_copy_value(&args->values[args->count++], value); |
} |
} |
} |
} |
|
|
if ((parse->lower != -1 && args->argc < parse->lower) || |
if ((parse->lower != -1 && args->count < (u_int)parse->lower) || |
(parse->upper != -1 && args->argc > parse->upper)) { |
(parse->upper != -1 && args->count > (u_int)parse->upper)) { |
args_free(args); |
args_free(args); |
return (NULL); |
return (NULL); |
} |
} |
|
|
cmd_list_free(value->cmdlist); |
cmd_list_free(value->cmdlist); |
break; |
break; |
} |
} |
|
free(value->cached); |
} |
} |
|
|
/* Free an arguments set. */ |
/* Free an arguments set. */ |
|
|
struct args_entry *entry1; |
struct args_entry *entry1; |
struct args_value *value; |
struct args_value *value; |
struct args_value *value1; |
struct args_value *value1; |
|
u_int i; |
|
|
cmd_free_argv(args->argc, args->argv); |
for (i = 0; i < args->count; i++) |
|
args_free_value(&args->values[i]); |
|
free(args->values); |
|
|
RB_FOREACH_SAFE(entry, args_tree, &args->tree, entry1) { |
RB_FOREACH_SAFE(entry, args_tree, &args->tree, entry1) { |
RB_REMOVE(args_tree, &args->tree, entry); |
RB_REMOVE(args_tree, &args->tree, entry); |
|
|
void |
void |
args_vector(struct args *args, int *argc, char ***argv) |
args_vector(struct args *args, int *argc, char ***argv) |
{ |
{ |
*argc = args->argc; |
struct args_value *value; |
*argv = cmd_copy_argv(args->argc, args->argv); |
u_int i; |
|
|
|
*argc = 0; |
|
*argv = NULL; |
|
|
|
for (i = 0; i < args->count; i++) { |
|
value = &args->values[i]; |
|
cmd_append_argv(argc, argv, args_value_as_string(value)); |
|
} |
} |
} |
|
|
/* Add to string. */ |
/* Add to string. */ |
|
|
free(s); |
free(s); |
} |
} |
|
|
/* Add argument to string. */ |
/* Add value to string. */ |
static void |
static void |
args_print_add_argument(char **buf, size_t *len, const char *argument) |
args_print_add_value(char **buf, size_t *len, struct args_value *value) |
{ |
{ |
char *escaped; |
char *expanded = NULL; |
|
|
if (**buf != '\0') |
if (**buf != '\0') |
args_print_add(buf, len, " "); |
args_print_add(buf, len, " "); |
|
|
escaped = args_escape(argument); |
switch (value->type) { |
args_print_add(buf, len, "%s", escaped); |
case ARGS_NONE: |
free(escaped); |
break; |
|
case ARGS_COMMANDS: |
|
expanded = cmd_list_print(value->cmdlist, 0); |
|
args_print_add(buf, len, "{ %s }", expanded); |
|
break; |
|
case ARGS_STRING: |
|
expanded = args_escape(value->string); |
|
args_print_add(buf, len, "%s", expanded); |
|
break; |
|
} |
|
free(expanded); |
} |
} |
|
|
/* Print a set of arguments. */ |
/* Print a set of arguments. */ |
|
|
{ |
{ |
size_t len; |
size_t len; |
char *buf; |
char *buf; |
int i; |
u_int i, j; |
u_int j; |
|
struct args_entry *entry; |
struct args_entry *entry; |
struct args_value *value; |
struct args_value *value; |
|
|
|
|
args_print_add(&buf, &len, " -%c", entry->flag); |
args_print_add(&buf, &len, " -%c", entry->flag); |
else |
else |
args_print_add(&buf, &len, "-%c", entry->flag); |
args_print_add(&buf, &len, "-%c", entry->flag); |
args_print_add_argument(&buf, &len, value->string); |
args_print_add_value(&buf, &len, value); |
} |
} |
} |
} |
|
|
/* And finally the argument vector. */ |
/* And finally the argument vector. */ |
for (i = 0; i < args->argc; i++) |
for (i = 0; i < args->count; i++) |
args_print_add_argument(&buf, &len, args->argv[i]); |
args_print_add_value(&buf, &len, &args->values[i]); |
|
|
return (buf); |
return (buf); |
} |
} |
|
|
|
|
/* Set argument value in the arguments tree. */ |
/* Set argument value in the arguments tree. */ |
void |
void |
args_set(struct args *args, u_char flag, const char *s) |
args_set(struct args *args, u_char flag, struct args_value *value) |
{ |
{ |
struct args_entry *entry; |
struct args_entry *entry; |
struct args_value *value; |
|
|
|
entry = args_find(args, flag); |
entry = args_find(args, flag); |
if (entry == NULL) { |
if (entry == NULL) { |
|
|
RB_INSERT(args_tree, &args->tree, entry); |
RB_INSERT(args_tree, &args->tree, entry); |
} else |
} else |
entry->count++; |
entry->count++; |
|
if (value != NULL && value->type != ARGS_NONE) |
if (s != NULL) { |
|
value = xcalloc(1, sizeof *value); |
|
value->string = xstrdup(s); |
|
TAILQ_INSERT_TAIL(&entry->values, value, entry); |
TAILQ_INSERT_TAIL(&entry->values, value, entry); |
} |
|
} |
} |
|
|
/* Get argument value. Will be NULL if it isn't present. */ |
/* Get argument value. Will be NULL if it isn't present. */ |
|
|
u_int |
u_int |
args_count(struct args *args) |
args_count(struct args *args) |
{ |
{ |
return (args->argc); |
return (args->count); |
} |
} |
|
|
|
/* Get argument value. */ |
|
struct args_value * |
|
args_value(struct args *args, u_int idx) |
|
{ |
|
if (idx >= args->count) |
|
return (NULL); |
|
return (&args->values[idx]); |
|
} |
|
|
/* Return argument as string. */ |
/* Return argument as string. */ |
const char * |
const char * |
args_string(struct args *args, u_int idx) |
args_string(struct args *args, u_int idx) |
{ |
{ |
if (idx >= (u_int)args->argc) |
if (idx >= (u_int)args->count) |
return (NULL); |
return (NULL); |
return (args->argv[idx]); |
return (args_value_as_string(&args->values[idx])); |
} |
} |
|
|
/* Get first value in argument. */ |
/* Get first value in argument. */ |