nmcli: allow cmd specific option parsing in next_arg() func

Options dependant on specific commands (e.g., nmcli connection show
--active) are now allowed to be processed by the next_arg() function.
This would allow autocompletion to expand options belonging to specific
command first, and then global ones.

Note that global options ("--ask" and "--show-secrets") will be auto-completed
everywhere but only if at least a '-' is passed. Command specific ones
(--temporary, --active, --order) will be auto-completed only after the command
they belongs to but without requiring the user to pass a heading '-'.

Example:
'nmcli connection show -a'
will expand '-a' into '--active', but
'nmcli connection add -a`
will expand '-a' into '--ask' (as it is a global option)

This commit fixes also autocompletion for:
nmcli connection modify --temporary

(cherry picked from commit 6a3d77fbe6)
This commit is contained in:
Francesco Giudici
2017-03-30 16:09:46 +02:00
parent 77e1304f73
commit 72d5be1789
8 changed files with 189 additions and 79 deletions

View File

@@ -139,6 +139,7 @@ secrets_requested (NMSecretAgentSimple *agent,
static NMCResultCode static NMCResultCode
do_agent_secret (NmCli *nmc, int argc, char **argv) do_agent_secret (NmCli *nmc, int argc, char **argv)
{ {
next_arg (nmc, &argc, &argv, NULL);
if (nmc->complete) if (nmc->complete)
return nmc->return_value; return nmc->return_value;
@@ -167,6 +168,7 @@ do_agent_polkit (NmCli *nmc, int argc, char **argv)
{ {
GError *error = NULL; GError *error = NULL;
next_arg (nmc, &argc, &argv, NULL);
if (nmc->complete) if (nmc->complete)
return nmc->return_value; return nmc->return_value;
@@ -192,6 +194,7 @@ do_agent_all (NmCli *nmc, int argc, char **argv)
{ {
NMCResultCode secret_res; NMCResultCode secret_res;
next_arg (nmc, &argc, &argv, NULL);
if (nmc->complete) if (nmc->complete)
return nmc->return_value; return nmc->return_value;
@@ -218,6 +221,7 @@ static const NMCCommand agent_cmds[] = {
NMCResultCode NMCResultCode
do_agent (NmCli *nmc, int argc, char **argv) do_agent (NmCli *nmc, int argc, char **argv)
{ {
next_arg (nmc, &argc, &argv, NULL);
nmc_do_cmd (nmc, agent_cmds, *argv, argc, argv); nmc_do_cmd (nmc, agent_cmds, *argv, argc, argv);
return nmc->return_value; return nmc->return_value;

View File

@@ -1754,7 +1754,6 @@ nmc_do_cmd (NmCli *nmc, const NMCCommand cmds[], const char *cmd, int argc, char
g_simple_async_result_complete_in_idle (simple); g_simple_async_result_complete_in_idle (simple);
g_object_unref (simple); g_object_unref (simple);
} else { } else {
next_arg (nmc, &argc, &argv);
call_cmd (nmc, simple, c, argc, argv); call_cmd (nmc, simple, c, argc, argv);
} }
} else if (cmd) { } else if (cmd) {

View File

@@ -1734,7 +1734,7 @@ get_connection (NmCli *nmc, int *argc, char ***argv, int *pos, GError **error)
* don't switch to next argument. * don't switch to next argument.
*/ */
if (!pos || !*pos) if (!pos || !*pos)
next_arg (nmc, argc, argv); next_arg (nmc, argc, argv, NULL);
return connection; return connection;
} }
@@ -1747,19 +1747,15 @@ do_connections_show (NmCli *nmc, int argc, char **argv)
GPtrArray *invisibles, *sorted_cons; GPtrArray *invisibles, *sorted_cons;
gboolean active_only = FALSE; gboolean active_only = FALSE;
GArray *order = NULL; GArray *order = NULL;
int i; int i, option;
/* check connection show options [--active] */ /* check connection show options [--active] [--order <order spec>] */
while (argc) { while ((option = next_arg (nmc, &argc, &argv, "--active", "--order", NULL)) > 0) {
if (argc == 1 && nmc->complete) { switch (option) {
nmc_complete_strings (*argv, "--active", case 1: /* --active */
"--order", NULL);
}
if (!active_only && nmc_arg_is_option (*argv, "active")) {
active_only = TRUE; active_only = TRUE;
next_arg (nmc, &argc, &argv); break;
} else if (!order && nmc_arg_is_option (*argv, "order")) { case 2: /* --order */
argc--; argc--;
argv++; argv++;
if (!argc) { if (!argc) {
@@ -1767,12 +1763,12 @@ do_connections_show (NmCli *nmc, int argc, char **argv)
_("'--order' argument is missing")); _("'--order' argument is missing"));
goto finish; goto finish;
} }
/* TODO: complete --order */
order = parse_preferred_connection_order (*argv, &err); order = parse_preferred_connection_order (*argv, &err);
if (err) if (err)
goto finish; goto finish;
next_arg (nmc, &argc, &argv); break;
} else { default:
g_assert_not_reached();
break; break;
} }
} }
@@ -1890,12 +1886,12 @@ do_connections_show (NmCli *nmc, int argc, char **argv)
if (!acon) if (!acon)
acon = get_ac_for_connection (active_cons, con); acon = get_ac_for_connection (active_cons, con);
if (active_only && !acon) { if (active_only && !acon) {
next_arg (nmc, &argc, &argv); next_arg (nmc, &argc, &argv, NULL);
continue; continue;
} }
if (nmc->complete) { if (nmc->complete) {
next_arg (nmc, &argc, &argv); next_arg (nmc, &argc, &argv, NULL);
continue; continue;
} }
@@ -1933,7 +1929,7 @@ do_connections_show (NmCli *nmc, int argc, char **argv)
* so process the same argument again. * so process the same argument again.
*/ */
if (!pos) if (!pos)
next_arg (nmc, &argc, &argv); next_arg (nmc, &argc, &argv, NULL);
} }
} }
@@ -2558,8 +2554,8 @@ do_connection_up (NmCli *nmc, int argc, char **argv)
gs_free_error GError *error = NULL; gs_free_error GError *error = NULL;
char **arg_arr = NULL; char **arg_arr = NULL;
int arg_num; int arg_num;
char ***argv_ptr = &argv; char ***argv_ptr;
int *argc_ptr = &argc; int *argc_ptr;
/* /*
* Set default timeout for connection activation. * Set default timeout for connection activation.
@@ -2568,6 +2564,10 @@ do_connection_up (NmCli *nmc, int argc, char **argv)
if (nmc->timeout == -1) if (nmc->timeout == -1)
nmc->timeout = 90; nmc->timeout = 90;
next_arg (nmc, &argc, &argv, NULL);
argv_ptr = &argv;
argc_ptr = &argc;
if (argc == 0 && nmc->ask) { if (argc == 0 && nmc->ask) {
char *line; char *line;
@@ -2634,7 +2634,7 @@ do_connection_up (NmCli *nmc, int argc, char **argv)
g_printerr (_("Unknown parameter: %s\n"), *argv); g_printerr (_("Unknown parameter: %s\n"), *argv);
} }
next_arg (nmc, &argc, &argv); next_arg (nmc, &argc, &argv, NULL);
} }
if (nmc->complete) if (nmc->complete)
@@ -2751,13 +2751,17 @@ do_connection_down (NmCli *nmc, int argc, char **argv)
const GPtrArray *active_cons; const GPtrArray *active_cons;
GSList *queue = NULL, *iter; GSList *queue = NULL, *iter;
char **arg_arr = NULL; char **arg_arr = NULL;
char **arg_ptr = argv; char **arg_ptr;
int arg_num = argc; int arg_num;
int idx = 0; int idx = 0;
if (nmc->timeout == -1) if (nmc->timeout == -1)
nmc->timeout = 10; nmc->timeout = 10;
next_arg (nmc, &argc, &argv, NULL);
arg_ptr = argv;
arg_num = argc;
if (argc == 0) { if (argc == 0) {
/* nmc_do_cmd() should not call this with argc=0. */ /* nmc_do_cmd() should not call this with argc=0. */
g_assert (!nmc->complete); g_assert (!nmc->complete);
@@ -2816,7 +2820,7 @@ do_connection_down (NmCli *nmc, int argc, char **argv)
} }
if (idx == 0) if (idx == 0)
next_arg (nmc->ask ? NULL : nmc, &arg_num, &arg_ptr); next_arg (nmc->ask ? NULL : nmc, &arg_num, &arg_ptr, NULL);
} }
if (!queue) { if (!queue) {
@@ -4930,6 +4934,8 @@ do_connection_add (NmCli *nmc, int argc, char **argv)
OptionInfo *candidate; OptionInfo *candidate;
gboolean seen_dash_dash = FALSE; gboolean seen_dash_dash = FALSE;
next_arg (nmc, &argc, &argv, NULL);
rl_attempted_completion_function = (rl_completion_func_t *) nmcli_con_add_tab_completion; rl_attempted_completion_function = (rl_completion_func_t *) nmcli_con_add_tab_completion;
nmc->return_value = NMC_RESULT_SUCCESS; nmc->return_value = NMC_RESULT_SUCCESS;
@@ -4949,7 +4955,7 @@ read_properties:
* options and properties to be separated with "--" */ * options and properties to be separated with "--" */
g_clear_error (&error); g_clear_error (&error);
seen_dash_dash = TRUE; seen_dash_dash = TRUE;
next_arg (nmc, &argc, &argv); next_arg (nmc, &argc, &argv, NULL);
goto read_properties; goto read_properties;
} else if (g_strcmp0 (*argv, "save") == 0) { } else if (g_strcmp0 (*argv, "save") == 0) {
/* It would be better if "save" was a separate argument and not /* It would be better if "save" was a separate argument and not
@@ -4971,7 +4977,7 @@ read_properties:
g_clear_error (&error); g_clear_error (&error);
goto finish; goto finish;
} }
next_arg (nmc, &argc, &argv); next_arg (nmc, &argc, &argv, NULL);
goto read_properties; goto read_properties;
} }
@@ -7891,6 +7897,7 @@ do_connection_edit (NmCli *nmc, int argc, char **argv)
{"path", TRUE, &con_path, FALSE}, {"path", TRUE, &con_path, FALSE},
{NULL} }; {NULL} };
next_arg (nmc, &argc, &argv, NULL);
if (argc == 1 && nmc->complete) if (argc == 1 && nmc->complete)
nmc_complete_strings (*argv, "type", "con-name", "id", "uuid", "path", NULL); nmc_complete_strings (*argv, "type", "con-name", "id", "uuid", "path", NULL);
@@ -8094,11 +8101,10 @@ do_connection_modify (NmCli *nmc,
GError *error = NULL; GError *error = NULL;
gboolean temporary = FALSE; gboolean temporary = FALSE;
if (argc && nmc_arg_is_option (*argv, "temporary")) { /* Check --temporary */
if (nmc->complete) if (next_arg (nmc, &argc, &argv, "--temporary", NULL) > 0) {
goto finish;
temporary = TRUE; temporary = TRUE;
next_arg (nmc, &argc, &argv); next_arg (nmc, &argc, &argv, NULL);
} }
connection = get_connection (nmc, &argc, &argv, NULL, &error); connection = get_connection (nmc, &argc, &argv, NULL, &error);
@@ -8187,12 +8193,17 @@ do_connection_clone (NmCli *nmc, int argc, char **argv)
gboolean temporary = FALSE; gboolean temporary = FALSE;
char **arg_arr = NULL; char **arg_arr = NULL;
int arg_num; int arg_num;
char ***argv_ptr = &argv; char ***argv_ptr;
int *argc_ptr = &argc; int *argc_ptr;
GError *error = NULL; GError *error = NULL;
if (argc == 1 && nmc->complete) if (next_arg (nmc, &argc, &argv, "--temporary", NULL) > 0) {
nmc_complete_strings (*argv, "temporary", NULL); temporary = TRUE;
next_arg (nmc, &argc, &argv, NULL);
}
argv_ptr = &argv;
argc_ptr = &argc;
if (argc == 0 && nmc->ask) { if (argc == 0 && nmc->ask) {
char *line; char *line;
@@ -8205,9 +8216,6 @@ do_connection_clone (NmCli *nmc, int argc, char **argv)
g_free (line); g_free (line);
argv_ptr = &arg_arr; argv_ptr = &arg_arr;
argc_ptr = &arg_num; argc_ptr = &arg_num;
} else if (nmc_arg_is_option (*argv, "temporary")) {
temporary = TRUE;
next_arg (nmc, &argc, &argv);
} }
connection = get_connection (nmc, argc_ptr, argv_ptr, NULL, &error); connection = get_connection (nmc, argc_ptr, argv_ptr, NULL, &error);
@@ -8230,7 +8238,7 @@ do_connection_clone (NmCli *nmc, int argc, char **argv)
goto finish; goto finish;
} }
if (next_arg (nmc->ask ? NULL : nmc, argc_ptr, argv_ptr) == 0) { if (next_arg (nmc->ask ? NULL : nmc, argc_ptr, argv_ptr, NULL) == 0) {
g_string_printf (nmc->return_text, _("Error: unknown extra argument: '%s'."), *argv); g_string_printf (nmc->return_text, _("Error: unknown extra argument: '%s'."), *argv);
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
goto finish; goto finish;
@@ -8301,8 +8309,8 @@ do_connection_delete (NmCli *nmc, int argc, char **argv)
ConnectionCbInfo *info = NULL; ConnectionCbInfo *info = NULL;
GSList *queue = NULL, *iter; GSList *queue = NULL, *iter;
char **arg_arr = NULL, *old_arg; char **arg_arr = NULL, *old_arg;
char **arg_ptr = argv; char **arg_ptr;
int arg_num = argc; int arg_num;
GString *invalid_cons = NULL; GString *invalid_cons = NULL;
int pos = 0; int pos = 0;
GError *error = NULL; GError *error = NULL;
@@ -8310,6 +8318,10 @@ do_connection_delete (NmCli *nmc, int argc, char **argv)
if (nmc->timeout == -1) if (nmc->timeout == -1)
nmc->timeout = 10; nmc->timeout = 10;
next_arg (nmc, &argc, &argv, NULL);
arg_ptr = argv;
arg_num = argc;
if (argc == 0) { if (argc == 0) {
if (nmc->ask) { if (nmc->ask) {
char *line; char *line;
@@ -8440,6 +8452,7 @@ do_connection_monitor (NmCli *nmc, int argc, char **argv)
{ {
GError *error = NULL; GError *error = NULL;
next_arg (nmc, &argc, &argv, NULL);
if (argc == 0) { if (argc == 0) {
/* No connections specified. Monitor all. */ /* No connections specified. Monitor all. */
const GPtrArray *connections; const GPtrArray *connections;
@@ -8488,6 +8501,7 @@ do_connection_reload (NmCli *nmc, int argc, char **argv)
{ {
GError *error = NULL; GError *error = NULL;
next_arg (nmc, &argc, &argv, NULL);
if (nmc->complete) if (nmc->complete)
return nmc->return_value; return nmc->return_value;
@@ -8508,6 +8522,7 @@ do_connection_load (NmCli *nmc, int argc, char **argv)
char **filenames, **failures = NULL; char **filenames, **failures = NULL;
int i; int i;
next_arg (nmc, &argc, &argv, NULL);
if (argc == 0) { if (argc == 0) {
g_string_printf (nmc->return_text, _("Error: No connection specified.")); g_string_printf (nmc->return_text, _("Error: No connection specified."));
return NMC_RESULT_ERROR_USER_INPUT; return NMC_RESULT_ERROR_USER_INPUT;
@@ -8571,6 +8586,13 @@ do_connection_import (NmCli *nmc, int argc, char **argv)
gs_free char *service_type = NULL; gs_free char *service_type = NULL;
gboolean temporary = FALSE; gboolean temporary = FALSE;
/* Check --temporary */
if (next_arg (nmc, &argc, &argv, "--temporary", NULL) > 0) {
temporary = TRUE;
next_arg (nmc, &argc, &argv, NULL);
}
if (argc == 0) { if (argc == 0) {
/* nmc_do_cmd() should not call this with argc=0. */ /* nmc_do_cmd() should not call this with argc=0. */
g_assert (!nmc->complete); g_assert (!nmc->complete);
@@ -8589,11 +8611,7 @@ do_connection_import (NmCli *nmc, int argc, char **argv)
while (argc > 0) { while (argc > 0) {
if (argc == 1 && nmc->complete) if (argc == 1 && nmc->complete)
nmc_complete_strings (*argv, "temporary", "type", "file", NULL); nmc_complete_strings (*argv, "type", "file", NULL);
if (nmc_arg_is_option (*argv, "temporary")) {
temporary = TRUE;
next_arg (nmc, &argc, &argv);
}
if (strcmp (*argv, "type") == 0) { if (strcmp (*argv, "type") == 0) {
argc--; argc--;
@@ -8632,7 +8650,7 @@ do_connection_import (NmCli *nmc, int argc, char **argv)
goto finish; goto finish;
} }
next_arg (nmc, &argc, &argv); next_arg (nmc, &argc, &argv, NULL);
} }
if (nmc->complete) if (nmc->complete)
@@ -8708,8 +8726,12 @@ do_connection_export (NmCli *nmc, int argc, char **argv)
char tmpfile[] = "/tmp/nmcli-export-temp-XXXXXX"; char tmpfile[] = "/tmp/nmcli-export-temp-XXXXXX";
char **arg_arr = NULL; char **arg_arr = NULL;
int arg_num; int arg_num;
char ***argv_ptr = &argv; char ***argv_ptr;
int *argc_ptr = &argc; int *argc_ptr;
next_arg (nmc, &argc, &argv, NULL);
argv_ptr = &argv;
argc_ptr = &argc;
if (argc == 0 && nmc->ask) { if (argc == 0 && nmc->ask) {
char *line; char *line;
@@ -8740,7 +8762,7 @@ do_connection_export (NmCli *nmc, int argc, char **argv)
argv++; argv++;
} }
if (next_arg (nmc->ask ? NULL : nmc, argc_ptr, argv_ptr) == 0) { if (next_arg (nmc->ask ? NULL : nmc, argc_ptr, argv_ptr, NULL) == 0) {
g_string_printf (nmc->return_text, _("Error: unknown extra argument: '%s'."), *argv); g_string_printf (nmc->return_text, _("Error: unknown extra argument: '%s'."), *argv);
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
goto finish; goto finish;
@@ -8916,6 +8938,8 @@ static const NMCCommand connection_cmds[] = {
NMCResultCode NMCResultCode
do_connections (NmCli *nmc, int argc, char **argv) do_connections (NmCli *nmc, int argc, char **argv)
{ {
next_arg (nmc, &argc, &argv, NULL);
/* Register polkit agent */ /* Register polkit agent */
nmc_start_polkit_agent_start_try (nmc); nmc_start_polkit_agent_start_try (nmc);

View File

@@ -613,7 +613,7 @@ get_device_list (NmCli *nmc, int argc, char **argv)
} }
/* Take next argument */ /* Take next argument */
next_arg (nmc->ask ? NULL : nmc, &arg_num, &arg_ptr); next_arg (nmc->ask ? NULL : nmc, &arg_num, &arg_ptr, NULL);
} }
g_free (devices); g_free (devices);
@@ -642,7 +642,7 @@ get_device (NmCli *nmc, int *argc, char ***argv, GError **error)
} }
} else { } else {
ifname = **argv; ifname = **argv;
next_arg (nmc, argc, argv); next_arg (nmc, argc, argv, NULL);
} }
devices = nmc_get_devices_sorted (nmc->client); devices = nmc_get_devices_sorted (nmc->client);
@@ -1490,13 +1490,15 @@ do_devices_status (NmCli *nmc, int argc, char **argv)
NmcOutputField *tmpl, *arr; NmcOutputField *tmpl, *arr;
size_t tmpl_len; size_t tmpl_len;
next_arg (nmc, &argc, &argv, NULL);
/* Nothing to complete */ /* Nothing to complete */
if (nmc->complete) if (nmc->complete)
return nmc->return_value; return nmc->return_value;
while (argc > 0) { while (argc > 0) {
g_printerr (_("Unknown parameter: %s\n"), *argv); g_printerr (_("Unknown parameter: %s\n"), *argv);
next_arg (nmc, &argc, &argv); next_arg (nmc, &argc, &argv, NULL);
} }
if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0) if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
@@ -1538,6 +1540,7 @@ do_device_show (NmCli *nmc, int argc, char **argv)
{ {
gs_free_error GError *error = NULL; gs_free_error GError *error = NULL;
next_arg (nmc, &argc, &argv, NULL);
if (!nmc->mode_specified) if (!nmc->mode_specified)
nmc->multiline_output = TRUE; /* multiline mode is default for 'device show' */ nmc->multiline_output = TRUE; /* multiline mode is default for 'device show' */
@@ -1830,6 +1833,7 @@ do_device_connect (NmCli *nmc, int argc, char **argv)
if (nmc->timeout == -1) if (nmc->timeout == -1)
nmc->timeout = 90; nmc->timeout = 90;
next_arg (nmc, &argc, &argv, NULL);
device = get_device (nmc, &argc, &argv, &error); device = get_device (nmc, &argc, &argv, &error);
if (!device) { if (!device) {
g_string_printf (nmc->return_text, _("Error: %s."), error->message); g_string_printf (nmc->return_text, _("Error: %s."), error->message);
@@ -1998,6 +2002,7 @@ do_device_reapply (NmCli *nmc, int argc, char **argv)
if (nmc->timeout == -1) if (nmc->timeout == -1)
nmc->timeout = 10; nmc->timeout = 10;
next_arg (nmc, &argc, &argv, NULL);
device = get_device (nmc, &argc, &argv, &error); device = get_device (nmc, &argc, &argv, &error);
if (!device) { if (!device) {
g_string_printf (nmc->return_text, _("Error: %s."), error->message); g_string_printf (nmc->return_text, _("Error: %s."), error->message);
@@ -2105,6 +2110,7 @@ do_device_modify (NmCli *nmc, int argc, char **argv)
ModifyInfo *info = NULL; ModifyInfo *info = NULL;
gs_free_error GError *error = NULL; gs_free_error GError *error = NULL;
next_arg (nmc, &argc, &argv, NULL);
device = get_device (nmc, &argc, &argv, &error); device = get_device (nmc, &argc, &argv, &error);
if (!device) { if (!device) {
g_string_printf (nmc->return_text, _("Error: %s."), error->message); g_string_printf (nmc->return_text, _("Error: %s."), error->message);
@@ -2171,6 +2177,7 @@ do_devices_disconnect (NmCli *nmc, int argc, char **argv)
if (nmc->timeout == -1) if (nmc->timeout == -1)
nmc->timeout = 10; nmc->timeout = 10;
next_arg (nmc, &argc, &argv, NULL);
queue = get_device_list (nmc, argc, argv); queue = get_device_list (nmc, argc, argv);
if (!queue) if (!queue)
return nmc->return_value; return nmc->return_value;
@@ -2240,6 +2247,7 @@ do_devices_delete (NmCli *nmc, int argc, char **argv)
if (nmc->timeout == -1) if (nmc->timeout == -1)
nmc->timeout = 10; nmc->timeout = 10;
next_arg (nmc, &argc, &argv, NULL);
queue = get_device_list (nmc, argc, argv); queue = get_device_list (nmc, argc, argv);
if (!queue) if (!queue)
return nmc->return_value; return nmc->return_value;
@@ -2288,9 +2296,9 @@ do_device_set (NmCli *nmc, int argc, char **argv)
}; };
gs_free_error GError *error = NULL; gs_free_error GError *error = NULL;
if (argc >= 1 && g_strcmp0 (*argv, "ifname") == 0) { next_arg (nmc, &argc, &argv, NULL);
next_arg (nmc, &argc, &argv); if (argc >= 1 && g_strcmp0 (*argv, "ifname") == 0)
} next_arg (nmc, &argc, &argv, NULL);
device = get_device (nmc, &argc, &argv, &error); device = get_device (nmc, &argc, &argv, &error);
if (!device) { if (!device) {
@@ -2348,7 +2356,7 @@ do_device_set (NmCli *nmc, int argc, char **argv)
g_string_printf (nmc->return_text, _("Error: property '%s' is not known."), *argv); g_string_printf (nmc->return_text, _("Error: property '%s' is not known."), *argv);
return NMC_RESULT_ERROR_USER_INPUT; return NMC_RESULT_ERROR_USER_INPUT;
} }
} while (next_arg (nmc, &argc, &argv) == 0); } while (next_arg (nmc, &argc, &argv, NULL) == 0);
if (nmc->complete) if (nmc->complete)
return nmc->return_value; return nmc->return_value;
@@ -2441,6 +2449,7 @@ do_devices_monitor (NmCli *nmc, int argc, char **argv)
if (nmc->complete) if (nmc->complete)
return nmc->return_value; return nmc->return_value;
next_arg (nmc, &argc, &argv, NULL);
if (argc == 0) { if (argc == 0) {
/* No devices specified. Monitor all. */ /* No devices specified. Monitor all. */
const GPtrArray *devices = nm_client_get_devices (nmc->client); const GPtrArray *devices = nm_client_get_devices (nmc->client);
@@ -2629,6 +2638,7 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv)
devices = nmc_get_devices_sorted (nmc->client); devices = nmc_get_devices_sorted (nmc->client);
next_arg (nmc, &argc, &argv, NULL);
while (argc > 0) { while (argc > 0) {
if (argc == 1 && nmc->complete) if (argc == 1 && nmc->complete)
nmc_complete_strings (*argv, "ifname", "bssid", NULL); nmc_complete_strings (*argv, "ifname", "bssid", NULL);
@@ -2657,7 +2667,7 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv)
g_printerr (_("Unknown parameter: %s\n"), *argv); g_printerr (_("Unknown parameter: %s\n"), *argv);
} }
next_arg (nmc, &argc, &argv); next_arg (nmc, &argc, &argv, NULL);
} }
if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0) if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
@@ -2846,6 +2856,7 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv)
devices = nmc_get_devices_sorted (nmc->client); devices = nmc_get_devices_sorted (nmc->client);
next_arg (nmc, &argc, &argv, NULL);
/* Get the first compulsory argument (SSID or BSSID) */ /* Get the first compulsory argument (SSID or BSSID) */
if (argc > 0) { if (argc > 0) {
param_user = *argv; param_user = *argv;
@@ -2854,7 +2865,7 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv)
if (argc == 1 && nmc->complete) if (argc == 1 && nmc->complete)
complete_aps (devices, NULL, param_user, param_user); complete_aps (devices, NULL, param_user, param_user);
next_arg (nmc, &argc, &argv); next_arg (nmc, &argc, &argv, NULL);
} else { } else {
/* nmc_do_cmd() should not call this with argc=0. */ /* nmc_do_cmd() should not call this with argc=0. */
g_assert (!nmc->complete); g_assert (!nmc->complete);
@@ -2985,7 +2996,7 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv)
g_printerr (_("Unknown parameter: %s\n"), *argv); g_printerr (_("Unknown parameter: %s\n"), *argv);
} }
next_arg (nmc, &argc, &argv); next_arg (nmc, &argc, &argv, NULL);
} }
if (nmc->complete) if (nmc->complete)
@@ -3079,7 +3090,7 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv)
if (con_name) if (con_name)
g_object_set (s_con, NM_SETTING_CONNECTION_ID, con_name, NULL); g_object_set (s_con, NM_SETTING_CONNECTION_ID, con_name, NULL);
/* Connection will only be visible to this user when '--private' is specified */ /* Connection will only be visible to this user when 'private' is specified */
if (private) if (private)
nm_setting_connection_add_permission (s_con, "user", g_get_user_name (), NULL); nm_setting_connection_add_permission (s_con, "user", g_get_user_name (), NULL);
} }
@@ -3336,6 +3347,7 @@ do_device_wifi_hotspot (NmCli *nmc, int argc, char **argv)
devices = nmc_get_devices_sorted (nmc->client); devices = nmc_get_devices_sorted (nmc->client);
next_arg (nmc, &argc, &argv, NULL);
while (argc > 0) { while (argc > 0) {
if (argc == 1 && nmc->complete) { if (argc == 1 && nmc->complete) {
nmc_complete_strings (*argv, "ifname", "con-name", "ssid", "band", nmc_complete_strings (*argv, "ifname", "con-name", "ssid", "band",
@@ -3412,7 +3424,7 @@ do_device_wifi_hotspot (NmCli *nmc, int argc, char **argv)
return NMC_RESULT_ERROR_USER_INPUT; return NMC_RESULT_ERROR_USER_INPUT;
} }
next_arg (nmc, &argc, &argv); next_arg (nmc, &argc, &argv, NULL);
} }
show_password = nmc->show_secrets || show_password; show_password = nmc->show_secrets || show_password;
@@ -3558,6 +3570,7 @@ do_device_wifi_rescan (NmCli *nmc, int argc, char **argv)
ssids = g_ptr_array_new (); ssids = g_ptr_array_new ();
devices = nmc_get_devices_sorted (nmc->client); devices = nmc_get_devices_sorted (nmc->client);
next_arg (nmc, &argc, &argv, NULL);
/* Get the parameters */ /* Get the parameters */
while (argc > 0) { while (argc > 0) {
if (argc == 1 && nmc->complete) if (argc == 1 && nmc->complete)
@@ -3591,7 +3604,7 @@ do_device_wifi_rescan (NmCli *nmc, int argc, char **argv)
} else if (!nmc->complete) } else if (!nmc->complete)
g_printerr (_("Unknown parameter: %s\n"), *argv); g_printerr (_("Unknown parameter: %s\n"), *argv);
next_arg (nmc, &argc, &argv); next_arg (nmc, &argc, &argv, NULL);
} }
if (nmc->complete) if (nmc->complete)
@@ -3646,6 +3659,7 @@ static NMCCommand device_wifi_cmds[] = {
static NMCResultCode static NMCResultCode
do_device_wifi (NmCli *nmc, int argc, char **argv) do_device_wifi (NmCli *nmc, int argc, char **argv)
{ {
next_arg (nmc, &argc, &argv, NULL);
nmc_do_cmd (nmc, device_wifi_cmds, *argv, argc, argv); nmc_do_cmd (nmc, device_wifi_cmds, *argv, argc, argv);
return nmc->return_value; return nmc->return_value;
@@ -3743,6 +3757,7 @@ do_device_lldp_list (NmCli *nmc, int argc, char **argv)
char *fields_str; char *fields_str;
int counter = 0; int counter = 0;
next_arg (nmc, &argc, &argv, NULL);
while (argc > 0) { while (argc > 0) {
if (argc == 1 && nmc->complete) if (argc == 1 && nmc->complete)
nmc_complete_strings (*argv, "ifname", NULL); nmc_complete_strings (*argv, "ifname", NULL);
@@ -3765,7 +3780,7 @@ do_device_lldp_list (NmCli *nmc, int argc, char **argv)
return NMC_RESULT_ERROR_USER_INPUT; return NMC_RESULT_ERROR_USER_INPUT;
} }
next_arg (nmc, &argc, &argv); next_arg (nmc, &argc, &argv, NULL);
} }
if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0) if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
@@ -3814,6 +3829,7 @@ do_device_lldp (NmCli *nmc, int argc, char **argv)
if (!nmc->mode_specified) if (!nmc->mode_specified)
nmc->multiline_output = TRUE; /* multiline mode is default for 'device lldp' */ nmc->multiline_output = TRUE; /* multiline mode is default for 'device lldp' */
next_arg (nmc, &argc, &argv, NULL);
nmc_do_cmd (nmc, device_lldp_cmds, *argv, argc, argv); nmc_do_cmd (nmc, device_lldp_cmds, *argv, argc, argv);
return nmc->return_value; return nmc->return_value;
@@ -3879,6 +3895,8 @@ static const NMCCommand device_cmds[] = {
NMCResultCode NMCResultCode
do_devices (NmCli *nmc, int argc, char **argv) do_devices (NmCli *nmc, int argc, char **argv)
{ {
next_arg (nmc, &argc, &argv, NULL);
/* Register polkit agent */ /* Register polkit agent */
nmc_start_polkit_agent_start_try (nmc); nmc_start_polkit_agent_start_try (nmc);

View File

@@ -385,6 +385,7 @@ show_nm_status (NmCli *nmc, const char *pretty_header_name, const char *print_fl
static NMCResultCode static NMCResultCode
do_general_status (NmCli *nmc, int argc, char **argv) do_general_status (NmCli *nmc, int argc, char **argv)
{ {
next_arg (nmc, &argc, &argv, NULL);
if (nmc->complete) if (nmc->complete)
return nmc->return_value; return nmc->return_value;
@@ -559,6 +560,7 @@ show_nm_permissions (NmCli *nmc)
static NMCResultCode static NMCResultCode
do_general_permissions (NmCli *nmc, int argc, char **argv) do_general_permissions (NmCli *nmc, int argc, char **argv)
{ {
next_arg (nmc, &argc, &argv, NULL);
if (nmc->complete) if (nmc->complete)
return nmc->return_value; return nmc->return_value;
@@ -640,6 +642,7 @@ do_general_logging (NmCli *nmc, int argc, char **argv)
{ {
gs_free_error GError *error = NULL; gs_free_error GError *error = NULL;
next_arg (nmc, &argc, &argv, NULL);
if (argc == 0) { if (argc == 0) {
if (nmc->complete) if (nmc->complete)
return nmc->return_value; return nmc->return_value;
@@ -687,7 +690,7 @@ do_general_logging (NmCli *nmc, int argc, char **argv)
g_string_printf (nmc->return_text, _("Error: property '%s' is not known."), *argv); g_string_printf (nmc->return_text, _("Error: property '%s' is not known."), *argv);
return NMC_RESULT_ERROR_USER_INPUT; return NMC_RESULT_ERROR_USER_INPUT;
} }
} while (next_arg (nmc, &argc, &argv) == 0); } while (next_arg (nmc, &argc, &argv, NULL) == 0);
if (nmc->complete) if (nmc->complete)
return nmc->return_value; return nmc->return_value;
@@ -722,6 +725,7 @@ save_hostname_cb (GObject *object, GAsyncResult *result, gpointer user_data)
static NMCResultCode static NMCResultCode
do_general_hostname (NmCli *nmc, int argc, char **argv) do_general_hostname (NmCli *nmc, int argc, char **argv)
{ {
next_arg (nmc, &argc, &argv, NULL);
if (nmc->complete) if (nmc->complete)
return nmc->return_value; return nmc->return_value;
@@ -737,7 +741,7 @@ do_general_hostname (NmCli *nmc, int argc, char **argv)
/* hostname provided -> set it */ /* hostname provided -> set it */
const char *hostname = *argv; const char *hostname = *argv;
if (next_arg (nmc, &argc, &argv) == 0) if (next_arg (nmc, &argc, &argv, NULL) == 0)
g_print ("Warning: ignoring extra garbage after '%s' hostname\n", hostname); g_print ("Warning: ignoring extra garbage after '%s' hostname\n", hostname);
nmc->should_wait++; nmc->should_wait++;
@@ -762,6 +766,8 @@ static const NMCCommand general_cmds[] = {
NMCResultCode NMCResultCode
do_general (NmCli *nmc, int argc, char **argv) do_general (NmCli *nmc, int argc, char **argv)
{ {
next_arg (nmc, &argc, &argv, NULL);
/* Register polkit agent */ /* Register polkit agent */
nmc_start_polkit_agent_start_try (nmc); nmc_start_polkit_agent_start_try (nmc);
@@ -827,18 +833,21 @@ do_networking_on_off (NmCli *nmc, int argc, char **argv, gboolean enable)
static NMCResultCode static NMCResultCode
do_networking_on (NmCli *nmc, int argc, char **argv) do_networking_on (NmCli *nmc, int argc, char **argv)
{ {
next_arg (nmc, &argc, &argv, NULL);
return do_networking_on_off (nmc, argc, argv, TRUE); return do_networking_on_off (nmc, argc, argv, TRUE);
} }
static NMCResultCode static NMCResultCode
do_networking_off (NmCli *nmc, int argc, char **argv) do_networking_off (NmCli *nmc, int argc, char **argv)
{ {
next_arg (nmc, &argc, &argv, NULL);
return do_networking_on_off (nmc, argc, argv, FALSE); return do_networking_on_off (nmc, argc, argv, FALSE);
} }
static NMCResultCode static NMCResultCode
do_networking_connectivity (NmCli *nmc, int argc, char **argv) do_networking_connectivity (NmCli *nmc, int argc, char **argv)
{ {
next_arg (nmc, &argc, &argv, NULL);
if (nmc->complete) { if (nmc->complete) {
if (argc == 1) if (argc == 1)
nmc_complete_strings (*argv, "check", NULL); nmc_complete_strings (*argv, "check", NULL);
@@ -872,6 +881,7 @@ do_networking_connectivity (NmCli *nmc, int argc, char **argv)
static NMCResultCode static NMCResultCode
do_networking_show (NmCli *nmc, int argc, char **argv) do_networking_show (NmCli *nmc, int argc, char **argv)
{ {
next_arg (nmc, &argc, &argv, NULL);
if (nmc->complete) if (nmc->complete)
return nmc->return_value; return nmc->return_value;
@@ -893,6 +903,7 @@ static const NMCCommand networking_cmds[] = {
NMCResultCode NMCResultCode
do_networking (NmCli *nmc, int argc, char **argv) do_networking (NmCli *nmc, int argc, char **argv)
{ {
next_arg (nmc, &argc, &argv, NULL);
nmc_do_cmd (nmc, networking_cmds, *argv, argc, argv); nmc_do_cmd (nmc, networking_cmds, *argv, argc, argv);
return nmc->return_value; return nmc->return_value;
@@ -903,6 +914,7 @@ do_radio_all (NmCli *nmc, int argc, char **argv)
{ {
gboolean enable_flag; gboolean enable_flag;
next_arg (nmc, &argc, &argv, NULL);
if (argc == 0) { if (argc == 0) {
if (nmc->complete) if (nmc->complete)
return nmc->return_value; return nmc->return_value;
@@ -932,6 +944,7 @@ do_radio_wifi (NmCli *nmc, int argc, char **argv)
{ {
gboolean enable_flag; gboolean enable_flag;
next_arg (nmc, &argc, &argv, NULL);
if (argc == 0) { if (argc == 0) {
if (nmc->complete) if (nmc->complete)
return nmc->return_value; return nmc->return_value;
@@ -958,6 +971,7 @@ do_radio_wwan (NmCli *nmc, int argc, char **argv)
{ {
gboolean enable_flag; gboolean enable_flag;
next_arg (nmc, &argc, &argv, NULL);
if (argc == 0) { if (argc == 0) {
if (nmc->complete) if (nmc->complete)
return nmc->return_value; return nmc->return_value;
@@ -992,6 +1006,8 @@ static const NMCCommand radio_cmds[] = {
NMCResultCode NMCResultCode
do_radio (NmCli *nmc, int argc, char **argv) do_radio (NmCli *nmc, int argc, char **argv)
{ {
next_arg (nmc, &argc, &argv, NULL);
/* Register polkit agent */ /* Register polkit agent */
nmc_start_polkit_agent_start_try (nmc); nmc_start_polkit_agent_start_try (nmc);
@@ -1217,6 +1233,8 @@ do_overview (NmCli *nmc, int argc, char **argv)
char *tmp; char *tmp;
int i; int i;
next_arg (nmc, &argc, &argv, NULL);
/* Register polkit agent */ /* Register polkit agent */
nmc_start_polkit_agent_start_try (nmc); nmc_start_polkit_agent_start_try (nmc);
@@ -1316,6 +1334,8 @@ do_overview (NmCli *nmc, int argc, char **argv)
NMCResultCode NMCResultCode
do_monitor (NmCli *nmc, int argc, char **argv) do_monitor (NmCli *nmc, int argc, char **argv)
{ {
next_arg (nmc, &argc, &argv, NULL);
if (nmc->complete) if (nmc->complete)
return nmc->return_value; return nmc->return_value;

View File

@@ -219,9 +219,9 @@ process_command_line (NmCli *nmc, int argc, char **argv)
if (argc > 1 && nm_streq (argv[1], "--complete-args")) { if (argc > 1 && nm_streq (argv[1], "--complete-args")) {
nmc->complete = TRUE; nmc->complete = TRUE;
argv[1] = argv[0]; argv[1] = argv[0];
next_arg (nmc, &argc, &argv); next_arg (nmc, &argc, &argv, NULL);
} }
next_arg (nmc, &argc, &argv); next_arg (nmc, &argc, &argv, NULL);
/* parse options */ /* parse options */
while (argc) { while (argc) {
@@ -239,7 +239,7 @@ process_command_line (NmCli *nmc, int argc, char **argv)
opt++; opt++;
/* '--' ends options */ /* '--' ends options */
if (opt[1] == '\0') { if (opt[1] == '\0') {
next_arg (nmc, &argc, &argv); next_arg (nmc, &argc, &argv, NULL);
break; break;
} }
} }
@@ -390,7 +390,7 @@ process_command_line (NmCli *nmc, int argc, char **argv)
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
return FALSE; return FALSE;
} }
next_arg (nmc, &argc, &argv); next_arg (nmc, &argc, &argv, NULL);
} }
/* Now run the requested command */ /* Now run the requested command */

View File

@@ -51,21 +51,66 @@ parse_global_arg (NmCli *nmc, const char *arg)
return TRUE; return TRUE;
} }
/**
* next_arg:
* @nmc: NmCli data
* @*argc: pointer to left number of arguments to parse
* @***argv: pointer to const char *array of arguments still to parse
* @...: a %NULL terminated list of cmd options to match (e.g., "--active")
*
* Takes care of autocompleting options when needed and performs
* match against passed options while moving forward the pointer
* to the remaining arguments.
*
* Returns: the number of the matched option if a match is found against
* one of the custom options passed; 0 if no custom option matched and still
* some args need to be processed or autocompletion has been performed;
* -1 otherwise (no more args).
*/
int int
next_arg (NmCli *nmc, int *argc, char ***argv) next_arg (NmCli *nmc, int *argc, char ***argv, ...)
{ {
int arg_num = *argc; va_list args;
const char *cmd_option;
g_assert (*argc >= 0);
do { do {
if (arg_num > 0) { int cmd_option_pos = 1;
if (*argc > 0) {
(*argc)--; (*argc)--;
(*argv)++; (*argv)++;
} }
if (nmc && nmc->complete && *argc == 1 && ***argv == '-') if (*argc == 0)
nmc_complete_strings (**argv, "--ask", "--show-secrets", NULL);
if (arg_num <= 1)
return -1; return -1;
va_start (args, argv);
if (nmc && nmc->complete && *argc == 1) {
while ((cmd_option = va_arg (args, const char *)))
nmc_complete_strings (**argv, cmd_option, NULL);
if (***argv == '-')
nmc_complete_strings (**argv, "--ask", "--show-secrets", NULL);
va_end (args);
return 0;
}
/* Check command dependent options first */
while ((cmd_option = va_arg (args, const char *))) {
/* strip heading "--" form cmd_option */
if (nmc_arg_is_option (**argv, cmd_option + 2)) {
va_end (args);
return cmd_option_pos;
}
cmd_option_pos++;
}
va_end (args);
} while (nmc && parse_global_arg (nmc, **argv)); } while (nmc && parse_global_arg (nmc, **argv));
return 0; return 0;
@@ -170,7 +215,7 @@ nmc_parse_args (nmc_arg_t *arg_arr, gboolean last, int *argc, char ***argv, GErr
return FALSE; return FALSE;
} }
next_arg (NULL, argc, argv); next_arg (NULL, argc, argv, NULL);
} }
return TRUE; return TRUE;

View File

@@ -40,7 +40,7 @@ typedef enum {
/* === Functions === */ /* === Functions === */
gboolean matches (const char *cmd, const char *pattern); gboolean matches (const char *cmd, const char *pattern);
int next_arg (NmCli *nmc, int *argc, char ***argv); int next_arg (NmCli *nmc, int *argc, char ***argv, ...);
gboolean nmc_arg_is_help (const char *arg); gboolean nmc_arg_is_help (const char *arg);
gboolean nmc_arg_is_option (const char *arg, const char *opt_name); gboolean nmc_arg_is_option (const char *arg, const char *opt_name);
gboolean nmc_parse_args (nmc_arg_t *arg_arr, gboolean last, int *argc, char ***argv, GError **error); gboolean nmc_parse_args (nmc_arg_t *arg_arr, gboolean last, int *argc, char ***argv, GError **error);