diff options
Diffstat (limited to 'clients/cli/nmcli.c')
| -rw-r--r-- | clients/cli/nmcli.c | 256 |
1 files changed, 174 insertions, 82 deletions
diff --git a/clients/cli/nmcli.c b/clients/cli/nmcli.c index 7e788654..8bc8828b 100644 --- a/clients/cli/nmcli.c +++ b/clients/cli/nmcli.c @@ -19,7 +19,6 @@ * Copyright 2010 - 2015 Red Hat, Inc. */ -/* Generated configuration file */ #include "nm-default.h" #include <stdio.h> @@ -41,6 +40,7 @@ #include "devices.h" #include "general.h" #include "agent.h" +#include "settings.h" #if defined(NM_DIST_VERSION) # define NMCLI_VERSION NM_DIST_VERSION @@ -64,6 +64,105 @@ GMainLoop *loop = NULL; static sigset_t signal_set; struct termios termios_orig; +static void +complete_field (GHashTable *h, const char *setting, NmcOutputField field[]) +{ + int i; + + for (i = 0; field[i].name; i++) { + if (setting) + g_hash_table_add (h, g_strdup_printf ("%s.%s", setting, field[i].name)); + else + g_hash_table_add (h, g_strdup (field[i].name)); + } +} + +static void +complete_one (gpointer key, gpointer value, gpointer user_data) +{ + const char *prefix = user_data; + const char *name = key; + const char *last; + + last = strrchr (prefix, ','); + if (last) + last++; + else + last = prefix; + + if ((!*last && !strchr (name, '.')) || matches (last, name) == 0) { + g_print ("%.*s%s%s\n", (int)(last-prefix), prefix, name, + strcmp (last, name) == 0 ? "," : ""); + } +} + +static void +complete_fields (const char *prefix) +{ + + GHashTable *h; + + h = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + complete_field (h, NULL, nmc_fields_ip4_config); + complete_field (h, NULL, nmc_fields_dhcp4_config); + complete_field (h, NULL, nmc_fields_ip6_config); + complete_field (h, NULL, nmc_fields_dhcp6_config); + complete_field (h, NULL, nmc_fields_con_show); + complete_field (h, NULL, nmc_fields_settings_names); + complete_field (h, NULL, nmc_fields_con_active_details_general); + complete_field (h, NULL, nmc_fields_con_active_details_vpn); + complete_field (h, NULL, nmc_fields_con_active_details_groups); + complete_field (h, NULL, nmc_fields_dev_status); + complete_field (h, NULL, nmc_fields_dev_show_general); + complete_field (h, NULL, nmc_fields_dev_show_connections); + complete_field (h, NULL, nmc_fields_dev_show_cap); + complete_field (h, NULL, nmc_fields_dev_show_wired_prop); + complete_field (h, NULL, nmc_fields_dev_show_wifi_prop); + complete_field (h, NULL, nmc_fields_dev_show_wimax_prop); + complete_field (h, NULL, nmc_fields_dev_wifi_list); + complete_field (h, NULL, nmc_fields_dev_wimax_list); + complete_field (h, NULL, nmc_fields_dev_show_master_prop); + complete_field (h, NULL, nmc_fields_dev_show_team_prop); + complete_field (h, NULL, nmc_fields_dev_show_vlan_prop); + complete_field (h, NULL, nmc_fields_dev_show_bluetooth); + complete_field (h, NULL, nmc_fields_dev_show_sections); + complete_field (h, NULL, nmc_fields_dev_lldp_list); + + complete_field (h, "connection", nmc_fields_setting_connection); + complete_field (h, "wired", nmc_fields_setting_wired); + complete_field (h, "8021X", nmc_fields_setting_8021X); + complete_field (h, "wireless", nmc_fields_setting_wireless); + complete_field (h, "wireless_security", nmc_fields_setting_wireless_security); + complete_field (h, "ip4-config", nmc_fields_setting_ip4_config); + complete_field (h, "ip6-config", nmc_fields_setting_ip6_config); + complete_field (h, "serial", nmc_fields_setting_serial); + complete_field (h, "ppp", nmc_fields_setting_ppp); + complete_field (h, "pppoe", nmc_fields_setting_pppoe); + complete_field (h, "adsl", nmc_fields_setting_adsl); + complete_field (h, "gsm", nmc_fields_setting_gsm); + complete_field (h, "cdma", nmc_fields_setting_cdma); + complete_field (h, "bluetooth", nmc_fields_setting_bluetooth); + complete_field (h, "olpc-mesh", nmc_fields_setting_olpc_mesh); + complete_field (h, "vpn", nmc_fields_setting_vpn); + complete_field (h, "wimax", nmc_fields_setting_wimax); + complete_field (h, "infiniband", nmc_fields_setting_infiniband); + complete_field (h, "bond", nmc_fields_setting_bond); + complete_field (h, "vlan", nmc_fields_setting_vlan); + complete_field (h, "bridge", nmc_fields_setting_bridge); + complete_field (h, "bridge-port", nmc_fields_setting_bridge_port); + complete_field (h, "team", nmc_fields_setting_team); + complete_field (h, "team0port", nmc_fields_setting_team_port); + complete_field (h, "dcb", nmc_fields_setting_dcb); + complete_field (h, "tun", nmc_fields_setting_tun); + complete_field (h, "ip-tunnel", nmc_fields_setting_ip_tunnel); + complete_field (h, "macvlan", nmc_fields_setting_macvlan); + complete_field (h, "vxlan", nmc_fields_setting_vxlan); + + g_hash_table_foreach (h, complete_one, (gpointer) prefix); + g_hash_table_destroy (h); +} + /* Get an error quark for use with GError */ GQuark @@ -78,9 +177,9 @@ nmcli_error_quark (void) } static void -usage (const char *prog_name) +usage (void) { - g_printerr (_("Usage: %s [OPTIONS] OBJECT { COMMAND | help }\n" + g_printerr (_("Usage: nmcli [OPTIONS] OBJECT { COMMAND | help }\n" "\n" "OPTIONS\n" " -t[erse] terse output\n" @@ -103,48 +202,21 @@ usage (const char *prog_name) " d[evice] devices managed by NetworkManager\n" " a[gent] NetworkManager secret agent or polkit agent\n" " m[onitor] monitor NetworkManager changes\n" - "\n"), - prog_name); -} - -static NMCResultCode -do_help (NmCli *nmc, int argc, char **argv) -{ - usage ("nmcli"); - return NMC_RESULT_SUCCESS; + "\n")); } -static const struct cmd { - const char *cmd; - NMCResultCode (*func) (NmCli *nmc, int argc, char **argv); -} nmcli_cmds[] = { - { "general", do_general }, - { "monitor", do_monitor }, - { "networking", do_networking }, - { "radio", do_radio }, - { "connection", do_connections }, - { "device", do_devices }, - { "agent", do_agent }, - { "help", do_help }, - { 0 } +static const NMCCommand nmcli_cmds[] = { + { "general", do_general, NULL }, + { "monitor", do_monitor, NULL }, + { "networking", do_networking, NULL }, + { "radio", do_radio, NULL }, + { "connection", do_connections, NULL }, + { "device", do_devices, NULL }, + { "agent", do_agent, NULL }, + { NULL, do_overview, usage } }; static NMCResultCode -do_cmd (NmCli *nmc, const char *argv0, int argc, char **argv) -{ - const struct cmd *c; - - for (c = nmcli_cmds; c->cmd; ++c) { - if (matches (argv0, c->cmd) == 0) - return c->func (nmc, argc-1, argv+1); - } - - g_string_printf (nmc->return_text, _("Error: Object '%s' is unknown, try 'nmcli help'."), argv0); - nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; - return nmc->return_value; -} - -static NMCResultCode parse_command_line (NmCli *nmc, int argc, char **argv) { char *base; @@ -154,19 +226,34 @@ parse_command_line (NmCli *nmc, int argc, char **argv) base = argv[0]; else base++; + if (argc > 1 && nm_streq (argv[1], "--complete-args")) { + nmc->complete = TRUE; + argv[1] = argv[0]; + argc--; argv++; + } + argc--; argv++; /* parse options */ - while (argc > 1) { - char *opt = argv[1]; - /* '--' ends options */ - if (strcmp (opt, "--") == 0) { - argc--; argv++; - break; - } + while (argc) { + char *opt = argv[0]; if (opt[0] != '-') break; - if (opt[1] == '-') + + if (argc == 1 && nmc->complete) { + nmc_complete_strings (opt, "--terse", "--pretty", "--mode", "--colors", "--escape", + "--fields", "--nocheck", "--ask", "--show-secrets", + "--wait", "--version", "--help", NULL); + } + + if (opt[1] == '-') { opt++; + /* '--' ends options */ + if (opt[1] == '\0') { + argc--; argv++; + break; + } + } + if (matches (opt, "-terse") == 0) { if (nmc->print_output == NMC_PRINT_TERSE) { g_string_printf (nmc->return_text, _("Error: Option '--terse' is specified the second time.")); @@ -195,63 +282,67 @@ parse_command_line (NmCli *nmc, int argc, char **argv) nmc->print_output = NMC_PRINT_PRETTY; } else if (matches (opt, "-mode") == 0) { nmc->mode_specified = TRUE; - next_arg (&argc, &argv); - if (argc <= 1) { + if (next_arg (&argc, &argv) != 0) { g_string_printf (nmc->return_text, _("Error: missing argument for '%s' option."), opt); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; return nmc->return_value; } - if (matches (argv[1], "tabular") == 0) + if (argc == 1 && nmc->complete) + nmc_complete_strings (argv[0], "tabular", "multiline", NULL); + if (matches (argv[0], "tabular") == 0) nmc->multiline_output = FALSE; - else if (matches (argv[1], "multiline") == 0) + else if (matches (argv[0], "multiline") == 0) nmc->multiline_output = TRUE; else { - g_string_printf (nmc->return_text, _("Error: '%s' is not valid argument for '%s' option."), argv[1], opt); + g_string_printf (nmc->return_text, _("Error: '%s' is not valid argument for '%s' option."), argv[0], opt); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; return nmc->return_value; } } else if (matches (opt, "-colors") == 0) { - next_arg (&argc, &argv); - if (argc <= 1) { + if (next_arg (&argc, &argv) != 0) { g_string_printf (nmc->return_text, _("Error: missing argument for '%s' option."), opt); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; return nmc->return_value; } - if (matches (argv[1], "auto") == 0) + if (argc == 1 && nmc->complete) + nmc_complete_strings (argv[0], "yes", "no", "auto", NULL); + if (matches (argv[0], "auto") == 0) nmc->use_colors = NMC_USE_COLOR_AUTO; - else if (matches (argv[1], "yes") == 0) + else if (matches (argv[0], "yes") == 0) nmc->use_colors = NMC_USE_COLOR_YES; - else if (matches (argv[1], "no") == 0) + else if (matches (argv[0], "no") == 0) nmc->use_colors = NMC_USE_COLOR_NO; else { - g_string_printf (nmc->return_text, _("Error: '%s' is not valid argument for '%s' option."), argv[1], opt); + g_string_printf (nmc->return_text, _("Error: '%s' is not valid argument for '%s' option."), argv[0], opt); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; return nmc->return_value; } } else if (matches (opt, "-escape") == 0) { - next_arg (&argc, &argv); - if (argc <= 1) { + if (next_arg (&argc, &argv) != 0) { g_string_printf (nmc->return_text, _("Error: missing argument for '%s' option."), opt); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; return nmc->return_value; } - if (matches (argv[1], "yes") == 0) + if (argc == 1 && nmc->complete) + nmc_complete_strings (argv[0], "yes", "no", NULL); + if (matches (argv[0], "yes") == 0) nmc->escape_values = TRUE; - else if (matches (argv[1], "no") == 0) + else if (matches (argv[0], "no") == 0) nmc->escape_values = FALSE; else { - g_string_printf (nmc->return_text, _("Error: '%s' is not valid argument for '%s' option."), argv[1], opt); + g_string_printf (nmc->return_text, _("Error: '%s' is not valid argument for '%s' option."), argv[0], opt); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; return nmc->return_value; } } else if (matches (opt, "-fields") == 0) { - next_arg (&argc, &argv); - if (argc <= 1) { + if (next_arg (&argc, &argv) != 0) { g_string_printf (nmc->return_text, _("Error: fields for '%s' options are missing."), opt); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; return nmc->return_value; } - nmc->required_fields = g_strdup (argv[1]); + if (argc == 1 && nmc->complete) + complete_fields (argv[0]); + nmc->required_fields = g_strdup (argv[0]); } else if (matches (opt, "-nocheck") == 0) { /* ignore for backward compatibility */ } else if (matches (opt, "-ask") == 0) { @@ -260,24 +351,25 @@ parse_command_line (NmCli *nmc, int argc, char **argv) nmc->show_secrets = TRUE; } else if (matches (opt, "-wait") == 0) { unsigned long timeout; - next_arg (&argc, &argv); - if (argc <= 1) { + if (next_arg (&argc, &argv) != 0) { g_string_printf (nmc->return_text, _("Error: missing argument for '%s' option."), opt); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; return nmc->return_value; } - if (!nmc_string_to_uint (argv[1], TRUE, 0, G_MAXINT, &timeout)) { + if (!nmc_string_to_uint (argv[0], TRUE, 0, G_MAXINT, &timeout)) { g_string_printf (nmc->return_text, _("Error: '%s' is not a valid timeout for '%s' option."), - argv[1], opt); + argv[0], opt); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; return nmc->return_value; } nmc->timeout = (int) timeout; } else if (matches (opt, "-version") == 0) { - g_print (_("nmcli tool, version %s\n"), NMCLI_VERSION); + if (!nmc->complete) + g_print (_("nmcli tool, version %s\n"), NMCLI_VERSION); return NMC_RESULT_SUCCESS; } else if (matches (opt, "-help") == 0) { - usage (base); + if (!nmc->complete) + usage (); return NMC_RESULT_SUCCESS; } else { g_string_printf (nmc->return_text, _("Error: Option '%s' is unknown, try 'nmcli -help'."), opt); @@ -288,13 +380,8 @@ parse_command_line (NmCli *nmc, int argc, char **argv) argv++; } - if (argc > 1) { - /* Now run the requested command */ - return do_cmd (nmc, argv[1], argc-1, argv+1); - } - - usage (base); - return nmc->return_value; + /* Now run the requested command */ + return nmc_do_cmd (nmc, nmcli_cmds, *argv, argc, argv); } static gboolean nmcli_sigint = FALSE; @@ -545,6 +632,7 @@ nmc_init (NmCli *nmc) nmc->output_data = g_ptr_array_new_full (20, g_free); memset (&nmc->print_fields, '\0', sizeof (NmcPrintFields)); nmc->ask = FALSE; + nmc->complete = FALSE; nmc->show_secrets = FALSE; nmc->use_colors = NMC_USE_COLOR_AUTO; nmc->in_editor = FALSE; @@ -628,8 +716,12 @@ main (int argc, char *argv[]) loop = g_main_loop_new (NULL, FALSE); /* create main loop */ g_main_loop_run (loop); /* run main loop */ - /* Print result descripting text */ - if (nm_cli.return_value != NMC_RESULT_SUCCESS) { + if (nm_cli.complete) { + /* Remove error statuses from command completion runs. */ + if (nm_cli.return_value < NMC_RESULT_COMPLETE_FILE) + nm_cli.return_value = NMC_RESULT_SUCCESS; + } else if (nm_cli.return_value != NMC_RESULT_SUCCESS) { + /* Print result descripting text */ g_printerr ("%s\n", nm_cli.return_text->str); } |