diff options
| author | Michael Biebl <biebl@debian.org> | 2018-06-04 00:08:31 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2018-06-04 00:08:31 +0200 |
| commit | 0dd9df69fdbd475c48a0c8d5b0a1882550fe7321 (patch) | |
| tree | 249cf25643b1fe408e10679bb61613bc6540e894 /clients/cli | |
| parent | 2e94a3b93171ab3fb95bf689aab1664d23988809 (diff) | |
| parent | 04bc9e1cd3544445d883ad29ea108c1645c8e7b7 (diff) | |
Update upstream source from tag 'upstream/1.11.4'
Update to upstream version '1.11.4' with Debian dir d0638aa2e32d5bae4e8daa021b9a66b7c4d6647e
Diffstat (limited to 'clients/cli')
| -rw-r--r-- | clients/cli/agent.c | 1 | ||||
| -rw-r--r-- | clients/cli/common.c | 275 | ||||
| -rw-r--r-- | clients/cli/common.h | 14 | ||||
| -rw-r--r-- | clients/cli/connections.c | 1252 | ||||
| -rw-r--r-- | clients/cli/connections.h | 4 | ||||
| -rw-r--r-- | clients/cli/devices.c | 73 | ||||
| -rw-r--r-- | clients/cli/devices.h | 4 | ||||
| -rw-r--r-- | clients/cli/general.c | 118 | ||||
| -rw-r--r-- | clients/cli/meson.build | 3 | ||||
| -rw-r--r-- | clients/cli/nmcli.c | 410 | ||||
| -rw-r--r-- | clients/cli/nmcli.h | 22 | ||||
| -rw-r--r-- | clients/cli/settings.c | 4 | ||||
| -rw-r--r-- | clients/cli/utils.c | 203 | ||||
| -rw-r--r-- | clients/cli/utils.h | 85 |
14 files changed, 1286 insertions, 1182 deletions
diff --git a/clients/cli/agent.c b/clients/cli/agent.c index 46725c94..bbfe47fb 100644 --- a/clients/cli/agent.c +++ b/clients/cli/agent.c @@ -136,7 +136,6 @@ secrets_requested (NMSecretAgentSimple *agent, nm_secret_agent_simple_response (agent, request_id, NULL); } - static NMCResultCode do_agent_secret (NmCli *nmc, int argc, char **argv) { diff --git a/clients/cli/common.c b/clients/cli/common.c index 81a3183d..e566de47 100644 --- a/clients/cli/common.c +++ b/clients/cli/common.c @@ -16,7 +16,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2012 - 2017 Red Hat, Inc. + * Copyright 2012 - 2018 Red Hat, Inc. */ #include "nm-default.h" @@ -100,15 +100,7 @@ _ip_config_get_routes (NMIPConfig *cfg) } static gconstpointer -_metagen_ip4_config_get_fcn (const NMMetaEnvironment *environment, - gpointer environment_user_data, - const NmcMetaGenericInfo *info, - gpointer target, - NMMetaAccessorGetType get_type, - NMMetaAccessorGetFlags get_flags, - NMMetaAccessorGetOutFlags *out_flags, - gboolean *out_is_default, - gpointer *out_to_free) +_metagen_ip4_config_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS) { NMIPConfig *cfg4 = target; GPtrArray *ptr_array; @@ -119,7 +111,7 @@ _metagen_ip4_config_get_fcn (const NMMetaEnvironment *environment, nm_assert (info->info_type < _NMC_GENERIC_INFO_TYPE_IP4_CONFIG_NUM); - NMC_HANDLE_TERMFORMAT (NM_META_TERM_COLOR_NORMAL); + NMC_HANDLE_COLOR (NM_META_COLOR_NONE); NM_SET_OUT (out_is_default, TRUE); switch (info->info_type) { @@ -183,15 +175,7 @@ arr_out: } static gconstpointer -_metagen_ip6_config_get_fcn (const NMMetaEnvironment *environment, - gpointer environment_user_data, - const NmcMetaGenericInfo *info, - gpointer target, - NMMetaAccessorGetType get_type, - NMMetaAccessorGetFlags get_flags, - NMMetaAccessorGetOutFlags *out_flags, - gboolean *out_is_default, - gpointer *out_to_free) +_metagen_ip6_config_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS) { NMIPConfig *cfg6 = target; GPtrArray *ptr_array; @@ -202,7 +186,7 @@ _metagen_ip6_config_get_fcn (const NMMetaEnvironment *environment, nm_assert (info->info_type < _NMC_GENERIC_INFO_TYPE_IP6_CONFIG_NUM); - NMC_HANDLE_TERMFORMAT (NM_META_TERM_COLOR_NORMAL); + NMC_HANDLE_COLOR (NM_META_COLOR_NONE); NM_SET_OUT (out_is_default, TRUE); switch (info->info_type) { @@ -271,11 +255,6 @@ const NmcMetaGenericInfo *const metagen_ip4_config[_NMC_GENERIC_INFO_TYPE_IP4_CO _METAGEN_IP4_CONFIG (NMC_GENERIC_INFO_TYPE_IP4_CONFIG_WINS, "WINS"), }; -static const NmcMetaGenericInfo *const metagen_ip4_config_group[] = { - NMC_META_GENERIC_WITH_NESTED ("IP4", metagen_ip4_config, .name_header = N_("GROUP")), - NULL, -}; - 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) @@ -286,14 +265,9 @@ const NmcMetaGenericInfo *const metagen_ip6_config[_NMC_GENERIC_INFO_TYPE_IP6_CO _METAGEN_IP6_CONFIG (NMC_GENERIC_INFO_TYPE_IP6_CONFIG_DOMAIN, "DOMAIN"), }; -static const NmcMetaGenericInfo *const metagen_ip6_config_group[] = { - NMC_META_GENERIC_WITH_NESTED ("IP6", metagen_ip6_config, .name_header = N_("GROUP")), - NULL, -}; - /*****************************************************************************/ -const NmcMetaGenericInfo *const nmc_fields_dhcp4_config[] = { +const NmcMetaGenericInfo *const nmc_fields_dhcp_config[] = { NMC_META_GENERIC ("GROUP"), /* 0 */ NMC_META_GENERIC ("OPTION"), /* 1 */ NULL, @@ -309,12 +283,6 @@ const NmcMetaGenericInfo *const nmc_fields_ip6_config[] = { NULL, }; -const NmcMetaGenericInfo *const nmc_fields_dhcp6_config[] = { - NMC_META_GENERIC ("GROUP"), /* 0 */ - NMC_META_GENERIC ("OPTION"), /* 1 */ - NULL, -}; - gboolean print_ip4_config (NMIPConfig *cfg4, const NmcConfig *nmc_config, @@ -332,7 +300,7 @@ print_ip4_config (NMIPConfig *cfg4, if (!nmc_print (nmc_config, (gpointer[]) { cfg4, NULL }, NULL, - (const NMMetaAbstractInfo *const*) metagen_ip4_config_group, + NMC_META_GENERIC_GROUP ("IP4", metagen_ip4_config, N_("GROUP")), field_str, &error)) { return FALSE; @@ -358,7 +326,7 @@ print_ip6_config (NMIPConfig *cfg6, if (!nmc_print (nmc_config, (gpointer[]) { cfg6, NULL }, NULL, - (const NMMetaAbstractInfo *const*) metagen_ip6_config_group, + NMC_META_GENERIC_GROUP ("IP6", metagen_ip6_config, N_("GROUP")), field_str, &error)) { return FALSE; @@ -367,82 +335,37 @@ print_ip6_config (NMIPConfig *cfg6, } gboolean -print_dhcp4_config (NMDhcpConfig *dhcp4, - const NmcConfig *nmc_config, - const char *group_prefix, - const char *one_field) +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 (dhcp4 == NULL) + if (dhcp == NULL) return FALSE; - table = nm_dhcp_config_get_options (dhcp4); + table = nm_dhcp_config_get_options (dhcp); if (table) { - GHashTableIter table_iter; - gpointer key, value; char **options_arr = NULL; - int i = 0; NMC_OUTPUT_DATA_DEFINE_SCOPED (out); + gs_free const char **keys = NULL; + guint i, nkeys; - tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dhcp4_config; + 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); - options_arr = g_new (char *, g_hash_table_size (table) + 1); - g_hash_table_iter_init (&table_iter, table); - while (g_hash_table_iter_next (&table_iter, &key, &value)) - options_arr[i++] = g_strdup_printf ("%s = %s", (char *) key, (char *) value); - 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; -} - -gboolean -print_dhcp6_config (NMDhcpConfig *dhcp6, - const NmcConfig *nmc_config, - const char *group_prefix, - const char *one_field) -{ - GHashTable *table; - const NMMetaAbstractInfo *const*tmpl; - NmcOutputField *arr; - - if (dhcp6 == NULL) - return FALSE; - - table = nm_dhcp_config_get_options (dhcp6); - if (table) { - GHashTableIter table_iter; - gpointer key, value; - char **options_arr = NULL; - int i = 0; - NMC_OUTPUT_DATA_DEFINE_SCOPED (out); - - tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dhcp6_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 *, g_hash_table_size (table) + 1); - g_hash_table_iter_init (&table_iter, table); - while (g_hash_table_iter_next (&table_iter, &key, &value)) - options_arr[i++] = g_strdup_printf ("%s = %s", (char *) key, (char *) value); + 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); @@ -463,8 +386,11 @@ print_dhcp6_config (NMDhcpConfig *dhcp6, * @connections: array of NMConnections to search in * @filter_type: "id", "uuid", "path" or %NULL * @filter_val: connection to find (connection name, UUID or path) - * @start: where to start in @list. The location is updated so that the function - * can be called multiple times (for connections with the same name). + * @out_result: if not NULL, attach all matching connection to this + * list. If necessary, a new array will be allocated. If the array + * already contains a connection, it will not be added a second time. + * All object are referenced by the array. If the function allocates + * a new array, it will set the free function to g_object_unref. * @complete: print possible completions * * Find a connection in @list according to @filter_val. @filter_type determines @@ -479,64 +405,153 @@ NMConnection * nmc_find_connection (const GPtrArray *connections, const char *filter_type, const char *filter_val, - int *start, + GPtrArray **out_result, gboolean complete) { NMConnection *connection; - NMConnection *found = NULL; - int i; - const char *id; - const char *uuid; - const char *path, *path_num; + NMConnection *best_candidate = NULL; + GPtrArray *result = out_result ? *out_result : NULL; + guint i, j; - for (i = start ? *start : 0; i < connections->len; i++) { - connection = NM_CONNECTION (connections->pdata[i]); + nm_assert (connections); + nm_assert (filter_val); - id = nm_connection_get_id (connection); - uuid = nm_connection_get_uuid (connection); - path = nm_connection_get_path (connection); - path_num = path ? strrchr (path, '/') + 1 : NULL; + for (i = 0; i < connections->len; i++) { + const char *v, *v_num; + + connection = NM_CONNECTION (connections->pdata[i]); /* When filter_type is NULL, compare connection ID (filter_val) * against all types. Otherwise, only compare against the specific * type. If 'path' filter type is specified, comparison against * numeric index (in addition to the whole path) is allowed. */ - if (!filter_type || strcmp (filter_type, "id") == 0) { + if (NM_IN_STRSET (filter_type, NULL, "id")) { + v = nm_connection_get_id (connection); if (complete) - nmc_complete_strings (filter_val, id, NULL); - if (strcmp (filter_val, id) == 0) + nmc_complete_strings (filter_val, v, NULL); + if (nm_streq0 (filter_val, v)) goto found; } - if (!filter_type || strcmp (filter_type, "uuid") == 0) { + if (NM_IN_STRSET (filter_type, NULL, "uuid")) { + v = nm_connection_get_uuid (connection); if (complete && (filter_type || *filter_val)) - nmc_complete_strings (filter_val, uuid, NULL); - if (strcmp (filter_val, uuid) == 0) + nmc_complete_strings (filter_val, v, NULL); + if (nm_streq0 (filter_val, v)) goto found; } - if (!filter_type || strcmp (filter_type, "path") == 0) { + if (NM_IN_STRSET (filter_type, NULL, "path")) { + v = nm_connection_get_path (connection); + v_num = nm_utils_dbus_path_get_last_component (v); if (complete && (filter_type || *filter_val)) - nmc_complete_strings (filter_val, path, filter_type ? path_num : NULL, NULL); - if (g_strcmp0 (filter_val, path) == 0 || (filter_type && g_strcmp0 (filter_val, path_num) == 0)) + nmc_complete_strings (filter_val, v, filter_type ? v_num : NULL, NULL); + if ( nm_streq0 (filter_val, v) + || (filter_type && nm_streq0 (filter_val, v_num))) goto found; } continue; found: - if (!start) + if (!out_result) return connection; - if (found) { - *start = i; - return found; + if (!best_candidate) + best_candidate = connection; + if (!result) + result = g_ptr_array_new_with_free_func (g_object_unref); + for (j = 0; j < result->len; j++) { + if (connection == result->pdata[j]) + break; + } + if (j == result->len) + g_ptr_array_add (result, g_object_ref (connection)); + } + + NM_SET_OUT (out_result, result); + return best_candidate; +} + +NMActiveConnection * +nmc_find_active_connection (const GPtrArray *active_cons, + const char *filter_type, + const char *filter_val, + GPtrArray **out_result, + gboolean complete) +{ + guint i, j; + NMActiveConnection *best_candidate = NULL; + GPtrArray *result = out_result ? *out_result : NULL; + + nm_assert (filter_val); + + for (i = 0; i < active_cons->len; i++) { + NMRemoteConnection *con; + NMActiveConnection *candidate = g_ptr_array_index (active_cons, i); + const char *v, *v_num; + + con = nm_active_connection_get_connection (candidate); + + /* When filter_type is NULL, compare connection ID (filter_val) + * against all types. Otherwise, only compare against the specific + * type. If 'path' or 'apath' filter types are specified, comparison + * against numeric index (in addition to the whole path) is allowed. + */ + if (NM_IN_STRSET (filter_type, NULL, "id")) { + v = nm_active_connection_get_id (candidate); + if (complete) + nmc_complete_strings (filter_val, v, NULL); + if (nm_streq0 (filter_val, v)) + goto found; + } + + if (NM_IN_STRSET (filter_type, NULL, "uuid")) { + v = nm_active_connection_get_uuid (candidate); + if (complete && (filter_type || *filter_val)) + nmc_complete_strings (filter_val, v, NULL); + if (nm_streq0 (filter_val, v)) + goto found; + } + + if (NM_IN_STRSET (filter_type, NULL, "path")) { + v = con ? nm_connection_get_path (NM_CONNECTION (con)) : NULL; + v_num = nm_utils_dbus_path_get_last_component (v); + if (complete && (filter_type || *filter_val)) + nmc_complete_strings (filter_val, v, filter_type ? v_num : NULL, NULL); + if ( nm_streq0 (filter_val, v) + || (filter_type && nm_streq0 (filter_val, v_num))) + goto found; + } + + if (NM_IN_STRSET (filter_type, NULL, "apath")) { + v = nm_object_get_path (NM_OBJECT (candidate)); + v_num = nm_utils_dbus_path_get_last_component (v); + if (complete && (filter_type || *filter_val)) + nmc_complete_strings (filter_val, v, filter_type ? v_num : NULL, NULL); + if ( nm_streq0 (filter_val, v) + || (filter_type && nm_streq0 (filter_val, v_num))) + goto found; + } + + continue; + +found: + if (!out_result) + return candidate; + if (!best_candidate) + best_candidate = candidate; + if (!result) + result = g_ptr_array_new_with_free_func (g_object_unref); + for (j = 0; j < result->len; j++) { + if (candidate == result->pdata[j]) + break; } - found = connection; + if (j == result->len) + g_ptr_array_add (result, g_object_ref (candidate)); } - if (start) - *start = 0; - return found; + NM_SET_OUT (out_result, result); + return best_candidate; } static gboolean diff --git a/clients/cli/common.h b/clients/cli/common.h index 354b2a5f..8f4e47c2 100644 --- a/clients/cli/common.h +++ b/clients/cli/common.h @@ -27,15 +27,20 @@ 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_dhcp4_config (NMDhcpConfig *dhcp4, const NmcConfig *nmc_config, const char *group_prefix, const char *one_field); -gboolean print_dhcp6_config (NMDhcpConfig *dhcp6, 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); NMConnection *nmc_find_connection (const GPtrArray *connections, const char *filter_type, const char *filter_val, - int *start, + GPtrArray **out_result, gboolean complete); +NMActiveConnection *nmc_find_active_connection (const GPtrArray *active_cons, + const char *filter_type, + const char *filter_val, + GPtrArray **out_result, + gboolean complete); + void nmc_secrets_requested (NMSecretAgentSimple *agent, const char *request_id, const char *title, @@ -78,8 +83,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_dhcp4_config[]; extern const NmcMetaGenericInfo *const nmc_fields_ip6_config[]; -extern const NmcMetaGenericInfo *const nmc_fields_dhcp6_config[]; +extern const NmcMetaGenericInfo *const nmc_fields_dhcp_config[]; #endif /* NMC_COMMON_H */ diff --git a/clients/cli/connections.c b/clients/cli/connections.c index 705d3c25..a4f129b6 100644 --- a/clients/cli/connections.c +++ b/clients/cli/connections.c @@ -14,7 +14,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2010 - 2017 Red Hat, Inc. + * Copyright 2010 - 2018 Red Hat, Inc. */ #include "nm-default.h" @@ -76,6 +76,82 @@ struct _OptionInfo { /*****************************************************************************/ +NM_UTILS_LOOKUP_STR_DEFINE_STATIC (active_connection_state_to_string, NMActiveConnectionState, + NM_UTILS_LOOKUP_DEFAULT (N_("unknown")), + NM_UTILS_LOOKUP_ITEM (NM_ACTIVE_CONNECTION_STATE_ACTIVATING, N_("activating")), + NM_UTILS_LOOKUP_ITEM (NM_ACTIVE_CONNECTION_STATE_ACTIVATED, N_("activated")), + NM_UTILS_LOOKUP_ITEM (NM_ACTIVE_CONNECTION_STATE_DEACTIVATING, N_("deactivating")), + NM_UTILS_LOOKUP_ITEM (NM_ACTIVE_CONNECTION_STATE_DEACTIVATED, N_("deactivated")), + NM_UTILS_LOOKUP_ITEM_IGNORE (NM_ACTIVE_CONNECTION_STATE_UNKNOWN), +) + +NM_UTILS_LOOKUP_STR_DEFINE_STATIC (vpn_connection_state_to_string, NMVpnConnectionState, + NM_UTILS_LOOKUP_DEFAULT (N_("unknown")), + NM_UTILS_LOOKUP_ITEM (NM_VPN_CONNECTION_STATE_PREPARE, N_("VPN connecting (prepare)")), + NM_UTILS_LOOKUP_ITEM (NM_VPN_CONNECTION_STATE_NEED_AUTH, N_("VPN connecting (need authentication)")), + NM_UTILS_LOOKUP_ITEM (NM_VPN_CONNECTION_STATE_CONNECT, N_("VPN connecting")), + NM_UTILS_LOOKUP_ITEM (NM_VPN_CONNECTION_STATE_IP_CONFIG_GET, N_("VPN connecting (getting IP configuration)")), + NM_UTILS_LOOKUP_ITEM (NM_VPN_CONNECTION_STATE_ACTIVATED, N_("VPN connected")), + NM_UTILS_LOOKUP_ITEM (NM_VPN_CONNECTION_STATE_FAILED, N_("VPN connection failed")), + NM_UTILS_LOOKUP_ITEM (NM_VPN_CONNECTION_STATE_DISCONNECTED, N_("VPN disconnected")), + NM_UTILS_LOOKUP_ITEM_IGNORE (NM_VPN_CONNECTION_STATE_UNKNOWN), +) + +/* Essentially a version of nm_setting_connection_get_connection_type() that + * prefers an alias instead of the settings name when in pretty print mode. + * That is so that we print "wifi" instead of "802-11-wireless" in "nmcli c". */ +static const char * +connection_type_pretty (const char *type, NMCPrintOutput print_output) +{ + const NMMetaSettingInfoEditor *editor; + int i; + + if (print_output == NMC_PRINT_TERSE) + return type; + + for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) { + editor = &nm_meta_setting_infos_editor[i]; + if (strcmp (type, editor->general->setting_name) == 0) { + if (editor->alias) + return editor->alias; + break; + } + } + + return type; +} + +/* Caller has to free the returned string */ +static char * +get_ac_device_string (NMActiveConnection *active) +{ + GString *dev_str; + const GPtrArray *devices; + int i; + + if (!active) + return NULL; + + /* Get devices of the active connection */ + dev_str = g_string_new (NULL); + devices = nm_active_connection_get_devices (active); + for (i = 0; i < devices->len; i++) { + NMDevice *device = g_ptr_array_index (devices, i); + const char *dev_iface = nm_device_get_iface (device); + + if (dev_iface) { + g_string_append (dev_str, dev_iface); + g_string_append_c (dev_str, ','); + } + } + if (dev_str->len > 0) + g_string_truncate (dev_str, dev_str->len - 1); /* Cut off last ',' */ + + return g_string_free (dev_str, FALSE); +} + +/*****************************************************************************/ + const NmcMetaGenericInfo *const nmc_fields_con_show[] = { NMC_META_GENERIC ("NAME"), /* 0 */ NMC_META_GENERIC ("UUID"), /* 1 */ @@ -149,7 +225,6 @@ const NmcMetaGenericInfo *const nmc_fields_con_active_details_general[] = { // 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 */ @@ -164,9 +239,9 @@ const NmcMetaGenericInfo *const nmc_fields_con_active_details_vpn[] = { const NmcMetaGenericInfo *const nmc_fields_con_active_details_groups[] = { NMC_META_GENERIC_WITH_NESTED ("GENERAL", nmc_fields_con_active_details_general + 1), /* 0 */ NMC_META_GENERIC_WITH_NESTED ("IP4", metagen_ip4_config), /* 1 */ - NMC_META_GENERIC_WITH_NESTED ("DHCP4", nmc_fields_dhcp4_config + 1), /* 2 */ + 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_dhcp6_config + 1), /* 4 */ + 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 */ NULL, }; @@ -187,7 +262,10 @@ typedef struct { NMSetting *setting; const char *property; } TabCompletionInfo; -static TabCompletionInfo nmc_tab_completion = {NULL, NULL, NULL, NULL}; + +static TabCompletionInfo nmc_tab_completion; + +/*****************************************************************************/ static void usage (void) @@ -517,97 +595,38 @@ construct_header_name (const char *base, const char *spec) return g_strdup_printf ("%s (%s)", base, spec); } -static const char * -active_connection_state_to_string (NMActiveConnectionState state) -{ - switch (state) { - case NM_ACTIVE_CONNECTION_STATE_ACTIVATING: - return _("activating"); - case NM_ACTIVE_CONNECTION_STATE_ACTIVATED: - return _("activated"); - case NM_ACTIVE_CONNECTION_STATE_DEACTIVATING: - return _("deactivating"); - case NM_ACTIVE_CONNECTION_STATE_DEACTIVATED: - return _("deactivated"); - case NM_ACTIVE_CONNECTION_STATE_UNKNOWN: - default: - return _("unknown"); - } -} - -static const char * -vpn_connection_state_to_string (NMVpnConnectionState state) -{ - switch (state) { - case NM_VPN_CONNECTION_STATE_PREPARE: - return _("VPN connecting (prepare)"); - case NM_VPN_CONNECTION_STATE_NEED_AUTH: - return _("VPN connecting (need authentication)"); - case NM_VPN_CONNECTION_STATE_CONNECT: - return _("VPN connecting"); - case NM_VPN_CONNECTION_STATE_IP_CONFIG_GET: - return _("VPN connecting (getting IP configuration)"); - case NM_VPN_CONNECTION_STATE_ACTIVATED: - return _("VPN connected"); - case NM_VPN_CONNECTION_STATE_FAILED: - return _("VPN connection failed"); - case NM_VPN_CONNECTION_STATE_DISCONNECTED: - return _("VPN disconnected"); - default: - return _("unknown"); - } -} - -/* Caller has to free the returned string */ -static char * -get_ac_device_string (NMActiveConnection *active) -{ - GString *dev_str; - const GPtrArray *devices; - int i; - - if (!active) - return NULL; - - /* Get devices of the active connection */ - dev_str = g_string_new (NULL); - devices = nm_active_connection_get_devices (active); - for (i = 0; i < devices->len; i++) { - NMDevice *device = g_ptr_array_index (devices, i); - const char *dev_iface = nm_device_get_iface (device); - - if (dev_iface) { - g_string_append (dev_str, dev_iface); - g_string_append_c (dev_str, ','); - } - } - if (dev_str->len > 0) - g_string_truncate (dev_str, dev_str->len - 1); /* Cut off last ',' */ - - return g_string_free (dev_str, FALSE); -} - static NMActiveConnection * -get_ac_for_connection (const GPtrArray *active_cons, NMConnection *connection) +get_ac_for_connection (const GPtrArray *active_cons, NMConnection *connection, GPtrArray **out_result) { const char *con_path, *ac_con_path; - int i; - NMActiveConnection *ac = NULL; + guint i; + NMActiveConnection *best_candidate = NULL; + GPtrArray *result = out_result ? *out_result : NULL; - /* Is the connection active? */ con_path = nm_connection_get_path (connection); for (i = 0; i < active_cons->len; i++) { NMActiveConnection *candidate = g_ptr_array_index (active_cons, i); NMRemoteConnection *con; con = nm_active_connection_get_connection (candidate); - ac_con_path = con ? nm_connection_get_path (NM_CONNECTION (con)) : NULL; - if (!g_strcmp0 (ac_con_path, con_path)) { - ac = candidate; - break; + if (NM_CONNECTION (con) != connection) { + /* also compare the D-Bus paths. Why? I don't know. */ + ac_con_path = con ? nm_connection_get_path (NM_CONNECTION (con)) : NULL; + if (!nm_streq0 (ac_con_path, con_path)) + continue; } + + if (!out_result) + return candidate; + if (!best_candidate) + best_candidate = candidate; + if (!result) + result = g_ptr_array_new_with_free_func (g_object_unref); + g_ptr_array_add (result, g_object_ref (candidate)); } - return ac; + + NM_SET_OUT (out_result, result); + return best_candidate; } typedef struct { @@ -735,118 +754,17 @@ nmc_connection_profile_details (NMConnection *connection, NmCli *nmc) return TRUE; } -static NMActiveConnection * -find_active_connection (const GPtrArray *active_cons, - const GPtrArray *cons, - const char *filter_type, - const char *filter_val, - int *idx, - gboolean complete) +NMMetaColor +nmc_active_connection_state_to_color (NMActiveConnectionState state) { - int i; - int start = (idx && *idx > 0) ? *idx : 0; - const char *path, *a_path, *path_num, *a_path_num; - const char *id; - const char *uuid; - NMRemoteConnection *con; - NMActiveConnection *found = NULL; - - for (i = start; i < active_cons->len; i++) { - NMActiveConnection *candidate = g_ptr_array_index (active_cons, i); - - con = nm_active_connection_get_connection (candidate); - - id = nm_active_connection_get_id (candidate); - uuid = nm_active_connection_get_uuid (candidate); - path = con ? nm_connection_get_path (NM_CONNECTION (con)) : NULL; - path_num = path ? strrchr (path, '/') + 1 : NULL; - a_path = nm_object_get_path (NM_OBJECT (candidate)); - a_path_num = a_path ? strrchr (a_path, '/') + 1 : NULL; - - /* When filter_type is NULL, compare connection ID (filter_val) - * against all types. Otherwise, only compare against the specific - * type. If 'path' or 'apath' filter types are specified, comparison - * against numeric index (in addition to the whole path) is allowed. - */ - if (!filter_type || strcmp (filter_type, "id") == 0) { - if (complete) - nmc_complete_strings (filter_val, id, NULL); - if (strcmp (filter_val, id) == 0) - goto found; - } - - if (!filter_type || strcmp (filter_type, "uuid") == 0) { - if (complete && (filter_type || *filter_val)) - nmc_complete_strings (filter_val, uuid, NULL); - if (strcmp (filter_val, uuid) == 0) - goto found; - } - - if (!filter_type || strcmp (filter_type, "path") == 0) { - if (complete && (filter_type || *filter_val)) - nmc_complete_strings (filter_val, path, filter_type ? path_num : NULL, NULL); - if (g_strcmp0 (filter_val, path) == 0 || (filter_type && g_strcmp0 (filter_val, path_num) == 0)) - goto found; - } - - if (!filter_type || strcmp (filter_type, "apath") == 0) { - if (complete && (filter_type || *filter_val)) - nmc_complete_strings (filter_val, a_path, filter_type ? a_path_num : NULL, NULL); - if (g_strcmp0 (filter_val, a_path) == 0 || (filter_type && g_strcmp0 (filter_val, a_path_num) == 0)) - goto found; - } - - continue; -found: - if (!idx) - return candidate; - if (found) { - *idx = i; - return found; - } - found = candidate; - } - - if (idx) - *idx = 0; - return found; -} - -void -nmc_active_connection_state_to_color (NMActiveConnectionState state, NMMetaTermColor *color) -{ - *color = NM_META_TERM_COLOR_NORMAL; - if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING) - *color = NM_META_TERM_COLOR_YELLOW; + return NM_META_COLOR_CONNECTION_ACTIVATING; else if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) - *color = NM_META_TERM_COLOR_GREEN; + return NM_META_COLOR_CONNECTION_ACTIVATED; else if (state > NM_ACTIVE_CONNECTION_STATE_ACTIVATED) - *color = NM_META_TERM_COLOR_RED; -} - -/* Essentially a version of nm_setting_connection_get_connection_type() that - * prefers an alias instead of the settings name when in pretty print mode. - * That is so that we print "wifi" instead of "802-11-wireless" in "nmcli c". */ -static const char * -connection_type_pretty (const char *type, NMCPrintOutput print_output) -{ - const NMMetaSettingInfoEditor *editor; - int i; - - if (print_output == NMC_PRINT_TERSE) - return type; - - for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) { - editor = &nm_meta_setting_infos_editor[i]; - if (strcmp (type, editor->general->setting_name) == 0) { - if (editor->alias) - return editor->alias; - break; - } - } - - return type; + return NM_META_COLOR_CONNECTION_DISCONNECTING; + else + return NM_META_COLOR_CONNECTION_UNKNOWN; } static void @@ -865,19 +783,19 @@ fill_output_connection (NMConnection *connection, NMClient *client, NMCPrintOutp const char *ac_state = NULL; NMActiveConnectionState ac_state_int = NM_ACTIVE_CONNECTION_STATE_UNKNOWN; char *ac_dev = NULL; - NMMetaTermColor color; + NMMetaColor color; s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); - ac = get_ac_for_connection (nm_client_get_active_connections (client), connection); + ac = get_ac_for_connection (nm_client_get_active_connections (client), connection, NULL); if (active_only && !ac) return; if (ac) { ac_path = nm_object_get_path (NM_OBJECT (ac)); ac_state_int = nm_active_connection_get_state (ac); - ac_state = active_connection_state_to_string (ac_state_int); + ac_state = gettext (active_connection_state_to_string (ac_state_int)); ac_dev = get_ac_device_string (ac); } @@ -894,7 +812,7 @@ fill_output_connection (NMConnection *connection, NMClient *client, NMCPrintOutp arr = nmc_dup_fields_array ((const NMMetaAbstractInfo *const*) nmc_fields_con_show, 0); /* Show active connections in color */ - nmc_active_connection_state_to_color (ac_state_int, &color); + color = nmc_active_connection_state_to_color (ac_state_int); set_val_color_all (arr, color); set_val_strc (arr, 0, nm_setting_connection_get_id (s_con)); @@ -945,7 +863,7 @@ fill_output_connection_for_invisible (NMActiveConnection *ac, NMCPrintOutput pri set_val_strc (arr, 12, ac_path); set_val_strc (arr, 13, NULL); - set_val_color_fmt_all (arr, NM_META_TERM_FORMAT_DIM); + set_val_color_all (arr, NM_META_COLOR_CONNECTION_INVISIBLE); g_ptr_array_add (output_data, arr); } @@ -972,7 +890,7 @@ fill_output_active_connection (NMActiveConnection *active, if (con) { con_path = nm_connection_get_path (NM_CONNECTION (con)); s_con = nm_connection_get_setting_connection (NM_CONNECTION (con)); - g_assert (s_con != NULL); + g_assert (s_con); con_zone = nm_setting_connection_get_zone (s_con); } @@ -1093,7 +1011,9 @@ static const gchar * get_vpn_data_item (NMConnection *connection, enum VpnDataItem vpn_data_item) { const char *key; - char *type = get_vpn_connection_type (connection); + gs_free char *type = NULL; + + type = get_vpn_connection_type (connection); switch (vpn_data_item) { case VPN_DATA_ITEM_GATEWAY: @@ -1106,7 +1026,6 @@ get_vpn_data_item (NMConnection *connection, enum VpnDataItem vpn_data_item) key = ""; break; } - g_free (type); return nm_setting_vpn_get_data_item (nm_connection_get_setting_vpn (connection), key); } @@ -1203,7 +1122,7 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc) gboolean b1 = FALSE; NMDhcpConfig *dhcp4 = nm_active_connection_get_dhcp4_config (acon); - b1 = print_dhcp4_config (dhcp4, &nmc->nmc_config, "DHCP4", group_fld); + b1 = print_dhcp_config (dhcp4, &nmc->nmc_config, "DHCP4", group_fld); was_output = was_output || b1; } @@ -1221,7 +1140,7 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc) gboolean b1 = FALSE; NMDhcpConfig *dhcp6 = nm_active_connection_get_dhcp6_config (acon); - b1 = print_dhcp6_config (dhcp6, &nmc->nmc_config, "DHCP6", group_fld); + b1 = print_dhcp_config (dhcp6, &nmc->nmc_config, "DHCP6", group_fld); was_output = was_output || b1; } @@ -1242,7 +1161,7 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc) con = NM_CONNECTION (nm_active_connection_get_connection (acon)); s_con = nm_connection_get_setting_connection (con); - g_assert (s_con != NULL); + g_assert (s_con); tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_con_active_details_vpn; out_indices = parse_output_fields (group_fld, @@ -1270,13 +1189,15 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc) 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, vpn_connection_state_to_string (vpn_state)); + 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 ? username : get_vpn_data_item (con, VPN_DATA_ITEM_USERNAME)); + 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); @@ -1431,34 +1352,34 @@ typedef struct { static int compare_connections (gconstpointer a, gconstpointer b, gpointer user_data) { - NMConnection *ca = *(NMConnection **)a; - NMConnection *cb = *(NMConnection **)b; + NMConnection *ca = *(NMConnection **) a; + NMConnection *cb = *(NMConnection **) b; + const NmcSortInfo *info = user_data; NMActiveConnection *aca, *acb; - NmcSortInfo *info = (NmcSortInfo *) user_data; - GArray *default_order = NULL; - const GArray *order; - NmcSortOrder item; - int cmp = 0, i; + const NmcSortOrder *order_arr; + guint i, order_len; const char *tmp1, *tmp2; unsigned long tmp1_int, tmp2_int; - if (info->order ) - order = info->order; - else { - NmcSortOrder def[] = { NMC_SORT_ACTIVE, NMC_SORT_NAME, NMC_SORT_PATH }; - int num = G_N_ELEMENTS (def); - default_order = g_array_sized_new (FALSE, FALSE, sizeof (NmcSortOrder), num); - g_array_append_vals (default_order, def, num); - order = default_order; + if (info->order) { + order_arr = &g_array_index (info->order, NmcSortOrder, 0); + order_len = info->order->len; + } else { + static const NmcSortOrder def[] = { NMC_SORT_ACTIVE, NMC_SORT_NAME, NMC_SORT_PATH }; + + order_arr = def; + order_len = G_N_ELEMENTS (def); } - for (i = 0; i < order->len; i++) { - item = g_array_index (order, NmcSortOrder, i); + for (i = 0; i < order_len; i++) { + NmcSortOrder item = order_arr[i]; + int cmp = 0; + switch (item) { case NMC_SORT_ACTIVE: case NMC_SORT_ACTIVE_INV: - aca = get_ac_for_connection (nm_client_get_active_connections (info->nmc->client), ca); - acb = get_ac_for_connection (nm_client_get_active_connections (info->nmc->client), cb); + aca = get_ac_for_connection (nm_client_get_active_connections (info->nmc->client), ca, NULL); + acb = get_ac_for_connection (nm_client_get_active_connections (info->nmc->client), cb, NULL); cmp = (aca && !acb) ? -1 : (!aca && acb) ? 1 : 0; if (item == NMC_SORT_ACTIVE_INV) cmp = -(cmp); @@ -1494,12 +1415,10 @@ compare_connections (gconstpointer a, gconstpointer b, gpointer user_data) break; } if (cmp != 0) - goto end; + return cmp; } -end: - if (default_order) - g_array_unref (default_order); - return cmp; + + return 0; } static GPtrArray * @@ -1551,7 +1470,7 @@ get_invisible_active_connections (NmCli *nmc) GPtrArray *invisibles; int a, c; - g_return_val_if_fail (nmc != NULL, NULL); + g_return_val_if_fail (nmc, NULL); invisibles = g_ptr_array_new (); acons = nm_client_get_active_connections (nmc->client); @@ -1638,12 +1557,21 @@ parse_preferred_connection_order (const char *order, GError **error) } static NMConnection * -get_connection (NmCli *nmc, int *argc, char ***argv, int *pos, GError **error) +get_connection (NmCli *nmc, + int *argc, + char ***argv, + const char **out_selector, + const char **out_value, + GPtrArray **out_result, + GError **error) { const GPtrArray *connections; NMConnection *connection = NULL; const char *selector = NULL; + NM_SET_OUT (out_selector, NULL); + NM_SET_OUT (out_value, NULL); + if (*argc == 0) { g_set_error_literal (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, _("No connection specified")); @@ -1667,32 +1595,32 @@ get_connection (NmCli *nmc, int *argc, char ***argv, int *pos, GError **error) } } + NM_SET_OUT (out_selector, selector); + NM_SET_OUT (out_value, **argv); + connections = nm_client_get_connections (nmc->client); - connection = nmc_find_connection (connections, selector, **argv, pos, + connection = nmc_find_connection (connections, selector, **argv, out_result, *argc == 1 && nmc->complete); if (!connection) { g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_NOT_FOUND, _("unknown connection '%s'"), **argv); } - /* If the caller wants multiple results (pos is set) and there are any, - * don't switch to next argument. - */ - if (!pos || !*pos) - next_arg (nmc, argc, argv, NULL); - + next_arg (nmc, argc, argv, NULL); return connection; } static NMCResultCode do_connections_show (NmCli *nmc, int argc, char **argv) { - GError *err = NULL; - char *profile_flds = NULL, *active_flds = NULL; + gs_free_error GError *err = NULL; + gs_free char *profile_flds = NULL; + gs_free char *active_flds = NULL; GPtrArray *invisibles, *sorted_cons; gboolean active_only = FALSE; - GArray *order = NULL; - int i, option; + gs_unref_array GArray *order = NULL; + guint i, j; + int option; /* check connection show options [--active] [--order <order spec>] */ while ((option = next_arg (nmc, &argc, &argv, "--active", "--order", NULL)) > 0) { @@ -1767,7 +1695,6 @@ do_connections_show (NmCli *nmc, int argc, char **argv) gboolean new_line = FALSE; gboolean without_fields = (nmc->required_fields == NULL); const GPtrArray *active_cons = nm_client_get_active_connections (nmc->client); - int pos = 0; /* multiline mode is default for 'connection show <ID>' */ if (!nmc->mode_specified) @@ -1776,8 +1703,8 @@ do_connections_show (NmCli *nmc, int argc, char **argv) /* Split required fields into the settings and active ones. */ if (!split_required_fields_for_con_show (nmc->required_fields, &profile_flds, &active_flds, &err)) goto finish; - g_free (nmc->required_fields); - nmc->required_fields = NULL; + + nm_clear_g_free (&nmc->required_fields); /* Before printing the connections check if we have a "--show-secret" * option after the connection ids */ @@ -1786,10 +1713,7 @@ do_connections_show (NmCli *nmc, int argc, char **argv) char **argv_cp = argv; do { - if ( nm_streq (*argv_cp, "id") - || nm_streq (*argv_cp, "uuid") - || nm_streq (*argv_cp, "path") - || nm_streq (*argv_cp, "apath")) { + if (NM_IN_STRSET (*argv_cp, "id", "uuid", "path", "apath")) { argc_cp--; argv_cp++; } @@ -1800,16 +1724,16 @@ do_connections_show (NmCli *nmc, int argc, char **argv) const GPtrArray *connections; gboolean res; NMConnection *con; - NMActiveConnection *acon = NULL; + gs_unref_object NMActiveConnection *explicit_acon = NULL; const char *selector = NULL; + gs_unref_ptrarray GPtrArray *found_cons = NULL; + gboolean explicit_acon_handled = FALSE; + guint i_found_cons; if (argc == 1 && nmc->complete) nmc_complete_strings (*argv, "id", "uuid", "path", "apath", NULL); - if ( strcmp (*argv, "id") == 0 - || strcmp (*argv, "uuid") == 0 - || strcmp (*argv, "path") == 0 - || strcmp (*argv, "apath") == 0) { + if (NM_IN_STRSET (*argv, "id", "uuid", "path", "apath")) { selector = *argv; argc--; argv++; @@ -1822,17 +1746,26 @@ do_connections_show (NmCli *nmc, int argc, char **argv) /* Try to find connection by id, uuid or path first */ connections = nm_client_get_connections (nmc->client); - con = nmc_find_connection (connections, selector, *argv, &pos, + con = nmc_find_connection (connections, selector, *argv, &found_cons, argc == 1 && nmc->complete); - if (!con && (!selector || strcmp (selector, "apath") == 0)) { + if ( !con + && NM_IN_STRSET (selector, NULL, "apath")) { /* Try apath too */ - acon = find_active_connection (active_cons, connections, "apath", *argv, NULL, - argc == 1 && nmc->complete); - if (acon) - con = NM_CONNECTION (nm_active_connection_get_connection (acon)); + explicit_acon = nmc_find_active_connection (active_cons, "apath", *argv, NULL, + argc == 1 && nmc->complete); + if (explicit_acon) { + if ( !selector + && !nm_streq0 (*argv, nm_object_get_path (NM_OBJECT (explicit_acon)))) { + /* we matched the apath based on the last component alone (note the full D-Bus path). + * That is how nmc_find_active_connection() works, if you pass in a selector. + * Reject it. */ + explicit_acon = NULL; + } + nm_g_object_ref (explicit_acon); + } } - if (!con && !acon) { + if (!con && !explicit_acon) { g_string_printf (nmc->return_text, _("Error: %s - no such connection profile."), *argv); nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND; goto finish; @@ -1844,54 +1777,81 @@ do_connections_show (NmCli *nmc, int argc, char **argv) * may see only the active connection. */ - /* Filter only active connections */ - if (!acon) - acon = get_ac_for_connection (active_cons, con); - if (active_only && !acon) { - next_arg (nmc, &argc, &argv, NULL); - continue; - } - if (nmc->complete) { next_arg (nmc, &argc, &argv, NULL); continue; } - /* Show an empty line between connections */ - if (new_line) - g_print ("\n"); - - /* Show profile configuration */ - if (without_fields || profile_flds) { - if (con) { - nmc->required_fields = profile_flds; - if (nmc->nmc_config.show_secrets) - update_secrets_in_connection (NM_REMOTE_CONNECTION (con), con); - res = nmc_connection_profile_details (con, nmc); - nmc->required_fields = NULL; - if (!res) - goto finish; + explicit_acon_handled = FALSE; + i_found_cons = 0; + for (;;) { + gs_unref_ptrarray GPtrArray *found_acons = NULL; + + if (explicit_acon) { + if (explicit_acon_handled) + break; + explicit_acon_handled = TRUE; + /* the user referenced an "apath". In this case, we can only have at most one connection + * and one apath. */ + con = NM_CONNECTION (nm_active_connection_get_connection (explicit_acon)); + } else { + if (i_found_cons >= found_cons->len) + break; + con = found_cons->pdata[i_found_cons++]; + get_ac_for_connection (active_cons, con, &found_acons); } - } - /* If the profile is active, print also active details */ - if (without_fields || active_flds) { - if (acon) { - nmc->required_fields = active_flds; - res = nmc_active_connection_details (acon, nmc); - nmc->required_fields = NULL; - if (!res) - goto finish; + if (active_only && !explicit_acon && !found_acons) { + /* this connection is not interesting, we only print active ones. */ + continue; + } + + nm_assert (explicit_acon || con); + + if (new_line) + g_print ("\n"); + new_line = TRUE; + + if (without_fields || profile_flds) { + if (con) { + nmc->required_fields = profile_flds; + if (nmc->nmc_config.show_secrets) + update_secrets_in_connection (NM_REMOTE_CONNECTION (con), con); + res = nmc_connection_profile_details (con, nmc); + nmc->required_fields = NULL; + if (!res) + goto finish; + } + } + + if (without_fields || active_flds) { + guint l = explicit_acon ? 1 : (found_acons ? found_acons->len : 0); + + for (j = 0; j < l; j++) { + NMActiveConnection *acon; + + if (j > 0) { + /* if there are multiple active connections, separate them with newline. + * that is a bit odd, because we already separate connections with newlines, + * and commonly don't separate the connection from the first active connection. */ + g_print ("\n"); + } + + if (explicit_acon) + acon = explicit_acon; + else + acon = found_acons->pdata[j]; + + nmc->required_fields = active_flds; + res = nmc_active_connection_details (acon, nmc); + nmc->required_fields = NULL; + if (!res) + goto finish; + } } } - new_line = TRUE; - /* Take next argument. - * But for pos != NULL we have more connections of the same name, - * so process the same argument again. - */ - if (!pos) - next_arg (nmc, &argc, &argv, NULL); + next_arg (nmc, &argc, &argv, NULL); } } @@ -1899,12 +1859,7 @@ finish: if (err) { g_string_printf (nmc->return_text, _("Error: %s."), err->message); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; - g_error_free (err); } - g_free (profile_flds); - g_free (active_flds); - if (order) - g_array_unref (order); return nmc->return_value; } @@ -1917,8 +1872,8 @@ get_default_active_connection (NmCli *nmc, NMDevice **device) const GPtrArray *connections; int i; - g_return_val_if_fail (nmc != NULL, NULL); - g_return_val_if_fail (device != NULL, NULL); + g_return_val_if_fail (nmc, NULL); + g_return_val_if_fail (device, NULL); g_return_val_if_fail (*device == NULL, NULL); connections = nm_client_get_active_connections (nmc->client); @@ -1976,10 +1931,10 @@ find_device_for_connection (NmCli *nmc, const char *con_type; int i, j; - g_return_val_if_fail (nmc != NULL, FALSE); + g_return_val_if_fail (nmc, FALSE); g_return_val_if_fail (iface || ap || nsp, FALSE); - g_return_val_if_fail (device != NULL && *device == NULL, FALSE); - g_return_val_if_fail (spec_object != NULL && *spec_object == NULL, FALSE); + g_return_val_if_fail (device && *device == NULL, FALSE); + g_return_val_if_fail (spec_object && *spec_object == NULL, FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); s_con = nm_connection_get_setting_connection (connection); @@ -2034,8 +1989,10 @@ find_device_for_connection (NmCli *nmc, } found_device = dev; - if (ap && !strcmp (con_type, NM_SETTING_WIRELESS_SETTING_NAME) && NM_IS_DEVICE_WIFI (dev)) { - char *bssid_up = g_ascii_strup (ap, -1); + if ( ap + && nm_streq (con_type, NM_SETTING_WIRELESS_SETTING_NAME) + && NM_IS_DEVICE_WIFI (dev)) { + gs_free char *bssid_up = g_ascii_strup (ap, -1); const GPtrArray *aps = nm_device_wifi_get_access_points (NM_DEVICE_WIFI (dev)); found_device = NULL; /* Mark as not found; set to the device again later, only if AP matches */ @@ -2043,29 +2000,28 @@ find_device_for_connection (NmCli *nmc, NMAccessPoint *candidate_ap = g_ptr_array_index (aps, j); const char *candidate_bssid = nm_access_point_get_bssid (candidate_ap); - if (!strcmp (bssid_up, candidate_bssid)) { + if (nm_streq0 (bssid_up, candidate_bssid)) { found_device = dev; *spec_object = nm_object_get_path (NM_OBJECT (candidate_ap)); break; } } - g_free (bssid_up); } - } - if (found_device) { - *device = found_device; - return TRUE; - } else { - if (iface) + if (!found_device) { + if (iface) { g_set_error (error, NMCLI_ERROR, 0, _("device '%s' not compatible with connection '%s'"), iface, nm_setting_connection_get_id (s_con)); - else + } else { g_set_error (error, NMCLI_ERROR, 0, _("no device found for connection '%s'"), nm_setting_connection_get_id (s_con)); + } return FALSE; } + + *device = found_device; + return TRUE; } } @@ -2348,8 +2304,6 @@ parse_passwords (const char *passwd_file, GError **error) return g_steal_pointer (&pwds_hash); } - - static gboolean nmc_activate_connection (NmCli *nmc, NMConnection *connection, @@ -2368,7 +2322,7 @@ nmc_activate_connection (NmCli *nmc, gboolean device_found; GError *local = NULL; - g_return_val_if_fail (nmc != NULL, FALSE); + g_return_val_if_fail (nmc, FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); if (connection && (ifname || ap || nsp)) { @@ -2468,7 +2422,7 @@ do_connection_up (NmCli *nmc, int argc, char **argv) } if (argc > 0 && strcmp (*argv, "ifname") != 0) { - connection = get_connection (nmc, argc_ptr, argv_ptr, NULL, &error); + connection = get_connection (nmc, argc_ptr, argv_ptr, NULL, NULL, NULL, &error); if (!connection) { g_string_printf (nmc->return_text, _("Error: %s."), error->message); return error->code; @@ -2547,20 +2501,108 @@ do_connection_up (NmCli *nmc, int argc, char **argv) return nmc->return_value; } +/*****************************************************************************/ + typedef struct { NmCli *nmc; - GSList *queue; + /* a list of object that is relevant for the callback. The object + * type differs, and depends on the type of callback. */ + GPtrArray *obj_list; guint timeout_id; GCancellable *cancellable; } ConnectionCbInfo; -static void connection_cb_info_finish (ConnectionCbInfo *info, - gpointer connection); +static void connection_removed_cb (NMClient *client, NMConnection *connection, ConnectionCbInfo *info); + +static void down_active_connection_state_cb (NMActiveConnection *active, + GParamSpec *pspec, + ConnectionCbInfo *info); + +static void +connection_cb_info_obj_list_destroy (ConnectionCbInfo *info, gpointer obj) +{ + nm_assert (info); + nm_assert (info->obj_list); + nm_assert (G_IS_OBJECT (obj)); + + g_signal_handlers_disconnect_by_func (obj, down_active_connection_state_cb, info); + g_object_unref (obj); +} + +static gssize +connection_cb_info_obj_list_idx (ConnectionCbInfo *info, gpointer obj) +{ + guint i; + + nm_assert (info); + nm_assert (info->obj_list); + nm_assert (G_IS_OBJECT (obj)); + + for (i = 0; i < info->obj_list->len; i++) { + if (info->obj_list->pdata[i] == obj) + return i; + } + return -1; +} + +static gpointer +connection_cb_info_obj_list_has (ConnectionCbInfo *info, gpointer obj) +{ + gssize idx; + + idx = connection_cb_info_obj_list_idx (info, obj); + if (idx >= 0) + return info->obj_list->pdata[idx]; + return NULL; +} + +static gpointer +connection_cb_info_obj_list_steal (ConnectionCbInfo *info, gpointer obj) +{ + gssize idx; + + idx = connection_cb_info_obj_list_idx (info, obj); + if (idx >= 0) { + g_ptr_array_remove_index (info->obj_list, idx); + return obj; + } + return NULL; +} + +static void +connection_cb_info_finish (ConnectionCbInfo *info, gpointer obj) +{ + if (obj) { + obj = connection_cb_info_obj_list_steal (info, obj); + if (obj) + connection_cb_info_obj_list_destroy (info, obj); + } else { + while (info->obj_list->len > 0) { + obj = info->obj_list->pdata[info->obj_list->len - 1]; + g_ptr_array_remove_index (info->obj_list, info->obj_list->len); + connection_cb_info_obj_list_destroy (info, obj); + } + } + + if (info->obj_list->len > 0) + return; + + nm_clear_g_source (&info->timeout_id); + nm_clear_g_cancellable (&info->cancellable); + + g_signal_handlers_disconnect_by_func (info->nmc->client, connection_removed_cb, info); + + g_slice_free (ConnectionCbInfo, info); + + quit (); +} + +/*****************************************************************************/ static void connection_removed_cb (NMClient *client, NMConnection *connection, ConnectionCbInfo *info) { - if (!g_slist_find (info->queue, connection)) + if (!connection_cb_info_obj_list_has (info, connection)) return; g_print (_("Connection '%s' (%s) successfully deleted.\n"), nm_connection_get_id (connection), @@ -2597,49 +2639,17 @@ connection_op_timeout_cb (gpointer user_data) return G_SOURCE_REMOVE; } -static void -destroy_queue_element (gpointer data) -{ - g_signal_handlers_disconnect_matched (data, G_SIGNAL_MATCH_FUNC, 0, 0, 0, - down_active_connection_state_cb, NULL); - g_object_unref (data); -} - -static void -connection_cb_info_finish (ConnectionCbInfo *info, gpointer connection) -{ - if (connection) { - info->queue = g_slist_remove (info->queue, connection); - g_object_unref (G_OBJECT (connection)); - } else { - g_slist_free_full (info->queue, destroy_queue_element); - info->queue = NULL; - } - - if (info->queue) - return; - - if (info->timeout_id) - g_source_remove (info->timeout_id); - - nm_clear_g_cancellable (&info->cancellable); - - g_signal_handlers_disconnect_by_func (info->nmc->client, connection_removed_cb, info); - g_slice_free (ConnectionCbInfo, info); - quit (); -} - static NMCResultCode do_connection_down (NmCli *nmc, int argc, char **argv) { NMActiveConnection *active; ConnectionCbInfo *info = NULL; const GPtrArray *active_cons; - GSList *queue = NULL, *iter, *next; - char **arg_arr = NULL; + gs_strfreev char **arg_arr = NULL; char **arg_ptr; int arg_num; - int idx = 0; + guint i; + gs_unref_ptrarray GPtrArray *found_active_cons = NULL; if (nmc->timeout == -1) nmc->timeout = 10; @@ -2660,108 +2670,88 @@ do_connection_down (NmCli *nmc, int argc, char **argv) } if (arg_num == 0) { g_string_printf (nmc->return_text, _("Error: No connection specified.")); - nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; - goto finish; + NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); } } /* Get active connections */ active_cons = nm_client_get_active_connections (nmc->client); while (arg_num > 0) { - const GPtrArray *connections; const char *selector = NULL; if (arg_num == 1 && nmc->complete) nmc_complete_strings (*arg_ptr, "id", "uuid", "path", "apath", NULL); - if ( strcmp (*arg_ptr, "id") == 0 - || strcmp (*arg_ptr, "uuid") == 0 - || strcmp (*arg_ptr, "path") == 0 - || strcmp (*arg_ptr, "apath") == 0) { - + if (NM_IN_STRSET (*arg_ptr, "id", "uuid", "path", "apath")) { selector = *arg_ptr; arg_num--; arg_ptr++; if (!arg_num) { g_string_printf (nmc->return_text, _("Error: %s argument is missing."), selector); - nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; - goto finish; + NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); } } - connections = nm_client_get_connections (nmc->client); - active = find_active_connection (active_cons, connections, selector, *arg_ptr, &idx, - arg_num == 1 && nmc->complete); - if (active) { - /* Check if the connection is unique. */ - /* Calling down for the same connection repeatedly would result in - * NM responding for the last D-Bus call only and we would stall. */ - if (!g_slist_find (queue, active)) - queue = g_slist_prepend (queue, g_object_ref (active)); - } else { + active = nmc_find_active_connection (active_cons, + selector, + *arg_ptr, + &found_active_cons, + arg_num == 1 && nmc->complete); + if (!active) { if (!nmc->complete) g_printerr (_("Error: '%s' is not an active connection.\n"), *arg_ptr); g_string_printf (nmc->return_text, _("Error: not all active connections found.")); nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND; } - if (idx == 0) - next_arg (nmc->ask ? NULL : nmc, &arg_num, &arg_ptr, NULL); + next_arg (nmc->ask ? NULL : nmc, &arg_num, &arg_ptr, NULL); } - if (!queue) { + if (!found_active_cons) { g_string_printf (nmc->return_text, _("Error: no active connection provided.")); - nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND; - goto finish; - } else if (nmc->complete) { - g_slist_free (queue); - goto finish; + NMC_RETURN (nmc, NMC_RESULT_ERROR_NOT_FOUND); } - queue = g_slist_reverse (queue); + nm_assert (found_active_cons->len > 0); + + if (nmc->complete) + return nmc->return_value; if (nmc->timeout > 0) { nmc->should_wait++; info = g_slice_new0 (ConnectionCbInfo); info->nmc = nmc; - info->queue = queue; - info->timeout_id = g_timeout_add_seconds (nmc->timeout, connection_op_timeout_cb, info); - } - - iter = queue; - while (iter) { - GError *error = NULL; - - next = g_slist_next (iter); - active = iter->data; - - if (info) { + info->obj_list = g_ptr_array_sized_new (found_active_cons->len); + for (i = 0; i < found_active_cons->len; i++) { + active = found_active_cons->pdata[i]; + g_ptr_array_add (info->obj_list, g_object_ref (active)); g_signal_connect (active, "notify::" NM_ACTIVE_CONNECTION_STATE, G_CALLBACK (down_active_connection_state_cb), info); } + info->timeout_id = g_timeout_add_seconds (nmc->timeout, connection_op_timeout_cb, info); + } + + for (i = 0; i < found_active_cons->len; i++) { + GError *error = NULL; + + active = found_active_cons->pdata[i]; - /* Now deactivate the connection */ if (!nm_client_deactivate_connection (nmc->client, active, NULL, &error)) { g_print (_("Connection '%s' deactivation failed: %s\n"), nm_active_connection_get_id (active), error->message); - g_error_free (error); + g_clear_error (&error); if (info) { g_signal_handlers_disconnect_by_func (active, down_active_connection_state_cb, info); - /* Remove the active connection from @queue */ connection_cb_info_finish (info, active); } } - - iter = next; } -finish: - g_strfreev (arg_arr); return nmc->return_value; } @@ -3581,6 +3571,7 @@ set_property (NMConnection *connection, */ if (value) { unsigned long idx; + if (nmc_string_to_uint (value, TRUE, 0, G_MAXUINT32, &idx)) nmc_setting_remove_property_option (setting, property_name, NULL, idx, &local); else @@ -4251,7 +4242,7 @@ nmc_read_connection_properties (NmCli *nmc, return FALSE; if (!*argc && nmc->complete) - complete_property (setting, strv[1], value ? value : "", connection); + complete_property (setting, strv[1], value ?: "", connection); if (!set_property (connection, setting_name, strv[1], value, modifier, error)) return FALSE; @@ -4332,7 +4323,7 @@ nmc_read_connection_properties (NmCli *nmc, return FALSE; if (!*argc && nmc->complete) - complete_option (chosen, value ? value : "", connection); + complete_option (chosen, value ?: "", connection); if (!set_option (nmc, connection, chosen, value, error)) return FALSE; @@ -4443,8 +4434,8 @@ nmcli_con_add_tab_completion (const char *text, int start, int end) NMMetaSettingType s; char **match_array = NULL; rl_compentry_func_t *generator_func = NULL; - gs_free char *no = g_strdup_printf ("[%s]: ", gettext ("no")); - gs_free char *yes = g_strdup_printf ("[%s]: ", gettext ("yes")); + gs_free char *no = g_strdup_printf ("[%s]: ", _("no")); + gs_free char *yes = g_strdup_printf ("[%s]: ", _("yes")); /* Disable readline's default filename completion */ rl_attempted_completion_over = 1; @@ -4727,9 +4718,9 @@ again: static NMCResultCode do_connection_add (NmCli *nmc, int argc, char **argv) { - NMConnection *connection = NULL; + gs_unref_object NMConnection *connection = NULL; NMSettingConnection *s_con; - GError *error = NULL; + gs_free_error GError *error = NULL; AddConnectionInfo *info = NULL; gboolean save_bool = TRUE; gboolean seen_dash_dash = FALSE; @@ -4741,27 +4732,24 @@ do_connection_add (NmCli *nmc, int argc, char **argv) nmc->return_value = NMC_RESULT_SUCCESS; - /* Create a new connection object */ connection = nm_simple_connection_new (); - /* Build up the 'connection' setting */ s_con = (NMSettingConnection *) nm_setting_connection_new (); nm_connection_add_setting (connection, NM_SETTING (s_con)); read_properties: + g_clear_error (&error); /* Get the arguments from the command line if any */ if (argc && !nmc_read_connection_properties (nmc, connection, &argc, &argv, &error)) { if (g_strcmp0 (*argv, "--") == 0 && !seen_dash_dash) { /* This is for compatibility with older nmcli that required * options and properties to be separated with "--" */ - g_clear_error (&error); seen_dash_dash = TRUE; next_arg (nmc, &argc, &argv, NULL); goto read_properties; } else if (g_strcmp0 (*argv, "save") == 0) { /* It would be better if "save" was a separate argument and not * mixed with properties, but there's not much we can do about it now. */ - g_clear_error (&error); argc--; argv++; if (!argc) { @@ -4771,11 +4759,11 @@ read_properties: nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; goto finish; } + g_clear_error (&error); if (!nmc_string_to_bool (*argv, &save_bool, &error)) { g_string_printf (nmc->return_text, _("Error: 'save': %s."), error->message); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; - g_clear_error (&error); goto finish; } next_arg (nmc, &argc, &argv, NULL); @@ -4784,7 +4772,6 @@ read_properties: g_string_assign (nmc->return_text, error->message); nmc->return_value = error->code; - g_clear_error (&error); goto finish; } @@ -4894,9 +4881,6 @@ read_properties: finish: reset_options (); - if (connection) - g_object_unref (connection); - return nmc->return_value; } @@ -4948,15 +4932,7 @@ gen_nmcli_cmds_submenu (const char *text, int state) static char * gen_cmd_nmcli (const char *text, int state) { - const char *words[] = { "status-line", "save-confirmation", "show-secrets", "prompt-color", NULL }; - return nmc_rl_gen_func_basic (text, state, words); -} - -static char * -gen_cmd_nmcli_prompt_color (const char *text, int state) -{ - const char *words[] = { "normal", "black", "red", "green", "yellow", - "blue", "magenta", "cyan", "white", NULL }; + const char *words[] = { "status-line", "save-confirmation", "show-secrets", NULL }; return nmc_rl_gen_func_basic (text, state, words); } @@ -5272,8 +5248,6 @@ get_gen_func_cmd_nmcli (const char *str) return gen_func_bool_values; if (matches (str, "show-secrets")) return gen_func_bool_values; - if (matches (str, "prompt-color")) - return gen_cmd_nmcli_prompt_color; return NULL; } @@ -5887,7 +5861,7 @@ _split_cmd (const char *cmd, char **out_arg0, const char **out_argr) if (!cmd) return; - while (NM_IN_SET (cmd[0], ' ', '\t')) + while (nm_utils_is_separator (cmd[0])) cmd++; if (!cmd[0]) return; @@ -5896,7 +5870,7 @@ _split_cmd (const char *cmd, char **out_arg0, const char **out_argr) arg0 = g_strndup (cmd, l); cmd += l; if (cmd[0]) { - while (NM_IN_SET (cmd[0], ' ', '\t')) + while (nm_utils_is_separator (cmd[0])) cmd++; if (cmd[0]) argr = cmd; @@ -6274,8 +6248,8 @@ static gboolean progress_activation_editor_cb (gpointer user_data) { MonitorACInfo *info = (MonitorACInfo *) user_data; - NMDevice *device = info->device; - NMActiveConnection *ac = info->ac; + gs_unref_object NMDevice *device = info->device; + gs_unref_object NMActiveConnection *ac = info->ac; NMActiveConnectionState ac_state; NMDeviceState dev_state; @@ -6292,12 +6266,12 @@ progress_activation_editor_cb (gpointer user_data) nmc_terminal_erase_line (); g_print (_("Connection successfully activated (D-Bus active path: %s)\n"), nm_object_get_path (NM_OBJECT (ac))); - goto finish; /* we are done */ + goto finish; } else if ( ac_state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED || dev_state == NM_DEVICE_STATE_FAILED) { nmc_terminal_erase_line (); g_print (_("Error: Connection activation failed.\n")); - goto finish; /* we are done */ + goto finish; } if (info->nmc->secret_agent) { @@ -6312,10 +6286,6 @@ progress_activation_editor_cb (gpointer user_data) finish: info->monitor_id = 0; - if (device) - g_object_unref (device); - if (ac) - g_object_unref (ac); return FALSE; } @@ -6420,7 +6390,7 @@ refresh_remote_connection (GWeakRef *weak, NMRemoteConnection **remote) { gboolean previous; - g_return_val_if_fail (remote != NULL, FALSE); + g_return_val_if_fail (remote, FALSE); previous = (*remote != NULL); if (*remote) @@ -6469,33 +6439,31 @@ property_edit_submenu (NmCli *nmc, const char *prop_name) { NmcEditorSubCmd cmdsub; - gboolean cmd_property_loop = TRUE; - gboolean should_quit = FALSE; - char *prop_val_user; gboolean set_result; GError *tmp_err = NULL; - char *prompt; - gboolean dirty; - GValue prop_g_value = G_VALUE_INIT; + gs_free char *prompt = NULL; gboolean temp_changes; - gboolean removed; /* Set global variable for use in TAB completion */ nmc_tab_completion.property = prop_name; - prompt = nmc_colorize (nmc->nmc_config.use_colors, nmc->editor_prompt_color, NM_META_TERM_FORMAT_NORMAL, - "nmcli %s.%s> ", + prompt = nmc_colorize (&nmc->nmc_config, NM_META_COLOR_PROMPT, "nmcli %s.%s> ", nm_setting_get_name (curr_setting), prop_name); - while (cmd_property_loop) { - char *cmd_property_user; - char *cmd_property_arg; + for (;;) { + gs_free char *cmd_property_user = NULL; + gs_free char *cmd_property_arg = NULL; + gs_free char *prop_val_user = NULL; + nm_auto_unset_gvalue GValue prop_g_value = G_VALUE_INIT; + gboolean removed; + gboolean dirty; /* Get the remote connection again, it may have disapeared */ removed = refresh_remote_connection (rem_con_weak, rem_con); - if (removed) + if (removed) { g_print (_("The connection profile has been removed from another client. " "You may type 'save' in the main menu to restore it.\n")); + } /* Connection is dirty? (not saved or differs from the saved) */ dirty = is_connection_dirty (connection, *rem_con); @@ -6504,7 +6472,7 @@ property_edit_submenu (NmCli *nmc, editor_show_status_line (connection, dirty, temp_changes); cmd_property_user = nmc_readline ("%s", prompt); - if (!cmd_property_user || *cmd_property_user == '\0') + if (!cmd_property_user || !*cmd_property_user) continue; cmdsub = parse_editor_sub_cmd (g_strstrip (cmd_property_user), &cmd_property_arg); @@ -6540,7 +6508,6 @@ property_edit_submenu (NmCli *nmc, } set_result = nmc_setting_set_property (curr_setting, prop_name, prop_val_user, &tmp_err); - g_free (prop_val_user); if (!set_result) { g_print (_("Error: failed to set '%s' property: %s\n"), prop_name, tmp_err->message); g_clear_error (&tmp_err); @@ -6551,8 +6518,6 @@ property_edit_submenu (NmCli *nmc, g_signal_handlers_unblock_matched (curr_setting, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, NULL); } } - if (G_IS_VALUE (&prop_g_value)) - g_value_unset (&prop_g_value); break; case NMC_EDITOR_SUB_CMD_CHANGE: @@ -6570,9 +6535,6 @@ property_edit_submenu (NmCli *nmc, nmc_property_set_gvalue (curr_setting, prop_name, &prop_g_value); g_signal_handlers_unblock_matched (curr_setting, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, NULL); } - g_free (prop_val_user); - if (G_IS_VALUE (&prop_g_value)) - g_value_unset (&prop_g_value); break; case NMC_EDITOR_SUB_CMD_REMOVE: @@ -6625,8 +6587,7 @@ property_edit_submenu (NmCli *nmc, case NMC_EDITOR_SUB_CMD_BACK: /* Set global variable for use in TAB completion */ nmc_tab_completion.property = NULL; - cmd_property_loop = FALSE; - break; + return TRUE; case NMC_EDITOR_SUB_CMD_HELP: editor_sub_usage (cmd_property_arg); @@ -6634,14 +6595,10 @@ property_edit_submenu (NmCli *nmc, case NMC_EDITOR_SUB_CMD_QUIT: if (is_connection_dirty (connection, *rem_con)) { - if (confirm_quit ()) { - cmd_property_loop = FALSE; - should_quit = TRUE; /* we will quit nmcli */ - } - } else { - cmd_property_loop = FALSE; - should_quit = TRUE; /* we will quit nmcli */ - } + if (confirm_quit ()) + return FALSE; + } else + return FALSE; break; case NMC_EDITOR_SUB_CMD_UNKNOWN: @@ -6649,12 +6606,7 @@ property_edit_submenu (NmCli *nmc, g_print (_("Unknown command: '%s'\n"), cmd_property_user); break; } - g_free (cmd_property_user); - g_free (cmd_property_arg); } - g_free (prompt); - - return !should_quit; } /* @@ -6814,14 +6766,13 @@ typedef struct { } NmcEditorMenuContext; static void -menu_switch_to_level0 (NmcColorOption color_option, +menu_switch_to_level0 (const NmcConfig *nmc_config, NmcEditorMenuContext *menu_ctx, - const char *prompt, - NMMetaTermColor prompt_color) + const char *prompt) { menu_ctx->level = 0; g_free (menu_ctx->main_prompt); - menu_ctx->main_prompt = nmc_colorize (color_option, prompt_color, NM_META_TERM_FORMAT_NORMAL, "%s", prompt); + menu_ctx->main_prompt = nmc_colorize (nmc_config, NM_META_COLOR_PROMPT, "%s", prompt); menu_ctx->curr_setting = NULL; g_strfreev (menu_ctx->valid_props); menu_ctx->valid_props = NULL; @@ -6830,16 +6781,14 @@ menu_switch_to_level0 (NmcColorOption color_option, } static void -menu_switch_to_level1 (NmcColorOption color_option, +menu_switch_to_level1 (const NmcConfig *nmc_config, NmcEditorMenuContext *menu_ctx, NMSetting *setting, - const char *setting_name, - NMMetaTermColor prompt_color) + const char *setting_name) { menu_ctx->level = 1; g_free (menu_ctx->main_prompt); - menu_ctx->main_prompt = nmc_colorize (color_option, prompt_color, NM_META_TERM_FORMAT_NORMAL, - "nmcli %s> ", setting_name); + menu_ctx->main_prompt = nmc_colorize (nmc_config, NM_META_COLOR_PROMPT, "nmcli %s> ", setting_name); menu_ctx->curr_setting = setting; g_strfreev (menu_ctx->valid_props); menu_ctx->valid_props = nmc_setting_get_valid_properties (menu_ctx->curr_setting); @@ -6862,7 +6811,6 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t gs_free char *valid_settings_str = NULL; const char *s_type = NULL; AddConnectionInfo *info = NULL; - gboolean dirty; gboolean temp_changes; GError *err1 = NULL; NmcEditorMenuContext menu_ctx = { 0 }; @@ -6877,8 +6825,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t valid_settings_str = get_valid_options_string (valid_settings_main, valid_settings_slave); g_print (_("You may edit the following settings: %s\n"), valid_settings_str); - menu_ctx.main_prompt = nmc_colorize (nmc->nmc_config.use_colors, nmc->editor_prompt_color, NM_META_TERM_FORMAT_NORMAL, - BASE_PROMPT); + menu_ctx.main_prompt = nmc_colorize (&nmc->nmc_config, NM_META_COLOR_PROMPT, BASE_PROMPT); /* Get remote connection */ con_tmp = nm_client_get_connection_by_uuid (nmc->client, @@ -6892,6 +6839,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t gs_free char *cmd_arg_s = NULL; gs_free char *cmd_arg_p = NULL; gs_free char *cmd_arg_v = NULL; + gboolean dirty; /* Connection is dirty? (not saved or differs from the saved) */ dirty = is_connection_dirty (connection, rem_con); @@ -6899,17 +6847,18 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t if (nmc->editor_status_line) editor_show_status_line (connection, dirty, temp_changes); - /* Read user input */ cmd_user = nmc_readline ("%s", menu_ctx.main_prompt); /* Get the remote connection again, it may have disapeared */ removed = refresh_remote_connection (&weak, &rem_con); - if (removed) + if (removed) { g_print (_("The connection profile has been removed from another client. " "You may type 'save' to restore it.\n")); + } - if (!cmd_user || *cmd_user == '\0') + if (!cmd_user || !*cmd_user) continue; + cmd = parse_editor_main_cmd (g_strstrip (cmd_user), &cmd_arg); split_editor_main_cmd_args (cmd_arg, &cmd_arg_s, &cmd_arg_p, &cmd_arg_v); @@ -7017,7 +6966,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t /* in top level - no setting selected yet */ const char *setting_name; NMSetting *setting; - const char *user_arg = cmd_arg_s ? cmd_arg_s : cmd_arg_p; + const char *user_arg = cmd_arg_s ?: cmd_arg_p; setting_name = ask_check_setting (user_arg, valid_settings_main, @@ -7054,7 +7003,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t nmc_tab_completion.setting = setting; /* Switch to level 1 */ - menu_switch_to_level1 (nmc->nmc_config.use_colors, &menu_ctx, setting, setting_name, nmc->editor_prompt_color); + menu_switch_to_level1 (&nmc->nmc_config, &menu_ctx, setting, setting_name); if (!cmd_arg_s) { g_print (_("You may edit the following properties: %s\n"), menu_ctx.valid_props_str); @@ -7109,7 +7058,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t /* cmd_arg_s != NULL means argument is "setting.property" */ descr_all = !cmd_arg_s && !menu_ctx.curr_setting; - user_s = descr_all ? cmd_arg_p : cmd_arg_s ? cmd_arg_s : NULL; + user_s = descr_all ? cmd_arg_p : cmd_arg_s; if (user_s) { ss = is_setting_valid (connection, valid_settings_main, @@ -7136,7 +7085,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t connection_remove_setting (connection, ss); if (ss == menu_ctx.curr_setting) { /* If we removed the setting we are in, go up */ - menu_switch_to_level0 (nmc->nmc_config.use_colors, &menu_ctx, BASE_PROMPT, nmc->editor_prompt_color); + menu_switch_to_level0 (&nmc->nmc_config, &menu_ctx, BASE_PROMPT); nmc_tab_completion.setting = NULL; /* for TAB completion */ } } else { @@ -7164,7 +7113,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t /* coverity[copy_paste_error] - suppress Coverity COPY_PASTE_ERROR defect */ if (ss == menu_ctx.curr_setting) { /* If we removed the setting we are in, go up */ - menu_switch_to_level0 (nmc->nmc_config.use_colors, &menu_ctx, BASE_PROMPT, nmc->editor_prompt_color); + menu_switch_to_level0 (&nmc->nmc_config, &menu_ctx, BASE_PROMPT); nmc_tab_completion.setting = NULL; /* for TAB completion */ } } else @@ -7202,7 +7151,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t /* cmd_arg_s != NULL means argument is "setting.property" */ descr_all = !cmd_arg_s && !menu_ctx.curr_setting; - user_s = descr_all ? cmd_arg_p : cmd_arg_s ? cmd_arg_s : NULL; + user_s = descr_all ? cmd_arg_p : cmd_arg_s; if (user_s) { ss = is_setting_valid (connection, valid_settings_main, @@ -7259,7 +7208,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t case NMC_EDITOR_MAIN_CMD_PRINT: /* Print current connection settings/properties */ if (cmd_arg) { - if (strcmp (cmd_arg, "all") == 0) + if (nm_streq (cmd_arg, "all")) editor_show_connection (connection, nmc); else { NMSetting *ss = NULL; @@ -7268,7 +7217,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t /* cmd_arg_s != NULL means argument is "setting.property" */ whole_setting = !cmd_arg_s && !menu_ctx.curr_setting; - user_s = whole_setting ? cmd_arg_p : cmd_arg_s ? cmd_arg_s : NULL; + user_s = whole_setting ? cmd_arg_p : cmd_arg_s; if (user_s) { const char *s_name; @@ -7520,7 +7469,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t case NMC_EDITOR_MAIN_CMD_BACK: /* Go back (up) an the menu */ if (menu_ctx.level == 1) { - menu_switch_to_level0 (nmc->nmc_config.use_colors, &menu_ctx, BASE_PROMPT, nmc->editor_prompt_color); + menu_switch_to_level0 (&nmc->nmc_config, &menu_ctx, BASE_PROMPT); nmc_tab_completion.setting = NULL; /* for TAB completion */ } break; @@ -7556,37 +7505,18 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t } else nmc->nmc_config_mutable.show_secrets = bb; } else if (cmd_arg_p && matches (cmd_arg_p, "prompt-color")) { - GError *tmp_err = NULL; - NMMetaTermColor color; - color = nmc_term_color_parse_string (cmd_arg_v ? g_strstrip (cmd_arg_v) : " ", &tmp_err); - if (tmp_err) { - g_print (_("Error: bad color: %s\n"), tmp_err->message); - g_clear_error (&tmp_err); - } else { - nmc->editor_prompt_color = color; - nm_clear_g_free (&menu_ctx.main_prompt); - if (menu_ctx.level == 0) { - menu_ctx.main_prompt = nmc_colorize (nmc->nmc_config.use_colors, nmc->editor_prompt_color, NM_META_TERM_FORMAT_NORMAL, - BASE_PROMPT); - } else { - menu_ctx.main_prompt = nmc_colorize (nmc->nmc_config.use_colors, nmc->editor_prompt_color, NM_META_TERM_FORMAT_NORMAL, - "nmcli %s> ", - nm_setting_get_name (menu_ctx.curr_setting)); - } - } + g_debug ("Ignoring erroneous --prompt-color argument. Use terminal-colors.d(5) to set the prompt color.\n"); } else if (!cmd_arg_p) { g_print (_("Current nmcli configuration:\n")); g_print ("status-line: %s\n" "save-confirmation: %s\n" - "show-secrets: %s\n" - "prompt-color: %d\n", + "show-secrets: %s\n", nmc->editor_status_line ? "yes" : "no", nmc->editor_save_confirmation ? "yes" : "no", - nmc->nmc_config.show_secrets ? "yes" : "no", - nmc->editor_prompt_color); + nmc->nmc_config.show_secrets ? "yes" : "no"); } else g_print (_("Invalid configuration option '%s'; allowed [%s]\n"), - cmd_arg_v ? cmd_arg_v : "", "status-line, save-confirmation, show-secrets, prompt-color"); + cmd_arg_v ?: "", "status-line, save-confirmation, show-secrets"); break; @@ -7657,7 +7587,7 @@ editor_init_new_connection (NmCli *nmc, NMConnection *connection, const char *sl g_object_set (s_con, NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_CONNECTION_MASTER, dev_ifname ? dev_ifname : "eth0", + NM_SETTING_CONNECTION_MASTER, dev_ifname ?: "eth0", NM_SETTING_CONNECTION_SLAVE_TYPE, slave_type, NULL); } else { @@ -7678,11 +7608,10 @@ editor_init_new_connection (NmCli *nmc, NMConnection *connection, const char *sl const char *dev_ifname = get_ethernet_device_name (nmc); g_object_set (NM_SETTING_VLAN (base_setting), - NM_SETTING_VLAN_PARENT, dev_ifname ? dev_ifname : "eth0", + NM_SETTING_VLAN_PARENT, dev_ifname ?: "eth0", NULL); } - setting = nm_meta_setting_info_editor_new_setting (&nm_meta_setting_infos_editor[NM_META_SETTING_TYPE_IP4_CONFIG], NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI); nm_connection_add_setting (connection, setting); @@ -7743,28 +7672,24 @@ static NMCResultCode do_connection_edit (NmCli *nmc, int argc, char **argv) { const GPtrArray *connections; - NMConnection *connection = NULL; + gs_unref_object NMConnection *connection = NULL; NMSettingConnection *s_con; const char *connection_type; - char *uuid; - char *default_name = NULL; const char *type = NULL; - char *type_ask = NULL; const char *con_name = NULL; const char *con = NULL; const char *con_id = NULL; const char *con_uuid = NULL; const char *con_path = NULL; const char *selector = NULL; - char *tmp_str; - GError *error = NULL; + gs_free_error GError *error = NULL; GError *err1 = NULL; - nmc_arg_t exp_args[] = { {"type", TRUE, &type, FALSE}, - {"con-name", TRUE, &con_name, FALSE}, - {"id", TRUE, &con_id, FALSE}, - {"uuid", TRUE, &con_uuid, FALSE}, - {"path", TRUE, &con_path, FALSE}, - {NULL} }; + nmc_arg_t exp_args[] = { { "type", TRUE, &type, FALSE }, + { "con-name", TRUE, &con_name, FALSE }, + { "id", TRUE, &con_id, FALSE }, + { "uuid", TRUE, &con_uuid, FALSE }, + { "path", TRUE, &con_path, FALSE }, + { NULL } }; next_arg (nmc, &argc, &argv, NULL); if (argc == 1 && nmc->complete) @@ -7777,9 +7702,7 @@ do_connection_edit (NmCli *nmc, int argc, char **argv) else { if (!nmc_parse_args (exp_args, TRUE, &argc, &argv, &error)) { g_string_assign (nmc->return_text, error->message); - nmc->return_value = error->code; - g_clear_error (&error); - goto error; + NMC_RETURN (nmc, error->code); } } @@ -7806,8 +7729,7 @@ do_connection_edit (NmCli *nmc, int argc, char **argv) } else { g_string_printf (nmc->return_text, _("Error: only one of 'id', uuid, or 'path' can be provided.")); - nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; - goto error; + NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); } } @@ -7817,12 +7739,11 @@ do_connection_edit (NmCli *nmc, int argc, char **argv) found_con = nmc_find_connection (connections, selector, con, NULL, nmc->complete); if (nmc->complete) - goto error; + return nmc->return_value; if (!found_con) { g_string_printf (nmc->return_text, _("Error: Unknown connection '%s'."), con); - nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND; - goto error; + NMC_RETURN (nmc, NMC_RESULT_ERROR_NOT_FOUND); } /* Duplicate the connection and use that so that we need not @@ -7834,7 +7755,6 @@ do_connection_edit (NmCli *nmc, int argc, char **argv) update_secrets_in_connection (NM_REMOTE_CONNECTION (found_con), connection); s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); connection_type = nm_setting_connection_get_connection_type (s_con); if (type) @@ -7850,18 +7770,23 @@ do_connection_edit (NmCli *nmc, int argc, char **argv) editor_init_existing_connection (connection); } else { const char *slave_type = NULL; + gs_free char *uuid = NULL; + gs_free char *default_name = NULL; + gs_free char *tmp_str = NULL; /* New connection */ if (nmc->complete) { if (type && argc == 0) nmc_complete_connection_type (type); - goto error; + return nmc->return_value; } connection_type = check_valid_name_toplevel (type, &slave_type, &err1); tmp_str = get_valid_options_string_toplevel (); while (!connection_type) { + gs_free char *type_ask = NULL; + if (!type) g_print (_("Valid connection types: %s\n"), tmp_str); else @@ -7871,14 +7796,11 @@ do_connection_edit (NmCli *nmc, int argc, char **argv) type_ask = nmc_readline (EDITOR_PROMPT_CON_TYPE); type = type_ask = type_ask ? g_strstrip (type_ask) : NULL; connection_type = check_valid_name_toplevel (type_ask, &slave_type, &err1); - g_free (type_ask); } - g_free (tmp_str); + nm_clear_g_free (&tmp_str); - /* Create a new connection object */ connection = nm_simple_connection_new (); - /* Build up the 'connection' setting */ s_con = (NMSettingConnection *) nm_setting_connection_new (); uuid = nm_utils_uuid_generate (); if (con_name) @@ -7893,8 +7815,6 @@ do_connection_edit (NmCli *nmc, int argc, char **argv) NM_SETTING_CONNECTION_UUID, uuid, NM_SETTING_CONNECTION_TYPE, connection_type, NULL); - g_free (uuid); - g_free (default_name); nm_connection_add_setting (connection, NM_SETTING (s_con)); /* Initialize the new connection so that it is valid from the start */ @@ -7917,7 +7837,6 @@ do_connection_edit (NmCli *nmc, int argc, char **argv) g_print (_("Type 'describe [<setting>.<prop>]' for detailed property description.")); g_print ("\n\n"); - /* Set global variables for use in TAB completion */ nmc_tab_completion.nmc = nmc; nmc_tab_completion.con_type = g_strdup (connection_type); nmc_tab_completion.connection = connection; @@ -7925,15 +7844,9 @@ do_connection_edit (NmCli *nmc, int argc, char **argv) /* Run menu loop */ editor_menu_main (nmc, connection, connection_type); - if (connection) - g_object_unref (connection); - g_free (nmc_tab_completion.con_type); - - return nmc->return_value; - -error: - g_assert (!connection); - g_free (type_ask); + nmc_tab_completion.nmc = NULL; + nm_clear_g_free (&nmc_tab_completion.con_type); + nmc_tab_completion.connection = NULL; return nmc->return_value; } @@ -7943,8 +7856,8 @@ modify_connection_cb (GObject *connection, GAsyncResult *result, gpointer user_data) { - NmCli *nmc = (NmCli *) user_data; - GError *error = NULL; + NmCli *nmc = user_data; + gs_free_error GError *error = NULL; if (!nm_remote_connection_commit_changes_finish (NM_REMOTE_CONNECTION (connection), result, &error)) { @@ -7952,13 +7865,13 @@ modify_connection_cb (GObject *connection, _("Error: Failed to modify connection '%s': %s"), nm_connection_get_id (NM_CONNECTION (connection)), error->message); - g_error_free (error); nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; } else { - if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY) + if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY) { g_print (_("Connection '%s' (%s) successfully modified.\n"), nm_connection_get_id (NM_CONNECTION (connection)), nm_connection_get_uuid (NM_CONNECTION (connection))); + } } quit (); } @@ -7970,20 +7883,18 @@ do_connection_modify (NmCli *nmc, { NMConnection *connection = NULL; NMRemoteConnection *rc = NULL; - GError *error = NULL; + gs_free_error GError *error = NULL; gboolean temporary = FALSE; - /* Check --temporary */ if (next_arg (nmc, &argc, &argv, "--temporary", NULL) > 0) { temporary = TRUE; next_arg (nmc, &argc, &argv, NULL); } - connection = get_connection (nmc, &argc, &argv, NULL, &error); + connection = get_connection (nmc, &argc, &argv, NULL, NULL, NULL, &error); if (!connection) { g_string_printf (nmc->return_text, _("Error: %s."), error->message); - nmc->return_value = error->code; - goto finish; + NMC_RETURN (nmc, error->code); } rc = nm_client_get_connection_by_uuid (nmc->client, @@ -7991,24 +7902,20 @@ do_connection_modify (NmCli *nmc, if (!rc) { g_string_printf (nmc->return_text, _("Error: Unknown connection '%s'."), nm_connection_get_uuid (connection)); - nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND; - goto finish; + NMC_RETURN (nmc, NMC_RESULT_ERROR_NOT_FOUND); } if (!nmc_read_connection_properties (nmc, NM_CONNECTION (rc), &argc, &argv, &error)) { g_string_assign (nmc->return_text, error->message); - nmc->return_value = error->code; - g_clear_error (&error); - goto finish; + NMC_RETURN (nmc, error->code); } if (nmc->complete) - goto finish; + return nmc->return_value; update_connection (!temporary, rc, modify_connection_cb, nmc); nmc->should_wait++; -finish: return nmc->return_value; } @@ -8056,11 +7963,11 @@ static NMCResultCode do_connection_clone (NmCli *nmc, int argc, char **argv) { NMConnection *connection = NULL; - NMConnection *new_connection = NULL; + gs_unref_object NMConnection *new_connection = NULL; NMSettingConnection *s_con; CloneConnectionInfo *info; const char *new_name; - char *new_name_ask = NULL; + gs_free char *new_name_ask = NULL; char *uuid; gboolean temporary = FALSE; char **arg_arr = NULL; @@ -8090,15 +7997,14 @@ do_connection_clone (NmCli *nmc, int argc, char **argv) argc_ptr = &arg_num; } - connection = get_connection (nmc, argc_ptr, argv_ptr, NULL, &error); + connection = get_connection (nmc, argc_ptr, argv_ptr, NULL, NULL, NULL, &error); if (!connection) { g_string_printf (nmc->return_text, _("Error: %s."), error->message); - nmc->return_value = error->code; - goto finish; + NMC_RETURN (nmc, error->code); } if (nmc->complete) - goto finish; + return nmc->return_value; if (argv[0]) new_name = *argv; @@ -8106,14 +8012,12 @@ do_connection_clone (NmCli *nmc, int argc, char **argv) new_name = new_name_ask = nmc_readline (_("New connection name: ")); else { g_string_printf (nmc->return_text, _("Error: <new name> argument is missing.")); - nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; - goto finish; + NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); } if (next_arg (nmc->ask ? NULL : nmc, argc_ptr, argv_ptr, NULL) == 0) { g_string_printf (nmc->return_text, _("Error: unknown extra argument: '%s'."), *argv); - nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; - goto finish; + NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); } /* Copy the connection */ @@ -8145,11 +8049,6 @@ do_connection_clone (NmCli *nmc, int argc, char **argv) info); nmc->should_wait++; -finish: - if (new_connection) - g_object_unref (new_connection); - g_free (new_name_ask); - return nmc->return_value; } @@ -8179,12 +8078,12 @@ do_connection_delete (NmCli *nmc, int argc, char **argv) { NMConnection *connection; ConnectionCbInfo *info = NULL; - GSList *queue = NULL, *iter; - char **arg_arr = NULL, *old_arg; + gs_strfreev char **arg_arr = NULL; char **arg_ptr; + guint i; int arg_num; - GString *invalid_cons = NULL; - int pos = 0; + nm_auto_free_gstring GString *invalid_cons = NULL; + gs_unref_ptrarray GPtrArray *found_cons = NULL; GError *error = NULL; if (nmc->timeout == -1) @@ -8214,15 +8113,10 @@ do_connection_delete (NmCli *nmc, int argc, char **argv) } while (arg_num > 0) { - old_arg = *arg_ptr; - connection = get_connection (nmc, &arg_num, &arg_ptr, &pos, &error); - if (connection) { - /* Check if the connection is unique. */ - /* Calling delete for the same connection repeatedly would result in - * NM responding for the last D-Bus call only and we would stall. */ - if (!g_slist_find (queue, connection)) - queue = g_slist_prepend (queue, g_object_ref (connection)); - } else { + const char *cur_selector, *cur_value; + + connection = get_connection (nmc, &arg_num, &arg_ptr, &cur_selector, &cur_value, &found_cons, &error); + if (!connection) { if (!nmc->complete) g_printerr (_("Error: %s.\n"), error->message); g_string_printf (nmc->return_text, _("Error: not all connections found.")); @@ -8234,23 +8128,31 @@ do_connection_delete (NmCli *nmc, int argc, char **argv) if (!invalid_cons) invalid_cons = g_string_new (NULL); - g_string_append_printf (invalid_cons, "'%s', ", old_arg); + if (cur_selector) + g_string_append_printf (invalid_cons, "%s '%s', ", cur_selector, cur_value); + else + g_string_append_printf (invalid_cons, "'%s', ", cur_value); } } - if (!queue) { - g_string_printf (nmc->return_text, _("Error: No connection specified.")); - nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND; - goto finish; - } else if (nmc->complete) { - g_slist_free (queue); + if (!found_cons) { + if (!invalid_cons) { + g_string_printf (nmc->return_text, _("Error: No connection specified.")); + nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND; + } goto finish; } - queue = g_slist_reverse (queue); + + if (nmc->complete) + goto finish; info = g_slice_new0 (ConnectionCbInfo); info->nmc = nmc; - info->queue = queue; + info->obj_list = g_ptr_array_sized_new (found_cons->len); + for (i = 0; i < found_cons->len; i++) { + connection = found_cons->pdata[i]; + g_ptr_array_add (info->obj_list, g_object_ref (connection)); + } info->timeout_id = g_timeout_add_seconds (nmc->timeout, connection_op_timeout_cb, info); info->cancellable = g_cancellable_new (); @@ -8260,10 +8162,10 @@ do_connection_delete (NmCli *nmc, int argc, char **argv) g_signal_connect (nmc->client, NM_CLIENT_CONNECTION_REMOVED, G_CALLBACK (connection_removed_cb), info); - /* Now delete the connections */ - for (iter = queue; iter; iter = g_slist_next (iter)) - nm_remote_connection_delete_async (NM_REMOTE_CONNECTION (iter->data), + for (i = 0; i < found_cons->len; i++) { + nm_remote_connection_delete_async (NM_REMOTE_CONNECTION (found_cons->pdata[i]), info->cancellable, delete_cb, info); + } finish: if (invalid_cons) { @@ -8271,9 +8173,7 @@ finish: g_string_printf (nmc->return_text, _("Error: cannot delete unknown connection(s): %s."), invalid_cons->str); nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND; - g_string_free (invalid_cons, TRUE); } - g_strfreev (arg_arr); return nmc->return_value; } @@ -8323,31 +8223,21 @@ static NMCResultCode do_connection_monitor (NmCli *nmc, int argc, char **argv) { GError *error = NULL; + guint i; + gs_unref_ptrarray GPtrArray *found_cons = NULL; + const GPtrArray *connections = NULL; next_arg (nmc, &argc, &argv, NULL); if (argc == 0) { /* No connections specified. Monitor all. */ - const GPtrArray *connections; - int i; /* nmc_do_cmd() should not call this with argc=0. */ g_assert (!nmc->complete); connections = nm_client_get_connections (nmc->client); - for (i = 0; i < connections->len; i++) - connection_watch (nmc, g_ptr_array_index (connections, i)); - - /* We'll watch the connection additions too, never exit. */ - nmc->should_wait++; - g_signal_connect (nmc->client, NM_CLIENT_CONNECTION_ADDED, G_CALLBACK (connection_added), nmc); } else { - /* Look up the specified connections and watch them. */ - NMConnection *connection; - int pos = 0; - - do { - connection = get_connection (nmc, &argc, &argv, &pos, &error); - if (!connection) { + while (argc > 0) { + if (!get_connection (nmc, &argc, &argv, NULL, NULL, &found_cons, &error)) { if (!nmc->complete) g_printerr (_("Error: %s.\n"), error->message); g_string_printf (nmc->return_text, _("Error: not all connections found.")); @@ -8357,8 +8247,17 @@ do_connection_monitor (NmCli *nmc, int argc, char **argv) if (nmc->complete) continue; - connection_watch (nmc, connection); - } while (argc > 0); + connections = found_cons; + } + } + + for (i = 0; i < connections->len; i++) + connection_watch (nmc, connections->pdata[i]); + + if (argc == 0) { + /* We'll watch the connection additions too, never exit. */ + nmc->should_wait++; + g_signal_connect (nmc->client, NM_CLIENT_CONNECTION_ADDED, G_CALLBACK (connection_added), nmc); } if (nmc->complete) @@ -8431,11 +8330,12 @@ do_connection_load (NmCli *nmc, int argc, char **argv) static NMCResultCode do_connection_import (NmCli *nmc, int argc, char **argv) { - GError *error = NULL; + gs_free_error GError *error = NULL; const char *type = NULL, *filename = NULL; - char *type_ask = NULL, *filename_ask = NULL; + gs_free char *type_ask = NULL; + gs_free char *filename_ask = NULL; AddConnectionInfo *info; - NMConnection *connection = NULL; + gs_unref_object NMConnection *connection = NULL; NMVpnEditorPlugin *plugin; gs_free char *service_type = NULL; gboolean temporary = FALSE; @@ -8446,7 +8346,6 @@ do_connection_import (NmCli *nmc, int argc, char **argv) next_arg (nmc, &argc, &argv, NULL); } - if (argc == 0) { /* nmc_do_cmd() should not call this with argc=0. */ g_assert (!nmc->complete); @@ -8458,8 +8357,7 @@ do_connection_import (NmCli *nmc, int argc, char **argv) filename = filename_ask = filename_ask ? g_strstrip (filename_ask) : NULL; } else { g_string_printf (nmc->return_text, _("Error: No arguments provided.")); - nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; - goto finish; + NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); } } @@ -8472,8 +8370,7 @@ do_connection_import (NmCli *nmc, int argc, char **argv) argv++; if (!argc) { g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *(argv-1)); - nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; - goto finish; + NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); } if (argc == 1 && nmc->complete) @@ -8489,8 +8386,7 @@ do_connection_import (NmCli *nmc, int argc, char **argv) argv++; if (!argc) { g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *(argv-1)); - nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; - goto finish; + NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); } if (argc == 1 && nmc->complete) nmc->return_value = NMC_RESULT_COMPLETE_FILE; @@ -8500,32 +8396,28 @@ do_connection_import (NmCli *nmc, int argc, char **argv) g_printerr (_("Warning: 'file' already specified, ignoring extra one.\n")); } else { g_string_printf (nmc->return_text, _("Unknown parameter: %s"), *argv); - nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; - goto finish; + NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); } next_arg (nmc, &argc, &argv, NULL); } if (nmc->complete) - goto finish; + return nmc->return_value; if (!type) { g_string_printf (nmc->return_text, _("Error: 'type' argument is required.")); - nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; - goto finish; + NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); } if (!filename) { g_string_printf (nmc->return_text, _("Error: 'file' argument is required.")); - nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; - goto finish; + NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT); } service_type = nm_vpn_plugin_info_list_find_service_type (nm_vpn_get_plugin_infos (), type); if (!service_type) { g_string_printf (nmc->return_text, _("Error: failed to find VPN plugin for %s."), type); - nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; - goto finish; + NMC_RETURN (nmc, NMC_RESULT_ERROR_UNKNOWN); } /* Import VPN configuration */ @@ -8533,16 +8425,14 @@ do_connection_import (NmCli *nmc, int argc, char **argv) if (!plugin) { g_string_printf (nmc->return_text, _("Error: failed to load VPN plugin: %s."), error->message); - nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; - goto finish; + NMC_RETURN (nmc, NMC_RESULT_ERROR_UNKNOWN); } connection = nm_vpn_editor_plugin_import (plugin, filename, &error); if (!connection) { g_string_printf (nmc->return_text, _("Error: failed to import '%s': %s."), filename, error->message); - nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; - goto finish; + NMC_RETURN (nmc, NMC_RESULT_ERROR_UNKNOWN); } info = g_malloc0 (sizeof (AddConnectionInfo)); @@ -8557,12 +8447,6 @@ do_connection_import (NmCli *nmc, int argc, char **argv) info); nmc->should_wait++; -finish: - if (connection) - g_object_unref (connection); - g_clear_error (&error); - g_free (type_ask); - g_free (filename_ask); return nmc->return_value; } @@ -8571,12 +8455,11 @@ do_connection_export (NmCli *nmc, int argc, char **argv) { NMConnection *connection = NULL; const char *out_name = NULL; - char *name_ask = NULL; - char *out_name_ask = NULL; + gs_free char *out_name_ask = NULL; const char *path = NULL; const char *type = NULL; NMVpnEditorPlugin *plugin; - GError *error = NULL; + gs_free_error GError *error = NULL; char tmpfile[] = "/tmp/nmcli-export-temp-XXXXXX"; char **arg_arr = NULL; int arg_num; @@ -8600,7 +8483,7 @@ do_connection_export (NmCli *nmc, int argc, char **argv) argc_ptr = &arg_num; } - connection = get_connection (nmc, argc_ptr, argv_ptr, NULL, &error); + connection = get_connection (nmc, argc_ptr, argv_ptr, NULL, NULL, NULL, &error); if (!connection) { g_string_printf (nmc->return_text, _("Error: %s."), error->message); nmc->return_value = error->code; @@ -8641,14 +8524,14 @@ do_connection_export (NmCli *nmc, int argc, char **argv) if (out_name) path = out_name; else { - int fd; + nm_auto_close int fd = -1; + fd = g_mkstemp (tmpfile); if (fd == -1) { g_string_printf (nmc->return_text, _("Error: failed to create temporary file %s."), tmpfile); nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; goto finish; } - nm_close (fd); path = tmpfile; } @@ -8661,8 +8544,9 @@ do_connection_export (NmCli *nmc, int argc, char **argv) /* No output file -> copy data to stdout */ if (!out_name) { - char *contents = NULL; + gs_free char *contents = NULL; gsize len = 0; + if (!g_file_get_contents (path, &contents, &len, &error)) { g_string_printf (nmc->return_text, _("Error: failed to read temporary file '%s': %s."), path, error->message); @@ -8670,15 +8554,11 @@ do_connection_export (NmCli *nmc, int argc, char **argv) goto finish; } g_print ("%s", contents); - g_free (contents); } finish: if (!out_name && path) unlink (path); - g_clear_error (&error); - g_free (name_ask); - g_free (out_name_ask); return nmc->return_value; } diff --git a/clients/cli/connections.h b/clients/cli/connections.h index 01e78b02..591e9cda 100644 --- a/clients/cli/connections.h +++ b/clients/cli/connections.h @@ -14,7 +14,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * (C) Copyright 2010 - 2014 Red Hat, Inc. + * (C) Copyright 2010 - 2018 Red Hat, Inc. */ #ifndef NMC_CONNECTIONS_H @@ -33,7 +33,7 @@ nmc_read_connection_properties (NmCli *nmc, char ***argv, GError **error); -void nmc_active_connection_state_to_color (NMActiveConnectionState state, NMMetaTermColor *color); +NMMetaColor nmc_active_connection_state_to_color (NMActiveConnectionState state); extern const NmcMetaGenericInfo *const nmc_fields_con_show[]; extern const NmcMetaGenericInfo *const nmc_fields_con_active_details_general[]; diff --git a/clients/cli/devices.c b/clients/cli/devices.c index a43861fa..b99e606a 100644 --- a/clients/cli/devices.c +++ b/clients/cli/devices.c @@ -14,7 +14,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2010 - 2014 Red Hat, Inc. + * Copyright 2010 - 2018 Red Hat, Inc. */ #include "nm-default.h" @@ -51,7 +51,6 @@ const NmcMetaGenericInfo *const nmc_fields_dev_status[] = { }; #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 */ @@ -210,9 +209,9 @@ const NmcMetaGenericInfo *const nmc_fields_dev_show_sections[] = { NMC_META_GENERIC_WITH_NESTED ("WIMAX-PROPERTIES", nmc_fields_dev_show_wimax_prop + 1), /* 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_dhcp4_config + 1), /* 8 */ + 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_dhcp6_config + 1), /* 10 */ + NMC_META_GENERIC_WITH_NESTED ("DHCP6", nmc_fields_dhcp_config + 1), /* 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 */ @@ -708,22 +707,19 @@ sort_access_points (const GPtrArray *aps) return sorted; } -static void -wifi_signal_to_color (guint8 strength, NMMetaTermColor *color, NMMetaTermFormat *color_fmt) +static NMMetaColor +wifi_signal_to_color (guint8 strength) { - *color = NM_META_TERM_COLOR_NORMAL; - *color_fmt = NM_META_TERM_FORMAT_NORMAL; - if (strength > 80) - *color = NM_META_TERM_COLOR_GREEN; + return NM_META_COLOR_WIFI_SIGNAL_EXCELLENT; else if (strength > 55) - *color = NM_META_TERM_COLOR_YELLOW; + return NM_META_COLOR_WIFI_SIGNAL_GOOD; else if (strength > 30) - *color = NM_META_TERM_COLOR_MAGENTA; + return NM_META_COLOR_WIFI_SIGNAL_FAIR; else if (strength > 5) - *color = NM_META_TERM_COLOR_CYAN; + return NM_META_COLOR_WIFI_SIGNAL_POOR; else - *color_fmt = NM_META_TERM_FORMAT_DIM; + return NM_META_COLOR_WIFI_SIGNAL_UNKNOWN; } static char * @@ -796,8 +792,7 @@ fill_output_access_point (gpointer data, gpointer user_data) GString *security_str; char *ap_name; const char *sig_bars; - NMMetaTermColor color; - NMMetaTermFormat color_fmt; + NMMetaColor color; if (info->active_bssid) { const char *current_bssid = nm_access_point_get_bssid (ap); @@ -883,11 +878,10 @@ fill_output_access_point (gpointer data, gpointer user_data) set_val_strc (arr, 16, nm_object_get_path (NM_OBJECT (ap))); /* Set colors */ - wifi_signal_to_color (strength, &color, &color_fmt); + color = wifi_signal_to_color (strength); set_val_color_all (arr, color); - set_val_color_fmt_all (arr, color_fmt); if (active) - arr[15].color = NM_META_TERM_COLOR_GREEN; + arr[15].color = NM_META_COLOR_CONNECTION_ACTIVATED; g_ptr_array_add (info->output_data, arr); @@ -1161,7 +1155,7 @@ show_device_info (NMDevice *device, NmCli *nmc) 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 ? hwaddr : _("(unknown)")); + 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); @@ -1269,7 +1263,7 @@ show_device_info (NMDevice *device, NmCli *nmc) } tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_dev_wifi_list; - out_indices = parse_output_fields (section_fld ? section_fld : NMC_FIELDS_DEV_WIFI_LIST_FOR_DEV_LIST, + out_indices = parse_output_fields (section_fld ?: NMC_FIELDS_DEV_WIFI_LIST_FOR_DEV_LIST, tmpl, FALSE, NULL, NULL); arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES); g_ptr_array_add (out.output_data, arr); @@ -1329,7 +1323,7 @@ show_device_info (NMDevice *device, NmCli *nmc) /* DHCP4 */ if (dhcp4 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[8]->name)) - was_output = print_dhcp4_config (dhcp4, &nmc->nmc_config, nmc_fields_dev_show_sections[8]->name, section_fld); + was_output = print_dhcp_config (dhcp4, &nmc->nmc_config, nmc_fields_dev_show_sections[8]->name, section_fld); /* IP6 */ if (cfg6 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[9]->name)) @@ -1337,7 +1331,7 @@ show_device_info (NMDevice *device, NmCli *nmc) /* DHCP6 */ if (dhcp6 && !strcasecmp (nmc_fields_dev_show_sections[section_idx]->name, nmc_fields_dev_show_sections[10]->name)) - was_output = print_dhcp6_config (dhcp6, &nmc->nmc_config, nmc_fields_dev_show_sections[10]->name, section_fld); + was_output = print_dhcp_config (dhcp6, &nmc->nmc_config, nmc_fields_dev_show_sections[10]->name, section_fld); /* Bond specific information */ if (NM_IS_DEVICE_BOND (device)) { @@ -1464,20 +1458,19 @@ show_device_info (NMDevice *device, NmCli *nmc) return TRUE; } -void -nmc_device_state_to_color (NMDeviceState state, NMMetaTermColor *color, NMMetaTermFormat *color_fmt) +NMMetaColor +nmc_device_state_to_color (NMDeviceState state) { - *color = NM_META_TERM_COLOR_NORMAL; - *color_fmt = NM_META_TERM_FORMAT_NORMAL; - if (state <= NM_DEVICE_STATE_UNAVAILABLE) - *color_fmt= NM_META_TERM_FORMAT_DIM; + return NM_META_COLOR_DEVICE_UNAVAILABLE; else if (state == NM_DEVICE_STATE_DISCONNECTED) - *color = NM_META_TERM_COLOR_RED; + return NM_META_COLOR_DEVICE_DISCONNECTED; else if (state >= NM_DEVICE_STATE_PREPARE && state <= NM_DEVICE_STATE_SECONDARIES) - *color = NM_META_TERM_COLOR_YELLOW; + return NM_META_COLOR_DEVICE_ACTIVATING; else if (state == NM_DEVICE_STATE_ACTIVATED) - *color = NM_META_TERM_COLOR_GREEN; + return NM_META_COLOR_DEVICE_ACTIVATED; + + g_return_val_if_reached (NM_META_COLOR_DEVICE_UNKNOWN); } static void @@ -1485,8 +1478,7 @@ fill_output_device_status (NMDevice *device, GPtrArray *output_data) { NMActiveConnection *ac; NMDeviceState state; - NMMetaTermColor color; - NMMetaTermFormat color_fmt; + NMMetaColor color; NmcOutputField *arr = nmc_dup_fields_array ((const NMMetaAbstractInfo *const*) nmc_fields_dev_status, 0); @@ -1494,9 +1486,8 @@ fill_output_device_status (NMDevice *device, GPtrArray *output_data) ac = nm_device_get_active_connection (device); /* Show devices in color */ - nmc_device_state_to_color (state, &color, &color_fmt); + color = nmc_device_state_to_color (state); set_val_color_all (arr, color); - set_val_color_fmt_all (arr, color_fmt); set_val_strc (arr, 0, nm_device_get_iface (device)); set_val_strc (arr, 1, nm_device_get_type_description (device)); @@ -2407,12 +2398,11 @@ static void device_state (NMDevice *device, GParamSpec *pspec, NmCli *nmc) { NMDeviceState state = nm_device_get_state (device); - NMMetaTermColor color; - NMMetaTermFormat color_fmt; + NMMetaColor color; char *str; - nmc_device_state_to_color (state, &color, &color_fmt); - str = nmc_colorize (nmc->nmc_config.use_colors, color, color_fmt, "%s: %s\n", + 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)); @@ -2907,7 +2897,7 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv) if (nmc->ask) { ssid_ask = nmc_readline (_("SSID or BSSID: ")); - param_user = ssid_ask ? ssid_ask : ""; + param_user = ssid_ask ?: ""; bssid1_arr = nm_utils_hwaddr_atoba (param_user, ETH_ALEN); } if (!ssid_ask) { @@ -3658,7 +3648,6 @@ do_device_wifi_rescan (NmCli *nmc, int argc, char **argv) goto finish; } - if (ssids->len) { g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aay")); diff --git a/clients/cli/devices.h b/clients/cli/devices.h index 2c261bc7..c78680da 100644 --- a/clients/cli/devices.h +++ b/clients/cli/devices.h @@ -14,7 +14,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * (C) Copyright 2010 Red Hat, Inc. + * (C) Copyright 2010 - 2018 Red Hat, Inc. */ #ifndef NMC_DEVICES_H @@ -32,7 +32,7 @@ void monitor_devices (NmCli *nmc); NMDevice ** nmc_get_devices_sorted (NMClient *client); -void nmc_device_state_to_color (NMDeviceState state, NMMetaTermColor *color, NMMetaTermFormat *color_fmt); +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[]; diff --git a/clients/cli/general.c b/clients/cli/general.c index 647ee5fc..841df8bd 100644 --- a/clients/cli/general.c +++ b/clients/cli/general.c @@ -14,7 +14,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2010 - 2017 Red Hat, Inc. + * Copyright 2010 - 2018 Red Hat, Inc. */ #include "nm-default.h" @@ -55,23 +55,26 @@ nm_state_to_string (NMState state) return _(nm_state_to_string_no_l10n (state)); } -static NMMetaTermColor +static NMMetaColor state_to_color (NMState state) { switch (state) { case NM_STATE_CONNECTING: - return NM_META_TERM_COLOR_YELLOW; + return NM_META_COLOR_STATE_CONNECTING; case NM_STATE_CONNECTED_LOCAL: + return NM_META_COLOR_STATE_CONNECTED_LOCAL; case NM_STATE_CONNECTED_SITE: + return NM_META_COLOR_STATE_CONNECTED_SITE; case NM_STATE_CONNECTED_GLOBAL: - return NM_META_TERM_COLOR_GREEN; + return NM_META_COLOR_STATE_CONNECTED_GLOBAL; case NM_STATE_DISCONNECTING: - return NM_META_TERM_COLOR_YELLOW; + return NM_META_COLOR_STATE_DISCONNECTING; case NM_STATE_ASLEEP: + return NM_META_COLOR_STATE_ASLEEP; case NM_STATE_DISCONNECTED: - return NM_META_TERM_COLOR_RED; + return NM_META_COLOR_STATE_DISCONNECTED; default: - return NM_META_TERM_COLOR_NORMAL; + return NM_META_COLOR_STATE_UNKNOWN; } } @@ -90,19 +93,20 @@ nm_connectivity_to_string (NMConnectivityState connectivity) return _(nm_connectivity_to_string_no_l10n (connectivity)); } -static NMMetaTermColor +static NMMetaColor connectivity_to_color (NMConnectivityState connectivity) { switch (connectivity) { case NM_CONNECTIVITY_NONE: - return NM_META_TERM_COLOR_RED; + return NM_META_COLOR_CONNECTIVITY_NONE; case NM_CONNECTIVITY_PORTAL: + return NM_META_COLOR_CONNECTIVITY_PORTAL; case NM_CONNECTIVITY_LIMITED: - return NM_META_TERM_COLOR_YELLOW; + return NM_META_COLOR_CONNECTIVITY_LIMITED; case NM_CONNECTIVITY_FULL: - return NM_META_TERM_COLOR_GREEN; + return NM_META_COLOR_CONNECTIVITY_FULL; default: - return NM_META_TERM_COLOR_NORMAL; + return NM_META_COLOR_CONNECTIVITY_UNKNOWN; } } @@ -155,11 +159,11 @@ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (permission_result_to_string_no_l10n, NMClient NM_UTILS_LOOKUP_ITEM_IGNORE (NM_CLIENT_PERMISSION_RESULT_UNKNOWN), ); -_NM_UTILS_LOOKUP_DEFINE (static, permission_result_to_color, NMClientPermissionResult, NMMetaTermColor, - NM_UTILS_LOOKUP_DEFAULT (NM_META_TERM_COLOR_NORMAL), - NM_UTILS_LOOKUP_ITEM (NM_CLIENT_PERMISSION_RESULT_YES, NM_META_TERM_COLOR_GREEN), - NM_UTILS_LOOKUP_ITEM (NM_CLIENT_PERMISSION_RESULT_NO, NM_META_TERM_COLOR_RED), - NM_UTILS_LOOKUP_ITEM (NM_CLIENT_PERMISSION_RESULT_AUTH, NM_META_TERM_COLOR_YELLOW), +_NM_UTILS_LOOKUP_DEFINE (static, permission_result_to_color, NMClientPermissionResult, NMMetaColor, + NM_UTILS_LOOKUP_DEFAULT (NM_META_COLOR_PERMISSION_UNKNOWN), + NM_UTILS_LOOKUP_ITEM (NM_CLIENT_PERMISSION_RESULT_YES, NM_META_COLOR_PERMISSION_YES), + NM_UTILS_LOOKUP_ITEM (NM_CLIENT_PERMISSION_RESULT_NO, NM_META_COLOR_PERMISSION_NO), + NM_UTILS_LOOKUP_ITEM (NM_CLIENT_PERMISSION_RESULT_AUTH, NM_META_COLOR_PERMISSION_AUTH), NM_UTILS_LOOKUP_ITEM_IGNORE (NM_CLIENT_PERMISSION_RESULT_UNKNOWN), ); @@ -168,15 +172,7 @@ _NM_UTILS_LOOKUP_DEFINE (static, permission_result_to_color, NMClientPermissionR static const NmcMetaGenericInfo *const metagen_general_status[]; static gconstpointer -_metagen_general_status_get_fcn (const NMMetaEnvironment *environment, - gpointer environment_user_data, - const NmcMetaGenericInfo *info, - gpointer target, - NMMetaAccessorGetType get_type, - NMMetaAccessorGetFlags get_flags, - NMMetaAccessorGetOutFlags *out_flags, - gboolean *out_is_default, - gpointer *out_to_free) +_metagen_general_status_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS) { NmCli *nmc = target; const char *value; @@ -186,26 +182,26 @@ _metagen_general_status_get_fcn (const NMMetaEnvironment *environment, switch (info->info_type) { case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_RUNNING: - NMC_HANDLE_TERMFORMAT (NM_META_TERM_COLOR_NORMAL); + NMC_HANDLE_COLOR (NM_META_COLOR_NONE); value = N_("running"); goto translate_and_out; case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_VERSION: - NMC_HANDLE_TERMFORMAT (NM_META_TERM_COLOR_NORMAL); + NMC_HANDLE_COLOR (NM_META_COLOR_NONE); value = nm_client_get_version (nmc->client); goto clone_and_out; case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_STATE: state = nm_client_get_state (nmc->client); - NMC_HANDLE_TERMFORMAT (state_to_color (state)); + NMC_HANDLE_COLOR (state_to_color (state)); value = nm_state_to_string_no_l10n (state); goto translate_and_out; case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_STARTUP: v_bool = nm_client_get_startup (nmc->client); - NMC_HANDLE_TERMFORMAT (v_bool ? NM_META_TERM_COLOR_YELLOW : NM_META_TERM_COLOR_GREEN); + NMC_HANDLE_COLOR (v_bool ? NM_META_COLOR_MANAGER_STARTING : NM_META_COLOR_MANAGER_RUNNING); value = v_bool ? N_("starting") : N_("started"); goto translate_and_out; case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_CONNECTIVITY: connectivity = nm_client_get_connectivity (nmc->client); - NMC_HANDLE_TERMFORMAT (connectivity_to_color (connectivity)); + NMC_HANDLE_COLOR (connectivity_to_color (connectivity)); value = nm_connectivity_to_string_no_l10n (connectivity); goto translate_and_out; case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_NETWORKING: @@ -234,7 +230,7 @@ _metagen_general_status_get_fcn (const NMMetaEnvironment *environment, g_return_val_if_reached (NULL); enabled_out: - NMC_HANDLE_TERMFORMAT (v_bool ? NM_META_TERM_COLOR_GREEN : NM_META_TERM_COLOR_RED); + NMC_HANDLE_COLOR (v_bool ? NM_META_COLOR_ENABLED : NM_META_COLOR_DISABLED); value = v_bool ? N_("enabled") : N_("disabled"); goto translate_and_out; @@ -276,15 +272,7 @@ static const NmcMetaGenericInfo *const metagen_general_status[_NMC_GENERIC_INFO_ /*****************************************************************************/ static gconstpointer -_metagen_general_permissions_get_fcn (const NMMetaEnvironment *environment, - gpointer environment_user_data, - const NmcMetaGenericInfo *info, - gpointer target, - NMMetaAccessorGetType get_type, - NMMetaAccessorGetFlags get_flags, - NMMetaAccessorGetOutFlags *out_flags, - gboolean *out_is_default, - gpointer *out_to_free) +_metagen_general_permissions_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS) { NMClientPermission perm = GPOINTER_TO_UINT (target); NmCli *nmc = environment_user_data; @@ -293,11 +281,11 @@ _metagen_general_permissions_get_fcn (const NMMetaEnvironment *environment, switch (info->info_type) { case NMC_GENERIC_INFO_TYPE_GENERAL_PERMISSIONS_PERMISSION: - NMC_HANDLE_TERMFORMAT (NM_META_TERM_COLOR_NORMAL); + NMC_HANDLE_COLOR (NM_META_COLOR_NONE); return permission_to_string (perm); case NMC_GENERIC_INFO_TYPE_GENERAL_PERMISSIONS_VALUE: perm_result = nm_client_get_permission_result (nmc->client, perm); - NMC_HANDLE_TERMFORMAT (permission_result_to_color (perm_result)); + NMC_HANDLE_COLOR (permission_result_to_color (perm_result)); s = permission_result_to_string_no_l10n (perm_result); if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) return _(s); @@ -325,22 +313,14 @@ typedef struct { } GetGeneralLoggingData; static gconstpointer -_metagen_general_logging_get_fcn (const NMMetaEnvironment *environment, - gpointer environment_user_data, - const NmcMetaGenericInfo *info, - gpointer target, - NMMetaAccessorGetType get_type, - NMMetaAccessorGetFlags get_flags, - NMMetaAccessorGetOutFlags *out_flags, - gboolean *out_is_default, - gpointer *out_to_free) +_metagen_general_logging_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS) { NmCli *nmc = environment_user_data; GetGeneralLoggingData *d = target; nm_assert (info->info_type < _NMC_GENERIC_INFO_TYPE_GENERAL_LOGGING_NUM); - NMC_HANDLE_TERMFORMAT (NM_META_TERM_COLOR_NORMAL); + NMC_HANDLE_COLOR (NM_META_COLOR_NONE); if (!d->initialized) { d->initialized = TRUE; @@ -516,8 +496,8 @@ show_nm_status (NmCli *nmc, const char *pretty_header_name, const char *print_fl { gs_free_error GError *error = NULL; const char *fields_str; - const char *fields_all = print_flds ? print_flds : NMC_FIELDS_NM_STATUS_ALL; - const char *fields_common = print_flds ? print_flds : NMC_FIELDS_NM_STATUS_COMMON; + const char *fields_all = print_flds ?: NMC_FIELDS_NM_STATUS_ALL; + const char *fields_common = print_flds ?: NMC_FIELDS_NM_STATUS_COMMON; if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0) fields_str = fields_common; @@ -1086,9 +1066,8 @@ networkmanager_running (NMClient *client, GParamSpec *param, NmCli *nmc) char *str; running = nm_client_get_nm_running (client); - str = nmc_colorize (nmc->nmc_config.use_colors, - running ? NM_META_TERM_COLOR_GREEN : NM_META_TERM_COLOR_RED, - NM_META_TERM_FORMAT_NORMAL, + str = nmc_colorize (&nmc->nmc_config, + running ? NM_META_COLOR_MANAGER_RUNNING : NM_META_COLOR_MANAGER_STOPPED, running ? _("NetworkManager has started") : _("NetworkManager has stopped")); g_print ("%s\n", str); g_free (str); @@ -1128,7 +1107,7 @@ client_connectivity (NMClient *client, GParamSpec *param, NmCli *nmc) char *str; g_object_get (client, NM_CLIENT_CONNECTIVITY, &connectivity, NULL); - str = nmc_colorize (nmc->nmc_config.use_colors, connectivity_to_color (connectivity), NM_META_TERM_FORMAT_NORMAL, + str = nmc_colorize (&nmc->nmc_config, connectivity_to_color (connectivity), _("Connectivity is now '%s'\n"), nm_connectivity_to_string (connectivity)); g_print ("%s", str); g_free (str); @@ -1141,14 +1120,13 @@ client_state (NMClient *client, GParamSpec *param, NmCli *nmc) char *str; g_object_get (client, NM_CLIENT_STATE, &state, NULL); - str = nmc_colorize (nmc->nmc_config.use_colors, state_to_color (state), NM_META_TERM_FORMAT_NORMAL, + str = nmc_colorize (&nmc->nmc_config, state_to_color (state), _("Networkmanager is now in the '%s' state\n"), nm_state_to_string (state)); g_print ("%s", str); g_free (str); } - static void device_overview (NmCli *nmc, NMDevice *device) { @@ -1185,12 +1163,12 @@ device_overview (NmCli *nmc, NMDevice *device) if (!nm_device_get_autoconnect (device)) g_string_append_printf (outbuf, "%s, ", _("autoconnect")); if (nm_device_get_firmware_missing (device)) { - tmp = nmc_colorize (nmc->nmc_config.use_colors, NM_META_TERM_COLOR_RED, NM_META_TERM_FORMAT_NORMAL, _("fw missing")); + tmp = nmc_colorize (&nmc->nmc_config, NM_META_COLOR_DEVICE_FIRMWARE_MISSING, _("fw missing")); g_string_append_printf (outbuf, "%s, ", tmp); g_free (tmp); } if (nm_device_get_nm_plugin_missing (device)) { - tmp = nmc_colorize (nmc->nmc_config.use_colors, NM_META_TERM_COLOR_RED, NM_META_TERM_FORMAT_NORMAL, _("plugin missing")); + tmp = nmc_colorize (&nmc->nmc_config, NM_META_COLOR_DEVICE_PLUGIN_MISSING, _("plugin missing")); g_string_append_printf (outbuf, "%s, ", tmp); g_free (tmp); } @@ -1291,7 +1269,7 @@ do_overview (NmCli *nmc, int argc, char **argv) NMDevice **devices; const GPtrArray *p; NMActiveConnection *ac; - NMMetaTermColor color; + NMMetaColor color; NMDnsEntry *dns; char *tmp; int i; @@ -1315,8 +1293,8 @@ do_overview (NmCli *nmc, int argc, char **argv) continue; state = nm_active_connection_get_state (ac); - nmc_active_connection_state_to_color (state, &color); - tmp = nmc_colorize (nmc->nmc_config.use_colors, color, NM_META_TERM_FORMAT_NORMAL, _("%s VPN connection"), + color = nmc_active_connection_state_to_color (state); + tmp = nmc_colorize (&nmc->nmc_config, color, _("%s VPN connection"), nm_active_connection_get_id (ac)); g_print ("%s\n", tmp); g_free (tmp); @@ -1327,14 +1305,13 @@ do_overview (NmCli *nmc, int argc, char **argv) devices = nmc_get_devices_sorted (nmc->client); for (i = 0; devices[i]; i++) { - NMMetaTermFormat color_fmt; NMDeviceState state; ac = nm_device_get_active_connection (devices[i]); state = nm_device_get_state (devices[i]); - nmc_device_state_to_color (state, &color, &color_fmt); - tmp = nmc_colorize (nmc->nmc_config.use_colors, color, color_fmt, "%s: %s%s%s", + 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), ac ? " to " : "", @@ -1345,7 +1322,6 @@ do_overview (NmCli *nmc, int argc, char **argv) if (nm_device_get_description (devices[i]) && strcmp (nm_device_get_description (devices[i]), "")) g_print ("\t\"%s\"\n", nm_device_get_description (devices[i])); - device_overview (nmc, devices[i]); if (ac) ac_overview (nmc, ac); @@ -1418,7 +1394,7 @@ do_monitor (NmCli *nmc, int argc, char **argv) if (!nm_client_get_nm_running (nmc->client)) { char *str; - str = nmc_colorize (nmc->nmc_config.use_colors, NM_META_TERM_COLOR_RED, NM_META_TERM_FORMAT_NORMAL, + str = nmc_colorize (&nmc->nmc_config, NM_META_COLOR_MANAGER_STOPPED, _("Networkmanager is not running (waiting for it)\n")); g_print ("%s", str); g_free (str); diff --git a/clients/cli/meson.build b/clients/cli/meson.build index 65317a0a..9449ce63 100644 --- a/clients/cli/meson.build +++ b/clients/cli/meson.build @@ -27,8 +27,9 @@ deps = [ ] cflags = clients_cflags + [ + '-DSYSCONFDIR="@0@"'.format(nm_sysconfdir), '-DG_LOG_DOMAIN="@0@"'.format(name), - '-DNMCLI_LOCALEDIR="@0@"'.format(nm_localedir) + '-DNMLOCALEDIR="@0@"'.format(nm_localedir) ] if enable_polkit_agent diff --git a/clients/cli/nmcli.c b/clients/cli/nmcli.c index ec23ff43..e9752952 100644 --- a/clients/cli/nmcli.c +++ b/clients/cli/nmcli.c @@ -16,7 +16,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2010 - 2017 Red Hat, Inc. + * Copyright 2010 - 2018 Red Hat, Inc. */ #include "nm-default.h" @@ -51,8 +51,67 @@ # define NMCLI_VERSION VERSION #endif -/* Global NmCli object */ -NmCli nm_cli; +NmCli nm_cli = { + .client = NULL, + + .return_value = NMC_RESULT_SUCCESS, + + .timeout = -1, + + .secret_agent = NULL, + .pwds_hash = NULL, + .pk_listener = NULL, + + .should_wait = 0, + .nowait_flag = TRUE, + .nmc_config.print_output = NMC_PRINT_NORMAL, + .nmc_config.multiline_output = FALSE, + .mode_specified = FALSE, + .nmc_config.escape_values = TRUE, + .required_fields = NULL, + .ask = FALSE, + .complete = FALSE, + .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", + }, + .editor_status_line = FALSE, + .editor_save_confirmation = TRUE, +}; /*****************************************************************************/ @@ -127,9 +186,8 @@ 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_dhcp4_config); + complete_field (h, nmc_fields_dhcp_config); complete_field (h, nmc_fields_ip6_config); - complete_field (h, nmc_fields_dhcp6_config); complete_field (h, nmc_fields_con_show); complete_field (h, nmc_fields_con_active_details_general); complete_field (h, nmc_fields_con_active_details_vpn); @@ -271,9 +329,299 @@ matches_arg (NmCli *nmc, int *argc, char ***argv, const char *pattern, char **ar return TRUE; } +/*************************************************************************************/ + +typedef enum { + NMC_USE_COLOR_AUTO, + NMC_USE_COLOR_YES, + 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) +{ + 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 exists; +} + +static void +check_colors_files_for_term (NmCli *nmc, NmcColorOption *color_option, + 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; + } + + 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 (*color_option == NMC_USE_COLOR_NO) { + /* No need to bother any further. */ + return; + } + + if (nmc->palette_buffer == NULL) + check_colors_file (nmc, color_option, base_dir, name, term, "schem", &nmc->palette_buffer); +} + +static void +check_colors_files_for_name (NmCli *nmc, NmcColorOption *color_option, + const char *base_dir, const char *name) +{ + const gchar *term; + + /* Take a shortcut if the directory is not there. */ + if (!g_file_test (base_dir, G_FILE_TEST_EXISTS)) + return; + + 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); +} + +static void +check_colors_files_for_base_dir (NmCli *nmc, NmcColorOption *color_option, + const char *base_dir) +{ + check_colors_files_for_name (nmc, color_option, base_dir, "nmcli"); + check_colors_files_for_name (nmc, color_option, base_dir, NULL); +} + +static const char * +resolve_color_alias (const char *color) +{ + static const struct { + const char *name; + const char *alias; + } aliases[] = { + { "reset", "0" }, + { "bold", "1" }, + { "white", "1;37" }, + { "halfbright", "2" }, + { "underscore", "4" }, + { "blink", "5" }, + { "reverse", "7" }, + { "black", "30" }, + { "red", "31" }, + { "green", "32" }, + { "brown", "33" }, + { "yellow", "33" }, /* well, yellow */ + { "blue", "34" }, + { "magenta", "35" }, + { "cyan", "36" }, + { "gray", "37" }, + { "darkgray", "90" }, + { "lightred", "91" }, + { "lightgreen", "92" }, + { "lightblue", "94" }, + { "lightmagenta", "95" }, + { "lightcyan", "96" }, + { "lightgray", "97" }, + }; + int i; + + /* Shortcut literal sequences. */ + if (g_ascii_isdigit (*color)) + return color; + + for (i = 0; i < G_N_ELEMENTS (aliases); i++) { + if (strcmp (color, aliases[i].name) == 0) + return aliases[i].alias; + } + + return color; +} + +static gboolean +parse_color_scheme (NmCli *nmc, GError **error) +{ + char *p = nmc->palette_buffer; + const char *name; + const char *color; + const char *map[_NM_META_COLOR_NUM] = { + [NM_META_COLOR_NONE] = NULL, + [NM_META_COLOR_CONNECTION_ACTIVATED] = "connection-activated", + [NM_META_COLOR_CONNECTION_ACTIVATING] = "connection-activating", + [NM_META_COLOR_CONNECTION_DISCONNECTING] = "connection-disconnecting", + [NM_META_COLOR_CONNECTION_INVISIBLE] = "connection-invisible", + [NM_META_COLOR_CONNECTION_UNKNOWN] = "connection-unknown", + [NM_META_COLOR_CONNECTIVITY_FULL] = "connectivity-full", + [NM_META_COLOR_CONNECTIVITY_LIMITED] = "connectivity-limited", + [NM_META_COLOR_CONNECTIVITY_NONE] = "connectivity-none", + [NM_META_COLOR_CONNECTIVITY_PORTAL] = "connectivity-portal", + [NM_META_COLOR_CONNECTIVITY_UNKNOWN] = "connectivity-unknown", + [NM_META_COLOR_DEVICE_ACTIVATED] = "device-activated", + [NM_META_COLOR_DEVICE_ACTIVATING] = "device-activating", + [NM_META_COLOR_DEVICE_DISCONNECTED] = "device-disconnected", + [NM_META_COLOR_DEVICE_FIRMWARE_MISSING] = "device-firmware-missing", + [NM_META_COLOR_DEVICE_PLUGIN_MISSING] = "device-plugin-missing", + [NM_META_COLOR_DEVICE_UNAVAILABLE] = "device-unavailable", + [NM_META_COLOR_DEVICE_UNKNOWN] = "device-unknown", + [NM_META_COLOR_MANAGER_RUNNING] = "manager-running", + [NM_META_COLOR_MANAGER_STARTING] = "manager-starting", + [NM_META_COLOR_MANAGER_STOPPED] = "manager-stopped", + [NM_META_COLOR_PERMISSION_AUTH] = "permission-auth", + [NM_META_COLOR_PERMISSION_NO] = "permission-no", + [NM_META_COLOR_PERMISSION_UNKNOWN] = "permission-unknown", + [NM_META_COLOR_PERMISSION_YES] = "permission-yes", + [NM_META_COLOR_PROMPT] = "prompt", + [NM_META_COLOR_STATE_ASLEEP] = "state-asleep", + [NM_META_COLOR_STATE_CONNECTED_GLOBAL] = "state-connected-global", + [NM_META_COLOR_STATE_CONNECTED_LOCAL] = "state-connected-local", + [NM_META_COLOR_STATE_CONNECTED_SITE] = "state-connected-site", + [NM_META_COLOR_STATE_CONNECTING] = "state-connecting", + [NM_META_COLOR_STATE_DISCONNECTED] = "state-disconnected", + [NM_META_COLOR_STATE_DISCONNECTING] = "state-disconnecting", + [NM_META_COLOR_STATE_UNKNOWN] = "state-unknown", + [NM_META_COLOR_WIFI_SIGNAL_EXCELLENT] = "wifi-signal-excellent", + [NM_META_COLOR_WIFI_SIGNAL_FAIR] = "wifi-signal-fair", + [NM_META_COLOR_WIFI_SIGNAL_GOOD] = "wifi-signal-good", + [NM_META_COLOR_WIFI_SIGNAL_POOR] = "wifi-signal-poor", + [NM_META_COLOR_WIFI_SIGNAL_UNKNOWN] = "wifi-signal-unknown", + [NM_META_COLOR_DISABLED] = "disabled", + [NM_META_COLOR_ENABLED] = "enabled", + }; + int i; + + /* This reads through the raw color scheme file contents, identifying the + * color names and sequences, putting in terminating NULs in place, so that + * pointers into the buffer can readily be used as strings in the palette. */ + while (1) { + /* Leading whitespace. */ + while (nm_utils_is_separator (*p) || *p == '\n') + p++; + + if (*p == '\0') + break; + + /* Comments. */ + if (*p == '#') { + while (*p != '\n' && *p != '\0') + p++; + continue; + } + + /* Color name. */ + name = p; + while (g_ascii_isgraph (*p)) + p++; + if (*p == '\0') { + g_set_error (error, NMCLI_ERROR, 0, + _("Unexpected end of file following '%s'\n"), name); + return FALSE; + } + + /* Separating whitespace. */ + if (!nm_utils_is_separator (*p)) { + *p = '\0'; + g_set_error (error, NMCLI_ERROR, 0, + _("Expected whitespace following '%s'\n"), name); + return FALSE; + } + while (nm_utils_is_separator (*p)) { + *p = '\0'; + p++; + } + + /* Color sequence. */ + color = p; + if (!g_ascii_isgraph (*p)) { + g_set_error (error, NMCLI_ERROR, 0, + _("Expected a value for '%s'\n"), name); + return FALSE; + } + while (g_ascii_isgraph (*p)) + p++; + + /* Trailing whitespace. */ + while (nm_utils_is_separator (*p)) { + *p = '\0'; + p++; + } + if (*p != '\0') { + if (*p != '\n') { + g_set_error (error, NMCLI_ERROR, 0, + _("Expected a line break following '%s'\n"), color); + return FALSE; + } + *p = '\0'; + p++; + } + + /* 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); + break; + } + } + if (i == _NM_META_COLOR_NUM) + g_debug ("Ignoring an unrecognized color: '%s'\n", name); + } + + return TRUE; +} + +static void +set_colors (NmCli *nmc, NmcColorOption color_option) +{ + 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; + } + + check_colors_files_for_base_dir (nmc, &color_option, g_get_user_config_dir ()); + check_colors_files_for_base_dir (nmc, &color_option, SYSCONFDIR); + + 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; + } + + if (nmc->nmc_config_mutable.use_colors && nmc->palette_buffer) { + if (!parse_color_scheme (nmc, &error)) { + g_debug ("Error parsing color scheme: %s", error->message); + g_error_free (error); + } + } +} + +/*************************************************************************************/ + static gboolean process_command_line (NmCli *nmc, int argc, char **argv) { + NmcColorOption colors = NMC_USE_COLOR_AUTO; char *base; base = strrchr (argv[0], '/'); @@ -353,11 +701,11 @@ process_command_line (NmCli *nmc, int argc, char **argv) if (argc == 1 && nmc->complete) complete_option_with_value (argv[0], value, "yes", "no", "auto", NULL); if (matches (value, "auto")) - nmc->nmc_config_mutable.use_colors = NMC_USE_COLOR_AUTO; + colors = NMC_USE_COLOR_AUTO; else if (matches (value, "yes")) - nmc->nmc_config_mutable.use_colors = NMC_USE_COLOR_YES; + colors = NMC_USE_COLOR_YES; else if (matches (value, "no")) - nmc->nmc_config_mutable.use_colors = NMC_USE_COLOR_NO; + colors = NMC_USE_COLOR_NO; else { g_string_printf (nmc->return_text, _("Error: '%s' is not valid argument for '%s' option."), value, argv[0]); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; @@ -384,8 +732,8 @@ process_command_line (NmCli *nmc, int argc, char **argv) complete_fields (argv[0], value); nmc->required_fields = g_strdup (value); nmc->nmc_config_mutable.print_output = NMC_PRINT_TERSE; - /* We want fixed tabular mode here, but just set the mode specified and rely on the initialization - * in nmc_init: in this way we allow use of "-m multiline" to swap the output mode also if placed + /* We want fixed tabular mode here, but just set the mode specified and rely on defaults: + * in this way we allow use of "-m multiline" to swap the output mode also if placed * before the "-g <field>" option (-g may be still more practical and easy to remember than -t -f). */ nmc->mode_specified = TRUE; @@ -423,6 +771,8 @@ process_command_line (NmCli *nmc, int argc, char **argv) if (nmc->required_fields) nmc->nmc_config_mutable.overview = FALSE; + set_colors (nmc, colors); + /* Now run the requested command */ nmc_do_cmd (nmc, nmcli_cmds, *argv, argc, argv); @@ -559,38 +909,6 @@ nmc_value_transforms_register (void) nmc_convert_bytes_to_string); } -/* Initialize NmCli structure - set default values */ -static void -nmc_init (NmCli *nmc) -{ - nmc->client = NULL; - - nmc->return_value = NMC_RESULT_SUCCESS; - nmc->return_text = g_string_new (_("Success")); - - nmc->timeout = -1; - - nmc->secret_agent = NULL; - nmc->pwds_hash = NULL; - nmc->pk_listener = NULL; - - nmc->should_wait = 0; - nmc->nowait_flag = TRUE; - nmc->nmc_config_mutable.print_output = NMC_PRINT_NORMAL; - nmc->nmc_config_mutable.multiline_output = FALSE; - nmc->mode_specified = FALSE; - nmc->nmc_config_mutable.escape_values = TRUE; - nmc->required_fields = NULL; - nmc->ask = FALSE; - nmc->complete = FALSE; - nmc->nmc_config_mutable.show_secrets = FALSE; - nmc->nmc_config_mutable.use_colors = NMC_USE_COLOR_AUTO; - nmc->nmc_config_mutable.in_editor = FALSE; - nmc->editor_status_line = FALSE; - nmc->editor_save_confirmation = TRUE; - nmc->editor_prompt_color = NM_META_TERM_COLOR_NORMAL; -} - static void nmc_cleanup (NmCli *nmc) { @@ -608,7 +926,7 @@ nmc_cleanup (NmCli *nmc) if (nmc->pwds_hash) g_hash_table_destroy (nmc->pwds_hash); - g_free (nmc->required_fields); + nm_clear_g_free (&nmc->required_fields); if (nmc->pager_pid > 0) { fclose (stdout); @@ -619,6 +937,8 @@ nmc_cleanup (NmCli *nmc) nmc->pager_pid = 0; } + nm_clear_g_free (&nmc->palette_buffer); + nmc_polkit_agent_fini (nmc); } @@ -630,7 +950,7 @@ main (int argc, char *argv[]) #ifdef GETTEXT_PACKAGE /* Set i18n stuff */ - bindtextdomain (GETTEXT_PACKAGE, NMCLI_LOCALEDIR); + bindtextdomain (GETTEXT_PACKAGE, NMLOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); #endif @@ -640,7 +960,7 @@ main (int argc, char *argv[]) nmc_value_transforms_register (); - nmc_init (&nm_cli); + nm_cli.return_text = g_string_new (_("Success")); loop = g_main_loop_new (NULL, FALSE); g_unix_signal_add (SIGTERM, signal_handler, GINT_TO_POINTER (SIGTERM)); diff --git a/clients/cli/nmcli.h b/clients/cli/nmcli.h index 0f3d29cd..61bf86de 100644 --- a/clients/cli/nmcli.h +++ b/clients/cli/nmcli.h @@ -14,7 +14,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2010 - 2017 Red Hat, Inc. + * Copyright 2010 - 2018 Red Hat, Inc. */ #ifndef NMC_NMCLI_H @@ -93,24 +93,18 @@ struct _NmcOutputField { gboolean value_is_array; /* Whether value is char** instead of char* */ gboolean free_value; /* Whether to free the value */ NmcOfFlags flags; /* Flags - whether and how to print values/field names/headers */ - NMMetaTermColor color; /* Use this color to print value */ - NMMetaTermFormat color_fmt; /* Use this terminal format to print value */ + NMMetaColor color; /* Use this color to print value */ }; -typedef enum { - NMC_USE_COLOR_AUTO, - NMC_USE_COLOR_YES, - NMC_USE_COLOR_NO, -} NmcColorOption; - typedef struct _NmcConfig { NMCPrintOutput print_output; /* Output mode */ - NmcColorOption use_colors; /* Whether to use colors for output: option '--color' */ + gboolean 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' */ bool show_secrets; /* Whether to display secrets (both input and output): option '--show-secrets' */ bool overview; /* Overview mode (hide default values) */ + const char *palette[_NM_META_COLOR_NUM]; /* Color palette */ } NmcConfig; typedef struct _NmcOutputData { @@ -143,9 +137,15 @@ typedef struct _NmCli { gboolean complete; /* Autocomplete the command line */ gboolean editor_status_line; /* Whether to display status line in connection editor */ gboolean editor_save_confirmation; /* Whether to ask for confirmation on saving connections with 'autoconnect=yes' */ - NMMetaTermColor editor_prompt_color; /* Color of prompt in connection editor */ + + char *palette_buffer; /* Buffer with sequences for terminal-colors.d(5)-based coloring. */ } NmCli; +#define NMC_RETURN(nmc, rvalue) \ + G_STMT_START { \ + return ((nmc)->return_value = (rvalue)); \ + } G_STMT_END + extern NmCli nm_cli; /* Error quark for GError domain */ diff --git a/clients/cli/settings.c b/clients/cli/settings.c index 5c3deead..01142ba2 100644 --- a/clients/cli/settings.c +++ b/clients/cli/settings.c @@ -749,9 +749,9 @@ nmc_setting_get_property_desc (NMSetting *setting, const char *prop) return g_strdup_printf ("%s\n%s\n%s%s%s%s", setting_desc_title, - setting_desc ? setting_desc : "", + setting_desc ?: "", nmcli_nl, nmcli_desc_title, nmcli_nl, - nmcli_desc ? nmcli_desc : ""); + nmcli_desc ?: ""); } /* diff --git a/clients/cli/utils.c b/clients/cli/utils.c index 71fdcf30..32c44e39 100644 --- a/clients/cli/utils.c +++ b/clients/cli/utils.c @@ -15,7 +15,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright 2010 Lennart Poettering - * Copyright 2010 - 2017 Red Hat, Inc. + * Copyright 2010 - 2018 Red Hat, Inc. */ #include "nm-default.h" @@ -86,14 +86,15 @@ _meta_type_nmc_generic_info_get_fcn (const NMMetaAbstractInfo *abstract_info, if (!NM_IN_SET (get_type, NM_META_ACCESSOR_GET_TYPE_PARSABLE, NM_META_ACCESSOR_GET_TYPE_PRETTY, - NM_META_ACCESSOR_GET_TYPE_TERMFORMAT)) + NM_META_ACCESSOR_GET_TYPE_COLOR)) g_return_val_if_reached (NULL); - /* omitting the out_to_free value is only allowed for TERMFORMAT. */ - nm_assert (out_to_free || NM_IN_SET (get_type, NM_META_ACCESSOR_GET_TYPE_TERMFORMAT)); + /* omitting the out_to_free value is only allowed for COLOR. */ + nm_assert (out_to_free || NM_IN_SET (get_type, NM_META_ACCESSOR_GET_TYPE_COLOR)); if (info->get_fcn) { - return info->get_fcn (environment, environment_user_data, + return info->get_fcn (environment, + environment_user_data, info, target, get_type, get_flags, @@ -103,7 +104,7 @@ _meta_type_nmc_generic_info_get_fcn (const NMMetaAbstractInfo *abstract_info, } if (info->nested) { - NMC_HANDLE_TERMFORMAT (NM_META_TERM_COLOR_NORMAL); + NMC_HANDLE_COLOR (NM_META_COLOR_NONE); return info->name; } @@ -119,37 +120,16 @@ const NMMetaType nmc_meta_type_generic_info = { /*****************************************************************************/ -static gboolean -use_colors (NmcColorOption color_option) -{ - if (color_option == NMC_USE_COLOR_AUTO) { - static NmcColorOption cached = NMC_USE_COLOR_AUTO; - - if (G_UNLIKELY (cached == NMC_USE_COLOR_AUTO)) { - if ( g_strcmp0 (g_getenv ("TERM"), "dumb") == 0 - || !isatty (STDOUT_FILENO)) - cached = NMC_USE_COLOR_NO; - else - cached = NMC_USE_COLOR_YES; - } - return cached == NMC_USE_COLOR_YES; - } - - return color_option == NMC_USE_COLOR_YES; -} - static const char * -colorize_string (NmcColorOption color_option, - NMMetaTermColor color, - NMMetaTermFormat color_fmt, +colorize_string (const NmcConfig *nmc_config, + NMMetaColor color, const char *str, char **out_to_free) { const char *out = str; - if ( use_colors (color_option) - && (color != NM_META_TERM_COLOR_NORMAL || color_fmt != NM_META_TERM_FORMAT_NORMAL)) { - *out_to_free = nmc_colorize (color_option, color, color_fmt, "%s", str); + if (nmc_config && nmc_config->use_colors) { + *out_to_free = nmc_colorize (nmc_config, color, "%s", str); out = *out_to_free; } @@ -204,7 +184,6 @@ next_arg (NmCli *nmc, int *argc, char ***argv, ...) if (*argc == 0) return -1; - va_start (args, argv); if (nmc && nmc->complete && *argc == 1) { @@ -391,118 +370,30 @@ nmc_terminal_show_progress (const char *str) const char slashes[4] = {'|', '/', '-', '\\'}; nmc_terminal_erase_line (); - g_print ("%c %s", slashes[idx++], str ? str : ""); + g_print ("%c %s", slashes[idx++], str ?: ""); fflush (stdout); if (idx == 4) idx = 0; } -const char * -nmc_term_color_sequence (NMMetaTermColor color) -{ - switch (color) { - case NM_META_TERM_COLOR_BLACK: - return "\33[30m"; - break; - case NM_META_TERM_COLOR_RED: - return "\33[31m"; - break; - case NM_META_TERM_COLOR_GREEN: - return "\33[32m"; - break; - case NM_META_TERM_COLOR_YELLOW: - return "\33[33m"; - break; - case NM_META_TERM_COLOR_BLUE: - return "\33[34m"; - break; - case NM_META_TERM_COLOR_MAGENTA: - return "\33[35m"; - break; - case NM_META_TERM_COLOR_CYAN: - return "\33[36m"; - break; - case NM_META_TERM_COLOR_WHITE: - return "\33[37m"; - break; - default: - return ""; - break; - } -} - -/* Parses @str for color as string or number */ -NMMetaTermColor -nmc_term_color_parse_string (const char *str, GError **error) -{ - unsigned long color_int; - static const char *colors[] = { "normal", "black", "red", "green", "yellow", - "blue", "magenta", "cyan", "white", NULL }; - - if (nmc_string_to_uint (str, TRUE, 0, 8, &color_int)) { - return (NMMetaTermColor) color_int; - } else { - const char *color, **p; - int i; - - color = nmc_string_is_valid (str, colors, error); - for (p = colors, i = 0; *p != NULL; p++, i++) { - if (*p == color) - return (NMMetaTermColor) i; - } - return -1; - } -} - -const char * -nmc_term_format_sequence (NMMetaTermFormat format) -{ - switch (format) { - case NM_META_TERM_FORMAT_BOLD: - return "\33[1m"; - break; - case NM_META_TERM_FORMAT_DIM: - return "\33[2m"; - break; - case NM_META_TERM_FORMAT_UNDERLINE: - return "\33[4m"; - break; - case NM_META_TERM_FORMAT_BLINK: - return "\33[5m"; - break; - case NM_META_TERM_FORMAT_REVERSE: - return "\33[7m"; - break; - case NM_META_TERM_FORMAT_HIDDEN: - return "\33[8m"; - break; - default: - return ""; - break; - } -} - char * -nmc_colorize (NmcColorOption color_option, NMMetaTermColor color, NMMetaTermFormat format, const char *fmt, ...) +nmc_colorize (const NmcConfig *nmc_config, NMMetaColor color, const char *fmt, ...) { va_list args; char *str, *colored; - const char *ansi_color, *color_end, *ansi_fmt, *format_end; - static const char *end_seq = "\33[0m"; + const char *ansi_seq = NULL; va_start (args, fmt); str = g_strdup_vprintf (fmt, args); va_end (args); - if (!use_colors (color_option)) - return str; + if (nmc_config->use_colors) + ansi_seq = nmc_config->palette[color]; - ansi_color = nmc_term_color_sequence (color); - ansi_fmt = nmc_term_format_sequence (format); - color_end = *ansi_color ? end_seq : ""; - format_end = *ansi_fmt ? end_seq : ""; + if (ansi_seq == NULL) + return str; - colored = g_strdup_printf ("%s%s%s%s%s", ansi_fmt, ansi_color, str, color_end, format_end); + colored = g_strdup_printf ("\33[%sm%s\33[0m", ansi_seq, str); g_free (str); return colored; } @@ -719,7 +610,7 @@ set_val_arrc (NmcOutputField fields_array[], guint32 idx, const char **value) } void -set_val_color_all (NmcOutputField fields_array[], NMMetaTermColor color) +set_val_color_all (NmcOutputField fields_array[], NMMetaColor color) { int i; @@ -728,16 +619,6 @@ set_val_color_all (NmcOutputField fields_array[], NMMetaTermColor color) } } -void -set_val_color_fmt_all (NmcOutputField fields_array[], NMMetaTermFormat format) -{ - int i; - - for (i = 0; fields_array[i].info; i++) { - fields_array[i].color_fmt = format; - } -} - /* * Free 'value' members in array of NmcOutputField */ @@ -1016,8 +897,7 @@ typedef enum { typedef struct { guint row_idx; const PrintDataHeaderCell *header_cell; - NMMetaTermColor term_color; - NMMetaTermFormat term_format; + NMMetaColor color; union { const char *plain; const char *const*strv; @@ -1180,17 +1060,15 @@ _print_fill (const NmcConfig *nmc_config, cell->text_to_free = !!to_free; } - nm_meta_termformat_unpack (nm_meta_abstract_info_get (info, - nmc_meta_environment, - nmc_meta_environment_arg, - target, - NM_META_ACCESSOR_GET_TYPE_TERMFORMAT, - NM_META_ACCESSOR_GET_FLAGS_NONE, - &color_out_flags, - NULL, - NULL), - &cell->term_color, - &cell->term_format); + cell->color = GPOINTER_TO_INT (nm_meta_abstract_info_get (info, + nmc_meta_environment, + nmc_meta_environment_arg, + target, + NM_META_ACCESSOR_GET_TYPE_COLOR, + NM_META_ACCESSOR_GET_FLAGS_NONE, + &color_out_flags, + NULL, + NULL)); if (cell->text_format == PRINT_DATA_CELL_FORMAT_TYPE_PLAIN) { if (pretty && (!cell->text.plain|| !cell->text.plain[0])) { @@ -1375,9 +1253,7 @@ _print_do (const NmcConfig *nmc_config, gs_free char *text_to_free = NULL; const char *text; - text = colorize_string (nmc_config->use_colors, - cell->term_color, cell->term_format, - lines[i_lines], &text_to_free); + text = colorize_string (nmc_config, cell->color, lines[i_lines], &text_to_free); if (multiline) { gs_free char *prefix = NULL; @@ -1425,8 +1301,7 @@ _print_do (const NmcConfig *nmc_config, } if ( pretty - && ( i_row < row_len - 1 - || multiline)) { + && multiline) { gs_free char *line = NULL; g_print ("%s\n", (line = g_strnfill (ML_HEADER_WIDTH, '-'))); @@ -1506,7 +1381,7 @@ nmc_terminal_spawn_pager (const NmcConfig *nmc_config) if ( nm_cli.nmc_config.in_editor || nm_cli.pager_pid > 0 || nmc_config->print_output == NMC_PRINT_TERSE - || !use_colors (nmc_config->use_colors) + || !nmc_config->use_colors || g_strcmp0 (pager, "") == 0 || getauxval (AT_SECURE)) return; @@ -1577,7 +1452,7 @@ nmc_terminal_spawn_pager (const NmcConfig *nmc_config) /*****************************************************************************/ static const char * -get_value_to_print (NmcColorOption color_option, +get_value_to_print (const NmcConfig *nmc_config, const NmcOutputField *field, gboolean field_name, const char *not_set_str, @@ -1603,7 +1478,7 @@ get_value_to_print (NmcColorOption color_option, } /* colorize the value */ - out = colorize_string (color_option, field->color, field->color_fmt, value, out_to_free); + out = colorize_string (nmc_config, field->color, value, out_to_free); if (out && out == free_value) { nm_assert (!*out_to_free); @@ -1697,7 +1572,7 @@ print_required_fields (const NmcConfig *nmc_config, gs_free char *tmp = NULL; val = *p ?: not_set_str; - print_val = colorize_string (nmc_config->use_colors, field_values[idx].color, field_values[idx].color_fmt, + print_val = colorize_string (nmc_config, field_values[idx].color, val, &val_to_free); tmp = g_strdup_printf ("%s%s%s[%d]:", section_prefix ? (const char*) field_values[0].value : "", @@ -1718,7 +1593,7 @@ print_required_fields (const NmcConfig *nmc_config, /* value is a string */ val = val && *val ? val : not_set_str; - print_val = colorize_string (nmc_config->use_colors, field_values[idx].color, field_values[idx].color_fmt, + print_val = colorize_string (nmc_config, field_values[idx].color, val, &val_to_free); tmp = g_strdup_printf ("%s%s%s:", section_prefix ? hdr_name : "", @@ -1749,7 +1624,7 @@ print_required_fields (const NmcConfig *nmc_config, idx = g_array_index (indices, int, i); - value = get_value_to_print (nmc_config->use_colors, (NmcOutputField *) field_values+idx, field_names, + value = get_value_to_print (nmc_config, (NmcOutputField *) field_values+idx, field_names, not_set_str, &val_to_free); if (terse) { @@ -1822,7 +1697,7 @@ print_data_prepare_width (GPtrArray *output_data) row = g_ptr_array_index (output_data, j); field_names = row[0].flags & NMC_OF_FLAG_FIELD_NAMES; - value = get_value_to_print (NMC_USE_COLOR_NO, row+i, field_names, "--", &val_to_free); + value = get_value_to_print (NULL, row+i, field_names, "--", &val_to_free); len = nmc_string_screen_width (value, NULL); max_width = len > max_width ? len : max_width; } diff --git a/clients/cli/utils.h b/clients/cli/utils.h index c92c4e2e..dc0ce083 100644 --- a/clients/cli/utils.h +++ b/clients/cli/utils.h @@ -14,7 +14,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2010 - 2017 Red Hat, Inc. + * Copyright 2010 - 2018 Red Hat, Inc. */ #ifndef NMC_UTILS_H @@ -41,11 +41,7 @@ char *ssid_to_hex (const char *str, gsize len); void nmc_terminal_erase_line (void); void nmc_terminal_show_progress (const char *str); void nmc_terminal_spawn_pager (const NmcConfig *nmc_config); -gboolean nmc_term_use_colors (NmcColorOption color_option); -const char *nmc_term_color_sequence (NMMetaTermColor color); -const char *nmc_term_format_sequence (NMMetaTermFormat format); -NMMetaTermColor nmc_term_color_parse_string (const char *str, GError **error); -char *nmc_colorize (NmcColorOption color_option, NMMetaTermColor color, NMMetaTermFormat format, const char * fmt, ...) _nm_printf (4, 5); +char *nmc_colorize (const NmcConfig *nmc_config, NMMetaColor color, const char * fmt, ...) _nm_printf (3, 4); void nmc_filter_out_colors_inplace (char *str); char *nmc_filter_out_colors (const char *str); char *nmc_get_user_input (const char *ask_str); @@ -58,8 +54,7 @@ void set_val_str (NmcOutputField fields_array[], guint32 index, char *value); void set_val_strc (NmcOutputField fields_array[], guint32 index, const char *value); void set_val_arr (NmcOutputField fields_array[], guint32 index, char **value); void set_val_arrc (NmcOutputField fields_array[], guint32 index, const char **value); -void set_val_color_all (NmcOutputField fields_array[], NMMetaTermColor color); -void set_val_color_fmt_all (NmcOutputField fields_array[], NMMetaTermFormat format); +void set_val_color_all (NmcOutputField fields_array[], NMMetaColor color); void nmc_free_output_field_values (NmcOutputField fields_array[]); GArray *parse_output_fields (const char *fields_str, @@ -128,10 +123,10 @@ typedef enum { } NmcGenericInfoType; -#define NMC_HANDLE_TERMFORMAT(color) \ +#define NMC_HANDLE_COLOR(color) \ G_STMT_START { \ - if (get_type == NM_META_ACCESSOR_GET_TYPE_TERMFORMAT) \ - return nm_meta_termformat_pack ((color), NM_META_TERM_FORMAT_NORMAL); \ + if (get_type == NM_META_ACCESSOR_GET_TYPE_COLOR) \ + return GINT_TO_POINTER (color); \ } G_STMT_END struct _NmcMetaGenericInfo { @@ -143,15 +138,19 @@ struct _NmcMetaGenericInfo { const char *name; const char *name_header; const NmcMetaGenericInfo *const*nested; - gconstpointer (*get_fcn) (const NMMetaEnvironment *environment, - gpointer environment_user_data, - const NmcMetaGenericInfo *info, - gpointer target, - NMMetaAccessorGetType get_type, - NMMetaAccessorGetFlags get_flags, - NMMetaAccessorGetOutFlags *out_flags, - gboolean *out_is_default, - gpointer *out_to_free); + +#define NMC_META_GENERIC_INFO_GET_FCN_ARGS \ + const NMMetaEnvironment *environment, \ + gpointer environment_user_data, \ + const NmcMetaGenericInfo *info, \ + gpointer target, \ + NMMetaAccessorGetType get_type, \ + NMMetaAccessorGetFlags get_flags, \ + NMMetaAccessorGetOutFlags *out_flags, \ + gboolean *out_is_default, \ + gpointer *out_to_free + + gconstpointer (*get_fcn) (NMC_META_GENERIC_INFO_GET_FCN_ARGS); }; #define NMC_META_GENERIC(n, ...) \ @@ -164,6 +163,52 @@ struct _NmcMetaGenericInfo { #define NMC_META_GENERIC_WITH_NESTED(n, nest, ...) \ NMC_META_GENERIC (n, .nested = (nest), __VA_ARGS__) +#define NMC_META_GENERIC_GROUP(_group_name, _nested, _name_header) \ + ((const NMMetaAbstractInfo *const*) ((const NmcMetaGenericInfo *const[]) { \ + NMC_META_GENERIC_WITH_NESTED (_group_name,_nested, .name_header = _name_header), \ + NULL, \ + })) + +static inline const char * +nmc_meta_generic_get_str_i18n (const char *s, NMMetaAccessorGetType get_type) +{ + if (!NM_IN_SET (get_type, NM_META_ACCESSOR_GET_TYPE_PRETTY, + NM_META_ACCESSOR_GET_TYPE_PARSABLE)) + g_return_val_if_reached (NULL); + + if (!s) + return NULL; + if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) + return gettext (s); + return s; +} + +static inline const char * +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 char * +nmc_meta_generic_get_enum_with_detail (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)) + g_return_val_if_reached (NULL); + + if (!str_val) { + /* Pass %NULL for only printing the numeric value. */ + 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); +} + /*****************************************************************************/ gboolean nmc_print (const NmcConfig *nmc_config, |