From 72d5be1789b6ffa26a782b5884f8f958b31e07a6 Mon Sep 17 00:00:00 2001 From: Francesco Giudici Date: Thu, 30 Mar 2017 16:09:46 +0200 Subject: [PATCH 1/2] 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 6a3d77fbe6271bb632e5272ef49c58e30739c38e) --- clients/cli/agent.c | 4 ++ clients/cli/common.c | 1 - clients/cli/connections.c | 122 +++++++++++++++++++++++--------------- clients/cli/devices.c | 46 +++++++++----- clients/cli/general.c | 24 +++++++- clients/cli/nmcli.c | 8 +-- clients/cli/utils.c | 61 ++++++++++++++++--- clients/cli/utils.h | 2 +- 8 files changed, 189 insertions(+), 79 deletions(-) diff --git a/clients/cli/agent.c b/clients/cli/agent.c index 4cbf7d2d37..23582f49e9 100644 --- a/clients/cli/agent.c +++ b/clients/cli/agent.c @@ -139,6 +139,7 @@ secrets_requested (NMSecretAgentSimple *agent, static NMCResultCode do_agent_secret (NmCli *nmc, int argc, char **argv) { + next_arg (nmc, &argc, &argv, NULL); if (nmc->complete) return nmc->return_value; @@ -167,6 +168,7 @@ do_agent_polkit (NmCli *nmc, int argc, char **argv) { GError *error = NULL; + next_arg (nmc, &argc, &argv, NULL); if (nmc->complete) return nmc->return_value; @@ -192,6 +194,7 @@ do_agent_all (NmCli *nmc, int argc, char **argv) { NMCResultCode secret_res; + next_arg (nmc, &argc, &argv, NULL); if (nmc->complete) return nmc->return_value; @@ -218,6 +221,7 @@ static const NMCCommand agent_cmds[] = { NMCResultCode do_agent (NmCli *nmc, int argc, char **argv) { + next_arg (nmc, &argc, &argv, NULL); nmc_do_cmd (nmc, agent_cmds, *argv, argc, argv); return nmc->return_value; diff --git a/clients/cli/common.c b/clients/cli/common.c index 3e28eee7a9..aa2189d113 100644 --- a/clients/cli/common.c +++ b/clients/cli/common.c @@ -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_object_unref (simple); } else { - next_arg (nmc, &argc, &argv); call_cmd (nmc, simple, c, argc, argv); } } else if (cmd) { diff --git a/clients/cli/connections.c b/clients/cli/connections.c index 1a0bc7565a..3558c88c8b 100644 --- a/clients/cli/connections.c +++ b/clients/cli/connections.c @@ -1734,7 +1734,7 @@ get_connection (NmCli *nmc, int *argc, char ***argv, int *pos, GError **error) * don't switch to next argument. */ if (!pos || !*pos) - next_arg (nmc, argc, argv); + next_arg (nmc, argc, argv, NULL); return connection; } @@ -1747,19 +1747,15 @@ do_connections_show (NmCli *nmc, int argc, char **argv) GPtrArray *invisibles, *sorted_cons; gboolean active_only = FALSE; GArray *order = NULL; - int i; + int i, option; - /* check connection show options [--active] */ - while (argc) { - if (argc == 1 && nmc->complete) { - nmc_complete_strings (*argv, "--active", - "--order", NULL); - } - - if (!active_only && nmc_arg_is_option (*argv, "active")) { + /* check connection show options [--active] [--order ] */ + while ((option = next_arg (nmc, &argc, &argv, "--active", "--order", NULL)) > 0) { + switch (option) { + case 1: /* --active */ active_only = TRUE; - next_arg (nmc, &argc, &argv); - } else if (!order && nmc_arg_is_option (*argv, "order")) { + break; + case 2: /* --order */ argc--; argv++; if (!argc) { @@ -1767,12 +1763,12 @@ do_connections_show (NmCli *nmc, int argc, char **argv) _("'--order' argument is missing")); goto finish; } - /* TODO: complete --order */ order = parse_preferred_connection_order (*argv, &err); if (err) goto finish; - next_arg (nmc, &argc, &argv); - } else { + break; + default: + g_assert_not_reached(); break; } } @@ -1890,12 +1886,12 @@ do_connections_show (NmCli *nmc, int argc, char **argv) if (!acon) acon = get_ac_for_connection (active_cons, con); if (active_only && !acon) { - next_arg (nmc, &argc, &argv); + next_arg (nmc, &argc, &argv, NULL); continue; } if (nmc->complete) { - next_arg (nmc, &argc, &argv); + next_arg (nmc, &argc, &argv, NULL); continue; } @@ -1933,7 +1929,7 @@ do_connections_show (NmCli *nmc, int argc, char **argv) * so process the same argument again. */ 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; char **arg_arr = NULL; int arg_num; - char ***argv_ptr = &argv; - int *argc_ptr = &argc; + char ***argv_ptr; + int *argc_ptr; /* * Set default timeout for connection activation. @@ -2568,6 +2564,10 @@ do_connection_up (NmCli *nmc, int argc, char **argv) if (nmc->timeout == -1) nmc->timeout = 90; + next_arg (nmc, &argc, &argv, NULL); + argv_ptr = &argv; + argc_ptr = &argc; + if (argc == 0 && nmc->ask) { char *line; @@ -2634,7 +2634,7 @@ do_connection_up (NmCli *nmc, int argc, char **argv) g_printerr (_("Unknown parameter: %s\n"), *argv); } - next_arg (nmc, &argc, &argv); + next_arg (nmc, &argc, &argv, NULL); } if (nmc->complete) @@ -2751,13 +2751,17 @@ do_connection_down (NmCli *nmc, int argc, char **argv) const GPtrArray *active_cons; GSList *queue = NULL, *iter; char **arg_arr = NULL; - char **arg_ptr = argv; - int arg_num = argc; + char **arg_ptr; + int arg_num; int idx = 0; if (nmc->timeout == -1) nmc->timeout = 10; + next_arg (nmc, &argc, &argv, NULL); + arg_ptr = argv; + arg_num = argc; + if (argc == 0) { /* nmc_do_cmd() should not call this with argc=0. */ g_assert (!nmc->complete); @@ -2816,7 +2820,7 @@ do_connection_down (NmCli *nmc, int argc, char **argv) } 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) { @@ -4930,6 +4934,8 @@ do_connection_add (NmCli *nmc, int argc, char **argv) OptionInfo *candidate; gboolean seen_dash_dash = FALSE; + next_arg (nmc, &argc, &argv, NULL); + rl_attempted_completion_function = (rl_completion_func_t *) nmcli_con_add_tab_completion; nmc->return_value = NMC_RESULT_SUCCESS; @@ -4949,7 +4955,7 @@ read_properties: * options and properties to be separated with "--" */ g_clear_error (&error); seen_dash_dash = TRUE; - next_arg (nmc, &argc, &argv); + next_arg (nmc, &argc, &argv, NULL); goto read_properties; } else if (g_strcmp0 (*argv, "save") == 0) { /* It would be better if "save" was a separate argument and not @@ -4971,7 +4977,7 @@ read_properties: g_clear_error (&error); goto finish; } - next_arg (nmc, &argc, &argv); + next_arg (nmc, &argc, &argv, NULL); goto read_properties; } @@ -7891,6 +7897,7 @@ do_connection_edit (NmCli *nmc, int argc, char **argv) {"path", TRUE, &con_path, FALSE}, {NULL} }; + next_arg (nmc, &argc, &argv, NULL); if (argc == 1 && nmc->complete) nmc_complete_strings (*argv, "type", "con-name", "id", "uuid", "path", NULL); @@ -8094,11 +8101,10 @@ do_connection_modify (NmCli *nmc, GError *error = NULL; gboolean temporary = FALSE; - if (argc && nmc_arg_is_option (*argv, "temporary")) { - if (nmc->complete) - goto finish; + /* Check --temporary */ + if (next_arg (nmc, &argc, &argv, "--temporary", NULL) > 0) { temporary = TRUE; - next_arg (nmc, &argc, &argv); + next_arg (nmc, &argc, &argv, NULL); } connection = get_connection (nmc, &argc, &argv, NULL, &error); @@ -8187,12 +8193,17 @@ do_connection_clone (NmCli *nmc, int argc, char **argv) gboolean temporary = FALSE; char **arg_arr = NULL; int arg_num; - char ***argv_ptr = &argv; - int *argc_ptr = &argc; + char ***argv_ptr; + int *argc_ptr; GError *error = NULL; - if (argc == 1 && nmc->complete) - nmc_complete_strings (*argv, "temporary", NULL); + if (next_arg (nmc, &argc, &argv, "--temporary", NULL) > 0) { + temporary = TRUE; + next_arg (nmc, &argc, &argv, NULL); + } + + argv_ptr = &argv; + argc_ptr = &argc; if (argc == 0 && nmc->ask) { char *line; @@ -8205,9 +8216,6 @@ do_connection_clone (NmCli *nmc, int argc, char **argv) g_free (line); argv_ptr = &arg_arr; 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); @@ -8230,7 +8238,7 @@ do_connection_clone (NmCli *nmc, int argc, char **argv) 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); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; goto finish; @@ -8301,8 +8309,8 @@ do_connection_delete (NmCli *nmc, int argc, char **argv) ConnectionCbInfo *info = NULL; GSList *queue = NULL, *iter; char **arg_arr = NULL, *old_arg; - char **arg_ptr = argv; - int arg_num = argc; + char **arg_ptr; + int arg_num; GString *invalid_cons = NULL; int pos = 0; GError *error = NULL; @@ -8310,6 +8318,10 @@ do_connection_delete (NmCli *nmc, int argc, char **argv) if (nmc->timeout == -1) nmc->timeout = 10; + next_arg (nmc, &argc, &argv, NULL); + arg_ptr = argv; + arg_num = argc; + if (argc == 0) { if (nmc->ask) { char *line; @@ -8440,6 +8452,7 @@ do_connection_monitor (NmCli *nmc, int argc, char **argv) { GError *error = NULL; + next_arg (nmc, &argc, &argv, NULL); if (argc == 0) { /* No connections specified. Monitor all. */ const GPtrArray *connections; @@ -8488,6 +8501,7 @@ do_connection_reload (NmCli *nmc, int argc, char **argv) { GError *error = NULL; + next_arg (nmc, &argc, &argv, NULL); if (nmc->complete) return nmc->return_value; @@ -8508,6 +8522,7 @@ do_connection_load (NmCli *nmc, int argc, char **argv) char **filenames, **failures = NULL; int i; + next_arg (nmc, &argc, &argv, NULL); if (argc == 0) { g_string_printf (nmc->return_text, _("Error: No connection specified.")); 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; 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) { /* nmc_do_cmd() should not call this with argc=0. */ g_assert (!nmc->complete); @@ -8589,11 +8611,7 @@ do_connection_import (NmCli *nmc, int argc, char **argv) while (argc > 0) { if (argc == 1 && nmc->complete) - nmc_complete_strings (*argv, "temporary", "type", "file", NULL); - if (nmc_arg_is_option (*argv, "temporary")) { - temporary = TRUE; - next_arg (nmc, &argc, &argv); - } + nmc_complete_strings (*argv, "type", "file", NULL); if (strcmp (*argv, "type") == 0) { argc--; @@ -8632,7 +8650,7 @@ do_connection_import (NmCli *nmc, int argc, char **argv) goto finish; } - next_arg (nmc, &argc, &argv); + next_arg (nmc, &argc, &argv, NULL); } if (nmc->complete) @@ -8708,8 +8726,12 @@ do_connection_export (NmCli *nmc, int argc, char **argv) char tmpfile[] = "/tmp/nmcli-export-temp-XXXXXX"; char **arg_arr = NULL; int arg_num; - char ***argv_ptr = &argv; - int *argc_ptr = &argc; + char ***argv_ptr; + int *argc_ptr; + + next_arg (nmc, &argc, &argv, NULL); + argv_ptr = &argv; + argc_ptr = &argc; if (argc == 0 && nmc->ask) { char *line; @@ -8740,7 +8762,7 @@ do_connection_export (NmCli *nmc, int argc, char **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); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; goto finish; @@ -8916,6 +8938,8 @@ static const NMCCommand connection_cmds[] = { NMCResultCode do_connections (NmCli *nmc, int argc, char **argv) { + next_arg (nmc, &argc, &argv, NULL); + /* Register polkit agent */ nmc_start_polkit_agent_start_try (nmc); diff --git a/clients/cli/devices.c b/clients/cli/devices.c index ce8febcc61..12fb0b9ca0 100644 --- a/clients/cli/devices.c +++ b/clients/cli/devices.c @@ -613,7 +613,7 @@ get_device_list (NmCli *nmc, int argc, char **argv) } /* 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); @@ -642,7 +642,7 @@ get_device (NmCli *nmc, int *argc, char ***argv, GError **error) } } else { ifname = **argv; - next_arg (nmc, argc, argv); + next_arg (nmc, argc, argv, NULL); } devices = nmc_get_devices_sorted (nmc->client); @@ -1490,13 +1490,15 @@ do_devices_status (NmCli *nmc, int argc, char **argv) NmcOutputField *tmpl, *arr; size_t tmpl_len; + next_arg (nmc, &argc, &argv, NULL); + /* Nothing to complete */ if (nmc->complete) return nmc->return_value; while (argc > 0) { 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) @@ -1538,6 +1540,7 @@ do_device_show (NmCli *nmc, int argc, char **argv) { gs_free_error GError *error = NULL; + next_arg (nmc, &argc, &argv, NULL); if (!nmc->mode_specified) 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) nmc->timeout = 90; + next_arg (nmc, &argc, &argv, NULL); device = get_device (nmc, &argc, &argv, &error); if (!device) { 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) nmc->timeout = 10; + next_arg (nmc, &argc, &argv, NULL); device = get_device (nmc, &argc, &argv, &error); if (!device) { 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; gs_free_error GError *error = NULL; + next_arg (nmc, &argc, &argv, NULL); device = get_device (nmc, &argc, &argv, &error); if (!device) { 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) nmc->timeout = 10; + next_arg (nmc, &argc, &argv, NULL); queue = get_device_list (nmc, argc, argv); if (!queue) return nmc->return_value; @@ -2240,6 +2247,7 @@ do_devices_delete (NmCli *nmc, int argc, char **argv) if (nmc->timeout == -1) nmc->timeout = 10; + next_arg (nmc, &argc, &argv, NULL); queue = get_device_list (nmc, argc, argv); if (!queue) return nmc->return_value; @@ -2288,9 +2296,9 @@ do_device_set (NmCli *nmc, int argc, char **argv) }; gs_free_error GError *error = NULL; - if (argc >= 1 && g_strcmp0 (*argv, "ifname") == 0) { - next_arg (nmc, &argc, &argv); - } + next_arg (nmc, &argc, &argv, NULL); + if (argc >= 1 && g_strcmp0 (*argv, "ifname") == 0) + next_arg (nmc, &argc, &argv, NULL); device = get_device (nmc, &argc, &argv, &error); 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); return NMC_RESULT_ERROR_USER_INPUT; } - } while (next_arg (nmc, &argc, &argv) == 0); + } while (next_arg (nmc, &argc, &argv, NULL) == 0); if (nmc->complete) return nmc->return_value; @@ -2441,6 +2449,7 @@ do_devices_monitor (NmCli *nmc, int argc, char **argv) if (nmc->complete) return nmc->return_value; + next_arg (nmc, &argc, &argv, NULL); if (argc == 0) { /* No devices specified. Monitor all. */ 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); + next_arg (nmc, &argc, &argv, NULL); while (argc > 0) { if (argc == 1 && nmc->complete) 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); } - next_arg (nmc, &argc, &argv); + next_arg (nmc, &argc, &argv, NULL); } 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); + next_arg (nmc, &argc, &argv, NULL); /* Get the first compulsory argument (SSID or BSSID) */ if (argc > 0) { param_user = *argv; @@ -2854,7 +2865,7 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv) if (argc == 1 && nmc->complete) complete_aps (devices, NULL, param_user, param_user); - next_arg (nmc, &argc, &argv); + next_arg (nmc, &argc, &argv, NULL); } else { /* nmc_do_cmd() should not call this with argc=0. */ 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); } - next_arg (nmc, &argc, &argv); + next_arg (nmc, &argc, &argv, NULL); } if (nmc->complete) @@ -3079,7 +3090,7 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv) if (con_name) 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) 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); + next_arg (nmc, &argc, &argv, NULL); while (argc > 0) { if (argc == 1 && nmc->complete) { 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; } - next_arg (nmc, &argc, &argv); + next_arg (nmc, &argc, &argv, NULL); } 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 (); devices = nmc_get_devices_sorted (nmc->client); + next_arg (nmc, &argc, &argv, NULL); /* Get the parameters */ while (argc > 0) { if (argc == 1 && nmc->complete) @@ -3591,7 +3604,7 @@ do_device_wifi_rescan (NmCli *nmc, int argc, char **argv) } else if (!nmc->complete) g_printerr (_("Unknown parameter: %s\n"), *argv); - next_arg (nmc, &argc, &argv); + next_arg (nmc, &argc, &argv, NULL); } if (nmc->complete) @@ -3646,6 +3659,7 @@ static NMCCommand device_wifi_cmds[] = { static NMCResultCode 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); return nmc->return_value; @@ -3743,6 +3757,7 @@ do_device_lldp_list (NmCli *nmc, int argc, char **argv) char *fields_str; int counter = 0; + next_arg (nmc, &argc, &argv, NULL); while (argc > 0) { if (argc == 1 && nmc->complete) 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; } - next_arg (nmc, &argc, &argv); + next_arg (nmc, &argc, &argv, NULL); } 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) 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); return nmc->return_value; @@ -3879,6 +3895,8 @@ static const NMCCommand device_cmds[] = { NMCResultCode do_devices (NmCli *nmc, int argc, char **argv) { + next_arg (nmc, &argc, &argv, NULL); + /* Register polkit agent */ nmc_start_polkit_agent_start_try (nmc); diff --git a/clients/cli/general.c b/clients/cli/general.c index 8e52dd29ca..12e76efd62 100644 --- a/clients/cli/general.c +++ b/clients/cli/general.c @@ -385,6 +385,7 @@ show_nm_status (NmCli *nmc, const char *pretty_header_name, const char *print_fl static NMCResultCode do_general_status (NmCli *nmc, int argc, char **argv) { + next_arg (nmc, &argc, &argv, NULL); if (nmc->complete) return nmc->return_value; @@ -559,6 +560,7 @@ show_nm_permissions (NmCli *nmc) static NMCResultCode do_general_permissions (NmCli *nmc, int argc, char **argv) { + next_arg (nmc, &argc, &argv, NULL); if (nmc->complete) return nmc->return_value; @@ -640,6 +642,7 @@ do_general_logging (NmCli *nmc, int argc, char **argv) { gs_free_error GError *error = NULL; + next_arg (nmc, &argc, &argv, NULL); if (argc == 0) { if (nmc->complete) 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); return NMC_RESULT_ERROR_USER_INPUT; } - } while (next_arg (nmc, &argc, &argv) == 0); + } while (next_arg (nmc, &argc, &argv, NULL) == 0); if (nmc->complete) return nmc->return_value; @@ -722,6 +725,7 @@ save_hostname_cb (GObject *object, GAsyncResult *result, gpointer user_data) static NMCResultCode do_general_hostname (NmCli *nmc, int argc, char **argv) { + next_arg (nmc, &argc, &argv, NULL); if (nmc->complete) return nmc->return_value; @@ -737,7 +741,7 @@ do_general_hostname (NmCli *nmc, int argc, char **argv) /* hostname provided -> set it */ 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); nmc->should_wait++; @@ -762,6 +766,8 @@ static const NMCCommand general_cmds[] = { NMCResultCode do_general (NmCli *nmc, int argc, char **argv) { + next_arg (nmc, &argc, &argv, NULL); + /* Register polkit agent */ 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 do_networking_on (NmCli *nmc, int argc, char **argv) { + next_arg (nmc, &argc, &argv, NULL); return do_networking_on_off (nmc, argc, argv, TRUE); } static NMCResultCode do_networking_off (NmCli *nmc, int argc, char **argv) { + next_arg (nmc, &argc, &argv, NULL); return do_networking_on_off (nmc, argc, argv, FALSE); } static NMCResultCode do_networking_connectivity (NmCli *nmc, int argc, char **argv) { + next_arg (nmc, &argc, &argv, NULL); if (nmc->complete) { if (argc == 1) nmc_complete_strings (*argv, "check", NULL); @@ -872,6 +881,7 @@ do_networking_connectivity (NmCli *nmc, int argc, char **argv) static NMCResultCode do_networking_show (NmCli *nmc, int argc, char **argv) { + next_arg (nmc, &argc, &argv, NULL); if (nmc->complete) return nmc->return_value; @@ -893,6 +903,7 @@ static const NMCCommand networking_cmds[] = { NMCResultCode do_networking (NmCli *nmc, int argc, char **argv) { + next_arg (nmc, &argc, &argv, NULL); nmc_do_cmd (nmc, networking_cmds, *argv, argc, argv); return nmc->return_value; @@ -903,6 +914,7 @@ do_radio_all (NmCli *nmc, int argc, char **argv) { gboolean enable_flag; + next_arg (nmc, &argc, &argv, NULL); if (argc == 0) { if (nmc->complete) return nmc->return_value; @@ -932,6 +944,7 @@ do_radio_wifi (NmCli *nmc, int argc, char **argv) { gboolean enable_flag; + next_arg (nmc, &argc, &argv, NULL); if (argc == 0) { if (nmc->complete) return nmc->return_value; @@ -958,6 +971,7 @@ do_radio_wwan (NmCli *nmc, int argc, char **argv) { gboolean enable_flag; + next_arg (nmc, &argc, &argv, NULL); if (argc == 0) { if (nmc->complete) return nmc->return_value; @@ -992,6 +1006,8 @@ static const NMCCommand radio_cmds[] = { NMCResultCode do_radio (NmCli *nmc, int argc, char **argv) { + next_arg (nmc, &argc, &argv, NULL); + /* Register polkit agent */ nmc_start_polkit_agent_start_try (nmc); @@ -1217,6 +1233,8 @@ do_overview (NmCli *nmc, int argc, char **argv) char *tmp; int i; + next_arg (nmc, &argc, &argv, NULL); + /* Register polkit agent */ nmc_start_polkit_agent_start_try (nmc); @@ -1316,6 +1334,8 @@ do_overview (NmCli *nmc, int argc, char **argv) NMCResultCode do_monitor (NmCli *nmc, int argc, char **argv) { + next_arg (nmc, &argc, &argv, NULL); + if (nmc->complete) return nmc->return_value; diff --git a/clients/cli/nmcli.c b/clients/cli/nmcli.c index ee3f747b46..b8019403eb 100644 --- a/clients/cli/nmcli.c +++ b/clients/cli/nmcli.c @@ -219,9 +219,9 @@ process_command_line (NmCli *nmc, int argc, char **argv) if (argc > 1 && nm_streq (argv[1], "--complete-args")) { nmc->complete = TRUE; 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 */ while (argc) { @@ -239,7 +239,7 @@ process_command_line (NmCli *nmc, int argc, char **argv) opt++; /* '--' ends options */ if (opt[1] == '\0') { - next_arg (nmc, &argc, &argv); + next_arg (nmc, &argc, &argv, NULL); break; } } @@ -390,7 +390,7 @@ process_command_line (NmCli *nmc, int argc, char **argv) nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; return FALSE; } - next_arg (nmc, &argc, &argv); + next_arg (nmc, &argc, &argv, NULL); } /* Now run the requested command */ diff --git a/clients/cli/utils.c b/clients/cli/utils.c index fbd643ffc4..24686ec7bf 100644 --- a/clients/cli/utils.c +++ b/clients/cli/utils.c @@ -51,21 +51,66 @@ parse_global_arg (NmCli *nmc, const char *arg) 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 -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 { - if (arg_num > 0) { + int cmd_option_pos = 1; + + if (*argc > 0) { (*argc)--; (*argv)++; } - if (nmc && nmc->complete && *argc == 1 && ***argv == '-') - nmc_complete_strings (**argv, "--ask", "--show-secrets", NULL); - if (arg_num <= 1) + if (*argc == 0) 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)); return 0; @@ -170,7 +215,7 @@ nmc_parse_args (nmc_arg_t *arg_arr, gboolean last, int *argc, char ***argv, GErr return FALSE; } - next_arg (NULL, argc, argv); + next_arg (NULL, argc, argv, NULL); } return TRUE; diff --git a/clients/cli/utils.h b/clients/cli/utils.h index d889962df7..a1c08764cd 100644 --- a/clients/cli/utils.h +++ b/clients/cli/utils.h @@ -40,7 +40,7 @@ typedef enum { /* === Functions === */ 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_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); From ddbb63afeb68b213fa530baf0863593a42fd9688 Mon Sep 17 00:00:00 2001 From: Francesco Giudici Date: Mon, 3 Apr 2017 12:41:55 +0200 Subject: [PATCH 2/2] nmcli: fix 'nmcli con export' parameters check get_connection() will already move forward arguments (argc/argv): remove extra argv++/argc-- Example: "nmcli con export " now, extra_arg is detected, printing error: "Error: unknown extra argument: 'extra_arg'." (cherry picked from commit 512ed904c61418332633c7ed3da03777bdc269a1) --- clients/cli/connections.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/clients/cli/connections.c b/clients/cli/connections.c index 3558c88c8b..46b73257f4 100644 --- a/clients/cli/connections.c +++ b/clients/cli/connections.c @@ -8756,11 +8756,7 @@ do_connection_export (NmCli *nmc, int argc, char **argv) if (nmc->complete) return nmc->return_value; - if (argc) { - out_name = *argv; - argc--; - argv++; - } + out_name = *argv; 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);