diff options
| author | Michael Biebl <biebl@debian.org> | 2018-10-20 01:30:31 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2018-10-20 01:30:31 +0200 |
| commit | 6518e361171f64bcaaa4bf868139362ed95cc2e0 (patch) | |
| tree | d2d5b53faf80646a40ec2c0c7f2a42b3959612f5 /clients/cli | |
| parent | e126f3e804c35480c4f075777430419d6ece23da (diff) | |
New upstream version 1.14.2 upstream/1.14.2
Diffstat (limited to 'clients/cli')
| -rw-r--r-- | clients/cli/common.c | 191 | ||||
| -rw-r--r-- | clients/cli/common.h | 17 | ||||
| -rw-r--r-- | clients/cli/connections.c | 390 | ||||
| -rw-r--r-- | clients/cli/connections.h | 2 | ||||
| -rw-r--r-- | clients/cli/devices.c | 1002 | ||||
| -rw-r--r-- | clients/cli/devices.h | 14 | ||||
| -rw-r--r-- | clients/cli/general.c | 5 | ||||
| -rw-r--r-- | clients/cli/meson.build | 2 | ||||
| -rw-r--r-- | clients/cli/nmcli.c | 341 | ||||
| -rw-r--r-- | clients/cli/nmcli.h | 4 | ||||
| -rw-r--r-- | clients/cli/settings.c | 33 | ||||
| -rw-r--r-- | clients/cli/utils.c | 191 | ||||
| -rw-r--r-- | clients/cli/utils.h | 109 |
13 files changed, 1416 insertions, 885 deletions
diff --git a/clients/cli/common.c b/clients/cli/common.c index 4aea0d5b..88e98154 100644 --- a/clients/cli/common.c +++ b/clients/cli/common.c @@ -102,6 +102,8 @@ _ip_config_get_routes (NMIPConfig *cfg) return arr; } +/*****************************************************************************/ + static gconstpointer _metagen_ip4_config_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS) { @@ -177,6 +179,19 @@ arr_out: return arr; } +const NmcMetaGenericInfo *const metagen_ip4_config[_NMC_GENERIC_INFO_TYPE_IP4_CONFIG_NUM + 1] = { +#define _METAGEN_IP4_CONFIG(type, name) \ + [type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_ip4_config_get_fcn) + _METAGEN_IP4_CONFIG (NMC_GENERIC_INFO_TYPE_IP4_CONFIG_ADDRESS, "ADDRESS"), + _METAGEN_IP4_CONFIG (NMC_GENERIC_INFO_TYPE_IP4_CONFIG_GATEWAY, "GATEWAY"), + _METAGEN_IP4_CONFIG (NMC_GENERIC_INFO_TYPE_IP4_CONFIG_ROUTE, "ROUTE"), + _METAGEN_IP4_CONFIG (NMC_GENERIC_INFO_TYPE_IP4_CONFIG_DNS, "DNS"), + _METAGEN_IP4_CONFIG (NMC_GENERIC_INFO_TYPE_IP4_CONFIG_DOMAIN, "DOMAIN"), + _METAGEN_IP4_CONFIG (NMC_GENERIC_INFO_TYPE_IP4_CONFIG_WINS, "WINS"), +}; + +/*****************************************************************************/ + static gconstpointer _metagen_ip6_config_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS) { @@ -247,17 +262,6 @@ arr_out: return arr; } -const NmcMetaGenericInfo *const metagen_ip4_config[_NMC_GENERIC_INFO_TYPE_IP4_CONFIG_NUM + 1] = { -#define _METAGEN_IP4_CONFIG(type, name) \ - [type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_ip4_config_get_fcn) - _METAGEN_IP4_CONFIG (NMC_GENERIC_INFO_TYPE_IP4_CONFIG_ADDRESS, "ADDRESS"), - _METAGEN_IP4_CONFIG (NMC_GENERIC_INFO_TYPE_IP4_CONFIG_GATEWAY, "GATEWAY"), - _METAGEN_IP4_CONFIG (NMC_GENERIC_INFO_TYPE_IP4_CONFIG_ROUTE, "ROUTE"), - _METAGEN_IP4_CONFIG (NMC_GENERIC_INFO_TYPE_IP4_CONFIG_DNS, "DNS"), - _METAGEN_IP4_CONFIG (NMC_GENERIC_INFO_TYPE_IP4_CONFIG_DOMAIN, "DOMAIN"), - _METAGEN_IP4_CONFIG (NMC_GENERIC_INFO_TYPE_IP4_CONFIG_WINS, "WINS"), -}; - const NmcMetaGenericInfo *const metagen_ip6_config[_NMC_GENERIC_INFO_TYPE_IP6_CONFIG_NUM + 1] = { #define _METAGEN_IP6_CONFIG(type, name) \ [type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_ip6_config_get_fcn) @@ -270,40 +274,92 @@ const NmcMetaGenericInfo *const metagen_ip6_config[_NMC_GENERIC_INFO_TYPE_IP6_CO /*****************************************************************************/ -const NmcMetaGenericInfo *const nmc_fields_dhcp_config[] = { - NMC_META_GENERIC ("GROUP"), /* 0 */ - NMC_META_GENERIC ("OPTION"), /* 1 */ - NULL, -}; +static gconstpointer +_metagen_dhcp_config_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS) +{ + NMDhcpConfig *dhcp = target; + guint i; + char **arr = NULL; + + NMC_HANDLE_COLOR (NM_META_COLOR_NONE); -const NmcMetaGenericInfo *const nmc_fields_ip6_config[] = { - NMC_META_GENERIC ("GROUP"), /* 0 */ - NMC_META_GENERIC ("ADDRESS"), /* 1 */ - NMC_META_GENERIC ("GATEWAY"), /* 2 */ - NMC_META_GENERIC ("ROUTE"), /* 3 */ - NMC_META_GENERIC ("DNS"), /* 4 */ - NMC_META_GENERIC ("DOMAIN"), /* 5 */ - NULL, + switch (info->info_type) { + case NMC_GENERIC_INFO_TYPE_DHCP_CONFIG_OPTION: + { + GHashTable *table; + gs_free char **arr2 = NULL; + guint n; + + if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV)) + return NULL; + + table = nm_dhcp_config_get_options (dhcp); + if (!table) + goto arr_out; + + arr2 = (char **) nm_utils_strdict_get_keys (table, TRUE, &n); + if (!n) + goto arr_out; + + nm_assert (arr2 && !arr2[n] && n == NM_PTRARRAY_LEN (arr2)); + for (i = 0; i < n; i++) { + const char *k = arr2[i]; + const char *v; + + nm_assert (k); + v = g_hash_table_lookup (table, k); + arr2[i] = g_strdup_printf ("%s = %s", k, v); + } + + arr = g_steal_pointer (&arr2); + goto arr_out; + } + default: + break; + } + + g_return_val_if_reached (NULL); + +arr_out: + NM_SET_OUT (out_is_default, !arr || !arr[0]); + *out_flags |= NM_META_ACCESSOR_GET_OUT_FLAGS_STRV; + *out_to_free = arr; + return arr; +} + +const NmcMetaGenericInfo *const metagen_dhcp_config[_NMC_GENERIC_INFO_TYPE_DHCP_CONFIG_NUM + 1] = { +#define _METAGEN_DHCP_CONFIG(type, name) \ + [type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_dhcp_config_get_fcn) + _METAGEN_DHCP_CONFIG (NMC_GENERIC_INFO_TYPE_DHCP_CONFIG_OPTION, "OPTION"), }; +/*****************************************************************************/ + gboolean -print_ip4_config (NMIPConfig *cfg4, - const NmcConfig *nmc_config, - const char *one_field) +print_ip_config (NMIPConfig *cfg, + int addr_family, + const NmcConfig *nmc_config, + const char *one_field) { gs_free_error GError *error = NULL; gs_free char *field_str = NULL; - if (cfg4 == NULL) + if (!cfg) return FALSE; - if (one_field) - field_str = g_strdup_printf ("IP4.%s", one_field); + if (one_field) { + field_str = g_strdup_printf ("IP%c.%s", + nm_utils_addr_family_to_char (addr_family), + one_field); + } if (!nmc_print (nmc_config, - (gpointer[]) { cfg4, NULL }, + (gpointer[]) { cfg, NULL }, + NULL, NULL, - NMC_META_GENERIC_GROUP ("IP4", metagen_ip4_config, N_("GROUP")), + addr_family == AF_INET + ? NMC_META_GENERIC_GROUP ("IP4", metagen_ip4_config, N_("GROUP")) + : NMC_META_GENERIC_GROUP ("IP6", metagen_ip6_config, N_("GROUP")), field_str, &error)) { return FALSE; @@ -312,24 +368,30 @@ print_ip4_config (NMIPConfig *cfg4, } gboolean -print_ip6_config (NMIPConfig *cfg6, - const NmcConfig *nmc_config, - const char *group_prefix, - const char *one_field) +print_dhcp_config (NMDhcpConfig *dhcp, + int addr_family, + const NmcConfig *nmc_config, + const char *one_field) { gs_free_error GError *error = NULL; gs_free char *field_str = NULL; - if (cfg6 == NULL) + if (!dhcp) return FALSE; - if (one_field) - field_str = g_strdup_printf ("IP6.%s", one_field); + if (one_field) { + field_str = g_strdup_printf ("DHCP%c.%s", + nm_utils_addr_family_to_char (addr_family), + one_field); + } if (!nmc_print (nmc_config, - (gpointer[]) { cfg6, NULL }, + (gpointer[]) { dhcp, NULL }, NULL, - NMC_META_GENERIC_GROUP ("IP6", metagen_ip6_config, N_("GROUP")), + NULL, + addr_family == AF_INET + ? NMC_META_GENERIC_GROUP ("DHCP4", metagen_dhcp_config, N_("GROUP")) + : NMC_META_GENERIC_GROUP ("DHCP6", metagen_dhcp_config, N_("GROUP")), field_str, &error)) { return FALSE; @@ -337,53 +399,6 @@ print_ip6_config (NMIPConfig *cfg6, return TRUE; } -gboolean -print_dhcp_config (NMDhcpConfig *dhcp, - const NmcConfig *nmc_config, - const char *group_prefix, - const char *one_field) -{ - GHashTable *table; - const NMMetaAbstractInfo *const*tmpl; - NmcOutputField *arr; - - if (dhcp == NULL) - return FALSE; - - table = nm_dhcp_config_get_options (dhcp); - if (table) { - char **options_arr = NULL; - NMC_OUTPUT_DATA_DEFINE_SCOPED (out); - gs_free const char **keys = NULL; - guint i, nkeys; - - tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dhcp_config; - out_indices = parse_output_fields (one_field, - tmpl, FALSE, NULL, NULL); - arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES); - g_ptr_array_add (out.output_data, arr); - - keys = (const char **) g_hash_table_get_keys_as_array (table, &nkeys); - nm_utils_strv_sort (keys, nkeys); - - options_arr = g_new (char *, nkeys + 1); - for (i = 0; i < nkeys; i++) - options_arr[i] = g_strdup_printf ("%s = %s", keys[i], (const char *) g_hash_table_lookup (table, keys[i])); - options_arr[i] = NULL; - - arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX); - set_val_strc (arr, 0, group_prefix); - set_val_arr (arr, 1, options_arr); - g_ptr_array_add (out.output_data, arr); - - print_data_prepare_width (out.output_data); - print_data (nmc_config, out_indices, NULL, 0, &out); - - return TRUE; - } - return FALSE; -} - /* * nmc_find_connection: * @connections: array of NMConnections to search in diff --git a/clients/cli/common.h b/clients/cli/common.h index 8f4e47c2..c180dfb7 100644 --- a/clients/cli/common.h +++ b/clients/cli/common.h @@ -25,9 +25,16 @@ #include "nmcli.h" #include "nm-secret-agent-simple.h" -gboolean print_ip4_config (NMIPConfig *cfg4, const NmcConfig *nmc_config, const char *one_field); -gboolean print_ip6_config (NMIPConfig *cfg6, const NmcConfig *nmc_config, const char *group_prefix, const char *one_field); -gboolean print_dhcp_config (NMDhcpConfig *dhcp, const NmcConfig *nmc_config, const char *group_prefix, const char *one_field); + +gboolean print_ip_config (NMIPConfig *cfg, + int addr_family, + const NmcConfig *nmc_config, + const char *one_field); + +gboolean print_dhcp_config (NMDhcpConfig *dhcp, + int addr_family, + const NmcConfig *nmc_config, + const char *one_field); NMConnection *nmc_find_connection (const GPtrArray *connections, const char *filter_type, @@ -83,7 +90,7 @@ void nmc_complete_bool (const char *prefix); const char *nmc_error_get_simple_message (GError *error); extern const NmcMetaGenericInfo *const metagen_ip4_config[]; -extern const NmcMetaGenericInfo *const nmc_fields_ip6_config[]; -extern const NmcMetaGenericInfo *const nmc_fields_dhcp_config[]; +extern const NmcMetaGenericInfo *const metagen_ip6_config[]; +extern const NmcMetaGenericInfo *const metagen_dhcp_config[]; #endif /* NMC_COMMON_H */ diff --git a/clients/cli/connections.c b/clients/cli/connections.c index b547e34c..bcd257ac 100644 --- a/clients/cli/connections.c +++ b/clients/cli/connections.c @@ -67,10 +67,10 @@ struct _OptionInfo { /* define some other prompts */ -#define PROMPT_CONNECTION _("Connection (name, UUID, or path)") -#define PROMPT_VPN_CONNECTION _("VPN connection (name, UUID, or path)") -#define PROMPT_CONNECTIONS _("Connection(s) (name, UUID, or path)") -#define PROMPT_ACTIVE_CONNECTIONS _("Connection(s) (name, UUID, path or apath)") +#define PROMPT_CONNECTION _("Connection (name, UUID, or path): ") +#define PROMPT_VPN_CONNECTION _("VPN connection (name, UUID, or path): ") +#define PROMPT_CONNECTIONS _("Connection(s) (name, UUID, or path): ") +#define PROMPT_ACTIVE_CONNECTIONS _("Connection(s) (name, UUID, path or apath): ") #define BASE_PROMPT "nmcli> " @@ -185,17 +185,24 @@ get_ac_device_string (NMActiveConnection *active) /* FIXME: The same or similar code for VPN info appears also in nm-applet (applet-dialogs.c), * and in gnome-control-center as well. It could probably be shared somehow. */ -static char * +static const char * get_vpn_connection_type (NMConnection *connection) { + NMSettingVpn *s_vpn; const char *type, *p; + s_vpn = nm_connection_get_setting_vpn (connection); + if (!s_vpn) + return NULL; + /* The service type is in form of "org.freedesktop.NetworkManager.vpnc". * Extract end part after last dot, e.g. "vpnc" */ type = nm_setting_vpn_get_service_type (nm_connection_get_setting_vpn (connection)); + if (!type) + return NULL; p = strrchr (type, '.'); - return g_strdup (p ? p + 1 : type); + return p ? p + 1 : type; } /* VPN parameters can be found at: @@ -206,31 +213,35 @@ get_vpn_connection_type (NMConnection *connection) * http://git.gnome.org/browse/network-manager-openswan/tree/src/nm-openswan-service.h * See also 'properties' directory in these plugins. */ -static const gchar * +static const char * find_vpn_gateway_key (const char *vpn_type) { - if (g_strcmp0 (vpn_type, "openvpn") == 0) return "remote"; - if (g_strcmp0 (vpn_type, "vpnc") == 0) return "IPSec gateway"; - if (g_strcmp0 (vpn_type, "pptp") == 0) return "gateway"; - if (g_strcmp0 (vpn_type, "openconnect") == 0) return "gateway"; - if (g_strcmp0 (vpn_type, "openswan") == 0) return "right"; - if (g_strcmp0 (vpn_type, "libreswan") == 0) return "right"; - if (g_strcmp0 (vpn_type, "ssh") == 0) return "remote"; - if (g_strcmp0 (vpn_type, "l2tp") == 0) return "gateway"; - return ""; + if (vpn_type) { + if (nm_streq (vpn_type, "openvpn")) return "remote"; + if (nm_streq (vpn_type, "vpnc")) return "IPSec gateway"; + if (nm_streq (vpn_type, "pptp")) return "gateway"; + if (nm_streq (vpn_type, "openconnect")) return "gateway"; + if (nm_streq (vpn_type, "openswan")) return "right"; + if (nm_streq (vpn_type, "libreswan")) return "right"; + if (nm_streq (vpn_type, "ssh")) return "remote"; + if (nm_streq (vpn_type, "l2tp")) return "gateway"; + } + return NULL; } -static const gchar * +static const char * find_vpn_username_key (const char *vpn_type) { - if (g_strcmp0 (vpn_type, "openvpn") == 0) return "username"; - if (g_strcmp0 (vpn_type, "vpnc") == 0) return "Xauth username"; - if (g_strcmp0 (vpn_type, "pptp") == 0) return "user"; - if (g_strcmp0 (vpn_type, "openconnect") == 0) return "username"; - if (g_strcmp0 (vpn_type, "openswan") == 0) return "leftxauthusername"; - if (g_strcmp0 (vpn_type, "libreswan") == 0) return "leftxauthusername"; - if (g_strcmp0 (vpn_type, "l2tp") == 0) return "user"; - return ""; + if (vpn_type) { + if (nm_streq (vpn_type, "openvpn")) return "username"; + if (nm_streq (vpn_type, "vpnc")) return "Xauth username"; + if (nm_streq (vpn_type, "pptp")) return "user"; + if (nm_streq (vpn_type, "openconnect")) return "username"; + if (nm_streq (vpn_type, "openswan")) return "leftxauthusername"; + if (nm_streq (vpn_type, "libreswan")) return "leftxauthusername"; + if (nm_streq (vpn_type, "l2tp")) return "user"; + } + return NULL; } enum VpnDataItem { @@ -238,11 +249,11 @@ enum VpnDataItem { VPN_DATA_ITEM_USERNAME }; -static const gchar * +static const char * get_vpn_data_item (NMConnection *connection, enum VpnDataItem vpn_data_item) { - const char *key; - gs_free char *type = NULL; + const char *type; + const char *key = NULL; type = get_vpn_connection_type (connection); @@ -254,10 +265,11 @@ get_vpn_data_item (NMConnection *connection, enum VpnDataItem vpn_data_item) key = find_vpn_username_key (type); break; default: - key = ""; break; } + if (!key) + return NULL; return nm_setting_vpn_get_data_item (nm_connection_get_setting_vpn (connection), key); } @@ -627,7 +639,102 @@ const NmcMetaGenericInfo *const metagen_con_active_general[_NMC_GENERIC_INFO_TYP /*****************************************************************************/ +static gconstpointer +_metagen_con_active_vpn_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS) +{ + NMActiveConnection *ac = target; + NMConnection *c; + NMSettingVpn *s_vpn = NULL; + NMVpnConnectionState vpn_state; + guint i; + const char *s; + char **arr = NULL; + + nm_assert (NM_IS_VPN_CONNECTION (ac)); + + NMC_HANDLE_COLOR (NM_META_COLOR_NONE); + + nm_assert (NM_IN_SET (get_type, NM_META_ACCESSOR_GET_TYPE_PRETTY, NM_META_ACCESSOR_GET_TYPE_PARSABLE)); + + c = NM_CONNECTION (nm_active_connection_get_connection (ac)); + if (c) + s_vpn = nm_connection_get_setting_vpn (c); + + switch (info->info_type) { + case NMC_GENERIC_INFO_TYPE_CON_VPN_TYPE: + return c ? get_vpn_connection_type (c) : NULL; + case NMC_GENERIC_INFO_TYPE_CON_VPN_USERNAME: + if ( s_vpn + && (s = nm_setting_vpn_get_user_name (s_vpn))) + return s; + return c ? get_vpn_data_item (c, VPN_DATA_ITEM_USERNAME) : NULL; + case NMC_GENERIC_INFO_TYPE_CON_VPN_GATEWAY: + return c ? get_vpn_data_item (c, VPN_DATA_ITEM_GATEWAY) : NULL; + case NMC_GENERIC_INFO_TYPE_CON_VPN_BANNER: + s = nm_vpn_connection_get_banner (NM_VPN_CONNECTION (ac)); + if (s) + return (*out_to_free = g_strescape (s, "")); + return NULL; + case NMC_GENERIC_INFO_TYPE_CON_VPN_VPN_STATE: + vpn_state = nm_vpn_connection_get_vpn_state (NM_VPN_CONNECTION (ac)); + return (*out_to_free = nmc_meta_generic_get_enum_with_detail (NMC_META_GENERIC_GET_ENUM_TYPE_DASH, + vpn_state, + vpn_connection_state_to_string (vpn_state), + get_type)); + case NMC_GENERIC_INFO_TYPE_CON_VPN_CFG: + if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV)) + return NULL; + if (s_vpn) { + gs_free char **arr2 = NULL; + guint n; + + arr2 = (char **) nm_setting_vpn_get_data_keys (s_vpn, &n); + if (!n) + goto arr_out; + + nm_assert (arr2 && !arr2[n]); + for (i = 0; i < n; i++) { + const char *k = arr2[i]; + const char *v; + + nm_assert (k); + v = nm_setting_vpn_get_data_item (s_vpn, k); + /* update the arr array in-place. Previously it contained + * the constant keys, now it contains the strdup'ed output text. */ + arr2[i] = g_strdup_printf ("%s = %s", k, v); + } + + arr = g_steal_pointer (&arr2); + } + goto arr_out; + default: + break; + } + + g_return_val_if_reached (NULL); + +arr_out: + NM_SET_OUT (out_is_default, !arr || !arr[0]); + *out_flags |= NM_META_ACCESSOR_GET_OUT_FLAGS_STRV; + *out_to_free = arr; + return arr; +} + +const NmcMetaGenericInfo *const metagen_con_active_vpn[_NMC_GENERIC_INFO_TYPE_CON_ACTIVE_VPN_NUM + 1] = { +#define _METAGEN_CON_ACTIVE_VPN(type, name) \ + [type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_con_active_vpn_get_fcn) + _METAGEN_CON_ACTIVE_VPN (NMC_GENERIC_INFO_TYPE_CON_VPN_TYPE, "TYPE"), + _METAGEN_CON_ACTIVE_VPN (NMC_GENERIC_INFO_TYPE_CON_VPN_USERNAME, "USERNAME"), + _METAGEN_CON_ACTIVE_VPN (NMC_GENERIC_INFO_TYPE_CON_VPN_GATEWAY, "GATEWAY"), + _METAGEN_CON_ACTIVE_VPN (NMC_GENERIC_INFO_TYPE_CON_VPN_BANNER, "BANNER"), + _METAGEN_CON_ACTIVE_VPN (NMC_GENERIC_INFO_TYPE_CON_VPN_VPN_STATE, "VPN-STATE"), + _METAGEN_CON_ACTIVE_VPN (NMC_GENERIC_INFO_TYPE_CON_VPN_CFG, "CFG"), +}; + +/*****************************************************************************/ + #define NMC_FIELDS_SETTINGS_NAMES_ALL NM_SETTING_CONNECTION_SETTING_NAME","\ + NM_SETTING_MATCH_SETTING_NAME","\ NM_SETTING_WIRED_SETTING_NAME","\ NM_SETTING_802_1X_SETTING_NAME","\ NM_SETTING_WIRELESS_SETTING_NAME","\ @@ -660,29 +767,22 @@ const NmcMetaGenericInfo *const metagen_con_active_general[_NMC_GENERIC_INFO_TYP NM_SETTING_MACSEC_SETTING_NAME"," \ NM_SETTING_MACVLAN_SETTING_NAME"," \ NM_SETTING_VXLAN_SETTING_NAME"," \ + NM_SETTING_WPAN_SETTING_NAME","\ + NM_SETTING_6LOWPAN_SETTING_NAME","\ NM_SETTING_PROXY_SETTING_NAME"," \ - NM_SETTING_TC_CONFIG_SETTING_NAME + NM_SETTING_TC_CONFIG_SETTING_NAME"," \ + NM_SETTING_SRIOV_SETTING_NAME"," \ + NM_SETTING_ETHTOOL_SETTING_NAME // NM_SETTING_DUMMY_SETTING_NAME // NM_SETTING_WIMAX_SETTING_NAME -const NmcMetaGenericInfo *const nmc_fields_con_active_details_vpn[] = { - NMC_META_GENERIC ("GROUP"), /* 0 */ - NMC_META_GENERIC ("TYPE"), /* 1 */ - NMC_META_GENERIC ("USERNAME"), /* 2 */ - NMC_META_GENERIC ("GATEWAY"), /* 3 */ - NMC_META_GENERIC ("BANNER"), /* 4 */ - NMC_META_GENERIC ("VPN-STATE"), /* 5 */ - NMC_META_GENERIC ("CFG"), /* 6 */ - NULL, -}; - const NmcMetaGenericInfo *const nmc_fields_con_active_details_groups[] = { NMC_META_GENERIC_WITH_NESTED ("GENERAL", metagen_con_active_general), /* 0 */ NMC_META_GENERIC_WITH_NESTED ("IP4", metagen_ip4_config), /* 1 */ - NMC_META_GENERIC_WITH_NESTED ("DHCP4", nmc_fields_dhcp_config + 1), /* 2 */ - NMC_META_GENERIC_WITH_NESTED ("IP6", nmc_fields_ip6_config + 1), /* 3 */ - NMC_META_GENERIC_WITH_NESTED ("DHCP6", nmc_fields_dhcp_config + 1), /* 4 */ - NMC_META_GENERIC_WITH_NESTED ("VPN", nmc_fields_con_active_details_vpn + 1), /* 5 */ + NMC_META_GENERIC_WITH_NESTED ("DHCP4", metagen_dhcp_config), /* 2 */ + NMC_META_GENERIC_WITH_NESTED ("IP6", metagen_ip6_config), /* 3 */ + NMC_META_GENERIC_WITH_NESTED ("DHCP6", metagen_dhcp_config), /* 4 */ + NMC_META_GENERIC_WITH_NESTED ("VPN", metagen_con_active_vpn), /* 5 */ NULL, }; @@ -701,6 +801,7 @@ typedef struct { NMConnection *connection; NMSetting *setting; const char *property; + char **words; } TabCompletionInfo; static TabCompletionInfo nmc_tab_completion; @@ -890,7 +991,11 @@ usage_connection_add (void) " [source-port-min <0-65535>]\n" " [source-port-max <0-65535>]\n" " [destination-port <0-65535>]\n\n" - " dummy: \n\n" + " wpan: [short-addr <0x0000-0xffff>]\n\n" + " [pan-id <0x0000-0xffff>]\n\n" + " [mac <MAC address>]\n\n" + " 6lowpan: dev <parent device (connection UUID, ifname, or MAC)>\n" + " dummy:\n\n" " SLAVE_OPTIONS:\n" " bridge: [priority <0-63>]\n" " [path-cost <1-65535>]\n" @@ -1181,7 +1286,9 @@ nmc_connection_profile_details (NMConnection *connection, NmCli *nmc) int section_idx = g_array_index (print_settings_array, int, i); const char *prop_name = (const char *) g_ptr_array_index (prop_array, i); - if (nmc->nmc_config.print_output != NMC_PRINT_TERSE && !nmc->nmc_config.multiline_output && was_output) + if ( NM_IN_SET (nmc->nmc_config.print_output, NMC_PRINT_NORMAL, NMC_PRINT_PRETTY) + && !nmc->nmc_config.multiline_output + && was_output) g_print ("\n"); /* Empty line */ was_output = FALSE; @@ -1213,19 +1320,6 @@ nmc_active_connection_state_to_color (NMActiveConnectionState state) return NM_META_COLOR_CONNECTION_UNKNOWN; } -typedef struct { - char **array; - guint32 idx; -} FillVPNDataInfo; - -static void -fill_vpn_data_item (const char *key, const char *value, gpointer user_data) -{ - FillVPNDataInfo *info = (FillVPNDataInfo *) user_data; - - info->array[info->idx++] = g_strdup_printf ("%s = %s", key, value); -} - static gboolean nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc) { @@ -1234,8 +1328,6 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc) GPtrArray *group_fields = NULL; int i; const char *fields_str = NULL; - const NMMetaAbstractInfo *const*tmpl; - NmcOutputField *arr; const char *base_hdr = _("Activate connection details"); gboolean was_output = FALSE; @@ -1278,7 +1370,7 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc) int group_idx = g_array_index (print_groups, int, i); char *group_fld = (char *) g_ptr_array_index (group_fields, i); - if ( nmc->nmc_config.print_output != NMC_PRINT_TERSE + if ( NM_IN_SET (nmc->nmc_config.print_output, NMC_PRINT_NORMAL, NMC_PRINT_PRETTY) && !nmc->nmc_config.multiline_output && was_output) g_print ("\n"); @@ -1294,6 +1386,7 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc) nmc_print (&nmc->nmc_config, (gpointer[]) { acon, NULL }, NULL, + NULL, NMC_META_GENERIC_GROUP ("GENERAL", metagen_con_active_general, N_("GROUP")), f, NULL); @@ -1306,7 +1399,7 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc) gboolean b1 = FALSE; NMIPConfig *cfg4 = nm_active_connection_get_ip4_config (acon); - b1 = print_ip4_config (cfg4, &nmc->nmc_config, group_fld); + b1 = print_ip_config (cfg4, AF_INET, &nmc->nmc_config, group_fld); was_output = was_output || b1; } @@ -1315,7 +1408,7 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc) gboolean b1 = FALSE; NMDhcpConfig *dhcp4 = nm_active_connection_get_dhcp4_config (acon); - b1 = print_dhcp_config (dhcp4, &nmc->nmc_config, "DHCP4", group_fld); + b1 = print_dhcp_config (dhcp4, AF_INET, &nmc->nmc_config, group_fld); was_output = was_output || b1; } @@ -1324,7 +1417,7 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc) gboolean b1 = FALSE; NMIPConfig *cfg6 = nm_active_connection_get_ip6_config (acon); - b1 = print_ip6_config (cfg6, &nmc->nmc_config, "IP6", group_fld); + b1 = print_ip_config (cfg6, AF_INET6, &nmc->nmc_config, group_fld); was_output = was_output || b1; } @@ -1333,73 +1426,22 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc) gboolean b1 = FALSE; NMDhcpConfig *dhcp6 = nm_active_connection_get_dhcp6_config (acon); - b1 = print_dhcp_config (dhcp6, &nmc->nmc_config, "DHCP6", group_fld); + b1 = print_dhcp_config (dhcp6, AF_INET6, &nmc->nmc_config, group_fld); was_output = was_output || b1; } - /* VPN */ - if (NM_IS_VPN_CONNECTION (acon) && - strcasecmp (nmc_fields_con_active_details_groups[group_idx]->name, nmc_fields_con_active_details_groups[5]->name) == 0) { - NMConnection *con; - NMSettingConnection *s_con; - NMSettingVpn *s_vpn; - NMVpnConnectionState vpn_state; - char *type_str, *banner_str = NULL, *vpn_state_str; - const char *banner; - const char *username = NULL; - char **vpn_data_array = NULL; - guint32 items_num; - NMC_OUTPUT_DATA_DEFINE_SCOPED (out); - - con = NM_CONNECTION (nm_active_connection_get_connection (acon)); - - s_con = nm_connection_get_setting_connection (con); - g_assert (s_con); - - tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_con_active_details_vpn; - out_indices = parse_output_fields (group_fld, - tmpl, FALSE, NULL, NULL); - arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES); - g_ptr_array_add (out.output_data, arr); - - s_vpn = nm_connection_get_setting_vpn (con); - if (s_vpn) { - items_num = nm_setting_vpn_get_num_data_items (s_vpn); - if (items_num > 0) { - FillVPNDataInfo info; - - vpn_data_array = g_new (char *, items_num + 1); - info.array = vpn_data_array; - info.idx = 0; - nm_setting_vpn_foreach_data_item (s_vpn, &fill_vpn_data_item, &info); - vpn_data_array[items_num] = NULL; - } - username = nm_setting_vpn_get_user_name (s_vpn); + if (nmc_fields_con_active_details_groups[group_idx]->nested == metagen_con_active_vpn) { + if (NM_IS_VPN_CONNECTION (acon)) { + nmc_print (&nmc->nmc_config, + (gpointer[]) { acon, NULL }, + NULL, + NULL, + NMC_META_GENERIC_GROUP ("VPN", metagen_con_active_vpn, N_("NAME")), + group_fld, + NULL); + was_output = TRUE; } - - type_str = get_vpn_connection_type (con); - banner = nm_vpn_connection_get_banner (NM_VPN_CONNECTION (acon)); - if (banner) - banner_str = g_strescape (banner, ""); - vpn_state = nm_vpn_connection_get_vpn_state (NM_VPN_CONNECTION (acon)); - vpn_state_str = g_strdup_printf ("%d - %s", - vpn_state, - gettext (vpn_connection_state_to_string (vpn_state))); - - /* Add values */ - arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX); - set_val_strc (arr, 0, nmc_fields_con_active_details_groups[5]->name); - set_val_str (arr, 1, type_str); - set_val_strc (arr, 2, username ?: get_vpn_data_item (con, VPN_DATA_ITEM_USERNAME)); - set_val_strc (arr, 3, get_vpn_data_item (con, VPN_DATA_ITEM_GATEWAY)); - set_val_str (arr, 4, banner_str); - set_val_str (arr, 5, vpn_state_str); - set_val_arr (arr, 6, vpn_data_array); - g_ptr_array_add (out.output_data, arr); - - print_data_prepare_width (out.output_data); - print_data (&nmc->nmc_config, out_indices, NULL, 0, &out); - was_output = TRUE; + continue; } } @@ -1767,7 +1809,7 @@ parse_preferred_connection_order (const char *order, GError **error) gboolean inverse, unique; int i; - strv = nm_utils_strsplit_set (order, ":"); + strv = nm_utils_strsplit_set (order, ":", FALSE); if (!strv) { g_set_error (error, NMCLI_ERROR, 0, _("incorrect string '%s' of '--order' option"), order); @@ -1926,7 +1968,6 @@ do_connections_show (NmCli *nmc, int argc, char **argv) * a profile has multiple active connections, it will be listed multiple times. * If that's not the case, we filter out these duplicate lines. */ selection = nm_meta_selection_create_parse_list ((const NMMetaAbstractInfo *const*) metagen_con_show, - NULL, fields_str, FALSE, NULL); @@ -1951,10 +1992,11 @@ do_connections_show (NmCli *nmc, int argc, char **argv) g_ptr_array_add (items, NULL); if (!nmc_print (&nmc->nmc_config, items->pdata, + NULL, active_only ? _("NetworkManager active profiles") : _("NetworkManager connection profiles"), - (const NMMetaAbstractInfo *const*) metagen_con_show, + (const NMMetaAbstractInfo *const*) metagen_con_show, fields_str, &err)) goto finish; @@ -2406,7 +2448,7 @@ progress_active_connection_cb (gpointer user_data) } str = device - ? nmc_device_state_to_string (nm_device_get_state (device)) + ? gettext (nmc_device_state_to_string (nm_device_get_state (device))) : active_connection_state_to_string (ac_state); nmc_terminal_show_progress (str); @@ -2533,7 +2575,7 @@ parse_passwords (const char *passwd_file, GError **error) return NULL; } - strv = nm_utils_strsplit_set (contents, "\r\n"); + strv = nm_utils_strsplit_set (contents, "\r\n", FALSE); for (iter = strv; *iter; iter++) { gs_free char *iter_s = g_strdup (*iter); @@ -2689,7 +2731,7 @@ do_connection_up (NmCli *nmc, int argc, char **argv) /* nmc_do_cmd() should not call this with argc=0. */ g_assert (!nmc->complete); - line = nmc_readline ("%s: ", PROMPT_CONNECTION); + line = nmc_readline (PROMPT_CONNECTION); nmc_string_to_arg_array (line, NULL, TRUE, &arg_arr, &arg_num); g_free (line); argv_ptr = &arg_arr; @@ -3189,7 +3231,7 @@ get_valid_properties_string (const NMMetaSettingValidPartItem *const*array, /* Search the array with the arguments of the current property */ for (j = 0; j < setting_info->properties_num; j++) { - gchar *new; + char *new; const char *arg_name; arg_name = setting_info->properties[j]->property_name; @@ -3644,6 +3686,18 @@ _meta_abstract_complete (const NMMetaAbstractInfo *abstract_info, const char *te return NULL; } +static char * +_meta_abstract_generator (const char *text, int state) +{ + if (nmc_tab_completion.words) { + return nmc_rl_gen_func_basic (text, + state, + (const char *const *) nmc_tab_completion.words); + } + + return NULL; +} + static void _meta_abstract_get (const NMMetaAbstractInfo *abstract_info, const NMMetaSettingInfoEditor **out_setting_info, @@ -3673,7 +3727,7 @@ static const OptionInfo *_meta_abstract_get_option_info (const NMMetaAbstractInf * The questionnaire (for --ask) will ask for them. */ static void -enable_options (const gchar *setting_name, const gchar *property, const gchar * const *opts) +enable_options (const char *setting_name, const char *property, const char * const *opts) { const NMMetaPropertyInfo *property_info; @@ -3711,7 +3765,7 @@ enable_options (const gchar *setting_name, const gchar *property, const gchar * * The questionnaire (for --ask) will not ask for them. */ static void -disable_options (const gchar *setting_name, const gchar *property) +disable_options (const char *setting_name, const char *property) { const NMMetaPropertyInfo *property_infos_local[2]; const NMMetaPropertyInfo *const*property_infos; @@ -3869,7 +3923,7 @@ set_property (NMConnection *connection, } static gboolean -set_option (NmCli *nmc, NMConnection *connection, const NMMetaAbstractInfo *abstract_info, const gchar *value, GError **error) +set_option (NmCli *nmc, NMConnection *connection, const NMMetaAbstractInfo *abstract_info, const char *value, GError **error) { const char *setting_name, *property_name, *option_name; NMMetaPropertyInfFlags inf_flags; @@ -3993,7 +4047,7 @@ set_connection_type (NmCli *nmc, NMConnection *con, const OptionInfo *option, co const NMMetaSettingValidPartItem *const*type_settings; const NMMetaSettingValidPartItem *const*slv_settings; GError *local = NULL; - const gchar *master[] = { "master", NULL }; + const char *master[] = { "master", NULL }; const char *slave_type = NULL; value = check_valid_name_toplevel (value, &slave_type, &local); @@ -4101,7 +4155,7 @@ set_bond_option (NmCli *nmc, NMConnection *con, const OptionInfo *option, const return FALSE; if (g_strcmp0 (value, "active-backup") == 0) { - const gchar *primary[] = { "primary", NULL }; + const char *primary[] = { "primary", NULL }; enable_options (NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS, primary); } @@ -4136,9 +4190,9 @@ static gboolean set_bond_monitoring_mode (NmCli *nmc, NMConnection *con, const OptionInfo *option, const char *value, GError **error) { NMSettingBond *s_bond; - gs_free gchar *monitor_mode = NULL; - const gchar *miimon_opts[] = { "miimon", "downdelay", "updelay", NULL }; - const gchar *arp_opts[] = { "arp-interval", "arp-ip-target", NULL }; + gs_free char *monitor_mode = NULL; + const char *miimon_opts[] = { "miimon", "downdelay", "updelay", NULL }; + const char *arp_opts[] = { "arp-interval", "arp-ip-target", NULL }; s_bond = nm_connection_get_setting_bond (con); g_return_val_if_fail (s_bond, FALSE); @@ -4307,8 +4361,8 @@ option_relevant (NMConnection *connection, const NMMetaAbstractInfo *abstract_in static void complete_property_name (NmCli *nmc, NMConnection *connection, char modifier, - const gchar *prefix, - const gchar *postfix) + const char *prefix, + const char *postfix) { NMSettingConnection *s_con; const NMMetaSettingValidPartItem *const*valid_settings_main; @@ -4383,7 +4437,7 @@ run_rl_generator (rl_compentry_func_t *generator_func, const char *prefix) } static gboolean -complete_option (const NMMetaAbstractInfo *abstract_info, const gchar *prefix, NMConnection *context_connection) +complete_option (const NMMetaAbstractInfo *abstract_info, const char *prefix, NMConnection *context_connection) { const OptionInfo *candidate; const char *const*values; @@ -4414,7 +4468,7 @@ complete_option (const NMMetaAbstractInfo *abstract_info, const gchar *prefix, N } static void -complete_property (const gchar *setting_name, const gchar *property, const gchar *prefix, NMConnection *connection) +complete_property (const char *setting_name, const char *property, const char *prefix, NMConnection *connection) { const NMMetaPropertyInfo *property_info; @@ -4468,7 +4522,7 @@ nmc_read_connection_properties (NmCli *nmc, /* Go through arguments and set properties */ do { const NMMetaAbstractInfo *chosen = NULL; - gs_strfreev gchar **strv = NULL; + gs_strfreev char **strv = NULL; const NMMetaSettingValidPartItem *const*type_settings; const NMMetaSettingValidPartItem *const*slv_settings; char modifier = '\0'; @@ -4711,6 +4765,7 @@ nmcli_con_add_tab_completion (const char *text, int start, int end) rl_compentry_func_t *generator_func = NULL; gs_free char *no = g_strdup_printf ("[%s]: ", _("no")); gs_free char *yes = g_strdup_printf ("[%s]: ", _("yes")); + const NMMetaAbstractInfo *info; /* Disable readline's default filename completion */ rl_attempted_completion_over = 1; @@ -4745,12 +4800,13 @@ nmcli_con_add_tab_completion (const char *text, int start, int end) } else { if ( property_info->prompt && g_str_has_prefix (rl_prompt, property_info->prompt)) { - char **values; - - values = _meta_abstract_complete ((const NMMetaAbstractInfo *) property_info, text); - if (values) - return values; - goto next; + info = (const NMMetaAbstractInfo *) property_info; + nmc_tab_completion.words = _meta_abstract_complete (info, text); + if (nmc_tab_completion.words) { + match_array = rl_completion_matches (text, _meta_abstract_generator); + nm_clear_pointer (&nmc_tab_completion.words, g_strfreev); + } + return match_array; } } } @@ -4776,9 +4832,9 @@ next: static void ask_option (NmCli *nmc, NMConnection *connection, const NMMetaAbstractInfo *abstract_info) { - gchar *value; + char *value; GError *error = NULL; - gs_free gchar *prompt = NULL; + gs_free char *prompt = NULL; gboolean multi; const char *opt_prompt, *opt_def_hint; NMMetaPropertyInfFlags inf_flags; @@ -6534,7 +6590,7 @@ progress_activation_editor_cb (gpointer user_data) ac_state = nm_active_connection_get_state (ac); dev_state = nm_device_get_state (device); - nmc_terminal_show_progress (nmc_device_state_to_string (dev_state)); + nmc_terminal_show_progress (gettext (nmc_device_state_to_string (dev_state))); if ( ac_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED || dev_state == NM_DEVICE_STATE_ACTIVATED) { @@ -8114,6 +8170,8 @@ do_connection_edit (NmCli *nmc, int argc, char **argv) g_print ("\n\n"); g_print (_("Type 'help' or '?' for available commands.")); g_print ("\n"); + g_print (_("Type 'print' to show all the connection properties.")); + g_print ("\n"); g_print (_("Type 'describe [<setting>.<prop>]' for detailed property description.")); g_print ("\n\n"); @@ -8270,7 +8328,7 @@ do_connection_clone (NmCli *nmc, int argc, char **argv) /* nmc_do_cmd() should not call this with argc=0. */ g_assert (!nmc->complete); - line = nmc_readline ("%s: ", PROMPT_CONNECTION); + line = nmc_readline (PROMPT_CONNECTION); nmc_string_to_arg_array (line, NULL, TRUE, &arg_arr, &arg_num); g_free (line); argv_ptr = &arg_arr; @@ -8380,7 +8438,7 @@ do_connection_delete (NmCli *nmc, int argc, char **argv) /* nmc_do_cmd() should not call this with argc=0. */ g_assert (!nmc->complete); - line = nmc_readline ("%s: ", PROMPT_CONNECTIONS); + line = nmc_readline (PROMPT_CONNECTIONS); nmc_string_to_arg_array (line, NULL, TRUE, &arg_arr, &arg_num); g_free (line); arg_ptr = arg_arr; @@ -8631,7 +8689,7 @@ do_connection_import (NmCli *nmc, int argc, char **argv) g_assert (!nmc->complete); if (nmc->ask) { - type_ask = nmc_readline (gettext (NM_META_TEXT_PROMPT_VPN_TYPE)); + type_ask = nmc_readline ("%s: ", gettext (NM_META_TEXT_PROMPT_VPN_TYPE)); filename_ask = nmc_readline (gettext (PROMPT_IMPORT_FILE)); type = type_ask = type_ask ? g_strstrip (type_ask) : NULL; filename = filename_ask = filename_ask ? g_strstrip (filename_ask) : NULL; @@ -8756,7 +8814,7 @@ do_connection_export (NmCli *nmc, int argc, char **argv) /* nmc_do_cmd() should not call this with argc=0. */ g_assert (!nmc->complete); - line = nmc_readline ("%s: ", PROMPT_VPN_CONNECTION); + line = nmc_readline (PROMPT_VPN_CONNECTION); nmc_string_to_arg_array (line, NULL, TRUE, &arg_arr, &arg_num); g_free (line); argv_ptr = &arg_arr; @@ -8896,6 +8954,7 @@ nmcli_con_tab_completion (const char *text, int start, int end) { char **match_array = NULL; rl_compentry_func_t *generator_func = NULL; + const NMMetaAbstractInfo *info; /* Disable readline's default filename completion */ rl_attempted_completion_over = 1; @@ -8912,8 +8971,10 @@ nmcli_con_tab_completion (const char *text, int start, int end) generator_func = gen_func_connection_names; } else if (g_strcmp0 (rl_prompt, PROMPT_ACTIVE_CONNECTIONS) == 0) { generator_func = gen_func_active_connection_names; - } else if (g_strcmp0 (rl_prompt, NM_META_TEXT_PROMPT_VPN_TYPE) == 0) { - return _meta_abstract_complete ((const NMMetaAbstractInfo *) nm_meta_property_info_vpn_service_type, text); + } else if (rl_prompt && g_str_has_prefix (rl_prompt, NM_META_TEXT_PROMPT_VPN_TYPE)) { + info = (const NMMetaAbstractInfo *) nm_meta_property_info_vpn_service_type; + nmc_tab_completion.words = _meta_abstract_complete (info, text); + generator_func = _meta_abstract_generator; } else if (g_strcmp0 (rl_prompt, PROMPT_IMPORT_FILE) == 0) { rl_attempted_completion_over = 0; rl_complete_with_tilde_expansion = 1; @@ -8924,6 +8985,7 @@ nmcli_con_tab_completion (const char *text, int start, int end) if (generator_func) match_array = rl_completion_matches (text, generator_func); + g_clear_pointer (&nmc_tab_completion.words, g_strfreev); return match_array; } diff --git a/clients/cli/connections.h b/clients/cli/connections.h index 43cd97f6..22bfa8ec 100644 --- a/clients/cli/connections.h +++ b/clients/cli/connections.h @@ -37,7 +37,7 @@ NMMetaColor nmc_active_connection_state_to_color (NMActiveConnectionState state) extern const NmcMetaGenericInfo *const metagen_con_show[]; extern const NmcMetaGenericInfo *const metagen_con_active_general[]; -extern const NmcMetaGenericInfo *const nmc_fields_con_active_details_vpn[]; +extern const NmcMetaGenericInfo *const metagen_con_active_vpn[]; extern const NmcMetaGenericInfo *const nmc_fields_con_active_details_groups[]; #endif /* NMC_CONNECTIONS_H */ diff --git a/clients/cli/devices.c b/clients/cli/devices.c index be759732..ca575c33 100644 --- a/clients/cli/devices.c +++ b/clients/cli/devices.c @@ -39,99 +39,518 @@ #define PROMPT_INTERFACE _("Interface: ") #define PROMPT_INTERFACES _("Interface(s): ") -const NmcMetaGenericInfo *const nmc_fields_dev_status[] = { - NMC_META_GENERIC ("DEVICE"), /* 0 */ - NMC_META_GENERIC ("TYPE"), /* 1 */ - NMC_META_GENERIC ("STATE"), /* 2 */ - NMC_META_GENERIC ("DBUS-PATH"), /* 3 */ - NMC_META_GENERIC ("CONNECTION"), /* 4 */ - NMC_META_GENERIC ("CON-UUID"), /* 5 */ - NMC_META_GENERIC ("CON-PATH"), /* 6 */ - NULL, +/*****************************************************************************/ + +static char * +ap_wpa_rsn_flags_to_string (NM80211ApSecurityFlags flags) +{ + char *flags_str[16]; /* Enough space for flags and terminating NULL */ + char *ret_str; + int i = 0; + + if (flags & NM_802_11_AP_SEC_PAIR_WEP40) + flags_str[i++] = g_strdup ("pair_wpe40"); + if (flags & NM_802_11_AP_SEC_PAIR_WEP104) + flags_str[i++] = g_strdup ("pair_wpe104"); + if (flags & NM_802_11_AP_SEC_PAIR_TKIP) + flags_str[i++] = g_strdup ("pair_tkip"); + if (flags & NM_802_11_AP_SEC_PAIR_CCMP) + flags_str[i++] = g_strdup ("pair_ccmp"); + if (flags & NM_802_11_AP_SEC_GROUP_WEP40) + flags_str[i++] = g_strdup ("group_wpe40"); + if (flags & NM_802_11_AP_SEC_GROUP_WEP104) + flags_str[i++] = g_strdup ("group_wpe104"); + if (flags & NM_802_11_AP_SEC_GROUP_TKIP) + flags_str[i++] = g_strdup ("group_tkip"); + if (flags & NM_802_11_AP_SEC_GROUP_CCMP) + flags_str[i++] = g_strdup ("group_ccmp"); + if (flags & NM_802_11_AP_SEC_KEY_MGMT_PSK) + flags_str[i++] = g_strdup ("psk"); + if (flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) + flags_str[i++] = g_strdup ("802.1X"); + + if (i == 0) + flags_str[i++] = g_strdup (_("(none)")); + + flags_str[i] = NULL; + + ret_str = g_strjoinv (" ", flags_str); + + i = 0; + while (flags_str[i]) + g_free (flags_str[i++]); + + return ret_str; +} + +static NMMetaColor +wifi_signal_to_color (guint8 strength) +{ + if (strength > 80) + return NM_META_COLOR_WIFI_SIGNAL_EXCELLENT; + else if (strength > 55) + return NM_META_COLOR_WIFI_SIGNAL_GOOD; + else if (strength > 30) + return NM_META_COLOR_WIFI_SIGNAL_FAIR; + else if (strength > 5) + return NM_META_COLOR_WIFI_SIGNAL_POOR; + else + return NM_META_COLOR_WIFI_SIGNAL_UNKNOWN; +} + +/*****************************************************************************/ + +static gconstpointer +_metagen_device_status_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS) +{ + NMDevice *d = target; + NMActiveConnection *ac; + + NMC_HANDLE_COLOR (nmc_device_state_to_color (nm_device_get_state (d))); + + switch (info->info_type) { + case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_DEVICE: + return nm_device_get_iface (d); + case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_TYPE: + return nm_device_get_type_description (d); + case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_STATE: + return nmc_meta_generic_get_str_i18n (nmc_device_state_to_string (nm_device_get_state (d)), + get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_DBUS_PATH: + return nm_object_get_path (NM_OBJECT (d)); + case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CONNECTION: + ac = nm_device_get_active_connection (d); + return ac ? nm_active_connection_get_id (ac) : NULL; + case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CON_UUID: + ac = nm_device_get_active_connection (d); + return ac ? nm_active_connection_get_uuid (ac) : NULL; + case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CON_PATH: + ac = nm_device_get_active_connection (d); + return ac ? nm_object_get_path (NM_OBJECT (ac)) : NULL; + default: + break; + } + + g_return_val_if_reached (NULL); +} + +const NmcMetaGenericInfo *const metagen_device_status[_NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_NUM + 1] = { +#define _METAGEN_DEVICE_STATUS(type, name) \ + [type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_device_status_get_fcn) + _METAGEN_DEVICE_STATUS (NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_DEVICE, "DEVICE"), + _METAGEN_DEVICE_STATUS (NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_TYPE, "TYPE"), + _METAGEN_DEVICE_STATUS (NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_STATE, "STATE"), + _METAGEN_DEVICE_STATUS (NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_DBUS_PATH, "DBUS-PATH"), + _METAGEN_DEVICE_STATUS (NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CONNECTION, "CONNECTION"), + _METAGEN_DEVICE_STATUS (NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CON_UUID, "CON-UUID"), + _METAGEN_DEVICE_STATUS (NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CON_PATH, "CON-PATH"), }; -#define NMC_FIELDS_DEV_STATUS_COMMON "DEVICE,TYPE,STATE,CONNECTION" - -const NmcMetaGenericInfo *const nmc_fields_dev_show_general[] = { - NMC_META_GENERIC ("NAME"), /* 0 */ - NMC_META_GENERIC ("DEVICE"), /* 1 */ - NMC_META_GENERIC ("TYPE"), /* 2 */ - NMC_META_GENERIC ("NM-TYPE"), /* 3 */ - NMC_META_GENERIC ("VENDOR"), /* 4 */ - NMC_META_GENERIC ("PRODUCT"), /* 5 */ - NMC_META_GENERIC ("DRIVER"), /* 6 */ - NMC_META_GENERIC ("DRIVER-VERSION"), /* 7 */ - NMC_META_GENERIC ("FIRMWARE-VERSION"), /* 8 */ - NMC_META_GENERIC ("HWADDR"), /* 9 */ - NMC_META_GENERIC ("MTU"), /* 10 */ - NMC_META_GENERIC ("STATE"), /* 11 */ - NMC_META_GENERIC ("REASON"), /* 12 */ - NMC_META_GENERIC ("UDI"), /* 13 */ - NMC_META_GENERIC ("IP-IFACE"), /* 14 */ - NMC_META_GENERIC ("IS-SOFTWARE"), /* 15 */ - NMC_META_GENERIC ("NM-MANAGED"), /* 16 */ - NMC_META_GENERIC ("AUTOCONNECT"), /* 17 */ - NMC_META_GENERIC ("FIRMWARE-MISSING"), /* 18 */ - NMC_META_GENERIC ("NM-PLUGIN-MISSING"), /* 19 */ - NMC_META_GENERIC ("PHYS-PORT-ID"), /* 20 */ - NMC_META_GENERIC ("CONNECTION"), /* 21 */ - NMC_META_GENERIC ("CON-UUID"), /* 22 */ - NMC_META_GENERIC ("CON-PATH"), /* 23 */ - NMC_META_GENERIC ("METERED"), /* 24 */ - NULL, + +/*****************************************************************************/ + +static gconstpointer +_metagen_device_detail_general_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS) +{ + NMDevice *d = target; + NMActiveConnection *ac; + NMDeviceState state; + NMDeviceStateReason state_reason; + const char *s; + + NMC_HANDLE_COLOR (NM_META_COLOR_NONE); + + switch (info->info_type) { + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DEVICE: + return nm_device_get_iface (d); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_TYPE: + return nm_device_get_type_description (d); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_TYPE: + return G_OBJECT_TYPE_NAME (d); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_VENDOR: + return nm_device_get_vendor (d); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PRODUCT: + return nm_device_get_product (d); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DRIVER: + s = nm_device_get_driver (d); + return s ?: nmc_meta_generic_get_str_i18n (N_("(unknown)"), get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DRIVER_VERSION: + return nm_device_get_driver_version (d); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_FIRMWARE_VERSION: + return nm_device_get_firmware_version (d); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_HWADDR: + s = nm_device_get_hw_address (d); + return s ?: nmc_meta_generic_get_str_i18n (N_("(unknown)"), get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_MTU: + return (*out_to_free = g_strdup_printf ("%u", (guint) nm_device_get_mtu (d))); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_STATE: + state = nm_device_get_state (d); + return (*out_to_free = nmc_meta_generic_get_enum_with_detail (NMC_META_GENERIC_GET_ENUM_TYPE_PARENTHESES, + state, + nmc_device_state_to_string (state), + get_type)); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_REASON: + state_reason = nm_device_get_state_reason (d); + return (*out_to_free = nmc_meta_generic_get_enum_with_detail (NMC_META_GENERIC_GET_ENUM_TYPE_PARENTHESES, + state_reason, + nmc_device_reason_to_string (state_reason), + get_type)); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_UDI: + return nm_device_get_udi (d); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IP_IFACE: + return nm_device_get_ip_iface (d); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IS_SOFTWARE: + return nmc_meta_generic_get_bool (nm_device_is_software (d), get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_MANAGED: + return nmc_meta_generic_get_bool (nm_device_get_managed (d), get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_AUTOCONNECT: + return nmc_meta_generic_get_bool (nm_device_get_autoconnect (d), get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_FIRMWARE_MISSING: + return nmc_meta_generic_get_bool (nm_device_get_firmware_missing (d), get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_PLUGIN_MISSING: + return nmc_meta_generic_get_bool (nm_device_get_nm_plugin_missing (d), get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PHYS_PORT_ID: + return nm_device_get_physical_port_id (d); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CONNECTION: + ac = nm_device_get_active_connection (d); + return ac ? nm_active_connection_get_id (ac) : NULL; + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CON_UUID: + ac = nm_device_get_active_connection (d); + return ac ? nm_active_connection_get_uuid (ac) : NULL; + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CON_PATH: + ac = nm_device_get_active_connection (d); + return ac ? nm_object_get_path (NM_OBJECT (ac)) : NULL; + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_METERED: + return nmc_meta_generic_get_str_i18n (nmc_device_metered_to_string (nm_device_get_metered (d)), + get_type); + default: + break; + } + + g_return_val_if_reached (NULL); +} + +const NmcMetaGenericInfo *const metagen_device_detail_general[_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NUM + 1] = { +#define _METAGEN_DEVICE_DETAIL_GENERAL(type, name) \ + [type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_device_detail_general_get_fcn) + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DEVICE, "DEVICE"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_TYPE, "TYPE"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_TYPE, "NM-TYPE"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_VENDOR, "VENDOR"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PRODUCT, "PRODUCT"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DRIVER, "DRIVER"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DRIVER_VERSION, "DRIVER-VERSION"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_FIRMWARE_VERSION, "FIRMWARE-VERSION"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_HWADDR, "HWADDR"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_MTU, "MTU"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_STATE, "STATE"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_REASON, "REASON"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_UDI, "UDI"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IP_IFACE, "IP-IFACE"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IS_SOFTWARE, "IS-SOFTWARE"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_MANAGED, "NM-MANAGED"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_AUTOCONNECT, "AUTOCONNECT"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_FIRMWARE_MISSING, "FIRMWARE-MISSING"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_PLUGIN_MISSING, "NM-PLUGIN-MISSING"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PHYS_PORT_ID, "PHYS-PORT-ID"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CONNECTION, "CONNECTION"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CON_UUID, "CON-UUID"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CON_PATH, "CON-PATH"), + _METAGEN_DEVICE_DETAIL_GENERAL (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_METERED, "METERED"), }; -#define NMC_FIELDS_DEV_SHOW_GENERAL_COMMON "NAME,DEVICE,TYPE,VENDOR,PRODUCT,DRIVER,HWADDR,STATE" -const NmcMetaGenericInfo *const nmc_fields_dev_show_connections[] = { - NMC_META_GENERIC ("NAME"), /* 0 */ - NMC_META_GENERIC ("AVAILABLE-CONNECTION-PATHS"), /* 1 */ - NMC_META_GENERIC ("AVAILABLE-CONNECTIONS"), /* 2 */ - NULL, +/*****************************************************************************/ + +static NMRemoteConnection ** +_device_get_available_connections (NMDevice *d, guint *out_len) +{ + NMRemoteConnection **avail_cons; + const GPtrArray *avail_cons_arr; + + avail_cons_arr = nm_device_get_available_connections (d); + if (!avail_cons_arr || avail_cons_arr->len == 0) { + *out_len = 0; + return NULL; + } + + avail_cons = (NMRemoteConnection **) nmc_objects_sort_by_path ((const NMObject *const*) avail_cons_arr->pdata, + avail_cons_arr->len); + nm_assert (avail_cons_arr->len == NM_PTRARRAY_LEN (avail_cons)); + *out_len = avail_cons_arr->len; + return avail_cons; +} + +static gconstpointer +_metagen_device_detail_connections_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS) +{ + NMDevice *d = target; + gs_free NMRemoteConnection **avail_cons = NULL; + guint avail_cons_len; + guint i, j; + char **arr = NULL; + GString *str; + gboolean had_prefix, has_prefix; + + NMC_HANDLE_COLOR (NM_META_COLOR_NONE); + + switch (info->info_type) { + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_AVAILABLE_CONNECTIONS: + if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV)) + return NULL; + + avail_cons = _device_get_available_connections (d, &avail_cons_len); + if (avail_cons_len == 0) + goto arr_out; + + arr = g_new (char *, avail_cons_len + 1); + j = 0; + for (i = 0; i < avail_cons_len; i++) { + NMRemoteConnection *ac = avail_cons[i]; + const char *ac_id = nm_connection_get_id (NM_CONNECTION (ac)); + const char *ac_uuid = nm_connection_get_uuid (NM_CONNECTION (ac)); + + if (!ac_id || !ac_uuid) { + const char *ac_path = nm_connection_get_path (NM_CONNECTION (ac)); + + if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) { + arr[j++] = ac_path + ? g_strdup_printf (_("<invisible> | %s"), ac_path) + : g_strdup (_("<invisible>")); + } else { + arr[j++] = ac_path + ? g_strdup_printf ("<invisible> | %s", ac_path) + : g_strdup ("<invisible>"); + } + } else + arr[j++] = g_strdup_printf ("%s | %s", ac_uuid, ac_id); + } + arr[j] = NULL; + goto arr_out; + + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_AVAILABLE_CONNECTION_PATHS: + + avail_cons = _device_get_available_connections (d, &avail_cons_len); + if (avail_cons_len == 0) + return NULL; + + str = g_string_new (NULL); + + had_prefix = FALSE; + for (i = 0; i < avail_cons_len; i++) { + NMRemoteConnection *ac = avail_cons[i]; + const char *p = nm_connection_get_path (NM_CONNECTION (ac)); + + if (!p) + continue; + + has_prefix = g_str_has_prefix (p, NM_DBUS_PATH_SETTINGS_CONNECTION"/") + && p[NM_STRLEN (NM_DBUS_PATH_SETTINGS_CONNECTION"/")]; + + if (str->len > 0) { + if ( had_prefix + && !has_prefix) + g_string_append_c (str, '}'); + g_string_append_c (str, ','); + } + + if (!has_prefix) + g_string_append (str, p); + else { + if (!had_prefix) + g_string_printf (str, "%s/{", NM_DBUS_PATH_SETTINGS_CONNECTION); + g_string_append (str, &p[NM_STRLEN (NM_DBUS_PATH_SETTINGS_CONNECTION"/")]); + } + had_prefix = has_prefix; + } + if (had_prefix) + g_string_append_c (str, '}'); + + return (*out_to_free = g_string_free (str, FALSE)); + + default: + break; + } + + g_return_val_if_reached (NULL); + +arr_out: + NM_SET_OUT (out_is_default, !arr || !arr[0]); + *out_flags |= NM_META_ACCESSOR_GET_OUT_FLAGS_STRV; + *out_to_free = arr; + return arr; +} + +const NmcMetaGenericInfo *const metagen_device_detail_connections[_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_NUM + 1] = { +#define _METAGEN_DEVICE_DETAIL_CONNECTIONS(type, name) \ + [type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_device_detail_connections_get_fcn) + _METAGEN_DEVICE_DETAIL_CONNECTIONS (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_AVAILABLE_CONNECTION_PATHS, "AVAILABLE-CONNECTION-PATHS"), + _METAGEN_DEVICE_DETAIL_CONNECTIONS (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_AVAILABLE_CONNECTIONS, "AVAILABLE-CONNECTIONS"), }; -#define NMC_FIELDS_DEV_SHOW_CONNECTIONS_COMMON "NAME,AVAILABLE-CONNECTION-PATHS,AVAILABLE-CONNECTIONS" - -const NmcMetaGenericInfo *const nmc_fields_dev_show_cap[] = { - NMC_META_GENERIC ("NAME"), /* 0 */ - NMC_META_GENERIC ("CARRIER-DETECT"), /* 1 */ - NMC_META_GENERIC ("SPEED"), /* 2 */ - NMC_META_GENERIC ("IS-SOFTWARE"), /* 3 */ - NMC_META_GENERIC ("SRIOV"), /* 4 */ - NULL, + +/*****************************************************************************/ + +static gconstpointer +_metagen_device_detail_capabilities_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS) +{ + NMDevice *d = target; + NMDeviceCapabilities caps; + guint32 speed; + + NMC_HANDLE_COLOR (NM_META_COLOR_NONE); + + caps = nm_device_get_capabilities (d); + + switch (info->info_type) { + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_CARRIER_DETECT: + return nmc_meta_generic_get_bool (NM_FLAGS_HAS (caps, NM_DEVICE_CAP_CARRIER_DETECT), get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_SPEED: + speed = 0; + if (NM_IS_DEVICE_ETHERNET (d)) { + /* Speed in Mb/s */ + speed = nm_device_ethernet_get_speed (NM_DEVICE_ETHERNET (d)); + } else if (NM_IS_DEVICE_WIFI (d)) { + /* Speed in b/s */ + speed = nm_device_wifi_get_bitrate (NM_DEVICE_WIFI (d)); + speed /= 1000; + } + + if (speed) { + if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) + return (*out_to_free = g_strdup_printf (_("%u Mb/s"), (guint) speed)); + return (*out_to_free = g_strdup_printf ("%u Mb/s", (guint) speed)); + } + return nmc_meta_generic_get_str_i18n (N_("unknown"), get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_IS_SOFTWARE: + return nmc_meta_generic_get_bool (NM_FLAGS_HAS (caps, NM_DEVICE_CAP_IS_SOFTWARE), get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_SRIOV: + return nmc_meta_generic_get_bool (NM_FLAGS_HAS (caps, NM_DEVICE_CAP_SRIOV), get_type); + default: + break; + } + + g_return_val_if_reached (NULL); +} + +const NmcMetaGenericInfo *const metagen_device_detail_capabilities[_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_NUM + 1] = { +#define _METAGEN_DEVICE_DETAIL_CAPABILITIES(type, name) \ + [type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_device_detail_capabilities_get_fcn) + _METAGEN_DEVICE_DETAIL_CAPABILITIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_CARRIER_DETECT, "CARRIER-DETECT"), + _METAGEN_DEVICE_DETAIL_CAPABILITIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_SPEED, "SPEED"), + _METAGEN_DEVICE_DETAIL_CAPABILITIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_IS_SOFTWARE, "IS-SOFTWARE"), + _METAGEN_DEVICE_DETAIL_CAPABILITIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_SRIOV, "SRIOV"), }; -#define NMC_FIELDS_DEV_SHOW_CAP_COMMON "NAME,CARRIER-DETECT,SPEED,IS-SOFTWARE" -const NmcMetaGenericInfo *const nmc_fields_dev_show_wired_prop[] = { - NMC_META_GENERIC ("NAME"), /* 0 */ - NMC_META_GENERIC ("CARRIER"), /* 1 */ - NMC_META_GENERIC ("S390-SUBCHANNELS"), /* 2 */ - NULL, +/*****************************************************************************/ + +static gconstpointer +_metagen_device_detail_wired_properties_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS) +{ + NMDevice *d = target; + + NMC_HANDLE_COLOR (NM_META_COLOR_NONE); + + switch (info->info_type) { + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_CARRIER: + return nmc_meta_generic_get_bool_onoff (nm_device_ethernet_get_carrier (NM_DEVICE_ETHERNET (d)), + get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_S390_SUBCHANNELS: + if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV)) + return NULL; + *out_flags |= NM_META_ACCESSOR_GET_OUT_FLAGS_STRV; + return nm_device_ethernet_get_s390_subchannels (NM_DEVICE_ETHERNET (d)); + default: + break; + } + + g_return_val_if_reached (NULL); +} + +const NmcMetaGenericInfo *const metagen_device_detail_wired_properties[_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_NUM + 1] = { +#define _METAGEN_DEVICE_DETAIL_WIRED_PROPERTIES(type, name) \ + [type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_device_detail_wired_properties_get_fcn) + _METAGEN_DEVICE_DETAIL_WIRED_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_CARRIER, "CARRIER"), + _METAGEN_DEVICE_DETAIL_WIRED_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_S390_SUBCHANNELS, "S390-SUBCHANNELS"), }; -#define NMC_FIELDS_DEV_SHOW_WIRED_PROP_COMMON "NAME,CARRIER,S390-SUBCHANNELS" - -const NmcMetaGenericInfo *const nmc_fields_dev_show_wifi_prop[] = { - NMC_META_GENERIC ("NAME"), /* 0 */ - NMC_META_GENERIC ("WEP"), /* 1 */ - NMC_META_GENERIC ("WPA"), /* 2 */ - NMC_META_GENERIC ("WPA2"), /* 3 */ - NMC_META_GENERIC ("TKIP"), /* 4 */ - NMC_META_GENERIC ("CCMP"), /* 5 */ - NMC_META_GENERIC ("AP"), /* 6 */ - NMC_META_GENERIC ("ADHOC"), /* 7 */ - NMC_META_GENERIC ("2GHZ"), /* 8 */ - NMC_META_GENERIC ("5GHZ"), /* 9 */ - NULL, + +/*****************************************************************************/ + +static gconstpointer +_metagen_device_detail_wifi_properties_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS) +{ + NMDevice *d = target; + NMDeviceWifiCapabilities wcaps; + + NMC_HANDLE_COLOR (NM_META_COLOR_NONE); + + wcaps = nm_device_wifi_get_capabilities (NM_DEVICE_WIFI (d)); + + switch (info->info_type) { + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WEP: + return nmc_meta_generic_get_bool (NM_FLAGS_ANY (wcaps, NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104), + get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WPA: + return nmc_meta_generic_get_bool (NM_FLAGS_HAS (wcaps, NM_WIFI_DEVICE_CAP_WPA), + get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WPA2: + return nmc_meta_generic_get_bool (NM_FLAGS_HAS (wcaps, NM_WIFI_DEVICE_CAP_RSN), + get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_TKIP: + return nmc_meta_generic_get_bool (NM_FLAGS_HAS (wcaps, NM_WIFI_DEVICE_CAP_CIPHER_TKIP), + get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_CCMP: + return nmc_meta_generic_get_bool (NM_FLAGS_HAS (wcaps, NM_WIFI_DEVICE_CAP_CIPHER_CCMP), + get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_AP: + return nmc_meta_generic_get_bool (NM_FLAGS_HAS (wcaps, NM_WIFI_DEVICE_CAP_AP), + get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_ADHOC: + return nmc_meta_generic_get_bool (NM_FLAGS_HAS (wcaps, NM_WIFI_DEVICE_CAP_ADHOC), + get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_2GHZ: + return nmc_meta_generic_get_str_i18n ( NM_FLAGS_HAS (wcaps, NM_WIFI_DEVICE_CAP_FREQ_VALID) + ? ( NM_FLAGS_HAS (wcaps, NM_WIFI_DEVICE_CAP_FREQ_2GHZ) + ? N_("yes") + : N_("no")) + : N_("unknown"), + get_type); + case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_5GHZ: + return nmc_meta_generic_get_str_i18n ( NM_FLAGS_HAS (wcaps, NM_WIFI_DEVICE_CAP_FREQ_VALID) + ? ( NM_FLAGS_HAS (wcaps, NM_WIFI_DEVICE_CAP_FREQ_5GHZ) + ? N_("yes") + : N_("no")) + : N_("unknown"), + get_type); + default: + break; + } + + g_return_val_if_reached (NULL); +} + +const NmcMetaGenericInfo *const metagen_device_detail_wifi_properties[_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_NUM + 1] = { +#define _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES(type, name) \ + [type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_device_detail_wifi_properties_get_fcn) + _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WEP, "WEP"), + _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WPA, "WPA"), + _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WPA2, "WPA2"), + _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_TKIP, "TKIP"), + _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_CCMP, "CCMP"), + _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_AP, "AP"), + _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_ADHOC, "ADHOC"), + _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_2GHZ, "2GHZ"), + _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES (NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_5GHZ, "5GHZ"), }; -#define NMC_FIELDS_DEV_SHOW_WIFI_PROP_COMMON "NAME,WEP,WPA,WPA2,TKIP,CCMP,AP,ADHOC" - -const NmcMetaGenericInfo *const nmc_fields_dev_show_wimax_prop[] = { - NMC_META_GENERIC ("NAME"), /* 0 */ - NMC_META_GENERIC ("CTR-FREQ"), /* 1 */ - NMC_META_GENERIC ("RSSI"), /* 2 */ - NMC_META_GENERIC ("CINR"), /* 3 */ - NMC_META_GENERIC ("TX-POW"), /* 4 */ - NMC_META_GENERIC ("BSID"), /* 5 */ - NULL, + +/*****************************************************************************/ + +const NmcMetaGenericInfo *const metagen_device_detail_wimax_properties[] = { + NMC_META_GENERIC ("CTR-FREQ"), + NMC_META_GENERIC ("RSSI"), + NMC_META_GENERIC ("CINR"), + NMC_META_GENERIC ("TX-POW"), + NMC_META_GENERIC ("BSID"), }; -#define NMC_FIELDS_DEV_SHOW_WIMAX_PROP_COMMON "NAME,CTR-FREQ,RSSI,CINR,TX-POW,BSID" + +/*****************************************************************************/ const NmcMetaGenericInfo *const nmc_fields_dev_wifi_list[] = { NMC_META_GENERIC ("NAME"), /* 0 */ @@ -201,23 +620,23 @@ const NmcMetaGenericInfo *const nmc_fields_dev_show_bluetooth[] = { /* Available sections for 'device show' */ const NmcMetaGenericInfo *const nmc_fields_dev_show_sections[] = { - NMC_META_GENERIC_WITH_NESTED ("GENERAL", nmc_fields_dev_show_general + 1), /* 0 */ - NMC_META_GENERIC_WITH_NESTED ("CAPABILITIES", nmc_fields_dev_show_cap + 1), /* 1 */ - NMC_META_GENERIC_WITH_NESTED ("WIFI-PROPERTIES", nmc_fields_dev_show_wifi_prop + 1), /* 2 */ + NMC_META_GENERIC_WITH_NESTED ("GENERAL", metagen_device_detail_general), /* 0 */ + NMC_META_GENERIC_WITH_NESTED ("CAPABILITIES", metagen_device_detail_capabilities), /* 1 */ + NMC_META_GENERIC_WITH_NESTED ("WIFI-PROPERTIES", metagen_device_detail_wifi_properties), /* 2 */ NMC_META_GENERIC_WITH_NESTED ("AP", nmc_fields_dev_wifi_list + 1), /* 3 */ - NMC_META_GENERIC_WITH_NESTED ("WIRED-PROPERTIES", nmc_fields_dev_show_wired_prop + 1), /* 4 */ - NMC_META_GENERIC_WITH_NESTED ("WIMAX-PROPERTIES", nmc_fields_dev_show_wimax_prop + 1), /* 5 */ + NMC_META_GENERIC_WITH_NESTED ("WIRED-PROPERTIES", metagen_device_detail_wired_properties), /* 4 */ + NMC_META_GENERIC_WITH_NESTED ("WIMAX-PROPERTIES", metagen_device_detail_wimax_properties), /* 5 */ NMC_META_GENERIC_WITH_NESTED ("NSP", nmc_fields_dev_wimax_list + 1), /* 6 */ NMC_META_GENERIC_WITH_NESTED ("IP4", metagen_ip4_config), /* 7 */ - NMC_META_GENERIC_WITH_NESTED ("DHCP4", nmc_fields_dhcp_config + 1), /* 8 */ - NMC_META_GENERIC_WITH_NESTED ("IP6", nmc_fields_ip6_config + 1), /* 9 */ - NMC_META_GENERIC_WITH_NESTED ("DHCP6", nmc_fields_dhcp_config + 1), /* 10 */ + NMC_META_GENERIC_WITH_NESTED ("DHCP4", metagen_dhcp_config), /* 8 */ + NMC_META_GENERIC_WITH_NESTED ("IP6", metagen_ip6_config), /* 9 */ + NMC_META_GENERIC_WITH_NESTED ("DHCP6", metagen_dhcp_config), /* 10 */ NMC_META_GENERIC_WITH_NESTED ("BOND", nmc_fields_dev_show_master_prop + 1), /* 11 */ NMC_META_GENERIC_WITH_NESTED ("TEAM", nmc_fields_dev_show_team_prop + 1), /* 12 */ NMC_META_GENERIC_WITH_NESTED ("BRIDGE", nmc_fields_dev_show_master_prop + 1), /* 13 */ NMC_META_GENERIC_WITH_NESTED ("VLAN", nmc_fields_dev_show_vlan_prop + 1), /* 14 */ NMC_META_GENERIC_WITH_NESTED ("BLUETOOTH", nmc_fields_dev_show_bluetooth + 1), /* 15 */ - NMC_META_GENERIC_WITH_NESTED ("CONNECTIONS", nmc_fields_dev_show_connections + 1), /* 16 */ + NMC_META_GENERIC_WITH_NESTED ("CONNECTIONS", metagen_device_detail_connections), /* 16 */ NULL, }; #define NMC_FIELDS_DEV_SHOW_SECTIONS_COMMON "GENERAL.DEVICE,GENERAL.TYPE,GENERAL.HWADDR,GENERAL.MTU,GENERAL.STATE,"\ @@ -707,63 +1126,6 @@ sort_access_points (const GPtrArray *aps) return sorted; } -static NMMetaColor -wifi_signal_to_color (guint8 strength) -{ - if (strength > 80) - return NM_META_COLOR_WIFI_SIGNAL_EXCELLENT; - else if (strength > 55) - return NM_META_COLOR_WIFI_SIGNAL_GOOD; - else if (strength > 30) - return NM_META_COLOR_WIFI_SIGNAL_FAIR; - else if (strength > 5) - return NM_META_COLOR_WIFI_SIGNAL_POOR; - else - return NM_META_COLOR_WIFI_SIGNAL_UNKNOWN; -} - -static char * -ap_wpa_rsn_flags_to_string (NM80211ApSecurityFlags flags) -{ - char *flags_str[16]; /* Enough space for flags and terminating NULL */ - char *ret_str; - int i = 0; - - if (flags & NM_802_11_AP_SEC_PAIR_WEP40) - flags_str[i++] = g_strdup ("pair_wpe40"); - if (flags & NM_802_11_AP_SEC_PAIR_WEP104) - flags_str[i++] = g_strdup ("pair_wpe104"); - if (flags & NM_802_11_AP_SEC_PAIR_TKIP) - flags_str[i++] = g_strdup ("pair_tkip"); - if (flags & NM_802_11_AP_SEC_PAIR_CCMP) - flags_str[i++] = g_strdup ("pair_ccmp"); - if (flags & NM_802_11_AP_SEC_GROUP_WEP40) - flags_str[i++] = g_strdup ("group_wpe40"); - if (flags & NM_802_11_AP_SEC_GROUP_WEP104) - flags_str[i++] = g_strdup ("group_wpe104"); - if (flags & NM_802_11_AP_SEC_GROUP_TKIP) - flags_str[i++] = g_strdup ("group_tkip"); - if (flags & NM_802_11_AP_SEC_GROUP_CCMP) - flags_str[i++] = g_strdup ("group_ccmp"); - if (flags & NM_802_11_AP_SEC_KEY_MGMT_PSK) - flags_str[i++] = g_strdup ("psk"); - if (flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) - flags_str[i++] = g_strdup ("802.1X"); - - if (i == 0) - flags_str[i++] = g_strdup (_("(none)")); - - flags_str[i] = NULL; - - ret_str = g_strjoinv (" ", flags_str); - - i = 0; - while (flags_str[i]) - g_free (flags_str[i++]); - - return ret_str; -} - typedef struct { NmCli *nmc; int index; @@ -923,18 +1285,6 @@ construct_header_name (const char *base, const char *spec) return g_strdup_printf ("%s (%s)", base, spec); } -static const char * -get_active_connection_id (NMDevice *device) -{ - NMActiveConnection *ac; - - ac = nm_device_get_active_connection (device); - if (!ac) - return NULL; - - return nm_active_connection_get_id (ac); -} - static gboolean print_bond_bridge_info (NMDevice *device, NmCli *nmc, @@ -1061,13 +1411,7 @@ static gboolean show_device_info (NMDevice *device, NmCli *nmc) { GError *error = NULL; - const char *hwaddr = NULL; NMDeviceState state = NM_DEVICE_STATE_UNKNOWN; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - NMDeviceCapabilities caps; - NMActiveConnection *acon; - guint32 speed; - char *speed_str, *state_str, *reason_str, *mtu_str; GArray *sections_array; int k; const char *fields_str = NULL; @@ -1104,12 +1448,12 @@ show_device_info (NMDevice *device, NmCli *nmc) /* Lazy way to retrieve sorted array from 0 to the number of dev fields */ out_indices = parse_output_fields (NULL, - (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_general, + (const NMMetaAbstractInfo *const*) metagen_device_detail_general, FALSE, NULL, NULL); - row = g_new0 (NmcOutputField, G_N_ELEMENTS (nmc_fields_dev_show_general)); - for (i = 0; i < G_N_ELEMENTS (nmc_fields_dev_show_general); i++) - row[i].info = (const NMMetaAbstractInfo *) &nmc_fields_dev_show_general[i]; + row = g_new0 (NmcOutputField, G_N_ELEMENTS (metagen_device_detail_general)); + for (i = 0; i < G_N_ELEMENTS (metagen_device_detail_general); i++) + row[i].info = (const NMMetaAbstractInfo *) &metagen_device_detail_general[i]; print_required_fields (&nmc->nmc_config, NMC_OF_FLAG_MAIN_HEADER_ONLY, out_indices, header_name, @@ -1121,138 +1465,65 @@ show_device_info (NMDevice *device, NmCli *nmc) int section_idx = g_array_index (sections_array, int, k); char *section_fld = (char *) g_ptr_array_index (fields_in_section, k); - if (nmc->nmc_config.print_output != NMC_PRINT_TERSE && !nmc->nmc_config.multiline_output && was_output) + if ( NM_IN_SET (nmc->nmc_config.print_output, NMC_PRINT_NORMAL, NMC_PRINT_PRETTY) + && !nmc->nmc_config.multiline_output + && was_output) g_print ("\n"); /* Print empty line between groups in tabular mode */ was_output = FALSE; state = nm_device_get_state (device); - reason = nm_device_get_state_reason (device); - - /* section GENERAL */ - if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[0]->name)) { - NMC_OUTPUT_DATA_DEFINE_SCOPED (out); - tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_general; - out_indices = parse_output_fields (section_fld, - tmpl, FALSE, NULL, NULL); - arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES); - g_ptr_array_add (out.output_data, arr); - - state_str = g_strdup_printf ("%d (%s)", state, nmc_device_state_to_string (state)); - reason_str = g_strdup_printf ("%d (%s)", reason, nmc_device_reason_to_string (reason)); - hwaddr = nm_device_get_hw_address (device); - mtu_str = g_strdup_printf ("%u", nm_device_get_mtu (device)); - acon = nm_device_get_active_connection (device); - - arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX); - set_val_strc (arr, 0, nmc_fields_dev_show_sections[0]->name); /* "GENERAL"*/ - set_val_strc (arr, 1, nm_device_get_iface (device)); - set_val_strc (arr, 2, nm_device_get_type_description (device)); - set_val_strc (arr, 3, G_OBJECT_TYPE_NAME (device)); - set_val_strc (arr, 4, nm_device_get_vendor (device)); - set_val_strc (arr, 5, nm_device_get_product (device)); - set_val_strc (arr, 6, nm_device_get_driver (device) ? nm_device_get_driver (device) : _("(unknown)")); - set_val_strc (arr, 7, nm_device_get_driver_version (device)); - set_val_strc (arr, 8, nm_device_get_firmware_version (device)); - set_val_strc (arr, 9, hwaddr ?: _("(unknown)")); - set_val_str (arr, 10, mtu_str); - set_val_str (arr, 11, state_str); - set_val_str (arr, 12, reason_str); - set_val_strc (arr, 13, nm_device_get_udi (device)); - set_val_strc (arr, 14, nm_device_get_ip_iface (device)); - set_val_strc (arr, 15, nm_device_is_software (device) ? _("yes") : _("no")); - set_val_strc (arr, 16, nm_device_get_managed (device) ? _("yes") : _("no")); - set_val_strc (arr, 17, nm_device_get_autoconnect (device) ? _("yes") : _("no")); - set_val_strc (arr, 18, nm_device_get_firmware_missing (device) ? _("yes") : _("no")); - set_val_strc (arr, 19, nm_device_get_nm_plugin_missing (device) ? _("yes") : _("no")); - set_val_strc (arr, 20, nm_device_get_physical_port_id (device)); - set_val_strc (arr, 21, get_active_connection_id (device)); - set_val_strc (arr, 22, acon ? nm_active_connection_get_uuid (acon) : NULL); - set_val_strc (arr, 23, acon ? nm_object_get_path (NM_OBJECT (acon)) : NULL); - set_val_strc (arr, 24, nmc_device_metered_to_string (nm_device_get_metered (device))); - g_ptr_array_add (out.output_data, arr); + if (nmc_fields_dev_show_sections[section_idx]->nested == metagen_device_detail_general) { + gs_free char *f = section_fld ? g_strdup_printf ("GENERAL.%s", section_fld) : NULL; - print_data_prepare_width (out.output_data); - print_data (&nmc->nmc_config, out_indices, NULL, 0, &out); + nmc_print (&nmc->nmc_config, + (gpointer[]) { device, NULL }, + NULL, + NULL, + NMC_META_GENERIC_GROUP ("GENERAL", metagen_device_detail_general, N_("NAME")), + f, + NULL); was_output = TRUE; + continue; } - /* section CAPABILITIES */ - if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[1]->name)) { - NMC_OUTPUT_DATA_DEFINE_SCOPED (out); + if (nmc_fields_dev_show_sections[section_idx]->nested == metagen_device_detail_capabilities) { + gs_free char *f = section_fld ? g_strdup_printf ("CAPABILITIES.%s", section_fld) : NULL; - tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_cap; - out_indices = parse_output_fields (section_fld, - tmpl, FALSE, NULL, NULL); - arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES); - g_ptr_array_add (out.output_data, arr); + nmc_print (&nmc->nmc_config, + (gpointer[]) { device, NULL }, + NULL, + NULL, + NMC_META_GENERIC_GROUP ("CAPABILITIES", metagen_device_detail_capabilities, N_("NAME")), + f, + NULL); + was_output = TRUE; + continue; + } - caps = nm_device_get_capabilities (device); - speed = 0; - if (NM_IS_DEVICE_ETHERNET (device)) { - /* Speed in Mb/s */ - speed = nm_device_ethernet_get_speed (NM_DEVICE_ETHERNET (device)); - } else if (NM_IS_DEVICE_WIFI (device)) { - /* Speed in b/s */ - speed = nm_device_wifi_get_bitrate (NM_DEVICE_WIFI (device)); - speed /= 1000; + if (nmc_fields_dev_show_sections[section_idx]->nested == metagen_device_detail_wifi_properties) { + if (NM_IS_DEVICE_WIFI (device)) { + gs_free char *f = section_fld ? g_strdup_printf ("WIFI-PROPERTIES.%s", section_fld) : NULL; + + nmc_print (&nmc->nmc_config, + (gpointer[]) { device, NULL }, + NULL, + NULL, + NMC_META_GENERIC_GROUP ("WIFI-PROPERTIES", metagen_device_detail_wifi_properties, N_("NAME")), + f, + NULL); + was_output = TRUE; } - speed_str = speed ? g_strdup_printf (_("%u Mb/s"), speed) : g_strdup (_("unknown")); - - arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX); - set_val_strc (arr, 0, nmc_fields_dev_show_sections[1]->name); /* "CAPABILITIES" */ - set_val_strc (arr, 1, (caps & NM_DEVICE_CAP_CARRIER_DETECT) ? _("yes") : _("no")); - set_val_str (arr, 2, speed_str); - set_val_strc (arr, 3, (caps & NM_DEVICE_CAP_IS_SOFTWARE) ? _("yes") : _("no")); - set_val_strc (arr, 4, (caps & NM_DEVICE_CAP_SRIOV) ? _("yes") : _("no")); - g_ptr_array_add (out.output_data, arr); - - print_data_prepare_width (out.output_data); - print_data (&nmc->nmc_config, out_indices, NULL, 0, &out); - was_output = TRUE; + continue; } /* Wireless specific information */ if ((NM_IS_DEVICE_WIFI (device))) { - NMDeviceWifiCapabilities wcaps; NMAccessPoint *active_ap = NULL; const char *active_bssid = NULL; GPtrArray *aps; - /* section WIFI-PROPERTIES */ - if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[2]->name)) { - NMC_OUTPUT_DATA_DEFINE_SCOPED (out); - - wcaps = nm_device_wifi_get_capabilities (NM_DEVICE_WIFI (device)); - - tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_wifi_prop; - out_indices = parse_output_fields (section_fld, - tmpl, FALSE, NULL, NULL); - arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES); - g_ptr_array_add (out.output_data, arr); - - arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX); - set_val_strc (arr, 0, nmc_fields_dev_show_sections[2]->name); /* "WIFI-PROPERTIES" */ - set_val_strc (arr, 1, (wcaps & (NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104)) ? - _("yes") : _("no")); - set_val_strc (arr, 2, (wcaps & NM_WIFI_DEVICE_CAP_WPA) ? _("yes") : _("no")); - set_val_strc (arr, 3, (wcaps & NM_WIFI_DEVICE_CAP_RSN) ? _("yes") : _("no")); - set_val_strc (arr, 4, (wcaps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP) ? _("yes") : _("no")); - set_val_strc (arr, 5, (wcaps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP) ? _("yes") : _("no")); - set_val_strc (arr, 6, (wcaps & NM_WIFI_DEVICE_CAP_AP) ? _("yes") : _("no")); - set_val_strc (arr, 7, (wcaps & NM_WIFI_DEVICE_CAP_ADHOC) ? _("yes") : _("no")); - set_val_strc (arr, 8, !(wcaps & NM_WIFI_DEVICE_CAP_FREQ_VALID) ? _("unknown") : - ((wcaps & NM_WIFI_DEVICE_CAP_FREQ_2GHZ) ? _("yes") : _("no"))); - set_val_strc (arr, 9, !(wcaps & NM_WIFI_DEVICE_CAP_FREQ_VALID) ? _("unknown") : - ((wcaps & NM_WIFI_DEVICE_CAP_FREQ_5GHZ) ? _("yes") : _("no"))); - g_ptr_array_add (out.output_data, arr); - - print_data_prepare_width (out.output_data); - print_data (&nmc->nmc_config, out_indices, NULL, 0, &out); - was_output = TRUE; - } - /* section AP */ if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[3]->name)) { NMC_OUTPUT_DATA_DEFINE_SCOPED (out); @@ -1287,28 +1558,22 @@ show_device_info (NMDevice *device, NmCli *nmc) print_data (&nmc->nmc_config, out_indices, NULL, 0, &out); was_output = TRUE; } - } else if (NM_IS_DEVICE_ETHERNET (device)) { - /* WIRED-PROPERTIES */ - if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[4]->name)) { - NMC_OUTPUT_DATA_DEFINE_SCOPED (out); - - tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_wired_prop; - out_indices = parse_output_fields (section_fld, - tmpl, FALSE, NULL, NULL); - arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES); - g_ptr_array_add (out.output_data, arr); - - arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX); - set_val_strc (arr, 0, nmc_fields_dev_show_sections[4]->name); /* "WIRED-PROPERTIES" */ - set_val_strc (arr, 1, (nm_device_ethernet_get_carrier (NM_DEVICE_ETHERNET (device))) ? - _("on") : _("off")); - set_val_arrc (arr, 2, ((const char **) nm_device_ethernet_get_s390_subchannels (NM_DEVICE_ETHERNET (device)))); - g_ptr_array_add (out.output_data, arr); + } - print_data_prepare_width (out.output_data); - print_data (&nmc->nmc_config, out_indices, NULL, 0, &out); + if (nmc_fields_dev_show_sections[section_idx]->nested == metagen_device_detail_wired_properties) { + if ((NM_IS_DEVICE_ETHERNET (device))) { + gs_free char *f = section_fld ? g_strdup_printf ("WIRED-PROPERTIES.%s", section_fld) : NULL; + + nmc_print (&nmc->nmc_config, + (gpointer[]) { device, NULL }, + NULL, + NULL, + NMC_META_GENERIC_GROUP ("WIRED-PROPERTIES", metagen_device_detail_wired_properties, N_("NAME")), + f, + NULL); was_output = TRUE; } + continue; } /* IP configuration info */ @@ -1319,19 +1584,19 @@ show_device_info (NMDevice *device, NmCli *nmc) /* IP4 */ if (cfg4 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[7]->name)) - was_output = print_ip4_config (cfg4, &nmc->nmc_config, section_fld); + was_output = print_ip_config (cfg4, AF_INET, &nmc->nmc_config, section_fld); /* DHCP4 */ if (dhcp4 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[8]->name)) - was_output = print_dhcp_config (dhcp4, &nmc->nmc_config, nmc_fields_dev_show_sections[8]->name, section_fld); + was_output = print_dhcp_config (dhcp4, AF_INET, &nmc->nmc_config, section_fld); /* IP6 */ if (cfg6 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[9]->name)) - was_output = print_ip6_config (cfg6, &nmc->nmc_config, nmc_fields_dev_show_sections[9]->name, section_fld); + was_output = print_ip_config (cfg6, AF_INET6, &nmc->nmc_config, section_fld); /* DHCP6 */ if (dhcp6 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[10]->name)) - was_output = print_dhcp_config (dhcp6, &nmc->nmc_config, nmc_fields_dev_show_sections[10]->name, section_fld); + was_output = print_dhcp_config (dhcp6, AF_INET6, &nmc->nmc_config, section_fld); /* Bond specific information */ if (NM_IS_DEVICE_BOND (device)) { @@ -1398,55 +1663,18 @@ show_device_info (NMDevice *device, NmCli *nmc) } } - /* section CONNECTIONS */ - if (!strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[16]->name)) { - const GPtrArray *avail_cons; - GString *ac_paths_str; - char **ac_arr = NULL; - int i; - NMC_OUTPUT_DATA_DEFINE_SCOPED (out); - - tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_show_connections; - out_indices = parse_output_fields (section_fld, - tmpl, FALSE, NULL, NULL); - arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES); - g_ptr_array_add (out.output_data, arr); - - /* available-connections */ - avail_cons = nm_device_get_available_connections (device); - ac_paths_str = g_string_new (NULL); - if (avail_cons->len) { - ac_arr = g_new (char *, avail_cons->len + 1); - ac_arr[avail_cons->len] = NULL; - } - for (i = 0; i < avail_cons->len; i++) { - NMRemoteConnection *avail_con = g_ptr_array_index (avail_cons, i); - const char *ac_path = nm_connection_get_path (NM_CONNECTION (avail_con)); - const char *ac_id = nm_connection_get_id (NM_CONNECTION (avail_con)); - const char *ac_uuid = nm_connection_get_uuid (NM_CONNECTION (avail_con)); - - ac_arr[i] = g_strdup_printf ("%s | %s", ac_uuid, ac_id); - - if (i == 0) - g_string_printf (ac_paths_str, "%s/{", NM_DBUS_PATH_SETTINGS); - else - g_string_append_c (ac_paths_str, ','); - g_string_append (ac_paths_str, strrchr (ac_path, '/') + 1); - } - if (ac_paths_str->len > 0) - g_string_append_c (ac_paths_str, '}'); - - arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX); - set_val_strc (arr, 0, nmc_fields_dev_show_sections[16]->name); /* "CONNECTIONS" */ - set_val_str (arr, 1, ac_paths_str->str); - set_val_arr (arr, 2, (ac_arr)); - g_ptr_array_add (out.output_data, arr); - - print_data_prepare_width (out.output_data); - print_data (&nmc->nmc_config, out_indices, NULL, 0, &out); + if (nmc_fields_dev_show_sections[section_idx]->nested == metagen_device_detail_connections) { + gs_free char *f = section_fld ? g_strdup_printf ("CONNECTIONS.%s", section_fld) : NULL; - g_string_free (ac_paths_str, FALSE); + nmc_print (&nmc->nmc_config, + (gpointer[]) { device, NULL }, + NULL, + NULL, + NMC_META_GENERIC_GROUP ("CONNECTIONS", metagen_device_detail_connections, N_("NAME")), + f, + NULL); was_output = TRUE; + continue; } } @@ -1473,47 +1701,15 @@ nmc_device_state_to_color (NMDeviceState state) return NM_META_COLOR_DEVICE_UNKNOWN; } -static void -fill_output_device_status (NMDevice *device, GPtrArray *output_data) -{ - NMActiveConnection *ac; - NMDeviceState state; - NMMetaColor color; - NmcOutputField *arr = nmc_dup_fields_array ((const NMMetaAbstractInfo *const*) nmc_fields_dev_status, - 0); - - state = nm_device_get_state (device); - ac = nm_device_get_active_connection (device); - - /* Show devices in color */ - color = nmc_device_state_to_color (state); - set_val_color_all (arr, color); - - set_val_strc (arr, 0, nm_device_get_iface (device)); - set_val_strc (arr, 1, nm_device_get_type_description (device)); - set_val_strc (arr, 2, nmc_device_state_to_string (state)); - set_val_strc (arr, 3, nm_object_get_path (NM_OBJECT (device))); - set_val_strc (arr, 4, get_active_connection_id (device)); - set_val_strc (arr, 5, ac ? nm_active_connection_get_uuid (ac) : NULL); - set_val_strc (arr, 6, ac ? nm_object_get_path (NM_OBJECT (ac)) : NULL); - - g_ptr_array_add (output_data, arr); -} - static NMCResultCode do_devices_status (NmCli *nmc, int argc, char **argv) { GError *error = NULL; - NMDevice **devices; - int i; + gs_free NMDevice **devices = NULL; const char *fields_str = NULL; - const NMMetaAbstractInfo *const*tmpl; - NmcOutputField *arr; - NMC_OUTPUT_DATA_DEFINE_SCOPED (out); next_arg (nmc, &argc, &argv, NULL); - /* Nothing to complete */ if (nmc->complete) return nmc->return_value; @@ -1523,33 +1719,25 @@ do_devices_status (NmCli *nmc, int argc, char **argv) } if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0) - fields_str = NMC_FIELDS_DEV_STATUS_COMMON; + fields_str = "DEVICE,TYPE,STATE,CONNECTION"; else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0) { } else fields_str = nmc->required_fields; - tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_status; - out_indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, &error); + devices = nmc_get_devices_sorted (nmc->client); - if (error) { + if (!nmc_print (&nmc->nmc_config, + (gpointer *) devices, + NULL, + N_("Status of devices"), + (const NMMetaAbstractInfo *const*) metagen_device_status, + fields_str, + &error)) { g_string_printf (nmc->return_text, _("Error: 'device status': %s"), error->message); g_error_free (error); return NMC_RESULT_ERROR_USER_INPUT; } - /* Add headers */ - arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES); - g_ptr_array_add (out.output_data, arr); - - devices = nmc_get_devices_sorted (nmc->client); - for (i = 0; devices[i]; i++) - fill_output_device_status (devices[i], out.output_data); - - print_data_prepare_width (out.output_data); - print_data (&nmc->nmc_config, out_indices, _("Status of devices"), 0, &out); - - g_free (devices); - return NMC_RESULT_SUCCESS; } @@ -1619,7 +1807,7 @@ progress_cb (gpointer user_data) { NMDevice *device = (NMDevice *) user_data; - nmc_terminal_show_progress (device ? nmc_device_state_to_string (nm_device_get_state (device)) : ""); + nmc_terminal_show_progress (device ? gettext (nmc_device_state_to_string (nm_device_get_state (device))) : ""); return TRUE; } @@ -1664,7 +1852,7 @@ connected_state_cb (NMDevice *device, NMActiveConnection *active) || state >= NM_DEVICE_STATE_DEACTIVATING) { reason = nm_device_get_state_reason (device); g_print (_("Error: Connection activation failed: (%d) %s.\n"), - reason, nmc_device_reason_to_string (reason)); + reason, gettext (nmc_device_reason_to_string (reason))); } else return; @@ -2404,7 +2592,7 @@ device_state (NMDevice *device, GParamSpec *pspec, NmCli *nmc) color = nmc_device_state_to_color (state); str = nmc_colorize (&nmc->nmc_config, color, "%s: %s\n", nm_device_get_iface (device), - nmc_device_state_to_string (state)); + gettext (nmc_device_state_to_string (state))); g_print ("%s", str); g_free (str); @@ -3354,7 +3542,7 @@ generate_wpa_key (char *key, size_t len) while (!g_ascii_isalnum (c)) c = g_random_int_range (33, 126); - key[i] = (gchar) c; + key[i] = (char) c; } key[WPA_PASSKEY_SIZE] = '\0'; } diff --git a/clients/cli/devices.h b/clients/cli/devices.h index c78680da..7a05b50b 100644 --- a/clients/cli/devices.h +++ b/clients/cli/devices.h @@ -34,13 +34,13 @@ NMDevice ** nmc_get_devices_sorted (NMClient *client); NMMetaColor nmc_device_state_to_color (NMDeviceState state); -extern const NmcMetaGenericInfo *const nmc_fields_dev_status[]; -extern const NmcMetaGenericInfo *const nmc_fields_dev_show_general[]; -extern const NmcMetaGenericInfo *const nmc_fields_dev_show_connections[]; -extern const NmcMetaGenericInfo *const nmc_fields_dev_show_cap[]; -extern const NmcMetaGenericInfo *const nmc_fields_dev_show_wired_prop[]; -extern const NmcMetaGenericInfo *const nmc_fields_dev_show_wifi_prop[]; -extern const NmcMetaGenericInfo *const nmc_fields_dev_show_wimax_prop[]; +extern const NmcMetaGenericInfo *const metagen_device_status[]; +extern const NmcMetaGenericInfo *const metagen_device_detail_general[]; +extern const NmcMetaGenericInfo *const metagen_device_detail_connections[]; +extern const NmcMetaGenericInfo *const metagen_device_detail_capabilities[]; +extern const NmcMetaGenericInfo *const metagen_device_detail_wired_properties[]; +extern const NmcMetaGenericInfo *const metagen_device_detail_wifi_properties[]; +extern const NmcMetaGenericInfo *const metagen_device_detail_wimax_properties[]; extern const NmcMetaGenericInfo *const nmc_fields_dev_wifi_list[]; extern const NmcMetaGenericInfo *const nmc_fields_dev_wimax_list[]; extern const NmcMetaGenericInfo *const nmc_fields_dev_show_master_prop[]; diff --git a/clients/cli/general.c b/clients/cli/general.c index de743970..cb87c110 100644 --- a/clients/cli/general.c +++ b/clients/cli/general.c @@ -508,6 +508,7 @@ show_nm_status (NmCli *nmc, const char *pretty_header_name, const char *print_fl if (!nmc_print (&nmc->nmc_config, (gpointer[]) { nmc, NULL }, + NULL, pretty_header_name ?: N_("NetworkManager status"), (const NMMetaAbstractInfo *const*) metagen_general_status, fields_str, @@ -565,6 +566,7 @@ print_permissions (void *user_data) if (!nmc_print (&nmc->nmc_config, permissions, + NULL, _("NetworkManager permissions"), (const NMMetaAbstractInfo *const*) metagen_general_permissions, fields_str, @@ -657,6 +659,7 @@ show_general_logging (NmCli *nmc) if (!nmc_print (&nmc->nmc_config, (gpointer const []) { &d, NULL }, + NULL, _("NetworkManager logging"), (const NMMetaAbstractInfo *const*) metagen_general_logging, fields_str, @@ -1316,7 +1319,7 @@ do_overview (NmCli *nmc, int argc, char **argv) color = nmc_device_state_to_color (state); tmp = nmc_colorize (&nmc->nmc_config, color, "%s: %s%s%s", nm_device_get_iface (devices[i]), - nmc_device_state_to_string (state), + gettext (nmc_device_state_to_string (state)), ac ? " to " : "", ac ? nm_active_connection_get_id (ac) : ""); g_print ("%s\n", tmp); diff --git a/clients/cli/meson.build b/clients/cli/meson.build index 9449ce63..c5669c96 100644 --- a/clients/cli/meson.build +++ b/clients/cli/meson.build @@ -27,9 +27,7 @@ deps = [ ] cflags = clients_cflags + [ - '-DSYSCONFDIR="@0@"'.format(nm_sysconfdir), '-DG_LOG_DOMAIN="@0@"'.format(name), - '-DNMLOCALEDIR="@0@"'.format(nm_localedir) ] if enable_polkit_agent diff --git a/clients/cli/nmcli.c b/clients/cli/nmcli.c index 6407f50b..bbfc310d 100644 --- a/clients/cli/nmcli.c +++ b/clients/cli/nmcli.c @@ -51,6 +51,42 @@ # define NMCLI_VERSION VERSION #endif +#define DEFAULT_PALETTE_INIT \ + [NM_META_COLOR_CONNECTION_ACTIVATED] = "32", \ + [NM_META_COLOR_CONNECTION_ACTIVATING] = "33", \ + [NM_META_COLOR_CONNECTION_DISCONNECTING] = "31", \ + [NM_META_COLOR_CONNECTION_INVISIBLE] = "2", \ + [NM_META_COLOR_CONNECTIVITY_FULL] = "32", \ + [NM_META_COLOR_CONNECTIVITY_LIMITED] = "33", \ + [NM_META_COLOR_CONNECTIVITY_NONE] = "31", \ + [NM_META_COLOR_CONNECTIVITY_PORTAL] = "33", \ + [NM_META_COLOR_DEVICE_ACTIVATED] = "32", \ + [NM_META_COLOR_DEVICE_ACTIVATING] = "33", \ + [NM_META_COLOR_DEVICE_DISCONNECTED] = "31", \ + [NM_META_COLOR_DEVICE_FIRMWARE_MISSING] = "31", \ + [NM_META_COLOR_DEVICE_PLUGIN_MISSING] = "31", \ + [NM_META_COLOR_DEVICE_UNAVAILABLE] = "2", \ + [NM_META_COLOR_MANAGER_RUNNING] = "32", \ + [NM_META_COLOR_MANAGER_STARTING] = "33", \ + [NM_META_COLOR_MANAGER_STOPPED] = "31", \ + [NM_META_COLOR_PERMISSION_AUTH] = "33", \ + [NM_META_COLOR_PERMISSION_NO] = "31", \ + [NM_META_COLOR_PERMISSION_YES] = "32", \ + [NM_META_COLOR_STATE_ASLEEP] = "31", \ + [NM_META_COLOR_STATE_CONNECTED_GLOBAL] = "32", \ + [NM_META_COLOR_STATE_CONNECTED_LOCAL] = "32", \ + [NM_META_COLOR_STATE_CONNECTED_SITE] = "32", \ + [NM_META_COLOR_STATE_CONNECTING] = "33", \ + [NM_META_COLOR_STATE_DISCONNECTED] = "31", \ + [NM_META_COLOR_STATE_DISCONNECTING] = "33", \ + [NM_META_COLOR_WIFI_SIGNAL_EXCELLENT] = "32", \ + [NM_META_COLOR_WIFI_SIGNAL_FAIR] = "35", \ + [NM_META_COLOR_WIFI_SIGNAL_GOOD] = "33", \ + [NM_META_COLOR_WIFI_SIGNAL_POOR] = "36", \ + [NM_META_COLOR_WIFI_SIGNAL_UNKNOWN] = "2", \ + [NM_META_COLOR_ENABLED] = "32", \ + [NM_META_COLOR_DISABLED] = "31", \ + NmCli nm_cli = { .client = NULL, @@ -74,40 +110,7 @@ NmCli nm_cli = { .nmc_config.show_secrets = FALSE, .nmc_config.in_editor = FALSE, .nmc_config.palette = { - [NM_META_COLOR_CONNECTION_ACTIVATED] = "32", - [NM_META_COLOR_CONNECTION_ACTIVATING] = "33", - [NM_META_COLOR_CONNECTION_DISCONNECTING] = "31", - [NM_META_COLOR_CONNECTION_INVISIBLE] = "2", - [NM_META_COLOR_CONNECTIVITY_FULL] = "32", - [NM_META_COLOR_CONNECTIVITY_LIMITED] = "33", - [NM_META_COLOR_CONNECTIVITY_NONE] = "31", - [NM_META_COLOR_CONNECTIVITY_PORTAL] = "33", - [NM_META_COLOR_DEVICE_ACTIVATED] = "32", - [NM_META_COLOR_DEVICE_ACTIVATING] = "33", - [NM_META_COLOR_DEVICE_DISCONNECTED] = "31", - [NM_META_COLOR_DEVICE_FIRMWARE_MISSING] = "31", - [NM_META_COLOR_DEVICE_PLUGIN_MISSING] = "31", - [NM_META_COLOR_DEVICE_UNAVAILABLE] = "2", - [NM_META_COLOR_MANAGER_RUNNING] = "32", - [NM_META_COLOR_MANAGER_STARTING] = "33", - [NM_META_COLOR_MANAGER_STOPPED] = "31", - [NM_META_COLOR_PERMISSION_AUTH] = "33", - [NM_META_COLOR_PERMISSION_NO] = "31", - [NM_META_COLOR_PERMISSION_YES] = "32", - [NM_META_COLOR_STATE_ASLEEP] = "31", - [NM_META_COLOR_STATE_CONNECTED_GLOBAL] = "32", - [NM_META_COLOR_STATE_CONNECTED_LOCAL] = "32", - [NM_META_COLOR_STATE_CONNECTED_SITE] = "32", - [NM_META_COLOR_STATE_CONNECTING] = "33", - [NM_META_COLOR_STATE_DISCONNECTED] = "31", - [NM_META_COLOR_STATE_DISCONNECTING] = "33", - [NM_META_COLOR_WIFI_SIGNAL_EXCELLENT] = "32", - [NM_META_COLOR_WIFI_SIGNAL_FAIR] = "35", - [NM_META_COLOR_WIFI_SIGNAL_GOOD] = "33", - [NM_META_COLOR_WIFI_SIGNAL_POOR] = "36", - [NM_META_COLOR_WIFI_SIGNAL_UNKNOWN] = "2", - [NM_META_COLOR_ENABLED] = "32", - [NM_META_COLOR_DISABLED] = "31", + DEFAULT_PALETTE_INIT }, .editor_status_line = FALSE, .editor_save_confirmation = TRUE, @@ -186,19 +189,19 @@ complete_fields (const char *option, const char *prefix) h = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, NULL); complete_field (h, metagen_ip4_config); - complete_field (h, nmc_fields_dhcp_config); - complete_field (h, nmc_fields_ip6_config); + complete_field (h, metagen_dhcp_config); + complete_field (h, metagen_ip6_config); complete_field (h, metagen_con_show); complete_field (h, metagen_con_active_general); - complete_field (h, nmc_fields_con_active_details_vpn); + complete_field (h, metagen_con_active_vpn); complete_field (h, nmc_fields_con_active_details_groups); - complete_field (h, nmc_fields_dev_status); - complete_field (h, nmc_fields_dev_show_general); - complete_field (h, nmc_fields_dev_show_connections); - complete_field (h, nmc_fields_dev_show_cap); - complete_field (h, nmc_fields_dev_show_wired_prop); - complete_field (h, nmc_fields_dev_show_wifi_prop); - complete_field (h, nmc_fields_dev_show_wimax_prop); + complete_field (h, metagen_device_status); + complete_field (h, metagen_device_detail_general); + complete_field (h, metagen_device_detail_connections); + complete_field (h, metagen_device_detail_capabilities); + complete_field (h, metagen_device_detail_wired_properties); + complete_field (h, metagen_device_detail_wifi_properties); + complete_field (h, metagen_device_detail_wimax_properties); complete_field (h, nmc_fields_dev_wifi_list); complete_field (h, nmc_fields_dev_wimax_list); complete_field (h, nmc_fields_dev_show_master_prop); @@ -337,76 +340,162 @@ typedef enum { NMC_USE_COLOR_NO, } NmcColorOption; -/* Checks whether a particular terminal-colors.d(5) file (.enabled, .disabled or .schem) - * exists. If contents is non-NULL, it returns the content. */ -static gboolean -check_colors_file (NmCli *nmc, NmcColorOption *color_option, - const char *base_dir, const char *name, const char *term, const char *type, - char **contents) +static char * +check_colors_construct_filename (const char *base_dir, + const char *name, + const char *term, + const char *type) { - char *filename; - gboolean exists; - - filename = g_strdup_printf ("%s/terminal-colors.d/%s%s%s%s%s", - base_dir, - name ? name : "", - term ? "@" : "", term ? term : "", - (name || term) ? "." : "", - type); - if (contents) - exists = g_file_get_contents (filename, contents, NULL, NULL); - else - exists = g_file_test (filename, G_FILE_TEST_EXISTS); - g_free (filename); + return g_strdup_printf ("%s/terminal-colors.d/%s%s%s%s%s", + base_dir, + name ? name : "", + term ? "@" : "", term ? term : "", + (name || term) ? "." : "", + type); +} + +static NmcColorOption +check_colors_check_enabled_one_file (const char *base_dir, + const char *name, + const char *term) +{ + gs_free char *filename_e = NULL; + gs_free char *filename_d = NULL; + + filename_e = check_colors_construct_filename (base_dir, name, term, "enable"); + if (g_file_test (filename_e, G_FILE_TEST_EXISTS)) + return NMC_USE_COLOR_YES; + + filename_d = check_colors_construct_filename (base_dir, name, term, "disable"); + if (g_file_test (filename_d, G_FILE_TEST_EXISTS)) + return NMC_USE_COLOR_NO; - return exists; + return NMC_USE_COLOR_AUTO; } -static void -check_colors_files_for_term (NmCli *nmc, NmcColorOption *color_option, - const char *base_dir, const char *name, const char *term) +static char * +check_colors_check_palette_one_file (const char *base_dir, + const char *name, + const char *term) { - if ( *color_option == NMC_USE_COLOR_AUTO - && check_colors_file (nmc, color_option, base_dir, name, term, "enable", NULL)) { - *color_option = NMC_USE_COLOR_YES; - } + gs_free char *filename = check_colors_construct_filename (base_dir, name, term, "schem"); + char *contents; - if ( *color_option == NMC_USE_COLOR_AUTO - && check_colors_file (nmc, color_option, base_dir, name, term, "disable", NULL)) { - *color_option = NMC_USE_COLOR_NO; - } + if (g_file_get_contents (filename, &contents, NULL, NULL)) + return contents; + return NULL; +} - if (*color_option == NMC_USE_COLOR_NO) { - /* No need to bother any further. */ - return; - } +static gboolean +check_colors_check_enabled (const char *base_dir_1, const char *base_dir_2, const char *name, const char *term) +{ + int i; + + if (term && strchr (term, '/')) + term = NULL; + +#define CHECK_AND_RETURN(cmd) \ + G_STMT_START { \ + NmcColorOption _color_option; \ + \ + _color_option = (cmd); \ + if (_color_option != NMC_USE_COLOR_AUTO) \ + return _color_option == NMC_USE_COLOR_YES; \ + } G_STMT_END + + for (i = 0; i < 2; i++) { + const char *base_dir = (i == 0 ? base_dir_1 : base_dir_2); - if (nmc->palette_buffer == NULL) - check_colors_file (nmc, color_option, base_dir, name, term, "schem", &nmc->palette_buffer); + if (!base_dir) + continue; + if (name && term) + CHECK_AND_RETURN (check_colors_check_enabled_one_file (base_dir, name, term)); + if (name) + CHECK_AND_RETURN (check_colors_check_enabled_one_file (base_dir, name, NULL)); + if (term) + CHECK_AND_RETURN (check_colors_check_enabled_one_file (base_dir, NULL, term)); + if (TRUE) + CHECK_AND_RETURN (check_colors_check_enabled_one_file (base_dir, NULL, NULL)); + } +#undef CHECK_AND_RETURN + return TRUE; } -static void -check_colors_files_for_name (NmCli *nmc, NmcColorOption *color_option, - const char *base_dir, const char *name) +static char * +check_colors_check_palette (const char *base_dir_1, const char *base_dir_2, const char *name, const char *term) { - const gchar *term; + int i; - /* Take a shortcut if the directory is not there. */ - if (!g_file_test (base_dir, G_FILE_TEST_EXISTS)) - return; + if (term && strchr (term, '/')) + term = NULL; - term = g_getenv ("TERM"); - if (term) - check_colors_files_for_term (nmc, color_option, base_dir, name, term); - check_colors_files_for_term (nmc, color_option, base_dir, name, NULL); +#define CHECK_AND_RETURN(cmd) \ + G_STMT_START { \ + char *_palette; \ + \ + _palette = (cmd); \ + if (_palette) \ + return _palette; \ + } G_STMT_END + + for (i = 0; i < 2; i++) { + const char *base_dir = (i == 0 ? base_dir_1 : base_dir_2); + + if (!base_dir) + continue; + if (name && term) + CHECK_AND_RETURN (check_colors_check_palette_one_file (base_dir, name, term)); + if (name) + CHECK_AND_RETURN (check_colors_check_palette_one_file (base_dir, name, NULL)); + if (term) + CHECK_AND_RETURN (check_colors_check_palette_one_file (base_dir, NULL, term)); + if (TRUE) + CHECK_AND_RETURN (check_colors_check_palette_one_file (base_dir, NULL, NULL)); + } +#undef CHECK_AND_RETURN + return NULL; } -static void -check_colors_files_for_base_dir (NmCli *nmc, NmcColorOption *color_option, - const char *base_dir) +static gboolean +check_colors (NmcColorOption color_option, + char **out_palette_str) { - check_colors_files_for_name (nmc, color_option, base_dir, "nmcli"); - check_colors_files_for_name (nmc, color_option, base_dir, NULL); + const char *base_dir_1, *base_dir_2; + const char *const NAME = "nmcli"; + const char *term; + + *out_palette_str = NULL; + + if (!NM_IN_SET (color_option, NMC_USE_COLOR_AUTO, NMC_USE_COLOR_YES)) { + /* nothing to do. Colors are disabled. */ + return FALSE; + } + + term = g_getenv ("TERM"); + + if (color_option == NMC_USE_COLOR_AUTO) { + if ( nm_streq0 (term, "dumb") + || !isatty (STDOUT_FILENO)) + return FALSE; + } + + base_dir_1 = g_get_user_config_dir (); + base_dir_2 = ""SYSCONFDIR; + + if (base_dir_1) { + if ( nm_streq (base_dir_1, base_dir_2) + || !g_file_test (base_dir_1, G_FILE_TEST_EXISTS)) + base_dir_1 = NULL; + } + if (!g_file_test (base_dir_2, G_FILE_TEST_EXISTS)) + base_dir_2 = NULL; + + if ( color_option == NMC_USE_COLOR_AUTO + && !check_colors_check_enabled (base_dir_1, base_dir_2, NAME, term)) + return FALSE; + + *out_palette_str = check_colors_check_palette (base_dir_1, base_dir_2, NAME, term); + return TRUE; } static const char * @@ -415,7 +504,7 @@ resolve_color_alias (const char *color) static const struct { const char *name; const char *alias; - } aliases[] = { + } const aliases[] = { { "reset", "0" }, { "bold", "1" }, { "white", "1;37" }, @@ -455,12 +544,17 @@ resolve_color_alias (const char *color) } static gboolean -parse_color_scheme (NmCli *nmc, GError **error) +parse_color_scheme (char *palette_buffer, + const char **palette /* _NM_META_COLOR_NUM elements */, + GError **error) { - char *p = nmc->palette_buffer; + char *p = palette_buffer; const char *name; const char *color; - const char *map[_NM_META_COLOR_NUM] = { + const char *tmp_palette[_NM_META_COLOR_NUM] = { + DEFAULT_PALETTE_INIT + }; + static const char *const map[_NM_META_COLOR_NUM] = { [NM_META_COLOR_NONE] = NULL, [NM_META_COLOR_CONNECTION_ACTIVATED] = "connection-activated", [NM_META_COLOR_CONNECTION_ACTIVATING] = "connection-activating", @@ -573,7 +667,7 @@ parse_color_scheme (NmCli *nmc, GError **error) /* All good, set the palette entry. */ for (i = NM_META_COLOR_NONE + 1; i < _NM_META_COLOR_NUM; i++) { if (strcmp (map[i], name) == 0) { - nmc->nmc_config_mutable.palette[i] = resolve_color_alias (color); + tmp_palette[i] = resolve_color_alias (color); break; } } @@ -581,38 +675,30 @@ parse_color_scheme (NmCli *nmc, GError **error) g_debug ("Ignoring an unrecognized color: '%s'\n", name); } + memcpy (palette, tmp_palette, sizeof (tmp_palette)); return TRUE; } static void -set_colors (NmCli *nmc, NmcColorOption color_option) +set_colors (NmcColorOption color_option, + bool *out_use_colors, + char **out_palette_buffer, + const char **palette /* _NM_META_COLOR_NUM elements */) { - GError *error = NULL; - - if (color_option == NMC_USE_COLOR_AUTO) { - if ( g_strcmp0 (g_getenv ("TERM"), "dumb") == 0 - || !isatty (STDOUT_FILENO)) - color_option = NMC_USE_COLOR_NO; - } + gs_free char *palette_str = NULL; + gboolean use_colors; - check_colors_files_for_base_dir (nmc, &color_option, g_get_user_config_dir ()); - check_colors_files_for_base_dir (nmc, &color_option, SYSCONFDIR); + use_colors = check_colors (color_option, &palette_str); - switch (color_option) { - case NMC_USE_COLOR_YES: - case NMC_USE_COLOR_AUTO: - nmc->nmc_config_mutable.use_colors = TRUE; - break; - case NMC_USE_COLOR_NO: - nmc->nmc_config_mutable.use_colors = FALSE; - break; - } + *out_use_colors = use_colors; + if (use_colors && palette_str) { + GError *error = NULL; - if (nmc->nmc_config_mutable.use_colors && nmc->palette_buffer) { - if (!parse_color_scheme (nmc, &error)) { + if (!parse_color_scheme (palette_str, palette, &error)) { g_debug ("Error parsing color scheme: %s", error->message); g_error_free (error); - } + } else + *out_palette_buffer = g_steal_pointer (&palette_str); } } @@ -771,7 +857,10 @@ process_command_line (NmCli *nmc, int argc, char **argv) if (nmc->required_fields) nmc->nmc_config_mutable.overview = FALSE; - set_colors (nmc, colors); + set_colors (colors, + &nmc->nmc_config_mutable.use_colors, + &nmc->palette_buffer, + nmc->nmc_config_mutable.palette); /* Now run the requested command */ nmc_do_cmd (nmc, nmcli_cmds, *argv, argc, argv); diff --git a/clients/cli/nmcli.h b/clients/cli/nmcli.h index bcf1c01b..28616855 100644 --- a/clients/cli/nmcli.h +++ b/clients/cli/nmcli.h @@ -75,7 +75,7 @@ typedef enum { static inline NMMetaAccessorGetType nmc_print_output_to_accessor_get_type (NMCPrintOutput print_output) { - return (print_output != NMC_PRINT_TERSE) + return NM_IN_SET (print_output, NMC_PRINT_NORMAL, NMC_PRINT_PRETTY) ? NM_META_ACCESSOR_GET_TYPE_PRETTY : NM_META_ACCESSOR_GET_TYPE_PARSABLE; } @@ -106,7 +106,7 @@ struct _NmcOutputField { typedef struct _NmcConfig { NMCPrintOutput print_output; /* Output mode */ - gboolean use_colors; /* Whether to use colors for output: option '--color' */ + bool use_colors; /* Whether to use colors for output: option '--color' */ bool multiline_output; /* Multiline output instead of default tabular */ bool escape_values; /* Whether to escape ':' and '\' in terse tabular mode */ bool in_editor; /* Whether running the editor - nmcli con edit' */ diff --git a/clients/cli/settings.c b/clients/cli/settings.c index 01142ba2..2d231e1c 100644 --- a/clients/cli/settings.c +++ b/clients/cli/settings.c @@ -318,7 +318,7 @@ _set_fcn_precheck_connection_secondaries (const char *value, char **iter; gboolean modified = FALSE; - strv0 = nm_utils_strsplit_set (value, " \t,"); + strv0 = nm_utils_strsplit_set (value, " \t,", FALSE); if (!strv0) return TRUE; @@ -662,25 +662,19 @@ nmc_setting_remove_property_option (NMSetting *setting, char ** nmc_setting_get_valid_properties (NMSetting *setting) { - char **valid_props = NULL; - GParamSpec **props, **iter; - guint num; - int i; - - /* Iterate through properties */ - i = 0; - props = g_object_class_list_properties (G_OBJECT_GET_CLASS (G_OBJECT (setting)), &num); - valid_props = g_malloc0 (sizeof (char*) * (num + 1)); - for (iter = props; iter && *iter; iter++) { - const char *key_name = g_param_spec_get_name (*iter); - - /* Add all properties except for "name" that is non-editable */ - if (g_strcmp0 (key_name, "name") != 0) - valid_props[i++] = g_strdup (key_name); - } - valid_props[i] = NULL; - g_free (props); + const NMMetaSettingInfoEditor *setting_info; + char **valid_props; + guint i, num; + + setting_info = nm_meta_setting_info_editor_find_by_setting (setting); + num = setting_info ? setting_info->properties_num : 0; + + valid_props = g_new (char *, num + 1); + for (i = 0; i < num; i++) + valid_props[i] = g_strdup (setting_info->properties[i]->property_name); + + valid_props[num] = NULL; return valid_props; } @@ -814,6 +808,7 @@ setting_details (const NmcConfig *nmc_config, NMSetting *setting, const char *on if (!nmc_print (nmc_config, (gpointer[]) { setting, NULL }, NULL, + NULL, (const NMMetaAbstractInfo *const[]) { (const NMMetaAbstractInfo *) setting_info, NULL }, fields_str, &error)) diff --git a/clients/cli/utils.c b/clients/cli/utils.c index 365a0303..e21c108d 100644 --- a/clients/cli/utils.c +++ b/clients/cli/utils.c @@ -62,7 +62,6 @@ _meta_type_nmc_generic_info_get_nested (const NMMetaAbstractInfo *abstract_info, info = (const NmcMetaGenericInfo *) abstract_info; - *out_to_free = NULL; NM_SET_OUT (out_len, NM_PTRARRAY_LEN (info->nested)); return (const NMMetaAbstractInfo *const*) info->nested; } @@ -72,6 +71,7 @@ _meta_type_nmc_generic_info_get_fcn (const NMMetaAbstractInfo *abstract_info, const NMMetaEnvironment *environment, gpointer environment_user_data, gpointer target, + gpointer target_data, NMMetaAccessorGetType get_type, NMMetaAccessorGetFlags get_flags, NMMetaAccessorGetOutFlags *out_flags, @@ -95,7 +95,9 @@ _meta_type_nmc_generic_info_get_fcn (const NMMetaAbstractInfo *abstract_info, if (info->get_fcn) { return info->get_fcn (environment, environment_user_data, - info, target, + info, + target, + target_data, get_type, get_flags, out_flags, @@ -507,7 +509,7 @@ nmc_string_to_arg_array (const char *line, const char *delim, gboolean unquote, gs_free const char **arr0 = NULL; char **arr; - arr0 = nm_utils_strsplit_set (line ?: "", delim ?: " \t"); + arr0 = nm_utils_strsplit_set (line ?: "", delim ?: " \t", FALSE); if (!arr0) arr = g_new0 (char *, 1); else @@ -651,16 +653,24 @@ nmc_free_output_field_values (NmcOutputField fields_array[]) #define PRINT_DATA_COL_PARENT_NIL (G_MAXUINT) -typedef struct { +typedef struct _PrintDataCol { + union { + const struct _PrintDataCol *parent_col; + + /* while constructing the list of columns in _output_selection_append(), we keep track + * of the parent by index. The reason is, that at that point our columns are still + * tracked in a GArray which is growing (hence, the pointers are changing). + * Later, _output_selection_complete() converts the index into the actual pointer. + */ + guint _parent_idx; + }; const NMMetaSelectionItem *selection_item; - guint parent_idx; guint self_idx; bool is_leaf; } PrintDataCol; static gboolean _output_selection_append (GArray *cols, - const char *fields_prefix, guint parent_idx, const NMMetaSelectionItem *selection_item, GPtrArray *gfree_keeper, @@ -678,7 +688,7 @@ _output_selection_append (GArray *cols, { PrintDataCol col = { .selection_item = selection_item, - .parent_idx = parent_idx, + ._parent_idx = parent_idx, .self_idx = col_idx, .is_leaf = TRUE, }; @@ -724,8 +734,11 @@ _output_selection_append (GArray *cols, for (i = 0; i < selection->num; i++) { si = &selection->items[i]; - if (!_output_selection_append (cols, si->self_selection, col_idx, - si, gfree_keeper, error)) + if (!_output_selection_append (cols, + col_idx, + si, + gfree_keeper, + error)) return FALSE; } @@ -738,6 +751,26 @@ _output_selection_append (GArray *cols, return TRUE; } +static void +_output_selection_complete (GArray *cols) +{ + guint i; + + nm_assert (cols); + nm_assert (g_array_get_element_size (cols) == sizeof (PrintDataCol)); + + for (i = 0; i < cols->len; i++) { + PrintDataCol *col = &g_array_index (cols, PrintDataCol, i); + + if (col->_parent_idx == PRINT_DATA_COL_PARENT_NIL) + col->parent_col = NULL; + else { + nm_assert (col->_parent_idx < i); + col->parent_col = &g_array_index (cols, PrintDataCol, col->_parent_idx); + } + } +} + /*****************************************************************************/ /** @@ -768,7 +801,7 @@ _output_selection_parse (const NMMetaAbstractInfo *const*fields, gs_unref_array GArray *cols = NULL; guint i; - selection = nm_meta_selection_create_parse_list (fields, NULL, fields_str, FALSE, error); + selection = nm_meta_selection_create_parse_list (fields, fields_str, FALSE, error); if (!selection) return FALSE; @@ -786,11 +819,13 @@ _output_selection_parse (const NMMetaAbstractInfo *const*fields, for (i = 0; i < selection->num; i++) { const NMMetaSelectionItem *si = &selection->items[i]; - if (!_output_selection_append (cols, NULL, PRINT_DATA_COL_PARENT_NIL, + if (!_output_selection_append (cols, PRINT_DATA_COL_PARENT_NIL, si, gfree_keeper, error)) return FALSE; } + _output_selection_complete (cols); + *out_cols = g_steal_pointer (&cols); *out_gfree_keeper = g_steal_pointer (&gfree_keeper); return TRUE; @@ -833,7 +868,7 @@ parse_output_fields (const char *fields_str, g_return_val_if_fail (!error || !*error, NULL); g_return_val_if_fail (!out_group_fields || !*out_group_fields, NULL); - selection = nm_meta_selection_create_parse_list (fields_array, NULL, fields_str, TRUE, error); + selection = nm_meta_selection_create_parse_list (fields_array, fields_str, TRUE, error); if (!selection) return NULL; @@ -893,7 +928,11 @@ typedef struct { const PrintDataCol *col; const char *title; bool title_to_free:1; - bool skip:1; + + /* whether the column should be printed. If not %TRUE, + * the column will be skipped. */ + bool to_print:1; + int width; } PrintDataHeaderCell; @@ -929,18 +968,20 @@ _print_data_header_cell_clear (gpointer cell_p) static void _print_data_cell_clear_text (PrintDataCell *cell) { - if (cell->text_to_free) { - switch (cell->text_format) { - case PRINT_DATA_CELL_FORMAT_TYPE_PLAIN: + switch (cell->text_format) { + case PRINT_DATA_CELL_FORMAT_TYPE_PLAIN: + if (cell->text_to_free) g_free ((char *) cell->text.plain); - break; - case PRINT_DATA_CELL_FORMAT_TYPE_STRV: + cell->text.plain = NULL; + break; + case PRINT_DATA_CELL_FORMAT_TYPE_STRV: + if (cell->text_to_free) g_strfreev ((char **) cell->text.strv); - break; - }; - cell->text_to_free = FALSE; - } - memset (&cell->text, 0, sizeof (cell->text)); + cell->text.strv = NULL; + break; + }; + cell->text_format = PRINT_DATA_CELL_FORMAT_TYPE_PLAIN; + cell->text_to_free = FALSE; } static void @@ -954,6 +995,7 @@ _print_data_cell_clear (gpointer cell_p) static void _print_fill (const NmcConfig *nmc_config, gpointer const *targets, + gpointer targets_data, const PrintDataCol *cols, guint cols_len, GArray **out_header_row, @@ -963,11 +1005,9 @@ _print_fill (const NmcConfig *nmc_config, GArray *header_row; guint i_row, i_col; guint targets_len; - gboolean pretty; NMMetaAccessorGetType text_get_type; NMMetaAccessorGetFlags text_get_flags; - pretty = (nmc_config->print_output != NMC_PRINT_TERSE); header_row = g_array_sized_new (FALSE, TRUE, sizeof (PrintDataHeaderCell), cols_len); g_array_set_clear_func (header_row, _print_data_header_cell_clear); @@ -991,16 +1031,19 @@ _print_fill (const NmcConfig *nmc_config, header_cell->col_idx = col_idx; header_cell->col = col; - header_cell->skip = FALSE; + + /* by default, the entire column is skipped. That is the case, + * unless we have a cell (below) which opts-in to be printed. */ + header_cell->to_print = FALSE; header_cell->title = nm_meta_abstract_info_get_name (info, TRUE); if ( nmc_config->multiline_output - && col->parent_idx != PRINT_DATA_COL_PARENT_NIL + && col->parent_col && NM_IN_SET (info->meta_type, &nm_meta_type_property_info, &nmc_meta_type_generic_info)) { header_cell->title = g_strdup_printf ("%s.%s", - nm_meta_abstract_info_get_name (cols[col->parent_idx].selection_item->info, FALSE), + nm_meta_abstract_info_get_name (col->parent_col->selection_item->info, FALSE), header_cell->title); header_cell->title_to_free = TRUE; } @@ -1040,6 +1083,7 @@ _print_fill (const NmcConfig *nmc_config, nmc_meta_environment, nmc_meta_environment_arg, target, + targets_data, text_get_type, text_get_flags, &text_out_flags, @@ -1048,7 +1092,19 @@ _print_fill (const NmcConfig *nmc_config, nm_assert (!to_free || value == to_free); - header_cell->skip = nmc_config->overview && is_default; + if ( is_default + && ( nmc_config->overview + || NM_FLAGS_HAS (text_out_flags, NM_META_ACCESSOR_GET_OUT_FLAGS_HIDE))) { + /* don't mark the entry for display. This is to shorten the output in case + * the property is the default value. But we only do that, if the user + * opts in to this behavior (-overview), or of the property marks itself + * elegible to be hidden. + * + * In general, only new API shall mark itself eligible to be hidden. + * Long established properties cannot, because it would be a change + * in behavior. */ + } else + header_cell->to_print = TRUE; if (NM_FLAGS_HAS (text_out_flags, NM_META_ACCESSOR_GET_OUT_FLAGS_STRV)) { if (nmc_config->multiline_output) { @@ -1072,6 +1128,7 @@ _print_fill (const NmcConfig *nmc_config, nmc_meta_environment, nmc_meta_environment_arg, target, + targets_data, NM_META_ACCESSOR_GET_TYPE_COLOR, NM_META_ACCESSOR_GET_FLAGS_NONE, &color_out_flags, @@ -1079,11 +1136,14 @@ _print_fill (const NmcConfig *nmc_config, NULL)); if (cell->text_format == PRINT_DATA_CELL_FORMAT_TYPE_PLAIN) { - if (pretty && (!cell->text.plain|| !cell->text.plain[0])) { + if ( NM_IN_SET (nmc_config->print_output, NMC_PRINT_NORMAL, NMC_PRINT_PRETTY) + && ( !cell->text.plain + || !cell->text.plain[0])) { _print_data_cell_clear_text (cell); cell->text.plain = "--"; } else if (!cell->text.plain) cell->text.plain = ""; + nm_assert (cell->text_format == PRINT_DATA_CELL_FORMAT_TYPE_PLAIN); } } } @@ -1131,7 +1191,7 @@ _print_skip_column (const NmcConfig *nmc_config, selection_item = header_cell->col->selection_item; info = selection_item->info; - if (header_cell->skip) + if (!header_cell->to_print) return TRUE; if (nmc_config->multiline_output) { @@ -1167,23 +1227,21 @@ _print_do (const NmcConfig *nmc_config, { int width1, width2; int table_width = 0; - gboolean pretty = (nmc_config->print_output == NMC_PRINT_PRETTY); - gboolean terse = (nmc_config->print_output == NMC_PRINT_TERSE); - gboolean multiline = nmc_config->multiline_output; guint i_row, i_col; nm_auto_free_gstring GString *str = NULL; g_assert (col_len); /* Main header */ - if (pretty && header_name_no_l10n) { + if ( nmc_config->print_output == NMC_PRINT_PRETTY + && header_name_no_l10n) { gs_free char *line = NULL; int header_width; const char *header_name = _(header_name_no_l10n); header_width = nmc_string_screen_width (header_name, NULL) + 4; - if (multiline) { + if (nmc_config->multiline_output) { table_width = NM_MAX (header_width, ML_HEADER_WIDTH); line = g_strnfill (ML_HEADER_WIDTH, '='); } else { /* tabular */ @@ -1198,12 +1256,13 @@ _print_do (const NmcConfig *nmc_config, g_print ("%s\n", line); } - str = !multiline + str = !nmc_config->multiline_output ? g_string_sized_new (100) : NULL; /* print the header for the tabular form */ - if (!multiline && !terse) { + if ( NM_IN_SET (nmc_config->print_output, NMC_PRINT_NORMAL, NMC_PRINT_PRETTY) + && !nmc_config->multiline_output) { for (i_col = 0; i_col < col_len; i_col++) { const PrintDataHeaderCell *header_cell = &header_row[i_col]; const char *title; @@ -1226,7 +1285,7 @@ _print_do (const NmcConfig *nmc_config, g_string_truncate (str, 0); /* Print horizontal separator */ - if (pretty) { + if (nmc_config->print_output == NMC_PRINT_PRETTY) { gs_free char *line = NULL; g_print ("%s\n", (line = g_strnfill (table_width, '-'))); @@ -1251,7 +1310,7 @@ _print_do (const NmcConfig *nmc_config, lines_len = 1; break; case PRINT_DATA_CELL_FORMAT_TYPE_STRV: - nm_assert (multiline); + nm_assert (nmc_config->multiline_output); lines = cell->text.strv; lines_len = NM_PTRARRAY_LEN (lines); break; @@ -1262,7 +1321,7 @@ _print_do (const NmcConfig *nmc_config, const char *text; text = colorize_string (nmc_config, cell->color, lines[i_lines], &text_to_free); - if (multiline) { + if (nmc_config->multiline_output) { gs_free char *prefix = NULL; if (cell->text_format == PRINT_DATA_CELL_FORMAT_TYPE_STRV) @@ -1271,10 +1330,15 @@ _print_do (const NmcConfig *nmc_config, prefix = g_strdup_printf ("%s:", cell->header_cell->title); width1 = strlen (prefix); width2 = nmc_string_screen_width (prefix, NULL); - g_print ("%-*s%s\n", (int) (terse ? 0 : ML_VALUE_INDENT+width1-width2), prefix, text); + g_print ("%-*s%s\n", + (int) ( nmc_config->print_output == NMC_PRINT_TERSE + ? 0 + : ML_VALUE_INDENT+width1-width2), + prefix, + text); } else { nm_assert (str); - if (terse) { + if (nmc_config->print_output == NMC_PRINT_TERSE) { if (nmc_config->escape_values) { const char *p = text; while (*p) { @@ -1300,7 +1364,7 @@ _print_do (const NmcConfig *nmc_config, } } - if (!multiline) { + if (!nmc_config->multiline_output) { if (str->len) g_string_truncate (str, str->len-1); /* Chop off last column separator */ g_print ("%s\n", str->str); @@ -1308,8 +1372,8 @@ _print_do (const NmcConfig *nmc_config, g_string_truncate (str, 0); } - if ( pretty - && multiline) { + if ( nmc_config->print_output == NMC_PRINT_PRETTY + && nmc_config->multiline_output) { gs_free char *line = NULL; g_print ("%s\n", (line = g_strnfill (ML_HEADER_WIDTH, '-'))); @@ -1320,6 +1384,7 @@ _print_do (const NmcConfig *nmc_config, gboolean nmc_print (const NmcConfig *nmc_config, gpointer const *targets, + gpointer targets_data, const char *header_name_no_l10n, const NMMetaAbstractInfo *const*fields, const char *fields_str, @@ -1337,6 +1402,7 @@ nmc_print (const NmcConfig *nmc_config, _print_fill (nmc_config, targets, + targets_data, &g_array_index (cols, PrintDataCol, 0), cols->len, &header_row, @@ -1516,8 +1582,6 @@ print_required_fields (const NmcConfig *nmc_config, int table_width = 0; const char *not_set_str; int i; - gboolean terse = (nmc_config->print_output == NMC_PRINT_TERSE); - gboolean pretty = (nmc_config->print_output == NMC_PRINT_PRETTY); gboolean main_header_add = of_flags & NMC_OF_FLAG_MAIN_HEADER_ADD; gboolean main_header_only = of_flags & NMC_OF_FLAG_MAIN_HEADER_ONLY; gboolean field_names = of_flags & NMC_OF_FLAG_FIELD_NAMES; @@ -1527,7 +1591,9 @@ print_required_fields (const NmcConfig *nmc_config, nmc_terminal_spawn_pager (nmc_config); /* --- Main header --- */ - if ((main_header_add || main_header_only) && pretty) { + if ( nmc_config->print_output == NMC_PRINT_PRETTY + && ( main_header_add + || main_header_only)) { gs_free char *line = NULL; int header_width; @@ -1552,11 +1618,13 @@ print_required_fields (const NmcConfig *nmc_config, return; /* No field headers are printed in terse mode nor for multiline output */ - if ((terse || nmc_config->multiline_output) && field_names) + if ( ( nmc_config->print_output == NMC_PRINT_TERSE + || nmc_config->multiline_output) + && field_names) return; /* Don't replace empty strings in terse mode */ - not_set_str = terse ? "" : "--"; + not_set_str = nmc_config->print_output == NMC_PRINT_TERSE ? "" : "--"; if (nmc_config->multiline_output) { for (i = 0; i < indices->len; i++) { @@ -1589,7 +1657,12 @@ print_required_fields (const NmcConfig *nmc_config, j); width1 = strlen (tmp); width2 = nmc_string_screen_width (tmp, NULL); - g_print ("%-*s%s\n", (int) (terse ? 0 : ML_VALUE_INDENT+width1-width2), tmp, print_val); + g_print ("%-*s%s\n", + (int) (nmc_config->print_output == NMC_PRINT_TERSE + ? 0 + : ML_VALUE_INDENT + width1 - width2), + tmp, + print_val); } } else { gs_free char *val_to_free = NULL; @@ -1609,10 +1682,15 @@ print_required_fields (const NmcConfig *nmc_config, nm_meta_abstract_info_get_name (field_values[idx].info, FALSE)); width1 = strlen (tmp); width2 = nmc_string_screen_width (tmp, NULL); - g_print ("%-*s%s\n", (int) (terse ? 0 : ML_VALUE_INDENT+width1-width2), tmp, print_val); + g_print ("%-*s%s\n", + (int) ( nmc_config->print_output == NMC_PRINT_TERSE + ? 0 + : ML_VALUE_INDENT + width1 - width2), + tmp, + print_val); } } - if (pretty) { + if (nmc_config->print_output == NMC_PRINT_PRETTY) { gs_free char *line = NULL; g_print ("%s\n", (line = g_strnfill (ML_HEADER_WIDTH, '-'))); @@ -1635,7 +1713,7 @@ print_required_fields (const NmcConfig *nmc_config, value = get_value_to_print (nmc_config, (NmcOutputField *) field_values+idx, field_names, not_set_str, &val_to_free); - if (terse) { + if (nmc_config->print_output == NMC_PRINT_TERSE) { if (nmc_config->escape_values) { const char *p = value; while (*p) { @@ -1669,7 +1747,8 @@ print_required_fields (const NmcConfig *nmc_config, g_print ("%s\n", str->str); /* Print horizontal separator */ - if (field_names && pretty) { + if ( nmc_config->print_output == NMC_PRINT_PRETTY + && field_names) { gs_free char *line = NULL; g_print ("%s\n", (line = g_strnfill (table_width, '-'))); diff --git a/clients/cli/utils.h b/clients/cli/utils.h index 19694d11..b2a3e5eb 100644 --- a/clients/cli/utils.h +++ b/clients/cli/utils.h @@ -121,6 +121,9 @@ typedef enum { NMC_GENERIC_INFO_TYPE_IP6_CONFIG_DOMAIN, _NMC_GENERIC_INFO_TYPE_IP6_CONFIG_NUM, + NMC_GENERIC_INFO_TYPE_DHCP_CONFIG_OPTION = 0, + _NMC_GENERIC_INFO_TYPE_DHCP_CONFIG_NUM, + NMC_GENERIC_INFO_TYPE_CON_SHOW_NAME = 0, NMC_GENERIC_INFO_TYPE_CON_SHOW_UUID, NMC_GENERIC_INFO_TYPE_CON_SHOW_TYPE, @@ -152,6 +155,74 @@ typedef enum { NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_MASTER_PATH, _NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_NUM, + NMC_GENERIC_INFO_TYPE_CON_VPN_TYPE = 0, + NMC_GENERIC_INFO_TYPE_CON_VPN_USERNAME, + NMC_GENERIC_INFO_TYPE_CON_VPN_GATEWAY, + NMC_GENERIC_INFO_TYPE_CON_VPN_BANNER, + NMC_GENERIC_INFO_TYPE_CON_VPN_VPN_STATE, + NMC_GENERIC_INFO_TYPE_CON_VPN_CFG, + _NMC_GENERIC_INFO_TYPE_CON_ACTIVE_VPN_NUM, + + NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_DEVICE = 0, + NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_TYPE, + NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_STATE, + NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_DBUS_PATH, + NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CONNECTION, + NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CON_UUID, + NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CON_PATH, + _NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_NUM, + + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DEVICE = 0, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_TYPE, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_TYPE, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_VENDOR, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PRODUCT, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DRIVER, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DRIVER_VERSION, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_FIRMWARE_VERSION, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_HWADDR, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_MTU, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_STATE, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_REASON, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_UDI, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IP_IFACE, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IS_SOFTWARE, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_MANAGED, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_AUTOCONNECT, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_FIRMWARE_MISSING, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_PLUGIN_MISSING, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PHYS_PORT_ID, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CONNECTION, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CON_UUID, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CON_PATH, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_METERED, + _NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NUM, + + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_AVAILABLE_CONNECTION_PATHS = 0, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_AVAILABLE_CONNECTIONS, + _NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_NUM, + + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_CARRIER_DETECT = 0, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_SPEED, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_IS_SOFTWARE, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_SRIOV, + _NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_NUM, + + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_CARRIER = 0, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_S390_SUBCHANNELS, + _NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_NUM, + + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WEP = 0, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WPA, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WPA2, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_TKIP, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_CCMP, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_AP, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_ADHOC, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_2GHZ, + NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_5GHZ, + _NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_NUM, + } NmcGenericInfoType; #define NMC_HANDLE_COLOR(color) \ @@ -175,6 +246,7 @@ struct _NmcMetaGenericInfo { gpointer environment_user_data, \ const NmcMetaGenericInfo *info, \ gpointer target, \ + gpointer target_data, \ NMMetaAccessorGetType get_type, \ NMMetaAccessorGetFlags get_flags, \ NMMetaAccessorGetOutFlags *out_flags, \ @@ -220,8 +292,19 @@ nmc_meta_generic_get_bool (gboolean val, NMMetaAccessorGetType get_type) return nmc_meta_generic_get_str_i18n (val ? N_("yes") : N_("no"), get_type); } +static inline const char * +nmc_meta_generic_get_bool_onoff (gboolean val, NMMetaAccessorGetType get_type) +{ + return nmc_meta_generic_get_str_i18n (val ? N_("on") : N_("off"), get_type); +} + +typedef enum { + NMC_META_GENERIC_GET_ENUM_TYPE_PARENTHESES, + NMC_META_GENERIC_GET_ENUM_TYPE_DASH, +} NmcMetaGenericGetEnumType; + static inline char * -nmc_meta_generic_get_enum_with_detail (gint64 enum_val, const char *str_val, NMMetaAccessorGetType get_type) +nmc_meta_generic_get_enum_with_detail (NmcMetaGenericGetEnumType get_enum_type, gint64 enum_val, const char *str_val, NMMetaAccessorGetType get_type) { if (!NM_IN_SET (get_type, NM_META_ACCESSOR_GET_TYPE_PRETTY, NM_META_ACCESSOR_GET_TYPE_PARSABLE)) @@ -232,18 +315,30 @@ nmc_meta_generic_get_enum_with_detail (gint64 enum_val, const char *str_val, NMM return g_strdup_printf ("%lld", (long long) enum_val); } - /* note that this function will always print "$NUM ($NICK)", also in PARSABLE - * mode. That might not be desired, but it's done for certain properties to preserve - * previous behavior. */ - if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) - return g_strdup_printf (_("%lld (%s)"), (long long) enum_val, gettext (str_val)); - return g_strdup_printf ("%lld (%s)", (long long) enum_val, str_val); + switch (get_enum_type) { + case NMC_META_GENERIC_GET_ENUM_TYPE_PARENTHESES: + /* note that this function will always print "$NUM ($NICK)", also in PARSABLE + * mode. That might not be desired, but it's done for certain properties to preserve + * previous behavior. */ + if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) + return g_strdup_printf (_("%lld (%s)"), (long long) enum_val, gettext (str_val)); + return g_strdup_printf ("%lld (%s)", (long long) enum_val, str_val); + case NMC_META_GENERIC_GET_ENUM_TYPE_DASH: + /* note that this function will always print "$NUM ($NICK)", also in PARSABLE + * mode. That might not be desired, but it's done for certain properties to preserve + * previous behavior. */ + if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) + return g_strdup_printf (_("%lld - %s"), (long long) enum_val, gettext (str_val)); + return g_strdup_printf ("%lld - %s", (long long) enum_val, str_val); + } + g_return_val_if_reached (NULL); } /*****************************************************************************/ gboolean nmc_print (const NmcConfig *nmc_config, gpointer const *targets, + gpointer targets_data, const char *header_name_no_l10n, const NMMetaAbstractInfo *const*fields, const char *fields_str, |