diff --git a/cli/src/utils.c b/cli/src/utils.c index 4c4703123..db4d2f1c8 100644 --- a/cli/src/utils.c +++ b/cli/src/utils.c @@ -57,6 +57,80 @@ next_arg (int *argc, char ***argv) return 0; } +/* + * Helper function to parse command-line arguments. + * arg_arr: description of arguments to look for + * last: whether these are last expected arguments + * argc: command-line argument array + * argv: command-line argument array size + * error: error set on a failure (when FALSE is returned) + * Returns: TRUE on success, FALSE on an error and sets 'error' + */ +gboolean +nmc_parse_args (nmc_arg_t *arg_arr, gboolean last, int *argc, char ***argv, GError **error) +{ + nmc_arg_t *p; + gboolean found; + gboolean have_mandatory; + + g_return_val_if_fail (arg_arr != NULL, FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + while (*argc > 0) { + found = FALSE; + + for (p = arg_arr; p->name; p++) { + if (strcmp (**argv, p->name) == 0) { + + if (p->found) { + /* Don't allow repeated arguments, because the argument of the same + * name could be used later on the line for another purpose. Assume + * that's the case and return. + */ + return TRUE; + } + + if (p->has_value) { + if (next_arg (argc, argv) != 0) { + g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: value for '%s' argument is required."), *(*argv-1)); + return FALSE; + } + *(p->value) = **argv; + } + p->found = TRUE; + found = TRUE; + break; + } + } + + if (!found) { + have_mandatory = TRUE; + for (p = arg_arr; p->name; p++) { + if (p->mandatory && !p->found) { + have_mandatory = FALSE; + break; + } + } + + if (have_mandatory && !last) + return TRUE; + + if (p && p->name) + g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: Argument '%s' was expected, but '%s' provided."), p->name, **argv); + else + g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: Unexpected argument '%s'"), **argv); + return FALSE; + } + + next_arg (argc, argv); + } + + return TRUE; +} + /* * Convert SSID to a printable form. * If it is an UTF-8 string, enclose it in quotes and return it. diff --git a/cli/src/utils.h b/cli/src/utils.h index 7aabd9644..226857ec0 100644 --- a/cli/src/utils.h +++ b/cli/src/utils.h @@ -24,9 +24,20 @@ #include "nmcli.h" +/* === Types === */ + +typedef struct { + const char *name; + gboolean has_value; + const char **value; + gboolean mandatory; + gboolean found; +} nmc_arg_t; + /* === Functions === */ int matches (const char *cmd, const char *pattern); int next_arg (int *argc, char ***argv); +gboolean nmc_parse_args (nmc_arg_t *arg_arr, gboolean last, int *argc, char ***argv, GError **error); char *ssid_to_printable (const char *str, gsize len); char *nmc_ip4_address_as_string (guint32 ip, GError **error); char *nmc_ip6_address_as_string (const struct in6_addr *ip, GError **error);